static int enumerate_partitions(dev_t devnum) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *home = NULL, *srv = NULL; struct udev_list_entry *first, *item; struct udev_device *parent = NULL; const char *node, *pttype, *devtype; int home_nr = -1, srv_nr = -1; bool home_rw = true, srv_rw = true; blkid_partlist pl; int r, k; dev_t pn; udev = udev_new(); if (!udev) return log_oom(); d = udev_device_new_from_devnum(udev, 'b', devnum); if (!d) return log_oom(); parent = udev_device_get_parent(d); if (!parent) { log_debug("Not a partitioned device, ignoring."); return 0; } /* Does it have a devtype? */ devtype = udev_device_get_devtype(parent); if (!devtype) { log_debug("Parent doesn't have a device type, ignoring."); return 0; } /* Is this a disk or a partition? We only care for disks... */ if (!streq(devtype, "disk")) { log_debug("Parent isn't a raw disk, ignoring."); return 0; } /* Does it have a device node? */ node = udev_device_get_devnode(parent); if (!node) { log_debug("Parent device does not have device node, ignoring."); return 0; } log_debug("Root device %s.", node); pn = udev_device_get_devnum(parent); if (major(pn) == 0) return 0; errno = 0; b = blkid_new_probe_from_filename(node); if (!b) { if (errno == 0) return log_oom(); log_error_errno(errno, "Failed allocate prober: %m"); return -errno; } blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == -2 || r == 1) /* no result or uncertain */ return 0; else if (r != 0) { if (errno == 0) errno = EIO; log_error_errno(errno, "Failed to probe %s: %m", node); return -errno; } errno = 0; r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (r != 0) { if (errno == 0) errno = EIO; log_error_errno(errno, "Failed to determine partition table type of %s: %m", node); return -errno; } /* We only do this all for GPT... */ if (!streq_ptr(pttype, "gpt")) { log_debug("Not a GPT partition table, ignoring."); return 0; } errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return log_oom(); log_error_errno(errno, "Failed to list partitions of %s: %m", node); return -errno; } e = udev_enumerate_new(udev); if (!e) return log_oom(); r = udev_enumerate_add_match_parent(e, parent); if (r < 0) return log_oom(); r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return log_oom(); r = udev_enumerate_scan_devices(e); if (r < 0) return log_error_errno(r, "Failed to enumerate partitions on %s: %m", node); first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; const char *stype, *subnode; sd_id128_t type_id; blkid_partition pp; dev_t qn; int nr; unsigned long long flags; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) continue; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (qn == devnum) continue; if (qn == pn) continue; subnode = udev_device_get_devnode(q); if (!subnode) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; flags = blkid_partition_get_flags(pp); /* Ignore partitions that are not marked for automatic * mounting on discovery */ if (flags & GPT_FLAG_NO_AUTO) continue; nr = blkid_partition_get_partno(pp); if (nr < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; if (sd_id128_equal(type_id, GPT_SWAP)) { if (flags & GPT_FLAG_READ_ONLY) { log_debug("%s marked as read-only swap partition, which is bogus, ignoring.", subnode); continue; } k = add_swap(subnode); if (k < 0) r = k; } else if (sd_id128_equal(type_id, GPT_HOME)) { /* We only care for the first /home partition */ if (home && nr >= home_nr) continue; home_nr = nr; home_rw = !(flags & GPT_FLAG_READ_ONLY), free(home); home = strdup(subnode); if (!home) return log_oom(); } else if (sd_id128_equal(type_id, GPT_SRV)) { /* We only care for the first /srv partition */ if (srv && nr >= srv_nr) continue; srv_nr = nr; srv_rw = !(flags & GPT_FLAG_READ_ONLY), free(srv); srv = strdup(node); if (!srv) return log_oom(); } }
/* * enumerate available v4l2 devices * and creates list in vd->list_devices * args: * none * * asserts: * my_device_list.udev is not null * my_device_list.list_devices is null * * returns: error code */ int enum_v4l2_devices() { struct udev_enumerate *enumerate; struct udev_list_entry *devices; struct udev_list_entry *dev_list_entry; int num_dev = 0; struct v4l2_capability v4l2_cap; my_device_list.list_devices = calloc(1, sizeof(v4l2_dev_sys_data_t)); if(my_device_list.list_devices == NULL) { fprintf(stderr, "V4L2_CORE: FATAL memory allocation failure (enum_v4l2_devices): %s\n", strerror(errno)); exit(-1); } /* Create a list of the devices in the 'v4l2' subsystem. */ enumerate = udev_enumerate_new(my_device_list.udev); udev_enumerate_add_match_subsystem(enumerate, "video4linux"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* * For each item enumerated, print out its information. * udev_list_entry_foreach is a macro which expands to * a loop. The loop will be executed for each member in * devices, setting dev_list_entry to a list entry * which contains the device's path in /sys. */ udev_list_entry_foreach(dev_list_entry, devices) { const char *path; /* * Get the filename of the /sys entry for the device * and create a udev_device object (dev) representing it */ path = udev_list_entry_get_name(dev_list_entry); struct udev_device *dev = udev_device_new_from_syspath(my_device_list.udev, path); /* usb_device_get_devnode() returns the path to the device node itself in /dev. */ const char *v4l2_device = udev_device_get_devnode(dev); if (verbosity > 0) printf("V4L2_CORE: Device Node Path: %s\n", v4l2_device); int fd = 0; /* open the device and query the capabilities */ if ((fd = v4l2_open(v4l2_device, O_RDWR | O_NONBLOCK, 0)) < 0) { fprintf(stderr, "V4L2_CORE: ERROR opening V4L2 interface for %s\n", v4l2_device); v4l2_close(fd); continue; /*next dir entry*/ } if (xioctl(fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) { fprintf(stderr, "V4L2_CORE: VIDIOC_QUERYCAP error: %s\n", strerror(errno)); fprintf(stderr, "V4L2_CORE: couldn't query device %s\n", v4l2_device); v4l2_close(fd); continue; /*next dir entry*/ } v4l2_close(fd); num_dev++; /* Update the device list*/ my_device_list.list_devices = realloc(my_device_list.list_devices, num_dev * sizeof(v4l2_dev_sys_data_t)); if(my_device_list.list_devices == NULL) { fprintf(stderr, "V4L2_CORE: FATAL memory allocation failure (enum_v4l2_devices): %s\n", strerror(errno)); exit(-1); } my_device_list.list_devices[num_dev-1].device = strdup(v4l2_device); my_device_list.list_devices[num_dev-1].name = strdup((char *) v4l2_cap.card); my_device_list.list_devices[num_dev-1].driver = strdup((char *) v4l2_cap.driver); my_device_list.list_devices[num_dev-1].location = strdup((char *) v4l2_cap.bus_info); my_device_list.list_devices[num_dev-1].valid = 1; my_device_list.list_devices[num_dev-1].current = 0; /* The device pointed to by dev contains information about the v4l2 device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it.*/ dev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); if (!dev) { fprintf(stderr, "V4L2_CORE: Unable to find parent usb device."); continue; } /* From here, we can call get_sysattr_value() for each file in the device's /sys entry. The strings passed into these functions (idProduct, idVendor, serial, etc.) correspond directly to the files in the directory which represents the USB device. Note that USB strings are Unicode, UCS2 encoded, but the strings returned from udev_device_get_sysattr_value() are UTF-8 encoded. */ if (verbosity > 0) { printf(" VID/PID: %s %s\n", udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct")); printf(" %s\n %s\n", udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product")); printf(" serial: %s\n", udev_device_get_sysattr_value(dev, "serial")); printf(" busnum: %s\n", udev_device_get_sysattr_value(dev, "busnum")); printf(" devnum: %s\n", udev_device_get_sysattr_value(dev, "devnum")); } my_device_list.list_devices[num_dev-1].vendor = strtoull(udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16); my_device_list.list_devices[num_dev-1].product = strtoull(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16); my_device_list.list_devices[num_dev-1].busnum = strtoull(udev_device_get_sysattr_value(dev, "busnum"), NULL, 10); my_device_list.list_devices[num_dev-1].devnum = strtoull(udev_device_get_sysattr_value(dev, "devnum"), NULL, 10); udev_device_unref(dev); } /* Free the enumerator object */ udev_enumerate_unref(enumerate); my_device_list.num_devices = num_dev; return(E_OK); }
static int enumerate_partitions(dev_t devnum) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL; struct udev_list_entry *first, *item; struct udev_device *parent = NULL; const char *name, *node, *pttype, *devtype; int boot_nr = -1, home_nr = -1, srv_nr = -1; bool home_rw = true, srv_rw = true; blkid_partlist pl; int r, k; dev_t pn; udev = udev_new(); if (!udev) return log_oom(); d = udev_device_new_from_devnum(udev, 'b', devnum); if (!d) return log_oom(); name = udev_device_get_devnode(d); if (!name) name = udev_device_get_syspath(d); if (!name) { log_debug("Device %u:%u does not have a name, ignoring.", major(devnum), minor(devnum)); return 0; } parent = udev_device_get_parent(d); if (!parent) { log_debug("%s: not a partitioned device, ignoring.", name); return 0; } /* Does it have a devtype? */ devtype = udev_device_get_devtype(parent); if (!devtype) { log_debug("%s: parent doesn't have a device type, ignoring.", name); return 0; } /* Is this a disk or a partition? We only care for disks... */ if (!streq(devtype, "disk")) { log_debug("%s: parent isn't a raw disk, ignoring.", name); return 0; } /* Does it have a device node? */ node = udev_device_get_devnode(parent); if (!node) { log_debug("%s: parent device does not have device node, ignoring.", name); return 0; } log_debug("%s: root device %s.", name, node); pn = udev_device_get_devnum(parent); if (major(pn) == 0) return 0; errno = 0; b = blkid_new_probe_from_filename(node); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to allocate prober: %m", node); } blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == 1) return 0; /* no results */ else if (r == -2) { log_warning("%s: probe gave ambiguous results, ignoring", node); return 0; } else if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node); errno = 0; r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to determine partition table type: %m", node); /* We only do this all for GPT... */ if (!streq_ptr(pttype, "gpt")) { log_debug("%s: not a GPT partition table, ignoring.", node); return 0; } errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to list partitions: %m", node); } e = udev_enumerate_new(udev); if (!e) return log_oom(); r = udev_enumerate_add_match_parent(e, parent); if (r < 0) return log_oom(); r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return log_oom(); r = udev_enumerate_scan_devices(e); if (r < 0) return log_error_errno(r, "%s: failed to enumerate partitions: %m", node); first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; unsigned long long flags; const char *stype, *subnode; sd_id128_t type_id; blkid_partition pp; dev_t qn; int nr; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) continue; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (qn == devnum) continue; if (qn == pn) continue; subnode = udev_device_get_devnode(q); if (!subnode) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; nr = blkid_partition_get_partno(pp); if (nr < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; flags = blkid_partition_get_flags(pp); if (sd_id128_equal(type_id, GPT_SWAP)) { if (flags & GPT_FLAG_NO_AUTO) continue; if (flags & GPT_FLAG_READ_ONLY) { log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode); continue; } k = add_swap(subnode); if (k < 0) r = k; } else if (sd_id128_equal(type_id, GPT_ESP)) { /* We only care for the first /boot partition */ if (boot && nr >= boot_nr) continue; /* Note that we do not honour the "no-auto" * flag for the ESP, as it is often unset, to * hide it from Windows. */ boot_nr = nr; r = free_and_strdup(&boot, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_HOME)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /home partition */ if (home && nr >= home_nr) continue; home_nr = nr; home_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&home, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_SRV)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /srv partition */ if (srv && nr >= srv_nr) continue; srv_nr = nr; srv_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&srv, subnode); if (r < 0) return log_oom(); } }
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; struct hid_device_info *prev_dev = NULL; /* previous device */ hid_init(); /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); return NULL; } /* Create a list of the devices in the 'hidraw' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "hidraw"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each item, see if it matches the vid/pid, and if so create a udev_device record for it */ udev_list_entry_foreach(dev_list_entry, devices) { const char *sysfs_path; const char *dev_path; const char *str; struct udev_device *raw_dev; /* The device's hidraw udev node. */ struct udev_device *hid_dev; /* The device's HID udev node. */ struct udev_device *usb_dev; /* The device's USB udev node. */ struct udev_device *intf_dev; /* The device's interface (in the USB sense). */ unsigned short dev_vid; unsigned short dev_pid; char *serial_number_utf8 = NULL; char *product_name_utf8 = NULL; int bus_type; int result; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ sysfs_path = udev_list_entry_get_name(dev_list_entry); raw_dev = udev_device_new_from_syspath(udev, sysfs_path); dev_path = udev_device_get_devnode(raw_dev); hid_dev = udev_device_get_parent_with_subsystem_devtype( raw_dev, "hid", NULL); if (!hid_dev) { /* Unable to find parent hid device. */ goto next; } result = parse_uevent_info( udev_device_get_sysattr_value(hid_dev, "uevent"), &bus_type, &dev_vid, &dev_pid, &serial_number_utf8, &product_name_utf8); if (!result) { /* parse_uevent_info() failed for at least one field. */ goto next; } if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) { /* We only know how to handle USB and BT devices. */ goto next; } /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 || vendor_id == dev_vid) && (product_id == 0x0 || product_id == dev_pid)) { struct hid_device_info *tmp; /* VID/PID match. Create the record. */ tmp = malloc(sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } prev_dev = cur_dev; cur_dev = tmp; /* Fill out the record */ cur_dev->next = NULL; cur_dev->path = dev_path? strdup(dev_path): NULL; /* VID/PID */ cur_dev->vendor_id = dev_vid; cur_dev->product_id = dev_pid; /* Serial Number */ cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8); /* Release Number */ cur_dev->release_number = 0x0; /* Interface Number */ cur_dev->interface_number = -1; switch (bus_type) { case BUS_USB: /* The device pointed to by raw_dev contains information about the hidraw device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it. */ usb_dev = udev_device_get_parent_with_subsystem_devtype( raw_dev, "usb", "usb_device"); if (!usb_dev) { /* Free this device */ free(cur_dev->serial_number); free(cur_dev->path); free(cur_dev); /* Take it off the device list. */ if (prev_dev) { prev_dev->next = NULL; cur_dev = prev_dev; } else { cur_dev = root = NULL; } goto next; } /* Manufacturer and Product strings */ cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]); cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]); /* Release Number */ str = udev_device_get_sysattr_value(usb_dev, "bcdDevice"); cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; /* Get a handle to the interface's udev node. */ intf_dev = udev_device_get_parent_with_subsystem_devtype( raw_dev, "usb", "usb_interface"); if (intf_dev) { str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; } break; case BUS_BLUETOOTH: /* Manufacturer and Product strings */ cur_dev->manufacturer_string = wcsdup(L""); cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); break; default: /* Unknown device type - this should never happen, as we * check for USB and Bluetooth devices above */ break; } } next: free(serial_number_utf8); free(product_name_utf8); udev_device_unref(raw_dev); /* hid_dev, usb_dev and intf_dev don't need to be (and can't be) unref()d. It will cause a double-free() error. I'm not sure why. */ } /* Free the enumerator and udev objects. */ udev_enumerate_unref(enumerate); udev_unref(udev); return root; }
static int get_js_number(struct udev_device *udevice) { struct udev_list_entry *devices, *dev_list_entry; struct udev_enumerate *enumerate; struct udev_device *hid_parent; const char *hidraw_node; const char *hid_id; int number = 0; hid_parent = udev_device_get_parent_with_subsystem_devtype(udevice, "hid", NULL); /* * Look for HID_UNIQ first for the correct behavior via BT, if * HID_UNIQ is not available it means the USB bus is being used and we * can rely on HID_PHYS. */ hid_id = udev_device_get_property_value(hid_parent, "HID_UNIQ"); if (!hid_id) hid_id = udev_device_get_property_value(hid_parent, "HID_PHYS"); hidraw_node = udev_device_get_devnode(udevice); if (!hid_id || !hidraw_node) return 0; enumerate = udev_enumerate_new(udev_device_get_udev(udevice)); udev_enumerate_add_match_sysname(enumerate, "js*"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); udev_list_entry_foreach(dev_list_entry, devices) { struct udev_device *input_parent; struct udev_device *js_dev; const char *input_id; const char *devname; devname = udev_list_entry_get_name(dev_list_entry); js_dev = udev_device_new_from_syspath( udev_device_get_udev(udevice), devname); input_parent = udev_device_get_parent_with_subsystem_devtype( js_dev, "input", NULL); if (!input_parent) goto next; /* check if this is the joystick relative to the hidraw device * above */ input_id = udev_device_get_sysattr_value(input_parent, "uniq"); /* * A strlen() check is needed because input device over USB * have the UNIQ attribute defined but with an empty value. */ if (!input_id || strlen(input_id) == 0) input_id = udev_device_get_sysattr_value(input_parent, "phys"); if (!input_id) goto next; if (!strcmp(input_id, hid_id)) { number = atoi(udev_device_get_sysnum(js_dev)); /* joystick numbers start from 0, leds from 1 */ number++; udev_device_unref(js_dev); break; } next: udev_device_unref(js_dev); } udev_enumerate_unref(enumerate); return number; }
void CUDevProvider::GetDisks(VECSOURCES& disks, bool removable) { // enumerate existing block devices struct udev_enumerate *u_enum = udev_enumerate_new(m_udev); if (u_enum == NULL) { fprintf(stderr, "Error: udev_enumerate_new(udev)\n"); return; } udev_enumerate_add_match_subsystem(u_enum, "block"); udev_enumerate_add_match_property(u_enum, "DEVTYPE", "disk"); udev_enumerate_add_match_property(u_enum, "DEVTYPE", "partition"); udev_enumerate_scan_devices(u_enum); struct udev_list_entry *u_list_ent; struct udev_list_entry *u_first_list_ent; u_first_list_ent = udev_enumerate_get_list_entry(u_enum); udev_list_entry_foreach(u_list_ent, u_first_list_ent) { const char *name = udev_list_entry_get_name(u_list_ent); struct udev *context = udev_enumerate_get_udev(u_enum); struct udev_device *device = udev_device_new_from_syspath(context, name); if (device == NULL) continue; // filter out devices that are not mounted const char *mountpoint = get_mountpoint(udev_device_get_devnode(device)); if (!mountpoint) { udev_device_unref(device); continue; } // filter out root partition if (strcmp(mountpoint, "/") == 0) { udev_device_unref(device); continue; } // filter out things mounted on /tmp if (strstr(mountpoint, "/tmp")) { udev_device_unref(device); continue; } // look for devices on the usb bus, or mounted on */media/ (sdcards), or optical devices const char *bus = udev_device_get_property_value(device, "ID_BUS"); const char *optical = udev_device_get_property_value(device, "ID_CDROM"); // matches also DVD, Blu-ray bool isRemovable = ((bus && strstr(bus, "usb")) || (optical && strstr(optical,"1")) || (mountpoint && strstr(mountpoint, "/media/"))); // filter according to requested device type if (removable != isRemovable) { udev_device_unref(device); continue; } const char *udev_label = udev_device_get_property_value(device, "ID_FS_LABEL"); std::string label; if (udev_label) label = udev_label; else label = URIUtils::GetFileName(mountpoint); CMediaSource share; share.strName = label; share.strPath = mountpoint; share.m_ignore = true; if (isRemovable) { if (optical) share.m_iDriveType = CMediaSource::SOURCE_TYPE_DVD; else share.m_iDriveType = CMediaSource::SOURCE_TYPE_REMOVABLE; } else share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL; disks.push_back(share); udev_device_unref(device); } udev_enumerate_unref(u_enum); }
static char *map_block_to_usb_dev(const char *block_dev) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; char *usb_dev_path = NULL; udev = udev_new(); if (!udev) err(errno, "Can't create udev"); /* XXX Avoid the enumeration using udev_device_new_from_devnum(). */ enumerate = udev_enumerate_new(udev); assert(enumerate); assert(!udev_enumerate_add_match_subsystem(enumerate, "block")); assert(!udev_enumerate_scan_devices(enumerate)); devices = udev_enumerate_get_list_entry(enumerate); assert(devices); udev_list_entry_foreach(dev_list_entry, devices) { const char *sys_path, *dev_path; struct udev_device *dev, *parent_dev; /* Get the filename of the /sys entry for the device, * and create a udev_device object (dev) representing it. */ sys_path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, sys_path); /* usb_device_get_devnode() returns the path to * the device node itself in /dev. */ dev_path = udev_device_get_devnode(dev); if (strcmp(block_dev, dev_path)) { assert(!udev_device_unref(dev)); continue; } /* The device pointed to by dev contains information about * the USB device. * In order to get information about the USB device, * get the parent device with the subsystem/devtype pair of * "usb"/"usb_device". * This will be several levels up the tree, * but the function will find it. */ parent_dev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); if (!parent_dev) err(errno, "Unable to find parent usb device of `%s'", block_dev); usb_dev_path = strdup(udev_device_get_devnode(parent_dev)); /* @parent_dev is not referenced, and will be freed when * the child (i.e. @dev) is freed. * See udev_device_get_parent_with_subsystem_devtype() for * details. */ assert(!udev_device_unref(dev)); break; } /* Free the enumerator object. */ assert(!udev_enumerate_unref(enumerate)); assert(!udev_unref(udev)); return usb_dev_path; }
/* * Finds if a USB device whose VID, PID and serial number is given is connected to system * or not using platform specific APIs. * * Returns 1 if device is connected, returns 0 if not connected, -1 if an error occurs. */ jint is_usb_dev_connected(JNIEnv *env, jint usbvid_to_match, jint usbpid_to_match, jstring serial_number) { int vid = 0; int pid = 0; struct udev *udev_ctx; struct udev_enumerate *enumerator; struct udev_list_entry *devices, *dev_list_entry; const char *sysattr_val; const char *path; struct udev_device *udev_device; char *endptr; const char* serial = NULL; if(serial_number != NULL) { serial = (*env)->GetStringUTFChars(env, serial_number, NULL); if((serial == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { throw_serialcom_exception(env, 3, 0, E_GETSTRUTFCHARSTR); return -1; } } /* libudev is reference counted. Memory is freed when counts reach to zero. */ udev_ctx = udev_new(); enumerator = udev_enumerate_new(udev_ctx); udev_enumerate_add_match_subsystem(enumerator, "usb"); udev_enumerate_scan_devices(enumerator); devices = udev_enumerate_get_list_entry(enumerator); udev_list_entry_foreach(dev_list_entry, devices) { path = udev_list_entry_get_name(dev_list_entry); udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path); if(udev_device == NULL) { continue; } if(strcmp("usb_device", udev_device_get_devtype(udev_device)) == 0) { /* match vid */ sysattr_val = udev_device_get_sysattr_value(udev_device, "idVendor"); if(sysattr_val != NULL) { vid = 0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16); if(vid != usbvid_to_match) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } /* match pid */ sysattr_val = udev_device_get_sysattr_value(udev_device, "idProduct"); if(sysattr_val != NULL) { pid = 0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16); if(pid != usbpid_to_match) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } /* match serial number if requested by application */ if (serial != NULL) { sysattr_val = udev_device_get_sysattr_value(udev_device, "serial"); if(sysattr_val != NULL) { if(strcasecmp(sysattr_val, serial) != 0) { udev_device_unref(udev_device); continue; } }else { udev_device_unref(udev_device); continue; } } /* reaching here means device is connected to system at present which matches given criteria. */ udev_device_unref(udev_device); udev_enumerate_unref(enumerator); udev_unref(udev_ctx); return 1; } udev_device_unref(udev_device); }
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; struct hid_device_info *root = NULL; // return object struct hid_device_info *cur_dev = NULL; setlocale(LC_ALL,""); /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); return NULL; } /* Create a list of the devices in the 'hidraw' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "hidraw"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each item, see if it matches the vid/pid, and if so create a udev_device record for it */ udev_list_entry_foreach(dev_list_entry, devices) { const char *sysfs_path; const char *dev_path; const char *str; unsigned short dev_vid; unsigned short dev_pid; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ sysfs_path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, sysfs_path); dev_path = udev_device_get_devnode(dev); /* The device pointed to by dev contains information about the hidraw device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it.*/ dev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); if (!dev) { /* Unable to find parent usb device. */ goto next; } /* Get the VID/PID of the device */ str = udev_device_get_sysattr_value(dev,"idVendor"); dev_vid = (str)? strtol(str, NULL, 16): 0x0; str = udev_device_get_sysattr_value(dev, "idProduct"); dev_pid = (str)? strtol(str, NULL, 16): 0x0; /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 && product_id == 0x0) || (vendor_id == dev_vid && product_id == dev_pid)) { struct hid_device_info *tmp; size_t len; /* VID/PID match. Create the record. */ tmp = malloc(sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Fill out the record */ cur_dev->next = NULL; str = dev_path; if (str) { len = strlen(str); cur_dev->path = calloc(len+1, sizeof(char)); strncpy(cur_dev->path, str, len+1); cur_dev->path[len] = '\0'; } else cur_dev->path = NULL; /* Serial Number */ cur_dev->serial_number = copy_udev_string(dev, "serial"); /* Manufacturer and Product strings */ cur_dev->manufacturer_string = copy_udev_string(dev, "manufacturer"); cur_dev->product_string = copy_udev_string(dev, "product"); /* VID/PID */ cur_dev->vendor_id = dev_vid; cur_dev->product_id = dev_pid; /* Release Number */ str = udev_device_get_sysattr_value(dev, "bcdDevice"); cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; /* Interface Number (Unsupported on Linux/hidraw) */ cur_dev->interface_number = -1; } else goto next; next: udev_device_unref(dev); } /* Free the enumerator and udev objects. */ udev_enumerate_unref(enumerate); udev_unref(udev); return root; }
/** * Probes and initializes. */ static int Open (vlc_object_t *obj, const struct subsys *subsys) { services_discovery_t *sd = (services_discovery_t *)obj; services_discovery_sys_t *p_sys = malloc (sizeof (*p_sys)); if (p_sys == NULL) return VLC_ENOMEM; sd->p_sys = p_sys; p_sys->subsys = subsys; p_sys->root = NULL; struct udev_monitor *mon = NULL; struct udev *udev = udev_new (); if (udev == NULL) goto error; mon = udev_monitor_new_from_netlink (udev, "udev"); if (mon == NULL || udev_monitor_filter_add_match_subsystem_devtype (mon, subsys->name, NULL)) goto error; p_sys->monitor = mon; /* Enumerate existing devices */ struct udev_enumerate *devenum = udev_enumerate_new (udev); if (devenum == NULL) goto error; if (udev_enumerate_add_match_subsystem (devenum, subsys->name)) { udev_enumerate_unref (devenum); goto error; } udev_monitor_enable_receiving (mon); /* Note that we enumerate _after_ monitoring is enabled so that we do not * loose device events occuring while we are enumerating. We could still * loose events if the Netlink socket receive buffer overflows. */ udev_enumerate_scan_devices (devenum); struct udev_list_entry *devlist = udev_enumerate_get_list_entry (devenum); struct udev_list_entry *deventry; udev_list_entry_foreach (deventry, devlist) { const char *path = udev_list_entry_get_name (deventry); struct udev_device *dev = udev_device_new_from_syspath (udev, path); AddDevice (sd, dev); udev_device_unref (dev); } udev_enumerate_unref (devenum); if (vlc_clone (&p_sys->thread, Run, sd, VLC_THREAD_PRIORITY_LOW)) { /* Fallback without thread */ udev_monitor_unref (mon); udev_unref (udev); p_sys->monitor = NULL; } return VLC_SUCCESS; error: if (mon != NULL) udev_monitor_unref (mon); if (udev != NULL) udev_unref (udev); free (p_sys); return VLC_EGENERIC; }
int main (void) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; struct udev_monitor *mon; int fd; /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); exit(1); } /* This section sets up a monitor which will report events when devices attached to the system change. Events include "add", "remove", "change", "online", and "offline". This section sets up and starts the monitoring. Events are polled for (and delivered) later in the file. It is important that the monitor be set up before the call to udev_enumerate_scan_devices() so that events (and devices) are not missed. For example, if enumeration happened first, there would be no event generated for a device which was attached after enumeration but before monitoring began. Note that a filter is added so that we only get events for "hidraw" devices. */ /* Set up a monitor to monitor hidraw devices */ mon = udev_monitor_new_from_netlink(udev, "udev"); udev_monitor_filter_add_match_subsystem_devtype(mon, "hidraw", NULL); udev_monitor_enable_receiving(mon); /* Get the file descriptor (fd) for the monitor. This fd will get passed to select() */ fd = udev_monitor_get_fd(mon); /* Create a list of the devices in the 'hidraw' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "hidraw"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each item enumerated, print out its information. udev_list_entry_foreach is a macro which expands to a loop. The loop will be executed for each member in devices, setting dev_list_entry to a list entry which contains the device's path in /sys. */ udev_list_entry_foreach(dev_list_entry, devices) { const char *path; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, path); /* usb_device_get_devnode() returns the path to the device node itself in /dev. */ printf("Device Node Path: %s\n", udev_device_get_devnode(dev)); /* The device pointed to by dev contains information about the hidraw device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it.*/ dev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); if (!dev) { printf("Unable to find parent usb device."); exit(1); } /* From here, we can call get_sysattr_value() for each file in the device's /sys entry. The strings passed into these functions (idProduct, idVendor, serial, etc.) correspond directly to the files in the /sys directory which represents the USB device. Note that USB strings are Unicode, UCS2 encoded, but the strings returned from udev_device_get_sysattr_value() are UTF-8 encoded. */ printf(" VID/PID: %s %s\n", udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct")); printf(" %s\n %s\n", udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product")); printf(" serial: %s\n", udev_device_get_sysattr_value(dev, "serial")); udev_device_unref(dev); } /* Free the enumerator object */ udev_enumerate_unref(enumerate); /* Begin polling for udev events. Events occur when devices attached to the system are added, removed, or change state. udev_monitor_receive_device() will return a device object representing the device which changed and what type of change occured. The select() system call is used to ensure that the call to udev_monitor_receive_device() will not block. The monitor was set up earler in this file, and monitoring is already underway. This section will run continuously, calling usleep() at the end of each pass. This is to demonstrate how to use a udev_monitor in a non-blocking way. */ while (1) { /* Set up the call to select(). In this case, select() will only operate on a single file descriptor, the one associated with our udev_monitor. Note that the timeval object is set to 0, which will cause select() to not block. */ fd_set fds; struct timeval tv; int ret; FD_ZERO(&fds); FD_SET(fd, &fds); tv.tv_sec = 0; tv.tv_usec = 0; ret = select(fd+1, &fds, NULL, NULL, &tv); /* Check if our file descriptor has received data. */ if (ret > 0 && FD_ISSET(fd, &fds)) { printf("\nselect() says there should be data\n"); /* Make the call to receive the device. select() ensured that this will not block. */ dev = udev_monitor_receive_device(mon); if (dev) { printf("Got Device\n"); printf(" Node: %s\n", udev_device_get_devnode(dev)); printf(" Subsystem: %s\n", udev_device_get_subsystem(dev)); printf(" Devtype: %s\n", udev_device_get_devtype(dev)); printf(" Action: %s\n", udev_device_get_action(dev)); udev_device_unref(dev); } else { printf("No Device from receive_device(). An error occured.\n"); } } usleep(250*1000); printf("."); fflush(stdout); } udev_unref(udev); return 0; }
static int get_js_number(struct udev_device *udevice) { struct udev_list_entry *devices, *dev_list_entry; struct udev_enumerate *enumerate; struct udev_device *hid_parent; const char *hidraw_node; const char *hid_phys; int number = 0; hid_parent = udev_device_get_parent_with_subsystem_devtype(udevice, "hid", NULL); hid_phys = udev_device_get_property_value(hid_parent, "HID_PHYS"); hidraw_node = udev_device_get_devnode(udevice); if (!hid_phys || !hidraw_node) return 0; enumerate = udev_enumerate_new(udev_device_get_udev(udevice)); udev_enumerate_add_match_sysname(enumerate, "js*"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); udev_list_entry_foreach(dev_list_entry, devices) { struct udev_device *input_parent; struct udev_device *js_dev; const char *input_phys; const char *devname; devname = udev_list_entry_get_name(dev_list_entry); js_dev = udev_device_new_from_syspath( udev_device_get_udev(udevice), devname); input_parent = udev_device_get_parent_with_subsystem_devtype( js_dev, "input", NULL); if (!input_parent) goto next; /* check if this is the joystick relative to the hidraw device * above */ input_phys = udev_device_get_sysattr_value(input_parent, "phys"); if (!input_phys) goto next; if (!strcmp(input_phys, hid_phys)) { number = atoi(udev_device_get_sysnum(js_dev)); /* joystick numbers start from 0, leds from 1 */ number++; udev_device_unref(js_dev); break; } next: udev_device_unref(js_dev); } udev_enumerate_unref(enumerate); return number; }
static int udev_fill_info(struct device_info *info, struct stat *stat) { struct udev *ctx; struct udev_device *dev, *parent; struct udev_enumerate *uenum; const char *attr; char holders_path[PATH_MAX + 1]; DIR *holders_dir; struct dirent *dir_entry; unsigned long number; char *endptr; if (device_info_verbose >= 3) printf("udev_fill_info()\n"); ctx = udev_new(); if (!ctx) { if (device_info_verbose) printf("no udev library context\n"); return -1; } dev = udev_device_new_from_devnum(ctx, 'b', stat->st_rdev); if (!dev) { if (device_info_verbose) printf("no udev context\n"); udev_unref(ctx); return -1; } /* * first, look for for dependent devices (partitions or virtual mappings on * this device) */ if (device_info_verbose >= 3) printf("looking for dependent devices\n"); uenum = udev_enumerate_new(ctx); if (uenum) { struct udev_list_entry *entry; if (udev_enumerate_add_match_parent(uenum, dev) >= 0 && udev_enumerate_scan_devices(uenum) >= 0) { entry = udev_enumerate_get_list_entry(uenum); if (entry) { /* * the list of children includes the parent device, so make * sure that has_children is -1 to end up with the correct * count */ info->has_children = -1; while (entry) { if (device_info_verbose >= 2) printf("child-or-self: %s\n", udev_list_entry_get_name(entry)); entry = udev_list_entry_get_next(entry); info->has_children++; } } else info->has_children = 0; } udev_enumerate_unref(uenum); } /* see if the holders directory in sysfs exists and has entries */ if (device_info_verbose >= 2) printf("syspath: %s\n", udev_device_get_syspath(dev)); if (info->has_children < 1 || device_info_verbose >= 3) { snprintf(holders_path, PATH_MAX, "%s/holders", udev_device_get_syspath(dev)); holders_path[PATH_MAX] = 0; if (info->has_children < 0) info->has_children = 0; holders_dir = opendir(holders_path); if (holders_dir) { dir_entry = readdir(holders_dir); while (dir_entry) { if (dir_entry->d_reclen && dir_entry->d_name[0] != '.') { if (device_info_verbose >= 2) printf("holder: %s\n", dir_entry->d_name); info->has_children++; /* look up and print every holder when very verbose */ if (device_info_verbose < 3) break; } dir_entry = readdir(holders_dir); } closedir(holders_dir); } } /* * block devices on real hardware have either other block devices * (in the case of partitions) or the actual hardware as parent */ parent = udev_device_get_parent(dev); if (!parent) { if (device_info_verbose >= 3) printf("no parent found, therefore virtual device\n"); info->type = TYPE_VIRTUAL; info->partition = 0; udev_device_unref(dev); return 0; } attr = udev_device_get_sysattr_value(dev, "removable"); if (device_info_verbose >= 3) { if (attr) printf("attribute \"removable\" is \"%s\"\n", attr); else printf("attribute \"removable\" not found\n"); } if (attr && !strcmp(attr, "1")) info->type = TYPE_REMOVABLE; else info->type = TYPE_FIXED; attr = udev_device_get_sysattr_value(dev, "partition"); if (attr) { if (device_info_verbose >= 3) printf("attribute \"partition\" is \"%s\"\n", attr); number = strtoul(attr, &endptr, 10); if (!*endptr) info->partition = number; } else { printf("attribute \"partition\" not found\n"); if (info->type != TYPE_VIRTUAL && parent) { /* partitions have other block devices as parent */ attr = udev_device_get_subsystem(parent); if (attr) { if (device_info_verbose >= 3) printf("parent subsystem is \"%s\"\n", attr); if (!strcmp(attr, "block")) /* we don't know the partition number, use 1 */ info->partition = 1; else info->partition = 0; } } } udev_device_unref(dev); udev_unref(ctx); return 0; }
/** * get_dmi_info: **/ DmiInfo * get_dmi_info () { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices; struct udev_list_entry *dev_list_entry; struct udev_device *dev; DmiInfo *info = NULL; udev = udev_new (); if (!udev) { g_warning ("Cannot create udev"); return NULL; } info = g_new0 (DmiInfo, 1); enumerate = udev_enumerate_new (udev); udev_enumerate_add_match_subsystem (enumerate, "dmi"); udev_enumerate_scan_devices (enumerate); devices = udev_enumerate_get_list_entry (enumerate); udev_list_entry_foreach (dev_list_entry, devices) { const char *path; const char *attribute; path = udev_list_entry_get_name (dev_list_entry); dev = udev_device_new_from_syspath (udev, path); attribute = udev_device_get_sysattr_value (dev, "sys_vendor"); if (attribute) info->sys_vendor = g_strdup (attribute); attribute = udev_device_get_sysattr_value (dev, "bios_date"); if (attribute) info->bios_date = g_strdup (attribute); attribute = udev_device_get_sysattr_value (dev, "bios_vendor"); if (attribute) info->bios_vendor = g_strdup (attribute); attribute = udev_device_get_sysattr_value (dev, "bios_version"); if (attribute) info->bios_version = g_strdup (attribute); attribute = udev_device_get_sysattr_value (dev, "product_name"); if (attribute) info->product_name = g_strdup (attribute); attribute = udev_device_get_sysattr_value (dev, "product_version"); if (attribute) info->product_version = g_strdup (attribute); udev_device_unref (dev); } udev_enumerate_unref (enumerate); udev_unref (udev); return info; }
LDevices *enum_devices( gchar *videodevice, struct udev *udev, int debug) { struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; int num_dev = 0; int fd = 0; struct v4l2_capability v4l2_cap; if (!udev) { /*use fall through method (sysfs)*/ g_printf("Can't create udev...using sysfs method\n"); return(list_devices(videodevice)); } LDevices *listDevices = NULL; listDevices = g_new0( LDevices, 1); listDevices->listVidDevices = NULL; /* Create a list of the devices in the 'v4l2' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "video4linux"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each item enumerated, print out its information. udev_list_entry_foreach is a macro which expands to a loop. The loop will be executed for each member in devices, setting dev_list_entry to a list entry which contains the device's path in /sys. */ udev_list_entry_foreach(dev_list_entry, devices) { const char *path; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, path); /* usb_device_get_devnode() returns the path to the device node itself in /dev. */ const gchar *v4l2_device = udev_device_get_devnode(dev); if (debug) g_printf("Device Node Path: %s\n", v4l2_device); /* open the device and query the capabilities */ if ((fd = v4l2_open(v4l2_device, O_RDWR | O_NONBLOCK, 0)) < 0) { g_printerr("ERROR opening V4L2 interface for %s\n", v4l2_device); v4l2_close(fd); continue; /*next dir entry*/ } if (xioctl(fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) { perror("VIDIOC_QUERYCAP error"); g_printerr(" couldn't query device %s\n", v4l2_device); v4l2_close(fd); continue; /*next dir entry*/ } v4l2_close(fd); num_dev++; /* Update the device list*/ listDevices->listVidDevices = g_renew(VidDevice, listDevices->listVidDevices, num_dev); listDevices->listVidDevices[num_dev-1].device = g_strdup(v4l2_device); listDevices->listVidDevices[num_dev-1].name = g_strdup((gchar *) v4l2_cap.card); listDevices->listVidDevices[num_dev-1].driver = g_strdup((gchar *) v4l2_cap.driver); listDevices->listVidDevices[num_dev-1].location = g_strdup((gchar *) v4l2_cap.bus_info); listDevices->listVidDevices[num_dev-1].valid = 1; if(g_strcmp0(videodevice,listDevices->listVidDevices[num_dev-1].device)==0) { listDevices->listVidDevices[num_dev-1].current = 1; listDevices->current_device = num_dev-1; } else listDevices->listVidDevices[num_dev-1].current = 0; /* The device pointed to by dev contains information about the v4l2 device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it.*/ dev = udev_device_get_parent_with_subsystem_devtype( dev, "usb", "usb_device"); if (!dev) { printf("Unable to find parent usb device."); continue; } /* From here, we can call get_sysattr_value() for each file in the device's /sys entry. The strings passed into these functions (idProduct, idVendor, serial, etc.) correspond directly to the files in the directory which represents the USB device. Note that USB strings are Unicode, UCS2 encoded, but the strings returned from udev_device_get_sysattr_value() are UTF-8 encoded. */ if (debug) { g_printf(" VID/PID: %s %s\n", udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct")); g_printf(" %s\n %s\n", udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product")); g_printf(" serial: %s\n", udev_device_get_sysattr_value(dev, "serial")); } listDevices->listVidDevices[num_dev-1].vendor = g_ascii_strtoull(udev_device_get_sysattr_value(dev,"idVendor"), NULL, 16); listDevices->listVidDevices[num_dev-1].product = g_ascii_strtoull(udev_device_get_sysattr_value(dev, "idProduct"), NULL, 16); udev_device_unref(dev); } /* Free the enumerator object */ udev_enumerate_unref(enumerate); listDevices->num_devices = num_dev; return(listDevices); }
static void get_video_devices (ofGstCamData & cam_data) { int fd, ok; struct udev * my_udev; struct udev_enumerate * enumerate; struct udev_list_entry * list; struct udev_list_entry * entry; my_udev = udev_new(); enumerate = udev_enumerate_new(my_udev); udev_enumerate_scan_devices(enumerate); list = udev_enumerate_get_list_entry(enumerate); int num_devices = 0; udev_list_entry_foreach(entry,list) { const char * name = udev_list_entry_get_name(entry); struct udev_device * device = udev_device_new_from_syspath(my_udev, name); const char * subsystem = udev_device_get_subsystem(device); if(strcmp(subsystem,"video4linux")==0) { num_devices++; } } cam_data.num_webcam_devices = 0; cam_data.webcam_devices = new ofGstDevice[num_devices]; // ofLog (OF_LOG_NOTICE, "Probing devices with udev..."); /* Initialize webcam structures */ udev_list_entry_foreach(entry,list) { const char * name = udev_list_entry_get_name(entry); struct udev_device * device = udev_device_new_from_syspath(my_udev, name); const char * subsystem = udev_device_get_subsystem(device); if(subsystem && strcmp(subsystem,"video4linux")==0) { const char *gstreamer_src, *product_name; struct v4l2_capability v2cap; struct video_capability v1cap; string vendor_id; string product_id; const char * dev_node = udev_device_get_devnode(device); struct udev_list_entry * properties = udev_device_get_properties_list_entry(device); struct udev_list_entry * property; udev_list_entry_foreach(property,properties) { const char * name = udev_list_entry_get_name(property); if(strcmp(name,"ID_VENDOR_ID")==0) { vendor_id = udev_list_entry_get_value(property); } if(strcmp(name,"ID_MODEL_ID")==0) { product_id = udev_list_entry_get_value(property); } } // ofLog (OF_LOG_NOTICE, "Found device " + vendor_id + ":" + product_id + ", getting capabilities..."); /* vbi devices support capture capability too, but cannot be used, * so detect them by device name */ if (strstr (dev_node, "vbi")) { // ofLog (OF_LOG_WARNING, "Skipping vbi device: %s", dev_node); continue; } if ((fd = open (dev_node, O_RDONLY | O_NONBLOCK)) < 0) { // ofLog (OF_LOG_WARNING, "Failed to open %s: %s", dev_node, strerror (errno)); continue; } ok = ioctl (fd, VIDIOC_QUERYCAP, &v2cap); if (ok < 0) { ok = ioctl (fd, VIDIOCGCAP, &v1cap); if (ok < 0) { // ofLog (OF_LOG_WARNING, "Error while probing v4l capabilities for %s: %s", // dev_node, strerror (errno)); close (fd); continue; } // ofLog (OF_LOG_NOTICE,"Detected v4l device: %s", v1cap.name); // ofLog (OF_LOG_NOTICE,"Device type: %d", v1cap.type); gstreamer_src = "v4lsrc"; product_name = v1cap.name; } else { guint cap = v2cap.capabilities; // ofLog (OF_LOG_NOTICE,"Detected v4l2 device: %s", v2cap.card); // ofLog (OF_LOG_NOTICE,"Driver: %s, version: %d", v2cap.driver, v2cap.version); /* g_print ("Bus info: %s\n", v2cap.bus_info); */ /* Doesn't seem anything useful */ // ofLog (OF_LOG_NOTICE,"Capabilities: 0x%08X", v2cap.capabilities); if (!(cap & V4L2_CAP_VIDEO_CAPTURE)) { // ofLog (OF_LOG_NOTICE,"Device %s seems to not have the capture capability, (radio tuner?)\n" // "Removing it from device list.", dev_node); close (fd); continue; } gstreamer_src = "v4l2src"; product_name = (char *) v2cap.card; } //cam_data.webcam_devices[cam_data.num_webcam_devices].hal_udi = g_strdup (udis[i]); cam_data.webcam_devices[cam_data.num_webcam_devices].video_device = g_strdup (dev_node); cam_data.webcam_devices[cam_data.num_webcam_devices].gstreamer_src = g_strdup (gstreamer_src); cam_data.webcam_devices[cam_data.num_webcam_devices].product_name = g_strdup (product_name); cam_data.webcam_devices[cam_data.num_webcam_devices].num_video_formats = 0; cam_data.webcam_devices[cam_data.num_webcam_devices].supported_resolutions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); cam_data.num_webcam_devices++; close (fd); } } /*if (cam_data.num_webcam_devices == 0) { fallback: if (num_udis == 0) { cam_data.webcam_devices = new ofGstDevice; } cam_data.webcam_devices[0].num_video_formats = 0; cam_data.webcam_devices[0].hal_udi = g_strdup ("oF_fake_videodevice"); }*/ cam_data.bInited=true; }
/* * Finds information about USB devices using operating system specific facilities and API. * The sequence of entries in array must match with what java layer expect. If a particular USB attribute * is not set in descriptor or can not be obtained "---" is placed in its place. */ jobjectArray list_usb_devices(JNIEnv *env, jint vendor_to_match) { int x = 0; struct jstrarray_list list = {0}; jstring usb_dev_info; jclass strClass = NULL; jobjectArray usbDevicesFound = NULL; #if defined (__linux__) struct udev *udev_ctx; struct udev_enumerate *enumerator; struct udev_list_entry *devices, *dev_list_entry; const char *sysattr_val; const char *path; struct udev_device *udev_device; char *endptr; #endif #if defined (__APPLE__) kern_return_t kr; CFDictionaryRef matching_dictionary = NULL; io_iterator_t iterator = 0; io_service_t usb_dev_obj; CFNumberRef num_ref; CFStringRef str_ref; int result; char hexcharbuffer[5]; /* For storing USB descriptor attributes string like manufacturer, product, serial number etc. * in any encoding 1024 is sufficient. We prevented malloc() every time for every new attribute. */ char charbuffer[1024]; #endif init_jstrarraylist(&list, 100); #if defined (__linux__) /* libudev is reference counted. Memory is freed when counts reach to zero. */ udev_ctx = udev_new(); enumerator = udev_enumerate_new(udev_ctx); udev_enumerate_add_match_subsystem(enumerator, "usb"); udev_enumerate_scan_devices(enumerator); devices = udev_enumerate_get_list_entry(enumerator); udev_list_entry_foreach(dev_list_entry, devices) { path = udev_list_entry_get_name(dev_list_entry); udev_device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerator), path); if(udev_device == NULL) { continue; } if(strcmp("usb_device", udev_device_get_devtype(udev_device)) == 0) { /* USB-IF vendor ID */ sysattr_val = udev_device_get_sysattr_value(udev_device, "idVendor"); if(sysattr_val != NULL) { if(vendor_to_match != 0) { /* we need to apply filter for identify specific vendor */ if(vendor_to_match != (0x0000FFFF & (int)strtol(sysattr_val, &endptr, 16))) { udev_device_unref(udev_device); continue; } } usb_dev_info = (*env)->NewStringUTF(env, sysattr_val); }else { usb_dev_info = (*env)->NewStringUTF(env, "---"); } if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { return linux_clean_up_and_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx); } insert_jstrarraylist(&list, usb_dev_info); /* USB product ID */ sysattr_val = udev_device_get_sysattr_value(udev_device, "idProduct"); if(sysattr_val != NULL) { usb_dev_info = (*env)->NewStringUTF(env, sysattr_val); }else { usb_dev_info = (*env)->NewStringUTF(env, "---"); } if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { return linux_clean_up_and_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx); } insert_jstrarraylist(&list, usb_dev_info); /* SERIAL NUMBER */ sysattr_val = udev_device_get_sysattr_value(udev_device, "serial"); if(sysattr_val != NULL) { usb_dev_info = (*env)->NewStringUTF(env, sysattr_val); }else { usb_dev_info = (*env)->NewStringUTF(env, "---"); } if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { return linux_clean_up_and_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx); } insert_jstrarraylist(&list, usb_dev_info); /* PRODUCT */ sysattr_val = udev_device_get_sysattr_value(udev_device, "product"); if(sysattr_val != NULL) { usb_dev_info = (*env)->NewStringUTF(env, sysattr_val); }else { usb_dev_info = (*env)->NewStringUTF(env, "---"); } if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { return linux_clean_up_and_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx); } insert_jstrarraylist(&list, usb_dev_info); /* MANUFACTURER */ sysattr_val = udev_device_get_sysattr_value(udev_device, "manufacturer"); if(sysattr_val != NULL) { usb_dev_info = (*env)->NewStringUTF(env, sysattr_val); }else { usb_dev_info = (*env)->NewStringUTF(env, "---"); } if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { return linux_clean_up_and_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx); } insert_jstrarraylist(&list, usb_dev_info); /* BUS NUMBER */ sysattr_val = udev_device_get_sysattr_value(udev_device, "busnum"); if(sysattr_val != NULL) { usb_dev_info = (*env)->NewStringUTF(env, sysattr_val); }else { usb_dev_info = (*env)->NewStringUTF(env, "---"); } if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { return linux_clean_up_and_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx); } insert_jstrarraylist(&list, usb_dev_info); /* CONNECTED USB DEVICE NUMBER */ sysattr_val = udev_device_get_sysattr_value(udev_device, "devnum"); if(sysattr_val != NULL) { usb_dev_info = (*env)->NewStringUTF(env, sysattr_val); }else { usb_dev_info = (*env)->NewStringUTF(env, "---"); } if((usb_dev_info == NULL) || ((*env)->ExceptionOccurred(env) != NULL)) { return linux_clean_up_and_throw_exp(env, 1, NULL, &list, udev_device, enumerator, udev_ctx); } insert_jstrarraylist(&list, usb_dev_info); } udev_device_unref(udev_device); }