summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2012-12-07 13:37:26 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2012-12-07 13:37:26 +0100
commit775ab07d5e710c4811a66b246f8f8708a09eba28 (patch)
treedf725ba1aea0bccbfb64e29d49fa04bfc671ec11
parentfb43a137e72d1f428efef00047a416497463edfb (diff)
downloadrockbox-775ab07d5e710c4811a66b246f8f8708a09eba28.tar.gz
rockbox-775ab07d5e710c4811a66b246f8f8708a09eba28.zip
usb: add support for hardware handled SET ADDR/CONFIG
Some USB controllers like the one of the Rockchip 27xx handle some requests in pure hardware. This is especially a problem for two of them: - SET ADDR which is used by our core to track the DEFAULT/ADDRESS state and is required for the drivers to work properly - SET CONFIG which is used by our core to initialise the drivers by calling init_connection() In these cases we need a way to notify the core that such requests happened. We do this by exporting two functions which directly notify the core about these requests and perform the necessary init steps required without doing the actual USB transfers. Special care is needed because these functions could be called from an interrupt handler. For this reason we still use the usb_queue and introduce new IDs so that they are processed in order and safely. No functional change is intended, both in the usbstack and on targets without such quirks. Change-Id: Ie42feffd4584e88bf37cff018b627f333dca1140
-rw-r--r--firmware/export/usb.h3
-rw-r--r--firmware/export/usb_core.h4
-rw-r--r--firmware/usb.c11
-rw-r--r--firmware/usbstack/usb_core.c70
4 files changed, 71 insertions, 17 deletions
diff --git a/firmware/export/usb.h b/firmware/export/usb.h
index 8954e9cc59..13ef3983b2 100644
--- a/firmware/export/usb.h
+++ b/firmware/export/usb.h
@@ -44,6 +44,8 @@ enum
44#endif 44#endif
45#ifdef HAVE_USBSTACK 45#ifdef HAVE_USBSTACK
46 USB_TRANSFER_COMPLETION, /* Event */ 46 USB_TRANSFER_COMPLETION, /* Event */
47 USB_NOTIFY_SET_ADDR, /* Event */
48 USB_NOTIFY_SET_CONFIG, /* Event */
47#endif 49#endif
48#ifdef USB_FIREWIRE_HANDLING 50#ifdef USB_FIREWIRE_HANDLING
49 USB_REQUEST_REBOOT, /* Event */ 51 USB_REQUEST_REBOOT, /* Event */
@@ -130,6 +132,7 @@ void usb_charger_update(void);
130#ifdef HAVE_USBSTACK 132#ifdef HAVE_USBSTACK
131void usb_signal_transfer_completion( 133void usb_signal_transfer_completion(
132 struct usb_transfer_completion_event_data *event_data); 134 struct usb_transfer_completion_event_data *event_data);
135void usb_signal_notify(long id, intptr_t data);
133bool usb_driver_enabled(int driver); 136bool usb_driver_enabled(int driver);
134bool usb_exclusive_storage(void); /* storage is available for usb */ 137bool usb_exclusive_storage(void); /* storage is available for usb */
135#endif 138#endif
diff --git a/firmware/export/usb_core.h b/firmware/export/usb_core.h
index 6405aa492d..9e3d0d7916 100644
--- a/firmware/export/usb_core.h
+++ b/firmware/export/usb_core.h
@@ -51,6 +51,10 @@ void usb_core_enable_driver(int driver,bool enabled);
51bool usb_core_driver_enabled(int driver); 51bool usb_core_driver_enabled(int driver);
52void usb_core_handle_transfer_completion( 52void usb_core_handle_transfer_completion(
53 struct usb_transfer_completion_event_data* event); 53 struct usb_transfer_completion_event_data* event);
54void usb_core_handle_notify(long id, intptr_t data);
55/* For controllers which handle SET ADDR and/or SET CONFIG in hardware */
56void usb_core_notify_set_address(uint8_t addr);
57void usb_core_notify_set_config(uint8_t config);
54 58
55int usb_core_request_endpoint(int type, int dir,struct usb_class_driver* drv); 59int usb_core_request_endpoint(int type, int dir,struct usb_class_driver* drv);
56void usb_core_release_endpoint(int dir); 60void usb_core_release_endpoint(int dir);
diff --git a/firmware/usb.c b/firmware/usb.c
index 6823851e08..b8c9822ff6 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -270,6 +270,11 @@ void usb_signal_transfer_completion(
270 queue_post(&usb_queue, USB_TRANSFER_COMPLETION, (intptr_t)event_data); 270 queue_post(&usb_queue, USB_TRANSFER_COMPLETION, (intptr_t)event_data);
271} 271}
272 272
273void usb_signal_notify(long id, intptr_t data)
274{
275 queue_post(&usb_queue, id, data);
276}
277
273#else /* !HAVE_USBSTACK */ 278#else /* !HAVE_USBSTACK */
274 279
275static inline void usb_stack_enable(bool enable) 280static inline void usb_stack_enable(bool enable)
@@ -431,6 +436,12 @@ static void NORETURN_ATTR usb_thread(void)
431 /*** Main USB thread duties ***/ 436 /*** Main USB thread duties ***/
432 437
433#ifdef HAVE_USBSTACK 438#ifdef HAVE_USBSTACK
439 case USB_NOTIFY_SET_ADDR:
440 case USB_NOTIFY_SET_CONFIG:
441 if(usb_state <= USB_EXTRACTED)
442 break;
443 usb_core_handle_notify(ev.id, ev.data);
444 break;
434 case USB_TRANSFER_COMPLETION: 445 case USB_TRANSFER_COMPLETION:
435 if(usb_state <= USB_EXTRACTED) 446 if(usb_state <= USB_EXTRACTED)
436 break; 447 break;
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 801325b692..2a3cc1c525 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -663,10 +663,31 @@ static void request_handler_device_get_descriptor(struct usb_ctrlrequest* req)
663 } 663 }
664} 664}
665 665
666static void request_handler_device(struct usb_ctrlrequest* req) 666static void usb_core_do_set_addr(uint8_t address)
667{ 667{
668 int i; 668 logf("usb_core: SET_ADR %d", address);
669 usb_address = address;
670 usb_state = ADDRESS;
671}
672
673static void usb_core_do_set_config(uint8_t config)
674{
675 logf("usb_core: SET_CONFIG");
676 if(config) {
677 usb_state = CONFIGURED;
678 for(int i = 0; i < USB_NUM_DRIVERS; i++)
679 if(drivers[i].enabled && drivers[i].init_connection)
680 drivers[i].init_connection();
681 }
682 else
683 usb_state = ADDRESS;
684 #ifdef HAVE_USB_CHARGING_ENABLE
685 usb_charging_maxcurrent_change(usb_charging_maxcurrent());
686 #endif
687}
669 688
689static void request_handler_device(struct usb_ctrlrequest* req)
690{
670 switch(req->bRequest) { 691 switch(req->bRequest) {
671 case USB_REQ_GET_CONFIGURATION: { 692 case USB_REQ_GET_CONFIGURATION: {
672 logf("usb_core: GET_CONFIG"); 693 logf("usb_core: GET_CONFIG");
@@ -676,20 +697,9 @@ static void request_handler_device(struct usb_ctrlrequest* req)
676 break; 697 break;
677 } 698 }
678 case USB_REQ_SET_CONFIGURATION: { 699 case USB_REQ_SET_CONFIGURATION: {
679 logf("usb_core: SET_CONFIG");
680 usb_drv_cancel_all_transfers(); 700 usb_drv_cancel_all_transfers();
681 if(req->wValue) { 701 usb_core_do_set_config(req->wValue);
682 usb_state = CONFIGURED;
683 for(i = 0; i < USB_NUM_DRIVERS; i++)
684 if(drivers[i].enabled && drivers[i].init_connection)
685 drivers[i].init_connection();
686 }
687 else
688 usb_state = ADDRESS;
689 usb_drv_send(EP_CONTROL, NULL, 0); 702 usb_drv_send(EP_CONTROL, NULL, 0);
690#ifdef HAVE_USB_CHARGING_ENABLE
691 usb_charging_maxcurrent_change(usb_charging_maxcurrent());
692#endif
693 break; 703 break;
694 } 704 }
695 case USB_REQ_SET_ADDRESS: { 705 case USB_REQ_SET_ADDRESS: {
@@ -697,9 +707,8 @@ static void request_handler_device(struct usb_ctrlrequest* req)
697 logf("usb_core: SET_ADR %d", address); 707 logf("usb_core: SET_ADR %d", address);
698 usb_drv_send(EP_CONTROL, NULL, 0); 708 usb_drv_send(EP_CONTROL, NULL, 0);
699 usb_drv_cancel_all_transfers(); 709 usb_drv_cancel_all_transfers();
700 usb_address = address; 710 usb_drv_set_address(address);
701 usb_drv_set_address(usb_address); 711 usb_core_do_set_addr(address);
702 usb_state = ADDRESS;
703 break; 712 break;
704 } 713 }
705 case USB_REQ_GET_DESCRIPTOR: 714 case USB_REQ_GET_DESCRIPTOR:
@@ -913,6 +922,21 @@ void usb_core_transfer_complete(int endpoint, int dir, int status, int length)
913 } 922 }
914} 923}
915 924
925void usb_core_handle_notify(long id, intptr_t data)
926{
927 switch(id)
928 {
929 case USB_NOTIFY_SET_ADDR:
930 usb_core_do_set_addr(data);
931 break;
932 case USB_NOTIFY_SET_CONFIG:
933 usb_core_do_set_config(data);
934 break;
935 default:
936 break;
937 }
938}
939
916/* called by usb_drv_int() */ 940/* called by usb_drv_int() */
917void usb_core_control_request(struct usb_ctrlrequest* req) 941void usb_core_control_request(struct usb_ctrlrequest* req)
918{ 942{
@@ -928,6 +952,18 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
928 usb_signal_transfer_completion(completion_event); 952 usb_signal_transfer_completion(completion_event);
929} 953}
930 954
955void usb_core_notify_set_address(uint8_t addr)
956{
957 logf("notify set addr received %ld", current_tick);
958 usb_signal_notify(USB_NOTIFY_SET_ADDR, addr);
959}
960
961void usb_core_notify_set_config(uint8_t config)
962{
963 logf("notify set config received %ld", current_tick);
964 usb_signal_notify(USB_NOTIFY_SET_CONFIG, config);
965}
966
931#ifdef HAVE_USB_CHARGING_ENABLE 967#ifdef HAVE_USB_CHARGING_ENABLE
932void usb_charging_enable(int state) 968void usb_charging_enable(int state)
933{ 969{