Hello,

I am currently working on a project which uses I2C devices through libi2c
API.

The problem that I am facing is that this function:
rtems_libi2c_register_drv actually registeres the device before
drvtbl->ops->initialization_entry returns success or failure. This means
that it is impossible to probe a device which might be at 2 different I2C
addreses on different PCB revisions.

For a device driver with no initialization function it should make no
difference, the function call being ignored, and the minor being returned.
If the device driver has a initialization function, it calls it and makes
sure that the return value is 0 before registering the name. If it returns
something different than RTEMS_SUCCESS, it makes sure the driver
registration returns negative error code (so it's not mistaken with minor
number), and does not register the device driver.

I have attached a patch to solve this problem, and bypass device
registration in the filesystem if the initialziation fails.
Please review the changes and merge if you agree.

Thank you,
Alex H.
From cacb39244bcde68b65aa90e0c8699c42e53812ac Mon Sep 17 00:00:00 2001
From: Alexandru-Sever Horin <alexandru.ho...@movidius.com>
Date: Wed, 1 Apr 2015 16:48:36 +0300
Subject: [PATCH] libi2c registration of a device fails if the device
 initialization fails Benefits: allows for device probing on multiple addreses

---
 cpukit/libi2c/libi2c.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/cpukit/libi2c/libi2c.c b/cpukit/libi2c/libi2c.c
index 233cb68..db014b0 100644
--- a/cpukit/libi2c/libi2c.c
+++ b/cpukit/libi2c/libi2c.c
@@ -736,6 +736,19 @@ rtems_libi2c_register_drv (const char *name, rtems_libi2c_drv_t * drvtbl,
       /* found a free slot; encode slot + 1 ! */
       minor = ((i + 1) << 13) | RTEMS_LIBI2C_MAKE_MINOR (busno, i2caddr);
 
+      /* before registering, try to initialize the device to check it's there */
+      if (drvtbl->ops->initialization_entry)
+      {
+        err = drvtbl->ops->initialization_entry (rtems_libi2c_major,
+                                                 minor, 0);
+        if(err)
+        {
+          LIBUNLOCK ();
+          /* make sure the returned value is negative, not to mistake it for minor number */
+          return err < 0 ? err : -err;
+        }
+      }
+
       if (name) {
         size_t length = strlen (busses[busno].name) + strlen (name) + 2;
         str = malloc (length);
@@ -761,17 +774,11 @@ rtems_libi2c_register_drv (const char *name, rtems_libi2c_drv_t * drvtbl,
 
       drvs[i].drv = drvtbl;
 
-      if (drvtbl->ops->initialization_entry)
-        err =
-          drvs[i].drv->ops->initialization_entry (rtems_libi2c_major, minor,
-                                                  0);
-      else
-        err = RTEMS_SUCCESSFUL;
-
       LIBUNLOCK ();
-      return err ? -err : minor;
+      return minor;
     }
   }
+
   LIBUNLOCK ();
   return -RTEMS_TOO_MANY;
 }
-- 
2.3.5

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to