usbus: Rework handling of set control requests
This commit is contained in:
parent
00131b3ba3
commit
5b477918b6
@ -64,6 +64,11 @@ typedef struct {
|
||||
*/
|
||||
usbus_control_slicer_t slicer;
|
||||
|
||||
/**
|
||||
* @brief Received bytes for set requests
|
||||
*/
|
||||
size_t received_len;
|
||||
|
||||
/**
|
||||
* @brief EP0 OUT endpoint
|
||||
*/
|
||||
@ -123,6 +128,18 @@ void usbus_control_slicer_ready(usbus_t *usbus);
|
||||
*/
|
||||
int usbus_control_slicer_nextslice(usbus_t *usbus);
|
||||
|
||||
/**
|
||||
* @brief Retrieve the data from the OUT pipe of the control endpoint
|
||||
*
|
||||
* @pre usbus->state == USBUS_CONTROL_REQUEST_STATE_OUTDATA
|
||||
*
|
||||
* @param[in] usbus USBUS context
|
||||
* @param[out] len Length of the data part
|
||||
*
|
||||
* @return pointer to the data buffer
|
||||
*/
|
||||
uint8_t *usbus_control_get_out_data(usbus_t *usbus, size_t *len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -192,7 +192,6 @@ static int _req_descriptor(usbus_t *usbus, usb_setup_t *pkt)
|
||||
|
||||
static int _recv_dev_setup(usbus_t *usbus, usb_setup_t *pkt)
|
||||
{
|
||||
usbus_control_handler_t *ep0 = (usbus_control_handler_t *)usbus->control;
|
||||
int res = -1;
|
||||
|
||||
if (usb_setup_is_read(pkt)) {
|
||||
@ -213,21 +212,19 @@ static int _recv_dev_setup(usbus_t *usbus, usb_setup_t *pkt)
|
||||
case USB_SETUP_REQ_SET_ADDRESS:
|
||||
DEBUG("usbus_control: Setting address\n");
|
||||
usbus->addr = (uint8_t)pkt->value;
|
||||
res = 0;
|
||||
res = 1;
|
||||
break;
|
||||
case USB_SETUP_REQ_SET_CONFIGURATION:
|
||||
/* Nothing configuration dependent to do here, only one
|
||||
* configuration supported */
|
||||
usbus->state = USBUS_STATE_CONFIGURED;
|
||||
_activate_endpoints(usbus);
|
||||
res = 0;
|
||||
res = 1;
|
||||
break;
|
||||
default:
|
||||
DEBUG("usbus: Unknown write request %u\n", pkt->request);
|
||||
break;
|
||||
}
|
||||
/* Signal zero-length packet */
|
||||
usbdev_ep_ready(ep0->in, 0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -257,19 +254,7 @@ static void _recv_setup(usbus_t *usbus, usbus_control_handler_t *handler)
|
||||
|
||||
DEBUG("usbus_control: Received setup %x %x @ %d\n", pkt->type,
|
||||
pkt->request, pkt->length);
|
||||
if (usb_setup_is_read(pkt)) {
|
||||
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_INDATA;
|
||||
}
|
||||
else {
|
||||
if (pkt->length) {
|
||||
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_OUTDATA;
|
||||
usbdev_ep_ready(handler->out, 0);
|
||||
}
|
||||
else {
|
||||
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_INACK;
|
||||
usbdev_ep_ready(handler->in, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t destination = pkt->type & USB_SETUP_REQUEST_RECIPIENT_MASK;
|
||||
int res = 0;
|
||||
switch (destination) {
|
||||
@ -290,7 +275,22 @@ static void _recv_setup(usbus_t *usbus, usbus_control_handler_t *handler)
|
||||
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY;
|
||||
}
|
||||
else if (res) {
|
||||
usbus_control_slicer_ready(usbus);
|
||||
if (usb_setup_is_read(pkt)) {
|
||||
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_INDATA;
|
||||
usbus_control_slicer_ready(usbus);
|
||||
}
|
||||
else {
|
||||
/* Signal ready for new data in case there is more */
|
||||
if (handler->received_len < pkt->length) {
|
||||
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_OUTDATA;
|
||||
usbdev_ep_ready(handler->out, 1);
|
||||
}
|
||||
else {
|
||||
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_INACK;
|
||||
usbdev_ep_ready(handler->in, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,6 +307,19 @@ static void _usbus_config_ep0(usbus_control_handler_t *ep0_handler)
|
||||
usbdev_ep_ready(ep0_handler->out, 0);
|
||||
}
|
||||
|
||||
uint8_t *usbus_control_get_out_data(usbus_t *usbus, size_t *len)
|
||||
{
|
||||
usbus_control_handler_t *handler = (usbus_control_handler_t*)usbus->control;
|
||||
|
||||
assert(len);
|
||||
assert(handler->control_request_state == USBUS_CONTROL_REQUEST_STATE_OUTDATA);
|
||||
|
||||
usbdev_ep_t *ep_out = handler->out;
|
||||
usbdev_ep_get(ep_out, USBOPT_EP_AVAILABLE,
|
||||
len, sizeof(size_t));
|
||||
return ep_out->buf;
|
||||
}
|
||||
|
||||
static void _init(usbus_t *usbus, usbus_handler_t *handler)
|
||||
{
|
||||
DEBUG("usbus_control: Initializing EP0\n");
|
||||
@ -334,12 +347,15 @@ static int _handle_tr_complete(usbus_t *usbus,
|
||||
usbus->state = USBUS_STATE_ADDR;
|
||||
}
|
||||
ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY;
|
||||
/* Ready for new control request */
|
||||
usbdev_ep_ready(ep0_handler->out, 0);
|
||||
}
|
||||
break;
|
||||
case USBUS_CONTROL_REQUEST_STATE_OUTACK:
|
||||
if (ep->dir == USB_EP_DIR_OUT) {
|
||||
memset(&ep0_handler->slicer, 0, sizeof(usbus_control_slicer_t));
|
||||
ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY;
|
||||
/* Ready for new control request */
|
||||
usbdev_ep_ready(ep0_handler->out, 0);
|
||||
}
|
||||
break;
|
||||
case USBUS_CONTROL_REQUEST_STATE_INDATA:
|
||||
@ -357,18 +373,11 @@ static int _handle_tr_complete(usbus_t *usbus,
|
||||
break;
|
||||
case USBUS_CONTROL_REQUEST_STATE_OUTDATA:
|
||||
if (ep->dir == USB_EP_DIR_OUT) {
|
||||
/* Ready in ZLP */
|
||||
ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_INACK;
|
||||
size_t len = 0;
|
||||
usbdev_ep_get(ep, USBOPT_EP_AVAILABLE, &len, sizeof(size_t));
|
||||
DEBUG("Expected len: %d, received: %d\n",
|
||||
ep0_handler->setup.length, len);
|
||||
if (ep0_handler->setup.length == len) {
|
||||
DEBUG("DATA complete\n");
|
||||
usbdev_ep_ready(ep0_handler->in, 0);
|
||||
}
|
||||
/* Flush OUT buffer */
|
||||
usbdev_ep_ready(ep0_handler->out, 0);
|
||||
usbdev_ep_get(ep0_handler->out, USBOPT_EP_AVAILABLE,
|
||||
&len, sizeof(size_t));
|
||||
ep0_handler->received_len += len;
|
||||
_recv_setup(usbus, ep0_handler);
|
||||
}
|
||||
else {
|
||||
DEBUG("usbus_control: Invalid state OUTDATA with IN request\n");
|
||||
@ -379,6 +388,7 @@ static int _handle_tr_complete(usbus_t *usbus,
|
||||
memset(&ep0_handler->slicer, 0, sizeof(usbus_control_slicer_t));
|
||||
memcpy(&ep0_handler->setup, ep0_handler->out->buf,
|
||||
sizeof(usb_setup_t));
|
||||
ep0_handler->received_len = 0;
|
||||
ep0_handler->slicer.reqlen = ep0_handler->setup.length;
|
||||
_recv_setup(usbus, ep0_handler);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user