1
// *************************************************************************
4
// * File: gsm_me_ta.cc
6
// * Purpose: Mobile Equipment/Terminal Adapter functions
9
// * Author: Peter Hofmann (software@pxh.de)
11
// * Created: 10.5.1999
12
// *************************************************************************
15
#include <gsm_config.h>
17
#include <gsmlib/gsm_nls.h>
18
#include <gsmlib/gsm_me_ta.h>
19
#include <gsmlib/gsm_parser.h>
20
#include <gsmlib/gsm_sysdep.h>
24
using namespace gsmlib;
26
// Capabilities members
28
Capabilities::Capabilities() :
29
_hasSMSSCAprefix(true),
30
_cpmsParamCount(-1), // initialize to -1, must be set later by
31
// setSMSStore() function
32
_omitsColon(true), // FIXME
33
_veryShortCOPSanswer(false), // Falcom A2-1
34
_wrongSMSStatusCode(false), // Motorola Timeport 260
35
_CDSmeansCDSI(false), // Nokia Cellular Card Phone RPE-1 GSM900 and
36
// Nokia Card Phone RPM-1 GSM900/1800
37
_sendAck(false) // send ack for directly routed SMS
43
void MeTa::init() throw(GsmException)
45
// switch on extended error codes
46
// caution: may be ignored by some TAs, so allow it to fail
47
_at->chat("+CMEE=1", "", true, true);
49
// select SMS pdu mode
52
// now fill in capability object
53
MEInfo info = getMEInfo();
55
// Ericsson model 6050102
56
if ((info._manufacturer == "ERICSSON" &&
57
(info._model == "1100801" ||
58
info._model == "1140801")) ||
59
getenv("GSMLIB_SH888_FIX") != NULL)
61
// the Ericsson leaves out the service centre address
62
_capabilities._hasSMSSCAprefix = false;
65
// handle Falcom strangeness
66
if ((info._manufacturer == "Funkanlagen Leipoldt OHG" &&
67
info._revision == "01.95.F2") ||
68
getenv("GSMLIB_FALCOM_A2_1_FIX") != NULL)
70
_capabilities._veryShortCOPSanswer = true;
73
// handle Motorola SMS store bug - wrong status code
74
if ((info._manufacturer == "Motorola" &&
75
info._model == "L Series"))
77
_capabilities._wrongSMSStatusCode = true;
80
// handle Nokia Cellular Card Phone RPE-1 GSM900 and
81
// Nokia Card Phone RPM-1 GSM900/1800 bug - CDS means CDSI
82
if ((info._manufacturer == "Nokia Mobile Phones" &&
83
(info._model == "Nokia Cellular Card Phone RPE-1 GSM900" ||
84
info._model == "Nokia Card Phone RPM-1 GSM900/1800")))
86
_capabilities._CDSmeansCDSI = true;
89
// find out whether we are supposed to send an acknowledgment
90
Parser p(_at->chat("+CSMS?", "+CSMS:"));
92
_capabilities._sendAck = p.parseInt() >= 1;
94
catch (GsmException &e)
96
if (e.getErrorClass() == ParserError) {
97
_capabilities._sendAck = 0;
103
// set GSM default character set
110
// ignore errors, some devices don't support this
113
// set default event handler
114
// necessary to handle at least RING indications that might
115
// otherwise confuse gsmlib
116
_at->setEventHandler(&_defaultEventHandler);
119
MeTa::MeTa(Ref<Port> port) throw(GsmException) : _port(port)
121
// initialize AT handling
122
_at = new GsmAt(*this);
127
// MeTa::MeTa(Ref<GsmAt> at) throw(GsmException) :
133
void MeTa::setPIN(std::string pin) throw(GsmException)
135
_at->chat("+CPIN=\"" + pin + "\"");
138
std::string MeTa::getPINStatus() throw(GsmException)
140
Parser p(_at->chat("+CPIN?", "+CPIN:"));
141
return p.parseString();
144
void MeTa::setPhonebook(std::string phonebookName) throw(GsmException)
146
if (phonebookName != _lastPhonebookName)
148
_at->chat("+CPBS=\"" + phonebookName + "\"");
149
_lastPhonebookName = phonebookName;
153
std::string MeTa::setSMSStore(std::string smsStore, int storeTypes, bool needResultCode)
156
if (_capabilities._cpmsParamCount == -1)
158
// count the number of parameters for the CPMS AT sequences
159
_capabilities._cpmsParamCount = 1;
160
Parser p(_at->chat("+CPMS=?", "+CPMS:"));
162
while (p.parseComma(true))
164
++_capabilities._cpmsParamCount;
169
// optimatization: only set current SMS store if different from last call
170
// or the result code is needed
171
if (needResultCode || _lastSMSStoreName != smsStore)
173
_lastSMSStoreName = smsStore;
176
std::string chatString = "+CPMS=\"" + smsStore + "\"";
177
for (int i = 1; i < std::min(_capabilities._cpmsParamCount, storeTypes); ++i)
178
chatString += ",\"" + smsStore + "\"";
180
return _at->chat(chatString, "+CPMS:");
185
void MeTa::getSMSStore(std::string &readDeleteStore,
186
std::string &writeSendStore,
187
std::string &receiveStore) throw(GsmException)
189
Parser p(_at->chat("+CPMS?", "+CPMS:"));
190
writeSendStore = receiveStore = "";
191
readDeleteStore = p.parseString();
196
if (p.parseComma(true))
198
writeSendStore = p.parseString();
203
if (p.parseComma(true))
205
receiveStore = p.parseString();
210
void MeTa::waitEvent(GsmTime timeout) throw(GsmException)
212
if (_at->wait(timeout))
213
_at->chat(); // send AT, wait for OK, handle events
216
// aux function for MeTa::getMEInfo()
218
static std::string stringVectorToString(const std::vector<std::string>& v,
219
char separator = '\n')
224
// concatenate string in vector as rows
226
for (std::vector<std::string>::const_iterator i = v.begin();;)
229
// remove leading and trailing "s
230
if (s.length() > 0 && s[0] == '"')
232
if (s.length() > 0 && s[s.length() - 1] == '"')
233
s.erase(s.end() - 1);
236
// don't add end line to last
237
if ( ++i == v.end() || !separator)
244
MEInfo MeTa::getMEInfo() throw(GsmException)
247
// some TAs just return OK and no info line
248
// leave the info empty in this case
249
// some TAs return multirows with info like address, firmware version
250
result._manufacturer =
251
stringVectorToString(_at->chatv("+CGMI", "+CGMI:", false));
252
result._model = stringVectorToString(_at->chatv("+CGMM", "+CGMM:", false));
254
stringVectorToString(_at->chatv("+CGMR", "+CGMR:", false));
255
result._serialNumber =
256
stringVectorToString(_at->chatv("+CGSN", "+CGSN:", false),0);
260
std::vector<std::string> MeTa::getSupportedCharSets() throw(GsmException)
262
Parser p(_at->chat("+CSCS=?", "+CSCS:"));
263
return p.parseStringList();
266
std::string MeTa::getCurrentCharSet() throw(GsmException)
268
if (_lastCharSet == "")
270
Parser p(_at->chat("+CSCS?", "+CSCS:"));
271
_lastCharSet = p.parseString();
276
void MeTa::setCharSet(std::string charSetName) throw(GsmException)
278
_at->chat("+CSCS=\"" + charSetName + "\"");
282
std::string MeTa::getExtendedErrorReport() throw(GsmException)
284
return _at->chat("+CEER", "+CEER:");
287
void MeTa::dial(std::string number) throw(GsmException)
289
_at->chat("D" + number + ";");
292
void MeTa::answer() throw(GsmException)
297
void MeTa::hangup() throw(GsmException)
303
std::vector<OPInfo> MeTa::getAvailableOPInfo() throw(GsmException)
305
std::vector<OPInfo> result;
306
std::vector<std::string> responses = _at->chatv("+COPS=?", "+COPS:");
308
// special treatment for Falcom A2-1, answer looks like
309
// responses.push_back("(1,29341),(3,29340)");
310
if (_capabilities._veryShortCOPSanswer)
312
if (responses.size() == 1)
314
Parser p(responses[0]);
315
while (p.parseChar('(', true))
318
opi._status = (OPStatus)p.parseInt();
320
opi._numericName = p.parseInt();
323
result.push_back(opi);
328
// some formats I have encountered...
329
//responses.push_back("2,,,31017,,(0,1),(2)");
330
//responses.push_back("(3,\"UK CELLNET\",\"CLNET\",\"23410\"),"
331
// "(3,\"ONE2 ONE\",\"ONE2ONE\",\"23430\"),"
332
// "(3,\"ORANGE\",\"ORANGE\",\"23433\")");
333
//responses.push_back("(2,\"D1-TELEKOM\",,26201),"
334
// "(3,\"D2 PRIVAT\",,26202),,(0,1,3,4),(0,2)");
335
// some phones arbitrarily split the response into several lines
336
//responses.push_back("(1,\"AMENA\",,\"21403\"),"
337
// "(3,\"MOVISTAR\",,\"21407\"),");
338
//responses.push_back("(3,\"E VODAFONE\",,\"21401\"),,(0,1),(2)");
340
// GSM modems might return
341
// 1. quadruplets of info enclosed in brackets separated by comma
342
// 2. several lines of quadruplets of info enclosed in brackets
343
// 3. several lines of quadruplets without brackets and additional
344
// info at EOL (e.g. Nokia 8290)
345
for (std::vector<std::string>::iterator i = responses.begin();
346
i != responses.end(); ++i)
348
// while (i->length() > 0 && ! isprint((*i)[i->length() - 1]))
349
// i->erase(i->length() - 1, 1);
351
bool expectClosingBracket = false;
356
expectClosingBracket = p.parseChar('(', true);
357
int status = p.parseInt(true);
358
opi._status = (status == NOT_SET ? UnknownOPStatus : (OPStatus)status);
360
opi._longName = p.parseString(true);
362
opi._shortName = p.parseString(true);
366
opi._numericName = p.parseInt(true);
368
catch (GsmException &e)
370
if (e.getErrorClass() == ParserError)
372
// the Ericsson GM12 GSM modem returns the numeric ID as string
373
std::string s = p.parseString();
374
opi._numericName = checkNumber(s);
379
if (expectClosingBracket) p.parseChar(')');
380
result.push_back(opi);
381
if (! p.parseComma(true)) break;
382
// two commas ",," mean the list is finished
383
if (p.getEol() == "" || p.parseComma(true)) break;
385
// without brackets, the ME/TA must use format 3.
386
if (! expectClosingBracket) break;
391
OPInfo MeTa::getCurrentOPInfo() throw(GsmException)
395
// 1. This exception thing is necessary because not all ME/TA combinations
396
// might support all the formats and then return "ERROR".
397
// 2. Additionally some modems return "ERROR" for all "COPS=3,n" command
398
// and report only one format with the "COPS?" command (e.g. Nokia 8290).
405
_at->chat("+COPS=3,0");
407
catch (GsmException &e)
409
if (e.getErrorClass() != ChatError) throw;
411
Parser p(_at->chat("+COPS?", "+COPS:"));
412
result._mode = (OPModes)p.parseInt();
413
// some phones (e.g. Nokia Card Phone 2.0) just return "+COPS: 0"
414
// if no network connection
415
if (p.parseComma(true))
417
if (p.parseInt() == 0)
420
result._longName = p.parseString();
424
catch (GsmException &e)
426
if (e.getErrorClass() != ChatError) throw;
434
_at->chat("+COPS=3,1");
436
catch (GsmException &e)
438
if (e.getErrorClass() != ChatError) throw;
440
Parser p(_at->chat("+COPS?", "+COPS:"));
441
result._mode = (OPModes)p.parseInt();
442
// some phones (e.g. Nokia Card Phone 2.0) just return "+COPS: 0"
443
// if no network connection
444
if (p.parseComma(true))
446
if (p.parseInt() == 1)
449
result._shortName = p.parseString();
453
catch (GsmException &e)
455
if (e.getErrorClass() != ChatError) throw;
458
// get numeric format
463
_at->chat("+COPS=3,2");
465
catch (GsmException &e)
467
if (e.getErrorClass() != ChatError) throw;
469
Parser p(_at->chat("+COPS?", "+COPS:"));
470
result._mode = (OPModes)p.parseInt();
471
// some phones (e.g. Nokia Card Phone 2.0) just return "+COPS: 0"
472
// if no network connection
473
if (p.parseComma(true))
475
if (p.parseInt() == 2)
480
result._numericName = p.parseInt();
482
catch (GsmException &e)
484
if (e.getErrorClass() == ParserError)
486
// the Ericsson GM12 GSM modem returns the numeric ID as string
487
std::string s = p.parseString();
488
result._numericName = checkNumber(s);
496
catch (GsmException &e)
498
if (e.getErrorClass() != ChatError) throw;
503
void MeTa::setCurrentOPInfo(OPModes mode,
504
std::string longName,
505
std::string shortName,
506
int numericName) throw(GsmException)
513
_at->chat("+COPS=" + intToStr((int)mode) + ",0,\"" + longName + "\"");
516
catch (GsmException &e)
518
if (e.getErrorClass() != ChatError) throw;
521
if (shortName != "" && ! done)
525
_at->chat("+COPS=" + intToStr((int)mode) + ",1,\"" + shortName + "\"");
528
catch (GsmException &e)
530
if (e.getErrorClass() != ChatError) throw;
533
if (numericName != NOT_SET && ! done)
537
_at->chat("+COPS=" + intToStr((int)mode) + ",2," +
538
intToStr(numericName));
541
catch (GsmException &e)
543
if (e.getErrorClass() != ChatError) throw;
547
throw GsmException(_("unable to set operator"), OtherError);
550
std::vector<std::string> MeTa::getFacilityLockCapabilities() throw(GsmException)
552
std::string locks = _at->chat("+CLCK=?", "+CLCK:");
553
// some TA don't add '(' and ')' (Option FirstFone)
554
if (locks.length() && locks[0] != '(')
556
locks.insert(locks.begin(),'(');
560
return p.parseStringList();
563
bool MeTa::getFacilityLockStatus(std::string facility, FacilityClass cl)
566
// some TA return always multiline response with all classes
567
// (Option FirstFone)
568
// !!! errors handling is correct (responses.empty() true) ?
569
std::vector<std::string> responses =
570
_at->chatv("+CLCK=\"" + facility + "\",2,," + intToStr((int)cl),"+CLCK:",true);
571
for (std::vector<std::string>::iterator i = responses.begin();
572
i != responses.end(); ++i)
575
int enabled = p.parseInt();
577
// if the first time and there is no comma this
578
// return direct state of classes
579
// else return all classes
580
if (i == responses.begin())
582
if (!p.parseComma(true))
588
if ( p.parseInt() == (int)cl )
593
// Parser p(_at->chat("+CLCK=\"" + facility + "\",2,," + intToStr((int)cl),
595
// return p.parseInt() == 1;
598
void MeTa::lockFacility(std::string facility, FacilityClass cl, std::string passwd)
602
_at->chat("+CLCK=\"" + facility + "\",1,," + intToStr((int)cl));
604
_at->chat("+CLCK=\"" + facility + "\",1,\"" + passwd + "\","
605
+ intToStr((int)cl));
608
void MeTa::unlockFacility(std::string facility, FacilityClass cl, std::string passwd)
612
_at->chat("+CLCK=\"" + facility + "\",0,," + intToStr((int)cl));
614
_at->chat("+CLCK=\"" + facility + "\",0,\"" + passwd + "\","
615
+ intToStr((int)cl));
618
std::vector<PWInfo> MeTa::getPasswords() throw(GsmException)
620
std::vector<PWInfo> result;
621
Parser p(_at->chat("+CPWD=?", "+CPWD:"));
625
if (!p.parseChar('(', true)) break; // exit if no new tuple
626
pwi._facility = p.parseString();
628
pwi._maxPasswdLen = p.parseInt();
631
result.push_back(pwi);
636
void MeTa::setPassword(std::string facility, std::string oldPasswd, std::string newPasswd)
639
_at->chat("+CPWD=\"" + facility + "\",\"" + oldPasswd + "\",\"" +
643
bool MeTa::getNetworkCLIP() throw(GsmException)
645
Parser p(_at->chat("+CLIP?", "+CLIP:"));
646
p.parseInt(); // ignore result code presentation
648
return p.parseInt() == 1;
651
void MeTa::setCLIPPresentation(bool enable) throw(GsmException)
654
_at->chat("+CLIP=1");
656
_at->chat("+CLIP=0");
659
bool MeTa::getCLIPPresentation() throw(GsmException)
661
Parser p(_at->chat("+CLIP?", "+CLIP:"));
662
return p.parseInt() == 1; // ignore rest of line
665
void MeTa::setCallForwarding(ForwardReason reason,
670
int forwardTime) throw(GsmException)
672
// FIXME subaddr is currently ignored
673
if (forwardTime != NOT_SET && (forwardTime < 0 || forwardTime > 30))
674
throw GsmException(_("call forward time must be in the range 0..30"),
678
number = removeWhiteSpace(number);
679
if (number.length() > 0 && number[0] == '+')
681
numberType = InternationalNumberFormat;
682
number = number.substr(1); // skip the '+' at the beginning
685
numberType = UnknownNumberFormat;
686
_at->chat("+CCFC=" + intToStr(reason) + "," + intToStr(mode) + ","
687
"\"" + number + "\"," +
688
(number.length() > 0 ? intToStr(numberType) : "") +
690
// FIXME subaddr and type
691
(forwardTime == NOT_SET ? "" :
692
(",,," + intToStr(forwardTime))));
695
void MeTa::getCallForwardInfo(ForwardReason reason,
698
ForwardInfo &data) throw(GsmException)
700
// Initialize to some sensible values:
701
voice._active = false;
702
voice._cl = VoiceFacility;
704
voice._reason = NoReason;
705
data._active = false;
706
data._cl = DataFacility;
708
data._reason = NoReason;
710
fax._cl = FaxFacility;
712
fax._reason = NoReason;
714
std::vector<std::string> responses =
715
_at->chatv("+CCFC=" + intToStr(reason) + ",2", "+CCFC:");
716
if (responses.size() == 1)
718
// only one line was returned. We have to ask for all three classes
719
// (voice, data, fax) separately
721
responses.push_back(_at->chat("+CCFC=" + intToStr(reason) +
722
",2,,,1", "+CCFC:"));
723
responses.push_back(_at->chat("+CCFC=" + intToStr(reason) +
724
",2,,,2", "+CCFC:"));
725
responses.push_back(_at->chat("+CCFC=" + intToStr(reason) +
726
",2,,,4", "+CCFC:"));
729
for (std::vector<std::string>::iterator i = responses.begin();
730
i != responses.end(); ++i)
733
int status = p.parseInt();
735
FacilityClass cl = (FacilityClass)p.parseInt();
738
int forwardTime = NOT_SET;
741
if (p.parseComma(true))
743
number = p.parseString();
745
unsigned int numberType = p.parseInt();
746
if (numberType == InternationalNumberFormat) number = "+" + number;
749
if (p.parseComma(true))
751
// FIXME subaddr type not handled
752
subAddr = p.parseString(true);
757
if (p.parseComma(true))
759
forwardTime = p.parseInt();
766
voice._active = (status == 1);
767
voice._cl = VoiceFacility;
768
voice._number = number;
769
voice._subAddr = subAddr;
770
voice._time = forwardTime;
771
voice._reason = reason;
774
data._active = (status == 1);
775
data._cl = DataFacility;
776
data._number = number;
777
data._subAddr = subAddr;
778
data._time = forwardTime;
779
data._reason = reason;
782
fax._active = (status == 1);
783
fax._cl = FaxFacility;
784
fax._number = number;
785
fax._subAddr = subAddr;
786
fax._time = forwardTime;
787
fax._reason = reason;
793
int MeTa::getBatteryChargeStatus() throw(GsmException)
795
Parser p(_at->chat("+CBC", "+CBC:"));
799
int MeTa::getBatteryCharge() throw(GsmException)
801
Parser p(_at->chat("+CBC", "+CBC:"));
807
int MeTa::getFunctionalityLevel() throw(GsmException)
810
Parser p(_at->chat("+CFUN?", "+CFUN:"));
811
// some phones return functionality level like "(2)"
812
bool expectClosingParen = p.parseChar('(', true);
813
int result = p.parseInt();
814
if (expectClosingParen)
818
catch (GsmException &x)
820
if (x.getErrorClass() == ChatError)
822
throw GsmException(_("Functionality Level commands not supported by ME"),
823
MeTaCapabilityError);
830
void MeTa::setFunctionalityLevel(int level) throw(GsmException)
833
Parser p(_at->chat("+CFUN=" + intToStr(level)));
834
} catch (GsmException &x) {
835
if (x.getErrorClass() == ChatError)
837
// If the command AT+CFUN commands really aren't supported by the ME,
838
// then this will throw an appropriate exception for us.
839
getFunctionalityLevel();
840
// If the number was just out of range, we get here.
841
throw GsmException(_("Requested Functionality Level out of range"),
848
int MeTa::getSignalStrength() throw(GsmException)
850
Parser p(_at->chat("+CSQ", "+CSQ:"));
854
int MeTa::getBitErrorRate() throw(GsmException)
856
Parser p(_at->chat("+CSQ", "+CSQ:"));
862
std::vector<std::string> MeTa::getPhoneBookStrings() throw(GsmException)
864
Parser p(_at->chat("+CPBS=?", "+CPBS:"));
865
return p.parseStringList();
868
PhonebookRef MeTa::getPhonebook(std::string phonebookString,
869
bool preload) throw(GsmException)
871
for (PhonebookVector::iterator i = _phonebookCache.begin();
872
i != _phonebookCache.end(); ++i)
874
if ((*i)->name() == phonebookString)
877
PhonebookRef newPb(new Phonebook(phonebookString, _at, *this, preload));
878
_phonebookCache.push_back(newPb);
882
std::string MeTa::getServiceCentreAddress() throw(GsmException)
884
Parser p(_at->chat("+CSCA?", "+CSCA:"));
885
return p.parseString();
888
void MeTa::setServiceCentreAddress(std::string sca) throw(GsmException)
891
sca = removeWhiteSpace(sca);
892
if (sca.length() > 0 && sca[0] == '+')
894
type = InternationalNumberFormat;
895
sca = sca.substr(1, sca.length() - 1);
898
type = UnknownNumberFormat;
899
Parser p(_at->chat("+CSCA=\"" + sca + "\"," + intToStr(type)));
902
std::vector<std::string> MeTa::getSMSStoreNames() throw(GsmException)
904
Parser p(_at->chat("+CPMS=?", "+CPMS:"));
905
// only return <mem1> values
906
return p.parseStringList();
909
SMSStoreRef MeTa::getSMSStore(std::string storeName) throw(GsmException)
911
for (SMSStoreVector::iterator i = _smsStoreCache.begin();
912
i != _smsStoreCache.end(); ++i)
914
if ((*i)->name() == storeName)
917
SMSStoreRef newSs(new SMSStore(storeName, _at, *this));
918
_smsStoreCache.push_back(newSs);
922
void MeTa::sendSMS(Ref<SMSSubmitMessage> smsMessage) throw(GsmException)
924
smsMessage->setAt(_at);
928
void MeTa::sendSMSs(Ref<SMSSubmitMessage> smsTemplate, std::string text,
930
int concatenatedMessageId)
933
assert(! smsTemplate.isnull());
935
// compute maximum text length for normal SMSs and concatenated SMSs
936
unsigned int maxTextLength, concMaxTextLength;
937
switch (smsTemplate->dataCodingScheme().getAlphabet())
939
case DCS_DEFAULT_ALPHABET:
941
concMaxTextLength = 152;
943
case DCS_EIGHT_BIT_ALPHABET:
945
concMaxTextLength = 134;
947
case DCS_SIXTEEN_BIT_ALPHABET:
949
concMaxTextLength = 67;
952
throw GsmException(_("unsupported alphabet for SMS"),
957
// simple case, only send one SMS
958
if (oneSMS || text.length() <= maxTextLength)
960
if (text.length() > maxTextLength)
961
throw GsmException(_("SMS text is larger than allowed"),
963
smsTemplate->setUserData(text);
964
sendSMS(smsTemplate);
966
else // send multiple SMSs
968
if (concatenatedMessageId != -1)
969
maxTextLength = concMaxTextLength;
971
int numMessages = (text.length() + maxTextLength - 1) / maxTextLength;
972
if (numMessages > 255)
973
throw GsmException(_("not more than 255 concatenated SMSs allowed"),
975
unsigned char numMessage = 0;
978
if (concatenatedMessageId != -1)
980
unsigned char udhs[] = {0x00, 0x03, concatenatedMessageId,
981
numMessages, ++numMessage};
982
UserDataHeader udh(std::string((char*)udhs, 5));
983
smsTemplate->setUserDataHeader(udh);
985
smsTemplate->setUserData(text.substr(0, maxTextLength));
986
sendSMS(smsTemplate);
987
if (text.length() < maxTextLength)
989
text.erase(0, maxTextLength);
994
void MeTa::setMessageService(int serviceLevel) throw(GsmException)
997
switch (serviceLevel)
1006
throw GsmException(_("only serviceLevel 0 or 1 supported"),
1009
// some devices (eg. Origo 900) don't support service level setting
1010
_at->chat("+CSMS=" + s, "+CSMS:", true);
1013
unsigned int MeTa::getMessageService() throw(GsmException)
1016
Parser p(_at->chat("+CSMS?", "+CSMS:"));
1017
return p.parseInt();
1019
catch (GsmException &e)
1021
if (e.getErrorClass() == ParserError) {
1029
void MeTa::getSMSRoutingToTA(bool &smsRouted,
1031
bool &statusReportsRouted) throw(GsmException)
1033
Parser p(_at->chat("+CNMI?", "+CNMI:"));
1041
if (p.parseComma(true))
1043
smsMode = p.parseInt();
1044
if (p.parseComma(true))
1046
cbsMode = p.parseInt();
1047
if (p.parseComma(true))
1049
statMode = p.parseInt();
1050
/*if (p.parseComma(true))
1052
bufferMode = p.parseInt();
1058
smsRouted = (smsMode == 2) || (smsMode == 3);
1059
cbsRouted = (cbsMode == 2) || (cbsMode == 3);
1060
statusReportsRouted = (statMode == 1);
1063
void MeTa::setSMSRoutingToTA(bool enableSMS, bool enableCBS,
1064
bool enableStatReport,
1065
bool onlyReceptionIndication)
1068
bool smsModesSet = false;
1069
bool cbsModesSet = false;
1070
bool statModesSet = false;
1071
bool bufferModesSet = false;
1073
// find out capabilities
1074
Parser p(_at->chat("+CNMI=?", "+CNMI:"));
1075
std::vector<bool> modes = p.parseIntList();
1076
std::vector<bool> smsModes(1);
1077
std::vector<bool> cbsModes(1);
1078
std::vector<bool> statModes(1);
1079
std::vector<bool> bufferModes(1);
1080
if (p.parseComma(true))
1082
smsModes = p.parseIntList();
1084
if (p.parseComma(true))
1086
cbsModes = p.parseIntList();
1088
if (p.parseComma(true))
1090
statModes = p.parseIntList();
1091
statModesSet = true;
1092
if (p.parseComma(true))
1094
bufferModes = p.parseIntList();
1095
bufferModesSet = true;
1101
// now set the mode vectors to the default if not set
1102
if (! smsModesSet) smsModes[0] = true;
1103
if (! cbsModesSet) cbsModes[0] = true;
1104
if (! statModesSet) statModes[0] = true;
1105
if (! bufferModesSet) bufferModes[0] = true;
1107
std::string chatString;
1109
// now try to set some optimal combination depending on
1110
// ME/TA's capabilities
1113
if (isSet(modes, 2))
1115
else if (isSet(modes, 1))
1117
else if (isSet(modes, 0))
1119
else if (isSet(modes, 3))
1122
if (onlyReceptionIndication)
1127
if (isSet(smsModes, 1))
1130
throw GsmException(_("cannot route SMS messages to TE"),
1131
MeTaCapabilityError);
1139
if (isSet(cbsModes, 1))
1141
else if (isSet(cbsModes, 2))
1144
throw GsmException(_("cannot route cell broadcast messages to TE"),
1145
MeTaCapabilityError);
1151
if (enableStatReport)
1153
if (isSet(statModes, 2))
1156
throw GsmException(_("cannot route status reports messages to TE"),
1157
MeTaCapabilityError);
1167
if (isSet(smsModes, 2))
1169
else if (isSet(smsModes, 3))
1172
throw GsmException(_("cannot route SMS messages to TE"),
1173
MeTaCapabilityError);
1181
if (isSet(cbsModes, 2))
1183
else if (isSet(cbsModes, 3))
1186
throw GsmException(_("cannot route cell broadcast messages to TE"),
1187
MeTaCapabilityError);
1193
if (enableStatReport)
1195
if (isSet(statModes, 1))
1197
else if (isSet(statModes, 2))
1200
throw GsmException(_("cannot route status report messages to TE"),
1201
MeTaCapabilityError);
1207
// handle buffer mode but only if it was reported by the +CNMI=? command
1208
// the Ericsson GM12 GSM modem does not like it otherwise
1211
if (isSet(bufferModes, 1))
1217
_at->chat("+CNMI=" + chatString);
1220
bool MeTa::getCallWaitingLockStatus(FacilityClass cl)
1223
// some TA return always multiline response with all classes
1224
// (Option FirstFone)
1225
// !!! errors handling is correct (responses.empty() true) ?
1226
std::vector<std::string> responses =
1227
_at->chatv("+CCWA=0,2," + intToStr((int)cl),"+CCWA:",true);
1228
for (std::vector<std::string>::iterator i = responses.begin();
1229
i != responses.end(); ++i)
1232
int enabled = p.parseInt();
1234
// if the first time and there is no comma this
1235
// return direct state of classes
1236
// else return all classes
1237
if (i == responses.begin())
1239
if (! p.parseComma(true))
1240
return enabled == 1;
1245
if (p.parseInt() == (int)cl)
1246
return enabled == 1;
1251
void MeTa::setCallWaitingLockStatus(FacilityClass cl, bool lock)
1255
_at->chat("+CCWA=0,1," + intToStr((int)cl));
1257
_at->chat("+CCWA=0,0," + intToStr((int)cl));
1260
void MeTa::setCLIRPresentation(bool enable) throw(GsmException)
1263
_at->chat("+CLIR=1");
1265
_at->chat("+CLIR=0");
1268
int MeTa::getCLIRPresentation() throw(GsmException)
1270
// 0:according to the subscription of the CLIR service
1271
// 1:CLIR invocation
1272
// 2:CLIR suppression
1273
Parser p(_at->chat("+CLIR?", "+CLIR:"));
1274
return p.parseInt();