Module: xenomai-forge
Branch: next
Commit: e78e861c0a89789943630e2c70084b325ec43676
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=e78e861c0a89789943630e2c70084b325ec43676

Author: Philippe Gerum <r...@xenomai.org>
Date:   Mon Aug 18 21:10:39 2014 +0200

cobalt/rtdm: extend specification of device minor

This patch enables the usual form of minor specification without
requiring a special '@' marker to be detected in the non-ambiguous
cases (i.e. when the device radix name does not end with a digit).

e.g.

open("/dev/foo0", ...)  => connect to unit #0 of device type "foo"
open("/dev/foo@7", ...) => connect to unit #7 of device type "foo"
open("/dev/foo", ...)   => connect to control channel of device "foo"
open("/dev/foo42", ...) => connect to device type "foo42"
open("/dev/foo42@3", ...) => connect to unit #3 of device type "foo42"

In additition, minor detection is only enabled for drivers bearing the
RTDM_MINOR device flag.

This change allows converting multi-device drivers which currently
assign a distinct device descriptor for each unit, to using a single
descriptor along with a minor specification instead, without affecting
the device names exposed to the application code.

---

 include/cobalt/kernel/rtdm/driver.h |    3 +++
 include/cobalt/kernel/rtdm/fd.h     |   37 +++++++++++++++++++++++------------
 kernel/cobalt/rtdm/device.c         |   22 ++++++++++++++++-----
 kernel/drivers/udd/udd.c            |    4 ++--
 4 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/include/cobalt/kernel/rtdm/driver.h 
b/include/cobalt/kernel/rtdm/driver.h
index d95f86e..28484be 100644
--- a/include/cobalt/kernel/rtdm/driver.h
+++ b/include/cobalt/kernel/rtdm/driver.h
@@ -69,6 +69,9 @@ enum rtdm_selecttype;
  *  application. */
 #define RTDM_EXCLUSIVE                 0x0001
 
+/** If set, the device supports minor specification. */
+#define RTDM_MINOR                     0x0002
+
 /** If set, the device is addressed via a clear-text name. */
 #define RTDM_NAMED_DEVICE              0x0010
 
diff --git a/include/cobalt/kernel/rtdm/fd.h b/include/cobalt/kernel/rtdm/fd.h
index c5159cf..3fe353a 100644
--- a/include/cobalt/kernel/rtdm/fd.h
+++ b/include/cobalt/kernel/rtdm/fd.h
@@ -47,28 +47,39 @@ struct xnsys_ppd;
  * retrieved by a call to rtdm_fd_minor(fd). The minor number can be
  * used for distinguishing several instances of the same rtdm_device
  * type. Prior to entering this handler, the device minor information
- * may have been extracted from the pathname passed to the @a open()
+ * may have been extracted from the path name passed to the @a open()
  * call, according to the following rules:
  *
- * - RTDM first attempts to match the pathname exactly as passed by
+ * - RTDM first attempts to match the path name exactly as passed by
  * the application, against the registered rtdm_device descriptors. On
  * success, the special minor -1 is assigned to @a fd and this handler
  * is called.
  *
- * - if the original pathname does not match any device descriptor, it
- * is scanned for the \@\<minor> suffix. If present, a second lookup is
- * performed only looking for the radix portion of the pathname
- * (i.e. stripping the suffix), and the file descriptor is assigned
- * the minor value retrieved earlier on success, at which point this
- * handler is called. When present, \<minor> must be a positive or null
- * decimal value, otherwise the open() call fails.
+ * - if the original path name does not match any device descriptor,
+ * it is scanned backward for a \<minor> suffix, which starts after
+ * the first non-digit character found. If present, a second lookup is
+ * performed in the device registry for the radix portion of the path
+ * name (i.e. stripping the \<minor>), looking for a device bearing
+ * the RTDM_MINOR flag.  If found, the file descriptor is assigned the
+ * minor value retrieved earlier on success, at which point the
+ * binding succeeds and the open() handler is called.
  *
- * For instance:
+ * When present, \<minor> must be a positive or null decimal value,
+ * otherwise the open() call fails.
+ *
+ * For disambiguation, the special \@ character can be used as an
+ * explicit separator between the radix and the \<minor>, which is
+ * ignored in the final lookup for the path name.
+ *
+ * For instance, with two distinct registered devices bearing the
+ * RTDM_MINOR flag, namely "foo" and "foo42", lookups would resolve as
+ * follows:
  *
  * @code
