diff --git a/firmware/export/config.h b/firmware/export/config.h index 85c83015bd..9af8b1f70d 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -787,7 +787,7 @@ Lyre prototype 1 */ /* Priority in bootloader is wanted */ #define HAVE_PRIORITY_SCHEDULING #define USB_STATUS_BY_EVENT -#define USB_DETECT_BY_CORE +#define USB_DETECT_BY_REQUEST #if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC #define INCLUDE_TIMEOUT_API #define USB_DRIVER_CLOSE @@ -815,17 +815,17 @@ Lyre prototype 1 */ #ifdef HAVE_USBSTACK #if CONFIG_USBOTG == USBOTG_ARC #define USB_STATUS_BY_EVENT -#define USB_DETECT_BY_CORE +#define USB_DETECT_BY_REQUEST #define INCLUDE_TIMEOUT_API #elif CONFIG_USBOTG == USBOTG_AS3525 #define USB_STATUS_BY_EVENT -#define USB_DETECT_BY_CORE +#define USB_DETECT_BY_REQUEST #elif CONFIG_USBOTG == USBOTG_S3C6400X /* FIXME */ && CONFIG_CPU == AS3525v2 #define USB_STATUS_BY_EVENT -#define USB_DETECT_BY_CORE +#define USB_DETECT_BY_REQUEST #elif CONFIG_USBOTG == USBOTG_RK27XX #define USB_STATUS_BY_EVENT -#define USB_DETECT_BY_CORE +#define USB_DETECT_BY_REQUEST #endif /* CONFIG_USB == */ #endif /* HAVE_USBSTACK */ diff --git a/firmware/export/usb.h b/firmware/export/usb.h index 4af5617b3e..8954e9cc59 100644 --- a/firmware/export/usb.h +++ b/firmware/export/usb.h @@ -39,9 +39,6 @@ enum USB_EXTRACTED = 0, /* Event+State */ USB_INSERTED, /* Event+State */ USB_POWERED, /* State - transitional indicator if no power */ -#ifdef USB_DETECT_BY_CORE - USB_HOSTED, /* Event - host presence was detected */ -#endif #if (CONFIG_STORAGE & STORAGE_MMC) USB_REENABLE, /* Event */ #endif diff --git a/firmware/export/usb_drv.h b/firmware/export/usb_drv.h index c0b4d561f2..969a7b358a 100644 --- a/firmware/export/usb_drv.h +++ b/firmware/export/usb_drv.h @@ -24,7 +24,6 @@ #include "kernel.h" void usb_drv_startup(void); -void usb_drv_usb_detect_event(void); /* Target implemented */ void usb_drv_int_enable(bool enable); /* Target implemented */ void usb_drv_init(void); void usb_drv_exit(void); diff --git a/firmware/target/arm/as3525/usb-as3525.c b/firmware/target/arm/as3525/usb-as3525.c index 508906965e..99ae66dc15 100644 --- a/firmware/target/arm/as3525/usb-as3525.c +++ b/firmware/target/arm/as3525/usb-as3525.c @@ -58,22 +58,6 @@ void usb_remove_int(void) #endif } -void usb_drv_usb_detect_event(void) -{ -#if (CONFIG_CPU != AS3525v2 || defined(USE_ROCKBOX_USB)) \ - && defined (USB_STATUS_BY_EVENT) -/* Rebooting on USB plug can crash these players in a state where - * hardware power off (pressing the power button) doesn't work anymore - * TODO: Implement USB in rockbox for these players */ - int oldstatus = disable_irq_save(); /* May come via USB thread */ - - if (usb_status == USB_INSERTED) - usb_status_event(USB_HOSTED); - - restore_irq(oldstatus); -#endif -} - int usb_detect(void) { return usb_status; diff --git a/firmware/target/arm/imx233/usb-imx233.c b/firmware/target/arm/imx233/usb-imx233.c index e2bab4fef4..a89a2611ba 100644 --- a/firmware/target/arm/imx233/usb-imx233.c +++ b/firmware/target/arm/imx233/usb-imx233.c @@ -40,11 +40,6 @@ void usb_remove_int(void) usb_status_event(USB_EXTRACTED); } -void usb_drv_usb_detect_event() -{ - usb_status_event(USB_HOSTED); -} - void usb_attach(void) { usb_drv_attach(); diff --git a/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c index 1584ffb574..c838f65c8a 100644 --- a/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c @@ -145,13 +145,6 @@ void usb_drv_int_enable(bool enable) } } -/* Called during the setup packet request by the host */ -void usb_drv_usb_detect_event(void) -{ - if (usb_drv_powered()) - usb_status_event(USB_HOSTED); -} - /* Called when reading the MBR */ void usb_fix_mbr(unsigned char *mbr) { diff --git a/firmware/target/arm/pp/usb-fw-pp502x.c b/firmware/target/arm/pp/usb-fw-pp502x.c index 5272102fad..010cdb718c 100644 --- a/firmware/target/arm/pp/usb-fw-pp502x.c +++ b/firmware/target/arm/pp/usb-fw-pp502x.c @@ -224,15 +224,6 @@ void usb_insert_int(void) USB_GPIO_INT_CLR = USB_GPIO_MASK; timeout_register(&usb_oneshot, usb_timeout_event, HZ/5, val); } - -/* USB_DETECT_BY_CORE: Called when device descriptor is requested */ -void usb_drv_usb_detect_event(void) -{ - /* Filter for invalid bus reset when unplugging by checking the pin state. */ - if(usb_plugged()) { - usb_status_event(USB_HOSTED); - } -} #endif /* USB_STATUS_BY_EVENT */ #ifdef HAVE_BOOTLOADER_USB_MODE diff --git a/firmware/target/arm/rk27xx/usb-rk27xx.c b/firmware/target/arm/rk27xx/usb-rk27xx.c index 2bae9745c0..20bf867c8d 100644 --- a/firmware/target/arm/rk27xx/usb-rk27xx.c +++ b/firmware/target/arm/rk27xx/usb-rk27xx.c @@ -30,11 +30,6 @@ int usb_status = USB_EXTRACTED; -void usb_drv_usb_detect_event() -{ - usb_status_event(USB_INSERTED); -} - void usb_init_device(void) { } diff --git a/firmware/usb.c b/firmware/usb.c index 6251677e45..436b840a13 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -63,7 +63,9 @@ bool do_screendump_instead_of_usb = false; /* We assume that the USB cable is extracted */ static int usb_state = USB_EXTRACTED; - +static bool usb_host_present = false; +static int usb_num_acks_to_expect = 0; +static long usb_last_broadcast_tick = 0; #if (CONFIG_STORAGE & STORAGE_MMC) && defined(USB_FULL_INIT) && !defined(HAVE_USBSTACK) static int usb_mmc_countdown = 0; #endif @@ -109,21 +111,20 @@ static void try_reboot(void) #endif /* USB_FIRWIRE_HANDLING || (HAVE_USBSTACK && !USE_ROCKBOX_USB) */ /* Screen dump */ +#ifdef HAVE_LCD_BITMAP static inline bool usb_do_screendump(void) { -#ifdef HAVE_LCD_BITMAP if(do_screendump_instead_of_usb) { - usb_state = USB_SCREENDUMP; screen_dump(); #ifdef HAVE_REMOTE_LCD remote_screen_dump(); #endif /* HAVE_REMOTE_LCD */ return true; } -#endif /* HAVE_LCD_BITMAP */ return false; } +#endif /* HAVE_LCD_BITMAP */ /* Power (charging-only) button */ static inline bool usb_power_button(void) @@ -356,13 +357,69 @@ static inline void usb_slave_mode(bool on) } #endif /* HAVE_USBSTACK */ +static void usb_set_host_present(bool present) +{ + if(usb_host_present == present) + return; + + usb_host_present = present; + + if(!usb_host_present) + { + usb_configure_drivers(USB_EXTRACTED); + return; + } + + if(usb_power_button()) + { + /* Only charging is desired */ + usb_configure_drivers(USB_POWERED); + return; + } + + if(!usb_configure_drivers(USB_INSERTED)) + return; /* Exclusive storage access not required */ + + /* Tell all threads that they have to back off the storage. + We subtract one for our own thread. Expect an ACK for every + listener for each broadcast they received. If it has been too + long, the user might have entered a screen that didn't ACK + when inserting the cable, such as a debugging screen. In that + case, reset the count or else USB would be locked out until + rebooting because it most likely won't ever come. Simply + resetting to the most recent broadcast count is racy. */ + if(TIME_AFTER(current_tick, usb_last_broadcast_tick + HZ*5)) + { + usb_num_acks_to_expect = 0; + usb_last_broadcast_tick = current_tick; + } + + usb_num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1; + DEBUGF("usb: waiting for %d acks...\n", num_acks_to_expect); +} + +static bool usb_handle_connected_ack(void) +{ + if(usb_num_acks_to_expect > 0 && --usb_num_acks_to_expect == 0) + { + DEBUGF("usb: all threads have acknowledged the connect.\n"); + if(usb_host_present) + { + usb_slave_mode(true); + return true; + } + } + else + { + DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect); + } + + return false; +} /*--- General driver code ---*/ static void NORETURN_ATTR usb_thread(void) { - int num_acks_to_expect = 0; - long last_broadcast_tick = current_tick; - bool host_detected = false; struct queue_event ev; while(1) @@ -378,6 +435,10 @@ static void NORETURN_ATTR usb_thread(void) if(usb_state <= USB_EXTRACTED) break; +#ifdef USB_DETECT_BY_REQUEST + usb_set_host_present(true); +#endif + usb_core_handle_transfer_completion( (struct usb_transfer_completion_event_data*)ev.data); break; @@ -387,72 +448,26 @@ static void NORETURN_ATTR usb_thread(void) if(usb_state != USB_EXTRACTED) break; +#ifdef HAVE_LCD_BITMAP if(usb_do_screendump()) + { + usb_state = USB_SCREENDUMP; break; + } +#endif usb_state = USB_POWERED; usb_stack_enable(true); -#ifdef USB_DETECT_BY_CORE - /* Wait for USB core to detect the host */ +#ifndef USB_DETECT_BY_REQUEST + usb_set_host_present(true); +#endif break; - - case USB_HOSTED: - if(usb_state != USB_POWERED) - break; -#endif /* USB_DETECT_BY_CORE */ - - if(host_detected) - break; - - host_detected = true; - - if(usb_power_button()) - { - /* Only charging is desired */ - usb_configure_drivers(USB_POWERED); - break; - } - - if(!usb_configure_drivers(USB_INSERTED)) - break; /* Exclusive storage access not required */ - - /* Tell all threads that they have to back off the storage. - We subtract one for our own thread. Expect an ACK for every - listener for each broadcast they received. If it has been too - long, the user might have entered a screen that didn't ACK - when inserting the cable, such as a debugging screen. In that - case, reset the count or else USB would be locked out until - rebooting because it most likely won't ever come. Simply - resetting to the most recent broadcast count is racy. */ - if(TIME_AFTER(current_tick, last_broadcast_tick + HZ*5)) - { - num_acks_to_expect = 0; - last_broadcast_tick = current_tick; - } - - num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1; - DEBUGF("usb: waiting for %d acks...\n", num_acks_to_expect); - - /* Leave the state as USB_POWERED until the expected number of - ACKS are received. */ - break; - /* USB_INSERTED: or USB_HOSTED: */ + /* USB_INSERTED */ case SYS_USB_CONNECTED_ACK: - if(num_acks_to_expect > 0 && --num_acks_to_expect == 0) - { - DEBUGF("usb: all threads have acknowledged the connect.\n"); - if(host_detected) - { - usb_slave_mode(true); - usb_state = USB_INSERTED; - } - } - else - { - DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect); - } + if(usb_handle_connected_ack()) + usb_state = USB_INSERTED; break; /* SYS_USB_CONNECTED_ACK */ @@ -470,13 +485,7 @@ static void NORETURN_ATTR usb_thread(void) usb_state = USB_EXTRACTED; - if(host_detected) - { - /* Ok to broadcast disconnect now */ - usb_configure_drivers(USB_EXTRACTED); - host_detected = false; - } - + usb_set_host_present(false); break; /* USB_EXTRACTED: */ @@ -530,8 +539,7 @@ void usb_status_event(int current_status) { /* Caller isn't expected to filter for changes in status. * current_status: - * all: USB_INSERTED, USB_EXTRACTED - * USB_DETECT_BY_CORE: USB_HOSTED (from core) + * USB_INSERTED, USB_EXTRACTED */ if(usb_monitor_enabled) { @@ -552,10 +560,6 @@ void usb_start_monitoring(void) /* An event may have been missed because it was sent before monitoring * was enabled due to the connector already having been inserted before * before or during boot. */ -#ifdef USB_DETECT_BY_CORE - /* Filter the status - USB_HOSTED may happen later */ - status = (status == USB_INSERTED) ? : USB_EXTRACTED; -#endif usb_status_event(status); #ifdef USB_FIREWIRE_HANDLING diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 1ea70ee882..eb17073e51 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c @@ -559,11 +559,6 @@ static void request_handler_device_get_descriptor(struct usb_ctrlrequest* req) case USB_DT_DEVICE: ptr = &device_descriptor; size = sizeof(struct usb_device_descriptor); -#ifdef USB_DETECT_BY_CORE - /* Something requested a device descriptor; consider this a legit - connection */ - usb_drv_usb_detect_event(); -#endif break; case USB_DT_OTHER_SPEED_CONFIG: