summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-11-08 21:12:24 +0000
committerAidan MacDonald <amachronic@protonmail.com>2021-11-08 21:46:36 +0000
commit8c954c68e59ca2e644d08524f74e9dc5b728ee6e (patch)
tree5f92fd3cf17b6c8d351d49b09c3ed66fe7a36b15
parentaed113042d7467f1bf0793443e65a6941975394f (diff)
downloadrockbox-8c954c68e59ca2e644d08524f74e9dc5b728ee6e.tar.gz
rockbox-8c954c68e59ca2e644d08524f74e9dc5b728ee6e.zip
usb: Attempt to fix race condition in compatibility layer
Because usb_core_legacy_control_request() is called by an interrupt handler the global variables used to track the current control request at the very least need to be volatile. It might also be necessary to disable IRQs but I'm not sure of that. Change-Id: I0f0bb86d0ad63734e8d3c73cb1c52fedf5a98120
-rw-r--r--firmware/usbstack/usb_core.c24
1 files changed, 14 insertions, 10 deletions
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 5e87b0ad69..5de892196d 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -265,9 +265,9 @@ static struct usb_class_driver drivers[USB_NUM_DRIVERS] =
265 265
266#ifdef USB_LEGACY_CONTROL_API 266#ifdef USB_LEGACY_CONTROL_API
267static struct usb_ctrlrequest active_request_buf; 267static struct usb_ctrlrequest active_request_buf;
268static struct usb_ctrlrequest* active_request = NULL; 268static struct usb_ctrlrequest* volatile active_request = NULL;
269static void* control_write_data = NULL; 269static void* volatile control_write_data = NULL;
270static bool control_write_data_done = false; 270static volatile bool control_write_data_done = false;
271#endif 271#endif
272 272
273static void usb_core_control_request_handler(struct usb_ctrlrequest* req, void* reqdata); 273static void usb_core_control_request_handler(struct usb_ctrlrequest* req, void* reqdata);
@@ -956,10 +956,12 @@ void usb_core_transfer_complete(int endpoint, int dir, int status, int length)
956 956
957#ifdef USB_LEGACY_CONTROL_API 957#ifdef USB_LEGACY_CONTROL_API
958 if(endpoint == EP_CONTROL) { 958 if(endpoint == EP_CONTROL) {
959 if(dir == USB_DIR_OUT && active_request && control_write_data_done) { 959 bool cwdd = control_write_data_done;
960 completion_event->data[0] = active_request; 960 struct usb_ctrlrequest* req = active_request;
961 if(control_write_data_done && dir == USB_DIR_OUT) 961
962 completion_event->data[1] = control_write_data; 962 if(dir == USB_DIR_OUT && req && cwdd) {
963 completion_event->data[0] = req;
964 completion_event->data[1] = control_write_data;
963 } else { 965 } else {
964 return; 966 return;
965 } 967 }
@@ -1023,10 +1025,12 @@ void usb_core_legacy_control_request(struct usb_ctrlrequest* req)
1023void usb_drv_control_response(enum usb_control_response resp, 1025void usb_drv_control_response(enum usb_control_response resp,
1024 void* data, int length) 1026 void* data, int length)
1025{ 1027{
1026 if(!active_request) 1028 struct usb_ctrlrequest* req = active_request;
1029
1030 if(!req)
1027 panicf("null ctrl req"); 1031 panicf("null ctrl req");
1028 1032
1029 if(active_request->wLength == 0) 1033 if(req->wLength == 0)
1030 { 1034 {
1031 active_request = NULL; 1035 active_request = NULL;
1032 1036
@@ -1038,7 +1042,7 @@ void usb_drv_control_response(enum usb_control_response resp,
1038 else 1042 else
1039 panicf("RECEIVE on non-data req"); 1043 panicf("RECEIVE on non-data req");
1040 } 1044 }
1041 else if(active_request->bRequestType & USB_DIR_IN) 1045 else if(req->bRequestType & USB_DIR_IN)
1042 { 1046 {
1043 /* Control read request */ 1047 /* Control read request */
1044 if(resp == USB_CONTROL_ACK) 1048 if(resp == USB_CONTROL_ACK)