- *    fd = open("/dev/foo@0", ...); // rtdm_fd_minor(fd) == 0
- *    fd = open("/dev/foo@7", ...); // rtdm_fd_minor(fd) == 7
- *    fd = open("/dev/foo", ...);   // rtdm_fd_minor(fd) == -1
+ *    fd = open("/dev/foo0", ...);    // dev = foo, rtdm_fd_minor(fd) = 0
+ *    fd = open("/dev/foo", ...);     // dev = foo, rtdm_fd_minor(fd) = -1
+ *    fd = open("/dev/foo42@7", ...); // dev = foo42, rtdm_fd_minor(fd) = 7
+ *    fd = open("/dev/foo42", ...);   // dev = foo42, rtdm_fd_minor(fd) = -1
  * @endcode
  *
  * @note the device minor scheme is not supported by Xenomai 2.x.
diff --git a/kernel/cobalt/rtdm/device.c b/kernel/cobalt/rtdm/device.c
index 4c6f4c8..63f2e1b 100644
--- a/kernel/cobalt/rtdm/device.c
+++ b/kernel/cobalt/rtdm/device.c
@@ -22,6 +22,7 @@
 #include <linux/delay.h>
 #include <linux/semaphore.h>
 #include <linux/slab.h>
+#include <linux/ctype.h>
 #include <cobalt/kernel/apc.h>
 #include "rtdm/internal.h"
 #include <trace/events/cobalt-rtdm.h>
@@ -68,7 +69,7 @@ struct rtdm_device *__rtdm_get_named_device(const char *name, 
int *minor_r)
         * First we look for an exact match. If this fails, we look
         * for a device minor specification. If we find one, we redo
         * the search only looking for the device base name. The
-        * default minor value is zero.
+        * default minor value if unspecified is -1.
         */
        for (;;) {
                ret = xnregistry_bind(name, XN_NONBLOCK, XN_RELATIVE, &handle);
@@ -78,8 +79,14 @@ struct rtdm_device *__rtdm_get_named_device(const char 
*name, int *minor_r)
                        break;
                if (p)  /* Look for minor only once. */
                        return NULL;
-               p = strrchr(name, '@');
-               if (p == NULL || p[1] == '\0')
+               p = name + strlen(name);
+               while (--p >= name) {
+                       if (!isdigit(*p))
+                               break;
+               }
+               if (p < name)   /* no minor spec. */
+                       return NULL;
+               if (p[1] == '\0')
                        return NULL;
                ret = kstrtoint(p + 1, 10, &minor);
                if (ret || minor < 0)
@@ -87,7 +94,10 @@ struct rtdm_device *__rtdm_get_named_device(const char 
*name, int *minor_r)
                base = kstrdup(name, GFP_KERNEL);
                if (base == NULL)
                        return NULL;
-               base[p - name] = '\0';
+               if (*p == '@')
+                       base[p - name] = '\0';
+               else
+                       base[p - name + 1] = '\0';
                name = base;
        }
 
@@ -95,7 +105,9 @@ struct rtdm_device *__rtdm_get_named_device(const char 
*name, int *minor_r)
 
        device = xnregistry_lookup(handle, NULL);
        if (device) {
-               if (device->reserved.magic == RTDM_DEVICE_MAGIC) {
+               if (device->reserved.magic == RTDM_DEVICE_MAGIC &&
+                   ((device->device_flags & RTDM_MINOR) != 0 ||
+                    minor < 0)) {
                        rtdm_reference_device(device);
                        *minor_r = minor;
                } else
diff --git a/kernel/drivers/udd/udd.c b/kernel/drivers/udd/udd.c
index 37b4db9..6cffa1a 100644
--- a/kernel/drivers/udd/udd.c
+++ b/kernel/drivers/udd/udd.c
@@ -197,7 +197,7 @@ static int mapper_open(struct rtdm_fd *fd, int oflags)
         * Check that we are opening a mapper instance pointing at a
         * valid memory region. e.g. UDD creates the companion device
         * "foo,mapper" on the fly when registering the main device
-        * "foo". Userland may then open("/dev/foo,mapper@0", ...)
+        * "foo". Userland may then open("/dev/foo,mapper0", ...)
         * followed by a call to mmap() for mapping the memory region
         * #0 as declared in the mem_regions[] array of the main
         * device.
@@ -289,7 +289,7 @@ static inline int register_mapper(struct udd_device *udd)
 
        memset(dev, 0, sizeof(*dev));
        dev->struct_version = RTDM_DEVICE_STRUCT_VER;
-       dev->device_flags = RTDM_NAMED_DEVICE;
+       dev->device_flags = RTDM_NAMED_DEVICE|RTDM_MINOR;
        dev->context_size = 0;
        dev->ops = (struct rtdm_fd_ops){
                .open = mapper_open,


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to