void HPMPrivate::run() { udev *udev_ctx = udev_new(); Q_ASSERT(udev_ctx != NULL); udev_monitor *mon = udev_monitor_new_from_netlink(udev_ctx, UDEV_NETLINK_SOURCE); Q_ASSERT(mon != NULL); if (udev_monitor_filter_add_match_subsystem_devtype(mon, USB_SUBSYSTEM, USB_DEVICE_TYPE) < 0) { qWarning() << Q_FUNC_INFO << "Unable to add match for USB devices"; udev_monitor_unref(mon); udev_unref(udev_ctx); return; } if (udev_monitor_enable_receiving(mon) < 0) { qWarning() << Q_FUNC_INFO << "Unable to enable udev uevent reception"; udev_monitor_unref(mon); udev_unref(udev_ctx); return; } int fd = udev_monitor_get_fd(mon); fd_set readfs; FD_ZERO(&readfs); m_run = true; while (m_run == true) { struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; FD_SET(fd, &readfs); int retval = select(fd + 1, &readfs, NULL, NULL, &tv); if (retval == -1) { qWarning() << Q_FUNC_INFO << strerror(errno); m_run = false; } else if (retval > 0 && FD_ISSET(fd, &readfs)) { udev_device *dev = udev_monitor_receive_device(mon); if (dev != NULL) { QString action = QString(udev_device_get_action(dev)); QString vendor = QString(udev_device_get_property_value(dev, PROPERTY_VID)); QString product = QString(udev_device_get_property_value(dev, PROPERTY_PID)); // fallback to composite PRODUCT property VID/PID/REV if (vendor.isEmpty() && product.isEmpty()) { QString compProduct = QString(udev_device_get_property_value(dev, PROPERTY_PRODUCT)); QStringList tokens = compProduct.split("/"); if (tokens.count() >= 2) { vendor = tokens.at(0); product = tokens.at(1); } } if (action.isEmpty() || vendor.isEmpty() || product.isEmpty()) { qWarning() << Q_FUNC_INFO << "Unable to get device properties" << (void*) dev << "Action:" << QString(action); } else if (action == QString(DEVICE_ACTION_ADD)) { uint vid = vendor.toUInt(0, 16); uint pid = product.toUInt(0, 16); HotPlugMonitor* hpm = qobject_cast<HotPlugMonitor*> (parent()); Q_ASSERT(hpm != NULL); hpm->emitDeviceAdded(vid, pid); } else if (action == QString(DEVICE_ACTION_REMOVE)) { uint vid = vendor.toUInt(0, 16); uint pid = product.toUInt(0, 16); HotPlugMonitor* hpm = qobject_cast<HotPlugMonitor*> (parent()); Q_ASSERT(hpm != NULL); hpm->emitDeviceRemoved(vid, pid); } else { qWarning() << Q_FUNC_INFO << "Unhandled udev action:" << action; } udev_device_unref(dev); } } } udev_monitor_unref(mon); udev_unref(udev_ctx); }
static void dev_kmsg_record(Server *s, char *p, size_t l) { struct iovec iovec[N_IOVEC_META_FIELDS + 7 + N_IOVEC_KERNEL_FIELDS + 2 + N_IOVEC_UDEV_FIELDS]; char *message = NULL, *syslog_priority = NULL, *syslog_pid = NULL, *syslog_facility = NULL, *syslog_identifier = NULL, *source_time = NULL; int priority, r; unsigned n = 0, z = 0, j; unsigned long long usec; char *identifier = NULL, *pid = NULL, *e, *f, *k; uint64_t serial; size_t pl; char *kernel_device = NULL; assert(s); assert(p); if (l <= 0) return; e = memchr(p, ',', l); if (!e) return; *e = 0; r = safe_atoi(p, &priority); if (r < 0 || priority < 0 || priority > 999) return; if (s->forward_to_kmsg && (priority & LOG_FACMASK) != LOG_KERN) return; l -= (e - p) + 1; p = e + 1; e = memchr(p, ',', l); if (!e) return; *e = 0; r = safe_atou64(p, &serial); if (r < 0) return; if (s->kernel_seqnum) { /* We already read this one? */ if (serial < *s->kernel_seqnum) return; /* Did we lose any? */ if (serial > *s->kernel_seqnum) server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %"PRIu64" kernel messages", serial - *s->kernel_seqnum); /* Make sure we never read this one again. Note that * we always store the next message serial we expect * here, simply because this makes handling the first * message with serial 0 easy. */ *s->kernel_seqnum = serial + 1; } l -= (e - p) + 1; p = e + 1; f = memchr(p, ';', l); if (!f) return; /* Kernel 3.6 has the flags field, kernel 3.5 lacks that */ e = memchr(p, ',', l); if (!e || f < e) e = f; *e = 0; r = safe_atollu(p, &usec); if (r < 0) return; l -= (f - p) + 1; p = f + 1; e = memchr(p, '\n', l); if (!e) return; *e = 0; pl = e - p; l -= (e - p) + 1; k = e + 1; for (j = 0; l > 0 && j < N_IOVEC_KERNEL_FIELDS; j++) { char *m; /* Meta data fields attached */ if (*k != ' ') break; k ++, l --; e = memchr(k, '\n', l); if (!e) return; *e = 0; m = cunescape_length_with_prefix(k, e - k, "_KERNEL_"); if (!m) break; if (startswith(m, "_KERNEL_DEVICE=")) kernel_device = m + 15; IOVEC_SET_STRING(iovec[n++], m); z++; l -= (e - k) + 1; k = e + 1; } if (kernel_device) { struct udev_device *ud; ud = udev_device_new_from_device_id(s->udev, kernel_device); if (ud) { const char *g; struct udev_list_entry *ll; char *b; g = udev_device_get_devnode(ud); if (g) { b = strappend("_UDEV_DEVNODE=", g); if (b) { IOVEC_SET_STRING(iovec[n++], b); z++; } } g = udev_device_get_sysname(ud); if (g) { b = strappend("_UDEV_SYSNAME=", g); if (b) { IOVEC_SET_STRING(iovec[n++], b); z++; } } j = 0; ll = udev_device_get_devlinks_list_entry(ud); udev_list_entry_foreach(ll, ll) { if (j > N_IOVEC_UDEV_FIELDS) break; g = udev_list_entry_get_name(ll); if (g) { b = strappend("_UDEV_DEVLINK=", g); if (b) { IOVEC_SET_STRING(iovec[n++], b); z++; } } j++; } udev_device_unref(ud); } } if (asprintf(&source_time, "_SOURCE_MONOTONIC_TIMESTAMP=%llu", usec) >= 0) IOVEC_SET_STRING(iovec[n++], source_time); IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=kernel"); if (asprintf(&syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK) >= 0) IOVEC_SET_STRING(iovec[n++], syslog_priority); if ((priority & LOG_FACMASK) == LOG_KERN) IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=kernel"); else { pl -= syslog_parse_identifier((const char**) &p, &identifier, &pid); /* Avoid any messages we generated ourselves via * log_info() and friends. */ if (pid && is_us(pid)) goto finish; if (identifier) { syslog_identifier = strappend("SYSLOG_IDENTIFIER=", identifier); if (syslog_identifier) IOVEC_SET_STRING(iovec[n++], syslog_identifier); } if (pid) { syslog_pid = strappend("SYSLOG_PID=", pid); if (syslog_pid) IOVEC_SET_STRING(iovec[n++], syslog_pid); } if (asprintf(&syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority)) >= 0) IOVEC_SET_STRING(iovec[n++], syslog_facility); } message = cunescape_length_with_prefix(p, pl, "MESSAGE="); if (message) IOVEC_SET_STRING(iovec[n++], message); server_dispatch_message(s, iovec, n, ELEMENTSOF(iovec), NULL, NULL, NULL, 0, NULL, priority, 0); finish: for (j = 0; j < z; j++) free(iovec[j].iov_base); free(message); free(syslog_priority); free(syslog_identifier); free(syslog_pid); free(syslog_facility); free(source_time); free(identifier); free(pid); }
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; }
/* * 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, jobject obj, jobject status, 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) { 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, "---"); } insert_jstrarraylist(&list, usb_dev_info); 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, "---"); } insert_jstrarraylist(&list, usb_dev_info); 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, "---"); } insert_jstrarraylist(&list, usb_dev_info); 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, "---"); } insert_jstrarraylist(&list, usb_dev_info); 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, "---"); } insert_jstrarraylist(&list, usb_dev_info); } udev_device_unref(udev_device); }
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); } /* 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); /* 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, NULL); /* 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; }
/** * 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; }
void operator()(struct udev_device* dev) const { udev_device_unref(dev); }
static int adm_monitor(struct udev *udev, int argc, char *argv[]) { struct sigaction act; sigset_t mask; int option; bool prop = false; bool print_kernel = false; bool print_udev = false; struct udev_list subsystem_match_list; struct udev_list tag_match_list; struct udev_monitor *udev_monitor = NULL; struct udev_monitor *kernel_monitor = NULL; int fd_ep = -1; int fd_kernel = -1, fd_udev = -1; struct epoll_event ep_kernel, ep_udev; int rc = 0; static const struct option options[] = { { "property", no_argument, NULL, 'p' }, { "environment", no_argument, NULL, 'e' }, { "kernel", no_argument, NULL, 'k' }, { "udev", no_argument, NULL, 'u' }, { "subsystem-match", required_argument, NULL, 's' }, { "tag-match", required_argument, NULL, 't' }, { "help", no_argument, NULL, 'h' }, {} }; udev_list_init(udev, &subsystem_match_list, true); udev_list_init(udev, &tag_match_list, true); for (;;) { option = getopt_long(argc, argv, "pekus:t:h", options, NULL); if (option == -1) break; switch (option) { case 'p': case 'e': prop = true; break; case 'k': print_kernel = true; break; case 'u': print_udev = true; break; case 's': { char subsys[UTIL_NAME_SIZE]; char *devtype; strscpy(subsys, sizeof(subsys), optarg); devtype = strchr(subsys, '/'); if (devtype != NULL) { devtype[0] = '\0'; devtype++; } udev_list_entry_add(&subsystem_match_list, subsys, devtype); break; } case 't': udev_list_entry_add(&tag_match_list, optarg, NULL); break; case 'h': printf("Usage: udevadm monitor [--property] [--kernel] [--udev] [--help]\n" " --property print the event properties\n" " --kernel print kernel uevents\n" " --udev print udev events\n" " --subsystem-match=<subsystem[/devtype]> filter events by subsystem\n" " --tag-match=<tag> filter events by tag\n" " --help\n\n"); goto out; default: rc = 1; goto out; } } if (!print_kernel && !print_udev) { print_kernel = true; print_udev = true; } /* set signal handlers */ memset(&act, 0x00, sizeof(struct sigaction)); act.sa_handler = sig_handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTERM); sigprocmask(SIG_UNBLOCK, &mask, NULL); fd_ep = epoll_create1(EPOLL_CLOEXEC); if (fd_ep < 0) { log_error("error creating epoll fd: %m\n"); goto out; } printf("monitor will print the received events for:\n"); if (print_udev) { struct udev_list_entry *entry; udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (udev_monitor == NULL) { fprintf(stderr, "error: unable to create netlink socket\n"); rc = 1; goto out; } udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024); fd_udev = udev_monitor_get_fd(udev_monitor); udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) { const char *subsys = udev_list_entry_get_name(entry); const char *devtype = udev_list_entry_get_value(entry); if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, subsys, devtype) < 0) fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); } udev_list_entry_foreach(entry, udev_list_get_entry(&tag_match_list)) { const char *tag = udev_list_entry_get_name(entry); if (udev_monitor_filter_add_match_tag(udev_monitor, tag) < 0) fprintf(stderr, "error: unable to apply tag filter '%s'\n", tag); } if (udev_monitor_enable_receiving(udev_monitor) < 0) { fprintf(stderr, "error: unable to subscribe to udev events\n"); rc = 2; goto out; } memset(&ep_udev, 0, sizeof(struct epoll_event)); ep_udev.events = EPOLLIN; ep_udev.data.fd = fd_udev; if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) { log_error("fail to add fd to epoll: %m\n"); goto out; } printf("UDEV - the event which udev sends out after rule processing\n"); } if (print_kernel) { struct udev_list_entry *entry; kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel"); if (kernel_monitor == NULL) { fprintf(stderr, "error: unable to create netlink socket\n"); rc = 3; goto out; } udev_monitor_set_receive_buffer_size(kernel_monitor, 128*1024*1024); fd_kernel = udev_monitor_get_fd(kernel_monitor); udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) { const char *subsys = udev_list_entry_get_name(entry); if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor, subsys, NULL) < 0) fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys); } if (udev_monitor_enable_receiving(kernel_monitor) < 0) { fprintf(stderr, "error: unable to subscribe to kernel events\n"); rc = 4; goto out; } memset(&ep_kernel, 0, sizeof(struct epoll_event)); ep_kernel.events = EPOLLIN; ep_kernel.data.fd = fd_kernel; if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_kernel, &ep_kernel) < 0) { log_error("fail to add fd to epoll: %m\n"); goto out; } printf("KERNEL - the kernel uevent\n"); } printf("\n"); while (!udev_exit) { int fdcount; struct epoll_event ev[4]; int i; fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1); if (fdcount < 0) { if (errno != EINTR) fprintf(stderr, "error receiving uevent message: %m\n"); continue; } for (i = 0; i < fdcount; i++) { if (ev[i].data.fd == fd_kernel && ev[i].events & EPOLLIN) { struct udev_device *device; device = udev_monitor_receive_device(kernel_monitor); if (device == NULL) continue; print_device(device, "KERNEL", prop); udev_device_unref(device); } else if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) { struct udev_device *device; device = udev_monitor_receive_device(udev_monitor); if (device == NULL) continue; print_device(device, "UDEV", prop); udev_device_unref(device); } } } out: if (fd_ep >= 0) close(fd_ep); udev_monitor_unref(udev_monitor); udev_monitor_unref(kernel_monitor); udev_list_cleanup(&subsystem_match_list); udev_list_cleanup(&tag_match_list); return rc; }
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); }
int main(int argc, char *argv[]) { struct udev *udev; struct udev_event *event; struct udev_device *dev; struct udev_rules *rules; char syspath[UTIL_PATH_SIZE]; const char *devpath; const char *action; const char *subsystem; struct sigaction act; int err = -EINVAL; udev = udev_new(); if (udev == NULL) exit(1); info(udev, "version %s\n", VERSION); udev_selinux_init(udev); /* set signal handlers */ memset(&act, 0x00, sizeof(act)); act.sa_handler = (void (*)(int)) sig_handler; sigemptyset (&act.sa_mask); act.sa_flags = 0; sigaction(SIGALRM, &act, NULL); sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); /* trigger timeout to prevent hanging processes */ alarm(UDEV_EVENT_TIMEOUT); action = getenv("ACTION"); devpath = getenv("DEVPATH"); subsystem = getenv("SUBSYSTEM"); if (action == NULL || subsystem == NULL || devpath == NULL) { err(udev, "action, subsystem or devpath missing\n"); goto exit; } rules = udev_rules_new(udev, 1); util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath)); util_strlcat(syspath, devpath, sizeof(syspath)); dev = udev_device_new_from_syspath(udev, syspath); if (dev == NULL) { info(udev, "unknown device '%s'\n", devpath); goto fail; } /* skip reading of db, but read kernel parameters */ udev_device_set_info_loaded(dev); udev_device_read_uevent_file(dev); udev_device_set_action(dev, action); event = udev_event_new(dev); err = udev_event_execute_rules(event, rules); /* rules may change/disable the timeout */ if (udev_device_get_event_timeout(dev) >= 0) alarm(udev_device_get_event_timeout(dev)); if (err == 0 && !event->ignore_device && udev_get_run(udev)) udev_event_execute_run(event); udev_event_unref(event); udev_device_unref(dev); fail: udev_rules_unref(rules); exit: udev_selinux_exit(udev); udev_unref(udev); if (err != 0) return 1; 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_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; }
static void udev_monitor_watcher (struct udev_monitor *udev_monitor, NihIoWatch * watch, NihIoEvents events) { struct udev_device * udev_device; nih_local char * subsystem = NULL; nih_local char * action = NULL; nih_local char * kernel = NULL; nih_local char * devpath = NULL; nih_local char * devname = NULL; nih_local char * name = NULL; nih_local char ** env = NULL; const char * value = NULL; size_t env_len = 0; DBusPendingCall * pending_call; char *(*copy_string)(const void *, const char *) = NULL; udev_device = udev_monitor_receive_device (udev_monitor); if (! udev_device) return; copy_string = no_strip_udev_data ? nih_strdup : make_safe_string; value = udev_device_get_subsystem (udev_device); subsystem = value ? copy_string (NULL, value) : NULL; value = udev_device_get_action (udev_device); action = value ? copy_string (NULL, value) : NULL; value = udev_device_get_sysname (udev_device); kernel = value ? copy_string (NULL, value) : NULL; value = udev_device_get_devpath (udev_device); devpath = value ? copy_string (NULL, value) : NULL; value = udev_device_get_devnode (udev_device); devname = value ? copy_string (NULL, value) : NULL; /* Protect against the "impossible" */ if (! action) goto out; if (! strcmp (action, "add")) { name = NIH_MUST (nih_sprintf (NULL, "%s-device-added", subsystem)); } else if (! strcmp (action, "change")) { name = NIH_MUST (nih_sprintf (NULL, "%s-device-changed", subsystem)); } else if (! strcmp (action, "remove")) { name = NIH_MUST (nih_sprintf (NULL, "%s-device-removed", subsystem)); } else { name = NIH_MUST (nih_sprintf (NULL, "%s-device-%s", subsystem, action)); } env = NIH_MUST (nih_str_array_new (NULL)); if (kernel) { nih_local char *var = NULL; var = NIH_MUST (nih_sprintf (NULL, "KERNEL=%s", kernel)); NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var)); } if (devpath) { nih_local char *var = NULL; var = NIH_MUST (nih_sprintf (NULL, "DEVPATH=%s", devpath)); NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var)); } if (devname) { nih_local char *var = NULL; var = NIH_MUST (nih_sprintf (NULL, "DEVNAME=%s", devname)); NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var)); } if (subsystem) { nih_local char *var = NULL; var = NIH_MUST (nih_sprintf (NULL, "SUBSYSTEM=%s", subsystem)); NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var)); } if (action) { nih_local char *var = NULL; var = NIH_MUST (nih_sprintf (NULL, "ACTION=%s", action)); NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var)); } for (struct udev_list_entry *list_entry = udev_device_get_properties_list_entry (udev_device); list_entry != NULL; list_entry = udev_list_entry_get_next (list_entry)) { nih_local char *udev_name = NULL; nih_local char *udev_value = NULL; nih_local char *var = NULL; udev_name = copy_string (NULL, udev_list_entry_get_name (list_entry)); if (! strcmp (udev_name, "DEVPATH")) continue; if (! strcmp (udev_name, "DEVNAME")) continue; if (! strcmp (udev_name, "SUBSYSTEM")) continue; if (! strcmp (udev_name, "ACTION")) continue; udev_value = copy_string (NULL, udev_list_entry_get_value (list_entry)); var = NIH_MUST (nih_sprintf (NULL, "%s=%s", udev_name, udev_value)); NIH_MUST (nih_str_array_addp (&env, NULL, &env_len, var)); } nih_debug ("%s %s", name, devname ? devname : ""); pending_call = upstart_emit_event (upstart, name, env, FALSE, NULL, emit_event_error, NULL, NIH_DBUS_TIMEOUT_NEVER); if (! pending_call) { NihError *err; int saved = errno; err = nih_error_get (); nih_warn ("%s", err->message); if (saved != ENOMEM && subsystem) nih_warn ("Likely that udev '%s' event contains binary garbage", subsystem); nih_free (err); } dbus_pending_call_unref (pending_call); out: udev_device_unref (udev_device); }
/// Checks which key events the keypad offers. If it offers the QWERTY key /// events, sets kbPresent to true, otherwise, to false. void KbSliderPlugin::readKbPresent() { static bool read = false; if (read) return; read = true; struct udev* udev = udev_new(); if (udev == NULL) { return; } QString sysPath = QString("/sys/%1") .arg(findKeypadDevice()); struct udev_device* originalDev = udev_device_new_from_syspath(udev, sysPath.toAscii().constData()); struct udev_device* dev = originalDev; const char* capabilities = 0; QStringList split; unsigned long lowBits[1] = {0}; bool ok = false; if (dev == NULL) { goto out_udev; } // Walk to the parent until we get a device with "capabilities/key". E.g., // this device is /devices/platform/something/input/inputX/eventX but we // need to go to the parent /devices/platform/something/input/inputX while (dev != NULL && udev_device_get_sysattr_value(dev, "capabilities/key") == NULL) { dev = udev_device_get_parent_with_subsystem_devtype(dev, "input", NULL); // We don't need to decrement the ref count, since the returned device // is not referenced, and will be cleaned up when the child device is // cleaned up. } // We can assume that the input device in question has events of type // KEY. The only thing to check is which key events are supported. // Get the key bitmask. The returned string contains hexadecimal numbers // separated by spaces. The actual key bitmask is these numbers in reverse // order. We're only interested in the low bits, so we check only the last // number. capabilities = udev_device_get_sysattr_value(dev, "capabilities/key"); if (capabilities == 0) goto out_device; split = QString(capabilities).split(' ', QString::SkipEmptyParts); if (split.isEmpty()) goto out_device; lowBits[0] = split.last().toULong(&ok, 16); if (!ok) goto out_device; // Check the bits KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T and KEY_Y. kbPresent = test_bit(KEY_Q, lowBits) && test_bit(KEY_W, lowBits) && test_bit(KEY_E, lowBits) && test_bit(KEY_R, lowBits) && test_bit(KEY_T, lowBits) && test_bit(KEY_Y, lowBits); out_device: udev_device_unref(originalDev); out_udev: udev_unref(udev); }
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 HPRescanUsbBus(struct udev *udev) { int i, j; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; /* all reader are marked absent */ for (i=0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) readerTracker[i].status = READER_ABSENT; /* Create a list of the devices in the 'usb' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "usb"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each item enumerated */ udev_list_entry_foreach(dev_list_entry, devices) { const char *devpath; struct udev_device *dev, *parent; struct _driverTracker *driver, *classdriver; int newreader; int bInterfaceNumber; const char *interface; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ devpath = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev, devpath); /* The device pointed to by dev contains information about the interface. 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 = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"); if (!parent) continue; devpath = udev_device_get_devnode(parent); if (!devpath) { /* the device disapeared? */ Log1(PCSC_LOG_ERROR, "udev_device_get_devnode() failed"); continue; } driver = get_driver(parent, devpath, &classdriver); if (NULL == driver) /* no driver known for this device */ continue; #ifdef DEBUG_HOTPLUG Log2(PCSC_LOG_DEBUG, "Found matching USB device: %s", devpath); #endif newreader = TRUE; bInterfaceNumber = 0; interface = udev_device_get_sysattr_value(dev, "bInterfaceNumber"); if (interface) bInterfaceNumber = atoi(interface); /* Check if the reader is a new one */ for (j=0; j<PCSCLITE_MAX_READERS_CONTEXTS; j++) { if (readerTracker[j].devpath && (strcmp(readerTracker[j].devpath, devpath) == 0) && (bInterfaceNumber == readerTracker[j].bInterfaceNumber)) { /* The reader is already known */ readerTracker[j].status = READER_PRESENT; newreader = FALSE; #ifdef DEBUG_HOTPLUG Log2(PCSC_LOG_DEBUG, "Refresh USB device: %s", devpath); #endif break; } } /* New reader found */ if (newreader) HPAddDevice(dev, parent, devpath); /* free device */ udev_device_unref(dev); } /* Free the enumerator object */ udev_enumerate_unref(enumerate); pthread_mutex_lock(&usbNotifierMutex); /* check if all the previously found readers are still present */ for (i=0; i<PCSCLITE_MAX_READERS_CONTEXTS; i++) { if ((READER_ABSENT == readerTracker[i].status) && (readerTracker[i].fullName != NULL)) { Log4(PCSC_LOG_INFO, "Removing USB device[%d]: %s at %s", i, readerTracker[i].fullName, readerTracker[i].devpath); RFRemoveReader(readerTracker[i].fullName, PCSCLITE_HP_BASE_PORT + i); readerTracker[i].status = READER_ABSENT; free(readerTracker[i].devpath); readerTracker[i].devpath = NULL; free(readerTracker[i].fullName); readerTracker[i].fullName = NULL; } } pthread_mutex_unlock(&usbNotifierMutex); }
bool CUDevProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback) { bool changed = false; fd_set readfds; FD_ZERO(&readfds); FD_SET(udev_monitor_get_fd(m_udevMon), &readfds); // non-blocking, check the file descriptor for received data struct timeval tv = {0}; int count = select(udev_monitor_get_fd(m_udevMon) + 1, &readfds, NULL, NULL, &tv); if (count < 0) return false; if (FD_ISSET(udev_monitor_get_fd(m_udevMon), &readfds)) { struct udev_device *dev = udev_monitor_receive_device(m_udevMon); if (!dev) return false; const char *action = udev_device_get_action(dev); if (action) { std::string label; const char *udev_label = udev_device_get_property_value(dev, "ID_FS_LABEL"); const char *mountpoint = get_mountpoint(udev_device_get_devnode(dev)); if (udev_label) label = udev_label; else if (mountpoint) label = URIUtils::GetFileName(mountpoint); const char *fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE"); if (mountpoint && strcmp(action, "add") == 0 && (fs_usage && strcmp(fs_usage, "filesystem") == 0)) { CLog::Log(LOGNOTICE, "UDev: Added %s", mountpoint); if (callback) callback->OnStorageAdded(label, mountpoint); changed = true; } if (strcmp(action, "remove") == 0 && (fs_usage && strcmp(fs_usage, "filesystem") == 0)) { if (callback) callback->OnStorageSafelyRemoved(label); changed = true; } if (strcmp(action, "change") == 0) { if (mountpoint) { CLog::Log(LOGNOTICE, "UDev: Changed / Added %s", mountpoint); if (callback) callback->OnStorageAdded(label, mountpoint); changed = true; } const char *eject_request = udev_device_get_property_value(dev, "DISK_EJECT_REQUEST"); if (eject_request && strcmp(eject_request, "1") == 0) { if (callback) callback->OnStorageSafelyRemoved(label); changed = true; } } } udev_device_unref(dev); } return changed; }
static void HPEstablishUSBNotifications(struct udev *udev) { struct udev_monitor *udev_monitor; int r, i; int fd; fd_set fds; udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); /* filter only the interfaces */ r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_interface"); if (r) { Log2(PCSC_LOG_ERROR, "udev_monitor_filter_add_match_subsystem_devtype() error: %d\n", r); return; } r = udev_monitor_enable_receiving(udev_monitor); if (r) { Log2(PCSC_LOG_ERROR, "udev_monitor_enable_receiving() error: %d\n", r); return; } /* udev monitor file descriptor */ fd = udev_monitor_get_fd(udev_monitor); while (!AraKiriHotPlug) { struct udev_device *dev, *parent; const char *action, *devpath; #ifdef DEBUG_HOTPLUG Log0(PCSC_LOG_INFO); #endif FD_ZERO(&fds); FD_SET(fd, &fds); /* wait for a udev event */ r = select(fd+1, &fds, NULL, NULL, NULL); if (r < 0) { Log2(PCSC_LOG_ERROR, "select(): %s", strerror(errno)); return; } dev = udev_monitor_receive_device(udev_monitor); if (!dev) { Log1(PCSC_LOG_ERROR, "udev_monitor_receive_device() error\n"); return; } action = udev_device_get_action(dev); if (0 == strcmp("remove", action)) { Log1(PCSC_LOG_INFO, "Device removed"); HPRescanUsbBus(udev); continue; } if (strcmp("add", action)) continue; parent = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"); devpath = udev_device_get_devnode(parent); if (!devpath) { /* the device disapeared? */ Log1(PCSC_LOG_ERROR, "udev_device_get_devnode() failed"); continue; } HPAddDevice(dev, parent, devpath); /* free device */ udev_device_unref(dev); } for (i=0; i<driverSize; i++) { /* free strings allocated by strdup() */ free(driverTracker[i].bundleName); free(driverTracker[i].libraryPath); free(driverTracker[i].readerName); } free(driverTracker); Log1(PCSC_LOG_INFO, "Hotplug stopped"); } /* HPEstablishUSBNotifications */
/* * check for new devices * args: * vd - pointer to device data (can be null) * * asserts: * my_device_list.udev is not null * my_device_list.udev_fd is valid (> 0) * my_device_list.udev_mon is not null * * returns: true(1) if device list was updated, false(0) otherwise */ int check_device_list_events(v4l2_dev_t *vd) { /*assertions*/ assert(my_device_list.udev != NULL); assert(my_device_list.udev_fd > 0); assert(my_device_list.udev_mon != NULL); fd_set fds; struct timeval tv; int ret = 0; FD_ZERO(&fds); FD_SET(my_device_list.udev_fd, &fds); tv.tv_sec = 0; tv.tv_usec = 0; ret = select(my_device_list.udev_fd+1, &fds, NULL, NULL, &tv); /* Check if our file descriptor has received data. */ if (ret > 0 && FD_ISSET(my_device_list.udev_fd, &fds)) { /* * Make the call to receive the device. * select() ensured that this will not block. */ struct udev_device *dev = udev_monitor_receive_device(my_device_list.udev_mon); if (dev) { if (verbosity > 0) { printf("V4L2_CORE: Got Device event\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)); } /*update device list*/ if(my_device_list.list_devices != NULL) free_device_list(); enum_v4l2_devices(); /*update the current device index*/ if(vd) { vd->this_device = v4l2core_get_device_index(vd->videodevice); if(vd->this_device < 0) vd->this_device = 0; if(my_device_list.list_devices) my_device_list.list_devices[vd->this_device].current = 1; } udev_device_unref(dev); return(1); } else fprintf(stderr, "V4L2_CORE: No Device from receive_device(). An error occured.\n"); } return(0); }
bool udev_initial_probe(udev_probe_device_f_t probe_device) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; /* Create the udev object */ udev = udev_new(); if (!udev) { ERROR("can't create udev"); return false; } /* Create a list of the devices in the 'hidraw' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "input"); 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. */ DEBUG("Device Node Path: %s", udev_device_get_devnode(dev)); /* 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. */ DEBUG(" VID/PID: %s %s", udev_device_get_sysattr_value(dev,"idVendor"), udev_device_get_sysattr_value(dev, "idProduct")); DEBUG(" %s\n %s", udev_device_get_sysattr_value(dev,"manufacturer"), udev_device_get_sysattr_value(dev,"product")); DEBUG(" serial: %s", udev_device_get_sysattr_value(dev, "serial")); probe_device(dev); udev_device_unref(dev); } /* Free the enumerator object */ udev_enumerate_unref(enumerate); udev_unref(udev); return true; }
/* * 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); }
void get_seecam(char cpath[]) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); exit(1); } /* 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. */ const char * node = udev_device_get_devnode(dev); #if DEBUG printf("Device Node Path: %s\n", node); #endif /* 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 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(strcmp(udev_device_get_sysattr_value(dev, "idVendor"), CAMERA_VID) == 0 && strcmp(udev_device_get_sysattr_value(dev, "idProduct"), CAMERA_PID) == 0) { strcpy(cpath,node); } #if DEBUG 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")); #endif udev_device_unref(dev); } /* Free the enumerator object */ udev_enumerate_unref(enumerate); udev_unref(udev); return; }
/** * 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; }
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; 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; struct udev_device *hid_dev; // The device's HID udev node. struct udev_device *dev; // The actual hardware device. struct udev_device *intf_dev; // The device's interface (in the USB sense). 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); hid_dev = udev_device_new_from_syspath(udev, sysfs_path); dev_path = udev_device_get_devnode(hid_dev); /* The device pointed to by hid_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( hid_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 */ cur_dev->interface_number = -1; /* Get a handle to the interface's udev node. */ intf_dev = udev_device_get_parent_with_subsystem_devtype( hid_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; } } else goto next; next: udev_device_unref(hid_dev); /* 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; }
libusbp_error * libusbp_serial_port_create( const libusbp_device * device, uint8_t interface_number, bool composite, libusbp_serial_port ** port) { LIBUSBP_UNUSED(composite); if (port == NULL) { return error_create("Serial port output pointer is null."); } *port = NULL; if (device == NULL) { return error_create("Device is null."); } libusbp_error * error = NULL; libusbp_serial_port * new_port = NULL; if (error == NULL) { new_port = calloc(1, sizeof(libusbp_serial_port)); if (new_port == NULL) { error = &error_no_memory; } } // Get the syspath of the physical device. char * new_device_syspath = NULL; if (error == NULL) { error = libusbp_device_get_os_id(device, &new_device_syspath); } // Get a udev context. struct udev * new_udev = NULL; if (error == NULL) { error = udevw_create_context(&new_udev); } // Get the USB interface device. struct udev_device * new_interface_dev = NULL; if (error == NULL) { error = udevw_get_interface(new_udev, new_device_syspath, interface_number, &new_interface_dev); } // Get the tty device. struct udev_device * new_tty_dev = NULL; if (error == NULL) { error = udevw_get_tty(new_udev, new_interface_dev, &new_tty_dev); } // Get the syspath of the tty device. if (error == NULL) { error = udevw_get_syspath_copy(new_tty_dev, &new_port->syspath); } // Get the port name (e.g. /dev/ttyACM0) const char * port_name = NULL; if (error == NULL) { port_name = udev_device_get_property_value(new_tty_dev, "DEVNAME"); if (port_name == NULL) { error = error_create("The DEVNAME property does not exist."); } } // Copy the port name to the new serial port object. if (error == NULL) { error = string_copy(port_name, &new_port->port_name); } // Pass the new object to the caller. if (error == NULL) { *port = new_port; new_port = NULL; } if (new_tty_dev != NULL) { udev_device_unref(new_tty_dev); } if (new_interface_dev != NULL) { udev_device_unref(new_interface_dev); } if (new_udev != NULL) { udev_unref(new_udev); } libusbp_string_free(new_device_syspath); libusbp_serial_port_free(new_port); return error; }
int main (int argc, char ** argv) { struct udev * udev; struct udev_device * dev; char * device = NULL; struct udev_monitor * mon = NULL; fd_set readfds; int fdcount, devnum, errcount = 0; unsigned short int i, major, minor; short int * maxminor; char * notification = NULL; char * icon = NULL; NotifyNotification * netlink; NotifyNotification *** netlinkref; blkid_cache cache = NULL; char *read = NULL; blkid_tag_iterate iter; const char *type, *value, *devname; blkid_dev blkdev; GError * error = NULL; printf("%s: %s v%s (compiled: %s)\n", argv[0], PROGNAME, VERSION, DATE); if(!notify_init("Udev-Block-Notification")) { fprintf(stderr, "%s: Can't create notify.\n", argv[0]); exit(EXIT_FAILURE); } udev = udev_new(); if(!udev) { fprintf(stderr, "%s: Can't create udev.\n", argv[0]); exit(EXIT_FAILURE); } mon = udev_monitor_new_from_netlink(udev, "udev"); udev_monitor_filter_add_match_subsystem_devtype(mon, "block", NULL); udev_monitor_enable_receiving(mon); netlinkref = malloc(256 * sizeof(size_t)); for(i = 0; i < 256; i++) netlinkref[i] = NULL; maxminor = malloc(256 * sizeof(short int)); for(i = 0; i < 256; i++) maxminor[i] = -1; while (1) { FD_ZERO(&readfds); if (mon != NULL) FD_SET(udev_monitor_get_fd(mon), &readfds); fdcount = select(udev_monitor_get_fd(mon) + 1, &readfds, NULL, NULL, NULL); if ((mon != NULL) && FD_ISSET(udev_monitor_get_fd(mon), &readfds)) { dev = udev_monitor_receive_device(mon); if(dev) { device = (char *) udev_device_get_sysname(dev); devnum = udev_device_get_devnum(dev); major = devnum / 256; minor = devnum - (major * 256); switch(udev_device_get_action(dev)[0]) { case 'a': // a: add notification = (char *) malloc(strlen(TEXT_ADD) + strlen(device)); sprintf(notification, TEXT_ADD, device, major, minor); icon = ICON_ADD; break; case 'r': // r: remove notification = (char *) malloc(strlen(TEXT_REMOVE) + strlen(device)); sprintf(notification, TEXT_REMOVE, device, major, minor); icon = ICON_REMOVE; break; case 'm': // m: move notification = (char *) malloc(strlen(TEXT_MOVE) + strlen(device)); sprintf(notification, TEXT_MOVE, device, major, minor); icon = ICON_MOVE; break; case 'c': // c: change notification = (char *) malloc(strlen(TEXT_CHANGE) + strlen(device)); sprintf(notification, TEXT_CHANGE, device, major, minor); icon = ICON_CHANGE; break; default: // we should never get here I think... notification = (char *) malloc(strlen(TEXT_DEFAULT) + strlen(device)); sprintf(notification, TEXT_CHANGE, device, major, minor); icon = ICON_DEFAULT; } blkid_get_cache(&cache, read); blkdev = blkid_get_dev(cache, udev_device_get_devnode(dev), BLKID_DEV_NORMAL); if (blkdev) { iter = blkid_tag_iterate_begin(blkdev); while (blkid_tag_next(iter, &type, &value) == 0) { notification = (char *) realloc(notification, strlen(TEXT_TAG) + strlen(notification) + strlen(type) + strlen(value)); sprintf(notification, TEXT_TAG, notification, type, value); } blkid_tag_iterate_end(iter); blkid_put_cache(cache); } printf("%s: %s\n", argv[0], notification); if (maxminor[major] < minor) { netlinkref[major] = realloc(netlinkref[major], (minor + 1) * sizeof(size_t)); while(maxminor[major] < minor) netlinkref[major][++maxminor[major]] = NULL; } if (netlinkref[major][minor] == NULL) { netlink = notify_notification_new("Udev-Block", notification, icon); netlinkref[major][minor] = netlink; } else { netlink = netlinkref[major][minor]; notify_notification_update(netlink, "Udev-Block", notification, icon); } notify_notification_set_timeout(netlink, NOTIFICATION_TIMEOUT); notify_notification_set_category(netlink, "Udev-Block"); notify_notification_set_urgency (netlink, NOTIFY_URGENCY_NORMAL); while(!notify_notification_show(netlink, &error)) { if (errcount > 1) { fprintf(stderr, "%s: Looks like we can not reconnect to notification daemon... Exiting.\n", argv[0]); exit(EXIT_FAILURE); } else { g_printerr("%s: Error \"%s\" while trying to show notification. Trying to reconnect.\n", argv[0], error->message); errcount++; g_error_free(error); error = NULL; notify_uninit(); usleep(500 * 1000); if(!notify_init("Udev-Block-Notification")) { fprintf(stderr, "%s: Can't create notify.\n", argv[0]); exit(EXIT_FAILURE); } } } errcount = 0; free(notification); udev_device_unref(dev); } // This is not really needed... But we want to make shure not to eat 100% CPU if anything breaks. ;) usleep(500 * 1000); } } udev_unref(udev); return EXIT_SUCCESS; }
QList<QextPortInfo> QextSerialEnumeratorPrivate::getPorts_sys() { QList<QextPortInfo> infoList; #ifndef QESP_NO_UDEV struct udev *ud = udev_new(); if (!ud) { qCritical() << "Unable to enumerate ports because udev is not initialized."; return infoList; } struct udev_enumerate *enumerate = udev_enumerate_new(ud); udev_enumerate_add_match_subsystem(enumerate, "tty"); udev_enumerate_scan_devices(enumerate); struct udev_list_entry *list = udev_enumerate_get_list_entry(enumerate); struct udev_list_entry *entry; udev_list_entry_foreach(entry, list) { const char *path; struct udev_device *dev; // Have to grab the actual udev device here... path = udev_list_entry_get_name(entry); dev = udev_device_new_from_syspath(ud, path); infoList.append(portInfoFromDevice(dev)); // Done with this device udev_device_unref(dev); } // Done with the list and this udev udev_enumerate_unref(enumerate); udev_unref(ud); #else QStringList portNamePrefixes, portNameList; portNamePrefixes << QLatin1String("ttyS*"); // list normal serial ports first QDir dir(QLatin1String("/dev")); portNameList = dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); // remove the values which are not serial ports for e.g. /dev/ttysa for (int i = 0; i < portNameList.size(); i++) { bool ok; QString current = portNameList.at(i); // remove the ttyS part, and check, if the other part is a number current.remove(0,4).toInt(&ok, 10); if (!ok) { portNameList.removeAt(i); i--; } } // get the non standard serial ports names // (USB-serial, bluetooth-serial, 18F PICs, and so on) // if you know an other name prefix for serial ports please let us know portNamePrefixes.clear(); portNamePrefixes << QLatin1String("ttyACM*") << QLatin1String("ttyUSB*") << QLatin1String("rfcomm*"); portNameList += dir.entryList(portNamePrefixes, (QDir::System | QDir::Files), QDir::Name); foreach (QString str , portNameList) { QextPortInfo inf; inf.physName = QLatin1String("/dev/")+str; inf.portName = str; if (str.contains(QLatin1String("ttyS"))) { inf.friendName = QLatin1String("Serial port ")+str.remove(0, 4); } else if (str.contains(QLatin1String("ttyUSB"))) { inf.friendName = QLatin1String("USB-serial adapter ")+str.remove(0, 6); } else if (str.contains(QLatin1String("rfcomm"))) { inf.friendName = QLatin1String("Bluetooth-serial adapter ")+str.remove(0, 6); } inf.enumName = QLatin1String("/dev"); // is there a more helpful name for this? infoList.append(inf); }
static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen) { struct udev *udev; struct udev_device *udev_dev, *parent, *hid_dev; struct stat s; int ret = -1; char *serial_number_utf8 = NULL; char *product_name_utf8 = NULL; /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); return -1; } /* Get the dev_t (major/minor numbers) from the file handle. */ fstat(dev->device_handle, &s); /* Open a udev device from the dev_t. 'c' means character device. */ udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); if (udev_dev) { hid_dev = udev_device_get_parent_with_subsystem_devtype( udev_dev, "hid", NULL); if (hid_dev) { unsigned short dev_vid; unsigned short dev_pid; int bus_type; size_t retm; ret = parse_uevent_info( udev_device_get_sysattr_value(hid_dev, "uevent"), &bus_type, &dev_vid, &dev_pid, &serial_number_utf8, &product_name_utf8); if (bus_type == BUS_BLUETOOTH) { switch (key) { case DEVICE_STRING_MANUFACTURER: wcsncpy(string, L"", maxlen); ret = 0; break; case DEVICE_STRING_PRODUCT: retm = mbstowcs(string, product_name_utf8, maxlen); ret = (retm == (size_t)-1)? -1: 0; break; case DEVICE_STRING_SERIAL: retm = mbstowcs(string, serial_number_utf8, maxlen); ret = (retm == (size_t)-1)? -1: 0; break; case DEVICE_STRING_COUNT: default: ret = -1; break; } } else { /* This is a USB device. Find its parent USB Device node. */ parent = udev_device_get_parent_with_subsystem_devtype( udev_dev, "usb", "usb_device"); if (parent) { const char *str; const char *key_str = NULL; if (key >= 0 && key < DEVICE_STRING_COUNT) { key_str = device_string_names[key]; } else { ret = -1; goto end; } str = udev_device_get_sysattr_value(parent, key_str); if (str) { /* Convert the string from UTF-8 to wchar_t */ retm = mbstowcs(string, str, maxlen); ret = (retm == (size_t)-1)? -1: 0; goto end; } } } } } end: free(serial_number_utf8); free(product_name_utf8); udev_device_unref(udev_dev); /* parent and hid_dev don't need to be (and can't be) unref'd. I'm not sure why, but they'll throw double-free() errors. */ udev_unref(udev); return ret; }
/* move any old watches directory out of the way, and then restore * the watches */ void udev_watch_restore(struct udev *udev) { char filename[UTIL_PATH_SIZE], oldname[UTIL_PATH_SIZE]; if (inotify_fd < 0) return; util_strlcpy(oldname, udev_get_dev_path(udev), sizeof(oldname)); util_strlcat(oldname, "/.udev/watch.old", sizeof(oldname)); util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); util_strlcat(filename, "/.udev/watch", sizeof(filename)); if (rename(filename, oldname) == 0) { DIR *dir; struct dirent *ent; dir = opendir(oldname); if (dir == NULL) { err(udev, "unable to open old watches dir '%s', old watches will not be restored: %m", oldname); return; } while ((ent = readdir(dir)) != NULL) { char path[UTIL_PATH_SIZE]; char buf[UTIL_PATH_SIZE]; ssize_t syslen; ssize_t len; struct udev_device *dev; if (ent->d_name[0] < '0' || ent->d_name[0] > '9') continue; util_strlcpy(path, oldname, sizeof(path)); util_strlcat(path, "/", sizeof(path)); util_strlcat(path, ent->d_name, sizeof(path)); syslen = util_strlcpy(buf, udev_get_sys_path(udev), sizeof(buf)); len = readlink(path, &buf[syslen], sizeof(buf)-syslen); if (len <= 0 || len >= (ssize_t)(sizeof(buf)-syslen)) { unlink(path); continue; } buf[syslen + len] = '\0'; dbg(udev, "old watch to '%s' found\n", buf); dev = udev_device_new_from_syspath(udev, buf); if (dev == NULL) { unlink(path); continue; } info(udev, "restoring old watch on '%s'\n", udev_device_get_devnode(dev)); udev_watch_begin(udev, dev); udev_device_unref(dev); unlink(path); } closedir(dir); rmdir(oldname); } else if (errno != ENOENT) { err(udev, "unable to move watches dir '%s', old watches will not be restored: %m", filename); } }
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { struct udev *udev = udev_device_get_udev(names->pcidev); unsigned domain, bus, slot, func, dev_port = 0; size_t l; char *s; const char *attr; struct udev_device *pci = NULL; char slots[256], str[256]; _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; int hotplug_slot = 0, err = 0; if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4) return -ENOENT; /* kernel provided port index for multiple ports on a single PCI function */ attr = udev_device_get_sysattr_value(dev, "dev_port"); if (attr) dev_port = strtol(attr, NULL, 10); /* compose a name based on the raw kernel's PCI bus, slot numbers */ s = names->pci_path; l = sizeof(names->pci_path); if (domain > 0) l = strpcpyf(&s, l, "P%u", domain); l = strpcpyf(&s, l, "p%us%u", bus, slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%u", func); if (dev_port > 0) l = strpcpyf(&s, l, "d%u", dev_port); if (l == 0) names->pci_path[0] = '\0'; /* ACPI _SUN -- slot user number */ pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); if (!pci) { err = -ENOENT; goto out; } snprintf(slots, sizeof(slots), "%s/slots", udev_device_get_syspath(pci)); dir = opendir(slots); if (!dir) { err = -errno; goto out; } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { int i; char *rest; char *address; if (dent->d_name[0] == '.') continue; i = strtol(dent->d_name, &rest, 10); if (rest[0] != '\0') continue; if (i < 1) continue; snprintf(str, sizeof(str), "%s/%s/address", slots, dent->d_name); if (read_one_line_file(str, &address) >= 0) { /* match slot address with device by stripping the function */ if (strneq(address, udev_device_get_sysname(names->pcidev), strlen(address))) hotplug_slot = i; free(address); } if (hotplug_slot > 0) break; } if (hotplug_slot > 0) { s = names->pci_slot; l = sizeof(names->pci_slot); if (domain > 0) l = strpcpyf(&s, l, "P%d", domain); l = strpcpyf(&s, l, "s%d", hotplug_slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%d", func); if (dev_port > 0) l = strpcpyf(&s, l, "d%d", dev_port); if (l == 0) names->pci_slot[0] = '\0'; } out: udev_device_unref(pci); return err; }
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; }