~ubuntu-branches/debian/jessie/gsmlib/jessie

« back to all changes in this revision

Viewing changes to .pc/03-fix-cops.diff/gsmlib/gsm_me_ta.cc

  • Committer: Package Import Robot
  • Author(s): Andrew Shadura
  • Date: 2013-10-15 13:29:27 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20131015132927-1i5iwvj21wue3uvu
Tags: 1.10+20120414.gita5e5ae9a-0.1
* Non-maintainer upload.
* Update to the latest Git version by Vianney Bouchaud.
* Use 3.0 (quilt) source package format.
* Own the run subdirectory (Closes: #689891).
* Don't remove the system user on package remove.
* Fix init script (LP: #30228).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// *************************************************************************
 
2
// * GSM TA/ME library
 
3
// *
 
4
// * File:    gsm_me_ta.cc
 
5
// *
 
6
// * Purpose: Mobile Equipment/Terminal Adapter functions
 
7
// *          (ETSI GSM 07.07)
 
8
// *
 
9
// * Author:  Peter Hofmann (software@pxh.de)
 
10
// *
 
11
// * Created: 10.5.1999
 
12
// *************************************************************************
 
13
 
 
14
#ifdef HAVE_CONFIG_H
 
15
#include <gsm_config.h>
 
16
#endif
 
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>
 
21
 
 
22
#include <cstdlib>
 
23
 
 
24
using namespace gsmlib;
 
25
 
 
26
// Capabilities members
 
27
 
 
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
 
38
{
 
39
}
 
40
 
 
41
// MeTa members
 
42
 
 
43
void MeTa::init() throw(GsmException)
 
44
{
 
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);
 
48
  
 
49
  // select SMS pdu mode
 
50
  _at->chat("+CMGF=0");
 
51
 
 
52
  // now fill in capability object
 
53
  MEInfo info = getMEInfo();
 
54
  
 
55
  // Ericsson model 6050102
 
56
  if ((info._manufacturer == "ERICSSON" &&
 
57
      (info._model == "1100801" ||
 
58
       info._model == "1140801")) ||
 
59
      getenv("GSMLIB_SH888_FIX") != NULL)
 
60
  {
 
61
    // the Ericsson leaves out the service centre address
 
62
    _capabilities._hasSMSSCAprefix = false;
 
63
  }
 
64
 
 
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)
 
69
  {
 
70
    _capabilities._veryShortCOPSanswer = true;
 
71
  }
 
72
 
 
73
  // handle Motorola SMS store bug - wrong status code
 
74
  if ((info._manufacturer == "Motorola" &&
 
75
       info._model == "L Series"))
 
76
  {
 
77
    _capabilities._wrongSMSStatusCode = true;
 
78
  } 
 
79
 
 
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")))
 
85
  {
 
86
    _capabilities._CDSmeansCDSI = true;
 
87
  } 
 
88
 
 
89
  // find out whether we are supposed to send an acknowledgment
 
90
  Parser p(_at->chat("+CSMS?", "+CSMS:"));
 
91
  try {
 
92
    _capabilities._sendAck = p.parseInt() >= 1;
 
93
  }
 
94
  catch (GsmException &e)
 
95
  {
 
96
    if (e.getErrorClass() == ParserError) {
 
97
      _capabilities._sendAck = 0;
 
98
    } else {
 
99
      throw e;
 
100
    }
 
101
  }
 
102
      
 
103
  // set GSM default character set
 
104
  try
 
105
  {
 
106
    setCharSet("GSM");
 
107
  }
 
108
  catch (GsmException)
 
109
  {
 
110
    // ignore errors, some devices don't support this
 
111
  }
 
112
 
 
113
  // set default event handler
 
114
  // necessary to handle at least RING indications that might
 
115
  // otherwise confuse gsmlib
 
116
  _at->setEventHandler(&_defaultEventHandler);
 
117
}
 
118
 
 
119
MeTa::MeTa(Ref<Port> port) throw(GsmException) : _port(port)
 
120
{
 
121
  // initialize AT handling
 
122
  _at = new GsmAt(*this);
 
123
 
 
124
  init();
 
125
}
 
126
 
 
127
// MeTa::MeTa(Ref<GsmAt> at) throw(GsmException) :
 
128
//   _at(at)
 
129
// {
 
130
//   init();
 
131
// }
 
132
 
 
133
void MeTa::setPIN(std::string pin) throw(GsmException)
 
134
{
 
135
  _at->chat("+CPIN=\"" + pin + "\"");
 
136
}
 
137
 
 
138
std::string MeTa::getPINStatus() throw(GsmException)
 
139
{
 
140
  Parser p(_at->chat("+CPIN?", "+CPIN:"));
 
141
  return p.parseString();
 
142
}
 
143
 
 
144
void MeTa::setPhonebook(std::string phonebookName) throw(GsmException)
 
145
{
 
146
  if (phonebookName != _lastPhonebookName)
 
147
  {
 
148
    _at->chat("+CPBS=\"" + phonebookName + "\"");
 
149
    _lastPhonebookName = phonebookName;
 
150
  }
 
151
}
 
152
 
 
153
std::string MeTa::setSMSStore(std::string smsStore, int storeTypes, bool needResultCode)
 
154
  throw(GsmException)
 
