Changes to support Vodafone K4606

Dependents:   VodafoneUSBModem

Fork of USBHostWANDongle by mbed official

Files at this revision

API Documentation at this revision

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

USB3GModule/WANDongle.cpp Show annotated file Show diff for this revision Revisions of this file
USB3GModule/WANDongle.h Show annotated file Show diff for this revision Revisions of this file
USB3GModule/WANDongleInitializer.cpp Show annotated file Show diff for this revision Revisions of this file
USB3GModule/WANDongleInitializer.h Show annotated file Show diff for this revision Revisions of this file
--- 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