Reorganise USB initialisation to not depend on a specific enumeration sequence, by Bartosz Fabianowski, with minor tweaks by Michael Sevakis (FS#12497)
FreeBSD apparently sends a SET_ADDRESS first, which confused our code. This patch fixes that, and also simplifies the connection handling a bit. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31582 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
fd5524ff92
commit
4fcffcbdf3
10 changed files with 86 additions and 133 deletions
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
158
firmware/usb.c
158
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
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue