/*
* 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_ */