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:
Tue Jan 12 09:08:15 2016 +0000
Revision:
0:86284a262735
Child:
1:29ad1d1ac1f9
first drop

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