Changes to support Vodafone K4606
Fork of USBHostWANDongle by
Revision 28:34cdecfff9f4, committed 2015-01-28
- Comitter:
- dmitryp
- Date:
- Wed Jan 28 11:38:44 2015 +0000
- Parent:
- 27:980fe31c14f7
- Commit message:
- Added support for Vodafone K4606, for more details refer to ; http://atmega.magictale.com/2215/hacking-vodafone-k4606-3g-hsdpa-usb-modem/
Changed in this revision
--- a/USB3GModule/WANDongle.cpp Fri Sep 20 10:40:15 2013 +0000 +++ b/USB3GModule/WANDongle.cpp Wed Jan 28 11:38:44 2015 +0000 @@ -30,6 +30,7 @@ WANDongle::WANDongle() : m_pInitializer(NULL), m_serialCount(0) { + m_lastDongle = NULL; host = USBHost::getHostInst(); init(); DBG("WANDongle object instantiated. getHostInst method called on USBHost."); @@ -112,7 +113,7 @@ } else if ((dev->getVid() == m_pInitializer->getMSDVid()) && (dev->getPid() == m_pInitializer->getMSDPid())) { - DBG("Vodafone K3370 dongle detected in MSD mode"); + DBG("Vodafone dongle detected in MSD mode"); //Try to switch if( m_pInitializer->switchMode(dev) ) { @@ -192,6 +193,14 @@ while(*initializer) { + if (m_lastDongle) + { + DBG("Initializer has been already detected in previous step"); + m_pInitializer = m_lastDongle; + break; + } + + DBG("*initializer=%p", *initializer); DBG("(*initializer)->getSerialVid()=%04x", (*initializer)->getSerialVid()); DBG("(*initializer)->getSerialPid()=%04x", (*initializer)->getSerialPid()); @@ -205,6 +214,11 @@ { DBG("Vodafone K3370 dongle detected in MSD mode"); m_pInitializer = *initializer; + + //Store successfully detected modem type so that after switch to serial mode + //we can distinuguish modems with same Vid-Pid pairs + m_lastDongle = *initializer; + break; } initializer++;
--- a/USB3GModule/WANDongle.h Fri Sep 20 10:40:15 2013 +0000 +++ b/USB3GModule/WANDongle.h Wed Jan 28 11:38:44 2015 +0000 @@ -92,6 +92,7 @@ WANDongleSerialPort m_serial[WANDONGLE_MAX_SERIAL_PORTS]; int m_serialCount; + WANDongleInitializer* m_lastDongle; }; #endif
--- a/USB3GModule/WANDongleInitializer.cpp Fri Sep 20 10:40:15 2013 +0000 +++ b/USB3GModule/WANDongleInitializer.cpp Wed Jan 28 11:38:44 2015 +0000 @@ -28,9 +28,9 @@ #include "WANDongleInitializer.h" + WANDongleInitializer::WANDongleInitializer(USBHost* pHost) : m_pHost(pHost) { - } WANDongleInitializer** WANDongleInitializer::getInitializers(USBHost* pHost) @@ -41,6 +41,8 @@ static VodafoneK3773Initializer vodafoneK3773(pHost); static HuaweiMU509Initializer huaweiMU509(pHost); static UbloxLISAU200Initializer ubloxLISAU200(pHost); + static VodafoneK4606Initializer vodafoneK4606(pHost); + const static WANDongleInitializer* list[] = { &vodafoneK3770, &vodafoneK3772Z, @@ -48,6 +50,7 @@ &vodafoneK3773, &huaweiMU509, &ubloxLISAU200, + &vodafoneK4606, NULL }; return (WANDongleInitializer**)list; @@ -681,4 +684,118 @@ /*virtual*/ WAN_DONGLE_TYPE UbloxLISAU200Initializer::getType() { return WAN_DONGLE_TYPE_UBLOX_LISAU200; -} \ No newline at end of file +} + + +//----------------------------------------------------------------------- +// Huawei K4606 (Vodafone) +//----------------------------------------------------------------------- +// Switching from mass storage device string is: "55 53 42 43 12 34 56 78 00 00 00 00 00 00 00 11 06 20 00 00 01 00 00 00 00 00 00 00 00 00 00" +static uint8_t vodafone_k4606_switch_packet[] = { + 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0, 0, 0, 0, 0x11, 0x06, 0x00, 0, 0, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +VodafoneK4606Initializer::VodafoneK4606Initializer(USBHost* pHost) : WANDongleInitializer(pHost) +{ +} + +uint16_t VodafoneK4606Initializer::getMSDVid() { return 0x12D1; } +uint16_t VodafoneK4606Initializer::getMSDPid() { return 0x1F19; } + +uint16_t VodafoneK4606Initializer::getSerialVid() { return 0x12D1; } +uint16_t VodafoneK4606Initializer::getSerialPid() { return 0x1001;} + +bool VodafoneK4606Initializer::switchMode(USBDeviceConnected* pDev) +{ + for (int i = 0; i < pDev->getNbInterface(); i++) + { + if (pDev->getInterface(i)->intf_class == MSD_CLASS) + { + USBEndpoint* pEp = pDev->getEndpoint(i, BULK_ENDPOINT, OUT); + if ( pEp != NULL ) + { + DBG("Vodafone K4606 MSD descriptor found on device %p, intf %d, will now try to switch into serial mode", (void *)pDev, i); + m_pHost->bulkWrite(pDev, pEp, vodafone_k4606_switch_packet, 31); + return true; + } + } + } + return false; +} + +USBEndpoint* VodafoneK4606Initializer::getEp(USBDeviceConnected* pDev, int serialPortNumber, bool tx) +{ + return pDev->getEndpoint(serialPortNumber, BULK_ENDPOINT, tx?OUT:IN, 0); +} + +int VodafoneK4606Initializer::getSerialPortCount() +{ + return 2; +} + +void VodafoneK4606Initializer::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; + } +} + +bool VodafoneK4606Initializer::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 ) + { + DBG("*K4606 parsing intf %d, intf_class %d, m_currentSerialIntf %d", intf_nb, intf_class, m_currentSerialIntf); + + if( intf_class == 0x2 ) + { + if( (m_currentSerialIntf == 0) || (m_currentSerialIntf == 2) ) + { + m_currentSerialIntf++; + return true; + } + m_currentSerialIntf++; + } + } + else + { + if( (intf_nb == 0) && (intf_class == MSD_CLASS) ) + { + return true; + } + } + return false; +} + +bool VodafoneK4606Initializer::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; +} + + WAN_DONGLE_TYPE VodafoneK4606Initializer::getType() +{ + return WAN_DONGLE_TYPE_VODAFONE_K4606; +}
--- a/USB3GModule/WANDongleInitializer.h Fri Sep 20 10:40:15 2013 +0000 +++ b/USB3GModule/WANDongleInitializer.h Wed Jan 28 11:38:44 2015 +0000 @@ -34,7 +34,8 @@ WAN_DONGLE_TYPE_VODAFONE_K3772 = 2, WAN_DONGLE_TYPE_VODAFONE_K3773 = 3, WAN_DONGLE_TYPE_HUAWEI_MU509 = 4, - WAN_DONGLE_TYPE_UBLOX_LISAU200 = 5 + WAN_DONGLE_TYPE_UBLOX_LISAU200 = 5, + WAN_DONGLE_TYPE_VODAFONE_K4606 = 6 }; class WANDongleInitializer : public IUSBEnumerator @@ -262,5 +263,39 @@ int m_endpointsToFetch; }; + +class VodafoneK4606Initializer : public WANDongleInitializer +{ +public: + VodafoneK4606Initializer(USBHost* pHost); + + virtual uint16_t getMSDVid(); + virtual uint16_t getMSDPid(); + + virtual uint16_t getSerialVid(); + virtual uint16_t getSerialPid(); + + virtual bool switchMode(USBDeviceConnected* pDev); + + virtual USBEndpoint* 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 + + virtual WAN_DONGLE_TYPE getType(); + +private: + + bool m_hasSwitched; + int m_currentSerialIntf; + int m_endpointsToFetch; +}; + + #endif