NetServices Stack source

Dependents:   HelloWorld ServoInterfaceBoardExample1 4180_Lab4

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UMTSStick.cpp Source File

UMTSStick.cpp

00001 
00002 /*
00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00004  
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011  
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014  
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00021 THE SOFTWARE.
00022 */
00023 
00024 #include "netCfg.h"
00025 #if NET_UMTS
00026 
00027 #include "UMTSStick.h"
00028 
00029 #define __DEBUG
00030 #include "dbg/dbg.h"
00031 
00032 UMTSStick::UMTSStick() : m_host(), m_pDev(NULL)
00033 {
00034 
00035 }
00036 
00037 UMTSStick::~UMTSStick()
00038 {
00039 
00040 }
00041 
00042 
00043 UMTSStickErr UMTSStick::getSerial(UsbSerial** ppUsbSerial)
00044 {
00045   m_host.init();
00046   
00047   UMTSStickErr rc;
00048   
00049   rc = waitForDevice();
00050   if(rc)
00051     return rc;
00052    
00053   //Device is now enumerated, read table
00054   
00055   uint16_t vid = m_pDev->getVid();
00056   uint16_t pid = m_pDev->getPid();
00057   
00058   DBG("Configuration set: vid:%04x pid:%04x\n", vid, pid);
00059     
00060   bool handled = false;
00061   bool cdfs = false;
00062   const UMTSSwitchingInfo* pInfo;
00063   for(int i = 0; i < UMTS_SWITCHING_COUNT; i++)
00064   {
00065     pInfo = &UMTSwitchingTable[i];
00066     if( !checkDeviceState(pInfo, &cdfs) )
00067     {
00068       handled = true;
00069       break;
00070     }
00071     
00072   } //for(int i = 0; i < UMTS_SWITCHING_COUNT; i++)
00073   
00074   if(!handled)
00075   {
00076     DBG("Don't know this device!\n");
00077     return UMTSERR_NOTIMPLEMENTED;
00078   }
00079   
00080   //Check if the device is in CDFS mode, in this case switch
00081   if(cdfs)
00082   {
00083     DBG("Switching the device by sending a magic packet\n");
00084   
00085     rc = switchMode(pInfo);
00086     if(rc)
00087       return rc;
00088       
00089     DBG("Now wait for device to reconnect\n");
00090     
00091     m_host.releaseDevice(m_pDev);
00092       
00093     //Wait for device to reconnect
00094     wait(3);
00095     rc = waitForDevice();
00096     if(rc)
00097       return rc;
00098   }
00099   
00100   rc = findSerial(ppUsbSerial);
00101   if(rc)
00102     return rc;
00103   
00104   return UMTSERR_OK;
00105 }
00106 
00107 UMTSStickErr UMTSStick::waitForDevice()
00108 {
00109   bool ready = false;
00110   while(!ready)
00111   {
00112     while(!m_host.devicesCount())
00113     {}
00114     wait(1);
00115     if(m_host.devicesCount())
00116       ready = true;
00117   }
00118   
00119   wait(2); //Wait for device to be initialized
00120   
00121   if(!m_host.devicesCount())
00122     return UMTSERR_DISCONNECTED;
00123   
00124   m_pDev = m_host.getDevice(0);
00125   
00126   while(!m_pDev->enumerated())
00127   {
00128     m_host.poll();
00129     if(!m_host.devicesCount())
00130       return UMTSERR_DISCONNECTED;
00131   }
00132    
00133   return UMTSERR_OK;
00134 }
00135 
00136 UMTSStickErr UMTSStick::checkDeviceState(const UMTSSwitchingInfo* pInfo, bool* pCdfs)
00137 {
00138   uint16_t vid = m_pDev->getVid();
00139   uint16_t pid = m_pDev->getPid();
00140   bool handled = false;
00141   if( (vid == pInfo->cdfsVid) && (pid == pInfo->cdfsPid) )
00142   {
00143     DBG("Match on dongles list\n");
00144     if( !pInfo->targetClass ) //No specific interface to check, vid/pid couple is specific to CDFS mode
00145     {
00146       DBG("Found device in CDFS mode\n");
00147       handled = true;
00148       *pCdfs = true;
00149     }
00150     else //if( !pInfo->targetClass )
00151     {
00152       //Has to check if there is an interface of class targetClass
00153       byte* desc = NULL;
00154       int c = 0;
00155              
00156       while( !m_pDev->getInterfaceDescriptor(1, c++, &desc) )
00157       {
00158         if( desc[5] == pInfo->targetClass )
00159         {
00160           DBG("Found device in Serial mode\n");
00161           handled = true;
00162           *pCdfs = false;
00163           break;
00164         }
00165       }        
00166       
00167       if(!handled)
00168       {
00169         //All interfaces were tried, so we are in CDFS mode
00170         DBG("Found device in CDFS mode\n");
00171         handled = true;
00172         *pCdfs = true;
00173       }
00174     } //if( !pInfo->targetClass )
00175   } //if( (vid == pInfo->cdfsVid) && (pid == pInfo->cdfsPid) )
00176   else
00177   {
00178     //Try every vid/pid couple of the serial list
00179     for( int i = 0; i < 16 ; i++)
00180     {
00181       if(!pInfo->serialPidList[i])
00182         break;
00183       if( (pInfo->serialVid == vid) && (pInfo->serialPidList[i] == pid) )
00184       {
00185         DBG("Found device in Serial mode\n");
00186         handled = true;
00187         *pCdfs = false;
00188         break;
00189       }
00190     }
00191   } //if( (vid == pInfo->cdfsVid) && (pid == pInfo->cdfsPid) )
00192   
00193   if(!handled)
00194     return UMTSERR_NOTFOUND;
00195     
00196   return UMTSERR_OK;
00197 }
00198 
00199 UMTSStickErr UMTSStick::switchMode(const UMTSSwitchingInfo* pInfo)
00200 {
00201   if(!pInfo->huaweiPacket) //Send SCSI packet on first bulk ep
00202   {
00203     //Find first bulk ep           
00204     byte* desc = NULL;
00205     int c = 0;
00206     
00207     UsbEndpoint *pEpOut = NULL;
00208        
00209     while( !m_pDev->getInterfaceDescriptor(1, c++, &desc) )
00210     {
00211       byte* p = desc;
00212       int epNum = 0;
00213       p = p + p[0]; //Move to next descriptor (which should be an ep descriptor)
00214       while (epNum < desc[4]) //Eps count in this if
00215       {
00216         if (p[1] != USB_DESCRIPTOR_TYPE_ENDPOINT)
00217           break;
00218         
00219         if( (p[3] == 0x02) && !(p[2] & 0x80) ) //Bulk endpoint, out
00220         {
00221           DBG("Found bulk ep %02x\n", p[2]);
00222           pEpOut = new UsbEndpoint( m_pDev, p[2], false, USB_BULK, *((uint16_t*)&p[4]) );
00223           break;
00224         }
00225         
00226         p = p + p[0]; //Move to next ep desc
00227         epNum++;
00228       }
00229       if(pEpOut)
00230         break;
00231     }        
00232     
00233     if(!pEpOut)
00234       return UMTSERR_NOTFOUND;
00235       
00236     //Send SCSI packet
00237     
00238     DBG("Sending SCSI Packet to switch\n");
00239     byte ramCdfsBuf[31];
00240     memcpy(ramCdfsBuf, pInfo->cdfsPacket, 31);
00241     pEpOut->transfer((volatile byte*)ramCdfsBuf, 31);
00242     while(pEpOut->status() == USBERR_PROCESSING);
00243     int ret = pEpOut->status();
00244     if((ret < 0) && (ret !=USBERR_DISCONNECTED)) //Packet was not transfered
00245     {
00246       DBG("Usb error %d\n", ret);
00247       delete pEpOut;
00248       return UMTSERR_USBERR;
00249     }
00250     
00251     delete pEpOut;
00252   }  
00253   else
00254   {
00255     UsbErr usbErr;
00256     //Send the Huawei-specific control packet
00257     usbErr = m_pDev->controlSend(0, 0x03, 1, 0, NULL, 0);
00258     if(usbErr && (usbErr != USBERR_DISCONNECTED))
00259       return UMTSERR_USBERR;  
00260   }
00261   
00262   DBG("The stick should be switching in serial mode now\n");
00263   
00264   return UMTSERR_OK;
00265 }
00266 
00267 UMTSStickErr UMTSStick::findSerial(UsbSerial** ppUsbSerial)
00268 {
00269   byte* desc = NULL;
00270   int c = 0;
00271 
00272   int epOut = 0;
00273   int epIn = 0;
00274       
00275   while( !m_pDev->getInterfaceDescriptor(1, c++, &desc) )
00276   {
00277     byte* p = desc;
00278     int epNum = 0;
00279     
00280     DBG("Interface of type %02x\n", desc[5]);
00281     
00282     if(desc[5] != 0xFF) //Not a serial-like if
00283       continue;
00284     
00285     p = p + p[0]; //Move to next descriptor (which should be an ep descriptor)
00286     while (epNum < desc[4]) //Eps count in this if
00287     {
00288       if (p[1] == USB_DESCRIPTOR_TYPE_ENDPOINT)
00289       {
00290         if( (p[3] == 0x02) && !(p[2] & 0x80) && !epOut ) //Bulk endpoint, out
00291         {
00292           DBG("Found bulk out ep %02x of payload size %04x\n", p[2], *((uint16_t*)&p[4]));
00293           epOut = p[2] & 0x7F;
00294         }
00295       
00296         if( (p[3] == 0x02) && (p[2] & 0x80) && !epIn ) //Bulk endpoint, in
00297         {
00298           DBG("Found bulk in ep %02x of payload size %04x\n", p[2], *((uint16_t*)&p[4]));
00299           epIn = p[2] & 0x7F;
00300         }
00301        
00302         if(epOut && epIn)
00303           break;
00304       }
00305       
00306       p = p + p[0]; //Move to next ep desc
00307       epNum++;
00308     }
00309     
00310     if(epOut && epIn)
00311       break;
00312   }
00313   
00314   if(!epOut || !epIn)
00315     return UMTSERR_NOTFOUND;
00316     
00317   DBG("Endpoints found, create serial object\n");
00318     
00319   *ppUsbSerial = new UsbSerial(m_pDev, epIn, epOut);
00320   
00321   DBG("UsbSerial object created\n");
00322     
00323   return UMTSERR_OK;
00324 }
00325 
00326 #endif