?? gsm_me_ta.c
字號(hào):
// *************************************************************************
// * 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>
#define min(a,b) (((a) < (b)) ? (a) : (b))
using namespace std;
using namespace gsmlib;
// Capabilities members
Capabilities::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
{
}
// MeTa members
void 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;
}
// 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::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::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 + ";");
}
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;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -