mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
usbus: Implement GET STATUS and SET/CLEAR FEATURE requests
This extends support for the GET STATUS requests to support endpoints and interfaces as recipient. It also adds the SET and CLEAR FEATURE requests for the endpoints with support to set and clear the halt condition on an endpoint.
This commit is contained in:
parent
13b4f8de2c
commit
7b2db7bf2b
@ -58,6 +58,15 @@ extern "C" {
|
||||
#define USB_TYPE_DESCRIPTOR_INTERFACE_ASSOC 0x0b /**< Interface association */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name USB standard feature selectors
|
||||
* @{
|
||||
*/
|
||||
#define USB_FEATURE_ENDPOINT_HALT 0x00 /**< Endpoint halt */
|
||||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 0x01 /**< Device remote wakeup */
|
||||
#define USB_FEATURE_TEST_MODE 0x02 /**< Test mode feature */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name USB configuration attributes
|
||||
* @anchor USB_CONF_ATTR
|
||||
|
@ -105,13 +105,39 @@ static usbus_string_t *_get_descriptor(usbus_t *usbus, uint16_t idx)
|
||||
|
||||
static int _req_status(usbus_t *usbus)
|
||||
{
|
||||
uint8_t status[2];
|
||||
|
||||
memset(status, 0, sizeof(status));
|
||||
usbus_control_slicer_put_bytes(usbus, status, sizeof(status));
|
||||
/* Signal self powered */
|
||||
uint16_t status = (CONFIG_USB_SELF_POWERED) ? 1 : 0;
|
||||
usbus_control_slicer_put_bytes(usbus, (uint8_t*)&status, sizeof(status));
|
||||
return sizeof(status);
|
||||
}
|
||||
|
||||
static int _req_iface_status(usbus_t *usbus)
|
||||
{
|
||||
uint16_t status = 0; /* always zero */
|
||||
usbus_control_slicer_put_bytes(usbus, (uint8_t*)&status, sizeof(status));
|
||||
return sizeof(status);
|
||||
}
|
||||
|
||||
static int _req_endpoint_status(usbus_t *usbus, usbus_endpoint_t *ep)
|
||||
{
|
||||
uint16_t status = ep->halted ? 1 : 0;
|
||||
usbus_control_slicer_put_bytes(usbus, (uint8_t*)&status, sizeof(status));
|
||||
return sizeof(status);
|
||||
}
|
||||
|
||||
static int _req_endpoint_feature(usbus_endpoint_t *ep, uint16_t feature, bool enable)
|
||||
{
|
||||
switch (feature) {
|
||||
case USB_FEATURE_ENDPOINT_HALT:
|
||||
enable ? usbus_endpoint_halt(ep) : usbus_endpoint_clear_halt(ep);
|
||||
break;
|
||||
default:
|
||||
DEBUG("usbus: unknown endpoint feature request: %u\n", feature);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _req_str(usbus_t *usbus, uint16_t idx)
|
||||
{
|
||||
/* Return an error condition by default */
|
||||
@ -238,6 +264,11 @@ static int _recv_interface_setup(usbus_t *usbus, usb_setup_t *pkt)
|
||||
(usbus_control_handler_t *)usbus->control;
|
||||
uint16_t destination = pkt->index & 0x0f;
|
||||
|
||||
/* Globally handle the iface get status request */
|
||||
if (pkt->request == USB_SETUP_REQ_GET_STATUS) {
|
||||
return _req_iface_status(usbus);
|
||||
}
|
||||
|
||||
/* Find interface handler */
|
||||
for (usbus_interface_t *iface = usbus->iface; iface; iface = iface->next) {
|
||||
if (destination == iface->idx &&
|
||||
@ -251,6 +282,26 @@ static int _recv_interface_setup(usbus_t *usbus, usb_setup_t *pkt)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _recv_endpoint_setup(usbus_t *usbus, usb_setup_t *pkt)
|
||||
{
|
||||
uint8_t destination = pkt->index & 0x0f;
|
||||
bool in = pkt->index & (1 << 7); /* Bit seven is 1 for IN, 0 for OUT */
|
||||
usbus_endpoint_t *ep = in ? &usbus->ep_in[destination] :
|
||||
&usbus->ep_out[destination];
|
||||
|
||||
switch (pkt->request) {
|
||||
case USB_SETUP_REQ_GET_STATUS:
|
||||
return _req_endpoint_status(usbus, ep);
|
||||
case USB_SETUP_REQ_SET_FEATURE:
|
||||
return _req_endpoint_feature(ep, pkt->value, true);
|
||||
case USB_SETUP_REQ_CLEAR_FEATURE:
|
||||
return _req_endpoint_feature(ep, pkt->value, false);
|
||||
default:
|
||||
DEBUG("usbus: Unknown endpoint request %u\n", pkt->request);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void _recv_setup(usbus_t *usbus, usbus_control_handler_t *handler)
|
||||
{
|
||||
usb_setup_t *pkt = &handler->setup;
|
||||
@ -272,6 +323,9 @@ static void _recv_setup(usbus_t *usbus, usbus_control_handler_t *handler)
|
||||
case USB_SETUP_REQUEST_RECIPIENT_INTERFACE:
|
||||
res = _recv_interface_setup(usbus, pkt);
|
||||
break;
|
||||
case USB_SETUP_REQUEST_RECIPIENT_ENDPOINT:
|
||||
res = _recv_endpoint_setup(usbus, pkt);
|
||||
break;
|
||||
default:
|
||||
DEBUG("usbus_control: Unhandled setup request\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user