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/USBHost.cpp
- Revision:
- 9:7f9f64cf5ded
- Parent:
- 8:6463cd1964c0
- Child:
- 10:40c7f6788902
diff -r 6463cd1964c0 -r 7f9f64cf5ded USBHost/USBHost.cpp --- a/USBHost/USBHost.cpp Fri Jan 31 13:45:07 2014 +0000 +++ b/USBHost/USBHost.cpp Mon Feb 03 13:00:16 2014 +0000 @@ -2,34 +2,6 @@ #include "USBHost.h" #include <algorithm> -template <bool>struct CtAssert; -template <>struct CtAssert<true> {}; -#define CTASSERT(A) CtAssert<A>(); - - -#ifdef _USB_DBG -#define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0); -#define USB_DBG2(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0); -#define USB_DBG_HEX(A,B) debug_hex(A,B) -#define USB_DBG_ERRSTAT() report.print_errstat(); -void debug_hex(uint8_t* buf, int size); -#else -#define USB_DBG(...) while(0) -#define USB_DBG2(...) while(0) -#define USB_DBG_HEX(A,B) while(0) -#define USB_DBG_ERRSTAT() 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 - -#define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);}while(0); - USBHost* USBHost::inst = NULL; USBHost* USBHost::getHostInst() @@ -41,8 +13,14 @@ return inst; } +void USBHost::poll() +{ + if (inst) { + inst->task(); + } +} + USBHost::USBHost() { - DeviceLists_count = 0; } /* virtual */ bool USBHost::addDevice(int hub, int port, bool lowSpeed) { @@ -74,12 +52,11 @@ dev->setVid(dev_desc->idVendor); dev->setPid(dev_desc->idProduct); dev->setClass(dev_desc->bDeviceClass); - USB_INFO("hub: %d port: %d speed: %s vid: %04x pid: %04x class: %02x addr: %d\n", + USB_INFO("hub: %d port: %d speed: %s vid: %04x pid: %04x class: %02x addr: %d", hub, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(), dev->getAddress()); - USB_TEST_ASSERT(DeviceLists_count < MAX_DEVICE_CONNECTED); - DeviceLists[DeviceLists_count++] = dev; + DeviceLists.push(dev); if (dev->getClass() == HUB_CLASS) { const int config = 1; @@ -146,7 +123,6 @@ uint32_t index = 0; uint32_t len_desc = 0; uint8_t id = 0; - int nb_endpoints_used = 0; USBEndpoint * ep = NULL; uint8_t intf_nb = 0; bool parsing_intf = false; @@ -156,6 +132,7 @@ while (index < len) { len_desc = conf_descr[index]; id = conf_descr[index+1]; + USB_DBG_HEX(conf_descr+index, len_desc); switch (id) { case CONFIGURATION_DESCRIPTOR: USB_DBG("dev: %p has %d intf", dev, conf_descr[4]); @@ -163,14 +140,10 @@ break; case INTERFACE_DESCRIPTOR: if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) { - if (intf_nb++ <= MAX_INTF) { - current_intf = conf_descr[index + 2]; - dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); - nb_endpoints_used = 0; - USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); - } else { - USB_DBG("Drop intf..."); - } + intf_nb++; + current_intf = conf_descr[index + 2]; + dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); + USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); parsing_intf = true; } else { parsing_intf = false; @@ -179,19 +152,16 @@ case ENDPOINT_DESCRIPTOR: ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index); if (parsing_intf && (intf_nb <= MAX_INTF) ) { - if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) { - ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); - ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; - if(pEnumerator->useEndpoint(current_intf, type, dir)) { - ep = new USBEndpoint; - ep->setDevice(dev); - ep->setType(type); - ep->setAddress(ep_desc->bEndpointAddress); - ep->setSize(ep_desc->wMaxPacketSize); - USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); - dev->addEndpoint(current_intf, ep); - nb_endpoints_used++; - } + ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03); + ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT; + if(pEnumerator->useEndpoint(current_intf, type, dir)) { + ep = new USBEndpoint; + ep->setDevice(dev); + ep->setType(type); + ep->setAddress(ep_desc->bEndpointAddress); + ep->setSize(ep_desc->wMaxPacketSize); + USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev); + dev->addEndpoint(current_intf, ep); } } break; @@ -223,9 +193,14 @@ return USB_TYPE_ERROR; } -USB_TYPE USBHost::bulkRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { - USB_TEST_ASSERT(blocking); - int result = BulkRead(ep, buf, len); +USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setType(BULK_ENDPOINT); + ep->setBuffer(buf, len); + ep_queue.push(ep); + return USB_TYPE_PROCESSING; + } + int result = bulkReadBLOCK(ep, buf, len, -1); if (result >= 0) { return USB_TYPE_OK; } @@ -233,9 +208,9 @@ return USB_TYPE_ERROR; } -USB_TYPE USBHost::bulkWrite(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { +USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { USB_TEST_ASSERT(blocking); - int result = BulkWrite(ep, buf, len); + int result = bulkWriteNB(ep, buf, len); if (result >= 0) { return USB_TYPE_OK; } @@ -243,12 +218,32 @@ return USB_TYPE_ERROR; } -USB_TYPE USBHost::interruptRead(USBDeviceConnected * dev, USBEndpoint * ep, uint8_t * buf, uint32_t len, bool blocking) { - int result = InterruptRead(ep, buf, len); - if (result >= 0) { - return USB_TYPE_OK; +USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setType(INTERRUPT_ENDPOINT); + ep->setBuffer(buf, len); + ep_queue.push(ep); + return USB_TYPE_PROCESSING; } - return USB_TYPE_ERROR; + interruptReadNB(ep, buf, len); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + USB_TEST_ASSERT(blocking); + interruptWriteNB(ep, buf, len); + return USB_TYPE_OK; +} + +USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) { + if (blocking == false) { + ep->setType(ISOCHRONOUS_ENDPOINT); + ep->setBuffer(buf, len); + ep_queue.push(ep); + return USB_TYPE_PROCESSING; + } + isochronousReadNB(ep, buf, len); + return USB_TYPE_OK; } int USBHost::ControlRead(USBDeviceConnected* dev, SETUP_PACKET* setup, uint8_t* data, int size) { @@ -316,7 +311,8 @@ return write_len; } -int USBHost::InterruptRead(USBEndpoint* ep, uint8_t* data, int size) { +int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) +{ USB_TEST_ASSERT(ep); USBDeviceConnected* dev = ep->getDevice(); USB_TEST_ASSERT(dev); @@ -346,7 +342,43 @@ return read_len; } -int USBHost::BulkRead(USBEndpoint* ep, uint8_t* data, int size, int timeout_ms) { +int USBHost::interruptWriteNB(USBEndpoint* ep, const uint8_t* data, int size) +{ + USB_TEST_ASSERT(ep); + USBDeviceConnected* dev = ep->getDevice(); + USB_TEST_ASSERT(dev); + setAddr(dev->getAddress(), dev->getSpeed()); + setEndpoint(); + const int retryLimit = 0; + int transferred_len = 0; + for(int n = 0; transferred_len < size; n++) { + int size2 = std::min(size-transferred_len, ep->getSize()); + int result = token_out(ep, data+transferred_len, size2, retryLimit); + if (result < 0) { + if (LastStatus == NAK) { + if (n == 0) { + return -1; + } + break; + } + //USB_DBG("token_in result=%d %02x", result, LastStatus); + return result; + } + transferred_len += result; + if (result < ep->getSize()) { + break; + } + } + ep->setLengthTransferred(transferred_len); + return transferred_len; +} + +int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) +{ + return bulkReadBLOCK(ep, data, size, 0); +} + +int USBHost::bulkReadBLOCK(USBEndpoint* ep, uint8_t* data, int size, int timeout_ms) { USB_TEST_ASSERT(ep); USBDeviceConnected* dev = ep->getDevice(); USB_TEST_ASSERT(dev); @@ -381,7 +413,7 @@ return read_len; } -int USBHost::BulkWrite(USBEndpoint* ep, const uint8_t* data, int size) { +int USBHost::bulkWriteNB(USBEndpoint* ep, const uint8_t* data, int size) { USB_TEST_ASSERT(ep); USBDeviceConnected* dev = ep->getDevice(); USB_TEST_ASSERT(dev); @@ -410,7 +442,7 @@ return write_len; } -int USBHost::IsochronousRead(USBEndpoint* ep, uint8_t* data, int size) { +int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) { USBDeviceConnected* dev = ep->getDevice(); USB_TEST_ASSERT(dev); setAddr(dev->getAddress()); @@ -421,3 +453,30 @@ return result; } +void USBHost::task() +{ + if (ep_queue.empty()) { + return; + } + USBEndpoint* ep = ep_queue.pop(); + USB_TEST_ASSERT(ep); + ep->setLengthTransferred(0); + switch(ep->getType()) { + case INTERRUPT_ENDPOINT: + if (ep->getDir() == IN) { + interruptReadNB(ep, ep->getBufStart(), ep->getBufSize()); + } + break; + case BULK_ENDPOINT: + if (ep->getDir() == IN) { + bulkReadNB(ep, ep->getBufStart(), ep->getBufSize()); + } + break; + case ISOCHRONOUS_ENDPOINT: + if (ep->getDir() == IN) { + isochronousReadNB(ep, ep->getBufStart(), ep->getBufSize()); + } + break; + } + ep->call(); +}