]> mj.ucw.cz Git - home-hw.git/blobdiff - Src/usb.c
Split to low/high-level part
[home-hw.git] / Src / usb.c
index ce0bddc235500e866a149dc937023aedc8698317..c6867da79b8a7bec04c45e0c1abcf9642d741c57 100644 (file)
--- a/Src/usb.c
+++ b/Src/usb.c
@@ -6,82 +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
-  0x01,                                // 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[] = {
-  "",                          // 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
-};
-
 void usb_init(struct usb *usb, PCD_HandleTypeDef *hpcd)
 {
   memset(usb, 0, sizeof(*usb));
@@ -99,33 +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);
 }
 
-#if 0  // FIXME
-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);
 }
-#endif
 
-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;
@@ -134,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;
@@ -143,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)
 {
@@ -153,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);
@@ -271,19 +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 < sizeof(desc_string) / sizeof(desc_string[0]))
-       return dev_desc_send_string(usb, setup, desc_string[desc_index]);
+      if (!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);
@@ -322,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;
@@ -330,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;
@@ -375,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;
     }
@@ -477,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);
@@ -509,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);
 }
@@ -524,6 +424,7 @@ void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
   if (!epnum)
     {
       // HAL/LL handle EP0 transfers in a completely different way, we have to do many things ourselves
+      usb_debug("Ep0 OUT: state=%u rem=%u total=%u\n", usb->ep0_state, usb->ep0_remaining_length, usb->ep0_total_length);
       if (usb->ep0_state != USB_EP0_DATA_OUT)
        return;
       if (usb->ep0_remaining_length > ep->maxpacket)
@@ -534,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);
     }
 }
 
@@ -557,6 +454,7 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
   if (!epnum)
     {
       // HAL/LL handle EP0 transfers in a completely different way, we have to do many things ourselves
+      usb_debug("Ep0 IN: state=%u rem=%u total=%u want=%u\n", usb->ep0_state, usb->ep0_remaining_length, usb->ep0_total_length, usb->ep0_setup_data_length);
       if (usb->ep0_state != USB_EP0_DATA_IN)
        return;
       if (usb->ep0_remaining_length > ep->maxpacket)
@@ -579,19 +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);
     }
 }
 
@@ -602,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);