iio: Fixed device id check bug
[contrib/mraa.git] / src / iio / iio.c
1 /*
2  * Author: Brendan Le Foll <brendan.le.foll@intel.com>
3  * Copyright (c) 2015 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 #include "iio.h"
26 #include "mraa_internal.h"
27 #include "dirent.h"
28 #include <string.h>
29 #include <poll.h>
30 #include <stropts.h>
31
32 #define MAX_SIZE 128
33 #define IIO_DEVICE "iio:device"
34 #define IIO_SCAN_ELEM "scan_elements"
35 #define IIO_MOUNTING_MATRIX "mounting_matrix"
36 #define IIO_SLASH_DEV "/dev/" IIO_DEVICE
37 #define IIO_SYSFS_DEVICE "/sys/bus/iio/devices/" IIO_DEVICE
38 #define IIO_EVENTS "events"
39 #define IIO_CONFIGFS_TRIGGER "/sys/kernel/config/iio/triggers/"
40
41 mraa_iio_context
42 mraa_iio_init(int device)
43 {
44     if (plat_iio->iio_device_count == 0 || device >= plat_iio->iio_device_count) {
45         return NULL;
46     }
47
48     mraa_iio_get_channel_data(&plat_iio->iio_devices[device]);
49     mraa_iio_get_event_data(&plat_iio->iio_devices[device]);
50
51     return &plat_iio->iio_devices[device];
52 }
53
54 int
55 mraa_iio_read_size(mraa_iio_context dev)
56 {
57     return dev->datasize;
58 }
59
60 mraa_iio_channel*
61 mraa_iio_get_channels(mraa_iio_context dev)
62 {
63     return dev->channels;
64 }
65
66 int
67 mraa_iio_get_channel_count(mraa_iio_context dev)
68 {
69     return dev->chan_num;
70 }
71
72 mraa_result_t
73 mraa_iio_get_channel_data(mraa_iio_context dev)
74 {
75     const struct dirent* ent;
76     DIR* dir;
77     int chan_num = 0;
78     char buf[MAX_SIZE];
79     char readbuf[32];
80     int fd;
81     int ret = 0;
82     int padint = 0;
83     int curr_bytes = 0;
84     char shortbuf, signchar;
85
86     dev->datasize = 0;
87
88     memset(buf, 0, MAX_SIZE);
89     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_SCAN_ELEM, dev->num);
90     dir = opendir(buf);
91     if (dir != NULL) {
92         while ((ent = readdir(dir)) != NULL) {
93             if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) {
94                 chan_num++;
95             }
96         }
97     }
98     dev->chan_num = chan_num;
99     // no need proceed if no channel found
100     if (chan_num == 0)
101         return MRAA_SUCCESS;
102     mraa_iio_channel* chan;
103     dev->channels = calloc(chan_num, sizeof(mraa_iio_channel));
104     seekdir(dir, 0);
105     while ((ent = readdir(dir)) != NULL) {
106         if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_index"), "_index") == 0) {
107             snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_SCAN_ELEM "/%s", dev->num, ent->d_name);
108             fd = open(buf, O_RDONLY);
109             if (fd > 0) {
110                 if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
111                     break;
112                 }
113                 chan_num = ((int) strtol(readbuf, NULL, 10));
114                 chan = &dev->channels[chan_num];
115                 chan->index = chan_num;
116                 close(fd);
117
118                 buf[(strlen(buf) - 5)] = '\0';
119                 char* str = strdup(buf);
120                 // grab the type of the buffer
121                 snprintf(buf, MAX_SIZE, "%stype", str);
122                 fd = open(buf, O_RDONLY);
123                 if (fd > 0) {
124                     read(fd, readbuf, 31 * sizeof(char));
125                     ret = sscanf(readbuf, "%ce:%c%u/%u>>%u", &shortbuf, &signchar, &chan->bits_used,
126                                  &padint, &chan->shift);
127                     chan->bytes = padint / 8;
128                     if (curr_bytes % chan->bytes == 0) {
129                         chan->location = curr_bytes;
130                     } else {
131                         chan->location = curr_bytes - curr_bytes % chan->bytes + chan->bytes;
132                     }
133                     curr_bytes = chan->location + chan->bytes;
134                     // probably should be 5?
135                     if (ret < 0) {
136                         // cleanup
137                         free(str);
138                         close(fd);
139                         return MRAA_IO_SETUP_FAILURE;
140                     }
141                     chan->signedd = (signchar == 's');
142                     chan->lendian = (shortbuf == 'l');
143                     if (chan->bits_used == 64) {
144                         chan->mask = ~0;
145                     } else {
146                         chan->mask = (1 << chan->bits_used) - 1;
147                     }
148                     close(fd);
149                 }
150                 // grab the enable flag of channel
151                 snprintf(buf, MAX_SIZE, "%sen", str);
152                 fd = open(buf, O_RDONLY);
153                 if (fd > 0) {
154                     if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
155                         syslog(LOG_ERR, "iio: Failed to read a sensible value from sysfs");
156                         return -1;
157                     }
158                     chan->enabled = (int) strtol(readbuf, NULL, 10);
159                     // only calculate enable buffer size for trigger buffer extract data
160                     if (chan->enabled) {
161                         dev->datasize += chan->bytes;
162                     }
163                     close(fd);
164                 }
165                 // clean up str var
166                 free(str);
167             }
168         }
169     }
170
171     return MRAA_SUCCESS;
172 }
173
174 const char*
175 mraa_iio_get_device_name(mraa_iio_context dev)
176 {
177     return dev->name;
178 }
179
180 int
181 mraa_iio_get_device_num_by_name(const char* name)
182 {
183     int i;
184
185     if (plat_iio == NULL) {
186         syslog(LOG_ERR, "iio: platform IIO structure is not initialized");
187         return -1;
188     }
189
190     if (name == NULL) {
191         syslog(LOG_ERR, "iio: device name is NULL, unable to find its number");
192         return -1;
193     }
194
195     for (i = 0; i < plat_iio->iio_device_count; i++) {
196         struct _iio* device;
197         device = &plat_iio->iio_devices[i];
198         // we want to check for exact match
199         if (strncmp(device->name, name, strlen(device->name) + 1) == 0) {
200             return device->num;
201         }
202     }
203
204     return -1;
205 }
206
207 mraa_result_t
208 mraa_iio_read_float(mraa_iio_context dev, const char* attr_name, float* data)
209 {
210     char buf[MAX_SIZE];
211     mraa_result_t result = mraa_iio_read_string(dev, attr_name, buf);
212     if (result != MRAA_SUCCESS)
213         return result;
214     int status = sscanf(buf, "%f", data);
215     result = status == 1 ? MRAA_SUCCESS : MRAA_ERROR_UNSPECIFIED;
216     return result;
217 }
218
219
220 mraa_result_t
221 mraa_iio_read_integer(mraa_iio_context dev, const char* attr_name, int* data)
222 {
223     char buf[MAX_SIZE];
224     mraa_result_t result = mraa_iio_read_string(dev, attr_name, buf);
225     if (result != MRAA_SUCCESS)
226         return result;
227     int status = sscanf(buf, "%d", data);
228     result = status == 1 ? MRAA_SUCCESS : MRAA_ERROR_UNSPECIFIED;
229     return result;
230 }
231
232 mraa_result_t
233 mraa_iio_read_string(mraa_iio_context dev, const char* attr_name, char* data)
234 {
235     char buf[MAX_SIZE];
236     mraa_result_t result = MRAA_ERROR_UNSPECIFIED;
237     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/%s", dev->num, attr_name);
238     int fd = open(buf, O_RDONLY);
239     if (fd != -1) {
240         ssize_t len = read(fd, data, MAX_SIZE);
241         if (len > 0)
242             result = MRAA_SUCCESS;
243         close(fd);
244     }
245     return result;
246
247 }
248
249 mraa_result_t
250 mraa_iio_write_float(mraa_iio_context dev, const char* attr_name, const float data)
251 {
252     char buf[MAX_SIZE];
253     snprintf(buf, MAX_SIZE, "%f", data);
254     return mraa_iio_write_string(dev, attr_name, buf);
255 }
256
257 mraa_result_t
258 mraa_iio_write_integer(mraa_iio_context dev, const char* attr_name, const int data)
259 {
260     char buf[MAX_SIZE];
261     snprintf(buf, MAX_SIZE, "%d", data);
262     return mraa_iio_write_string(dev, attr_name, buf);
263 }
264
265 mraa_result_t
266 mraa_iio_write_string(mraa_iio_context dev, const char* attr_name, const char* data)
267 {
268     char buf[MAX_SIZE];
269     mraa_result_t result = MRAA_ERROR_UNSPECIFIED;
270     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/%s", dev->num, attr_name);
271     int fd = open(buf, O_WRONLY);
272     if (fd != -1) {
273         size_t len = strlen(data);
274         ssize_t status = write(fd, data, len);
275         if (status == len)
276              result = MRAA_SUCCESS;
277         close(fd);
278     }
279     return result;
280 }
281
282 static mraa_result_t
283 mraa_iio_wait_event(int fd, char* data, int* read_size)
284 {
285     struct pollfd pfd;
286
287     if (fd < 0) {
288         return MRAA_ERROR_INVALID_RESOURCE;
289     }
290
291     pfd.fd = fd;
292     pfd.events = POLLIN;
293
294     // Wait for it forever or until pthread_cancel
295     // poll is a cancelable point like sleep()
296     int x = poll(&pfd, 1, -1);
297
298     memset(data, 0, 100);
299     *read_size = read(fd, data, 100);
300
301     return MRAA_SUCCESS;
302 }
303
304 static void*
305 mraa_iio_trigger_handler(void* arg)
306 {
307     mraa_iio_context dev = (mraa_iio_context) arg;
308     int i;
309     char data[MAX_SIZE * 100];
310     int read_size;
311
312     for (;;) {
313         if (mraa_iio_wait_event(dev->fp, &data[0], &read_size) == MRAA_SUCCESS) {
314             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
315             // only can process if readsize >= enabled channel's datasize
316             for (i = 0; i < (read_size / dev->datasize); i++) {
317                 dev->isr((void*)&data);
318             }
319             pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
320         } else {
321             // we must have got an error code so die nicely
322             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
323             return NULL;
324         }
325     }
326 }
327
328 mraa_result_t
329 mraa_iio_trigger_buffer(mraa_iio_context dev, void (*fptr)(char* data), void* args)
330 {
331     char bu[MAX_SIZE];
332     if (dev->thread_id != 0) {
333         return MRAA_ERROR_NO_RESOURCES;
334     }
335
336     sprintf(bu, IIO_SLASH_DEV "%d", dev->num);
337     dev->fp = open(bu, O_RDONLY | O_NONBLOCK);
338     if (dev->fp == -1) {
339         return MRAA_ERROR_INVALID_RESOURCE;
340     }
341
342     dev->isr = fptr;
343     pthread_create(&dev->thread_id, NULL, mraa_iio_trigger_handler, (void*) dev);
344
345     return MRAA_SUCCESS;
346 }
347
348 mraa_result_t
349 mraa_iio_get_event_data(mraa_iio_context dev)
350 {
351     const struct dirent* ent;
352     DIR* dir;
353     int event_num = 0;
354     char buf[MAX_SIZE];
355     char readbuf[32];
356     int fd;
357     int ret = 0;
358     int padint = 0;
359     int curr_bytes = 0;
360     char shortbuf, signchar;
361     memset(buf, 0, MAX_SIZE);
362     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_EVENTS, dev->num);
363     dir = opendir(buf);
364     if (dir != NULL) {
365         while ((ent = readdir(dir)) != NULL) {
366             if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) {
367                 event_num++;
368             }
369         }
370         dev->event_num = event_num;
371         // no need proceed if no event found
372         if (event_num == 0)
373             return MRAA_SUCCESS;
374         mraa_iio_event* event;
375         dev->events = calloc(event_num, sizeof(mraa_iio_event));
376         if (dev->events == NULL) {
377             closedir(dir);
378             return MRAA_ERROR_UNSPECIFIED;
379         }
380         rewinddir(dir);
381         event_num = 0;
382         while ((ent = readdir(dir)) != NULL) {
383             if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) {
384                 event = &dev->events[event_num];
385                 event->name = strdup(ent->d_name);
386                 snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_EVENTS "/%s", dev->num, ent->d_name);
387                 fd = open(buf, O_RDONLY);
388                 if (fd > 0) {
389                     if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
390                         break;
391                     }
392                     close(fd);
393                 }
394                 event->enabled = ((int) strtol(readbuf, NULL, 10));
395                 // Todo, read other event info.
396                 event_num++;
397             }
398         }
399         closedir(dir);
400     }
401     return MRAA_SUCCESS;
402 }
403
404 static mraa_result_t
405 mraa_iio_event_poll_nonblock(int fd, struct iio_event_data* data)
406 {
407     struct pollfd pfd;
408
409     if (fd < 0) {
410         return MRAA_ERROR_INVALID_RESOURCE;
411     }
412
413     pfd.fd = fd;
414     pfd.events = POLLIN;
415
416     // Wait for it forever or until pthread_cancel
417     // poll is a cancelable point like sleep()
418     int x = poll(&pfd, 1, -1);
419
420     read(fd, data, sizeof(struct iio_event_data));
421
422     return MRAA_SUCCESS;
423 }
424
425 mraa_result_t
426 mraa_iio_event_poll(mraa_iio_context dev, struct iio_event_data* data)
427 {
428     char bu[MAX_SIZE];
429     int ret;
430     int event_fd;
431     int fd;
432
433     sprintf(bu, IIO_SLASH_DEV "%d", dev->num);
434     fd = open(bu, 0);
435     ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
436     close(fd);
437
438     if (ret == -1 || event_fd == -1)
439         return MRAA_ERROR_UNSPECIFIED;
440
441     ret = read(event_fd, data, sizeof(struct iio_event_data));
442
443     close(event_fd);
444     return MRAA_SUCCESS;
445 }
446
447 static void*
448 mraa_iio_event_handler(void* arg)
449 {
450     struct iio_event_data data;
451     mraa_iio_context dev = (mraa_iio_context) arg;
452
453     for (;;) {
454         if (mraa_iio_event_poll_nonblock(dev->fp_event, &data) == MRAA_SUCCESS) {
455             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
456             dev->isr_event(&data);
457             pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
458         } else {
459             // we must have got an error code so die nicely
460             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
461             return NULL;
462         }
463     }
464 }
465
466 mraa_result_t
467 mraa_iio_event_setup_callback(mraa_iio_context dev, void (*fptr)(struct iio_event_data* data), void* args)
468 {
469     int ret;
470     char bu[MAX_SIZE];
471     if (dev->thread_id != 0) {
472         return MRAA_ERROR_NO_RESOURCES;
473     }
474
475     sprintf(bu, IIO_SLASH_DEV "%d", dev->num);
476     dev->fp = open(bu, O_RDONLY | O_NONBLOCK);
477     if (dev->fp == -1) {
478         return MRAA_ERROR_INVALID_RESOURCE;
479     }
480     ret = ioctl(dev->fp, IIO_GET_EVENT_FD_IOCTL, &dev->fp_event);
481     close(dev->fp);
482
483     if (ret == -1 || dev->fp_event == -1) {
484         return MRAA_ERROR_UNSPECIFIED;
485     }
486
487     dev->isr_event = fptr;
488     pthread_create(&dev->thread_id, NULL, mraa_iio_event_handler, (void*) dev);
489
490     return MRAA_SUCCESS;
491 }
492
493 mraa_result_t
494 mraa_iio_event_extract_event(struct iio_event_data* event,
495                              int* chan_type,
496                              int* modifier,
497                              int* type,
498                              int* direction,
499                              int* channel,
500                              int* channel2,
501                              int* different)
502 {
503     *chan_type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
504     *modifier = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
505     *type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
506     *direction = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
507     *channel = IIO_EVENT_CODE_EXTRACT_CHAN(event->id);
508     *channel2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id);
509     *different = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
510     return MRAA_SUCCESS;
511 }
512
513 mraa_result_t
514 mraa_iio_get_mounting_matrix(mraa_iio_context dev, float mm[9])
515 {
516     char buf[MAX_SIZE];
517     FILE* fp;
518
519     memset(buf, 0, MAX_SIZE);
520     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_MOUNTING_MATRIX, dev->num);
521     fp = fopen(buf, "r");
522     if (fp != NULL) {
523         fscanf(fp, "%f %f %f\n%f %f %f\n%f %f %f\n", &mm[0], &mm[1], &mm[2], &mm[3], &mm[4], &mm[5],
524                &mm[6], &mm[7], &mm[8]);
525         fclose(fp);
526         return MRAA_SUCCESS;
527     }
528     return MRAA_ERROR_UNSPECIFIED;
529 }
530
531 mraa_result_t
532 mraa_iio_create_trigger(mraa_iio_context dev, const char* trigger)
533 {
534     struct stat configfs_status;
535     struct stat trigger_status;
536     char buf[MAX_SIZE];
537
538     if (stat(IIO_CONFIGFS_TRIGGER, &configfs_status) == 0) {
539         memset(buf, 0, MAX_SIZE);
540         snprintf(buf, MAX_SIZE, IIO_CONFIGFS_TRIGGER "%s", trigger);
541         if (stat(buf, &trigger_status) != 0) {
542             if (mkdir(buf, configfs_status.st_mode) == 0)
543                 return MRAA_SUCCESS;
544         } else {
545             // trigger folder already created
546             return MRAA_SUCCESS;
547         }
548     }
549
550     return MRAA_ERROR_UNSPECIFIED;
551 }
552
553 mraa_result_t
554 mraa_iio_update_channels(mraa_iio_context dev)
555 {
556     const struct dirent* ent;
557     DIR* dir;
558     int chan_num = 0;
559     char buf[MAX_SIZE];
560     char readbuf[32];
561     int fd;
562     mraa_iio_channel* chan;
563
564     dev->datasize = 0;
565     memset(buf, 0, MAX_SIZE);
566     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_SCAN_ELEM, dev->num);
567     dir = opendir(buf);
568     if (dir != NULL) {
569         while ((ent = readdir(dir)) != NULL) {
570             if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_index"), "_index") == 0) {
571                 snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_SCAN_ELEM "/%s", dev->num, ent->d_name);
572                 fd = open(buf, O_RDONLY);
573                 if (fd > 0) {
574                     if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
575                         break;
576                     }
577                     chan_num = ((int) strtol(readbuf, NULL, 10));
578                     chan = &dev->channels[chan_num];
579                     chan->index = chan_num;
580                     close(fd);
581
582                     buf[(strlen(buf) - 5)] = '\0';
583                     char* str = strdup(buf);
584                     // grab the enable flag of channel
585                     snprintf(buf, MAX_SIZE, "%sen", str);
586                     fd = open(buf, O_RDONLY);
587                     if (fd > 0) {
588                         if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
589                             syslog(LOG_ERR, "iio: Failed to read a sensible value from sysfs");
590                             return -1;
591                         }
592                         chan->enabled = (int) strtol(readbuf, NULL, 10);
593                         // only calculate enable buffer size for trigger buffer extract data
594                         if (chan->enabled) {
595                             dev->datasize += chan->bytes;
596                         }
597                         close(fd);
598                     }
599                     // clean up str var
600                     free(str);
601                 }
602             }
603         }
604     }
605     return MRAA_SUCCESS;
606 }
607
608 mraa_result_t
609 mraa_iio_stop(mraa_iio_context dev)
610 {
611     free(dev->channels);
612     return MRAA_SUCCESS;
613 }