155
{
 
156
  if (_capabilities._cpmsParamCount == -1)
 
157
  {
 
158
    // count the number of parameters for the CPMS AT sequences
 
159
    _capabilities._cpmsParamCount = 1;
 
160
    Parser p(_at->chat("+CPMS=?", "+CPMS:"));
 
161
    p.parseStringList();
 
162
    while (p.parseComma(true))
 
163
    {
 
164
      ++_capabilities._cpmsParamCount;
 
165
      p.parseStringList();
 
166
    }
 
167
  }
 
168
 
 
169
  // optimatization: only set current SMS store if different from last call
 
170
  // or the result code is needed
 
171
  if (needResultCode || _lastSMSStoreName != smsStore)
 
172
  {
 
173
    _lastSMSStoreName = smsStore;
 
174
 
 
175
    // build chat string
 
176
    std::string chatString = "+CPMS=\"" + smsStore + "\"";
 
177
    for (int i = 1; i < std::min(_capabilities._cpmsParamCount, storeTypes); ++i)
 
178
      chatString += ",\"" + smsStore + "\"";
 
179
 
 
180
    return _at->chat(chatString, "+CPMS:");
 
181
  }
 
182
  return "";
 
183
}
 
184
 
 
185
void MeTa::getSMSStore(std::string &readDeleteStore,
 
186
                       std::string &writeSendStore,
 
187
                       std::string &receiveStore) throw(GsmException)
 
188
{
 
189
  Parser p(_at->chat("+CPMS?", "+CPMS:"));
 
190
  writeSendStore = receiveStore = "";
 
191
  readDeleteStore = p.parseString();
 
192
  p.parseComma();
 
193
  p.parseInt();
 
194
  p.parseComma();
 
195
  p.parseInt();
 
196
  if (p.parseComma(true))
 
197
  {
 
198
    writeSendStore = p.parseString();
 
199
    p.parseComma();
 
200
    p.parseInt();
 
201
    p.parseComma();
 
202
    p.parseInt();
 
203
    if (p.parseComma(true))
 
204
    {
 
205
      receiveStore = p.parseString();
 
206
    }
 
207
  }
 
208
}
 
209
 
 
210
void MeTa::waitEvent(GsmTime timeout) throw(GsmException)
 
211
{
 
212
  if (_at->wait(timeout))
 
213
    _at->chat();                // send AT, wait for OK, handle events
 
214
}
 
215
 
 
216
// aux function for MeTa::getMEInfo()
 
217
 
 
218
static std::string stringVectorToString(const std::vector<std::string>& v,
 
219
                                        char separator = '\n')
 
220
{
 
221
  if (v.empty())
 
222
    return "";
 
223
 
 
224
  // concatenate string in vector as rows
 
225
  std::string result;
 
226
  for (std::vector<std::string>::const_iterator i = v.begin();;)
 
227
  {
 
228
    std::string s = *i;
 
229
    // remove leading and trailing "s
 
230
    if (s.length() > 0 && s[0] == '"')
 
231
      s.erase(s.begin());
 
232
    if (s.length() > 0 && s[s.length() - 1] == '"')
 
233
      s.erase(s.end() - 1);
 
234
 
 
235
    result += s;
 
236
    // don't add end line to last
 
237
    if ( ++i == v.end() || !separator)
 
238
      break;
 
239
    result += separator;
 
240
  }
 
241
  return result;
 
242
}
 
243
 
 
244
MEInfo MeTa::getMEInfo() throw(GsmException)
 
245
{
 
246
  MEInfo result;
 
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));
 
253
  result._revision =
 
254
    stringVectorToString(_at->chatv("+CGMR", "+CGMR:", false));
 
255
  result._serialNumber =
 
256
    stringVectorToString(_at->chatv("+CGSN", "+CGSN:", false),0);
 
257
  return result;
 
258
}
 
259
 
 
260
std::vector<std::string> MeTa::getSupportedCharSets() throw(GsmException)
 
261
{
 
262
  Parser p(_at->chat("+CSCS=?", "+CSCS:"));
 
263
  return p.parseStringList();
 
264
}
 
265
    
 
266
std::string MeTa::getCurrentCharSet() throw(GsmException)
 
267
{
 
268
  if (_lastCharSet == "")
 
269
  {
 
270
    Parser p(_at->chat("+CSCS?", "+CSCS:"));
 
271
    _lastCharSet = p.parseString();
 
272
  }
 
273
  return _lastCharSet;
 
274
}
 
275
 
 
276
void MeTa::setCharSet(std::string charSetName) throw(GsmException)
 
277
{
 
278
  _at->chat("+CSCS=\"" + charSetName + "\"");
 
279
  _lastCharSet = "";
 
280
}
 
281
 
 
282
std::string MeTa::getExtendedErrorReport() throw(GsmException)
 
283
{
 
284
  return _at->chat("+CEER", "+CEER:");
 
285
}
 
286
 
 
287
void MeTa::dial(std::string number) throw(GsmException)
 
288
{
 
289
  _at->chat("D" + number + ";");
 
290
}
 
291
 
 
292
void MeTa::answer() throw(GsmException)
 
293
{
 
294
  _at->chat("A");
 
295
}
 
296
 
 
297
void MeTa::hangup() throw(GsmException)
 
298
{
 
299
  _at->chat("H");
 
300
 
 
301
}
 
302
 
 
303
std::vector<OPInfo> MeTa::getAvailableOPInfo() throw(GsmException)
 
