Browse Source

Merge pull request #22 fixing usb and f4 alignment issues

Merge remote-tracking branch 'jdk/master'

Conflicts:
	lib/stm32/f1/Makefile
	lib/stm32/f4/Makefile
pull/57/merge
Piotr Esden-Tempski 12 years ago
parent
commit
6b2ca89f48
  1. 28
      examples/stm32/f1/lisa-m-1/usb_cdcacm/cdcacm.c
  2. 18
      examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c
  3. 29
      examples/stm32/f1/lisa-m-1/usb_hid/usbhid.c
  4. 28
      examples/stm32/f1/other/usb_cdcacm/cdcacm.c
  5. 18
      examples/stm32/f1/other/usb_dfu/usbdfu.c
  6. 30
      examples/stm32/f1/other/usb_hid/usbhid.c
  7. 30
      examples/stm32/f1/stm32-h103/usb_cdcacm/cdcacm.c
  8. 22
      examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c
  9. 32
      examples/stm32/f1/stm32-h103/usb_hid/usbhid.c
  10. 22
      examples/stm32/f1/stm32-h103/usb_iap/usbiap.c
  11. 12
      examples/stm32/f1/stm32-h107/usb_simple/usb_simple.c
  12. 30
      examples/stm32/f4/stm32f4-discovery/usb_cdcacm/cdcacm.c
  13. 15
      include/libopencm3/stm32/otg_fs.h
  14. 396
      include/libopencm3/stm32/otg_hs.h
  15. 58
      include/libopencm3/usb/usbd.h
  16. 3
      include/libopencm3/usb/usbstd.h
  17. 3
      lib/stm32/f1/Makefile
  18. 2
      lib/stm32/f2/gpio.c
  19. 3
      lib/stm32/f4/Makefile
  20. 2
      lib/stm32/f4/gpio.c
  21. 103
      lib/usb/usb.c
  22. 194
      lib/usb/usb_control.c
  23. 99
      lib/usb/usb_f103.c
  24. 338
      lib/usb/usb_f107.c
  25. 91
      lib/usb/usb_f207.c
  26. 318
      lib/usb/usb_fx07_common.c
  27. 38
      lib/usb/usb_fx07_common.h
  28. 81
      lib/usb/usb_private.h
  29. 127
      lib/usb/usb_standard.c

28
examples/stm32/f1/lisa-m-1/usb_cdcacm/cdcacm.c

@ -164,11 +164,12 @@ static const char *usb_strings[] = {
"DEMO", "DEMO",
}; };
static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf, static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)complete; (void)complete;
(void)buf; (void)buf;
(void)usbd_dev;
switch (req->bRequest) { switch (req->bRequest) {
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
@ -200,15 +201,15 @@ static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf,
return 0; return 0;
} }
static void cdcacm_data_rx_cb(u8 ep) static void cdcacm_data_rx_cb(usbd_device *usbd_dev, u8 ep)
{ {
(void)ep; (void)ep;
char buf[64]; char buf[64];
int len = usbd_ep_read_packet(0x01, buf, 64); int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
if (len) { if (len) {
while (usbd_ep_write_packet(0x82, buf, len) == 0) while (usbd_ep_write_packet(usbd_dev, 0x82, buf, len) == 0)
; ;
buf[len] = 0; buf[len] = 0;
} }
@ -216,15 +217,16 @@ static void cdcacm_data_rx_cb(u8 ep)
gpio_toggle(GPIOC, GPIO5); gpio_toggle(GPIOC, GPIO5);
} }
static void cdcacm_set_config(u16 wValue) static void cdcacm_set_config(usbd_device *usbd_dev, u16 wValue)
{ {
(void)wValue; (void)wValue;
usbd_ep_setup(0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
usbd_ep_setup(0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
usbd_ep_setup(0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
cdcacm_control_request); cdcacm_control_request);
@ -234,6 +236,8 @@ int main(void)
{ {
int i; int i;
usbd_device *usbd_dev;
rcc_clock_setup_in_hsi_out_48mhz(); rcc_clock_setup_in_hsi_out_48mhz();
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
@ -246,13 +250,13 @@ int main(void)
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO5); GPIO_CNF_OUTPUT_PUSHPULL, GPIO5);
usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
usbd_register_set_config_callback(cdcacm_set_config); usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
for (i = 0; i < 0x800000; i++) for (i = 0; i < 0x800000; i++)
__asm__("nop"); __asm__("nop");
gpio_clear(GPIOC, GPIO2); gpio_clear(GPIOC, GPIO2);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

18
examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c

@ -130,10 +130,11 @@ static u8 usbdfu_getstatus(u32 *bwPollTimeout)
} }
} }
static void usbdfu_getstatus_complete(struct usb_setup_data *req) static void usbdfu_getstatus_complete(usbd_device *usbd_dev, struct usb_setup_data *req)
{ {
int i; int i;
(void)req; (void)req;
(void)usbd_dev;
switch (usbdfu_state) { switch (usbdfu_state) {
case STATE_DFU_DNBUSY: case STATE_DFU_DNBUSY:
@ -166,9 +167,11 @@ static void usbdfu_getstatus_complete(struct usb_setup_data *req)
} }
} }
static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf, static int usbdfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)usbd_dev;
if ((req->bmRequestType & 0x7F) != 0x21) if ((req->bmRequestType & 0x7F) != 0x21)
return 0; /* Only accept class request. */ return 0; /* Only accept class request. */
@ -221,6 +224,8 @@ static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf,
int main(void) int main(void)
{ {
usbd_device *usbd_dev;
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
if (!gpio_get(GPIOA, GPIO10)) { if (!gpio_get(GPIOA, GPIO10)) {
@ -245,9 +250,10 @@ int main(void)
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO2); GPIO_CNF_OUTPUT_PUSHPULL, GPIO2);
usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
usbd_set_control_buffer_size(sizeof(usbd_control_buffer)); usbd_set_control_buffer_size(usbd_dev, sizeof(usbd_control_buffer));
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
usbdfu_control_request); usbdfu_control_request);
@ -255,5 +261,5 @@ int main(void)
gpio_clear(GPIOC, GPIO2); gpio_clear(GPIOC, GPIO2);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

29
examples/stm32/f1/lisa-m-1/usb_hid/usbhid.c

@ -36,6 +36,8 @@
#include <libopencm3/usb/dfu.h> #include <libopencm3/usb/dfu.h>
#endif #endif
static usbd_device *usbd_dev;
const struct usb_device_descriptor dev = { const struct usb_device_descriptor dev = {
.bLength = USB_DT_DEVICE_SIZE, .bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE, .bDescriptorType = USB_DT_DEVICE,
@ -173,10 +175,11 @@ static const char *usb_strings[] = {
"DEMO", "DEMO",
}; };
static int hid_control_request(struct usb_setup_data *req, u8 **buf, u16 *len, static int hid_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf, u16 *len,
void (**complete)(struct usb_setup_data *req)) void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)complete; (void)complete;
(void)usbd_dev;
if((req->bmRequestType != 0x81) || if((req->bmRequestType != 0x81) ||
(req->bRequest != USB_REQ_GET_DESCRIPTOR) || (req->bRequest != USB_REQ_GET_DESCRIPTOR) ||
@ -191,9 +194,10 @@ static int hid_control_request(struct usb_setup_data *req, u8 **buf, u16 *len,
} }
#ifdef INCLUDE_DFU_INTERFACE #ifdef INCLUDE_DFU_INTERFACE
static void dfu_detach_complete(struct usb_setup_data *req) static void dfu_detach_complete(usbd_device *usbd_dev, struct usb_setup_data *req)
{ {
(void)req; (void)req;
(void)usbd_dev;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
@ -202,11 +206,12 @@ static void dfu_detach_complete(struct usb_setup_data *req)
scb_reset_core(); scb_reset_core();
} }
static int dfu_control_request(struct usb_setup_data *req, u8 **buf, u16 *len, static int dfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf, u16 *len,
void (**complete)(struct usb_setup_data *req)) void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)buf; (void)buf;
(void)len; (void)len;
(void)usbd_dev;
if ((req->bmRequestType != 0x21) || (req->bRequest != DFU_DETACH)) if ((req->bmRequestType != 0x21) || (req->bRequest != DFU_DETACH))
return 0; /* Only accept class request. */ return 0; /* Only accept class request. */
@ -217,18 +222,20 @@ static int dfu_control_request(struct usb_setup_data *req, u8 **buf, u16 *len,
} }
#endif #endif
static void hid_set_config(u16 wValue) static void hid_set_config(usbd_device *usbd_dev, u16 wValue)
{ {
(void)wValue; (void)wValue;
usbd_ep_setup(0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL); usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL);
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
hid_control_request); hid_control_request);
#ifdef INCLUDE_DFU_INTERFACE #ifdef INCLUDE_DFU_INTERFACE
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
dfu_control_request); dfu_control_request);
@ -329,8 +336,8 @@ int main(void)
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO2); GPIO_CNF_OUTPUT_PUSHPULL, GPIO2);
usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
usbd_register_set_config_callback(hid_set_config); usbd_register_set_config_callback(usbd_dev, hid_set_config);
/* Delay some seconds to show that pull-up switch works. */ /* Delay some seconds to show that pull-up switch works. */
for (i = 0; i < 0x800000; i++) for (i = 0; i < 0x800000; i++)
@ -345,7 +352,7 @@ int main(void)
// OTG_FS_GCCFG &= ~OTG_FS_GCCFG_VBUSBSEN; // OTG_FS_GCCFG &= ~OTG_FS_GCCFG_VBUSBSEN;
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }
void sys_tick_handler(void) void sys_tick_handler(void)
@ -357,5 +364,5 @@ void sys_tick_handler(void)
buf[1] = x >> 9; buf[1] = x >> 9;
buf[2] = y >> 9; buf[2] = y >> 9;
usbd_ep_write_packet(0x81, buf, 4); usbd_ep_write_packet(usbd_dev, 0x81, buf, 4);
} }

28
examples/stm32/f1/other/usb_cdcacm/cdcacm.c

@ -164,11 +164,12 @@ static const char *usb_strings[] = {
"DEMO", "DEMO",
}; };
static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf, static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)complete; (void)complete;
(void)buf; (void)buf;
(void)usbd_dev;
switch(req->bRequest) { switch(req->bRequest) {
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
@ -200,28 +201,29 @@ static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf,
return 0; return 0;
} }
static void cdcacm_data_rx_cb(u8 ep) static void cdcacm_data_rx_cb(usbd_device *usbd_dev, u8 ep)
{ {
(void)ep; (void)ep;
char buf[64]; char buf[64];
int len = usbd_ep_read_packet(0x01, buf, 64); int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
if (len) { if (len) {
usbd_ep_write_packet(0x82, buf, len); usbd_ep_write_packet(usbd_dev, 0x82, buf, len);
buf[len] = 0; buf[len] = 0;
} }
} }
static void cdcacm_set_config(u16 wValue) static void cdcacm_set_config(usbd_device *usbd_dev, u16 wValue)
{ {
(void)wValue; (void)wValue;
usbd_ep_setup(0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
usbd_ep_setup(0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
usbd_ep_setup(0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
cdcacm_control_request); cdcacm_control_request);
@ -229,6 +231,8 @@ static void cdcacm_set_config(u16 wValue)
int main(void) int main(void)
{ {
usbd_device *usbd_dev;
rcc_clock_setup_in_hsi_out_48mhz(); rcc_clock_setup_in_hsi_out_48mhz();
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
@ -238,13 +242,13 @@ int main(void)
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings);
usbd_register_set_config_callback(cdcacm_set_config); usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
gpio_set(GPIOA, GPIO15); gpio_set(GPIOA, GPIO15);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15); GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

18
examples/stm32/f1/other/usb_dfu/usbdfu.c

@ -130,10 +130,11 @@ static u8 usbdfu_getstatus(u32 *bwPollTimeout)
} }
} }
static void usbdfu_getstatus_complete(struct usb_setup_data *req) static void usbdfu_getstatus_complete(usbd_device *usbd_dev, struct usb_setup_data *req)
{ {
int i; int i;
(void)req; (void)req;
(void)usbd_dev;
switch (usbdfu_state) { switch (usbdfu_state) {
case STATE_DFU_DNBUSY: case STATE_DFU_DNBUSY:
@ -166,9 +167,11 @@ static void usbdfu_getstatus_complete(struct usb_setup_data *req)
} }
} }
static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf, static int usbdfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)usbd_dev;
if ((req->bmRequestType & 0x7F) != 0x21) if ((req->bmRequestType & 0x7F) != 0x21)
return 0; /* Only accept class request. */ return 0; /* Only accept class request. */
@ -221,6 +224,8 @@ static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf,
int main(void) int main(void)
{ {
usbd_device *usbd_dev;
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
if (!gpio_get(GPIOA, GPIO10)) { if (!gpio_get(GPIOA, GPIO10)) {
@ -244,9 +249,10 @@ int main(void)
AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON; AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
usbd_set_control_buffer_size(sizeof(usbd_control_buffer)); usbd_set_control_buffer_size(usbd_dev, sizeof(usbd_control_buffer));
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
usbdfu_control_request); usbdfu_control_request);
@ -256,5 +262,5 @@ int main(void)
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15); GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

30
examples/stm32/f1/other/usb_hid/usbhid.c

@ -32,6 +32,8 @@
#include <libopencm3/usb/dfu.h> #include <libopencm3/usb/dfu.h>
#endif #endif
static usbd_device *usbd_dev;
const struct usb_device_descriptor dev = { const struct usb_device_descriptor dev = {
.bLength = USB_DT_DEVICE_SIZE, .bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE, .bDescriptorType = USB_DT_DEVICE,
@ -169,10 +171,11 @@ static const char *usb_strings[] = {
"DEMO", "DEMO",
}; };
static int hid_control_request(struct usb_setup_data *req, u8 **buf, u16 *len, static int hid_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf, u16 *len,
void (**complete)(struct usb_setup_data *req)) void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)complete; (void)complete;
(void)usbd_dev;
if((req->bmRequestType != 0x81) || if((req->bmRequestType != 0x81) ||
(req->bRequest != USB_REQ_GET_DESCRIPTOR) || (req->bRequest != USB_REQ_GET_DESCRIPTOR) ||
@ -187,9 +190,10 @@ static int hid_control_request(struct usb_setup_data *req, u8 **buf, u16 *len,
} }
#ifdef INCLUDE_DFU_INTERFACE #ifdef INCLUDE_DFU_INTERFACE
static void dfu_detach_complete(struct usb_setup_data *req) static void dfu_detach_complete(usbd_device *usbd_dev, struct usb_setup_data *req)
{ {
(void)req; (void)req;
(void)usbd_dev;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
@ -198,11 +202,12 @@ static void dfu_detach_complete(struct usb_setup_data *req)
scb_reset_core(); scb_reset_core();
} }
static int dfu_control_request(struct usb_setup_data *req, u8 **buf, u16 *len, static int dfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf, u16 *len,
void (**complete)(struct usb_setup_data *req)) void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)buf; (void)buf;
(void)len; (void)len;
(void)usbd_dev;
if ((req->bmRequestType != 0x21) || (req->bRequest != DFU_DETACH)) if ((req->bmRequestType != 0x21) || (req->bRequest != DFU_DETACH))
return 0; /* Only accept class request. */ return 0; /* Only accept class request. */
@ -213,18 +218,21 @@ static int dfu_control_request(struct usb_setup_data *req, u8 **buf, u16 *len,
} }
#endif #endif
static void hid_set_config(u16 wValue) static void hid_set_config(usbd_device *usbd_dev, u16 wValue)
{ {
(void)wValue; (void)wValue;
(void)usbd_dev;
usbd_ep_setup(0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL); usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL);
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
hid_control_request); hid_control_request);
#ifdef INCLUDE_DFU_INTERFACE #ifdef INCLUDE_DFU_INTERFACE
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
dfu_control_request); dfu_control_request);
@ -246,15 +254,15 @@ int main(void)
AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON; AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings);
usbd_register_set_config_callback(hid_set_config); usbd_register_set_config_callback(usbd_dev, hid_set_config);
gpio_set(GPIOA, GPIO15); gpio_set(GPIOA, GPIO15);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15); GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }
void sys_tick_handler(void) void sys_tick_handler(void)
@ -270,5 +278,5 @@ void sys_tick_handler(void)
if (x < -30) if (x < -30)
dir = -dir; dir = -dir;
usbd_ep_write_packet(0x81, buf, 4); usbd_ep_write_packet(usbd_dev, 0x81, buf, 4);
} }

30
examples/stm32/f1/stm32-h103/usb_cdcacm/cdcacm.c

