mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* UbloxUSBCDMAModem.cpp */
elessair 0:f269e3021894 2 /* Copyright (C) 2012 mbed.org, MIT License
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
elessair 0:f269e3021894 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
elessair 0:f269e3021894 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
elessair 0:f269e3021894 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
elessair 0:f269e3021894 8 * furnished to do so, subject to the following conditions:
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * The above copyright notice and this permission notice shall be included in all copies or
elessair 0:f269e3021894 11 * substantial portions of the Software.
elessair 0:f269e3021894 12 *
elessair 0:f269e3021894 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
elessair 0:f269e3021894 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
elessair 0:f269e3021894 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
elessair 0:f269e3021894 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
elessair 0:f269e3021894 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
elessair 0:f269e3021894 18 */
elessair 0:f269e3021894 19
elessair 0:f269e3021894 20 #define __DEBUG__ 4
elessair 0:f269e3021894 21 #ifndef __MODULE__
elessair 0:f269e3021894 22 #define __MODULE__ "UbloxUSBCDMAModem.cpp"
elessair 0:f269e3021894 23 #endif
elessair 0:f269e3021894 24
elessair 0:f269e3021894 25 #include "core/fwk.h"
elessair 0:f269e3021894 26
elessair 0:f269e3021894 27 #include "UbloxUSBCDMAModem.h"
elessair 0:f269e3021894 28 #include "UbloxCDMAModemInitializer.h"
elessair 0:f269e3021894 29 #include "USBHost.h"
elessair 0:f269e3021894 30
elessair 0:f269e3021894 31 #define USE_ONE_PORT 1
elessair 0:f269e3021894 32
elessair 0:f269e3021894 33 UbloxUSBCDMAModem::UbloxUSBCDMAModem(PinName powerGatingPin /*= NC*/, bool powerGatingOnWhenPinHigh /* = true*/, int serial /* 0 */) : m_dongle(),
elessair 0:f269e3021894 34 m_stream(m_dongle.getSerial(serial)),
elessair 0:f269e3021894 35 m_at(&m_stream),
elessair 0:f269e3021894 36 m_sms(&m_at), m_ppp(&m_stream),
elessair 0:f269e3021894 37 m_dongleConnected(false), m_ipInit(false), m_smsInit(false), m_atOpen(false),
elessair 0:f269e3021894 38 m_powerGatingPin(powerGatingPin), m_powerGatingOnWhenPinHigh(powerGatingOnWhenPinHigh)
elessair 0:f269e3021894 39 {
elessair 0:f269e3021894 40 USBHost* host = USBHost::getHostInst();
elessair 0:f269e3021894 41 m_dongle.addInitializer(new UbloxCDMAModemInitializer(host));
elessair 0:f269e3021894 42 if( m_powerGatingPin != NC )
elessair 0:f269e3021894 43 {
elessair 0:f269e3021894 44 power(false); //Dongle will have to be powered on manually
elessair 0:f269e3021894 45 }
elessair 0:f269e3021894 46 }
elessair 0:f269e3021894 47
elessair 0:f269e3021894 48 class CSSProcessor : public IATCommandsProcessor
elessair 0:f269e3021894 49 {
elessair 0:f269e3021894 50 public:
elessair 0:f269e3021894 51 CSSProcessor() : status(STATUS_REGISTERING)
elessair 0:f269e3021894 52 {
elessair 0:f269e3021894 53
elessair 0:f269e3021894 54 }
elessair 0:f269e3021894 55 enum REGISTERING_STATUS { STATUS_REGISTERING, STATUS_OK };
elessair 0:f269e3021894 56 REGISTERING_STATUS getStatus()
elessair 0:f269e3021894 57 {
elessair 0:f269e3021894 58 return status;
elessair 0:f269e3021894 59 }
elessair 0:f269e3021894 60 private:
elessair 0:f269e3021894 61 virtual int onNewATResponseLine(ATCommandsInterface* pInst, const char* line)
elessair 0:f269e3021894 62 {
elessair 0:f269e3021894 63 char b;
elessair 0:f269e3021894 64 char bc[3] = "";
elessair 0:f269e3021894 65 int sid = 99999;
elessair 0:f269e3021894 66
elessair 0:f269e3021894 67 //if( sscanf(line, "%*d, %c", &r) == 1 )
elessair 0:f269e3021894 68 if(sscanf(line, "%*s %c,%2s,%d", &b,bc,&sid)==3)
elessair 0:f269e3021894 69 {
elessair 0:f269e3021894 70 if(strcmp("Z", bc) == 0)
elessair 0:f269e3021894 71 status = STATUS_REGISTERING;
elessair 0:f269e3021894 72 else
elessair 0:f269e3021894 73 status = STATUS_OK;
elessair 0:f269e3021894 74 }
elessair 0:f269e3021894 75 return OK;
elessair 0:f269e3021894 76 }
elessair 0:f269e3021894 77 virtual int onNewEntryPrompt(ATCommandsInterface* pInst)
elessair 0:f269e3021894 78 {
elessair 0:f269e3021894 79 return OK;
elessair 0:f269e3021894 80 }
elessair 0:f269e3021894 81 volatile REGISTERING_STATUS status;
elessair 0:f269e3021894 82 };
elessair 0:f269e3021894 83
elessair 0:f269e3021894 84 int UbloxUSBCDMAModem::connect(const char* apn, const char* user, const char* password)
elessair 0:f269e3021894 85 {
elessair 0:f269e3021894 86 if( !m_ipInit )
elessair 0:f269e3021894 87 {
elessair 0:f269e3021894 88 m_ipInit = true;
elessair 0:f269e3021894 89 m_ppp.init();
elessair 0:f269e3021894 90 }
elessair 0:f269e3021894 91 m_ppp.setup(user, password, DEFAULT_MSISDN_CDMA);
elessair 0:f269e3021894 92
elessair 0:f269e3021894 93 int ret = init();
elessair 0:f269e3021894 94 if(ret)
elessair 0:f269e3021894 95 {
elessair 0:f269e3021894 96 return ret;
elessair 0:f269e3021894 97 }
elessair 0:f269e3021894 98
elessair 0:f269e3021894 99 #if USE_ONE_PORT
elessair 0:f269e3021894 100 m_smsInit = false; //SMS status reset
elessair 0:f269e3021894 101 //m_ussdInit = false; //USSD status reset
elessair 0:f269e3021894 102 //m_linkMonitorInit = false; //Link monitor status reset
elessair 0:f269e3021894 103 #endif
elessair 0:f269e3021894 104
elessair 0:f269e3021894 105 ATCommandsInterface::ATResult result;
elessair 0:f269e3021894 106
elessair 0:f269e3021894 107 if(apn != NULL)
elessair 0:f269e3021894 108 {
elessair 0:f269e3021894 109 char cmd[48];
elessair 0:f269e3021894 110 sprintf(cmd, "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
elessair 0:f269e3021894 111 ret = m_at.executeSimple(cmd, &result);
elessair 0:f269e3021894 112 DBG("Result of command: Err code=%d", ret);
elessair 0:f269e3021894 113 DBG("ATResult: AT return=%d (code %d)", result.result, result.code);
elessair 0:f269e3021894 114 DBG("APN set to %s", apn);
elessair 0:f269e3021894 115 }
elessair 0:f269e3021894 116
elessair 0:f269e3021894 117
elessair 0:f269e3021894 118 //Connect
elessair 0:f269e3021894 119 DBG("Connecting");
elessair 0:f269e3021894 120 #if USE_ONE_PORT
elessair 0:f269e3021894 121 m_at.close(); // Closing AT parser
elessair 0:f269e3021894 122 m_atOpen = false; //Will need to be reinitialized afterwards
elessair 0:f269e3021894 123 #endif
elessair 0:f269e3021894 124
elessair 0:f269e3021894 125 DBG("Connecting PPP");
elessair 0:f269e3021894 126
elessair 0:f269e3021894 127 ret = m_ppp.connect();
elessair 0:f269e3021894 128 DBG("Result of connect: Err code=%d", ret);
elessair 0:f269e3021894 129 return ret;
elessair 0:f269e3021894 130 }
elessair 0:f269e3021894 131
elessair 0:f269e3021894 132
elessair 0:f269e3021894 133 int UbloxUSBCDMAModem::disconnect()
elessair 0:f269e3021894 134 {
elessair 0:f269e3021894 135 DBG("Disconnecting from PPP");
elessair 0:f269e3021894 136 int ret = m_ppp.disconnect();
elessair 0:f269e3021894 137 if(ret)
elessair 0:f269e3021894 138 {
elessair 0:f269e3021894 139 ERR("Disconnect returned %d, still trying to disconnect", ret);
elessair 0:f269e3021894 140 }
elessair 0:f269e3021894 141
elessair 0:f269e3021894 142 //Ugly but leave dongle time to recover
elessair 0:f269e3021894 143 Thread::wait(500);
elessair 0:f269e3021894 144
elessair 0:f269e3021894 145 #if USE_ONE_PORT
elessair 0:f269e3021894 146 ATCommandsInterface::ATResult result;
elessair 0:f269e3021894 147 DBG("Starting AT thread");
elessair 0:f269e3021894 148 ret = m_at.open();
elessair 0:f269e3021894 149 if(ret)
elessair 0:f269e3021894 150 {
elessair 0:f269e3021894 151 return ret;
elessair 0:f269e3021894 152 }
elessair 0:f269e3021894 153 #endif
elessair 0:f269e3021894 154
elessair 0:f269e3021894 155 DBG("Trying to hangup");
elessair 0:f269e3021894 156
elessair 0:f269e3021894 157 #if 0 //Does not appear to work
elessair 0:f269e3021894 158 int tries = 10;
elessair 0:f269e3021894 159 do
elessair 0:f269e3021894 160 {
elessair 0:f269e3021894 161 ret = m_at.executeSimple("+++", &result, 1000);
elessair 0:f269e3021894 162 DBG("Result of command: Err code=%d\n", ret);
elessair 0:f269e3021894 163 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
elessair 0:f269e3021894 164 } while(tries-- && ret);
elessair 0:f269e3021894 165 if(!ret)
elessair 0:f269e3021894 166 {
elessair 0:f269e3021894 167 ret = m_at.executeSimple("ATH", &result);
elessair 0:f269e3021894 168 DBG("Result of command: Err code=%d\n", ret);
elessair 0:f269e3021894 169 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
elessair 0:f269e3021894 170 }
elessair 0:f269e3021894 171 #endif
elessair 0:f269e3021894 172
elessair 0:f269e3021894 173 #if USE_ONE_PORT
elessair 0:f269e3021894 174 //Reinit AT parser
elessair 0:f269e3021894 175 ret = m_at.init();
elessair 0:f269e3021894 176 DBG("Result of command: Err code=%d\n", ret);
elessair 0:f269e3021894 177 if(ret)
elessair 0:f269e3021894 178 {
elessair 0:f269e3021894 179 m_at.close(); // Closing AT parser
elessair 0:f269e3021894 180 DBG("AT Parser closed, could not complete disconnection");
elessair 0:f269e3021894 181 return NET_TIMEOUT;
elessair 0:f269e3021894 182 }
elessair 0:f269e3021894 183
elessair 0:f269e3021894 184 #if 0
elessair 0:f269e3021894 185 m_at.close(); // Closing AT parser
elessair 0:f269e3021894 186 DBG("AT Parser closed");
elessair 0:f269e3021894 187 #endif
elessair 0:f269e3021894 188 #endif
elessair 0:f269e3021894 189 return OK;
elessair 0:f269e3021894 190 }
elessair 0:f269e3021894 191
elessair 0:f269e3021894 192 int UbloxUSBCDMAModem::sendSM(const char* number, const char* message)
elessair 0:f269e3021894 193 {
elessair 0:f269e3021894 194 int ret = init();
elessair 0:f269e3021894 195 if(ret)
elessair 0:f269e3021894 196 {
elessair 0:f269e3021894 197 return ret;
elessair 0:f269e3021894 198 }
elessair 0:f269e3021894 199
elessair 0:f269e3021894 200 if(!m_smsInit)
elessair 0:f269e3021894 201 {
elessair 0:f269e3021894 202 ret = m_sms.init();
elessair 0:f269e3021894 203 if(ret)
elessair 0:f269e3021894 204 {
elessair 0:f269e3021894 205 return ret;
elessair 0:f269e3021894 206 }
elessair 0:f269e3021894 207 m_smsInit = true;
elessair 0:f269e3021894 208 }
elessair 0:f269e3021894 209
elessair 0:f269e3021894 210 ret = m_sms.send(number, message);
elessair 0:f269e3021894 211 if(ret)
elessair 0:f269e3021894 212 {
elessair 0:f269e3021894 213 return ret;
elessair 0:f269e3021894 214 }
elessair 0:f269e3021894 215
elessair 0:f269e3021894 216 return OK;
elessair 0:f269e3021894 217 }
elessair 0:f269e3021894 218
elessair 0:f269e3021894 219 int UbloxUSBCDMAModem::getSM(char* number, char* message, size_t maxLength)
elessair 0:f269e3021894 220 {
elessair 0:f269e3021894 221 int ret = init();
elessair 0:f269e3021894 222 if(ret)
elessair 0:f269e3021894 223 {
elessair 0:f269e3021894 224 return ret;
elessair 0:f269e3021894 225 }
elessair 0:f269e3021894 226
elessair 0:f269e3021894 227 if(!m_smsInit)
elessair 0:f269e3021894 228 {
elessair 0:f269e3021894 229 ret = m_sms.init();
elessair 0:f269e3021894 230 if(ret)
elessair 0:f269e3021894 231 {
elessair 0:f269e3021894 232 return ret;
elessair 0:f269e3021894 233 }
elessair 0:f269e3021894 234 m_smsInit = true;
elessair 0:f269e3021894 235 }
elessair 0:f269e3021894 236
elessair 0:f269e3021894 237 ret = m_sms.get(number, message, maxLength);
elessair 0:f269e3021894 238 if(ret)
elessair 0:f269e3021894 239 {
elessair 0:f269e3021894 240 return ret;
elessair 0:f269e3021894 241 }
elessair 0:f269e3021894 242
elessair 0:f269e3021894 243 return OK;
elessair 0:f269e3021894 244 }
elessair 0:f269e3021894 245
elessair 0:f269e3021894 246 int UbloxUSBCDMAModem::getSMCount(size_t* pCount)
elessair 0:f269e3021894 247 {
elessair 0:f269e3021894 248 int ret = init();
elessair 0:f269e3021894 249 if(ret)
elessair 0:f269e3021894 250 {
elessair 0:f269e3021894 251 return ret;
elessair 0:f269e3021894 252 }
elessair 0:f269e3021894 253
elessair 0:f269e3021894 254 if(!m_smsInit)
elessair 0:f269e3021894 255 {
elessair 0:f269e3021894 256 ret = m_sms.init();
elessair 0:f269e3021894 257 if(ret)
elessair 0:f269e3021894 258 {
elessair 0:f269e3021894 259 return ret;
elessair 0:f269e3021894 260 }
elessair 0:f269e3021894 261 m_smsInit = true;
elessair 0:f269e3021894 262 }
elessair 0:f269e3021894 263
elessair 0:f269e3021894 264 ret = m_sms.getCount(pCount);
elessair 0:f269e3021894 265 if(ret)
elessair 0:f269e3021894 266 {
elessair 0:f269e3021894 267 return ret;
elessair 0:f269e3021894 268 }
elessair 0:f269e3021894 269
elessair 0:f269e3021894 270 return OK;
elessair 0:f269e3021894 271 }
elessair 0:f269e3021894 272
elessair 0:f269e3021894 273 ATCommandsInterface* UbloxUSBCDMAModem::getATCommandsInterface()
elessair 0:f269e3021894 274 {
elessair 0:f269e3021894 275 return &m_at;
elessair 0:f269e3021894 276 }
elessair 0:f269e3021894 277
elessair 0:f269e3021894 278 int UbloxUSBCDMAModem::power(bool enable)
elessair 0:f269e3021894 279 {
elessair 0:f269e3021894 280 if( m_powerGatingPin == NC )
elessair 0:f269e3021894 281 {
elessair 0:f269e3021894 282 return NET_INVALID; //A pin name has not been provided in the constructor
elessair 0:f269e3021894 283 }
elessair 0:f269e3021894 284
elessair 0:f269e3021894 285 if(!enable) //Will force components to re-init
elessair 0:f269e3021894 286 {
elessair 0:f269e3021894 287 cleanup();
elessair 0:f269e3021894 288 }
elessair 0:f269e3021894 289
elessair 0:f269e3021894 290 DigitalOut powerGatingOut(m_powerGatingPin);
elessair 0:f269e3021894 291 powerGatingOut = m_powerGatingOnWhenPinHigh?enable:!enable;
elessair 0:f269e3021894 292
elessair 0:f269e3021894 293 return OK;
elessair 0:f269e3021894 294 }
elessair 0:f269e3021894 295
elessair 0:f269e3021894 296 bool UbloxUSBCDMAModem::power()
elessair 0:f269e3021894 297 {
elessair 0:f269e3021894 298 if( m_powerGatingPin == NC )
elessair 0:f269e3021894 299 {
elessair 0:f269e3021894 300 return true; //Assume power is always on
elessair 0:f269e3021894 301 }
elessair 0:f269e3021894 302
elessair 0:f269e3021894 303 DigitalOut powerGatingOut(m_powerGatingPin);
elessair 0:f269e3021894 304 return m_powerGatingOnWhenPinHigh?powerGatingOut:!powerGatingOut;
elessair 0:f269e3021894 305 }
elessair 0:f269e3021894 306
elessair 0:f269e3021894 307 int UbloxUSBCDMAModem::init()
elessair 0:f269e3021894 308 {
elessair 0:f269e3021894 309 if( !m_dongleConnected )
elessair 0:f269e3021894 310 {
elessair 0:f269e3021894 311 if(!power())
elessair 0:f269e3021894 312 {
elessair 0:f269e3021894 313 //Obviously cannot initialize the dongle if it is disconnected...
elessair 0:f269e3021894 314 ERR("Power is off");
elessair 0:f269e3021894 315 return NET_INVALID;
elessair 0:f269e3021894 316 }
elessair 0:f269e3021894 317 m_dongleConnected = true;
elessair 0:f269e3021894 318 while( !m_dongle.connected() )
elessair 0:f269e3021894 319 {
elessair 0:f269e3021894 320 m_dongle.tryConnect();
elessair 0:f269e3021894 321 Thread::wait(100);
elessair 0:f269e3021894 322 }
elessair 0:f269e3021894 323 }
elessair 0:f269e3021894 324
elessair 0:f269e3021894 325 if(m_atOpen)
elessair 0:f269e3021894 326 {
elessair 0:f269e3021894 327 return OK;
elessair 0:f269e3021894 328 }
elessair 0:f269e3021894 329
elessair 0:f269e3021894 330 DBG("Starting AT thread if needed");
elessair 0:f269e3021894 331 int ret = m_at.open();
elessair 0:f269e3021894 332 if(ret)
elessair 0:f269e3021894 333 {
elessair 0:f269e3021894 334 return ret;
elessair 0:f269e3021894 335 }
elessair 0:f269e3021894 336
elessair 0:f269e3021894 337 DBG("Sending initialisation commands");
elessair 0:f269e3021894 338 ret = m_at.init();
elessair 0:f269e3021894 339 if(ret)
elessair 0:f269e3021894 340 {
elessair 0:f269e3021894 341 return ret;
elessair 0:f269e3021894 342 }
elessair 0:f269e3021894 343
elessair 0:f269e3021894 344 if(m_dongle.getDongleType() == WAN_DONGLE_TYPE_UBLOX_LISAC200)
elessair 0:f269e3021894 345 {
elessair 0:f269e3021894 346 INFO("Using a UBLOX C200 Dongle");
elessair 0:f269e3021894 347 }
elessair 0:f269e3021894 348 else
elessair 0:f269e3021894 349 {
elessair 0:f269e3021894 350 WARN("Using an Unknown Dongle");
elessair 0:f269e3021894 351 }
elessair 0:f269e3021894 352
elessair 0:f269e3021894 353 ATCommandsInterface::ATResult result;
elessair 0:f269e3021894 354
elessair 0:f269e3021894 355 //Wait for network registration
elessair 0:f269e3021894 356 CSSProcessor cssProcessor;
elessair 0:f269e3021894 357 do
elessair 0:f269e3021894 358 {
elessair 0:f269e3021894 359 DBG("Waiting for network registration");
elessair 0:f269e3021894 360 ret = m_at.execute("AT+CSS?", &cssProcessor, &result);
elessair 0:f269e3021894 361 DBG("Result of command: Err code=%d\n", ret);
elessair 0:f269e3021894 362 DBG("ATResult: AT return=%d (code %d)\n", result.result, result.code);
elessair 0:f269e3021894 363 if(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING)
elessair 0:f269e3021894 364 {
elessair 0:f269e3021894 365 Thread::wait(3000);
elessair 0:f269e3021894 366 }
elessair 0:f269e3021894 367 } while(cssProcessor.getStatus() == CSSProcessor::STATUS_REGISTERING);
elessair 0:f269e3021894 368
elessair 0:f269e3021894 369 m_atOpen = true;
elessair 0:f269e3021894 370
elessair 0:f269e3021894 371 return OK;
elessair 0:f269e3021894 372 }
elessair 0:f269e3021894 373
elessair 0:f269e3021894 374 int UbloxUSBCDMAModem::cleanup()
elessair 0:f269e3021894 375 {
elessair 0:f269e3021894 376 if(m_ppp.isConnected())
elessair 0:f269e3021894 377 {
elessair 0:f269e3021894 378 WARN("Data connection is still open"); //Try to encourage good behaviour from the user
elessair 0:f269e3021894 379 m_ppp.disconnect();
elessair 0:f269e3021894 380 }
elessair 0:f269e3021894 381
elessair 0:f269e3021894 382 m_smsInit = false;
elessair 0:f269e3021894 383 // m_linkMonitorInit = false;
elessair 0:f269e3021894 384 //We don't reset m_ipInit as PPPIPInterface::init() only needs to be called once
elessair 0:f269e3021894 385
elessair 0:f269e3021894 386 if(m_atOpen)
elessair 0:f269e3021894 387 {
elessair 0:f269e3021894 388 m_at.close();
elessair 0:f269e3021894 389 m_atOpen = false;
elessair 0:f269e3021894 390 }
elessair 0:f269e3021894 391
elessair 0:f269e3021894 392 m_dongle.disconnect();
elessair 0:f269e3021894 393 m_dongleConnected = false;
elessair 0:f269e3021894 394
elessair 0:f269e3021894 395 return OK;
elessair 0:f269e3021894 396 }
elessair 0:f269e3021894 397
elessair 0:f269e3021894 398