304
{
 
305
  std::vector<OPInfo> result;
 
306
  std::vector<std::string> responses = _at->chatv("+COPS=?", "+COPS:");
 
307
 
 
308
  // special treatment for Falcom A2-1, answer looks like
 
309
  //   responses.push_back("(1,29341),(3,29340)");
 
310
  if (_capabilities._veryShortCOPSanswer)
 
311
  {
 
312
    if (responses.size() == 1)
 
313
    {
 
314
      Parser p(responses[0]);
 
315
      while (p.parseChar('(', true))
 
316
      {
 
317
        OPInfo opi;
 
318
        opi._status = (OPStatus)p.parseInt();
 
319
        p.parseComma();
 
320
        opi._numericName = p.parseInt();
 
321
        p.parseChar(')');
 
322
        p.parseComma(true);
 
323
        result.push_back(opi);
 
324
      }
 
325
    }
 
326
  }
 
327
  else
 
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)");
 
339
 
 
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)
 
347
    {
 
348
//       while (i->length() > 0 && ! isprint((*i)[i->length() - 1]))
 
349
//         i->erase(i->length() - 1, 1);
 
350
 
 
351
      bool expectClosingBracket = false;
 
352
      Parser p(*i);
 
353
      while (1)
 
354
      {
 
355
        OPInfo opi;
 
356
        expectClosingBracket = p.parseChar('(', true);
 
357
        int status = p.parseInt(true);
 
358
        opi._status = (status == NOT_SET ? UnknownOPStatus : (OPStatus)status);
 
359
        p.parseComma();
 
360
        opi._longName = p.parseString(true);
 
361
        p.parseComma();
 
362
        opi._shortName = p.parseString(true);
 
363
        p.parseComma();
 
364
        try
 
365
        {
 
366
          opi._numericName = p.parseInt(true);
 
367
        }
 
368
        catch (GsmException &e)
 
369
        {
 
370
          if (e.getErrorClass() == ParserError)
 
371
          {
 
372
            // the Ericsson GM12 GSM modem returns the numeric ID as string
 
373
            std::string s = p.parseString();
 
374
            opi._numericName = checkNumber(s);
 
375
          }
 
376
          else
 
377
            throw e;
 
378
        }
 
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;
 
384
      }
 
385
      // without brackets, the ME/TA must use format 3.
 
386
      if (! expectClosingBracket) break;
 
387
    }
 
388
  return result;
 
389
}
 
390
 
 
391
OPInfo MeTa::getCurrentOPInfo() throw(GsmException)
 
392
{
 
393
  OPInfo result;
 
394
 
 
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).
 
399
 
 
400
  // get long format
 
401
  try
 
402
  {
 
403
    try
 
404
    {
 
405
      _at->chat("+COPS=3,0");
 
406
    }
 
407
    catch (GsmException &e)
 
408
    {
 
409
      if (e.getErrorClass() != ChatError) throw;
 
410
    }
 
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))
 
416
    {
 
417
      if (p.parseInt() == 0)
 
418
      {
 
419
        p.parseComma();
 
420
        result._longName = p.parseString();
 
421
      }
 
422
    }
 
423
  }
 
424
  catch (GsmException &e)
 
425
  {
 
426
    if (e.getErrorClass() != ChatError) throw;
 
427
  }
 
428
 
 
429
  // get short format
 
430
  try
 
431
  {
 
432
    try
 
433
    {
 
434
      _at->chat("+COPS=3,1");
 
435
    }
 
436
    catch (GsmException &e)
 
437
    {
 
438
      if (e.getErrorClass() != ChatError) throw;
 
439
    }
 
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))
 
445
    {
 
446
      if (p.parseInt() == 1)
 
447
      {
 
448
        p.parseComma();
 
449
        result._shortName = p.parseString();
 
450
      }
 
451
    }
 
452
  }
 
453
  catch (GsmException &e)
 
454
  {
 
455
    if (e.getErrorClass() != ChatError) throw;
 
456
  }
 
457
 
 
458
  // get numeric format
 
459
  try
 
460
  {
 
461
    try
 
462
    {
 
463
      _at->chat("+COPS=3,2");
 
464
    }
 
465
    catch (GsmException &e)
 
466
    {
 
467
      if (e.getErrorClass() != ChatError) throw;
 
468
    }
 
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))
 
474
    {
 
475
      if (p.parseInt() == 2)
 
476
      {
 
477
        p.parseComma();
 
478
        try
 
479
        {
 
480
          result._numericName = p.parseInt();
 
481
        }
 
482
        catch (GsmException &e)
 
483
        {
 
484
          if (e.getErrorClass() == ParserError)
 
485
          {
 
486
            // the Ericsson GM12 GSM modem returns the numeric ID as string
 
487
            std::string s = p.parseString();
 
488
            result._numericName = checkNumber(s);
 
489
          }
 
490
          else
 
491
            throw e;
 
492
        }
 
493
      }
 
494
    }
 
495
  }
 
496
  catch (GsmException &e)
 
497
  {
 
498
    if (e.getErrorClass() != ChatError) throw;
 
499
  }
 
500
  return result;
 
501
}
 
502
 
 
503
void MeTa::setCurrentOPInfo(OPModes mode,
 
504
                            std::string longName,
 
505
                            std::string shortName,
 
506
                            int numericName) throw(GsmException)
 
