summaryrefslogtreecommitdiff
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
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
-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 */
787/* Priority in bootloader is wanted */ 787/* Priority in bootloader is wanted */
788#define HAVE_PRIORITY_SCHEDULING 788#define HAVE_PRIORITY_SCHEDULING
789#define USB_STATUS_BY_EVENT 789#define USB_STATUS_BY_EVENT
790#define USB_DETECT_BY_CORE 790#define USB_DETECT_BY_REQUEST
791#if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC 791#if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC
792#define INCLUDE_TIMEOUT_API 792#define INCLUDE_TIMEOUT_API
793#define USB_DRIVER_CLOSE 793#define USB_DRIVER_CLOSE
@@ -815,17 +815,17 @@ Lyre prototype 1 */
815#ifdef HAVE_USBSTACK 815#ifdef HAVE_USBSTACK
816#if CONFIG_USBOTG == USBOTG_ARC 816#if CONFIG_USBOTG == USBOTG_ARC
817#define USB_STATUS_BY_EVENT 817#define USB_STATUS_BY_EVENT
818#define USB_DETECT_BY_CORE 818#define USB_DETECT_BY_REQUEST
819#define INCLUDE_TIMEOUT_API 819#define INCLUDE_TIMEOUT_API
820#elif CONFIG_USBOTG == USBOTG_AS3525 820#elif CONFIG_USBOTG == USBOTG_AS3525
821#define USB_STATUS_BY_EVENT 821#define USB_STATUS_BY_EVENT
822#define USB_DETECT_BY_CORE 822#define USB_DETECT_BY_REQUEST
823#elif CONFIG_USBOTG == USBOTG_S3C6400X /* FIXME */ && CONFIG_CPU == AS3525v2 823#elif CONFIG_USBOTG == USBOTG_S3C6400X /* FIXME */ && CONFIG_CPU == AS3525v2
824#define USB_STATUS_BY_EVENT 824#define USB_STATUS_BY_EVENT
825#define USB_DETECT_BY_CORE 825#define USB_DETECT_BY_REQUEST
826#elif CONFIG_USBOTG == USBOTG_RK27XX 826#elif CONFIG_USBOTG == USBOTG_RK27XX
827#define USB_STATUS_BY_EVENT 827#define USB_STATUS_BY_EVENT
828#define USB_DETECT_BY_CORE 828#define USB_DETECT_BY_REQUEST
829#endif /* CONFIG_USB == */ 829#endif /* CONFIG_USB == */
830#endif /* HAVE_USBSTACK */ 830#endif /* HAVE_USBSTACK */
831 831
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
39 USB_EXTRACTED = 0, /* Event+State */ 39 USB_EXTRACTED = 0, /* Event+State */
40 USB_INSERTED, /* Event+State */ 40 USB_INSERTED, /* Event+State */
41 USB_POWERED, /* State - transitional indicator if no power */ 41 USB_POWERED, /* State - transitional indicator if no power */
42#ifdef USB_DETECT_BY_CORE
43 USB_HOSTED, /* Event - host presence was detected */
44#endif
45#if (CONFIG_STORAGE & STORAGE_MMC) 42#if (CONFIG_STORAGE & STORAGE_MMC)
46 USB_REENABLE, /* Event */ 43 USB_REENABLE, /* Event */
47#endif 44#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 @@
24#include "kernel.h" 24#include "kernel.h"
25 25
26void usb_drv_startup(void); 26void usb_drv_startup(void);
27void usb_drv_usb_detect_event(void); /* Target implemented */
28void usb_drv_int_enable(bool enable); /* Target implemented */ 27void usb_drv_int_enable(bool enable); /* Target implemented */
29void usb_drv_init(void); 28void usb_drv_init(void);
30void usb_drv_exit(void); 29void 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)
58#endif 58#endif
59} 59}
60 60
61void usb_drv_usb_detect_event(void)
62{
63#if (CONFIG_CPU != AS3525v2 || defined(USE_ROCKBOX_USB)) \
64 && defined (USB_STATUS_BY_EVENT)
65/* Rebooting on USB plug can crash these players in a state where
66 * hardware power off (pressing the power button) doesn't work anymore
67 * TODO: Implement USB in rockbox for these players */
68 int oldstatus = disable_irq_save(); /* May come via USB thread */
69
70 if (usb_status == USB_INSERTED)
71 usb_status_event(USB_HOSTED);
72
73 restore_irq(oldstatus);
74#endif
75}
76
77int usb_detect(void) 61int usb_detect(void)
78{ 62{
79 return usb_status; 63 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)
40 usb_status_event(USB_EXTRACTED); 40 usb_status_event(USB_EXTRACTED);
41} 41}
42 42
43void usb_drv_usb_detect_event()
44{
45 usb_status_event(USB_HOSTED);
46}
47
48void usb_attach(void) 43void usb_attach(void)
49{ 44{
50 usb_drv_attach(); 45 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)
145 } 145 }
146} 146}
147 147
148/* Called during the setup packet request by the host */
149void usb_drv_usb_detect_event(void)
150{
151 if (usb_drv_powered())
152 usb_status_event(USB_HOSTED);
153}
154
155/* Called when reading the MBR */ 148/* Called when reading the MBR */
156void usb_fix_mbr(unsigned char *mbr) 149void usb_fix_mbr(unsigned char *mbr)
157{ 150{
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)
224 USB_GPIO_INT_CLR = USB_GPIO_MASK; 224 USB_GPIO_INT_CLR = USB_GPIO_MASK;
225 timeout_register(&usb_oneshot, usb_timeout_event, HZ/5, val); 225 timeout_register(&usb_oneshot, usb_timeout_event, HZ/5, val);
226} 226}
227
228/* USB_DETECT_BY_CORE: Called when device descriptor is requested */
229void usb_drv_usb_detect_event(void)
230{
231 /* Filter for invalid bus reset when unplugging by checking the pin state. */
232 if(usb_plugged()) {
233 usb_status_event(USB_HOSTED);
234 }
235}
236#endif /* USB_STATUS_BY_EVENT */ 227#endif /* USB_STATUS_BY_EVENT */
237 228
238#ifdef HAVE_BOOTLOADER_USB_MODE 229#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 @@
30 30
31int usb_status = USB_EXTRACTED; 31int usb_status = USB_EXTRACTED;
32 32
33void usb_drv_usb_detect_event()
34{
35 usb_status_event(USB_INSERTED);
36}
37
38void usb_init_device(void) 33void usb_init_device(void)
39{ 34{
40} 35}
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;
63 63
64/* We assume that the USB cable is extracted */ 64/* We assume that the USB cable is extracted */
65static int usb_state = USB_EXTRACTED; 65static int usb_state = USB_EXTRACTED;
66 66static bool usb_host_present = false;
67static int usb_num_acks_to_expect = 0;
68static long usb_last_broadcast_tick = 0;
67#if (CONFIG_STORAGE & STORAGE_MMC) && defined(USB_FULL_INIT) && !defined(HAVE_USBSTACK) 69#if (CONFIG_STORAGE & STORAGE_MMC) && defined(USB_FULL_INIT) && !defined(HAVE_USBSTACK)
68static int usb_mmc_countdown = 0; 70static int usb_mmc_countdown = 0;
69#endif 71#endif
@@ -109,21 +111,20 @@ static void try_reboot(void)
109#endif /* USB_FIRWIRE_HANDLING || (HAVE_USBSTACK && !USE_ROCKBOX_USB) */ 111#endif /* USB_FIRWIRE_HANDLING || (HAVE_USBSTACK && !USE_ROCKBOX_USB) */
110 112
111/* Screen dump */ 113/* Screen dump */
114#ifdef HAVE_LCD_BITMAP
112static inline bool usb_do_screendump(void) 115static inline bool usb_do_screendump(void)
113{ 116{
114#ifdef HAVE_LCD_BITMAP
115 if(do_screendump_instead_of_usb) 117 if(do_screendump_instead_of_usb)
116 { 118 {
117 usb_state = USB_SCREENDUMP;
118 screen_dump(); 119 screen_dump();
119#ifdef HAVE_REMOTE_LCD 120#ifdef HAVE_REMOTE_LCD
120 remote_screen_dump(); 121 remote_screen_dump();
121#endif /* HAVE_REMOTE_LCD */ 122#endif /* HAVE_REMOTE_LCD */
122 return true; 123 return true;
123 } 124 }
124#endif /* HAVE_LCD_BITMAP */
125 return false; 125 return false;
126} 126}
127#endif /* HAVE_LCD_BITMAP */
127 128
128/* Power (charging-only) button */ 129/* Power (charging-only) button */
129static inline bool usb_power_button(void) 130static inline bool usb_power_button(void)
@@ -356,13 +357,69 @@ static inline void usb_slave_mode(bool on)
356} 357}
357#endif /* HAVE_USBSTACK */ 358#endif /* HAVE_USBSTACK */
358 359
360static void usb_set_host_present(bool present)
361{
362 if(usb_host_present == present)
363 return;
364
365 usb_host_present = present;
366
367 if(!usb_host_present)
368 {
369 usb_configure_drivers(USB_EXTRACTED);
370 return;
371 }
372
373 if(usb_power_button())
374 {
375 /* Only charging is desired */
376 usb_configure_drivers(USB_POWERED);
377 return;
378 }
379
380 if(!usb_configure_drivers(USB_INSERTED))
381 return; /* Exclusive storage access not required */
382
383 /* Tell all threads that they have to back off the storage.
384 We subtract one for our own thread. Expect an ACK for every
385 listener for each broadcast they received. If it has been too
386 long, the user might have entered a screen that didn't ACK
387 when inserting the cable, such as a debugging screen. In that
388 case, reset the count or else USB would be locked out until
389 rebooting because it most likely won't ever come. Simply
390 resetting to the most recent broadcast count is racy. */
391 if(TIME_AFTER(current_tick, usb_last_broadcast_tick + HZ*5))
392 {
393 usb_num_acks_to_expect = 0;
394 usb_last_broadcast_tick = current_tick;
395 }
396
397 usb_num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
398 DEBUGF("usb: waiting for %d acks...\n", num_acks_to_expect);
399}
400
401static bool usb_handle_connected_ack(void)
402{
403 if(usb_num_acks_to_expect > 0 && --usb_num_acks_to_expect == 0)
404 {
405 DEBUGF("usb: all threads have acknowledged the connect.\n");
406 if(usb_host_present)
407 {
408 usb_slave_mode(true);
409 return true;
410 }
411 }
412 else
413 {
414 DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect);
415 }
416
417 return false;
418}
359 419
360/*--- General driver code ---*/ 420/*--- General driver code ---*/
361static void NORETURN_ATTR usb_thread(void) 421static void NORETURN_ATTR usb_thread(void)
362{ 422{
363 int num_acks_to_expect = 0;
364 long last_broadcast_tick = current_tick;
365 bool host_detected = false;
366 struct queue_event ev; 423 struct queue_event ev;
367 424
368 while(1) 425 while(1)
@@ -378,6 +435,10 @@ static void NORETURN_ATTR usb_thread(void)
378 if(usb_state <= USB_EXTRACTED) 435 if(usb_state <= USB_EXTRACTED)
379 break; 436 break;
380 437
438#ifdef USB_DETECT_BY_REQUEST
439 usb_set_host_present(true);
440#endif
441
381 usb_core_handle_transfer_completion( 442 usb_core_handle_transfer_completion(
382 (struct usb_transfer_completion_event_data*)ev.data); 443 (struct usb_transfer_completion_event_data*)ev.data);
383 break; 444 break;
@@ -387,72 +448,26 @@ static void NORETURN_ATTR usb_thread(void)
387 if(usb_state != USB_EXTRACTED) 448 if(usb_state != USB_EXTRACTED)
388 break; 449 break;
389 450
451#ifdef HAVE_LCD_BITMAP
390 if(usb_do_screendump()) 452 if(usb_do_screendump())
391 break;
392
393 usb_state = USB_POWERED;
394 usb_stack_enable(true);
395
396#ifdef USB_DETECT_BY_CORE
397 /* Wait for USB core to detect the host */
398 break;
399
400 case USB_HOSTED:
401 if(usb_state != USB_POWERED)
402 break;
403#endif /* USB_DETECT_BY_CORE */
404
405 if(host_detected)
406 break;
407
408 host_detected = true;
409
410 if(usb_power_button())
411 { 453 {
412 /* Only charging is desired */ 454 usb_state = USB_SCREENDUMP;
413 usb_configure_drivers(USB_POWERED);
414 break; 455 break;
415 } 456 }
457#endif
416 458
417 if(!usb_configure_drivers(USB_INSERTED)) 459 usb_state = USB_POWERED;
418 break; /* Exclusive storage access not required */ 460 usb_stack_enable(true);
419
420 /* Tell all threads that they have to back off the storage.
421 We subtract one for our own thread. Expect an ACK for every
422 listener for each broadcast they received. If it has been too
423 long, the user might have entered a screen that didn't ACK
424 when inserting the cable, such as a debugging screen. In that
425 case, reset the count or else USB would be locked out until
426 rebooting because it most likely won't ever come. Simply
427 resetting to the most recent broadcast count is racy. */
428 if(TIME_AFTER(current_tick, last_broadcast_tick + HZ*5))
429 {
430 num_acks_to_expect = 0;
431 last_broadcast_tick = current_tick;
432 }
433
434 num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
435 DEBUGF("usb: waiting for %d acks...\n", num_acks_to_expect);
436 461
437 /* Leave the state as USB_POWERED until the expected number of 462#ifndef USB_DETECT_BY_REQUEST
438 ACKS are received. */ 463 usb_set_host_present(true);
464#endif
439 break; 465 break;
440 /* USB_INSERTED: or USB_HOSTED: */ 466 /* USB_INSERTED */
441 467
442 case SYS_USB_CONNECTED_ACK: 468 case SYS_USB_CONNECTED_ACK:
443 if(num_acks_to_expect > 0 && --num_acks_to_expect == 0) 469 if(usb_handle_connected_ack())
444 { 470 usb_state = USB_INSERTED;
445 DEBUGF("usb: all threads have acknowledged the connect.\n");
446 if(host_detected)
447 {
448 usb_slave_mode(true);
449 usb_state = USB_INSERTED;
450 }
451 }
452 else
453 {
454 DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect);
455 }
456 break; 471 break;
457 /* SYS_USB_CONNECTED_ACK */ 472 /* SYS_USB_CONNECTED_ACK */
458 473
@@ -470,13 +485,7 @@ static void NORETURN_ATTR usb_thread(void)
470 485
471 usb_state = USB_EXTRACTED; 486 usb_state = USB_EXTRACTED;
472 487
473 if(host_detected) 488 usb_set_host_present(false);
474 {
475 /* Ok to broadcast disconnect now */
476 usb_configure_drivers(USB_EXTRACTED);
477 host_detected = false;
478 }
479
480 break; 489 break;
481 /* USB_EXTRACTED: */ 490 /* USB_EXTRACTED: */
482 491
@@ -530,8 +539,7 @@ void usb_status_event(int current_status)
530{ 539{
531 /* Caller isn't expected to filter for changes in status. 540 /* Caller isn't expected to filter for changes in status.
532 * current_status: 541 * current_status:
533 * all: USB_INSERTED, USB_EXTRACTED 542 * USB_INSERTED, USB_EXTRACTED
534 * USB_DETECT_BY_CORE: USB_HOSTED (from core)
535 */ 543 */
536 if(usb_monitor_enabled) 544 if(usb_monitor_enabled)
537 { 545 {
@@ -552,10 +560,6 @@ void usb_start_monitoring(void)
552 /* An event may have been missed because it was sent before monitoring 560 /* An event may have been missed because it was sent before monitoring
553 * was enabled due to the connector already having been inserted before 561 * was enabled due to the connector already having been inserted before
554 * before or during boot. */ 562 * before or during boot. */
555#ifdef USB_DETECT_BY_CORE
556 /* Filter the status - USB_HOSTED may happen later */
557 status = (status == USB_INSERTED) ? : USB_EXTRACTED;
558#endif
559 usb_status_event(status); 563 usb_status_event(status);
560 564
561#ifdef USB_FIREWIRE_HANDLING 565#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)
559 case USB_DT_DEVICE: 559 case USB_DT_DEVICE:
560 ptr = &device_descriptor; 560 ptr = &device_descriptor;
561 size = sizeof(struct usb_device_descriptor); 561 size = sizeof(struct usb_device_descriptor);
562#ifdef USB_DETECT_BY_CORE
563 /* Something requested a device descriptor; consider this a legit
564 connection */
565 usb_drv_usb_detect_event();
566#endif
567 break; 562 break;
568 563
569 case USB_DT_OTHER_SPEED_CONFIG: 564 case USB_DT_OTHER_SPEED_CONFIG: