u-blox / CNManager

Dependents:   C027_demo_ConnMan

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CNManager.cpp Source File

CNManager.cpp

00001 #include "CNManager.h"
00002 
00003 #include "CNData.h"
00004 #include "CNUtil.h"
00005 #include "CNLib.h"
00006 #include "CNReg.h"
00007 
00008 //! Manager internal state
00009 typedef enum {
00010     MNG_NOT_INIT = 0,       //!< not initiated
00011     MNG_RADIO_OFF,          //!< radio is off
00012     MNG_RADIO_ON,           //!< radio is on
00013     MNG_IDLE,               //!< idle
00014     MNG_DATA_UP,            //!< data connection is active
00015     MNG_ERROR_RESET,        //!< reset
00016     MNG_ERROR_STUCK         //!< unrecoverable error
00017 } MngState;
00018 
00019 static MngState state = MNG_NOT_INIT;    //!< Manager state
00020 static bool moduleOn;                    //!< Module power requested power status
00021 static bool dataOn;
00022 static CNLib* cnLib;                      //!< Pointer to CN library
00023 static char simPin[10];                   //!< Sim Pin
00024 static int errorCounter;                  //!< Error counter
00025 static evMngHandler mngHandler;         //!< Function point handler
00026 static void* paramDataHandler;            //!< Pointer to pass to the handler    
00027 static int respError;
00028 
00029 static CNResp radioSwitchOn(CNLib*& lib);
00030 static CNResp radioSwitchOff(CNLib*& lib);
00031 static CNResp simInit(CNLib* lib, char* simPin);
00032 
00033 bool cnInit(bool powerOn /*=true*/, bool dataEnabled /*=true*/, bool roomingEnabled /*=true*/){
00034     mngHandler = NULL;
00035     paramDataHandler = NULL;
00036     state = MNG_RADIO_OFF;
00037     moduleOn = powerOn;
00038     errorCounter = 0;
00039     respError = 0;
00040     cnRegInit();
00041     cnDataInit();
00042     dataOn = dataEnabled;
00043     cnRegSetRoaming(roomingEnabled);
00044     return true;
00045 }
00046 
00047 void cnRegHandler(evMngHandler handler, void* param/*=NULL*/)
00048 {
00049      mngHandler = handler;     
00050      paramDataHandler = param;
00051 }
00052 
00053 MDMSerial* cnGetMDM(){
00054     return (MDMSerial*) cnLib;
00055 }
00056 
00057 void cnSetPower(bool on){
00058     moduleOn = on;
00059 }
00060 
00061 void cnSetDataEnabled(bool hasDataConnToBeEnabled){
00062      TRACE("%s enter \r\n", __FUNCTION__); 
00063     dataOn = hasDataConnToBeEnabled;
00064     cnDataEnable(dataOn);
00065 }
00066 
00067 void cnSetRoamingOn(bool isRoomingEnabled){
00068     cnRegSetRoaming(isRoomingEnabled);
00069 }
00070 
00071 void cnSetApn(const char *apn,const  char* username/*= NULL*/,const  char* password/*= NULL*/){
00072     cnDataSetupApn(apn, username, password);
00073 }
00074 
00075 void cnSetSimPin(const char* pin){
00076     if (pin)
00077         strncpy(simPin,pin, sizeof(simPin)); 
00078 }
00079 
00080 bool cnIsDataUp(){
00081     return (state == MNG_DATA_UP)? true : false;
00082 }
00083 
00084 bool cnSetDebug(int level){
00085      if (!setUtilDebugLevel(level))
00086          return false;
00087      return true;
00088 }
00089 
00090 int cnLoop(){
00091     int ret;
00092     MngState oldState = state;
00093 
00094     TRACE("%s enter \r\n", __FUNCTION__);   
00095     //check if init has been called
00096     if (state == MNG_NOT_INIT){
00097         ERROR("%s Module has not been initiated\r\n", __FUNCTION__);
00098         return false;
00099     }
00100     //switch on
00101     if (state == MNG_RADIO_OFF && moduleOn ){
00102         INFO("%s: Switching ON radio \r\n", __FUNCTION__);
00103         cnDataEnable(dataOn);
00104         ret = radioSwitchOn(cnLib);
00105         state = (ret == RES_OK) ? MNG_RADIO_ON : MNG_ERROR_RESET;
00106         
00107     }
00108     //switch off
00109     if (state != MNG_RADIO_OFF && !moduleOn){
00110         INFO("%s: Switching OFF radio \r\n", __FUNCTION__);
00111         if (state == MNG_DATA_UP)
00112             //disable data
00113             cnDataEnable(false);
00114         else if (state == MNG_IDLE){
00115             //switching off
00116             cnDataReset();
00117             cnRegReset();
00118             radioSwitchOff(cnLib);
00119             state = MNG_RADIO_OFF;
00120         }
00121     }
00122     //sim initialization
00123     if (state == MNG_RADIO_ON ){
00124         ret = simInit(cnLib, simPin);
00125         state = (ret == RES_OK) ? MNG_IDLE : MNG_ERROR_RESET;
00126         if (state == MNG_IDLE && mngHandler)
00127             mngHandler(MNG_EV_IDLE, paramDataHandler);
00128     }
00129     //cycle the registration and data service
00130     if (state == MNG_IDLE ||  state == MNG_DATA_UP){
00131         RegStatus regStatus;
00132         int res;
00133         DataConnStatus dataStatus;
00134         //Tick the registration service
00135         res = cnRegLoop(cnLib, &regStatus);        
00136         if (res != RES_OK && ++respError > MEX_RESP_ERROR)
00137             state = MNG_ERROR_RESET;            
00138         //Tick Data service
00139         cnDataLoop(cnLib, regStatus, &dataStatus);
00140         //manage data status
00141         if (dataStatus == DATA_IS_CONNECTED){
00142             state = MNG_DATA_UP;            
00143             if (mngHandler) mngHandler(MNG_EV_DATA_UP, paramDataHandler);
00144         } else if (dataStatus == DATA_IS_DISCONNECTED){
00145             state = MNG_IDLE;
00146             if (mngHandler) mngHandler(MNG_EV_DATA_DOWN, paramDataHandler);
00147         }
00148     }
00149     //error management
00150     if (state == MNG_ERROR_RESET){
00151         //block state machine when errors reach a max value counter
00152         if (++errorCounter > MAX_ERROR_RETRIES)
00153             state = MNG_ERROR_STUCK;
00154         else{
00155             //otherwise start reset procedure
00156             ERROR("%s: State machine is in Error state, doing Reset.\r\n", __FUNCTION__);
00157             respError=0;
00158             cnDataReset();
00159             cnRegReset();
00160             radioSwitchOff(cnLib);
00161             state = MNG_RADIO_OFF;
00162         }
00163     }
00164     //when the state is stuck stay here forever
00165     if (state == MNG_ERROR_STUCK){
00166         ERROR("%s: State machine is in Blocked state, please change setting.\r\n", __FUNCTION__);
00167         return false;
00168     }
00169     //dump info
00170     if (getUtilDebugLevel() > 1 && oldState != state){
00171         INFO("CNManager Dump\r\n");
00172         const char* txtState[] = { "Not Initiated", "Radio is Off", "Radio is On", \
00173         "Idle", "Connected", "Reset Error", "Blocked Error"};
00174         if (state < sizeof(txtState)/sizeof(*txtState))
00175             INFO("  Internal State: %s\r\n", txtState[state]);
00176     }
00177     return true;
00178 }
00179 
00180 /** Switch On Radio
00181    \param lib pointer to library
00182  */
00183 CNResp radioSwitchOn(CNLib*& lib)
00184 {
00185     TRACE("%s enter \r\n", __FUNCTION__);
00186     lib =  new CNLib();
00187     if (lib == NULL){
00188         ERROR("%s: Error on allocating lib\r\n", __FUNCTION__);
00189         goto error;
00190     }
00191     lib->setDebug(getUtilDebugLevel());
00192     //power on the module and detect if alive
00193     if (!RESPOK(lib->powerOnModem())){
00194         ERROR("%s: Error on detecting the modem\r\n", __FUNCTION__);
00195         goto error;
00196     }
00197     //init generic modem
00198     if (!RESPOK(lib->initModem())){
00199         ERROR("%s: Error on init device\r\n", __FUNCTION__);
00200         goto error;
00201     }
00202     //handle unknown device
00203     if (lib->getDev()->dev == MDMParser::DEV_UNKNOWN){
00204         ERROR("%s: Device is unknown\r\n", __FUNCTION__);
00205         goto error;
00206     }
00207     return RES_OK;
00208 
00209 error:
00210     return RES_ERROR;
00211 
00212 }
00213 
00214 /** Switch off the radio
00215     \param lib pointer to CN library
00216  */
00217 CNResp radioSwitchOff(CNLib*& lib){
00218     TRACE("%s enter \r\n", __FUNCTION__);
00219     if (lib != NULL){
00220         lib->powerOff();
00221         delete lib;
00222     }
00223     return RES_OK;
00224 }
00225 
00226 /** Sim Pin initialization
00227      \param lib pointer to CN library
00228      \param simPin sim pin
00229  */
00230 CNResp simEnterPin(CNLib* lib, char* simPin){
00231     int res;
00232 
00233     if (simPin == NULL){
00234         ERROR("%s: Sim Pin is required but not provided\r\n", __FUNCTION__);
00235         return RES_ERROR_STUCK;
00236     }
00237     res = lib->simInit(simPin);
00238     if (RESPOK(res) )
00239         return RES_OK;
00240     if (lib->getDev()->sim == MDMParser::WRONG_PIN){
00241         ERROR("%s: Sim pin, %s ,provided is wrong\r\n", simPin);
00242         return RES_ERROR_STUCK;
00243         }
00244     return RES_ERROR;
00245 }
00246 
00247 /** Sim initialization
00248      \param lib pointer to CN library
00249      \param simPin sim pin
00250  */
00251 CNResp simInit(CNLib* lib, char* simPin)
00252 {
00253     CNResp res = RES_ERROR;
00254     int _simWaitCounter=0;
00255     TRACE("CNLib::%s enter\r\n", __FUNCTION__);
00256 
00257     do{
00258         if (RESPOK(lib->simInit(NULL)))
00259             break;
00260         wait_ms(10);
00261     } while(_simWaitCounter++ < SIM_WAIT_MAX_CYCLE);
00262     INFO("Sim status is %d \r\n", lib->getDev()->sim);
00263     //handle sim status
00264     switch (lib->getDev()->sim){
00265       case MDMParser::SIM_READY:
00266           INFO("%s: Sim has been initiated correctly\r\n", __FUNCTION__);
00267           res = RES_OK;
00268           break;
00269       case MDMParser::SIM_PIN:
00270           INFO("%s: Sim Pin is requested\r\n");
00271           res = simEnterPin(lib, simPin);
00272           break;
00273       case MDMParser::SIM_MISSING:
00274           ERROR("%s: Sim has not been inserted, HALT\r\n", __FUNCTION__);
00275           res = RES_ERROR;
00276           break;
00277       case MDMParser::SIM_PUK:
00278           ERROR("%s: Sim Puk is required, HALT\r\n", __FUNCTION__);
00279           res = RES_ERROR_STUCK;
00280           break;
00281       case MDMParser::SIM_UNKNOWN:
00282           ERROR("%s: Sim Unknown state\r\n", __FUNCTION__);
00283           res = RES_ERROR_STUCK;
00284           break;
00285       case MDMParser::WRONG_PIN:
00286           ERROR("%s: Wrong sim pin provided, HALT\r\n", __FUNCTION__);
00287           res = RES_ERROR_STUCK;
00288           break;
00289     }
00290     //sim has been successfully initialized
00291     if (res == RES_OK){
00292         lib->getSimInfo();
00293     }
00294     return res;
00295 }
00296 
00297 void getNetStatus(MDMParser::NetStatus* net){
00298     if (net && cnLib)
00299         memcpy(net, cnLib->getNet(), sizeof(MDMParser::NetStatus));
00300 }
00301 void getDevStatus(MDMParser::DevStatus* dev){
00302     if (dev && cnLib)
00303         memcpy(dev, cnLib->getDev(), sizeof(MDMParser::DevStatus));
00304 }