507
{
 
508
  bool done = false;
 
509
  if (longName != "")
 
510
  {
 
511
    try
 
512
    {
 
513
      _at->chat("+COPS=" + intToStr((int)mode) + ",0,\"" + longName + "\"");
 
514
      done = true;
 
515
    }
 
516
    catch (GsmException &e)
 
517
    {
 
518
      if (e.getErrorClass() != ChatError) throw;
 
519
    }
 
520
  }
 
521
  if (shortName != "" && ! done)
 
522
  {
 
523
    try
 
524
    {
 
525
      _at->chat("+COPS=" + intToStr((int)mode) + ",1,\"" + shortName + "\"");
 
526
      done = true;
 
527
    }
 
528
    catch (GsmException &e)
 
529
    {
 
530
      if (e.getErrorClass() != ChatError) throw;
 
531
    }
 
532
  }
 
533
  if (numericName != NOT_SET && ! done)
 
534
  {
 
535
    try
 
536
    {
 
537
      _at->chat("+COPS=" + intToStr((int)mode) + ",2," +
 
538
                intToStr(numericName));
 
539
      done = true;
 
540
    }
 
541
    catch (GsmException &e)
 
542
    {
 
543
      if (e.getErrorClass() != ChatError) throw;
 
544
    }
 
545
  }
 
546
  if (! done)
 
547
    throw GsmException(_("unable to set operator"), OtherError);
 
548
}
 
549
 
 
550
std::vector<std::string> MeTa::getFacilityLockCapabilities() throw(GsmException)
 
551
{
 
552
  std::string locks = _at->chat("+CLCK=?", "+CLCK:");
 
553
  // some TA don't add '(' and ')' (Option FirstFone)
 
554
  if (locks.length() && locks[0] != '(')
 
555
  {
 
556
    locks.insert(locks.begin(),'(');
 
557
    locks += ')';
 
558
  }
 
559
  Parser p(locks);
 
560
  return p.parseStringList();
 
561
}
 
562
 
 
563
bool MeTa::getFacilityLockStatus(std::string facility, FacilityClass cl)
 
564
  throw(GsmException)
 
565
{
 
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)
 
573
  {
 
574
    Parser p(*i);
 
575
    int enabled = p.parseInt();
 
576
 
 
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())
 
581
    {
 
582
      if (!p.parseComma(true))
 
583
        return enabled == 1;
 
584
    }
 
585
    else
 
586
      p.parseComma();
 
587
 
 
588
    if ( p.parseInt() == (int)cl )
 
589
      return enabled == 1;
 
590
  }
 
591
  return false;
 
592
 
 
593
//  Parser p(_at->chat("+CLCK=\"" + facility + "\",2,," + intToStr((int)cl),
 
594
//                     "+CLCK:"));
 
595
//  return p.parseInt() == 1;
 
596
}
 
597
 
 
598
void MeTa::lockFacility(std::string facility, FacilityClass cl, std::string passwd)
 
599
  throw(GsmException)
 
600
{
 
601
  if (passwd == "")
 
602
    _at->chat("+CLCK=\"" + facility + "\",1,," + intToStr((int)cl));
 
603
  else
 
604
    _at->chat("+CLCK=\"" + facility + "\",1,\"" + passwd + "\","
 
605
              + intToStr((int)cl));
 
606
}
 
607
 
 
608
void MeTa::unlockFacility(std::string facility, FacilityClass cl, std::string passwd)
 
609
  throw(GsmException)
 
610
{
 
611
  if (passwd == "")
 
612
    _at->chat("+CLCK=\"" + facility + "\",0,," + intToStr((int)cl));
 
613
  else
 
614
    _at->chat("+CLCK=\"" + facility + "\",0,\"" + passwd + "\","
 
615
              + intToStr((int)cl));
 
616
}
 
617
 
 
618
std::vector<PWInfo> MeTa::getPasswords() throw(GsmException)
 
619
{
 
620
  std::vector<PWInfo> result;
 
621
  Parser p(_at->chat("+CPWD=?", "+CPWD:"));
 
622
  while (1)
 
623
  {
 
624
    PWInfo pwi;
 
625
    if (!p.parseChar('(', true)) break; // exit if no new tuple
 
626
    pwi._facility = p.parseString();
 
627
    p.parseComma();
 
628
    pwi._maxPasswdLen = p.parseInt();
 
629
    p.parseChar(')');
 
630
    p.parseComma(true);
 
631
    result.push_back(pwi);
 
632
  }
 
633
  return result;
 
634
}
 
635
 
 
636
void MeTa::setPassword(std::string facility, std::string oldPasswd, std::string newPasswd)
 
637
  throw(GsmException)
 
638
{
 
639
  _at->chat("+CPWD=\"" + facility + "\",\"" + oldPasswd + "\",\"" +
 
640
            newPasswd + "\"");
 
641
}
 
642
 
 
643
bool MeTa::getNetworkCLIP() throw(GsmException)
 
644
{
 
645
  Parser p(_at->chat("+CLIP?", "+CLIP:"));
 
646
  p.parseInt();                 // ignore result code presentation
 
647
  p.parseComma();
 
648
  return p.parseInt() == 1;
 
649
}
 
650
 
 
651
void MeTa::setCLIPPresentation(bool enable) throw(GsmException)
 
