X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Fcortex-m3%2Fdrv%2Fusb_stm32.c;h=55e27788f5876f313921a03fd4538d801420a20f;hb=493d98f6f007571506feb2d6b4250b63e2edc7e1;hp=ef1abda2aec54ad33d3fb1d220b7fefe41d021be;hpb=7713a5e329a770f53d53e39e9b3b8dae55c71614;p=bertos.git diff --git a/bertos/cpu/cortex-m3/drv/usb_stm32.c b/bertos/cpu/cortex-m3/drv/usb_stm32.c index ef1abda2..55e27788 100644 --- a/bertos/cpu/cortex-m3/drv/usb_stm32.c +++ b/bertos/cpu/cortex-m3/drv/usb_stm32.c @@ -87,7 +87,7 @@ static struct stm32_usb *usb = (struct stm32_usb *)USB_BASE_ADDR; static stm32_usb_ep_t ep_cnfg[ENP_MAX_NUMB]; /* USB EP0 control descriptor */ -static const usb_endpoint_descriptor_t USB_CtrlEpDescr0 = +static const UsbEndpointDesc USB_CtrlEpDescr0 = { .bLength = sizeof(USB_CtrlEpDescr0), .bDescriptorType = USB_DT_ENDPOINT, @@ -98,7 +98,7 @@ static const usb_endpoint_descriptor_t USB_CtrlEpDescr0 = }; /* USB EP1 control descriptor */ -static const usb_endpoint_descriptor_t USB_CtrlEpDescr1 = +static const UsbEndpointDesc USB_CtrlEpDescr1 = { .bLength = sizeof(USB_CtrlEpDescr1), .bDescriptorType = USB_DT_ENDPOINT, @@ -109,7 +109,7 @@ static const usb_endpoint_descriptor_t USB_CtrlEpDescr1 = }; /* USB setup packet */ -static usb_ctrlrequest_t setup_packet; +static UsbCtrlRequest setup_packet; /* USB device controller: max supported interfaces */ #define USB_MAX_INTERFACE 1 @@ -123,7 +123,7 @@ typedef struct stm32_udc { uint8_t state; uint32_t cfg_id; - const usb_config_descriptor_t *cfg; + const UsbConfigDesc *cfg; uint32_t interfaces; uint32_t alt[USB_MAX_INTERFACE]; uint32_t address; @@ -134,7 +134,7 @@ typedef struct stm32_udc static stm32_udc_t udc; /* Generic USB Device Controller structure */ -static struct usb_device *usb_dev; +static UsbDevice *usb_dev; /* USB packet memory management: list of allocated chunks */ static pack_mem_slot_t *pPacketMemUse; @@ -446,7 +446,15 @@ static void __usb_ep_io(int EP) bool CurrentBuffer; stm32_usb_ep_t *epd = &ep_cnfg[EP]; - ASSERT(epd->hw); + if (UNLIKELY(epd->hw == NULL)) + { + LOG_ERR("%s: invalid endpoint (EP%d-%s)\n", + __func__, + EP >> 1, + (EP & 0x01) ? "IN" : "OUT"); + ASSERT(0); + return; + } if (epd->status != BEGIN_SERVICED && epd->status != NO_SERVICED) return; @@ -605,15 +613,26 @@ static void __usb_ep_io(int EP) } } +/* + * Return the lower value from Host expected size and size and set a flag + * STM32_USB_EP_ZERO_POSSIBLE when size is lower that host expected size. + */ +static size_t usb_size(size_t size, size_t host_size) +{ + if (size < host_size) + { + ep_cnfg[CTRL_ENP_IN].flags |= STM32_USB_EP_ZERO_POSSIBLE; + return size; + } + return host_size; +} + /* Configure an EP descriptor before performing a I/O operation */ #define USB_EP_IO(__EP, __op, __buf, __size, __complete) \ ({ \ cpu_flags_t flags; \ stm32_usb_io_status_t ret; \ \ - /* NOTE: buffer must be 4-bytes aligned */ \ - ASSERT(!((size_t)__buf & 0x03)); \ - \ /* Fill EP descriptor */ \ IRQ_SAVE_DISABLE(flags); \ if (__size < 0) \ @@ -680,72 +699,6 @@ __usb_ep_write(int ep, const void *buffer, ssize_t size, void (*complete)(int)) return USB_EP_IO(ep, write, buffer, size, complete); } -static bool rx_done; -static size_t rx_size; - -static void usb_ep_read_complete(int ep) -{ - if (UNLIKELY(ep >= ENP_MAX_NUMB)) - { - ASSERT(0); - return; - } - ASSERT(!(ep & 0x01)); - - rx_done = true; - rx_size = ep_cnfg[ep].size; -} - -ssize_t usb_ep_read(int ep, void *buffer, ssize_t size) -{ - if (UNLIKELY(!size)) - return 0; - size = MIN(size, USB_RX_MAX_SIZE); - rx_done = false; - rx_size = 0; - - /* Blocking read */ - __usb_ep_read(USB_EpLogToPhysAdd(ep), buffer, size, - usb_ep_read_complete); - while (!rx_done) - cpu_relax(); - - return rx_size; -} - -static bool tx_done; -static size_t tx_size; - -static void usb_ep_write_complete(int ep) -{ - if (UNLIKELY(ep >= ENP_MAX_NUMB)) - { - ASSERT(0); - return; - } - ASSERT(ep & 0x01); - - tx_done = true; - tx_size = ep_cnfg[ep].size; -} - -ssize_t usb_ep_write(int ep, const void *buffer, ssize_t size) -{ - if (UNLIKELY(!size)) - return 0; - size = MIN(size, USB_TX_MAX_SIZE); - tx_done = false; - tx_size = 0; - - /* Blocking write */ - __usb_ep_write(USB_EpLogToPhysAdd(ep), buffer, size, - usb_ep_write_complete); - while (!tx_done) - cpu_relax(); - - return tx_size; -} - static void usb_ep_low_level_config(int ep, uint16_t offset, uint16_t size) { stm32_usb_ep_t *epc = &ep_cnfg[ep]; @@ -787,7 +740,7 @@ static void usb_ep_low_level_config(int ep, uint16_t offset, uint16_t size) } /* Enable/Disable an endpoint */ -static int usb_ep_configure(const usb_endpoint_descriptor_t *epd, bool enable) +static int usb_ep_configure(const UsbEndpointDesc *epd, bool enable) { int EP; stm32_usb_ep_t *ep_hw; @@ -814,7 +767,7 @@ static int usb_ep_configure(const usb_endpoint_descriptor_t *epd, bool enable) ep_hw->flags = 0; /* Set endpoint type */ - ep_hw->type = usb_endpoint_type(epd); + ep_hw->type = usb_endpointType(epd); /* Init EP max packet size */ ep_hw->max_size = epd->wMaxPacketSize; @@ -828,6 +781,8 @@ static int usb_ep_configure(const usb_endpoint_descriptor_t *epd, bool enable) /* Set Ep Address */ EpCtrlSet_EA(hw, EP >> 1); ep_hw->hw = hw; + LOG_INFO("%s: EP%d-%s configured\n", + __func__, EP >> 1, EP & 1 ? "IN" : "OUT"); /* Low-level endpoint configuration */ usb_ep_low_level_config(EP, Offset, MaxPacketSizeTmp); @@ -974,13 +929,13 @@ static void USB_StallCtrlEP(void) */ static int usb_find_interface(uint32_t num, uint32_t alt) { - usb_interface_descriptor_t *id; + const UsbInterfaceDesc *id; int i; for (i = 0; ; i++) { /* TODO: support more than one configuration per device */ - id = (usb_interface_descriptor_t *)usb_dev->config[i]; + id = (const UsbInterfaceDesc *)usb_dev->config[i]; if (id == NULL) break; if (id->bDescriptorType != USB_DT_INTERFACE) @@ -998,7 +953,7 @@ static int usb_find_interface(uint32_t num, uint32_t alt) static void usb_configure_ep_interface(unsigned int num, unsigned int alt, bool enable) { - usb_endpoint_descriptor_t *epd; + const UsbEndpointDesc *epd; int i, start; /* @@ -1021,9 +976,11 @@ usb_configure_ep_interface(unsigned int num, unsigned int alt, bool enable) */ for (i = start + 1; ; i++) { - epd = (usb_endpoint_descriptor_t *)usb_dev->config[i]; - if ((epd == NULL) || (epd->bDescriptorType != USB_DT_ENDPOINT)) + epd = (const UsbEndpointDesc *)usb_dev->config[i]; + if ((epd == NULL) || (epd->bDescriptorType == USB_DT_INTERFACE)) break; + if (epd->bDescriptorType != USB_DT_ENDPOINT) + continue; if (UNLIKELY(usb_ep_configure(epd, enable) < 0)) { LOG_ERR("%s: out of memory, can't initialize EP\n", @@ -1125,6 +1082,96 @@ static void USB_StatusHandler(UNUSED_ARG(int, EP)) } } +static bool rx_done; +static size_t rx_size; + +static void usb_ep_read_complete(int ep) +{ + if (UNLIKELY(ep >= ENP_MAX_NUMB)) + { + ASSERT(0); + return; + } + ASSERT(!(ep & 0x01)); + + rx_done = true; + rx_size = ep_cnfg[ep].size; +} + +ssize_t usb_ep_read(int ep, void *buffer, ssize_t size) +{ + int ep_num = USB_EpLogToPhysAdd(ep); + + /* Non-blocking read for EP0 */ + if (ep_num == CTRL_ENP_OUT) + { + size = usb_size(size, usb_le16_to_cpu(setup_packet.wLength)); + if (!size) + USB_StatusHandler(ep_num); + else + __usb_ep_read(ep_num, buffer, size, + USB_StatusHandler); + return size; + } + if (UNLIKELY(!size)) + return 0; + size = MIN(size, USB_RX_MAX_SIZE); + rx_done = false; + rx_size = 0; + + /* Blocking read */ + __usb_ep_read(ep_num, buffer, size, usb_ep_read_complete); + while (!rx_done) + cpu_relax(); + + return rx_size; +} + +static bool tx_done; +static size_t tx_size; + +static void usb_ep_write_complete(int ep) +{ + if (UNLIKELY(ep >= ENP_MAX_NUMB)) + { + ASSERT(0); + return; + } + ASSERT(ep & 0x01); + + tx_done = true; + tx_size = ep_cnfg[ep].size; +} + +ssize_t usb_ep_write(int ep, const void *buffer, ssize_t size) +{ + int ep_num = USB_EpLogToPhysAdd(ep); + + /* Non-blocking write for EP0 */ + if (ep_num == CTRL_ENP_IN) + { + size = usb_size(size, usb_le16_to_cpu(setup_packet.wLength)); + if (!size) + USB_StatusHandler(ep_num); + else + __usb_ep_write(ep_num, buffer, size, + USB_StatusHandler); + return size; + } + if (UNLIKELY(!size)) + return 0; + size = MIN(size, USB_TX_MAX_SIZE); + tx_done = false; + tx_size = 0; + + /* Blocking write */ + __usb_ep_write(ep_num, buffer, size, usb_ep_write_complete); + while (!tx_done) + cpu_relax(); + + return tx_size; +} + /* Global variable to handle the following non-blocking I/O operations */ static uint32_t InData; @@ -1135,8 +1182,9 @@ static int UsbDevStatus(uint16_t index) return -USB_NODEV_ERROR; InData = ((uint32_t)udc.feature) & 0xff; - __usb_ep_write(CTRL_ENP_IN, (uint8_t *)&InData, 2, USB_StatusHandler); - + __usb_ep_write(CTRL_ENP_IN, + (uint8_t *)&InData, sizeof(uint16_t), + USB_StatusHandler); return 0; } @@ -1144,8 +1192,9 @@ static int UsbDevStatus(uint16_t index) static int UsbInterfaceStatus(UNUSED_ARG(uint16_t, index)) { InData = 0; - __usb_ep_write(CTRL_ENP_IN, (uint8_t *)&InData, 2, USB_StatusHandler); - + __usb_ep_write(CTRL_ENP_IN, + (uint8_t *)&InData, sizeof(uint16_t), + USB_StatusHandler); return 0; } @@ -1157,8 +1206,9 @@ static int UsbEpStatus(uint16_t index) InData = 0; USB_GetStallEP(USB_EpLogToPhysAdd(index), (bool *)&InData); - __usb_ep_write(CTRL_ENP_IN, (uint8_t *)&InData, 2, USB_StatusHandler); - + __usb_ep_write(CTRL_ENP_IN, + (uint8_t *)&InData, sizeof(uint16_t), + USB_StatusHandler); return 0; } @@ -1243,20 +1293,6 @@ static void USB_GetStatusHandler(void) } } -/* - * Return the lower value from Host expected size and size and set a flag - * STM32_USB_EP_ZERO_POSSIBLE when size is lower that host expected size. - */ -static size_t usb_size(size_t size, size_t host_size) -{ - if (size < host_size) - { - ep_cnfg[CTRL_ENP_IN].flags |= STM32_USB_EP_ZERO_POSSIBLE; - return size; - } - return host_size; -} - static int usb_get_device_descriptor(int id) { if (id) @@ -1265,7 +1301,7 @@ static int usb_get_device_descriptor(int id) usb_dev->device->bMaxPacketSize0 = USB_EP0_MAX_SIZE; __usb_ep_write(CTRL_ENP_IN, (const uint8_t *)usb_dev->device, usb_size(usb_dev->device->bLength, - setup_packet.wLength), + usb_le16_to_cpu(setup_packet.wLength)), USB_StatusHandler); return 0; } @@ -1275,8 +1311,8 @@ static uint8_t usb_cfg_buffer[USB_BUFSIZE]; static int usb_get_configuration_descriptor(int id) { - const usb_config_descriptor_t **config = - (const usb_config_descriptor_t **)usb_dev->config; + const UsbConfigDesc **config = + (const UsbConfigDesc **)usb_dev->config; uint8_t *p = usb_cfg_buffer; int i; @@ -1295,22 +1331,23 @@ static int usb_get_configuration_descriptor(int id) return -USB_BUF_OVERFLOW; } } - ((usb_config_descriptor_t *)usb_cfg_buffer)->wTotalLength = + ((UsbConfigDesc *)usb_cfg_buffer)->wTotalLength = usb_cpu_to_le16(p - usb_cfg_buffer); __usb_ep_write(CTRL_ENP_IN, usb_cfg_buffer, usb_size(p - usb_cfg_buffer, - setup_packet.wLength), + usb_le16_to_cpu(setup_packet.wLength)), USB_StatusHandler); return 0; } static int usb_get_string_descriptor(unsigned int id) { - usb_string_descriptor_t *lang_str; + const UsbStringDesc *lang_str; unsigned int lang_id, str_id; uint16_t w_index_lo = usb_le16_to_cpu(setup_packet.wIndex) & 0x00ff; - uint16_t w_index_hi = (usb_le16_to_cpu(setup_packet.wIndex) & 0xff00) >> 8; + uint16_t w_index_hi = (usb_le16_to_cpu(setup_packet.wIndex) & + 0xff00) >> 8; ASSERT(usb_dev->strings != NULL); ASSERT(usb_dev->strings[0] != NULL); @@ -1321,8 +1358,8 @@ static int usb_get_string_descriptor(unsigned int id) /* Find Language index */ for (lang_id = 0; ; lang_id++) { - usb_string_descriptor_t *str = usb_dev->strings[lang_id]; - + const UsbStringDesc *str = + usb_dev->strings[lang_id]; if (UNLIKELY(str == NULL)) return -USB_NODEV_ERROR; if ((str->data[0] == w_index_lo) && @@ -1339,7 +1376,8 @@ static int usb_get_string_descriptor(unsigned int id) } __usb_ep_write(CTRL_ENP_IN, lang_str, - usb_size(lang_str->bLength, setup_packet.wLength), + usb_size(lang_str->bLength, + usb_le16_to_cpu(setup_packet.wLength)), USB_StatusHandler); return 0; } @@ -1384,6 +1422,17 @@ static void UsbGetDescriptor(void) } } +/* USB setup packet: class/vendor request handler */ +static void usb_event_handler(UsbDevice *dev) +{ + /* + * TODO: get the appropriate usb_dev in function of the endpoint + * address. + */ + if (dev->event_cb) + dev->event_cb(&setup_packet); +} + /* USB setup packet: GET_DESCRIPTOR handler */ static void UBS_GetDescriptorHandler(void) { @@ -1393,6 +1442,9 @@ static void UBS_GetDescriptorHandler(void) if ((setup_packet.mRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) UsbGetDescriptor(); + /* Getting descriptor for a device is a standard request */ + else if ((setup_packet.mRequestType & USB_DIR_MASK) == USB_DIR_IN) + usb_event_handler(usb_dev); else ep_cnfg[CTRL_ENP_OUT].status = STALLED; } @@ -1432,14 +1484,14 @@ static void USB_GetConfigurationHandler(void) ep_cnfg[CTRL_ENP_OUT].status = STALLED; } -static const usb_config_descriptor_t *usb_find_configuration(int num) +static const UsbConfigDesc *usb_find_configuration(int num) { - const usb_config_descriptor_t *cfg; + const UsbConfigDesc *cfg; int i; for (i = 0; ; i++) { - cfg = (const usb_config_descriptor_t *)usb_dev->config[i]; + cfg = (const UsbConfigDesc *)usb_dev->config[i]; if (cfg == NULL) break; if (cfg->bDescriptorType != USB_DT_CONFIG) @@ -1452,7 +1504,7 @@ static const usb_config_descriptor_t *usb_find_configuration(int num) static int UsbSetConfigurationState(uint32_t Configuration) { - const usb_config_descriptor_t *pCnfg; + const UsbConfigDesc *pCnfg; unsigned int i; if (Configuration) @@ -1573,11 +1625,13 @@ static void USB_SetupHandler(void) case USB_TYPE_CLASS: LOG_INFO("%s: bmRequestType=%02x (Class)\n", __func__, setup_packet.mRequestType); + usb_event_handler(usb_dev); break; /* Vendor */ case USB_TYPE_VENDOR: LOG_INFO("%s: bmRequestType=%02x (Vendor)\n", __func__, setup_packet.mRequestType); + usb_event_handler(usb_dev); break; case USB_TYPE_RESERVED: LOG_INFO("%s: bmRequestType=%02x (Reserved)\n", @@ -1592,6 +1646,7 @@ static void USB_SetupHandler(void) } } +/* USB: low-level hardware initialization */ static void usb_hw_reset(void) { unsigned int i; @@ -1627,13 +1682,8 @@ static void usb_hw_reset(void) usb_set_address(0); /* Enable all the device interrupts */ -#if 0 usb->CNTR = bmCTRM | bmRESETM | bmSOFM | bmERRM | bmPMAOVRM | bmSUSPM | bmWKUPM; -#else - /* XXX: disable frame interrupts for now (too much noise!) */ - usb->CNTR = bmCTRM | bmRESETM | bmERRM | bmPMAOVRM | bmSUSPM | bmWKUPM; -#endif } /* Handle a correct transfer under ISR */ @@ -1723,9 +1773,13 @@ static void usb_isr(void) } if (interrupt.SOF) { +#if 0 + /* + * XXX: disable logging of frame interrupts (too much noise!) + */ uint16_t frame_nr = usb->FNR & 0x0fff; - LOG_INFO("%s: frame %#x\n", __func__, frame_nr); +#endif usb->ISTR = ~bmSOFM; } if (interrupt.WKUP) @@ -1807,7 +1861,7 @@ static void usb_init(void) } /* Register an upper layer USB device into the driver */ -int usb_device_register(struct usb_device *dev) +int usb_device_register(UsbDevice *dev) { #if CONFIG_KERN MOD_CHECK(proc);