@ -164,11 +164,12 @@ static const char *usb_strings[] = {
"DEMO", "DEMO",
}; };
static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf, static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)complete; (void)complete;
(void)buf; (void)buf;
(void)usbd_dev;
switch (req->bRequest) { switch (req->bRequest) {
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
@ -199,28 +200,31 @@ static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf,
return 0; return 0;
} }
static void cdcacm_data_rx_cb(u8 ep) static void cdcacm_data_rx_cb(usbd_device *usbd_dev, u8 ep)
{ {
(void)ep; (void)ep;
(void)usbd_dev;
char buf[64]; char buf[64];
int len = usbd_ep_read_packet(0x01, buf, 64); int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
if (len) { if (len) {
usbd_ep_write_packet(0x82, buf, len); usbd_ep_write_packet(usbd_dev, 0x82, buf, len);
buf[len] = 0; buf[len] = 0;
} }
} }
static void cdcacm_set_config(u16 wValue) static void cdcacm_set_config(usbd_device *usbd_dev, u16 wValue)
{ {
(void)wValue; (void)wValue;
(void)usbd_dev;
usbd_ep_setup(0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
usbd_ep_setup(0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
usbd_ep_setup(0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
cdcacm_control_request); cdcacm_control_request);
@ -230,6 +234,8 @@ int main(void)
{ {
int i; int i;
usbd_device *usbd_dev;
rcc_clock_setup_in_hsi_out_48mhz(); rcc_clock_setup_in_hsi_out_48mhz();
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
@ -238,13 +244,13 @@ int main(void)
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); GPIO_CNF_OUTPUT_PUSHPULL, GPIO11);
usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings);
usbd_register_set_config_callback(cdcacm_set_config); usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
for (i = 0; i < 0x800000; i++) for (i = 0; i < 0x800000; i++)
__asm__("nop"); __asm__("nop");
gpio_clear(GPIOC, GPIO11); gpio_clear(GPIOC, GPIO11);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

22
examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c

@ -114,8 +114,10 @@ static const char *usb_strings[] = {
"@Internal Flash /0x08000000/8*001Ka,56*001Kg", "@Internal Flash /0x08000000/8*001Ka,56*001Kg",
}; };
static u8 usbdfu_getstatus(u32 *bwPollTimeout) static u8 usbdfu_getstatus(usbd_device *usbd_dev, u32 *bwPollTimeout)
{ {
(void)usbd_dev;
switch (usbdfu_state) { switch (usbdfu_state) {
case STATE_DFU_DNLOAD_SYNC: case STATE_DFU_DNLOAD_SYNC:
usbdfu_state = STATE_DFU_DNBUSY; usbdfu_state = STATE_DFU_DNBUSY;
@ -130,10 +132,11 @@ static u8 usbdfu_getstatus(u32 *bwPollTimeout)
} }
} }
static void usbdfu_getstatus_complete(struct usb_setup_data *req) static void usbdfu_getstatus_complete(usbd_device *usbd_dev, struct usb_setup_data *req)
{ {
int i; int i;
(void)req; (void)req;
(void)usbd_dev;
switch (usbdfu_state) { switch (usbdfu_state) {
case STATE_DFU_DNBUSY: case STATE_DFU_DNBUSY:
@ -166,8 +169,8 @@ static void usbdfu_getstatus_complete(struct usb_setup_data *req)
} }
} }
static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf, static int usbdfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
if ((req->bmRequestType & 0x7F) != 0x21) if ((req->bmRequestType & 0x7F) != 0x21)
return 0; /* Only accept class request. */ return 0; /* Only accept class request. */
@ -199,7 +202,7 @@ static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf,
return 0; return 0;
case DFU_GETSTATUS: { case DFU_GETSTATUS: {
u32 bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ u32 bwPollTimeout = 0; /* 24-bit integer in DFU class spec */
(*buf)[0] = usbdfu_getstatus(&bwPollTimeout); (*buf)[0] = usbdfu_getstatus(usbd_dev, &bwPollTimeout);
(*buf)[1] = bwPollTimeout & 0xFF; (*buf)[1] = bwPollTimeout & 0xFF;
(*buf)[2] = (bwPollTimeout >> 8) & 0xFF; (*buf)[2] = (bwPollTimeout >> 8) & 0xFF;
(*buf)[3] = (bwPollTimeout >> 16) & 0xFF; (*buf)[3] = (bwPollTimeout >> 16) & 0xFF;
@ -221,6 +224,8 @@ static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf,
int main(void) int main(void)
{ {
usbd_device *usbd_dev;
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
if (!gpio_get(GPIOA, GPIO10)) { if (!gpio_get(GPIOA, GPIO10)) {
@ -244,9 +249,10 @@ int main(void)
GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); GPIO_CNF_OUTPUT_PUSHPULL, GPIO11);
gpio_set(GPIOC, GPIO11); gpio_set(GPIOC, GPIO11);
usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings);
usbd_set_control_buffer_size(sizeof(usbd_control_buffer)); usbd_set_control_buffer_size(usbd_dev, sizeof(usbd_control_buffer));
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
usbdfu_control_request); usbdfu_control_request);
@ -254,5 +260,5 @@ int main(void)
gpio_clear(GPIOC, GPIO11); gpio_clear(GPIOC, GPIO11);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

32
examples/stm32/f1/stm32-h103/usb_hid/usbhid.c

@ -169,10 +169,11 @@ static const char *usb_strings[] = {
"DEMO", "DEMO",
}; };
static int hid_control_request(struct usb_setup_data *req, u8 **buf, u16 *len, static int hid_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf, u16 *len,
void (**complete)(struct usb_setup_data *req)) void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)complete; (void)complete;
(void)usbd_dev;
if ((req->bmRequestType != 0x81) || if ((req->bmRequestType != 0x81) ||
(req->bRequest != USB_REQ_GET_DESCRIPTOR) || (req->bRequest != USB_REQ_GET_DESCRIPTOR) ||
@ -187,9 +188,10 @@ static int hid_control_request(struct usb_setup_data *req, u8 **buf, u16 *len,
} }
#ifdef INCLUDE_DFU_INTERFACE #ifdef INCLUDE_DFU_INTERFACE
static void dfu_detach_complete(struct usb_setup_data *req) static void dfu_detach_complete(usbd_device *usbd_dev, struct usb_setup_data *req)
{ {
(void)req; (void)req;
(void)usbd_dev;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
@ -198,11 +200,12 @@ static void dfu_detach_complete(struct usb_setup_data *req)
scb_reset_core(); scb_reset_core();
} }
static int dfu_control_request(struct usb_setup_data *req, u8 **buf, u16 *len, static int dfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf, u16 *len,
void (**complete)(struct usb_setup_data *req)) void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)buf; (void)buf;
(void)len; (void)len;
(void)usbd_dev;
if ((req->bmRequestType != 0x21) || (req->bRequest != DFU_DETACH)) if ((req->bmRequestType != 0x21) || (req->bRequest != DFU_DETACH))
return 0; /* Only accept class request. */ return 0; /* Only accept class request. */
@ -213,18 +216,21 @@ static int dfu_control_request(struct usb_setup_data *req, u8 **buf, u16 *len,
} }
#endif #endif
static void hid_set_config(u16 wValue) static void hid_set_config(usbd_device *usbd_dev, u16 wValue)
{ {
(void)wValue; (void)wValue;
(void)usbd_dev;
usbd_ep_setup(0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL); usbd_ep_setup(usbd_dev, 0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL);
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
hid_control_request); hid_control_request);
#ifdef INCLUDE_DFU_INTERFACE #ifdef INCLUDE_DFU_INTERFACE
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
dfu_control_request); dfu_control_request);
@ -240,6 +246,8 @@ int main(void)
{ {
int i; int i;
usbd_device *usbd_dev;
rcc_clock_setup_in_hsi_out_48mhz(); rcc_clock_setup_in_hsi_out_48mhz();
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
@ -248,8 +256,8 @@ int main(void)
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); GPIO_CNF_OUTPUT_PUSHPULL, GPIO11);
usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings);
usbd_register_set_config_callback(hid_set_config); usbd_register_set_config_callback(usbd_dev, hid_set_config);
for (i = 0; i < 0x80000; i++) for (i = 0; i < 0x80000; i++)
__asm__("nop"); __asm__("nop");
@ -257,9 +265,10 @@ int main(void)
gpio_clear(GPIOC, GPIO11); gpio_clear(GPIOC, GPIO11);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }
#if 0 /* is this used? */
void sys_tick_handler(void) void sys_tick_handler(void)
{ {
static int x = 0; static int x = 0;
@ -273,5 +282,6 @@ void sys_tick_handler(void)
if (x < -30) if (x < -30)
dir = -dir; dir = -dir;
usbd_ep_write_packet(0x81, buf, 4); usbd_ep_write_packet(usbd_dev, 0x81, buf, 4);
} }
#endif

22
examples/stm32/f1/stm32-h103/usb_iap/usbiap.c

@ -114,8 +114,10 @@ static const char *usb_strings[] = {
"@Internal Flash /0x08000000/8*001Ka,56*001Kg", "@Internal Flash /0x08000000/8*001Ka,56*001Kg",
}; };
static u8 usbdfu_getstatus(u32 *bwPollTimeout) static u8 usbdfu_getstatus(usbd_device *usbd_dev, u32 *bwPollTimeout)
{ {
(void)usbd_dev;
switch (usbdfu_state) { switch (usbdfu_state) {
case STATE_DFU_DNLOAD_SYNC: case STATE_DFU_DNLOAD_SYNC:
usbdfu_state = STATE_DFU_DNBUSY; usbdfu_state = STATE_DFU_DNBUSY;
@ -130,10 +132,11 @@ static u8 usbdfu_getstatus(u32 *bwPollTimeout)
} }
} }
static void usbdfu_getstatus_complete(struct usb_setup_data *req) static void usbdfu_getstatus_complete(usbd_device *usbd_dev, struct usb_setup_data *req)
{ {
int i; int i;
(void)req; (void)req;
(void)usbd_dev;
switch (usbdfu_state) { switch (usbdfu_state) {
case STATE_DFU_DNBUSY: case STATE_DFU_DNBUSY:
@ -166,8 +169,8 @@ static void usbdfu_getstatus_complete(struct usb_setup_data *req)
} }
} }
static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf, static int usbdfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
if ((req->bmRequestType & 0x7F) != 0x21) if ((req->bmRequestType & 0x7F) != 0x21)
return 0; /* Only accept class request. */ return 0; /* Only accept class request. */
@ -199,7 +202,7 @@ static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf,
return 0; return 0;
case DFU_GETSTATUS: { case DFU_GETSTATUS: {
u32 bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ u32 bwPollTimeout = 0; /* 24-bit integer in DFU class spec */
(*buf)[0] = usbdfu_getstatus(&bwPollTimeout); (*buf)[0] = usbdfu_getstatus(usbd_dev, &bwPollTimeout);
(*buf)[1] = bwPollTimeout & 0xFF; (*buf)[1] = bwPollTimeout & 0xFF;
(*buf)[2] = (bwPollTimeout >> 8) & 0xFF; (*buf)[2] = (bwPollTimeout >> 8) & 0xFF;
(*buf)[3] = (bwPollTimeout >> 16) & 0xFF; (*buf)[3] = (bwPollTimeout >> 16) & 0xFF;
@ -221,6 +224,8 @@ static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf,
int main(void) int main(void)
{ {
usbd_device *usbd_dev;
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
if (!gpio_get(GPIOA, GPIO10)) { if (!gpio_get(GPIOA, GPIO10)) {
@ -244,9 +249,10 @@ int main(void)
AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON; AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15);
usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings);
usbd_set_control_buffer_size(sizeof(usbd_control_buffer)); usbd_set_control_buffer_size(usbd_dev, sizeof(usbd_control_buffer));
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
usbdfu_control_request); usbdfu_control_request);
@ -256,5 +262,5 @@ int main(void)
GPIO_CNF_OUTPUT_PUSHPULL, GPIO15); GPIO_CNF_OUTPUT_PUSHPULL, GPIO15);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

12
examples/stm32/f1/stm32-h107/usb_simple/usb_simple.c

@ -75,12 +75,13 @@ const char *usb_strings[] = {
"1001", "1001",
}; };
static int simple_control_callback(struct usb_setup_data *req, u8 **buf, static int simple_control_callback(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)buf; (void)buf;
(void)len; (void)len;
(void)complete; (void)complete;
(void)usbd_dev;
if (req->bmRequestType != 0x40) if (req->bmRequestType != 0x40)
return 0; /* Only accept vendor request. */ return 0; /* Only accept vendor request. */
@ -95,6 +96,8 @@ static int simple_control_callback(struct usb_setup_data *req, u8 **buf,
int main(void) int main(void)
{ {
usbd_device *usbd_dev;
rcc_clock_setup_in_hse_8mhz_out_72mhz(); rcc_clock_setup_in_hse_8mhz_out_72mhz();
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN);
@ -105,13 +108,14 @@ int main(void)
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, GPIO6); GPIO_CNF_OUTPUT_PUSHPULL, GPIO6);
usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&stm32f107_usb_driver, &dev, &config, usb_strings);
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_VENDOR, USB_REQ_TYPE_VENDOR,
USB_REQ_TYPE_TYPE, USB_REQ_TYPE_TYPE,
simple_control_callback); simple_control_callback);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

30
examples/stm32/f4/stm32f4-discovery/usb_cdcacm/cdcacm.c

@ -22,6 +22,7 @@
#include <libopencm3/stm32/f4/gpio.h> #include <libopencm3/stm32/f4/gpio.h>
#include <libopencm3/usb/usbd.h> #include <libopencm3/usb/usbd.h>
#include <libopencm3/usb/cdc.h> #include <libopencm3/usb/cdc.h>
#include <libopencm3/stm32/f4/scb.h>
static const struct usb_device_descriptor dev = { static const struct usb_device_descriptor dev = {
.bLength = USB_DT_DEVICE_SIZE, .bLength = USB_DT_DEVICE_SIZE,
@ -164,11 +165,12 @@ static const char *usb_strings[] = {
"DEMO", "DEMO",
}; };
static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf, static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, u8 **buf,
u16 *len, void (**complete)(struct usb_setup_data *req)) u16 *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
{ {
(void)complete; (void)complete;
(void)buf; (void)buf;
(void)usbd_dev;
switch (req->bRequest) { switch (req->bRequest) {
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
@ -188,30 +190,31 @@ static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf,
return 0; return 0;
} }
static void cdcacm_data_rx_cb(u8 ep) static void cdcacm_data_rx_cb(usbd_device *usbd_dev, u8 ep)
{ {
(void)ep; (void)ep;
char buf[64]; char buf[64];
int len = usbd_ep_read_packet(0x01, buf, 64); int len = usbd_ep_read_packet(usbd_dev, 0x01, buf, 64);
if (len) { if (len) {
while (usbd_ep_write_packet(0x82, buf, len) == 0) while (usbd_ep_write_packet(usbd_dev, 0x82, buf, len) == 0)
; ;
} }
gpio_toggle(GPIOC, GPIO5); gpio_toggle(GPIOC, GPIO5);
} }
static void cdcacm_set_config(u16 wValue) static void cdcacm_set_config(usbd_device *usbd_dev, u16 wValue)
{ {
(void)wValue; (void)wValue;
usbd_ep_setup(0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); usbd_ep_setup(usbd_dev, 0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
usbd_ep_setup(0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); usbd_ep_setup(usbd_dev, 0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL);
usbd_ep_setup(0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); usbd_ep_setup(usbd_dev, 0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
usbd_register_control_callback( usbd_register_control_callback(
usbd_dev,
USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
cdcacm_control_request); cdcacm_control_request);
@ -219,6 +222,8 @@ static void cdcacm_set_config(u16 wValue)
int main(void) int main(void)
{ {
usbd_device *usbd_dev;
rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_120MHZ]); rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_120MHZ]);
rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);
@ -228,10 +233,9 @@ int main(void)
GPIO9 | GPIO11 | GPIO12); GPIO9 | GPIO11 | GPIO12);
gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12);
usbd_init(&otgfs_usb_driver, &dev, &config, usb_strings); usbd_dev = usbd_init(&otgfs_usb_driver, &dev, &config, usb_strings);
usbd_register_set_config_callback(cdcacm_set_config); usbd_register_set_config_callback(usbd_dev, cdcacm_set_config);
while (1) while (1)
usbd_poll(); usbd_poll(usbd_dev);
} }

15
include/libopencm3/stm32/otg_fs.h

@ -24,7 +24,7 @@
#include <libopencm3/cm3/common.h> #include <libopencm3/cm3/common.h>
/* Core Global Control and Status Registers */ /* Core Global Control and Status Registers */
#define OTG_FS_OTGCTL MMIO32(USB_OTG_FS_BASE + 0x000) #define OTG_FS_GOTGCTL MMIO32(USB_OTG_FS_BASE + 0x000)
#define OTG_FS_GOTGINT MMIO32(USB_OTG_FS_BASE + 0x004) #define OTG_FS_GOTGINT MMIO32(USB_OTG_FS_BASE + 0x004)
#define OTG_FS_GAHBCFG MMIO32(USB_OTG_FS_BASE + 0x008) #define OTG_FS_GAHBCFG MMIO32(USB_OTG_FS_BASE + 0x008)
#define OTG_FS_GUSBCFG MMIO32(USB_OTG_FS_BASE + 0x00C) #define OTG_FS_GUSBCFG MMIO32(USB_OTG_FS_BASE + 0x00C)
@ -84,6 +84,18 @@
#define OTG_FS_FIFO(x) ((volatile u32*)(USB_OTG_FS_BASE + (((x) + 1) << 12))) #define OTG_FS_FIFO(x) ((volatile u32*)(USB_OTG_FS_BASE + (((x) + 1) << 12)))
/* Global CSRs */ /* Global CSRs */
/* OTG_FS USB control registers (OTG_HS_GOTGCTL) */
#define OTG_FS_GOTGCTL_BSVLD (1 << 19)
#define OTG_FS_GOTGCTL_ASVLD (1 << 18)
#define OTG_FS_GOTGCTL_DBCT (1 << 17)
#define OTG_FS_GOTGCTL_CIDSTS (1 << 16)
#define OTG_FS_GOTGCTL_DHNPEN (1 << 11)
#define OTG_FS_GOTGCTL_HSHNPEN (1 << 10)
#define OTG_FS_GOTGCTL_HNPRQ (1 << 9)
#define OTG_FS_GOTGCTL_HNGSCS (1 << 8)
#define OTG_FS_GOTGCTL_SRQ (1 << 1)
#define OTG_FS_GOTGCTL_SRQSCS (1 << 0)
/* OTG_FS AHB configuration register (OTG_FS_GAHBCFG) */ /* OTG_FS AHB configuration register (OTG_FS_GAHBCFG) */
#define OTG_FS_GAHBCFG_GINT 0x0001 #define OTG_FS_GAHBCFG_GINT 0x0001
#define OTG_FS_GAHBCFG_TXFELVL 0x0080 #define OTG_FS_GAHBCFG_TXFELVL 0x0080
@ -320,4 +332,3 @@
#define OTG_FS_DIEPSIZ0_XFRSIZ_MASK (0x7f << 0) #define OTG_FS_DIEPSIZ0_XFRSIZ_MASK (0x7f << 0)
#endif #endif

396
include/libopencm3/stm32/otg_hs.h

