mraa: add internal mraa_find_i2c_bus function
authorBrendan Le Foll <brendan.le.foll@intel.com>
Fri, 10 Jul 2015 16:52:50 +0000 (17:52 +0100)
committerBrendan Le Foll <brendan.le.foll@intel.com>
Fri, 10 Jul 2015 10:11:41 +0000 (11:11 +0100)
Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
include/mraa_internal.h
src/mraa.c
src/x86/intel_de3815.c
src/x86/intel_minnow_max.c

index c9eaa7b..f35a197 100644 (file)
@@ -105,6 +105,16 @@ mraa_boolean_t mraa_file_contains_both(const char* filename, const char* content
  */
 mraa_boolean_t mraa_link_targets(const char* filename, const char* targetname);
 
+/**
+ * helper function to find the first i2c bus containing devname starting from
+ * i2c-n where n is startfrom
+ *
+ * @param device name to match
+ * @param i2c-dev number to start search from
+ * @return the matching i2c-dev bus id or -1
+ */
+int mraa_find_i2c_bus(const char* devname, int startfrom);
+
 #ifdef __cplusplus
 }
 #endif
index 75084e5..6a4914e 100644 (file)
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#define _GNU_SOURCE
+#if !defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
+#define _XOPEN_SOURCE 600 /* Get nftw() and S_IFSOCK declarations */
+#endif
+
 #include <stddef.h>
 #include <stdlib.h>
 #include <sched.h>
 #include <string.h>
 #include <pwd.h>
 #include <glob.h>
-
+#include <ftw.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
 
 #include "mraa_internal.h"
 #include "gpio.h"
@@ -426,3 +436,77 @@ mraa_link_targets(const char* filename, const char* targetname)
         return 0;
     }
 }
+
+static int num_i2c_devices = 0;
+
+static int
+mraa_count_files(const char* path, const struct stat* sb, int flag, struct FTW* ftwb)
+{
+    switch (sb->st_mode & S_IFMT) {
+        case S_IFLNK:
+            num_i2c_devices++;
+            break;
+    }
+    return 0;
+}
+
+int
+mraa_find_i2c_bus(const char* devname, int startfrom)
+{
+    char path[64], value[64];
+    int fd;
+    int i = startfrom;
+    int ret = -1;
+
+    // because feeding mraa_find_i2c_bus result back into the function is
+    // useful treat -1 as 0
+    if (startfrom < 0) {
+        startfrom = 0;
+    }
+
+    // find how many i2c buses we have if we haven't already
+    if (num_i2c_devices == 0) {
+        if (nftw("/sys/class/i2c-dev/", &mraa_count_files, 20, FTW_PHYS) == -1) {
+            return -1;
+        }
+    }
+
+    // i2c devices are numbered numerically so 0 must exist otherwise there is
+    // no i2c-dev loaded
+    if (mraa_file_exist("/sys/class/i2c-dev/i2c-0")) {
+        for (i; i < num_i2c_devices; i++) {
+            off_t size, err;
+            snprintf(path, 64, "/sys/class/i2c-dev/i2c-%u/name", i);
+            fd = open(path, O_RDONLY);
+            if (fd < 0) {
+                break;
+            }
+            size = lseek(fd, 0, SEEK_END);
+            if (size < 0) {
+                syslog(LOG_WARNING, "mraa: failed to seek i2c filename file");
+                close(fd);
+                break;
+            }
+            err = lseek(fd, 0, SEEK_SET);
+            if (err < 0) {
+                syslog(LOG_WARNING, "mraa: failed to seek i2c filename file");
+                close(fd);
+                break;
+            }
+            ssize_t r = read(fd, value, size);
+            if (r > 0) {
+                if (strcasestr(value, devname) != NULL) {
+                    close(fd);
+                    return i;
+                }
+            } else {
+                syslog(LOG_ERR, "mraa: sysfs i2cdev failed");
+            }
+            close(fd);
+        }
+    } else {
+        syslog(LOG_WARNING, "mraa: no i2c-dev detected, load i2c-dev");
+    }
+
+    return ret;
+}
index f197bbc..e06c913 100644 (file)
@@ -22,7 +22,6 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#define _GNU_SOURCE
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
@@ -33,7 +32,6 @@
 #include "x86/intel_de3815.h"
 
 #define PLATFORM_NAME "Intel DE3815"
-#define MAX_SIZE 64
 #define SYSFS_CLASS_GPIO "/sys/class/gpio"
 #define I2CNAME "designware"
 
@@ -119,73 +117,25 @@ mraa_intel_de3815()
     strncpy(b->pins[17].name, "SMB_SDA", 8);
     b->pins[17].capabilites = (mraa_pincapabilities_t){ 1, 0, 0, 0, 0, 0, 0, 0 };
 
