summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2012-01-04 21:55:09 +0000
committerFrank Gevaerts <frank@gevaerts.be>2012-01-04 21:55:09 +0000
commit4fcffcbdf34fc7a619c0626f8478cf06cdf1a043 (patch)
treead3a951e3ec9566b315807af8ab4045529c8878c /firmware
parentfd5524ff92b49d9fb14d3feaca4d26d86a05b2b2 (diff)
downloadrockbox-4fcffcbdf34fc7a619c0626f8478cf06cdf1a043.tar.gz
rockbox-4fcffcbdf34fc7a619c0626f8478cf06cdf1a043.zip
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
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/config.h10
-rw-r--r--firmware/export/usb.h3
-rw-r--r--firmware/export/usb_drv.h1
-rw-r--r--firmware/target/arm/as3525/usb-as3525.c16
-rw-r--r--firmware/target/arm/imx233/usb-imx233.c5
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c7
-rw-r--r--firmware/target/arm/pp/usb-fw-pp502x.c9
-rw-r--r--firmware/target/arm/rk27xx/usb-rk27xx.c5
-rw-r--r--firmware/usb.c158
-rw-r--r--firmware/usbstack/usb_core.c5
10 files changed, 86 insertions, 133 deletions
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())
- break;
-
- usb_state = USB_POWERED;
- usb_stack_enable(true);
-
-#ifdef USB_DETECT_BY_CORE
- /* Wait for USB core to detect the host */
- 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);
+ usb_state = USB_SCREENDUMP;
break;
}
+#endif
- 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);
+ usb_state = USB_POWERED;
+ usb_stack_enable(true);
- /* Leave the state as USB_POWERED until the expected number of
- ACKS are received. */
+#ifndef USB_DETECT_BY_REQUEST
+ usb_set_host_present(true);
+#endif
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: