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