?? gsm_me_ta.cc
字號:
// *************************************************************************// * GSM TA/ME library// *// * File: gsm_me_ta.cc// *// * Purpose: Mobile Equipment/Terminal Adapter functions// * (ETSI GSM 07.07)// *// * Author: Peter Hofmann (software@pxh.de)// *// * Created: 10.5.1999// *************************************************************************#ifdef HAVE_CONFIG_H#include <gsm_config.h>#endif#include <gsmlib/gsm_nls.h>#include <gsmlib/gsm_me_ta.h>#include <gsmlib/gsm_parser.h>#include <gsmlib/gsm_sysdep.h>using namespace std;using namespace gsmlib;// Capabilities membersCapabilities::Capabilities() : _hasSMSSCAprefix(true), _cpmsParamCount(-1), // initialize to -1, must be set later by // setSMSStore() function _omitsColon(true), // FIXME _veryShortCOPSanswer(false), // Falcom A2-1 _wrongSMSStatusCode(false), // Motorola Timeport 260 _CDSmeansCDSI(false), // Nokia Cellular Card Phone RPE-1 GSM900 and // Nokia Card Phone RPM-1 GSM900/1800 _sendAck(false) // send ack for directly routed SMS{}// MeTa membersvoid MeTa::init() throw(GsmException){ // switch on extended error codes // caution: may be ignored by some TAs, so allow it to fail _at->chat("+CMEE=1", "", true, true); // select SMS pdu mode _at->chat("+CMGF=0"); // now fill in capability object MEInfo info = getMEInfo(); // Ericsson model 6050102 if ((info._manufacturer == "ERICSSON" && (info._model == "1100801" || info._model == "1140801")) || getenv("GSMLIB_SH888_FIX") != NULL) { // the Ericsson leaves out the service centre address _capabilities._hasSMSSCAprefix = false; } // handle Falcom strangeness if ((info._manufacturer == "Funkanlagen Leipoldt OHG" && info._revision == "01.95.F2") || getenv("GSMLIB_FALCOM_A2_1_FIX") != NULL) { _capabilities._veryShortCOPSanswer = true; } // handle Motorola SMS store bug - wrong status code if ((info._manufacturer == "Motorola" && info._model == "L Series")) { _capabilities._wrongSMSStatusCode = true; } // handle Nokia Cellular Card Phone RPE-1 GSM900 and // Nokia Card Phone RPM-1 GSM900/1800 bug - CDS means CDSI if ((info._manufacturer == "Nokia Mobile Phones" && (info._model == "Nokia Cellular Card Phone RPE-1 GSM900" || info._model == "Nokia Card Phone RPM-1 GSM900/1800"))) { _capabilities._CDSmeansCDSI = true; } // find out whether we are supposed to send an acknowledgment Parser p(_at->chat("+CSMS?", "+CSMS:")); _capabilities._sendAck = p.parseInt() >= 1; // set GSM default character set try { setCharSet("GSM"); } catch (GsmException) { // ignore errors, some devices don't support this } // set default event handler // necessary to handle at least RING indications that might // otherwise confuse gsmlib _at->setEventHandler(&_defaultEventHandler);}MeTa::MeTa(Ref<Port> port) throw(GsmException) : _port(port){ // initialize AT handling _at = new GsmAt(*this); init();}// MeTa::MeTa(Ref<GsmAt> at) throw(GsmException) :// _at(at)// {// init();// }void MeTa::setPIN(string pin) throw(GsmException){ _at->chat("+CPIN=\"" + pin + "\"");}string MeTa::getPINStatus() throw(GsmException){ Parser p(_at->chat("+CPIN?", "+CPIN:")); return p.parseString();}void MeTa::setPhonebook(string phonebookName) throw(GsmException){ if (phonebookName != _lastPhonebookName) { _at->chat("+CPBS=\"" + phonebookName + "\""); _lastPhonebookName = phonebookName; }}string MeTa::setSMSStore(string smsStore, int storeTypes, bool needResultCode) throw(GsmException){ if (_capabilities._cpmsParamCount == -1) { // count the number of parameters for the CPMS AT sequences _capabilities._cpmsParamCount = 1; Parser p(_at->chat("+CPMS=?", "+CPMS:")); p.parseStringList(); while (p.parseComma(true)) { ++_capabilities._cpmsParamCount; p.parseStringList(); } } // optimatization: only set current SMS store if different from last call // or the result code is needed if (needResultCode || _lastSMSStoreName != smsStore) { _lastSMSStoreName = smsStore; // build chat string string chatString = "+CPMS=\"" + smsStore + "\""; for (int i = 1; i < min(_capabilities._cpmsParamCount, storeTypes); ++i) chatString += ",\"" + smsStore + "\""; return _at->chat(chatString, "+CPMS:"); } return "";}void MeTa::getSMSStore(string &readDeleteStore, string &writeSendStore, string &receiveStore) throw(GsmException){ Parser p(_at->chat("+CPMS?", "+CPMS:")); writeSendStore = receiveStore = ""; readDeleteStore = p.parseString(); p.parseComma(); p.parseInt(); p.parseComma(); p.parseInt(); if (p.parseComma(true)) { writeSendStore = p.parseString(); p.parseComma(); p.parseInt(); p.parseComma(); p.parseInt(); if (p.parseComma(true)) { receiveStore = p.parseString(); } }}void MeTa::waitEvent(GsmTime timeout) throw(GsmException){ if (_at->wait(timeout)) _at->chat(); // send AT, wait for OK, handle events}// aux function for MeTa::getMEInfo()static string stringVectorToString(const vector<string>& v, char separator = '\n'){ if (v.empty()) return ""; // concatenate string in vector as rows string result; for (vector<string>::const_iterator i = v.begin();;) { string s = *i; // remove leading and trailing "s if (s.length() > 0 && s[0] == '"') s.erase(s.begin()); if (s.length() > 0 && s[s.length() - 1] == '"') s.erase(s.end() - 1); result += s; // don't add end line to last if ( ++i == v.end() || !separator) break; result += separator; } return result;}MEInfo MeTa::getMEInfo() throw(GsmException){ MEInfo result; // some TAs just return OK and no info line // leave the info empty in this case // some TAs return multirows with info like address, firmware version result._manufacturer = stringVectorToString(_at->chatv("+CGMI", "+CGMI:", false)); result._model = stringVectorToString(_at->chatv("+CGMM", "+CGMM:", false)); result._revision = stringVectorToString(_at->chatv("+CGMR", "+CGMR:", false)); result._serialNumber = stringVectorToString(_at->chatv("+CGSN", "+CGSN:", false),0); return result;}vector<string> MeTa::getSupportedCharSets() throw(GsmException){ Parser p(_at->chat("+CSCS=?", "+CSCS:")); return p.parseStringList();} string MeTa::getCurrentCharSet() throw(GsmException){ if (_lastCharSet == "") { Parser p(_at->chat("+CSCS?", "+CSCS:")); _lastCharSet = p.parseString(); } return _lastCharSet;}void MeTa::setCharSet(string charSetName) throw(GsmException){ _at->chat("+CSCS=\"" + charSetName + "\""); _lastCharSet = "";}string MeTa::getExtendedErrorReport() throw(GsmException){ return _at->chat("+CEER", "+CEER:");}void MeTa::dial(string number) throw(GsmException){ _at->chat("D" + number + ";");}void MeTa::answer() throw(GsmException){ _at->chat("A");}void MeTa::hangup() throw(GsmException){ _at->chat("H");}vector<OPInfo> MeTa::getAvailableOPInfo() throw(GsmException){ vector<OPInfo> result; vector<string> responses = _at->chatv("+COPS=?", "+COPS:"); // special treatment for Falcom A2-1, answer looks like // responses.push_back("(1,29341),(3,29340)"); if (_capabilities._veryShortCOPSanswer) { if (responses.size() == 1) { Parser p(responses[0]); while (p.parseChar('(', true)) { OPInfo opi; opi._status = (OPStatus)p.parseInt(); p.parseComma(); opi._numericName = p.parseInt(); p.parseChar(')'); p.parseComma(true); result.push_back(opi); } } } else // some formats I have encountered... //responses.push_back("2,,,31017,,(0,1),(2)"); //responses.push_back("(3,\"UK CELLNET\",\"CLNET\",\"23410\")," // "(3,\"ONE2 ONE\",\"ONE2ONE\",\"23430\")," // "(3,\"ORANGE\",\"ORANGE\",\"23433\")"); //responses.push_back("(2,\"D1-TELEKOM\",,26201)," // "(3,\"D2 PRIVAT\",,26202),,(0,1,3,4),(0,2)"); // GSM modems might return // 1. quadruplets of info enclosed in brackets separated by comma // 2. several lines of quadruplets of info enclosed in brackets // 3. several lines of quadruplets without brackets and additional // info at EOL (e.g. Nokia 8290) for (vector<string>::iterator i = responses.begin(); i != responses.end(); ++i) { bool expectClosingBracket = false; Parser p(*i); while (1) { OPInfo opi; expectClosingBracket = p.parseChar('(', true); int status = p.parseInt(true); opi._status = (status == NOT_SET ? UnknownOPStatus : (OPStatus)status); p.parseComma(); opi._longName = p.parseString(true); p.parseComma(); opi._shortName = p.parseString(true); p.parseComma(); try { opi._numericName = p.parseInt(true); } catch (GsmException &e) { if (e.getErrorClass() == ParserError) { // the Ericsson GM12 GSM modem returns the numeric ID as string string s = p.parseString(); opi._numericName = checkNumber(s); } else throw e; } if (expectClosingBracket) p.parseChar(')'); result.push_back(opi); if (! p.parseComma(true)) break; // two commas ",," mean the list is finished if (p.parseComma(true)) break; } // without brackets, the ME/TA must use format 3. if (! expectClosingBracket) break; } return result;}OPInfo MeTa::getCurrentOPInfo() throw(GsmException){ OPInfo result; // 1. This exception thing is necessary because not all ME/TA combinations // might support all the formats and then return "ERROR". // 2. Additionally some modems return "ERROR" for all "COPS=3,n" command // and report only one format with the "COPS?" command (e.g. Nokia 8290). // get long format try { try { _at->chat("+COPS=3,0"); } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } Parser p(_at->chat("+COPS?", "+COPS:")); result._mode = (OPModes)p.parseInt(); // some phones (e.g. Nokia Card Phone 2.0) just return "+COPS: 0" // if no network connection if (p.parseComma(true)) { if (p.parseInt() == 0) { p.parseComma(); result._longName = p.parseString(); } } } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } // get short format try { try { _at->chat("+COPS=3,1"); } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } Parser p(_at->chat("+COPS?", "+COPS:")); result._mode = (OPModes)p.parseInt(); // some phones (e.g. Nokia Card Phone 2.0) just return "+COPS: 0" // if no network connection if (p.parseComma(true)) { if (p.parseInt() == 1) { p.parseComma(); result._shortName = p.parseString(); } } } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } // get numeric format try { try { _at->chat("+COPS=3,2"); } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } Parser p(_at->chat("+COPS?", "+COPS:")); result._mode = (OPModes)p.parseInt(); // some phones (e.g. Nokia Card Phone 2.0) just return "+COPS: 0" // if no network connection if (p.parseComma(true)) { if (p.parseInt() == 2) { p.parseComma(); try { result._numericName = p.parseInt(); } catch (GsmException &e) { if (e.getErrorClass() == ParserError) { // the Ericsson GM12 GSM modem returns the numeric ID as string string s = p.parseString(); result._numericName = checkNumber(s); } else throw e; } } } } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } return result;}void MeTa::setCurrentOPInfo(OPModes mode, string longName, string shortName, int numericName) throw(GsmException){ bool done = false; if (longName != "") { try { _at->chat("+COPS=" + intToStr((int)mode) + ",0,\"" + longName + "\""); done = true; } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } } if (shortName != "" && ! done) { try { _at->chat("+COPS=" + intToStr((int)mode) + ",1,\"" + shortName + "\""); done = true; } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } } if (numericName != NOT_SET && ! done) { try { _at->chat("+COPS=" + intToStr((int)mode) + ",2," + intToStr(numericName)); done = true; } catch (GsmException &e) { if (e.getErrorClass() != ChatError) throw; } } if (! done) throw GsmException(_("unable to set operator"), OtherError);}vector<string> MeTa::getFacilityLockCapabilities() throw(GsmException){ string locks = _at->chat("+CLCK=?", "+CLCK:"); // some TA don't add '(' and ')' (Option FirstFone) if (locks.length() && locks[0] != '(') { locks.insert(locks.begin(),'('); locks += ')'; } Parser p(locks); return p.parseStringList();}bool MeTa::getFacilityLockStatus(string facility, FacilityClass cl) throw(GsmException){ // some TA return always multiline response with all classes // (Option FirstFone) // !!! errors handling is correct (responses.empty() true) ? vector<string> responses = _at->chatv("+CLCK=\"" + facility + "\",2,," + intToStr((int)cl),"+CLCK:",true); for (vector<string>::iterator i = responses.begin(); i != responses.end(); ++i) { Parser p(*i); int enabled = p.parseInt(); // if the first time and there is no comma this // return direct state of classes // else return all classes if (i == responses.begin()) { if (!p.parseComma(true)) return enabled == 1; } else p.parseComma(); if ( p.parseInt() == (int)cl ) return enabled == 1; } return false;// Parser p(_at->chat("+CLCK=\"" + facility + "\",2,," + intToStr((int)cl),// "+CLCK:"));// return p.parseInt() == 1;}void MeTa::lockFacility(string facility, FacilityClass cl, string passwd)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -