iio: mraa_iio_write_string now using open insteam of fopen
[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 (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* filename, float* data)
209 {
210     char buf[MAX_SIZE];
211     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/%s", dev->num, filename);
212     FILE* fp = fopen(buf, "r");
213     if (fp != NULL) {
214         fscanf(fp, "%f\n", data);
215         fclose(fp);
216         return MRAA_SUCCESS;
217     }
218     return MRAA_ERROR_UNSPECIFIED;
219 }
220
221 mraa_result_t
222 mraa_iio_read_integer(mraa_iio_context dev, const char* filename, int* data)
223 {
224     char buf[MAX_SIZE];
225     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/%s", dev->num, filename);
226     FILE* fp = fopen(buf, "r");
227     if (fp != NULL) {
228         fscanf(fp, "%d\n", data);
229         fclose(fp);
230         return MRAA_SUCCESS;
231     }
232     return MRAA_ERROR_UNSPECIFIED;
233 }
234
235 mraa_result_t
236 mraa_iio_read_string(mraa_iio_context dev, const char* filename, char* data)
237 {
238     char buf[MAX_SIZE];
239     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/%s", dev->num, filename);
240     FILE* fp = fopen(buf, "r");
241     if (fp != NULL) {
242         fscanf(fp, "%s\n", data);
243         fclose(fp);
244         return MRAA_SUCCESS;
245     }
246     return MRAA_ERROR_UNSPECIFIED;
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* filename, const int data)
259 {
260     char buf[MAX_SIZE];
261     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/%s", dev->num, filename);
262     FILE* fp = fopen(buf, "w");
263     if (fp != NULL) {
264         fprintf(fp, "%d", data);
265         fclose(fp);
266         return MRAA_SUCCESS;
267     }
268     return MRAA_ERROR_UNSPECIFIED;
269 }
270
271 mraa_result_t
272 mraa_iio_write_string(mraa_iio_context dev, const char* attr_name, const char* data)
273 {
274     char buf[MAX_SIZE];
275     mraa_result_t result = MRAA_ERROR_UNSPECIFIED;
276     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/%s", dev->num, attr_name);
277     int fh = open(buf, O_RDWR);
278     if (fh != -1) {
279         size_t len = strlen(data);
280         ssize_t status = write(fh, data, len);
281         printf("mraa_iio_write_string status %d\n", status);
282         if (status == len)
283              result = MRAA_SUCCESS;
284     }
285     return result;
286 }
287
288 static mraa_result_t
289 mraa_iio_wait_event(int fd, char* data, int* read_size)
290 {
291     struct pollfd pfd;
292
293     if (fd < 0) {
294         return MRAA_ERROR_INVALID_RESOURCE;
295     }
296
297     pfd.fd = fd;
298     pfd.events = POLLIN;
299
300     // Wait for it forever or until pthread_cancel
301     // poll is a cancelable point like sleep()
302     int x = poll(&pfd, 1, -1);
303
304     memset(data, 0, 100);
305     *read_size = read(fd, data, 100);
306
307     return MRAA_SUCCESS;
308 }
309
310 static void*
311 mraa_iio_trigger_handler(void* arg)
312 {
313     mraa_iio_context dev = (mraa_iio_context) arg;
314     int i;
315     char data[MAX_SIZE * 100];
316     int read_size;
317
318     for (;;) {
319         if (mraa_iio_wait_event(dev->fp, &data[0], &read_size) == MRAA_SUCCESS) {
320             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
321             // only can process if readsize >= enabled channel's datasize
322             for (i = 0; i < (read_size / dev->datasize); i++) {
323                 dev->isr(&data);
324             }
325             pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
326         } else {
327             // we must have got an error code so die nicely
328             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
329             return NULL;
330         }
331     }
332 }
333
334 mraa_result_t
335 mraa_iio_trigger_buffer(mraa_iio_context dev, void (*fptr)(char* data), void* args)
336 {
337     char bu[MAX_SIZE];
338     if (dev->thread_id != 0) {
339         return MRAA_ERROR_NO_RESOURCES;
340     }
341
342     sprintf(bu, IIO_SLASH_DEV "%d", dev->num);
343     dev->fp = open(bu, O_RDONLY | O_NONBLOCK);
344     if (dev->fp == -1) {
345         return MRAA_ERROR_INVALID_RESOURCE;
346     }
347
348     dev->isr = fptr;
349     pthread_create(&dev->thread_id, NULL, mraa_iio_trigger_handler, (void*) dev);
350
351     return MRAA_SUCCESS;
352 }
353
354 mraa_result_t
355 mraa_iio_get_event_data(mraa_iio_context dev)
356 {
357     const struct dirent* ent;
358     DIR* dir;
359     int event_num = 0;
360     char buf[MAX_SIZE];
361     char readbuf[32];
362     int fd;
363     int ret = 0;
364     int padint = 0;
365     int curr_bytes = 0;
366     char shortbuf, signchar;
367     memset(buf, 0, MAX_SIZE);
368     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_EVENTS, dev->num);
369     dir = opendir(buf);
370     if (dir != NULL) {
371         while ((ent = readdir(dir)) != NULL) {
372             if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) {
373                 event_num++;
374             }
375         }
376         dev->event_num = event_num;
377         // no need proceed if no event found
378         if (event_num == 0)
379             return MRAA_SUCCESS;
380         mraa_iio_event* event;
381         dev->events = calloc(event_num, sizeof(mraa_iio_event));
382         if (dev->events == NULL) {
383             closedir(dir);
384             return MRAA_ERROR_UNSPECIFIED;
385         }
386         rewinddir(dir);
387         event_num = 0;
388         while ((ent = readdir(dir)) != NULL) {
389             if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"), "_en") == 0) {
390                 event = &dev->events[event_num];
391                 event->name = strdup(ent->d_name);
392                 snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_EVENTS "/%s", dev->num, ent->d_name);
393                 fd = open(buf, O_RDONLY);
394                 if (fd > 0) {
395                     if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
396                         break;
397                     }
398                     close(fd);
399                 }
400                 event->enabled = ((int) strtol(readbuf, NULL, 10));
401                 // Todo, read other event info.
402                 event_num++;
403             }
404         }
405         closedir(dir);
406     }
407     return MRAA_SUCCESS;
408 }
409
410 static mraa_result_t
411 mraa_iio_event_poll_nonblock(int fd, struct iio_event_data* data)
412 {
413     struct pollfd pfd;
414
415     if (fd < 0) {
416         return MRAA_ERROR_INVALID_RESOURCE;
417     }
418
419     pfd.fd = fd;
420     pfd.events = POLLIN;
421
422     // Wait for it forever or until pthread_cancel
423     // poll is a cancelable point like sleep()
424     int x = poll(&pfd, 1, -1);
425
426     read(fd, data, sizeof(struct iio_event_data));
427
428     return MRAA_SUCCESS;
429 }
430
431 mraa_result_t
432 mraa_iio_event_poll(mraa_iio_context dev, struct iio_event_data* data)
433 {
434     char bu[MAX_SIZE];
435     int ret;
436     int event_fd;
437     int fd;
438
439     sprintf(bu, IIO_SLASH_DEV "%d", dev->num);
440     fd = open(bu, 0);
441     ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
442     close(fd);
443
444     if (ret == -1 || event_fd == -1)
445         return MRAA_ERROR_UNSPECIFIED;
446
447     ret = read(event_fd, data, sizeof(struct iio_event_data));
448
449     close(event_fd);
450     return MRAA_SUCCESS;
451 }
452
453 static void*
454 mraa_iio_event_handler(void* arg)
455 {
456     struct iio_event_data data;
457     mraa_iio_context dev = (mraa_iio_context) arg;
458
459     for (;;) {
460         if (mraa_iio_event_poll_nonblock(dev->fp_event, &data) == MRAA_SUCCESS) {
461             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
462             dev->isr_event(&data);
463             pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
464         } else {
465             // we must have got an error code so die nicely
466             pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
467             return NULL;
468         }
469     }
470 }
471
472 mraa_result_t
473 mraa_iio_event_setup_callback(mraa_iio_context dev, void (*fptr)(struct iio_event_data* data), void* args)
474 {
475     int ret;
476     char bu[MAX_SIZE];
477     if (dev->thread_id != 0) {
478         return MRAA_ERROR_NO_RESOURCES;
479     }
480
481     sprintf(bu, IIO_SLASH_DEV "%d", dev->num);
482     dev->fp = open(bu, O_RDONLY | O_NONBLOCK);
483     if (dev->fp == -1) {
484         return MRAA_ERROR_INVALID_RESOURCE;
485     }
486     ret = ioctl(dev->fp, IIO_GET_EVENT_FD_IOCTL, &dev->fp_event);
487     close(dev->fp);
488
489     if (ret == -1 || dev->fp_event == -1) {
490         return MRAA_ERROR_UNSPECIFIED;
491     }
492
493     dev->isr_event = fptr;
494     pthread_create(&dev->thread_id, NULL, mraa_iio_event_handler, (void*) dev);
495
496     return MRAA_SUCCESS;
497 }
498
499 mraa_result_t
500 mraa_iio_event_extract_event(struct iio_event_data* event,
501                              int* chan_type,
502                              int* modifier,
503                              int* type,
504                              int* direction,
505                              int* channel,
506                              int* channel2,
507                              int* different)
508 {
509     *chan_type = IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id);
510     *modifier = IIO_EVENT_CODE_EXTRACT_MODIFIER(event->id);
511     *type = IIO_EVENT_CODE_EXTRACT_TYPE(event->id);
512     *direction = IIO_EVENT_CODE_EXTRACT_DIR(event->id);
513     *channel = IIO_EVENT_CODE_EXTRACT_CHAN(event->id);
514     *channel2 = IIO_EVENT_CODE_EXTRACT_CHAN2(event->id);
515     *different = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
516     return MRAA_SUCCESS;
517 }
518
519 mraa_result_t
520 mraa_iio_get_mounting_matrix(mraa_iio_context dev, float mm[9])
521 {
522     char buf[MAX_SIZE];
523     FILE* fp;
524
525     memset(buf, 0, MAX_SIZE);
526     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_MOUNTING_MATRIX, dev->num);
527     fp = fopen(buf, "r");
528     if (fp != NULL) {
529         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],
530                &mm[6], &mm[7], &mm[8]);
531         fclose(fp);
532         return MRAA_SUCCESS;
533     }
534     return MRAA_ERROR_UNSPECIFIED;
535 }
536
537 mraa_result_t
538 mraa_iio_create_trigger(mraa_iio_context dev, const char* trigger)
539 {
540     struct stat configfs_status;
541     struct stat trigger_status;
542     char buf[MAX_SIZE];
543
544     if (stat(IIO_CONFIGFS_TRIGGER, &configfs_status) == 0) {
545         memset(buf, 0, MAX_SIZE);
546         snprintf(buf, MAX_SIZE, IIO_CONFIGFS_TRIGGER "%s", trigger);
547         if (stat(buf, &trigger_status) != 0) {
548             if (mkdir(buf, configfs_status.st_mode) == 0)
549                 return MRAA_SUCCESS;
550         } else {
551             // trigger folder already created
552             return MRAA_SUCCESS;
553         }
554     }
555
556     return MRAA_ERROR_UNSPECIFIED;
557 }
558
559 mraa_result_t
560 mraa_iio_update_channels(mraa_iio_context dev)
561 {
562     const struct dirent* ent;
563     DIR* dir;
564     int chan_num = 0;
565     char buf[MAX_SIZE];
566     char readbuf[32];
567     int fd;
568     mraa_iio_channel* chan;
569
570     dev->datasize = 0;
571     memset(buf, 0, MAX_SIZE);
572     snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_SCAN_ELEM, dev->num);
573     dir = opendir(buf);
574     if (dir != NULL) {
575         while ((ent = readdir(dir)) != NULL) {
576             if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_index"), "_index") == 0) {
577                 snprintf(buf, MAX_SIZE, IIO_SYSFS_DEVICE "%d/" IIO_SCAN_ELEM "/%s", dev->num, ent->d_name);
578                 fd = open(buf, O_RDONLY);
579                 if (fd > 0) {
580                     if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
581                         break;
582                     }
583                     chan_num = ((int) strtol(readbuf, NULL, 10));
584                     chan = &dev->channels[chan_num];
585                     chan->index = chan_num;
586                     close(fd);
587
588                     buf[(strlen(buf) - 5)] = '\0';
589                     char* str = strdup(buf);
590                     // grab the enable flag of channel
591                     snprintf(buf, MAX_SIZE, "%sen", str);
592                     fd = open(buf, O_RDONLY);
593                     if (fd > 0) {
594                         if (read(fd, readbuf, 2 * sizeof(char)) != 2) {
595                             syslog(LOG_ERR, "iio: Failed to read a sensible value from sysfs");
596                             return -1;
597                         }
598                         chan->enabled = (int) strtol(readbuf, NULL, 10);
599                         // only calculate enable buffer size for trigger buffer extract data
600                         if (chan->enabled) {
601                             dev->datasize += chan->bytes;
602                         }
603                         close(fd);
604                     }
605                     // clean up str var
606                     free(str);
607                 }
608             }
609         }
610     }
611     return MRAA_SUCCESS;
612 }
613 #if 0
614 // does stop make any sense on iio devices?
615 mraa_result_t
616 mraa_iio_stop(mraa_iio_context dev)
617 {
618     return MRAA_SUCCESS;
619 }
620 #endif