Dmitry Pakhomenko / USBHostWANDongle

Dependents:   VodafoneUSBModem

Fork of USBHostWANDongle by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WANDongle.cpp Source File

WANDongle.cpp

00001 /* Copyright (c) 2010-2012 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 #define __DEBUG__ 0
00020 #ifndef __MODULE__
00021 #define __MODULE__ "WANDongle.cpp"
00022 #endif
00023 
00024 #include "core/dbg.h"
00025 #include <cstdint>
00026 #include "rtos.h"
00027 
00028 #include "WANDongle.h"
00029 #include "WANDongleInitializer.h"
00030 
00031 WANDongle::WANDongle() : m_pInitializer(NULL), m_serialCount(0)
00032 {
00033     m_lastDongle = NULL;
00034     host = USBHost::getHostInst();
00035     init();
00036     DBG("WANDongle object instantiated. getHostInst method called on USBHost.");
00037 }
00038 
00039 
00040 bool WANDongle::connected() {
00041   return dev_connected;
00042 }
00043 
00044 bool WANDongle::tryConnect()
00045 {
00046   //FIXME should run on USB thread
00047 
00048   DBG("Trying to connect device");
00049 
00050   if (dev_connected) {
00051       return true;
00052   }
00053   
00054   m_pInitializer = NULL;
00055 
00056   host->lock();
00057 
00058   for (int i = 0; i < MAX_DEVICE_NB; i++)
00059   {
00060       if ((dev = host->getDevice(i)) != NULL)
00061       {
00062           m_pInitializer = NULL; //Will be set in setVidPid callback
00063       
00064           DBG("Found one device reset it");
00065           int ret = host->resetDevice(dev);
00066           if(ret)
00067           {
00068             host->unlock();
00069             return false;
00070           }
00071 
00072           DBG("Enumerate");
00073           ret = host->enumerate(dev, this);
00074           
00075           if(ret)
00076           {
00077             host->unlock();
00078             return false;
00079           }
00080           
00081           DBG("Device has VID:%04x PID:%04x", dev->getVid(), dev->getPid());
00082                    
00083           if(m_pInitializer) //If an initializer has been found
00084           {
00085             DBG("m_pInitializer=%p", m_pInitializer);
00086             DBG("m_pInitializer->getSerialVid()=%04x", m_pInitializer->getSerialVid());
00087             DBG("m_pInitializer->getSerialPid()=%04x", m_pInitializer->getSerialPid());
00088             if ((dev->getVid() == m_pInitializer->getSerialVid()) && (dev->getPid() == m_pInitializer->getSerialPid()))
00089             {
00090               DBG("The dongle is in virtual serial mode");
00091               host->registerDriver(dev, 0, this, &WANDongle::init);
00092               m_serialCount = m_pInitializer->getSerialPortCount();
00093               DBG("Num serial ports: %d",m_serialCount);
00094               if( m_serialCount > WANDONGLE_MAX_SERIAL_PORTS )
00095               {
00096                 DBG("setting serial count %d to %d",m_serialCount,WANDONGLE_MAX_SERIAL_PORTS);
00097                 m_serialCount = WANDONGLE_MAX_SERIAL_PORTS;
00098               }
00099               for(int j = 0; j < m_serialCount; j++)
00100               {
00101                 DBG("Connecting serial port #%d", j+1);
00102                 DBG("Ep %p", m_pInitializer->getEp(dev, j, false));
00103                 DBG("Ep %p", m_pInitializer->getEp(dev, j, true));
00104                 m_serial[j].connect( dev, m_pInitializer->getEp(dev, j, false), m_pInitializer->getEp(dev, j, true) );
00105               }
00106               
00107               DBG("Device connected");
00108               
00109               dev_connected = true;
00110               host->unlock();
00111               
00112               return true;
00113             }
00114             else if ((dev->getVid() == m_pInitializer->getMSDVid()) && (dev->getPid() == m_pInitializer->getMSDPid()))
00115             {
00116               DBG("Vodafone dongle detected in MSD mode");
00117               //Try to switch   
00118               if( m_pInitializer->switchMode(dev) )
00119               {
00120                 DBG("Switched OK");
00121                 host->unlock();
00122                 return false; //Will be connected on a next iteration
00123               }
00124               else
00125               {
00126                 ERR("Could not switch mode");
00127                 host->unlock();
00128                 return false;
00129               }
00130             }
00131           } //if()
00132       } //if()
00133       /*else
00134       {
00135         // Looks like the getDevice method failed and returned a null pointer. Maybe there has been a power cut, modem pulled or something to stop the modem.
00136         // Lets run the initilise routine again. Next time round the loop we might have a handle to an end point!
00137         DBG("Trying to initialise the USB stack since the getDevice method has returned a null pointer");
00138         init();
00139       }*/
00140   } //for()
00141   host->unlock();
00142   return false;
00143 }
00144 
00145 bool WANDongle::disconnect()
00146 {
00147   dev_connected = false;
00148   for(int i = 0; i < WANDONGLE_MAX_SERIAL_PORTS; i++)
00149   {
00150     m_serial[i].disconnect();
00151   }
00152   return true;
00153 }
00154 
00155 WAN_DONGLE_TYPE WANDongle::getDongleType()
00156 {
00157   if( m_pInitializer != NULL )
00158   {
00159     return m_pInitializer->getType();
00160   }
00161   else
00162   {
00163     return WAN_DONGLE_TYPE_UNKNOWN;
00164   }
00165 }
00166 
00167 IUSBHostSerial& WANDongle::getSerial(int index)
00168 {
00169   return m_serial[index];
00170 }
00171 
00172 int WANDongle::getSerialCount()
00173 {
00174   return m_serialCount;
00175 }
00176 
00177 //Private methods
00178 void WANDongle::init()
00179 {
00180   m_pInitializer = NULL;
00181   dev_connected = false;
00182   for(int i = 0; i < WANDONGLE_MAX_SERIAL_PORTS; i++)
00183   {
00184     m_serial[i].init(host);
00185   }
00186 }
00187 
00188 
00189 /*virtual*/ void WANDongle::setVidPid(uint16_t vid, uint16_t pid)
00190 {
00191     //Load right initializer
00192   WANDongleInitializer** initializer = WANDongleInitializer::getInitializers(host);
00193   
00194   while(*initializer)
00195   {
00196     if (m_lastDongle)
00197     {
00198         DBG("Initializer has been already detected in previous step");
00199         m_pInitializer = m_lastDongle;    
00200         break;
00201     }
00202     
00203     
00204     DBG("*initializer=%p", *initializer);
00205     DBG("(*initializer)->getSerialVid()=%04x", (*initializer)->getSerialVid());
00206     DBG("(*initializer)->getSerialPid()=%04x", (*initializer)->getSerialPid());
00207     if ((dev->getVid() == (*initializer)->getSerialVid()) && (dev->getPid() == (*initializer)->getSerialPid()))
00208     {
00209       DBG("The dongle is in virtual serial mode");
00210       m_pInitializer = *initializer;
00211       break;
00212     }
00213     else if ((dev->getVid() == (*initializer)->getMSDVid()) && (dev->getPid() == (*initializer)->getMSDPid()))
00214     {
00215       DBG("Vodafone K3370 dongle detected in MSD mode");
00216       m_pInitializer = *initializer;
00217       
00218       //Store successfully detected modem type so that after switch to serial mode 
00219       //we can distinuguish modems with same Vid-Pid pairs
00220       m_lastDongle = *initializer;
00221       
00222       break;
00223     }
00224     initializer++;
00225   } //while()
00226   if(m_pInitializer)
00227   {
00228     m_pInitializer->setVidPid(vid, pid);
00229   }
00230 }
00231 
00232 /*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
00233 {
00234   if(m_pInitializer)
00235   {
00236     return m_pInitializer->parseInterface(intf_nb, intf_class, intf_subclass, intf_protocol);
00237   }
00238   else
00239   {
00240     return false;
00241   }
00242 }
00243 
00244 /*virtual*/ bool WANDongle::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
00245 {
00246   if(m_pInitializer)
00247   {
00248     return m_pInitializer->useEndpoint(intf_nb, type, dir);
00249   }
00250   else
00251   {
00252     return false;
00253   }
00254 }