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