bdc91bc8affde34003f59efeb0c0ae569247e06a
[contrib/mraa.git] / src / mraa.c
1 /*
2  * Author: Brendan Le Foll <brendan.le.foll@intel.com>
3  * Author: Thomas Ingleby <thomas.c.ingleby@intel.com>
4  * Copyright (c) 2014 Intel Corporation.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 #define _GNU_SOURCE
27 #if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
28 #define _XOPEN_SOURCE 600 /* Get nftw() and S_IFSOCK declarations */
29 #endif
30
31 #include <stddef.h>
32 #include <stdlib.h>
33 #include <sched.h>
34 #include <string.h>
35 #include <pwd.h>
36 #include <glob.h>
37 #include <ftw.h>
38 #include <dirent.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <string.h>
42 #include <stdio.h>
43
44 #include "mraa_internal.h"
45 #include "gpio.h"
46 #include "version.h"
47
48 #define MAX_PLATFORM_NAME_LENGTH 128
49 mraa_board_t* plat = NULL;
50 // static mraa_board_t* current_plat = NULL;
51
52 static char platform_name[MAX_PLATFORM_NAME_LENGTH];
53 mraa_adv_func_t* advance_func;
54
55 static int num_i2c_devices = 0;
56 static int num_iio_devices = 0;
57
58 const char*
59 mraa_get_version()
60 {
61     return gVERSION;
62 }
63
64 mraa_result_t
65 mraa_set_log_level(int level)
66 {
67     if (level <= 7 && level >= 0) {
68         setlogmask(LOG_UPTO(level));
69         syslog(LOG_DEBUG, "Loglevel %d is set", level);
70         return MRAA_SUCCESS;
71     }
72     syslog(LOG_NOTICE, "Invalid loglevel %d requested", level);
73     return MRAA_ERROR_INVALID_PARAMETER;
74 }
75
76 static int
77 mraa_count_iio_devices(const char* path, const struct stat* sb, int flag, struct FTW* ftwb)
78 {
79     switch (sb->st_mode & S_IFMT) {
80         case S_IFLNK:
81             num_iio_devices++;
82             break;
83     }
84     return 0;
85 }
86
87 #if (defined SWIGPYTHON) || (defined SWIG)
88 mraa_result_t
89 #else
90 mraa_result_t __attribute__((constructor))
91 #endif
92 mraa_init()
93 {
94     if (plat != NULL) {
95         return MRAA_ERROR_PLATFORM_ALREADY_INITIALISED;
96     }
97
98     uid_t proc_euid = geteuid();
99     struct passwd* proc_user = getpwuid(proc_euid);
100
101 #ifdef DEBUG
102     setlogmask(LOG_UPTO(LOG_DEBUG));
103 #else
104     setlogmask(LOG_UPTO(LOG_NOTICE));
105 #endif
106
107     openlog("libmraa", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
108     syslog(LOG_NOTICE, "libmraa version %s initialised by user '%s' with EUID %d",
109            mraa_get_version(), (proc_user != NULL) ? proc_user->pw_name : "<unknown>", proc_euid);
110
111 #ifdef SWIGPYTHON
112     // Initialise python threads, this allows use to grab the GIL when we are
113     // required to do so
114     Py_InitializeEx(0);
115     PyEval_InitThreads();
116 #endif
117
118     advance_func = (mraa_adv_func_t*) malloc(sizeof(mraa_adv_func_t));
119     memset(advance_func, 0, sizeof(mraa_adv_func_t));
120
121     mraa_platform_t platform_type;
122 #if defined(X86PLAT)
123     // Use runtime x86 platform detection
124     platform_type = mraa_x86_platform();
125 #elif defined(ARMPLAT)
126     // Use runtime ARM platform detection
127     platform_type = mraa_arm_platform();
128 #else
129 #error mraa_ARCH NOTHING
130 #endif
131
132     if (plat != NULL)
133         plat->platform_type = platform_type;
134
135     // This is a platform extender so create null base platform if one doesn't already exist
136     if (plat == NULL) {
137         plat = (mraa_board_t*) calloc(1, sizeof(mraa_board_t));
138         if (plat != NULL) {
139             plat->platform_type = MRAA_NULL_PLATFORM;
140             plat->platform_name = "Null platform";
141         }
142     }
143 #if defined(USBPLAT)
144     // Now detect sub platform
145     if (plat != NULL) {
146         mraa_platform_t usb_platform_type = mraa_usb_platform_extender(plat);
147         if (plat->platform_type == MRAA_UNKNOWN_PLATFORM && usb_platform_type != MRAA_UNKNOWN_PLATFORM) {
148             plat->platform_type = usb_platform_type;
149         } else {
150             return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
151         }
152     }
153     if (plat == NULL) {
154         printf("mraa: FATAL error, failed to initialise platform\n");
155         return MRAA_ERROR_PLATFORM_NOT_INITIALISED;
156     }
157 #endif
158
159     // Now detect IIO devices, linux only
160     // find how many i2c buses we have if we haven't already
161     if (num_iio_devices == 0) {
162         if (nftw("/sys/bus/iio/devices", &mraa_count_iio_devices, 20, FTW_PHYS) == -1) {
163             return MRAA_ERROR_UNSPECIFIED;
164         }
165     }
166     char name[64], filepath[64];
167     int fd, len, i;
168     plat->iio_device_count = num_iio_devices;
169     plat->iio_devices = calloc(num_iio_devices, sizeof(struct _iio));
170     struct _iio* device;
171     for (i=0; i < num_iio_devices; i++) {
172         device = &plat->iio_devices[i];
173         device->num = i;
174         snprintf(filepath, 64, "/sys/bus/iio/devices/iio:device%d/name", i);
175         fd = open(filepath, O_RDONLY);
176         if (fd != -1) {
177             len = read(fd, &name, 64);
178             if (len > 1) {
179                 // use strndup
180                 device->name = malloc((sizeof(char) * len) + sizeof(char));
181                 strncpy(device->name, name, len);
182             }
183         }
184     }
185
186     syslog(LOG_NOTICE, "libmraa initialised for platform '%s' of type %d", mraa_get_platform_name(), mraa_get_platform_type());
187     return MRAA_SUCCESS;
188 }
189
190 void
191 mraa_deinit()
192 {
193     if (plat != NULL) {
194         if (plat->pins != NULL) {
195             free(plat->pins);
196         }
197         mraa_board_t* sub_plat = plat->sub_platform;
198         if (sub_plat != NULL) {
199             if (sub_plat->pins != NULL) {
200                 free(sub_plat->pins);
201             }
202             free(sub_plat);
203         }
204         free(plat);
205
206     }
207     closelog();
208 }
209
210 int
211 mraa_set_priority(const unsigned int priority)
212 {
213     struct sched_param sched_s;
214
215     memset(&sched_s, 0, sizeof(struct sched_param));
216     if (priority > sched_get_priority_max(SCHED_RR)) {
217         sched_s.sched_priority = sched_get_priority_max(SCHED_RR);
218     } else {
219         sched_s.sched_priority = priority;
220     }
221
222     return sched_setscheduler(0, SCHED_RR, &sched_s);
223 }
224
225 mraa_result_t
226 mraa_setup_mux_mapped(mraa_pin_t meta)
227 {
228     int mi;
229
230     for (mi = 0; mi < meta.mux_total; mi++) {
231         mraa_gpio_context mux_i;
232         mux_i = mraa_gpio_init_raw(meta.mux[mi].pin);
233         if (mux_i == NULL) {
234             return MRAA_ERROR_INVALID_HANDLE;
235         }
236         // this function will sometimes fail, however this is not critical as
237         // long as the write succeeds - Test case galileo gen2 pin2
238         mraa_gpio_dir(mux_i, MRAA_GPIO_OUT);
239         mraa_gpio_owner(mux_i, 0);
240
241         if (mraa_gpio_write(mux_i, meta.mux[mi].value) != MRAA_SUCCESS) {
242             mraa_gpio_close(mux_i);
243             return MRAA_ERROR_INVALID_RESOURCE;
244         }
245         mraa_gpio_close(mux_i);
246     }
247
248     return MRAA_SUCCESS;
249 }
250
251 void
252 mraa_result_print(mraa_result_t result)
253 {
254     switch (result) {
255         case MRAA_SUCCESS:
256             fprintf(stdout, "MRAA: SUCCESS\n");
257             break;
258         case MRAA_ERROR_FEATURE_NOT_IMPLEMENTED:
259             fprintf(stdout, "MRAA: Feature not implemented.\n");
260             break;
261         case MRAA_ERROR_FEATURE_NOT_SUPPORTED:
262             fprintf(stdout, "MRAA: Feature not supported by Hardware.\n");
263             break;
264         case MRAA_ERROR_INVALID_VERBOSITY_LEVEL:
265             fprintf(stdout, "MRAA: Invalid verbosity level.\n");
266             break;
267         case MRAA_ERROR_INVALID_PARAMETER:
268             fprintf(stdout, "MRAA: Invalid parameter.\n");
269             break;
270         case MRAA_ERROR_INVALID_HANDLE:
271             fprintf(stdout, "MRAA: Invalid Handle.\n");
272             break;
273         case MRAA_ERROR_NO_RESOURCES:
274             fprintf(stdout, "MRAA: No resources.\n");
275             break;
276         case MRAA_ERROR_INVALID_RESOURCE:
277             fprintf(stdout, "MRAA: Invalid resource.\n");
278             break;
279         case MRAA_ERROR_INVALID_QUEUE_TYPE:
280             fprintf(stdout, "MRAA: Invalid Queue Type.\n");
281             break;
282         case MRAA_ERROR_NO_DATA_AVAILABLE:
283             fprintf(stdout, "MRAA: No Data available.\n");
284             break;
285         case MRAA_ERROR_INVALID_PLATFORM:
286             fprintf(stdout, "MRAA: Platform not recognised.\n");
287             break;
288         case MRAA_ERROR_PLATFORM_NOT_INITIALISED:
289             fprintf(stdout, "MRAA: Platform not initialised.\n");
290             break;
291         case MRAA_ERROR_PLATFORM_ALREADY_INITIALISED:
292             fprintf(stdout, "MRAA: Platform already initialised.\n");
293             break;
294         case MRAA_ERROR_UNSPECIFIED:
295             fprintf(stdout, "MRAA: Unspecified Error.\n");
296             break;
297         default:
298             fprintf(stdout, "MRAA: Unrecognised error.\n");
299             break;
300     }
301 }
302
303
304 mraa_boolean_t
305 mraa_has_sub_platform()
306 {
307     return (plat != NULL) && (plat->sub_platform != NULL);
308 }
309
310 mraa_boolean_t
311 mraa_pin_mode_test(int pin, mraa_pinmodes_t mode)
312 {
313     if (plat == NULL)
314         return 0;
315
316     mraa_board_t* current_plat = plat;
317     if (mraa_is_sub_platform_id(pin)) {
318         current_plat = plat->sub_platform;
319         if (current_plat == NULL) {
320             syslog(LOG_ERR, "mraa_pin_mode_test: Sub platform Not Initialised");
321             return 0;
322         }
323         pin = mraa_get_sub_platform_index(pin);
324     }
325
326     if (current_plat == NULL || current_plat->platform_type == MRAA_UNKNOWN_PLATFORM) {
327         return 0;
328     }
329     if (pin > (current_plat->phy_pin_count - 1) || pin < 0)
330         return 0;
331
332     switch (mode) {
333         case MRAA_PIN_VALID:
334             if (current_plat->pins[pin].capabilites.valid == 1)
335                 return 1;
336             break;
337         case MRAA_PIN_GPIO:
338             if (current_plat->pins[pin].capabilites.gpio == 1)
339                 return 1;
340             break;
341         case MRAA_PIN_PWM:
342             if (current_plat->pins[pin].capabilites.pwm == 1)
343                 return 1;
344             break;
345         case MRAA_PIN_FAST_GPIO:
346             if (current_plat->pins[pin].capabilites.fast_gpio == 1)
347                 return 1;
348             break;
349         case MRAA_PIN_SPI:
350             if (current_plat->pins[pin].capabilites.spi == 1)
351                 return 1;
352             break;
353         case MRAA_PIN_I2C:
354             if (current_plat->pins[pin].capabilites.i2c == 1)
355                 return 1;
356             break;
357         case MRAA_PIN_AIO:
358             if (current_plat->pins[pin].capabilites.aio == 1)
359                 return 1;
360             break;
361         case MRAA_PIN_UART:
362             if (current_plat->pins[pin].capabilites.uart == 1)
363                 return 1;
364             break;
365         default:
366             syslog(LOG_NOTICE, "requested pinmode invalid");
367             break;
368     }
369     return 0;
370 }
371
372 mraa_platform_t
373 mraa_get_platform_type()
374 {
375     if (plat == NULL)
376         return MRAA_UNKNOWN_PLATFORM;
377     return plat->platform_type;
378 }
379
380 int
381 mraa_get_platform_combined_type()
382 {
383     int type = mraa_get_platform_type();
384     int sub_type = mraa_has_sub_platform() ? plat->sub_platform->platform_type : MRAA_UNKNOWN_PLATFORM;
385     return type | (sub_type << 8);
386 }
387
388 unsigned int
389 mraa_adc_raw_bits()
390 {
391     if (plat == NULL)
392         return 0;
393
394     if (plat->aio_count == 0)
395         return 0;
396
397     return plat->adc_raw;
398 }
399
400 unsigned int
401 mraa_get_platform_adc_raw_bits(uint8_t platform_offset)
402 {
403     if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET)
404         return mraa_adc_raw_bits();
405     else {
406         if (!mraa_has_sub_platform())
407             return 0;
408
409         if (plat->sub_platform->aio_count == 0)
410             return 0;
411
412         return plat->sub_platform->adc_raw;
413     }
414 }
415
416
417 unsigned int
418 mraa_adc_supported_bits()
419 {
420     if (plat == NULL)
421         return 0;
422
423     if (plat->aio_count == 0)
424         return 0;
425
426     return plat->adc_supported;
427 }
428
429 unsigned int
430 mraa_get_platform_adc_supported_bits(int platform_offset)
431 {
432     if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET)
433         return mraa_adc_supported_bits();
434     else {
435         if (!mraa_has_sub_platform())
436             return 0;
437
438         if (plat->sub_platform->aio_count == 0)
439             return 0;
440
441         return plat->sub_platform->adc_supported;
442     }
443 }
444
445
446 char*
447 mraa_get_platform_name()
448 {
449     if (plat == NULL) {
450         return NULL;
451     }
452     if (mraa_has_sub_platform()) {
453         snprintf(platform_name, MAX_PLATFORM_NAME_LENGTH, "%s + %s", plat->platform_name, plat->sub_platform->platform_name);
454     } else {
455         strncpy(platform_name, plat->platform_name, MAX_PLATFORM_NAME_LENGTH-1);
456     }
457
458     return platform_name;
459 }
460
461 int
462 mraa_get_i2c_bus_count()
463 {
464     if (plat == NULL) {
465         return -1;
466     }
467     return plat->i2c_bus_count;
468 }
469
470 int
471 mraa_get_i2c_bus_id(unsigned i2c_bus)
472 {
473     if (plat == NULL) {
474         return -1;
475     }
476
477     if (i2c_bus >= plat->i2c_bus_count) {
478         return -1;
479     }
480
481     return plat->i2c_bus[i2c_bus].bus_id;
482 }
483
484 unsigned int
485 mraa_get_pin_count()
486 {
487     if (plat == NULL) {
488         return 0;
489     }
490     return plat->phy_pin_count;
491 }
492
493 unsigned int
494 mraa_get_platform_pin_count(uint8_t platform_offset)
495 {
496     if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET)
497         return mraa_get_pin_count();
498     else {
499         if (mraa_has_sub_platform())
500            return plat->sub_platform->phy_pin_count;
501         else
502            return 0;
503     }
504 }
505
506
507 char*
508 mraa_get_pin_name(int pin)
509 {
510     if (plat == NULL)
511         return 0;
512
513     mraa_board_t* current_plat = plat;
514     if (mraa_is_sub_platform_id(pin)) {
515         current_plat = plat->sub_platform;
516         if (current_plat == NULL) {
517             syslog(LOG_ERR, "mraa_get_pin_name: Sub platform Not Initialised");
518             return 0;
519         }
520         pin = mraa_get_sub_platform_index(pin);
521     }
522
523     if (pin > (current_plat->phy_pin_count - 1) || pin < 0)
524         return NULL;
525     return (char*) current_plat->pins[pin].name;
526 }
527
528 int
529 mraa_get_default_i2c_bus(uint8_t platform_offset)
530 {
531     if (plat == NULL)
532         return -1;
533     if (platform_offset == MRAA_MAIN_PLATFORM_OFFSET) {
534         return plat->def_i2c_bus;
535     } else {
536         if (mraa_has_sub_platform())
537            return plat->sub_platform->def_i2c_bus;
538         else
539            return -1;
540     }
541 }
542
543
544 mraa_boolean_t
545 mraa_file_exist(const char* filename)
546 {
547     glob_t results;
548     results.gl_pathc = 0;
549     glob(filename, 0, NULL, &results);
550     int file_found = results.gl_pathc == 1;
551     globfree(&results);
552     return file_found;
553 }
554
555 mraa_boolean_t
556 mraa_file_contains(const char* filename, const char* content)
557 {
558     mraa_boolean_t found = 0;
559     if ((filename == NULL) || (content == NULL)) {
560         return 0;
561     }
562
563     char* file = mraa_file_unglob(filename);
564     if (file != NULL) {
565         size_t len = 1024;
566         char* line = malloc(len);
567         if (line == NULL) {
568             free(file);
569             return 0;
570         }
571         FILE* fh = fopen(file, "r");
572         if (fh == NULL) {
573             free(file);
574             free(line);
575             return 0;
576         }
577         while ((getline(&line, &len, fh) != -1) && (found == 0)) {
578             if (strstr(line, content)) {
579                 found = 1;
580                 break;
581             }
582         }
583         fclose(fh);
584         free(file);
585         free(line);
586     }
587     return found;
588 }
589
590 mraa_boolean_t
591 mraa_file_contains_both(const char* filename, const char* content, const char* content2)
592 {
593     mraa_boolean_t found = 0;
594     if ((filename == NULL) || (content == NULL)) {
595         return 0;
596     }
597
598     char* file = mraa_file_unglob(filename);
599     if (file != NULL) {
600         size_t len = 1024;
601         char* line = malloc(len);
602         if (line == NULL) {
603             free(file);
604             return 0;
605         }
606         FILE* fh = fopen(file, "r");
607         if (fh == NULL) {
608             free(file);
609             free(line);
610             return 0;
611         }
612         while ((getline(&line, &len, fh) != -1) && (found == 0)) {
613             if (strstr(line, content) && strstr(line, content2)) {
614                 found = 1;
615                 break;
616             }
617         }
618         fclose(fh);
619         free(file);
620         free(line);
621     }
622     return found;
623 }
624
625 char*
626 mraa_file_unglob(const char* filename)
627 {
628     glob_t results;
629     char* res = NULL;
630     results.gl_pathc = 0;
631     glob(filename, 0, NULL, &results);
632     if (results.gl_pathc == 1)
633         res = strdup(results.gl_pathv[0]);
634     globfree(&results);
635     return res;
636 }
637
638 mraa_boolean_t
639 mraa_link_targets(const char* filename, const char* targetname)
640 {
641     int size = 100;
642     int nchars = 0;
643     char* buffer = NULL;
644     while (nchars == 0) {
645         buffer = (char*) realloc(buffer, size);
646         if (buffer == NULL)
647             return 0;
648         nchars = readlink(filename, buffer, size);
649         if (nchars < 0) {
650             free(buffer);
651             return 0;
652         } else {
653             buffer[nchars] = '\0';
654         }
655         if (nchars >= size) {
656             size *= 2;
657             nchars = 0;
658         }
659     }
660     if (strstr(buffer, targetname)) {
661         free(buffer);
662         return 1;
663     } else {
664         free(buffer);
665         return 0;
666     }
667 }
668
669 static int
670 mraa_count_i2c_files(const char* path, const struct stat* sb, int flag, struct FTW* ftwb)
671 {
672     switch (sb->st_mode & S_IFMT) {
673         case S_IFLNK:
674             num_i2c_devices++;
675             break;
676     }
677     return 0;
678 }
679
680 int
681 mraa_find_i2c_bus(const char* devname, int startfrom)
682 {
683     char path[64];
684     int fd;
685     int i = startfrom;
686     int ret = -1;
687
688     // because feeding mraa_find_i2c_bus result back into the function is
689     // useful treat -1 as 0
690     if (startfrom < 0) {
691         startfrom = 0;
692     }
693
694     // find how many i2c buses we have if we haven't already
695     if (num_i2c_devices == 0) {
696         if (nftw("/sys/class/i2c-dev/", &mraa_count_i2c_files, 20, FTW_PHYS) == -1) {
697             return -1;
698         }
699     }
700
701     // i2c devices are numbered numerically so 0 must exist otherwise there is
702     // no i2c-dev loaded
703     if (mraa_file_exist("/sys/class/i2c-dev/i2c-0")) {
704         for (i; i < num_i2c_devices; i++) {
705             off_t size, err;
706             snprintf(path, 64, "/sys/class/i2c-dev/i2c-%u/name", i);
707             fd = open(path, O_RDONLY);
708             if (fd < 0) {
709                 break;
710             }
711             size = lseek(fd, 0, SEEK_END);
712             if (size < 0) {
713                 syslog(LOG_WARNING, "mraa: failed to seek i2c filename file");
714                 close(fd);
715                 break;
716             }
717             err = lseek(fd, 0, SEEK_SET);
718             if (err < 0) {
719                 syslog(LOG_WARNING, "mraa: failed to seek i2c filename file");
720                 close(fd);
721                 break;
722             }
723             char* value = malloc(size);
724             if (value == NULL) {
725                 syslog(LOG_ERR, "mraa: failed to allocate memory for i2c file");
726                 close(fd);
727                 break;
728             }
729             ssize_t r = read(fd, value, size);
730             if (r > 0) {
731                 if (strcasestr(value, devname) != NULL) {
732                     free(value);
733                     close(fd);
734                     return i;
735                 }
736             } else {
737                 syslog(LOG_ERR, "mraa: sysfs i2cdev failed");
738             }
739             free(value);
740             close(fd);
741         }
742     } else {
743         syslog(LOG_WARNING, "mraa: no i2c-dev detected, load i2c-dev");
744     }
745
746     return ret;
747 }
748
749 mraa_boolean_t
750 mraa_is_sub_platform_id(int pin_or_bus)
751 {
752     return (pin_or_bus & MRAA_SUB_PLATFORM_MASK) != 0;
753 }
754
755 int
756 mraa_get_sub_platform_id(int pin_or_bus)
757 {
758     return pin_or_bus | MRAA_SUB_PLATFORM_MASK;
759 }
760
761 int
762 mraa_get_sub_platform_index(int pin_or_bus)
763 {
764     return pin_or_bus & (~MRAA_SUB_PLATFORM_MASK);
765 }
766
767 int
768 mraa_get_iio_device_count()
769 {
770     return plat->iio_device_count;
771 }
772
773 int
774 mraa_find_iio_device(const char* devicename)
775 {
776     int i = 0;
777     for (i; i < plat->iio_device_count; i++) {
778 #if 0
779         // compare with devices array
780         if (!strcmp() {
781         }
782 #endif
783     }
784     return 0;
785 }