652
{
 
653
  if (enable)
 
654
    _at->chat("+CLIP=1");
 
655
  else
 
656
    _at->chat("+CLIP=0");
 
657
}
 
658
 
 
659
bool MeTa::getCLIPPresentation() throw(GsmException)
 
660
{
 
661
  Parser p(_at->chat("+CLIP?", "+CLIP:"));
 
662
  return p.parseInt() == 1;     // ignore rest of line
 
663
}
 
664
 
 
665
void MeTa::setCallForwarding(ForwardReason reason,
 
666
                             ForwardMode mode,
 
667
                             std::string number,
 
668
                             std::string subaddr,
 
669
                             FacilityClass cl,
 
670
                             int forwardTime) throw(GsmException)
 
671
{
 
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"),
 
675
                       ParameterError);
 
676
  
 
677
  int numberType;
 
678
  number = removeWhiteSpace(number);
 
679
  if (number.length() > 0 && number[0] == '+')
 
680
  {
 
681
    numberType = InternationalNumberFormat;
 
682
    number = number.substr(1);  // skip the '+' at the beginning
 
683
  }
 
684
  else
 
685
    numberType = UnknownNumberFormat;
 
686
  _at->chat("+CCFC=" + intToStr(reason) + "," +  intToStr(mode) + "," 
 
687
            "\"" + number + "\"," +
 
688
            (number.length() > 0 ? intToStr(numberType) : "") +
 
689
            "," +  intToStr(cl) +
 
690
                                // FIXME subaddr and type
 
691
            (forwardTime == NOT_SET ? "" :
 
692
             (",,," + intToStr(forwardTime))));
 
693
}
 
694
                           
 
695
void MeTa::getCallForwardInfo(ForwardReason reason,
 
696
                              ForwardInfo &voice,
 
697
                              ForwardInfo &fax,
 
698
                              ForwardInfo &data) throw(GsmException)
 
699
{
 
700
  // Initialize to some sensible values:
 
701
  voice._active = false;
 
702
  voice._cl = VoiceFacility;
 
703
  voice._time = -1;
 
704
  voice._reason = NoReason;
 
705
  data._active = false;
 
706
  data._cl = DataFacility;
 
707
  data._time = -1;
 
708
  data._reason = NoReason;
 
709
  fax._active = false;
 
710
  fax._cl = FaxFacility;
 
711
  fax._time = -1;
 
712
  fax._reason = NoReason;
 
713
 
 
714
  std::vector<std::string> responses =
 
715
    _at->chatv("+CCFC=" + intToStr(reason) + ",2", "+CCFC:");
 
716
  if (responses.size() == 1)
 
717
  {
 
718
    // only one line was returned. We have to ask for all three classes
 
719
    // (voice, data, fax) separately
 
720
    responses.clear();
 
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:"));
 
727
  }
 
728
 
 
729
  for (std::vector<std::string>::iterator i = responses.begin();
 
730
       i != responses.end(); ++i)
 
731
  {
 
732
    Parser p(*i);
 
733
    int status = p.parseInt();
 
734
    p.parseComma();
 
735
    FacilityClass cl = (FacilityClass)p.parseInt();
 
736
    std::string number;
 
737
    std::string subAddr;
 
738
    int forwardTime = NOT_SET;
 
739
      
 
740
    // parse number
 
741
    if (p.parseComma(true))
 
742
    {
 
743
      number = p.parseString();
 
744
      p.parseComma();
 
745
      unsigned int numberType = p.parseInt();
 
746
      if (numberType == InternationalNumberFormat) number = "+" + number;
 
747
 
 
748
      // parse subaddr
 
749
      if (p.parseComma(true))
 
750
      {
 
751
        // FIXME subaddr type not handled
 
752
        subAddr = p.parseString(true);
 
753
        p.parseComma();
 
754
        p.parseInt(true);
 
755
          
 
756
        // parse forwardTime
 
757
        if (p.parseComma(true))
 
758
        {
 
759
          forwardTime = p.parseInt();
 
760
        }
 
761
      }
 
762
    }
 
763
    switch (cl)
 
764
    {
 
765
    case VoiceFacility:
 
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;
 
772
      break;
 
773
    case DataFacility:
 
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;
 
780
      break;
 
781
    case FaxFacility:
 
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;
 
788
      break;
 
789
    }
 
790
  }
 
791
}
 
792
 
 
793
int MeTa::getBatteryChargeStatus() throw(GsmException)
 
794
{
 
795
  Parser p(_at->chat("+CBC", "+CBC:"));
 
796
  return p.parseInt();
 
797
}
 
798
 
 
799
int MeTa::getBatteryCharge() throw(GsmException)
 
800
{
 
801
  Parser p(_at->chat("+CBC", "+CBC:"));
 
802
  p.parseInt();
 
803
  p.parseComma();
 
804
  return p.parseInt();
 
805
}
 
806
 
 
807
int MeTa::getFunctionalityLevel() throw(GsmException)
 
808
{
 
809
  try {
 
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)
 
815
      p.parseChar(')');
 
816
    return result;
 
817
  }
 
818
  catch (GsmException &x)
 
819
  {
 
820
    if (x.getErrorClass() == ChatError)
 
821
    {
 
822
      throw GsmException(_("Functionality Level commands not supported by ME"),
 
823
                         MeTaCapabilityError);
 
824
    } else {
 
825
      throw;
 
826
    }
 
827
  }
 
