aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/stm32/f1/other/usb_dfu/usbdfu.c2
-rw-r--r--include/libopencm3/stm32/f1/desig.h9
-rw-r--r--include/libopencm3/usb/usbd.h9
-rw-r--r--include/libopencm3/usb/usbstd.h3
-rw-r--r--lib/stm32/f1/desig.c22
-rw-r--r--lib/usb/usb.c4
-rw-r--r--lib/usb/usb_control.c3
-rw-r--r--lib/usb/usb_private.h1
-rw-r--r--lib/usb/usb_standard.c72
9 files changed, 98 insertions, 27 deletions
diff --git a/examples/stm32/f1/other/usb_dfu/usbdfu.c b/examples/stm32/f1/other/usb_dfu/usbdfu.c
index 0211a47..f30783f 100644
--- a/examples/stm32/f1/other/usb_dfu/usbdfu.c
+++ b/examples/stm32/f1/other/usb_dfu/usbdfu.c
@@ -244,6 +244,8 @@ int main(void)
AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
+ rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_OTGFSEN);
+
usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
usbd_set_control_buffer_size(sizeof(usbd_control_buffer));
usbd_register_control_callback(
diff --git a/include/libopencm3/stm32/f1/desig.h b/include/libopencm3/stm32/f1/desig.h
index 74cfb35..6ceb665 100644
--- a/include/libopencm3/stm32/f1/desig.h
+++ b/include/libopencm3/stm32/f1/desig.h
@@ -51,6 +51,15 @@ u16 desig_get_flash_size(void);
*/
void desig_get_unique_id(u32 result[]);
+/**
+ * Read the full 96 bit unique identifier and return it as a
+ * zero-terminated string
+ * @param string memory region to write the result to
+ 8 @param string_len the size of string in bytes
+ */
+void desig_get_unique_id_as_string(char *string,
+ unsigned int string_len);
+
END_DECLS
#endif
diff --git a/include/libopencm3/usb/usbd.h b/include/libopencm3/usb/usbd.h
index e4b3578..8f68555 100644
--- a/include/libopencm3/usb/usbd.h
+++ b/include/libopencm3/usb/usbd.h
@@ -24,6 +24,13 @@
BEGIN_DECLS
+
+enum usbd_request_return_codes {
+ USBD_REQ_NOTSUPP = 0,
+ USBD_REQ_HANDLED = 1,
+ USBD_REQ_NEXT_CALLBACK = 2,
+};
+
typedef struct _usbd_driver usbd_driver;
extern const usbd_driver stm32f103_usb_driver;
extern const usbd_driver stm32f107_usb_driver;
@@ -38,7 +45,7 @@ extern u8 usbd_control_buffer[];
extern int 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);
extern void usbd_set_control_buffer_size(u16 size);
extern void usbd_register_reset_callback(void (*callback)(void));
diff --git a/include/libopencm3/usb/usbstd.h b/include/libopencm3/usb/usbstd.h
index 8610fdb..01fc7e3 100644
--- a/include/libopencm3/usb/usbstd.h
+++ b/include/libopencm3/usb/usbstd.h
@@ -220,4 +220,7 @@ struct usb_iface_assoc_descriptor {
#define USB_DT_INTERFACE_ASSOCIATION_SIZE \
sizeof(struct usb_iface_assoc_descriptor)
+enum usb_language_id {
+ USB_LANGID_ENGLISH_US = 0x409,
+};
#endif
diff --git a/lib/stm32/f1/desig.c b/lib/stm32/f1/desig.c
index 7ae968e..7f213fa 100644
--- a/lib/stm32/f1/desig.c
+++ b/lib/stm32/f1/desig.c
@@ -35,3 +35,25 @@ void desig_get_unique_id(u32 result[])
result[1] = bits63_32;
result[2] = bits31_16 << 16 | bits15_0;
}
+
+void desig_get_unique_id_as_string(char *string,
+ unsigned int string_len)
+{
+ int i, len;
+ u8 device_id[12];
+ static const char chars[] = "0123456789ABCDEF";
+
+ desig_get_unique_id((u32 *)device_id);
+
+ /* Each byte produces two characters */
+ len = (2 * sizeof(device_id) < string_len) ?
+ 2 * sizeof(device_id) : string_len - 1;
+
+ for (i = 0; i < len; i += 2) {
+ string[i] = chars[(device_id[i / 2] >> 0) & 0x0F];
+ string[i + 1] = chars[(device_id[i / 2] >> 4) & 0x0F];
+ }
+
+ string[len] = '\0';
+}
+
diff --git a/lib/usb/usb.c b/lib/usb/usb.c
index 1ebb6ec..d5ec980 100644
--- a/lib/usb/usb.c
+++ b/lib/usb/usb.c
@@ -45,12 +45,14 @@ u8 usbd_control_buffer[128] __attribute__((weak));
*/
int usbd_init(const usbd_driver *driver,
const struct usb_device_descriptor *dev,
- const struct usb_config_descriptor *conf, const char **strings)
+ const struct usb_config_descriptor *conf,
+ const char **strings, int num_strings)
{
_usbd_device.driver = driver;
_usbd_device.desc = dev;
_usbd_device.config = conf;
_usbd_device.strings = strings;
+ _usbd_device.num_strings = num_strings;
_usbd_device.ctrl_buf = usbd_control_buffer;
_usbd_device.ctrl_buf_len = sizeof(usbd_control_buffer);
diff --git a/lib/usb/usb_control.c b/lib/usb/usb_control.c
index 3dd0857..b4ac57e 100644
--- a/lib/usb/usb_control.c
+++ b/lib/usb/usb_control.c
@@ -102,7 +102,8 @@ static int usb_control_request_dispatch(struct usb_setup_data *req)
result = cb[i].cb(req, &control_state.ctrl_buf,
&control_state.ctrl_len,
&control_state.complete);
- if (result)
+ if (result == USBD_REQ_HANDLED ||
+ result == USBD_REQ_NOTSUPP)
return result;
}
}
diff --git a/lib/usb/usb_private.h b/lib/usb/usb_private.h
index a1e5e4c..238f14f 100644
--- a/lib/usb/usb_private.h
+++ b/lib/usb/usb_private.h
@@ -29,6 +29,7 @@ extern 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 2d7c619..08923d8 100644
--- a/lib/usb/usb_standard.c
+++ b/lib/usb/usb_standard.c
@@ -87,50 +87,74 @@ static u16 build_config_descriptor(u8 index, u8 *buf, u16 len)
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(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_device.desc;
*len = MIN(*len, _usbd_device.desc->bLength);
- return 1;
+ return USBD_REQ_HANDLED;
case USB_DT_CONFIGURATION:
*buf = _usbd_device.ctrl_buf;
- *len = build_config_descriptor(req->wValue & 0xff, *buf, *len);
- return 1;
+ *len = build_config_descriptor(descr_idx, *buf, *len);
+ return USBD_REQ_HANDLED;
case USB_DT_STRING:
sd = (struct usb_string_descriptor *)_usbd_device.ctrl_buf;
- if (!_usbd_device.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_device.strings[i] == NULL)
- return 0;
+ *len = MIN(*len, sd->bLength);
+ } else {
+ array_idx = descr_idx - 1;
- sd->bLength = strlen(_usbd_device.strings[req->wValue & 0xff])
- * 2 + 2;
- sd->bDescriptorType = USB_DT_STRING;
+ if (!_usbd_device.strings)
+ return USBD_REQ_NOTSUPP; /* Device doesn't support strings. */
+ /* Check that string index is in range. */
+ if (array_idx >= _usbd_device.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_device.strings[req->wValue & 0xff][i];
+ /* Ths string is returned as UTF16, hence the multiplication */
+ sd->bLength = strlen(_usbd_device.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_device.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(struct usb_setup_data *req, u8 **buf,