this commit is a combination of the following changes, which significantly refactors usb core and class drivers. 1. unify usb buffers of each class driver to reduce iram usage currently, many class drivers allocate their own buffer to receive control out data, which is a waste of iram. share one common buffer for that usage to address the issue. 2. simplify control request handling by implicitly receiving write request data packets change 1 above fixed the data destination. therefore, having the core receive the data allows us to reduce the class driver's work and simplifies the api. 3. enhance usb core's control request handling and unify the legacy driver api in order to implement change 2, both the legacy and new driver apis should be supported. so that, using the designware driver as a reference, the new driver api functionality is move into usb core. this simplifies the usb device drivers by requiring them to implement only the functionalities equivalent to the legacy api. tested with ipodvideo(arc) and erosqnative(designware) Change-Id: I3627daa90278751f599e2108ec150ec3f8f6c524
2 KiB
Handling USB control requests
API overview
A control request goes through from device driver to class drivers, via usb core. Each step is done by those functions:
# from device driver to usb core
void usb_core_setup_received(struct usb_ctrlrequest* req);
# from usb core to class drivers
bool usb_class_driver::control_request(struct usb_ctrlrequest* req);
Also control response goes through the inverse steps, and the following functions are used:
# from class drivers to usb core
void usb_core_control_response(enum usb_control_response response, const void* data, size_t size);
# from usb core to device drivers
int usb_drv_{send,recv}_nonblocking(int endpoint, void *ptr, int length);
Request handling process
The driver submits control requests to the USB core one at a time. Once a request is submitted, it must be completed before the next request can be submitted. This mirrors normal USB operation.
When the USB driver receives a setup packet from the host, it submits it
to the core to begin handling the control transfer. The driver calls
usb_core_setup_received(req), passing the setup packet in req.
If the request was a Non-data transfer, the core or recipient class driver will
call usb_core_control_response(USB_CONTROL_ACK, NULL, 0) for ACK or
usb_core_control_response(USB_CONTROL_STALL, NULL, 0) for NAK.
If the request was a Control read transfer, the core or recipient class driver
will call usb_core_control_response(USB_CONTROL_ACK, data, size) to send data packets,
or usb_core_control_response(false, USB_CONTROL_STALL, 0) for NAK.
If the request was a Control write transfer, the core firstly receive data packets
using usb_drv_recv_nonblocking. Once it's done, the core or recipient class
driver will process it, then usb_core_control_response(USB_CONTROL_ACK, NULL, 0) for ACK
or usb_core_control_response(USB_CONTROL_STALL, NULL, 0) for NAK.