Connection Manager library for u-blox cellular modules. It manages the modem for keeping data connection always active.

Dependents:   C027_demo_ConnMan

Committer:
msinig
Date:
Thu Jan 21 14:00:25 2016 +0000
Revision:
1:29ad1d1ac1f9
Parent:
0:86284a262735
fix bugs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
msinig 0:86284a262735 1 #include "CNManager.h"
msinig 0:86284a262735 2
msinig 0:86284a262735 3 #include "CNData.h"
msinig 0:86284a262735 4 #include "CNUtil.h"
msinig 0:86284a262735 5 #include "CNLib.h"
msinig 0:86284a262735 6 #include "CNReg.h"
msinig 0:86284a262735 7
msinig 1:29ad1d1ac1f9 8 //! Manager internal state
msinig 0:86284a262735 9 typedef enum {
msinig 0:86284a262735 10 MNG_NOT_INIT = 0, //!< not initiated
msinig 0:86284a262735 11 MNG_RADIO_OFF, //!< radio is off
msinig 0:86284a262735 12 MNG_RADIO_ON, //!< radio is on
msinig 0:86284a262735 13 MNG_IDLE, //!< idle
msinig 0:86284a262735 14 MNG_DATA_UP, //!< data connection is active
msinig 0:86284a262735 15 MNG_ERROR_RESET, //!< reset
msinig 0:86284a262735 16 MNG_ERROR_STUCK //!< unrecoverable error
msinig 0:86284a262735 17 } MngState;
msinig 0:86284a262735 18
msinig 0:86284a262735 19 static MngState state = MNG_NOT_INIT; //!< Manager state
msinig 0:86284a262735 20 static bool moduleOn; //!< Module power requested power status
msinig 0:86284a262735 21 static bool dataOn;
msinig 0:86284a262735 22 static CNLib* cnLib; //!< Pointer to CN library
msinig 0:86284a262735 23 static char simPin[10]; //!< Sim Pin
msinig 0:86284a262735 24 static int errorCounter; //!< Error counter
msinig 1:29ad1d1ac1f9 25 static evMngHandler mngHandler; //!< Function point handler
msinig 1:29ad1d1ac1f9 26 static void* paramDataHandler; //!< Pointer to pass to the handler
msinig 1:29ad1d1ac1f9 27 static int respError;
msinig 0:86284a262735 28
msinig 0:86284a262735 29 static CNResp radioSwitchOn(CNLib*& lib);
msinig 0:86284a262735 30 static CNResp radioSwitchOff(CNLib*& lib);
msinig 0:86284a262735 31 static CNResp simInit(CNLib* lib, char* simPin);
msinig 0:86284a262735 32
msinig 1:29ad1d1ac1f9 33 bool cnInit(bool powerOn /*=true*/, bool dataEnabled /*=true*/, bool roomingEnabled /*=true*/){
msinig 1:29ad1d1ac1f9 34 mngHandler = NULL;
msinig 1:29ad1d1ac1f9 35 paramDataHandler = NULL;
msinig 0:86284a262735 36 state = MNG_RADIO_OFF;
msinig 0:86284a262735 37 moduleOn = powerOn;
msinig 0:86284a262735 38 errorCounter = 0;
msinig 1:29ad1d1ac1f9 39 respError = 0;
msinig 0:86284a262735 40 cnRegInit();
msinig 0:86284a262735 41 cnDataInit();
msinig 0:86284a262735 42 dataOn = dataEnabled;
msinig 0:86284a262735 43 cnRegSetRoaming(roomingEnabled);
msinig 0:86284a262735 44 return true;
msinig 0:86284a262735 45 }
msinig 0:86284a262735 46
msinig 1:29ad1d1ac1f9 47 void cnRegHandler(evMngHandler handler, void* param/*=NULL*/)
msinig 1:29ad1d1ac1f9 48 {
msinig 1:29ad1d1ac1f9 49 mngHandler = handler;
msinig 1:29ad1d1ac1f9 50 paramDataHandler = param;
msinig 1:29ad1d1ac1f9 51 }
msinig 1:29ad1d1ac1f9 52
msinig 1:29ad1d1ac1f9 53 MDMSerial* cnGetMDM(){
msinig 1:29ad1d1ac1f9 54 return (MDMSerial*) cnLib;
msinig 0:86284a262735 55 }
msinig 0:86284a262735 56
msinig 0:86284a262735 57 void cnSetPower(bool on){
msinig 0:86284a262735 58 moduleOn = on;
msinig 0:86284a262735 59 }
msinig 0:86284a262735 60
msinig 0:86284a262735 61 void cnSetDataEnabled(bool hasDataConnToBeEnabled){
msinig 1:29ad1d1ac1f9 62 TRACE("%s enter \r\n", __FUNCTION__);
msinig 0:86284a262735 63 dataOn = hasDataConnToBeEnabled;
msinig 0:86284a262735 64 cnDataEnable(dataOn);
msinig 0:86284a262735 65 }
msinig 0:86284a262735 66
msinig 0:86284a262735 67 void cnSetRoamingOn(bool isRoomingEnabled){
msinig 0:86284a262735 68 cnRegSetRoaming(isRoomingEnabled);
msinig 0:86284a262735 69 }
msinig 0:86284a262735 70
msinig 0:86284a262735 71 void cnSetApn(const char *apn,const char* username/*= NULL*/,const char* password/*= NULL*/){
msinig 0:86284a262735 72 cnDataSetupApn(apn, username, password);
msinig 0:86284a262735 73 }
msinig 0:86284a262735 74
msinig 0:86284a262735 75 void cnSetSimPin(const char* pin){
msinig 1:29ad1d1ac1f9 76 if (pin)
msinig 0:86284a262735 77 strncpy(simPin,pin, sizeof(simPin));
msinig 0:86284a262735 78 }
msinig 0:86284a262735 79
msinig 1:29ad1d1ac1f9 80 bool cnIsDataUp(){
msinig 1:29ad1d1ac1f9 81 return (state == MNG_DATA_UP)? true : false;
msinig 0:86284a262735 82 }
msinig 0:86284a262735 83
msinig 0:86284a262735 84 bool cnSetDebug(int level){
msinig 0:86284a262735 85 if (!setUtilDebugLevel(level))
msinig 0:86284a262735 86 return false;
msinig 0:86284a262735 87 return true;
msinig 0:86284a262735 88 }
msinig 0:86284a262735 89
msinig 0:86284a262735 90 int cnLoop(){
msinig 0:86284a262735 91 int ret;
msinig 0:86284a262735 92 MngState oldState = state;
msinig 0:86284a262735 93
msinig 0:86284a262735 94 TRACE("%s enter \r\n", __FUNCTION__);
msinig 0:86284a262735 95 //check if init has been called
msinig 0:86284a262735 96 if (state == MNG_NOT_INIT){
msinig 0:86284a262735 97 ERROR("%s Module has not been initiated\r\n", __FUNCTION__);
msinig 0:86284a262735 98 return false;
msinig 0:86284a262735 99 }
msinig 0:86284a262735 100 //switch on
msinig 0:86284a262735 101 if (state == MNG_RADIO_OFF && moduleOn ){
msinig 0:86284a262735 102 INFO("%s: Switching ON radio \r\n", __FUNCTION__);
msinig 0:86284a262735 103 cnDataEnable(dataOn);
msinig 0:86284a262735 104 ret = radioSwitchOn(cnLib);
msinig 0:86284a262735 105 state = (ret == RES_OK) ? MNG_RADIO_ON : MNG_ERROR_RESET;
msinig 1:29ad1d1ac1f9 106
msinig 0:86284a262735 107 }
msinig 0:86284a262735 108 //switch off
msinig 0:86284a262735 109 if (state != MNG_RADIO_OFF && !moduleOn){
msinig 0:86284a262735 110 INFO("%s: Switching OFF radio \r\n", __FUNCTION__);
msinig 0:86284a262735 111 if (state == MNG_DATA_UP)
msinig 0:86284a262735 112 //disable data
msinig 0:86284a262735 113 cnDataEnable(false);
msinig 0:86284a262735 114 else if (state == MNG_IDLE){
msinig 0:86284a262735 115 //switching off
msinig 0:86284a262735 116 cnDataReset();
msinig 0:86284a262735 117 cnRegReset();
msinig 0:86284a262735 118 radioSwitchOff(cnLib);
msinig 0:86284a262735 119 state = MNG_RADIO_OFF;
msinig 0:86284a262735 120 }
msinig 0:86284a262735 121 }
msinig 0:86284a262735 122 //sim initialization
msinig 0:86284a262735 123 if (state == MNG_RADIO_ON ){
msinig 0:86284a262735 124 ret = simInit(cnLib, simPin);
msinig 0:86284a262735 125 state = (ret == RES_OK) ? MNG_IDLE : MNG_ERROR_RESET;
msinig 1:29ad1d1ac1f9 126 if (state == MNG_IDLE && mngHandler)
msinig 1:29ad1d1ac1f9 127 mngHandler(MNG_EV_IDLE, paramDataHandler);
msinig 0:86284a262735 128 }
msinig 0:86284a262735 129 //cycle the registration and data service
msinig 0:86284a262735 130 if (state == MNG_IDLE || state == MNG_DATA_UP){
msinig 0:86284a262735 131 RegStatus regStatus;
msinig 1:29ad1d1ac1f9 132 int res;
msinig 0:86284a262735 133 DataConnStatus dataStatus;
msinig 0:86284a262735 134 //Tick the registration service
msinig 1:29ad1d1ac1f9 135 res = cnRegLoop(cnLib, &regStatus);
msinig 1:29ad1d1ac1f9 136 if (res != RES_OK && ++respError > MEX_RESP_ERROR)
msinig 1:29ad1d1ac1f9 137 state = MNG_ERROR_RESET;
msinig 0:86284a262735 138 //Tick Data service
msinig 0:86284a262735 139 cnDataLoop(cnLib, regStatus, &dataStatus);
msinig 0:86284a262735 140 //manage data status
msinig 0:86284a262735 141 if (dataStatus == DATA_IS_CONNECTED){
msinig 1:29ad1d1ac1f9 142 state = MNG_DATA_UP;
msinig 1:29ad1d1ac1f9 143 if (mngHandler) mngHandler(MNG_EV_DATA_UP, paramDataHandler);
msinig 0:86284a262735 144 } else if (dataStatus == DATA_IS_DISCONNECTED){
msinig 0:86284a262735 145 state = MNG_IDLE;
msinig 1:29ad1d1ac1f9 146 if (mngHandler) mngHandler(MNG_EV_DATA_DOWN, paramDataHandler);
msinig 0:86284a262735 147 }
msinig 0:86284a262735 148 }
msinig 0:86284a262735 149 //error management
msinig 0:86284a262735 150 if (state == MNG_ERROR_RESET){
msinig 0:86284a262735 151 //block state machine when errors reach a max value counter
msinig 0:86284a262735 152 if (++errorCounter > MAX_ERROR_RETRIES)
msinig 0:86284a262735 153 state = MNG_ERROR_STUCK;
msinig 0:86284a262735 154 else{
msinig 0:86284a262735 155 //otherwise start reset procedure
msinig 1:29ad1d1ac1f9 156 ERROR("%s: State machine is in Error state, doing Reset.\r\n", __FUNCTION__);
msinig 1:29ad1d1ac1f9 157 respError=0;
msinig 0:86284a262735 158 cnDataReset();
msinig 0:86284a262735 159 cnRegReset();
msinig 0:86284a262735 160 radioSwitchOff(cnLib);
msinig 0:86284a262735 161 state = MNG_RADIO_OFF;
msinig 0:86284a262735 162 }
msinig 0:86284a262735 163 }
msinig 0:86284a262735 164 //when the state is stuck stay here forever
msinig 0:86284a262735 165 if (state == MNG_ERROR_STUCK){
msinig 1:29ad1d1ac1f9 166 ERROR("%s: State machine is in Blocked state, please change setting.\r\n", __FUNCTION__);
msinig 0:86284a262735 167 return false;
msinig 0:86284a262735 168 }
msinig 0:86284a262735 169 //dump info
msinig 1:29ad1d1ac1f9 170 if (getUtilDebugLevel() > 1 && oldState != state){
msinig 1:29ad1d1ac1f9 171 INFO("CNManager Dump\r\n");
msinig 1:29ad1d1ac1f9 172 const char* txtState[] = { "Not Initiated", "Radio is Off", "Radio is On", \
msinig 1:29ad1d1ac1f9 173 "Idle", "Connected", "Reset Error", "Blocked Error"};
msinig 1:29ad1d1ac1f9 174 if (state < sizeof(txtState)/sizeof(*txtState))
msinig 1:29ad1d1ac1f9 175 INFO(" Internal State: %s\r\n", txtState[state]);
msinig 1:29ad1d1ac1f9 176 }
msinig 0:86284a262735 177 return true;
msinig 0:86284a262735 178 }
msinig 0:86284a262735 179
msinig 0:86284a262735 180 /** Switch On Radio
msinig 0:86284a262735 181 \param lib pointer to library
msinig 0:86284a262735 182 */
msinig 0:86284a262735 183 CNResp radioSwitchOn(CNLib*& lib)
msinig 0:86284a262735 184 {
msinig 0:86284a262735 185 TRACE("%s enter \r\n", __FUNCTION__);
msinig 0:86284a262735 186 lib = new CNLib();
msinig 0:86284a262735 187 if (lib == NULL){
msinig 1:29ad1d1ac1f9 188 ERROR("%s: Error on allocating lib\r\n", __FUNCTION__);
msinig 0:86284a262735 189 goto error;
msinig 0:86284a262735 190 }
msinig 0:86284a262735 191 lib->setDebug(getUtilDebugLevel());
msinig 0:86284a262735 192 //power on the module and detect if alive
msinig 0:86284a262735 193 if (!RESPOK(lib->powerOnModem())){
msinig 1:29ad1d1ac1f9 194 ERROR("%s: Error on detecting the modem\r\n", __FUNCTION__);
msinig 0:86284a262735 195 goto error;
msinig 0:86284a262735 196 }
msinig 0:86284a262735 197 //init generic modem
msinig 0:86284a262735 198 if (!RESPOK(lib->initModem())){
msinig 1:29ad1d1ac1f9 199 ERROR("%s: Error on init device\r\n", __FUNCTION__);
msinig 0:86284a262735 200 goto error;
msinig 0:86284a262735 201 }
msinig 0:86284a262735 202 //handle unknown device
msinig 0:86284a262735 203 if (lib->getDev()->dev == MDMParser::DEV_UNKNOWN){
msinig 1:29ad1d1ac1f9 204 ERROR("%s: Device is unknown\r\n", __FUNCTION__);
msinig 0:86284a262735 205 goto error;
msinig 0:86284a262735 206 }
msinig 0:86284a262735 207 return RES_OK;
msinig 0:86284a262735 208
msinig 0:86284a262735 209 error:
msinig 0:86284a262735 210 return RES_ERROR;
msinig 0:86284a262735 211
msinig 0:86284a262735 212 }
msinig 0:86284a262735 213
msinig 0:86284a262735 214 /** Switch off the radio
msinig 0:86284a262735 215 \param lib pointer to CN library
msinig 0:86284a262735 216 */
msinig 0:86284a262735 217 CNResp radioSwitchOff(CNLib*& lib){
msinig 0:86284a262735 218 TRACE("%s enter \r\n", __FUNCTION__);
msinig 0:86284a262735 219 if (lib != NULL){
msinig 0:86284a262735 220 lib->powerOff();
msinig 0:86284a262735 221 delete lib;
msinig 0:86284a262735 222 }
msinig 0:86284a262735 223 return RES_OK;
msinig 0:86284a262735 224 }
msinig 0:86284a262735 225
msinig 0:86284a262735 226 /** Sim Pin initialization
msinig 0:86284a262735 227 \param lib pointer to CN library
msinig 0:86284a262735 228 \param simPin sim pin
msinig 0:86284a262735 229 */
msinig 0:86284a262735 230 CNResp simEnterPin(CNLib* lib, char* simPin){
msinig 0:86284a262735 231 int res;
msinig 0:86284a262735 232
msinig 0:86284a262735 233 if (simPin == NULL){
msinig 1:29ad1d1ac1f9 234 ERROR("%s: Sim Pin is required but not provided\r\n", __FUNCTION__);
msinig 0:86284a262735 235 return RES_ERROR_STUCK;
msinig 0:86284a262735 236 }
msinig 0:86284a262735 237 res = lib->simInit(simPin);
msinig 0:86284a262735 238 if (RESPOK(res) )
msinig 0:86284a262735 239 return RES_OK;
msinig 0:86284a262735 240 if (lib->getDev()->sim == MDMParser::WRONG_PIN){
msinig 1:29ad1d1ac1f9 241 ERROR("%s: Sim pin, %s ,provided is wrong\r\n", simPin);
msinig 0:86284a262735 242 return RES_ERROR_STUCK;
msinig 0:86284a262735 243 }
msinig 0:86284a262735 244 return RES_ERROR;
msinig 0:86284a262735 245 }
msinig 0:86284a262735 246
msinig 0:86284a262735 247 /** Sim initialization
msinig 0:86284a262735 248 \param lib pointer to CN library
msinig 0:86284a262735 249 \param simPin sim pin
msinig 0:86284a262735 250 */
msinig 0:86284a262735 251 CNResp simInit(CNLib* lib, char* simPin)
msinig 0:86284a262735 252 {
msinig 0:86284a262735 253 CNResp res = RES_ERROR;
msinig 0:86284a262735 254 int _simWaitCounter=0;
msinig 0:86284a262735 255 TRACE("CNLib::%s enter\r\n", __FUNCTION__);
msinig 0:86284a262735 256
msinig 0:86284a262735 257 do{
msinig 0:86284a262735 258 if (RESPOK(lib->simInit(NULL)))
msinig 0:86284a262735 259 break;
msinig 0:86284a262735 260 wait_ms(10);
msinig 0:86284a262735 261 } while(_simWaitCounter++ < SIM_WAIT_MAX_CYCLE);
msinig 0:86284a262735 262 INFO("Sim status is %d \r\n", lib->getDev()->sim);
msinig 0:86284a262735 263 //handle sim status
msinig 0:86284a262735 264 switch (lib->getDev()->sim){
msinig 0:86284a262735 265 case MDMParser::SIM_READY:
msinig 1:29ad1d1ac1f9 266 INFO("%s: Sim has been initiated correctly\r\n", __FUNCTION__);
msinig 0:86284a262735 267 res = RES_OK;
msinig 0:86284a262735 268 break;
msinig 0:86284a262735 269 case MDMParser::SIM_PIN:
msinig 1:29ad1d1ac1f9 270 INFO("%s: Sim Pin is requested\r\n");
msinig 0:86284a262735 271 res = simEnterPin(lib, simPin);
msinig 0:86284a262735 272 break;
msinig 0:86284a262735 273 case MDMParser::SIM_MISSING:
msinig 1:29ad1d1ac1f9 274 ERROR("%s: Sim has not been inserted, HALT\r\n", __FUNCTION__);
msinig 0:86284a262735 275 res = RES_ERROR;
msinig 0:86284a262735 276 break;
msinig 0:86284a262735 277 case MDMParser::SIM_PUK:
msinig 1:29ad1d1ac1f9 278 ERROR("%s: Sim Puk is required, HALT\r\n", __FUNCTION__);
msinig 0:86284a262735 279 res = RES_ERROR_STUCK;
msinig 0:86284a262735 280 break;
msinig 0:86284a262735 281 case MDMParser::SIM_UNKNOWN:
msinig 1:29ad1d1ac1f9 282 ERROR("%s: Sim Unknown state\r\n", __FUNCTION__);
msinig 0:86284a262735 283 res = RES_ERROR_STUCK;
msinig 0:86284a262735 284 break;
msinig 0:86284a262735 285 case MDMParser::WRONG_PIN:
msinig 1:29ad1d1ac1f9 286 ERROR("%s: Wrong sim pin provided, HALT\r\n", __FUNCTION__);
msinig 0:86284a262735 287 res = RES_ERROR_STUCK;
msinig 0:86284a262735 288 break;
msinig 0:86284a262735 289 }
msinig 0:86284a262735 290 //sim has been successfully initialized
msinig 0:86284a262735 291 if (res == RES_OK){
msinig 0:86284a262735 292 lib->getSimInfo();
msinig 0:86284a262735 293 }
msinig 0:86284a262735 294 return res;
msinig 1:29ad1d1ac1f9 295 }
msinig 1:29ad1d1ac1f9 296
msinig 1:29ad1d1ac1f9 297 void getNetStatus(MDMParser::NetStatus* net){
msinig 1:29ad1d1ac1f9 298 if (net && cnLib)
msinig 1:29ad1d1ac1f9 299 memcpy(net, cnLib->getNet(), sizeof(MDMParser::NetStatus));
msinig 1:29ad1d1ac1f9 300 }
msinig 1:29ad1d1ac1f9 301 void getDevStatus(MDMParser::DevStatus* dev){
msinig 1:29ad1d1ac1f9 302 if (dev && cnLib)
msinig 1:29ad1d1ac1f9 303 memcpy(dev, cnLib->getDev(), sizeof(MDMParser::DevStatus));
msinig 0:86284a262735 304 }