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;
|
usbus_control_slicer_t slicer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Received bytes for set requests
|
||||||
|
*/
|
||||||
|
size_t received_len;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief EP0 OUT endpoint
|
* @brief EP0 OUT endpoint
|
||||||
*/
|
*/
|
||||||
@ -123,6 +128,18 @@ void usbus_control_slicer_ready(usbus_t *usbus);
|
|||||||
*/
|
*/
|
||||||
int usbus_control_slicer_nextslice(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
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;
|
int res = -1;
|
||||||
|
|
||||||
if (usb_setup_is_read(pkt)) {
|
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:
|
case USB_SETUP_REQ_SET_ADDRESS:
|
||||||
DEBUG("usbus_control: Setting address\n");
|
DEBUG("usbus_control: Setting address\n");
|
||||||
usbus->addr = (uint8_t)pkt->value;
|
usbus->addr = (uint8_t)pkt->value;
|
||||||
res = 0;
|
res = 1;
|
||||||
break;
|
break;
|
||||||
case USB_SETUP_REQ_SET_CONFIGURATION:
|
case USB_SETUP_REQ_SET_CONFIGURATION:
|
||||||
/* Nothing configuration dependent to do here, only one
|
/* Nothing configuration dependent to do here, only one
|
||||||
* configuration supported */
|
* configuration supported */
|
||||||
usbus->state = USBUS_STATE_CONFIGURED;
|
usbus->state = USBUS_STATE_CONFIGURED;
|
||||||
_activate_endpoints(usbus);
|
_activate_endpoints(usbus);
|
||||||
res = 0;
|
res = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG("usbus: Unknown write request %u\n", pkt->request);
|
DEBUG("usbus: Unknown write request %u\n", pkt->request);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Signal zero-length packet */
|
|
||||||
usbdev_ep_ready(ep0->in, 0);
|
|
||||||
}
|
}
|
||||||
return res;
|
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,
|
DEBUG("usbus_control: Received setup %x %x @ %d\n", pkt->type,
|
||||||
pkt->request, pkt->length);
|
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;
|
uint8_t destination = pkt->type & USB_SETUP_REQUEST_RECIPIENT_MASK;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
switch (destination) {
|
switch (destination) {
|
||||||
@ -290,8 +275,23 @@ static void _recv_setup(usbus_t *usbus, usbus_control_handler_t *handler)
|
|||||||
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY;
|
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY;
|
||||||
}
|
}
|
||||||
else if (res) {
|
else if (res) {
|
||||||
|
if (usb_setup_is_read(pkt)) {
|
||||||
|
handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_INDATA;
|
||||||
usbus_control_slicer_ready(usbus);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _usbus_config_ep0(usbus_control_handler_t *ep0_handler)
|
static void _usbus_config_ep0(usbus_control_handler_t *ep0_handler)
|
||||||
@ -307,6 +307,19 @@ static void _usbus_config_ep0(usbus_control_handler_t *ep0_handler)
|
|||||||
usbdev_ep_ready(ep0_handler->out, 0);
|
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)
|
static void _init(usbus_t *usbus, usbus_handler_t *handler)
|
||||||
{
|
{
|
||||||
DEBUG("usbus_control: Initializing EP0\n");
|
DEBUG("usbus_control: Initializing EP0\n");
|
||||||
@ -334,12 +347,15 @@ static int _handle_tr_complete(usbus_t *usbus,
|
|||||||
usbus->state = USBUS_STATE_ADDR;
|
usbus->state = USBUS_STATE_ADDR;
|
||||||
}
|
}
|
||||||
ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY;
|
ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY;
|
||||||
|
/* Ready for new control request */
|
||||||
|
usbdev_ep_ready(ep0_handler->out, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USBUS_CONTROL_REQUEST_STATE_OUTACK:
|
case USBUS_CONTROL_REQUEST_STATE_OUTACK:
|
||||||
if (ep->dir == USB_EP_DIR_OUT) {
|
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;
|
ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_READY;
|
||||||
|
/* Ready for new control request */
|
||||||
|
usbdev_ep_ready(ep0_handler->out, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USBUS_CONTROL_REQUEST_STATE_INDATA:
|
case USBUS_CONTROL_REQUEST_STATE_INDATA:
|
||||||
@ -357,18 +373,11 @@ static int _handle_tr_complete(usbus_t *usbus,
|
|||||||
break;
|
break;
|
||||||
case USBUS_CONTROL_REQUEST_STATE_OUTDATA:
|
case USBUS_CONTROL_REQUEST_STATE_OUTDATA:
|
||||||
if (ep->dir == USB_EP_DIR_OUT) {
|
if (ep->dir == USB_EP_DIR_OUT) {
|
||||||
/* Ready in ZLP */
|
|
||||||
ep0_handler->control_request_state = USBUS_CONTROL_REQUEST_STATE_INACK;
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
usbdev_ep_get(ep, USBOPT_EP_AVAILABLE, &len, sizeof(size_t));
|
usbdev_ep_get(ep0_handler->out, USBOPT_EP_AVAILABLE,
|
||||||
DEBUG("Expected len: %d, received: %d\n",
|
&len, sizeof(size_t));
|
||||||
ep0_handler->setup.length, len);
|
ep0_handler->received_len += len;
|
||||||
if (ep0_handler->setup.length == len) {
|
_recv_setup(usbus, ep0_handler);
|
||||||
DEBUG("DATA complete\n");
|
|
||||||
usbdev_ep_ready(ep0_handler->in, 0);
|
|
||||||
}
|
|
||||||
/* Flush OUT buffer */
|
|
||||||
usbdev_ep_ready(ep0_handler->out, 0);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DEBUG("usbus_control: Invalid state OUTDATA with IN request\n");
|
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));
|
memset(&ep0_handler->slicer, 0, sizeof(usbus_control_slicer_t));
|
||||||
memcpy(&ep0_handler->setup, ep0_handler->out->buf,
|
memcpy(&ep0_handler->setup, ep0_handler->out->buf,
|
||||||
sizeof(usb_setup_t));
|
sizeof(usb_setup_t));
|
||||||
|
ep0_handler->received_len = 0;
|
||||||
ep0_handler->slicer.reqlen = ep0_handler->setup.length;
|
ep0_handler->slicer.reqlen = ep0_handler->setup.length;
|
||||||
_recv_setup(usbus, ep0_handler);
|
_recv_setup(usbus, ep0_handler);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user