X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=Src%2Fusb.c;h=c6867da79b8a7bec04c45e0c1abcf9642d741c57;hb=2fe5a1535ede515a5f2037f9323e7d960358ad96;hp=ce0bddc235500e866a149dc937023aedc8698317;hpb=2d024d38ea3094cf50ef92e00589fb56a066ea9a;p=home-hw.git diff --git a/Src/usb.c b/Src/usb.c index ce0bddc..c6867da 100644 --- a/Src/usb.c +++ b/Src/usb.c @@ -6,82 +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 - 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);