@ -0,0 +1,396 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBOPENCM3_OTG_HS_H
#define LIBOPENCM3_OTG_HS_H
#include <libopencm3/stm32/memorymap.h>
#include <libopencm3/cm3/common.h>
/* Core Global Control and Status Registers */
#define OTG_GOTGCTL 0x000
#define OTG_GOTGIN 0x004
#define OTG_GAHBCFG 0x008
#define OTG_GUSBCFG 0x00C
#define OTG_GRSTCTL 0x010
#define OTG_GINTSTS 0x014
#define OTG_GINTMSK 0x018
#define OTG_GRXSTSR 0x01C
#define OTG_GRXSTSP 0x020
#define OTG_GRXFSIZ 0x024
#define OTG_GNPTXFSIZ 0x028
#define OTG_GNPTXSTS 0x02C
#define OTG_GCCFG 0x038
#define OTG_CID 0x03C
#define OTG_HPTXFSIZ 0x100
#define OTG_DIEPTXF(x) (0x104 + 4*(x-1))
/* Host-mode Control and Status Registers */
#define OTG_HCFG 0x400
#define OTG_HFIR 0x404
#define OTG_HFNUM 0x408
#define OTG_HPTXSTS 0x410
#define OTG_HAINT 0x414
#define OTG_HAINTMSK 0x418
#define OTG_HPRT 0x440
#define OTG_HCCHARx 0x500
#define OTG_HCINTx 0x508
#define OTG_HCINTMSKx 0x50C
#define OTG_HCTSIZx 0x510
/* Device-mode Control and Status Registers */
#define OTG_DCFG 0x800
#define OTG_DCTL 0x804
#define OTG_DSTS 0x808
#define OTG_DIEPMSK 0x810
#define OTG_DOEPMSK 0x814
#define OTG_DAINT 0x818
#define OTG_DAINTMSK 0x81C
#define OTG_DVBUSDIS 0x828
#define OTG_DVBUSPULSE 0x82C
#define OTG_DIEPEMPMSK 0x834
#define OTG_DIEPCTL0 0x900
#define OTG_DIEPCTL(x) (0x900 + 0x20*(x))
#define OTG_DOEPCTL0 0xB00
#define OTG_DOEPCTL(x) (0xB00 + 0x20*(x))
#define OTG_DIEPINT(x) (0x908 + 0x20*(x))
#define OTG_DOEPINT(x) (0xB08 + 0x20*(x))
#define OTG_DIEPTSIZ0 0x910
#define OTG_DOEPTSIZ0 0xB10
#define OTG_DIEPTSIZ(x) (0x910 + 0x20*(x))
#define OTG_DTXFSTS(x) (0x918 + 0x20*(x))
#define OTG_DOEPTSIZ(x) (0xB10 + 0x20*(x))
/* Power and clock gating control and status register */
#define OTG_PCGCCTL 0xE00
/* Data FIFO */
#define OTG_FIFO(x) (((x) + 1) << 12)
/***********************************************************************/
/* Core Global Control and Status Registers */
#define OTG_HS_GOTGCTL MMIO32(USB_OTG_HS_BASE + OTG_GOTGCTL)
#define OTG_HS_GOTGINT MMIO32(USB_OTG_HS_BASE + OTG_GOTGINT)
#define OTG_HS_GAHBCFG MMIO32(USB_OTG_HS_BASE + OTG_GAHBCFG)
#define OTG_HS_GUSBCFG MMIO32(USB_OTG_HS_BASE + OTG_GUSBCFG)
#define OTG_HS_GRSTCTL MMIO32(USB_OTG_HS_BASE + OTG_GRSTCTL)
#define OTG_HS_GINTSTS MMIO32(USB_OTG_HS_BASE + OTG_GINTSTS)
#define OTG_HS_GINTMSK MMIO32(USB_OTG_HS_BASE + OTG_GINTMSK)
#define OTG_HS_GRXSTSR MMIO32(USB_OTG_HS_BASE + OTG_GRXSTSR)
#define OTG_HS_GRXSTSP MMIO32(USB_OTG_HS_BASE + OTG_GRXSTSP)
#define OTG_HS_GRXFSIZ MMIO32(USB_OTG_HS_BASE + OTG_GRXFSIZ)
#define OTG_HS_GNPTXFSIZ MMIO32(USB_OTG_HS_BASE + OTG_GNPTXFSIZ)
#define OTG_HS_GNPTXSTS MMIO32(USB_OTG_HS_BASE + OTG_GNPTXSTS)
#define OTG_HS_GCCFG MMIO32(USB_OTG_HS_BASE + OTG_GCCFG)
#define OTG_HS_CID MMIO32(USB_OTG_HS_BASE + OTG_CID)
#define OTG_HS_HPTXFSIZ MMIO32(USB_OTG_HS_BASE + OTG_HPTXFSIZ)
#define OTG_HS_DIEPTXF(x) MMIO32(USB_OTG_HS_BASE + OTG_DIEPTXF(x))
/* Host-mode Control and Status Registers */
#define OTG_HS_HCFG MMIO32(USB_OTG_HS_BASE + OTG_HCFG)
#define OTG_HS_HFIR MMIO32(USB_OTG_HS_BASE + OTG_HFIR)
#define OTG_HS_HFNUM MMIO32(USB_OTG_HS_BASE + OTG_HFNUM)
#define OTG_HS_HPTXSTS MMIO32(USB_OTG_HS_BASE + OTG_HPTXSTS)
#define OTG_HS_HAINT MMIO32(USB_OTG_HS_BASE + OTG_HAINT)
#define OTG_HS_HAINTMSK MMIO32(USB_OTG_HS_BASE + OTG_HAINTMSK)
#define OTG_HS_HPRT MMIO32(USB_OTG_HS_BASE + OTG_HPRT)
#define OTG_HS_HCCHARx MMIO32(USB_OTG_HS_BASE + OTG_HCCHARx)
#define OTG_HS_HCINTx MMIO32(USB_OTG_HS_BASE + OTG_HCINTx)
#define OTG_HS_HCINTMSKx MMIO32(USB_OTG_HS_BASE + OTG_HCINTMSKx)
#define OTG_HS_HCTSIZx MMIO32(USB_OTG_HS_BASE + OTG_HCTSIZx)
/* Device-mode Control and Status Registers */
#define OTG_HS_DCFG MMIO32(USB_OTG_HS_BASE + OTG_DCFG)
#define OTG_HS_DCTL MMIO32(USB_OTG_HS_BASE + OTG_DCTL)
#define OTG_HS_DSTS MMIO32(USB_OTG_HS_BASE + OTG_DSTS)
#define OTG_HS_DIEPMSK MMIO32(USB_OTG_HS_BASE + OTG_DIEPMSK)
#define OTG_HS_DOEPMSK MMIO32(USB_OTG_HS_BASE + OTG_DOEPMSK)
#define OTG_HS_DAINT MMIO32(USB_OTG_HS_BASE + OTG_DAINT)
#define OTG_HS_DAINTMSK MMIO32(USB_OTG_HS_BASE + OTG_DAINTMSK)
#define OTG_HS_DVBUSDIS MMIO32(USB_OTG_HS_BASE + OTG_DVBUSDIS)
#define OTG_HS_DVBUSPULSE MMIO32(USB_OTG_HS_BASE + OTG_DVBUSPULSE)
#define OTG_HS_DIEPEMPMSK MMIO32(USB_OTG_HS_BASE + OTG_DIEPEMPMSK)
#define OTG_HS_DIEPCTL0 MMIO32(USB_OTG_HS_BASE + OTG_DIEPCTL0)
#define OTG_HS_DIEPCTL(x) MMIO32(USB_OTG_HS_BASE + OTG_DIEPCTL(x))
#define OTG_HS_DOEPCTL0 MMIO32(USB_OTG_HS_BASE + OTG_DOEPCTL0)
#define OTG_HS_DOEPCTL(x) MMIO32(USB_OTG_HS_BASE + OTG_DOEPCTL(x))
#define OTG_HS_DIEPINT(x) MMIO32(USB_OTG_HS_BASE + OTG_DIEPINT(x))
#define OTG_HS_DOEPINT(x) MMIO32(USB_OTG_HS_BASE + OTG_DOEPINT(x))
#define OTG_HS_DIEPTSIZ0 MMIO32(USB_OTG_HS_BASE + OTG_DIEPTSIZ0)
#define OTG_HS_DOEPTSIZ0 MMIO32(USB_OTG_HS_BASE + OTG_DOEPTSIZ0)
#define OTG_HS_DIEPTSIZ(x) MMIO32(USB_OTG_HS_BASE + OTG_DIEPTSIZ(x)))
#define OTG_HS_DTXFSTS(x) MMIO32(USB_OTG_HS_BASE + OTG_DTXFSTS(x))
#define OTG_HS_DOEPTSIZ(x) MMIO32(USB_OTG_HS_BASE + OTG_DOEPTSIZ(x))
/* Power and clock gating control and status register */
#define OTG_HS_PCGCCTL MMIO32(USB_OTG_HS_BASE + OTG_PCGCCTL)
/* Data FIFO */
#define OTG_HS_FIFO(x) ((volatile u32*)(USB_OTG_HS_BASE + OTG_FIFO(x)))
/* Global CSRs */
/* OTG_HS USB control registers (OTG_FS_GOTGCTL) */
#define OTG_HS_GOTGCTL_BSVLD (1 << 19)
#define OTG_HS_GOTGCTL_ASVLD (1 << 18)
#define OTG_HS_GOTGCTL_DBCT (1 << 17)
#define OTG_HS_GOTGCTL_CIDSTS (1 << 16)
#define OTG_HS_GOTGCTL_DHNPEN (1 << 11)
#define OTG_HS_GOTGCTL_HSHNPEN (1 << 10)
#define OTG_HS_GOTGCTL_HNPRQ (1 << 9)
#define OTG_HS_GOTGCTL_HNGSCS (1 << 8)
#define OTG_HS_GOTGCTL_SRQ (1 << 1)
#define OTG_HS_GOTGCTL_SRQSCS (1 << 0)
/* OTG_FS AHB configuration register (OTG_HS_GAHBCFG) */
#define OTG_HS_GAHBCFG_GINT 0x0001
#define OTG_HS_GAHBCFG_TXFELVL 0x0080
#define OTG_HS_GAHBCFG_PTXFELVL 0x0100
/* OTG_FS USB configuration register (OTG_HS_GUSBCFG) */
#define OTG_HS_GUSBCFG_TOCAL 0x00000003
#define OTG_HS_GUSBCFG_SRPCAP 0x00000100
#define OTG_HS_GUSBCFG_HNPCAP 0x00000200
#define OTG_HS_GUSBCFG_TRDT_MASK (0xf << 10)
#define OTG_HS_GUSBCFG_TRDT_16BIT (0x5 << 10)
#define OTG_HS_GUSBCFG_TRDT_8BIT (0x9 << 10)
#define OTG_HS_GUSBCFG_NPTXRWEN 0x00004000
#define OTG_HS_GUSBCFG_FHMOD 0x20000000
#define OTG_HS_GUSBCFG_FDMOD 0x40000000
#define OTG_HS_GUSBCFG_CTXPKT 0x80000000
#define OTG_HS_GUSBCFG_PHYSEL (1 << 6)
/* OTG_FS reset register (OTG_HS_GRSTCTL) */
#define OTG_HS_GRSTCTL_AHBIDL (1 << 31)
/* Bits 30:11 - Reserved */
#define OTG_HS_GRSTCTL_TXFNUM_MASK (0x1f << 6)
#define OTG_HS_GRSTCTL_TXFFLSH (1 << 5)
#define OTG_HS_GRSTCTL_RXFFLSH (1 << 4)
/* Bit 3 - Reserved */
#define OTG_HS_GRSTCTL_FCRST (1 << 2)
#define OTG_HS_GRSTCTL_HSRST (1 << 1)
#define OTG_HS_GRSTCTL_CSRST (1 << 0)
/* OTG_FS interrupt status register (OTG_HS_GINTSTS) */
#define OTG_HS_GINTSTS_WKUPINT (1 << 31)
#define OTG_HS_GINTSTS_SRQINT (1 << 30)
#define OTG_HS_GINTSTS_DISCINT (1 << 29)
#define OTG_HS_GINTSTS_CIDSCHG (1 << 28)
/* Bit 27 - Reserved */
#define OTG_HS_GINTSTS_PTXFE (1 << 26)
#define OTG_HS_GINTSTS_HCINT (1 << 25)
#define OTG_HS_GINTSTS_HPRTINT (1 << 24)
/* Bits 23:22 - Reserved */
#define OTG_HS_GINTSTS_IPXFR (1 << 21)
#define OTG_HS_GINTSTS_INCOMPISOOUT (1 << 21)
#define OTG_HS_GINTSTS_IISOIXFR (1 << 20)
#define OTG_HS_GINTSTS_OEPINT (1 << 19)
#define OTG_HS_GINTSTS_IEPINT (1 << 18)
/* Bits 17:16 - Reserved */
#define OTG_HS_GINTSTS_EOPF (1 << 15)
#define OTG_HS_GINTSTS_ISOODRP (1 << 14)
#define OTG_HS_GINTSTS_ENUMDNE (1 << 13)
#define OTG_HS_GINTSTS_USBRST (1 << 12)
#define OTG_HS_GINTSTS_USBSUSP (1 << 11)
#define OTG_HS_GINTSTS_ESUSP (1 << 10)
/* Bits 9:8 - Reserved */
#define OTG_HS_GINTSTS_GONAKEFF (1 << 7)
#define OTG_HS_GINTSTS_GINAKEFF (1 << 6)
#define OTG_HS_GINTSTS_NPTXFE (1 << 5)
#define OTG_HS_GINTSTS_RXFLVL (1 << 4)
#define OTG_HS_GINTSTS_SOF (1 << 3)
#define OTG_HS_GINTSTS_OTGINT (1 << 2)
#define OTG_HS_GINTSTS_MMIS (1 << 1)
#define OTG_HS_GINTSTS_CMOD (1 << 0)
/* OTG_FS interrupt mask register (OTG_HS_GINTMSK) */
#define OTG_HS_GINTMSK_MMISM 0x00000002
#define OTG_HS_GINTMSK_OTGINT 0x00000004
#define OTG_HS_GINTMSK_SOFM 0x00000008
#define OTG_HS_GINTMSK_RXFLVLM 0x00000010
#define OTG_HS_GINTMSK_NPTXFEM 0x00000020
#define OTG_HS_GINTMSK_GINAKEFFM 0x00000040
#define OTG_HS_GINTMSK_GONAKEFFM 0x00000080
#define OTG_HS_GINTMSK_ESUSPM 0x00000400
#define OTG_HS_GINTMSK_USBSUSPM 0x00000800
#define OTG_HS_GINTMSK_USBRST 0x00001000
#define OTG_HS_GINTMSK_ENUMDNEM 0x00002000
#define OTG_HS_GINTMSK_ISOODRPM 0x00004000
#define OTG_HS_GINTMSK_EOPFM 0x00008000
#define OTG_HS_GINTMSK_EPMISM 0x00020000
#define OTG_HS_GINTMSK_IEPINT 0x00040000
#define OTG_HS_GINTMSK_OEPINT 0x00080000
#define OTG_HS_GINTMSK_IISOIXFRM 0x00100000
#define OTG_HS_GINTMSK_IISOOXFRM 0x00200000
#define OTG_HS_GINTMSK_IPXFRM 0x00200000
#define OTG_HS_GINTMSK_PRTIM 0x01000000
#define OTG_HS_GINTMSK_HCIM 0x02000000
#define OTG_HS_GINTMSK_PTXFEM 0x04000000
#define OTG_HS_GINTMSK_CIDSCHGM 0x10000000
#define OTG_HS_GINTMSK_DISCINT 0x20000000
#define OTG_HS_GINTMSK_SRQIM 0x40000000
#define OTG_HS_GINTMSK_WUIM 0x80000000
/* OTG_FS Receive Status Pop Register (OTG_HS_GRXSTSP) */
/* Bits 31:25 - Reserved */
#define OTG_HS_GRXSTSP_FRMNUM_MASK (0xf << 21)
#define OTG_HS_GRXSTSP_PKTSTS_MASK (0xf << 17)
#define OTG_HS_GRXSTSP_PKTSTS_GOUTNAK (0x1 << 17)
#define OTG_HS_GRXSTSP_PKTSTS_OUT (0x2 << 17)
#define OTG_HS_GRXSTSP_PKTSTS_OUT_COMP (0x3 << 17)
#define OTG_HS_GRXSTSP_PKTSTS_SETUP_COMP (0x4 << 17)
#define OTG_HS_GRXSTSP_PKTSTS_SETUP (0x6 << 17)
#define OTG_HS_GRXSTSP_DPID_MASK (0x3 << 15)
#define OTG_HS_GRXSTSP_DPID_DATA0 (0x0 << 15)
#define OTG_HS_GRXSTSP_DPID_DATA1 (0x2 << 15)
#define OTG_HS_GRXSTSP_DPID_DATA2 (0x1 << 15)
#define OTG_HS_GRXSTSP_DPID_MDATA (0x3 << 15)
#define OTG_HS_GRXSTSP_BCNT_MASK (0x7ff << 4)
#define OTG_HS_GRXSTSP_EPNUM_MASK (0xf << 0)
/* OTG_FS general core configuration register (OTG_HS_GCCFG) */
/* Bits 31:21 - Reserved */
#define OTG_HS_GCCFG_SOFOUTEN (1 << 20)
#define OTG_HS_GCCFG_VBUSBSEN (1 << 19)
#define OTG_HS_GCCFG_VBUSASEN (1 << 18)
/* Bit 17 - Reserved */
#define OTG_HS_GCCFG_PWRDWN (1 << 16)
/* Bits 15:0 - Reserved */
/* Device-mode CSRs */
/* OTG_FS device control register (OTG_HS_DCTL) */
/* Bits 31:12 - Reserved */
#define OTG_HS_DCTL_POPRGDNE (1 << 11)
#define OTG_HS_DCTL_CGONAK (1 << 10)
#define OTG_HS_DCTL_SGONAK (1 << 9)
#define OTG_HS_DCTL_SGINAK (1 << 8)
#define OTG_HS_DCTL_TCTL_MASK (7 << 4)
#define OTG_HS_DCTL_GONSTS (1 << 3)
#define OTG_HS_DCTL_GINSTS (1 << 2)
#define OTG_HS_DCTL_SDIS (1 << 1)
#define OTG_HS_DCTL_RWUSIG (1 << 0)
/* OTG_FS device configuration register (OTG_HS_DCFG) */
#define OTG_HS_DCFG_DSPD 0x0003
#define OTG_HS_DCFG_NZLSOHSK 0x0004
#define OTG_HS_DCFG_DAD 0x07F0
#define OTG_HS_DCFG_PFIVL 0x1800
/* OTG_FS Device IN Endpoint Common Interrupt Mask Register (OTG_HS_DIEPMSK) */
/* Bits 31:10 - Reserved */
#define OTG_HS_DIEPMSK_BIM (1 << 9)
#define OTG_HS_DIEPMSK_TXFURM (1 << 8)
/* Bit 7 - Reserved */
#define OTG_HS_DIEPMSK_INEPNEM (1 << 6)
#define OTG_HS_DIEPMSK_INEPNMM (1 << 5)
#define OTG_HS_DIEPMSK_ITTXFEMSK (1 << 4)
#define OTG_HS_DIEPMSK_TOM (1 << 3)
/* Bit 2 - Reserved */
#define OTG_HS_DIEPMSK_EPDM (1 << 1)
#define OTG_HS_DIEPMSK_XFRCM (1 << 0)
/* OTG_FS Device OUT Endpoint Common Interrupt Mask Register (OTG_HS_DOEPMSK) */
/* Bits 31:10 - Reserved */
#define OTG_HS_DOEPMSK_BOIM (1 << 9)
#define OTG_HS_DOEPMSK_OPEM (1 << 8)
/* Bit 7 - Reserved */
#define OTG_HS_DOEPMSK_B2BSTUP (1 << 6)
/* Bit 5 - Reserved */
#define OTG_HS_DOEPMSK_OTEPDM (1 << 4)
#define OTG_HS_DOEPMSK_STUPM (1 << 3)
/* Bit 2 - Reserved */
#define OTG_HS_DOEPMSK_EPDM (1 << 1)
#define OTG_HS_DOEPMSK_XFRCM (1 << 0)
/* OTG_FS Device Control IN Endpoint 0 Control Register (OTG_HS_DIEPCTL0) */
#define OTG_HS_DIEPCTL0_EPENA (1 << 31)
#define OTG_HS_DIEPCTL0_EPDIS (1 << 30)
/* Bits 29:28 - Reserved */
#define OTG_HS_DIEPCTLX_SD0PID (1 << 28)
#define OTG_HS_DIEPCTL0_SNAK (1 << 27)
#define OTG_HS_DIEPCTL0_CNAK (1 << 26)
#define OTG_HS_DIEPCTL0_TXFNUM_MASK (0xf << 22)
#define OTG_HS_DIEPCTL0_STALL (1 << 21)
/* Bit 20 - Reserved */
#define OTG_HS_DIEPCTL0_EPTYP_MASK (0x3 << 18)
#define OTG_HS_DIEPCTL0_NAKSTS (1 << 17)
/* Bit 16 - Reserved */
#define OTG_HS_DIEPCTL0_USBAEP (1 << 15)
/* Bits 14:2 - Reserved */
#define OTG_HS_DIEPCTL0_MPSIZ_MASK (0x3 << 0)
#define OTG_HS_DIEPCTL0_MPSIZ_64 (0x0 << 0)
#define OTG_HS_DIEPCTL0_MPSIZ_32 (0x1 << 0)
#define OTG_HS_DIEPCTL0_MPSIZ_16 (0x2 << 0)
#define OTG_HS_DIEPCTL0_MPSIZ_8 (0x3 << 0)
/* OTG_FS Device Control OUT Endpoint 0 Control Register (OTG_HS_DOEPCTL0) */
#define OTG_HS_DOEPCTL0_EPENA (1 << 31)
#define OTG_HS_DOEPCTL0_EPDIS (1 << 30)
/* Bits 29:28 - Reserved */
#define OTG_HS_DOEPCTLX_SD0PID (1 << 28)
#define OTG_HS_DOEPCTL0_SNAK (1 << 27)
#define OTG_HS_DOEPCTL0_CNAK (1 << 26)
/* Bits 25:22 - Reserved */
#define OTG_HS_DOEPCTL0_STALL (1 << 21)
#define OTG_HS_DOEPCTL0_SNPM (1 << 20)
#define OTG_HS_DOEPCTL0_EPTYP_MASK (0x3 << 18)
#define OTG_HS_DOEPCTL0_NAKSTS (1 << 17)
/* Bit 16 - Reserved */
#define OTG_HS_DOEPCTL0_USBAEP (1 << 15)
/* Bits 14:2 - Reserved */
#define OTG_HS_DOEPCTL0_MPSIZ_MASK (0x3 << 0)
#define OTG_HS_DOEPCTL0_MPSIZ_64 (0x0 << 0)
#define OTG_HS_DOEPCTL0_MPSIZ_32 (0x1 << 0)
#define OTG_HS_DOEPCTL0_MPSIZ_16 (0x2 << 0)
#define OTG_HS_DOEPCTL0_MPSIZ_8 (0x3 << 0)
/* OTG_FS Device IN Endpoint Interrupt Register (OTG_HS_DIEPINTx) */
/* Bits 31:8 - Reserved */
#define OTG_HS_DIEPINTX_TXFE (1 << 7)
#define OTG_HS_DIEPINTX_INEPNE (1 << 6)
/* Bit 5 - Reserved */
#define OTG_HS_DIEPINTX_ITTXFE (1 << 4)
#define OTG_HS_DIEPINTX_TOC (1 << 3)
/* Bit 2 - Reserved */
#define OTG_HS_DIEPINTX_EPDISD (1 << 1)
#define OTG_HS_DIEPINTX_XFRC (1 << 0)
/* OTG_FS Device IN Endpoint Interrupt Register (OTG_HS_DOEPINTx) */
/* Bits 31:7 - Reserved */
#define OTG_HS_DOEPINTX_B2BSTUP (1 << 6)
/* Bit 5 - Reserved */
#define OTG_HS_DOEPINTX_OTEPDIS (1 << 4)
#define OTG_HS_DOEPINTX_STUP (1 << 3)
/* Bit 2 - Reserved */
#define OTG_HS_DOEPINTX_EPDISD (1 << 1)
#define OTG_HS_DOEPINTX_XFRC (1 << 0)
/* OTG_FS Device OUT Endpoint 0 Transfer Size Regsiter (OTG_HS_DOEPTSIZ0) */
/* Bit 31 - Reserved */
#define OTG_HS_DIEPSIZ0_STUPCNT_1 (0x1 << 29)
#define OTG_HS_DIEPSIZ0_STUPCNT_2 (0x2 << 29)
#define OTG_HS_DIEPSIZ0_STUPCNT_3 (0x3 << 29)
#define OTG_HS_DIEPSIZ0_STUPCNT_MASK (0x3 << 29)
/* Bits 28:20 - Reserved */
#define OTG_HS_DIEPSIZ0_PKTCNT (1 << 19)
/* Bits 18:7 - Reserved */
#define OTG_HS_DIEPSIZ0_XFRSIZ_MASK (0x7f << 0)
#endif

