From 7cd72125779641b97532b49fa89fbfc410bc85df Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Dhaka Date: Sun, 20 Apr 2014 14:49:05 +0530 Subject: [PATCH] usb: Validate and accept set_configuration properly Setting the same configuration again should act as a lightweight reset, not be ignored. This resulted in data toggle bits not being reset and alternet settings not being reset. Further, completely invalid configurations were accepted, when they should have result in a stall. (Section 9.4.7 of USB 2.0 spec) fixes Github issue #302 Tested-by: Karl Palsson --- lib/usb/usb_standard.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/usb/usb_standard.c b/lib/usb/usb_standard.c index 92c89460..0333edea 100644 --- a/lib/usb/usb_standard.c +++ b/lib/usb/usb_standard.c @@ -245,18 +245,38 @@ static int usb_standard_set_configuration(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len) { - int i; + unsigned i; + int found_index = -1; + const struct usb_config_descriptor *cfg; (void)req; (void)buf; (void)len; - /* Is this correct, or should we reset alternate settings. */ - if (req->wValue == usbd_dev->current_config) { - return 1; + if(req->wValue > 0) { + for (i = 0; i < usbd_dev->desc->bNumConfigurations; i++) { + if (req->wValue == usbd_dev->config[i].bConfigurationValue) { + found_index = i; + break; + } + } + if (found_index < 0) { + return USBD_REQ_NOTSUPP; + } } - usbd_dev->current_config = req->wValue; + usbd_dev->current_config = found_index + 1; + + if (usbd_dev->current_config > 0) { + cfg = &usbd_dev->config[usbd_dev->current_config - 1]; + + /* reset all alternate settings configuration */ + for (i = 0; i < cfg->bNumInterfaces; i++) { + if (cfg->interface[i].cur_altsetting) { + *cfg->interface[i].cur_altsetting = 0; + } + } + } /* Reset all endpoints. */ usbd_dev->driver->ep_reset(usbd_dev);