gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
IIOMMap.H
Go to the documentation of this file.
1 /* Copyright 2000-2018 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16 */
17 #ifndef IIOMMAP_H_
18 #define IIOMMAP_H_
19 
20 #include "IIO.H"
21 
22 #include <sys/mman.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <linux/ioctl.h>
26 #include <linux/types.h>
27 #include <stdio.h>
28 #include <sys/ioctl.h>
29 
30 // referenced from iio_fm_radio.c
31 #define IIO_BLOCK_ALLOC_IOCTL _IOWR('i', 0xa0, struct iio_buffer_block_alloc_req)
32 #define IIO_BLOCK_FREE_IOCTL _IO('i', 0xa1)
33 #define IIO_BLOCK_QUERY_IOCTL _IOWR('i', 0xa2, struct iio_buffer_block)
34 #define IIO_BLOCK_ENQUEUE_IOCTL _IOWR('i', 0xa3, struct iio_buffer_block)
35 #define IIO_BLOCK_DEQUEUE_IOCTL _IOWR('i', 0xa4, struct iio_buffer_block)
36 
38  __u32 type;
39  __u32 size;
40  __u32 count;
41  __u32 id;
42 };
43 
45  __u32 id;
46  __u32 size;
47  __u32 bytes_used;
48  __u32 type;
49  __u32 flags;
50  union {
51  __u32 offset;
52  } data;
53  __u64 timestamp;
54 };
55 
56 struct block {
58  unsigned short *addr;
59 };
60 
61 #define DEFAULT_BLOCK_COUNT 4
62 #define DEFAULT_BLOCK_SIZE 0x100000
63 
66  int fd;
68 
72  int allocate() {
73  cout<<__func__<<endl;
74  int ret = ioctl(fd, IIO_BLOCK_ALLOC_IOCTL, &req);
75  if (ret < 0) {
76  perror("Failed to allocate memory blocks");
78  }
79  return NO_ERROR;
80  }
81 
84  void deAllocate() {
85  cout<<__func__<<endl;
86  ioctl(fd, IIO_BLOCK_FREE_IOCTL, 0);
87  }
88 
92  int memoryMap() {
93  cout<<__func__<<endl;
94  std::cout << "MMappedBlocks::memoryMap resizing blocks "<<req.count<<endl;
95  blocks.resize(req.count);
96  for (uint i = 0; i < req.count; i++) {
97  std::cout << "MMappedBlocks::memoryMap query i="<<i<<endl;
98  blocks[i].block.id = i;
99  if (ioctl(fd, IIO_BLOCK_QUERY_IOCTL, &blocks[i].block)!=0) {
100  perror("Failed to query block");
102  }
103 
104  std::cout << "MMappedBlocks::memoryMap mapping"<<endl;
105  blocks[i].addr = (unsigned short *)mmap(0, blocks[i].block.size, PROT_READ, MAP_SHARED, fd, blocks[i].block.data.offset);
106  if (blocks[i].addr == MAP_FAILED) {
107  perror("Failed to mmap block");
109  }
110 
111  std::cout << "MMappedBlocks::memoryMap enqueueing "<<endl;
112  if (ioctl(fd, IIO_BLOCK_ENQUEUE_IOCTL, &blocks[i].block)!=0) {
113  perror("Failed to enqueue block");
115  }
116 
117  fprintf(stderr, "Sucessfully mapped block %d (offset %x, size %d) at %p\n", i, blocks[i].block.data.offset, blocks[i].block.size, blocks[i].addr);
118  }
119  return NO_ERROR;
120  }
121 
124  void memoryUnmap() {
125  cout<<__func__<<endl;
126  for (uint i = 0; i < req.count; i++)
127  munmap(blocks[i].addr, blocks[i].block.size);
128  blocks.resize(0);
129  }
130 public:
131  vector<struct block> blocks;
132 
136  req.size=0;
137  req.count=0;
138  blocks.resize(0);
139  }
140 
143  memoryUnmap();
144  deAllocate();
145  }
146 
151  int reset(int fdIn) {
152  return reset(fdIn, DEFAULT_BLOCK_COUNT, DEFAULT_BLOCK_SIZE);
153  }
154 
161  int reset(int fdIn, int count, int size) {
162  if (req.size!=0) {
163  memoryUnmap();
164  deAllocate();
165  }
166 
167  int ret=NO_ERROR;
168  fd=fdIn;
169  req.type = 0x0;
170  req.size = size;
171  req.count = count;
172  if (count>0 && size>0) {
173  ret=allocate();
174  if (ret!=NO_ERROR)
175  return ret;
176  ret=memoryMap();
177  if (ret!=NO_ERROR) {
178  memoryUnmap();
179  deAllocate();
180  }
181  }
182  return ret;
183  }
184 };
185 
186 class IIOMMap : public IIO {
187  vector<MMappedBlocks> mMappedBlocks;
188 public:
189  IIOMMap() {}
190 
192  virtual ~IIOMMap() {
193  close();
194  }
195 
199  int open(void) {
201  }
202 
208  int open(int count, int sizeIn) {
209  if (getDeviceCnt()<1)
211  int ret=NO_ERROR;
212  for (unsigned int i=0; i<getDeviceCnt(); i++) {
213  std::cout << "opening device "<<i<<endl;
214  if ((ret=operator[](i).open(O_RDWR))!=NO_ERROR) {
215  ostringstream deviceDetail;
216  deviceDetail<<" Device "<<i;
217  IIODebug().evaluateError(ret, deviceDetail.str());
218  break;
219  }
220  }
221 
222  std::cout << "mmapping"<<endl;
223  if (ret==NO_ERROR) // init the memory mapped buffers
224  resizeMMapBlocks(count, sizeIn);
225 
226  int closeRet;
227  if (ret!=NO_ERROR) // if we couldn't open everything, then close everything
228  for (unsigned int i=0; i<getDeviceCnt(); i++)
229  if ((closeRet=operator[](i).close())!=NO_ERROR)
230  IIODebug().evaluateError(closeRet);
231  return ret;
232  }
233 
239  int resizeMMapBlocks(int count, int sizeIn) {
240  int ret=NO_ERROR;
241  mMappedBlocks.resize(IIO::size());
242  std::cout << "mMappedBlocks resized"<<endl;
243  for (unsigned int i=0; i<getDeviceCnt(); i++) {
244  std::cout << "resetting mmapped blocks "<<i<<endl;
245  int ret=mMappedBlocks[i].reset(operator[](i).getFD(), count, sizeIn*operator[](i).getChCnt()*operator[](i).getChFrameSize());
246  if (ret!=NO_ERROR)
247  break;
248  }
249  return ret;
250  }
251 
255  int close(void) {
256  mMappedBlocks.resize(0); // remove any memory mapping stuff.
257  return IIO::close();
258  }
259 
266  template<typename TYPE>
267  int read(uint N, const Eigen::Array<TYPE, Eigen::Dynamic, Eigen::Dynamic> &array) {
268  // error check that the blocks are initialised, the data types match and the array is of the minimum required size.
269  if (mMappedBlocks.size()<=0)
271  if (sizeof(TYPE)!=operator[](0).getChFrameSize()) {
272  ostringstream msg;
273  msg<<"The provided array type has "<<sizeof(TYPE)<<" bytes per sample, where as the IIO devices have "<<getChFrameSize()<<" bytes per sample\n";
275  }
276  if (array.rows()!=N*operator[](0).getChCnt() && array.cols()>getDeviceCnt()) {
277  ostringstream msg;
278  msg<<"The provided array is not shaped correctly, size=("<<array.rows()<<", "<<array.cols()<<") but size=(N*device ch cnt, device cnt) is required, where size=("<<N*getChCnt()<<", "<<getDeviceCnt()<<")\n";
280  }
281 
282  // grab blocks off the queue and memory copy them to the input array and re-enqueue them
283  struct iio_buffer_block block; // the block to grab off the mmap queue
284  for (int i=0; i <array.cols(); i++) { // read N samples from each device which is requested
285  int ret = ioctl(operator[](i).getFD(), IIO_BLOCK_DEQUEUE_IOCTL, &block);
286  if (ret!=0) {
287  ostringstream msg;
288  msg<<"Couldn't dequeue a mmaped block from device "<<i<<endl;
289  return IIODebug().evaluateError(IIODEVICE_READ_ERROR, msg.str());
290  }
291  int bytesPerFrame=operator[](i).getChFrameSize()*operator[](i).getChCnt();
292  uint bytesToRead=N*bytesPerFrame;
293  if (bytesToRead!=block.size) {
294  ostringstream msg;
295  msg<<"The mmapped block has a size="<<block.size<<" and the input array requires size="<<bytesToRead<<"\n";
297  }
298 
299  TYPE *dataSrc=mMappedBlocks[i].blocks[block.id].addr;
300  TYPE *dataDest=(unsigned short *)array.col(i).data();
301  for (int j=0; j<N*operator[](i).getChCnt(); j++)
302  dataDest[j]=dataSrc[j];
303 
304  ret = ioctl(operator[](i).getFD(), IIO_BLOCK_ENQUEUE_IOCTL, &block);
305  if (ret!=0) {
306  ostringstream msg;
307  msg<<"Couldn't enqueue the mmaped block to device "<<i<<endl;
308  return IIODebug().evaluateError(IIODEVICE_READ_ERROR, msg.str());
309  }
310  }
311  return NO_ERROR;
312  }
313 
317  double getMaxDelay(float fs){
318  if (mMappedBlocks.size()<=0)
319  return 0.;
320  double chCnt=(double)operator[](0).getChCnt();
321  double periodN=(double)mMappedBlocks[0].blocks.size();
322  if (periodN<=0)
323  return 0.;
324  double N=(double)mMappedBlocks[0].blocks[0].block.size;
325  double frameByteCnt=operator[](0).getChFrameSize();
326  return periodN*N/fs/chCnt/frameByteCnt;
327  }
328 };
329 
330 #endif // IIOMMAP_H_
#define IIOMMAP_ALLOCATE_ERROR
Couldn&#39;t allocate the iio memory buffers in the kernel using ioctl.
Definition: IIOChannel.H:43
size(signal)
int N
int fd
The file descriptior of the device.
Definition: IIOMMap.H:66
#define IIO_BLOCK_DEQUEUE_IOCTL
Definition: IIOMMap.H:35
#define IIOMMAP_WRONGOPEN_ERROR
The wrong open method was called.
Definition: IIOChannel.H:48
IIOMMap()
Constructor.
Definition: IIOMMap.H:189
virtual int evaluateError(int errorNum)
Definition: Debug.H:132
#define IIOMMAP_NOINIT_ERROR
The MMapedBlocks system is not initialised.
Definition: IIOChannel.H:47
__u32 offset
Definition: IIOMMap.H:51
#define IIOMMAP_QUERY_ERROR
Couldn&#39;t query the iio device for allocated kernel memory.
Definition: IIOChannel.H:44
unsigned short * addr
Definition: IIOMMap.H:58
int close(void)
Definition: IIOMMap.H:255
#define NO_ERROR
There is no error.
Definition: Debug.H:33
void deAllocate()
Definition: IIOMMap.H:84
void memoryUnmap()
Definition: IIOMMap.H:124
The iio_channel_info structure is external.
Definition: IIO.H:72
__u64 timestamp
Definition: IIOMMap.H:53
int read(uint N, const Eigen::Array< TYPE, Eigen::Dynamic, Eigen::Dynamic > &array)
Definition: IIOMMap.H:267
#define IIODEVICE_READ_ERROR
There was an error whilst reading from a device.
Definition: IIOChannel.H:38
int allocate()
Definition: IIOMMap.H:72
unsigned int uint
Definition: Box.H:28
#define IIO_ARRAY_FRAME_MISMATCH_ERROR
The sample type of the provided array doesn&#39;t match the sample type of the devices.
Definition: IIOChannel.H:36
int reset(int fdIn)
Definition: IIOMMap.H:151
__u32 bytes_used
Definition: IIOMMap.H:47
vector< struct block > blocks
The block information and address.
Definition: IIOMMap.H:131
Definition: IIOMMap.H:56
int reset(int fdIn, int count, int size)
Definition: IIOMMap.H:161
virtual ~IIOMMap()
Destructor.
Definition: IIOMMap.H:192
vector< MMappedBlocks > mMappedBlocks
The memory mapped blocks.
Definition: IIOMMap.H:187
#define DEFAULT_BLOCK_SIZE
Definition: IIOMMap.H:62
int close(void)
Definition: IIO.H:179
#define DEFAULT_BLOCK_COUNT
Definition: IIOMMap.H:61
int resizeMMapBlocks(int count, int sizeIn)
Definition: IIOMMap.H:239
#define IIO_ARRAY_SIZE_MISMATCH_ERROR
The provided array doesn&#39;t match the number of channels and requested samples.
Definition: IIOChannel.H:37
#define IIOMMAP_ENQUEUE_ERROR
Couldn&#39;t enqueue the mmaped block.
Definition: IIOChannel.H:46
~MMappedBlocks()
Destructor.
Definition: IIOMMap.H:142
#define IIOMMAP_BLOCK_SIZE_MISMATCH_ERROR
The user and mmaped block sizes don&#39;t match.
Definition: IIOChannel.H:49
#define IIO_NODEVICES_ERROR
There are no devices.
Definition: IIOChannel.H:35
double getMaxDelay(float fs)
Definition: IIOMMap.H:317
int open(int count, int sizeIn)
Definition: IIOMMap.H:208
int memoryMap()
Definition: IIOMMap.H:92
int open(void)
Definition: IIOMMap.H:199
#define IIOMMAP_MMAP_ERROR
Couldn&#39;t execute mmap.
Definition: IIOChannel.H:45
#define IIO_BLOCK_QUERY_IOCTL
Definition: IIOMMap.H:33
#define IIO_BLOCK_FREE_IOCTL
Definition: IIOMMap.H:32
#define IIO_BLOCK_ENQUEUE_IOCTL
Definition: IIOMMap.H:34
#define IIO_BLOCK_ALLOC_IOCTL
Definition: IIOMMap.H:31
gtkIOStream: /tmp/gtkiostream/include/IIO/IIOMMap.H Source File
GTK+ IOStream  Beta