58
include/libopencm3/usb/usbd.h

@ -25,9 +25,13 @@
BEGIN_DECLS BEGIN_DECLS
typedef struct _usbd_driver usbd_driver; typedef struct _usbd_driver usbd_driver;
typedef struct _usbd_device usbd_device;
extern const usbd_driver stm32f103_usb_driver; extern const usbd_driver stm32f103_usb_driver;
extern const usbd_driver stm32f107_usb_driver; extern const usbd_driver stm32f107_usb_driver;
extern const usbd_driver stm32f207_usb_driver;
#define otgfs_usb_driver stm32f107_usb_driver #define otgfs_usb_driver stm32f107_usb_driver
#define otghs_usb_driver stm32f207_usb_driver
/* Static buffer for control transactions: /* Static buffer for control transactions:
* This is defined as weak in the library, applicaiton * This is defined as weak in the library, applicaiton
@ -35,45 +39,55 @@ extern const usbd_driver stm32f107_usb_driver;
extern u8 usbd_control_buffer[]; extern u8 usbd_control_buffer[];
/* <usb.c> */ /* <usb.c> */
extern int usbd_init(const usbd_driver *driver, extern usbd_device *usbd_init(const usbd_driver *driver,
const struct usb_device_descriptor *dev, const struct usb_device_descriptor *dev,
const struct usb_config_descriptor *conf, const struct usb_config_descriptor *conf,
const char **strings); const char **strings);
extern void usbd_set_control_buffer_size(u16 size); extern void usbd_set_control_buffer_size(usbd_device *usbd_dev, u16 size);
extern void usbd_register_reset_callback(void (*callback)(void)); extern void usbd_register_reset_callback(usbd_device *usbd_dev,
extern void usbd_register_suspend_callback(void (*callback)(void)); void (*callback)(void));
extern void usbd_register_resume_callback(void (*callback)(void)); extern void usbd_register_suspend_callback(usbd_device *usbd_dev,
extern void usbd_register_sof_callback(void (*callback)(void)); void (*callback)(void));
extern void usbd_register_resume_callback(usbd_device *usbd_dev,
typedef int (*usbd_control_callback)(struct usb_setup_data *req, u8 **buf, void (*callback)(void));
u16 *len, void (**complete)(struct usb_setup_data *req)); extern void usbd_register_sof_callback(usbd_device *usbd_dev,
void (*callback)(void));
typedef int (*usbd_control_callback)(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf, u16 *len,
void (**complete)(usbd_device *usbd_dev,
struct usb_setup_data *req));
/* <usb_control.c> */ /* <usb_control.c> */
extern int usbd_register_control_callback(u8 type, u8 type_mask, extern int usbd_register_control_callback(usbd_device *usbd_dev, u8 type,
u8 type_mask,
usbd_control_callback callback); usbd_control_callback callback);
/* <usb_standard.c> */ /* <usb_standard.c> */
extern void usbd_register_set_config_callback(void (*callback)(u16 wValue)); extern void usbd_register_set_config_callback(usbd_device *usbd_dev,
void (*callback)(usbd_device *usbd_dev, u16 wValue));
/* Functions to be provided by the hardware abstraction layer */ /* Functions to be provided by the hardware abstraction layer */
extern void usbd_poll(void); extern void usbd_poll(usbd_device *usbd_dev);
extern void usbd_disconnect(bool disconnected); extern void usbd_disconnect(usbd_device *usbd_dev, bool disconnected);
extern void usbd_ep_setup(u8 addr, u8 type, u16 max_size, extern void usbd_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
void (*callback)(u8 ep)); void (*callback)(usbd_device *usbd_dev, u8 ep));
extern u16 usbd_ep_write_packet(u8 addr, const void *buf, u16 len); extern u16 usbd_ep_write_packet(usbd_device *usbd_dev, u8 addr,
const void *buf, u16 len);
extern u16 usbd_ep_read_packet(u8 addr, void *buf, u16 len); extern u16 usbd_ep_read_packet(usbd_device *usbd_dev, u8 addr,
void *buf, u16 len);
extern void usbd_ep_stall_set(u8 addr, u8 stall); extern void usbd_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall);
extern u8 usbd_ep_stall_get(u8 addr); extern u8 usbd_ep_stall_get(usbd_device *usbd_dev, u8 addr);
extern void usbd_ep_nak_set(u8 addr, u8 nak); extern void usbd_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak);
/* Optional */ /* Optional */
extern void usbd_cable_connect(u8 on); extern void usbd_cable_connect(usbd_device *usbd_dev, u8 on);
END_DECLS END_DECLS

3
include/libopencm3/usb/usbstd.h

@ -38,6 +38,9 @@ struct usb_setup_data {
u16 wLength; u16 wLength;
} __attribute__((packed)); } __attribute__((packed));
/* Class Definition */
#define USB_CLASS_VENDOR 0xFF
/* bmRequestType bit definitions */ /* bmRequestType bit definitions */
#define USB_REQ_TYPE_IN 0x80 #define USB_REQ_TYPE_IN 0x80
#define USB_REQ_TYPE_STANDARD 0x00 #define USB_REQ_TYPE_STANDARD 0x00

3
lib/stm32/f1/Makefile

@ -31,7 +31,8 @@ ARFLAGS = rcs
OBJS = rcc.o gpio.o usart.o adc.o spi.o flash.o \ OBJS = rcc.o gpio.o usart.o adc.o spi.o flash.o \
rtc.o i2c.o dma.o exti.o ethernet.o \ rtc.o i2c.o dma.o exti.o ethernet.o \
usb_f103.o usb.o usb_control.o usb_standard.o can.o \ usb_f103.o usb.o usb_control.o usb_standard.o can.o \
timer.o usb_f107.o desig.o crc.o dac.o iwdg.o pwr.o timer.o usb_f107.o desig.o crc.o dac.o iwdg.o pwr.o \
usb_fx07_common.o
VPATH += ../../usb:../:../../cm3 VPATH += ../../usb:../:../../cm3

2
lib/stm32/f2/gpio.c

@ -86,7 +86,7 @@ void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios)
for (i = 8; i < 16; i++) { for (i = 8; i < 16; i++) {
if (!((1 << i) & gpios)) if (!((1 << i) & gpios))
continue; continue;
afrl &= ~GPIO_AFR_MASK(i - 8); afrh &= ~GPIO_AFR_MASK(i - 8);
afrh |= GPIO_AFR(i - 8, alt_func_num); afrh |= GPIO_AFR(i - 8, alt_func_num);
} }

3
lib/stm32/f4/Makefile

@ -31,7 +31,8 @@ CFLAGS = -Os -g -Wall -Wextra -I../../../include -fno-common \
ARFLAGS = rcs ARFLAGS = rcs
OBJS = rcc.o gpio.o usart.o spi.o flash.o \ OBJS = rcc.o gpio.o usart.o spi.o flash.o \
i2c.o exti.o pwr.o timer.o \ i2c.o exti.o pwr.o timer.o \
usb.o usb_standard.o usb_control.o usb_f107.o usb.o usb_standard.o usb_control.o usb_fx07_common.o usb_f107.o \
usb_f207.o
VPATH += ../../usb:../:../../cm3 VPATH += ../../usb:../:../../cm3

2
lib/stm32/f4/gpio.c

@ -86,7 +86,7 @@ void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios)
for (i = 8; i < 16; i++) { for (i = 8; i < 16; i++) {
if (!((1 << i) & gpios)) if (!((1 << i) & gpios))
continue; continue;
afrl &= ~GPIO_AFR_MASK(i - 8); afrh &= ~GPIO_AFR_MASK(i - 8);
afrh |= GPIO_AFR(i - 8, alt_func_num); afrh |= GPIO_AFR(i - 8, alt_func_num);
} }

103
lib/usb/usb.c

@ -21,8 +21,6 @@
#include <libopencm3/usb/usbd.h> #include <libopencm3/usb/usbd.h>
#include "usb_private.h" #include "usb_private.h"
struct _usbd_device _usbd_device;
u8 usbd_control_buffer[128] __attribute__((weak)); u8 usbd_control_buffer[128] __attribute__((weak));
/** /**
@ -43,104 +41,111 @@ u8 usbd_control_buffer[128] __attribute__((weak));
* @param strings TODO * @param strings TODO
* @return Zero on success (currently cannot fail). * @return Zero on success (currently cannot fail).
*/ */
int usbd_init(const usbd_driver *driver, usbd_device *usbd_init(const usbd_driver *driver,
const struct usb_device_descriptor *dev, const struct usb_device_descriptor *dev,
const struct usb_config_descriptor *conf, const char **strings) const struct usb_config_descriptor *conf,
const char **strings)
{ {
_usbd_device.driver = driver; usbd_device *usbd_dev;
_usbd_device.desc = dev;
_usbd_device.config = conf; usbd_dev = driver->init();
_usbd_device.strings = strings;
_usbd_device.ctrl_buf = usbd_control_buffer;
_usbd_device.ctrl_buf_len = sizeof(usbd_control_buffer);
_usbd_hw_init(); usbd_dev->driver = driver;
usbd_dev->desc = dev;
usbd_dev->config = conf;
usbd_dev->strings = strings;
usbd_dev->ctrl_buf = usbd_control_buffer;
usbd_dev->ctrl_buf_len = sizeof(usbd_control_buffer);
_usbd_device.user_callback_ctr[0][USB_TRANSACTION_SETUP] = usbd_dev->user_callback_ctr[0][USB_TRANSACTION_SETUP] =
_usbd_control_setup; _usbd_control_setup;
_usbd_device.user_callback_ctr[0][USB_TRANSACTION_OUT] = usbd_dev->user_callback_ctr[0][USB_TRANSACTION_OUT] =
_usbd_control_out; _usbd_control_out;
_usbd_device.user_callback_ctr[0][USB_TRANSACTION_IN] = usbd_dev->user_callback_ctr[0][USB_TRANSACTION_IN] =
_usbd_control_in; _usbd_control_in;
return 0; return usbd_dev;
} }
void usbd_register_reset_callback(void (*callback)(void)) void usbd_register_reset_callback(usbd_device *usbd_dev, void (*callback)(void))
{ {
_usbd_device.user_callback_reset = callback; usbd_dev->user_callback_reset = callback;
} }
void usbd_register_suspend_callback(void (*callback)(void)) void usbd_register_suspend_callback(usbd_device *usbd_dev,
void (*callback)(void))
{ {
_usbd_device.user_callback_suspend = callback; usbd_dev->user_callback_suspend = callback;
} }
void usbd_register_resume_callback(void (*callback)(void)) void usbd_register_resume_callback(usbd_device *usbd_dev,
void (*callback)(void))
{ {
_usbd_device.user_callback_resume = callback; usbd_dev->user_callback_resume = callback;
} }
void usbd_register_sof_callback(void (*callback)(void)) void usbd_register_sof_callback(usbd_device *usbd_dev, void (*callback)(void))
{ {
_usbd_device.user_callback_sof = callback; usbd_dev->user_callback_sof = callback;
} }
void usbd_set_control_buffer_size(u16 size) void usbd_set_control_buffer_size(usbd_device *usbd_dev, u16 size)
{ {
_usbd_device.ctrl_buf_len = size; usbd_dev->ctrl_buf_len = size;
} }
void _usbd_reset(void) void _usbd_reset(usbd_device *usbd_dev)
{ {
_usbd_device.current_address = 0; usbd_dev->current_address = 0;
_usbd_device.current_config = 0; usbd_dev->current_config = 0;
usbd_ep_setup(0, USB_ENDPOINT_ATTR_CONTROL, 64, NULL); usbd_ep_setup(usbd_dev, 0, USB_ENDPOINT_ATTR_CONTROL, 64, NULL);
_usbd_hw_set_address(0); usbd_dev->driver->set_address(usbd_dev, 0);
if (_usbd_device.user_callback_reset) if (usbd_dev->user_callback_reset)
_usbd_device.user_callback_reset(); usbd_dev->user_callback_reset();
} }
/* Functions to wrap the low-level driver */ /* Functions to wrap the low-level driver */
void usbd_poll(void) void usbd_poll(usbd_device *usbd_dev)
{ {
_usbd_device.driver->poll(); usbd_dev->driver->poll(usbd_dev);
} }
void usbd_disconnect(bool disconnected) void usbd_disconnect(usbd_device *usbd_dev, bool disconnected)
{ {
/* not all drivers support disconnection */ /* not all drivers support disconnection */
if (_usbd_device.driver->disconnect) if (usbd_dev->driver->disconnect)
_usbd_device.driver->disconnect(disconnected); usbd_dev->driver->disconnect(usbd_dev, disconnected);
} }
void usbd_ep_setup(u8 addr, u8 type, u16 max_size, void (*callback)(u8 ep)) void usbd_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
void (*callback)(usbd_device *usbd_dev, u8 ep))
{ {
_usbd_device.driver->ep_setup(addr, type, max_size, callback); usbd_dev->driver->ep_setup(usbd_dev, addr, type, max_size, callback);
} }
u16 usbd_ep_write_packet(u8 addr, const void *buf, u16 len) u16 usbd_ep_write_packet(usbd_device *usbd_dev, u8 addr,
const void *buf, u16 len)
{ {
return _usbd_device.driver->ep_write_packet(addr, buf, len); return usbd_dev->driver->ep_write_packet(usbd_dev, addr, buf, len);
} }
u16 usbd_ep_read_packet(u8 addr, void *buf, u16 len) u16 usbd_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf, u16 len)
{ {
return _usbd_device.driver->ep_read_packet(addr, buf, len); return usbd_dev->driver->ep_read_packet(usbd_dev, addr, buf, len);
} }
void usbd_ep_stall_set(u8 addr, u8 stall) void usbd_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall)
{ {
_usbd_device.driver->ep_stall_set(addr, stall); usbd_dev->driver->ep_stall_set(usbd_dev, addr, stall);
} }
u8 usbd_ep_stall_get(u8 addr) u8 usbd_ep_stall_get(usbd_device *usbd_dev, u8 addr)
{ {
return _usbd_device.driver->ep_stall_get(addr); return usbd_dev->driver->ep_stall_get(usbd_dev, addr);
} }
void usbd_ep_nak_set(u8 addr, u8 nak) void usbd_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak)
{ {
_usbd_device.driver->ep_nak_set(addr, nak); usbd_dev->driver->ep_nak_set(usbd_dev, addr, nak);
} }

