static void udev_hotplug_event(struct udev_device* udev_dev) { const char* udev_action; const char* sys_name = NULL; uint8_t busnum = 0, devaddr = 0; int detached; int r; do { udev_action = udev_device_get_action(udev_dev); if (!udev_action) { break; } detached = !strncmp(udev_action, "remove", 6); r = udev_device_info(NULL, detached, udev_dev, &busnum, &devaddr, &sys_name); if (LIBUSB_SUCCESS != r) { break; } usbi_dbg("udev hotplug event. action: %s.", udev_action); if (strncmp(udev_action, "add", 3) == 0) { linux_hotplug_enumerate(busnum, devaddr, sys_name); } else if (detached) { linux_hotplug_disconnected(busnum, devaddr, sys_name); } else { usbi_err(NULL, "ignoring udev action %s", udev_action); } } while (0); udev_device_unref(udev_dev); }
static int linux_netlink_read_message(void) { unsigned char buffer[1024]; struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer)}; struct msghdr meh = { .msg_iov=&iov, .msg_iovlen=1, .msg_name=&snl, .msg_namelen=sizeof(snl) }; const char *sys_name = NULL; uint8_t busnum, devaddr; int detached, r; size_t len; /* read netlink message */ memset(buffer, 0, sizeof(buffer)); len = recvmsg(linux_netlink_socket, &meh, 0); if (len < 32) { if (errno != EAGAIN) usbi_dbg("error recieving message from netlink"); return -1; } /* TODO -- authenticate this message is from the kernel or udevd */ r = linux_netlink_parse(buffer, len, &detached, &sys_name, &busnum, &devaddr); if (r) return r; usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s", busnum, devaddr, sys_name, detached ? "yes" : "no"); /* signal device is available (or not) to all contexts */ if (detached) linux_hotplug_disconnected(busnum, devaddr, sys_name); else linux_hotplug_enumerate(busnum, devaddr, sys_name); return 0; } static void *linux_netlink_event_thread_main(void *arg) { char dummy; int r; struct pollfd fds[] = { { .fd = netlink_control_pipe[0], .events = POLLIN }, { .fd = linux_netlink_socket, .events = POLLIN }, };
static int linux_netlink_read_message(void) { unsigned char buffer[1024]; struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer)}; struct msghdr meh = { .msg_iov=&iov, .msg_iovlen=1, .msg_name=&snl, .msg_namelen=sizeof(snl) }; const char *sys_name = NULL; uint8_t busnum, devaddr; int detached, r; size_t len; /* read netlink message */ memset(buffer, 0, sizeof(buffer)); len = recvmsg(linux_netlink_socket, &meh, 0); if (len < 32) { if (errno != EAGAIN) usbi_dbg("error recieving message from netlink"); return -1; } /* TODO -- authenticate this message is from the kernel or udevd */ r = linux_netlink_parse(buffer, len, &detached, &sys_name, &busnum, &devaddr); if (r) return r; usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s", busnum, devaddr, sys_name, detached ? "yes" : "no"); /* signal device is available (or not) to all contexts */ if (detached) linux_hotplug_disconnected(busnum, devaddr, sys_name); else linux_hotplug_enumerate(busnum, devaddr, sys_name); return 0; } static void *linux_netlink_event_thread_main(void *arg) { struct pollfd fds = {.fd = linux_netlink_socket, .events = POLLIN}; /* silence compiler warning */ (void) arg; while (1 == poll(&fds, 1, -1)) { if (POLLIN != fds.revents) { break; } usbi_mutex_static_lock(&linux_hotplug_lock); linux_netlink_read_message(); usbi_mutex_static_unlock(&linux_hotplug_lock); } return NULL; } void linux_netlink_hotplug_poll(void) { int r; usbi_mutex_static_lock(&linux_hotplug_lock); do { r = linux_netlink_read_message(); } while (r == 0); usbi_mutex_static_unlock(&linux_hotplug_lock); }