Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/thirdpin/libopencm3.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib/usb
diff options
context:
space:
mode:
authorKuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>2014-04-20 13:19:05 +0400
committerKarl Palsson <karlp@tweak.net.au>2015-09-23 01:28:02 +0300
commit7cd72125779641b97532b49fa89fbfc410bc85df (patch)
treeaf901431cd4a8074d5fee4f91196f397302d9953 /lib/usb
parenteb18cc19cb392a69f8675c42776c644d1003ed89 (diff)
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 <karlp@tweak.net.au>
Diffstat (limited to 'lib/usb')
-rw-r--r--lib/usb/usb_standard.c30
1 files 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);