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 Norimasa Okamoto

Revision:
16:981c3104f6c0
Parent:
14:b167f2b97cb7
Child:
18:61554f238584
diff -r d14c06cc5c07 -r 981c3104f6c0 USBHost/USBHALHost_F401RE.cpp
--- 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