From: Martin Mares Date: Sun, 24 Jun 2018 14:19:40 +0000 (+0200) Subject: Split to low/high-level part X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=2fe5a1535ede515a5f2037f9323e7d960358ad96;p=home-hw.git Split to low/high-level part --- diff --git a/Inc/usb.h b/Inc/usb.h index e33a71f..114a537 100644 --- a/Inc/usb.h +++ b/Inc/usb.h @@ -1,3 +1,5 @@ +/*** Configurable parameters ***/ + #define USB_SELF_POWERED #define USB_NUM_CONFIGURATIONS 1 #define USB_DEBUG @@ -27,11 +29,17 @@ struct usb { u16 ep0_remaining_length; u16 ep0_total_length; byte ep0_buf[USB_EP0_BUF_SIZE]; + // Descriptor data to be filled by the user during usb_dev_reset() + const byte *desc_device; + const byte *desc_config; + const char * const *desc_string; + const byte *desc_languages; + u16 desc_device_len; + u16 desc_config_len; + u16 desc_string_items; + u16 desc_languages_len; }; -void usb_init(struct usb *usb, PCD_HandleTypeDef *hpcd); -void usb_start(struct usb *usb); - enum usb_device_state { USB_STATE_DEFAULT, USB_STATE_ADDRESSED, @@ -56,6 +64,54 @@ static inline void usb_debug(char *msg, ...) { } #endif +// Parsed setup request +struct setup_request { + byte bmRequest; + byte bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; +}; + +/*** Functions provided by low-level code ***/ + +void usb_init(struct usb *usb, PCD_HandleTypeDef *hpcd); +void usb_start(struct usb *usb); + +void usb_ctl_send_status(struct usb *usb); +void usb_ctl_recv_status(struct usb *usb); +void usb_ctl_send_data(struct usb *usb, const byte *data, uint len); +void usb_ctl_recv_data(struct usb *usb, byte *data, uint len); +void usb_ctl_error(struct usb *usb); +void usb_ctl_setup_error(struct usb *usb, struct setup_request *setup); + +/*** Callbacks to user code ***/ + +// Device was reset +void usb_dev_reset(struct usb *usb); + +// Configure the device (usb->config is the selected configuration) +void usb_dev_configure(struct usb *usb); + +// Un-configure the device (usb->config is the configuration we are leaving) +void usb_dev_unconfigure(struct usb *usb); + +// Intercept a setup packet. Returns true if default processing should be skipped. +// Remember to check if usb->state == USB_STATE_CONFIGURED for most requests. +bool usb_dev_setup_hook(struct usb *usb, struct setup_request *setup); + +// Finished receiving control packet data requested by usb_ctl_recv_data() +void usb_dev_ctl_recv_done(struct usb *usb); + +// Finished sending control packet data requested by usb_ctl_send_data() +void usb_dev_ctl_send_done(struct usb *usb); + +// Finished receiving data on a non-control endpoint +void usb_dev_recv_done(struct usb *usb, byte epnum); + +// Finished sending data on a non-control endpoint +void usb_dev_send_done(struct usb *usb, byte epnum); + /*** Constants from USB specs ***/ #define USB_REQ_DIRECTION 0x80 diff --git a/Inc/util.h b/Inc/util.h index 388a1bd..6772a50 100644 --- a/Inc/util.h +++ b/Inc/util.h @@ -1,4 +1,5 @@ #include +#include typedef unsigned int uint; typedef uint8_t byte; @@ -10,6 +11,17 @@ typedef int32_t s32; #define MIN(x,y) ((x) < (y) ? (x) : (y)) #define MAX(x,y) ((x) > (y) ? (x) : (y)) +static inline uint get_u16_le(byte *p) +{ + return (p[1] << 8) | p[0]; +} + +static inline void put_u16_le(byte *p, u16 x) +{ + p[0] = x; + p[1] = x >> 8; +} + // debug.c #undef DEBUG_SEMIHOSTING diff --git a/Makefile b/Makefile index a50db71..a1e31eb 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,7 @@ C_SOURCES = \ Src/main.c \ Src/debug.c \ Src/usb.c \ +Src/usbdev.c \ /aux/misc/stm/F1-package/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rcc.c \ /Src/system_stm32f1xx.c \ Src/stm32f1xx_it.c \ diff --git a/Src/usb.c b/Src/usb.c index b7f7313..c6867da 100644 --- a/Src/usb.c +++ b/Src/usb.c @@ -6,88 +6,6 @@ #include -void _Error_Handler(char * file, int line); // FIXME - -#define DESC_U16(x) ((x) & 0xff), ((x) >> 8) - -enum desc_string { - DESC_STR_NONE = 0, - DESC_STR_MANUFACTURER, - DESC_STR_PRODUCT, - DESC_STR_SERIAL, - DESC_STR_CONFIGURATION, - DESC_STR_INTERFACE, -}; - -static const byte desc_device[] = { - 18, // bLength - USB_DESC_TYPE_DEVICE, // bDescriptorType - DESC_U16(0x0200), // bcdUSB - 0x00, // bDeviceClass - 0x00, // bDeviceSubClass - 0x00, // bDeviceProtocol - USB_MAX_EP0_SIZE, // bMaxPacketSize - DESC_U16(0x4242), // idVendor - DESC_U16(0x0001), // idProduct - DESC_U16(0x0200), // bcdDevice - DESC_STR_MANUFACTURER, // iManufacturer - DESC_STR_PRODUCT, // iProduct - DESC_STR_SERIAL, // iSerialNumber - USB_NUM_CONFIGURATIONS, // bNumConfigurations -}; - -static const byte desc_config[] = { - // Configuration descriptor - 9, // bLength - USB_DESC_TYPE_CONFIGURATION, // bDescriptorType - 32, // wTotalLength - 0, - 0x01, // bNumInterfaces - 0x01, // bConfigurationValue - DESC_STR_CONFIGURATION, // iConfiguration - 0xc0, // bmAttributes: bus-powered, supports remote wakeup - 0x32, // Max power: 100 mA - // Interface descriptor - 9, // bLength - USB_DESC_TYPE_INTERFACE, // bDescriptorType - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndpoints - 0xff, // bInterfaceClass: vendor-defined - 0x00, // bInterfaceSubClass - 0x00, // nInterfaceProtocol - DESC_STR_INTERFACE, // iInterface - // End-point descriptor - 7, // bLength - USB_DESC_TYPE_ENDPOINT, // bDescriptorType - 0x01, // bEndpointAddress - USB_EP_TYPE_BULK, // bmAttributes - 0x40, 0x00, // wMaxPacketSize - 0x00, // bInterval: unused - // End-point descriptor - 7, // bLength - USB_DESC_TYPE_ENDPOINT, // bDescriptorType - 0x81, // bEndpointAddress - USB_EP_TYPE_BULK, // bmAttributes - 0x40, 0x00, // wMaxPacketSize - 0x00, // bInterval: unused -}; - -static const char * const desc_string[] = { - NULL, // DESC_STR_NONE - "United Computer Wizards", // DESC_STR_MANUFACTURER - "Mysterious Gadget", // DESC_STR_PRODUCT - "00000042", // DESC_STR_SERIAL - "Default Configuration", // DESC_STR_CONFIGURATION - "Default Interface", // DESC_STR_INTERFACE -}; - -static const byte desc_languages[] = { - 4, // bLength - USB_DESC_TYPE_STRING, // bDescriptorType - DESC_U16(1033), // English -}; - void usb_init(struct usb *usb, PCD_HandleTypeDef *hpcd) { memset(usb, 0, sizeof(*usb)); @@ -105,31 +23,20 @@ void usb_start(struct usb *usb) HAL_PCD_Start(usb->hpcd); } -static inline uint get_u16(byte *p) -{ - return (p[1] << 8) | p[0]; -} - -static inline void put_u16(byte *p, u16 x) -{ - p[0] = x; - p[1] = x >> 8; -} - -static void usb_ctl_send_status(struct usb *usb) +void usb_ctl_send_status(struct usb *usb) { usb_debug("Control send: status\n"); usb->ep0_state = USB_EP0_STATUS_IN; usb_ep_transmit(usb, 0x00, NULL, 0); } -static void usb_ctl_recv_status(struct usb *usb) +void usb_ctl_recv_status(struct usb *usb) { usb->ep0_state = USB_EP0_STATUS_OUT; usb_ep_receive(usb, 0x00, NULL, 0); } -static void usb_ctl_send_data(struct usb *usb, const byte *data, uint len) +void usb_ctl_send_data(struct usb *usb, const byte *data, uint len) { usb_debug("Control send: %u bytes\n", len); usb->ep0_state = USB_EP0_DATA_IN; @@ -138,8 +45,7 @@ static void usb_ctl_send_data(struct usb *usb, const byte *data, uint len) usb_ep_transmit(usb, 0x00, data, len); } -#if 0 // FIXME -static void usb_ctl_recv_data(struct usb *usb, byte *data, uint len) +void usb_ctl_recv_data(struct usb *usb, byte *data, uint len) { usb_debug("Control recv: %u bytes\n", len); usb->ep0_state = USB_EP0_DATA_OUT; @@ -147,7 +53,6 @@ static void usb_ctl_recv_data(struct usb *usb, byte *data, uint len) usb->ep0_remaining_length = len; usb_ep_transmit(usb, 0x00, data, len); } -#endif static void usb_ctl_send_byte(struct usb *usb, byte data) { @@ -157,26 +62,18 @@ static void usb_ctl_send_byte(struct usb *usb, byte data) static void usb_ctl_send_u16(struct usb *usb, u16 data) { - put_u16(usb->ep0_buf, data); + put_u16_le(usb->ep0_buf, data); usb_ctl_send_data(usb, usb->ep0_buf, 2); } -static void usb_ctl_error(struct usb *usb) +void usb_ctl_error(struct usb *usb) { usb_debug("Control packet error\n"); usb_ep_stall(usb, 0x00); usb_ep_stall(usb, 0x80); } -struct setup_request { - byte bmRequest; - byte bRequest; - u16 wValue; - u16 wIndex; - u16 wLength; -}; - -static void usb_ctl_setup_error(struct usb *usb, struct setup_request *setup) +void usb_ctl_setup_error(struct usb *usb, struct setup_request *setup) { usb_debug("Setup packet error\n"); usb_ep_stall(usb, setup->bmRequest & USB_REQ_DIRECTION); @@ -275,21 +172,19 @@ static void dev_get_descriptor(struct usb *usb, struct setup_request *setup) switch (desc_type) { case USB_DESC_TYPE_DEVICE: - return dev_desc_send(usb, setup, desc_device, sizeof(desc_device)); + return dev_desc_send(usb, setup, usb->desc_device, usb->desc_device_len); case USB_DESC_TYPE_CONFIGURATION: - return dev_desc_send(usb, setup, desc_config, sizeof(desc_config)); + return dev_desc_send(usb, setup, usb->desc_config, usb->desc_config_len); case USB_DESC_TYPE_STRING: if (!desc_index) - return dev_desc_send(usb, setup, desc_languages, sizeof(desc_languages)); - if (desc_index < sizeof(desc_string) / sizeof(desc_string[0])) - return dev_desc_send_string(usb, setup, desc_string[desc_index]); + return dev_desc_send(usb, setup, usb->desc_languages, usb->desc_languages_len); + if (desc_index < usb->desc_string_items) + return dev_desc_send_string(usb, setup, usb->desc_string[desc_index]); break; case USB_DESC_TYPE_DEVICE_QUALIFIER: - // FIXME case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: - // FIXME - // if (usb->hpcd->Init.speed == PCD_SPEED_HIGH) - ; + // We do not support high-speed USB + break; } usb_ctl_error(usb); @@ -328,7 +223,7 @@ static void dev_set_configuration(struct usb *usb, struct setup_request *setup) { usb->config = cfg; usb->state = USB_STATE_CONFIGURED; - // FIXME: Notify that the device was configured + usb_dev_configure(usb); } usb_ctl_send_status(usb); break; @@ -336,14 +231,15 @@ static void dev_set_configuration(struct usb *usb, struct setup_request *setup) if (!cfg) { // Unconfiguring + usb_dev_unconfigure(usb); usb->config = 0; usb->state = USB_STATE_ADDRESSED; - // FIXME: Notify that the device was unconfigured } else if (cfg != usb->config) { + usb_dev_unconfigure(usb); usb->config = cfg; - // FIXME: Notify about configuration change + usb_dev_configure(usb); } usb_ctl_send_status(usb); break; @@ -381,7 +277,7 @@ static void intf_setup(struct usb *usb, struct setup_request *setup) if (!intf) { - // FIXME: Support more interfaces + // FIXME: Currently, we do not support more than 1 interface per configuration usb_ctl_error(usb); return; } @@ -483,25 +379,23 @@ static void ep_setup(struct usb *usb, struct setup_request *setup) static void usb_handle_setup(struct usb *usb, struct setup_request *setup) { usb_debug("Setup: type=%02x req=%02x val=%04x idx=%04x len=%04x\n", setup->bmRequest, setup->bRequest, setup->wValue, setup->wIndex, setup->wLength); - usb->ep0_state = USB_EP0_SETUP; usb->ep0_setup_data_length = setup->wLength; - if ((setup->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) - { - // FIXME: Class-specific and vendor-specific setup packets not supported - // FIXME: Check USB_STATE_CONFIGURED here - usb_ctl_setup_error(usb, setup); - } + if (usb_dev_setup_hook(usb, setup)) + return; - switch (setup->bmRequest & USB_REQ_RECIPIENT_MASK) + if ((setup->bmRequest & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD) { - case USB_REQ_RECIPIENT_DEVICE: - return dev_setup(usb, setup); - case USB_REQ_RECIPIENT_INTERFACE: - return intf_setup(usb, setup); - case USB_REQ_RECIPIENT_ENDPOINT: - return ep_setup(usb, setup); + switch (setup->bmRequest & USB_REQ_RECIPIENT_MASK) + { + case USB_REQ_RECIPIENT_DEVICE: + return dev_setup(usb, setup); + case USB_REQ_RECIPIENT_INTERFACE: + return intf_setup(usb, setup); + case USB_REQ_RECIPIENT_ENDPOINT: + return ep_setup(usb, setup); + } } usb_ctl_setup_error(usb, setup); @@ -515,9 +409,9 @@ void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) struct setup_request setup = { .bmRequest = req[0], .bRequest = req[1], - .wValue = get_u16(req+2), - .wIndex = get_u16(req+4), - .wLength = get_u16(req+6), + .wValue = get_u16_le(req+2), + .wIndex = get_u16_le(req+4), + .wLength = get_u16_le(req+6), }; usb_handle_setup(usb, &setup); } @@ -541,18 +435,14 @@ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) else { if (usb->state == USB_STATE_CONFIGURED) - { - // FIXME: Handle incoming control packet - } + usb_dev_ctl_recv_done(usb); usb_ctl_send_status(usb); } } else { if (usb->state == USB_STATE_CONFIGURED) - { - // FIXME: Custom data callback - } + usb_dev_recv_done(usb, epnum); } } @@ -587,20 +477,14 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) else { if (usb->state == USB_STATE_CONFIGURED) - { - // FIXME: Custom data callback - // All data have been sent - } + usb_dev_ctl_send_done(usb); usb_ctl_recv_status(usb); } } else { if (usb->state == USB_STATE_CONFIGURED) - { - // FIXME: Custom data callback - // This gets called when a complete message is sent - } + usb_dev_send_done(usb, epnum); } } @@ -611,10 +495,11 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) } void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) -{ +{ struct usb *usb = hpcd->pData; usb->state = USB_STATE_DEFAULT; + usb_dev_reset(usb); usb_ep_open(usb, 0x00, USB_EP_TYPE_CTRL, USB_MAX_EP0_SIZE); usb_ep_open(usb, 0x80, USB_EP_TYPE_CTRL, USB_MAX_EP0_SIZE); diff --git a/Src/usbdev.c b/Src/usbdev.c new file mode 100644 index 0000000..3e6e76a --- /dev/null +++ b/Src/usbdev.c @@ -0,0 +1,130 @@ +#include "stm32f1xx.h" +#include "stm32f1xx_hal.h" + +#include "util.h" +#include "usb.h" + +/*** Descriptors ***/ + +#define DESC_U16(x) ((x) & 0xff), ((x) >> 8) + +enum desc_string { + DESC_STR_NONE = 0, + DESC_STR_MANUFACTURER, + DESC_STR_PRODUCT, + DESC_STR_SERIAL, + DESC_STR_CONFIGURATION, + DESC_STR_INTERFACE, +}; + +static const byte desc_device[] = { + 18, // bLength + USB_DESC_TYPE_DEVICE, // bDescriptorType + DESC_U16(0x0200), // bcdUSB + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + USB_MAX_EP0_SIZE, // bMaxPacketSize + DESC_U16(0x4242), // idVendor + DESC_U16(0x0001), // idProduct + DESC_U16(0x0200), // bcdDevice + DESC_STR_MANUFACTURER, // iManufacturer + DESC_STR_PRODUCT, // iProduct + DESC_STR_SERIAL, // iSerialNumber + USB_NUM_CONFIGURATIONS, // bNumConfigurations +}; + +static const byte desc_config[] = { + // Configuration descriptor + 9, // bLength + USB_DESC_TYPE_CONFIGURATION, // bDescriptorType + 32, // wTotalLength + 0, + 0x01, // bNumInterfaces + 0x01, // bConfigurationValue + DESC_STR_CONFIGURATION, // iConfiguration + 0xc0, // bmAttributes: bus-powered, supports remote wakeup + 0x32, // Max power: 100 mA + // Interface descriptor + 9, // bLength + USB_DESC_TYPE_INTERFACE, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints + 0xff, // bInterfaceClass: vendor-defined + 0x00, // bInterfaceSubClass + 0x00, // nInterfaceProtocol + DESC_STR_INTERFACE, // iInterface + // End-point descriptor + 7, // bLength + USB_DESC_TYPE_ENDPOINT, // bDescriptorType + 0x01, // bEndpointAddress + USB_EP_TYPE_BULK, // bmAttributes + 0x40, 0x00, // wMaxPacketSize + 0x00, // bInterval: unused + // End-point descriptor + 7, // bLength + USB_DESC_TYPE_ENDPOINT, // bDescriptorType + 0x81, // bEndpointAddress + USB_EP_TYPE_BULK, // bmAttributes + 0x40, 0x00, // wMaxPacketSize + 0x00, // bInterval: unused +}; + +static const char * const desc_string[] = { + NULL, // DESC_STR_NONE + "United Computer Wizards", // DESC_STR_MANUFACTURER + "Mysterious Gadget", // DESC_STR_PRODUCT + "00000042", // DESC_STR_SERIAL + "Default Configuration", // DESC_STR_CONFIGURATION + "Default Interface", // DESC_STR_INTERFACE +}; + +static const byte desc_languages[] = { + 4, // bLength + USB_DESC_TYPE_STRING, // bDescriptorType + DESC_U16(1033), // English +}; + +/*** Callbacks ***/ + +void usb_dev_reset(struct usb *usb) +{ + usb->desc_device = desc_device; + usb->desc_device_len = sizeof(desc_device); + usb->desc_config = desc_config; + usb->desc_config_len = sizeof(desc_config); + usb->desc_string = desc_string; + usb->desc_string_items = sizeof(desc_string) / sizeof(desc_string[0]); + usb->desc_languages = desc_languages; + usb->desc_languages_len = sizeof(desc_languages); +} + +void usb_dev_configure(struct usb *usb) +{ +} + +void usb_dev_unconfigure(struct usb *usb) +{ +} + +bool usb_dev_setup_hook(struct usb *usb, struct setup_request *setup) +{ + return false; +} + +void usb_dev_ctl_recv_done(struct usb *usb) +{ +} + +void usb_dev_ctl_send_done(struct usb *usb) +{ +} + +void usb_dev_recv_done(struct usb *usb, byte epnum) +{ +} + +void usb_dev_send_done(struct usb *usb, byte epnum) +{ +}