static void usb_monitor_check_timeouts(struct usb_monitor_ctx *ctx) { struct usb_port *timeout_itr = NULL, *old_timeout = NULL; struct timeval tv; uint64_t cur_time; gettimeofday(&tv, NULL); cur_time = (tv.tv_sec * 1e6) + tv.tv_usec; timeout_itr = ctx->timeout_list.lh_first; while (timeout_itr != NULL) { if (cur_time >= timeout_itr->timeout_expire) { //Detatch from list, then run timeout old_timeout = timeout_itr; timeout_itr = timeout_itr->timeout_next.le_next; usb_monitor_lists_del_timeout(old_timeout); //Due to async requests, this guard is needed to prevent us //accidentaly sending PING on disabled port for example if (old_timeout->enabled) old_timeout->timeout(old_timeout); } else { timeout_itr = timeout_itr->timeout_next.le_next; } } }
static void gpio_update_port(struct usb_port *port) { struct gpio_port *gport = (struct gpio_port*) port; uint8_t gpio_val = 0; //We will just write to /sys/class/gpio/gpioX/value, so no need for the full //4096 (upper limit according to getconf) char file_path[64]; int32_t bytes_written = 0, fd = 0; gport->msg_mode = RESET; //Guard agains async reset requests. This guard is also needed for the //scenario where we are waiting to ping and device is reset. Then we will //still be in timeout list, but also reset. Since we then re-add port to //timeout (there is no USB timer), we create infinite loop and that is that if (gport->timeout_next.le_next != NULL || gport->timeout_next.le_prev != NULL) usb_monitor_lists_del_timeout((struct usb_port*) gport); //POWER_OFF is 0, so then we should switch on port if (!gport->pwr_state) gpio_val = 1; //Do a write, if write is successful then we update power state snprintf(file_path, sizeof(file_path), "/sys/class/gpio/gpio%u/value", gport->port_num); fd = open(file_path, O_WRONLY | FD_CLOEXEC); if (fd == -1) { USB_DEBUG_PRINT(port->ctx->logfile, "Failed to open gpio file\n"); usb_helpers_start_timeout((struct usb_port*) gport, DEFAULT_TIMEOUT_SEC); return; } if (gpio_val) bytes_written = write(fd, "1", 1); else bytes_written = write(fd, "0", 1); close(fd); if (bytes_written > 0) { gport->pwr_state = !gport->pwr_state; if (gport->pwr_state) { gport->msg_mode = IDLE; return; } } //There is no error case. If we fail, then we simply sleep and try again. No //device to free or anything //Sleep no matter if write is successful or not usb_helpers_start_timeout((struct usb_port*) gport, GPIO_TIMEOUT_SLEEP_SEC); //TODO: How to check if we are done? If we get here, and inverse of //power_state is off, then we have switched? Or? //USB_DEBUG_PRINT(stderr, "GPIO update\n"); }