Dependents:   TimeZoneDemo EthernetJackTestCode MMEx_Challenge ntp_mem ... more

Committer:
segundo
Date:
Wed Dec 15 18:01:30 2010 +0000
Revision:
7:4e2468d7d5cb
Parent:
0:ac1725ba162c

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
segundo 0:ac1725ba162c 1
segundo 0:ac1725ba162c 2 /*
segundo 0:ac1725ba162c 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
segundo 0:ac1725ba162c 4
segundo 0:ac1725ba162c 5 Permission is hereby granted, free of charge, to any person obtaining a copy
segundo 0:ac1725ba162c 6 of this software and associated documentation files (the "Software"), to deal
segundo 0:ac1725ba162c 7 in the Software without restriction, including without limitation the rights
segundo 0:ac1725ba162c 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
segundo 0:ac1725ba162c 9 copies of the Software, and to permit persons to whom the Software is
segundo 0:ac1725ba162c 10 furnished to do so, subject to the following conditions:
segundo 0:ac1725ba162c 11
segundo 0:ac1725ba162c 12 The above copyright notice and this permission notice shall be included in
segundo 0:ac1725ba162c 13 all copies or substantial portions of the Software.
segundo 0:ac1725ba162c 14
segundo 0:ac1725ba162c 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
segundo 0:ac1725ba162c 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
segundo 0:ac1725ba162c 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
segundo 0:ac1725ba162c 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
segundo 0:ac1725ba162c 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
segundo 0:ac1725ba162c 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
segundo 0:ac1725ba162c 21 THE SOFTWARE.
segundo 0:ac1725ba162c 22 */
segundo 0:ac1725ba162c 23
segundo 0:ac1725ba162c 24 #include "netCfg.h"
segundo 0:ac1725ba162c 25 #if NET_UMTS
segundo 0:ac1725ba162c 26
segundo 0:ac1725ba162c 27 #include "UMTSStick.h"
segundo 0:ac1725ba162c 28
segundo 0:ac1725ba162c 29 #define __DEBUG
segundo 0:ac1725ba162c 30 #include "dbg/dbg.h"
segundo 0:ac1725ba162c 31
segundo 0:ac1725ba162c 32 UMTSStick::UMTSStick() : m_host(), m_pDev(NULL)
segundo 0:ac1725ba162c 33 {
segundo 0:ac1725ba162c 34
segundo 0:ac1725ba162c 35 }
segundo 0:ac1725ba162c 36
segundo 0:ac1725ba162c 37 UMTSStick::~UMTSStick()
segundo 0:ac1725ba162c 38 {
segundo 0:ac1725ba162c 39
segundo 0:ac1725ba162c 40 }
segundo 0:ac1725ba162c 41
segundo 0:ac1725ba162c 42
segundo 0:ac1725ba162c 43 UMTSStickErr UMTSStick::getSerial(UsbSerial** ppUsbSerial)
segundo 0:ac1725ba162c 44 {
segundo 0:ac1725ba162c 45 m_host.init();
segundo 0:ac1725ba162c 46
segundo 0:ac1725ba162c 47 UMTSStickErr rc;
segundo 0:ac1725ba162c 48
segundo 0:ac1725ba162c 49 rc = waitForDevice();
segundo 0:ac1725ba162c 50 if(rc)
segundo 0:ac1725ba162c 51 return rc;
segundo 0:ac1725ba162c 52
segundo 0:ac1725ba162c 53 //Device is now enumerated, read table
segundo 0:ac1725ba162c 54
segundo 0:ac1725ba162c 55 uint16_t vid = m_pDev->getVid();
segundo 0:ac1725ba162c 56 uint16_t pid = m_pDev->getPid();
segundo 0:ac1725ba162c 57
segundo 0:ac1725ba162c 58 DBG("Configuration set: vid:%04x pid:%04x\n", vid, pid);
segundo 0:ac1725ba162c 59
segundo 0:ac1725ba162c 60 bool handled = false;
segundo 0:ac1725ba162c 61 bool cdfs = false;
segundo 0:ac1725ba162c 62 const UMTSSwitchingInfo* pInfo;
segundo 0:ac1725ba162c 63 for(int i = 0; i < UMTS_SWITCHING_COUNT; i++)
segundo 0:ac1725ba162c 64 {
segundo 0:ac1725ba162c 65 pInfo = &UMTSwitchingTable[i];
segundo 0:ac1725ba162c 66 if( !checkDeviceState(pInfo, &cdfs) )
segundo 0:ac1725ba162c 67 {
segundo 0:ac1725ba162c 68 handled = true;
segundo 0:ac1725ba162c 69 break;
segundo 0:ac1725ba162c 70 }
segundo 0:ac1725ba162c 71
segundo 0:ac1725ba162c 72 } //for(int i = 0; i < UMTS_SWITCHING_COUNT; i++)
segundo 0:ac1725ba162c 73
segundo 0:ac1725ba162c 74 if(!handled)
segundo 0:ac1725ba162c 75 {
segundo 0:ac1725ba162c 76 DBG("Don't know this device!\n");
segundo 0:ac1725ba162c 77 return UMTSERR_NOTIMPLEMENTED;
segundo 0:ac1725ba162c 78 }
segundo 0:ac1725ba162c 79
segundo 0:ac1725ba162c 80 //Check if the device is in CDFS mode, in this case switch
segundo 0:ac1725ba162c 81 if(cdfs)
segundo 0:ac1725ba162c 82 {
segundo 0:ac1725ba162c 83 DBG("Switching the device by sending a magic packet\n");
segundo 0:ac1725ba162c 84
segundo 0:ac1725ba162c 85 rc = switchMode(pInfo);
segundo 0:ac1725ba162c 86 if(rc)
segundo 0:ac1725ba162c 87 return rc;
segundo 0:ac1725ba162c 88
segundo 0:ac1725ba162c 89 DBG("Now wait for device to reconnect\n");
segundo 0:ac1725ba162c 90
segundo 0:ac1725ba162c 91 m_host.releaseDevice(m_pDev);
segundo 0:ac1725ba162c 92
segundo 0:ac1725ba162c 93 //Wait for device to reconnect
segundo 0:ac1725ba162c 94 wait(3);
segundo 0:ac1725ba162c 95 rc = waitForDevice();
segundo 0:ac1725ba162c 96 if(rc)
segundo 0:ac1725ba162c 97 return rc;
segundo 0:ac1725ba162c 98 }
segundo 0:ac1725ba162c 99
segundo 0:ac1725ba162c 100 rc = findSerial(ppUsbSerial);
segundo 0:ac1725ba162c 101 if(rc)
segundo 0:ac1725ba162c 102 return rc;
segundo 0:ac1725ba162c 103
segundo 0:ac1725ba162c 104 return UMTSERR_OK;
segundo 0:ac1725ba162c 105 }
segundo 0:ac1725ba162c 106
segundo 0:ac1725ba162c 107 UMTSStickErr UMTSStick::waitForDevice()
segundo 0:ac1725ba162c 108 {
segundo 0:ac1725ba162c 109 bool ready = false;
segundo 0:ac1725ba162c 110 while(!ready)
segundo 0:ac1725ba162c 111 {
segundo 0:ac1725ba162c 112 while(!m_host.devicesCount())
segundo 0:ac1725ba162c 113 {}
segundo 0:ac1725ba162c 114 wait(1);
segundo 0:ac1725ba162c 115 if(m_host.devicesCount())
segundo 0:ac1725ba162c 116 ready = true;
segundo 0:ac1725ba162c 117 }
segundo 0:ac1725ba162c 118
segundo 0:ac1725ba162c 119 wait(2); //Wait for device to be initialized
segundo 0:ac1725ba162c 120
segundo 0:ac1725ba162c 121 if(!m_host.devicesCount())
segundo 0:ac1725ba162c 122 return UMTSERR_DISCONNECTED;
segundo 0:ac1725ba162c 123
segundo 0:ac1725ba162c 124 m_pDev = m_host.getDevice(0);
segundo 0:ac1725ba162c 125
segundo 0:ac1725ba162c 126 while(!m_pDev->enumerated())
segundo 0:ac1725ba162c 127 {
segundo 0:ac1725ba162c 128 m_host.poll();
segundo 0:ac1725ba162c 129 if(!m_host.devicesCount())
segundo 0:ac1725ba162c 130 return UMTSERR_DISCONNECTED;
segundo 0:ac1725ba162c 131 }
segundo 0:ac1725ba162c 132
segundo 0:ac1725ba162c 133 return UMTSERR_OK;
segundo 0:ac1725ba162c 134 }
segundo 0:ac1725ba162c 135
segundo 0:ac1725ba162c 136 UMTSStickErr UMTSStick::checkDeviceState(const UMTSSwitchingInfo* pInfo, bool* pCdfs)
segundo 0:ac1725ba162c 137 {
segundo 0:ac1725ba162c 138 uint16_t vid = m_pDev->getVid();
segundo 0:ac1725ba162c 139 uint16_t pid = m_pDev->getPid();
segundo 0:ac1725ba162c 140 bool handled = false;
segundo 0:ac1725ba162c 141 if( (vid == pInfo->cdfsVid) && (pid == pInfo->cdfsPid) )
segundo 0:ac1725ba162c 142 {
segundo 0:ac1725ba162c 143 DBG("Match on dongles list\n");
segundo 0:ac1725ba162c 144 if( !pInfo->targetClass ) //No specific interface to check, vid/pid couple is specific to CDFS mode
segundo 0:ac1725ba162c 145 {
segundo 0:ac1725ba162c 146 DBG("Found device in CDFS mode\n");
segundo 0:ac1725ba162c 147 handled = true;
segundo 0:ac1725ba162c 148 *pCdfs = true;
segundo 0:ac1725ba162c 149 }
segundo 0:ac1725ba162c 150 else //if( !pInfo->targetClass )
segundo 0:ac1725ba162c 151 {
segundo 0:ac1725ba162c 152 //Has to check if there is an interface of class targetClass
segundo 0:ac1725ba162c 153 byte* desc = NULL;
segundo 0:ac1725ba162c 154 int c = 0;
segundo 0:ac1725ba162c 155
segundo 0:ac1725ba162c 156 while( !m_pDev->getInterfaceDescriptor(1, c++, &desc) )
segundo 0:ac1725ba162c 157 {
segundo 0:ac1725ba162c 158 if( desc[5] == pInfo->targetClass )
segundo 0:ac1725ba162c 159 {
segundo 0:ac1725ba162c 160 DBG("Found device in Serial mode\n");
segundo 0:ac1725ba162c 161 handled = true;
segundo 0:ac1725ba162c 162 *pCdfs = false;
segundo 0:ac1725ba162c 163 break;
segundo 0:ac1725ba162c 164 }
segundo 0:ac1725ba162c 165 }
segundo 0:ac1725ba162c 166
segundo 0:ac1725ba162c 167 if(!handled)
segundo 0:ac1725ba162c 168 {
segundo 0:ac1725ba162c 169 //All interfaces were tried, so we are in CDFS mode
segundo 0:ac1725ba162c 170 DBG("Found device in CDFS mode\n");
segundo 0:ac1725ba162c 171 handled = true;
segundo 0:ac1725ba162c 172 *pCdfs = true;
segundo 0:ac1725ba162c 173 }
segundo 0:ac1725ba162c 174 } //if( !pInfo->targetClass )
segundo 0:ac1725ba162c 175 } //if( (vid == pInfo->cdfsVid) && (pid == pInfo->cdfsPid) )
segundo 0:ac1725ba162c 176 else
segundo 0:ac1725ba162c 177 {
segundo 0:ac1725ba162c 178 //Try every vid/pid couple of the serial list
segundo 0:ac1725ba162c 179 for( int i = 0; i < 16 ; i++)
segundo 0:ac1725ba162c 180 {
segundo 0:ac1725ba162c 181 if(!pInfo->serialPidList[i])
segundo 0:ac1725ba162c 182 break;
segundo 0:ac1725ba162c 183 if( (pInfo->serialVid == vid) && (pInfo->serialPidList[i] == pid) )
segundo 0:ac1725ba162c 184 {
segundo 0:ac1725ba162c 185 DBG("Found device in Serial mode\n");
segundo 0:ac1725ba162c 186 handled = true;
segundo 0:ac1725ba162c 187 *pCdfs = false;
segundo 0:ac1725ba162c 188 break;
segundo 0:ac1725ba162c 189 }
segundo 0:ac1725ba162c 190 }
segundo 0:ac1725ba162c 191 } //if( (vid == pInfo->cdfsVid) && (pid == pInfo->cdfsPid) )
segundo 0:ac1725ba162c 192
segundo 0:ac1725ba162c 193 if(!handled)
segundo 0:ac1725ba162c 194 return UMTSERR_NOTFOUND;
segundo 0:ac1725ba162c 195
segundo 0:ac1725ba162c 196 return UMTSERR_OK;
segundo 0:ac1725ba162c 197 }
segundo 0:ac1725ba162c 198
segundo 0:ac1725ba162c 199 UMTSStickErr UMTSStick::switchMode(const UMTSSwitchingInfo* pInfo)
segundo 0:ac1725ba162c 200 {
segundo 0:ac1725ba162c 201 if(!pInfo->huaweiPacket) //Send SCSI packet on first bulk ep
segundo 0:ac1725ba162c 202 {
segundo 0:ac1725ba162c 203 //Find first bulk ep
segundo 0:ac1725ba162c 204 byte* desc = NULL;
segundo 0:ac1725ba162c 205 int c = 0;
segundo 0:ac1725ba162c 206
segundo 0:ac1725ba162c 207 UsbEndpoint *pEpOut = NULL;
segundo 0:ac1725ba162c 208
segundo 0:ac1725ba162c 209 while( !m_pDev->getInterfaceDescriptor(1, c++, &desc) )
segundo 0:ac1725ba162c 210 {
segundo 0:ac1725ba162c 211 byte* p = desc;
segundo 0:ac1725ba162c 212 int epNum = 0;
segundo 0:ac1725ba162c 213 p = p + p[0]; //Move to next descriptor (which should be an ep descriptor)
segundo 0:ac1725ba162c 214 while (epNum < desc[4]) //Eps count in this if
segundo 0:ac1725ba162c 215 {
segundo 0:ac1725ba162c 216 if (p[1] != USB_DESCRIPTOR_TYPE_ENDPOINT)
segundo 0:ac1725ba162c 217 break;
segundo 0:ac1725ba162c 218
segundo 0:ac1725ba162c 219 if( (p[3] == 0x02) && !(p[2] & 0x80) ) //Bulk endpoint, out
segundo 0:ac1725ba162c 220 {
segundo 0:ac1725ba162c 221 DBG("Found bulk ep %02x\n", p[2]);
segundo 0:ac1725ba162c 222 pEpOut = new UsbEndpoint( m_pDev, p[2], false, USB_BULK, *((uint16_t*)&p[4]) );
segundo 0:ac1725ba162c 223 break;
segundo 0:ac1725ba162c 224 }
segundo 0:ac1725ba162c 225
segundo 0:ac1725ba162c 226 p = p + p[0]; //Move to next ep desc
segundo 0:ac1725ba162c 227 epNum++;
segundo 0:ac1725ba162c 228 }
segundo 0:ac1725ba162c 229 if(pEpOut)
segundo 0:ac1725ba162c 230 break;
segundo 0:ac1725ba162c 231 }
segundo 0:ac1725ba162c 232
segundo 0:ac1725ba162c 233 if(!pEpOut)
segundo 0:ac1725ba162c 234 return UMTSERR_NOTFOUND;
segundo 0:ac1725ba162c 235
segundo 0:ac1725ba162c 236 //Send SCSI packet
segundo 0:ac1725ba162c 237
segundo 0:ac1725ba162c 238 DBG("Sending SCSI Packet to switch\n");
segundo 0:ac1725ba162c 239 byte ramCdfsBuf[31];
segundo 0:ac1725ba162c 240 memcpy(ramCdfsBuf, pInfo->cdfsPacket, 31);
segundo 0:ac1725ba162c 241 pEpOut->transfer((volatile byte*)ramCdfsBuf, 31);
segundo 0:ac1725ba162c 242 while(pEpOut->status() == USBERR_PROCESSING);
segundo 0:ac1725ba162c 243 int ret = pEpOut->status();
segundo 0:ac1725ba162c 244 if((ret < 0) && (ret !=USBERR_DISCONNECTED)) //Packet was not transfered
segundo 0:ac1725ba162c 245 {
segundo 0:ac1725ba162c 246 DBG("Usb error %d\n", ret);
segundo 0:ac1725ba162c 247 delete pEpOut;
segundo 0:ac1725ba162c 248 return UMTSERR_USBERR;
segundo 0:ac1725ba162c 249 }
segundo 0:ac1725ba162c 250
segundo 0:ac1725ba162c 251 delete pEpOut;
segundo 0:ac1725ba162c 252 }
segundo 0:ac1725ba162c 253 else
segundo 0:ac1725ba162c 254 {
segundo 0:ac1725ba162c 255 UsbErr usbErr;
segundo 0:ac1725ba162c 256 //Send the Huawei-specific control packet
segundo 0:ac1725ba162c 257 usbErr = m_pDev->controlSend(0, 0x03, 1, 0, NULL, 0);
segundo 0:ac1725ba162c 258 if(usbErr && (usbErr != USBERR_DISCONNECTED))
segundo 0:ac1725ba162c 259 return UMTSERR_USBERR;
segundo 0:ac1725ba162c 260 }
segundo 0:ac1725ba162c 261
segundo 0:ac1725ba162c 262 DBG("The stick should be switching in serial mode now\n");
segundo 0:ac1725ba162c 263
segundo 0:ac1725ba162c 264 return UMTSERR_OK;
segundo 0:ac1725ba162c 265 }
segundo 0:ac1725ba162c 266
segundo 0:ac1725ba162c 267 UMTSStickErr UMTSStick::findSerial(UsbSerial** ppUsbSerial)
segundo 0:ac1725ba162c 268 {
segundo 0:ac1725ba162c 269 byte* desc = NULL;
segundo 0:ac1725ba162c 270 int c = 0;
segundo 0:ac1725ba162c 271
segundo 0:ac1725ba162c 272 int epOut = 0;
segundo 0:ac1725ba162c 273 int epIn = 0;
segundo 0:ac1725ba162c 274
segundo 0:ac1725ba162c 275 while( !m_pDev->getInterfaceDescriptor(1, c++, &desc) )
segundo 0:ac1725ba162c 276 {
segundo 0:ac1725ba162c 277 byte* p = desc;
segundo 0:ac1725ba162c 278 int epNum = 0;
segundo 0:ac1725ba162c 279
segundo 0:ac1725ba162c 280 DBG("Interface of type %02x\n", desc[5]);
segundo 0:ac1725ba162c 281
segundo 0:ac1725ba162c 282 if(desc[5] != 0xFF) //Not a serial-like if
segundo 0:ac1725ba162c 283 continue;
segundo 0:ac1725ba162c 284
segundo 0:ac1725ba162c 285 p = p + p[0]; //Move to next descriptor (which should be an ep descriptor)
segundo 0:ac1725ba162c 286 while (epNum < desc[4]) //Eps count in this if
segundo 0:ac1725ba162c 287 {
segundo 0:ac1725ba162c 288 if (p[1] == USB_DESCRIPTOR_TYPE_ENDPOINT)
segundo 0:ac1725ba162c 289 {
segundo 0:ac1725ba162c 290 if( (p[3] == 0x02) && !(p[2] & 0x80) && !epOut ) //Bulk endpoint, out
segundo 0:ac1725ba162c 291 {
segundo 0:ac1725ba162c 292 DBG("Found bulk out ep %02x of payload size %04x\n", p[2], *((uint16_t*)&p[4]));
segundo 0:ac1725ba162c 293 epOut = p[2] & 0x7F;
segundo 0:ac1725ba162c 294 }
segundo 0:ac1725ba162c 295
segundo 0:ac1725ba162c 296 if( (p[3] == 0x02) && (p[2] & 0x80) && !epIn ) //Bulk endpoint, in
segundo 0:ac1725ba162c 297 {
segundo 0:ac1725ba162c 298 DBG("Found bulk in ep %02x of payload size %04x\n", p[2], *((uint16_t*)&p[4]));
segundo 0:ac1725ba162c 299 epIn = p[2] & 0x7F;
segundo 0:ac1725ba162c 300 }
segundo 0:ac1725ba162c 301
segundo 0:ac1725ba162c 302 if(epOut && epIn)
segundo 0:ac1725ba162c 303 break;
segundo 0:ac1725ba162c 304 }
segundo 0:ac1725ba162c 305
segundo 0:ac1725ba162c 306 p = p + p[0]; //Move to next ep desc
segundo 0:ac1725ba162c 307 epNum++;
segundo 0:ac1725ba162c 308 }
segundo 0:ac1725ba162c 309
segundo 0:ac1725ba162c 310 if(epOut && epIn)
segundo 0:ac1725ba162c 311 break;
segundo 0:ac1725ba162c 312 }
segundo 0:ac1725ba162c 313
segundo 0:ac1725ba162c 314 if(!epOut || !epIn)
segundo 0:ac1725ba162c 315 return UMTSERR_NOTFOUND;
segundo 0:ac1725ba162c 316
segundo 0:ac1725ba162c 317 DBG("Endpoints found, create serial object\n");
segundo 0:ac1725ba162c 318
segundo 0:ac1725ba162c 319 *ppUsbSerial = new UsbSerial(m_pDev, epIn, epOut);
segundo 0:ac1725ba162c 320
segundo 0:ac1725ba162c 321 DBG("UsbSerial object created\n");
segundo 0:ac1725ba162c 322
segundo 0:ac1725ba162c 323 return UMTSERR_OK;
segundo 0:ac1725ba162c 324 }
segundo 0:ac1725ba162c 325
segundo 0:ac1725ba162c 326 #endif