828
}
 
829
 
 
830
void MeTa::setFunctionalityLevel(int level) throw(GsmException)
 
831
{
 
832
  try {
 
833
    Parser p(_at->chat("+CFUN="  + intToStr(level)));
 
834
  } catch (GsmException &x) {
 
835
    if (x.getErrorClass() == ChatError)
 
836
    {
 
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"),
 
842
                         ParameterError);
 
843
    }
 
844
    throw;
 
845
  }
 
846
}
 
847
 
 
848
int MeTa::getSignalStrength() throw(GsmException)
 
849
{
 
850
  Parser p(_at->chat("+CSQ", "+CSQ:"));
 
851
  return p.parseInt();
 
852
}
 
853
 
 
854
int MeTa::getBitErrorRate() throw(GsmException)
 
855
{
 
856
  Parser p(_at->chat("+CSQ", "+CSQ:"));
 
857
  p.parseInt();
 
858
  p.parseComma();
 
859
  return p.parseInt();
 
860
}
 
861
 
 
862
std::vector<std::string> MeTa::getPhoneBookStrings() throw(GsmException)
 
863
{
 
864
  Parser p(_at->chat("+CPBS=?", "+CPBS:"));
 
865
  return p.parseStringList();
 
866
}
 
867
 
 
868
PhonebookRef MeTa::getPhonebook(std::string phonebookString,
 
869
                                bool preload) throw(GsmException)
 
870
{
 
871
  for (PhonebookVector::iterator i = _phonebookCache.begin();
 
872
       i !=  _phonebookCache.end(); ++i)
 
873
  {
 
874
    if ((*i)->name() == phonebookString)
 
875
      return *i;
 
876
  }
 
877
  PhonebookRef newPb(new Phonebook(phonebookString, _at, *this, preload));
 
878
  _phonebookCache.push_back(newPb);
 
879
  return newPb;
 
880
}
 
881
 
 
882
std::string MeTa::getServiceCentreAddress() throw(GsmException)
 
883
{
 
884
  Parser p(_at->chat("+CSCA?", "+CSCA:"));
 
885
  return p.parseString();
 
886
}
 
887
 
 
888
void MeTa::setServiceCentreAddress(std::string sca) throw(GsmException)
 
889
{
 
890
  int type;
 
891
  sca = removeWhiteSpace(sca);
 
892
  if (sca.length() > 0 && sca[0] == '+')
 
893
  {
 
894
    type = InternationalNumberFormat;
 
895
    sca = sca.substr(1, sca.length() - 1);
 
896
  }
 
897
  else
 
898
    type = UnknownNumberFormat;
 
899
  Parser p(_at->chat("+CSCA=\"" + sca + "\"," + intToStr(type)));
 
900
}
 
901
 
 
902
std::vector<std::string> MeTa::getSMSStoreNames() throw(GsmException)
 
903
{
 
904
  Parser p(_at->chat("+CPMS=?", "+CPMS:"));
 
905
  // only return <mem1> values
 
906
  return p.parseStringList();
 
907
}
 
908
 
 
909
SMSStoreRef MeTa::getSMSStore(std::string storeName) throw(GsmException)
 
910
{
 
911
  for (SMSStoreVector::iterator i = _smsStoreCache.begin();
 
912
       i !=  _smsStoreCache.end(); ++i)
 
913
  {
 
914
    if ((*i)->name() == storeName)
 
915
      return *i;
 
916
  }
 
917
  SMSStoreRef newSs(new SMSStore(storeName, _at, *this));
 
918
  _smsStoreCache.push_back(newSs);
 
919
  return newSs;
 
920
}
 
921
 
 
922
void MeTa::sendSMS(Ref<SMSSubmitMessage> smsMessage) throw(GsmException)
 
923
{
 
924
  smsMessage->setAt(_at);
 
925
  smsMessage->send();
 
926
}
 
927
 
 
928
void MeTa::sendSMSs(Ref<SMSSubmitMessage> smsTemplate, std::string text,
 
929
                    bool oneSMS,
 
930
                    int concatenatedMessageId)
 
931
  throw(GsmException)
 
