/* * Copyright (C) 2015 by Multi-Tech Systems * * This file is part of libmts-io. * * libmts-io is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * libmts-io is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libmts-io. If not, see . * */ /*! \file MTS_IO_CellularRadio.h \brief A brief description \date Nov 5, 2014 \author sgodinez A more elaborate description */ #ifndef MTS_IO_CELLULARRADIO_H_ #define MTS_IO_CELLULARRADIO_H_ #include #include #include #include #include #include #include #include namespace MTS { namespace IO { class CellularRadio : public ICellularRadio { public: const std::string& getName() const override; ~CellularRadio() override; bool initialize(uint32_t iTimeoutMillis = 5000) override; bool resetConnection(uint32_t iTimeoutMillis = 5000) override; void shutdown() override; CODE getFirmware(std::string& sFirmware) override; CODE getFirmwareBuild(std::string& sFirmwareBuild) override; CODE getVendorFirmware(std::string& sVendorFirmware) override; CODE getHardware(std::string& sHardware) override; CODE getManufacturer(std::string& sManufacturer) override; CODE getImei(std::string& sImei) override; CODE getMeid(std::string& sMeid) override; CODE getImsi(std::string& sImsi) override; CODE getSimStatus(std::string& sSimStatus) override; CODE getSimStatusSummary(Json::Value& jData) override; CODE getLac(std::string& sLac) override; CODE getMdn(std::string& sMdn) override; CODE getMsid(std::string& sMsid) override; CODE getType(std::string& sType) override; CODE getCarrier(std::string& sCarrier) override; CODE getTower(std::string& sTower) override; CODE getTime(std::string& sDate, std::string& sTime, std::string& sTimeZone) override; CODE getRoaming(bool& bRoaming) override; CODE getCellularMode(CELLULAR_MODES &networks) override; CODE getSelectedBandsRaw(std::string& sRawBands) override; CODE getSignalStrength(int32_t& iRssi) override; CODE getModemLocation(std::string& sLocation) override; CODE getRegistration(REGISTRATION& eRegistration) override; CODE convertRegistrationToString(REGISTRATION eRegistration, std::string& sRegistration) override; CODE convertCellModesToString(CELLULAR_MODES eCellModes, std::string& sCellModes) override; CODE unlockSimCard(const Json::Value& jArgs) override; CODE getSimCarrierCode(std::string& sCarrierCode) override; CODE getMipProfile(Json::Value& jMipProfile) override; CODE validateMsl(const Json::Value& jArgs) override; CODE setMsid(const Json::Value& jArgs) override; CODE setMipActiveProfile(const Json::Value& jArgs) override; CODE setMipNai(const Json::Value& jArgs) override; CODE setMipHomeIp(const Json::Value& jArgs) override; CODE setMipPrimaryHa(const Json::Value& jArgs) override; CODE setMipSecondaryHa(const Json::Value& jArgs) override; CODE setMipMnAaaSpi(const Json::Value& jArgs) override; CODE setMipMnHaSpi(const Json::Value& jArgs) override; CODE setMipRevTun(const Json::Value& jArgs) override; CODE setMipMnAaaSs(const Json::Value& jArgs) override; CODE setMipMnHaSs(const Json::Value& jArgs) override; CODE updateDc(const Json::Value& jArgs, UpdateCb& stepCb) override; CODE updatePrl(const Json::Value& jArgs, UpdateCb& stepCb) override; CODE updateFumo(const Json::Value& jArgs, UpdateCb& stepCb) override; CODE updateFumoLocal(int fd, UpdateCb& stepCb) override; CODE fumoLocalInject(int fd, UpdateCb& stepCb) override; CODE fumoLocalApply(UpdateCb& stepCb) override; CODE fumoLocalCleanup() override; CODE resetHfa(const Json::Value& jArgs, UpdateCb& stepCb) override; CODE activate(const Json::Value& jArgs, UpdateCb& stepCb) override; CODE startOmaDm(UpdateCb& stepCb) override; CODE setActiveFirmware(const Json::Value& jArgs) override; CODE getActiveFirmware(std::string& sFwId) override; CODE getEcho(bool& bEnabled) override; CODE setEcho(bool bEnabled = true) override; CODE getStaticInformation(Json::Value& jData) override; CODE sendBasicCommand(const std::string& sCmd, int32_t timeoutMillis = 100, const char& ESC = ICellularRadio::CR) override; std::string sendCommand(const std::string& sCmd, const std::vector& vBail = DEFAULT_BAIL_STRINGS, int32_t timeoutMillis = 100, const char& ESC = ICellularRadio::CR) override; std::string sendCommand(const std::string& sCmd, IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis = 100, const char& ESC = ICellularRadio::CR) override; //! Wait for response from the radio without sending any data to it virtual std::string waitResponse(const std::vector& vBail = DEFAULT_BAIL_STRINGS, int32_t timeoutMillis = 100) override; //! Wait for response from the radio without sending any data to it virtual std::string waitResponse(IsNeedMoreData& isNeedMoreData, int32_t timeoutMillis = 100) override; CODE setUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION mode) override; CODE getUeModeOfOperation(ICellularRadio::UE_MODES_OF_OPERATION& mode) override; CODE getSimMccMnc(std::string& sMccMnc) override; CODE getSimMccMnc(std::string& sMcc, std::string& sMnc) override; CODE disableVoiceSupport() override; CODE getVoiceSupport(Json::Value& jData) override; CODE getVoiceSupport(bool& bVoiceEnabled, bool& bSmsOnly) override; CODE getPdpContexts(Json::Value& jData) override; CODE setPdpContext(const std::string& sId, const Json::Value& jConfig) override; CODE getDiagnostics(std::string& sReport) override; protected: CellularRadio(const std::string& sName, const std::string& sRadioPort); virtual bool getCarrierFromFirmware(const std::string& sFirmware, std::string& sCarrier); virtual bool getHardwareVersionFromFirmware(const std::string& sFirmware, std::string& sHardware); virtual void getCommonNetworkStats(Json::Value& jData); /** * @brief getIsSimInserted - returns if the SIM card is inserted / installed or not. * * @param bData - an object to be filled with the SIM card insertion status. * `true` when SIM card is inserted / installed / present, * `false` otherwise. * @return CODE::SUCCESS when SIM insertion status is fetched successfully, * CODE::NOT_APPLICABLE when the modem doesn't support this feature, * CODE::ERROR otherwise (when modem is inaccessible or in other cases). */ virtual CODE getIsSimInserted(bool& bData) = 0; /** * @brief getSimLockStatus - return the SIM lock status as defined by AT+CPIN? command. * Returns "READY", "SIM PIN", "SIM PUK" or other SIM status. * * @param sData - an object to be filled with the SIM lock status * @return CODE::SUCCESS when SIM status is fetched successfully, * CODE::NOT_APPLICABLE when the modem doesn't support this feature, * CODE::ERROR otherwise (SIM card removed, modem is inaccessible, etc). */ virtual CODE getSimLockStatus(std::string& sData); /** * @brief getSimLockAttempts - get the number of SIM unlock attempts left. * * @param iAttemptsPin - the number of attempts left to enter a PIN code. * @param iAttemptsPuk - the number of attempts left to enter a PUK code. * @return CODE::SUCCESS when both numbers are fetched successfully, * CODE::NOT_APPLICABLE when the modem doesn't support this feature, * CODE::ERROR otherwise (SIM card removed, modem is inaccessible, etc). */ virtual CODE getSimLockAttempts(int& iAttemptsPin, int& iAttemptsPuk) = 0; //! Get carrier code based on the SIM card ID (ICCID) virtual CODE getSimCarrierCode(const std::string& sIccid, std::string& sCarrierCode); //! Get carrier code based on the SIM MCC/MNC virtual CODE getSimCarrierCode(const std::string& sMcc, const std::string& sMnc, std::string& sCarrierCode); /** * @brief simAccessReadBinary - Read a string of bytes from the SIM Elementary File. * Please see ETSI TS 102 221 v16.4.0 and ETSI TS 127 007 v16.6.0 for the details. * * @param iFiledId - identifier of the Elementary File to read from. * @param iP1 - offset (ETSI TS 102 221 v16.4.0, Section 11.1.3.2). * @param iP2 - offset low (ETSI TS 102 221 v16.4.0, Section 11.1.3.2). * @param iLe - number of bytes to be read (ETSI TS 102 221 v16.4.0, Section 11.1.3.2). * @param sResult - container for the hex-encoded result string, * example for EFpnn: "004F474F21FFFFFFFFFFFFFFFFFFFFFFFF". * @return CODE::SUCCESS when the read is completed successfully, * CODE::NOT_APPLICABLE when the modem doesn't support this feature, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR" (SIM card removed, SIM card locked etc), * CODE::FAILURE otherwise (unexpected response, no data in SIM etc). */ virtual CODE simAccessReadBinary(uint16_t iFiledId, uint8_t iP1, uint8_t iP2, uint8_t iLe, std::string& sResult); /** * @brief getSimMncLength - Read the length of the MNC from SIM EFad. * Please see ETSI TS 131 102 V16.4.0, Section 4.2.18 for the details. * * @param iLength - container for the number of digits in SIM MNC. * @return CODE::SUCCESS when the read is completed successfully, * CODE::NOT_APPLICABLE when the modem doesn't support this feature, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR" (SIM card removed, SIM card locked etc), * CODE::FAILURE otherwise (unexpected response, no data in SIM etc). */ virtual CODE getSimMncLength(uint8_t& iLength); /** * @brief getCarrierFromSimMccMnc - get a carrier name based on the MCC/MNC values. * * @param sCarrier - a string to be filled with carrier based on the MCC/MNC values. * * @return CODE::SUCCESS when the read is completed successfully, * CODE::NOT_APPLICABLE when the modem doesn't support this feature, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR" (SIM card removed, SIM card locked etc), * CODE::FAILURE otherwise (unexpected response, no data in SIM etc). */ virtual CODE getCarrierFromSimMccMnc(std::string& sCarrier); /** * @brief getCarrierFromSimSpn - get a carrier name from SIM EFspn. * * @param sCarrier - a string to be filled with carrier obtained from SIM EFspn. * * @return CODE::SUCCESS when the read is completed successfully, * CODE::NOT_APPLICABLE when the modem doesn't support this feature, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR" (SIM card removed, SIM card locked etc), * CODE::FAILURE otherwise (unexpected response, no data in SIM etc). */ virtual CODE getCarrierFromSimSpn(std::string& sCarrier); void initMipProfile(Json::Value& jData); bool splitAndAssign(const std::string& sLine, const std::string& sKey, Json::Value& jParent, const std::string& sJsonKey, Json::ValueType eType = Json::ValueType::stringValue); virtual std::string queryLteLac(); virtual std::string queryCGREGstring(); virtual void setCGREG(std::string value); virtual const std::vector getRegistrationCommands() = 0; REGISTRATION parseRegResponse(std::string sResult); CODE getRegistration(REGISTRATION& eRegistration, const std::string& sType); virtual CODE sendData(const char* pData, size_t nBytes); virtual CODE sendBasicQuery(const std::string& sCmd, const std::string& sLabel, std::string& sResult, int32_t timeoutMillis = 100, const char& ESC = ICellularRadio::CR); virtual CODE isCommandSupported(const std::string& sCmd, bool& bIsSupported); /** * @brief getDiagCommands - returns the list of Cellular Diagnostics commands for this radio. * * @param bIsSimReady - set to "true" if the SIM card is inserted and NOT locked by PIN or PUK. * * @return the list of AT commands (strings). */ virtual const std::vector& getDiagCommands(bool bIsSimReady = true) = 0; struct PdpContextInfo { std::string sId; std::string sIpMode; std::string sApn; std::string sAuthType; std::string sUsername; std::string sPassword; }; virtual std::vector getSupportedPdpContextAuthTypes() const = 0; static CODE convertPdpContextAuthTypeToString(PDP_CONTEXT_AUTH_TYPE eAuthType, std::string& sAuthType); static CODE convertStringToPdpContextAuthType(const std::string& sAuthType, PDP_CONTEXT_AUTH_TYPE& eAuthType); /** * @brief checks if PDP context authentication is supported by the modem. * * @param isSupported - sets to "true" if PDP context authentication is supported, "false" otherwise. * * @return CODE::SUCCESS when the response from the radio is received * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::FAILURE otherwise. */ virtual CODE isPdpContextAuthSupported(bool& isSupported) = 0; /** * @brief Get the list of PDP contexts with the base info about them from the radio. * * @param jData - a JSON object to be filled with data. * { * "context_number : STRING": { * "apn" : "apn_value: STRING", * "ipMode" : "ip_mode_value: STRING", * } * } * * @return CODE::SUCCESS when fetched successfully, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR", * CODE::FAILURE otherwise (unexpected response). */ virtual CODE getPdpContextsBase(Json::Value& jData); /** * @brief fills jData with the information about PDP context authentication * * @param jData - a JSON object that is pre-filled with the list of PDP contexts: * { * "context_number : STRING": { * "apn" : "apn_value: STRING", * "ipMode" : "ip_mode_value: STRING", * } * } * On success the method will complement jData with the PDP context authentication fields: * { * "context_number : STRING": { * "apn" : "apn_value: STRING", * "authType" : "auth_type_value: STRING", * "ipMode" : "ip_mode_value: STRING", * "password" : "password_value (optional): STRING", * "username" : "username_value (optional): STRING" * } * } * * @return CODE::SUCCESS when fetched successfully, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR", * CODE::FAILURE otherwise (unexpected response). */ virtual CODE fillPdpContextAuthFields(Json::Value& jData) = 0; /** * @brief merges the current configuration of the PDP context with the one requested by user * * @param sId - ID of the PDP context to change. * @param jCurrentContext - a JSON object filled with current configuration data * { * "apn" : "apn_value (optional): STRING", * "authType" : "auth_type_value: STRING", * "ipMode" : "ip_mode_value: STRING", * "password" : "password_value (optional): STRING", * "username" : "username_value (optional): STRING" * } * @param jChanges - a JSON object filled with new configuration data * { * "apn" : "apn_value (optional): STRING", * "authType" : "auth_type_value (optional): STRING", * "ipMode" : "ip_mode_value (optional): STRING", * "password" : "password_value (optional): STRING", * "username" : "username_value (optional): STRING" * } * @param jResult - a JSON object to be filled with merged data * { * "apn" : "apn_value (optional): STRING", * "authType" : "auth_type_value (optional): STRING", * "id" : "ctx_id (optional): STRING", * "ipMode" : "ip_mode_value (optional): STRING", * "password" : "password_value (optional): STRING", * "username" : "username_value (optional): STRING" * } * @return CODE::SUCCESS. */ virtual CODE mergePdpContexts(const std::string& sId, const Json::Value& jCurrentContext, const Json::Value& jChanges, Json::Value& jResult); /** * @brief fills a PdpContextInfo instance with the data from JSON * @param jData - a JSON object that contains: * { * "apn" : "apn_value: STRING", * "authType" : "auth_type_value: STRING", * "id" : "ctx_id: STRING", * "ipMode" : "ip_mode_value: STRING", * "password" : "password_value: STRING", * "username" : "username_value: STRING" * } * @param pdpContextResult - PdpContextInfo object to be filled with parameters. * @return CODE::SUCCESS if validated successfully, * CODE::INVALID_ARGS if validation failed. */ virtual CODE initPdpContextInfo(const Json::Value& jConfig, PdpContextInfo& pdpContextResult); /** * @brief checks if PDP context authentication should be configured * @param jData - a JSON object that contains: * { * "apn" : "apn_value (optional): STRING", * "authType" : "auth_type_value: STRING", * "ipMode" : "ip_mode_value: STRING", * "password" : "password_value (optional): STRING", * "username" : "username_value (optional): STRING" * } * @param bIsAuthEditRequired - sets to "false" if there are no authType, username, and password fields in the json, otherwise sets to "true". * @return CODE::SUCCESS. */ static CODE isPdpContextAuthEditRequired(const Json::Value& jConfig, bool& bIsAuthEditRequired); /** * @brief Sets the base PDP context parameters: IP Mode and APN * @param pdpContext - The new PDP context configuration * @return CODE::SUCCESS when set successfully, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR", * CODE::FAILURE otherwise (unexpected response). */ virtual CODE setPdpContextBase(const PdpContextInfo& pdpContext); /** * @brief Sets the Cellular Authentication parameters for this PDP context: Authentication Type, Username and Password. * NOTE: Some implementations (Quectel) override the current IP Mode and APN in addition to the authentication fields. * @param pdpContext - The new PDP context configuration * @return CODE::SUCCESS when set successfully, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR", * CODE::FAILURE otherwise (unexpected response). */ virtual CODE setPdpContextAuth(const PdpContextInfo& pdpContext) = 0; /** * @brief Delete the PDP context by its ID. * @param sId - PDP context ID * @return CODE::SUCCESS when delete successfully, * CODE::NO_RESPONSE when the modem doesn't respond, * CODE::ERROR when the radio returns "ERROR", * CODE::FAILURE otherwise (unexpected response). */ virtual CODE deletePdpContext(const std::string& sId); class RadioBandMap : public MTS::NonCopyable { public: RadioBandMap() { m_sChannel = ICellularRadio::VALUE_UNKNOWN; m_iChannel = 0; m_sRadioType = ICellularRadio::VALUE_UNKNOWN; } RadioBandMap(const std::string &channel, const std::string &radioType) : m_sChannel(channel), m_sRadioType(radioType) { m_iChannel = strtol(m_sChannel.c_str(), NULL, 10); } virtual ~RadioBandMap() {} const char *getRadioBandName(); const char *getRadioBandName(const std::string &channel, const std::string &radioType); private: const char *getLTEBand(const int channel); const char *getCDMABand(const int channel); const char *getGSMBand(const int channel); std::string m_sChannel; int m_iChannel; std::string m_sRadioType; }; static CODE getFileSize(int fd, size_t& nBytes); static CODE sizeToChunks(const size_t nBytes, const size_t chunkSize, size_t& nChunks); static CODE readChunk(int fd, char* pChunk, size_t dChunkSize, size_t& nReadBytes); private: std::string m_sName; std::string m_sRadioPort; std::string m_sFirmware; std::string m_sCarrier; MTS::AutoPtr m_apIo; bool m_bEchoEnabled; bool m_bEnableEchoOnClose; }; } } #endif /* MTS_IO_CELLULARRADIO_H_ */