1
0
Fork 0
forked from len0rd/rockbox

Change control handling to start expecting host packets before sending data to the host. This makes the handling less timing sensitive on some controllers

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23263 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Frank Gevaerts 2009-10-19 16:21:50 +00:00
parent ee6557eeda
commit bad510ad10
4 changed files with 33 additions and 36 deletions

View file

@ -51,7 +51,6 @@ void usb_core_enable_driver(int driver,bool enabled);
bool usb_core_driver_enabled(int driver); bool usb_core_driver_enabled(int driver);
void usb_core_handle_transfer_completion( void usb_core_handle_transfer_completion(
struct usb_transfer_completion_event_data* event); struct usb_transfer_completion_event_data* event);
int usb_core_ack_control(struct usb_ctrlrequest* req);
int usb_core_request_endpoint(int type, int dir,struct usb_class_driver* drv); int usb_core_request_endpoint(int type, int dir,struct usb_class_driver* drv);
void usb_core_release_endpoint(int dir); void usb_core_release_endpoint(int dir);

View file

@ -507,6 +507,15 @@ static void allocate_interfaces_and_endpoints(void)
usb_core_num_interfaces = interface; usb_core_num_interfaces = interface;
} }
static int usb_core_ack_control(struct usb_ctrlrequest* req)
{
if (req->bRequestType & USB_DIR_IN)
return usb_drv_recv(EP_CONTROL,NULL,0);
else
return usb_drv_send(EP_CONTROL,NULL,0);
}
static void control_request_handler_drivers(struct usb_ctrlrequest* req) static void control_request_handler_drivers(struct usb_ctrlrequest* req)
{ {
int i, interface = req->wIndex; int i, interface = req->wIndex;
@ -608,11 +617,9 @@ static void request_handler_device_get_descriptor(struct usb_ctrlrequest* req)
memcpy(response_data,ptr,length); memcpy(response_data,ptr,length);
} }
if(usb_drv_send(EP_CONTROL,response_data,length)) usb_drv_recv(EP_CONTROL,NULL,0);
return; usb_drv_send(EP_CONTROL,response_data,length);
} }
if (handled)
usb_core_ack_control(req);
} }
static void request_handler_device(struct usb_ctrlrequest* req) static void request_handler_device(struct usb_ctrlrequest* req)
@ -623,8 +630,8 @@ static void request_handler_device(struct usb_ctrlrequest* req)
case USB_REQ_GET_CONFIGURATION: { case USB_REQ_GET_CONFIGURATION: {
logf("usb_core: GET_CONFIG"); logf("usb_core: GET_CONFIG");
response_data[0] = (usb_state == ADDRESS ? 0 : 1); response_data[0] = (usb_state == ADDRESS ? 0 : 1);
if(!usb_drv_send(EP_CONTROL, response_data, 1)) usb_drv_recv(EP_CONTROL,NULL,0);
usb_core_ack_control(req); usb_drv_send(EP_CONTROL, response_data, 1);
break; break;
} }
case USB_REQ_SET_CONFIGURATION: { case USB_REQ_SET_CONFIGURATION: {
@ -640,14 +647,13 @@ static void request_handler_device(struct usb_ctrlrequest* req)
else { else {
usb_state = ADDRESS; usb_state = ADDRESS;
} }
usb_core_ack_control(req); usb_drv_send(EP_CONTROL,NULL,0);
break; break;
} }
case USB_REQ_SET_ADDRESS: { case USB_REQ_SET_ADDRESS: {
unsigned char address = req->wValue; unsigned char address = req->wValue;
logf("usb_core: SET_ADR %d", address); logf("usb_core: SET_ADR %d", address);
if(usb_core_ack_control(req)) usb_drv_send(EP_CONTROL,NULL,0);
break;
usb_drv_cancel_all_transfers(); usb_drv_cancel_all_transfers();
usb_address = address; usb_address = address;
usb_drv_set_address(usb_address); usb_drv_set_address(usb_address);
@ -663,15 +669,15 @@ static void request_handler_device(struct usb_ctrlrequest* req)
case USB_REQ_SET_FEATURE: case USB_REQ_SET_FEATURE:
if(req->wValue==USB_DEVICE_TEST_MODE) { if(req->wValue==USB_DEVICE_TEST_MODE) {
int mode=req->wIndex>>8; int mode=req->wIndex>>8;
usb_core_ack_control(req); usb_drv_send(EP_CONTROL,NULL,0);
usb_drv_set_test_mode(mode); usb_drv_set_test_mode(mode);
} }
break; break;
case USB_REQ_GET_STATUS: case USB_REQ_GET_STATUS:
response_data[0]= 0; response_data[0]= 0;
response_data[1]= 0; response_data[1]= 0;
if(!usb_drv_send(EP_CONTROL, response_data, 2)) usb_drv_recv(EP_CONTROL,NULL,0);
usb_core_ack_control(req); usb_drv_send(EP_CONTROL, response_data, 2);
break; break;
default: default:
break; break;
@ -684,14 +690,14 @@ static void request_handler_interface_standard(struct usb_ctrlrequest* req)
{ {
case USB_REQ_SET_INTERFACE: case USB_REQ_SET_INTERFACE:
logf("usb_core: SET_INTERFACE"); logf("usb_core: SET_INTERFACE");
usb_core_ack_control(req); usb_drv_send(EP_CONTROL,NULL,0);
break; break;
case USB_REQ_GET_INTERFACE: case USB_REQ_GET_INTERFACE:
logf("usb_core: GET_INTERFACE"); logf("usb_core: GET_INTERFACE");
response_data[0]=0; response_data[0]=0;
if(!usb_drv_send(EP_CONTROL,response_data,1)) usb_drv_recv(EP_CONTROL,NULL,0);
usb_core_ack_control(req); usb_drv_send(EP_CONTROL,response_data,1);
break; break;
case USB_REQ_CLEAR_FEATURE: case USB_REQ_CLEAR_FEATURE:
break; break;
@ -700,8 +706,8 @@ static void request_handler_interface_standard(struct usb_ctrlrequest* req)
case USB_REQ_GET_STATUS: case USB_REQ_GET_STATUS:
response_data[0]=0; response_data[0]=0;
response_data[1]=0; response_data[1]=0;
if(!usb_drv_send(EP_CONTROL, response_data, 2)) usb_drv_recv(EP_CONTROL,NULL,0);
usb_core_ack_control(req); usb_drv_send(EP_CONTROL, response_data, 2);
break; break;
default: default:
control_request_handler_drivers(req); control_request_handler_drivers(req);
@ -730,13 +736,13 @@ static void request_handler_endpoint(struct usb_ctrlrequest* req)
if (req->wValue==USB_ENDPOINT_HALT) { if (req->wValue==USB_ENDPOINT_HALT) {
usb_drv_stall(EP_NUM(req->wIndex), false, EP_DIR(req->wIndex)); usb_drv_stall(EP_NUM(req->wIndex), false, EP_DIR(req->wIndex));
} }
usb_core_ack_control(req); usb_drv_send(EP_CONTROL,NULL,0);
break; break;
case USB_REQ_SET_FEATURE: case USB_REQ_SET_FEATURE:
if (req->wValue==USB_ENDPOINT_HALT) { if (req->wValue==USB_ENDPOINT_HALT) {
usb_drv_stall(EP_NUM(req->wIndex), true, EP_DIR(req->wIndex)); usb_drv_stall(EP_NUM(req->wIndex), true, EP_DIR(req->wIndex));
} }
usb_core_ack_control(req); usb_drv_send(EP_CONTROL,NULL,0);
break; break;
case USB_REQ_GET_STATUS: case USB_REQ_GET_STATUS:
response_data[0]=0; response_data[0]=0;
@ -746,8 +752,8 @@ static void request_handler_endpoint(struct usb_ctrlrequest* req)
response_data[0]=usb_drv_stalled(EP_NUM(req->wIndex), response_data[0]=usb_drv_stalled(EP_NUM(req->wIndex),
EP_DIR(req->wIndex)); EP_DIR(req->wIndex));
} }
if(!usb_drv_send(EP_CONTROL,response_data,2)) usb_drv_recv(EP_CONTROL,NULL,0);
usb_core_ack_control(req); usb_drv_send(EP_CONTROL,response_data,2);
break; break;
default: { default: {
bool handled; bool handled;
@ -843,14 +849,6 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
usb_signal_transfer_completion(completion_event); usb_signal_transfer_completion(completion_event);
} }
int usb_core_ack_control(struct usb_ctrlrequest* req)
{
if (req->bRequestType & USB_DIR_IN)
return usb_drv_recv(EP_CONTROL,NULL,0);
else
return usb_drv_send(EP_CONTROL,NULL,0);
}
#ifdef HAVE_USB_POWER #ifdef HAVE_USB_POWER
unsigned short usb_allowed_current() unsigned short usb_allowed_current()
{ {

View file

@ -739,10 +739,10 @@ bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest)
logf("hid: unsup. std. req"); logf("hid: unsup. std. req");
break; break;
} }
if (dest != orig_dest && if (dest != orig_dest)
!usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest))
{ {
usb_core_ack_control(req); usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */
usb_drv_send(EP_CONTROL, orig_dest, dest - orig_dest);
handled = true; handled = true;
} }
break; break;
@ -754,14 +754,14 @@ bool usb_hid_control_request(struct usb_ctrlrequest *req, unsigned char *dest)
{ {
case USB_HID_SET_IDLE: case USB_HID_SET_IDLE:
logf("hid: set idle"); logf("hid: set idle");
usb_core_ack_control(req); usb_drv_send(EP_CONTROL, NULL, 0); /* ack */
handled = true; handled = true;
break; break;
case USB_HID_SET_REPORT: case USB_HID_SET_REPORT:
logf("hid: set report"); logf("hid: set report");
if (!usb_hid_set_report(req)) if (!usb_hid_set_report(req))
{ {
usb_core_ack_control(req); usb_drv_send(EP_CONTROL, NULL, 0); /* ack */
handled = true; handled = true;
} }
break; break;

View file

@ -659,8 +659,8 @@ bool usb_storage_control_request(struct usb_ctrlrequest* req, unsigned char* des
*tb.max_lun --; *tb.max_lun --;
#endif #endif
logf("ums: getmaxlun"); logf("ums: getmaxlun");
usb_drv_send(EP_CONTROL, tb.max_lun, 1);
usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */ usb_drv_recv(EP_CONTROL, NULL, 0); /* ack */
usb_drv_send(EP_CONTROL, tb.max_lun, 1);
handled = true; handled = true;
break; break;
} }