932
{
 
933
  assert(! smsTemplate.isnull());
 
934
 
 
935
  // compute maximum text length for normal SMSs and concatenated SMSs
 
936
  unsigned int maxTextLength, concMaxTextLength;
 
937
  switch (smsTemplate->dataCodingScheme().getAlphabet())
 
938
  {
 
939
  case DCS_DEFAULT_ALPHABET:
 
940
    maxTextLength = 160;
 
941
    concMaxTextLength = 152;
 
942
    break;
 
943
  case DCS_EIGHT_BIT_ALPHABET:
 
944
    maxTextLength = 140;
 
945
    concMaxTextLength = 134;
 
946
    break;
 
947
  case DCS_SIXTEEN_BIT_ALPHABET:
 
948
    maxTextLength = 70;
 
949
    concMaxTextLength = 67;
 
950
    break;
 
951
  default:
 
952
    throw GsmException(_("unsupported alphabet for SMS"),
 
953
                       ParameterError);
 
954
    break;
 
955
  }
 
956
 
 
957
  // simple case, only send one SMS
 
958
  if (oneSMS || text.length() <= maxTextLength)
 
959
  {
 
960
    if (text.length() > maxTextLength)
 
961
      throw GsmException(_("SMS text is larger than allowed"),
 
962
                         ParameterError);
 
963
    smsTemplate->setUserData(text);
 
964
    sendSMS(smsTemplate);
 
965
  }
 
966
  else                          // send multiple SMSs
 
967
  {
 
968
    if (concatenatedMessageId != -1)
 
969
      maxTextLength = concMaxTextLength;
 
970
 
 
971
    int numMessages = (text.length() + maxTextLength - 1) / maxTextLength;
 
972
    if (numMessages > 255)
 
973
      throw GsmException(_("not more than 255 concatenated SMSs allowed"),
 
974
                         ParameterError);
 
975
    unsigned char numMessage = 0;
 
976
    while (true)
 
977
    {
 
978
      if (concatenatedMessageId != -1)
 
979
      {
 
980
        unsigned char udhs[] = {0x00, 0x03, concatenatedMessageId,
 
981
                                numMessages, ++numMessage};
 
982
        UserDataHeader udh(std::string((char*)udhs, 5));
 
983
        smsTemplate->setUserDataHeader(udh);
 
984
      }
 
985
      smsTemplate->setUserData(text.substr(0, maxTextLength));
 
986
      sendSMS(smsTemplate);
 
987
      if (text.length() < maxTextLength)
 
988
        break;
 
989
      text.erase(0, maxTextLength);
 
990
    }
 
991
  }
 
992
}
 
993
 
 
994
void MeTa::setMessageService(int serviceLevel) throw(GsmException)
 
995
{
 
996
  std::string s;
 
997
  switch (serviceLevel)
 
998
  {
 
999
  case 0:
 
1000
    s = "0";
 
1001
    break;
 
1002
  case 1:
 
1003
    s = "1";
 
1004
    break;
 
1005
  default:
 
1006
    throw GsmException(_("only serviceLevel 0 or 1 supported"),
 
1007
                       ParameterError);
 
1008
  }
 
1009
  // some devices (eg. Origo 900) don't support service level setting
 
1010
  _at->chat("+CSMS=" + s, "+CSMS:", true);
 
1011
}
 
1012
 
 
1013
unsigned int MeTa::getMessageService() throw(GsmException)
 
1014
{
 
1015
  try {
 
1016
    Parser p(_at->chat("+CSMS?", "+CSMS:"));
 
1017
    return p.parseInt();
 
1018
  }
 
1019
  catch (GsmException &e)
 
1020
  {
 
1021
    if (e.getErrorClass() == ParserError) {
 
1022
      return 0;
 
1023
    } else {
 
1024
      throw e;
 
1025
    }
 
1026
  }
 
1027
}
 
1028
 
 
1029
void MeTa::getSMSRoutingToTA(bool &smsRouted,
 
1030
                             bool &cbsRouted,
 
1031
                             bool &statusReportsRouted) throw(GsmException)
 
1032
{
 
1033
  Parser p(_at->chat("+CNMI?", "+CNMI:"));
 
1034
  p.parseInt();
 
1035
  int smsMode = 0;
 
1036
  int cbsMode = 0;
 
1037
  int statMode = 0;
 
1038
  //  int bufferMode;
 
1039
 
 
1040
  //  bufferMode = 0;
 
1041
  if (p.parseComma(true))
 
1042
  {
 
1043
    smsMode = p.parseInt();
 
1044
    if (p.parseComma(true))
 
1045
    {
 
1046
      cbsMode = p.parseInt();
 
1047
      if (p.parseComma(true))
 
1048
      {
 
1049
        statMode = p.parseInt();
 
1050
        /*if (p.parseComma(true))
 
1051
        {
 
1052
          bufferMode = p.parseInt();
 
1053
        }*/
 
1054
      }
 
1055
    }
 
1056
  }
 
1057
 
 
1058
  smsRouted = (smsMode == 2) || (smsMode == 3);
 
1059
  cbsRouted = (cbsMode == 2) || (cbsMode == 3);
 
1060
  statusReportsRouted = (statMode == 1);
 
1061
}
 
1062
 
 
1063
void MeTa::setSMSRoutingToTA(bool enableSMS, bool enableCBS,
 
1064
                             bool enableStatReport,
 
1065
                             bool onlyReceptionIndication)
 
1066
  throw(GsmException)
 
1067
{
 
1068
  bool smsModesSet = false;
 
1069
  bool cbsModesSet = false;
 
1070
  bool statModesSet = false;
 
1071
  bool bufferModesSet = false;
 
1072
 
 
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))
 
1081
  {
 
1082
    smsModes = p.parseIntList();
 
1083
    smsModesSet = true;
 
1084
    if (p.parseComma(true))
 
1085
    {
 
1086
      cbsModes = p.parseIntList();
 
1087
      cbsModesSet = true;
 
1088
      if (p.parseComma(true))
 
1089
      {
 
1090
        statModes = p.parseIntList();
 
1091
        statModesSet = true;
 
1092
        if (p.parseComma(true))
 
1093
        {
 
1094
          bufferModes = p.parseIntList();
 
1095
          bufferModesSet = true;
 
1096
        }
 
1097
      }
 
1098
    }
 
1099
  }
 
1100
 
 
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;
 
1106
  
 
1107
  std::string chatString;
 
1108
    
 
1109
  // now try to set some optimal combination depending on
 
1110
  // ME/TA's capabilities
 
