static void wait_for_usb(void) { struct timeval to, now; usb_dev_handle *dev; gettimeofday(&to, NULL); to.tv_sec += timeout; while (1) { usb_rescan(); dev = open_usb(0, 0); if (dev) { if (!need_removal) return; usb_close(dev); } else { need_removal = 0; } if (timeout) { gettimeofday(&now, NULL); if (now.tv_sec > to.tv_sec) break; if (now.tv_sec == to.tv_sec && now.tv_usec > to.tv_usec) break; } if (usleep(interval_us) < 0) { perror("usleep"); exit(1); } } fprintf(stderr, "timeout\n"); exit(1); }
static void handle_sigusr1(void) { #ifdef BRICKD_WITH_USB_REOPEN_ON_SIGUSR1 usb_reopen(); #else usb_rescan(); #endif }
static void forward_notifications(void *opaque) { uint8_t byte; (void)opaque; if (pipe_read(&_notification_pipe, &byte, sizeof(byte)) < 0) { log_error("Could not read from notification pipe: %s (%d)", get_errno_name(errno), errno); return; } usb_rescan(); }
static void udev_handle_event(void *opaque) { struct udev_device* device; const char *action; const char *dev_node; const char *sys_name; (void)opaque; device = udev_monitor_receive_device(_udev_monitor); if (device == NULL) { log_error("Could not read data from udev monitor socket"); return; } action = udev_device_get_action(device); if (action == NULL) { goto cleanup; } dev_node = udev_device_get_devnode(device); if (dev_node == NULL) { goto cleanup; } sys_name = udev_device_get_sysname(device); if (sys_name == NULL) { goto cleanup; } if (strncmp(action, "add", 3) == 0 || strncmp(action, "remove", 6) == 0) { log_debug("Received udev event (action: %s, dev node: %s, sys name: %s)", action, dev_node, sys_name); usb_rescan(); } else { log_debug("Ignoring udev event (action: %s, dev node: %s, sys name: %s)", action, dev_node, sys_name); } cleanup: udev_device_unref(device); }
int usb_reopen(void) { int i; USBStack *usb_stack; log_debug("Reopening all USB devices"); // iterate backwards for simpler index handling and to avoid memmove in // array_remove call for (i = _usb_stacks.count - 1; i >= 0; --i) { usb_stack = array_get(&_usb_stacks, i); log_info("Temporarily removing USB device (bus: %u, device: %u) at index %d: %s", usb_stack->bus_number, usb_stack->device_address, i, usb_stack->base.name); stack_announce_disconnect(&usb_stack->base); array_remove(&_usb_stacks, i, (ItemDestroyFunction)usb_stack_destroy); } return usb_rescan(); }
int usb_init(void) { int phase = 0; log_debug("Initializing USB subsystem"); _libusb_log_source.file = "libusb"; _libusb_log_source.name = "libusb"; #if defined(_WIN32) || defined(__APPLE__) libusb_set_log_function(usb_forward_message); #endif switch (log_get_effective_level()) { case LOG_LEVEL_ERROR: putenv("LIBUSB_DEBUG=1"); break; case LOG_LEVEL_WARN: putenv("LIBUSB_DEBUG=2"); break; case LOG_LEVEL_INFO: putenv("LIBUSB_DEBUG=3"); break; case LOG_LEVEL_DEBUG: if (log_is_included(LOG_LEVEL_DEBUG, &_libusb_log_source, LOG_DEBUG_GROUP_LIBUSB)) { putenv("LIBUSB_DEBUG=4"); } else { putenv("LIBUSB_DEBUG=3"); } break; default: break; } if (usb_init_platform() < 0) { goto cleanup; } phase = 1; // initialize main libusb context if (usb_create_context(&_context)) { goto cleanup; } phase = 2; if (!libusb_pollfds_handle_timeouts(_context)) { log_debug("libusb requires special timeout handling"); // FIXME } else { log_debug("libusb can handle timeouts on its own"); } // create USB stack array. the USBStack struct is not relocatable, because // its USB transfers keep a pointer to it if (array_create(&_usb_stacks, 32, sizeof(USBStack), false) < 0) { log_error("Could not create USB stack array: %s (%d)", get_errno_name(errno), errno); goto cleanup; } phase = 3; if (usb_has_hotplug()) { log_debug("libusb supports hotplug"); if (usb_init_hotplug(_context) < 0) { goto cleanup; } _initialized_hotplug = true; } else { log_debug("libusb does not support hotplug"); } if (usb_rescan() < 0) { goto cleanup; } phase = 4; cleanup: switch (phase) { // no breaks, all cases fall through intentionally case 3: array_destroy(&_usb_stacks, (ItemDestroyFunction)usb_stack_destroy); case 2: usb_destroy_context(_context); case 1: usb_exit_platform(); default: break; } return phase == 4 ? 0 : -1; }