194
lib/usb/usb_control.c

@ -21,77 +21,73 @@
#include <libopencm3/usb/usbd.h> #include <libopencm3/usb/usbd.h>
#include "usb_private.h" #include "usb_private.h"
static struct usb_control_state {
enum {
IDLE, STALLED,
DATA_IN, LAST_DATA_IN, STATUS_IN,
DATA_OUT, LAST_DATA_OUT, STATUS_OUT,
} state;
struct usb_setup_data req;
u8 *ctrl_buf;
u16 ctrl_len;
void (*complete)(struct usb_setup_data *req);
} control_state;
/* Register application callback function for handling USB control requests. */ /* Register application callback function for handling USB control requests. */
int usbd_register_control_callback(u8 type, u8 type_mask, int usbd_register_control_callback(usbd_device *usbd_dev, u8 type, u8 type_mask,
usbd_control_callback callback) usbd_control_callback callback)
{ {
int i; int i;
for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++) { for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++) {
if (_usbd_device.user_control_callback[i].cb) if (usbd_dev->user_control_callback[i].cb)
continue; continue;
_usbd_device.user_control_callback[i].type = type; usbd_dev->user_control_callback[i].type = type;
_usbd_device.user_control_callback[i].type_mask = type_mask; usbd_dev->user_control_callback[i].type_mask = type_mask;
_usbd_device.user_control_callback[i].cb = callback; usbd_dev->user_control_callback[i].cb = callback;
return 0; return 0;
} }
return -1; return -1;
} }
static void usb_control_send_chunk(void) static void usb_control_send_chunk(usbd_device *usbd_dev)
{ {
if (_usbd_device.desc->bMaxPacketSize0 < control_state.ctrl_len) { if (usbd_dev->desc->bMaxPacketSize0 < usbd_dev->control_state.ctrl_len) {
/* Data stage, normal transmission */ /* Data stage, normal transmission */
usbd_ep_write_packet(0, control_state.ctrl_buf, usbd_ep_write_packet(usbd_dev, 0,
_usbd_device.desc->bMaxPacketSize0); usbd_dev->control_state.ctrl_buf,
control_state.state = DATA_IN; usbd_dev->desc->bMaxPacketSize0);
control_state.ctrl_buf += _usbd_device.desc->bMaxPacketSize0; usbd_dev->control_state.state = DATA_IN;
control_state.ctrl_len -= _usbd_device.desc->bMaxPacketSize0; usbd_dev->control_state.ctrl_buf +=
usbd_dev->desc->bMaxPacketSize0;
usbd_dev->control_state.ctrl_len -=
usbd_dev->desc->bMaxPacketSize0;
} else { } else {
/* Data stage, end of transmission */ /* Data stage, end of transmission */
usbd_ep_write_packet(0, control_state.ctrl_buf, usbd_ep_write_packet(usbd_dev, 0,
control_state.ctrl_len); usbd_dev->control_state.ctrl_buf,
control_state.state = LAST_DATA_IN; usbd_dev->control_state.ctrl_len);
control_state.ctrl_len = 0; usbd_dev->control_state.state = LAST_DATA_IN;
control_state.ctrl_buf = NULL; usbd_dev->control_state.ctrl_len = 0;
usbd_dev->control_state.ctrl_buf = NULL;
} }
} }
static int usb_control_recv_chunk(void) static int usb_control_recv_chunk(usbd_device *usbd_dev)
{ {
u16 packetsize = MIN(_usbd_device.desc->bMaxPacketSize0, u16 packetsize = MIN(usbd_dev->desc->bMaxPacketSize0,
control_state.req.wLength - control_state.ctrl_len); usbd_dev->control_state.req.wLength -
u16 size = usbd_ep_read_packet(0, control_state.ctrl_buf + usbd_dev->control_state.ctrl_len);
control_state.ctrl_len, packetsize); u16 size = usbd_ep_read_packet(usbd_dev, 0,
usbd_dev->control_state.ctrl_buf +
usbd_dev->control_state.ctrl_len,
packetsize);
if (size != packetsize) { if (size != packetsize) {
usbd_ep_stall_set(0, 1); usbd_ep_stall_set(usbd_dev, 0, 1);
return -1; return -1;
} }
control_state.ctrl_len += size; usbd_dev->control_state.ctrl_len += size;
return packetsize; return packetsize;
} }
static int usb_control_request_dispatch(struct usb_setup_data *req) static int usb_control_request_dispatch(usbd_device *usbd_dev,
struct usb_setup_data *req)
{ {
int i, result = 0; int i, result = 0;
struct user_control_callback *cb = _usbd_device.user_control_callback; struct user_control_callback *cb = usbd_dev->user_control_callback;
/* Call user command hook function. */ /* Call user command hook function. */
for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++) { for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++) {
@ -99,140 +95,148 @@ static int usb_control_request_dispatch(struct usb_setup_data *req)
break; break;
if ((req->bmRequestType & cb[i].type_mask) == cb[i].type) { if ((req->bmRequestType & cb[i].type_mask) == cb[i].type) {
result = cb[i].cb(req, &control_state.ctrl_buf, result = cb[i].cb(usbd_dev, req,
&control_state.ctrl_len, &(usbd_dev->control_state.ctrl_buf),
&control_state.complete); &(usbd_dev->control_state.ctrl_len),
&(usbd_dev->control_state.complete));
if (result) if (result)
return result; return result;
} }
} }
/* Try standard request if not already handled. */ /* Try standard request if not already handled. */
return _usbd_standard_request(req, &control_state.ctrl_buf, return _usbd_standard_request(usbd_dev, req,
&control_state.ctrl_len); &(usbd_dev->control_state.ctrl_buf),
&(usbd_dev->control_state.ctrl_len));
} }
/* Handle commands and read requests. */ /* Handle commands and read requests. */
static void usb_control_setup_read(struct usb_setup_data *req) static void usb_control_setup_read(usbd_device *usbd_dev,
struct usb_setup_data *req)
{ {
control_state.ctrl_buf = _usbd_device.ctrl_buf; usbd_dev->control_state.ctrl_buf = usbd_dev->ctrl_buf;
control_state.ctrl_len = req->wLength; usbd_dev->control_state.ctrl_len = req->wLength;
if (usb_control_request_dispatch(req)) { if (usb_control_request_dispatch(usbd_dev, req)) {
if (control_state.ctrl_len) { if (usbd_dev->control_state.ctrl_len) {
/* Go to data out stage if handled. */ /* Go to data out stage if handled. */
usb_control_send_chunk(); usb_control_send_chunk(usbd_dev);
} else { } else {
/* Go to status stage if handled. */ /* Go to status stage if handled. */
usbd_ep_write_packet(0, NULL, 0); usbd_ep_write_packet(usbd_dev, 0, NULL, 0);
control_state.state = STATUS_IN; usbd_dev->control_state.state = STATUS_IN;
} }
} else { } else {
/* Stall endpoint on failure. */ /* Stall endpoint on failure. */
usbd_ep_stall_set(0, 1); usbd_ep_stall_set(usbd_dev, 0, 1);
} }
} }
static void usb_control_setup_write(struct usb_setup_data *req) static void usb_control_setup_write(usbd_device *usbd_dev,
struct usb_setup_data *req)
{ {
if (req->wLength > _usbd_device.ctrl_buf_len) { if (req->wLength > usbd_dev->ctrl_buf_len) {
usbd_ep_stall_set(0, 1); usbd_ep_stall_set(usbd_dev, 0, 1);
return; return;
} }
/* Buffer into which to write received data. */ /* Buffer into which to write received data. */
control_state.ctrl_buf = _usbd_device.ctrl_buf; usbd_dev->control_state.ctrl_buf = usbd_dev->ctrl_buf;
control_state.ctrl_len = 0; usbd_dev->control_state.ctrl_len = 0;
/* Wait for DATA OUT stage. */ /* Wait for DATA OUT stage. */
if (req->wLength > _usbd_device.desc->bMaxPacketSize0) if (req->wLength > usbd_dev->desc->bMaxPacketSize0)
control_state.state = DATA_OUT; usbd_dev->control_state.state = DATA_OUT;
else else
control_state.state = LAST_DATA_OUT; usbd_dev->control_state.state = LAST_DATA_OUT;
} }
void _usbd_control_setup(u8 ea) void _usbd_control_setup(usbd_device *usbd_dev, u8 ea)
{ {
struct usb_setup_data *req = &control_state.req; struct usb_setup_data *req = &usbd_dev->control_state.req;
(void)ea; (void)ea;
control_state.complete = NULL; usbd_dev->control_state.complete = NULL;
if (usbd_ep_read_packet(0, req, 8) != 8) { if (usbd_ep_read_packet(usbd_dev, 0, req, 8) != 8) {
usbd_ep_stall_set(0, 1); usbd_ep_stall_set(usbd_dev, 0, 1);
return; return;
} }
if (req->wLength == 0) { if (req->wLength == 0) {
usb_control_setup_read(req); usb_control_setup_read(usbd_dev, req);
} else if (req->bmRequestType & 0x80) { } else if (req->bmRequestType & 0x80) {
usb_control_setup_read(req); usb_control_setup_read(usbd_dev, req);
} else { } else {
usb_control_setup_write(req); usb_control_setup_write(usbd_dev, req);
} }
} }
void _usbd_control_out(u8 ea) void _usbd_control_out(usbd_device *usbd_dev, u8 ea)
{ {
(void)ea; (void)ea;
switch (control_state.state) { switch (usbd_dev->control_state.state) {
case DATA_OUT: case DATA_OUT:
if (usb_control_recv_chunk() < 0) if (usb_control_recv_chunk(usbd_dev) < 0)
break; break;
if ((control_state.req.wLength - control_state.ctrl_len) <= if ((usbd_dev->control_state.req.wLength -
_usbd_device.desc->bMaxPacketSize0) usbd_dev->control_state.ctrl_len) <=
control_state.state = LAST_DATA_OUT; usbd_dev->desc->bMaxPacketSize0)
usbd_dev->control_state.state = LAST_DATA_OUT;
break; break;
case LAST_DATA_OUT: case LAST_DATA_OUT:
if (usb_control_recv_chunk() < 0) if (usb_control_recv_chunk(usbd_dev) < 0)
break; break;
/* /*
* We have now received the full data payload. * We have now received the full data payload.
* Invoke callback to process. * Invoke callback to process.
*/ */
if (usb_control_request_dispatch(&control_state.req)) { if (usb_control_request_dispatch(usbd_dev,
&(usbd_dev->control_state.req))) {
/* Got to status stage on success. */ /* Got to status stage on success. */
usbd_ep_write_packet(0, NULL, 0); usbd_ep_write_packet(usbd_dev, 0, NULL, 0);
control_state.state = STATUS_IN; usbd_dev->control_state.state = STATUS_IN;
} else { } else {
usbd_ep_stall_set(0, 1); usbd_ep_stall_set(usbd_dev, 0, 1);
} }
break; break;
case STATUS_OUT: case STATUS_OUT:
usbd_ep_read_packet(0, NULL, 0); usbd_ep_read_packet(usbd_dev, 0, NULL, 0);
control_state.state = IDLE; usbd_dev->control_state.state = IDLE;
if (control_state.complete) if (usbd_dev->control_state.complete)
control_state.complete(&control_state.req); usbd_dev->control_state.complete(usbd_dev,
control_state.complete = NULL; &(usbd_dev->control_state.req));
usbd_dev->control_state.complete = NULL;
break; break;
default: default:
usbd_ep_stall_set(0, 1); usbd_ep_stall_set(usbd_dev, 0, 1);
} }
} }
void _usbd_control_in(u8 ea) void _usbd_control_in(usbd_device *usbd_dev, u8 ea)
{ {
(void)ea; (void)ea;
struct usb_setup_data *req = &control_state.req; struct usb_setup_data *req = &(usbd_dev->control_state.req);
switch (control_state.state) { switch (usbd_dev->control_state.state) {
case DATA_IN: case DATA_IN:
usb_control_send_chunk(); usb_control_send_chunk(usbd_dev);
break; break;
case LAST_DATA_IN: case LAST_DATA_IN:
control_state.state = STATUS_OUT; usbd_dev->control_state.state = STATUS_OUT;
break; break;
case STATUS_IN: case STATUS_IN:
if (control_state.complete) if (usbd_dev->control_state.complete)
control_state.complete(&control_state.req); usbd_dev->control_state.complete(usbd_dev,
&(usbd_dev->control_state.req));
/* Exception: Handle SET ADDRESS function here... */ /* Exception: Handle SET ADDRESS function here... */
if ((req->bmRequestType == 0) && if ((req->bmRequestType == 0) &&
(req->bRequest == USB_REQ_SET_ADDRESS)) (req->bRequest == USB_REQ_SET_ADDRESS))
_usbd_hw_set_address(req->wValue); usbd_dev->driver->set_address(usbd_dev, req->wValue);
control_state.state = IDLE; usbd_dev->control_state.state = IDLE;
break; break;
default: default:
usbd_ep_stall_set(0, 1); usbd_ep_stall_set(usbd_dev, 0, 1);
} }
} }

99
lib/usb/usb_f103.c