-    // BUS DEFINITIONS
-    int fd;
-    if (mraa_file_exist("/dev/i2c-0")) {
-        b->i2c_bus_count = 2;
-        int i = 0;
-        int suc = 0;
-        for (i = 0; i < 9; i++) {
-            off_t size, err;
-            char path[MAX_SIZE];
-            char value[MAX_SIZE];
-            snprintf(path, MAX_SIZE, "/sys/class/i2c-dev/i2c-%u/name", i);
-            fd = open(path, O_RDONLY);
-            if (fd < 0) {
-                break;
-            }
-            size = lseek(fd, 0, SEEK_END);
-            if (size < 0) {
-                syslog(LOG_WARNING, "mraa: failed to seek i2c filename file");
-                close(fd);
-                break;
-            }
-            err = lseek(fd, 0, SEEK_SET);
-            if (err < 0) {
-                syslog(LOG_WARNING, "mraa: failed to seek i2c filename file");
-                close(fd);
-                break;
-            }
-            if (size >= MAX_SIZE) {
-                syslog(LOG_NOTICE, "mraa: i2c filename file too big, skipping");
-                close(fd);
-                break;
-            }
-            ssize_t r = read(fd, value, size);
-            if (r > 0) {
-                if (strcasestr(value, I2CNAME) != NULL) {
-                    suc = 1;
-                    b->i2c_bus_count = 2;
-                    b->def_i2c_bus = 0;
-                    b->i2c_bus[0].bus_id = i;
-                    b->i2c_bus[0].sda = 12;
-                    b->i2c_bus[0].scl = 13;
-
-                    b->i2c_bus[1].bus_id = i + 1;
-                    b->i2c_bus[1].sda = 14;
-                    b->i2c_bus[1].scl = 15;
-                    close(fd);
-                    break;
-                }
-            } else {
-                syslog(LOG_ERR, "mraa: sysfs i2cdev failed");
-                close(fd);
-                break;
-            }
-            close(fd);
+    b->i2c_bus_count = 0;
+    int i2c_num = -1;
+    int i;
+    for (i = 0; i < 2; i++) {
+        i2c_num = mraa_find_i2c_bus(I2CNAME, i2c_num + 1);
+        if (i2c_num == -1) {
+            break;
         }
+        b->i2c_bus_count++;
+        b->i2c_bus[i].bus_id = i2c_num;
+        b->i2c_bus[i].sda = 12 + i;
+        b->i2c_bus[i].scl = 13 + i;
+    }
 
-        if (!suc) {
-            syslog(LOG_WARNING, "mraa: no i2c-dev detected, load i2c-dev");
-            b->i2c_bus_count = 0;
-            b->def_i2c_bus = 0;
-        }
-    } else {
-        syslog(LOG_WARNING, "mraa: no i2c-dev detected, load i2c-dev");
-        b->i2c_bus_count = 0;
-        b->def_i2c_bus = 0;
+    if (b->i2c_bus_count > 0) {
+        b->def_i2c_bus = b->i2c_bus[0].bus_id;
     }
 
+
     b->spi_bus_count = 1;
     b->def_spi_bus = 0;
     b->spi_bus[0].bus_id = 1;
index 48b30b7..8b4128d 100644 (file)
@@ -31,9 +31,9 @@
 #include "x86/intel_minnow_max.h"
 
 #define PLATFORM_NAME "MinnowBoard MAX"
-#define I2C_BUS_COUNT 10
 #define I2C_BUS_DEFAULT 7
 #define MAX_LENGTH 8
+#define I2CNAME "designware"
 
 int arch_nr_gpios_adjust = 0x100;
 
@@ -151,24 +151,22 @@ mraa_intel_minnow_max()
     mraa_set_pininfo(b, 25, "S5_4", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, 84);
     mraa_set_pininfo(b, 26, "IBL8254", (mraa_pincapabilities_t){ 1, 1, 0, 0, 0, 0, 0, 0 }, 208);
 
-    // Set number of i2c adaptors
-    // Got this from running 'i2cdetect -l'
-    b->i2c_bus_count = I2C_BUS_COUNT;
-
-    // Disable all i2c adaptors
-    int ici;
-    for (ici = 0; ici < b->i2c_bus_count; ici++) {
-        b->i2c_bus[ici].bus_id = -1;
-    }
+    // Set number of i2c adaptors usable from userspace
+    b->i2c_bus_count = 2;
 
     // Configure i2c adaptor #7 and make it the default
     int pin_index_sda, pin_index_scl;
     if (mraa_get_pin_index(b, "I2C_SDA", &pin_index_sda) == MRAA_SUCCESS &&
         mraa_get_pin_index(b, "I2C_SCL", &pin_index_scl) == MRAA_SUCCESS) {
-        b->def_i2c_bus = I2C_BUS_DEFAULT;
-        b->i2c_bus[b->def_i2c_bus].bus_id = b->def_i2c_bus;
-        b->i2c_bus[b->def_i2c_bus].sda = pin_index_sda;
-        b->i2c_bus[b->def_i2c_bus].scl = pin_index_scl;
+        int bus = mraa_find_i2c_bus(I2CNAME, 0);
+        if (bus == -1) {
+            b->i2c_bus_count = 0;
+        } else {
+            b->def_i2c_bus = bus;
+            b->i2c_bus[b->def_i2c_bus].bus_id = b->def_i2c_bus;
+            b->i2c_bus[b->def_i2c_bus].sda = pin_index_sda;
+            b->i2c_bus[b->def_i2c_bus].scl = pin_index_scl;
+        }
     }
 
     // Configure PWM