aboutsummaryrefslogtreecommitdiff
path: root/lib/usb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/usb')
-rw-r--r--lib/usb/usb.c3
-rw-r--r--lib/usb/usb_control.c5
-rw-r--r--lib/usb/usb_private.h1
-rw-r--r--lib/usb/usb_standard.c73
4 files changed, 54 insertions, 28 deletions
diff --git a/lib/usb/usb.c b/lib/usb/usb.c
index ecebde2..0799202 100644
--- a/lib/usb/usb.c
+++ b/lib/usb/usb.c
@@ -44,7 +44,7 @@ u8 usbd_control_buffer[128] __attribute__((weak));
usbd_device *usbd_init(const usbd_driver *driver,
const struct usb_device_descriptor *dev,
const struct usb_config_descriptor *conf,
- const char **strings)
+ const char **strings, int num_strings)
{
usbd_device *usbd_dev;
@@ -54,6 +54,7 @@ usbd_device *usbd_init(const usbd_driver *driver,
usbd_dev->desc = dev;
usbd_dev->config = conf;
usbd_dev->strings = strings;
+ usbd_dev->num_strings = num_strings;
usbd_dev->ctrl_buf = usbd_control_buffer;
usbd_dev->ctrl_buf_len = sizeof(usbd_control_buffer);
diff --git a/lib/usb/usb_control.c b/lib/usb/usb_control.c
index 245ab1c..82843df 100644
--- a/lib/usb/usb_control.c
+++ b/lib/usb/usb_control.c
@@ -99,11 +99,12 @@ static int usb_control_request_dispatch(usbd_device *usbd_dev,
&(usbd_dev->control_state.ctrl_buf),
&(usbd_dev->control_state.ctrl_len),
&(usbd_dev->control_state.complete));
- if (result)
+ if (result == USBD_REQ_HANDLED ||
+ result == USBD_REQ_NOTSUPP)
return result;
}
}
-
+
/* Try standard request if not already handled. */
return _usbd_standard_request(usbd_dev, req,
&(usbd_dev->control_state.ctrl_buf),
diff --git a/lib/usb/usb_private.h b/lib/usb/usb_private.h
index 2506ba5..454e8c6 100644
--- a/lib/usb/usb_private.h
+++ b/lib/usb/usb_private.h
@@ -29,6 +29,7 @@ struct _usbd_device {
const struct usb_device_descriptor *desc;
const struct usb_config_descriptor *config;
const char **strings;
+ int num_strings;
u8 *ctrl_buf; /**< Internal buffer used for control transfers */
u16 ctrl_buf_len;
diff --git a/lib/usb/usb_standard.c b/lib/usb/usb_standard.c
index 5a92cd8..e14fee3 100644
--- a/lib/usb/usb_standard.c
+++ b/lib/usb/usb_standard.c
@@ -90,52 +90,75 @@ static u16 build_config_descriptor(usbd_device *usbd_dev,
return total;
}
+static int usb_descriptor_type(u16 wValue)
+{
+ return wValue >> 8;
+}
+
+static int usb_descriptor_index(u16 wValue)
+{
+ return wValue & 0xFF;
+}
+
static int usb_standard_get_descriptor(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len)
{
- int i;
+ int i, array_idx, descr_idx;
struct usb_string_descriptor *sd;
- switch (req->wValue >> 8) {
+ descr_idx = usb_descriptor_index(req->wValue);
+
+ switch (usb_descriptor_type(req->wValue)) {
case USB_DT_DEVICE:
*buf = (u8 *) usbd_dev->desc;
*len = MIN(*len, usbd_dev->desc->bLength);
- return 1;
+ return USBD_REQ_HANDLED;
case USB_DT_CONFIGURATION:
*buf = usbd_dev->ctrl_buf;
- *len = build_config_descriptor(usbd_dev, req->wValue & 0xff,
- *buf, *len);
- return 1;
+ *len = build_config_descriptor(usbd_dev, descr_idx, *buf, *len);
+ return USBD_REQ_HANDLED;
case USB_DT_STRING:
sd = (struct usb_string_descriptor *)usbd_dev->ctrl_buf;
- if (!usbd_dev->strings)
- return 0; /* Device doesn't support strings. */
+ if (descr_idx == 0) {
+ /* Send sane Language ID descriptor... */
+ sd->wData[0] = USB_LANGID_ENGLISH_US;
+ sd->bLength = sizeof(sd->bLength) + sizeof(sd->bDescriptorType)
+ + sizeof(sd->wData[0]);
- /* Check that string index is in range. */
- for (i = 0; i <= (req->wValue & 0xff); i++)
- if (usbd_dev->strings[i] == NULL)
- return 0;
+ *len = MIN(*len, sd->bLength);
+ } else {
+ array_idx = descr_idx - 1;
- sd->bLength = strlen(usbd_dev->strings[req->wValue & 0xff])
- * 2 + 2;
- sd->bDescriptorType = USB_DT_STRING;
+ if (!usbd_dev->strings)
+ return USBD_REQ_NOTSUPP; /* Device doesn't support strings. */
+ /* Check that string index is in range. */
+ if (array_idx >= usbd_dev->num_strings)
+ return USBD_REQ_NOTSUPP;
- *buf = (u8 *)sd;
- *len = MIN(*len, sd->bLength);
+ /* Strings with Language ID differnet from
+ * USB_LANGID_ENGLISH_US are not supported */
+ if (req->wIndex != USB_LANGID_ENGLISH_US)
+ return USBD_REQ_NOTSUPP;
- for (i = 0; i < (*len / 2) - 1; i++)
- sd->wData[i] =
- usbd_dev->strings[req->wValue & 0xff][i];
+ /* Ths string is returned as UTF16, hence the multiplication */
+ sd->bLength = strlen(usbd_dev->strings[array_idx]) * 2 +
+ sizeof(sd->bLength) + sizeof(sd->bDescriptorType);
- /* Send sane Language ID descriptor... */
- if ((req->wValue & 0xff) == 0)
- sd->wData[0] = 0x409;
+ *len = MIN(*len, sd->bLength);
- return 1;
+ for (i = 0; i < (*len / 2) - 1; i++)
+ sd->wData[i] =
+ usbd_dev->strings[array_idx][i];
+ }
+
+ sd->bDescriptorType = USB_DT_STRING;
+ *buf = (u8 *)sd;
+
+ return USBD_REQ_HANDLED;
}
- return 0;
+ return USBD_REQ_NOTSUPP;
}
static int usb_standard_set_address(usbd_device *usbd_dev,