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