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:
- 16:981c3104f6c0
- Parent:
- 14:b167f2b97cb7
- Child:
- 18:61554f238584
--- a/USBHost/USBHALHost_F401RE.cpp Fri Jun 13 01:52:44 2014 +0000 +++ b/USBHost/USBHALHost_F401RE.cpp Mon Jun 23 20:30:04 2014 +0900 @@ -1,6 +1,7 @@ // Simple USBHost for Nucleo F401RE #if defined(TARGET_NUCLEO_F401RE) #include "USBHALHost_F401RE.h" +#include <algorithm> template <bool>struct CtAssert; template <>struct CtAssert<true> {}; @@ -9,6 +10,7 @@ #ifdef _USB_DBG extern RawSerial pc; +//RawSerial pc(USBTX,USBRX); #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) @@ -41,15 +43,13 @@ #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 +// usbh_conf.c extern HCD_HandleTypeDef hhcd_USB_OTG_FS; void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd) @@ -79,7 +79,7 @@ } } -// from stm32f4xx_it.c +// stm32f4xx_it.c extern "C" { void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) { @@ -87,33 +87,8 @@ 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() { @@ -156,19 +131,19 @@ } int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { + const uint8_t ep_addr = 0x00; + HC hc; USBDeviceConnected* dev = ep->getDevice(); - - HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_OUT, 0x00, + hc.Init(ep_addr, dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, EP_TYPE_CTRL, ep->getSize()); setup->wLength = wLength; + hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP + while(hc.GetURBState() == URB_IDLE); - 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)) { + switch(hc.GetURBState()) { case URB_DONE: LastStatus = ACK; break; @@ -177,36 +152,7 @@ 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); + return 8; } int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { @@ -222,17 +168,20 @@ } int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + const uint8_t ep_addr = 0x80; + HC hc; USBDeviceConnected* dev = ep->getDevice(); - HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_CTL_IN, 0x80, + hc.Init(ep_addr, 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; + + hc.SetToggle((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); + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); - switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_IN)) { + switch(hc.GetURBState()) { case URB_DONE: LastStatus = ACK; break; @@ -241,27 +190,29 @@ return -1; } ep->toggleData01(); - return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_CTL_IN); + return hc.GetXferCount(); } int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) { + HC hc; USBDeviceConnected* dev = ep->getDevice(); - HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_INT_IN, + hc.Init( 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; + + hc.SetToggle((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)) { + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); + switch(hc.GetURBState()) { case URB_DONE: - switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_INT_IN)) { + switch(hc.GetState()) { case HC_XFRC: LastStatus = ep->getData01(); ep->toggleData01(); - return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_INT_IN); + return hc.GetXferCount(); case HC_NAK: LastStatus = NAK; return -1; @@ -273,26 +224,28 @@ } int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { + HC hc; USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), + dev->getAddress(), + HCD_SPEED_FULL, + EP_TYPE_BULK, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + 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; + hc.SubmitRequest(data, size); + while(hc.GetURBState() == URB_IDLE); - 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)) { + switch(hc.GetURBState()) { case URB_DONE: - switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_BLK_IN)) { + switch(hc.GetState()) { case HC_XFRC: LastStatus = ep->getData01(); ep->toggleData01(); - return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_BLK_IN); + return hc.GetXferCount(); case HC_NAK: LastStatus = NAK; if (retryLimit > 0) { @@ -328,18 +281,21 @@ } int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + const uint8_t ep_addr = 0x00; + HC hc; 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; + hc.Init(ep_addr, + dev->getAddress(), + dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, + EP_TYPE_CTRL, ep->getSize()); + + hc.SetToggle((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); + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); - switch(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_CTL_OUT)) { + switch(hc.GetURBState()) { case URB_DONE: LastStatus = ACK; ep->toggleData01(); @@ -354,19 +310,19 @@ } int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) { + HC hc; USBDeviceConnected* dev = ep->getDevice(); - HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_INT_OUT, + hc.Init( 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; + + hc.SetToggle((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) { + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); + if (hc.GetURBState() != URB_DONE) { return -1; } ep->toggleData01(); @@ -374,20 +330,22 @@ } int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { + HC hc; USBDeviceConnected* dev = ep->getDevice(); + hc.Init( + ep->getAddress(), dev->getAddress(), + HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize()); + + hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); + 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; + hc.SubmitRequest((uint8_t*)data, size); + while(hc.GetURBState() == URB_IDLE); - 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)) { + switch(hc.GetURBState()) { case URB_DONE: - switch(HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, CH_BLK_OUT)) { + switch(hc.GetState()) { case HC_XFRC: // ACK LastStatus = ep->getData01(); ep->toggleData01(); @@ -409,17 +367,158 @@ } int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { - static bool init = false; - if (!init) { - init = true; + HC* hc = ep->getHALData<HC*>(); + if (hc == NULL) { + hc = new HC; + ep->setHALData<HC*>(hc); USBDeviceConnected* dev = ep->getDevice(); - HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, CH_ISO_IN, + hc->Init( ep->getAddress(), dev->getAddress(), HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize()); } - HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, CH_ISO_IN, DIR_IN, EP_TYPE_ISOC, 1, data, size, 0); - while(HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, CH_ISO_IN) == URB_IDLE); - return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, CH_ISO_IN); + hc->SubmitRequest(data, size); + while(hc->GetURBState() == URB_IDLE); + return hc->GetXferCount(); +} + +int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block) { + if (total == 0) { + return token_in(ep); + } + int retryLimit = block ? 10 : 0; + int read_len = 0; + for(int n = 0; read_len < total; n++) { + int size = std::min((int)total-read_len, ep->getSize()); + int result = token_in(ep, data+read_len, size, retryLimit); + if (result < 0) { + if (block) { + return -1; + } + if (LastStatus == NAK) { + if (n == 0) { + return -1; + } + break; + } + return result; + } + read_len += result; + if (result < ep->getSize()) { + break; + } + } + return read_len; +} + +int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total, bool block) { + if (total == 0) { + return token_out(ep); + } + int write_len = 0; + for(int n = 0; write_len < total; n++) { + int size = std::min((int)total-write_len, ep->getSize()); + int result = token_out(ep, data+write_len, size); + if (result < 0) { + if (LastStatus == NAK) { + if (n == 0) { + return -1; + } + break; + } + USB_DBG("token_out result=%d %02x", result, LastStatus); + return result; + } + write_len += result; + if (result < ep->getSize()) { + break; + } + } + return write_len; +} + +uint8_t HC::slot = 0x00; + +HC::HC() { + uint8_t mask = 0x01; + for(int i = 1; i < 8; i++, mask <<= 1) { + if (!(slot & mask)) { + slot |= mask; + _ch = i; + return; + } + } + _ch = 0; // ERROR!!! +} + +HC::HC(int ch) { + _ch = ch; + slot |= (1<<_ch); +} + +HC::~HC() { + slot &= ~(1<<_ch); +} + +HAL_StatusTypeDef HC::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) { + _ep_addr = epnum; + _ep_type = ep_type; + return HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, _ch, + epnum, dev_address, speed, ep_type, mps); +} + +HAL_StatusTypeDef HC::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup) { + uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT; + if (_ep_type == EP_TYPE_CTRL) { + HCD_HCTypeDef* hc = &hhcd_USB_OTG_FS.hc[_ch]; + if (setup) { + hc->data_pid = HC_PID_SETUP; + hc->toggle_out = 0; + } else { + if (direction == DIR_IN) { + if (hc->toggle_in == 0) { + hc->data_pid = HC_PID_DATA0; + } else { + hc->data_pid = HC_PID_DATA1; + } + } else { // OUT + if (hc->toggle_out == 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; + hc->state = HC_IDLE; + + return USB_HC_StartXfer(hhcd_USB_OTG_FS.Instance, hc, 0); + } + return HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, _ch, + direction, _ep_type, 0, pbuff, length, 0); +} + +HCD_URBStateTypeDef HC::GetURBState() { + return HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, _ch); +} + +HCD_HCStateTypeDef HC::GetState() { + return HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, _ch); +} + +uint32_t HC::GetXferCount() { + return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, _ch); +} + +void HC::SetToggle(uint8_t toggle) { + if (_ep_addr & 0x80) { // IN + hhcd_USB_OTG_FS.hc[_ch].toggle_in = toggle; + } else { // OUT + hhcd_USB_OTG_FS.hc[_ch].toggle_out = toggle; + } } #endif