USB Host WAN Dongle library
Fork of USBHostWANDongle_bleedingedge by
Revision 6:075e36a3463e, committed 2012-07-27
- Comitter:
- donatien
- Date:
- Fri Jul 27 16:14:07 2012 +0000
- Parent:
- 5:3189db174f6b
- Child:
- 7:c4483d48fe96
- Commit message:
- New enumeration model to only instantiate needed endpoints
Changed in this revision
--- a/USB3GModule/WANDongle.cpp Wed Jul 25 11:13:50 2012 +0000 +++ b/USB3GModule/WANDongle.cpp Fri Jul 27 16:14:07 2012 +0000 @@ -16,7 +16,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#define __DEBUG__ 0 //Maximum verbosity +#define __DEBUG__ 0 #ifndef __MODULE__ #define __MODULE__ "WANDongle.cpp" #endif @@ -28,7 +28,7 @@ #include "WANDongle.h" #include "WANDongleInitializer.h" -WANDongle::WANDongle() : m_serialCount(0) +WANDongle::WANDongle() : m_pInitializer(NULL), m_serialCount(0) { host = USBHost::getHostInst(); init(); @@ -41,8 +41,6 @@ bool WANDongle::tryConnect() { - bool found = false; - //FIXME should run on USB thread DBG("Trying to connect device"); @@ -50,6 +48,8 @@ if (dev_connected) { return true; } + + m_pInitializer = NULL; host->lock(); @@ -57,26 +57,26 @@ { if ((dev = host->getDevice(i)) != NULL) { - DBG("Found one device, reset it"); + m_pInitializer = NULL; //Will be set in setVidPid callback + + DBG("Found one device reset it"); host->resetDevice(dev); DBG("Enumerate"); - host->enumerate(dev); + host->enumerate(dev, this); DBG("Device has VID:%04x PID%04x", dev->getVid(), dev->getPid()); - - WANDongleInitializer** initializer = WANDongleInitializer::getInitializers(host); - - while((*initializer)) + + if(m_pInitializer) //If an initializer has been found { - DBG("*initializer=%p", *initializer); - DBG("(*initializer)->getSerialVid()=%04x", (*initializer)->getSerialVid()); - DBG("(*initializer)->getSerialPid()=%04x", (*initializer)->getSerialPid()); - if ((dev->getVid() == (*initializer)->getSerialVid()) && (dev->getPid() == (*initializer)->getSerialPid())) + DBG("m_pInitializer=%p", m_pInitializer); + DBG("m_pInitializer->getSerialVid()=%04x", m_pInitializer->getSerialVid()); + DBG("m_pInitializer->getSerialPid()=%04x", m_pInitializer->getSerialPid()); + if ((dev->getVid() == m_pInitializer->getSerialVid()) && (dev->getPid() == m_pInitializer->getSerialPid())) { DBG("The dongle is in virtual serial mode"); host->registerDriver(dev, 0, this, &WANDongle::init); - m_serialCount = (*initializer)->getSerialPortCount(); + m_serialCount = m_pInitializer->getSerialPortCount(); if( m_serialCount > WANDONGLE_MAX_SERIAL_PORTS ) { m_serialCount = WANDONGLE_MAX_SERIAL_PORTS; @@ -84,9 +84,9 @@ for(int j = 0; j < m_serialCount; j++) { DBG("Connecting serial port #%d", j+1); - DBG("Ep %p", (*initializer)->getEp(dev, j, false)); - DBG("Ep %p", (*initializer)->getEp(dev, j, true)); - m_serial[j].connect( dev, (*initializer)->getEp(dev, j, false), (*initializer)->getEp(dev, j, true) ); + DBG("Ep %p", m_pInitializer->getEp(dev, j, false)); + DBG("Ep %p", m_pInitializer->getEp(dev, j, true)); + m_serial[j].connect( dev, m_pInitializer->getEp(dev, j, false), m_pInitializer->getEp(dev, j, true) ); } DBG("Device connected"); @@ -97,11 +97,11 @@ return true; } - else if ((dev->getVid() == (*initializer)->getMSDVid()) && (dev->getPid() == (*initializer)->getMSDPid())) + else if ((dev->getVid() == m_pInitializer->getMSDVid()) && (dev->getPid() == m_pInitializer->getMSDPid())) { DBG("Vodafone K3370 dongle detected in MSD mode"); //Try to switch - if( (*initializer)->switchMode(dev) ) + if( m_pInitializer->switchMode(dev) ) { DBG("Switched OK"); host->unlock(); @@ -114,8 +114,7 @@ return false; } } - (*initializer)++; - } //while() + } //if() } //if() } //for() host->unlock(); @@ -141,3 +140,58 @@ m_serial[i].init(host); } } + + +/*virtual*/ void WANDongle::setVidPid(uint16_t vid, uint16_t pid) +{ + //Load right initializer + WANDongleInitializer** initializer = WANDongleInitializer::getInitializers(host); + + while((*initializer)) + { + DBG("*initializer=%p", *initializer); + DBG("(*initializer)->getSerialVid()=%04x", (*initializer)->getSerialVid()); + DBG("(*initializer)->getSerialPid()=%04x", (*initializer)->getSerialPid()); + if ((dev->getVid() == (*initializer)->getSerialVid()) && (dev->getPid() == (*initializer)->getSerialPid())) + { + DBG("The dongle is in virtual serial mode"); + m_pInitializer = *initializer; + break; + } + else if ((dev->getVid() == (*initializer)->getMSDVid()) && (dev->getPid() == (*initializer)->getMSDPid())) + { + DBG("Vodafone K3370 dongle detected in MSD mode"); + m_pInitializer = *initializer; + break; + } + (*initializer)++; + } //while() + if(m_pInitializer) + { + m_pInitializer->setVidPid(vid, pid); + } +} + +/*virtual*/ bool WANDongle::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed +{ + if(m_pInitializer) + { + return m_pInitializer->parseInterface(intf_nb, intf_class, intf_subclass, intf_protocol); + } + else + { + return false; + } +} + +/*virtual*/ bool WANDongle::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if(m_pInitializer) + { + return m_pInitializer->useEndpoint(intf_nb, type, dir); + } + else + { + return false; + } +}
--- a/USB3GModule/WANDongle.h Wed Jul 25 11:13:50 2012 +0000 +++ b/USB3GModule/WANDongle.h Fri Jul 27 16:14:07 2012 +0000 @@ -25,6 +25,8 @@ #include "rtos.h" #include "WANDongleSerialPort.h" +#include "WANDongleInitializer.h" +#include "IUSBEnumerator.h" #define WANDONGLE_MAX_OUTEP_SIZE 64 #define WANDONGLE_MAX_INEP_SIZE 64 @@ -34,7 +36,7 @@ /** A class to use a WAN (3G/LTE) access dongle * */ -class WANDongle { +class WANDongle : public IUSBEnumerator { public: /* * Constructor @@ -60,10 +62,20 @@ IUSBHostSerial& getSerial(int index); int getSerialCount(); + //From IUSBEnumerator + + virtual void setVidPid(uint16_t vid, uint16_t pid); + + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed + + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used + protected: USBHost * host; USBDeviceConnected * dev; bool dev_connected; + + WANDongleInitializer* m_pInitializer; void init();
--- a/USB3GModule/WANDongleInitializer.cpp Wed Jul 25 11:13:50 2012 +0000 +++ b/USB3GModule/WANDongleInitializer.cpp Fri Jul 27 16:14:07 2012 +0000 @@ -85,12 +85,70 @@ Endpoint* VodafoneK3770Initializer::getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx) { - const int intf[3] = {0,4,2}; - return pDev->getEndpoint(intf[serialPortNumber], BULK_ENDPOINT, tx?OUT:IN, 0); + return pDev->getEndpoint(serialPortNumber, BULK_ENDPOINT, tx?OUT:IN, 0); } int VodafoneK3770Initializer::getSerialPortCount() { - return 3; + return 2; +} + +/*virtual*/ void VodafoneK3770Initializer::setVidPid(uint16_t vid, uint16_t pid) +{ + if( (vid == getSerialVid() ) && ( pid == getSerialPid() ) ) + { + m_hasSwitched = true; + m_currentSerialIntf = 0; + m_endpointsToFetch = 4; + } + else + { + m_hasSwitched = false; + m_endpointsToFetch = 1; + } } +/*virtual*/ bool VodafoneK3770Initializer::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed +{ + if( m_hasSwitched ) + { + if( intf_class == 0xFF ) + { + if( (m_currentSerialIntf == 0) || (m_currentSerialIntf == 4) ) + { + m_currentSerialIntf++; + return true; + } + m_currentSerialIntf++; + } + } + else + { + if( (intf_nb == 0) && (intf_class == MSD_CLASS) ) + { + return true; + } + } + return false; +} + +/*virtual*/ bool VodafoneK3770Initializer::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used +{ + if( m_hasSwitched ) + { + if( (type == BULK_ENDPOINT) && m_endpointsToFetch ) + { + m_endpointsToFetch--; + return true; + } + } + else + { + if( (type == BULK_ENDPOINT) && (dir == OUT) && m_endpointsToFetch ) + { + m_endpointsToFetch--; + return true; + } + } + return false; +}
--- a/USB3GModule/WANDongleInitializer.h Wed Jul 25 11:13:50 2012 +0000 +++ b/USB3GModule/WANDongleInitializer.h Fri Jul 27 16:14:07 2012 +0000 @@ -24,8 +24,9 @@ using std::uint32_t; #include "USBHost.h" +#include "IUSBEnumerator.h" -class WANDongleInitializer +class WANDongleInitializer : public IUSBEnumerator { protected: WANDongleInitializer(USBHost* pHost); @@ -44,6 +45,12 @@ virtual int getSerialPortCount() = 0; + virtual void setVidPid(uint16_t vid, uint16_t pid) = 0; + + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) = 0; //Must return true if the interface should be parsed + + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) = 0; //Must return true if the endpoint will be used + static WANDongleInitializer** getInitializers(USBHost* pHost); }; @@ -63,6 +70,18 @@ virtual Endpoint* getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx); virtual int getSerialPortCount(); + + virtual void setVidPid(uint16_t vid, uint16_t pid); + + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed + + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used + +private: + + bool m_hasSwitched; + int m_currentSerialIntf; + int m_endpointsToFetch; }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/IUSBEnumerator.h Fri Jul 27 16:14:07 2012 +0000 @@ -0,0 +1,41 @@ +/* Copyright (c) 2010-2012 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef IUSBENUMERATOR_H_ +#define IUSBENUMERATOR_H_ + +#include "stdint.h" + +#include "Endpoint.h" + +/* +Generic interface to implement for "smart" USB enumeration +*/ + +class IUSBEnumerator { +public: + + virtual void setVidPid(uint16_t vid, uint16_t pid) = 0; + + virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) = 0; //Must return true if the interface should be parsed + + virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) = 0; //Must return true if the endpoint will be used + +}; + +#endif /*IUSBENUMERATOR_H_*/ \ No newline at end of file
--- a/USBHost/USBDeviceConnected.h Wed Jul 25 11:13:50 2012 +0000 +++ b/USBHost/USBDeviceConnected.h Fri Jul 27 16:14:07 2012 +0000 @@ -22,8 +22,8 @@ #include "stdint.h" #include "Endpoint.h" -#define MAX_ENDPOINT_PER_INTERFACE 4 -#define MAX_INTF 5 +#define MAX_ENDPOINT_PER_INTERFACE 2 +#define MAX_INTF 2 typedef struct { bool in_use;
--- a/USBHost/USBHALHost.h Wed Jul 25 11:13:50 2012 +0000 +++ b/USBHost/USBHALHost.h Fri Jul 27 16:14:07 2012 +0000 @@ -23,7 +23,7 @@ #include "USBHostTypes.h" -#define MAX_ENDPOINT 16 +#define MAX_ENDPOINT 5 #define MAX_TD (MAX_ENDPOINT*2) #define USBHALHOST_SIG_INIT 0x01
--- a/USBHost/USBHost.cpp Wed Jul 25 11:13:50 2012 +0000 +++ b/USBHost/USBHost.cpp Fri Jul 27 16:14:07 2012 +0000 @@ -29,7 +29,7 @@ #include "rtos.h" -#define NB_MAX_INTF 5 +#define NB_MAX_INTF 2 USBHost * USBHost::instHost = NULL; @@ -558,7 +558,7 @@ // enumerate a device with the control endpoint -USB_TYPE USBHost::enumerate(USBDeviceConnected * dev) { +USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) { uint8_t data[256]; uint8_t total_conf_descr_length = 0; USB_TYPE res; @@ -585,7 +585,7 @@ } dev->setSizeControlEndpoint(data[7]); DBG("size control Endpoint: %d", dev->getSizeControlEndpoint()); - + DBG("Now set addr"); // second step: set an address to the device res = controlWrite( dev, @@ -617,6 +617,8 @@ dev->setVid(data[8] | (data[9] << 8)); dev->setPid(data[10] | (data[11] << 8)); DBG("CLASS: %02X \t VID: %04X \t PID: %04X", data[4], data[8] | (data[9] << 8), data[10] | (data[11] << 8)); + + pEnumerator->setVidPid( data[8] | (data[9] << 8), data[10] | (data[11] << 8) ); res = getConfigurationDescriptor(dev, data, &total_conf_descr_length); if (res != USB_TYPE_OK) { @@ -624,7 +626,7 @@ } // Parse the configuration descriptor - parseConfDescr(dev, data, total_conf_descr_length); + parseConfDescr(dev, data, total_conf_descr_length, pEnumerator); // sixth step: set configuration (only 1 supported) @@ -647,13 +649,14 @@ } // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor. -void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len) { +void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) { uint32_t index = 0; uint32_t len_desc = 0; uint8_t id = 0; int nb_endpoints_used = 0; Endpoint * ep = NULL; uint8_t intf_nb = 0; + bool parsing_intf = false; while (index < len) { len_desc = conf_descr[index]; @@ -662,33 +665,44 @@ case CONFIGURATION_DESCRIPTOR: break; case INTERFACE_DESCRIPTOR: - if (intf_nb++ <= NB_MAX_INTF) { - dev->addInterface(intf_nb - 1, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); - nb_endpoints_used = 0; - DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", intf_nb - 1, (void *)dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); - } else { - DBG("Drop intf..."); + if(pEnumerator->parseInterface(intf_nb, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) + { + if (intf_nb++ <= NB_MAX_INTF) { + dev->addInterface(intf_nb - 1, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]); + nb_endpoints_used = 0; + DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", intf_nb - 1, (void *)dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]); + } else { + DBG("Drop intf..."); + } + parsing_intf = true; + } + else + { + parsing_intf = false; } break; case ENDPOINT_DESCRIPTOR: DBG("Ep DESC"); - if (intf_nb <= NB_MAX_INTF) { + if (parsing_intf && (intf_nb <= NB_MAX_INTF) ) { if (nb_endpoints_used < MAX_ENDPOINT_PER_INTERFACE) { - // if the endpoint is isochronous -> skip it (TODO: fix this) - if ((conf_descr[index + 3] & 0x03) != ISOCHRONOUS_ENDPOINT) { - ep = newEndpoint((ENDPOINT_TYPE)(conf_descr[index+3] & 0x03), - (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1), - conf_descr[index + 4] | (conf_descr[index + 5] << 8), - conf_descr[index + 2] & 0x0f); - DBG("ADD ENDPOINT %p, on interf %d on device %p", (void *)ep, intf_nb - 1, (void *)dev); - if (ep != NULL && dev != NULL) { - addEndpoint(dev, intf_nb - 1, ep); + if( pEnumerator->useEndpoint(intf_nb - 1, (ENDPOINT_TYPE)(conf_descr[index + 3] & 0x03), (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1)) ) + { + // if the endpoint is isochronous -> skip it (TODO: fix this) + if ((conf_descr[index + 3] & 0x03) != ISOCHRONOUS_ENDPOINT) { + ep = newEndpoint((ENDPOINT_TYPE)(conf_descr[index+3] & 0x03), + (ENDPOINT_DIRECTION)((conf_descr[index + 2] >> 7) + 1), + conf_descr[index + 4] | (conf_descr[index + 5] << 8), + conf_descr[index + 2] & 0x0f); + DBG("ADD ENDPOINT %p, on interf %d on device %p", (void *)ep, intf_nb - 1, (void *)dev); + if (ep != NULL && dev != NULL) { + addEndpoint(dev, intf_nb - 1, ep); + } else { + DBG("EP NULL"); + } + nb_endpoints_used++; } else { - DBG("EP NULL"); + DBG("ISO ENDPOINT NOT SUPPORTED"); } - nb_endpoints_used++; - } else { - DBG("ISO ENDPOINT NOT SUPPORTED"); } } }
--- a/USBHost/USBHost.h Wed Jul 25 11:13:50 2012 +0000 +++ b/USBHost/USBHost.h Fri Jul 27 16:14:07 2012 +0000 @@ -22,6 +22,7 @@ #include "USBHALHost.h" #include "USBDeviceConnected.h" #include "Endpoint.h" +#include "IUSBEnumerator.h" #define MAX_DEVICE_NB 1 @@ -133,7 +134,7 @@ * * @returns status of the enumeration */ - USB_TYPE enumerate(USBDeviceConnected * dev) ; + USB_TYPE enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator) ; /* * Get a device @@ -228,7 +229,7 @@ uint16_t lenReportDescr; void fillControlBuf(uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, int len) ; - void parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len) ; + void parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator) ; void freeDevice(USBDeviceConnected * dev) ; int findDevice(USBDeviceConnected * dev) ;