|
|
|
@ -48,6 +48,9 @@ int usbd_register_set_config_callback(usbd_device *usbd_dev,
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < MAX_USER_SET_CONFIG_CALLBACK; i++) {
|
|
|
|
|
if (usbd_dev->user_callback_set_config[i]) {
|
|
|
|
|
if (usbd_dev->user_callback_set_config[i] == callback) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -131,8 +134,9 @@ static uint16_t build_config_descriptor(usbd_device *usbd_dev,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Fill in wTotalLength. */
|
|
|
|
|
*(uint16_t *)(tmpbuf + 2) = totallen;
|
|
|
|
|
/* Fill in wTotalLength.
|
|
|
|
|
* Note that tmpbuf is sometimes not halfword-aligned */
|
|
|
|
|
memcpy((tmpbuf + 2), &totallen, sizeof(uint16_t));
|
|
|
|
|
|
|
|
|
|
return total;
|
|
|
|
|
}
|
|
|
|
@ -147,9 +151,10 @@ static int usb_descriptor_index(uint16_t wValue)
|
|
|
|
|
return wValue & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_get_descriptor(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_get_descriptor(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
wait_random();
|
|
|
|
@ -221,9 +226,10 @@ static int usb_standard_get_descriptor(usbd_device *usbd_dev,
|
|
|
|
|
return USBD_REQ_NOTSUPP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_set_address(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req, uint8_t **buf,
|
|
|
|
|
uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_set_address(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req, uint8_t **buf,
|
|
|
|
|
uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
(void)req;
|
|
|
|
|
(void)buf;
|
|
|
|
@ -231,7 +237,7 @@ static int usb_standard_set_address(usbd_device *usbd_dev,
|
|
|
|
|
|
|
|
|
|
/* The actual address is only latched at the STATUS IN stage. */
|
|
|
|
|
if ((req->bmRequestType != 0) || (req->wValue >= 128)) {
|
|
|
|
|
return 0;
|
|
|
|
|
return USBD_REQ_NOTSUPP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usbd_dev->current_address = req->wValue;
|
|
|
|
@ -244,12 +250,13 @@ static int usb_standard_set_address(usbd_device *usbd_dev,
|
|
|
|
|
usbd_dev->driver->set_address(usbd_dev, req->wValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_set_configuration(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_set_configuration(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
unsigned i;
|
|
|
|
|
int found_index = -1;
|
|
|
|
@ -305,12 +312,13 @@ static int usb_standard_set_configuration(usbd_device *usbd_dev,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_get_configuration(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_get_configuration(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
(void)req;
|
|
|
|
|
|
|
|
|
@ -325,12 +333,13 @@ static int usb_standard_get_configuration(usbd_device *usbd_dev,
|
|
|
|
|
(*buf)[0] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_set_interface(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_set_interface(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
const struct usb_config_descriptor *cfx =
|
|
|
|
|
&usbd_dev->config[usbd_dev->current_config - 1];
|
|
|
|
@ -365,9 +374,10 @@ static int usb_standard_set_interface(usbd_device *usbd_dev,
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_get_interface(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_get_interface(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *cur_altsetting;
|
|
|
|
|
const struct usb_config_descriptor *cfx =
|
|
|
|
@ -384,9 +394,10 @@ static int usb_standard_get_interface(usbd_device *usbd_dev,
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_device_get_status(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_device_get_status(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
(void)usbd_dev;
|
|
|
|
|
(void)req;
|
|
|
|
@ -399,12 +410,13 @@ static int usb_standard_device_get_status(usbd_device *usbd_dev,
|
|
|
|
|
(*buf)[0] = 0;
|
|
|
|
|
(*buf)[1] = 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_interface_get_status(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_interface_get_status(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
(void)usbd_dev;
|
|
|
|
|
(void)req;
|
|
|
|
@ -416,12 +428,13 @@ static int usb_standard_interface_get_status(usbd_device *usbd_dev,
|
|
|
|
|
(*buf)[0] = 0;
|
|
|
|
|
(*buf)[1] = 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_endpoint_get_status(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_endpoint_get_status(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
(void)req;
|
|
|
|
|
|
|
|
|
@ -431,42 +444,46 @@ static int usb_standard_endpoint_get_status(usbd_device *usbd_dev,
|
|
|
|
|
(*buf)[0] = usbd_ep_stall_get(usbd_dev, req->wIndex) ? 1 : 0;
|
|
|
|
|
(*buf)[1] = 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_endpoint_stall(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_endpoint_stall(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
(void)buf;
|
|
|
|
|
(void)len;
|
|
|
|
|
|
|
|
|
|
usbd_ep_stall_set(usbd_dev, req->wIndex, 1);
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int usb_standard_endpoint_unstall(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
static enum usbd_request_return_codes
|
|
|
|
|
usb_standard_endpoint_unstall(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
(void)buf;
|
|
|
|
|
(void)len;
|
|
|
|
|
|
|
|
|
|
usbd_ep_stall_set(usbd_dev, req->wIndex, 0);
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
return USBD_REQ_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Do not appear to belong to the API, so are omitted from docs */
|
|
|
|
|
/**@}*/
|
|
|
|
|
|
|
|
|
|
int _usbd_standard_request_device(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req, uint8_t **buf,
|
|
|
|
|
uint16_t *len)
|
|
|
|
|
enum usbd_request_return_codes
|
|
|
|
|
_usbd_standard_request_device(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req, uint8_t **buf,
|
|
|
|
|
uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
int (*command)(usbd_device *usbd_dev, struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len) = NULL;
|
|
|
|
|
enum usbd_request_return_codes (*command)(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len) = NULL;
|
|
|
|
|
|
|
|
|
|
switch (req->bRequest) {
|
|
|
|
|
case USB_REQ_CLEAR_FEATURE:
|
|
|
|
@ -509,18 +526,20 @@ int _usbd_standard_request_device(usbd_device *usbd_dev,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!command) {
|
|
|
|
|
return 0;
|
|
|
|
|
return USBD_REQ_NOTSUPP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return command(usbd_dev, req, buf, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int _usbd_standard_request_interface(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req, uint8_t **buf,
|
|
|
|
|
uint16_t *len)
|
|
|
|
|
enum usbd_request_return_codes
|
|
|
|
|
_usbd_standard_request_interface(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req, uint8_t **buf,
|
|
|
|
|
uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
int (*command)(usbd_device *usbd_dev, struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len) = NULL;
|
|
|
|
|
enum usbd_request_return_codes (*command)(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len) = NULL;
|
|
|
|
|
|
|
|
|
|
switch (req->bRequest) {
|
|
|
|
|
case USB_REQ_CLEAR_FEATURE:
|
|
|
|
@ -539,18 +558,20 @@ int _usbd_standard_request_interface(usbd_device *usbd_dev,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!command) {
|
|
|
|
|
return 0;
|
|
|
|
|
return USBD_REQ_NOTSUPP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return command(usbd_dev, req, buf, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int _usbd_standard_request_endpoint(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req, uint8_t **buf,
|
|
|
|
|
uint16_t *len)
|
|
|
|
|
enum usbd_request_return_codes
|
|
|
|
|
_usbd_standard_request_endpoint(usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req, uint8_t **buf,
|
|
|
|
|
uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
int (*command) (usbd_device *usbd_dev, struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len) = NULL;
|
|
|
|
|
enum usbd_request_return_codes (*command) (usbd_device *usbd_dev,
|
|
|
|
|
struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len) = NULL;
|
|
|
|
|
|
|
|
|
|
switch (req->bRequest) {
|
|
|
|
|
case USB_REQ_CLEAR_FEATURE:
|
|
|
|
@ -576,18 +597,19 @@ int _usbd_standard_request_endpoint(usbd_device *usbd_dev,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!command) {
|
|
|
|
|
return 0;
|
|
|
|
|
return USBD_REQ_NOTSUPP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return command(usbd_dev, req, buf, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int _usbd_standard_request(usbd_device *usbd_dev, struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
enum usbd_request_return_codes
|
|
|
|
|
_usbd_standard_request(usbd_device *usbd_dev, struct usb_setup_data *req,
|
|
|
|
|
uint8_t **buf, uint16_t *len)
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: Have class/vendor requests as well. */
|
|
|
|
|
if ((req->bmRequestType & USB_REQ_TYPE_TYPE) != USB_REQ_TYPE_STANDARD) {
|
|
|
|
|
return 0;
|
|
|
|
|
return USBD_REQ_NOTSUPP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (req->bmRequestType & USB_REQ_TYPE_RECIPIENT) {
|
|
|
|
@ -599,7 +621,7 @@ int _usbd_standard_request(usbd_device *usbd_dev, struct usb_setup_data *req,
|
|
|
|
|
case USB_REQ_TYPE_ENDPOINT:
|
|
|
|
|
return _usbd_standard_request_endpoint(usbd_dev, req, buf, len);
|
|
|
|
|
default:
|
|
|
|
|
return 0;
|
|
|
|
|
return USBD_REQ_NOTSUPP;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|