@ -24,19 +24,23 @@
#include <libopencm3/usb/usbd.h> #include <libopencm3/usb/usbd.h>
#include "usb_private.h" #include "usb_private.h"
static void stm32f103_usbd_init(void); static usbd_device *stm32f103_usbd_init(void);
static void stm32f103_set_address(u8 addr); static void stm32f103_set_address(usbd_device *usbd_dev, u8 addr);
static void stm32f103_ep_setup(u8 addr, u8 type, u16 max_size, static void stm32f103_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type,
void (*callback) (u8 ep)); u16 max_size,
static void stm32f103_endpoints_reset(void); void (*callback) (usbd_device *usbd_dev, u8 ep));
static void stm32f103_ep_stall_set(u8 addr, u8 stall); static void stm32f103_endpoints_reset(usbd_device *usbd_dev);
static u8 stm32f103_ep_stall_get(u8 addr); static void stm32f103_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall);
static void stm32f103_ep_nak_set(u8 addr, u8 nak); static u8 stm32f103_ep_stall_get(usbd_device *usbd_dev, u8 addr);
static u16 stm32f103_ep_write_packet(u8 addr, const void *buf, u16 len); static void stm32f103_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak);
static u16 stm32f103_ep_read_packet(u8 addr, void *buf, u16 len); static u16 stm32f103_ep_write_packet(usbd_device *usbd_dev, u8 addr,
static void stm32f103_poll(void); const void *buf, u16 len);
static u16 stm32f103_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf,
u16 len);
static void stm32f103_poll(usbd_device *usbd_dev);
static u8 force_nak[8]; static u8 force_nak[8];
static struct _usbd_device usbd_dev;
const struct _usbd_driver stm32f103_usb_driver = { const struct _usbd_driver stm32f103_usb_driver = {
.init = stm32f103_usbd_init, .init = stm32f103_usbd_init,
@ -52,7 +56,7 @@ const struct _usbd_driver stm32f103_usb_driver = {
}; };
/** Initialize the USB device controller hardware of the STM32. */ /** Initialize the USB device controller hardware of the STM32. */
static void stm32f103_usbd_init(void) static usbd_device *stm32f103_usbd_init(void)
{ {
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN);
SET_REG(USB_CNTR_REG, 0); SET_REG(USB_CNTR_REG, 0);
@ -62,10 +66,12 @@ static void stm32f103_usbd_init(void)
/* Enable RESET, SUSPEND, RESUME and CTR interrupts. */ /* Enable RESET, SUSPEND, RESUME and CTR interrupts. */
SET_REG(USB_CNTR_REG, USB_CNTR_RESETM | USB_CNTR_CTRM | SET_REG(USB_CNTR_REG, USB_CNTR_RESETM | USB_CNTR_CTRM |
USB_CNTR_SUSPM | USB_CNTR_WKUPM); USB_CNTR_SUSPM | USB_CNTR_WKUPM);
return &usbd_dev;
} }
static void stm32f103_set_address(u8 addr) static void stm32f103_set_address(usbd_device *usbd_dev, u8 addr)
{ {
(void)usbd_dev;
/* Set device address and enable. */ /* Set device address and enable. */
SET_REG(USB_DADDR_REG, (addr & USB_DADDR_ADDR) | USB_DADDR_ENABLE); SET_REG(USB_DADDR_REG, (addr & USB_DADDR_ADDR) | USB_DADDR_ENABLE);
} }
@ -76,8 +82,9 @@ static void stm32f103_set_address(u8 addr)
* @param ep Index of endpoint to configure. * @param ep Index of endpoint to configure.
* @param size Size in bytes of the RX buffer. * @param size Size in bytes of the RX buffer.
*/ */
static void usb_set_ep_rx_bufsize(u8 ep, u32 size) static void usb_set_ep_rx_bufsize(usbd_device *usbd_dev, u8 ep, u32 size)
{ {
(void)usbd_dev;
if (size > 62) { if (size > 62) {
if (size & 0x1f) if (size & 0x1f)
size -= 32; size -= 32;
@ -89,8 +96,9 @@ static void usb_set_ep_rx_bufsize(u8 ep, u32 size)
} }
} }
static void stm32f103_ep_setup(u8 addr, u8 type, u16 max_size, static void stm32f103_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type,
void (*callback) (u8 ep)) u16 max_size,
void (*callback) (usbd_device *usbd_dev, u8 ep))
{ {
/* Translate USB standard type codes to STM32. */ /* Translate USB standard type codes to STM32. */
const u16 typelookup[] = { const u16 typelookup[] = {
@ -107,32 +115,30 @@ static void stm32f103_ep_setup(u8 addr, u8 type, u16 max_size,
USB_SET_EP_TYPE(addr, typelookup[type]); USB_SET_EP_TYPE(addr, typelookup[type]);
if (dir || (addr == 0)) { if (dir || (addr == 0)) {
USB_SET_EP_TX_ADDR(addr, _usbd_device.pm_top); USB_SET_EP_TX_ADDR(addr, usbd_dev->pm_top);
if (callback) { if (callback) {
_usbd_device. usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_IN] =
user_callback_ctr[addr][USB_TRANSACTION_IN] =
(void *)callback; (void *)callback;
} }
USB_CLR_EP_TX_DTOG(addr); USB_CLR_EP_TX_DTOG(addr);
USB_SET_EP_TX_STAT(addr, USB_EP_TX_STAT_NAK); USB_SET_EP_TX_STAT(addr, USB_EP_TX_STAT_NAK);
_usbd_device.pm_top += max_size; usbd_dev->pm_top += max_size;
} }
if (!dir) { if (!dir) {
USB_SET_EP_RX_ADDR(addr, _usbd_device.pm_top); USB_SET_EP_RX_ADDR(addr, usbd_dev->pm_top);
usb_set_ep_rx_bufsize(addr, max_size); usb_set_ep_rx_bufsize(usbd_dev, addr, max_size);
if (callback) { if (callback) {
_usbd_device. usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_OUT] =
user_callback_ctr[addr][USB_TRANSACTION_OUT] =
(void *)callback; (void *)callback;
} }
USB_CLR_EP_RX_DTOG(addr); USB_CLR_EP_RX_DTOG(addr);
USB_SET_EP_RX_STAT(addr, USB_EP_RX_STAT_VALID); USB_SET_EP_RX_STAT(addr, USB_EP_RX_STAT_VALID);
_usbd_device.pm_top += max_size; usbd_dev->pm_top += max_size;
} }
} }
static void stm32f103_endpoints_reset(void) static void stm32f103_endpoints_reset(usbd_device *usbd_dev)
{ {
int i; int i;
@ -141,11 +147,12 @@ static void stm32f103_endpoints_reset(void)
USB_SET_EP_TX_STAT(i, USB_EP_TX_STAT_DISABLED); USB_SET_EP_TX_STAT(i, USB_EP_TX_STAT_DISABLED);
USB_SET_EP_RX_STAT(i, USB_EP_RX_STAT_DISABLED); USB_SET_EP_RX_STAT(i, USB_EP_RX_STAT_DISABLED);
} }
_usbd_device.pm_top = 0x40 + (2 * _usbd_device.desc->bMaxPacketSize0); usbd_dev->pm_top = 0x40 + (2 * usbd_dev->desc->bMaxPacketSize0);
} }
static void stm32f103_ep_stall_set(u8 addr, u8 stall) static void stm32f103_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall)
{ {
(void)usbd_dev;
if (addr == 0) if (addr == 0)
USB_SET_EP_TX_STAT(addr, stall ? USB_EP_TX_STAT_STALL : USB_SET_EP_TX_STAT(addr, stall ? USB_EP_TX_STAT_STALL :
USB_EP_TX_STAT_NAK); USB_EP_TX_STAT_NAK);
@ -169,8 +176,9 @@ static void stm32f103_ep_stall_set(u8 addr, u8 stall)
} }
} }
static u8 stm32f103_ep_stall_get(u8 addr) static u8 stm32f103_ep_stall_get(usbd_device *usbd_dev, u8 addr)
{ {
(void)usbd_dev;
if (addr & 0x80) { if (addr & 0x80) {
if ((*USB_EP_REG(addr & 0x7F) & USB_EP_TX_STAT) == if ((*USB_EP_REG(addr & 0x7F) & USB_EP_TX_STAT) ==
USB_EP_TX_STAT_STALL) USB_EP_TX_STAT_STALL)
@ -183,8 +191,9 @@ static u8 stm32f103_ep_stall_get(u8 addr)
return 0; return 0;
} }
static void stm32f103_ep_nak_set(u8 addr, u8 nak) static void stm32f103_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak)
{ {
(void)usbd_dev;
/* It does not make sence to force NAK on IN endpoints. */ /* It does not make sence to force NAK on IN endpoints. */
if (addr & 0x80) if (addr & 0x80)
return; return;
@ -213,8 +222,10 @@ static void usb_copy_to_pm(volatile void *vPM, const void *buf, u16 len)
*PM = *lbuf; *PM = *lbuf;
} }
static u16 stm32f103_ep_write_packet(u8 addr, const void *buf, u16 len) static u16 stm32f103_ep_write_packet(usbd_device *usbd_dev, u8 addr,
const void *buf, u16 len)
{ {
(void)usbd_dev;
addr &= 0x7F; addr &= 0x7F;
if ((*USB_EP_REG(addr) & USB_EP_TX_STAT) == USB_EP_TX_STAT_VALID) if ((*USB_EP_REG(addr) & USB_EP_TX_STAT) == USB_EP_TX_STAT_VALID)
@ -247,8 +258,10 @@ static void usb_copy_from_pm(void *buf, const volatile void *vPM, u16 len)
*(u8 *) lbuf = *(u8 *) PM; *(u8 *) lbuf = *(u8 *) PM;
} }
static u16 stm32f103_ep_read_packet(u8 addr, void *buf, u16 len) static u16 stm32f103_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf,
u16 len)
{ {
(void)usbd_dev;
if ((*USB_EP_REG(addr) & USB_EP_RX_STAT) == USB_EP_RX_STAT_VALID) if ((*USB_EP_REG(addr) & USB_EP_RX_STAT) == USB_EP_RX_STAT_VALID)
return 0; return 0;
@ -262,13 +275,13 @@ static u16 stm32f103_ep_read_packet(u8 addr, void *buf, u16 len)
return len; return len;
} }
static void stm32f103_poll(void) static void stm32f103_poll(usbd_device *usbd_dev)
{ {
u16 istr = *USB_ISTR_REG; u16 istr = *USB_ISTR_REG;
if (istr & USB_ISTR_RESET) { if (istr & USB_ISTR_RESET) {
_usbd_device.pm_top = 0x40; usbd_dev->pm_top = 0x40;
_usbd_reset(); _usbd_reset(usbd_dev);
USB_CLR_ISTR_RESET(); USB_CLR_ISTR_RESET();
return; return;
} }
@ -282,27 +295,27 @@ static void stm32f103_poll(void)
else /* IN transaction */ else /* IN transaction */
USB_CLR_EP_TX_CTR(ep); USB_CLR_EP_TX_CTR(ep);
if (_usbd_device.user_callback_ctr[ep][type]) if (usbd_dev->user_callback_ctr[ep][type])
_usbd_device.user_callback_ctr[ep][type] (ep); usbd_dev->user_callback_ctr[ep][type] (usbd_dev, ep);
else else
USB_CLR_EP_RX_CTR(ep); USB_CLR_EP_RX_CTR(ep);
} }
if (istr & USB_ISTR_SUSP) { if (istr & USB_ISTR_SUSP) {
USB_CLR_ISTR_SUSP(); USB_CLR_ISTR_SUSP();
if (_usbd_device.user_callback_suspend) if (usbd_dev->user_callback_suspend)
_usbd_device.user_callback_suspend(); usbd_dev->user_callback_suspend();
} }
if (istr & USB_ISTR_WKUP) { if (istr & USB_ISTR_WKUP) {
USB_CLR_ISTR_WKUP(); USB_CLR_ISTR_WKUP();
if (_usbd_device.user_callback_resume) if (usbd_dev->user_callback_resume)
_usbd_device.user_callback_resume(); usbd_dev->user_callback_resume();
} }
if (istr & USB_ISTR_SOF) { if (istr & USB_ISTR_SOF) {
if (_usbd_device.user_callback_sof) if (usbd_dev->user_callback_sof)
_usbd_device.user_callback_sof(); usbd_dev->user_callback_sof();
USB_CLR_ISTR_SOF(); USB_CLR_ISTR_SOF();
} }
} }

338
lib/usb/usb_f107.c

