16 #include <sys/types.h> 
   37 static const int GLOB_CHUNK_SIZE = 32;
 
   42         memset(glob, 0, 
sizeof(glob_t));
 
   43         glob->gl_offs = GLOB_CHUNK_SIZE;
 
   44         glob->gl_pathv = (
char**) calloc(glob->gl_offs, 
sizeof(
char*));
 
   52         if (glob->gl_pathc >= glob->gl_offs) {
 
   53                 glob->gl_offs += GLOB_CHUNK_SIZE;
 
   54                 glob->gl_pathv = realloc(glob->gl_pathv,
 
   55                                          glob->gl_offs * 
sizeof(
char*));
 
   57         glob->gl_pathv[glob->gl_pathc] = strdup(path);
 
   69         for (i = 0; i < glob->gl_pathc; i += 1)
 
   70                 free(glob->gl_pathv[i]);
 
   76 static const char* get_sysattr(
struct udev_device* device, 
const char* attr);
 
   80 static struct udev_device* udev_from_dev_path(
struct udev* udev,
 
   86         if (stat(path, &statbuf) != 0) {
 
   90         if (!S_ISCHR(statbuf.st_mode)) {
 
   91                 log_debug(
"Ignoring non-character device %s", path);
 
   94         snprintf(dev_id, 
sizeof(dev_id), 
"c%d:%d",
 
   95                 major(statbuf.st_rdev), minor(statbuf.st_rdev));
 
   96         return udev_device_new_from_device_id(udev, dev_id);
 
  104 static struct udev_device* get_some_info(
struct udev_device* device,
 
  105                                          const char** idVendor,
 
  106                                          const char** idProduct)
 
  108         struct udev_device* usb_device = NULL;
 
  109         const char* subsystem = udev_device_get_subsystem(device);
 
  111         if (subsystem && (strcmp(subsystem, 
"usb") != 0)) {
 
  112                 usb_device = udev_device_get_parent_with_subsystem_devtype(
 
  113                         device, 
"usb", 
"usb_device");
 
  115                         log_error(
"Unable to find parent usb device.");
 
  118         *idVendor = udev_device_get_sysattr_value(device, 
"idVendor");
 
  119         *idProduct = udev_device_get_sysattr_value(device, 
"idProduct");
 
  120         if (!*idProduct && usb_device)
 
  121                 *idProduct = get_sysattr(usb_device, 
"idProduct");
 
  122         if (!*idVendor && usb_device)
 
  123                 *idVendor = get_sysattr(usb_device, 
"idVendor");
 
  124         return usb_device ? usb_device : device;
 
  135         struct udev* udev = udev_new();
 
  136         const char* idVendor;
 
  137         const char* idProduct;
 
  140         for (i = 0; i < oldbuf->gl_pathc; i += 1) {
 
  141                 device_path = strdup(oldbuf->gl_pathv[i]);
 
  142                 device_path = strtok(device_path, 
"\n \t");
 
  143                 struct udev_device* udev_device =
 
  144                         udev_from_dev_path(udev, device_path);
 
  145                 if (udev_device == NULL) {
 
  148                         udev_device = get_some_info(udev_device,
 
  151                         snprintf(line, 
sizeof(line),
 
  152                                  "%s [%s:%s] %s %s version: %s serial: %s",
 
  156                                  get_sysattr(udev_device, 
"manufacturer"),
 
  157                                  get_sysattr(udev_device, 
"product"),
 
  158                                  get_sysattr(udev_device, 
"version"),
 
  159                                  get_sysattr(udev_device, 
"serial")
 
  161                         if (idVendor == NULL && idProduct == NULL)
 
  169         memcpy(oldbuf, &newbuf, 
sizeof(glob_t));
 
  190         buff.gl_pathv = NULL;
 
  193         for (flags = 0; *patterns; patterns++) {
 
  194                 r = glob(*patterns, flags, NULL, &buff);
 
  195                 if (r == GLOB_NOMATCH)
 
  203         for (i = 0; i < buff.gl_pathc; i += 1) {
 
  214         const char* globs[] = {pattern, NULL};
 
  223                  int (*is_device_ok)(uint16_t vendor, uint16_t product))
 
  225         struct usb_bus* usb_bus;
 
  226         struct usb_device* dev;
 
  227         char device_path[2 * MAXPATHLEN + 32];
 
  233         for (usb_bus = usb_busses; usb_bus; usb_bus = usb_bus->next) {
 
  234                 for (dev = usb_bus->devices; dev; dev = dev->next) {
 
  235                         if (!is_device_ok(dev->descriptor.idVendor,
 
  236                                           dev->descriptor.idProduct))
 
  238                         snprintf(device_path, 
sizeof(device_path),
 
  239                                  "/dev/bus/usb/%s/%s     %04x:%04x",
 
  240                                  dev->bus->dirname, dev->filename,
 
  241                                  dev->descriptor.idVendor,
 
  242                                  dev->descriptor.idProduct);
 
  253                  int (*is_device_ok)(uint16_t vendor, uint16_t product))
 
  261 #ifdef HAVE_LIBUDEV_H 
  263 static const char* get_sysattr(
struct udev_device* device, 
const char* attr)
 
  265         const char* s = udev_device_get_sysattr_value(device, attr);
 
  272 static bool format_udev_entry(
struct udev* udev,
 
  273                               struct udev_list_entry* device,
 
  277         const char* 
const syspath = udev_list_entry_get_name(device);
 
  278         struct udev_device* udev_device =
 
  279                 udev_device_new_from_syspath(udev, syspath);
 
  280         const char* 
const devnode = udev_device_get_devnode(udev_device);
 
  281         const char* idVendor;
 
  282         const char* idProduct;
 
  286         udev_device = get_some_info(udev_device, &idVendor, &idProduct);
 
  287         snprintf(buff, size, 
"%s [%s:%s] %s %s version: %s serial: %s",
 
  291                  get_sysattr(udev_device, 
"manufacturer"),
 
  292                  get_sysattr(udev_device, 
"product"),
 
  293                  get_sysattr(udev_device, 
"version"),
 
  294                  get_sysattr(udev_device, 
"serial")
 
  301 static void add_links(glob_t* globbuf,
 
  303                       struct udev_list_entry* target_entry)
 
  309         const char* 
const syspath = udev_list_entry_get_name(target_entry);
 
  310         struct udev_device* target_device =
 
  311                 udev_device_new_from_syspath(udev, syspath);
 
  312         struct udev_list_entry* links =
 
  313                 udev_device_get_devlinks_list_entry(target_device);
 
  315         while (links != NULL) {
 
  316                 pathlen = readlink(udev_list_entry_get_name(links),
 
  319                 path[pathlen] = 
'\0';
 
  320                 snprintf(buff, 
sizeof(buff), 
"%s -> %s",
 
  321                          udev_list_entry_get_name(links), path);
 
  322                 links = udev_list_entry_get_next(links);
 
  329 static bool is_dup(glob_t* globbuf, 
const char* buff)
 
  333         for (i = 0; i < globbuf->gl_pathc; i += 1) {
 
  334                 if (strcmp(globbuf->gl_pathv[i], buff) == 0)
 
  344                                 struct udev_list_entry* device_entry)
 
  348         const char* 
const syspath = udev_list_entry_get_name(device_entry);
 
  349         struct udev_device* device =
 
  350                 udev_device_new_from_syspath(udev, syspath);
 
  351         struct udev_device* parent =
 
  352             udev_device_get_parent_with_subsystem_devtype(device,
 
  356         return parent != NULL;
 
  366         struct udev_enumerate* enumerate;
 
  367         struct udev_list_entry* devices;
 
  368         struct udev_list_entry* device;
 
  380                 enumerate = udev_enumerate_new(udev);
 
  381                 if (what->idVendor != NULL)
 
  382                         udev_enumerate_add_match_sysattr(
 
  383                                 enumerate, 
"idVendor", what->idVendor);
 
  384                 if (what->idProduct != NULL)
 
  385                         udev_enumerate_add_match_sysattr(
 
  386                                 enumerate, 
"idProduct", what->idProduct);
 
  388                         udev_enumerate_add_match_subsystem(enumerate,
 
  390                 udev_enumerate_scan_devices(enumerate);
 
  391                 devices = udev_enumerate_get_list_entry(enumerate);
 
  392                 udev_list_entry_foreach(device, devices) {
 
  393                         if (!check_parent_subsys(what, udev, device))
 
  395                         if (!format_udev_entry(udev, device,
 
  398                         if (is_dup(globbuf, buff))
 
  401                         add_links(globbuf, udev, device);
 
  403                 udev_enumerate_unref(enumerate);
 
Interface to the userspace drivers.
void drv_enum_free(glob_t *glob)
Free memory allocated by for a glob_t.
int drv_enum_glob(glob_t *globbuf, const char *const pattern)
List all devices matching glob(3) pattern.
void drv_enum_add_udev_info(glob_t *oldbuf)
Try to add udev info to existing entries in glob.
void glob_t_init(glob_t *glob)
Setup a glob_t variable to empty state.
int drv_enum_globs(glob_t *globbuf, const char *const *patterns)
List devices matching any of patterns in null-terminated list.
int drv_enum_udev(glob_t *globbuf, const struct drv_enum_udev_what *what)
List all devices matching any of conditions in {0}-terminated list.
int drv_enum_usb(glob_t *glob, int(*is_device_ok)(uint16_t vendor, uint16_t product))
List all available devices matched by is_device_ok() using libusb.
void glob_t_add_path(glob_t *glob, const char *path)
Add a path to glob, allocating memory as necessary.
dynamic drivers device enumeration support
#define DRV_ERR_BAD_VALUE
drvctl error: arg is bad
#define DRV_ERR_ENUM_EMPTY
No requested data available.
#define DRV_ERR_NOT_IMPLEMENTED
drvctl definitions
#define DRV_ERR_BAD_STATE
drvctl error: cmd and arg is OK, but other errors.
#define log_debug(fmt,...)
Log a debug message.
#define log_perror_debug(fmt,...)
perror wrapper logging with level LIRC_DEBUG.
#define log_error(fmt,...)
Log an error message.
logchannel_t
Log channels used to filter messages.
Condition to match in drv_enum_udev().
const char * subsystem
Require given subsystem.
const char * parent_subsys
Require a given subsystem parent.