]> mj.ucw.cz Git - home-hw.git/commitdiff
Split to low/high-level part
authorMartin Mares <mj@ucw.cz>
Sun, 24 Jun 2018 14:19:40 +0000 (16:19 +0200)
committerMartin Mares <mj@ucw.cz>
Sun, 24 Jun 2018 14:19:40 +0000 (16:19 +0200)
Inc/usb.h
Inc/util.h
Makefile
Src/usb.c
Src/usbdev.c [new file with mode: 0644]

index e33a71f1442faf532ab1407b531633167ccbe06f..114a5378ea81f4e7e2361dfbc60f4f666778ab59 100644 (file)
--- 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
index 388a1bd758946472fc8a1ba8701c9f03d5ec4de5..6772a50adeec9b177b3e9d1cdff0c9ffb5015379 100644 (file)
@@ -1,4 +1,5 @@
 #include <stdint.h>
+#include <stdbool.h>
 
 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
index a50db714e8f32dcc8a7fcd35847062e6018c0da2..a1e31eb671ea2c2ac41838e26919953bb45c4098 100644 (file)
--- 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 \
index b7f731331e89a3b51f7fadb1714db6c80d98d6dc..c6867da79b8a7bec04c45e0c1abcf9642d741c57 100644 (file)
--- a/Src/usb.c
+++ b/Src/usb.c
@@ -6,88 +6,6 @@
 
 #include <string.h>
 
-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 (file)
index 0000000..3e6e76a
--- /dev/null
@@ -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)
+{
+}