qatresult.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /****************************************************************************
  2. **
  3. ** This file is part of the Qt Extended Opensource Package.
  4. **
  5. ** Copyright (C) 2009 Trolltech ASA.
  6. **
  7. ** Contact: Qt Extended Information (info@qtextended.org)
  8. **
  9. ** This file may be used under the terms of the GNU General Public License
  10. ** version 2.0 as published by the Free Software Foundation and appearing
  11. ** in the file LICENSE.GPL included in the packaging of this file.
  12. **
  13. ** Please review the following information to ensure GNU General Public
  14. ** Licensing requirements will be met:
  15. ** http://www.fsf.org/licensing/licenses/info/GPLv2.html.
  16. **
  17. **
  18. ****************************************************************************/
  19. #include "qatresult.h"
  20. /*!
  21. \class QAtResult
  22. \inpublicgroup QtBaseModule
  23. \brief The QAtResult class provides access to the results of AT modem commands and unsolicited notifications
  24. \ingroup telephony::serial
  25. AT commands that are sent to a modem with QAtChat::chat() result in a QAtResult
  26. object being made available to describe the result of the command when it completes.
  27. The resultCode() method can be used to determine the exact cause of an AT
  28. modem command failure. The content() method can be used to access the
  29. response content that was returned from the command. For complex response
  30. contents, the QAtResultParser class can be used to decode the response.
  31. \sa QAtChat, QAtResultParser
  32. */
  33. class QAtResultPrivate
  34. {
  35. public:
  36. QAtResultPrivate()
  37. {
  38. result = "OK";
  39. resultCode = QAtResult::OK;
  40. verbose = true;
  41. userData = 0;
  42. }
  43. ~QAtResultPrivate()
  44. {
  45. if ( userData )
  46. delete userData;
  47. }
  48. QString result;
  49. QString content;
  50. QAtResult::ResultCode resultCode;
  51. bool verbose;
  52. QAtResult::UserData *userData;
  53. };
  54. /*!
  55. \enum QAtResult::ResultCode
  56. Result codes for AT modem commands.
  57. \value OK Command responded with \c{OK}
  58. \value Connect Command responded with \c{CONNECT}
  59. \value NoCarrier Command responded with \c{NO CARRIER}
  60. \value Error Command responded with \c{ERROR}
  61. \value NoDialtone Command responded with \c{NO DIALTONE}
  62. \value Busy Command responded with \c{BUSY}
  63. \value NoAnswer Command responded with \c{NO ANSWER}
  64. \value Dead The link is dead
  65. \value PhoneFailure GSM 27.07 code 0: phone failure
  66. \value NoConnectionToPhone GSM 27.07 code 1: no connection to phone
  67. \value PhoneAdapterLinkReserved GSM 27.07 code 2: phone-adaptor link reserved
  68. \value OperationNotAllowed GSM 27.07 code 3: operation not allowed
  69. \value OperationNotSupported GSM 27.07 code 4: operation not supported
  70. \value PhSimPinRequired GSM 27.07 code 5: PH-SIM PIN required
  71. \value PhFSimPinRequired GSM 27.07 code 6: PH-FSIM PIN required
  72. \value PhFSimPukRequired GSM 27.07 code 7: PH-FSIM PUK required
  73. \value SimNotInserted GSM 27.07 code 10: SIM not inserted
  74. \value SimPinRequired GSM 27.07 code 11: SIM PIN required
  75. \value SimPukRequired GSM 27.07 code 12: SIM PUK required
  76. \value SimFailure GSM 27.07 code 13: SIM failure
  77. \value SimBusy GSM 27.07 code 14: SIM busy
  78. \value SimWrong GSM 27.07 code 15: SIM wrong
  79. \value IncorrectPassword GSM 27.07 code 16: incorrect password
  80. \value SimPin2Required GSM 27.07 code 17: SIM PIN2 required
  81. \value SimPuk2Required GSM 27.07 code 18: SIM PUK2 required
  82. \value MemoryFull GSM 27.07 code 20: memory full
  83. \value InvalidIndex GSM 27.07 code 21: invalid index
  84. \value NotFound GSM 27.07 code 22: not found
  85. \value MemoryFailure GSM 27.07 code 23: memory failure
  86. \value TextStringTooLong GSM 27.07 code 24: text string too long
  87. \value InvalidCharsInTextString GSM 27.07 code 25: invalid characters in text string
  88. \value DialStringTooLong GSM 27.07 code 26: dial string too long
  89. \value InvalidCharsInDialString GSM 27.07 code 27: invalid characters in dial string
  90. \value NoNetworkService GSM 27.07 code 30: no network service
  91. \value NetworkTimeout GSM 27.07 code 31: network timeout
  92. \value NetworkNotAllowed GSM 27.07 code 32: network not allowed - emergency calls only
  93. \value NetPersPinRequired GSM 27.07 code 40: network personalization PIN required
  94. \value NetPersPukRequired GSM 27.07 code 41: network personalization PUK required
  95. \value NetSubsetPersPinRequired GSM 27.07 code 42: network subset personalization PIN required
  96. \value NetSubsetPersPukRequired GSM 27.07 code 43: network subset personalization PUK required
  97. \value ServProvPersPinRequired GSM 27.07 code 44: service provider personalization PIN required
  98. \value ServProvPersPukRequired GSM 27.07 code 45: service provider personalization PUK required
  99. \value CorpPersPinRequired GSM 27.07 code 46: corporate personalization PIN required
  100. \value CorpPersPukRequired GSM 27.07 code 47: corporate personalization PUK required
  101. \value HiddenKeyRequired GSM 27.07 code 48: hidden key required
  102. \value Unknown GSM 27.07 code 100: unknown
  103. \value IllegalMS GSM 27.07 code 103: Illegal MS
  104. \value IllegalME GSM 27.07 code 106: Illegal ME
  105. \value GPRSServicesNotAllowed GSM 27.07 code 107: GPRS services not allowed
  106. \value PLMNNotAllowed GSM 27.07 code 111: PLMN not allowed
  107. \value LocationAreaNotAllowed GSM 27.07 code 112: Location area not allowed
  108. \value RoamingNotAllowed GSM 27.07 code 113: Roaming not allowed in this location area
  109. \value ServiceOptionNotSupported GSM 27.07 code 132: service option not supported
  110. \value ServiceOptionNotSubscribed GSM 27.07 code 133: service option not subscribed
  111. \value ServiceOptionOutOfOrder GSM 27.07 code 134: service option temporarily out of order
  112. \value UnspecifiedGPRSError GSM 27.07 code 148: unspecified GPRS error
  113. \value PDPAuthenticationFailure GSM 27.07 code 149: PDP authentication failure
  114. \value InvalidMobileClass GSM 27.07 code 150: invalid mobile class
  115. \value VBSVGCSNotSupported GSM 27.07 code 151: VBS/VGCS not supported by the network
  116. \value NoServiceSubscriptionOnSim GSM 27.07 code 152: No service subscription on SIM
  117. \value NoSubscriptionForGroupId GSM 27.07 code 153: No subscription for group ID
  118. \value GroupIdNotActivatedOnSim GSM 27.07 code 154: Group Id not activated on SIM
  119. \value NoMatchingNotification GSM 27.07 code 155: No matching notification
  120. \value VBSVGCSCallAlreadyPresent GSM 27.07 code 156: VBS/VGCS call already present
  121. \value Congestion GSM 27.07 code 157: Congestion
  122. \value NetworkFailure GSM 27.07 code 158: Network failure
  123. \value UplinkBusy GSM 27.07 code 159: Uplink busy
  124. \value NoAccessRightsForSimFile GSM 27.07 code 160: No access rights for SIM file
  125. \value NoSubscriptionForPriority GSM 27.07 code 161: No subscription for priority
  126. \value OperationNotApplicable GSM 27.07 code 162: operation not applicable or not possible
  127. \value MEFailure GSM 27.05 code 300: ME failure
  128. \value SMSServiceOfMEReserved GSM 27.05 code 301: SMS service of ME reserved
  129. \value SMSOperationNotAllowed GSM 27.05 code 302: operation not allowed
  130. \value SMSOperationNotSupported GSM 27.05 code 303: operation not supported
  131. \value InvalidPDUModeParameter GSM 27.05 code 304: invalid PDU mode parameter
  132. \value InvalidTextModeParameter GSM 27.05 code 305: invalid text mode parameter
  133. \value USimNotInserted GSM 27.05 code 310: (U)SIM not inserted
  134. \value USimPinRequired GSM 27.05 code 311: (U)SIM PIN required
  135. \value PHUSimPinRequired GSM 27.05 code 312: PH-(U)SIM PIN required
  136. \value USimFailure GSM 27.05 code 313: (U)SIM failure
  137. \value USimBusy GSM 27.05 code 314: (U)SIM busy
  138. \value USimWrong GSM 27.05 code 315: (U)SIM wrong
  139. \value USimPukRequired GSM 27.05 code 316: (U)SIM PUK required
  140. \value USimPin2Required GSM 27.05 code 317: (U)SIM PIN2 required
  141. \value USimPuk2Required GSM 27.05 code 318: (U)SIM PUK2 required
  142. \value SMSMemoryFailure GSM 27.05 code 320: memory failure
  143. \value InvalidMemoryIndex GSM 27.05 code 321: invalid memory index
  144. \value SMSMemoryFull GSM 27.05 code 322: memory full
  145. \value SMSCAddressUnknown GSM 27.05 code 330: SMSC address unknown
  146. \value SMSNoNetworkService GSM 27.05 code 331: no network service
  147. \value SMSNetworkTimeout GSM 27.05 code 332: network timeout
  148. \value NoCNMAAckExpected GSM 27.05 code 340: no +CNMA acknowledgment expected
  149. \value UnknownError GSM 27.05 code 500: unknown error
  150. */
  151. /*!
  152. \class QAtResult::UserData
  153. \inpublicgroup QtBaseModule
  154. \ingroup telephony::serial
  155. \brief The UserData class provides a mechanism to add user data to a result object via QAtChat::chat().
  156. Usually this class will be inherited, with extra fields added to hold the user data.
  157. \sa QAtChat::chat()
  158. */
  159. /*!
  160. \fn QAtResult::UserData::~UserData()
  161. Destructs a user data object.
  162. */
  163. /*!
  164. Construct a new QAtResult object. The result() will be \c{OK},
  165. and the content() empty.
  166. */
  167. QAtResult::QAtResult()
  168. {
  169. d = new QAtResultPrivate();
  170. }
  171. /*!
  172. Construct a copy of \a other.
  173. */
  174. QAtResult::QAtResult( const QAtResult& other )
  175. {
  176. d = new QAtResultPrivate();
  177. *this = other;
  178. }
  179. /*!
  180. Destruct this QAtResult object.
  181. */
  182. QAtResult::~QAtResult()
  183. {
  184. delete d;
  185. }
  186. /*!
  187. Assign the contents of \a other to this object.
  188. */
  189. QAtResult& QAtResult::operator=( const QAtResult& other )
  190. {
  191. if ( this != &other ) {
  192. d->result = other.d->result;
  193. d->content = other.d->content;
  194. d->resultCode = other.d->resultCode;
  195. }
  196. return *this;
  197. }
  198. /*!
  199. Returns the result line that terminated the command's response.
  200. This is usually a string such as \c{OK}, \c{ERROR}, \c{+CME ERROR: N},
  201. and so on.
  202. The resultCode() function is a better way to determine why a command
  203. failed, but sometimes it is necessary to parse the text result line.
  204. For example, for \c{CONNECT baudrate}, the caller may be interested in
  205. the baud rate.
  206. \sa resultCode(), ok()
  207. */
  208. QString QAtResult::result() const
  209. {
  210. return d->result;
  211. }
  212. /*!
  213. Sets the result line that terminated the command's response to \a value.
  214. This will also update resultCode() to reflect the appropriate code.
  215. \sa result(), resultCode()
  216. */
  217. void QAtResult::setResult( const QString& value )
  218. {
  219. d->result = value;
  220. resultToCode( value );
  221. }
  222. /*!
  223. Returns the content that was returned with an AT command's result.
  224. \sa setContent(), append()
  225. */
  226. QString QAtResult::content() const
  227. {
  228. return d->content;
  229. }
  230. /*!
  231. Sets the content that was returned with an AT command's result to \a value.
  232. \sa content(), append()
  233. */
  234. void QAtResult::setContent( const QString& value )
  235. {
  236. d->content = value;
  237. }
  238. /*!
  239. Append \a value to the current content, after a line terminator.
  240. \sa content(), setContent()
  241. */
  242. void QAtResult::append( const QString& value )
  243. {
  244. if ( d->content.isEmpty() )
  245. d->content = value;
  246. else
  247. d->content = d->content + "\n" + value;
  248. }
  249. /*!
  250. Returns the numeric result code associated with result().
  251. Extended error codes are only possible if the appropriate modem error
  252. mode has been enabled (e.g. with the \c{AT+CMEE=1} command). Otherwise
  253. most errors will simply be reported as QAtResult::Error.
  254. \sa setResultCode(), result(), ok()
  255. */
  256. QAtResult::ResultCode QAtResult::resultCode() const
  257. {
  258. return d->resultCode;
  259. }
  260. /*!
  261. Sets the numeric result code to \a value, and update result()
  262. to reflect the value.
  263. \sa resultCode(), result()
  264. */
  265. void QAtResult::setResultCode( QAtResult::ResultCode value )
  266. {
  267. d->resultCode = value;
  268. d->result = codeToResult( QString() );
  269. d->verbose = true;
  270. }
  271. /*!
  272. Returns true if this result indicates a successful command; false otherwise.
  273. Success is indicated when resultCode() returns either
  274. QAtResult::OK or QAtResult::Connect. All other result
  275. codes indicate failure.
  276. \sa resultCode()
  277. */
  278. bool QAtResult::ok() const
  279. {
  280. return ( d->resultCode == QAtResult::OK ||
  281. d->resultCode == QAtResult::Connect );
  282. }
  283. /*!
  284. Returns a more verbose version of result(), suitable for debug output.
  285. Many modems report extended errors by number (e.g. \c{+CME ERROR: 4}),
  286. which can be difficult to use when diagnosing problems. This function
  287. returns a string that is more suitable for diagnostic output than result().
  288. If result() is already verbose, it will be returned as-is.
  289. \sa result()
  290. */
  291. QString QAtResult::verboseResult() const
  292. {
  293. if ( d->verbose )
  294. return d->result;
  295. else
  296. return codeToResult( d->result );
  297. }
  298. /*!
  299. Returns the user data associated with this result object.
  300. \sa setUserData()
  301. */
  302. QAtResult::UserData *QAtResult::userData() const
  303. {
  304. return d->userData;
  305. }
  306. /*!
  307. Sets the user data associated with this result object to \a value.
  308. \sa userData()
  309. */
  310. void QAtResult::setUserData( QAtResult::UserData *value )
  311. {
  312. if ( d->userData && d->userData != value )
  313. delete d->userData;
  314. d->userData = value;
  315. }
  316. // Table of result codes. Note: these strings are not translatable,
  317. // as they are used to parse values on the wire.
  318. struct QAtCodeInfo
  319. {
  320. QAtResult::ResultCode code;
  321. const char *name;
  322. };
  323. static QAtCodeInfo const basic_codes[] = {
  324. {QAtResult::OK, "OK"}, // no tr
  325. {QAtResult::OK, "0"}, // no tr
  326. {QAtResult::Connect, "CONNECT"}, // no tr
  327. {QAtResult::Connect, "1"}, // no tr
  328. {QAtResult::NoCarrier, "NO CARRIER"}, // no tr
  329. {QAtResult::NoCarrier, "3"}, // no tr
  330. {QAtResult::Error, "ERROR"}, // no tr
  331. {QAtResult::Error, "4"}, // no tr
  332. {QAtResult::NoDialtone, "NO DIALTONE"}, // no tr
  333. {QAtResult::NoDialtone, "6"}, // no tr
  334. {QAtResult::Busy, "BUSY"}, // no tr
  335. {QAtResult::Busy, "7"}, // no tr
  336. {QAtResult::NoAnswer, "NO ANSWER"}, // no tr
  337. {QAtResult::NoAnswer, "8"}, // no tr
  338. {QAtResult::OK, "VCON"} // no tr
  339. };
  340. static QAtCodeInfo const ext_codes[] = {
  341. {QAtResult::PhoneFailure, "phone failure"}, // no tr
  342. {QAtResult::NoConnectionToPhone, "no connection to phone"}, // no tr
  343. {QAtResult::PhoneAdapterLinkReserved, "phone-adaptor link reserved"}, // no tr
  344. {QAtResult::OperationNotAllowed, "operation not allowed"}, // no tr
  345. {QAtResult::OperationNotSupported, "operation not supported"}, // no tr
  346. {QAtResult::PhSimPinRequired, "PH-SIM PIN required"}, // no tr
  347. {QAtResult::PhFSimPinRequired, "PH-FSIM PIN required"}, // no tr
  348. {QAtResult::PhFSimPukRequired, "PH-FSIM PUK required"}, // no tr
  349. {QAtResult::SimNotInserted, "SIM not inserted"}, // no tr
  350. {QAtResult::SimPinRequired, "SIM PIN required"}, // no tr
  351. {QAtResult::SimPukRequired, "SIM PUK required"}, // no tr
  352. {QAtResult::SimFailure, "SIM failure"}, // no tr
  353. {QAtResult::SimBusy, "SIM busy"}, // no tr
  354. {QAtResult::SimWrong, "SIM wrong"}, // no tr
  355. {QAtResult::IncorrectPassword, "incorrect password"}, // no tr
  356. {QAtResult::SimPin2Required, "SIM PIN2 required"}, // no tr
  357. {QAtResult::SimPuk2Required, "SIM PUK2 required"}, // no tr
  358. {QAtResult::MemoryFull, "memory full"}, // no tr
  359. {QAtResult::InvalidIndex, "invalid index"}, // no tr
  360. {QAtResult::NotFound, "not found"}, // no tr
  361. {QAtResult::MemoryFailure, "memory failure"}, // no tr
  362. {QAtResult::TextStringTooLong, "text string too long"}, // no tr
  363. {QAtResult::InvalidCharsInTextString, "invalid characters in text string"}, // no tr
  364. {QAtResult::DialStringTooLong, "dial string too long"}, // no tr
  365. {QAtResult::InvalidCharsInDialString, "invalid characters in dial string"}, // no tr
  366. {QAtResult::NoNetworkService, "no network service"}, // no tr
  367. {QAtResult::NetworkTimeout, "network timeout"}, // no tr
  368. {QAtResult::NetworkNotAllowed, "network not allowed - emergency calls only"}, // no tr
  369. {QAtResult::NetPersPinRequired, "network personalization PIN required"}, // no tr
  370. {QAtResult::NetPersPukRequired, "network personalization PUK required"}, // no tr
  371. {QAtResult::NetSubsetPersPinRequired, "network subset personalization PIN required"}, // no tr
  372. {QAtResult::NetSubsetPersPukRequired, "network subset personalization PUK required"}, // no tr
  373. {QAtResult::ServProvPersPinRequired, "service provider personalization PIN required"}, // no tr
  374. {QAtResult::ServProvPersPukRequired, "service provider personalization PUK required"}, // no tr
  375. {QAtResult::CorpPersPinRequired, "corporate personalization PIN required"}, // no tr
  376. {QAtResult::CorpPersPukRequired, "corporate personalization PUK required"}, // no tr
  377. {QAtResult::HiddenKeyRequired, "hidden key required"}, // no tr
  378. {QAtResult::Unknown, "unknown"}, // no tr
  379. {QAtResult::IllegalMS, "Illegal MS"}, // no tr
  380. {QAtResult::IllegalME, "Illegal ME"}, // no tr
  381. {QAtResult::GPRSServicesNotAllowed , "GPRS services not allowed"}, // no tr
  382. {QAtResult::PLMNNotAllowed, "PLMN not allowed"}, // no tr
  383. {QAtResult::LocationAreaNotAllowed, "Location area not allowed"}, // no tr
  384. {QAtResult::RoamingNotAllowed, "Roaming not allowed in this location area"}, // no tr
  385. {QAtResult::ServiceOptionNotSupported, "service option not supported"}, // no tr
  386. {QAtResult::ServiceOptionNotSubscribed, "requested service option not subscribed"}, // no tr
  387. {QAtResult::ServiceOptionOutOfOrder, "service option temporarily out of order"}, // no tr
  388. {QAtResult::UnspecifiedGPRSError, "unspecified GPRS error"}, // no tr
  389. {QAtResult::PDPAuthenticationFailure, "PDP authentication failure"}, // no tr
  390. {QAtResult::InvalidMobileClass, "invalid mobile class"}, // no tr
  391. // no tr
  392. {QAtResult::VBSVGCSNotSupported, "VBS/VGCS not supported by the network"}, // no tr
  393. {QAtResult::NoServiceSubscriptionOnSim, "No service subscription on SIM"}, // no tr
  394. {QAtResult::NoSubscriptionForGroupId, "No subscription for group ID"}, // no tr
  395. {QAtResult::GroupIdNotActivatedOnSim, "Group Id not activated on SIM"}, // no tr
  396. {QAtResult::NoMatchingNotification, "No matching notification"}, // no tr
  397. {QAtResult::VBSVGCSCallAlreadyPresent, "VBS/VGCS call already present"}, // no tr
  398. {QAtResult::Congestion, "Congestion"}, // no tr
  399. {QAtResult::NetworkFailure, "Network failure"}, // no tr
  400. {QAtResult::UplinkBusy, "Uplink busy"}, // no tr
  401. {QAtResult::NoAccessRightsForSimFile, "No access rights for SIM file"}, // no tr
  402. {QAtResult::NoSubscriptionForPriority, "No subscription for priority"}, // no tr
  403. {QAtResult::OperationNotApplicable, "operation not applicable or not possible"}, // no tr
  404. {QAtResult::MEFailure, "ME failure"}, // no tr
  405. {QAtResult::SMSServiceOfMEReserved, "SMS service of ME reserved"}, // no tr
  406. {QAtResult::SMSOperationNotAllowed, "operation not allowed"}, // no tr
  407. {QAtResult::SMSOperationNotSupported, "operation not supported"}, // no tr
  408. {QAtResult::InvalidPDUModeParameter, "invalid PDU mode parameter"}, // no tr
  409. {QAtResult::InvalidTextModeParameter, "invalid text mode parameter"}, // no tr
  410. {QAtResult::USimNotInserted, "(U)SIM not inserted"}, // no tr
  411. {QAtResult::USimPinRequired, "(U)SIM PIN required"}, // no tr
  412. {QAtResult::PHUSimPinRequired, "PH-(U)SIM PIN required"}, // no tr
  413. {QAtResult::USimFailure, "(U)SIM failure"}, // no tr
  414. {QAtResult::USimBusy, "(U)SIM busy"}, // no tr
  415. {QAtResult::USimWrong, "(U)SIM wrong"}, // no tr
  416. {QAtResult::USimPukRequired, "(U)SIM PUK required"}, // no tr
  417. {QAtResult::USimPin2Required, "(U)SIM PIN2 required"}, // no tr
  418. {QAtResult::USimPuk2Required, "(U)SIM PUK2 required"}, // no tr
  419. {QAtResult::SMSMemoryFailure, "memory failure"}, // no tr
  420. {QAtResult::InvalidMemoryIndex, "invalid memory index"}, // no tr
  421. {QAtResult::MemoryFull, "memory full"}, // no tr
  422. {QAtResult::SMSCAddressUnknown, "SMSC address unknown"}, // no tr
  423. {QAtResult::SMSNoNetworkService, "no network service"}, // no tr
  424. {QAtResult::SMSNetworkTimeout, "network timeout"}, // no tr
  425. {QAtResult::NoCNMAAckExpected, "no +CNMA acknowledgement expected"}, // no tr
  426. {QAtResult::UnknownError, "unknown error"} // no tr
  427. };
  428. #define num_basic_codes ((int)( sizeof(basic_codes) / sizeof(QAtCodeInfo) ))
  429. #define num_ext_codes ((int)( sizeof(ext_codes) / sizeof(QAtCodeInfo) ))
  430. // Extract a numeric error code from the front of "value", or -1 if not.
  431. static int numeric( const QString& value )
  432. {
  433. int posn = 0;
  434. if ( posn >= value.length() || value[posn] < '0' || value[posn] > '9' )
  435. return -1;
  436. int number = 0;
  437. while ( posn < value.length() && value[posn] >= '0' && value[posn] <= '9' )
  438. number = number * 10 + (int)(value[posn++].unicode() - '0');
  439. return number;
  440. }
  441. // Determine if we have a prefix match, ignoring case.
  442. static bool match( const QString& value, const char *prefix )
  443. {
  444. int posn = 0;
  445. while ( posn < value.length() && *prefix != '\0' ) {
  446. int ch1 = value[posn++].unicode();
  447. int ch2 = *prefix++;
  448. if ( ch1 >= 'A' && ch1 <= 'Z' )
  449. ch1 = ch1 - 'A' + 'a';
  450. if ( ch2 >= 'A' && ch2 <= 'Z' )
  451. ch2 = ch2 - 'A' + 'a';
  452. if ( ch1 != ch2 )
  453. return false;
  454. }
  455. if ( *prefix != '\0' )
  456. return false;
  457. return ( posn >= value.length() || value[posn] == ' ' );
  458. }
  459. void QAtResult::resultToCode( const QString& value )
  460. {
  461. QString val;
  462. int index;
  463. // Determine what kind of error report we have.
  464. if ( value.startsWith( "+CME ERROR:", Qt::CaseInsensitive ) ||
  465. value.startsWith( "+EXT ERROR:", Qt::CaseInsensitive ) ) {
  466. // Extended or GPRS error report.
  467. val = value.mid( 11 ).trimmed();
  468. index = numeric( val );
  469. if ( index >= 0 ) {
  470. d->resultCode = (QAtResult::ResultCode)index;
  471. d->verbose = false;
  472. return;
  473. }
  474. } else if ( value.startsWith( "+CMS ERROR:", Qt::CaseInsensitive ) ) {
  475. // Check the SMS codes before the main codes, as there is
  476. // some overlap in the message names.
  477. val = value.mid( 11 ).trimmed();
  478. index = numeric( val );
  479. if ( index >= 0 ) {
  480. d->resultCode = (QAtResult::ResultCode)index;
  481. d->verbose = false;
  482. return;
  483. }
  484. index = 0;
  485. while ( ext_codes[index].code != QAtResult::MEFailure )
  486. ++index;
  487. while ( index < num_ext_codes ) {
  488. if ( match( val, ext_codes[index].name ) ) {
  489. d->resultCode = ext_codes[index].code;
  490. d->verbose = true;
  491. return;
  492. }
  493. ++index;
  494. }
  495. } else {
  496. // Probably something like OK, ERROR, etc. Scan the basic codes only.
  497. for ( index = 0; index < num_basic_codes; ++index ) {
  498. if ( match( value, basic_codes[index].name ) ) {
  499. d->resultCode = basic_codes[index].code;
  500. d->verbose = true;
  501. return;
  502. }
  503. }
  504. d->resultCode = QAtResult::UnknownError;
  505. d->verbose = true;
  506. }
  507. // Scan the extended code list for a match.
  508. for ( index = 0; index < num_ext_codes; ++index ) {
  509. if ( match( val, ext_codes[index].name ) ) {
  510. d->resultCode = ext_codes[index].code;
  511. d->verbose = true;
  512. return;
  513. }
  514. }
  515. d->resultCode = QAtResult::UnknownError;
  516. d->verbose = true;
  517. }
  518. QString QAtResult::codeToResult( const QString& defaultValue ) const
  519. {
  520. int index;
  521. for ( index = 0; index < num_basic_codes; ++index ) {
  522. if ( basic_codes[index].code == d->resultCode ) {
  523. return basic_codes[index].name;
  524. }
  525. }
  526. for ( index = 0; index < num_ext_codes; ++index ) {
  527. if ( ext_codes[index].code == d->resultCode ) {
  528. if ( d->resultCode >= 300 && d->resultCode <= 500 )
  529. return QString( "+CMS ERROR: " ) + ext_codes[index].name;
  530. else
  531. return QString( "+CME ERROR: " ) + ext_codes[index].name;
  532. }
  533. }
  534. if ( defaultValue.isEmpty() ) {
  535. if ( ((int)d->resultCode) >= 300 &&
  536. ((int)d->resultCode) <= 500 ) {
  537. return "+CMS ERROR: " + QString::number( d->resultCode );
  538. } else {
  539. return "+CME ERROR: " + QString::number( d->resultCode );
  540. }
  541. } else {
  542. return defaultValue;
  543. }
  544. }