USB Host Driver with Socket Modem support. Works with revision 323 of mbed-src but broken with any later version.
Dependencies: FATFileSystem
Fork of F401RE-USBHost by
Diff: USBHost/USBHALHost_F401RE.cpp
- Revision:
- 11:61843badd06e
- Child:
- 13:8774c07f12a5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/USBHALHost_F401RE.cpp Mon Jun 09 09:00:49 2014 +0000 @@ -0,0 +1,434 @@ +// Simple USBHost for Nucleo F401RE +#if defined(TARGET_NUCLEO_F401RE) +#include "USBHALHost_F401RE.h" + +template <bool>struct CtAssert; +template <>struct CtAssert<true> {}; +#define CTASSERT(A) CtAssert<A>(); + + +#ifdef _USB_DBG +extern RawSerial pc; +#include "mydebug.h" +#define USB_DBG(...) do{pc.printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);pc.printf(__VA_ARGS__);pc.puts("\n");} while(0); +#define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B) + +#else +#define USB_DBG(...) while(0) +#define USB_DBG_HEX(A,B) while(0) +#endif + +#ifdef _USB_TEST +#define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; +#define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A)) +#else +#define USB_TEST_ASSERT(A) while(0) +#define USB_TEST_ASSERT_FALSE(A) while(0) +#endif + +#ifdef _USB_TRACE +#define USB_TRACE() while(0) +#define USB_TRACE1(A) while(0) +#define USB_TRACE_VIEW() while(0) +#define USB_TRACE_CLEAR() while(0) +#else +#define USB_TRACE() while(0) +#define USB_TRACE1(A) while(0) +#define USB_TRACE_VIEW() while(0) +#define USB_TRACE_CLEAR() while(0) +#endif + +#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); + +__IO bool attach_done = false; +__IO bool token_done = false; +__IO HCD_URBStateTypeDef g_urb_state = URB_IDLE; + +void delay_ms(uint32_t t) +{ + HAL_Delay(t); +} + +// from usbh_conf.c +extern HCD_HandleTypeDef hhcd_USB_OTG_FS; + +void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if(hhcd->Instance==USB_OTG_FS) + { + /* Peripheral clock enable */ + __USB_OTG_FS_CLK_ENABLE(); + + /**USB_OTG_FS GPIO Configuration + PA11 ------> USB_OTG_FS_DM + PA12 ------> USB_OTG_FS_DP + */ + GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral interrupt init*/ + /* Sets the priority grouping field */ + HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0); + HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } +} + +// from stm32f4xx_it.c +extern "C" { +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + USB_TRACE(); + attach_done = true; +} + +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + USB_TRACE(); +} + +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + USB_TRACE1(chnum); + USB_TRACE1(urb_state); + g_urb_state = urb_state; + token_done = true; +} + +} // extern "C" + +const int CH_CTL_IN = 0; +const int CH_CTL_OUT = 1; +const int CH_INT_IN = 2; +const int CH_INT_OUT = 3; +const int CH_BLK_IN = 4; +const int CH_BLK_OUT = 5; +const int CH_ISO_IN = 6; +const int DIR_IN = 1; +const int DIR_OUT = 0; + + + +USBHALHost* USBHALHost::instHost; + +USBHALHost::USBHALHost() { + instHost = this; +} + +void USBHALHost::init() { + hhcd_USB_OTG_FS.Instance = USB_OTG_FS; + hhcd_USB_OTG_FS.Init.Host_channels = 8; + hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL; + hhcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED; + hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + hhcd_USB_OTG_FS.Init.low_power_enable = ENABLE; + hhcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE; + hhcd_USB_OTG_FS.Init.use_external_vbus = DISABLE; + + HAL_HCD_Init(&hhcd_USB_OTG_FS); + HAL_HCD_Start(&hhcd_USB_OTG_FS); + + bool lowSpeed = wait_attach(); + delay_ms(200); + HAL_HCD_ResetPort(&hhcd_USB_OTG_FS); + delay_ms(100); // Wait for 100 ms after Reset + addDevice(NULL, 0, lowSpeed); +} + +bool USBHALHost::wait_attach() { + Timer t; + t.reset(); + t.start(); + while(!attach_done) { + if (t.read_ms() > 5*1000) { + t.reset(); + USB_INFO("Please attach USB device."); + } + } + wait_ms(100); + return HAL_HCD_GetCurrentSpeed(&hhcd_USB_OTG_FS) == USB_OTG_SPEED_LOW; +} + +int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { + USBDeviceConnected* dev = ep->getDevice(); + + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_OUT, 0x00, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + setup->wLength = wLength; + + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_CTL_OUT, DIR_OUT, EP_TYPE_CTRL, 0, (uint8_t*)setup, 8, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT)) { + case URB_DONE: + LastStatus = ACK; + break; + default: + LastStatus = 0xff; + break; + } + ep->setData01(DATA1); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_OUT); +} + +HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest2(HCD_HandleTypeDef *hhcd, + uint8_t ch_num, + uint8_t direction , + uint8_t ep_type, + uint8_t token, + uint8_t* pbuff, + uint16_t length, + uint8_t do_ping) +{ + HCD_HCTypeDef* hc = &(hhcd->hc[ch_num]); + hc->ep_is_in = direction; + hc->ep_type = ep_type; + + if (hc->toggle_in == 0) { + hc->data_pid = HC_PID_DATA0; + } else { + hc->data_pid = HC_PID_DATA1; + } + + hc->xfer_buff = pbuff; + hc->xfer_len = length; + hc->urb_state = URB_IDLE; + hc->xfer_count = 0 ; + hc->ch_num = ch_num; + hc->state = HC_IDLE; + + return USB_HC_StartXfer(hhcd->Instance, hc, hhcd->Init.dma_enable); +} + +int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + switch(ep->getType()) { + case CONTROL_ENDPOINT: + return token_ctl_in(ep, data, size, retryLimit); + case INTERRUPT_ENDPOINT: + return token_int_in(ep, data, size); + case BULK_ENDPOINT: + return token_blk_in(ep, data, size, retryLimit); + } + return -1; +} + +int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_IN, 0x80, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_CTL_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1; + + HAL_HCD_HC_SubmitRequest2(&hhcd_USB_OTG_FS, CH_CTL_IN, DIR_IN, EP_TYPE_CTRL, 1, data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_IN) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_IN)) { + case URB_DONE: + LastStatus = ACK; + break; + default: + LastStatus = 0xff; + return -1; + } + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_IN); +} + +int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_INT_IN, + ep->getAddress(), + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_INTR, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_INT_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1; + + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_INT_IN, DIR_IN, EP_TYPE_INTR, 1, data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_IN) == URB_IDLE); + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_IN)) { + case URB_DONE: + switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_INT_IN)) { + case HC_XFRC: + LastStatus = ep->getData01(); + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_INT_IN); + case HC_NAK: + LastStatus = NAK; + return -1; + } + break; + } + LastStatus = STALL; + return -1; +} + +int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + int retry = 0; + do { + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_BLK_IN, + ep->getAddress(), + dev->getAddress(), + HCD_SPEED_FULL, + EP_TYPE_BULK, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_BLK_IN].toggle_in = (ep->getData01() == DATA0) ? 0 : 1; + + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_BLK_IN, DIR_IN, EP_TYPE_BULK, 1, data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_IN) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_IN)) { + case URB_DONE: + switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_BLK_IN)) { + case HC_XFRC: + LastStatus = ep->getData01(); + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_BLK_IN); + case HC_NAK: + LastStatus = NAK; + if (retryLimit > 0) { + delay_ms(1 + 10 * retry); + } + break; + default: + break; + } + break; + case URB_STALL: + LastStatus = STALL; + return -1; + default: + LastStatus = STALL; + delay_ms(500 + 100 * retry); + break; + } + }while(retry++ < retryLimit); + return -1; +} + +int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + switch(ep->getType()) { + case CONTROL_ENDPOINT: + return token_ctl_out(ep, data, size, retryLimit); + case INTERRUPT_ENDPOINT: + return token_int_out(ep, data, size); + case BULK_ENDPOINT: + return token_blk_out(ep, data, size, retryLimit); + } + return -1; +} + +int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_OUT, 0x00, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_CTL_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1; + + do { + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_CTL_OUT, DIR_OUT, EP_TYPE_CTRL, 1, (uint8_t*)data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT)) { + case URB_DONE: + LastStatus = ACK; + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_OUT); + + default: + break; + } + delay_ms(1); + }while(retryLimit-- > 0); + return -1; +} + +int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_INT_OUT, + ep->getAddress(), + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_INTR, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_INT_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1; + + token_done = false; + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_INT_OUT, DIR_OUT, EP_TYPE_INTR, 1, (uint8_t*)data, size, 0); + while(!token_done); + + if (HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_INT_OUT) != URB_DONE) { + return -1; + } + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_INT_OUT); +} + +int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + USBDeviceConnected* dev = ep->getDevice(); + int retry = 0; + do { + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_BLK_OUT, + ep->getAddress(), dev->getAddress(), + HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize()); + hhcd_USB_OTG_FS.hc[CH_BLK_OUT].toggle_out = (ep->getData01() == DATA0) ? 0 : 1; + + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_BLK_OUT, DIR_OUT, EP_TYPE_BULK, 1, (uint8_t*)data, size, 0); + while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_OUT) == URB_IDLE); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_BLK_OUT)) { + case URB_DONE: + switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_BLK_OUT)) { + case HC_XFRC: // ACK + LastStatus = ep->getData01(); + ep->toggleData01(); + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_BLK_OUT); + default: + break; + } + break; + case URB_NOTREADY: // HC_NAK + LastStatus = NAK; + delay_ms(100 * retry); + break; + default: + LastStatus = STALL; + return -1; + } + } while(retry++ < retryLimit); + return -1; +} + +int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { + USBDeviceConnected* dev = ep->getDevice(); + HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_ISO_IN, + ep->getAddress(), + dev->getAddress(), + HCD_SPEED_FULL, + EP_TYPE_ISOC, ep->getSize()); + + token_done = false; + HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_ISO_IN, DIR_IN, EP_TYPE_ISOC, 1, data, size, 0); + while(!token_done); + + switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_ISO_IN)) { + case URB_DONE: + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_ISO_IN); + + default: + return -1; + } +} + +#endif + +