1111
 
 
1112
  // handle modes
 
1113
  if (isSet(modes, 2))
 
1114
    chatString = "2";
 
1115
  else if (isSet(modes, 1))
 
1116
    chatString = "1";
 
1117
  else if (isSet(modes, 0))
 
1118
    chatString = "0";
 
1119
  else if (isSet(modes, 3))
 
1120
    chatString = "3";
 
1121
 
 
1122
  if (onlyReceptionIndication)
 
1123
  {
 
1124
    // handle sms mode
 
1125
    if (enableSMS)
 
1126
    {
 
1127
      if (isSet(smsModes, 1))
 
1128
        chatString += ",1";
 
1129
      else 
 
1130
        throw GsmException(_("cannot route SMS messages to TE"),
 
1131
                           MeTaCapabilityError);
 
1132
    }
 
1133
    else
 
1134
      chatString += ",0";
 
1135
      
 
1136
    // handle cbs mode
 
1137
    if (enableCBS)
 
1138
    {
 
1139
      if (isSet(cbsModes, 1))
 
1140
        chatString += ",1";
 
1141
      else if (isSet(cbsModes, 2))
 
1142
        chatString += ",2";
 
1143
      else 
 
1144
        throw GsmException(_("cannot route cell broadcast messages to TE"),
 
1145
                           MeTaCapabilityError);
 
1146
    }
 
1147
    else
 
1148
      chatString += ",0";
 
1149
 
 
1150
    // handle stat mode
 
1151
    if (enableStatReport)
 
1152
    {
 
1153
      if (isSet(statModes, 2))
 
1154
        chatString += ",2";
 
1155
      else 
 
1156
        throw GsmException(_("cannot route status reports messages to TE"),
 
1157
                           MeTaCapabilityError);
 
1158
    }
 
1159
    else
 
1160
      chatString += ",0";
 
1161
  }
 
1162
  else
 
1163
  {
 
1164
    // handle sms mode
 
1165
    if (enableSMS)
 
1166
    {
 
1167
      if (isSet(smsModes, 2))
 
1168
        chatString += ",2";
 
1169
      else if (isSet(smsModes, 3))
 
1170
        chatString += ",3";
 
1171
      else 
 
1172
        throw GsmException(_("cannot route SMS messages to TE"),
 
1173
                           MeTaCapabilityError);
 
1174
    }
 
1175
    else
 
1176
      chatString += ",0";
 
1177
      
 
1178
    // handle cbs mode
 
1179
    if (enableCBS)
 
1180
    {
 
1181
      if (isSet(cbsModes, 2))
 
1182
        chatString += ",2";
 
1183
      else if (isSet(cbsModes, 3))
 
1184
        chatString += ",3";
 
1185
      else 
 
1186
        throw GsmException(_("cannot route cell broadcast messages to TE"),
 
1187
                           MeTaCapabilityError);
 
1188
    }
 
1189
    else
 
1190
      chatString += ",0";
 
1191
 
 
1192
    // handle stat mode
 
1193
    if (enableStatReport)
 
1194
    {
 
1195
      if (isSet(statModes, 1))
 
1196
        chatString += ",1";
 
1197
      else if (isSet(statModes, 2))
 
1198
        chatString += ",2";
 
1199
      else 
 
1200
        throw GsmException(_("cannot route status report messages to TE"),
 
1201
                           MeTaCapabilityError);
 
1202
    }
 
1203
    else
 
1204
      chatString += ",0";
 
1205
  }
 
1206
 
 
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
 
1209
  if (bufferModesSet)
 
1210
    {
 
1211
      if (isSet(bufferModes, 1))
 
1212
        chatString += ",1";
 
1213
      else
 
1214
        chatString += ",0";
 
1215
    }
 
1216
 
 
1217
  _at->chat("+CNMI=" + chatString);
 
1218
}
 
1219
 
 
1220
bool MeTa::getCallWaitingLockStatus(FacilityClass cl)
 
1221
  throw(GsmException)
 
1222
{
 
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)
 
1230
  {
 
1231
    Parser p(*i);
 
1232
    int enabled = p.parseInt();
 
1233
 
 
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())
 
1238
    {
 
1239
      if (! p.parseComma(true))
 
1240
        return enabled == 1;
 
1241
    }
 
1242
    else
 
1243
      p.parseComma();
 
1244
 
 
1245
    if (p.parseInt() == (int)cl)
 
1246
      return enabled == 1;
 
1247
  }
 
1248
  return false;
 
1249
 
 
1250
}
 
1251
void MeTa::setCallWaitingLockStatus(FacilityClass cl, bool lock)
 
1252
  throw(GsmException)
 
1253
{
 
1254
  if(lock)
 
1255
    _at->chat("+CCWA=0,1," + intToStr((int)cl));
 
1256
  else
 
1257
    _at->chat("+CCWA=0,0," + intToStr((int)cl));
 
1258
}
 
1259
 
 
1260
void MeTa::setCLIRPresentation(bool enable) throw(GsmException)
 
1261
{
 
1262
  if (enable)
 
1263
    _at->chat("+CLIR=1");
 
1264
  else
 
1265
    _at->chat("+CLIR=0");
 
1266
}
 
1267
 
 
1268
int MeTa::getCLIRPresentation() throw(GsmException)
 
1269
{
 
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();
 
1275
}
 
1276