@ -23,49 +23,34 @@
#include <libopencm3/stm32/otg_fs.h> #include <libopencm3/stm32/otg_fs.h>
#include <libopencm3/usb/usbd.h> #include <libopencm3/usb/usbd.h>
#include "usb_private.h" #include "usb_private.h"
#include "usb_fx07_common.h"
/* Receive FIFO size in 32-bit words. */ /* Receive FIFO size in 32-bit words. */
#define RX_FIFO_SIZE 128 #define RX_FIFO_SIZE 128
static uint16_t fifo_mem_top;
static uint16_t fifo_mem_top_ep0;
static u8 force_nak[4]; static usbd_device *stm32f107_usbd_init(void);
static void stm32f107_usbd_init(void); static struct _usbd_device usbd_dev;
static void stm32f107_set_address(u8 addr);
static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
void (*callback)(u8 ep));
static void stm32f107_endpoints_reset(void);
static void stm32f107_ep_stall_set(u8 addr, u8 stall);
static u8 stm32f107_ep_stall_get(u8 addr);
static void stm32f107_ep_nak_set(u8 addr, u8 nak);
static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len);
static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len);
static void stm32f107_poll(void);
static void stm32f107_disconnect(bool disconnected);
/*
* We keep a backup copy of the out endpoint size registers to restore them
* after a transaction.
*/
static u32 doeptsiz[4];
const struct _usbd_driver stm32f107_usb_driver = { const struct _usbd_driver stm32f107_usb_driver = {
.init = stm32f107_usbd_init, .init = stm32f107_usbd_init,
.set_address = stm32f107_set_address, .set_address = stm32fx07_set_address,
.ep_setup = stm32f107_ep_setup, .ep_setup = stm32fx07_ep_setup,
.ep_reset = stm32f107_endpoints_reset, .ep_reset = stm32fx07_endpoints_reset,
.ep_stall_set = stm32f107_ep_stall_set, .ep_stall_set = stm32fx07_ep_stall_set,
.ep_stall_get = stm32f107_ep_stall_get, .ep_stall_get = stm32fx07_ep_stall_get,
.ep_nak_set = stm32f107_ep_nak_set, .ep_nak_set = stm32fx07_ep_nak_set,
.ep_write_packet = stm32f107_ep_write_packet, .ep_write_packet = stm32fx07_ep_write_packet,
.ep_read_packet = stm32f107_ep_read_packet, .ep_read_packet = stm32fx07_ep_read_packet,
.poll = stm32f107_poll, .poll = stm32fx07_poll,
.disconnect = stm32f107_disconnect, .disconnect = stm32fx07_disconnect,
.base_address = USB_OTG_FS_BASE,
.set_address_before_status = 1,
.rx_fifo_size = RX_FIFO_SIZE,
}; };
/** Initialize the USB device controller hardware of the STM32. */ /** Initialize the USB device controller hardware of the STM32. */
static void stm32f107_usbd_init(void) static usbd_device *stm32f107_usbd_init(void)
{ {
OTG_FS_GINTSTS = OTG_FS_GINTSTS_MMIS; OTG_FS_GINTSTS = OTG_FS_GINTSTS_MMIS;
@ -88,8 +73,8 @@ static void stm32f107_usbd_init(void)
/* Restart the PHY clock. */ /* Restart the PHY clock. */
OTG_FS_PCGCCTL = 0; OTG_FS_PCGCCTL = 0;
OTG_FS_GRXFSIZ = RX_FIFO_SIZE; OTG_FS_GRXFSIZ = stm32f107_usb_driver.rx_fifo_size;
fifo_mem_top = RX_FIFO_SIZE; usbd_dev.fifo_mem_top = stm32f107_usb_driver.rx_fifo_size;
/* Unmask interrupts for TX and RX. */ /* Unmask interrupts for TX and RX. */
OTG_FS_GAHBCFG |= OTG_FS_GAHBCFG_GINT; OTG_FS_GAHBCFG |= OTG_FS_GAHBCFG_GINT;
@ -101,289 +86,6 @@ static void stm32f107_usbd_init(void)
OTG_FS_GINTMSK_SOFM; OTG_FS_GINTMSK_SOFM;
OTG_FS_DAINTMSK = 0xF; OTG_FS_DAINTMSK = 0xF;
OTG_FS_DIEPMSK = OTG_FS_DIEPMSK_XFRCM; OTG_FS_DIEPMSK = OTG_FS_DIEPMSK_XFRCM;
}
static void stm32f107_set_address(u8 addr)
{
OTG_FS_DCFG = (OTG_FS_DCFG & ~OTG_FS_DCFG_DAD) | (addr << 4);
}
static void stm32f107_ep_setup(u8 addr, u8 type, u16 max_size,
void (*callback) (u8 ep))
{
/*
* Configure endpoint address and type. Allocate FIFO memory for
* endpoint. Install callback funciton.
*/
u8 dir = addr & 0x80;
addr &= 0x7f;
if (addr == 0) { /* For the default control endpoint */
/* Configure IN part. */
if (max_size >= 64) {
OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_64;
} else if (max_size >= 32) {
OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_32;
} else if (max_size >= 16) {
OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_16;
} else {
OTG_FS_DIEPCTL0 = OTG_FS_DIEPCTL0_MPSIZ_8;
}
OTG_FS_DIEPTSIZ0 = (max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
OTG_FS_DIEPCTL0 |= OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
/* Configure OUT part. */
doeptsiz[0] = OTG_FS_DIEPSIZ0_STUPCNT_1 | (1 << 19) |
(max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
OTG_FS_DOEPTSIZ(0) = doeptsiz[0];
OTG_FS_DOEPCTL(0) |=
OTG_FS_DOEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
OTG_FS_GNPTXFSIZ = ((max_size / 4) << 16) | RX_FIFO_SIZE;
fifo_mem_top += max_size / 4;
fifo_mem_top_ep0 = fifo_mem_top;
return;
}
if (dir) {
OTG_FS_DIEPTXF(addr) = ((max_size / 4) << 16) | fifo_mem_top;
fifo_mem_top += max_size / 4;
OTG_FS_DIEPTSIZ(addr) =
(max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
OTG_FS_DIEPCTL(addr) |=
OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK | (type << 18)
| OTG_FS_DIEPCTL0_USBAEP | OTG_FS_DIEPCTLX_SD0PID
| (addr << 22) | max_size;
if (callback) {
_usbd_device.
user_callback_ctr[addr][USB_TRANSACTION_IN] =
(void *)callback;
}
}
if (!dir) {
doeptsiz[addr] = (1 << 19) |
(max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr];
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA |
OTG_FS_DOEPCTL0_USBAEP | OTG_FS_DIEPCTL0_CNAK |
OTG_FS_DOEPCTLX_SD0PID | (type << 18) | max_size;
if (callback) {
_usbd_device.
user_callback_ctr[addr][USB_TRANSACTION_OUT] =
(void *)callback;
}
}
}
static void stm32f107_endpoints_reset(void)
{
/* The core resets the endpoints automatically on reset. */
fifo_mem_top = fifo_mem_top_ep0;
}
static void stm32f107_ep_stall_set(u8 addr, u8 stall)
{
if (addr == 0) {
if (stall)
OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_STALL;
else
OTG_FS_DIEPCTL(addr) &= ~OTG_FS_DIEPCTL0_STALL;
}
if (addr & 0x80) {
addr &= 0x7F;
if (stall) {
OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_STALL;
} else {
OTG_FS_DIEPCTL(addr) &= ~OTG_FS_DIEPCTL0_STALL;
OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTLX_SD0PID;
}
} else {
if (stall) {
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_STALL;
} else {
OTG_FS_DOEPCTL(addr) &= ~OTG_FS_DOEPCTL0_STALL;
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTLX_SD0PID;
}
}
}
static u8 stm32f107_ep_stall_get(u8 addr)
{
/* Return non-zero if STALL set. */
if (addr & 0x80)
return
(OTG_FS_DIEPCTL(addr & 0x7f) & OTG_FS_DIEPCTL0_STALL) ? 1 : 0;
else
return (OTG_FS_DOEPCTL(addr) & OTG_FS_DOEPCTL0_STALL) ? 1 : 0;
}
static void stm32f107_ep_nak_set(u8 addr, u8 nak)
{
/* It does not make sence to force NAK on IN endpoints. */
if (addr & 0x80)
return;
force_nak[addr] = nak;
if (nak)
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_SNAK;
else
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_CNAK;
}
static u16 stm32f107_ep_write_packet(u8 addr, const void *buf, u16 len)
{
const u32 *buf32 = buf;
int i;
addr &= 0x7F;
/* Return if endpoint is already enabled. */
if (OTG_FS_DIEPTSIZ(addr) & OTG_FS_DIEPSIZ0_PKTCNT)
return 0;
/* Enable endpoint for transmission. */
OTG_FS_DIEPTSIZ(addr) = (1 << 19) | len;
OTG_FS_DIEPCTL(addr) |= OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_CNAK;
/* Copy buffer to endpoint FIFO. */
volatile u32 *fifo = OTG_FS_FIFO(addr);
for (i = len; i > 0; i -= 4)
*fifo++ = *buf32++;
return len;
}
/*
* Received packet size for each endpoint. This is assigned in
* stm32f107_poll() which reads the packet status push register GRXSTSP
* for use in stm32f107_ep_read_packet().
*/
static uint16_t rxbcnt;
static u16 stm32f107_ep_read_packet(u8 addr, void *buf, u16 len)
{
int i;
u32 *buf32 = buf;
u32 extra;
len = MIN(len, rxbcnt);
rxbcnt -= len;
volatile u32 *fifo = OTG_FS_FIFO(addr);
for (i = len; i >= 4; i -= 4)
*buf32++ = *fifo++;
if (i) {
extra = *fifo++;
memcpy(buf32, &extra, i);
}
OTG_FS_DOEPTSIZ(addr) = doeptsiz[addr];
OTG_FS_DOEPCTL(addr) |= OTG_FS_DOEPCTL0_EPENA |
(force_nak[addr] ? OTG_FS_DOEPCTL0_SNAK : OTG_FS_DOEPCTL0_CNAK);
return len;
}
static void stm32f107_poll(void)
{
/* Read interrupt status register. */
u32 intsts = OTG_FS_GINTSTS;
int i;
if (intsts & OTG_FS_GINTSTS_ENUMDNE) {
/* Handle USB RESET condition. */
OTG_FS_GINTSTS = OTG_FS_GINTSTS_ENUMDNE;
fifo_mem_top = RX_FIFO_SIZE;
_usbd_reset();
return;
}
/* Note: RX and TX handled differently in this device. */
if (intsts & OTG_FS_GINTSTS_RXFLVL) {
/* Receive FIFO non-empty. */
u32 rxstsp = OTG_FS_GRXSTSP;
u32 pktsts = rxstsp & OTG_FS_GRXSTSP_PKTSTS_MASK;
if ((pktsts != OTG_FS_GRXSTSP_PKTSTS_OUT) &&
(pktsts != OTG_FS_GRXSTSP_PKTSTS_SETUP))
return;
u8 ep = rxstsp & OTG_FS_GRXSTSP_EPNUM_MASK; return &usbd_dev;
u8 type;
if (pktsts == OTG_FS_GRXSTSP_PKTSTS_SETUP)
type = USB_TRANSACTION_SETUP;
else
type = USB_TRANSACTION_OUT;
/* Save packet size for stm32f107_ep_read_packet(). */
rxbcnt = (rxstsp & OTG_FS_GRXSTSP_BCNT_MASK) >> 4;
/*
* FIXME: Why is a delay needed here?
* This appears to fix a problem where the first 4 bytes
* of the DATA OUT stage of a control transaction are lost.
*/
for (i = 0; i < 1000; i++)
__asm__("nop");
if (_usbd_device.user_callback_ctr[ep][type])
_usbd_device.user_callback_ctr[ep][type] (ep);
/* Discard unread packet data. */
for (i = 0; i < rxbcnt; i += 4)
(void)*OTG_FS_FIFO(ep);
rxbcnt = 0;
}
/*
* There is no global interrupt flag for transmit complete.
* The XFRC bit must be checked in each OTG_FS_DIEPINT(x).
*/
for (i = 0; i < 4; i++) { /* Iterate over endpoints. */
if (OTG_FS_DIEPINT(i) & OTG_FS_DIEPINTX_XFRC) {
/* Transfer complete. */
if (_usbd_device.
user_callback_ctr[i][USB_TRANSACTION_IN]) {
_usbd_device.
user_callback_ctr[i][USB_TRANSACTION_IN](i);
}
OTG_FS_DIEPINT(i) = OTG_FS_DIEPINTX_XFRC;
}
}
if (intsts & OTG_FS_GINTSTS_USBSUSP) {
if (_usbd_device.user_callback_suspend)
_usbd_device.user_callback_suspend();
OTG_FS_GINTSTS = OTG_FS_GINTSTS_USBSUSP;
}
if (intsts & OTG_FS_GINTSTS_WKUPINT) {
if (_usbd_device.user_callback_resume)
_usbd_device.user_callback_resume();
OTG_FS_GINTSTS = OTG_FS_GINTSTS_WKUPINT;
}
if (intsts & OTG_FS_GINTSTS_SOF) {
if (_usbd_device.user_callback_sof)
_usbd_device.user_callback_sof();
OTG_FS_GINTSTS = OTG_FS_GINTSTS_SOF;
}
}
static void stm32f107_disconnect(bool disconnected)
{
if (disconnected) {
OTG_FS_DCTL |= OTG_FS_DCTL_SDIS;
} else {
OTG_FS_DCTL &= ~OTG_FS_DCTL_SDIS;
}
} }

91
lib/usb/usb_f207.c

@ -0,0 +1,91 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/tools.h>
#include <libopencm3/stm32/otg_hs.h>
#include <libopencm3/usb/usbd.h>
#include "usb_private.h"
#include "usb_fx07_common.h"
/* Receive FIFO size in 32-bit words. */
#define RX_FIFO_SIZE 512
static usbd_device *stm32f207_usbd_init(void);
static struct _usbd_device usbd_dev;
const struct _usbd_driver stm32f207_usb_driver = {
.init = stm32f207_usbd_init,
.set_address = stm32fx07_set_address,
.ep_setup = stm32fx07_ep_setup,
.ep_reset = stm32fx07_endpoints_reset,
.ep_stall_set = stm32fx07_ep_stall_set,
.ep_stall_get = stm32fx07_ep_stall_get,
.ep_nak_set = stm32fx07_ep_nak_set,
.ep_write_packet = stm32fx07_ep_write_packet,
.ep_read_packet = stm32fx07_ep_read_packet,
.poll = stm32fx07_poll,
.disconnect = stm32fx07_disconnect,
.base_address = USB_OTG_HS_BASE,
.set_address_before_status = 1,
.rx_fifo_size = RX_FIFO_SIZE,
};
/** Initialize the USB device controller hardware of the STM32. */
static usbd_device *stm32f207_usbd_init(void)
{
OTG_HS_GINTSTS = OTG_HS_GINTSTS_MMIS;
OTG_HS_GUSBCFG |= OTG_HS_GUSBCFG_PHYSEL;
/* Enable VBUS sensing in device mode and power down the PHY. */
OTG_HS_GCCFG |= OTG_HS_GCCFG_VBUSBSEN | OTG_HS_GCCFG_PWRDWN;
/* Wait for AHB idle. */
while (!(OTG_HS_GRSTCTL & OTG_HS_GRSTCTL_AHBIDL)) ;
/* Do core soft reset. */
OTG_HS_GRSTCTL |= OTG_HS_GRSTCTL_CSRST;
while (OTG_HS_GRSTCTL & OTG_HS_GRSTCTL_CSRST) ;
/* Force peripheral only mode. */
OTG_HS_GUSBCFG |= OTG_HS_GUSBCFG_FDMOD | OTG_HS_GUSBCFG_TRDT_MASK;
/* Full speed device. */
OTG_HS_DCFG |= OTG_HS_DCFG_DSPD;
/* Restart the PHY clock. */
OTG_HS_PCGCCTL = 0;
OTG_HS_GRXFSIZ = stm32f207_usb_driver.rx_fifo_size;
usbd_dev.fifo_mem_top = stm32f207_usb_driver.rx_fifo_size;
/* Unmask interrupts for TX and RX. */
OTG_HS_GAHBCFG |= OTG_HS_GAHBCFG_GINT;
OTG_HS_GINTMSK = OTG_HS_GINTMSK_ENUMDNEM |
OTG_HS_GINTMSK_RXFLVLM |
OTG_HS_GINTMSK_IEPINT |
OTG_HS_GINTMSK_USBSUSPM |
OTG_HS_GINTMSK_WUIM |
OTG_HS_GINTMSK_SOFM;
OTG_HS_DAINTMSK = 0xF;
OTG_HS_DIEPMSK = OTG_HS_DIEPMSK_XFRCM;
return &usbd_dev;
}

318
lib/usb/usb_fx07_common.c

@ -0,0 +1,318 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <libopencm3/cm3/common.h>
#include <libopencm3/stm32/tools.h>
#include <libopencm3/stm32/otg_fs.h>
#include <libopencm3/stm32/otg_hs.h>
#include <libopencm3/usb/usbd.h>
#include "usb_private.h"
#include "usb_fx07_common.h"
/* The FS core and the HS core have the same register layout.
* As the code can be used on both cores, the registers offset is modified
* according to the selected cores base address. */
#define dev_base_address (usbd_dev->driver->base_address)
#define REBASE(x) MMIO32((x)+(dev_base_address))
#define REBASE_FIFO(x) ((volatile u32*)((dev_base_address) + (OTG_FIFO(x))))
void stm32fx07_set_address(usbd_device *usbd_dev, u8 addr)
{
REBASE(OTG_DCFG) = (REBASE(OTG_DCFG) & ~OTG_FS_DCFG_DAD) | (addr << 4);
}
void stm32fx07_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
void (*callback) (usbd_device *usbd_dev, u8 ep))
{
/*
* Configure endpoint address and type. Allocate FIFO memory for
* endpoint. Install callback funciton.
*/
u8 dir = addr & 0x80;
addr &= 0x7f;
if (addr == 0) { /* For the default control endpoint */
/* Configure IN part. */
if (max_size >= 64) {
REBASE(OTG_DIEPCTL0) = OTG_FS_DIEPCTL0_MPSIZ_64;
} else if (max_size >= 32) {
REBASE(OTG_DIEPCTL0) = OTG_FS_DIEPCTL0_MPSIZ_32;
} else if (max_size >= 16) {
REBASE(OTG_DIEPCTL0) = OTG_FS_DIEPCTL0_MPSIZ_16;
} else {
REBASE(OTG_DIEPCTL0) = OTG_FS_DIEPCTL0_MPSIZ_8;
}
REBASE(OTG_DIEPTSIZ0) =
(max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
REBASE(OTG_DIEPCTL0) |=
OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
/* Configure OUT part. */
usbd_dev->doeptsiz[0] = OTG_FS_DIEPSIZ0_STUPCNT_1 |
OTG_FS_DIEPSIZ0_PKTCNT |
(max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
REBASE(OTG_DOEPTSIZ(0)) = usbd_dev->doeptsiz[0];
REBASE(OTG_DOEPCTL(0)) |=
OTG_FS_DOEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK;
REBASE(OTG_GNPTXFSIZ) = ((max_size / 4) << 16) |
usbd_dev->driver->rx_fifo_size;
usbd_dev->fifo_mem_top += max_size / 4;
usbd_dev->fifo_mem_top_ep0 = usbd_dev->fifo_mem_top;
return;
}
if (dir) {
REBASE(OTG_DIEPTXF(addr)) = ((max_size / 4) << 16) |
usbd_dev->fifo_mem_top;
usbd_dev->fifo_mem_top += max_size / 4;
REBASE(OTG_DIEPTSIZ(addr)) =
(max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
REBASE(OTG_DIEPCTL(addr)) |=
OTG_FS_DIEPCTL0_EPENA | OTG_FS_DIEPCTL0_SNAK | (type << 18)
| OTG_FS_DIEPCTL0_USBAEP | OTG_FS_DIEPCTLX_SD0PID
| (addr << 22) | max_size;
if (callback) {
usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_IN] =
(void *)callback;
}
}
if (!dir) {
usbd_dev->doeptsiz[addr] = OTG_FS_DIEPSIZ0_PKTCNT |
(max_size & OTG_FS_DIEPSIZ0_XFRSIZ_MASK);
REBASE(OTG_DOEPTSIZ(addr)) = usbd_dev->doeptsiz[addr];
REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_EPENA |
OTG_FS_DOEPCTL0_USBAEP | OTG_FS_DIEPCTL0_CNAK |
OTG_FS_DOEPCTLX_SD0PID | (type << 18) | max_size;
if (callback) {
usbd_dev->user_callback_ctr[addr][USB_TRANSACTION_OUT] =
(void *)callback;
}
}
}
void stm32fx07_endpoints_reset(usbd_device *usbd_dev)
{
/* The core resets the endpoints automatically on reset. */
usbd_dev->fifo_mem_top = usbd_dev->fifo_mem_top_ep0;
}
void stm32fx07_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall)
{
if (addr == 0) {
if (stall)
REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTL0_STALL;
else
REBASE(OTG_DIEPCTL(addr)) &= ~OTG_FS_DIEPCTL0_STALL;
}
if (addr & 0x80) {
addr &= 0x7F;
if (stall) {
REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTL0_STALL;
} else {
REBASE(OTG_DIEPCTL(addr)) &= ~OTG_FS_DIEPCTL0_STALL;
REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTLX_SD0PID;
}
} else {
if (stall) {
REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_STALL;
} else {
REBASE(OTG_DOEPCTL(addr)) &= ~OTG_FS_DOEPCTL0_STALL;
REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTLX_SD0PID;
}
}
}
u8 stm32fx07_ep_stall_get(usbd_device *usbd_dev, u8 addr)
{
/* Return non-zero if STALL set. */
if (addr & 0x80)
return (REBASE(OTG_DIEPCTL(addr & 0x7f)) &
OTG_FS_DIEPCTL0_STALL) ? 1 : 0;
else
return (REBASE(OTG_DOEPCTL(addr)) &
OTG_FS_DOEPCTL0_STALL) ? 1 : 0;
}
void stm32fx07_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak)
{
/* It does not make sence to force NAK on IN endpoints. */
if (addr & 0x80)
return;
usbd_dev->force_nak[addr] = nak;
if (nak)
REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_SNAK;
else
REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_CNAK;
}
u16 stm32fx07_ep_write_packet(usbd_device *usbd_dev, u8 addr,
const void *buf, u16 len)
{
const u32 *buf32 = buf;
int i;
addr &= 0x7F;
/* Return if endpoint is already enabled. */
if (REBASE(OTG_DIEPTSIZ(addr)) & OTG_FS_DIEPSIZ0_PKTCNT)
return 0;
/* Enable endpoint for transmission. */
REBASE(OTG_DIEPTSIZ(addr)) = OTG_FS_DIEPSIZ0_PKTCNT | len;
REBASE(OTG_DIEPCTL(addr)) |= OTG_FS_DIEPCTL0_EPENA |
OTG_FS_DIEPCTL0_CNAK;
volatile u32 *fifo = REBASE_FIFO(addr);
/* Copy buffer to endpoint FIFO, note - memcpy does not work */
for (i = len; i > 0; i -= 4)
*fifo++ = *buf32++;
return len;
}
u16 stm32fx07_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf, u16 len)
{
int i;
u32 *buf32 = buf;
u32 extra;
len = MIN(len, usbd_dev->rxbcnt);
usbd_dev->rxbcnt -= len;
volatile u32 *fifo = REBASE_FIFO(addr);
for (i = len; i >= 4; i -= 4)
*buf32++ = *fifo++;
if (i) {
extra = *fifo++;
memcpy(buf32, &extra, i);
}
REBASE(OTG_DOEPTSIZ(addr)) = usbd_dev->doeptsiz[addr];
REBASE(OTG_DOEPCTL(addr)) |= OTG_FS_DOEPCTL0_EPENA |
(usbd_dev->force_nak[addr] ?
OTG_FS_DOEPCTL0_SNAK : OTG_FS_DOEPCTL0_CNAK);
return len;
}
void stm32fx07_poll(usbd_device *usbd_dev)
{
/* Read interrupt status register. */
u32 intsts = REBASE(OTG_GINTSTS);
int i;
if (intsts & OTG_FS_GINTSTS_ENUMDNE) {
/* Handle USB RESET condition. */
REBASE(OTG_GINTSTS) = OTG_FS_GINTSTS_ENUMDNE;
usbd_dev->fifo_mem_top = usbd_dev->driver->rx_fifo_size;
_usbd_reset(usbd_dev);
return;
}
/* Note: RX and TX handled differently in this device. */
if (intsts & OTG_FS_GINTSTS_RXFLVL) {
/* Receive FIFO non-empty. */
u32 rxstsp = REBASE(OTG_GRXSTSP);
u32 pktsts = rxstsp & OTG_FS_GRXSTSP_PKTSTS_MASK;
if ((pktsts != OTG_FS_GRXSTSP_PKTSTS_OUT) &&
(pktsts != OTG_FS_GRXSTSP_PKTSTS_SETUP))
return;
u8 ep = rxstsp & OTG_FS_GRXSTSP_EPNUM_MASK;
u8 type;
if (pktsts == OTG_FS_GRXSTSP_PKTSTS_SETUP)
type = USB_TRANSACTION_SETUP;
else
type = USB_TRANSACTION_OUT;
/* Save packet size for stm32f107_ep_read_packet(). */
usbd_dev->rxbcnt = (rxstsp & OTG_FS_GRXSTSP_BCNT_MASK) >> 4;
/*
* FIXME: Why is a delay needed here?
* This appears to fix a problem where the first 4 bytes
* of the DATA OUT stage of a control transaction are lost.
*/
for (i = 0; i < 1000; i++)
__asm__("nop");
if (usbd_dev->user_callback_ctr[ep][type])
usbd_dev->user_callback_ctr[ep][type] (usbd_dev, ep);
/* Discard unread packet data. */
for (i = 0; i < usbd_dev->rxbcnt; i += 4)
(void)*REBASE_FIFO(ep);
usbd_dev->rxbcnt = 0;
}
/*
* There is no global interrupt flag for transmit complete.
* The XFRC bit must be checked in each OTG_FS_DIEPINT(x).
*/
for (i = 0; i < 4; i++) { /* Iterate over endpoints. */
if (REBASE(OTG_DIEPINT(i)) & OTG_FS_DIEPINTX_XFRC) {
/* Transfer complete. */
if (usbd_dev->user_callback_ctr[i][USB_TRANSACTION_IN])
usbd_dev->user_callback_ctr[i]
[USB_TRANSACTION_IN](usbd_dev, i);
REBASE(OTG_DIEPINT(i)) = OTG_FS_DIEPINTX_XFRC;
}
}
if (intsts & OTG_FS_GINTSTS_USBSUSP) {
if (usbd_dev->user_callback_suspend)
usbd_dev->user_callback_suspend();
REBASE(OTG_GINTSTS) = OTG_FS_GINTSTS_USBSUSP;
}
if (intsts & OTG_FS_GINTSTS_WKUPINT) {
if (usbd_dev->user_callback_resume)
usbd_dev->user_callback_resume();
REBASE(OTG_GINTSTS) = OTG_FS_GINTSTS_WKUPINT;
}
if (intsts & OTG_FS_GINTSTS_SOF) {
if (usbd_dev->user_callback_sof)
usbd_dev->user_callback_sof();
REBASE(OTG_GINTSTS) = OTG_FS_GINTSTS_SOF;
}
}
void stm32fx07_disconnect(usbd_device *usbd_dev, bool disconnected)
{
if (disconnected) {
REBASE(OTG_DCTL) |= OTG_FS_DCTL_SDIS;
} else {
REBASE(OTG_DCTL) &= ~OTG_FS_DCTL_SDIS;
}
}

38
lib/usb/usb_fx07_common.h

@ -0,0 +1,38 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __USB_FX07_COMMON_H_
#define __USB_FX07_COMMON_H_
void stm32fx07_set_address(usbd_device *usbd_dev, u8 addr);
void stm32fx07_ep_setup(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
void (*callback)(usbd_device *usbd_dev, u8 ep));
void stm32fx07_endpoints_reset(usbd_device *usbd_dev);
void stm32fx07_ep_stall_set(usbd_device *usbd_dev, u8 addr, u8 stall);
u8 stm32fx07_ep_stall_get(usbd_device *usbd_dev, u8 addr);
void stm32fx07_ep_nak_set(usbd_device *usbd_dev, u8 addr, u8 nak);
u16 stm32fx07_ep_write_packet(usbd_device *usbd_dev, u8 addr, const void *buf,
u16 len);
u16 stm32fx07_ep_read_packet(usbd_device *usbd_dev, u8 addr, void *buf,
u16 len);
void stm32fx07_poll(usbd_device *usbd_dev);
void stm32fx07_disconnect(usbd_device *usbd_dev, bool disconnected);
#endif /* __USB_FX07_COMMON_H_ */

81
lib/usb/usb_private.h

@ -25,7 +25,7 @@
#define MIN(a, b) ((a)<(b) ? (a) : (b)) #define MIN(a, b) ((a)<(b) ? (a) : (b))
/** Internal collection of device information. */ /** Internal collection of device information. */
extern struct _usbd_device { struct _usbd_device {
const struct usb_device_descriptor *desc; const struct usb_device_descriptor *desc;
const struct usb_config_descriptor *config; const struct usb_config_descriptor *config;
const char **strings; const char **strings;
@ -44,19 +44,49 @@ extern struct _usbd_device {
void (*user_callback_resume)(void); void (*user_callback_resume)(void);
void (*user_callback_sof)(void); void (*user_callback_sof)(void);
struct usb_control_state {
enum {
IDLE, STALLED,
DATA_IN, LAST_DATA_IN, STATUS_IN,
DATA_OUT, LAST_DATA_OUT, STATUS_OUT,
} state;
struct usb_setup_data req __attribute__((aligned(4)));
u8 *ctrl_buf;
u16 ctrl_len;
void (*complete)(usbd_device *usbd_dev,
struct usb_setup_data *req);
} control_state;
struct user_control_callback { struct user_control_callback {
usbd_control_callback cb; usbd_control_callback cb;
u8 type; u8 type;
u8 type_mask; u8 type_mask;
} user_control_callback[MAX_USER_CONTROL_CALLBACK]; } user_control_callback[MAX_USER_CONTROL_CALLBACK];
void (*user_callback_ctr[8][3])(u8 ea); void (*user_callback_ctr[8][3])(usbd_device *usbd_dev, u8 ea);
/* User callback function for some standard USB function hooks */ /* User callback function for some standard USB function hooks */
void (*user_callback_set_config)(u16 wValue); void (*user_callback_set_config)(usbd_device *usbd_dev, u16 wValue);
const struct _usbd_driver *driver; const struct _usbd_driver *driver;
} _usbd_device;
/* private driver data */
uint16_t fifo_mem_top;
uint16_t fifo_mem_top_ep0;
u8 force_nak[4];
/*
* We keep a backup copy of the out endpoint size registers to restore them
* after a transaction.
*/
u32 doeptsiz[4];
/*
* Received packet size for each endpoint. This is assigned in
* stm32f107_poll() which reads the packet status push register GRXSTSP
* for use in stm32f107_ep_read_packet().
*/
uint16_t rxbcnt;
};
enum _usbd_transaction { enum _usbd_transaction {
USB_TRANSACTION_IN, USB_TRANSACTION_IN,
@ -64,31 +94,34 @@ enum _usbd_transaction {
USB_TRANSACTION_SETUP, USB_TRANSACTION_SETUP,
}; };
void _usbd_control_in(u8 ea); void _usbd_control_in(usbd_device *usbd_dev, u8 ea);
void _usbd_control_out(u8 ea); void _usbd_control_out(usbd_device *usbd_dev, u8 ea);
void _usbd_control_setup(u8 ea); void _usbd_control_setup(usbd_device *usbd_dev, u8 ea);
int _usbd_standard_request(struct usb_setup_data *req, u8 **buf, u16 *len); int _usbd_standard_request(usbd_device *usbd_dev, struct usb_setup_data *req,
u8 **buf, u16 *len);
void _usbd_reset(void); void _usbd_reset(usbd_device *usbd_dev);
/* Functions provided by the hardware abstraction. */ /* Functions provided by the hardware abstraction. */
struct _usbd_driver { struct _usbd_driver {
void (*init)(void); usbd_device *(*init)(void);
void (*set_address)(u8 addr); void (*set_address)(usbd_device *usbd_dev, u8 addr);
void (*ep_setup)(u8 addr, u8 type, u16 max_size, void (*cb)(u8 ep)); void (*ep_setup)(usbd_device *usbd_dev, u8 addr, u8 type, u16 max_size,
void (*ep_reset)(void); void (*cb)(usbd_device *usbd_dev, u8 ep));
void (*ep_stall_set)(u8 addr, u8 stall); void (*ep_reset)(usbd_device *usbd_dev);
void (*ep_nak_set)(u8 addr, u8 nak); void (*ep_stall_set)(usbd_device *usbd_dev, u8 addr, u8 stall);
u8 (*ep_stall_get)(u8 addr); void (*ep_nak_set)(usbd_device *usbd_dev, u8 addr, u8 nak);
u16 (*ep_write_packet)(u8 addr, const void *buf, u16 len); u8 (*ep_stall_get)(usbd_device *usbd_dev, u8 addr);
u16 (*ep_read_packet)(u8 addr, void *buf, u16 len); u16 (*ep_write_packet)(usbd_device *usbd_dev, u8 addr, const void *buf,
void (*poll)(void); u16 len);
void (*disconnect)(bool disconnected); u16 (*ep_read_packet)(usbd_device *usbd_dev, u8 addr, void *buf,
u16 len);
void (*poll)(usbd_device *usbd_dev);
void (*disconnect)(usbd_device *usbd_dev, bool disconnected);
u32 base_address;
bool set_address_before_status;
u16 rx_fifo_size;
}; };
#define _usbd_hw_init() _usbd_device.driver->init()
#define _usbd_hw_set_address(addr) _usbd_device.driver->set_address(addr)
#define _usbd_hw_endpoints_reset() _usbd_device.driver->ep_reset()
#endif #endif

127
lib/usb/usb_standard.c

@ -21,15 +21,18 @@
#include <libopencm3/usb/usbd.h> #include <libopencm3/usb/usbd.h>
#include "usb_private.h" #include "usb_private.h"
void usbd_register_set_config_callback(void (*callback)(u16 wValue)) void usbd_register_set_config_callback(usbd_device *usbd_dev,
void (*callback)(usbd_device *usbd_dev,
u16 wValue))
{ {
_usbd_device.user_callback_set_config = callback; usbd_dev->user_callback_set_config = callback;
} }
static u16 build_config_descriptor(u8 index, u8 *buf, u16 len) static u16 build_config_descriptor(usbd_device *usbd_dev,
u8 index, u8 *buf, u16 len)
{ {
u8 *tmpbuf = buf; u8 *tmpbuf = buf;
const struct usb_config_descriptor *cfg = &_usbd_device.config[index]; const struct usb_config_descriptor *cfg = &usbd_dev->config[index];
u16 count, total = 0, totallen = 0; u16 count, total = 0, totallen = 0;
u16 i, j, k; u16 i, j, k;
@ -87,7 +90,8 @@ static u16 build_config_descriptor(u8 index, u8 *buf, u16 len)
return total; return total;
} }
static int usb_standard_get_descriptor(struct usb_setup_data *req, static int usb_standard_get_descriptor(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
int i; int i;
@ -95,25 +99,26 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req,
switch (req->wValue >> 8) { switch (req->wValue >> 8) {
case USB_DT_DEVICE: case USB_DT_DEVICE:
*buf = (u8 *) _usbd_device.desc; *buf = (u8 *) usbd_dev->desc;
*len = MIN(*len, _usbd_device.desc->bLength); *len = MIN(*len, usbd_dev->desc->bLength);
return 1; return 1;
case USB_DT_CONFIGURATION: case USB_DT_CONFIGURATION:
*buf = _usbd_device.ctrl_buf; *buf = usbd_dev->ctrl_buf;
*len = build_config_descriptor(req->wValue & 0xff, *buf, *len); *len = build_config_descriptor(usbd_dev, req->wValue & 0xff,
*buf, *len);
return 1; return 1;
case USB_DT_STRING: case USB_DT_STRING:
sd = (struct usb_string_descriptor *)_usbd_device.ctrl_buf; sd = (struct usb_string_descriptor *)usbd_dev->ctrl_buf;
if (!_usbd_device.strings) if (!usbd_dev->strings)
return 0; /* Device doesn't support strings. */ return 0; /* Device doesn't support strings. */
/* Check that string index is in range. */ /* Check that string index is in range. */
for (i = 0; i <= (req->wValue & 0xff); i++) for (i = 0; i <= (req->wValue & 0xff); i++)
if (_usbd_device.strings[i] == NULL) if (usbd_dev->strings[i] == NULL)
return 0; return 0;
sd->bLength = strlen(_usbd_device.strings[req->wValue & 0xff]) sd->bLength = strlen(usbd_dev->strings[req->wValue & 0xff])
* 2 + 2; * 2 + 2;
sd->bDescriptorType = USB_DT_STRING; sd->bDescriptorType = USB_DT_STRING;
@ -122,7 +127,7 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req,
for (i = 0; i < (*len / 2) - 1; i++) for (i = 0; i < (*len / 2) - 1; i++)
sd->wData[i] = sd->wData[i] =
_usbd_device.strings[req->wValue & 0xff][i]; usbd_dev->strings[req->wValue & 0xff][i];
/* Send sane Language ID descriptor... */ /* Send sane Language ID descriptor... */
if ((req->wValue & 0xff) == 0) if ((req->wValue & 0xff) == 0)
@ -133,7 +138,8 @@ static int usb_standard_get_descriptor(struct usb_setup_data *req,
return 0; return 0;
} }
static int usb_standard_set_address(struct usb_setup_data *req, u8 **buf, static int usb_standard_set_address(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf,
u16 *len) u16 *len)
{ {
(void)req; (void)req;
@ -144,19 +150,20 @@ static int usb_standard_set_address(struct usb_setup_data *req, u8 **buf,
if ((req->bmRequestType != 0) || (req->wValue >= 128)) if ((req->bmRequestType != 0) || (req->wValue >= 128))
return 0; return 0;
_usbd_device.current_address = req->wValue; usbd_dev->current_address = req->wValue;
/* /*
* Special workaround for STM32F10[57] that require the address * Special workaround for STM32F10[57] that require the address
* to be set here. This is undocumented! * to be set here. This is undocumented!
*/ */
if (_usbd_device.driver == &stm32f107_usb_driver) if ( usbd_dev->driver->set_address_before_status)
_usbd_device.driver->set_address(req->wValue); usbd_dev->driver->set_address(usbd_dev, req->wValue);
return 1; return 1;
} }
static int usb_standard_set_configuration(struct usb_setup_data *req, static int usb_standard_set_configuration(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
int i; int i;
@ -166,43 +173,46 @@ static int usb_standard_set_configuration(struct usb_setup_data *req,
(void)len; (void)len;
/* Is this correct, or should we reset alternate settings. */ /* Is this correct, or should we reset alternate settings. */
if (req->wValue == _usbd_device.current_config) if (req->wValue == usbd_dev->current_config)
return 1; return 1;
_usbd_device.current_config = req->wValue; usbd_dev->current_config = req->wValue;
/* Reset all endpoints. */ /* Reset all endpoints. */
_usbd_hw_endpoints_reset(); usbd_dev->driver->ep_reset(usbd_dev);
if (_usbd_device.user_callback_set_config) { if (usbd_dev->user_callback_set_config) {
/* /*
* Flush control callbacks. These will be reregistered * Flush control callbacks. These will be reregistered
* by the user handler. * by the user handler.
*/ */
for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++) for (i = 0; i < MAX_USER_CONTROL_CALLBACK; i++)
_usbd_device.user_control_callback[i].cb = NULL; usbd_dev->user_control_callback[i].cb = NULL;
_usbd_device.user_callback_set_config(req->wValue); usbd_dev->user_callback_set_config(usbd_dev, req->wValue);
} }
return 1; return 1;
} }
static int usb_standard_get_configuration(struct usb_setup_data *req, static int usb_standard_get_configuration(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
(void)req; (void)req;
if (*len > 1) if (*len > 1)
*len = 1; *len = 1;
(*buf)[0] = _usbd_device.current_config; (*buf)[0] = usbd_dev->current_config;
return 1; return 1;
} }
static int usb_standard_set_interface(struct usb_setup_data *req, static int usb_standard_set_interface(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
(void)usbd_dev;
(void)req; (void)req;
(void)buf; (void)buf;
@ -214,9 +224,11 @@ static int usb_standard_set_interface(struct usb_setup_data *req,
return 1; return 1;
} }
static int usb_standard_get_interface(struct usb_setup_data *req, static int usb_standard_get_interface(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
(void)usbd_dev;
(void)req; (void)req;
(void)buf; (void)buf;
@ -227,9 +239,11 @@ static int usb_standard_get_interface(struct usb_setup_data *req,
return 1; return 1;
} }
static int usb_standard_device_get_status(struct usb_setup_data *req, static int usb_standard_device_get_status(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
(void)usbd_dev;
(void)req; (void)req;
/* bit 0: self powered */ /* bit 0: self powered */
@ -242,9 +256,11 @@ static int usb_standard_device_get_status(struct usb_setup_data *req,
return 1; return 1;
} }
static int usb_standard_interface_get_status(struct usb_setup_data *req, static int usb_standard_interface_get_status(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
(void)usbd_dev;
(void)req; (void)req;
/* not defined */ /* not defined */
@ -256,45 +272,50 @@ static int usb_standard_interface_get_status(struct usb_setup_data *req,
return 1; return 1;
} }
static int usb_standard_endpoint_get_status(struct usb_setup_data *req, static int usb_standard_endpoint_get_status(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
(void)req; (void)req;
if (*len > 2) if (*len > 2)
*len = 2; *len = 2;
(*buf)[0] = usbd_ep_stall_get(req->wIndex) ? 1 : 0; (*buf)[0] = usbd_ep_stall_get(usbd_dev, req->wIndex) ? 1 : 0;
(*buf)[1] = 0; (*buf)[1] = 0;
return 1; return 1;
} }
static int usb_standard_endpoint_stall(struct usb_setup_data *req, static int usb_standard_endpoint_stall(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
(void)buf; (void)buf;
(void)len; (void)len;
usbd_ep_stall_set(req->wIndex, 1); usbd_ep_stall_set(usbd_dev, req->wIndex, 1);
return 1; return 1;
} }
static int usb_standard_endpoint_unstall(struct usb_setup_data *req, static int usb_standard_endpoint_unstall(usbd_device *usbd_dev,
struct usb_setup_data *req,
u8 **buf, u16 *len) u8 **buf, u16 *len)
{ {
(void)buf; (void)buf;
(void)len; (void)len;
usbd_ep_stall_set(req->wIndex, 0); usbd_ep_stall_set(usbd_dev, req->wIndex, 0);
return 1; return 1;
} }
int _usbd_standard_request_device(struct usb_setup_data *req, u8 **buf, int _usbd_standard_request_device(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf,
u16 *len) u16 *len)
{ {
int (*command)(struct usb_setup_data *req, u8 **buf, u16 *len) = NULL; int (*command)(usbd_device *usbd_dev, struct usb_setup_data *req, u8
**buf, u16 *len) = NULL;
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE: case USB_REQ_CLEAR_FEATURE:
@ -337,13 +358,15 @@ int _usbd_standard_request_device(struct usb_setup_data *req, u8 **buf,
if (!command) if (!command)
return 0; return 0;
return command(req, buf, len); return command(usbd_dev, req, buf, len);
} }
int _usbd_standard_request_interface(struct usb_setup_data *req, u8 **buf, int _usbd_standard_request_interface(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf,
u16 *len) u16 *len)
{ {
int (*command)(struct usb_setup_data *req, u8 **buf, u16 *len) = NULL; int (*command)(usbd_device *usbd_dev, struct usb_setup_data *req,
u8 **buf, u16 *len) = NULL;
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE: case USB_REQ_CLEAR_FEATURE:
@ -364,13 +387,15 @@ int _usbd_standard_request_interface(struct usb_setup_data *req, u8 **buf,
if (!command) if (!command)
return 0; return 0;
return command(req, buf, len); return command(usbd_dev, req, buf, len);
} }
int _usbd_standard_request_endpoint(struct usb_setup_data *req, u8 **buf, int _usbd_standard_request_endpoint(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf,
u16 *len) u16 *len)
{ {
int (*command) (struct usb_setup_data *req, u8 **buf, u16 *len) = NULL; int (*command) (usbd_device *usbd_dev, struct usb_setup_data *req,
u8 **buf, u16 *len) = NULL;
switch (req->bRequest) { switch (req->bRequest) {
case USB_REQ_CLEAR_FEATURE: case USB_REQ_CLEAR_FEATURE:
@ -396,10 +421,11 @@ int _usbd_standard_request_endpoint(struct usb_setup_data *req, u8 **buf,
if (!command) if (!command)
return 0; return 0;
return command(req, buf, len); return command(usbd_dev, req, buf, len);
} }
int _usbd_standard_request(struct usb_setup_data *req, u8 **buf, u16 *len) int _usbd_standard_request(usbd_device *usbd_dev,
struct usb_setup_data *req, u8 **buf, u16 *len)
{ {
/* FIXME: Have class/vendor requests as well. */ /* FIXME: Have class/vendor requests as well. */
if ((req->bmRequestType & USB_REQ_TYPE_TYPE) != USB_REQ_TYPE_STANDARD) if ((req->bmRequestType & USB_REQ_TYPE_TYPE) != USB_REQ_TYPE_STANDARD)
@ -407,11 +433,12 @@ int _usbd_standard_request(struct usb_setup_data *req, u8 **buf, u16 *len)
switch (req->bmRequestType & USB_REQ_TYPE_RECIPIENT) { switch (req->bmRequestType & USB_REQ_TYPE_RECIPIENT) {
case USB_REQ_TYPE_DEVICE: case USB_REQ_TYPE_DEVICE:
return _usbd_standard_request_device(req, buf, len); return _usbd_standard_request_device(usbd_dev, req, buf, len);
case USB_REQ_TYPE_INTERFACE: case USB_REQ_TYPE_INTERFACE:
return _usbd_standard_request_interface(req, buf, len); return _usbd_standard_request_interface(usbd_dev, req,
buf, len);
case USB_REQ_TYPE_ENDPOINT: case USB_REQ_TYPE_ENDPOINT:
return _usbd_standard_request_endpoint(req, buf, len); return _usbd_standard_request_endpoint(usbd_dev, req, buf, len);
default: default:
return 0; return 0;
} }

Loading…
Cancel
Save