r3288 - in trunk/src/host/qemu-neo1973: . phonesim phonesim/lib phonesim/lib/serial phonesim/lib/wap

andrew at sita.openmoko.org andrew at sita.openmoko.org
Fri Oct 26 19:28:28 CEST 2007


Author: andrew
Date: 2007-10-26 19:27:58 +0200 (Fri, 26 Oct 2007)
New Revision: 3288

Added:
   trunk/src/host/qemu-neo1973/phonesim/
   trunk/src/host/qemu-neo1973/phonesim/DESCRIPTION
   trunk/src/host/qemu-neo1973/phonesim/GSMSpecification.xml
   trunk/src/host/qemu-neo1973/phonesim/Makefile
   trunk/src/host/qemu-neo1973/phonesim/attranslator.cpp
   trunk/src/host/qemu-neo1973/phonesim/attranslator.h
   trunk/src/host/qemu-neo1973/phonesim/control.cpp
   trunk/src/host/qemu-neo1973/phonesim/control.h
   trunk/src/host/qemu-neo1973/phonesim/controlbase.ui
   trunk/src/host/qemu-neo1973/phonesim/gsm-xml.pl
   trunk/src/host/qemu-neo1973/phonesim/gsmitem.cpp
   trunk/src/host/qemu-neo1973/phonesim/gsmitem.h
   trunk/src/host/qemu-neo1973/phonesim/gsmspec.cpp
   trunk/src/host/qemu-neo1973/phonesim/gsmspec.h
   trunk/src/host/qemu-neo1973/phonesim/lib/
   trunk/src/host/qemu-neo1973/phonesim/lib/DESCRIPTION
   trunk/src/host/qemu-neo1973/phonesim/lib/callmanager.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/callmanager.h
   trunk/src/host/qemu-neo1973/phonesim/lib/hardwaremanipulator.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/hardwaremanipulator.h
   trunk/src/host/qemu-neo1973/phonesim/lib/inheritedshareddata.h
   trunk/src/host/qemu-neo1973/phonesim/lib/lib.pro
   trunk/src/host/qemu-neo1973/phonesim/lib/phonesim.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/phonesim.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qcbsmessage.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/qcbsmessage.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qcontent.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qcontentfilter.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qcontentset.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qcontentsortcriteria.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qdrmcontent.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qdrmrights.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qlog.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qmimetype.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qsimcommand.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/qsimcommand.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qsimcontrolevent.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/qsimcontrolevent.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qsimenvelope.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/qsimenvelope.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qsimterminalresponse.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/qsimterminalresponse.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage_p.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessagelist.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessagelist.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qtimestring.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaglobal.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaipcadaptor.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaipcmarshal.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qtopialog-config.h
   trunk/src/host/qemu-neo1973/phonesim/lib/qtopialog.h
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresult.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresult.h
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresultparser.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresultparser.h
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.h
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/qgsmcodec.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/serial/qgsmcodec.h
   trunk/src/host/qemu-neo1973/phonesim/lib/server.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/server.h
   trunk/src/host/qemu-neo1973/phonesim/lib/simapplication.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/simapplication.h
   trunk/src/host/qemu-neo1973/phonesim/lib/simfilesystem.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/simfilesystem.h
   trunk/src/host/qemu-neo1973/phonesim/lib/wap/
   trunk/src/host/qemu-neo1973/phonesim/lib/wap/qwsppdu.cpp
   trunk/src/host/qemu-neo1973/phonesim/lib/wap/qwsppdu.h
   trunk/src/host/qemu-neo1973/phonesim/main.cpp
   trunk/src/host/qemu-neo1973/phonesim/peers.xml
   trunk/src/host/qemu-neo1973/phonesim/phonesim.pro
Log:
Import a phonesim version modified to be buildable out-of-qtopia-tree.


Added: trunk/src/host/qemu-neo1973/phonesim/DESCRIPTION
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/DESCRIPTION	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/DESCRIPTION	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1 @@
+Phone simulator for modem testing, compiled to run on host architecture.

Added: trunk/src/host/qemu-neo1973/phonesim/GSMSpecification.xml
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/GSMSpecification.xml	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/GSMSpecification.xml	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,4685 @@
+<gsm>
+<spec>
+    <command>AT+CGMI</command>
+    <profile>Request manufacturer identification </profile>
+    <description>Execution command causes the TA to return one or more lines of information text [manufacturer], determined by the MT manufacturer, which is intended to permit the user of the TA to identify the manufacturer of the MT to which it is connected to. Typically, the text will consist of a single line containing the name of the manufacturer, but manufacturers may choose to provide more information if desired. Refer subclause 9.2 for possible [err] values.
+Defined values
+[manufacturer]: the total number of characters, including line terminators, in the information text shall not exceed 2048 characters.
+Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CGMI=?</command>
+    <profile>Request manufacturer identification (Query all)</profile>
+    <description>Execution command causes the TA to return one or more lines of information text [manufacturer], determined by the MT manufacturer, which is intended to permit the user of the TA to identify the manufacturer of the MT to which it is connected to. Typically, the text will consist of a single line containing the name of the manufacturer, but manufacturers may choose to provide more information if desired. Refer subclause 9.2 for possible [err] values.
+Defined values
+[manufacturer]: the total number of characters, including line terminators, in the information text shall not exceed 2048 characters.
+Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CGMM</command>
+    <profile>Request model identification </profile>
+    <description>Execution command causes the TA to return one or more lines of information text [model], determined by the MT manufacturer, which is intended to permit the user of the TA to identify the specific model of the MT to which it is connected to. Typically, the text will consist of a single line containing the name of the product, but manufacturers may choose to provide more information if desired. Refer to subclause 9.2 for possible [err] values.
+Defined values
+[model]: the total number of characters, including line terminators, in the information text shall not exceed 2048 characters.
+Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CGMM=?</command>
+    <profile>Request model identification (Query all)</profile>
+    <description>Execution command causes the TA to return one or more lines of information text [model], determined by the MT manufacturer, which is intended to permit the user of the TA to identify the specific model of the MT to which it is connected to. Typically, the text will consist of a single line containing the name of the product, but manufacturers may choose to provide more information if desired. Refer to subclause 9.2 for possible [err] values.
+Defined values
+[model]: the total number of characters, including line terminators, in the information text shall not exceed 2048 characters.
+Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CGMR</command>
+    <profile>Request revision identification </profile>
+    <description>Execution command causes the TA to return one or more lines of information text [revision], determined by the MT manufacturer, which is intended to permit the user of the TA to identify the version, revision level or date, or other pertinent information of the MT to which it is connected to. Typically, the text will consist of a single line containing the version of the product, but manufacturers may choose to provide more information if desired. Refer subclause 9.2 for possible [err] values.
+Defined values
+[revision]: the total number of characters, including line terminators, in the information text shall not exceed 2048 characters.
+Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CGMR=?</command>
+    <profile>Request revision identification (Query all)</profile>
+    <description>Execution command causes the TA to return one or more lines of information text [revision], determined by the MT manufacturer, which is intended to permit the user of the TA to identify the version, revision level or date, or other pertinent information of the MT to which it is connected to. Typically, the text will consist of a single line containing the version of the product, but manufacturers may choose to provide more information if desired. Refer subclause 9.2 for possible [err] values.
+Defined values
+[revision]: the total number of characters, including line terminators, in the information text shall not exceed 2048 characters.
+Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CGSN</command>
+    <profile>Request product serial number identification </profile>
+    <description>Execution command causes the TA to return one or more lines of information text [sn], determined by the MT manufacturer, which is intended to permit the user of the TA to identify the individual MT to which it is connected to. Typically, the text will consist of a single line containing the IMEI (International Mobile station Equipment Identity; refer 3GPP TS 23.003 [7]) number of the MT, but manufacturers may choose to provide more information if desired. Refer subclause 9.2 for possible [err] values.
+Defined values
+[sn]: the total number of characters, including line terminators, in the information text shall not exceed 2048 characters.
+Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CGSN=?</command>
+    <profile>Request product serial number identification (Query all)</profile>
+    <description>Execution command causes the TA to return one or more lines of information text [sn], determined by the MT manufacturer, which is intended to permit the user of the TA to identify the individual MT to which it is connected to. Typically, the text will consist of a single line containing the IMEI (International Mobile station Equipment Identity; refer 3GPP TS 23.003 [7]) number of the MT, but manufacturers may choose to provide more information if desired. Refer subclause 9.2 for possible [err] values.
+Defined values
+[sn]: the total number of characters, including line terminators, in the information text shall not exceed 2048 characters.
+Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CSCS=</command>
+    <profile>Select TE character set (Assign)</profile>
+    <description>Set command informs TA which character set [chset] is used by the TE. TA is then able to convert character strings correctly between TE and MT character sets.
+When TA‑TE interface is set to 8‑bit operation and used TE alphabet is 7‑bit, the highest bit shall be set to zero.
+NOTE 1:	It is manufacturer specific how the internal alphabet of MT is converted to/from the TE alphabet.
+Read command shows current setting and test command displays conversion schemes implemented in the TA.
+Defined values
+[chset] (conversion schemes not listed here can be defined by manufacturers):
+'GSM'	GSM 7 bit default alphabet (3GPP TS 23.038 [25]); this setting causes easily software flow control (XON/XOFF) problems.
+'HEX'	Character strings consist only of hexadecimal numbers from 00 to FF; e.g. '032FE6' equals three 8-bit characters with decimal values 3, 47 and 230; no conversions to the original MT character set shall be done.
+NOTE 2:	If MT is using GSM 7 bit default alphabet, its characters shall be padded with 8th bit (zero) before converting them to hexadecimal numbers (i.e. no SMS‑style packing of 7‑bit alphabet).
+'IRA'	International reference alphabet (ITU‑T T.50 [13]).
+'PCCPxxx'	PC character set Code Page xxx
+'PCDN'	PC Danish/Norwegian character set
+'UCS2'	16-bit universal multiple-octet coded character set (ISO/IEC10646 [32]); UCS2 character strings are converted to hexadecimal numbers from 0000 to FFFF; e.g. '004100620063' equals three 16-bit characters with decimal values 65, 98 and 99.
+'UTF-8'	Octet (8-bit) lossless encoding of UCS characters (RFC 3629 [69]); UTF-8 encodes each UCS character as a variable number of octets, where the number of octets depends on the integer value assigned to the UCS character. The input format shall be a stream of octets. It shall not be converted to hexadecimal numbers as in 'HEX' or 'UCS2'. This character set requires an 8-bit TA – TE interface.
+'8859-n'	ISO 8859 Latin n (1‑6) character set
+'8859-C'	ISO 8859 Latin/Cyrillic character set
+'8859-A'	ISO 8859 Latin/Arabic character set
+'8859-G'	ISO 8859 Latin/Greek character set
+'8859-H'	ISO 8859 Latin/Hebrew character set
+</description>
+</spec>
+<spec>
+    <command>AT+CSCS?</command>
+    <profile>Select TE character set (Query)</profile>
+    <description>Set command informs TA which character set [chset] is used by the TE. TA is then able to convert character strings correctly between TE and MT character sets.
+When TA‑TE interface is set to 8‑bit operation and used TE alphabet is 7‑bit, the highest bit shall be set to zero.
+NOTE 1:	It is manufacturer specific how the internal alphabet of MT is converted to/from the TE alphabet.
+Read command shows current setting and test command displays conversion schemes implemented in the TA.
+Defined values
+[chset] (conversion schemes not listed here can be defined by manufacturers):
+'GSM'	GSM 7 bit default alphabet (3GPP TS 23.038 [25]); this setting causes easily software flow control (XON/XOFF) problems.
+'HEX'	Character strings consist only of hexadecimal numbers from 00 to FF; e.g. '032FE6' equals three 8-bit characters with decimal values 3, 47 and 230; no conversions to the original MT character set shall be done.
+NOTE 2:	If MT is using GSM 7 bit default alphabet, its characters shall be padded with 8th bit (zero) before converting them to hexadecimal numbers (i.e. no SMS‑style packing of 7‑bit alphabet).
+'IRA'	International reference alphabet (ITU‑T T.50 [13]).
+'PCCPxxx'	PC character set Code Page xxx
+'PCDN'	PC Danish/Norwegian character set
+'UCS2'	16-bit universal multiple-octet coded character set (ISO/IEC10646 [32]); UCS2 character strings are converted to hexadecimal numbers from 0000 to FFFF; e.g. '004100620063' equals three 16-bit characters with decimal values 65, 98 and 99.
+'UTF-8'	Octet (8-bit) lossless encoding of UCS characters (RFC 3629 [69]); UTF-8 encodes each UCS character as a variable number of octets, where the number of octets depends on the integer value assigned to the UCS character. The input format shall be a stream of octets. It shall not be converted to hexadecimal numbers as in 'HEX' or 'UCS2'. This character set requires an 8-bit TA – TE interface.
+'8859-n'	ISO 8859 Latin n (1‑6) character set
+'8859-C'	ISO 8859 Latin/Cyrillic character set
+'8859-A'	ISO 8859 Latin/Arabic character set
+'8859-G'	ISO 8859 Latin/Greek character set
+'8859-H'	ISO 8859 Latin/Hebrew character set
+</description>
+</spec>
+<spec>
+    <command>AT+CSCS=?</command>
+    <profile>Select TE character set (Query all)</profile>
+    <description>Set command informs TA which character set [chset] is used by the TE. TA is then able to convert character strings correctly between TE and MT character sets.
+When TA‑TE interface is set to 8‑bit operation and used TE alphabet is 7‑bit, the highest bit shall be set to zero.
+NOTE 1:	It is manufacturer specific how the internal alphabet of MT is converted to/from the TE alphabet.
+Read command shows current setting and test command displays conversion schemes implemented in the TA.
+Defined values
+[chset] (conversion schemes not listed here can be defined by manufacturers):
+'GSM'	GSM 7 bit default alphabet (3GPP TS 23.038 [25]); this setting causes easily software flow control (XON/XOFF) problems.
+'HEX'	Character strings consist only of hexadecimal numbers from 00 to FF; e.g. '032FE6' equals three 8-bit characters with decimal values 3, 47 and 230; no conversions to the original MT character set shall be done.
+NOTE 2:	If MT is using GSM 7 bit default alphabet, its characters shall be padded with 8th bit (zero) before converting them to hexadecimal numbers (i.e. no SMS‑style packing of 7‑bit alphabet).
+'IRA'	International reference alphabet (ITU‑T T.50 [13]).
+'PCCPxxx'	PC character set Code Page xxx
+'PCDN'	PC Danish/Norwegian character set
+'UCS2'	16-bit universal multiple-octet coded character set (ISO/IEC10646 [32]); UCS2 character strings are converted to hexadecimal numbers from 0000 to FFFF; e.g. '004100620063' equals three 16-bit characters with decimal values 65, 98 and 99.
+'UTF-8'	Octet (8-bit) lossless encoding of UCS characters (RFC 3629 [69]); UTF-8 encodes each UCS character as a variable number of octets, where the number of octets depends on the integer value assigned to the UCS character. The input format shall be a stream of octets. It shall not be converted to hexadecimal numbers as in 'HEX' or 'UCS2'. This character set requires an 8-bit TA – TE interface.
+'8859-n'	ISO 8859 Latin n (1‑6) character set
+'8859-C'	ISO 8859 Latin/Cyrillic character set
+'8859-A'	ISO 8859 Latin/Arabic character set
+'8859-G'	ISO 8859 Latin/Greek character set
+'8859-H'	ISO 8859 Latin/Hebrew character set
+</description>
+</spec>
+<spec>
+    <command>AT+CIMI</command>
+    <profile>Request international mobile subscriber identity </profile>
+    <description>Execution command causes the TA to return [IMSI], which is intended to permit the TE to identify the individual SIM card or active application in the UICC (GSM or USIM) which is attached to MT. Refer subclause 9.2 for possible [err] values. 
+Defined values
+[IMSI]: International Mobile Subscriber Identity (string without double quotes)
+</description>
+</spec>
+<spec>
+    <command>AT+CIMI=?</command>
+    <profile>Request international mobile subscriber identity (Query all)</profile>
+    <description>Execution command causes the TA to return [IMSI], which is intended to permit the TE to identify the individual SIM card or active application in the UICC (GSM or USIM) which is attached to MT. Refer subclause 9.2 for possible [err] values. 
+Defined values
+[IMSI]: International Mobile Subscriber Identity (string without double quotes)
+</description>
+</spec>
+<spec>
+    <command>AT+CMUX=</command>
+    <profile>Multiplexing mode (Assign)</profile>
+    <description>This command is used to enable/disable the 3GPP TS 27.010 [45] multiplexing protocol control channel. Refer to subclause 9.2 for possible [err] values. The AT command sets parameters for the Control Channel. If the parameters are left out, the default value is used. 
+Read command returns the current mode and the settings.
+Test command returns the supported modes and parameters. 
+It is recommended that the MT/TA/TE should autobaud to the +CMUX command up to and including an interface speed of 9600 bits/s. 
+The OK or +CME ERROR: [err] response is returned at the speed of the +CMUX command prior to entering [mode].
+It is recommended that whenever the multiplexer control channel is released the MT/TA/TE should assume an interface rate of up to and including 9600 bits/s for auto bauding purposes irrespective of any previous higher speed having been selected.
+If a +CMUX command is issued whilst in any multiplexer mode then that +CMUX command shall be ignored and the MT/TA shall return an +CME ERROR: [err] response.
+Defined values
+[operation] (multiplexer Transparency Mechanism)
+0	 Basic option
+1	 Advanced option
+[subset]:
+	This parameter defines the way in which the multiplexer control channel is set up. A virtual channel may subsequently be set up differently but in the absence of any negotiation for the settings of a virtual channel, the virtual channel shall be set up according to the control channel [subset] setting.
+0	UIH frames used only
+1	UI frames used only
+2	I frames used only
+Default value: 0
+[port_speed] (transmission rate):
+1	9 600 bit/s
+2	19 200 bit/s
+3	38 400 bit/s
+4	57 600 bit/s
+5	115 200 bit/s
+6	230 400 bits/s
+[N1] (maximum frame size):
+1- 32768
+default Value : 31 (64 if Advanced option is used)
+[T1] (acknowledgement timer in units of ten milliseconds):
+1-255, where 10 is default (100 ms) 
+[N2] (maximum number of re-transmissions):
+0-100, where 3 is default
+[T2] (response timer for the multiplexer control channel in units of ten milliseconds):
+2-255, where 30 is default (300 ms)
+NOTE:	T2 must be longer than T1.
+[T3] (wake up response timer in seconds):
+1-255, where 10 is default 
+[k] (window size, for Advanced operation with Error Recovery options):
+1-7, where 2 is default
+</description>
+</spec>
+<spec>
+    <command>AT+CMUX?</command>
+    <profile>Multiplexing mode (Query)</profile>
+    <description>This command is used to enable/disable the 3GPP TS 27.010 [45] multiplexing protocol control channel. Refer to subclause 9.2 for possible [err] values. The AT command sets parameters for the Control Channel. If the parameters are left out, the default value is used. 
+Read command returns the current mode and the settings.
+Test command returns the supported modes and parameters. 
+It is recommended that the MT/TA/TE should autobaud to the +CMUX command up to and including an interface speed of 9600 bits/s. 
+The OK or +CME ERROR: [err] response is returned at the speed of the +CMUX command prior to entering [mode].
+It is recommended that whenever the multiplexer control channel is released the MT/TA/TE should assume an interface rate of up to and including 9600 bits/s for auto bauding purposes irrespective of any previous higher speed having been selected.
+If a +CMUX command is issued whilst in any multiplexer mode then that +CMUX command shall be ignored and the MT/TA shall return an +CME ERROR: [err] response.
+Defined values
+[operation] (multiplexer Transparency Mechanism)
+0	 Basic option
+1	 Advanced option
+[subset]:
+	This parameter defines the way in which the multiplexer control channel is set up. A virtual channel may subsequently be set up differently but in the absence of any negotiation for the settings of a virtual channel, the virtual channel shall be set up according to the control channel [subset] setting.
+0	UIH frames used only
+1	UI frames used only
+2	I frames used only
+Default value: 0
+[port_speed] (transmission rate):
+1	9 600 bit/s
+2	19 200 bit/s
+3	38 400 bit/s
+4	57 600 bit/s
+5	115 200 bit/s
+6	230 400 bits/s
+[N1] (maximum frame size):
+1- 32768
+default Value : 31 (64 if Advanced option is used)
+[T1] (acknowledgement timer in units of ten milliseconds):
+1-255, where 10 is default (100 ms) 
+[N2] (maximum number of re-transmissions):
+0-100, where 3 is default
+[T2] (response timer for the multiplexer control channel in units of ten milliseconds):
+2-255, where 30 is default (300 ms)
+NOTE:	T2 must be longer than T1.
+[T3] (wake up response timer in seconds):
+1-255, where 10 is default 
+[k] (window size, for Advanced operation with Error Recovery options):
+1-7, where 2 is default
+</description>
+</spec>
+<spec>
+    <command>AT+CMUX=?</command>
+    <profile>Multiplexing mode (Query all)</profile>
+    <description>This command is used to enable/disable the 3GPP TS 27.010 [45] multiplexing protocol control channel. Refer to subclause 9.2 for possible [err] values. The AT command sets parameters for the Control Channel. If the parameters are left out, the default value is used. 
+Read command returns the current mode and the settings.
+Test command returns the supported modes and parameters. 
+It is recommended that the MT/TA/TE should autobaud to the +CMUX command up to and including an interface speed of 9600 bits/s. 
+The OK or +CME ERROR: [err] response is returned at the speed of the +CMUX command prior to entering [mode].
+It is recommended that whenever the multiplexer control channel is released the MT/TA/TE should assume an interface rate of up to and including 9600 bits/s for auto bauding purposes irrespective of any previous higher speed having been selected.
+If a +CMUX command is issued whilst in any multiplexer mode then that +CMUX command shall be ignored and the MT/TA shall return an +CME ERROR: [err] response.
+Defined values
+[operation] (multiplexer Transparency Mechanism)
+0	 Basic option
+1	 Advanced option
+[subset]:
+	This parameter defines the way in which the multiplexer control channel is set up. A virtual channel may subsequently be set up differently but in the absence of any negotiation for the settings of a virtual channel, the virtual channel shall be set up according to the control channel [subset] setting.
+0	UIH frames used only
+1	UI frames used only
+2	I frames used only
+Default value: 0
+[port_speed] (transmission rate):
+1	9 600 bit/s
+2	19 200 bit/s
+3	38 400 bit/s
+4	57 600 bit/s
+5	115 200 bit/s
+6	230 400 bits/s
+[N1] (maximum frame size):
+1- 32768
+default Value : 31 (64 if Advanced option is used)
+[T1] (acknowledgement timer in units of ten milliseconds):
+1-255, where 10 is default (100 ms) 
+[N2] (maximum number of re-transmissions):
+0-100, where 3 is default
+[T2] (response timer for the multiplexer control channel in units of ten milliseconds):
+2-255, where 30 is default (300 ms)
+NOTE:	T2 must be longer than T1.
+[T3] (wake up response timer in seconds):
+1-255, where 10 is default 
+[k] (window size, for Advanced operation with Error Recovery options):
+1-7, where 2 is default
+</description>
+</spec>
+<spec>
+    <command>AT+CSTA=</command>
+    <profile>Select type of address (Assign)</profile>
+    <description>Set command selects the type of number for further dialling commands (D) according to GSM/UMTS specifications. Test command returns values supported a compound value.
+Defined values
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+</description>
+</spec>
+<spec>
+    <command>AT+CSTA?</command>
+    <profile>Select type of address (Query)</profile>
+    <description>Set command selects the type of number for further dialling commands (D) according to GSM/UMTS specifications. Test command returns values supported a compound value.
+Defined values
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+</description>
+</spec>
+<spec>
+    <command>AT+CSTA=?</command>
+    <profile>Select type of address (Query all)</profile>
+    <description>Set command selects the type of number for further dialling commands (D) according to GSM/UMTS specifications. Test command returns values supported a compound value.
+Defined values
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+</description>
+</spec>
+<spec>
+    <command>AT+CMOD=</command>
+    <profile>Call mode (Assign)</profile>
+    <description>Set command selects the call mode of further dialling commands (D) or for next answering command (A). Mode can be either single or alternating (in the present document, terms 'alternating mode' and 'alternating call' refer to all GSM/UMTS bearer and teleservices that incorporate more than one basic service (voice, data, fax) within one call). When single mode is selected the call originating and hangup procedures are similar to procedures specified in ITU‑T Recommendations V.250 [14], T.31 [11] and T.32 [12]. In GSM/UMTS there can be voice followed by data (refer 3GPP TS 22.002 [1]), alternating voice/data (refer 3GPP TS 22.002 [1]) and alternating voice/fax calls (refer 3GPP TS 22.003 [2]). Refer next two subclauses for alternating call control methods.
+Test command returns values supported as a compound value.
+NOTE:	+CMOD shall be set to zero after a successfully completed alternating mode call. It shall be set to zero also after a failed answering. The power‑up, factory (:F) and user resets (Z) shall also set the value to zero. This reduces the possibility that alternating mode calls are originated or answered accidentally.
+Defined values
+[mode]:
+0	single mode
+1	alternating voice/fax (teleservice 61)
+2	alternating voice/data (bearer service 61)
+3	voice followed by data (bearer service 81)
+also all other values below 128 are reserved by the present document
+</description>
+</spec>
+<spec>
+    <command>AT+CMOD?</command>
+    <profile>Call mode (Query)</profile>
+    <description>Set command selects the call mode of further dialling commands (D) or for next answering command (A). Mode can be either single or alternating (in the present document, terms 'alternating mode' and 'alternating call' refer to all GSM/UMTS bearer and teleservices that incorporate more than one basic service (voice, data, fax) within one call). When single mode is selected the call originating and hangup procedures are similar to procedures specified in ITU‑T Recommendations V.250 [14], T.31 [11] and T.32 [12]. In GSM/UMTS there can be voice followed by data (refer 3GPP TS 22.002 [1]), alternating voice/data (refer 3GPP TS 22.002 [1]) and alternating voice/fax calls (refer 3GPP TS 22.003 [2]). Refer next two subclauses for alternating call control methods.
+Test command returns values supported as a compound value.
+NOTE:	+CMOD shall be set to zero after a successfully completed alternating mode call. It shall be set to zero also after a failed answering. The power‑up, factory (:F) and user resets (Z) shall also set the value to zero. This reduces the possibility that alternating mode calls are originated or answered accidentally.
+Defined values
+[mode]:
+0	single mode
+1	alternating voice/fax (teleservice 61)
+2	alternating voice/data (bearer service 61)
+3	voice followed by data (bearer service 81)
+also all other values below 128 are reserved by the present document
+</description>
+</spec>
+<spec>
+    <command>AT+CMOD=?</command>
+    <profile>Call mode (Query all)</profile>
+    <description>Set command selects the call mode of further dialling commands (D) or for next answering command (A). Mode can be either single or alternating (in the present document, terms 'alternating mode' and 'alternating call' refer to all GSM/UMTS bearer and teleservices that incorporate more than one basic service (voice, data, fax) within one call). When single mode is selected the call originating and hangup procedures are similar to procedures specified in ITU‑T Recommendations V.250 [14], T.31 [11] and T.32 [12]. In GSM/UMTS there can be voice followed by data (refer 3GPP TS 22.002 [1]), alternating voice/data (refer 3GPP TS 22.002 [1]) and alternating voice/fax calls (refer 3GPP TS 22.003 [2]). Refer next two subclauses for alternating call control methods.
+Test command returns values supported as a compound value.
+NOTE:	+CMOD shall be set to zero after a successfully completed alternating mode call. It shall be set to zero also after a failed answering. The power‑up, factory (:F) and user resets (Z) shall also set the value to zero. This reduces the possibility that alternating mode calls are originated or answered accidentally.
+Defined values
+[mode]:
+0	single mode
+1	alternating voice/fax (teleservice 61)
+2	alternating voice/data (bearer service 61)
+3	voice followed by data (bearer service 81)
+also all other values below 128 are reserved by the present document
+</description>
+</spec>
+<spec>
+    <command>AT+CHUP</command>
+    <profile>Hangup call </profile>
+    <description>Execution command causes the TA to hangup the current GSM/UMTS call of the MT.
+NOTE:	The purpose of this command is not to replace the V.250 [14] command H, but to give an assured procedure to terminate an alternating mode call. Refer next subclause.
+</description>
+</spec>
+<spec>
+    <command>AT+CHUP=?</command>
+    <profile>Hangup call (Query all)</profile>
+    <description>Execution command causes the TA to hangup the current GSM/UMTS call of the MT.
+NOTE:	The purpose of this command is not to replace the V.250 [14] command H, but to give an assured procedure to terminate an alternating mode call. Refer next subclause.
+</description>
+</spec>
+<spec>
+    <command>AT+CBST=</command>
+    <profile>Select bearer service type (Assign)</profile>
+    <description>Set command selects the bearer service [name] with data rate [speed], and the connection element [ce] to be used when data calls are originated (refer 3GPP TS 22.002 [1]). Values may also be used during mobile terminated data call setup, especially in case of single numbering scheme calls (refer +CSNS).
+Test command returns values supported as compound values.
+Defined values
+NOTE:	The default values of the subparameters are manufacturer specific since they depend on the purpose of the device and data services provided by it. Not all combinations of these subparameters are supported by GSM/UMTS (refer 3GPP TS 22.002 [1]).
+[speed]:
+0	autobauding (automatic selection of the speed; this setting is possible in case of 3.1 kHz modem and non-transparent service)
+1	300 bps (V.21)
+2	1200 bps (V.22)
+3	1200/75 bps (V.23)
+4	2400 bps (V.22bis)
+5	2400 bps (V.26ter)
+6	4800 bps (V.32)
+7	9600 bps (V.32)
+12	9600 bps (V.34)
+14	14400 bps (V.34)
+15	19200 bps (V.34)
+16	28800 bps (V.34)
+17	33600 bps (V.34)
+34	1200 bps (V.120)
+36	2400 bps (V.120)
+38	4800 bps (V.120)
+39	9600 bps (V.120)
+43	14400 bps (V.120)
+47	19200 bps (V.120)
+48	28800 bps (V.120)
+49	38400 bps (V.120)
+50	48000 bps (V.120)
+51	56000 bps (V.120)
+65	300 bps (V.110)
+66	1200 bps (V.110)
+68	2400 bps (V.110 or X.31 flag stuffing)
+70	4800 bps (V.110 or X.31 flag stuffing)
+71	9600 bps (V.110 or X.31 flag stuffing)
+75	14400 bps (V.110 or X.31 flag stuffing)
+79	19200 bps (V.110 or X.31 flag stuffing)
+80	28800 bps (V.110 or X.31 flag stuffing)
+81	38400 bps (V.110 or X.31 flag stuffing)
+82	48000 bps (V.110 or X.31 flag stuffing)
+83	56000 bps (V.110 or X.31 flag stuffing; this setting can be used in conjunction with asynchronous non-transparent UDI or RDI service in order to get FTM)
+84	64000 bps (X.31 flag stuffing; this setting can be used in conjunction with asynchronous non-transparent UDI service in order to get FTM)
+115	56000 bps (bit transparent)
+116	64000 bps (bit transparent)
+120	32000 bps (PIAFS32k)
+121	64000 bps (PIAFS64k)
+130	28800 bps (multimedia)
+131	32000 bps (multimedia)
+132	33600 bps (multimedia)
+133	56000 bps (multimedia)
+134	64000 bps (multimedia)
+
+also all other values below 128 are reserved by the present document.
+[name]:
+0	data circuit asynchronous (UDI or 3.1 kHz modem)
+1	data circuit synchronous (UDI or 3.1 kHz modem)
+2	PAD Access (asynchronous) (UDI)
+3	Packet Access (synchronous) (UDI)
+4	data circuit asynchronous (RDI)
+5	data circuit synchronous (RDI)
+6	PAD Access (asynchronous) (RDI)
+7	Packet Access (synchronous) (RDI)
+also all other values below 128 are reserved by the present document.
+[ce]:
+0	transparent
+1	non-transparent
+2	both, transparent preferred
+3	both, non-transparent preferred
+</description>
+</spec>
+<spec>
+    <command>AT+CBST?</command>
+    <profile>Select bearer service type (Query)</profile>
+    <description>Set command selects the bearer service [name] with data rate [speed], and the connection element [ce] to be used when data calls are originated (refer 3GPP TS 22.002 [1]). Values may also be used during mobile terminated data call setup, especially in case of single numbering scheme calls (refer +CSNS).
+Test command returns values supported as compound values.
+Defined values
+NOTE:	The default values of the subparameters are manufacturer specific since they depend on the purpose of the device and data services provided by it. Not all combinations of these subparameters are supported by GSM/UMTS (refer 3GPP TS 22.002 [1]).
+[speed]:
+0	autobauding (automatic selection of the speed; this setting is possible in case of 3.1 kHz modem and non-transparent service)
+1	300 bps (V.21)
+2	1200 bps (V.22)
+3	1200/75 bps (V.23)
+4	2400 bps (V.22bis)
+5	2400 bps (V.26ter)
+6	4800 bps (V.32)
+7	9600 bps (V.32)
+12	9600 bps (V.34)
+14	14400 bps (V.34)
+15	19200 bps (V.34)
+16	28800 bps (V.34)
+17	33600 bps (V.34)
+34	1200 bps (V.120)
+36	2400 bps (V.120)
+38	4800 bps (V.120)
+39	9600 bps (V.120)
+43	14400 bps (V.120)
+47	19200 bps (V.120)
+48	28800 bps (V.120)
+49	38400 bps (V.120)
+50	48000 bps (V.120)
+51	56000 bps (V.120)
+65	300 bps (V.110)
+66	1200 bps (V.110)
+68	2400 bps (V.110 or X.31 flag stuffing)
+70	4800 bps (V.110 or X.31 flag stuffing)
+71	9600 bps (V.110 or X.31 flag stuffing)
+75	14400 bps (V.110 or X.31 flag stuffing)
+79	19200 bps (V.110 or X.31 flag stuffing)
+80	28800 bps (V.110 or X.31 flag stuffing)
+81	38400 bps (V.110 or X.31 flag stuffing)
+82	48000 bps (V.110 or X.31 flag stuffing)
+83	56000 bps (V.110 or X.31 flag stuffing; this setting can be used in conjunction with asynchronous non-transparent UDI or RDI service in order to get FTM)
+84	64000 bps (X.31 flag stuffing; this setting can be used in conjunction with asynchronous non-transparent UDI service in order to get FTM)
+115	56000 bps (bit transparent)
+116	64000 bps (bit transparent)
+120	32000 bps (PIAFS32k)
+121	64000 bps (PIAFS64k)
+130	28800 bps (multimedia)
+131	32000 bps (multimedia)
+132	33600 bps (multimedia)
+133	56000 bps (multimedia)
+134	64000 bps (multimedia)
+
+also all other values below 128 are reserved by the present document.
+[name]:
+0	data circuit asynchronous (UDI or 3.1 kHz modem)
+1	data circuit synchronous (UDI or 3.1 kHz modem)
+2	PAD Access (asynchronous) (UDI)
+3	Packet Access (synchronous) (UDI)
+4	data circuit asynchronous (RDI)
+5	data circuit synchronous (RDI)
+6	PAD Access (asynchronous) (RDI)
+7	Packet Access (synchronous) (RDI)
+also all other values below 128 are reserved by the present document.
+[ce]:
+0	transparent
+1	non-transparent
+2	both, transparent preferred
+3	both, non-transparent preferred
+</description>
+</spec>
+<spec>
+    <command>AT+CBST=?</command>
+    <profile>Select bearer service type (Query all)</profile>
+    <description>Set command selects the bearer service [name] with data rate [speed], and the connection element [ce] to be used when data calls are originated (refer 3GPP TS 22.002 [1]). Values may also be used during mobile terminated data call setup, especially in case of single numbering scheme calls (refer +CSNS).
+Test command returns values supported as compound values.
+Defined values
+NOTE:	The default values of the subparameters are manufacturer specific since they depend on the purpose of the device and data services provided by it. Not all combinations of these subparameters are supported by GSM/UMTS (refer 3GPP TS 22.002 [1]).
+[speed]:
+0	autobauding (automatic selection of the speed; this setting is possible in case of 3.1 kHz modem and non-transparent service)
+1	300 bps (V.21)
+2	1200 bps (V.22)
+3	1200/75 bps (V.23)
+4	2400 bps (V.22bis)
+5	2400 bps (V.26ter)
+6	4800 bps (V.32)
+7	9600 bps (V.32)
+12	9600 bps (V.34)
+14	14400 bps (V.34)
+15	19200 bps (V.34)
+16	28800 bps (V.34)
+17	33600 bps (V.34)
+34	1200 bps (V.120)
+36	2400 bps (V.120)
+38	4800 bps (V.120)
+39	9600 bps (V.120)
+43	14400 bps (V.120)
+47	19200 bps (V.120)
+48	28800 bps (V.120)
+49	38400 bps (V.120)
+50	48000 bps (V.120)
+51	56000 bps (V.120)
+65	300 bps (V.110)
+66	1200 bps (V.110)
+68	2400 bps (V.110 or X.31 flag stuffing)
+70	4800 bps (V.110 or X.31 flag stuffing)
+71	9600 bps (V.110 or X.31 flag stuffing)
+75	14400 bps (V.110 or X.31 flag stuffing)
+79	19200 bps (V.110 or X.31 flag stuffing)
+80	28800 bps (V.110 or X.31 flag stuffing)
+81	38400 bps (V.110 or X.31 flag stuffing)
+82	48000 bps (V.110 or X.31 flag stuffing)
+83	56000 bps (V.110 or X.31 flag stuffing; this setting can be used in conjunction with asynchronous non-transparent UDI or RDI service in order to get FTM)
+84	64000 bps (X.31 flag stuffing; this setting can be used in conjunction with asynchronous non-transparent UDI service in order to get FTM)
+115	56000 bps (bit transparent)
+116	64000 bps (bit transparent)
+120	32000 bps (PIAFS32k)
+121	64000 bps (PIAFS64k)
+130	28800 bps (multimedia)
+131	32000 bps (multimedia)
+132	33600 bps (multimedia)
+133	56000 bps (multimedia)
+134	64000 bps (multimedia)
+
+also all other values below 128 are reserved by the present document.
+[name]:
+0	data circuit asynchronous (UDI or 3.1 kHz modem)
+1	data circuit synchronous (UDI or 3.1 kHz modem)
+2	PAD Access (asynchronous) (UDI)
+3	Packet Access (synchronous) (UDI)
+4	data circuit asynchronous (RDI)
+5	data circuit synchronous (RDI)
+6	PAD Access (asynchronous) (RDI)
+7	Packet Access (synchronous) (RDI)
+also all other values below 128 are reserved by the present document.
+[ce]:
+0	transparent
+1	non-transparent
+2	both, transparent preferred
+3	both, non-transparent preferred
+</description>
+</spec>
+<spec>
+    <command>AT+CRLP=</command>
+    <profile>Radio link protocol (Assign)</profile>
+    <description>Radio link protocol (RLP) parameters used when non-transparent data calls are originated may be altered with set command. Available command subparameters depend on the RLP versions implemented by the device (e.g. [ver] may not be available if device supports only versions 0 and 1).
+NOTE 1:	If radio link protocol is not used, but some other error correcting protocol (for transparent data calls), V.250 [14] Error Control Selection test command +ES=? may be used to indicate the presence of the protocol.
+Read command returns current settings for each supported RLP version [verx]. Only RLP parameters applicable to the corresponding [verx] are returned.
+Test command returns values supported as a compound value. If MT/TA supports several RLP versions [verx], the RLP parameter value ranges for each [verx] are returned in a separate line.
+Defined values
+[ver], [verx]: RLP version number in integer format; when version indication is not present it shall equal 0
+NOTE 2:	Versions 0 and 1 share the same parameter set. Read and test commands shall return only one line for this set (where [verx] is not present).
+[iws], [mws], [T1], [N2], [T4]: IWF to MS window size, MS to IWF window size, acknowledgement timer T1, retransmission attempts N2, re-sequencing period T4 in integer format (default values and value ranges depend on RLP version; refer 3GPP TS 24.022 [18]): T1 and T4 are in units of 10 ms.
+</description>
+</spec>
+<spec>
+    <command>AT+CRLP?</command>
+    <profile>Radio link protocol (Query)</profile>
+    <description>Radio link protocol (RLP) parameters used when non-transparent data calls are originated may be altered with set command. Available command subparameters depend on the RLP versions implemented by the device (e.g. [ver] may not be available if device supports only versions 0 and 1).
+NOTE 1:	If radio link protocol is not used, but some other error correcting protocol (for transparent data calls), V.250 [14] Error Control Selection test command +ES=? may be used to indicate the presence of the protocol.
+Read command returns current settings for each supported RLP version [verx]. Only RLP parameters applicable to the corresponding [verx] are returned.
+Test command returns values supported as a compound value. If MT/TA supports several RLP versions [verx], the RLP parameter value ranges for each [verx] are returned in a separate line.
+Defined values
+[ver], [verx]: RLP version number in integer format; when version indication is not present it shall equal 0
+NOTE 2:	Versions 0 and 1 share the same parameter set. Read and test commands shall return only one line for this set (where [verx] is not present).
+[iws], [mws], [T1], [N2], [T4]: IWF to MS window size, MS to IWF window size, acknowledgement timer T1, retransmission attempts N2, re-sequencing period T4 in integer format (default values and value ranges depend on RLP version; refer 3GPP TS 24.022 [18]): T1 and T4 are in units of 10 ms.
+</description>
+</spec>
+<spec>
+    <command>AT+CRLP=?</command>
+    <profile>Radio link protocol (Query all)</profile>
+    <description>Radio link protocol (RLP) parameters used when non-transparent data calls are originated may be altered with set command. Available command subparameters depend on the RLP versions implemented by the device (e.g. [ver] may not be available if device supports only versions 0 and 1).
+NOTE 1:	If radio link protocol is not used, but some other error correcting protocol (for transparent data calls), V.250 [14] Error Control Selection test command +ES=? may be used to indicate the presence of the protocol.
+Read command returns current settings for each supported RLP version [verx]. Only RLP parameters applicable to the corresponding [verx] are returned.
+Test command returns values supported as a compound value. If MT/TA supports several RLP versions [verx], the RLP parameter value ranges for each [verx] are returned in a separate line.
+Defined values
+[ver], [verx]: RLP version number in integer format; when version indication is not present it shall equal 0
+NOTE 2:	Versions 0 and 1 share the same parameter set. Read and test commands shall return only one line for this set (where [verx] is not present).
+[iws], [mws], [T1], [N2], [T4]: IWF to MS window size, MS to IWF window size, acknowledgement timer T1, retransmission attempts N2, re-sequencing period T4 in integer format (default values and value ranges depend on RLP version; refer 3GPP TS 24.022 [18]): T1 and T4 are in units of 10 ms.
+</description>
+</spec>
+<spec>
+    <command>AT+CR=</command>
+    <profile>Service reporting control (Assign)</profile>
+    <description>Set command controls whether or not intermediate result code +CR: [serv] is returned from the TA to the TE. If enabled, the intermediate result code is transmitted at the point during connect negotiation at which the TA has determined which speed and quality of service will be used, before any error control or data compression reports are transmitted, and before the intermediate result code CONNECT is transmitted.
+NOTE:	This command replaces V.250 [14] command Modulation Reporting Control +MR, which is not appropriate for use in the GSM/UMTS network. Possible error control (other than radio link protocol) and data compression reporting can be enabled with V.250 commands Error Control Reporting +ER and Data Compression Reporting +DR.
+Test command returns values supported as a compound value.
+Defined values
+[mode]:
+0	disables reporting
+1	enables reporting
+[serv]:
+ASYNC	asynchronous transparent
+SYNC	synchronous transparent
+REL ASYNC	asynchronous non‑transparent
+REL SYNC	synchronous non‑transparent
+GPRS [[L2P]]	GPRS 
+The optional [L2P] proposes a layer 2 protocol to use between the MT and the TE. It is defined in the Enter GPRS Data Mode (+CGDATA) command.
+</description>
+</spec>
+<spec>
+    <command>AT+CR?</command>
+    <profile>Service reporting control (Query)</profile>
+    <description>Set command controls whether or not intermediate result code +CR: [serv] is returned from the TA to the TE. If enabled, the intermediate result code is transmitted at the point during connect negotiation at which the TA has determined which speed and quality of service will be used, before any error control or data compression reports are transmitted, and before the intermediate result code CONNECT is transmitted.
+NOTE:	This command replaces V.250 [14] command Modulation Reporting Control +MR, which is not appropriate for use in the GSM/UMTS network. Possible error control (other than radio link protocol) and data compression reporting can be enabled with V.250 commands Error Control Reporting +ER and Data Compression Reporting +DR.
+Test command returns values supported as a compound value.
+Defined values
+[mode]:
+0	disables reporting
+1	enables reporting
+[serv]:
+ASYNC	asynchronous transparent
+SYNC	synchronous transparent
+REL ASYNC	asynchronous non‑transparent
+REL SYNC	synchronous non‑transparent
+GPRS [[L2P]]	GPRS 
+The optional [L2P] proposes a layer 2 protocol to use between the MT and the TE. It is defined in the Enter GPRS Data Mode (+CGDATA) command.
+</description>
+</spec>
+<spec>
+    <command>AT+CR=?</command>
+    <profile>Service reporting control (Query all)</profile>
+    <description>Set command controls whether or not intermediate result code +CR: [serv] is returned from the TA to the TE. If enabled, the intermediate result code is transmitted at the point during connect negotiation at which the TA has determined which speed and quality of service will be used, before any error control or data compression reports are transmitted, and before the intermediate result code CONNECT is transmitted.
+NOTE:	This command replaces V.250 [14] command Modulation Reporting Control +MR, which is not appropriate for use in the GSM/UMTS network. Possible error control (other than radio link protocol) and data compression reporting can be enabled with V.250 commands Error Control Reporting +ER and Data Compression Reporting +DR.
+Test command returns values supported as a compound value.
+Defined values
+[mode]:
+0	disables reporting
+1	enables reporting
+[serv]:
+ASYNC	asynchronous transparent
+SYNC	synchronous transparent
+REL ASYNC	asynchronous non‑transparent
+REL SYNC	synchronous non‑transparent
+GPRS [[L2P]]	GPRS 
+The optional [L2P] proposes a layer 2 protocol to use between the MT and the TE. It is defined in the Enter GPRS Data Mode (+CGDATA) command.
+</description>
+</spec>
+<spec>
+    <command>AT+CEER</command>
+    <profile>Extended error report </profile>
+    <description>Execution command causes the TA to return one or more lines of information text [report], determined by the MT manufacturer, which should offer the user of the TA an extended report of the reason for
+-	the failure in the last unsuccessful call setup (originating or answering) or in‑call modification;
+-	the last call release;
+-	the last unsuccessful GPRS attach or unsuccessful PDP context activation;
+-	the last GPRS detach or PDP context deactivation.
+Typically, the text will consist of a single line containing the cause information given by GSM/UMTS network in textual format.
+Defined values
+[report]: the total number of characters, including line terminators, in the information text shall not exceed 2041 characters.
+Text shall not contain the sequence 0[CR] or OK[CR].
+</description>
+</spec>
+<spec>
+    <command>AT+CEER=?</command>
+    <profile>Extended error report (Query all)</profile>
+    <description>Execution command causes the TA to return one or more lines of information text [report], determined by the MT manufacturer, which should offer the user of the TA an extended report of the reason for
+-	the failure in the last unsuccessful call setup (originating or answering) or in‑call modification;
+-	the last call release;
+-	the last unsuccessful GPRS attach or unsuccessful PDP context activation;
+-	the last GPRS detach or PDP context deactivation.
+Typically, the text will consist of a single line containing the cause information given by GSM/UMTS network in textual format.
+Defined values
+[report]: the total number of characters, including line terminators, in the information text shall not exceed 2041 characters.
+Text shall not contain the sequence 0[CR] or OK[CR].
+</description>
+</spec>
+<spec>
+    <command>AT+CRC=</command>
+    <profile>Cellular result codes (Assign)</profile>
+    <description>Set command controls whether or not the extended format of incoming call indication or GPRS network request for PDP context activation or notification for VBS/VGCS calls is used. When enabled, an incoming call is indicated to the TE with unsolicited result code +CRING: [type] instead of the normal RING.
+Test command returns values supported as a compound value.
+NOTE:	Similar command may be found in TIA IS‑99 [15] and TIA IS‑135 [16].
+Defined values
+[mode]:
+0	disables extended format
+1	enables extended format
+[type]:
+ASYNC [,[priority][,[subaddr],[satype]]]			asynchronous transparent
+SYNC [,[priority][,[subaddr],[satype]]]			synchronous transparent
+REL ASYNC [,[priority][,[subaddr],[satype]]]		asynchronous non‑transparent
+REL SYNC [,[priority][,[subaddr],[satype]]]		synchronous non‑transparent
+FAX [,[priority][,[subaddr],[satype]]]			facsimile (TS 62)
+VOICE [,[priority][,[subaddr],[satype]]]			normal voice (TS 11)
+VOICE/XXX [,[priority][,[subaddr],[satype]]]		voice followed by data (BS 81) (XXX is ASYNC, SYNC, REL ASYNC or REL SYNC)
+ALT VOICE/XXX [,[priority][,[subaddr],[satype]]]	alternating voice/data, voice first (BS 61)
+ALT XXX/VOICE [,[priority][,[subaddr],[satype]]]	alternating voice/data, data first (BS 61)
+ALT VOICE/FAX [,[priority][,[subaddr],[satype]]]	alternating voice/fax, voice first (TS 61)
+ALT FAX/VOICE [,[priority][,[subaddr],[satype]]]	alternating voice/fax, fax first (TS 61)
+GPRS [PDP_type], [PDP_addr][, [[L2P]][,[APN]]]		GPRS network request for PDP context activation
+VGC [GCA], [GId], [ackflag] [,[priority]]			voice group call (TS 91)
+VBC [GCA], [GId], [ackflag] [,[priority]]			voice broadcast call (TS 92)
+The optional [priority] indicates the eMLPP priority level of the incoming call by paging, notification or setup message. The priority level values are as defined in eMLPP specification 3GPP TS 22.067 [54].
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer 3GPP TS 24.008 [8] subclause 10.5.4.8)
+[PDP_type] ,[PDP_addr] and [APN] are as defined in the Define PDP Context (+CGDCONT) command. The optional [L2P] proposes a layer 2 protocol to use between the MT and the TE. It is defined in the Enter GPRS Data Mode (+CGDATA) command. If the MT is unable to announce to the TE the network's request (for example it is in V.250 online data state) the MT shall reject the request. No corresponding unsolicited result code shall be issued when the MT returns to a command state.
+[GCA] is a part of the group call reference as specified in 3GPP TS 23.003 [7] and indicates group call area.
+[GId] is a part of the group call reference as specified in 3GPP TS 23.003 [7] and indicates group call identification.The [ackflag]=1 proposes that a predefined confirmation procedure is to be used after the call is ended. For [ackflag]=0 no confirmation procedure is required.
+</description>
+</spec>
+<spec>
+    <command>AT+CRC?</command>
+    <profile>Cellular result codes (Query)</profile>
+    <description>Set command controls whether or not the extended format of incoming call indication or GPRS network request for PDP context activation or notification for VBS/VGCS calls is used. When enabled, an incoming call is indicated to the TE with unsolicited result code +CRING: [type] instead of the normal RING.
+Test command returns values supported as a compound value.
+NOTE:	Similar command may be found in TIA IS‑99 [15] and TIA IS‑135 [16].
+Defined values
+[mode]:
+0	disables extended format
+1	enables extended format
+[type]:
+ASYNC [,[priority][,[subaddr],[satype]]]			asynchronous transparent
+SYNC [,[priority][,[subaddr],[satype]]]			synchronous transparent
+REL ASYNC [,[priority][,[subaddr],[satype]]]		asynchronous non‑transparent
+REL SYNC [,[priority][,[subaddr],[satype]]]		synchronous non‑transparent
+FAX [,[priority][,[subaddr],[satype]]]			facsimile (TS 62)
+VOICE [,[priority][,[subaddr],[satype]]]			normal voice (TS 11)
+VOICE/XXX [,[priority][,[subaddr],[satype]]]		voice followed by data (BS 81) (XXX is ASYNC, SYNC, REL ASYNC or REL SYNC)
+ALT VOICE/XXX [,[priority][,[subaddr],[satype]]]	alternating voice/data, voice first (BS 61)
+ALT XXX/VOICE [,[priority][,[subaddr],[satype]]]	alternating voice/data, data first (BS 61)
+ALT VOICE/FAX [,[priority][,[subaddr],[satype]]]	alternating voice/fax, voice first (TS 61)
+ALT FAX/VOICE [,[priority][,[subaddr],[satype]]]	alternating voice/fax, fax first (TS 61)
+GPRS [PDP_type], [PDP_addr][, [[L2P]][,[APN]]]		GPRS network request for PDP context activation
+VGC [GCA], [GId], [ackflag] [,[priority]]			voice group call (TS 91)
+VBC [GCA], [GId], [ackflag] [,[priority]]			voice broadcast call (TS 92)
+The optional [priority] indicates the eMLPP priority level of the incoming call by paging, notification or setup message. The priority level values are as defined in eMLPP specification 3GPP TS 22.067 [54].
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer 3GPP TS 24.008 [8] subclause 10.5.4.8)
+[PDP_type] ,[PDP_addr] and [APN] are as defined in the Define PDP Context (+CGDCONT) command. The optional [L2P] proposes a layer 2 protocol to use between the MT and the TE. It is defined in the Enter GPRS Data Mode (+CGDATA) command. If the MT is unable to announce to the TE the network's request (for example it is in V.250 online data state) the MT shall reject the request. No corresponding unsolicited result code shall be issued when the MT returns to a command state.
+[GCA] is a part of the group call reference as specified in 3GPP TS 23.003 [7] and indicates group call area.
+[GId] is a part of the group call reference as specified in 3GPP TS 23.003 [7] and indicates group call identification.The [ackflag]=1 proposes that a predefined confirmation procedure is to be used after the call is ended. For [ackflag]=0 no confirmation procedure is required.
+</description>
+</spec>
+<spec>
+    <command>AT+CRC=?</command>
+    <profile>Cellular result codes (Query all)</profile>
+    <description>Set command controls whether or not the extended format of incoming call indication or GPRS network request for PDP context activation or notification for VBS/VGCS calls is used. When enabled, an incoming call is indicated to the TE with unsolicited result code +CRING: [type] instead of the normal RING.
+Test command returns values supported as a compound value.
+NOTE:	Similar command may be found in TIA IS‑99 [15] and TIA IS‑135 [16].
+Defined values
+[mode]:
+0	disables extended format
+1	enables extended format
+[type]:
+ASYNC [,[priority][,[subaddr],[satype]]]			asynchronous transparent
+SYNC [,[priority][,[subaddr],[satype]]]			synchronous transparent
+REL ASYNC [,[priority][,[subaddr],[satype]]]		asynchronous non‑transparent
+REL SYNC [,[priority][,[subaddr],[satype]]]		synchronous non‑transparent
+FAX [,[priority][,[subaddr],[satype]]]			facsimile (TS 62)
+VOICE [,[priority][,[subaddr],[satype]]]			normal voice (TS 11)
+VOICE/XXX [,[priority][,[subaddr],[satype]]]		voice followed by data (BS 81) (XXX is ASYNC, SYNC, REL ASYNC or REL SYNC)
+ALT VOICE/XXX [,[priority][,[subaddr],[satype]]]	alternating voice/data, voice first (BS 61)
+ALT XXX/VOICE [,[priority][,[subaddr],[satype]]]	alternating voice/data, data first (BS 61)
+ALT VOICE/FAX [,[priority][,[subaddr],[satype]]]	alternating voice/fax, voice first (TS 61)
+ALT FAX/VOICE [,[priority][,[subaddr],[satype]]]	alternating voice/fax, fax first (TS 61)
+GPRS [PDP_type], [PDP_addr][, [[L2P]][,[APN]]]		GPRS network request for PDP context activation
+VGC [GCA], [GId], [ackflag] [,[priority]]			voice group call (TS 91)
+VBC [GCA], [GId], [ackflag] [,[priority]]			voice broadcast call (TS 92)
+The optional [priority] indicates the eMLPP priority level of the incoming call by paging, notification or setup message. The priority level values are as defined in eMLPP specification 3GPP TS 22.067 [54].
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer 3GPP TS 24.008 [8] subclause 10.5.4.8)
+[PDP_type] ,[PDP_addr] and [APN] are as defined in the Define PDP Context (+CGDCONT) command. The optional [L2P] proposes a layer 2 protocol to use between the MT and the TE. It is defined in the Enter GPRS Data Mode (+CGDATA) command. If the MT is unable to announce to the TE the network's request (for example it is in V.250 online data state) the MT shall reject the request. No corresponding unsolicited result code shall be issued when the MT returns to a command state.
+[GCA] is a part of the group call reference as specified in 3GPP TS 23.003 [7] and indicates group call area.
+[GId] is a part of the group call reference as specified in 3GPP TS 23.003 [7] and indicates group call identification.The [ackflag]=1 proposes that a predefined confirmation procedure is to be used after the call is ended. For [ackflag]=0 no confirmation procedure is required.
+</description>
+</spec>
+<spec>
+    <command>AT+CHSD</command>
+    <profile>HSCSD device parameters </profile>
+    <description>Execution command returns information about HSCSD features (refer 3GPP TS 22.034 [29]) supported by the MT/TA. Refer subclause 9.2 for possible [err] values.
+The return information is only applicable in GERAN.
+Defined values
+[mclass]: integer type; multislot class
+[maxRx]: integer type; maximum number of receive timeslots that MT can use
+[maxTx]: integer type; maximum number of transmit timeslots that MT can use
+[sum]: integer type; total number of receive and transmit timeslots that MT can use at the same time (per TDMA frame). The following applies in a HSCSD call: 1  (receive slots) + (transmit slots)  [sum]
+[codings] is a sum of integers each representing a supported channel coding (e.g. value 5 indicates that 4,8k and 9,6k channel codings are supported):
+1	4,8k full rate data traffic channel
+4	9,6k full rate data traffic channel
+8	14,4k full rate data traffic channel
+16	28,8k full rate data traffic channel (only possible when 14.4k is supported)
+32	32,0k full rate data traffic channel (only possible in a two-timeslot configuration)
+64	43,2k full rate data traffic channel (only possible when 14.4k is supported)
+</description>
+</spec>
+<spec>
+    <command>AT+CHSD=?</command>
+    <profile>HSCSD device parameters (Query all)</profile>
+    <description>Execution command returns information about HSCSD features (refer 3GPP TS 22.034 [29]) supported by the MT/TA. Refer subclause 9.2 for possible [err] values.
+The return information is only applicable in GERAN.
+Defined values
+[mclass]: integer type; multislot class
+[maxRx]: integer type; maximum number of receive timeslots that MT can use
+[maxTx]: integer type; maximum number of transmit timeslots that MT can use
+[sum]: integer type; total number of receive and transmit timeslots that MT can use at the same time (per TDMA frame). The following applies in a HSCSD call: 1  (receive slots) + (transmit slots)  [sum]
+[codings] is a sum of integers each representing a supported channel coding (e.g. value 5 indicates that 4,8k and 9,6k channel codings are supported):
+1	4,8k full rate data traffic channel
+4	9,6k full rate data traffic channel
+8	14,4k full rate data traffic channel
+16	28,8k full rate data traffic channel (only possible when 14.4k is supported)
+32	32,0k full rate data traffic channel (only possible in a two-timeslot configuration)
+64	43,2k full rate data traffic channel (only possible when 14.4k is supported)
+</description>
+</spec>
+<spec>
+    <command>AT+CHST=</command>
+    <profile>HSCSD transparent call configuration (Assign)</profile>
+    <description>Set command controls parameters for transparent HSCSD calls in GERAN. Changing them during a call does not affect the current call.
+NOTE: 	In UTRAN, values set with this command are not needed. The only applicable parameter is [SPEED], which is set with +CBST command.
+Defined values
+[wRx]: integer type; wanted amount of receive timeslots. Default value 0 indicates that TA shall calculate a proper value from currently selected fixed network user rate ([speed] subparameter from +CBST command) and [codings]
+[codings]: a sum of integers each representing a channel coding that is accepted for transparent HSCSD calls. Default value 0 indicates that all supported codings are accepted (refer +CHSD command for other values)
+</description>
+</spec>
+<spec>
+    <command>AT+CHST?</command>
+    <profile>HSCSD transparent call configuration (Query)</profile>
+    <description>Set command controls parameters for transparent HSCSD calls in GERAN. Changing them during a call does not affect the current call.
+NOTE: 	In UTRAN, values set with this command are not needed. The only applicable parameter is [SPEED], which is set with +CBST command.
+Defined values
+[wRx]: integer type; wanted amount of receive timeslots. Default value 0 indicates that TA shall calculate a proper value from currently selected fixed network user rate ([speed] subparameter from +CBST command) and [codings]
+[codings]: a sum of integers each representing a channel coding that is accepted for transparent HSCSD calls. Default value 0 indicates that all supported codings are accepted (refer +CHSD command for other values)
+</description>
+</spec>
+<spec>
+    <command>AT+CHST=?</command>
+    <profile>HSCSD transparent call configuration (Query all)</profile>
+    <description>Set command controls parameters for transparent HSCSD calls in GERAN. Changing them during a call does not affect the current call.
+NOTE: 	In UTRAN, values set with this command are not needed. The only applicable parameter is [SPEED], which is set with +CBST command.
+Defined values
+[wRx]: integer type; wanted amount of receive timeslots. Default value 0 indicates that TA shall calculate a proper value from currently selected fixed network user rate ([speed] subparameter from +CBST command) and [codings]
+[codings]: a sum of integers each representing a channel coding that is accepted for transparent HSCSD calls. Default value 0 indicates that all supported codings are accepted (refer +CHSD command for other values)
+</description>
+</spec>
+<spec>
+    <command>AT+CHSC</command>
+    <profile>HSCSD current call parameters </profile>
+    <description>Execution command returns information about current HSCSD call. If no HSCSD call is active, all parameters returned shall equal zero. If HSCSD call is active in UTRAN, all non-applicable parameters returned shall be equal to zero. (It is manufacturer specific whether non-zero information is returned in case of an active normal single-slot data call.)
+Defined values
+[rx]: integer type; number of receive timeslots currently in use. This parameter is not applicable in UTRAN.
+[tx]: integer type; number of transmit timeslots currently in use. This parameter is not applicable in UTRAN.
+[aiur]: integer type; current air interface user rate (in case of transparent service this equals fixed network user rate) (refer +CHSN command for possible values). For the two-timeslot ECSD bit transparent configuration the following additional values apply:
+8	56000 bps
+9	64000 bps
+[coding]: current channel coding (refer +CHSD command for possible values). This parameter is not applicable in UTRAN.
+</description>
+</spec>
+<spec>
+    <command>AT+CHSC=?</command>
+    <profile>HSCSD current call parameters (Query all)</profile>
+    <description>Execution command returns information about current HSCSD call. If no HSCSD call is active, all parameters returned shall equal zero. If HSCSD call is active in UTRAN, all non-applicable parameters returned shall be equal to zero. (It is manufacturer specific whether non-zero information is returned in case of an active normal single-slot data call.)
+Defined values
+[rx]: integer type; number of receive timeslots currently in use. This parameter is not applicable in UTRAN.
+[tx]: integer type; number of transmit timeslots currently in use. This parameter is not applicable in UTRAN.
+[aiur]: integer type; current air interface user rate (in case of transparent service this equals fixed network user rate) (refer +CHSN command for possible values). For the two-timeslot ECSD bit transparent configuration the following additional values apply:
+8	56000 bps
+9	64000 bps
+[coding]: current channel coding (refer +CHSD command for possible values). This parameter is not applicable in UTRAN.
+</description>
+</spec>
+<spec>
+    <command>AT+CHSR=</command>
+    <profile>HSCSD parameters report (Assign)</profile>
+    <description>Enabled command returns intermediate result code +CHSR: [type] from the TA to the TE when an HSCSD call is being set up. The result code represents the current (negotiated or renegotiated) HSCSD parameters. If enabled, the intermediate result code is transmitted at the point of the call setup negotiation where the TA has determined what type of an HSCSD connection will be used. Result code transmission is done after possible service (+CR), error control (+ER), and/or compression (+DR) reporting but before possible TE-TA rate (+ILRR) reporting and before the intermediate result code CONNECT is transmitted. The format of the intermediate result code is:
++CHSR: [rx],[tx],[aiur],[coding]
+For the value definitions, refer to +CHSN and +CHSC commands. For instance, for a non-transparent HSCSD call, result code '+CHSR: 2,2,4,8' means that the call has two timeslots in both up- and downlink, the air interface user rate is 28800 bps, and the used channel coding TCH/F14.4.
+In UTRAN, all non-applicable parameters returned shall be equal to zero.
+Defined values
+[mode]: 
+0     	disables reporting
+1		enables reporting
+</description>
+</spec>
+<spec>
+    <command>AT+CHSR?</command>
+    <profile>HSCSD parameters report (Query)</profile>
+    <description>Enabled command returns intermediate result code +CHSR: [type] from the TA to the TE when an HSCSD call is being set up. The result code represents the current (negotiated or renegotiated) HSCSD parameters. If enabled, the intermediate result code is transmitted at the point of the call setup negotiation where the TA has determined what type of an HSCSD connection will be used. Result code transmission is done after possible service (+CR), error control (+ER), and/or compression (+DR) reporting but before possible TE-TA rate (+ILRR) reporting and before the intermediate result code CONNECT is transmitted. The format of the intermediate result code is:
++CHSR: [rx],[tx],[aiur],[coding]
+For the value definitions, refer to +CHSN and +CHSC commands. For instance, for a non-transparent HSCSD call, result code '+CHSR: 2,2,4,8' means that the call has two timeslots in both up- and downlink, the air interface user rate is 28800 bps, and the used channel coding TCH/F14.4.
+In UTRAN, all non-applicable parameters returned shall be equal to zero.
+Defined values
+[mode]: 
+0     	disables reporting
+1		enables reporting
+</description>
+</spec>
+<spec>
+    <command>AT+CHSR=?</command>
+    <profile>HSCSD parameters report (Query all)</profile>
+    <description>Enabled command returns intermediate result code +CHSR: [type] from the TA to the TE when an HSCSD call is being set up. The result code represents the current (negotiated or renegotiated) HSCSD parameters. If enabled, the intermediate result code is transmitted at the point of the call setup negotiation where the TA has determined what type of an HSCSD connection will be used. Result code transmission is done after possible service (+CR), error control (+ER), and/or compression (+DR) reporting but before possible TE-TA rate (+ILRR) reporting and before the intermediate result code CONNECT is transmitted. The format of the intermediate result code is:
++CHSR: [rx],[tx],[aiur],[coding]
+For the value definitions, refer to +CHSN and +CHSC commands. For instance, for a non-transparent HSCSD call, result code '+CHSR: 2,2,4,8' means that the call has two timeslots in both up- and downlink, the air interface user rate is 28800 bps, and the used channel coding TCH/F14.4.
+In UTRAN, all non-applicable parameters returned shall be equal to zero.
+Defined values
+[mode]: 
+0     	disables reporting
+1		enables reporting
+</description>
+</spec>
+<spec>
+    <command>AT+CSNS=</command>
+    <profile>Single numbering scheme (Assign)</profile>
+    <description>Set command selects the bearer or teleservice to be used when mobile terminated single numbering scheme call is established. Parameter values set with +CBST command shall be used when [mode] equals to a data service. 
+Test command returns values supported as compound values.
+Defined values
+[mode]:
+0	voice
+1	alternating voice/fax, voice first (TS 61)
+2	fax (TS 62)
+3	alternating voice/data, voice first (BS 61)
+4	data
+5	alternating voice/fax, fax first (TS 61)
+6	alternating voice/data, data first (BS 61)
+7	voice followed by data (BS 81)
+</description>
+</spec>
+<spec>
+    <command>AT+CSNS?</command>
+    <profile>Single numbering scheme (Query)</profile>
+    <description>Set command selects the bearer or teleservice to be used when mobile terminated single numbering scheme call is established. Parameter values set with +CBST command shall be used when [mode] equals to a data service. 
+Test command returns values supported as compound values.
+Defined values
+[mode]:
+0	voice
+1	alternating voice/fax, voice first (TS 61)
+2	fax (TS 62)
+3	alternating voice/data, voice first (BS 61)
+4	data
+5	alternating voice/fax, fax first (TS 61)
+6	alternating voice/data, data first (BS 61)
+7	voice followed by data (BS 81)
+</description>
+</spec>
+<spec>
+    <command>AT+CSNS=?</command>
+    <profile>Single numbering scheme (Query all)</profile>
+    <description>Set command selects the bearer or teleservice to be used when mobile terminated single numbering scheme call is established. Parameter values set with +CBST command shall be used when [mode] equals to a data service. 
+Test command returns values supported as compound values.
+Defined values
+[mode]:
+0	voice
+1	alternating voice/fax, voice first (TS 61)
+2	fax (TS 62)
+3	alternating voice/data, voice first (BS 61)
+4	data
+5	alternating voice/fax, fax first (TS 61)
+6	alternating voice/data, data first (BS 61)
+7	voice followed by data (BS 81)
+</description>
+</spec>
+<spec>
+    <command>AT+CVHU=</command>
+    <profile>Voice Hangup Control (Assign)</profile>
+    <description>Set command selects whether ATH or 'drop DTR' shall cause a voice connection to be disconnected or not. By voice connection is also meant alternating mode calls that are currently in voice mode. (See subclause 6.6).
+NOTE:	When [mode] = 2, this command must be seen in conjunction with the V.250 [14] command :D. Else :D shall be ignored.
+Defined values
+[mode]:
+0	'Drop DTR' ignored but OK response given. ATH disconnects.
+1	'Drop DTR' and ATH ignored but OK response given.
+2	'Drop DTR' behaviour according to :D setting. ATH disconnects.
+</description>
+</spec>
+<spec>
+    <command>AT+CVHU?</command>
+    <profile>Voice Hangup Control (Query)</profile>
+    <description>Set command selects whether ATH or 'drop DTR' shall cause a voice connection to be disconnected or not. By voice connection is also meant alternating mode calls that are currently in voice mode. (See subclause 6.6).
+NOTE:	When [mode] = 2, this command must be seen in conjunction with the V.250 [14] command :D. Else :D shall be ignored.
+Defined values
+[mode]:
+0	'Drop DTR' ignored but OK response given. ATH disconnects.
+1	'Drop DTR' and ATH ignored but OK response given.
+2	'Drop DTR' behaviour according to :D setting. ATH disconnects.
+</description>
+</spec>
+<spec>
+    <command>AT+CVHU=?</command>
+    <profile>Voice Hangup Control (Query all)</profile>
+    <description>Set command selects whether ATH or 'drop DTR' shall cause a voice connection to be disconnected or not. By voice connection is also meant alternating mode calls that are currently in voice mode. (See subclause 6.6).
+NOTE:	When [mode] = 2, this command must be seen in conjunction with the V.250 [14] command :D. Else :D shall be ignored.
+Defined values
+[mode]:
+0	'Drop DTR' ignored but OK response given. ATH disconnects.
+1	'Drop DTR' and ATH ignored but OK response given.
+2	'Drop DTR' behaviour according to :D setting. ATH disconnects.
+</description>
+</spec>
+<spec>
+    <command>AT+CSDF=</command>
+    <profile>Settings date format (Assign)</profile>
+    <description>This command sets the date format via MMI of the date information presented to the user, which is specified by use of the [mode] parameter. The [mode] affects the date format on the phone display and doesn't affect the date format of the AT command serial interface. The command also sets the date format of the TE-TA interface, which is specified by use of the [auxmode] parameter (e.g. the [auxmode] affects the [time] of  +CCLK and +CALA). If the parameter is omitted ('+CSDF =','+CSDF =[mode]','+CSDF=,[auxmode]'),then this sets the default value.
+Defined values
+[mode]:
+NOTE:	It is manufacturer specific which modes that are supported.
+1	DD-MMM-YYYY	
+NOTE: 	Presentation of MMM is language dependent.
+2	DD-MM-YY
+3	MM/DD/YY
+4	DD/MM/YY
+5	DD.MM.YY
+6	YYMMDD
+7	YY-MM-DD
+8-255     Manufacturer specific
+[auxmode]: 
+1yy/MM/dd (default)
+2	yyyy/MM/dd
+also all other values are reserved by the present document
+NOTE:	The [time] format of +CCLK and +CALA 'yy/MM/dd,hh:mm:sszz' when [auxmode]=1 and it is 'yyyy/MM/dd,hh:mm:sszz' when [auxmode]=2. If the MT does not support time zone information then the three last characters may be omitted (see +CCLK command).
+</description>
+</spec>
+<spec>
+    <command>AT+CSDF?</command>
+    <profile>Settings date format (Query)</profile>
+    <description>This command sets the date format via MMI of the date information presented to the user, which is specified by use of the [mode] parameter. The [mode] affects the date format on the phone display and doesn't affect the date format of the AT command serial interface. The command also sets the date format of the TE-TA interface, which is specified by use of the [auxmode] parameter (e.g. the [auxmode] affects the [time] of  +CCLK and +CALA). If the parameter is omitted ('+CSDF =','+CSDF =[mode]','+CSDF=,[auxmode]'),then this sets the default value.
+Defined values
+[mode]:
+NOTE:	It is manufacturer specific which modes that are supported.
+1	DD-MMM-YYYY	
+NOTE: 	Presentation of MMM is language dependent.
+2	DD-MM-YY
+3	MM/DD/YY
+4	DD/MM/YY
+5	DD.MM.YY
+6	YYMMDD
+7	YY-MM-DD
+8-255     Manufacturer specific
+[auxmode]: 
+1yy/MM/dd (default)
+2	yyyy/MM/dd
+also all other values are reserved by the present document
+NOTE:	The [time] format of +CCLK and +CALA 'yy/MM/dd,hh:mm:sszz' when [auxmode]=1 and it is 'yyyy/MM/dd,hh:mm:sszz' when [auxmode]=2. If the MT does not support time zone information then the three last characters may be omitted (see +CCLK command).
+</description>
+</spec>
+<spec>
+    <command>AT+CSDF=?</command>
+    <profile>Settings date format (Query all)</profile>
+    <description>This command sets the date format via MMI of the date information presented to the user, which is specified by use of the [mode] parameter. The [mode] affects the date format on the phone display and doesn't affect the date format of the AT command serial interface. The command also sets the date format of the TE-TA interface, which is specified by use of the [auxmode] parameter (e.g. the [auxmode] affects the [time] of  +CCLK and +CALA). If the parameter is omitted ('+CSDF =','+CSDF =[mode]','+CSDF=,[auxmode]'),then this sets the default value.
+Defined values
+[mode]:
+NOTE:	It is manufacturer specific which modes that are supported.
+1	DD-MMM-YYYY	
+NOTE: 	Presentation of MMM is language dependent.
+2	DD-MM-YY
+3	MM/DD/YY
+4	DD/MM/YY
+5	DD.MM.YY
+6	YYMMDD
+7	YY-MM-DD
+8-255     Manufacturer specific
+[auxmode]: 
+1yy/MM/dd (default)
+2	yyyy/MM/dd
+also all other values are reserved by the present document
+NOTE:	The [time] format of +CCLK and +CALA 'yy/MM/dd,hh:mm:sszz' when [auxmode]=1 and it is 'yyyy/MM/dd,hh:mm:sszz' when [auxmode]=2. If the MT does not support time zone information then the three last characters may be omitted (see +CCLK command).
+</description>
+</spec>
+<spec>
+    <command>AT+CSIL=</command>
+    <profile>Silence Command (Assign)</profile>
+    <description>Set command enables/disables the silent mode. When the phone is in silent mode, all sounds from MT are suppressed except voice. 
+Read command reads the current setting.
+Test command lists the supported modes.
+Defined values
+[mode]:
+0	Silent mode off
+1	Silent mode on
+</description>
+</spec>
+<spec>
+    <command>AT+CSIL?</command>
+    <profile>Silence Command (Query)</profile>
+    <description>Set command enables/disables the silent mode. When the phone is in silent mode, all sounds from MT are suppressed except voice. 
+Read command reads the current setting.
+Test command lists the supported modes.
+Defined values
+[mode]:
+0	Silent mode off
+1	Silent mode on
+</description>
+</spec>
+<spec>
+    <command>AT+CSIL=?</command>
+    <profile>Silence Command (Query all)</profile>
+    <description>Set command enables/disables the silent mode. When the phone is in silent mode, all sounds from MT are suppressed except voice. 
+Read command reads the current setting.
+Test command lists the supported modes.
+Defined values
+[mode]:
+0	Silent mode off
+1	Silent mode on
+</description>
+</spec>
+<spec>
+    <command>AT+CSTF=</command>
+    <profile>Settings time format (Assign)</profile>
+    <description>Set command sets the time format of the time information presented to the user.
+Read commands reads the current setting.
+Test commands reads the supported [modes]s.
+Defined values
+[mode]:
+1	HH:MM (24 hour clock)
+2	HH:MM a.m./p.m.
+3-7	Manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CSTF?</command>
+    <profile>Settings time format (Query)</profile>
+    <description>Set command sets the time format of the time information presented to the user.
+Read commands reads the current setting.
+Test commands reads the supported [modes]s.
+Defined values
+[mode]:
+1	HH:MM (24 hour clock)
+2	HH:MM a.m./p.m.
+3-7	Manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CSTF=?</command>
+    <profile>Settings time format (Query all)</profile>
+    <description>Set command sets the time format of the time information presented to the user.
+Read commands reads the current setting.
+Test commands reads the supported [modes]s.
+Defined values
+[mode]:
+1	HH:MM (24 hour clock)
+2	HH:MM a.m./p.m.
+3-7	Manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CNUM</command>
+    <profile>Subscriber number </profile>
+    <description>Action command returns the MSISDNs related to the subscriber (this information can be stored in the SIM/UICC or in the MT). When storing information in the SIM/UICC, if a SIM card is present or if a UICC with an active GSM application is present, the information is stored in the EFMSISDN under DFTelecom. If a UICC with an active USIM application is present, the information is stored in the EFMSISDN under ADFUSIM). If subscriber has different MSISDN for different services, each MSISDN is returned in a separate line. Refer subclause 9.2 for possible [err] values.
+Defined values
+[alphax]: optional alphanumeric string associated with [numberx]; used character set should be the one selected with command Select TE Character Set +CSCS
+[numberx]: string type phone number of format specified by [typex]
+[typex]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[speed]: as defined in subclause 6.7
+[service] (service related to the phone number):
+0	asynchronous modem
+1	synchronous modem
+2	PAD Access (asynchronous)
+3	Packet Access (synchronous)
+4	voice
+5	fax
+also all other values below 128 are reserved by the present document
+[itc] (information transfer capability):
+0	3,1 kHz
+1	UDI
+</description>
+</spec>
+<spec>
+    <command>AT+CNUM=?</command>
+    <profile>Subscriber number (Query all)</profile>
+    <description>Action command returns the MSISDNs related to the subscriber (this information can be stored in the SIM/UICC or in the MT). When storing information in the SIM/UICC, if a SIM card is present or if a UICC with an active GSM application is present, the information is stored in the EFMSISDN under DFTelecom. If a UICC with an active USIM application is present, the information is stored in the EFMSISDN under ADFUSIM). If subscriber has different MSISDN for different services, each MSISDN is returned in a separate line. Refer subclause 9.2 for possible [err] values.
+Defined values
+[alphax]: optional alphanumeric string associated with [numberx]; used character set should be the one selected with command Select TE Character Set +CSCS
+[numberx]: string type phone number of format specified by [typex]
+[typex]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[speed]: as defined in subclause 6.7
+[service] (service related to the phone number):
+0	asynchronous modem
+1	synchronous modem
+2	PAD Access (asynchronous)
+3	Packet Access (synchronous)
+4	voice
+5	fax
+also all other values below 128 are reserved by the present document
+[itc] (information transfer capability):
+0	3,1 kHz
+1	UDI
+</description>
+</spec>
+<spec>
+    <command>AT+CREG=</command>
+    <profile>Network registration (Assign)</profile>
+    <description>Set command controls the presentation of an unsolicited result code +CREG: [stat] when [n]=1 and there is a change in the MT network registration status, or code +CREG: [stat][,[lac],[ci][,[AcT]]] when [n]=2 and there is a change of the network cell.
+Read command returns the status of result code presentation and an integer [stat] which shows whether the network has currently indicated the registration of the MT. Location information elements [lac], [ci] and [AcT]are returned only when [n]=2 and MT is registered in the network. Refer subclause 9.2 for possible [err] values.
+Defined values
+[n]:
+0	disable network registration unsolicited result code
+1	enable network registration unsolicited result code +CREG: [stat]
+2	enable network registration and location information unsolicited result code +CREG: [stat][,[lac],[ci][,[AcT]]]
+[stat]: registration status
+0	not registered, MT is not currently searching a new operator to register to
+1	registered, home network
+2	not registered, but MT is currently searching a new operator to register to
+3	registration denied
+4	unknown
+5	registered, roaming
+[lac]: string type; two byte location area code in hexadecimal format (e.g. '00C3' equals 195 in decimal)
+[ci]: string type; four byte UTRAN/GERAN cell ID in hexadecimal format
+[AcT]: access technology of the registered network
+0	GSM
+1	GSM Compact
+2	UTRAN
+</description>
+</spec>
+<spec>
+    <command>AT+CREG?</command>
+    <profile>Network registration (Query)</profile>
+    <description>Set command controls the presentation of an unsolicited result code +CREG: [stat] when [n]=1 and there is a change in the MT network registration status, or code +CREG: [stat][,[lac],[ci][,[AcT]]] when [n]=2 and there is a change of the network cell.
+Read command returns the status of result code presentation and an integer [stat] which shows whether the network has currently indicated the registration of the MT. Location information elements [lac], [ci] and [AcT]are returned only when [n]=2 and MT is registered in the network. Refer subclause 9.2 for possible [err] values.
+Defined values
+[n]:
+0	disable network registration unsolicited result code
+1	enable network registration unsolicited result code +CREG: [stat]
+2	enable network registration and location information unsolicited result code +CREG: [stat][,[lac],[ci][,[AcT]]]
+[stat]: registration status
+0	not registered, MT is not currently searching a new operator to register to
+1	registered, home network
+2	not registered, but MT is currently searching a new operator to register to
+3	registration denied
+4	unknown
+5	registered, roaming
+[lac]: string type; two byte location area code in hexadecimal format (e.g. '00C3' equals 195 in decimal)
+[ci]: string type; four byte UTRAN/GERAN cell ID in hexadecimal format
+[AcT]: access technology of the registered network
+0	GSM
+1	GSM Compact
+2	UTRAN
+</description>
+</spec>
+<spec>
+    <command>AT+CREG=?</command>
+    <profile>Network registration (Query all)</profile>
+    <description>Set command controls the presentation of an unsolicited result code +CREG: [stat] when [n]=1 and there is a change in the MT network registration status, or code +CREG: [stat][,[lac],[ci][,[AcT]]] when [n]=2 and there is a change of the network cell.
+Read command returns the status of result code presentation and an integer [stat] which shows whether the network has currently indicated the registration of the MT. Location information elements [lac], [ci] and [AcT]are returned only when [n]=2 and MT is registered in the network. Refer subclause 9.2 for possible [err] values.
+Defined values
+[n]:
+0	disable network registration unsolicited result code
+1	enable network registration unsolicited result code +CREG: [stat]
+2	enable network registration and location information unsolicited result code +CREG: [stat][,[lac],[ci][,[AcT]]]
+[stat]: registration status
+0	not registered, MT is not currently searching a new operator to register to
+1	registered, home network
+2	not registered, but MT is currently searching a new operator to register to
+3	registration denied
+4	unknown
+5	registered, roaming
+[lac]: string type; two byte location area code in hexadecimal format (e.g. '00C3' equals 195 in decimal)
+[ci]: string type; four byte UTRAN/GERAN cell ID in hexadecimal format
+[AcT]: access technology of the registered network
+0	GSM
+1	GSM Compact
+2	UTRAN
+</description>
+</spec>
+<spec>
+    <command>AT+COPS=</command>
+    <profile>PLMN selection (Assign)</profile>
+    <description>Set command forces an attempt to select and register the GSM/UMTS network operator. [mode] is used to select whether the selection is done automatically by the MT or is forced by this command to operator [oper] (it shall be given in format [format]) to a certain access technology, indicated in [AcT]. If the selected operator is not available, no other operator shall be selected (except [mode]=4). If the selected access technology is not available, then the same operator shall be selected in other access technology. The selected operator name format shall apply to further read commands (+COPS?) also. [mode]=2 forces an attempt to deregister from the network. The selected mode affects to all further network registration (e.g. after [mode]=2, MT shall be unregistered until [mode]=0 or 1 is selected). Refer subclause 9.2 for possible [err] values. This command should be abortable when registration/deregistration attempt is made.
+Read command returns the current mode, the currently selected operator and the current Access Technology. If no operator is selected, [format], [oper] and [ AcT]  are omitted.
+Test command returns a set of five parameters, each representing an operator present in the network. A set consists of an integer indicating the availability of the operator [stat], long and short alphanumeric format of the name of the operator, numeric format representation of the operator and access technology. Any of the formats may be unavailable and should then be an empty field. The list of operators shall be in order: home network, networks referenced in SIM or active application in the UICC (GSM or USIM) in the following order: HPLMN selector, User controlled PLMN selector, Operator controlled PLMN selector and PLMN selector (in the SIM or GSM application), and other networks.
+It is recommended (although optional) that after the operator list TA returns lists of supported [mode]s and [format]s. These lists shall be delimited from the operator list by two commas. 
+NOTE:	The access technology selected parameters, [AcT], should only be used in terminals capable to register to more than one access technology. Selection of [AcT] does not limit the capability to cell reselections, even though access technology is selected, the phone may still re-select a cell in other access technology.
+Defined values
+[mode]:
+0	automatic ([oper] field is ignored)
+1	manual ([oper] field shall be present, and [AcT] optionally)
+2	deregister from network
+3	set only [format] (for read command +COPS?), do not attempt registration/deregistration ([oper] and [ AcT] fields are ignored); this value is not applicable in read command response
+4	manual/automatic ([oper] field shall be present); if manual selection fails, automatic mode ([mode]=0) is entered
+[format]:
+0	long format alphanumeric [oper]
+1	short format alphanumeric [oper]
+2	numeric [oper]
+[oper]: string type; [format] indicates if the format is alphanumeric or numeric; long alphanumeric format can be upto 16 characters long and short format up to 8 characters (refer GSM MoU SE.13 [9]); numeric format is the GSM Location Area Identification number (refer TS 24.008 [8] subclause 10.5.1.3) which consists of a three BCD digit country code coded as in ITU‑T E.212 Annex A [10], plus a two BCD digit network code, which is administration specific; returned [oper] shall not be in BCD format, but in IRA characters converted from BCD; hence the number has structure: (country code digit 3)(country code digit 2)(country code digit 1)(network code digit 3)(network code digit 2)(network code digit 1)
+[stat]:
+0	unknown
+1	available
+2	current
+3	forbidden
+[AcT] access technology selected:
+0	GSM
+1	GSM Compact
+2	UTRAN
+</description>
+</spec>
+<spec>
+    <command>AT+COPS?</command>
+    <profile>PLMN selection (Query)</profile>
+    <description>Set command forces an attempt to select and register the GSM/UMTS network operator. [mode] is used to select whether the selection is done automatically by the MT or is forced by this command to operator [oper] (it shall be given in format [format]) to a certain access technology, indicated in [AcT]. If the selected operator is not available, no other operator shall be selected (except [mode]=4). If the selected access technology is not available, then the same operator shall be selected in other access technology. The selected operator name format shall apply to further read commands (+COPS?) also. [mode]=2 forces an attempt to deregister from the network. The selected mode affects to all further network registration (e.g. after [mode]=2, MT shall be unregistered until [mode]=0 or 1 is selected). Refer subclause 9.2 for possible [err] values. This command should be abortable when registration/deregistration attempt is made.
+Read command returns the current mode, the currently selected operator and the current Access Technology. If no operator is selected, [format], [oper] and [ AcT]  are omitted.
+Test command returns a set of five parameters, each representing an operator present in the network. A set consists of an integer indicating the availability of the operator [stat], long and short alphanumeric format of the name of the operator, numeric format representation of the operator and access technology. Any of the formats may be unavailable and should then be an empty field. The list of operators shall be in order: home network, networks referenced in SIM or active application in the UICC (GSM or USIM) in the following order: HPLMN selector, User controlled PLMN selector, Operator controlled PLMN selector and PLMN selector (in the SIM or GSM application), and other networks.
+It is recommended (although optional) that after the operator list TA returns lists of supported [mode]s and [format]s. These lists shall be delimited from the operator list by two commas. 
+NOTE:	The access technology selected parameters, [AcT], should only be used in terminals capable to register to more than one access technology. Selection of [AcT] does not limit the capability to cell reselections, even though access technology is selected, the phone may still re-select a cell in other access technology.
+Defined values
+[mode]:
+0	automatic ([oper] field is ignored)
+1	manual ([oper] field shall be present, and [AcT] optionally)
+2	deregister from network
+3	set only [format] (for read command +COPS?), do not attempt registration/deregistration ([oper] and [ AcT] fields are ignored); this value is not applicable in read command response
+4	manual/automatic ([oper] field shall be present); if manual selection fails, automatic mode ([mode]=0) is entered
+[format]:
+0	long format alphanumeric [oper]
+1	short format alphanumeric [oper]
+2	numeric [oper]
+[oper]: string type; [format] indicates if the format is alphanumeric or numeric; long alphanumeric format can be upto 16 characters long and short format up to 8 characters (refer GSM MoU SE.13 [9]); numeric format is the GSM Location Area Identification number (refer TS 24.008 [8] subclause 10.5.1.3) which consists of a three BCD digit country code coded as in ITU‑T E.212 Annex A [10], plus a two BCD digit network code, which is administration specific; returned [oper] shall not be in BCD format, but in IRA characters converted from BCD; hence the number has structure: (country code digit 3)(country code digit 2)(country code digit 1)(network code digit 3)(network code digit 2)(network code digit 1)
+[stat]:
+0	unknown
+1	available
+2	current
+3	forbidden
+[AcT] access technology selected:
+0	GSM
+1	GSM Compact
+2	UTRAN
+</description>
+</spec>
+<spec>
+    <command>AT+COPS=?</command>
+    <profile>PLMN selection (Query all)</profile>
+    <description>Set command forces an attempt to select and register the GSM/UMTS network operator. [mode] is used to select whether the selection is done automatically by the MT or is forced by this command to operator [oper] (it shall be given in format [format]) to a certain access technology, indicated in [AcT]. If the selected operator is not available, no other operator shall be selected (except [mode]=4). If the selected access technology is not available, then the same operator shall be selected in other access technology. The selected operator name format shall apply to further read commands (+COPS?) also. [mode]=2 forces an attempt to deregister from the network. The selected mode affects to all further network registration (e.g. after [mode]=2, MT shall be unregistered until [mode]=0 or 1 is selected). Refer subclause 9.2 for possible [err] values. This command should be abortable when registration/deregistration attempt is made.
+Read command returns the current mode, the currently selected operator and the current Access Technology. If no operator is selected, [format], [oper] and [ AcT]  are omitted.
+Test command returns a set of five parameters, each representing an operator present in the network. A set consists of an integer indicating the availability of the operator [stat], long and short alphanumeric format of the name of the operator, numeric format representation of the operator and access technology. Any of the formats may be unavailable and should then be an empty field. The list of operators shall be in order: home network, networks referenced in SIM or active application in the UICC (GSM or USIM) in the following order: HPLMN selector, User controlled PLMN selector, Operator controlled PLMN selector and PLMN selector (in the SIM or GSM application), and other networks.
+It is recommended (although optional) that after the operator list TA returns lists of supported [mode]s and [format]s. These lists shall be delimited from the operator list by two commas. 
+NOTE:	The access technology selected parameters, [AcT], should only be used in terminals capable to register to more than one access technology. Selection of [AcT] does not limit the capability to cell reselections, even though access technology is selected, the phone may still re-select a cell in other access technology.
+Defined values
+[mode]:
+0	automatic ([oper] field is ignored)
+1	manual ([oper] field shall be present, and [AcT] optionally)
+2	deregister from network
+3	set only [format] (for read command +COPS?), do not attempt registration/deregistration ([oper] and [ AcT] fields are ignored); this value is not applicable in read command response
+4	manual/automatic ([oper] field shall be present); if manual selection fails, automatic mode ([mode]=0) is entered
+[format]:
+0	long format alphanumeric [oper]
+1	short format alphanumeric [oper]
+2	numeric [oper]
+[oper]: string type; [format] indicates if the format is alphanumeric or numeric; long alphanumeric format can be upto 16 characters long and short format up to 8 characters (refer GSM MoU SE.13 [9]); numeric format is the GSM Location Area Identification number (refer TS 24.008 [8] subclause 10.5.1.3) which consists of a three BCD digit country code coded as in ITU‑T E.212 Annex A [10], plus a two BCD digit network code, which is administration specific; returned [oper] shall not be in BCD format, but in IRA characters converted from BCD; hence the number has structure: (country code digit 3)(country code digit 2)(country code digit 1)(network code digit 3)(network code digit 2)(network code digit 1)
+[stat]:
+0	unknown
+1	available
+2	current
+3	forbidden
+[AcT] access technology selected:
+0	GSM
+1	GSM Compact
+2	UTRAN
+</description>
+</spec>
+<spec>
+    <command>AT+CLCK=</command>
+    <profile>Facility lock (Assign)</profile>
+    <description>Execute command is used to lock, unlock or interrogate a MT or a network facility [fac]. Password is normally needed to do such actions. When querying the status of a network service ([mode]=2) the response line for 'not active' case ([status]=0) should be returned only if service is not active for any [class]. Refer subclause 9.2 for possible [err] values. This command should be abortable when network facilities are set or interrogated.
+Call barring facilities are based on GSM/UMTS supplementary services (refer 3GPP TS 22.088 [6]). The interaction of these with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standard.
+Test command returns facility values supported as a compound value.
+Defined values
+[fac] values reserved by the present document:
+'CS'	CNTRL (lock CoNTRoL surface (e.g. phone keyboard))
+'PS'	PH‑SIM (lock PHone to SIM/UICC card) (MT asks password when other than current SIM/UICC card inserted; MT may remember certain amount of previously used cards thus not requiring password when they are inserted)
+'PF'	lock Phone to the very First inserted SIM/UICC card (also referred in the present document as PH-FSIM) (MT asks password when other than the first SIM/UICC card is inserted)
+'SC'	SIM (lock SIM/UICC card) (SIM/UICC asks password in MT power‑up and when this lock command issued)
+'AO'	BAOC (Barr All Outgoing Calls) (refer 3GPP TS 22.088 [6] clause 1)
+'OI'	BOIC (Barr Outgoing International Calls) (refer 3GPP TS 22.088 [6] clause 1)
+'OX'	BOIC‑exHC (Barr Outgoing International Calls except to Home Country) (refer 3GPP TS 22.088 [6] clause 1)
+'AI'	BAIC (Barr All Incoming Calls) (refer 3GPP TS 22.088 [6] clause 2)
+'IR'	BIC‑Roam (Barr Incoming Calls when Roaming outside the home country) (refer 3GPP TS 22.088 [6] clause 2)
+'NT'	barr incoming calls from numbers Not stored to TA memory
+'NM'	barr incoming calls from numbers Not stored to MT memory
+'NS'	barr incoming calls from numbers Not stored to SIM/UICC memory
+'NA'	barr incoming calls from numbers Not stored in Any memory
+'AB'	All Barring services (refer 3GPP TS 22.030 [19]) (applicable only for [mode]=0)
+'AG'	All outGoing barring services (refer 3GPP TS 22.030 [19]) (applicable only for [mode]=0)
+'AC'	All inComing barring services (refer 3GPP TS 22.030 [19]) (applicable only for [mode]=0)
+'FD'	SIM card or active application in the UICC (GSM or USIM) fixed dialling memory feature (if PIN2 authentication has not been done during the current session, PIN2 is required as [passwd])
+'PN'	Network Personalization (refer 3GPP TS 22.022 [33])
+'PU'	network sUbset Personalization (refer 3GPP TS 22.022 [33])
+'PP'	service Provider Personalization (refer 3GPP TS 22.022 [33])
+'PC'	Corporate Personalization (refer 3GPP TS 22.022 [33])
+[mode]:
+0	unlock
+1	lock
+2	query status
+[status]:
+0	not active
+1	active
+[passwd]: string type; shall be the same as password specified for the facility from the MT user interface or with command Change Password +CPWD
+[classx] is a sum of integers each representing a class of information (default 7):
+1	voice (telephony)
+2	data (refers to all bearer services; with [mode]=2 this may refer only to some bearer service if TA does not support values 16, 32, 64 and 128)
+4	fax (facsimile services)
+8	short message service
+16	data circuit sync
+32	data circuit async
+64	dedicated packet access
+128	dedicated PAD access
+</description>
+</spec>
+<spec>
+    <command>AT+CLCK=?</command>
+    <profile>Facility lock (Query all)</profile>
+    <description>Execute command is used to lock, unlock or interrogate a MT or a network facility [fac]. Password is normally needed to do such actions. When querying the status of a network service ([mode]=2) the response line for 'not active' case ([status]=0) should be returned only if service is not active for any [class]. Refer subclause 9.2 for possible [err] values. This command should be abortable when network facilities are set or interrogated.
+Call barring facilities are based on GSM/UMTS supplementary services (refer 3GPP TS 22.088 [6]). The interaction of these with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standard.
+Test command returns facility values supported as a compound value.
+Defined values
+[fac] values reserved by the present document:
+'CS'	CNTRL (lock CoNTRoL surface (e.g. phone keyboard))
+'PS'	PH‑SIM (lock PHone to SIM/UICC card) (MT asks password when other than current SIM/UICC card inserted; MT may remember certain amount of previously used cards thus not requiring password when they are inserted)
+'PF'	lock Phone to the very First inserted SIM/UICC card (also referred in the present document as PH-FSIM) (MT asks password when other than the first SIM/UICC card is inserted)
+'SC'	SIM (lock SIM/UICC card) (SIM/UICC asks password in MT power‑up and when this lock command issued)
+'AO'	BAOC (Barr All Outgoing Calls) (refer 3GPP TS 22.088 [6] clause 1)
+'OI'	BOIC (Barr Outgoing International Calls) (refer 3GPP TS 22.088 [6] clause 1)
+'OX'	BOIC‑exHC (Barr Outgoing International Calls except to Home Country) (refer 3GPP TS 22.088 [6] clause 1)
+'AI'	BAIC (Barr All Incoming Calls) (refer 3GPP TS 22.088 [6] clause 2)
+'IR'	BIC‑Roam (Barr Incoming Calls when Roaming outside the home country) (refer 3GPP TS 22.088 [6] clause 2)
+'NT'	barr incoming calls from numbers Not stored to TA memory
+'NM'	barr incoming calls from numbers Not stored to MT memory
+'NS'	barr incoming calls from numbers Not stored to SIM/UICC memory
+'NA'	barr incoming calls from numbers Not stored in Any memory
+'AB'	All Barring services (refer 3GPP TS 22.030 [19]) (applicable only for [mode]=0)
+'AG'	All outGoing barring services (refer 3GPP TS 22.030 [19]) (applicable only for [mode]=0)
+'AC'	All inComing barring services (refer 3GPP TS 22.030 [19]) (applicable only for [mode]=0)
+'FD'	SIM card or active application in the UICC (GSM or USIM) fixed dialling memory feature (if PIN2 authentication has not been done during the current session, PIN2 is required as [passwd])
+'PN'	Network Personalization (refer 3GPP TS 22.022 [33])
+'PU'	network sUbset Personalization (refer 3GPP TS 22.022 [33])
+'PP'	service Provider Personalization (refer 3GPP TS 22.022 [33])
+'PC'	Corporate Personalization (refer 3GPP TS 22.022 [33])
+[mode]:
+0	unlock
+1	lock
+2	query status
+[status]:
+0	not active
+1	active
+[passwd]: string type; shall be the same as password specified for the facility from the MT user interface or with command Change Password +CPWD
+[classx] is a sum of integers each representing a class of information (default 7):
+1	voice (telephony)
+2	data (refers to all bearer services; with [mode]=2 this may refer only to some bearer service if TA does not support values 16, 32, 64 and 128)
+4	fax (facsimile services)
+8	short message service
+16	data circuit sync
+32	data circuit async
+64	dedicated packet access
+128	dedicated PAD access
+</description>
+</spec>
+<spec>
+    <command>AT+CPWD=</command>
+    <profile>Change password (Assign)</profile>
+    <description>Action command sets a new password for the facility lock function defined by command Facility Lock +CLCK. Refer subclause 9.2 for possible [err] values.
+Test command returns a list of pairs which present the available facilities and the maximum length of their password.
+Defined values
+[fac]: 
+'P2'	SIM PIN2
+ refer Facility Lock +CLCK for other values
+[oldpwd], [newpwd]: string type; [oldpwd] shall be the same as password specified for the facility from the MT user interface or with command Change Password +CPWD and [newpwd] is the new password; maximum length of password can be determined with [pwdlength]
+[pwdlength]: integer type maximum length of the password for the facility
+</description>
+</spec>
+<spec>
+    <command>AT+CPWD=?</command>
+    <profile>Change password (Query all)</profile>
+    <description>Action command sets a new password for the facility lock function defined by command Facility Lock +CLCK. Refer subclause 9.2 for possible [err] values.
+Test command returns a list of pairs which present the available facilities and the maximum length of their password.
+Defined values
+[fac]: 
+'P2'	SIM PIN2
+ refer Facility Lock +CLCK for other values
+[oldpwd], [newpwd]: string type; [oldpwd] shall be the same as password specified for the facility from the MT user interface or with command Change Password +CPWD and [newpwd] is the new password; maximum length of password can be determined with [pwdlength]
+[pwdlength]: integer type maximum length of the password for the facility
+</description>
+</spec>
+<spec>
+    <command>AT+CLIP=</command>
+    <profile>Calling line identification presentation (Assign)</profile>
+    <description>This command refers to the GSM/UMTS supplementary service CLIP (Calling Line Identification Presentation) that enables a called subscriber to get the calling line identity (CLI) of the calling party when receiving a mobile terminated call. Set command enables or disables the presentation of the CLI at the TE. It has no effect on the execution of the supplementary service CLIP in the network.
+When the presentation of the CLI at the TE is enabled (and calling subscriber allows), +CLIP: [number],[type][,[subaddr],[satype][,[[alpha]][,[CLI validity]]]] response is returned after every RING (or +CRING: [type]; refer subclause 'Cellular result codes +CRC') result code sent from TA to TE. It is manufacturer specific if this response is used when normal voice call is answered.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the CLIP service according 3GPP TS 22.081 [3] (given in [m]).Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber CLIP service status in the network):
+0	CLIP not provisioned
+1	CLIP provisioned
+2	unknown (e.g. no network, etc.)
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+[alpha]: optional string type alphanumeric representation of [number] corresponding to the entry found in phonebook; used character set should be the one selected with command Select TE Character Set +CSCS
+[CLI validity]:
+0	CLI valid
+1	CLI has been withheld by the originator.
+2	CLI is not available due to interworking problems or limitations of originating network. 
+When CLI is not available ( [CLI validity]=2), [number] shall be an empty string ('') and [type] value will not be significant. Nevertheless, TA may return the recommended value 128 for [type] ((TON/NPI unknown in accordance with TS 24.008 [8] subclause 10.5.4.7).
+When CLI has been withheld by the originator, ([CLI validity]=1) and the CLIP is provisioned with the 'override category' option (refer 3GPP TS 22.081[3] and 3GPP TS 23.081[40]), [number] and [type] is provided. Otherwise, TA shall return the same setting for [number] and [type] as if the CLI was not available.
+</description>
+</spec>
+<spec>
+    <command>AT+CLIP?</command>
+    <profile>Calling line identification presentation (Query)</profile>
+    <description>This command refers to the GSM/UMTS supplementary service CLIP (Calling Line Identification Presentation) that enables a called subscriber to get the calling line identity (CLI) of the calling party when receiving a mobile terminated call. Set command enables or disables the presentation of the CLI at the TE. It has no effect on the execution of the supplementary service CLIP in the network.
+When the presentation of the CLI at the TE is enabled (and calling subscriber allows), +CLIP: [number],[type][,[subaddr],[satype][,[[alpha]][,[CLI validity]]]] response is returned after every RING (or +CRING: [type]; refer subclause 'Cellular result codes +CRC') result code sent from TA to TE. It is manufacturer specific if this response is used when normal voice call is answered.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the CLIP service according 3GPP TS 22.081 [3] (given in [m]).Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber CLIP service status in the network):
+0	CLIP not provisioned
+1	CLIP provisioned
+2	unknown (e.g. no network, etc.)
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+[alpha]: optional string type alphanumeric representation of [number] corresponding to the entry found in phonebook; used character set should be the one selected with command Select TE Character Set +CSCS
+[CLI validity]:
+0	CLI valid
+1	CLI has been withheld by the originator.
+2	CLI is not available due to interworking problems or limitations of originating network. 
+When CLI is not available ( [CLI validity]=2), [number] shall be an empty string ('') and [type] value will not be significant. Nevertheless, TA may return the recommended value 128 for [type] ((TON/NPI unknown in accordance with TS 24.008 [8] subclause 10.5.4.7).
+When CLI has been withheld by the originator, ([CLI validity]=1) and the CLIP is provisioned with the 'override category' option (refer 3GPP TS 22.081[3] and 3GPP TS 23.081[40]), [number] and [type] is provided. Otherwise, TA shall return the same setting for [number] and [type] as if the CLI was not available.
+</description>
+</spec>
+<spec>
+    <command>AT+CLIP=?</command>
+    <profile>Calling line identification presentation (Query all)</profile>
+    <description>This command refers to the GSM/UMTS supplementary service CLIP (Calling Line Identification Presentation) that enables a called subscriber to get the calling line identity (CLI) of the calling party when receiving a mobile terminated call. Set command enables or disables the presentation of the CLI at the TE. It has no effect on the execution of the supplementary service CLIP in the network.
+When the presentation of the CLI at the TE is enabled (and calling subscriber allows), +CLIP: [number],[type][,[subaddr],[satype][,[[alpha]][,[CLI validity]]]] response is returned after every RING (or +CRING: [type]; refer subclause 'Cellular result codes +CRC') result code sent from TA to TE. It is manufacturer specific if this response is used when normal voice call is answered.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the CLIP service according 3GPP TS 22.081 [3] (given in [m]).Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber CLIP service status in the network):
+0	CLIP not provisioned
+1	CLIP provisioned
+2	unknown (e.g. no network, etc.)
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+[alpha]: optional string type alphanumeric representation of [number] corresponding to the entry found in phonebook; used character set should be the one selected with command Select TE Character Set +CSCS
+[CLI validity]:
+0	CLI valid
+1	CLI has been withheld by the originator.
+2	CLI is not available due to interworking problems or limitations of originating network. 
+When CLI is not available ( [CLI validity]=2), [number] shall be an empty string ('') and [type] value will not be significant. Nevertheless, TA may return the recommended value 128 for [type] ((TON/NPI unknown in accordance with TS 24.008 [8] subclause 10.5.4.7).
+When CLI has been withheld by the originator, ([CLI validity]=1) and the CLIP is provisioned with the 'override category' option (refer 3GPP TS 22.081[3] and 3GPP TS 23.081[40]), [number] and [type] is provided. Otherwise, TA shall return the same setting for [number] and [type] as if the CLI was not available.
+</description>
+</spec>
+<spec>
+    <command>AT+CLIR=</command>
+    <profile>Calling line identification restriction (Assign)</profile>
+    <description>This command refers to CLIR‑service according to 3GPP TS 22.081 [3] that allows a calling subscriber to enable or disable the presentation of the CLI to the called party when originating a call. 
+Set command overrides the CLIR subscription (default is restricted or allowed) when temporary mode is provisioned as a default adjustment for all following outgoing calls. This adjustment can be revoked by using the opposite command.. If this command is used by a subscriber without provision of CLIR in permanent mode the network will act according 3GPP TS 22.081 [3].
+Read command gives the default adjustment for all outgoing calls (given in [n]), and also triggers an interrogation of the provision status of the CLIR service (given in [m]). Test command returns values supported as a compound value.
+NOTE:	On a per call base CLIR functionality is explained in subclause 'ITU‑T V.250 [14] dial command'.
+Defined values
+[n] (parameter sets the adjustment for outgoing calls):
+0	presentation indicator is used according to the subscription of the CLIR service
+1	CLIR invocation
+2	CLIR suppression
+[m] (parameter shows the subscriber CLIR service status in the network):
+0	CLIR not provisioned
+1	CLIR provisioned in permanent mode
+2	unknown (e.g. no network, etc.)
+3	CLIR temporary mode presentation restricted
+4	CLIR temporary mode presentation allowed
+</description>
+</spec>
+<spec>
+    <command>AT+CLIR?</command>
+    <profile>Calling line identification restriction (Query)</profile>
+    <description>This command refers to CLIR‑service according to 3GPP TS 22.081 [3] that allows a calling subscriber to enable or disable the presentation of the CLI to the called party when originating a call. 
+Set command overrides the CLIR subscription (default is restricted or allowed) when temporary mode is provisioned as a default adjustment for all following outgoing calls. This adjustment can be revoked by using the opposite command.. If this command is used by a subscriber without provision of CLIR in permanent mode the network will act according 3GPP TS 22.081 [3].
+Read command gives the default adjustment for all outgoing calls (given in [n]), and also triggers an interrogation of the provision status of the CLIR service (given in [m]). Test command returns values supported as a compound value.
+NOTE:	On a per call base CLIR functionality is explained in subclause 'ITU‑T V.250 [14] dial command'.
+Defined values
+[n] (parameter sets the adjustment for outgoing calls):
+0	presentation indicator is used according to the subscription of the CLIR service
+1	CLIR invocation
+2	CLIR suppression
+[m] (parameter shows the subscriber CLIR service status in the network):
+0	CLIR not provisioned
+1	CLIR provisioned in permanent mode
+2	unknown (e.g. no network, etc.)
+3	CLIR temporary mode presentation restricted
+4	CLIR temporary mode presentation allowed
+</description>
+</spec>
+<spec>
+    <command>AT+CLIR=?</command>
+    <profile>Calling line identification restriction (Query all)</profile>
+    <description>This command refers to CLIR‑service according to 3GPP TS 22.081 [3] that allows a calling subscriber to enable or disable the presentation of the CLI to the called party when originating a call. 
+Set command overrides the CLIR subscription (default is restricted or allowed) when temporary mode is provisioned as a default adjustment for all following outgoing calls. This adjustment can be revoked by using the opposite command.. If this command is used by a subscriber without provision of CLIR in permanent mode the network will act according 3GPP TS 22.081 [3].
+Read command gives the default adjustment for all outgoing calls (given in [n]), and also triggers an interrogation of the provision status of the CLIR service (given in [m]). Test command returns values supported as a compound value.
+NOTE:	On a per call base CLIR functionality is explained in subclause 'ITU‑T V.250 [14] dial command'.
+Defined values
+[n] (parameter sets the adjustment for outgoing calls):
+0	presentation indicator is used according to the subscription of the CLIR service
+1	CLIR invocation
+2	CLIR suppression
+[m] (parameter shows the subscriber CLIR service status in the network):
+0	CLIR not provisioned
+1	CLIR provisioned in permanent mode
+2	unknown (e.g. no network, etc.)
+3	CLIR temporary mode presentation restricted
+4	CLIR temporary mode presentation allowed
+</description>
+</spec>
+<spec>
+    <command>AT+COLP=</command>
+    <profile>Connected line identification presentation (Assign)</profile>
+    <description>This command refers to the GSM/UMTS supplementary service COLP (Connected Line Identification Presentation) that enables a calling subscriber to get the connected line identity (COL) of the called party after setting up a mobile originated call. The command enables or disables the presentation of the COL at the TE. It has no effect on the execution of the supplementary service COLR in the network.
+When enabled (and called subscriber allows), +COLP: 	
+[number],[type][,[subaddr],[satype] [,[alpha]]] intermediate result code is returned from TA to TE before any +CR or V.250 [14] responses. It is manufacturer specific if this response is used when normal voice call is established.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the COLP service according 3GPP TS 22.081 [3] (given in [m]).
+Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber COLP service status in the network):
+0	COLP not provisioned
+1	COLP provisioned
+2	unknown (e.g. no network, etc.)
+[number], [type], [subaddr], [satype], [alpha]: refer +CLIP
+</description>
+</spec>
+<spec>
+    <command>AT+COLP?</command>
+    <profile>Connected line identification presentation (Query)</profile>
+    <description>This command refers to the GSM/UMTS supplementary service COLP (Connected Line Identification Presentation) that enables a calling subscriber to get the connected line identity (COL) of the called party after setting up a mobile originated call. The command enables or disables the presentation of the COL at the TE. It has no effect on the execution of the supplementary service COLR in the network.
+When enabled (and called subscriber allows), +COLP: 	
+[number],[type][,[subaddr],[satype] [,[alpha]]] intermediate result code is returned from TA to TE before any +CR or V.250 [14] responses. It is manufacturer specific if this response is used when normal voice call is established.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the COLP service according 3GPP TS 22.081 [3] (given in [m]).
+Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber COLP service status in the network):
+0	COLP not provisioned
+1	COLP provisioned
+2	unknown (e.g. no network, etc.)
+[number], [type], [subaddr], [satype], [alpha]: refer +CLIP
+</description>
+</spec>
+<spec>
+    <command>AT+COLP=?</command>
+    <profile>Connected line identification presentation (Query all)</profile>
+    <description>This command refers to the GSM/UMTS supplementary service COLP (Connected Line Identification Presentation) that enables a calling subscriber to get the connected line identity (COL) of the called party after setting up a mobile originated call. The command enables or disables the presentation of the COL at the TE. It has no effect on the execution of the supplementary service COLR in the network.
+When enabled (and called subscriber allows), +COLP: 	
+[number],[type][,[subaddr],[satype] [,[alpha]]] intermediate result code is returned from TA to TE before any +CR or V.250 [14] responses. It is manufacturer specific if this response is used when normal voice call is established.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the COLP service according 3GPP TS 22.081 [3] (given in [m]).
+Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber COLP service status in the network):
+0	COLP not provisioned
+1	COLP provisioned
+2	unknown (e.g. no network, etc.)
+[number], [type], [subaddr], [satype], [alpha]: refer +CLIP
+</description>
+</spec>
+<spec>
+    <command>AT+CDIP=</command>
+    <profile>Called line identification presentation (Assign)</profile>
+    <description>This command related to a network service that provides 'multiple called numbers (called line identifications) service' to an MT. This command enables a called subscriber to get the called line identification of the called party when receiving a mobile terminated call. Set command enables or disables the presentation of the called line identifications at the TE.
+When the presentation of the called line identification at the TE is enabled, +CDIP:[number],[type][,[subaddr],[satype]] response is returned after every RING (or +CRING: [type]; refer subclause 'Cellular result codes +CRC') result code sent from TA to TE. It is manufacturer specific if this response is used when normal voice call is answered.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the 'multiple called numbers' service. Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber 'multiple called numbers' service status in the network):
+0	'multiple called numbers service' is not provisioned
+1	'multiple called numbers service' is provisioned
+2	unknown (e.g. no network, etc.)
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+</description>
+</spec>
+<spec>
+    <command>AT+CDIP?</command>
+    <profile>Called line identification presentation (Query)</profile>
+    <description>This command related to a network service that provides 'multiple called numbers (called line identifications) service' to an MT. This command enables a called subscriber to get the called line identification of the called party when receiving a mobile terminated call. Set command enables or disables the presentation of the called line identifications at the TE.
+When the presentation of the called line identification at the TE is enabled, +CDIP:[number],[type][,[subaddr],[satype]] response is returned after every RING (or +CRING: [type]; refer subclause 'Cellular result codes +CRC') result code sent from TA to TE. It is manufacturer specific if this response is used when normal voice call is answered.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the 'multiple called numbers' service. Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber 'multiple called numbers' service status in the network):
+0	'multiple called numbers service' is not provisioned
+1	'multiple called numbers service' is provisioned
+2	unknown (e.g. no network, etc.)
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+</description>
+</spec>
+<spec>
+    <command>AT+CDIP=?</command>
+    <profile>Called line identification presentation (Query all)</profile>
+    <description>This command related to a network service that provides 'multiple called numbers (called line identifications) service' to an MT. This command enables a called subscriber to get the called line identification of the called party when receiving a mobile terminated call. Set command enables or disables the presentation of the called line identifications at the TE.
+When the presentation of the called line identification at the TE is enabled, +CDIP:[number],[type][,[subaddr],[satype]] response is returned after every RING (or +CRING: [type]; refer subclause 'Cellular result codes +CRC') result code sent from TA to TE. It is manufacturer specific if this response is used when normal voice call is answered.
+Read command gives the status of [n], and also triggers an interrogation of the provision status of the 'multiple called numbers' service. Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter shows the subscriber 'multiple called numbers' service status in the network):
+0	'multiple called numbers service' is not provisioned
+1	'multiple called numbers service' is provisioned
+2	unknown (e.g. no network, etc.)
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+</description>
+</spec>
+<spec>
+    <command>AT+CCUG=</command>
+    <profile>Closed user group (Assign)</profile>
+    <description>This command allows control of the Closed User Group supplementary service (refer 3GPP TS 22.085 [21]). Set command enables the served subscriber to select a CUG index, to suppress the Outgoing Access (OA), and to suppress the preferential CUG.
+Set command with [n]=1 enables to control the CUG information on the air interface as a default adjustment for all following outgoing calls. The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standard.
+NOTE:	On a per call base CUG functionality is explained in subclause 'ITU‑T V.250 [14] dial command'.
+Defined values
+[n]:
+0	disable CUG temporary mode
+1	enable CUG temporary mode
+[index]:
+0...9	CUG index
+10	no index (preferred CUG taken from subscriber data)
+[info]:
+0	no information
+1	suppress OA
+2	suppress preferential CUG
+3	suppress OA and preferential CUG
+</description>
+</spec>
+<spec>
+    <command>AT+CCUG?</command>
+    <profile>Closed user group (Query)</profile>
+    <description>This command allows control of the Closed User Group supplementary service (refer 3GPP TS 22.085 [21]). Set command enables the served subscriber to select a CUG index, to suppress the Outgoing Access (OA), and to suppress the preferential CUG.
+Set command with [n]=1 enables to control the CUG information on the air interface as a default adjustment for all following outgoing calls. The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standard.
+NOTE:	On a per call base CUG functionality is explained in subclause 'ITU‑T V.250 [14] dial command'.
+Defined values
+[n]:
+0	disable CUG temporary mode
+1	enable CUG temporary mode
+[index]:
+0...9	CUG index
+10	no index (preferred CUG taken from subscriber data)
+[info]:
+0	no information
+1	suppress OA
+2	suppress preferential CUG
+3	suppress OA and preferential CUG
+</description>
+</spec>
+<spec>
+    <command>AT+CCUG=?</command>
+    <profile>Closed user group (Query all)</profile>
+    <description>This command allows control of the Closed User Group supplementary service (refer 3GPP TS 22.085 [21]). Set command enables the served subscriber to select a CUG index, to suppress the Outgoing Access (OA), and to suppress the preferential CUG.
+Set command with [n]=1 enables to control the CUG information on the air interface as a default adjustment for all following outgoing calls. The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standard.
+NOTE:	On a per call base CUG functionality is explained in subclause 'ITU‑T V.250 [14] dial command'.
+Defined values
+[n]:
+0	disable CUG temporary mode
+1	enable CUG temporary mode
+[index]:
+0...9	CUG index
+10	no index (preferred CUG taken from subscriber data)
+[info]:
+0	no information
+1	suppress OA
+2	suppress preferential CUG
+3	suppress OA and preferential CUG
+</description>
+</spec>
+<spec>
+    <command>AT+CCFC=</command>
+    <profile>Call forwarding number and conditions (Assign)</profile>
+    <description>This command allows control of the call forwarding supplementary service according to 3GPP TS 22.082 [4]. Registration, erasure, activation, deactivation, and status query are supported. When querying the status of a network service ([mode]=2) the response line for 'not active' case ([status]=0) should be returned only if service is not active for any [class].
+Test command returns reason values supported as a compound value.
+Defined values
+[reason]:
+0	unconditional
+1	mobile busy
+2	no reply
+3	not reachable
+4	all call forwarding (refer 3GPP TS 22.030 [19])
+5	all conditional call forwarding (refer 3GPP TS 22.030 [19])
+[mode]:
+0	disable
+1	enable
+2	query status
+3	registration
+4	erasure
+[number]: string type phone number of forwarding address in format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8); default 128
+[classx] is a sum of integers each representing a class of information (default 7):
+1	voice (telephony)
+2	data (refers to all bearer services; with [mode]=2 this may refer only to some bearer service if TA does not support values 16, 32, 64 and 128)
+4	fax (facsimile services)
+8	short message service
+16	data circuit sync
+32	data circuit async
+64	dedicated packet access
+128	dedicated PAD access
+[time]:
+1...30	when 'no reply' is enabled or queried, this gives the time in seconds to wait before call is forwarded, default value 20
+[status]:
+0	not active
+1	active
+</description>
+</spec>
+<spec>
+    <command>AT+CCFC=?</command>
+    <profile>Call forwarding number and conditions (Query all)</profile>
+    <description>This command allows control of the call forwarding supplementary service according to 3GPP TS 22.082 [4]. Registration, erasure, activation, deactivation, and status query are supported. When querying the status of a network service ([mode]=2) the response line for 'not active' case ([status]=0) should be returned only if service is not active for any [class].
+Test command returns reason values supported as a compound value.
+Defined values
+[reason]:
+0	unconditional
+1	mobile busy
+2	no reply
+3	not reachable
+4	all call forwarding (refer 3GPP TS 22.030 [19])
+5	all conditional call forwarding (refer 3GPP TS 22.030 [19])
+[mode]:
+0	disable
+1	enable
+2	query status
+3	registration
+4	erasure
+[number]: string type phone number of forwarding address in format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8); default 128
+[classx] is a sum of integers each representing a class of information (default 7):
+1	voice (telephony)
+2	data (refers to all bearer services; with [mode]=2 this may refer only to some bearer service if TA does not support values 16, 32, 64 and 128)
+4	fax (facsimile services)
+8	short message service
+16	data circuit sync
+32	data circuit async
+64	dedicated packet access
+128	dedicated PAD access
+[time]:
+1...30	when 'no reply' is enabled or queried, this gives the time in seconds to wait before call is forwarded, default value 20
+[status]:
+0	not active
+1	active
+</description>
+</spec>
+<spec>
+    <command>AT+CCWA=</command>
+    <profile>Call waiting (Assign)</profile>
+    <description>This command allows control of the Call Waiting supplementary service according to 3GPP TS 22.083 [5]. Activation, deactivation and status query are supported. When querying the status of a network service ([mode]=2) the response line for 'not active' case ([status]=0) should be returned only if service is not active for any [class]. Parameter [n] is used to disable/enable the presentation of an unsolicited result code +CCWA: [number],[type],[class],[[alpha]][,[CLI validity][,[subaddr],[satype] [,[priority] ]]] to the TE when call waiting service is enabled. Command should be abortable when network is interrogated.
+The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+Test command returns values supported as a compound value.
+Defined values
+[n] (sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[mode] (when [mode] parameter is not given, network is not interrogated):
+0	disable
+1	enable
+2	query status
+[classx] is a sum of integers each representing a class of information (default 7):
+1	voice (telephony)
+2	data (refers to all bearer services; with [mode]=2 this may refer only to some bearer service if TA does not support values 16, 32, 64 and 128)
+4	fax (facsimile services)
+8	short message service
+16	data circuit sync
+32	data circuit async
+64	dedicated packet access
+128	dedicated PAD access
+[status]:
+0	not active
+1	active
+[number]: string type phone number of calling address in format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[alpha]: optional string type alphanumeric representation of [number] corresponding to the entry found in phonebook; used character set should be the one selected with command Select TE Character Set +CSCS
+[CLI validity]:
+0	CLI valid
+1	CLI has been withheld by the originator.
+2	CLI is not available due to interworking problems or limitations of originating network. 
+When CLI is not available ([CLI validity]=2), [number] shall be an empty string ('') and [type] value will not be significant. Nevertheless, TA may return the recommended value 128 for [type] ((TON/NPI unknown in accordance with TS 24.008 [8] subclause 10.5.4.7).
+When CLI has been withheld by the originator, ([CLI validity]=1) and the CLIP is provisioned with the 'override category' option (refer 3GPP TS 22.081[3] and 3GPP TS 23.081[40]), [number] and [type] is provided. Otherwise, TA shall return the same setting for [number] and [type] as if the CLI was not available.
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+[priority]: optional digit type parameter indicating that the eMLPP priority level of the incoming call. The priority level values are as defined in eMLPP specification 3GPP TS 22.067 [54].
+
+</description>
+</spec>
+<spec>
+    <command>AT+CCWA?</command>
+    <profile>Call waiting (Query)</profile>
+    <description>This command allows control of the Call Waiting supplementary service according to 3GPP TS 22.083 [5]. Activation, deactivation and status query are supported. When querying the status of a network service ([mode]=2) the response line for 'not active' case ([status]=0) should be returned only if service is not active for any [class]. Parameter [n] is used to disable/enable the presentation of an unsolicited result code +CCWA: [number],[type],[class],[[alpha]][,[CLI validity][,[subaddr],[satype] [,[priority] ]]] to the TE when call waiting service is enabled. Command should be abortable when network is interrogated.
+The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+Test command returns values supported as a compound value.
+Defined values
+[n] (sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[mode] (when [mode] parameter is not given, network is not interrogated):
+0	disable
+1	enable
+2	query status
+[classx] is a sum of integers each representing a class of information (default 7):
+1	voice (telephony)
+2	data (refers to all bearer services; with [mode]=2 this may refer only to some bearer service if TA does not support values 16, 32, 64 and 128)
+4	fax (facsimile services)
+8	short message service
+16	data circuit sync
+32	data circuit async
+64	dedicated packet access
+128	dedicated PAD access
+[status]:
+0	not active
+1	active
+[number]: string type phone number of calling address in format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[alpha]: optional string type alphanumeric representation of [number] corresponding to the entry found in phonebook; used character set should be the one selected with command Select TE Character Set +CSCS
+[CLI validity]:
+0	CLI valid
+1	CLI has been withheld by the originator.
+2	CLI is not available due to interworking problems or limitations of originating network. 
+When CLI is not available ([CLI validity]=2), [number] shall be an empty string ('') and [type] value will not be significant. Nevertheless, TA may return the recommended value 128 for [type] ((TON/NPI unknown in accordance with TS 24.008 [8] subclause 10.5.4.7).
+When CLI has been withheld by the originator, ([CLI validity]=1) and the CLIP is provisioned with the 'override category' option (refer 3GPP TS 22.081[3] and 3GPP TS 23.081[40]), [number] and [type] is provided. Otherwise, TA shall return the same setting for [number] and [type] as if the CLI was not available.
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+[priority]: optional digit type parameter indicating that the eMLPP priority level of the incoming call. The priority level values are as defined in eMLPP specification 3GPP TS 22.067 [54].
+
+</description>
+</spec>
+<spec>
+    <command>AT+CCWA=?</command>
+    <profile>Call waiting (Query all)</profile>
+    <description>This command allows control of the Call Waiting supplementary service according to 3GPP TS 22.083 [5]. Activation, deactivation and status query are supported. When querying the status of a network service ([mode]=2) the response line for 'not active' case ([status]=0) should be returned only if service is not active for any [class]. Parameter [n] is used to disable/enable the presentation of an unsolicited result code +CCWA: [number],[type],[class],[[alpha]][,[CLI validity][,[subaddr],[satype] [,[priority] ]]] to the TE when call waiting service is enabled. Command should be abortable when network is interrogated.
+The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+Test command returns values supported as a compound value.
+Defined values
+[n] (sets/shows the result code presentation status to the TE):
+0	disable
+1	enable
+[mode] (when [mode] parameter is not given, network is not interrogated):
+0	disable
+1	enable
+2	query status
+[classx] is a sum of integers each representing a class of information (default 7):
+1	voice (telephony)
+2	data (refers to all bearer services; with [mode]=2 this may refer only to some bearer service if TA does not support values 16, 32, 64 and 128)
+4	fax (facsimile services)
+8	short message service
+16	data circuit sync
+32	data circuit async
+64	dedicated packet access
+128	dedicated PAD access
+[status]:
+0	not active
+1	active
+[number]: string type phone number of calling address in format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[alpha]: optional string type alphanumeric representation of [number] corresponding to the entry found in phonebook; used character set should be the one selected with command Select TE Character Set +CSCS
+[CLI validity]:
+0	CLI valid
+1	CLI has been withheld by the originator.
+2	CLI is not available due to interworking problems or limitations of originating network. 
+When CLI is not available ([CLI validity]=2), [number] shall be an empty string ('') and [type] value will not be significant. Nevertheless, TA may return the recommended value 128 for [type] ((TON/NPI unknown in accordance with TS 24.008 [8] subclause 10.5.4.7).
+When CLI has been withheld by the originator, ([CLI validity]=1) and the CLIP is provisioned with the 'override category' option (refer 3GPP TS 22.081[3] and 3GPP TS 23.081[40]), [number] and [type] is provided. Otherwise, TA shall return the same setting for [number] and [type] as if the CLI was not available.
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+[priority]: optional digit type parameter indicating that the eMLPP priority level of the incoming call. The priority level values are as defined in eMLPP specification 3GPP TS 22.067 [54].
+
+</description>
+</spec>
+<spec>
+    <command>AT+CHLD=</command>
+    <profile>Call related supplementary services (Assign)</profile>
+    <description>This command allows the control of the following call related services:
+-	a call can be temporarily disconnected from the MT but the connection is retained by the network;
+-	multiparty conversation (conference calls);
+-	the served subscriber who has two calls (one held and the other either active or alerting) can connect the other parties and release the served subscriber's own connection.
+Calls can be put on hold, recovered, released, added to conversation, and transferred similarly as defined in 3GPP TS 22.030 [19]. Refer subclause 9.2 for possible [err] values.
+This is based on the GSM/UMTS supplementary services HOLD (Call Hold; refer 3GPP TS 22.083 [5] clause 2), MPTY (MultiParty; refer 3GPP TS 22.084 [22]) and ECT (Explicit Call Transfer; refer 3GPP TS 22.091 [29]). The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+NOTE:	Call Hold, MultiParty and Explicit Call Transfer are only applicable to teleservice 11.
+It is recommended (although optional) that test command returns a list of operations which are supported. The call number required by some operations shall be denoted by 'x' (e.g. +CHLD: (0,1,1x,2,2x,3)).
+Defined values
+[n]: integer type; equals to numbers entered before SEND button in 3GPP TS 22.030 [19] subclause 6.5.5.1
+NOTE:	The 'directory number' case shall be handled with dial command D, and the END case with hangup command H (or +CHUP). The 4*'directory number' case is handled with +CTFR command.
+</description>
+</spec>
+<spec>
+    <command>AT+CHLD=?</command>
+    <profile>Call related supplementary services (Query all)</profile>
+    <description>This command allows the control of the following call related services:
+-	a call can be temporarily disconnected from the MT but the connection is retained by the network;
+-	multiparty conversation (conference calls);
+-	the served subscriber who has two calls (one held and the other either active or alerting) can connect the other parties and release the served subscriber's own connection.
+Calls can be put on hold, recovered, released, added to conversation, and transferred similarly as defined in 3GPP TS 22.030 [19]. Refer subclause 9.2 for possible [err] values.
+This is based on the GSM/UMTS supplementary services HOLD (Call Hold; refer 3GPP TS 22.083 [5] clause 2), MPTY (MultiParty; refer 3GPP TS 22.084 [22]) and ECT (Explicit Call Transfer; refer 3GPP TS 22.091 [29]). The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+NOTE:	Call Hold, MultiParty and Explicit Call Transfer are only applicable to teleservice 11.
+It is recommended (although optional) that test command returns a list of operations which are supported. The call number required by some operations shall be denoted by 'x' (e.g. +CHLD: (0,1,1x,2,2x,3)).
+Defined values
+[n]: integer type; equals to numbers entered before SEND button in 3GPP TS 22.030 [19] subclause 6.5.5.1
+NOTE:	The 'directory number' case shall be handled with dial command D, and the END case with hangup command H (or +CHUP). The 4*'directory number' case is handled with +CTFR command.
+</description>
+</spec>
+<spec>
+    <command>AT+CTFR=</command>
+    <profile>Call deflection (Assign)</profile>
+    <description>This refers to a service that causes an incoming alerting call to be forwarded to a specified number. Action command does this. Refer subclause 9.2 for possible [err] values.
+This is based on the GSM/UMTS supplementary service CD (Call Deflection; refer 3GPP TS 22.072 [30]). The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+NOTE:	Call Deflection is only applicable to teleservice 11.
+Defined values
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8); default 128
+</description>
+</spec>
+<spec>
+    <command>AT+CTFR=?</command>
+    <profile>Call deflection (Query all)</profile>
+    <description>This refers to a service that causes an incoming alerting call to be forwarded to a specified number. Action command does this. Refer subclause 9.2 for possible [err] values.
+This is based on the GSM/UMTS supplementary service CD (Call Deflection; refer 3GPP TS 22.072 [30]). The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+NOTE:	Call Deflection is only applicable to teleservice 11.
+Defined values
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8); default 128
+</description>
+</spec>
+<spec>
+    <command>AT+CUSD=</command>
+    <profile>Unstructured supplementary service data (Assign)</profile>
+    <description>This command allows control of the Unstuctured Supplementary Service Data (USSD) according to 3GPP TS 22.090 [23]. Both network and mobile initiated operations are supported. Parameter [n] is used to disable/enable the presentation of an unsolicited result code (USSD response from the network, or network initiated operation) +CUSD: [m][,[str],[dcs]] to the TE. In addition, value [n]=2 is used to cancel an ongoing USSD session.
+When [str] is given, a mobile initiated USSD‑string or a response USSD‑string to a network initiated operation is sent to the network. The response USSD‑string from the network is returned in a subsequent unsolicited +CUSD result code.
+NOTE:	In case of successful mobile initiated operation, TA implemented according to a version prior to 6 of this standard, waits the USSD response from the network and sends it to the TE before the final result code. This will block the AT command interface for the period of the operation. Such TA does not support [n] value 2.
+The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+Test command returns values supported as a compound value.
+Defined values
+[n]:
+0	disable the result code presentation to the TE
+1	enable the result code presentation to the TE
+2	cancel session (not applicable to read command response)
+[str]: string type USSD‑string (when [str] parameter is not given, network is not interrogated):
+‑	if [dcs] indicates that 3GPP TS 23.038 [25] 7 bit default alphabet is used:
+‑	if TE character set other than 'HEX' (refer command Select TE Character Set +CSCS): MT/TA converts GSM alphabet into current TE character set according to rules of 3GPP TS 27.005 [24] Annex A
+‑	if TE character set is 'HEX': MT/TA converts each 7‑bit character of GSM alphabet into two IRA character long hexadecimal number (e.g. character  (GSM 23) is presented as 17 (IRA 49 and 55))
+‑	if [dcs] indicates that 8‑bit data coding scheme is used: MT/TA converts each 8‑bit octet into two IRA character long hexadecimal number (e.g. octet with integer value 42 is presented to TE as two characters 2A (IRA 50 and 65))
+[dcs]: 3GPP TS 23.038 [25] Cell Broadcast Data Coding Scheme in integer format (default 0)
+[m]:
+0	no further user action required (network initiated USSD‑Notify, or no further information needed after mobile initiated operation)
+1	further user action required (network initiated USSD‑Request, or further information needed after mobile initiated operation)
+2	USSD terminated by network
+3	other local client has responded
+4	operation not supported
+5	network time out
+</description>
+</spec>
+<spec>
+    <command>AT+CUSD?</command>
+    <profile>Unstructured supplementary service data (Query)</profile>
+    <description>This command allows control of the Unstuctured Supplementary Service Data (USSD) according to 3GPP TS 22.090 [23]. Both network and mobile initiated operations are supported. Parameter [n] is used to disable/enable the presentation of an unsolicited result code (USSD response from the network, or network initiated operation) +CUSD: [m][,[str],[dcs]] to the TE. In addition, value [n]=2 is used to cancel an ongoing USSD session.
+When [str] is given, a mobile initiated USSD‑string or a response USSD‑string to a network initiated operation is sent to the network. The response USSD‑string from the network is returned in a subsequent unsolicited +CUSD result code.
+NOTE:	In case of successful mobile initiated operation, TA implemented according to a version prior to 6 of this standard, waits the USSD response from the network and sends it to the TE before the final result code. This will block the AT command interface for the period of the operation. Such TA does not support [n] value 2.
+The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+Test command returns values supported as a compound value.
+Defined values
+[n]:
+0	disable the result code presentation to the TE
+1	enable the result code presentation to the TE
+2	cancel session (not applicable to read command response)
+[str]: string type USSD‑string (when [str] parameter is not given, network is not interrogated):
+‑	if [dcs] indicates that 3GPP TS 23.038 [25] 7 bit default alphabet is used:
+‑	if TE character set other than 'HEX' (refer command Select TE Character Set +CSCS): MT/TA converts GSM alphabet into current TE character set according to rules of 3GPP TS 27.005 [24] Annex A
+‑	if TE character set is 'HEX': MT/TA converts each 7‑bit character of GSM alphabet into two IRA character long hexadecimal number (e.g. character  (GSM 23) is presented as 17 (IRA 49 and 55))
+‑	if [dcs] indicates that 8‑bit data coding scheme is used: MT/TA converts each 8‑bit octet into two IRA character long hexadecimal number (e.g. octet with integer value 42 is presented to TE as two characters 2A (IRA 50 and 65))
+[dcs]: 3GPP TS 23.038 [25] Cell Broadcast Data Coding Scheme in integer format (default 0)
+[m]:
+0	no further user action required (network initiated USSD‑Notify, or no further information needed after mobile initiated operation)
+1	further user action required (network initiated USSD‑Request, or further information needed after mobile initiated operation)
+2	USSD terminated by network
+3	other local client has responded
+4	operation not supported
+5	network time out
+</description>
+</spec>
+<spec>
+    <command>AT+CUSD=?</command>
+    <profile>Unstructured supplementary service data (Query all)</profile>
+    <description>This command allows control of the Unstuctured Supplementary Service Data (USSD) according to 3GPP TS 22.090 [23]. Both network and mobile initiated operations are supported. Parameter [n] is used to disable/enable the presentation of an unsolicited result code (USSD response from the network, or network initiated operation) +CUSD: [m][,[str],[dcs]] to the TE. In addition, value [n]=2 is used to cancel an ongoing USSD session.
+When [str] is given, a mobile initiated USSD‑string or a response USSD‑string to a network initiated operation is sent to the network. The response USSD‑string from the network is returned in a subsequent unsolicited +CUSD result code.
+NOTE:	In case of successful mobile initiated operation, TA implemented according to a version prior to 6 of this standard, waits the USSD response from the network and sends it to the TE before the final result code. This will block the AT command interface for the period of the operation. Such TA does not support [n] value 2.
+The interaction of this command with other commands based on other GSM/UMTS supplementary services is described in the GSM/UMTS standards.
+Test command returns values supported as a compound value.
+Defined values
+[n]:
+0	disable the result code presentation to the TE
+1	enable the result code presentation to the TE
+2	cancel session (not applicable to read command response)
+[str]: string type USSD‑string (when [str] parameter is not given, network is not interrogated):
+‑	if [dcs] indicates that 3GPP TS 23.038 [25] 7 bit default alphabet is used:
+‑	if TE character set other than 'HEX' (refer command Select TE Character Set +CSCS): MT/TA converts GSM alphabet into current TE character set according to rules of 3GPP TS 27.005 [24] Annex A
+‑	if TE character set is 'HEX': MT/TA converts each 7‑bit character of GSM alphabet into two IRA character long hexadecimal number (e.g. character  (GSM 23) is presented as 17 (IRA 49 and 55))
+‑	if [dcs] indicates that 8‑bit data coding scheme is used: MT/TA converts each 8‑bit octet into two IRA character long hexadecimal number (e.g. octet with integer value 42 is presented to TE as two characters 2A (IRA 50 and 65))
+[dcs]: 3GPP TS 23.038 [25] Cell Broadcast Data Coding Scheme in integer format (default 0)
+[m]:
+0	no further user action required (network initiated USSD‑Notify, or no further information needed after mobile initiated operation)
+1	further user action required (network initiated USSD‑Request, or further information needed after mobile initiated operation)
+2	USSD terminated by network
+3	other local client has responded
+4	operation not supported
+5	network time out
+</description>
+</spec>
+<spec>
+    <command>AT+CAOC[=</command>
+    <profile>Advice of Charge (Assign)</profile>
+    <description>This refers to Advice of Charge supplementary service (3GPP TS 22.024 [26] and 3GPP TS 22.086 [27]) that enables subscriber to get information about the cost of calls. With [mode]=0, the execute command returns the current call meter value from the MT.
+The command also includes the possibility to enable an unsolicited event reporting of the CCM information. The unsolicited result code +CCCM: [ccm] is sent when the CCM value changes, but not more that every 10 seconds. Deactivation of the unsolicited event reporting is made with the same command. 
+Refer subclause 9.2 for possible [err] values.
+NOTE:	Advice of Charge values stored in the SIM card or in the active application in the UICC (GSM or USIM) (ACM, ACMmax, PUCT) can be accessed with generic or restricted SIM access command (+CSIM or +CRSM)).Those values can be more readily accessed with commands +CACM, +CAMM and +CPUC.
+The Read command indicates whether the unsolicited reporting is activated or not. Read command is available when the unsolicited result code is supported. 
+It is recommended (although optional) that the test command returns the supported mode values.
+Defined values
+[mode]: 
+0	query CCM value
+1	deactivate the unsolicited reporting of CCM value
+2	activate the unsolicited reporting of CCM value
+[ccm]: string type; three bytes of the current call meter value in hexadecimal format (e.g. '00001E' indicates decimal value 30); value is in home units and bytes are similarly coded as ACMmax value in the SIM card or in the active application in the UICC (GSM or USIM)
+</description>
+</spec>
+<spec>
+    <command>AT+CAOC?</command>
+    <profile>Advice of Charge (Query)</profile>
+    <description>This refers to Advice of Charge supplementary service (3GPP TS 22.024 [26] and 3GPP TS 22.086 [27]) that enables subscriber to get information about the cost of calls. With [mode]=0, the execute command returns the current call meter value from the MT.
+The command also includes the possibility to enable an unsolicited event reporting of the CCM information. The unsolicited result code +CCCM: [ccm] is sent when the CCM value changes, but not more that every 10 seconds. Deactivation of the unsolicited event reporting is made with the same command. 
+Refer subclause 9.2 for possible [err] values.
+NOTE:	Advice of Charge values stored in the SIM card or in the active application in the UICC (GSM or USIM) (ACM, ACMmax, PUCT) can be accessed with generic or restricted SIM access command (+CSIM or +CRSM)).Those values can be more readily accessed with commands +CACM, +CAMM and +CPUC.
+The Read command indicates whether the unsolicited reporting is activated or not. Read command is available when the unsolicited result code is supported. 
+It is recommended (although optional) that the test command returns the supported mode values.
+Defined values
+[mode]: 
+0	query CCM value
+1	deactivate the unsolicited reporting of CCM value
+2	activate the unsolicited reporting of CCM value
+[ccm]: string type; three bytes of the current call meter value in hexadecimal format (e.g. '00001E' indicates decimal value 30); value is in home units and bytes are similarly coded as ACMmax value in the SIM card or in the active application in the UICC (GSM or USIM)
+</description>
+</spec>
+<spec>
+    <command>AT+CAOC=?</command>
+    <profile>Advice of Charge (Query all)</profile>
+    <description>This refers to Advice of Charge supplementary service (3GPP TS 22.024 [26] and 3GPP TS 22.086 [27]) that enables subscriber to get information about the cost of calls. With [mode]=0, the execute command returns the current call meter value from the MT.
+The command also includes the possibility to enable an unsolicited event reporting of the CCM information. The unsolicited result code +CCCM: [ccm] is sent when the CCM value changes, but not more that every 10 seconds. Deactivation of the unsolicited event reporting is made with the same command. 
+Refer subclause 9.2 for possible [err] values.
+NOTE:	Advice of Charge values stored in the SIM card or in the active application in the UICC (GSM or USIM) (ACM, ACMmax, PUCT) can be accessed with generic or restricted SIM access command (+CSIM or +CRSM)).Those values can be more readily accessed with commands +CACM, +CAMM and +CPUC.
+The Read command indicates whether the unsolicited reporting is activated or not. Read command is available when the unsolicited result code is supported. 
+It is recommended (although optional) that the test command returns the supported mode values.
+Defined values
+[mode]: 
+0	query CCM value
+1	deactivate the unsolicited reporting of CCM value
+2	activate the unsolicited reporting of CCM value
+[ccm]: string type; three bytes of the current call meter value in hexadecimal format (e.g. '00001E' indicates decimal value 30); value is in home units and bytes are similarly coded as ACMmax value in the SIM card or in the active application in the UICC (GSM or USIM)
+</description>
+</spec>
+<spec>
+    <command>AT+CSSN=</command>
+    <profile>Supplementary service notifications (Assign)</profile>
+    <description>This command refers to supplementary service related network initiated notifications. The set command enables/disables the presentation of notification result codes from TA to TE.
+When [n]=1 and a supplementary service notification is received after a mobile originated call setup, intermediate result code +CSSI: [code1][,[index]] is sent to TE before any other MO call setup result codes presented in the present document or in V.250 [14]. When several different [code1]s are received from the network, each of them shall have its own +CSSI result code.
+When [m]=1 and a supplementary service notification is received during a mobile terminated call setup or during a call, or when a forward check supplementary service notification is received, unsolicited result code +CSSU: [code2][,[index][,[number],[type][,[subaddr],[satype]]]] is sent to TE. In case of MT call setup, result code is sent after every +CLIP result code (refer command 'Calling line identification presentation +CLIP') and when several different [code2]s are received from the network, each of them shall have its own +CSSU result code.
+Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the +CSSI result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter sets/shows the +CSSU result code presentation status to the TE):
+0	disable
+1	enable
+[code1] (it is manufacturer specific, which of these codes are supported):
+0	unconditional call forwarding is active
+1	some of the conditional call forwardings are active
+2	call has been forwarded
+3	call is waiting
+4	this is a CUG call (also [index] present)
+5	outgoing calls are barred
+6	incoming calls are barred
+7	CLIR suppression rejected
+8	call has been deflected
+[index]: refer 'Closed user group +CCUG'
+[code2] (it is manufacturer specific, which of these codes are supported):
+0	this is a forwarded call (MT call setup)
+1	this is a CUG call (also [index] present) (MT call setup)
+2	call has been put on hold (during a voice call)
+3	call has been retrieved (during a voice call)
+4	multiparty call entered (during a voice call)
+5	call on hold has been released (this is not a SS notification) (during a voice call)
+6	forward check SS message received (can be received whenever)
+7	call is being connected (alerting) with the remote party in alerting state in explicit call transfer operation (during a voice call)
+8	call has been connected with the other remote party in explicit call transfer operation (also number and subaddress parameters may be present) (during a voice call or MT call setup)
+9	this is a deflected call (MT call setup)
+10	sdditional incoming call forwarded
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+</description>
+</spec>
+<spec>
+    <command>AT+CSSN?</command>
+    <profile>Supplementary service notifications (Query)</profile>
+    <description>This command refers to supplementary service related network initiated notifications. The set command enables/disables the presentation of notification result codes from TA to TE.
+When [n]=1 and a supplementary service notification is received after a mobile originated call setup, intermediate result code +CSSI: [code1][,[index]] is sent to TE before any other MO call setup result codes presented in the present document or in V.250 [14]. When several different [code1]s are received from the network, each of them shall have its own +CSSI result code.
+When [m]=1 and a supplementary service notification is received during a mobile terminated call setup or during a call, or when a forward check supplementary service notification is received, unsolicited result code +CSSU: [code2][,[index][,[number],[type][,[subaddr],[satype]]]] is sent to TE. In case of MT call setup, result code is sent after every +CLIP result code (refer command 'Calling line identification presentation +CLIP') and when several different [code2]s are received from the network, each of them shall have its own +CSSU result code.
+Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the +CSSI result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter sets/shows the +CSSU result code presentation status to the TE):
+0	disable
+1	enable
+[code1] (it is manufacturer specific, which of these codes are supported):
+0	unconditional call forwarding is active
+1	some of the conditional call forwardings are active
+2	call has been forwarded
+3	call is waiting
+4	this is a CUG call (also [index] present)
+5	outgoing calls are barred
+6	incoming calls are barred
+7	CLIR suppression rejected
+8	call has been deflected
+[index]: refer 'Closed user group +CCUG'
+[code2] (it is manufacturer specific, which of these codes are supported):
+0	this is a forwarded call (MT call setup)
+1	this is a CUG call (also [index] present) (MT call setup)
+2	call has been put on hold (during a voice call)
+3	call has been retrieved (during a voice call)
+4	multiparty call entered (during a voice call)
+5	call on hold has been released (this is not a SS notification) (during a voice call)
+6	forward check SS message received (can be received whenever)
+7	call is being connected (alerting) with the remote party in alerting state in explicit call transfer operation (during a voice call)
+8	call has been connected with the other remote party in explicit call transfer operation (also number and subaddress parameters may be present) (during a voice call or MT call setup)
+9	this is a deflected call (MT call setup)
+10	sdditional incoming call forwarded
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+</description>
+</spec>
+<spec>
+    <command>AT+CSSN=?</command>
+    <profile>Supplementary service notifications (Query all)</profile>
+    <description>This command refers to supplementary service related network initiated notifications. The set command enables/disables the presentation of notification result codes from TA to TE.
+When [n]=1 and a supplementary service notification is received after a mobile originated call setup, intermediate result code +CSSI: [code1][,[index]] is sent to TE before any other MO call setup result codes presented in the present document or in V.250 [14]. When several different [code1]s are received from the network, each of them shall have its own +CSSI result code.
+When [m]=1 and a supplementary service notification is received during a mobile terminated call setup or during a call, or when a forward check supplementary service notification is received, unsolicited result code +CSSU: [code2][,[index][,[number],[type][,[subaddr],[satype]]]] is sent to TE. In case of MT call setup, result code is sent after every +CLIP result code (refer command 'Calling line identification presentation +CLIP') and when several different [code2]s are received from the network, each of them shall have its own +CSSU result code.
+Test command returns values supported as a compound value.
+Defined values
+[n] (parameter sets/shows the +CSSI result code presentation status to the TE):
+0	disable
+1	enable
+[m] (parameter sets/shows the +CSSU result code presentation status to the TE):
+0	disable
+1	enable
+[code1] (it is manufacturer specific, which of these codes are supported):
+0	unconditional call forwarding is active
+1	some of the conditional call forwardings are active
+2	call has been forwarded
+3	call is waiting
+4	this is a CUG call (also [index] present)
+5	outgoing calls are barred
+6	incoming calls are barred
+7	CLIR suppression rejected
+8	call has been deflected
+[index]: refer 'Closed user group +CCUG'
+[code2] (it is manufacturer specific, which of these codes are supported):
+0	this is a forwarded call (MT call setup)
+1	this is a CUG call (also [index] present) (MT call setup)
+2	call has been put on hold (during a voice call)
+3	call has been retrieved (during a voice call)
+4	multiparty call entered (during a voice call)
+5	call on hold has been released (this is not a SS notification) (during a voice call)
+6	forward check SS message received (can be received whenever)
+7	call is being connected (alerting) with the remote party in alerting state in explicit call transfer operation (during a voice call)
+8	call has been connected with the other remote party in explicit call transfer operation (also number and subaddress parameters may be present) (during a voice call or MT call setup)
+9	this is a deflected call (MT call setup)
+10	sdditional incoming call forwarded
+[number]: string type phone number of format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[subaddr]: string type subaddress of format specified by [satype]
+[satype]: type of subaddress octet in integer format (refer TS 24.008 [8] subclause 10.5.4.8)
+</description>
+</spec>
+<spec>
+    <command>AT+CLCC</command>
+    <profile>List current calls </profile>
+    <description>Returns list of current calls of MT. If command succeeds but no calls are available, no information response is sent to TE. Refer subclause 9.2 for possible [err] values.
+Defined values
+[idx]: integer type; call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1; this number can be used in +CHLD command operations
+[dir]:
+0	mobile originated (MO) call
+1	mobile terminated (MT) call
+[stat] (state of the call):
+0	active
+1	held
+2	dialing (MO call)
+3	alerting (MO call)
+4	incoming (MT call)
+5	waiting (MT call)
+[mode] (bearer/teleservice):
+0	voice
+1	data
+2	fax
+3	voice followed by data, voice mode
+4	alternating voice/data, voice mode
+5	alternating voice/fax, voice mode
+6	voice followed by data, data mode
+7	alternating voice/data, data mode
+8	alternating voice/fax, fax mode
+9	unknown
+[mpty]:
+0	call is not one of multiparty (conference) call parties
+1	call is one of multiparty (conference) call parties
+[number]: string type phone number in format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[alpha]: string type alphanumeric representation of [number] corresponding to the entry found in phonebook; used character set should be the one selected with command Select TE Character Set +CSCS
+[priority]: optional digit type parameter indicating the eMLPP priority level of the call, values specified in 3GPP TS 22.067 [54]
+</description>
+</spec>
+<spec>
+    <command>AT+CLCC=?</command>
+    <profile>List current calls (Query all)</profile>
+    <description>Returns list of current calls of MT. If command succeeds but no calls are available, no information response is sent to TE. Refer subclause 9.2 for possible [err] values.
+Defined values
+[idx]: integer type; call identification number as described in 3GPP TS 22.030 [19] subclause 4.5.5.1; this number can be used in +CHLD command operations
+[dir]:
+0	mobile originated (MO) call
+1	mobile terminated (MT) call
+[stat] (state of the call):
+0	active
+1	held
+2	dialing (MO call)
+3	alerting (MO call)
+4	incoming (MT call)
+5	waiting (MT call)
+[mode] (bearer/teleservice):
+0	voice
+1	data
+2	fax
+3	voice followed by data, voice mode
+4	alternating voice/data, voice mode
+5	alternating voice/fax, voice mode
+6	voice followed by data, data mode
+7	alternating voice/data, data mode
+8	alternating voice/fax, fax mode
+9	unknown
+[mpty]:
+0	call is not one of multiparty (conference) call parties
+1	call is one of multiparty (conference) call parties
+[number]: string type phone number in format specified by [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[alpha]: string type alphanumeric representation of [number] corresponding to the entry found in phonebook; used character set should be the one selected with command Select TE Character Set +CSCS
+[priority]: optional digit type parameter indicating the eMLPP priority level of the call, values specified in 3GPP TS 22.067 [54]
+</description>
+</spec>
+<spec>
+    <command>AT+CPOL=</command>
+    <profile>Preferred PLMN list (Assign)</profile>
+    <description>This command is used to edit the PLMN selector with Access Technology lists in the SIM card  or active application in the UICC(GSM or USIM). 
+Execute command writes an entry in the SIM/USIM list of preferred PLMNs, previously selected by the command +CPLS. If no list has been previously selected, the User controlled PLMN selector with Access Technology, EFPLMNwAcT, is the one accessed by default. If [index] is given but [oper] is left out, entry is deleted. If [oper] is given but [index] is left out, [oper] is put in the next free location. If only [format] is given, the format of the [oper] in the read command is changed. The Access Technology selection parameters, [GSM_AcT], [GSM_Compact_AcT] and [UTRAN_AcT], are required when writing User controlled PLMN selector with Access Technology, EF EFPLMNwAcT, Operator controlled PLMN selector with Access Technology EFOPLMNwAcT and HPLMN selector with Access Technology EFHPLMNwAcT, see TS 31.102. Refer subclause 9.2 for possible [err] values.
+NOTE1:	MT may also update the User controlled PLMN selector with Access Technology, EFPLMNwAcT, automatically when new networks are selected.
+NOTE2:	The Operator controlled PLMN selector with Access Technology EFOPLMNwAcT, can only be written if the write access condition in the SIM/USIM has been previously verified.
+Read command returns all used entries from the SIM/USIM list of preferred PLMNs, previously selected by the command +CPLS, with the Access Technologies for each PLMN in the list.
+Test command returns the whole index range supported by the SIM.
+Defined values
+[indexn]: integer type; the order number of operator in the SIM/USIM preferred operator list
+[format]:
+0	long format alphanumeric [oper]
+1	short format alphanumeric [oper]
+2	numeric [oper]
+[opern]: string type; [format] indicates if the format is alphanumeric or numeric (see +COPS) 
+[GSM_AcTn]: GSM access technology:
+0	access technology not selected
+1access technology selected
+[GSM_Compact_AcTn]: GSM compact access technology:
+0	access technology not selected
+1access technology selected
+[UTRA_AcTn]: UTRA access technology:
+0	access technology not selected
+1	access technology selected
+</description>
+</spec>
+<spec>
+    <command>AT+CPOL?</command>
+    <profile>Preferred PLMN list (Query)</profile>
+    <description>This command is used to edit the PLMN selector with Access Technology lists in the SIM card  or active application in the UICC(GSM or USIM). 
+Execute command writes an entry in the SIM/USIM list of preferred PLMNs, previously selected by the command +CPLS. If no list has been previously selected, the User controlled PLMN selector with Access Technology, EFPLMNwAcT, is the one accessed by default. If [index] is given but [oper] is left out, entry is deleted. If [oper] is given but [index] is left out, [oper] is put in the next free location. If only [format] is given, the format of the [oper] in the read command is changed. The Access Technology selection parameters, [GSM_AcT], [GSM_Compact_AcT] and [UTRAN_AcT], are required when writing User controlled PLMN selector with Access Technology, EF EFPLMNwAcT, Operator controlled PLMN selector with Access Technology EFOPLMNwAcT and HPLMN selector with Access Technology EFHPLMNwAcT, see TS 31.102. Refer subclause 9.2 for possible [err] values.
+NOTE1:	MT may also update the User controlled PLMN selector with Access Technology, EFPLMNwAcT, automatically when new networks are selected.
+NOTE2:	The Operator controlled PLMN selector with Access Technology EFOPLMNwAcT, can only be written if the write access condition in the SIM/USIM has been previously verified.
+Read command returns all used entries from the SIM/USIM list of preferred PLMNs, previously selected by the command +CPLS, with the Access Technologies for each PLMN in the list.
+Test command returns the whole index range supported by the SIM.
+Defined values
+[indexn]: integer type; the order number of operator in the SIM/USIM preferred operator list
+[format]:
+0	long format alphanumeric [oper]
+1	short format alphanumeric [oper]
+2	numeric [oper]
+[opern]: string type; [format] indicates if the format is alphanumeric or numeric (see +COPS) 
+[GSM_AcTn]: GSM access technology:
+0	access technology not selected
+1access technology selected
+[GSM_Compact_AcTn]: GSM compact access technology:
+0	access technology not selected
+1access technology selected
+[UTRA_AcTn]: UTRA access technology:
+0	access technology not selected
+1	access technology selected
+</description>
+</spec>
+<spec>
+    <command>AT+CPOL=?</command>
+    <profile>Preferred PLMN list (Query all)</profile>
+    <description>This command is used to edit the PLMN selector with Access Technology lists in the SIM card  or active application in the UICC(GSM or USIM). 
+Execute command writes an entry in the SIM/USIM list of preferred PLMNs, previously selected by the command +CPLS. If no list has been previously selected, the User controlled PLMN selector with Access Technology, EFPLMNwAcT, is the one accessed by default. If [index] is given but [oper] is left out, entry is deleted. If [oper] is given but [index] is left out, [oper] is put in the next free location. If only [format] is given, the format of the [oper] in the read command is changed. The Access Technology selection parameters, [GSM_AcT], [GSM_Compact_AcT] and [UTRAN_AcT], are required when writing User controlled PLMN selector with Access Technology, EF EFPLMNwAcT, Operator controlled PLMN selector with Access Technology EFOPLMNwAcT and HPLMN selector with Access Technology EFHPLMNwAcT, see TS 31.102. Refer subclause 9.2 for possible [err] values.
+NOTE1:	MT may also update the User controlled PLMN selector with Access Technology, EFPLMNwAcT, automatically when new networks are selected.
+NOTE2:	The Operator controlled PLMN selector with Access Technology EFOPLMNwAcT, can only be written if the write access condition in the SIM/USIM has been previously verified.
+Read command returns all used entries from the SIM/USIM list of preferred PLMNs, previously selected by the command +CPLS, with the Access Technologies for each PLMN in the list.
+Test command returns the whole index range supported by the SIM.
+Defined values
+[indexn]: integer type; the order number of operator in the SIM/USIM preferred operator list
+[format]:
+0	long format alphanumeric [oper]
+1	short format alphanumeric [oper]
+2	numeric [oper]
+[opern]: string type; [format] indicates if the format is alphanumeric or numeric (see +COPS) 
+[GSM_AcTn]: GSM access technology:
+0	access technology not selected
+1access technology selected
+[GSM_Compact_AcTn]: GSM compact access technology:
+0	access technology not selected
+1access technology selected
+[UTRA_AcTn]: UTRA access technology:
+0	access technology not selected
+1	access technology selected
+</description>
+</spec>
+<spec>
+    <command>AT+CPLS=</command>
+    <profile>Selection of preferred PLMN list (Assign)</profile>
+    <description>This command is used to select one PLMN selector with Access Technology list in the SIM card  or active application in the UICC(GSM or USIM), that is used by +CPOL command.
+Execute command selects a list in the SIM/USIM. Refer subclause 9.2 for possible [err] values.
+Read command returns the selected PLMN selector list from the SIM/USIM
+Test command returns the whole index range supported lists by the SIM./USIM
+Defined values
+[list]:
+0	User controlled PLMN selector with Access Technology EFPLMNwAcT, if not found in the SIM/UICC then PLMN preferred list EFPLMNsel  (this file is only available in SIM card or GSM application selected in UICC)
+1	Operator controlled PLMN selector with Access Technology EFOPLMNwAcT
+2HPLMN selector with Access Technology EFHPLMNwAcT
+</description>
+</spec>
+<spec>
+    <command>AT+CPLS?</command>
+    <profile>Selection of preferred PLMN list (Query)</profile>
+    <description>This command is used to select one PLMN selector with Access Technology list in the SIM card  or active application in the UICC(GSM or USIM), that is used by +CPOL command.
+Execute command selects a list in the SIM/USIM. Refer subclause 9.2 for possible [err] values.
+Read command returns the selected PLMN selector list from the SIM/USIM
+Test command returns the whole index range supported lists by the SIM./USIM
+Defined values
+[list]:
+0	User controlled PLMN selector with Access Technology EFPLMNwAcT, if not found in the SIM/UICC then PLMN preferred list EFPLMNsel  (this file is only available in SIM card or GSM application selected in UICC)
+1	Operator controlled PLMN selector with Access Technology EFOPLMNwAcT
+2HPLMN selector with Access Technology EFHPLMNwAcT
+</description>
+</spec>
+<spec>
+    <command>AT+CPLS=?</command>
+    <profile>Selection of preferred PLMN list (Query all)</profile>
+    <description>This command is used to select one PLMN selector with Access Technology list in the SIM card  or active application in the UICC(GSM or USIM), that is used by +CPOL command.
+Execute command selects a list in the SIM/USIM. Refer subclause 9.2 for possible [err] values.
+Read command returns the selected PLMN selector list from the SIM/USIM
+Test command returns the whole index range supported lists by the SIM./USIM
+Defined values
+[list]:
+0	User controlled PLMN selector with Access Technology EFPLMNwAcT, if not found in the SIM/UICC then PLMN preferred list EFPLMNsel  (this file is only available in SIM card or GSM application selected in UICC)
+1	Operator controlled PLMN selector with Access Technology EFOPLMNwAcT
+2HPLMN selector with Access Technology EFHPLMNwAcT
+</description>
+</spec>
+<spec>
+    <command>AT+COPN</command>
+    <profile>Read operator names </profile>
+    <description>Execute command returns the list of operator names from the MT. Each operator code [numericn] that has an alphanumeric equivalent [alphan] in the MT memory shall be returned. Refer subclause 9.2 for possible [err] values.
+Defined values
+[numericn]: string type; operator in numeric format (see +COPS)
+[alphan]: string type; operator in long alphanumeric format (see +COPS)
+</description>
+</spec>
+<spec>
+    <command>AT+COPN=?</command>
+    <profile>Read operator names (Query all)</profile>
+    <description>Execute command returns the list of operator names from the MT. Each operator code [numericn] that has an alphanumeric equivalent [alphan] in the MT memory shall be returned. Refer subclause 9.2 for possible [err] values.
+Defined values
+[numericn]: string type; operator in numeric format (see +COPS)
+[alphan]: string type; operator in long alphanumeric format (see +COPS)
+</description>
+</spec>
+<spec>
+    <command>AT+CFCS=</command>
+    <profile>Fast call setup conditions (Assign)</profile>
+    <description>The set command is used to edit the status of the priority level for fast call set-up stored on the SIM card or in the active application in the UICC (GSM or USIM) EFeMLPP. If the user has no subscription to the priority level status he wants to edit, an ERROR or +CME ERROR result code is returned.
+The read command returns all enabled priority levels for fast call set-up stored on the SIM card or in the active application in the UICC (GSM or USIM) EFeMLPP.  If  no priority level is enabled for fast call set-up, the result code OK is returned.
+
+Defined values
+[priority]: integer type, eMLPP fast call set-up priority level {0,1,..,4} as defined in 3GPP TS 22.067 [45]
+[status]: integer type
+0		disable [priority] for fast call set-up
+1		enable [priority] for fast call set-up
+</description>
+</spec>
+<spec>
+    <command>AT+CFCS?</command>
+    <profile>Fast call setup conditions (Query)</profile>
+    <description>The set command is used to edit the status of the priority level for fast call set-up stored on the SIM card or in the active application in the UICC (GSM or USIM) EFeMLPP. If the user has no subscription to the priority level status he wants to edit, an ERROR or +CME ERROR result code is returned.
+The read command returns all enabled priority levels for fast call set-up stored on the SIM card or in the active application in the UICC (GSM or USIM) EFeMLPP.  If  no priority level is enabled for fast call set-up, the result code OK is returned.
+
+Defined values
+[priority]: integer type, eMLPP fast call set-up priority level {0,1,..,4} as defined in 3GPP TS 22.067 [45]
+[status]: integer type
+0		disable [priority] for fast call set-up
+1		enable [priority] for fast call set-up
+</description>
+</spec>
+<spec>
+    <command>AT+CFCS=?</command>
+    <profile>Fast call setup conditions (Query all)</profile>
+    <description>The set command is used to edit the status of the priority level for fast call set-up stored on the SIM card or in the active application in the UICC (GSM or USIM) EFeMLPP. If the user has no subscription to the priority level status he wants to edit, an ERROR or +CME ERROR result code is returned.
+The read command returns all enabled priority levels for fast call set-up stored on the SIM card or in the active application in the UICC (GSM or USIM) EFeMLPP.  If  no priority level is enabled for fast call set-up, the result code OK is returned.
+
+Defined values
+[priority]: integer type, eMLPP fast call set-up priority level {0,1,..,4} as defined in 3GPP TS 22.067 [45]
+[status]: integer type
+0		disable [priority] for fast call set-up
+1		enable [priority] for fast call set-up
+</description>
+</spec>
+<spec>
+    <command>AT+CAAP=</command>
+    <profile>Automatic answer for eMLPP Service (Assign)</profile>
+    <description>The set command is used to edit the status of the priority level for automatic answering for eMLPP stored on the SIM card or in the active application in the UICC (GSM or USIM) EFAAeM. If the user has no subscription to the priority level status he wants to edit, an ERROR or +CME ERROR result code is returned.
+The read command returns all enabled priority levels for automatic answering for eMLPP stored on the SIM card or in the active application in the UICC (GSM or USIM) EFAAeM.  If  no priority level is enabled for automatic answering for eMLPP, the result code OK is returned.
+Defined values
+[priority]: eMLPP automatic answer priority level value {A,B,0,1,..,4} as defined in 3GPP TS 22.067 [45]
+[status]: integer type
+0		disable eMLPP [priority] for automatic answering
+1		enable eMLPP [priority] for automatic answering
+</description>
+</spec>
+<spec>
+    <command>AT+CAAP?</command>
+    <profile>Automatic answer for eMLPP Service (Query)</profile>
+    <description>The set command is used to edit the status of the priority level for automatic answering for eMLPP stored on the SIM card or in the active application in the UICC (GSM or USIM) EFAAeM. If the user has no subscription to the priority level status he wants to edit, an ERROR or +CME ERROR result code is returned.
+The read command returns all enabled priority levels for automatic answering for eMLPP stored on the SIM card or in the active application in the UICC (GSM or USIM) EFAAeM.  If  no priority level is enabled for automatic answering for eMLPP, the result code OK is returned.
+Defined values
+[priority]: eMLPP automatic answer priority level value {A,B,0,1,..,4} as defined in 3GPP TS 22.067 [45]
+[status]: integer type
+0		disable eMLPP [priority] for automatic answering
+1		enable eMLPP [priority] for automatic answering
+</description>
+</spec>
+<spec>
+    <command>AT+CAAP=?</command>
+    <profile>Automatic answer for eMLPP Service (Query all)</profile>
+    <description>The set command is used to edit the status of the priority level for automatic answering for eMLPP stored on the SIM card or in the active application in the UICC (GSM or USIM) EFAAeM. If the user has no subscription to the priority level status he wants to edit, an ERROR or +CME ERROR result code is returned.
+The read command returns all enabled priority levels for automatic answering for eMLPP stored on the SIM card or in the active application in the UICC (GSM or USIM) EFAAeM.  If  no priority level is enabled for automatic answering for eMLPP, the result code OK is returned.
+Defined values
+[priority]: eMLPP automatic answer priority level value {A,B,0,1,..,4} as defined in 3GPP TS 22.067 [45]
+[status]: integer type
+0		disable eMLPP [priority] for automatic answering
+1		enable eMLPP [priority] for automatic answering
+</description>
+</spec>
+<spec>
+    <command>AT+CPAS</command>
+    <profile>Phone activity status </profile>
+    <description>Execution command returns the activity status [pas] of the MT. It can be used to interrogate the MT before requesting action from the phone. Refer subclause 9.2 for possible [err] values.
+Test command returns values supported by the MT as a compound value.
+Defined values
+[pas]:
+0	ready (MT allows commands from TA/TE)
+1	unavailable (MT does not allow commands from TA/TE)
+2	unknown (MT is not guaranteed to respond to instructions)
+3	ringing (MT is ready for commands from TA/TE, but the ringer is active)
+4	call in progress (MT is ready for commands from TA/TE, but a call is in progress)
+5	asleep (MT is unable to process commands from TA/TE because it is in a low functionality state)
+also all other values below 128 are reserved by the present document.
+</description>
+</spec>
+<spec>
+    <command>AT+CPAS=?</command>
+    <profile>Phone activity status (Query all)</profile>
+    <description>Execution command returns the activity status [pas] of the MT. It can be used to interrogate the MT before requesting action from the phone. Refer subclause 9.2 for possible [err] values.
+Test command returns values supported by the MT as a compound value.
+Defined values
+[pas]:
+0	ready (MT allows commands from TA/TE)
+1	unavailable (MT does not allow commands from TA/TE)
+2	unknown (MT is not guaranteed to respond to instructions)
+3	ringing (MT is ready for commands from TA/TE, but the ringer is active)
+4	call in progress (MT is ready for commands from TA/TE, but a call is in progress)
+5	asleep (MT is unable to process commands from TA/TE because it is in a low functionality state)
+also all other values below 128 are reserved by the present document.
+</description>
+</spec>
+<spec>
+    <command>AT+CFUN=</command>
+    <profile>Set phone functionality (Assign)</profile>
+    <description>Set command selects the level of functionality [fun] in the MT. Level 'full functionality' is where the highest level of power is drawn. 'Minimum functionality' is where minimum power is drawn. Level of functionality between these may also be specified by manufacturers. When supported by manufacturers, MT resetting with [rst] parameter may be utilized. Refer subclause 9.2 for possible [err] values.
+NOTE:	It is manufacturer specific does this command affect network registration. Command Operator Selection +COPS is used to force registration/deregistration.
+Test command returns values supported by the MT as a compound value.
+Defined values
+[fun]:
+0	minimum functionality
+1	full functionality
+2	disable phone transmit RF circuits only
+3	disable phone receive RF circuits only
+4	disable phone both transmit and receive RF circuits
+5...127	reserved for manufacturers as intermediate states between full and minimum functionality
+[rst]:
+0	do not reset the MT before setting it to [fun] power level
+NOTE:	This shall be always default when [rst] is not given.
+1	reset the MT before setting it to [fun] power level
+</description>
+</spec>
+<spec>
+    <command>AT+CFUN?</command>
+    <profile>Set phone functionality (Query)</profile>
+    <description>Set command selects the level of functionality [fun] in the MT. Level 'full functionality' is where the highest level of power is drawn. 'Minimum functionality' is where minimum power is drawn. Level of functionality between these may also be specified by manufacturers. When supported by manufacturers, MT resetting with [rst] parameter may be utilized. Refer subclause 9.2 for possible [err] values.
+NOTE:	It is manufacturer specific does this command affect network registration. Command Operator Selection +COPS is used to force registration/deregistration.
+Test command returns values supported by the MT as a compound value.
+Defined values
+[fun]:
+0	minimum functionality
+1	full functionality
+2	disable phone transmit RF circuits only
+3	disable phone receive RF circuits only
+4	disable phone both transmit and receive RF circuits
+5...127	reserved for manufacturers as intermediate states between full and minimum functionality
+[rst]:
+0	do not reset the MT before setting it to [fun] power level
+NOTE:	This shall be always default when [rst] is not given.
+1	reset the MT before setting it to [fun] power level
+</description>
+</spec>
+<spec>
+    <command>AT+CFUN=?</command>
+    <profile>Set phone functionality (Query all)</profile>
+    <description>Set command selects the level of functionality [fun] in the MT. Level 'full functionality' is where the highest level of power is drawn. 'Minimum functionality' is where minimum power is drawn. Level of functionality between these may also be specified by manufacturers. When supported by manufacturers, MT resetting with [rst] parameter may be utilized. Refer subclause 9.2 for possible [err] values.
+NOTE:	It is manufacturer specific does this command affect network registration. Command Operator Selection +COPS is used to force registration/deregistration.
+Test command returns values supported by the MT as a compound value.
+Defined values
+[fun]:
+0	minimum functionality
+1	full functionality
+2	disable phone transmit RF circuits only
+3	disable phone receive RF circuits only
+4	disable phone both transmit and receive RF circuits
+5...127	reserved for manufacturers as intermediate states between full and minimum functionality
+[rst]:
+0	do not reset the MT before setting it to [fun] power level
+NOTE:	This shall be always default when [rst] is not given.
+1	reset the MT before setting it to [fun] power level
+</description>
+</spec>
+<spec>
+    <command>AT+CPIN=</command>
+    <profile>Enter PIN (Assign)</profile>
+    <description>Set command sends to the MT a password which is necessary before it can be operated (SIM PIN, SIM PUK, PH‑SIM PIN, etc.). If the PIN is to be entered twice, the TA shall automatically repeat the PIN. If no PIN request is pending, no action is taken towards MT and an error message, +CME ERROR, is returned to TE. Refer subclause 9.2 for possible [err] values.
+NOTE:	SIM PIN, SIM PUK, PH-SIM PIN, PH-FSIM PIN, PH-FSIM PUK, SIM PIN2 and SIM PUK2 refer to the PIN of the selected application on the UICC. For example, in an UTRAN context, the selected application on a UICC should be a USIM and the SIM PIN then represents the PIN of the selected USIM. See TS 31.101 [65] for further details on application selection on the UICC.
+If the PIN required is SIM PUK or SIM PUK2, the second pin is required. This second pin, [newpin], is used to replace the old pin in the SIM.
+NOTE:	Commands which interact with MT that are accepted when MT is pending SIM PIN, SIM PUK, or PH‑SIM are: +CGMI, +CGMM, +CGMR, +CGSN, D112; (emergency call), +CPAS, +CFUN, +CPIN, +CDIS (read and test command only), and +CIND (read and test command only).
+Read command returns an alphanumeric string indicating whether some password is required or not.
+Defined values
+[pin], [newpin]: string type values
+[code] values reserved by the present document:
+READY	MT is not pending for any password
+SIM PIN	MT is waiting SIM PIN to be given
+SIM PUK	MT is waiting SIM PUK to be given
+PH-SIM PIN	MT is waiting phone‑to‑SIM card password to be given
+PH-FSIM PIN	MT is waiting phone-to-very first SIM card password to be given
+PH-FSIM PUK	MT is waiting phone-to-very first SIM card unblocking password to be given
+SIM PIN2	MT is waiting SIM PIN2 to be given (this [code] is recommended to be returned only when the last executed command resulted in PIN2 authentication failure (i.e. +CME ERROR: 17); if PIN2 is not entered right after the failure, it is recommended that MT does not block its operation)
+SIM PUK2	MT is waiting SIM PUK2 to be given (this [code] is recommended to be returned only when the last executed command resulted in PUK2 authentication failure (i.e. +CME ERROR: 18); if PUK2 and new PIN2 are not entered right after the failure, it is recommended that MT does not block its operation)
+PH-NET PIN	MT is waiting network personalization password to be given
+PH-NET PUK	MT is waiting network personalization unblocking password to be given
+PH-NETSUB PIN	MT is waiting network subset personalization password to be given
+PH-NETSUB PUK	MT is waiting network subset personalization unblocking password to be given
+PH-SP PIN	MT is waiting service provider personalization password to be given
+PH-SP PUK	MT is waiting service provider personalization unblocking password to be given
+PH-CORP PIN	MT is waiting corporate personalization password to be given
+PH-CORP PUK	MT is waiting corporate personalization unblocking password to be given
+</description>
+</spec>
+<spec>
+    <command>AT+CPIN?</command>
+    <profile>Enter PIN (Query)</profile>
+    <description>Set command sends to the MT a password which is necessary before it can be operated (SIM PIN, SIM PUK, PH‑SIM PIN, etc.). If the PIN is to be entered twice, the TA shall automatically repeat the PIN. If no PIN request is pending, no action is taken towards MT and an error message, +CME ERROR, is returned to TE. Refer subclause 9.2 for possible [err] values.
+NOTE:	SIM PIN, SIM PUK, PH-SIM PIN, PH-FSIM PIN, PH-FSIM PUK, SIM PIN2 and SIM PUK2 refer to the PIN of the selected application on the UICC. For example, in an UTRAN context, the selected application on a UICC should be a USIM and the SIM PIN then represents the PIN of the selected USIM. See TS 31.101 [65] for further details on application selection on the UICC.
+If the PIN required is SIM PUK or SIM PUK2, the second pin is required. This second pin, [newpin], is used to replace the old pin in the SIM.
+NOTE:	Commands which interact with MT that are accepted when MT is pending SIM PIN, SIM PUK, or PH‑SIM are: +CGMI, +CGMM, +CGMR, +CGSN, D112; (emergency call), +CPAS, +CFUN, +CPIN, +CDIS (read and test command only), and +CIND (read and test command only).
+Read command returns an alphanumeric string indicating whether some password is required or not.
+Defined values
+[pin], [newpin]: string type values
+[code] values reserved by the present document:
+READY	MT is not pending for any password
+SIM PIN	MT is waiting SIM PIN to be given
+SIM PUK	MT is waiting SIM PUK to be given
+PH-SIM PIN	MT is waiting phone‑to‑SIM card password to be given
+PH-FSIM PIN	MT is waiting phone-to-very first SIM card password to be given
+PH-FSIM PUK	MT is waiting phone-to-very first SIM card unblocking password to be given
+SIM PIN2	MT is waiting SIM PIN2 to be given (this [code] is recommended to be returned only when the last executed command resulted in PIN2 authentication failure (i.e. +CME ERROR: 17); if PIN2 is not entered right after the failure, it is recommended that MT does not block its operation)
+SIM PUK2	MT is waiting SIM PUK2 to be given (this [code] is recommended to be returned only when the last executed command resulted in PUK2 authentication failure (i.e. +CME ERROR: 18); if PUK2 and new PIN2 are not entered right after the failure, it is recommended that MT does not block its operation)
+PH-NET PIN	MT is waiting network personalization password to be given
+PH-NET PUK	MT is waiting network personalization unblocking password to be given
+PH-NETSUB PIN	MT is waiting network subset personalization password to be given
+PH-NETSUB PUK	MT is waiting network subset personalization unblocking password to be given
+PH-SP PIN	MT is waiting service provider personalization password to be given
+PH-SP PUK	MT is waiting service provider personalization unblocking password to be given
+PH-CORP PIN	MT is waiting corporate personalization password to be given
+PH-CORP PUK	MT is waiting corporate personalization unblocking password to be given
+</description>
+</spec>
+<spec>
+    <command>AT+CPIN=?</command>
+    <profile>Enter PIN (Query all)</profile>
+    <description>Set command sends to the MT a password which is necessary before it can be operated (SIM PIN, SIM PUK, PH‑SIM PIN, etc.). If the PIN is to be entered twice, the TA shall automatically repeat the PIN. If no PIN request is pending, no action is taken towards MT and an error message, +CME ERROR, is returned to TE. Refer subclause 9.2 for possible [err] values.
+NOTE:	SIM PIN, SIM PUK, PH-SIM PIN, PH-FSIM PIN, PH-FSIM PUK, SIM PIN2 and SIM PUK2 refer to the PIN of the selected application on the UICC. For example, in an UTRAN context, the selected application on a UICC should be a USIM and the SIM PIN then represents the PIN of the selected USIM. See TS 31.101 [65] for further details on application selection on the UICC.
+If the PIN required is SIM PUK or SIM PUK2, the second pin is required. This second pin, [newpin], is used to replace the old pin in the SIM.
+NOTE:	Commands which interact with MT that are accepted when MT is pending SIM PIN, SIM PUK, or PH‑SIM are: +CGMI, +CGMM, +CGMR, +CGSN, D112; (emergency call), +CPAS, +CFUN, +CPIN, +CDIS (read and test command only), and +CIND (read and test command only).
+Read command returns an alphanumeric string indicating whether some password is required or not.
+Defined values
+[pin], [newpin]: string type values
+[code] values reserved by the present document:
+READY	MT is not pending for any password
+SIM PIN	MT is waiting SIM PIN to be given
+SIM PUK	MT is waiting SIM PUK to be given
+PH-SIM PIN	MT is waiting phone‑to‑SIM card password to be given
+PH-FSIM PIN	MT is waiting phone-to-very first SIM card password to be given
+PH-FSIM PUK	MT is waiting phone-to-very first SIM card unblocking password to be given
+SIM PIN2	MT is waiting SIM PIN2 to be given (this [code] is recommended to be returned only when the last executed command resulted in PIN2 authentication failure (i.e. +CME ERROR: 17); if PIN2 is not entered right after the failure, it is recommended that MT does not block its operation)
+SIM PUK2	MT is waiting SIM PUK2 to be given (this [code] is recommended to be returned only when the last executed command resulted in PUK2 authentication failure (i.e. +CME ERROR: 18); if PUK2 and new PIN2 are not entered right after the failure, it is recommended that MT does not block its operation)
+PH-NET PIN	MT is waiting network personalization password to be given
+PH-NET PUK	MT is waiting network personalization unblocking password to be given
+PH-NETSUB PIN	MT is waiting network subset personalization password to be given
+PH-NETSUB PUK	MT is waiting network subset personalization unblocking password to be given
+PH-SP PIN	MT is waiting service provider personalization password to be given
+PH-SP PUK	MT is waiting service provider personalization unblocking password to be given
+PH-CORP PIN	MT is waiting corporate personalization password to be given
+PH-CORP PUK	MT is waiting corporate personalization unblocking password to be given
+</description>
+</spec>
+<spec>
+    <command>AT+CBC</command>
+    <profile>Battery charge </profile>
+    <description>Execution command returns battery connection status [bcs] and battery charge level [bcl] of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns values supported as compound values.
+Defined values
+[bcs]:
+0	MT is powered by the battery
+1	MT has a battery connected, but is not powered by it
+2	MT does not have a battery connected
+3	Recognized power fault, calls inhibited
+[bcl]:
+0	battery is exhausted, or MT does not have a battery connected
+1...100	battery has 1‑100 percent of capacity remaining
+</description>
+</spec>
+<spec>
+    <command>AT+CBC=?</command>
+    <profile>Battery charge (Query all)</profile>
+    <description>Execution command returns battery connection status [bcs] and battery charge level [bcl] of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns values supported as compound values.
+Defined values
+[bcs]:
+0	MT is powered by the battery
+1	MT has a battery connected, but is not powered by it
+2	MT does not have a battery connected
+3	Recognized power fault, calls inhibited
+[bcl]:
+0	battery is exhausted, or MT does not have a battery connected
+1...100	battery has 1‑100 percent of capacity remaining
+</description>
+</spec>
+<spec>
+    <command>AT+CSQ</command>
+    <profile>Signal quality </profile>
+    <description>Execution command returns received signal strength indication [rssi] and channel bit error rate [ber] from the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns values supported as compound values.
+Defined values
+[rssi]:
+0	‑113 dBm or less
+1	‑111 dBm
+2...30	‑109... ‑53 dBm
+31	‑51 dBm or greater
+99	not known or not detectable
+[ber] (in percent):
+0...7	as RXQUAL values in the table in TS 45.008 [20] subclause 8.2.4
+99	not known or not detectable
+</description>
+</spec>
+<spec>
+    <command>AT+CSQ=?</command>
+    <profile>Signal quality (Query all)</profile>
+    <description>Execution command returns received signal strength indication [rssi] and channel bit error rate [ber] from the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns values supported as compound values.
+Defined values
+[rssi]:
+0	‑113 dBm or less
+1	‑111 dBm
+2...30	‑109... ‑53 dBm
+31	‑51 dBm or greater
+99	not known or not detectable
+[ber] (in percent):
+0...7	as RXQUAL values in the table in TS 45.008 [20] subclause 8.2.4
+99	not known or not detectable
+</description>
+</spec>
+<spec>
+    <command>AT+CIND=</command>
+    <profile>Indicator control (Assign)</profile>
+    <description>Set command is used to set the values of MT indicators. [ind] value 0 means that the indicator is off (or in state which can be identified as 'off'‑state), 1 means that indicator is on (or in a state which is more substantial than 'off'‑state), 2 is more substantial than 1, and so on. If the indicator is a simple on/off style element, it has values 0 and 1. The number of elements is MT specific. If MT does not allow setting of indicators or MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values. If certain indicator is not writable, setting of it should be ignored. If parameter is empty field, indicator shall remain in the previous value.
+Read command returns the status of MT indicators. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns pairs, where string value [descr] is a maximum 16 character description of the indicator and compound value is the allowed values for the indicator. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+NOTE:	MT manufacturer should offer the description of supported indicators not listed here and their value ranges and default values.
+Defined values
+[ind]: integer type value, which shall be in range of corresponding [descr]
+[descr] values reserved by the present document and their [ind] ranges:
+'battchg'	battery charge level (0‑5)
+'signal'	signal quality (0‑5)
+'service'	service availability (0‑1)
+'sounder'	sounder activity (0‑1)
+'message'	message received (0‑1)
+'call'	call in progress (0‑1)
+'vox'	transmit activated by voice activity (0‑1)
+'roam'	roaming indicator (0‑1) 
+'smsfull'	a short message memory storage in the MT has become full and a short message has been rejected (2), has become full (1), or memory locations are available (0); i.e. the range is (0‑2)
+
+</description>
+</spec>
+<spec>
+    <command>AT+CIND?</command>
+    <profile>Indicator control (Query)</profile>
+    <description>Set command is used to set the values of MT indicators. [ind] value 0 means that the indicator is off (or in state which can be identified as 'off'‑state), 1 means that indicator is on (or in a state which is more substantial than 'off'‑state), 2 is more substantial than 1, and so on. If the indicator is a simple on/off style element, it has values 0 and 1. The number of elements is MT specific. If MT does not allow setting of indicators or MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values. If certain indicator is not writable, setting of it should be ignored. If parameter is empty field, indicator shall remain in the previous value.
+Read command returns the status of MT indicators. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns pairs, where string value [descr] is a maximum 16 character description of the indicator and compound value is the allowed values for the indicator. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+NOTE:	MT manufacturer should offer the description of supported indicators not listed here and their value ranges and default values.
+Defined values
+[ind]: integer type value, which shall be in range of corresponding [descr]
+[descr] values reserved by the present document and their [ind] ranges:
+'battchg'	battery charge level (0‑5)
+'signal'	signal quality (0‑5)
+'service'	service availability (0‑1)
+'sounder'	sounder activity (0‑1)
+'message'	message received (0‑1)
+'call'	call in progress (0‑1)
+'vox'	transmit activated by voice activity (0‑1)
+'roam'	roaming indicator (0‑1) 
+'smsfull'	a short message memory storage in the MT has become full and a short message has been rejected (2), has become full (1), or memory locations are available (0); i.e. the range is (0‑2)
+
+</description>
+</spec>
+<spec>
+    <command>AT+CIND=?</command>
+    <profile>Indicator control (Query all)</profile>
+    <description>Set command is used to set the values of MT indicators. [ind] value 0 means that the indicator is off (or in state which can be identified as 'off'‑state), 1 means that indicator is on (or in a state which is more substantial than 'off'‑state), 2 is more substantial than 1, and so on. If the indicator is a simple on/off style element, it has values 0 and 1. The number of elements is MT specific. If MT does not allow setting of indicators or MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values. If certain indicator is not writable, setting of it should be ignored. If parameter is empty field, indicator shall remain in the previous value.
+Read command returns the status of MT indicators. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns pairs, where string value [descr] is a maximum 16 character description of the indicator and compound value is the allowed values for the indicator. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+NOTE:	MT manufacturer should offer the description of supported indicators not listed here and their value ranges and default values.
+Defined values
+[ind]: integer type value, which shall be in range of corresponding [descr]
+[descr] values reserved by the present document and their [ind] ranges:
+'battchg'	battery charge level (0‑5)
+'signal'	signal quality (0‑5)
+'service'	service availability (0‑1)
+'sounder'	sounder activity (0‑1)
+'message'	message received (0‑1)
+'call'	call in progress (0‑1)
+'vox'	transmit activated by voice activity (0‑1)
+'roam'	roaming indicator (0‑1) 
+'smsfull'	a short message memory storage in the MT has become full and a short message has been rejected (2), has become full (1), or memory locations are available (0); i.e. the range is (0‑2)
+
+</description>
+</spec>
+<spec>
+    <command>AT+CPBR=</command>
+    <profile>Read phonebook entries (Assign)</profile>
+    <description>Execution command returns phonebook entries in location number range [index1]... [index2] from the current phonebook memory storage selected with +CPBS. If [index2] is left out, only location [index1] is returned. Entry fields returned are location number [indexn], phone number stored there [number] (of format [type]), text [text] associated with the number, if the selected phonebook supports hidden entries, [hidden] indicating if the entry is hidden, [group] indicating a group the entry may belong to, [adnumber] an additional number (of format [adtype]), [secondtext] a second text field associated with the number and [email] an email field. If all queried locations are empty (but available), no information text lines may be returned. If listing fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns location range supported by the current storage as a compound value and the maximum lengths of [number], [text], [group], [secondtext] and [email]  fields. In case of (U)SIM storage, the lengths may not be available. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Defined values
+[index1], [index2], [index]: integer type values in the range of location numbers of phonebook memory
+[number]: string type phone number of format [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[text]: string type field of maximum length [tlength]; character set as specified by command Select TE Character Set +CSCS
+[group]: string type field of maximum length [glength]; character set as specified by command Select TE Character Set +CSCS
+[adnumber]: string type phone number of format [adtype]
+[adtype]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[secondtext]: string type field of maximum length [slength]; character set as specified by command Select TE Character Set +CSCS
+[email]: string type field of maximum length [elength]; character set as specified by command Select TE Character Set +CSCS
+[nlength]: integer type value indicating the maximum length of field [number]
+[tlength]: integer type value indicating the maximum length of field [text]
+[glength]: integer type value indicating the maximum length of field [group]
+[slength]: integer type value indicating the maximum length of field [secondtext]
+[elength]: integer type value indicating the maximum length of field [email]
+[hidden]: indicates if the entry is hidden or not
+0:	phonebook entry not hidden
+1:	phonebook entry hidden
+</description>
+</spec>
+<spec>
+    <command>AT+CPBR=?</command>
+    <profile>Read phonebook entries (Query all)</profile>
+    <description>Execution command returns phonebook entries in location number range [index1]... [index2] from the current phonebook memory storage selected with +CPBS. If [index2] is left out, only location [index1] is returned. Entry fields returned are location number [indexn], phone number stored there [number] (of format [type]), text [text] associated with the number, if the selected phonebook supports hidden entries, [hidden] indicating if the entry is hidden, [group] indicating a group the entry may belong to, [adnumber] an additional number (of format [adtype]), [secondtext] a second text field associated with the number and [email] an email field. If all queried locations are empty (but available), no information text lines may be returned. If listing fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns location range supported by the current storage as a compound value and the maximum lengths of [number], [text], [group], [secondtext] and [email]  fields. In case of (U)SIM storage, the lengths may not be available. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Defined values
+[index1], [index2], [index]: integer type values in the range of location numbers of phonebook memory
+[number]: string type phone number of format [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[text]: string type field of maximum length [tlength]; character set as specified by command Select TE Character Set +CSCS
+[group]: string type field of maximum length [glength]; character set as specified by command Select TE Character Set +CSCS
+[adnumber]: string type phone number of format [adtype]
+[adtype]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[secondtext]: string type field of maximum length [slength]; character set as specified by command Select TE Character Set +CSCS
+[email]: string type field of maximum length [elength]; character set as specified by command Select TE Character Set +CSCS
+[nlength]: integer type value indicating the maximum length of field [number]
+[tlength]: integer type value indicating the maximum length of field [text]
+[glength]: integer type value indicating the maximum length of field [group]
+[slength]: integer type value indicating the maximum length of field [secondtext]
+[elength]: integer type value indicating the maximum length of field [email]
+[hidden]: indicates if the entry is hidden or not
+0:	phonebook entry not hidden
+1:	phonebook entry hidden
+</description>
+</spec>
+<spec>
+    <command>AT+CPBF=</command>
+    <profile>Find phonebook entries (Assign)</profile>
+    <description>Execution command returns phonebook entries (from the current phonebook memory storage selected with +CPBS) which alphanumeric field start with string [findtext]. Entry fields returned are location number [indexn], phone number stored there [number] (of format [type]), text [text] associated with the number, if the selected phonebook supports hidden entries, [hidden] indicating if the entry is hidden, [group] indicating a group the entry may belong to, [adnumber] an additional number (of format [adtype]), [secondtext] a second text field associated with the number and [email] an email field. If listing fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns the maximum lengths of [number], [text], [group], [secondtext] and [email] fields. In case of (U)SIM storage, the lengths may not be available. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+
+Defined values
+[index1], [index2]: integer type values in the range of location numbers of phonebook memory
+[number]: string type phone number of format [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[group]: string type field of maximum length [glength]; character set as specified by command Select TE Character Set +CSCS
+[adnumber]: string type phone number of format [adtype]
+[adtype]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[secondtext]: string type field of maximum length [slength]; character set as specified by command Select TE Character Set +CSCS
+[email]: string type field of maximum length [elength]; character set as specified by command Select TE Character Set +CSCS
+[findtext], [text]: string type field of maximum length [tlength]; character set as specified by command Select TE Character Set +CSCS
+[nlength]: integer type value indicating the maximum length of field [number]
+[tlength]: integer type value indicating the maximum length of field [text]
+[glength]: integer type value indicating the maximum length of field [group]
+[slength]: integer type value indicating the maximum length of field [secondtext]
+[elength]: integer type value indicating the maximum length of field [email]
+[hidden]: indicates if the entry is hidden or not
+0: 	phonebook entry not hidden
+1:	phonebook entry hidden
+</description>
+</spec>
+<spec>
+    <command>AT+CPBF=?</command>
+    <profile>Find phonebook entries (Query all)</profile>
+    <description>Execution command returns phonebook entries (from the current phonebook memory storage selected with +CPBS) which alphanumeric field start with string [findtext]. Entry fields returned are location number [indexn], phone number stored there [number] (of format [type]), text [text] associated with the number, if the selected phonebook supports hidden entries, [hidden] indicating if the entry is hidden, [group] indicating a group the entry may belong to, [adnumber] an additional number (of format [adtype]), [secondtext] a second text field associated with the number and [email] an email field. If listing fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns the maximum lengths of [number], [text], [group], [secondtext] and [email] fields. In case of (U)SIM storage, the lengths may not be available. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+
+Defined values
+[index1], [index2]: integer type values in the range of location numbers of phonebook memory
+[number]: string type phone number of format [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[group]: string type field of maximum length [glength]; character set as specified by command Select TE Character Set +CSCS
+[adnumber]: string type phone number of format [adtype]
+[adtype]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[secondtext]: string type field of maximum length [slength]; character set as specified by command Select TE Character Set +CSCS
+[email]: string type field of maximum length [elength]; character set as specified by command Select TE Character Set +CSCS
+[findtext], [text]: string type field of maximum length [tlength]; character set as specified by command Select TE Character Set +CSCS
+[nlength]: integer type value indicating the maximum length of field [number]
+[tlength]: integer type value indicating the maximum length of field [text]
+[glength]: integer type value indicating the maximum length of field [group]
+[slength]: integer type value indicating the maximum length of field [secondtext]
+[elength]: integer type value indicating the maximum length of field [email]
+[hidden]: indicates if the entry is hidden or not
+0: 	phonebook entry not hidden
+1:	phonebook entry hidden
+</description>
+</spec>
+<spec>
+    <command>AT+CPBW=</command>
+    <profile>Write phonebook entry (Assign)</profile>
+    <description>Execution command writes phonebook entry in location number [index] in the current phonebook memory storage selected with +CPBS. Entry fields written are phone number [number] (in the format [type]), text [text] associated with the number, if the selected phonebook supports hidden entries, [hidden] parameter, which indicates if the entry is hidden or not, [group] indicating a group the entry may belong to, [adnumber] an additional number (of format [adtype]), [secondtext] a second text field associated with the number and [email] an email field. If those fields are omitted, phonebook entry is deleted. If [index] is left out, but [number] is given, entry is written to the first free location in the phonebook (the implementation of this feature is manufacturer specific). If writing fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns location range supported by the current storage as a compound value, the maximum length of [number] field, supported number formats of the storage, the maximum length of [text] field, the maximum length of [group], the maximum length of [secondtext], and the maximum length of [email]. In case of SIM storage, the lengths may not be available. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values. If storage does not offer format information, the format list should be empty parenthesis
+Defined values
+[index]: integer type values in the range of location numbers of phonebook memory
+[number]: string type phone number of format [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7) ; default 145 when dialling string includes international access code character '+', otherwise 129
+[text]: string type field of maximum length [tlength]; character set as specified by command Select TE Character Set +CSCS
+[group]: string type field of maximum length [glength]; character set as specified by command Select TE Character Set +CSCS
+[adnumber]: string type phone number of format [adtype]
+[adtype]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[secondtext]: string type field of maximum length [slength]; character set as specified by command Select TE Character Set +CSCS
+[email]: string type field of maximum length [elength]; character set as specified by command Select TE Character Set +CSCS
+[nlength]: integer type value indicating the maximum length of field [number]
+[tlength]: integer type value indicating the maximum length of field [text]
+[glength]: integer type value indicating the maximum length of field [group]
+[slength]: integer type value indicating the maximum length of field [secondtext]
+[elength]: integer type value indicating the maximum length of field [email]
+[hidden]: indicates if the entry is hidden or not
+0: 	phonebook entry not hidden
+1:	phonebook entry hidden
+</description>
+</spec>
+<spec>
+    <command>AT+CPBW=?</command>
+    <profile>Write phonebook entry (Query all)</profile>
+    <description>Execution command writes phonebook entry in location number [index] in the current phonebook memory storage selected with +CPBS. Entry fields written are phone number [number] (in the format [type]), text [text] associated with the number, if the selected phonebook supports hidden entries, [hidden] parameter, which indicates if the entry is hidden or not, [group] indicating a group the entry may belong to, [adnumber] an additional number (of format [adtype]), [secondtext] a second text field associated with the number and [email] an email field. If those fields are omitted, phonebook entry is deleted. If [index] is left out, but [number] is given, entry is written to the first free location in the phonebook (the implementation of this feature is manufacturer specific). If writing fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns location range supported by the current storage as a compound value, the maximum length of [number] field, supported number formats of the storage, the maximum length of [text] field, the maximum length of [group], the maximum length of [secondtext], and the maximum length of [email]. In case of SIM storage, the lengths may not be available. If MT is not currently reachable, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values. If storage does not offer format information, the format list should be empty parenthesis
+Defined values
+[index]: integer type values in the range of location numbers of phonebook memory
+[number]: string type phone number of format [type]
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7) ; default 145 when dialling string includes international access code character '+', otherwise 129
+[text]: string type field of maximum length [tlength]; character set as specified by command Select TE Character Set +CSCS
+[group]: string type field of maximum length [glength]; character set as specified by command Select TE Character Set +CSCS
+[adnumber]: string type phone number of format [adtype]
+[adtype]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7)
+[secondtext]: string type field of maximum length [slength]; character set as specified by command Select TE Character Set +CSCS
+[email]: string type field of maximum length [elength]; character set as specified by command Select TE Character Set +CSCS
+[nlength]: integer type value indicating the maximum length of field [number]
+[tlength]: integer type value indicating the maximum length of field [text]
+[glength]: integer type value indicating the maximum length of field [group]
+[slength]: integer type value indicating the maximum length of field [secondtext]
+[elength]: integer type value indicating the maximum length of field [email]
+[hidden]: indicates if the entry is hidden or not
+0: 	phonebook entry not hidden
+1:	phonebook entry hidden
+</description>
+</spec>
+<spec>
+    <command>AT+CCLK=</command>
+    <profile>Clock (Assign)</profile>
+    <description>Set command sets the real‑time clock of the MT. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current setting of the clock.
+Defined values
+[time]: string type value; format is 'yy/MM/dd,hh:mm:sszz', where characters indicate year (two last digits), month, day, hour, minutes, seconds and time zone (indicates the difference, expressed in quarters of an hour, between the local time and GMT; range -96...+96). E.g. 6th of May 1994, 22:10:00 GMT+2 hours equals to '94/05/06,22:10:00+08'
+NOTE:	If MT does not support time zone information then the three last characters of [time] are not returned by +CCLK?. The format of [time] is specified by use of the +CSDF command.
+</description>
+</spec>
+<spec>
+    <command>AT+CCLK?</command>
+    <profile>Clock (Query)</profile>
+    <description>Set command sets the real‑time clock of the MT. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current setting of the clock.
+Defined values
+[time]: string type value; format is 'yy/MM/dd,hh:mm:sszz', where characters indicate year (two last digits), month, day, hour, minutes, seconds and time zone (indicates the difference, expressed in quarters of an hour, between the local time and GMT; range -96...+96). E.g. 6th of May 1994, 22:10:00 GMT+2 hours equals to '94/05/06,22:10:00+08'
+NOTE:	If MT does not support time zone information then the three last characters of [time] are not returned by +CCLK?. The format of [time] is specified by use of the +CSDF command.
+</description>
+</spec>
+<spec>
+    <command>AT+CCLK=?</command>
+    <profile>Clock (Query all)</profile>
+    <description>Set command sets the real‑time clock of the MT. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current setting of the clock.
+Defined values
+[time]: string type value; format is 'yy/MM/dd,hh:mm:sszz', where characters indicate year (two last digits), month, day, hour, minutes, seconds and time zone (indicates the difference, expressed in quarters of an hour, between the local time and GMT; range -96...+96). E.g. 6th of May 1994, 22:10:00 GMT+2 hours equals to '94/05/06,22:10:00+08'
+NOTE:	If MT does not support time zone information then the three last characters of [time] are not returned by +CCLK?. The format of [time] is specified by use of the +CSDF command.
+</description>
+</spec>
+<spec>
+    <command>AT+CALA=</command>
+    <profile>Alarm (Assign)</profile>
+    <description>Set command sets an alarm time in the MT. There can be an array of different types of alarms, and each alarm may cause different text to be displayed in the MT display. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+To set up a recurrent alarm for one or more days in the week, the [recurr]-parameter may be used.
+When an alarm is timed out and executed, the unsolicited result code +CALV: [n] is always returned, even if the alarm is set up to be silent.
+Read command returns the list of current active alarm settings in the MT.
+Test command returns supported array index values, alarm types, and maximum length of the text to be displayed.
+Defined values
+[time]: refer +CCLK,+CSDF
+NOTE:	If the [recurr]-parameter is used, the [time]-parameter must not contain a date.
+[n], [n1], [n2]: integer type value indicating the index of the alarm; default is manufacturer specific
+[type]: integer type value indicating the type of the alarm (e.g. sound, volume, LED); values and default are manufacturer specific
+[text]: string type value indicating the text to be displayed when alarm time is reached; maximum length [tlength]
+[tlength]: integer type value indicating the maximum length of [text]
+[recurr]: string type value indicating day of week for the alarm in one of the following formats:
+
+'[1..7][,[1..7][…]]' – Sets a recurrent alarm for one or more days in the week. The digits 1 to 7 corresponds to the days in the week, Monday (1), …, Sunday (7).
+Example: The string '1,2,3,4,5' may be used to set an alarm for all weekdays.
+
+'0' – Sets a recurrent alarm for all days in the week.
+[rlength]: integer type value indicating the maximum length of [recurr]
+[silent]: Integer type value indicating if the alarm is silent or not. If set to 1 the alarm will be silent and the only result from the alarm is the unsolicited result code +CALV. If set to 0 the alarm will not be silent.
+</description>
+</spec>
+<spec>
+    <command>AT+CALA?</command>
+    <profile>Alarm (Query)</profile>
+    <description>Set command sets an alarm time in the MT. There can be an array of different types of alarms, and each alarm may cause different text to be displayed in the MT display. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+To set up a recurrent alarm for one or more days in the week, the [recurr]-parameter may be used.
+When an alarm is timed out and executed, the unsolicited result code +CALV: [n] is always returned, even if the alarm is set up to be silent.
+Read command returns the list of current active alarm settings in the MT.
+Test command returns supported array index values, alarm types, and maximum length of the text to be displayed.
+Defined values
+[time]: refer +CCLK,+CSDF
+NOTE:	If the [recurr]-parameter is used, the [time]-parameter must not contain a date.
+[n], [n1], [n2]: integer type value indicating the index of the alarm; default is manufacturer specific
+[type]: integer type value indicating the type of the alarm (e.g. sound, volume, LED); values and default are manufacturer specific
+[text]: string type value indicating the text to be displayed when alarm time is reached; maximum length [tlength]
+[tlength]: integer type value indicating the maximum length of [text]
+[recurr]: string type value indicating day of week for the alarm in one of the following formats:
+
+'[1..7][,[1..7][…]]' – Sets a recurrent alarm for one or more days in the week. The digits 1 to 7 corresponds to the days in the week, Monday (1), …, Sunday (7).
+Example: The string '1,2,3,4,5' may be used to set an alarm for all weekdays.
+
+'0' – Sets a recurrent alarm for all days in the week.
+[rlength]: integer type value indicating the maximum length of [recurr]
+[silent]: Integer type value indicating if the alarm is silent or not. If set to 1 the alarm will be silent and the only result from the alarm is the unsolicited result code +CALV. If set to 0 the alarm will not be silent.
+</description>
+</spec>
+<spec>
+    <command>AT+CALA=?</command>
+    <profile>Alarm (Query all)</profile>
+    <description>Set command sets an alarm time in the MT. There can be an array of different types of alarms, and each alarm may cause different text to be displayed in the MT display. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+To set up a recurrent alarm for one or more days in the week, the [recurr]-parameter may be used.
+When an alarm is timed out and executed, the unsolicited result code +CALV: [n] is always returned, even if the alarm is set up to be silent.
+Read command returns the list of current active alarm settings in the MT.
+Test command returns supported array index values, alarm types, and maximum length of the text to be displayed.
+Defined values
+[time]: refer +CCLK,+CSDF
+NOTE:	If the [recurr]-parameter is used, the [time]-parameter must not contain a date.
+[n], [n1], [n2]: integer type value indicating the index of the alarm; default is manufacturer specific
+[type]: integer type value indicating the type of the alarm (e.g. sound, volume, LED); values and default are manufacturer specific
+[text]: string type value indicating the text to be displayed when alarm time is reached; maximum length [tlength]
+[tlength]: integer type value indicating the maximum length of [text]
+[recurr]: string type value indicating day of week for the alarm in one of the following formats:
+
+'[1..7][,[1..7][…]]' – Sets a recurrent alarm for one or more days in the week. The digits 1 to 7 corresponds to the days in the week, Monday (1), …, Sunday (7).
+Example: The string '1,2,3,4,5' may be used to set an alarm for all weekdays.
+
+'0' – Sets a recurrent alarm for all days in the week.
+[rlength]: integer type value indicating the maximum length of [recurr]
+[silent]: Integer type value indicating if the alarm is silent or not. If set to 1 the alarm will be silent and the only result from the alarm is the unsolicited result code +CALV. If set to 0 the alarm will not be silent.
+</description>
+</spec>
+<spec>
+    <command>AT+CSIM=</command>
+    <profile>Generic SIM access (Assign)</profile>
+    <description>Set command transmits to the MT the [command] it then shall send as it is to the SIM. In the same manner the SIM [response] shall be sent back by the MT to the TA as it is. Refer subclause 9.2 for [err] values.
+This command allows a direct control of the SIM by an distant application on the TE. The TE shall then take care of processing SIM information within the frame specified by GSM/UMTS.
+NOTE:	Compared to Restricted SIM Access command +CRSM, the definition of +CSIM allows TE to take more control over the SIM‑MT interface. The locking and unlocking of the interface may be done by a special [command] value or automatically by TA/MT (by interpreting [command] parameter). In case that TE application does not use the unlock command (or does not send a [command] causing automatic unlock) in a certain timeout value, MT may release the locking.
+Defined values
+[length] : integer type; length of the characters that are sent to TE in [command] or [response] (two times the actual length of the command or response)
+[command] : command passed on by the MT to the SIM in the format as described in GSM 51.011 [28] (hexadecimal character format; refer +CSCS)
+[response] : response to the command passed on by the SIM to the MT in the format as described in GSM 51.011 [28] (hexadecimal character format; refer +CSCS)
+</description>
+</spec>
+<spec>
+    <command>AT+CSIM=?</command>
+    <profile>Generic SIM access (Query all)</profile>
+    <description>Set command transmits to the MT the [command] it then shall send as it is to the SIM. In the same manner the SIM [response] shall be sent back by the MT to the TA as it is. Refer subclause 9.2 for [err] values.
+This command allows a direct control of the SIM by an distant application on the TE. The TE shall then take care of processing SIM information within the frame specified by GSM/UMTS.
+NOTE:	Compared to Restricted SIM Access command +CRSM, the definition of +CSIM allows TE to take more control over the SIM‑MT interface. The locking and unlocking of the interface may be done by a special [command] value or automatically by TA/MT (by interpreting [command] parameter). In case that TE application does not use the unlock command (or does not send a [command] causing automatic unlock) in a certain timeout value, MT may release the locking.
+Defined values
+[length] : integer type; length of the characters that are sent to TE in [command] or [response] (two times the actual length of the command or response)
+[command] : command passed on by the MT to the SIM in the format as described in GSM 51.011 [28] (hexadecimal character format; refer +CSCS)
+[response] : response to the command passed on by the SIM to the MT in the format as described in GSM 51.011 [28] (hexadecimal character format; refer +CSCS)
+</description>
+</spec>
+<spec>
+    <command>AT+CRSM=</command>
+    <profile>Restricted SIM access (Assign)</profile>
+    <description>By using this command instead of Generic SIM Access +CSIM TE application has easier but more limited access to the SIM database. Set command transmits to the MT the SIM [command] and its required parameters. MT handles internally all SIM‑MT interface locking and file selection routines. As response to the command, MT sends the actual SIM information parameters and response data. MT error result code +CME ERROR may be returned when the command cannot be passed to the SIM, but failure in the execution of the command in the SIM is reported in [sw1] and [sw2] parameters. Refer to subclause 9.2 for [err] values.
+Coordination of command requests to SIM and the ones issued by GSM/UMTS application inside the MT is implementation dependent. However the TE should be aware of the precedence of the GSM/UMTS application commands to the TE commands.
+Defined values
+[command] (command passed on by the MT to the SIM; refer GSM 51.011 [28]):
+176	READ BINARY
+178	READ RECORD
+192	GET RESPONSE
+214	UPDATE BINARY
+220	UPDATE RECORD
+242	STATUS
+203	RETRIEVE DATA
+219	SET DATA
+all other values are reserved
+NOTE 1:	The MT internally executes all commands necessary for selecting the desired file, before performing the actual command.
+[fileid]: integer type; this is the identifier of a elementary datafile on SIM. Mandatory for every command except STATUS
+NOTE 2:	The range of valid file identifiers depends on the actual SIM and is defined in GSM 51.011 [28]. Optional files may not be present at all.
+[P1], [P2], [P3]: integer type; parameters passed on by the MT to the SIM. These parameters are mandatory for every command, except GET RESPONSE and STATUS. The values are described in GSM 51.011 [28]
+[data]: information which shall be written to the SIM (hexadecimal character format; refer +CSCS)
+[pathid]: string type; contains the path of an elementary file on the SIM/UICC  in hexadecimal format as defined in ETSI TS 102 221 [60] (e.g. '7F205F70' in SIM and UICC case). The [pathid] shall only be used in the mode 'select by path from MF' as defined in ETSI TS 102 221 [60].
+NOTE 3:	Since valid elementary file identifiers may not be unique over all valid dedicated file identifiers the [pathid] indicates the targeted UICC/SIM directory path in case of ambiguous file identifiers. For earlier  versions of this specification or if [pathid] is omitted, it could be implementation specific which one will be selected.
+[sw1], [sw2]: integer type; information from the SIM about the execution of the actual command. These parameters are delivered to the TE in both cases, on successful or failed execution of the command
+[response]: response of a successful completion of the command previously issued (hexadecimal character format; refer +CSCS). STATUS and GET RESPONSE return data, which gives information about the current elementary datafield. This information includes the type of file and its size (refer GSM 51.011 [28]). After READ BINARY, READ RECORD or RETRIEVE DATA command the requested data will be returned. [response] is not returned after a successful UPDATE BINARY, UPDATE RECORD or SET DATA command
+</description>
+</spec>
+<spec>
+    <command>AT+CRSM=?</command>
+    <profile>Restricted SIM access (Query all)</profile>
+    <description>By using this command instead of Generic SIM Access +CSIM TE application has easier but more limited access to the SIM database. Set command transmits to the MT the SIM [command] and its required parameters. MT handles internally all SIM‑MT interface locking and file selection routines. As response to the command, MT sends the actual SIM information parameters and response data. MT error result code +CME ERROR may be returned when the command cannot be passed to the SIM, but failure in the execution of the command in the SIM is reported in [sw1] and [sw2] parameters. Refer to subclause 9.2 for [err] values.
+Coordination of command requests to SIM and the ones issued by GSM/UMTS application inside the MT is implementation dependent. However the TE should be aware of the precedence of the GSM/UMTS application commands to the TE commands.
+Defined values
+[command] (command passed on by the MT to the SIM; refer GSM 51.011 [28]):
+176	READ BINARY
+178	READ RECORD
+192	GET RESPONSE
+214	UPDATE BINARY
+220	UPDATE RECORD
+242	STATUS
+203	RETRIEVE DATA
+219	SET DATA
+all other values are reserved
+NOTE 1:	The MT internally executes all commands necessary for selecting the desired file, before performing the actual command.
+[fileid]: integer type; this is the identifier of a elementary datafile on SIM. Mandatory for every command except STATUS
+NOTE 2:	The range of valid file identifiers depends on the actual SIM and is defined in GSM 51.011 [28]. Optional files may not be present at all.
+[P1], [P2], [P3]: integer type; parameters passed on by the MT to the SIM. These parameters are mandatory for every command, except GET RESPONSE and STATUS. The values are described in GSM 51.011 [28]
+[data]: information which shall be written to the SIM (hexadecimal character format; refer +CSCS)
+[pathid]: string type; contains the path of an elementary file on the SIM/UICC  in hexadecimal format as defined in ETSI TS 102 221 [60] (e.g. '7F205F70' in SIM and UICC case). The [pathid] shall only be used in the mode 'select by path from MF' as defined in ETSI TS 102 221 [60].
+NOTE 3:	Since valid elementary file identifiers may not be unique over all valid dedicated file identifiers the [pathid] indicates the targeted UICC/SIM directory path in case of ambiguous file identifiers. For earlier  versions of this specification or if [pathid] is omitted, it could be implementation specific which one will be selected.
+[sw1], [sw2]: integer type; information from the SIM about the execution of the actual command. These parameters are delivered to the TE in both cases, on successful or failed execution of the command
+[response]: response of a successful completion of the command previously issued (hexadecimal character format; refer +CSCS). STATUS and GET RESPONSE return data, which gives information about the current elementary datafield. This information includes the type of file and its size (refer GSM 51.011 [28]). After READ BINARY, READ RECORD or RETRIEVE DATA command the requested data will be returned. [response] is not returned after a successful UPDATE BINARY, UPDATE RECORD or SET DATA command
+</description>
+</spec>
+<spec>
+    <command>AT+CSCC=</command>
+    <profile>Secure control command (Assign)</profile>
+    <description>This command is used to enable/disable access to commands protected by security mechanism. This enables/disables access to command sets designated as 'secure' such as programming of MT. Refer subclause 9.2 for possible [err] values.
+The TE asks for a [challenge] with [mode]=1 and one specific command set ([cmd_set]), the MT replies with the [challenge], which should be inserted into the identification algorithm in both entities (TE and MT). The algorithm output [token] is sent to the MT with [mode]=2 to enable the specified command set. [mode]=3 is used to disable the command set. 
+The read command returns the status ([mode] 2 or 3) of each supported command set.
+Defined values
+[mode]:  
+1	request challenge token to enable access to specified command set
+2	enable access to specified command set ([token] required)
+3	disable access to specified command set
+[cmd_set], [cmd_set1], [cmd_set2]:
+0 	MT/TA code re-programming command set.
+other values below 128 are reserved by the present document
+[token]: string type; a variable length bit string represented with IRA characters 0 - 9 and A - F, each character representing a nibble; e.g. bit string '0110 1100 1001 1010' is represented by the IRA string '6C9A'. The length of the required bit string varies depending on the value of [cmd_set].
+[challenge]: same format as token
+</description>
+</spec>
+<spec>
+    <command>AT+CSCC?</command>
+    <profile>Secure control command (Query)</profile>
+    <description>This command is used to enable/disable access to commands protected by security mechanism. This enables/disables access to command sets designated as 'secure' such as programming of MT. Refer subclause 9.2 for possible [err] values.
+The TE asks for a [challenge] with [mode]=1 and one specific command set ([cmd_set]), the MT replies with the [challenge], which should be inserted into the identification algorithm in both entities (TE and MT). The algorithm output [token] is sent to the MT with [mode]=2 to enable the specified command set. [mode]=3 is used to disable the command set. 
+The read command returns the status ([mode] 2 or 3) of each supported command set.
+Defined values
+[mode]:  
+1	request challenge token to enable access to specified command set
+2	enable access to specified command set ([token] required)
+3	disable access to specified command set
+[cmd_set], [cmd_set1], [cmd_set2]:
+0 	MT/TA code re-programming command set.
+other values below 128 are reserved by the present document
+[token]: string type; a variable length bit string represented with IRA characters 0 - 9 and A - F, each character representing a nibble; e.g. bit string '0110 1100 1001 1010' is represented by the IRA string '6C9A'. The length of the required bit string varies depending on the value of [cmd_set].
+[challenge]: same format as token
+</description>
+</spec>
+<spec>
+    <command>AT+CSCC=?</command>
+    <profile>Secure control command (Query all)</profile>
+    <description>This command is used to enable/disable access to commands protected by security mechanism. This enables/disables access to command sets designated as 'secure' such as programming of MT. Refer subclause 9.2 for possible [err] values.
+The TE asks for a [challenge] with [mode]=1 and one specific command set ([cmd_set]), the MT replies with the [challenge], which should be inserted into the identification algorithm in both entities (TE and MT). The algorithm output [token] is sent to the MT with [mode]=2 to enable the specified command set. [mode]=3 is used to disable the command set. 
+The read command returns the status ([mode] 2 or 3) of each supported command set.
+Defined values
+[mode]:  
+1	request challenge token to enable access to specified command set
+2	enable access to specified command set ([token] required)
+3	disable access to specified command set
+[cmd_set], [cmd_set1], [cmd_set2]:
+0 	MT/TA code re-programming command set.
+other values below 128 are reserved by the present document
+[token]: string type; a variable length bit string represented with IRA characters 0 - 9 and A - F, each character representing a nibble; e.g. bit string '0110 1100 1001 1010' is represented by the IRA string '6C9A'. The length of the required bit string varies depending on the value of [cmd_set].
+[challenge]: same format as token
+</description>
+</spec>
+<spec>
+    <command>AT+CALM=</command>
+    <profile>Alert sound mode (Assign)</profile>
+    <description>This command is used to select the general alert sound mode of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[mode]:
+0	normal mode
+1	silent mode (all sounds from MT are prevented)
+2…	manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CALM?</command>
+    <profile>Alert sound mode (Query)</profile>
+    <description>This command is used to select the general alert sound mode of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[mode]:
+0	normal mode
+1	silent mode (all sounds from MT are prevented)
+2…	manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CALM=?</command>
+    <profile>Alert sound mode (Query all)</profile>
+    <description>This command is used to select the general alert sound mode of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[mode]:
+0	normal mode
+1	silent mode (all sounds from MT are prevented)
+2…	manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CRSL=</command>
+    <profile>Ringer sound level (Assign)</profile>
+    <description>This command is used to select the incoming call ringer sound level of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[level]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+</description>
+</spec>
+<spec>
+    <command>AT+CRSL?</command>
+    <profile>Ringer sound level (Query)</profile>
+    <description>This command is used to select the incoming call ringer sound level of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[level]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+</description>
+</spec>
+<spec>
+    <command>AT+CRSL=?</command>
+    <profile>Ringer sound level (Query all)</profile>
+    <description>This command is used to select the incoming call ringer sound level of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[level]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+</description>
+</spec>
+<spec>
+    <command>AT+CVIB=</command>
+    <profile>Vibrator mode (Assign)</profile>
+    <description>This command is used to enable and disable the vibrator alert feature of the MT. It is manufacturer specific how this interacts with +CALM command. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[mode]:
+0	disable
+1	enable
+...15	reserved by the present document
+16…	manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CVIB?</command>
+    <profile>Vibrator mode (Query)</profile>
+    <description>This command is used to enable and disable the vibrator alert feature of the MT. It is manufacturer specific how this interacts with +CALM command. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[mode]:
+0	disable
+1	enable
+...15	reserved by the present document
+16…	manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CVIB=?</command>
+    <profile>Vibrator mode (Query all)</profile>
+    <description>This command is used to enable and disable the vibrator alert feature of the MT. It is manufacturer specific how this interacts with +CALM command. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[mode]:
+0	disable
+1	enable
+...15	reserved by the present document
+16…	manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CLVL=</command>
+    <profile>Loudspeaker volume level (Assign)</profile>
+    <description>This command is used to select the volume of the internal loudspeaker of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[level]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+</description>
+</spec>
+<spec>
+    <command>AT+CLVL?</command>
+    <profile>Loudspeaker volume level (Query)</profile>
+    <description>This command is used to select the volume of the internal loudspeaker of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[level]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+</description>
+</spec>
+<spec>
+    <command>AT+CLVL=?</command>
+    <profile>Loudspeaker volume level (Query all)</profile>
+    <description>This command is used to select the volume of the internal loudspeaker of the MT. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[level]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+</description>
+</spec>
+<spec>
+    <command>AT+CMUT=</command>
+    <profile>Mute control (Assign)</profile>
+    <description>This command is used to enable and disable the uplink voice muting during a voice call. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[n]:
+0	mute off
+1	mute on
+</description>
+</spec>
+<spec>
+    <command>AT+CMUT?</command>
+    <profile>Mute control (Query)</profile>
+    <description>This command is used to enable and disable the uplink voice muting during a voice call. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[n]:
+0	mute off
+1	mute on
+</description>
+</spec>
+<spec>
+    <command>AT+CMUT=?</command>
+    <profile>Mute control (Query all)</profile>
+    <description>This command is used to enable and disable the uplink voice muting during a voice call. Refer subclause 9.2 for possible [err] values.
+Test command returns supported values as compound value.
+Defined values
+[n]:
+0	mute off
+1	mute on
+</description>
+</spec>
+<spec>
+    <command>AT+CACM=</command>
+    <profile>Accumulated call meter (Assign)</profile>
+    <description>Set command resets the Advice of Charge related accumulated call meter value in SIM card or in the active application in the UICC (GSM or USIM) file EFACM. ACM contains the total number of home units for both the current and preceding calls. SIM PIN2 is usually required to reset the value. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current value of ACM.
+Defined values
+[passwd]: string type; SIM PIN2
+[acm]: string type; accumulated call meter value similarly coded as [ccm] under +CAOC
+</description>
+</spec>
+<spec>
+    <command>AT+CACM?</command>
+    <profile>Accumulated call meter (Query)</profile>
+    <description>Set command resets the Advice of Charge related accumulated call meter value in SIM card or in the active application in the UICC (GSM or USIM) file EFACM. ACM contains the total number of home units for both the current and preceding calls. SIM PIN2 is usually required to reset the value. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current value of ACM.
+Defined values
+[passwd]: string type; SIM PIN2
+[acm]: string type; accumulated call meter value similarly coded as [ccm] under +CAOC
+</description>
+</spec>
+<spec>
+    <command>AT+CACM=?</command>
+    <profile>Accumulated call meter (Query all)</profile>
+    <description>Set command resets the Advice of Charge related accumulated call meter value in SIM card or in the active application in the UICC (GSM or USIM) file EFACM. ACM contains the total number of home units for both the current and preceding calls. SIM PIN2 is usually required to reset the value. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current value of ACM.
+Defined values
+[passwd]: string type; SIM PIN2
+[acm]: string type; accumulated call meter value similarly coded as [ccm] under +CAOC
+</description>
+</spec>
+<spec>
+    <command>AT+CAMM=</command>
+    <profile>Accumulated call meter maximum (Assign)</profile>
+    <description>Set command sets the Advice of Charge related accumulated call meter maximum value in SIM card or in the active application in the UICC (GSM or USIM) file EFACMmax. ACMmax contains the maximum number of home units allowed to be consumed by the subscriber. When ACM (refer +CACM) reaches ACMmax calls are prohibited (see also 3GPP TS 22.024 [26]). SIM PIN2 is usually required to set the value. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current value of ACMmax.
+Defined values
+[acmmax]: string type; accumulated call meter maximum value similarly coded as [ccm] under +CAOC; value zero disables ACMmax feature
+[passwd]: string type; SIM PIN2
+</description>
+</spec>
+<spec>
+    <command>AT+CAMM?</command>
+    <profile>Accumulated call meter maximum (Query)</profile>
+    <description>Set command sets the Advice of Charge related accumulated call meter maximum value in SIM card or in the active application in the UICC (GSM or USIM) file EFACMmax. ACMmax contains the maximum number of home units allowed to be consumed by the subscriber. When ACM (refer +CACM) reaches ACMmax calls are prohibited (see also 3GPP TS 22.024 [26]). SIM PIN2 is usually required to set the value. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current value of ACMmax.
+Defined values
+[acmmax]: string type; accumulated call meter maximum value similarly coded as [ccm] under +CAOC; value zero disables ACMmax feature
+[passwd]: string type; SIM PIN2
+</description>
+</spec>
+<spec>
+    <command>AT+CAMM=?</command>
+    <profile>Accumulated call meter maximum (Query all)</profile>
+    <description>Set command sets the Advice of Charge related accumulated call meter maximum value in SIM card or in the active application in the UICC (GSM or USIM) file EFACMmax. ACMmax contains the maximum number of home units allowed to be consumed by the subscriber. When ACM (refer +CACM) reaches ACMmax calls are prohibited (see also 3GPP TS 22.024 [26]). SIM PIN2 is usually required to set the value. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current value of ACMmax.
+Defined values
+[acmmax]: string type; accumulated call meter maximum value similarly coded as [ccm] under +CAOC; value zero disables ACMmax feature
+[passwd]: string type; SIM PIN2
+</description>
+</spec>
+<spec>
+    <command>AT+CPUC=</command>
+    <profile>Price per unit and currency table (Assign)</profile>
+    <description>Set command sets the parameters of Advice of Charge related price per unit and currency table in SIM card or in the active application in the UICC (GSM or USIM) file EFPUCT. PUCT information can be used to convert the home units (as used in +CAOC, +CACM and +CAMM) into currency units. SIM PIN2 is usually required to set the parameters. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current parameters of PUCT.
+Defined values
+[currency]: string type; three-character currency code (e.g. 'GBP', 'DEM'); character set as specified by command Select TE Character Set +CSCS
+[ppu]: string type; price per unit; dot is used as a decimal separator (e.g. '2.66')
+[passwd]: string type; SIM PIN2
+</description>
+</spec>
+<spec>
+    <command>AT+CPUC?</command>
+    <profile>Price per unit and currency table (Query)</profile>
+    <description>Set command sets the parameters of Advice of Charge related price per unit and currency table in SIM card or in the active application in the UICC (GSM or USIM) file EFPUCT. PUCT information can be used to convert the home units (as used in +CAOC, +CACM and +CAMM) into currency units. SIM PIN2 is usually required to set the parameters. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current parameters of PUCT.
+Defined values
+[currency]: string type; three-character currency code (e.g. 'GBP', 'DEM'); character set as specified by command Select TE Character Set +CSCS
+[ppu]: string type; price per unit; dot is used as a decimal separator (e.g. '2.66')
+[passwd]: string type; SIM PIN2
+</description>
+</spec>
+<spec>
+    <command>AT+CPUC=?</command>
+    <profile>Price per unit and currency table (Query all)</profile>
+    <description>Set command sets the parameters of Advice of Charge related price per unit and currency table in SIM card or in the active application in the UICC (GSM or USIM) file EFPUCT. PUCT information can be used to convert the home units (as used in +CAOC, +CACM and +CAMM) into currency units. SIM PIN2 is usually required to set the parameters. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current parameters of PUCT.
+Defined values
+[currency]: string type; three-character currency code (e.g. 'GBP', 'DEM'); character set as specified by command Select TE Character Set +CSCS
+[ppu]: string type; price per unit; dot is used as a decimal separator (e.g. '2.66')
+[passwd]: string type; SIM PIN2
+</description>
+</spec>
+<spec>
+    <command>AT+CCWE=</command>
+    <profile>Call Meter maximum event (Assign)</profile>
+    <description>Shortly before the ACM (Accumulated Call Meter) maximum value is reached, an unsolicited result code +CCWV will be sent, if enabled by this command. The warning is issued approximately when 30 seconds call time remains. It is also issued when starting a call if less than 30 s call time remains. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current setting.
+Test command returns supported settings.
+Defined values
+[mode]:
+0	Disable the call meter warning event
+1	Enable the call meter warning event
+</description>
+</spec>
+<spec>
+    <command>AT+CCWE?</command>
+    <profile>Call Meter maximum event (Query)</profile>
+    <description>Shortly before the ACM (Accumulated Call Meter) maximum value is reached, an unsolicited result code +CCWV will be sent, if enabled by this command. The warning is issued approximately when 30 seconds call time remains. It is also issued when starting a call if less than 30 s call time remains. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current setting.
+Test command returns supported settings.
+Defined values
+[mode]:
+0	Disable the call meter warning event
+1	Enable the call meter warning event
+</description>
+</spec>
+<spec>
+    <command>AT+CCWE=?</command>
+    <profile>Call Meter maximum event (Query all)</profile>
+    <description>Shortly before the ACM (Accumulated Call Meter) maximum value is reached, an unsolicited result code +CCWV will be sent, if enabled by this command. The warning is issued approximately when 30 seconds call time remains. It is also issued when starting a call if less than 30 s call time remains. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current setting.
+Test command returns supported settings.
+Defined values
+[mode]:
+0	Disable the call meter warning event
+1	Enable the call meter warning event
+</description>
+</spec>
+<spec>
+    <command>AT+CPWC=</command>
+    <profile>Power class (Assign)</profile>
+    <description>This command is used to set the preferred MT power class for each GSM frequency band supported. The interaction of this setting with the selected bearer service (+CBST and HSCSD commands) is manufacturer specific (for example, selecting a multislot operation might reduce the power class automatically). If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the currently selected output power class and default output power class for each supported frequency band (as defined by MT manufacturer). Parameter [band1] and its associated power class parameters refer to the currently used frequency band. For example, +CPWC: 2,1,1,5,4,0 in case of a dual-band MT currently using band GSM1800, for which the power class is currently set to 2, the default being class 1, and for which the currently set power class value for GSM900 is class 5 the default being class 4.
+Test command returns supported bands and their power classes. For example, 
++CPWC: (0,(0,4,5)),(1,(0-2)) in case of a dual-band handheld MT.
+Defined values
+[class], [curr_classn]s, [def_classn]s:
+0	default (not applicable to [curr_class]s or [def_classn]s)
+1…	MT output power class as in GSM 45.005 [38]
+[band], [bandn]s:
+0	GSM900
+1	GSM1800
+2	reserved for GSM1900
+3	GSM 400
+</description>
+</spec>
+<spec>
+    <command>AT+CPWC?</command>
+    <profile>Power class (Query)</profile>
+    <description>This command is used to set the preferred MT power class for each GSM frequency band supported. The interaction of this setting with the selected bearer service (+CBST and HSCSD commands) is manufacturer specific (for example, selecting a multislot operation might reduce the power class automatically). If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the currently selected output power class and default output power class for each supported frequency band (as defined by MT manufacturer). Parameter [band1] and its associated power class parameters refer to the currently used frequency band. For example, +CPWC: 2,1,1,5,4,0 in case of a dual-band MT currently using band GSM1800, for which the power class is currently set to 2, the default being class 1, and for which the currently set power class value for GSM900 is class 5 the default being class 4.
+Test command returns supported bands and their power classes. For example, 
++CPWC: (0,(0,4,5)),(1,(0-2)) in case of a dual-band handheld MT.
+Defined values
+[class], [curr_classn]s, [def_classn]s:
+0	default (not applicable to [curr_class]s or [def_classn]s)
+1…	MT output power class as in GSM 45.005 [38]
+[band], [bandn]s:
+0	GSM900
+1	GSM1800
+2	reserved for GSM1900
+3	GSM 400
+</description>
+</spec>
+<spec>
+    <command>AT+CPWC=?</command>
+    <profile>Power class (Query all)</profile>
+    <description>This command is used to set the preferred MT power class for each GSM frequency band supported. The interaction of this setting with the selected bearer service (+CBST and HSCSD commands) is manufacturer specific (for example, selecting a multislot operation might reduce the power class automatically). If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the currently selected output power class and default output power class for each supported frequency band (as defined by MT manufacturer). Parameter [band1] and its associated power class parameters refer to the currently used frequency band. For example, +CPWC: 2,1,1,5,4,0 in case of a dual-band MT currently using band GSM1800, for which the power class is currently set to 2, the default being class 1, and for which the currently set power class value for GSM900 is class 5 the default being class 4.
+Test command returns supported bands and their power classes. For example, 
++CPWC: (0,(0,4,5)),(1,(0-2)) in case of a dual-band handheld MT.
+Defined values
+[class], [curr_classn]s, [def_classn]s:
+0	default (not applicable to [curr_class]s or [def_classn]s)
+1…	MT output power class as in GSM 45.005 [38]
+[band], [bandn]s:
+0	GSM900
+1	GSM1800
+2	reserved for GSM1900
+3	GSM 400
+</description>
+</spec>
+<spec>
+    <command>AT+CLAN=</command>
+    <profile>Set Language (Assign)</profile>
+    <description>This command sets the language in the MT. The set-command must confirm the selected language with the MMI-module in the MT. If setting fails, a MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+The [code]-parameter is a two-letter abbreviation of the language. The language codes, as defined in ISO 639, consists of two characters, e.g. 'sv', 'en' etc.
+The complete set of language codes to be used are manufacturer specific and should all be possible to use with the command. Some examples are described under [code]. For a complete list see ISO 639.
+The read command gives the current language as output. If the language has been set to 'AUTO', the read command returns the current language set from the SIM-card /UICC. Hence, the 'AUTO'-code is never returned by the read-command.
+Test command returns supported [code]s.
+Defined values
+[code]: (not all language codes are present in this list)
+'AUTO'	Read language from SIM-card /UICC. 'Auto' is not returned by the read-command. 
+'sw' 		Swedish
+'fi' 		Finnish
+'da' 		Danish
+'no' 		Norwegian
+'de' 		German
+'fr' 		French
+'es' 		Spanish
+'it' 		Italian
+'en' 		English
+</description>
+</spec>
+<spec>
+    <command>AT+CLAN?</command>
+    <profile>Set Language (Query)</profile>
+    <description>This command sets the language in the MT. The set-command must confirm the selected language with the MMI-module in the MT. If setting fails, a MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+The [code]-parameter is a two-letter abbreviation of the language. The language codes, as defined in ISO 639, consists of two characters, e.g. 'sv', 'en' etc.
+The complete set of language codes to be used are manufacturer specific and should all be possible to use with the command. Some examples are described under [code]. For a complete list see ISO 639.
+The read command gives the current language as output. If the language has been set to 'AUTO', the read command returns the current language set from the SIM-card /UICC. Hence, the 'AUTO'-code is never returned by the read-command.
+Test command returns supported [code]s.
+Defined values
+[code]: (not all language codes are present in this list)
+'AUTO'	Read language from SIM-card /UICC. 'Auto' is not returned by the read-command. 
+'sw' 		Swedish
+'fi' 		Finnish
+'da' 		Danish
+'no' 		Norwegian
+'de' 		German
+'fr' 		French
+'es' 		Spanish
+'it' 		Italian
+'en' 		English
+</description>
+</spec>
+<spec>
+    <command>AT+CLAN=?</command>
+    <profile>Set Language (Query all)</profile>
+    <description>This command sets the language in the MT. The set-command must confirm the selected language with the MMI-module in the MT. If setting fails, a MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+The [code]-parameter is a two-letter abbreviation of the language. The language codes, as defined in ISO 639, consists of two characters, e.g. 'sv', 'en' etc.
+The complete set of language codes to be used are manufacturer specific and should all be possible to use with the command. Some examples are described under [code]. For a complete list see ISO 639.
+The read command gives the current language as output. If the language has been set to 'AUTO', the read command returns the current language set from the SIM-card /UICC. Hence, the 'AUTO'-code is never returned by the read-command.
+Test command returns supported [code]s.
+Defined values
+[code]: (not all language codes are present in this list)
+'AUTO'	Read language from SIM-card /UICC. 'Auto' is not returned by the read-command. 
+'sw' 		Swedish
+'fi' 		Finnish
+'da' 		Danish
+'no' 		Norwegian
+'de' 		German
+'fr' 		French
+'es' 		Spanish
+'it' 		Italian
+'en' 		English
+</description>
+</spec>
+<spec>
+    <command>AT+CLAE=</command>
+    <profile>Language Event (Assign)</profile>
+    <description>This command is used to enable/disable unsolicited result code +CLAV: [code]. If [mode]=1, +CLAV: [code ] is sent from the MT when the language in the MT is changed. If setting fails, a MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current status for [mode].
+Test command returns supported [mode]s.
+Defined values
+[mode]:
+0	Disable unsolicited result code +CLAE
+1	Enable unsolicited result code +CLAE
+[code]: For description see +CLAN.
+</description>
+</spec>
+<spec>
+    <command>AT+CLAE?</command>
+    <profile>Language Event (Query)</profile>
+    <description>This command is used to enable/disable unsolicited result code +CLAV: [code]. If [mode]=1, +CLAV: [code ] is sent from the MT when the language in the MT is changed. If setting fails, a MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current status for [mode].
+Test command returns supported [mode]s.
+Defined values
+[mode]:
+0	Disable unsolicited result code +CLAE
+1	Enable unsolicited result code +CLAE
+[code]: For description see +CLAN.
+</description>
+</spec>
+<spec>
+    <command>AT+CLAE=?</command>
+    <profile>Language Event (Query all)</profile>
+    <description>This command is used to enable/disable unsolicited result code +CLAV: [code]. If [mode]=1, +CLAV: [code ] is sent from the MT when the language in the MT is changed. If setting fails, a MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current status for [mode].
+Test command returns supported [mode]s.
+Defined values
+[mode]:
+0	Disable unsolicited result code +CLAE
+1	Enable unsolicited result code +CLAE
+[code]: For description see +CLAN.
+</description>
+</spec>
+<spec>
+    <command>AT+CSGT=</command>
+    <profile>Set Greeting Text (Assign)</profile>
+    <description>This command sets and activates the greeting text in the MT. The greeting text is shown in the MT display when the MT is turned on. The command can also be used to deactivate a text. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+The read command queries the current [text] and the status of the [mode] parameter
+Test command returns supported [mode]s and the maximum number of characters in [text]. For example, 
++CSGT: (0-1),20
+Defined values
+[text]: string type; A free text that shall be displayed. The text can not include [CR]
+[mode]:
+0	Turn off greeting text. 
+1	Turn on greeting text
+</description>
+</spec>
+<spec>
+    <command>AT+CSGT?</command>
+    <profile>Set Greeting Text (Query)</profile>
+    <description>This command sets and activates the greeting text in the MT. The greeting text is shown in the MT display when the MT is turned on. The command can also be used to deactivate a text. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+The read command queries the current [text] and the status of the [mode] parameter
+Test command returns supported [mode]s and the maximum number of characters in [text]. For example, 
++CSGT: (0-1),20
+Defined values
+[text]: string type; A free text that shall be displayed. The text can not include [CR]
+[mode]:
+0	Turn off greeting text. 
+1	Turn on greeting text
+</description>
+</spec>
+<spec>
+    <command>AT+CSGT=?</command>
+    <profile>Set Greeting Text (Query all)</profile>
+    <description>This command sets and activates the greeting text in the MT. The greeting text is shown in the MT display when the MT is turned on. The command can also be used to deactivate a text. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+The read command queries the current [text] and the status of the [mode] parameter
+Test command returns supported [mode]s and the maximum number of characters in [text]. For example, 
++CSGT: (0-1),20
+Defined values
+[text]: string type; A free text that shall be displayed. The text can not include [CR]
+[mode]:
+0	Turn off greeting text. 
+1	Turn on greeting text
+</description>
+</spec>
+<spec>
+    <command>AT+CSVM=</command>
+    <profile>Set Voice Mail Number (Assign)</profile>
+    <description>The number to the voice mail server is set with this command. The parameters [number] and [type] can be left out if the parameter [mode] is set to 0. If setting fails, an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the currently selected voice mail number and the status (i.e. enabled/disabled).
+Test command returns supported [mode]s and [type]s.
+Defined values
+[mode]:
+0	Disable the voice mail number. 
+1	Enable the voice mail number.
+[number]: string type; Character string [0..9,+]
+[type]: integer type; Type of address octet. (refer TS 24.008 subclause 10.5.4.7)
+129 		ISDN / telephony numbering plan, national / international unknown
+145 		ISDN / telephony numbering plan, international number
+161 		ISDN / telephony numbering plan, national number
+128 - 255 	Other values refer TS 24.008 section 10.5.4.7
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+</description>
+</spec>
+<spec>
+    <command>AT+CSVM?</command>
+    <profile>Set Voice Mail Number (Query)</profile>
+    <description>The number to the voice mail server is set with this command. The parameters [number] and [type] can be left out if the parameter [mode] is set to 0. If setting fails, an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the currently selected voice mail number and the status (i.e. enabled/disabled).
+Test command returns supported [mode]s and [type]s.
+Defined values
+[mode]:
+0	Disable the voice mail number. 
+1	Enable the voice mail number.
+[number]: string type; Character string [0..9,+]
+[type]: integer type; Type of address octet. (refer TS 24.008 subclause 10.5.4.7)
+129 		ISDN / telephony numbering plan, national / international unknown
+145 		ISDN / telephony numbering plan, international number
+161 		ISDN / telephony numbering plan, national number
+128 - 255 	Other values refer TS 24.008 section 10.5.4.7
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+</description>
+</spec>
+<spec>
+    <command>AT+CSVM=?</command>
+    <profile>Set Voice Mail Number (Query all)</profile>
+    <description>The number to the voice mail server is set with this command. The parameters [number] and [type] can be left out if the parameter [mode] is set to 0. If setting fails, an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the currently selected voice mail number and the status (i.e. enabled/disabled).
+Test command returns supported [mode]s and [type]s.
+Defined values
+[mode]:
+0	Disable the voice mail number. 
+1	Enable the voice mail number.
+[number]: string type; Character string [0..9,+]
+[type]: integer type; Type of address octet. (refer TS 24.008 subclause 10.5.4.7)
+129 		ISDN / telephony numbering plan, national / international unknown
+145 		ISDN / telephony numbering plan, international number
+161 		ISDN / telephony numbering plan, national number
+128 - 255 	Other values refer TS 24.008 section 10.5.4.7
+[type]: type of address octet in integer format (refer TS 24.008 [8] subclause 10.5.4.7); default 145 when dialling string includes international access code character '+', otherwise 129
+</description>
+</spec>
+<spec>
+    <command>AT+CRMC=</command>
+    <profile>Ring Melody Control (Assign)</profile>
+    <description>Write command causes the MT to set a specific ring melody and volume for the selected call type and profile. The default values for the optional parameters are defined by the manufacturer.
+Read command queries the settings for the ring melody. If call types and profiles are available the corresponding ring melodies are listed. Starting with call type1 and profile1 the ring melody settings for each available profile and call type is issued.
+Test command returns the list of available ring melodies, volumes, call types and profiles.
+Defined values:
+[index]: integer type; manufacturer specific number to identify a certain ring melody
+[volume]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+[call typex]: integer type; manufacturer specific number for a call type
+[profilex]: integer type; manufacturer specific number for a profile
+</description>
+</spec>
+<spec>
+    <command>AT+CRMC?</command>
+    <profile>Ring Melody Control (Query)</profile>
+    <description>Write command causes the MT to set a specific ring melody and volume for the selected call type and profile. The default values for the optional parameters are defined by the manufacturer.
+Read command queries the settings for the ring melody. If call types and profiles are available the corresponding ring melodies are listed. Starting with call type1 and profile1 the ring melody settings for each available profile and call type is issued.
+Test command returns the list of available ring melodies, volumes, call types and profiles.
+Defined values:
+[index]: integer type; manufacturer specific number to identify a certain ring melody
+[volume]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+[call typex]: integer type; manufacturer specific number for a call type
+[profilex]: integer type; manufacturer specific number for a profile
+</description>
+</spec>
+<spec>
+    <command>AT+CRMC=?</command>
+    <profile>Ring Melody Control (Query all)</profile>
+    <description>Write command causes the MT to set a specific ring melody and volume for the selected call type and profile. The default values for the optional parameters are defined by the manufacturer.
+Read command queries the settings for the ring melody. If call types and profiles are available the corresponding ring melodies are listed. Starting with call type1 and profile1 the ring melody settings for each available profile and call type is issued.
+Test command returns the list of available ring melodies, volumes, call types and profiles.
+Defined values:
+[index]: integer type; manufacturer specific number to identify a certain ring melody
+[volume]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+[call typex]: integer type; manufacturer specific number for a call type
+[profilex]: integer type; manufacturer specific number for a profile
+</description>
+</spec>
+<spec>
+    <command>AT+CRMP=</command>
+    <profile>Ring Melody Playback (Assign)</profile>
+    <description>Execution command causes the MT to playback a specific ring type. The default values for the optional parameters are the current selected in the MT. 
+Test command returns the available ring melodies.
+Defined values:
+[call type]: integer type; manufacturer specific
+[volume]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+[type]:
+0	Manufacturer defined
+1	User defined
+[index]: integer type;
+</description>
+</spec>
+<spec>
+    <command>AT+CRMP=?</command>
+    <profile>Ring Melody Playback (Query all)</profile>
+    <description>Execution command causes the MT to playback a specific ring type. The default values for the optional parameters are the current selected in the MT. 
+Test command returns the available ring melodies.
+Defined values:
+[call type]: integer type; manufacturer specific
+[volume]: integer type value with manufacturer specific range (smallest value represents the lowest sound level)
+[type]:
+0	Manufacturer defined
+1	User defined
+[index]: integer type;
+</description>
+</spec>
+<spec>
+    <command>AT+CMAR=</command>
+    <profile>Master Reset (Assign)</profile>
+    <description>This command requests the MT to reset user data. The user data in the phone will be reset to default values. If setting fails, a MT error, +CME ERROR: [err], is returned. Refer subclause 9.2 for [err] values.
+If the MT is locked and this command is used, then the MT will be unlocked after the master reset.
+Test command returns OK
+Defined values
+[phone lock code ] string type; Security code (Phone Lock code) must be verified before performing the master reset.
+</description>
+</spec>
+<spec>
+    <command>AT+CMAR=?</command>
+    <profile>Master Reset (Query all)</profile>
+    <description>This command requests the MT to reset user data. The user data in the phone will be reset to default values. If setting fails, a MT error, +CME ERROR: [err], is returned. Refer subclause 9.2 for [err] values.
+If the MT is locked and this command is used, then the MT will be unlocked after the master reset.
+Test command returns OK
+Defined values
+[phone lock code ] string type; Security code (Phone Lock code) must be verified before performing the master reset.
+</description>
+</spec>
+<spec>
+    <command>AT+CLAC</command>
+    <profile>List all available AT commands </profile>
+    <description>Execution command causes the MT to return one or more lines of AT Commands.
+Note: This command only returns the AT commands that are available for the user.
+Defined values
+[AT Command ]:
+Defines the AT command including the prefix AT. Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CLAC=?</command>
+    <profile>List all available AT commands (Query all)</profile>
+    <description>Execution command causes the MT to return one or more lines of AT Commands.
+Note: This command only returns the AT commands that are available for the user.
+Defined values
+[AT Command ]:
+Defines the AT command including the prefix AT. Text shall not contain the sequence 0[CR] or OK[CR]
+</description>
+</spec>
+<spec>
+    <command>AT+CALD=</command>
+    <profile>Delete alarm (Assign)</profile>
+    <description>Action command deletes an alarm in the MT. If the command fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns supported array index values.
+Defined values
+[n]: integer type value indicating the index of the alarm; default is manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CALD=?</command>
+    <profile>Delete alarm (Query all)</profile>
+    <description>Action command deletes an alarm in the MT. If the command fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns supported array index values.
+Defined values
+[n]: integer type value indicating the index of the alarm; default is manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CAPD=</command>
+    <profile>Postpone or dismiss an alarm (Assign)</profile>
+    <description>Set command postpones or dismisses a currently active alarm. If the command fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns supported [sec]-parameter values.
+Defined values
+[sec]: integer type value indicating the number of seconds to postpone the alarm. If [sec] is set to 0 (default), the alarm is dismissed.
+</description>
+</spec>
+<spec>
+    <command>AT+CAPD=?</command>
+    <profile>Postpone or dismiss an alarm (Query all)</profile>
+    <description>Set command postpones or dismisses a currently active alarm. If the command fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Test command returns supported [sec]-parameter values.
+Defined values
+[sec]: integer type value indicating the number of seconds to postpone the alarm. If [sec] is set to 0 (default), the alarm is dismissed.
+</description>
+</spec>
+<spec>
+    <command>AT+CTZU=</command>
+    <profile>Automatic Time Zone Update (Assign)</profile>
+    <description>Set command enables and disables automatic time zone update via NITZ. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current settings in the MT.
+Test command returns supported on- and off-values.
+Defined values
+[onoff]: integer type value indicating:
+	0 – Disable automatic time zone update via NITZ (default). 
+	1 – Enable automatic time zone update via NITZ.
+</description>
+</spec>
+<spec>
+    <command>AT+CTZU?</command>
+    <profile>Automatic Time Zone Update (Query)</profile>
+    <description>Set command enables and disables automatic time zone update via NITZ. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current settings in the MT.
+Test command returns supported on- and off-values.
+Defined values
+[onoff]: integer type value indicating:
+	0 – Disable automatic time zone update via NITZ (default). 
+	1 – Enable automatic time zone update via NITZ.
+</description>
+</spec>
+<spec>
+    <command>AT+CTZU=?</command>
+    <profile>Automatic Time Zone Update (Query all)</profile>
+    <description>Set command enables and disables automatic time zone update via NITZ. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current settings in the MT.
+Test command returns supported on- and off-values.
+Defined values
+[onoff]: integer type value indicating:
+	0 – Disable automatic time zone update via NITZ (default). 
+	1 – Enable automatic time zone update via NITZ.
+</description>
+</spec>
+<spec>
+    <command>AT+CTZR=</command>
+    <profile>Time Zone Reporting (Assign)</profile>
+    <description>This set command enables and disables the time zone change event reporting. If the reporting is enabled the MT returns the unsolicited result code +CTZV: [tz] whenever the time zone is changed. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current reporting settings in the MT.
+Test command returns supported [onoff]-values.
+	NOTE: The Time Zone reporting is not affected by the Automatic Time Zone setting command, +CTZU.
+Defined values
+[onoff]: integer type value indicating:
+	0 – disable time zone change event reporting (default).
+	1 – Enable time zone change event reporting.
+</description>
+</spec>
+<spec>
+    <command>AT+CTZR?</command>
+    <profile>Time Zone Reporting (Query)</profile>
+    <description>This set command enables and disables the time zone change event reporting. If the reporting is enabled the MT returns the unsolicited result code +CTZV: [tz] whenever the time zone is changed. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current reporting settings in the MT.
+Test command returns supported [onoff]-values.
+	NOTE: The Time Zone reporting is not affected by the Automatic Time Zone setting command, +CTZU.
+Defined values
+[onoff]: integer type value indicating:
+	0 – disable time zone change event reporting (default).
+	1 – Enable time zone change event reporting.
+</description>
+</spec>
+<spec>
+    <command>AT+CTZR=?</command>
+    <profile>Time Zone Reporting (Query all)</profile>
+    <description>This set command enables and disables the time zone change event reporting. If the reporting is enabled the MT returns the unsolicited result code +CTZV: [tz] whenever the time zone is changed. If setting fails in an MT error, +CME ERROR: [err] is returned. Refer subclause 9.2 for [err] values.
+Read command returns the current reporting settings in the MT.
+Test command returns supported [onoff]-values.
+	NOTE: The Time Zone reporting is not affected by the Automatic Time Zone setting command, +CTZU.
+Defined values
+[onoff]: integer type value indicating:
+	0 – disable time zone change event reporting (default).
+	1 – Enable time zone change event reporting.
+</description>
+</spec>
+<spec>
+    <command>AT+CPROT=</command>
+    <profile>Enter protocol mode(Assign)</profile>
+    <description>Set command informs TA that TE wants to establish a peer-to-peer protocol [proto] or upper layer connection (indicating by the [lsap]s setting) with the MT on the link from which the command was received.
+This command can be used in case the link between TE and MT does not provide itself such a mechanism.
+If MT has succeeded in establishing a logical link between application protocols and external interface, it will send CONNECT message to the TE. Otherwise, the NO CARRIER response will be returned.
+If the CONNECT response is received, TE can start sending [proto] or upper layer frames.
+The connection shall always return for [proto] mode when the protocol session is ended. When the MT receives a disconnect request from its peer entity, it will process it and send OK response to the TE indicating its capability for receiving new AT commands. Since [proto] or upper layers can be accessed in other ways, TA must have pre-knowledge of the fact that connection is initiated with AT+CPROT command. This means that switch to [proto] mode must include some sort of notification to the protocol entity.
+This command can be aborted by sending a [proto] or upper layer disconnection frame. In that case, MT will return in command mode by sending the OK response.
+Refer subclause 9.2 for possible [err] values.
+Test command returns values supported as a compound value.
+Defined values
+[proto]
+0		OBEX (refer.[44]) 
+…15	reserved by the present document
+16...	manufacturer specific
+[version]:	version number of [proto]: string type
+[lsap1]: defines a level of service or application protocol on the top of [proto] layer. It may refer to services or protocols defined in other standards development organizations (SDOs).
+1	IrMC level 1 (Minimum Level) Only .(refer [43] subclause 2.9.4)
+2	IrMC level 1 and 2 (Minimum and Access Levels) Only. .(refer [43] subclause 2.9.4)
+4IrMC level 1, 2 and 3 (Minimum, Access, Index Levels) Only- implies static index support. .(refer [43] subclause 2.9.4)
+8IrMC level 1, 2 and 4 (Minimum, Access and Sync Levels) Only-implies unique index support. .(refer [43] subclause 2.9.4)
+10	IrMC level 1, 2, 3 and 4 (Minimum, Access, Index and Sync Levels)-implies support of static and unique index. .(refer [43] subclause 2.9.4)
+…15	reserved by the present document
+16...	manufacturer specific
+[lsap2]...[lsapN]
+In case [lsapN],[lsapN+1] received in the +CPROT command identifies protocol layers, the protocol identified by N+1 shall be on the top of the protocol identified by N on a framework point of view.
+0…15	reserved by the present document
+16...	manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CPROT=?</command>
+    <profile>Enter protocol mode(Query all)</profile>
+    <description>Set command informs TA that TE wants to establish a peer-to-peer protocol [proto] or upper layer connection (indicating by the [lsap]s setting) with the MT on the link from which the command was received.
+This command can be used in case the link between TE and MT does not provide itself such a mechanism.
+If MT has succeeded in establishing a logical link between application protocols and external interface, it will send CONNECT message to the TE. Otherwise, the NO CARRIER response will be returned.
+If the CONNECT response is received, TE can start sending [proto] or upper layer frames.
+The connection shall always return for [proto] mode when the protocol session is ended. When the MT receives a disconnect request from its peer entity, it will process it and send OK response to the TE indicating its capability for receiving new AT commands. Since [proto] or upper layers can be accessed in other ways, TA must have pre-knowledge of the fact that connection is initiated with AT+CPROT command. This means that switch to [proto] mode must include some sort of notification to the protocol entity.
+This command can be aborted by sending a [proto] or upper layer disconnection frame. In that case, MT will return in command mode by sending the OK response.
+Refer subclause 9.2 for possible [err] values.
+Test command returns values supported as a compound value.
+Defined values
+[proto]
+0		OBEX (refer.[44]) 
+…15	reserved by the present document
+16...	manufacturer specific
+[version]:	version number of [proto]: string type
+[lsap1]: defines a level of service or application protocol on the top of [proto] layer. It may refer to services or protocols defined in other standards development organizations (SDOs).
+1	IrMC level 1 (Minimum Level) Only .(refer [43] subclause 2.9.4)
+2	IrMC level 1 and 2 (Minimum and Access Levels) Only. .(refer [43] subclause 2.9.4)
+4IrMC level 1, 2 and 3 (Minimum, Access, Index Levels) Only- implies static index support. .(refer [43] subclause 2.9.4)
+8IrMC level 1, 2 and 4 (Minimum, Access and Sync Levels) Only-implies unique index support. .(refer [43] subclause 2.9.4)
+10	IrMC level 1, 2, 3 and 4 (Minimum, Access, Index and Sync Levels)-implies support of static and unique index. .(refer [43] subclause 2.9.4)
+…15	reserved by the present document
+16...	manufacturer specific
+[lsap2]...[lsapN]
+In case [lsapN],[lsapN+1] received in the +CPROT command identifies protocol layers, the protocol identified by N+1 shall be on the top of the protocol identified by N on a framework point of view.
+0…15	reserved by the present document
+16...	manufacturer specific
+</description>
+</spec>
+<spec>
+    <command>AT+CGLA=</command>
+    <profile>Generic UICC Logical Channel access (Assign)</profile>
+    <description>Set command transmits to the MT the [command] it then shall send as it is to the UICC. In the same manner the UICC [response] shall be sent back by the MT to the TA as it is. Refer subclause 9.2 for [err] values.
+This command allows a direct control of the UICC by a distant application on the TE. The TE shall then take care of processing UICC information within the frame specified by GSM/UMTS.
+Although Generic UICC Logical Channel Access command +CGLA allows TE to take control over the UICC‑MT interface, there are some functions of the UICC-MT interface that logically do not need to be accessed from outside the TA/MT. Moreover, for security reason the GSM network authentication should not be handled outside the TA/MT. Therefore it shall not be allowed to execute a Run GSM Algorithm command or an Authenticate command in GSM context from the TE using +CGLA at all time whether the +CGLA is locked or unlocked. This shall not forbid the TE to send Authenticate commands in other security contexts (e.g. EAP security context).
+For example, the TA/MT shall forbid the transfer of the Authenticate command to a USIM application when parameters P2 = 0 (GSM security context). See TS 31.102 [59] for USIM authenticate command definition.
+NOTE:	Compared to Restricted UICC Access command +CRLA, the definition of +CGLA allows TE to take more control over the UICC‑MT interface. The locking and unlocking of the interface may be done by a special [command] value or automatically by TA/MT (by interpreting [command] parameter). In case that TE application does not use the unlock command (or does not send a [command] causing automatic unlock) in a certain timeout value, MT may release the locking.
+Defined values
+[sessionid]: integer type; this is the identifier of the session to be used in order to send the APDU commands to the UICC. It is manadatory in order to send commands to the UICC when targeting applications on the smart card using a logical channel other than the default channel (channel '0').
+[length] : integer type; length of the characters that are sent to TE in [command] or [response] (two times the actual length of the command or response)
+[command] : command passed on by the MT to the UICC in the format as described in 3GPP TS 31.101 [65] (hexadecimal character format; refer +CSCS)
+[response] : response to the command passed on by the UICC to the MT in the format as described in 3GPP TS 31.101 [65] (hexadecimal character format; refer +CSCS)
+</description>
+</spec>
+<spec>
+    <command>AT+CGLA=?</command>
+    <profile>Generic UICC Logical Channel access (Query all)</profile>
+    <description>Set command transmits to the MT the [command] it then shall send as it is to the UICC. In the same manner the UICC [response] shall be sent back by the MT to the TA as it is. Refer subclause 9.2 for [err] values.
+This command allows a direct control of the UICC by a distant application on the TE. The TE shall then take care of processing UICC information within the frame specified by GSM/UMTS.
+Although Generic UICC Logical Channel Access command +CGLA allows TE to take control over the UICC‑MT interface, there are some functions of the UICC-MT interface that logically do not need to be accessed from outside the TA/MT. Moreover, for security reason the GSM network authentication should not be handled outside the TA/MT. Therefore it shall not be allowed to execute a Run GSM Algorithm command or an Authenticate command in GSM context from the TE using +CGLA at all time whether the +CGLA is locked or unlocked. This shall not forbid the TE to send Authenticate commands in other security contexts (e.g. EAP security context).
+For example, the TA/MT shall forbid the transfer of the Authenticate command to a USIM application when parameters P2 = 0 (GSM security context). See TS 31.102 [59] for USIM authenticate command definition.
+NOTE:	Compared to Restricted UICC Access command +CRLA, the definition of +CGLA allows TE to take more control over the UICC‑MT interface. The locking and unlocking of the interface may be done by a special [command] value or automatically by TA/MT (by interpreting [command] parameter). In case that TE application does not use the unlock command (or does not send a [command] causing automatic unlock) in a certain timeout value, MT may release the locking.
+Defined values
+[sessionid]: integer type; this is the identifier of the session to be used in order to send the APDU commands to the UICC. It is manadatory in order to send commands to the UICC when targeting applications on the smart card using a logical channel other than the default channel (channel '0').
+[length] : integer type; length of the characters that are sent to TE in [command] or [response] (two times the actual length of the command or response)
+[command] : command passed on by the MT to the UICC in the format as described in 3GPP TS 31.101 [65] (hexadecimal character format; refer +CSCS)
+[response] : response to the command passed on by the UICC to the MT in the format as described in 3GPP TS 31.101 [65] (hexadecimal character format; refer +CSCS)
+</description>
+</spec>
+<spec>
+    <command>AT+CRLA=</command>
+    <profile>Restricted UICC Logical Channel access (Assign)</profile>
+    <description>By using this command instead of Generic UICC Access +CGLA TE application has easier but more limited access to the UICC database. Set command transmits to the MT the UICC [command] and its required parameters. MT handles internally all UICC‑MT interface locking and file selection routines. As response to the command, MT sends the actual UICC information parameters and response data. MT error result code +CME ERROR may be returned when the command cannot be passed to the UICC, but failure in the execution of the command in the UICC is reported in [sw1] and [sw2] parameters. Refer to subclause 9.2 for [err] values.
+Coordination of command requests to UICC and the ones issued by GSM/UMTS application inside the MT is implementation dependent. However the TE should be aware of the precedence of the GSM/UMTS application commands to the TE commands.
+Defined values
+[sessionid]: integer type; this is the identifier of the session to be used in order to send the APDU commands to the UICC. It is mandatory in order to send commands to the UICC when targeting applications on the smart card using a logical channel other than the default channel (channel '0').
+[command] (command passed on by the MT to the UICC; refer  3GPP TS 31.101 [65]):
+176	READ BINARY
+178	READ RECORD
+192	GET RESPONSE
+214	UPDATE BINARY
+220	UPDATE RECORD
+242	STATUS
+203	RETRIEVE DATA
+219	SET DATA
+all other values are reserved
+
+NOTE 1:	The MT internally executes all commands necessary for selecting the desired file, before performing the actual command.[fileid]: integer type; this is the identifier of a elementary datafile on UICC. Mandatory for every command except STATUS.
+NOTE 2:	The range of valid file identifiers depends on the actual UICC and is defined in  3GPP TS 31.101 [65]. Optional files may not be present at all.[P1], [P2], [P3]: integer type; parameters passed on by the MT to the UICC. These parameters are mandatory for every command, except GET RESPONSE and STATUS. The values are described in 3GPP TS 31.101 [65]
+[data]: information which shall be written to the SIM (hexadecimal character format; refer +CSCS)
+[pathid]: string type; contains the path of an elementary file on the UICC in hexadecimal format (e.g. '5F704F30' for DFSoLSA/EFSAI). The [pathid] shall only be used in the mode 'select by path from current DF' as defined in ETSI TS 102 221 [60].
+[sw1], [sw2]: integer type; information from the UICC about the execution of the actual command. These parameters are delivered to the TE in both cases, on successful or failed execution of the command
+[response]: response of a successful completion of the command previously issued (hexadecimal character format; refer +CSCS). STATUS and GET RESPONSE return data, which gives information about the current elementary datafield. This information includes the type of file and its size (refer 3GPP TS 31.101 [65]). After READ BINARY, READ RECORD or RETRIEVE DATA command the requested data will be returned. [response] is not returned after a successful UPDATE BINARY, UPDATE RECORD or SET DATA command
+</description>
+</spec>
+<spec>
+    <command>AT+CRLA=?</command>
+    <profile>Restricted UICC Logical Channel access (Query all)</profile>
+    <description>By using this command instead of Generic UICC Access +CGLA TE application has easier but more limited access to the UICC database. Set command transmits to the MT the UICC [command] and its required parameters. MT handles internally all UICC‑MT interface locking and file selection routines. As response to the command, MT sends the actual UICC information parameters and response data. MT error result code +CME ERROR may be returned when the command cannot be passed to the UICC, but failure in the execution of the command in the UICC is reported in [sw1] and [sw2] parameters. Refer to subclause 9.2 for [err] values.
+Coordination of command requests to UICC and the ones issued by GSM/UMTS application inside the MT is implementation dependent. However the TE should be aware of the precedence of the GSM/UMTS application commands to the TE commands.
+Defined values
+[sessionid]: integer type; this is the identifier of the session to be used in order to send the APDU commands to the UICC. It is mandatory in order to send commands to the UICC when targeting applications on the smart card using a logical channel other than the default channel (channel '0').
+[command] (command passed on by the MT to the UICC; refer  3GPP TS 31.101 [65]):
+176	READ BINARY
+178	READ RECORD
+192	GET RESPONSE
+214	UPDATE BINARY
+220	UPDATE RECORD
+242	STATUS
+203	RETRIEVE DATA
+219	SET DATA
+all other values are reserved
+
+NOTE 1:	The MT internally executes all commands necessary for selecting the desired file, before performing the actual command.[fileid]: integer type; this is the identifier of a elementary datafile on UICC. Mandatory for every command except STATUS.
+NOTE 2:	The range of valid file identifiers depends on the actual UICC and is defined in  3GPP TS 31.101 [65]. Optional files may not be present at all.[P1], [P2], [P3]: integer type; parameters passed on by the MT to the UICC. These parameters are mandatory for every command, except GET RESPONSE and STATUS. The values are described in 3GPP TS 31.101 [65]
+[data]: information which shall be written to the SIM (hexadecimal character format; refer +CSCS)
+[pathid]: string type; contains the path of an elementary file on the UICC in hexadecimal format (e.g. '5F704F30' for DFSoLSA/EFSAI). The [pathid] shall only be used in the mode 'select by path from current DF' as defined in ETSI TS 102 221 [60].
+[sw1], [sw2]: integer type; information from the UICC about the execution of the actual command. These parameters are delivered to the TE in both cases, on successful or failed execution of the command
+[response]: response of a successful completion of the command previously issued (hexadecimal character format; refer +CSCS). STATUS and GET RESPONSE return data, which gives information about the current elementary datafield. This information includes the type of file and its size (refer 3GPP TS 31.101 [65]). After READ BINARY, READ RECORD or RETRIEVE DATA command the requested data will be returned. [response] is not returned after a successful UPDATE BINARY, UPDATE RECORD or SET DATA command
+</description>
+</spec>
+<spec>
+    <command>AT+CCHO=</command>
+    <profile>Open Logical Channel (Assign)</profile>
+    <description>Execution of the command causes the MT to return [sessionid] to allow the TE to identify a channel that is being allocated by the UICC, which is attached to ME. The UICC will open a new logical channel; select the application identified by the [dfname] received with this command and return a session Id as the response. The ME shall restrict the communication between the TE and the UICC to this logical channel.
+This [sessionid] is to be used when sending commands with Restricted UICC Logical Channel access +CRLA or Generic UICC Logical Channel access +CGLA  commands.
+Note that the logical channel number is contained in the CLASS byte of an APDU command, thus implicitly contained in all APDU commands sent to a UICC. In this case it will be up to the MT to manage the logical channel part of the APDU CLASS byte and to ensure that the chosen logical channel is relevant to the [sessionid] indicated in the AT command. See 3GPP TS 31.101 [65] for further information on logical channels in APDU commands protocol.
+Refer subclause 9.2 for possible [err] values. 
+Defined values
+[dfname]: all selectable applications in the UICC are referenced by a DF name coded on 1 to 16 bytes
+[sessionid]:A session Id to be used in order to target a specific application on the smart card (e.g. (U)SIM, WIM, ISIM) using logical channels mechanism (string without double quotes that represents a decimal value)
+See 3GPP TS 31.101 [65] for more information about defined values.
+</description>
+</spec>
+<spec>
+    <command>AT+CCHO=?</command>
+    <profile>Open Logical Channel (Query all)</profile>
+    <description>Execution of the command causes the MT to return [sessionid] to allow the TE to identify a channel that is being allocated by the UICC, which is attached to ME. The UICC will open a new logical channel; select the application identified by the [dfname] received with this command and return a session Id as the response. The ME shall restrict the communication between the TE and the UICC to this logical channel.
+This [sessionid] is to be used when sending commands with Restricted UICC Logical Channel access +CRLA or Generic UICC Logical Channel access +CGLA  commands.
+Note that the logical channel number is contained in the CLASS byte of an APDU command, thus implicitly contained in all APDU commands sent to a UICC. In this case it will be up to the MT to manage the logical channel part of the APDU CLASS byte and to ensure that the chosen logical channel is relevant to the [sessionid] indicated in the AT command. See 3GPP TS 31.101 [65] for further information on logical channels in APDU commands protocol.
+Refer subclause 9.2 for possible [err] values. 
+Defined values
+[dfname]: all selectable applications in the UICC are referenced by a DF name coded on 1 to 16 bytes
+[sessionid]:A session Id to be used in order to target a specific application on the smart card (e.g. (U)SIM, WIM, ISIM) using logical channels mechanism (string without double quotes that represents a decimal value)
+See 3GPP TS 31.101 [65] for more information about defined values.
+</description>
+</spec>
+<spec>
+    <command>AT+CCHC=</command>
+    <profile>Close Logical Channel (Assign)</profile>
+    <description>This command asks the ME to close a communication session with the UICC. The ME shall close the previously opened logical channel. The TE will no longer be able to send commands on this logical channel. The UICC will close the logical channel when receiving this command. Refer subclause 9.2 for possible [err] values.
+Defined values
+[sessionid]:A session Id to be used in order to target a specific application on the smart card (e.g. (U)SIM, WIM, ISIM) using logical channels mechanism (string without double quotes that represents a decimal value)
+</description>
+</spec>
+<spec>
+    <command>AT+CCHC=?</command>
+    <profile>Close Logical Channel (Query all)</profile>
+    <description>This command asks the ME to close a communication session with the UICC. The ME shall close the previously opened logical channel. The TE will no longer be able to send commands on this logical channel. The UICC will close the logical channel when receiving this command. Refer subclause 9.2 for possible [err] values.
+Defined values
+[sessionid]:A session Id to be used in order to target a specific application on the smart card (e.g. (U)SIM, WIM, ISIM) using logical channels mechanism (string without double quotes that represents a decimal value)
+</description>
+</spec>
+<spec>
+    <command>AT+CEAP=</command>
+    <profile>EAP authentication (Assign)</profile>
+    <description>This command allows a TE to exchange EAP packets with the UICC or the ME. 
+Prior to the execution of this command, the TE shall retrieve the available AIDs using the +CUAD command. The TE shall select one appropriate AID to be addressed. Selection may include asking the user, and considering EAP methods supported by the AIDs. The TE shall set the [dfname] value using the selected AID and shall set the [EAPMethod] value to the requested EAP method. 
+If the targeted application on the UICC does support the requested EAP method, the MT shall derive the directory file identifier (see ETSI TS 102 310 [66]) from [dfname] and [EAPMethod], and it shall transmit the [EAP packet data] to the UICC application using the Authenticate APDU command as defined in ETSI TS 102 310 [66]. The appropriate DFEAP in the ADF must be selected prior to the submission of an EAP Authenticate command with the [EAP packet data]. Then the EAP Response data sent by the UICC application in its response to the Authenticate command shall be provided to the TE in [EAP packet response]. 
+If the targeted application on the UICC does not support the requested EAP method and if the MT does support this method then the [EAP packet data] shall be handled by the MT. During the handling of the EAP method, the MT shall run the authentication algorithm on the SIM or USIM, respectively. 
+Also the MT has to allocate an [EAPsessionid] in order to identify an EAP session and its corresponding keys and parameters.
+If neither the MT nor the appropriate UICC application support the requested EAP method, the MT shall respond with 'EAP method not supported'.
+Refer subclause 9.2 for possible [err] values.
+Defined values
+[dfname]: string type; all selectable applications represented in the UICC by an AID are referenced by a DF name coded on 1 to 16 bytes. 
+[EAPMethod]: octet type; this is the EAP Method Type as defined in [68]
+[EAP packet data]: as defined in ETSI TS 102 310 [66]
+[EAPsessionid]: integer type; this is the identifier of the EAP session to be used in order to retrieve the EAP parameters with EAP Retreive Parameters +CERP command.
+[EAP packet response]: as defined in ETSI TS 102 310 [66]
+</description>
+</spec>
+<spec>
+    <command>AT+CEAP=?</command>
+    <profile>EAP authentication (Query all)</profile>
+    <description>This command allows a TE to exchange EAP packets with the UICC or the ME. 
+Prior to the execution of this command, the TE shall retrieve the available AIDs using the +CUAD command. The TE shall select one appropriate AID to be addressed. Selection may include asking the user, and considering EAP methods supported by the AIDs. The TE shall set the [dfname] value using the selected AID and shall set the [EAPMethod] value to the requested EAP method. 
+If the targeted application on the UICC does support the requested EAP method, the MT shall derive the directory file identifier (see ETSI TS 102 310 [66]) from [dfname] and [EAPMethod], and it shall transmit the [EAP packet data] to the UICC application using the Authenticate APDU command as defined in ETSI TS 102 310 [66]. The appropriate DFEAP in the ADF must be selected prior to the submission of an EAP Authenticate command with the [EAP packet data]. Then the EAP Response data sent by the UICC application in its response to the Authenticate command shall be provided to the TE in [EAP packet response]. 
+If the targeted application on the UICC does not support the requested EAP method and if the MT does support this method then the [EAP packet data] shall be handled by the MT. During the handling of the EAP method, the MT shall run the authentication algorithm on the SIM or USIM, respectively. 
+Also the MT has to allocate an [EAPsessionid] in order to identify an EAP session and its corresponding keys and parameters.
+If neither the MT nor the appropriate UICC application support the requested EAP method, the MT shall respond with 'EAP method not supported'.
+Refer subclause 9.2 for possible [err] values.
+Defined values
+[dfname]: string type; all selectable applications represented in the UICC by an AID are referenced by a DF name coded on 1 to 16 bytes. 
+[EAPMethod]: octet type; this is the EAP Method Type as defined in [68]
+[EAP packet data]: as defined in ETSI TS 102 310 [66]
+[EAPsessionid]: integer type; this is the identifier of the EAP session to be used in order to retrieve the EAP parameters with EAP Retreive Parameters +CERP command.
+[EAP packet response]: as defined in ETSI TS 102 310 [66]
+</description>
+</spec>
+<spec>
+    <command>AT+CERP=</command>
+    <profile>EAP Retrieve Parameters (Assign)</profile>
+    <description>This command allows a TE to retrieve EAP session parameters / derived keys after a run of the +CEAP command. If the EAP session is handled by the UICC then the MT shall return the content of the elementary file corresponding to the indicated [EAPparameter]. Those EFs are defined in ETSI TS 102 310 [66].
+If the MT handles the EAP session then the MT shall return the corresponding parameter encoded as defined for EAP files, see ETSI TS 102 310 [66].
+For example, the keys shall be retrieved in the TLV format described in ETSI TS 102 310 [66].
+If neither the MT nor the appropriate UICC application can provide the requested information (e.g. because the requested EAP session ID does not exist), the MT shall respond with 'Incorrect parameters'.
+Refer subclause 9.2 for possible [err] values.
+Defined values
+[EAPparameter]:
+1Keys
+2Status
+3Identity
+4Pseudonym
+[EAPsessionid]: integer type; this is the identifier of the EAP session to be used in order to retrieve the EAP parameters corresponding to an active EAP session with EAP Retreive Parameters +CERP command.
+[EAP parameter response]: depends on the value of [EAPparameter]; format of the parameter retrieved is as defined in ETSI TS 102 310 [66].
+</description>
+</spec>
+<spec>
+    <command>AT+CERP=?</command>
+    <profile>EAP Retrieve Parameters (Query all)</profile>
+    <description>This command allows a TE to retrieve EAP session parameters / derived keys after a run of the +CEAP command. If the EAP session is handled by the UICC then the MT shall return the content of the elementary file corresponding to the indicated [EAPparameter]. Those EFs are defined in ETSI TS 102 310 [66].
+If the MT handles the EAP session then the MT shall return the corresponding parameter encoded as defined for EAP files, see ETSI TS 102 310 [66].
+For example, the keys shall be retrieved in the TLV format described in ETSI TS 102 310 [66].
+If neither the MT nor the appropriate UICC application can provide the requested information (e.g. because the requested EAP session ID does not exist), the MT shall respond with 'Incorrect parameters'.
+Refer subclause 9.2 for possible [err] values.
+Defined values
+[EAPparameter]:
+1Keys
+2Status
+3Identity
+4Pseudonym
+[EAPsessionid]: integer type; this is the identifier of the EAP session to be used in order to retrieve the EAP parameters corresponding to an active EAP session with EAP Retreive Parameters +CERP command.
+[EAP parameter response]: depends on the value of [EAPparameter]; format of the parameter retrieved is as defined in ETSI TS 102 310 [66].
+</description>
+</spec>
+<spec>
+    <command>AT+CUAD=</command>
+    <profile>UICC Application Discovery (Assign)</profile>
+    <description>This command asks the MT to discover what applications are available for selection on the UICC. According to TS 102.221 [60], the ME shall access and read the EFDIR file in the UICC and return the values that are stored in its records. Each record contains the AID and optionally application parameters of one of the applications available on the UICC.
+Defined values
+[response]:the response is the content of the EFDIR.
+</description>
+</spec>
+<spec>
+    <command>AT+CUAD=?</command>
+    <profile>UICC Application Discovery (Query all)</profile>
+    <description>This command asks the MT to discover what applications are available for selection on the UICC. According to TS 102.221 [60], the ME shall access and read the EFDIR file in the UICC and return the values that are stored in its records. Each record contains the AID and optionally application parameters of one of the applications available on the UICC.
+Defined values
+[response]:the response is the content of the EFDIR.
+</description>
+</spec>
+<spec>
+    <command>AT+CMEE=</command>
+    <profile>Report Mobile Termination error (Assign)</profile>
+    <description>Set command disables or enables the use of result code +CME ERROR: [err] as an indication of an error relating to the functionality of the MT. When enabled, MT related errors cause +CME ERROR: [err] final result code instead of the regular ERROR final result code. ERROR is returned normally when error is related to syntax, invalid parameters, or TA functionality.
+Test command returns values supported as a compound value.
+Defined values
+[n]:
+0	disable +CME ERROR: [err] result code and use ERROR instead
+1	enable +CME ERROR: [err] result code and use numeric [err] values (refer next subclause)
+2	enable +CME ERROR: [err] result code and use verbose [err] values (refer next subclause)
+</description>
+</spec>
+<spec>
+    <command>AT+CMEE?</command>
+    <profile>Report Mobile Termination error (Query)</profile>
+    <description>Set command disables or enables the use of result code +CME ERROR: [err] as an indication of an error relating to the functionality of the MT. When enabled, MT related errors cause +CME ERROR: [err] final result code instead of the regular ERROR final result code. ERROR is returned normally when error is related to syntax, invalid parameters, or TA functionality.
+Test command returns values supported as a compound value.
+Defined values
+[n]:
+0	disable +CME ERROR: [err] result code and use ERROR instead
+1	enable +CME ERROR: [err] result code and use numeric [err] values (refer next subclause)
+2	enable +CME ERROR: [err] result code and use verbose [err] values (refer next subclause)
+</description>
+</spec>
+<spec>
+    <command>AT+CMEE=?</command>
+    <profile>Report Mobile Termination error (Query all)</profile>
+    <description>Set command disables or enables the use of result code +CME ERROR: [err] as an indication of an error relating to the functionality of the MT. When enabled, MT related errors cause +CME ERROR: [err] final result code instead of the regular ERROR final result code. ERROR is returned normally when error is related to syntax, invalid parameters, or TA functionality.
+Test command returns values supported as a compound value.
+Defined values
+[n]:
+0	disable +CME ERROR: [err] result code and use ERROR instead
+1	enable +CME ERROR: [err] result code and use numeric [err] values (refer next subclause)
+2	enable +CME ERROR: [err] result code and use verbose [err] values (refer next subclause)
+</description>
+</spec>
+<spec>
+    <command>AT+CGDSCONT=</command>
+    <profile>Define Secondary PDP Context (Assign)</profile>
+    <description>The set command specifies PDP context parameter values for a Secondary PDP context identified by the (local) context identification parameter, [cid]. The number of PDP contexts that may be in a defined state at the same time is given by the range returned by the test command.
+A special form of the set command, +CGDSCONT= [cid] causes the values for context number [cid] to become undefined.
+The read command returns the current settings for each defined context.
+Defined values
+[cid]: (PDP Context Identifier) a numeric parameter which specifies a particular PDP context definition. The parameter is local to the TE-MT interface and is used in other PDP context-related commands. The range of permitted values (minimum value = 1) is returned by the test form of the command. 
+[p_cid]: (Primary PDP Context Identifier) a numeric parameter which specifies a particular PDP context definition which has been specified by use of the +CGDCONT command. The parameter is local to the TE-MT interface. The list of permitted values is returned by the test form of the command.
+[d_comp]: a numeric parameter that controls PDP data compression (applicable for SNDCPonly) (refer 3GPP TS 44.065 [61])
+0 - off  (default if value is omitted)
+1 - on (manufacturer preferred compression)
+2 - V.42bis
+3 - V.44
+Other values are reserved.
+[h_comp]: a numeric parameter that controls PDP header compression (refer 3GPP TS 44.065 [61] and 3GPP TS 25.323 [62])
+0 - off (default if value is omitted)
+1 - on (manufacturer preferred compression)
+2 - RFC1144 (applicable for SNDCP only)
+3 - RFC2507
+4 - RFC3095 (applicable for PDCP only)
+Other values are reserved.
+</description>
+</spec>
+<spec>
+    <command>AT+CGDSCONT?</command>
+    <profile>Define Secondary PDP Context (Query)</profile>
+    <description>The set command specifies PDP context parameter values for a Secondary PDP context identified by the (local) context identification parameter, [cid]. The number of PDP contexts that may be in a defined state at the same time is given by the range returned by the test command.
+A special form of the set command, +CGDSCONT= [cid] causes the values for context number [cid] to become undefined.
+The read command returns the current settings for each defined context.
+Defined values
+[cid]: (PDP Context Identifier) a numeric parameter which specifies a particular PDP context definition. The parameter is local to the TE-MT interface and is used in other PDP context-related commands. The range of permitted values (minimum value = 1) is returned by the test form of the command. 
+[p_cid]: (Primary PDP Context Identifier) a numeric parameter which specifies a particular PDP context definition which has been specified by use of the +CGDCONT command. The parameter is local to the TE-MT interface. The list of permitted values is returned by the test form of the command.
+[d_comp]: a numeric parameter that controls PDP data compression (applicable for SNDCPonly) (refer 3GPP TS 44.065 [61])
+0 - off  (default if value is omitted)
+1 - on (manufacturer preferred compression)
+2 - V.42bis
+3 - V.44
+Other values are reserved.
+[h_comp]: a numeric parameter that controls PDP header compression (refer 3GPP TS 44.065 [61] and 3GPP TS 25.323 [62])
+0 - off (default if value is omitted)
+1 - on (manufacturer preferred compression)
+2 - RFC1144 (applicable for SNDCP only)
+3 - RFC2507
+4 - RFC3095 (applicable for PDCP only)
+Other values are reserved.
+</description>
+</spec>
+<spec>
+    <command>AT+CGDSCONT=?</command>
+    <profile>Define Secondary PDP Context (Query all)</profile>
+    <description>The set command specifies PDP context parameter values for a Secondary PDP context identified by the (local) context identification parameter, [cid]. The number of PDP contexts that may be in a defined state at the same time is given by the range returned by the test command.
+A special form of the set command, +CGDSCONT= [cid] causes the values for context number [cid] to become undefined.
+The read command returns the current settings for each defined context.
+Defined values
+[cid]: (PDP Context Identifier) a numeric parameter which specifies a particular PDP context definition. The parameter is local to the TE-MT interface and is used in other PDP context-related commands. The range of permitted values (minimum value = 1) is returned by the test form of the command. 
+[p_cid]: (Primary PDP Context Identifier) a numeric parameter which specifies a particular PDP context definition which has been specified by use of the +CGDCONT command. The parameter is local to the TE-MT interface. The list of permitted values is returned by the test form of the command.
+[d_comp]: a numeric parameter that controls PDP data compression (applicable for SNDCPonly) (refer 3GPP TS 44.065 [61])
+0 - off  (default if value is omitted)
+1 - on (manufacturer preferred compression)
+2 - V.42bis
+3 - V.44
+Other values are reserved.
+[h_comp]: a numeric parameter that controls PDP header compression (refer 3GPP TS 44.065 [61] and 3GPP TS 25.323 [62])
+0 - off (default if value is omitted)
+1 - on (manufacturer preferred compression)
+2 - RFC1144 (applicable for SNDCP only)
+3 - RFC2507
+4 - RFC3095 (applicable for PDCP only)
+Other values are reserved.
+</description>
+</spec>
+<spec>
+    <command>AT+CGAUTO=</command>
+    <profile>Automatic response to a network request for PDP context activation (Assign)</profile>
+    <description>The set command disables or enables an automatic positive response (auto-answer) to the receipt of a Request PDP Context Activation message from the network. It also provides control over the use of the V.250 basic commands 'S0', 'A and 'H' for handling network requests for PDP context activation. The setting does not affect the issuing of the unsolicited result code RING or +CRING.
+The test command returns the values of [n] supported by the MT as a compound value.
+When the +CGAUTO=0 command is received, the MT shall not perform a PS detach if it is attached. Subsequently, when the MT announces a network request for PDP context activation by issuing the unsolicited result code RING or +CRING, the TE may manually accept or reject the request by issuing the +CGANS command or may simply ignore the network request.
+When the +CGAUTO=1 command is received, the MT shall attempt to perform a PS attach if it is not already attached. Failure will result in ERROR or, if enabled, +CME ERROR being returned to the TE. Subsequently, when the MT announces a network request for PDP context activation by issuing the unsolicited result code RING or +CRING to the TE, this is followed by the intermediate result code CONNECT. The MT then enters V.250 online data state and follows the same procedure as it would after having received a +CGANS=1 with no [L2P] or [cid] values specified.
+Defined values
+[n]:
+0	turn off automatic response for Packet Domain only
+1	turn on automatic response for Packet Domain only
+2	modem compatibility mode, Packet Domain only
+3	modem compatibility mode, Packet Domain and circuit switched calls (default)
+For [n] = 0 Packet DomainS network requests are manually accepted or rejected by the +CGANS command.
+For [n] = 1 Packet Domain network requests are automatically accepted according to the description above.
+For [n] = 2, automatic acceptance of Packet Domain network requests is controlled by the 'S0' command. Manual control uses the 'A' and 'H' commands, respectively, to accept and reject Packet Domain requests. (+CGANS may also be used.) Incoming circuit switched calls can be neither manually nor automatically answered.
+For [n] = 3, automatic acceptance of both Packet Domain network requests and incoming circuit switched calls is controlled by the 'S0' command. Manual control uses the 'A' and 'H' commands, respectively, to accept and reject Packet Domain requests. (+CGANS may also be used.) Circuit switched calls are handled as described elsewhere in this specification.
+</description>
+</spec>
+<spec>
+    <command>AT+CGAUTO?</command>
+    <profile>Automatic response to a network request for PDP context activation (Query)</profile>
+    <description>The set command disables or enables an automatic positive response (auto-answer) to the receipt of a Request PDP Context Activation message from the network. It also provides control over the use of the V.250 basic commands 'S0', 'A and 'H' for handling network requests for PDP context activation. The setting does not affect the issuing of the unsolicited result code RING or +CRING.
+The test command returns the values of [n] supported by the MT as a compound value.
+When the +CGAUTO=0 command is received, the MT shall not perform a PS detach if it is attached. Subsequently, when the MT announces a network request for PDP context activation by issuing the unsolicited result code RING or +CRING, the TE may manually accept or reject the request by issuing the +CGANS command or may simply ignore the network request.
+When the +CGAUTO=1 command is received, the MT shall attempt to perform a PS attach if it is not already attached. Failure will result in ERROR or, if enabled, +CME ERROR being returned to the TE. Subsequently, when the MT announces a network request for PDP context activation by issuing the unsolicited result code RING or +CRING to the TE, this is followed by the intermediate result code CONNECT. The MT then enters V.250 online data state and follows the same procedure as it would after having received a +CGANS=1 with no [L2P] or [cid] values specified.
+Defined values
+[n]:
+0	turn off automatic response for Packet Domain only
+1	turn on automatic response for Packet Domain only
+2	modem compatibility mode, Packet Domain only
+3	modem compatibility mode, Packet Domain and circuit switched calls (default)
+For [n] = 0 Packet DomainS network requests are manually accepted or rejected by the +CGANS command.
+For [n] = 1 Packet Domain network requests are automatically accepted according to the description above.
+For [n] = 2, automatic acceptance of Packet Domain network requests is controlled by the 'S0' command. Manual control uses the 'A' and 'H' commands, respectively, to accept and reject Packet Domain requests. (+CGANS may also be used.) Incoming circuit switched calls can be neither manually nor automatically answered.
+For [n] = 3, automatic acceptance of both Packet Domain network requests and incoming circuit switched calls is controlled by the 'S0' command. Manual control uses the 'A' and 'H' commands, respectively, to accept and reject Packet Domain requests. (+CGANS may also be used.) Circuit switched calls are handled as described elsewhere in this specification.
+</description>
+</spec>
+<spec>
+    <command>AT+CGAUTO=?</command>
+    <profile>Automatic response to a network request for PDP context activation (Query all)</profile>
+    <description>The set command disables or enables an automatic positive response (auto-answer) to the receipt of a Request PDP Context Activation message from the network. It also provides control over the use of the V.250 basic commands 'S0', 'A and 'H' for handling network requests for PDP context activation. The setting does not affect the issuing of the unsolicited result code RING or +CRING.
+The test command returns the values of [n] supported by the MT as a compound value.
+When the +CGAUTO=0 command is received, the MT shall not perform a PS detach if it is attached. Subsequently, when the MT announces a network request for PDP context activation by issuing the unsolicited result code RING or +CRING, the TE may manually accept or reject the request by issuing the +CGANS command or may simply ignore the network request.
+When the +CGAUTO=1 command is received, the MT shall attempt to perform a PS attach if it is not already attached. Failure will result in ERROR or, if enabled, +CME ERROR being returned to the TE. Subsequently, when the MT announces a network request for PDP context activation by issuing the unsolicited result code RING or +CRING to the TE, this is followed by the intermediate result code CONNECT. The MT then enters V.250 online data state and follows the same procedure as it would after having received a +CGANS=1 with no [L2P] or [cid] values specified.
+Defined values
+[n]:
+0	turn off automatic response for Packet Domain only
+1	turn on automatic response for Packet Domain only
+2	modem compatibility mode, Packet Domain only
+3	modem compatibility mode, Packet Domain and circuit switched calls (default)
+For [n] = 0 Packet DomainS network requests are manually accepted or rejected by the +CGANS command.
+For [n] = 1 Packet Domain network requests are automatically accepted according to the description above.
+For [n] = 2, automatic acceptance of Packet Domain network requests is controlled by the 'S0' command. Manual control uses the 'A' and 'H' commands, respectively, to accept and reject Packet Domain requests. (+CGANS may also be used.) Incoming circuit switched calls can be neither manually nor automatically answered.
+For [n] = 3, automatic acceptance of both Packet Domain network requests and incoming circuit switched calls is controlled by the 'S0' command. Manual control uses the 'A' and 'H' commands, respectively, to accept and reject Packet Domain requests. (+CGANS may also be used.) Circuit switched calls are handled as described elsewhere in this specification.
+</description>
+</spec>
+<spec>
+    <command>AT+CGANS=</command>
+    <profile>Manual response to a network request for PDP context activation (Assign)</profile>
+    <description>The execution command requests the MT to respond to a network request for Packet Domain PDP context activation which has been signalled to the TE by the RING or +CRING: unsolicited result code. The [response] parameter allows the TE to accept or reject the request. 
+If [response] is 0, the request is rejected and the MT returns OK to the TE.
+If [response] is 1, the following procedure is followed by the MT.
+Commands following the +CGANS command in the AT command line shall not be processed by the MT.
+If the [L2P] parameter value is unacceptable to the MT, the MT shall return an ERROR or +CME ERROR response. Otherwise, the MT issues the intermediate result code CONNECT and enters V.250 online data state.
+The detailed behaviour after the online data state has been entered is dependent on the PDP type. It is described briefly in 3GPP TS 27.060[34] and in more detail in 3GPP TS 29.061[39] and the specifications for the relevant PDPs. PDP context activation procedures shall take place prior to or during the PDP startup. 
+One or more [cid]s may be specified in order to provide the values needed for the context activation request.
+During the PDP startup procedure the MT has the PDP type and the PDP address provided by the network in the Request PDP Context Activation message. The MT may also have some or all of the following information -
+	The MT may have a priori knowledge, for example, it may implement only one PDP type.
+	The command may have provided an [L2P] parameter value.
+	The TE may provide one or both of PDP type and PDP address to the MT in the PDP startup.
+If any of this information is in conflict, the command will fail.
+If one or more [cid] is given then an attempt shall be made to identify an appropriate context definition by matching the PDP type and PDP address in the network request with the PDP type and PDP address in each of the specified context definitions (in the order in which their [cid]s appear in the command) as follows -
+	The PDP type must match exactly.
+	The PDP addresses are considered to match if they are identical or if the address in the context definition is unspecified.
+The context shall be activated using the values for PDP type and PDP address provided by the network, together with the other information found in the PDP context definition. An APN may or may not re required, depending on the application.
+If no [cid] is given or if there is no matching context definition, the MT will attempt to activate the context using the values for PDP type and PDP address provided by the network, together with any other relevant information known to the MT. The other context parameters will be set to their default values.
+If the activation is successful, data transfer may proceed.
+After data transfer is complete, and the layer 2 protocol termination procedure has completed successfully, the V.250 command state is re-entered and the MT returns the final result code OK
+In the event of an erroneous termination or a failure to startup, the V.250 command state is re-entered and the MT returns the final result code NO CARRIER or, if enabled, +CME ERROR. Attach, activate and other errors may be reported. It is also an error to issue the +CGANS command when there is no outstanding network request.
+NOTE:	This is not the same as if the MT issues a +CGDATA (or +CGACT) command after receiving a +CRING unsolicited result code. A +CGDATA (or +CGACT) does not command the MT to acknowledge the network request but rather to make a new request for context activation. The network request would be ignored.
+The test command returns the values of [response] and [L2P] supported by the MT as compound values.
+This command may be used in both normal and modem compatibility modes.
+Defined values
+[response]: is a numeric parameter which specifies how the request should be responded to.
+0	reject the request
+1	accept and request that the PDP context be activated
+If [response] is omitted it is assumed to be 0. Other values are reserved and will result in the ERROR response.
+[L2P]: a string parameter which indicates the layer 2 protocol to be used (see +CGDATA command).
+[cid]: a numeric parameter which specifies a particular PDP context definition (see the +CGDCONT and +CGDSCONT commands).
+</description>
+</spec>
+<spec>
+    <command>AT+CGANS=?</command>
+    <profile>Manual response to a network request for PDP context activation (Query all)</profile>
+    <description>The execution command requests the MT to respond to a network request for Packet Domain PDP context activation which has been signalled to the TE by the RING or +CRING: unsolicited result code. The [response] parameter allows the TE to accept or reject the request. 
+If [response] is 0, the request is rejected and the MT returns OK to the TE.
+If [response] is 1, the following procedure is followed by the MT.
+Commands following the +CGANS command in the AT command line shall not be processed by the MT.
+If the [L2P] parameter value is unacceptable to the MT, the MT shall return an ERROR or +CME ERROR response. Otherwise, the MT issues the intermediate result code CONNECT and enters V.250 online data state.
+The detailed behaviour after the online data state has been entered is dependent on the PDP type. It is described briefly in 3GPP TS 27.060[34] and in more detail in 3GPP TS 29.061[39] and the specifications for the relevant PDPs. PDP context activation procedures shall take place prior to or during the PDP startup. 
+One or more [cid]s may be specified in order to provide the values needed for the context activation request.
+During the PDP startup procedure the MT has the PDP type and the PDP address provided by the network in the Request PDP Context Activation message. The MT may also have some or all of the following information -
+	The MT may have a priori knowledge, for example, it may implement only one PDP type.
+	The command may have provided an [L2P] parameter value.
+	The TE may provide one or both of PDP type and PDP address to the MT in the PDP startup.
+If any of this information is in conflict, the command will fail.
+If one or more [cid] is given then an attempt shall be made to identify an appropriate context definition by matching the PDP type and PDP address in the network request with the PDP type and PDP address in each of the specified context definitions (in the order in which their [cid]s appear in the command) as follows -
+	The PDP type must match exactly.
+	The PDP addresses are considered to match if they are identical or if the address in the context definition is unspecified.
+The context shall be activated using the values for PDP type and PDP address provided by the network, together with the other information found in the PDP context definition. An APN may or may not re required, depending on the application.
+If no [cid] is given or if there is no matching context definition, the MT will attempt to activate the context using the values for PDP type and PDP address provided by the network, together with any other relevant information known to the MT. The other context parameters will be set to their default values.
+If the activation is successful, data transfer may proceed.
+After data transfer is complete, and the layer 2 protocol termination procedure has completed successfully, the V.250 command state is re-entered and the MT returns the final result code OK
+In the event of an erroneous termination or a failure to startup, the V.250 command state is re-entered and the MT returns the final result code NO CARRIER or, if enabled, +CME ERROR. Attach, activate and other errors may be reported. It is also an error to issue the +CGANS command when there is no outstanding network request.
+NOTE:	This is not the same as if the MT issues a +CGDATA (or +CGACT) command after receiving a +CRING unsolicited result code. A +CGDATA (or +CGACT) does not command the MT to acknowledge the network request but rather to make a new request for context activation. The network request would be ignored.
+The test command returns the values of [response] and [L2P] supported by the MT as compound values.
+This command may be used in both normal and modem compatibility modes.
+Defined values
+[response]: is a numeric parameter which specifies how the request should be responded to.
+0	reject the request
+1	accept and request that the PDP context be activated
+If [response] is omitted it is assumed to be 0. Other values are reserved and will result in the ERROR response.
+[L2P]: a string parameter which indicates the layer 2 protocol to be used (see +CGDATA command).
+[cid]: a numeric parameter which specifies a particular PDP context definition (see the +CGDCONT and +CGDSCONT commands).
+</description>
+</spec>
+<spec>
+    <command>AT+CGCS=</command>
+    <profile>VGCS subscriptions and GId status (Assign)</profile>
+    <description>This command works with SIM Card and when the GSM Application is selected in UICC.   Function with USIM is for further study.  The set command is used to edit the status of the GId EFVGCSS on the SIM. The read command returns all subscribed GIds in EFVGCS and their status in EFVGCSS from the SIM.
+
+Defined values
+[GId] integer type, group Id as specified in 3GPP TS 22.030 [19]
+[status]: integer type, value
+	0		deactivated
+	1		activated
+</description>
+</spec>
+<spec>
+    <command>AT+CGCS?</command>
+    <profile>VGCS subscriptions and GId status (Query)</profile>
+    <description>This command works with SIM Card and when the GSM Application is selected in UICC.   Function with USIM is for further study.  The set command is used to edit the status of the GId EFVGCSS on the SIM. The read command returns all subscribed GIds in EFVGCS and their status in EFVGCSS from the SIM.
+
+Defined values
+[GId] integer type, group Id as specified in 3GPP TS 22.030 [19]
+[status]: integer type, value
+	0		deactivated
+	1		activated
+</description>
+</spec>
+<spec>
+    <command>AT+CGCS=?</command>
+    <profile>VGCS subscriptions and GId status (Query all)</profile>
+    <description>This command works with SIM Card and when the GSM Application is selected in UICC.   Function with USIM is for further study.  The set command is used to edit the status of the GId EFVGCSS on the SIM. The read command returns all subscribed GIds in EFVGCS and their status in EFVGCSS from the SIM.
+
+Defined values
+[GId] integer type, group Id as specified in 3GPP TS 22.030 [19]
+[status]: integer type, value
+	0		deactivated
+	1		activated
+</description>
+</spec>
+<spec>
+    <command>AT+CBCS=</command>
+    <profile>VBS subscriptions and GId status (Assign)</profile>
+    <description>This command works with SIM Card and when the GSM Application is selected in UICC.   Function with USIM is for further study.  The set command is used to edit the status of the GId EFVBSS on the SIM. The read command returns all subscribed GIds in EFVBS and their status in EFVBSS from the SIM.
+
+Defined values
+[GId] integer type, group Id as specified in 3GPP TS 22.030 [19]
+[status]: integer type, value
+	0		deactivated
+	1		activated
+</description>
+</spec>
+<spec>
+    <command>AT+CBCS?</command>
+    <profile>VBS subscriptions and GId status (Query)</profile>
+    <description>This command works with SIM Card and when the GSM Application is selected in UICC.   Function with USIM is for further study.  The set command is used to edit the status of the GId EFVBSS on the SIM. The read command returns all subscribed GIds in EFVBS and their status in EFVBSS from the SIM.
+
+Defined values
+[GId] integer type, group Id as specified in 3GPP TS 22.030 [19]
+[status]: integer type, value
+	0		deactivated
+	1		activated
+</description>
+</spec>
+<spec>
+    <command>AT+CBCS=?</command>
+    <profile>VBS subscriptions and GId status (Query all)</profile>
+    <description>This command works with SIM Card and when the GSM Application is selected in UICC.   Function with USIM is for further study.  The set command is used to edit the status of the GId EFVBSS on the SIM. The read command returns all subscribed GIds in EFVBS and their status in EFVBSS from the SIM.
+
+Defined values
+[GId] integer type, group Id as specified in 3GPP TS 22.030 [19]
+[status]: integer type, value
+	0		deactivated
+	1		activated
+</description>
+</spec>
+</gsm>
\ No newline at end of file

Added: trunk/src/host/qemu-neo1973/phonesim/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/Makefile	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/Makefile	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,15 @@
+# Copyright (C) 2007 OpenMoko, Inc.
+
+QMAKE=qmake
+all: phonesim
+phonesim: Makefile.phonesim lib/libphonesim.a
+	$(MAKE) -f Makefile.phonesim
+Makefile.phonesim: phonesim.pro
+	$(QMAKE) -o $@
+lib/libphonesim.a: lib/Makefile
+	$(MAKE) -C lib
+lib/Makefile: lib/lib.pro
+	cd lib; $(QMAKE) 
+clean: Makefile.phonesim lib/Makefile
+	$(MAKE) -C lib clean
+	$(MAKE) -f Makefile.phonesim clean

Added: trunk/src/host/qemu-neo1973/phonesim/attranslator.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/attranslator.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/attranslator.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "attranslator.h"
+
+AtTranslator::AtTranslator(const QString& specFile)
+    : gsmSpec(specFile)
+{
+}
+
+QString AtTranslator::translateCommand( const QString& data )
+{
+    QString command;
+    QString parameters;
+
+    if( data.contains("?") ){
+        command = data.left( data.indexOf("?")+1 );
+    }else if( data.contains("=") ){
+        command = data.left( data.indexOf("=")+1 );
+        parameters = data.right( data.indexOf("=")+1 );
+    }else{
+        command = data;
+    }
+    QString answer = gsmSpec.getProfile(command);
+    if(!gsmSpec.validateCommand(command, parameters) )
+        answer = answer.append("\n").append("Parameters not valid, expected: ").append(gsmSpec.getParameterFormat(command).join("||"));
+    return answer;
+}
+
+QString AtTranslator::translateResponse( const QString& data )
+{
+    Q_UNUSED( data );
+    return "todo";
+}
+
+void AtTranslator::resetSpecification(const QString& filePath)
+{
+    gsmSpec.resetDictionary(filePath);
+}
+
+
+
+
+
+
+
+

Added: trunk/src/host/qemu-neo1973/phonesim/attranslator.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/attranslator.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/attranslator.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef ATTRANSLATOR_H
+#define ATTRANSLATOR_H
+
+#include <QString>
+#include <QMap>
+#include <QStringList>
+#include "gsmspec.h"
+
+class AtTranslator
+{
+
+public:
+    AtTranslator(const QString& specFile);
+    QString translateCommand( const QString& );
+    QString translateResponse( const QString& );
+    void resetSpecification(const QString& );
+
+private:
+    GSMSpec gsmSpec;
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/control.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/control.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/control.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "control.h"
+#include "ui_controlbase.h"
+#include <qpushbutton.h>
+#include <qslider.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <QtGui/qmessagebox.h>
+#include <qfiledialog.h>
+#include <Qt>
+#include <qbuffer.h>
+#include <qtimer.h>
+#include <qevent.h>
+#include <QFileInfo>
+#include <QFile>
+#include <QDir>
+
+#define TWO_BYTE_MAX 65535
+#define FOUR_CHAR 4
+#define HEX_BASE 16
+
+Control::Control(const QString& ruleFile, QWidget *parent)
+        : HardwareManipulator(parent)
+{
+    QFileInfo info( ruleFile );
+    QString specFile = info.absolutePath() + "/GSMSpecification.xml";
+    if (!QFile::exists(specFile))
+        specFile = QDir::currentPath() + "/GSMSpecification.xml";
+    translator = new AtTranslator(specFile);
+    ui = new Ui_ControlBase;
+    ui->setupUi(this);
+    connect(ui->hsSignalQuality, SIGNAL(valueChanged(int)), this, SLOT(sendSQ()));
+    connect(ui->hsBatteryCharge, SIGNAL(valueChanged(int)), this, SLOT(sendBC()));
+    connect(ui->pbSelectOperator, SIGNAL(clicked()), this, SLOT(sendOPS()));
+    connect(ui->pbRegistration, SIGNAL(clicked()), this, SLOT(sendREG()));
+    connect(ui->pbSendCellBroadcast, SIGNAL(clicked()), this, SLOT(sendCBM()));
+    connect(ui->pbSendSMSMessage, SIGNAL(clicked()), this, SLOT(sendSMSMessage()));
+    connect(ui->pbFile, SIGNAL(clicked()), this, SLOT(selectFile()));
+    connect(ui->pbSendSMSDatagram, SIGNAL(clicked()), this, SLOT(sendSMSDatagram()));
+    connect(ui->pbIncomingCall, SIGNAL(clicked()), this, SLOT(sendCall()));
+    connect(ui->openSpecButton, SIGNAL(clicked()), this, SLOT(resetTranslator()));
+    connect(ui->atCheckBox, SIGNAL(clicked()), this, SLOT(atChanged()));
+}
+
+bool Control::shouldShow() const
+{
+    return true;
+}
+
+void Control::sendSQ()
+{
+    emit variableChanged("SQ",QString::number(ui->hsSignalQuality->value())+",99");
+    emit unsolicitedCommand("+CSQ: "+QString::number(ui->hsSignalQuality->value())+",99");
+}
+
+
+void Control::sendBC()
+{
+    emit variableChanged("BC","1,"+QString::number(ui->hsSignalQuality->value()));
+    emit unsolicitedCommand("+CBC: 0,"+QString::number(ui->hsBatteryCharge->value()));
+}
+
+void Control::sendOPS()
+{
+    emit variableChanged("OP", ui->leOperatorName->text());
+    emit unsolicitedCommand("+CREG: 5");
+}
+
+void Control::sendREG()
+{
+    QString commandString = "+CREG: "+QString::number(ui->cbRegistrationStatus->currentIndex());
+
+    if ( ui->chkLocationInfo->checkState() == Qt::Checked ) {
+        bool ok;
+
+        int LAC = convertString(ui->leLAC->text(),TWO_BYTE_MAX,FOUR_CHAR,HEX_BASE, &ok);
+        if (!ok) {
+            QMessageBox::warning(this, tr("Invalid LAC"),
+                                 tr("Location Area Code must be 4 hex digits long"),
+                                 "OK");
+            return;
+        }
+
+        int cellID = convertString(ui->leCellID->text(),TWO_BYTE_MAX,FOUR_CHAR,HEX_BASE, &ok);
+        if (!ok) {
+            QMessageBox::warning(this, tr("Invalid Cell ID"),
+                                 tr("Cell ID must be 4 hex digits long"),
+                                 "OK");
+            return;
+        }
+
+        commandString.append("," + QString::number(LAC) + "," + QString::number(cellID));
+    }
+
+    emit unsolicitedCommand(commandString);
+}
+
+void Control::sendCBM()
+{
+    QString pdu = constructCBMessage(ui->leMessageCode->text(),ui->cbGeographicalScope->currentIndex(),
+                       ui->leUpdateNumber->text(),ui->leChannel->text(),ui->leScheme->text(),
+                       ui->cbLanguage->currentIndex(),ui->leNumPages->text(),ui->lePage->text(),
+                       ui->teContent->toPlainText());
+
+    emit unsolicitedCommand(QString("+CBM: ")+QString::number(pdu.length()/2)+'\r'+'\n'+ pdu);
+}
+
+void Control::sendSMSMessage()
+{
+    int originalCount = HardwareManipulator::getSMSList().count();
+    constructSMSMessage(ui->leMessageSender->text(), ui->leSMSServiceCenter->text(), ui->teSMSText->toPlainText());
+
+    int count = HardwareManipulator::getSMSList().count();
+    if ( count > originalCount )
+        emit unsolicitedCommand("+CMTI: \"SM\","+QString::number( HardwareManipulator::getSMSList().count()));
+}
+
+void Control::sendMGD()
+{
+    emit command("AT+CMGD=1");
+}
+
+void Control::selectFile()
+{
+    ui->leFile->setText(QFileDialog::getOpenFileName(this, "Select File", "/home", "Files (*.*)"));
+}
+
+void Control::sendSMSDatagram()
+{
+
+    QString portStr = ui->lePort->text();
+    if ( portStr.contains(QRegExp("\\D")) ) {
+       QMessageBox::warning(this, tr("Invalid Port"),
+        tr("Port number can contain only digits" ),
+        "OK");
+        return;
+    }
+    int port = portStr.toInt();
+
+    QString sender = ui->leDatagramSender->text();
+
+    //obtain data from either file or text edit
+    QFile file(ui->leFile->text());
+    QByteArray data;
+    if ( ui->chkAppData->checkState() ==Qt::Checked ) {
+        if ( !file.open(QIODevice::ReadOnly) ) {
+            QMessageBox::warning(this, tr("Invalid File"),
+            tr("File could not be opened"),
+            "OK");
+            return;
+        }
+        data = file.readAll();
+    } else {
+       data = ui->teAppData->toPlainText().toUtf8();
+    }
+
+    //obtain Content-Type if required
+    QByteArray contentType;
+    if ( ui->chkContentType->checkState() == Qt::Checked ) {
+        QString contentTypeStr = ui->leContentType->text();
+        if ( contentTypeStr.length() == 0 ) {
+            QMessageBox::warning(this, tr("Invalid ContentType"),
+                                 tr("Please check the Content Type"),
+                                    "OK");
+            return;
+        }
+        contentType = contentTypeStr.toUtf8();
+    }
+
+    //construct and place SMS datagram in SMSList
+    int originalCount = HardwareManipulator::getSMSList().count();
+    constructSMSDatagram(port, sender, data, contentType);
+
+    //if datagram successfully placed in SMSList emit CMTI
+    int count = HardwareManipulator::getSMSList().count();
+    if ( count > originalCount )
+        emit unsolicitedCommand("+CMTI: \"SM\","+QString::number( HardwareManipulator::getSMSList().count()));
+}
+
+void Control::sendCall()
+{
+    emit startIncomingCall( ui->leCaller->text() );
+}
+
+void Control::handleFromData( const QString& cmd )
+{
+    ui->atViewer->append(cmd);
+    /*QStringList dataList = cmd.split("\n");
+    QString dataItem;
+    foreach( dataItem, dataList ){
+        if( dataItem != "" ){
+            ui->atViewer->append(translator->translate(dataItem));
+            ui->atViewer->append(dataItem);
+        }
+    }*/
+}
+
+void Control::handleToData( const QString& cmd )
+{
+    QStringList dataList = cmd.split("\n");
+    QString dataItem;
+    foreach( dataItem, dataList ){
+        if( dataItem != "" ){
+            ui->atViewer->append( dataItem + " : " + translator->translateCommand(dataItem) );
+        }
+    }
+}
+
+void Control::resetTranslator()
+{
+    QString fileName = QFileDialog::getOpenFileName(this,
+     tr("Open Specification File"), QDir::homePath(), tr("Specification files (*.xml)"));
+    if(fileName != 0)
+        translator->resetSpecification(fileName);
+}
+
+void Control::atChanged()
+{
+    ui->atGroupBox->setVisible( ui->atCheckBox->isChecked() );
+}
+

Added: trunk/src/host/qemu-neo1973/phonesim/control.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/control.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/control.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef CONTROL_H
+#define CONTROL_H
+
+#include <qobject.h>
+#include <qdialog.h>
+
+#include <lib/hardwaremanipulator.h>
+#include <attranslator.h>
+
+class Ui_ControlBase;
+
+class Control: public HardwareManipulator
+{
+Q_OBJECT
+
+public:
+    Control(const QString& ruleFile, QWidget *parent=0);
+    bool shouldShow() const;
+
+public slots:
+    void handleFromData( const QString& );
+    void handleToData( const QString& );
+    void resetTranslator();
+
+private slots:
+    void sendSQ();
+    void sendBC();
+    void sendOPS();
+    void sendREG();
+    void sendCBM();
+    void sendSMSMessage();
+    void sendMGD();
+    void selectFile();
+    void sendSMSDatagram();
+    void sendCall();
+    void atChanged();
+
+private:
+    Ui_ControlBase *ui;
+    AtTranslator *translator;
+};
+
+class ControlFactory : public HardwareManipulatorFactory
+{
+public:
+    inline virtual HardwareManipulator *create(QWidget *parent)
+        { return new Control(ruleFile(), parent); }
+};
+
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/controlbase.ui
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/controlbase.ui	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/controlbase.ui	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,1177 @@
+<ui version="4.0" >
+ <class>ControlBase</class>
+ <widget class="QWidget" name="ControlBase" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>929</width>
+    <height>570</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>Phonesim</string>
+  </property>
+  <layout class="QHBoxLayout" >
+   <property name="margin" >
+    <number>9</number>
+   </property>
+   <property name="spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class="QTabWidget" name="tabWidget" >
+     <property name="sizePolicy" >
+      <sizepolicy>
+       <hsizetype>5</hsizetype>
+       <vsizetype>5</vsizetype>
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="currentIndex" >
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tab" >
+      <attribute name="title" >
+       <string>Registration</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>9</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class="QGroupBox" name="gbHardware" >
+           <property name="title" >
+            <string>Hardware</string>
+           </property>
+           <layout class="QVBoxLayout" >
+            <property name="margin" >
+             <number>9</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="lblSignalQuality" >
+              <property name="toolTip" >
+               <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;/head>&lt;body style=" white-space: pre-wrap; font-family:Sans Serif; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signal Quality Level&lt;/p>&lt;/body>&lt;/html></string>
+              </property>
+              <property name="text" >
+               <string>&amp;Signal Quality:</string>
+              </property>
+              <property name="buddy" >
+               <cstring>hsSignalQuality</cstring>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSlider" name="hsSignalQuality" >
+              <property name="toolTip" >
+               <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;/head>&lt;body style=" white-space: pre-wrap; font-family:Sans Serif; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Signal Quality Level&lt;/p>&lt;/body>&lt;/html></string>
+              </property>
+              <property name="maximum" >
+               <number>31</number>
+              </property>
+              <property name="sliderPosition" >
+               <number>31</number>
+              </property>
+              <property name="orientation" >
+               <enum>Qt::Horizontal</enum>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLabel" name="lblBatteryCharge" >
+              <property name="toolTip" >
+               <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;/head>&lt;body style=" white-space: pre-wrap; font-family:Sans Serif; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Battery Charge Level&lt;/p>&lt;/body>&lt;/html></string>
+              </property>
+              <property name="text" >
+               <string>&amp;Battery Charge:</string>
+              </property>
+              <property name="buddy" >
+               <cstring>hsBatteryCharge</cstring>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QSlider" name="hsBatteryCharge" >
+              <property name="toolTip" >
+               <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;/head>&lt;body style=" white-space: pre-wrap; font-family:Sans Serif; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Battery Charge Level&lt;/p>&lt;/body>&lt;/html></string>
+              </property>
+              <property name="maximum" >
+               <number>100</number>
+              </property>
+              <property name="value" >
+               <number>100</number>
+              </property>
+              <property name="orientation" >
+               <enum>Qt::Horizontal</enum>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+         <item>
+          <widget class="QGroupBox" name="gbIncomingCall" >
+           <property name="title" >
+            <string>Incoming Call</string>
+           </property>
+           <layout class="QVBoxLayout" >
+            <property name="margin" >
+             <number>9</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="lblCaller" >
+              <property name="text" >
+               <string>C&amp;aller</string>
+              </property>
+              <property name="alignment" >
+               <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+              </property>
+              <property name="buddy" >
+               <cstring>leCaller</cstring>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QLineEdit" name="leCaller" />
+            </item>
+            <item>
+             <layout class="QHBoxLayout" >
+              <property name="margin" >
+               <number>0</number>
+              </property>
+              <property name="spacing" >
+               <number>6</number>
+              </property>
+              <item>
+               <spacer>
+                <property name="orientation" >
+                 <enum>Qt::Horizontal</enum>
+                </property>
+                <property name="sizeHint" >
+                 <size>
+                  <width>111</width>
+                  <height>20</height>
+                 </size>
+                </property>
+               </spacer>
+              </item>
+              <item>
+               <widget class="QPushButton" name="pbIncomingCall" >
+                <property name="text" >
+                 <string>&amp;Call</string>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="atCheckBox" >
+         <property name="layoutDirection" >
+          <enum>Qt::RightToLeft</enum>
+         </property>
+         <property name="text" >
+          <string>Show AT data</string>
+         </property>
+         <property name="checked" >
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="gbNetworkRegistration" >
+         <property name="title" >
+          <string>Network Registration</string>
+         </property>
+         <layout class="QVBoxLayout" >
+          <property name="margin" >
+           <number>9</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="lblOperatorName" >
+            <property name="text" >
+             <string>Operator &amp;Name</string>
+            </property>
+            <property name="buddy" >
+             <cstring>leOperatorName</cstring>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLineEdit" name="leOperatorName" />
+            </item>
+            <item>
+             <widget class="QPushButton" name="pbSelectOperator" >
+              <property name="text" >
+               <string>Select &amp;Operator</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QGridLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item row="1" column="3" >
+             <widget class="QPushButton" name="pbRegistration" >
+              <property name="text" >
+               <string>Set &amp;Registration</string>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="0" >
+             <widget class="QComboBox" name="cbRegistrationStatus" >
+              <property name="currentIndex" >
+               <number>1</number>
+              </property>
+              <item>
+               <property name="text" >
+                <string>Not Reg (not searching)</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>Reg (home network)</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>Not Reg (searching)</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>Reg denied</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>Unknown</string>
+               </property>
+              </item>
+              <item>
+               <property name="text" >
+                <string>Reg (roaming)</string>
+               </property>
+              </item>
+             </widget>
+            </item>
+            <item row="1" column="1" >
+             <widget class="QLineEdit" name="leLAC" >
+              <property name="enabled" >
+               <bool>false</bool>
+              </property>
+              <property name="maxLength" >
+               <number>4</number>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="2" >
+             <widget class="QLineEdit" name="leCellID" >
+              <property name="enabled" >
+               <bool>false</bool>
+              </property>
+              <property name="maxLength" >
+               <number>4</number>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="2" >
+             <widget class="QLabel" name="lblCellID" >
+              <property name="text" >
+               <string>Cell &amp;ID</string>
+              </property>
+              <property name="buddy" >
+               <cstring>leCellID</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0" >
+             <widget class="QLabel" name="lblStatus" >
+              <property name="text" >
+               <string>S&amp;tatus</string>
+              </property>
+              <property name="buddy" >
+               <cstring>cbRegistrationStatus</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1" >
+             <widget class="QLabel" name="lbLAC" >
+              <property name="text" >
+               <string>&amp;LAC</string>
+              </property>
+              <property name="buddy" >
+               <cstring>leLAC</cstring>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <widget class="QCheckBox" name="chkLocationInfo" >
+            <property name="text" >
+             <string>&amp;enable location info</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tab_2" >
+      <attribute name="title" >
+       <string>CBM</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>9</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="lblContent" >
+         <property name="text" >
+          <string>Cell Broadcast &amp;Message</string>
+         </property>
+         <property name="buddy" >
+          <cstring>teContent</cstring>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QTextEdit" name="teContent" >
+         <property name="tabChangesFocus" >
+          <bool>true</bool>
+         </property>
+         <property name="tabStopWidth" >
+          <number>40</number>
+         </property>
+         <property name="acceptRichText" >
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" >
+         <property name="margin" >
+          <number>0</number>
+         </property>
+         <property name="spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <spacer>
+           <property name="orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeHint" >
+            <size>
+             <width>311</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QPushButton" name="pbSendCellBroadcast" >
+           <property name="text" >
+            <string>Send &amp;Broadcast</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="groupBox" >
+         <property name="title" >
+          <string>Message Parameters</string>
+         </property>
+         <property name="checkable" >
+          <bool>false</bool>
+         </property>
+         <property name="checked" >
+          <bool>false</bool>
+         </property>
+         <layout class="QGridLayout" >
+          <property name="margin" >
+           <number>9</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item row="1" column="0" >
+           <widget class="QLabel" name="lblUpdateNumber" >
+            <property name="text" >
+             <string>&amp;Update Number:</string>
+            </property>
+            <property name="buddy" >
+             <cstring>leUpdateNumber</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1" >
+           <widget class="QLineEdit" name="leUpdateNumber" >
+            <property name="text" >
+             <string>A</string>
+            </property>
+            <property name="maxLength" >
+             <number>1</number>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="2" >
+           <widget class="QLabel" name="lblNumPages" >
+            <property name="text" >
+             <string>&amp;Number of Pages</string>
+            </property>
+            <property name="buddy" >
+             <cstring>leNumPages</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="0" >
+           <widget class="QLabel" name="lblLanguage" >
+            <property name="text" >
+             <string>&amp;Language</string>
+            </property>
+            <property name="buddy" >
+             <cstring>cbLanguage</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="2" >
+           <widget class="QLabel" name="lblGeographicalScope" >
+            <property name="text" >
+             <string>&amp;Geographical Scope</string>
+            </property>
+            <property name="buddy" >
+             <cstring>cbGeographicalScope</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="3" >
+           <widget class="QLineEdit" name="lePage" >
+            <property name="text" >
+             <string>1</string>
+            </property>
+            <property name="maxLength" >
+             <number>1</number>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="1" >
+           <widget class="QComboBox" name="cbLanguage" >
+            <property name="currentIndex" >
+             <number>1</number>
+            </property>
+            <item>
+             <property name="text" >
+              <string>German</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>English</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Italian</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>French</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Spanish</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Dutch</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Swedish</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Danish</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Portuguese</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Finish</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Norwegian</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Greek</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Turkish</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="0" column="2" >
+           <widget class="QLabel" name="lblScheme" >
+            <property name="text" >
+             <string>&amp;Scheme</string>
+            </property>
+            <property name="buddy" >
+             <cstring>leScheme</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="0" >
+           <widget class="QLabel" name="lblChannel" >
+            <property name="text" >
+             <string>&amp;Channel</string>
+            </property>
+            <property name="buddy" >
+             <cstring>leChannel</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="2" >
+           <widget class="QLabel" name="lblPage" >
+            <property name="text" >
+             <string>&amp;Page</string>
+            </property>
+            <property name="buddy" >
+             <cstring>lePage</cstring>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="3" >
+           <widget class="QLineEdit" name="leScheme" >
+            <property name="text" >
+             <string>4</string>
+            </property>
+            <property name="maxLength" >
+             <number>1</number>
+            </property>
+            <property name="readOnly" >
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1" >
+           <widget class="QLineEdit" name="leMessageCode" >
+            <property name="text" >
+             <string>012</string>
+            </property>
+            <property name="maxLength" >
+             <number>3</number>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1" >
+           <widget class="QLineEdit" name="leChannel" >
+            <property name="text" >
+             <string>0032</string>
+            </property>
+            <property name="maxLength" >
+             <number>4</number>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="3" >
+           <widget class="QLineEdit" name="leNumPages" >
+            <property name="text" >
+             <string>1</string>
+            </property>
+            <property name="maxLength" >
+             <number>1</number>
+            </property>
+           </widget>
+          </item>
+          <item row="3" column="3" >
+           <widget class="QComboBox" name="cbGeographicalScope" >
+            <property name="currentIndex" >
+             <number>3</number>
+            </property>
+            <item>
+             <property name="text" >
+              <string>Cell wide(immediate)</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>PLMN wide</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Location Area wide</string>
+             </property>
+            </item>
+            <item>
+             <property name="text" >
+              <string>Cell wide(norm)</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="0" column="0" >
+           <widget class="QLabel" name="lblMessageCode" >
+            <property name="text" >
+             <string>Message C&amp;ode:</string>
+            </property>
+            <property name="buddy" >
+             <cstring>leMessageCode</cstring>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="tab_3" >
+      <attribute name="title" >
+       <string>SMS</string>
+      </attribute>
+      <layout class="QVBoxLayout" >
+       <property name="margin" >
+        <number>9</number>
+       </property>
+       <property name="spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class="QGroupBox" name="gbMessage" >
+         <property name="title" >
+          <string>Message</string>
+         </property>
+         <layout class="QVBoxLayout" >
+          <property name="margin" >
+           <number>9</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="leSMSText" >
+            <property name="text" >
+             <string>&amp;Text</string>
+            </property>
+            <property name="buddy" >
+             <cstring>teSMSText</cstring>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QTextEdit" name="teSMSText" >
+            <property name="tabChangesFocus" >
+             <bool>true</bool>
+            </property>
+            <property name="html" >
+             <string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
+p, li { white-space: pre-wrap; }
+&lt;/style>&lt;/head>&lt;body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal; text-decoration:none;">
+&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;/p>&lt;/body>&lt;/html></string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <layout class="QGridLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item row="0" column="1" >
+             <widget class="QLineEdit" name="leMessageSender" >
+              <property name="inputMask" >
+               <string/>
+              </property>
+              <property name="maxLength" >
+               <number>32767</number>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="0" >
+             <widget class="QLabel" name="lblSMSServiceCenter" >
+              <property name="text" >
+               <string>Service &amp;Center</string>
+              </property>
+              <property name="alignment" >
+               <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+              </property>
+              <property name="buddy" >
+               <cstring>leSMSServiceCenter</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="2" >
+             <widget class="QPushButton" name="pbSendSMSMessage" >
+              <property name="text" >
+               <string>Send &amp;Message</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0" >
+             <widget class="QLabel" name="lblSMSSender" >
+              <property name="text" >
+               <string>&amp;Sender</string>
+              </property>
+              <property name="alignment" >
+               <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+              </property>
+              <property name="buddy" >
+               <cstring>leMessageSender</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="1" >
+             <widget class="QLineEdit" name="leSMSServiceCenter" >
+              <property name="inputMask" >
+               <string/>
+              </property>
+              <property name="text" >
+               <string>123</string>
+              </property>
+              <property name="maxLength" >
+               <number>32767</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+       <item>
+        <spacer>
+         <property name="orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" >
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QGroupBox" name="gbDatagram" >
+         <property name="title" >
+          <string>Datagram</string>
+         </property>
+         <layout class="QHBoxLayout" >
+          <property name="margin" >
+           <number>9</number>
+          </property>
+          <property name="spacing" >
+           <number>6</number>
+          </property>
+          <item>
+           <layout class="QGridLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item row="1" column="1" >
+             <widget class="QLineEdit" name="leDatagramSender" >
+              <property name="sizeIncrement" >
+               <size>
+                <width>1</width>
+                <height>0</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="0" >
+             <widget class="QLabel" name="lbPort" >
+              <property name="text" >
+               <string>&amp;Port</string>
+              </property>
+              <property name="buddy" >
+               <cstring>lePort</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="0" >
+             <widget class="QCheckBox" name="chkAppData" >
+              <property name="text" >
+               <string>Fi&amp;le/Text</string>
+              </property>
+              <property name="checked" >
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="2" >
+             <widget class="QPushButton" name="pbFile" >
+              <property name="sizePolicy" >
+               <sizepolicy>
+                <hsizetype>4</hsizetype>
+                <vsizetype>5</vsizetype>
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text" >
+               <string>...</string>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="1" >
+             <widget class="QLineEdit" name="leFile" >
+              <property name="sizeIncrement" >
+               <size>
+                <width>1</width>
+                <height>0</height>
+               </size>
+              </property>
+             </widget>
+            </item>
+            <item row="2" column="0" >
+             <widget class="QLabel" name="lbFile" >
+              <property name="text" >
+               <string>&amp;File</string>
+              </property>
+              <property name="buddy" >
+               <cstring>leFile</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="1" column="0" >
+             <widget class="QLabel" name="lbSender" >
+              <property name="text" >
+               <string>S&amp;ender</string>
+              </property>
+              <property name="buddy" >
+               <cstring>leDatagramSender</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="3" column="1" >
+             <widget class="QPushButton" name="pbSendSMSDatagram" >
+              <property name="text" >
+               <string>Send &amp;Datagram</string>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="1" >
+             <widget class="QLineEdit" name="lePort" >
+              <property name="sizeIncrement" >
+               <size>
+                <width>1</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="inputMask" >
+               <string/>
+              </property>
+              <property name="cursorPosition" >
+               <number>0</number>
+              </property>
+             </widget>
+            </item>
+            <item row="4" column="0" >
+             <widget class="QCheckBox" name="chkContentType" >
+              <property name="text" >
+               <string>Content T&amp;ype</string>
+              </property>
+              <property name="checked" >
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+            <item row="4" column="1" >
+             <widget class="QLineEdit" name="leContentType" >
+              <property name="enabled" >
+               <bool>false</bool>
+              </property>
+              <property name="sizeIncrement" >
+               <size>
+                <width>1</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="readOnly" >
+               <bool>false</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QVBoxLayout" >
+            <property name="margin" >
+             <number>0</number>
+            </property>
+            <property name="spacing" >
+             <number>6</number>
+            </property>
+            <item>
+             <widget class="QLabel" name="lblAppData_2" >
+              <property name="text" >
+               <string>D&amp;ata</string>
+              </property>
+              <property name="buddy" >
+               <cstring>teAppData</cstring>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QTextEdit" name="teAppData" >
+              <property name="enabled" >
+               <bool>false</bool>
+              </property>
+              <property name="tabChangesFocus" >
+               <bool>true</bool>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </item>
+         </layout>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="atGroupBox" >
+     <property name="title" >
+      <string>Phonesim AT</string>
+     </property>
+     <layout class="QVBoxLayout" >
+      <property name="margin" >
+       <number>9</number>
+      </property>
+      <property name="spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <widget class="QTextBrowser" name="atViewer" />
+      </item>
+      <item>
+       <widget class="QPushButton" name="openSpecButton" >
+        <property name="text" >
+         <string>Open Specification File...</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <tabstops>
+  <tabstop>hsSignalQuality</tabstop>
+  <tabstop>hsBatteryCharge</tabstop>
+  <tabstop>leCaller</tabstop>
+  <tabstop>pbIncomingCall</tabstop>
+  <tabstop>leOperatorName</tabstop>
+  <tabstop>pbSelectOperator</tabstop>
+  <tabstop>cbRegistrationStatus</tabstop>
+  <tabstop>pbRegistration</tabstop>
+  <tabstop>chkLocationInfo</tabstop>
+  <tabstop>leLAC</tabstop>
+  <tabstop>leCellID</tabstop>
+  <tabstop>teContent</tabstop>
+  <tabstop>pbSendCellBroadcast</tabstop>
+  <tabstop>leMessageCode</tabstop>
+  <tabstop>leUpdateNumber</tabstop>
+  <tabstop>leChannel</tabstop>
+  <tabstop>cbLanguage</tabstop>
+  <tabstop>leScheme</tabstop>
+  <tabstop>leNumPages</tabstop>
+  <tabstop>lePage</tabstop>
+  <tabstop>cbGeographicalScope</tabstop>
+  <tabstop>teSMSText</tabstop>
+  <tabstop>leMessageSender</tabstop>
+  <tabstop>leSMSServiceCenter</tabstop>
+  <tabstop>pbSendSMSMessage</tabstop>
+  <tabstop>lePort</tabstop>
+  <tabstop>leDatagramSender</tabstop>
+  <tabstop>leFile</tabstop>
+  <tabstop>pbFile</tabstop>
+  <tabstop>pbSendSMSDatagram</tabstop>
+  <tabstop>chkAppData</tabstop>
+  <tabstop>teAppData</tabstop>
+  <tabstop>chkContentType</tabstop>
+  <tabstop>leContentType</tabstop>
+  <tabstop>tabWidget</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>chkLocationInfo</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>leLAC</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>139</x>
+     <y>495</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>248</x>
+     <y>463</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>chkLocationInfo</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>leCellID</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>116</x>
+     <y>495</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>312</x>
+     <y>463</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>chkAppData</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>teAppData</receiver>
+   <slot>setDisabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>120</x>
+     <y>458</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>373</x>
+     <y>385</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>chkContentType</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>leContentType</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>124</x>
+     <y>492</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>238</x>
+     <y>494</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>chkAppData</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>leFile</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>124</x>
+     <y>458</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>238</x>
+     <y>426</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>chkAppData</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>pbFile</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel" >
+     <x>82</x>
+     <y>438</y>
+    </hint>
+    <hint type="destinationlabel" >
+     <x>259</x>
+     <y>413</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

Added: trunk/src/host/qemu-neo1973/phonesim/gsm-xml.pl
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/gsm-xml.pl	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/gsm-xml.pl	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,136 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+#
+# Program to convert a GSM Specification into an xml data file
+#
+
+use Cwd;
+use File::Find;
+
+#
+# Iterate over the directory tree, looking for files containing test cases.
+#
+
+=head1 SYNOPSIS
+
+gen-report
+
+=head1 DESCRIPTION
+
+Generate reports of tests from html files
+=cut
+
+my $title_regex = qr/^[0-9.]+[0-9]+\s+[\w\s]+\+\w/ ;
+my $command_regex = qr/^[0-9.]+[0-9]+\s+[\w\s]+\+(.+)/ ;
+my $profile_regex = qr/^[0-9.]+[0-9]+\s+([\w\s]+)\+\w/ ;
+
+my $format_regex = qr/Table.+parameter command syntax/ ;
+my $responses_regex = qr/Possible responses/ ;
+my $description_regex = qr/Description\n+.*Implementation/ ;
+
+# total count of specs parsed
+my $spec_count = 0;
+my $inFile = "GSMSpecification.txt";
+my $outFile = "GSMSpecification.xml";
+
+open ( INFILE, $inFile ) or die "Couldn't open $inFile : $!";
+
+my $command;
+my $profile;
+my $format;
+my $response;
+my $description;
+my @commandlist;
+
+my $line;
+
+open(OUTFILE, ">$outFile") || die "Can't open $outFile : $!";
+print OUTFILE "<gsm>\n";
+
+while( defined ($line = <INFILE>) ){
+
+    $command = "";
+    $profile = "";
+    $format = "";
+    $response = "";
+    $description = "";
+    @commandlist = ();
+
+    if( $line =~ m/$title_regex/ ){
+
+        $line =~ /^[0-9.]+[0-9]+\s+([\w\s]+)\+(.*)[\s\n]*?/;
+        $command = $2;
+        $profile = $1;
+        chomp($command);
+        $command =~ s/\s//;
+        chomp($profile);
+
+        while( $line !~ /^Possible response\(s\)/ ){
+            $line = <INFILE>;
+        }
+
+        while( $line !~ /^Description/ ){
+            $line = <INFILE>;
+            if( $line !~ /:/ ){
+                if($line =~ /\+($command.*)/){
+                    my $commandString = $1;
+                    if($commandString =~ /\?/){
+                        $commandString =~ s/\?.*/?/;
+                    }elsif($commandString =~ /=/){
+                        $commandString =~ s/=.*/=/;
+                    }
+
+                    push( @commandlist, $commandString );
+                }
+            }
+        }
+
+        while( $line !~ /^Description/ ){
+            $line = <INFILE>;
+        }
+
+        if( $line =~ /^Description/ ){
+            $line = <INFILE>;
+            while( $line !~ /^Implementation/ ){
+                $description = $description.$line;
+                $line = <INFILE>;
+            }
+            $description =~ s/</[/g;
+            $description =~ s/>/]/g;
+            $description =~ s/"/'/g;
+            $description =~ s/&/:/g;
+
+            foreach my $commandItem(@commandlist){
+                print OUTFILE "<spec>\n";
+                print OUTFILE "    <command>AT+$commandItem</command>\n";
+                if( $commandItem =~ /=\?/ ){
+                    print OUTFILE "    <profile>$profile(Query all)</profile>\n";
+                }elsif($commandItem =~ /\?/){
+                    print OUTFILE "    <profile>$profile(Query)</profile>\n";
+                }elsif($commandItem =~ /=/){
+                    print OUTFILE "    <profile>$profile(Assign)</profile>\n";
+                }else{
+                    print OUTFILE "    <profile>$profile</profile>\n";
+                }
+                print OUTFILE "    <description>$description</description>\n";
+                print OUTFILE "</spec>\n";
+            }
+        }
+    }
+
+
+}
+
+
+
+print OUTFILE "</gsm>";
+
+
+close INFILE;
+close OUTFILE;
+
+print "Done\n\n\n\n";
+


Property changes on: trunk/src/host/qemu-neo1973/phonesim/gsm-xml.pl
___________________________________________________________________
Name: svn:executable
   + *

Added: trunk/src/host/qemu-neo1973/phonesim/gsmitem.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/gsmitem.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/gsmitem.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "gsmitem.h"
+
+GSMItem::GSMItem(const QString& comm, const QString& prof, const QStringList& farForm, const QStringList& respFormat, const QString& desc)
+{
+    command = comm;
+    profile = prof;
+    description = desc;
+    parameterFormat = farForm;
+    responses = respFormat;
+}
+
+GSMItem::GSMItem()
+{
+}
+
+QString GSMItem::getProfile()
+{
+    return profile;
+}
+
+
+QStringList GSMItem::getParameterFormat()
+{
+    return parameterFormat;
+}
+
+
+QStringList GSMItem::getResponseFormat()
+{
+    return responses;
+}
+
+QString GSMItem::getDescription()
+{
+    return description;
+}

Added: trunk/src/host/qemu-neo1973/phonesim/gsmitem.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/gsmitem.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/gsmitem.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef GSMITEM_H
+#define GSMITEM_H
+
+#include <QString>
+#include <QStringList>
+
+class GSMItem
+{
+
+public:
+    GSMItem(const QString&, const QString&, const QStringList&, const QStringList&, const QString&);
+    GSMItem();
+    QString getDescription();
+    QString getProfile();
+    QStringList getParameterFormat();
+    QStringList getResponseFormat();
+
+private:
+    QString command;
+    QString profile;
+    QStringList parameterFormat;
+    QStringList responses;
+    QString description;
+
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/gsmspec.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/gsmspec.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/gsmspec.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "gsmspec.h"
+#include <qdebug.h>
+
+GSMSpec::GSMSpec(const QString& specFile)
+{
+    setupDictionary(specFile);
+}
+
+
+QString GSMSpec::getProfile(const QString& command)
+{
+    if(commandExists(command)){
+        GSMItem gi = commandMap.value(command);
+        return gi.getProfile();
+    }else{
+        return "";
+    }
+}
+
+
+QStringList GSMSpec::getParameterFormat(const QString& command)
+{
+    if(commandExists(command)){
+        GSMItem gi = commandMap.value(command);
+        return gi.getParameterFormat();
+    }else{
+        return QStringList("format not available");
+    }
+}
+
+
+QStringList GSMSpec::getResponseFormat(const QString& command)
+{
+    if(commandExists(command)){
+        GSMItem gi = commandMap.value(command);
+        return gi.getParameterFormat();
+    }else{
+        return QStringList();
+    }
+}
+
+
+bool GSMSpec::commandExists(const QString& command)
+{
+    return commandMap.contains(command);
+}
+
+
+bool GSMSpec::validateCommand(QString format, QString pars)
+{
+    Q_UNUSED(pars);
+    QStringList formatList = format.split(",");
+    QStringList parsList = format.split(",");
+
+    if( formatList.size() == 0 && parsList.size() == 0 ){
+        return true;
+    }else if( true ){
+    }
+    return true; // TODO: Make useful
+}
+
+
+bool GSMSpec::validateResponse(QString format, QString pars)
+{
+    Q_UNUSED(pars);
+    QStringList formatList = format.split(",");
+    QStringList parsList = format.split(",");
+
+    if( formatList.size() == 0 && parsList.size() == 0 ){
+        return true;
+    }else if( true ){
+    }
+    return true; // TODO: Make useful
+}
+
+void GSMSpec::resetDictionary(const QString& filePath)
+{
+    if( QFile::exists(filePath) ){
+        setupDictionary(filePath);
+    }
+}
+
+void GSMSpec::setupDictionary(const QString& filePath)
+{
+
+    commandMap.clear();
+    QFile file(filePath);
+    QString line;
+    QStringList okList = QStringList("OK");
+
+    GsmXmlHandler *handler = new GsmXmlHandler();
+    QXmlSimpleReader *xmlReader = new QXmlSimpleReader();
+    xmlReader->setContentHandler( handler );
+
+    QXmlInputSource source( &file );
+
+    if( !xmlReader->parse(source) ){
+        qWarning() << "Failed to parse GSM xml file" ;
+        file.close();
+        return;
+    }
+    file.close();
+
+    GsmXmlNode *specNode = handler->documentElement()->children;
+    QString command, profile, format, response, description;
+
+    while ( specNode != 0 ) {
+        if ( specNode->tag == "spec" ) {
+
+            GsmXmlNode *specData = specNode->children;
+            while ( specData != 0 ) {
+
+                if( specData->tag == "command" ) {
+                    command = specData->contents;
+                }else if( specData->tag == "profile" ) {
+                    profile = specData->contents;
+                }else if( specData->tag == "format" ) {
+                    format = specData->contents;
+                }else if( specData->tag == "response" ) {
+                    response = specData->contents;
+                }else if( specData->tag == "description" ) {
+                    description = specData->contents;
+                }else{
+                    // not a valid entry
+                    break;
+                }
+                specData = specData->next;
+
+            }
+            // Add a phone simulator peer entry.
+            commandMap.insert( command, GSMItem(command, profile, format.split(";"), response.split(";"), description) );
+        }
+        specNode = specNode->next;
+    }
+    // Clean up the XML reader objects.
+    delete xmlReader;
+    delete handler;
+
+}
+
+GsmXmlNode::GsmXmlNode( const QString& _tag )
+{
+    parent = 0;
+    next = 0;
+    children = 0;
+    attributes = 0;
+    tag = _tag;
+}
+
+
+GsmXmlNode::~GsmXmlNode()
+{
+    GsmXmlNode *temp1, *temp2;
+    temp1 = children;
+    while ( temp1 ) {
+        temp2 = temp1->next;
+        delete temp1;
+        temp1 = temp2;
+    }
+    temp1 = attributes;
+    while ( temp1 ) {
+        temp2 = temp1->next;
+        delete temp1;
+        temp1 = temp2;
+    }
+}
+
+
+void GsmXmlNode::addChild( GsmXmlNode *child )
+{
+    GsmXmlNode *current = children;
+    GsmXmlNode *prev = 0;
+    while ( current ) {
+        prev = current;
+        current = current->next;
+    }
+    if ( prev ) {
+        prev->next = child;
+    } else {
+        children = child;
+    }
+    child->next = 0;
+    child->parent = this;
+}
+
+
+void GsmXmlNode::addAttribute( GsmXmlNode *child )
+{
+    GsmXmlNode *current = attributes;
+    GsmXmlNode *prev = 0;
+    while ( current ) {
+        prev = current;
+        current = current->next;
+    }
+    if ( prev ) {
+        prev->next = child;
+    } else {
+        attributes = child;
+    }
+    child->next = 0;
+    child->parent = this;
+}
+
+
+QString GsmXmlNode::getAttribute( const QString& name )
+{
+    GsmXmlNode *current = attributes;
+    while ( current ) {
+        if ( current->tag == name )
+            return current->contents;
+        current = current->next;
+    }
+    return QString();
+}
+
+
+GsmXmlHandler::GsmXmlHandler()
+{
+    tree = new GsmXmlNode( QString() );
+    current = tree;
+}
+
+
+GsmXmlHandler::~GsmXmlHandler()
+{
+    delete tree;
+}
+
+
+bool GsmXmlHandler::startElement( const QString&, const QString& localName, const QString&, const QXmlAttributes& atts )
+{
+    GsmXmlNode *node = new GsmXmlNode( localName );
+    GsmXmlNode *attr;
+    int index;
+    current->addChild( node );
+    for ( index = 0; index < atts.length(); ++index ) {
+        attr = new GsmXmlNode( atts.localName( index ) );
+        attr->contents = atts.value( index );
+        node->addAttribute( attr );
+    }
+    current = node;
+    return true;
+}
+
+
+bool GsmXmlHandler::endElement( const QString&, const QString& , const QString&)
+{
+    current = current->parent;
+    return true;
+}
+
+
+bool GsmXmlHandler::characters( const QString& ch )
+{
+    current->contents += ch;
+    return true;
+}
+
+
+bool GsmXmlHandler::ignorableWhitespace( const QString& ch )
+{
+    current->contents += ch;
+    return true;
+}
+
+
+GsmXmlNode *GsmXmlHandler::documentElement() const
+{
+    if ( tree->children && tree->children->tag == "gsm" ) {
+        return tree->children;
+    } else {
+        return tree;
+    }
+}

Added: trunk/src/host/qemu-neo1973/phonesim/gsmspec.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/gsmspec.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/gsmspec.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef GSMSPEC_H
+#define GSMSPEC_H
+
+#include <QString>
+#include <QMap>
+#include <QStringList>
+#include "gsmitem.h"
+#include <QFile>
+#include <QXmlSimpleReader>
+#include <QXmlInputSource>
+#include <QDir>
+
+class GsmXmlNode
+{
+public:
+    GsmXmlNode( const QString& tag );
+    ~GsmXmlNode();
+
+    GsmXmlNode *parent, *next, *children, *attributes;
+    QString tag;
+    QString contents;
+
+    void addChild( GsmXmlNode *child );
+    void addAttribute( GsmXmlNode *child );
+    QString getAttribute( const QString& name );
+};
+
+
+class GsmXmlHandler : public QXmlDefaultHandler
+{
+public:
+    GsmXmlHandler();
+    ~GsmXmlHandler();
+
+    bool startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts );
+    bool endElement( const QString& namespaceURI, const QString& localName, const QString& qName );
+    bool characters( const QString& ch );
+    bool ignorableWhitespace( const QString& ch );
+
+    GsmXmlNode *documentElement() const;
+
+private:
+    GsmXmlNode *tree;
+    GsmXmlNode *current;
+};
+
+class GSMSpec
+{
+
+public:
+    GSMSpec(const QString& specFile);
+    bool commandExists(const QString&);
+    QString getDescription(const QString&);
+    QString getProfile(const QString&);
+    QStringList getParameterFormat(const QString&);
+    QStringList getResponseFormat(const QString&);
+
+    bool validateCommand(QString format, QString pars);
+    bool validateResponse(QString format, QString pars);
+    void resetDictionary( const QString& );
+
+private:
+    QMap<QString, GSMItem> commandMap;
+    GSMItem getGSMItem( const QString& );
+    void setupDictionary( const QString& );
+    //GSMItem createGSMItem( QString command, QString profile, QStringList pars, QStringList resps );
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/DESCRIPTION
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/DESCRIPTION	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/DESCRIPTION	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1 @@
+Core parts of the Phone simulator.

Added: trunk/src/host/qemu-neo1973/phonesim/lib/callmanager.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/callmanager.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/callmanager.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,775 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "callmanager.h"
+#include <qatutils.h>
+#include <qsimcontrolevent.h>
+
+CallManager::CallManager( QObject *parent )
+    : QObject( parent )
+{
+    _holdWillFail = false;
+    _activateWillFail = false;
+    _joinWillFail = false;
+    _deflectWillFail = false;
+    _multipartyLimit = -1;
+    numRings = 0;
+
+    connectTimer = new QTimer(this);
+    connectTimer->setSingleShot(true);
+    connect( connectTimer, SIGNAL(timeout()), this, SLOT(dialingToConnected()) );
+
+    alertingTimer = new QTimer(this);
+    alertingTimer->setSingleShot(true);
+    connect( alertingTimer, SIGNAL(timeout()), this, SLOT(dialingToAlerting()) );
+
+    hangupTimer = new QTimer(this);
+    hangupTimer->setSingleShot(true);
+    connect( hangupTimer, SIGNAL(timeout()), this, SLOT(hangupTimeout()) );
+
+    ringTimer = new QTimer(this);
+    ringTimer->setSingleShot(true);
+    connect( ringTimer, SIGNAL(timeout()), this, SLOT(sendNextRing()) );
+}
+
+CallManager::~CallManager()
+{
+}
+
+bool CallManager::command( const QString& cmd )
+{
+    if ( cmd.startsWith( "ATD*" ) || cmd.startsWith( "ATD#" ) ) {
+
+        // Supplementary service request - just say OK for now.
+        emit send( "OK" );
+
+    } else if ( cmd.startsWith( "ATD" ) && cmd.endsWith( ";" ) ) {
+
+        // Voice call setup.
+        QString number = cmd.mid(3, cmd.length() - 4);
+        if ( number.endsWith( "g" ) || number.endsWith( "g" ) )
+            number = number.left(number.length() - 1);  // Closed user group flag - skip.
+        if ( number.endsWith( "i" ) || number.endsWith( "I" ) )
+            number = number.left(number.length() - 1);  // Caller id suppress flag - skip.
+
+        // Determine if the number is blocked by the fixed-dialing phone book.
+        bool dialCheckOk = true;
+        emit dialCheck( number, dialCheckOk );
+        if ( !dialCheckOk ) {
+            emit send( "ERROR" );
+            return true;
+        }
+
+        // Stop if a dialing call is already in progress, or there are both
+        // connected and held calls at the same time.
+        if ( hasCall( CallState_Dialing ) || hasCall( CallState_Alerting ) ) {
+            emit send( "ERROR" );
+            return true;
+        }
+        if ( hasCall( CallState_Active ) && hasCall( CallState_Held ) ) {
+            emit send( "ERROR" );
+            return true;
+        }
+
+        // If there is a connected call, place it on hold.
+        changeGroup( CallState_Active, CallState_Held );
+
+        // Check for special dial-back numbers.
+        if ( number == "199" ) {
+            send( "NO CARRIER" );
+            QTimer::singleShot( 5000, this, SLOT(dialBack()) );
+            return true;
+        } else if ( number == "1993" ) {
+            send( "NO CARRIER" );
+            QTimer::singleShot( 30000, this, SLOT(dialBack()) );
+            return true;
+        } else if ( number == "177" ) {
+            send( "NO CARRIER" );
+            QTimer::singleShot( 2000, this, SLOT(dialBackWithHangup5()) );
+            return true;
+        } else if ( number == "166" ) {
+            send( "NO CARRIER" );
+            QTimer::singleShot( 1000, this, SLOT(dialBackWithHangup4()) );
+            return true;
+        } else if ( number == "155" ) {
+            send( "BUSY" );
+            return true;
+        }
+
+        // Perform call control on certain numbers.
+        if ( number == "12399" ) {
+            QSimControlEvent event;
+            event.setType( QSimControlEvent::Call );
+            event.setResult( QSimControlEvent::Allowed );
+            event.setText( "12399 allowed by call control" );
+            emit controlEvent( event );
+        } else if ( number == "12388" ) {
+            QSimControlEvent event;
+            event.setType( QSimControlEvent::Call );
+            event.setResult( QSimControlEvent::AllowedWithModifications );
+            event.setText( "12388 allowed, but modified to 12389" );
+            number = "12389";
+            emit controlEvent( event );
+        } else if ( number == "12377" ) {
+            QSimControlEvent event;
+            event.setType( QSimControlEvent::Call );
+            event.setResult( QSimControlEvent::NotAllowed );
+            event.setText( "12377 disallowed by call control" );
+            send( "NO CARRIER" );
+            emit controlEvent( event );
+            return true;
+        }
+
+        // Create a new call and add it to the list.
+        CallInfo info;
+        info.id = newId();
+        info.state = CallState_Dialing;
+        info.number = number;
+        info.incoming = false;
+        info.dialBack = false;
+        callList += info;
+
+        // Advertise the call state change and then return to command mode.
+        sendState( info );
+        send( "OK" );
+
+        // Start timers to transition the dialing call to alerting and connected.
+        alertingTimer->start(2500);
+        connectTimer->start(3000);
+
+    } else if ( cmd.startsWith( "ATD" ) ) {
+
+        // Data call setup - not supported at present.
+        emit send( "NO CARRIER" );
+
+    } else if ( cmd == "AT+CLCC" ) {
+
+        // List all calls that are presently active.
+        foreach ( CallInfo info, callList ) {
+            int multiparty;
+            if ( countForState(info.state) >= 2 )
+                multiparty = 1;
+            else
+                multiparty = 0;
+            QString line =
+                "+CLCC: " + QString::number(info.id) + "," +
+                QString::number((int)(info.incoming)) + "," +
+                QString::number((int)(info.state)) + ",0," +
+                QString::number(multiparty);
+            if ( !info.number.isEmpty() ) {
+                line += ",";
+                line += QAtUtils::encodeNumber(info.number);
+            }
+            send( line );
+        }
+        send( "OK" );
+
+    } else if ( cmd.startsWith( "ATH" ) || cmd == "AT+CHUP" ) {
+
+        // Hang up all active and held calls in the system.
+        hangupAll();
+        send( "OK" );
+
+    } else if ( cmd == "AT+CHLD=0" ) {
+
+        // Reject incoming call, or release held calls.
+        if ( chld0() )
+            send( "OK" );
+        else
+            send( "ERROR" );
+
+    } else if ( cmd == "AT+CHLD=1" ) {
+
+        // Release all active calls and accept the held or waiting ones.
+        if ( chld1() )
+            send( "OK" );
+        else
+            send( "ERROR" );
+
+    } else if ( cmd.startsWith( "AT+CHLD=1" ) ) {
+
+        // Release a specific call.
+        if ( chld1x( cmd.mid(9).toInt() ) )
+            send( "OK" );
+        else
+            send( "ERROR" );
+
+    } else if ( cmd == "AT+CHLD=2" ) {
+
+        // Place active calls on hold and accept the held or waiting call.
+        if ( chld2() )
+            send( "OK" );
+        else
+            send( "ERROR" );
+
+    } else if ( cmd.startsWith( "AT+CHLD=2" ) ) {
+
+        // Place all active calls on hold except for the specified call.
+        if ( chld2x( cmd.mid(9).toInt() ) )
+            send( "OK" );
+        else
+            send( "ERROR" );
+
+    } else if ( cmd == "AT+CHLD=3" ) {
+
+        // Add a held call to the conversation.
+        if ( chld3() )
+            send( "OK" );
+        else
+            send( "ERROR" );
+
+    } else if ( cmd == "AT+CHLD=4" ) {
+
+        // Add a held call to the conversation, and then disconnect.
+        if ( chld4() )
+            send( "OK" );
+        else
+            send( "ERROR" );
+
+    } else if ( cmd == "ATA" ) {
+
+        // Accept the incoming call.
+        if ( acceptCall() )
+            send( "OK" );
+        else
+            send( "ERROR" );
+
+    } else if ( cmd.startsWith( "AT+CTFR=" ) ) {
+
+        // Deflect the incoming call to another number.
+        int id = idForIncoming();
+        if ( id >= 0 && !deflectWillFail() ) {
+            hangupCall(id);
+            hangupTimer->stop();
+            ringTimer->stop();
+            send( "OK" );
+        } else {
+            send( "ERROR" );
+        }
+
+    } else {
+        // Command is not understood by the call manager.
+        return false;
+    }
+
+    // If we get here, then the command was understood.
+    return true;
+}
+
+void CallManager::startIncomingCall( const QString& number, bool dialBack )
+{
+    // Bail out if there is already an incoming call.
+    if ( idForIncoming() >= 0 ) {
+        qWarning( "Incoming call already exists - connect create another" );
+        return;
+    }
+
+    // Create a new call and add it to the list.
+    CallInfo info;
+    info.id = newId();
+    if ( hasCall( CallState_Active ) || hasCall( CallState_Held ) ) {
+        // If there are active calls, the call state is "waiting", not "incoming".
+        info.state = CallState_Waiting;
+    } else {
+        info.state = CallState_Incoming;
+    }
+    info.number = number;
+    info.incoming = true;
+    info.dialBack = dialBack;
+    callList += info;
+
+    // Annouce the incoming call using GSM 27.007 notifications.
+    if ( info.state == CallState_Waiting ) {
+        emit unsolicited( "+CCWA: " + QAtUtils::encodeNumber( number ) + ",1" );
+    } else {
+        emit unsolicited( "RING\n+CLIP: " + QAtUtils::encodeNumber( number ) );
+    }
+
+    // Announce the incoming call using Ericsson-style state notifications.
+    sendState( info );
+
+    // Start the ring timer to periodically send RING notifications until call is accepted.
+    numRings = 0;
+    ringTimer->start(2000);
+}
+
+void CallManager::startIncomingCall( const QString& number )
+{
+    startIncomingCall( number, false );
+}
+
+void CallManager::hangupAll()
+{
+    for ( int index = 0; index < callList.size(); ++index ) {
+        callList[index].state = CallState_Hangup;
+        sendState( callList[index] );
+    }
+    callList.clear();
+    connectTimer->stop();
+    alertingTimer->stop();
+    hangupTimer->stop();
+}
+
+void CallManager::hangupConnected()
+{
+    QList<CallInfo> newCallList;
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].state == CallState_Active ) {
+            callList[index].state = CallState_Hangup;
+            sendState( callList[index] );
+        } else {
+            newCallList += callList[index];
+        }
+    }
+    callList = newCallList;
+}
+
+void CallManager::hangupHeld()
+{
+    QList<CallInfo> newCallList;
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].state == CallState_Held ) {
+            callList[index].state = CallState_Hangup;
+            sendState( callList[index] );
+        } else {
+            newCallList += callList[index];
+        }
+    }
+    callList = newCallList;
+}
+
+void CallManager::hangupConnectedAndHeld()
+{
+    QList<CallInfo> newCallList;
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].state == CallState_Active ||
+             callList[index].state == CallState_Held ) {
+            callList[index].state = CallState_Hangup;
+            sendState( callList[index] );
+        } else {
+            newCallList += callList[index];
+        }
+    }
+    callList = newCallList;
+}
+
+void CallManager::hangupCall( int id )
+{
+    chld1x( id );
+}
+
+bool CallManager::acceptCall()
+{
+    int id = idForIncoming();
+    int index = indexForId(id);
+    if ( id < 0 ) {
+        return false;
+    } else if ( hasCall( CallState_Active ) && hasCall( CallState_Held ) ) {
+        // No open slots to accept the call - fail it.  AT+CHLD=1 must be used instead.
+        return false;
+    } else if ( hasCall( CallState_Active ) ) {
+        // Put the active calls on hold and accept the incoming call.
+        changeGroup( CallState_Active, CallState_Held );
+        callList[index].state = CallState_Active;
+        sendState( callList[index] );
+        return true;
+    } else {
+        // Only held calls, or no other calls, so just make the incoming call active.
+        callList[index].state = CallState_Active;
+        sendState( callList[index] );
+        return true;
+    }
+}
+
+bool CallManager::chld0()
+{
+    // If there is an incoming call, then that is the one to hang up.
+    int id = idForIncoming();
+    if ( id >= 0 )
+        return chld1x( id );
+
+    // Bail out if no held calls.
+    if ( !hasCall( CallState_Held ) )
+        return false;
+
+    // Hang up the held calls.
+    hangupHeld();
+    return true;
+}
+
+bool CallManager::chld1()
+{
+    int id = idForIncoming();
+    if ( id >= 0 ) {
+        // Hangup the active calls and then make the incoming call active.
+        hangupConnected();
+        int index = indexForId(id);
+        callList[index].state = CallState_Active;
+        sendState( callList[index] );
+        return true;
+    } else if ( hasCall( CallState_Held ) ) {
+        // Hangup the active calls and activate the held ones.
+        hangupConnected();
+        for ( int index = 0; index < callList.size(); ++index ) {
+            if ( callList[index].state == CallState_Held ) {
+                callList[index].state = CallState_Active;
+                sendState( callList[index] );
+            }
+        }
+        return true;
+    } else if ( hasCall( CallState_Active ) ) {
+        // We only have active calls - hang them up.
+        hangupConnected();
+        return true;
+    } else if ( hasCall( CallState_Active ) ) {
+        // We only have active calls - hang them up.
+        hangupConnected();
+        return true;
+    } else if ( ( id = idForDialing() ) >= 0 ) {
+        // We have a dialing call.
+        hangupCall(id);
+        connectTimer->stop();
+        alertingTimer->stop();
+        hangupTimer->stop();
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool CallManager::chld1x( int x )
+{
+    QList<CallInfo> newCallList;
+    bool found = false;
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].id == x ) {
+            if ( callList[index].state == CallState_Dialing ||
+                 callList[index].state == CallState_Alerting ) {
+                connectTimer->stop();
+                alertingTimer->stop();
+                hangupTimer->stop();
+            }
+            callList[index].state = CallState_Hangup;
+            sendState( callList[index] );
+            found = true;
+        } else {
+            newCallList += callList[index];
+        }
+    }
+    callList = newCallList;
+    return found;
+}
+
+bool CallManager::chld2()
+{
+    int id = idForIncoming();
+    if ( id >= 0 ) {
+        if ( hasCall( CallState_Active ) && hasCall( CallState_Held ) ) {
+            // Three-way calling situation: cannot do anything.
+            return false;
+        }
+        if ( holdWillFail() && hasCall( CallState_Active ) ) {
+            // Cannot put calls on hold at this time.
+            return false;
+        }
+        changeGroup( CallState_Active, CallState_Held );
+        int index = indexForId( id );
+        callList[index].state = CallState_Active;
+        sendState( callList[index] );
+        return true;
+    } else if ( hasCall( CallState_Active ) && hasCall( CallState_Held ) ) {
+        // Swap the active and held calls.
+        if ( activateWillFail() || holdWillFail() )
+            return false;
+        changeGroup( CallState_Active, CallState_SwapDummy );
+        changeGroup( CallState_Held, CallState_Active );
+        changeGroup( CallState_SwapDummy, CallState_Held );
+        return true;
+    } else if ( hasCall( CallState_Active ) ) {
+        // No held calls - put active calls on hold.
+        if ( holdWillFail() )
+            return false;
+        changeGroup( CallState_Active, CallState_Held );
+        return true;
+    } else if ( hasCall( CallState_Held ) ) {
+        // Re-activate the held calls.
+        if ( activateWillFail() )
+            return false;
+        changeGroup( CallState_Held, CallState_Active );
+        return true;
+    } else {
+        // No held or active calls - cannot do anything.
+        return false;
+    }
+}
+
+bool CallManager::chld2x( int x )
+{
+    int index = indexForId(x);
+    if ( index < 0 )
+        return false;
+    if ( callList[index].state == CallState_Held ) {
+        // Call is currently on hold - activate it.
+        if ( activateWillFail() )
+            return false;
+        if ( hasCall( CallState_Active ) && countForState( CallState_Held ) > 1 ) {
+            // Cannot swap because there are active calls, but multiple held calls.
+            return false;
+        } else if ( hasCall( CallState_Active ) ) {
+            // Swap active and held calls.
+            if ( holdWillFail() )
+                return false;
+            changeGroup( CallState_Active, CallState_SwapDummy );
+            changeGroup( CallState_Held, CallState_Active );
+            changeGroup( CallState_SwapDummy, CallState_Held );
+        } else {
+            // No active calls, so make just this call active.
+            callList[index].state = CallState_Active;
+            sendState( callList[index] );
+        }
+        return true;
+    } else if ( callList[index].state == CallState_Active ) {
+        // Call is currently active - put all others in the active group on hold.
+        if ( activateWillFail() )
+            return false;
+        if ( hasCall( CallState_Held ) )
+            return false;       // Can't do this if there is already a hold group.
+        for ( int index2 = 0; index2 < callList.size(); ++index2 ) {
+            if ( callList[index2].state == CallState_Active && index2 != index ) {
+                if ( holdWillFail() )
+                    return false;
+                callList[index2].state = CallState_Held;
+                sendState( callList[index2] );
+            }
+        }
+        return true;
+    } else {
+        // Not held or active.
+        return false;
+    }
+}
+
+bool CallManager::chld3()
+{
+    if ( joinWillFail() ) {
+        return false;
+    } else if ( hasCall( CallState_Active ) && hasCall( CallState_Held ) ) {
+        if ( multipartyLimit() >= 0 &&
+             ( countForState( CallState_Active ) +
+               countForState( CallState_Held ) ) > multipartyLimit() ) {
+            // We have exceeded the multiparty limit.
+            return false;
+        }
+        changeGroup( CallState_Held, CallState_Active );
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool CallManager::chld4()
+{
+    if ( joinWillFail() ) {
+        return false;
+    } else if ( hasCall( CallState_Active ) && hasCall( CallState_Held ) ) {
+        if ( multipartyLimit() >= 0 &&
+             ( countForState( CallState_Active ) +
+               countForState( CallState_Held ) ) > multipartyLimit() ) {
+            // We have exceeded the multiparty limit.
+            return false;
+        }
+        hangupConnectedAndHeld();
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void CallManager::dialingToConnected()
+{
+    // Find the currently dialing or alerting call.
+    int index = indexForId( idForState( CallState_Dialing ) );
+    if ( index < 0 )
+        index = indexForId( idForState( CallState_Alerting ) );
+    if ( index < 0 )
+        return;
+
+    // Transition the call to its new state.
+    callList[index].state = CallState_Active;
+    sendState( callList[index] );
+}
+
+void CallManager::dialingToAlerting()
+{
+    // Find the currently dialing or alerting call.
+    int index = indexForId( idForState( CallState_Dialing ) );
+    if ( index < 0 )
+        return;
+
+    // Transition the call to its new state.
+    callList[index].state = CallState_Alerting;
+    sendState( callList[index] );
+}
+
+void CallManager::dialBack()
+{
+    startIncomingCall( "1234567", true );
+}
+
+void CallManager::dialBackWithHangup5()
+{
+    startIncomingCall( "1234567", true );
+    hangupTimer->start( 5000 );
+}
+
+void CallManager::dialBackWithHangup4()
+{
+    startIncomingCall( "1234567", true );
+    hangupTimer->start( 4000 );
+}
+
+void CallManager::hangupTimeout()
+{
+    // Find the call that started off as incoming, even if it isn't any longer.
+    // Note: this won't work too well if there are multiple dial-back calls.
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].dialBack ) {
+            hangupCall( callList[index].id );
+            break;
+        }
+    }
+}
+
+void CallManager::sendNextRing()
+{
+    if ( idForIncoming() >= 0 ) {
+        if ( numRings++ >= 4 ) {
+            // Ringing for too long, so hang up the call.
+            hangupCall( idForIncoming() );
+        } else {
+            emit unsolicited( "RING" );
+            ringTimer->start(2000);
+        }
+    }
+}
+
+int CallManager::newId()
+{
+    int id;
+    bool seen;
+    for ( id = 1; id <= 32; ++id ) {
+        seen = false;
+        foreach ( CallInfo info, callList ) {
+            if ( info.id == id ) {
+                seen = true;
+                break;
+            }
+        }
+        if ( !seen )
+            return id;
+    }
+    return -1;
+}
+
+int CallManager::idForDialing()
+{
+    int id = idForState( CallState_Dialing );
+    if ( id < 0 )
+        id = idForState( CallState_Alerting );
+    return id;
+}
+
+int CallManager::idForIncoming()
+{
+    int id = idForState( CallState_Incoming );
+    if ( id < 0 )
+        id = idForState( CallState_Waiting );
+    return id;
+}
+
+int CallManager::idForState( CallState state )
+{
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].state == state )
+            return callList[index].id;
+    }
+    return -1;
+}
+
+int CallManager::countForState( CallState state )
+{
+    int count = 0;
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].state == state )
+            ++count;
+    }
+    return count;
+}
+
+int CallManager::indexForId( int id )
+{
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].id == id )
+            return index;
+    }
+    return -1;
+}
+
+bool CallManager::hasCall( CallState state )
+{
+    foreach ( CallInfo info, callList ) {
+        if ( info.state == state )
+            return true;
+    }
+    return false;
+}
+
+void CallManager::changeGroup( CallState oldState, CallState newState )
+{
+    for ( int index = 0; index < callList.size(); ++index ) {
+        if ( callList[index].state == oldState ) {
+            callList[index].state = newState;
+            sendState( callList[index] );
+        }
+    }
+}
+
+void CallManager::sendState( const CallInfo& info )
+{
+    static int const stateMap[] = {3, 4, 1, 6, 5, 5, 0, 0};
+    if ( info.state == CallState_SwapDummy )
+        return;     // In the middle of a state swap: don't send this.
+    QString line =
+        "*ECAV: " + QString::number(info.id) + "," +
+        QString::number(stateMap[(int)(info.state)]) + ",0";
+    if ( !info.number.isEmpty() ) {
+        line += ",,," + QAtUtils::encodeNumber(info.number);
+    }
+    if ( info.state == CallState_Incoming || info.state == CallState_Waiting ) {
+        // Stop sending RING notifications.
+        ringTimer->stop();
+    }
+    if ( info.state == CallState_Hangup && info.dialBack ) {
+        // Hanging up an incoming call that started as a dialback.  Stop hangup timer.
+        hangupTimer->stop();
+    }
+    emit unsolicited( line );
+}

Added: trunk/src/host/qemu-neo1973/phonesim/lib/callmanager.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/callmanager.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/callmanager.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef CALLMANAGER_H
+#define CALLMANAGER_H
+
+#include "phonesim.h"
+
+enum CallState
+{
+    CallState_Active        = 0,
+    CallState_Held          = 1,
+    CallState_Dialing       = 2,
+    CallState_Alerting      = 3,
+    CallState_Incoming      = 4,
+    CallState_Waiting       = 5,
+    CallState_Hangup        = 6,      // Call about to go away.
+    CallState_SwapDummy     = 7       // Used internally in phonesim only.
+};
+
+struct CallInfo
+{
+    int         id;
+    CallState   state;
+    QString     number;
+    bool        incoming;
+    bool        dialBack;
+};
+
+class QSimControlEvent;
+
+class CallManager : public QObject
+{
+    Q_OBJECT
+public:
+    CallManager( QObject *parent = 0 );
+    ~CallManager();
+
+    // Process an AT command.  Returns false if not a call-related command.
+    bool command( const QString& cmd );
+
+    // Get the active call list.
+    QList<CallInfo> calls() const { return callList; }
+
+    // Hangup calls.
+    void hangupAll();
+    void hangupConnected();
+    void hangupHeld();
+    void hangupConnectedAndHeld();
+    void hangupCall( int id );
+
+    // Accept the incoming call.
+    bool acceptCall();
+
+    // Primitive GSM 22.030 call operations with AT+CHLD.
+    bool chld0();
+    bool chld1();
+    bool chld1x( int x );
+    bool chld2();
+    bool chld2x( int x );
+    bool chld3();
+    bool chld4();
+
+    // Adjust whether various commands will fail even if they would normally succeed.
+    bool holdWillFail() const { return _holdWillFail; }
+    void setHoldWillFail( bool value ) { _holdWillFail = value; }
+    bool activateWillFail() const { return _activateWillFail; }
+    void setActivateWillFail( bool value ) { _activateWillFail = value; }
+    bool joinWillFail() const { return _joinWillFail; }
+    void setJoinWillFail( bool value ) { _joinWillFail = value; }
+    bool deflectWillFail() const { return _deflectWillFail; }
+    void setDeflectWillFail( bool value ) { _deflectWillFail = value; }
+
+    // Get or set the maximum number of participants in a multiparty (-1 means unlimited).
+    int multipartyLimit() const { return _multipartyLimit; }
+    void setMultipartyLimit( int value ) { _multipartyLimit = value; }
+
+public slots:
+    // Start an incoming call simulation.
+    void startIncomingCall( const QString& number, bool dialBack );
+    void startIncomingCall( const QString& number );
+
+signals:
+    // Send a response to a command.
+    void send( const QString& line );
+
+    // Send an unsolicited notification related to calls.
+    void unsolicited( const QString& line );
+
+    // Verify a phone number to see if dialing is allowed.
+    // Set "ok" to false if the number should be disallowed.
+    void dialCheck( const QString& number, bool& ok );
+
+    // Send a call control event.
+    void controlEvent( const QSimControlEvent& event );
+
+private slots:
+    // Transition the active dialing or alerting call to connected.
+    void dialingToConnected();
+
+    // Transition the active dialing call to alerting.
+    void dialingToAlerting();
+
+    // Handle dial-backs.
+    void dialBack();
+    void dialBackWithHangup5();
+    void dialBackWithHangup4();
+
+    // Hangup after a dial-back timeout.
+    void hangupTimeout();
+
+    // Send the next RING indication for incoming calls.
+    void sendNextRing();
+
+private:
+    QList<CallInfo> callList;
+    QTimer *connectTimer;
+    QTimer *alertingTimer;
+    QTimer *hangupTimer;
+    QTimer *ringTimer;
+    bool _holdWillFail;
+    bool _activateWillFail;
+    bool _joinWillFail;
+    bool _deflectWillFail;
+    int _multipartyLimit;
+    int numRings;
+
+    int newId();
+    int idForDialing();
+    int idForIncoming();
+    int idForState( CallState state );
+    int countForState( CallState state );
+    int indexForId( int id );
+    bool hasCall( CallState state );
+    void changeGroup( CallState oldState, CallState newState );
+    void sendState( const CallInfo& info );
+};
+
+#endif /* CALLMANAGER_H */

Added: trunk/src/host/qemu-neo1973/phonesim/lib/hardwaremanipulator.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/hardwaremanipulator.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/hardwaremanipulator.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "hardwaremanipulator.h"
+#include <QtGui/qmessagebox.h>
+#include <Qt>
+#include <qdebug.h>
+#include <qbuffer.h>
+#include <qtimer.h>
+#include <qevent.h>
+#include "qsmsmessage.h"
+#include "qcbsmessage.h"
+#include "serial/qgsmcodec.h"
+#include "wap/qwsppdu.h"
+
+#define NIBBLE_MAX 15
+#define TWO_BYTE_MAX 65535
+#define THREE_BYTE_MAX 16777215
+#define PORT_MAX 999999;//arbitrary value
+#define FOUR_CHAR 4
+#define SIX_CHAR 6
+#define ONE_CHAR 1
+#define HEX_BASE 16
+
+HardwareManipulator::HardwareManipulator(QWidget *parent)
+        : QWidget(parent)
+{
+}
+
+
+QSMSMessageList & HardwareManipulator::getSMSList()
+{
+    return SMSList;
+}
+
+bool HardwareManipulator::shouldShow() const
+{
+    return false;
+}
+
+void HardwareManipulator::closeEvent(QCloseEvent *e)
+{
+    e->ignore();
+    this->hide();
+}
+
+QString PS_toHex( const QByteArray& binary );
+
+#define WARNING(A, B) \
+do {\
+    if (shouldShow()) {\
+        QMessageBox::warning(this, A, B);\
+    } else {\
+        qWarning() << (A) << ":" << (B);\
+    }\
+} while(0)
+
+QString HardwareManipulator::constructCBMessage(const QString &messageCode, int geographicalScope, const QString &updateNumber,
+    const QString &channel, const QString &/*scheme*/, int language, const QString &numPages, const QString &page, const QString &content)
+{
+
+    bool ok;
+    uint mc = convertString(messageCode,1023,3,HEX_BASE, &ok);
+    if ( !ok ) {
+        WARNING(tr("Invalid Message Code"),
+                tr("Message code 3 hex digits long and no larger than 3FF"));
+        return "";
+    }
+
+
+    QCBSMessage::GeographicalScope gs = (QCBSMessage::GeographicalScope)geographicalScope;
+
+    uint un = convertString(updateNumber,NIBBLE_MAX,ONE_CHAR,HEX_BASE,&ok);
+    if ( !ok ) {
+        WARNING(tr("Invalid Update Number"),
+                tr("Update number must be 1 hex digit long"
+                   "and no larger than F"));
+        return "";
+    }
+
+
+    uint ch = convertString(channel, TWO_BYTE_MAX,FOUR_CHAR,HEX_BASE,&ok);
+    if ( !ok ) {
+        WARNING(tr("Invalid Channel,"),
+                tr("Channel  must be 4 hex digits long "
+                   "and no larger than FFFF"));
+        return "";
+    }
+
+    //scheme is currently hardcoded to QSMS8_BitCodingScheme
+    //uint sch = convertString(scheme, NIBBLE_MAX, ONE_CHAR,HEX_BASE,&ok);
+    //if ( !ok )
+    //    return "";
+
+    QCBSMessage::Language lang = (QCBSMessage::Language)language;
+
+    uint npag = convertString(numPages, NIBBLE_MAX,ONE_CHAR,HEX_BASE,&ok);
+    if ( !ok ) {
+        WARNING(tr("Invalid number of pages,"),
+                tr("Number of pages  must be 1 hex digit long "
+                   "and no larger than F"));
+        return "";
+    }
+
+    uint pag = convertString(page, NIBBLE_MAX,ONE_CHAR,HEX_BASE,&ok);
+    if ( !ok ) {
+        WARNING(tr("Invalid page number,"),
+                tr("Page number  must be 1 hex digit long "
+                   "and no larger than F"));
+        return "";
+    }
+
+    QCBSMessage m;
+    m.setMessageCode(mc);
+    m.setScope(gs);
+    m.setUpdateNumber(un);
+    m.setChannel(ch);
+    m.setLanguage(lang);
+    m.setNumPages(npag);
+    m.setPage(pag);
+    m.setText(content);
+
+    return PS_toHex( m.toPdu() );
+}
+
+void HardwareManipulator::constructSMSMessage( const QString &sender, const QString &serviceCenter, const QString &text )
+{
+    QSMSMessage m;
+    if ( sender.contains(QRegExp("\\D")) ) {
+        WARNING(tr("Invalid Sender"),
+                tr("Sender must not be empty and contain "
+                   "only digits"));
+        return;
+    }
+    m.setSender(sender);
+
+    if ( serviceCenter.contains(QRegExp("\\D")) ) {
+        WARNING(tr("Invalid Service Center"),
+                tr("Service Center must not be empty and contain "
+                   "only digits"));
+        return;
+    }
+    m.setServiceCenter(serviceCenter);
+
+    m.setText(text);
+    m.setTimestamp(QDateTime::currentDateTime());
+
+    SMSList.appendSMS( m.toPdu() );
+}
+
+void HardwareManipulator::constructSMSDatagram(int port, const QString &sender, const QByteArray &data,
+                                               const QByteArray &contentType)
+{
+    QWspPush pdu;
+    pdu.setIdentifier(0);
+    pdu.setPduType(6);
+
+    pdu.setData(data.data(),data.length());
+
+    QBuffer buffer;
+    buffer.open(QBuffer::ReadWrite);
+    QWspPduEncoder encoder(&buffer);
+
+    if ( contentType.length() != 0 ) {
+        pdu.addHeader("Content-Type", contentType);
+        encoder.encodePush(pdu);
+    } else {
+        pdu.writeData(&buffer);
+    }
+    QByteArray appData = buffer.buffer();
+    buffer.close();
+
+    QSMSMessage m;
+    m.setDestinationPort(port);
+    m.setSender(sender);
+    m.setApplicationData(appData);
+
+    if( m.shouldSplit() ) {
+        QList<QSMSMessage> list = m.split();
+
+        for( int i =0; i < list.count(); i++ ) {
+           SMSList.appendSMS( list[i].toPdu() );
+        }
+    } else {
+        SMSList.appendSMS( m.toPdu() );
+    }
+}
+
+int HardwareManipulator::convertString(const QString &number, int maxValue, int numChar, int base, bool *ok)
+{
+    bool b;
+    int num = number.toInt(&b, base);
+
+    *ok = true;
+    if ( !b || num < 0 || num > maxValue || number.size() != numChar ) {
+        *ok = false;
+    }
+    return num;
+}
+
+void HardwareManipulator::handleFromData( const QString& cmd )
+{
+}
+
+void HardwareManipulator::handleToData( const QString& cmd )
+{
+}

Added: trunk/src/host/qemu-neo1973/phonesim/lib/hardwaremanipulator.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/hardwaremanipulator.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/hardwaremanipulator.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef HARDWAREMANIPULATOR_H
+#define HARDWAREMANIPULATOR_H
+
+#include <qwidget.h>
+
+#include "qsmsmessagelist.h"
+
+class HardwareManipulator : public QWidget
+{
+Q_OBJECT
+
+public:
+    HardwareManipulator(QWidget *parent=0);
+    QSMSMessageList & getSMSList();
+    virtual bool shouldShow() const;
+
+public slots:
+    virtual void handleFromData( const QString& );
+    virtual void handleToData( const QString& );
+
+signals:
+    void unsolicitedCommand(const QString &cmd);
+    void command(const QString &cmd);
+    void variableChanged(const QString &n, const QString &v);
+    void switchTo(const QString &cmd);
+    void startIncomingCall(const QString &number);
+
+protected:
+    virtual void closeEvent(QCloseEvent *e);
+
+    virtual QString constructCBMessage(const QString &messageCode, int geographicalScope, const QString &updateNumber, const QString &channel,
+    const QString &scheme, int language, const QString &numPages, const QString &page, const QString &content);
+    virtual void constructSMSMessage(const QString &sender, const QString &serviceCenter, const QString &text);
+    virtual void constructSMSDatagram(int port, const QString &sender,  const QByteArray &data, const QByteArray &contentType);
+
+    int convertString(const QString &number, int maxValue, int numChar, int base, bool *ok);
+
+private:
+    QSMSMessageList SMSList;
+};
+
+class HardwareManipulatorFactory
+{
+public:
+    virtual ~HardwareManipulatorFactory() {};
+    inline virtual HardwareManipulator *create(QWidget *p) { Q_UNUSED(p); return 0; }
+
+    QString ruleFile() const { return ruleFilename; }
+    void setRuleFile(const QString& filename) { ruleFilename = filename; }
+
+private:
+    QString ruleFilename;
+};
+
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/inheritedshareddata.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/inheritedshareddata.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/inheritedshareddata.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef INHERITEDSHAREDDATA_H
+#define INHERITEDSHAREDDATA_H
+
+#include <QSharedData>
+
+template <class T> class InheritedSharedDataPointer
+{
+public:
+    inline void detach() { if (d && d->ref != 1) detach_helper(); }
+    inline T &operator*() { detach(); return *d; }
+    inline const T &operator*() const { return *d; }
+    inline T *operator->() { detach(); return d; }
+    inline const T *operator->() const { return d; }
+    inline operator T *() { detach(); return d; }
+    inline operator const T *() const { return d; }
+    inline T *data() { detach(); return d; }
+    inline const T *data() const { return d; }
+    inline const T *constData() const { return d; }
+
+    inline bool operator==(const InheritedSharedDataPointer<T> &other) const { return d == other.d; }
+    inline bool operator!=(const InheritedSharedDataPointer<T> &other) const { return d != other.d; }
+
+    inline InheritedSharedDataPointer() { d = 0; }
+    inline ~InheritedSharedDataPointer() { if (d && !d->ref.deref()) delete d; }
+
+    explicit InheritedSharedDataPointer(T *data);
+    inline InheritedSharedDataPointer(const InheritedSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); }
+    inline InheritedSharedDataPointer<T> & operator=(const InheritedSharedDataPointer<T> &o) {
+        if (o.d != d) {
+#if QT_VERSION < 0x040400
+            T *x = o.d;
+            if (x) x->ref.ref();
+            x = qAtomicSetPtr(&d, x);
+            if (x && !x->ref.deref())
+                delete x;
+#else
+            if (o.d)
+                o.d->ref.ref();
+            if (d && !d->ref.deref())
+                delete d;
+            d = o.d;
+#endif
+        }
+        return *this;
+    }
+    inline InheritedSharedDataPointer &operator=(T *o) {
+        if (o != d) {
+#if QT_VERSION < 0x040400
+            T *x = o;
+            if (x) x->ref.ref();
+            x = qAtomicSetPtr(&d, x);
+            if (x && !x->ref.deref())
+                delete x;
+#else
+            if (o)
+                o->ref.ref();
+            if (d && !d->ref.deref())
+                delete d;
+            d = o;
+#endif
+        }
+        return *this;
+    }
+
+    inline bool operator!() const { return !d; }
+
+private:
+    void detach_helper();
+
+    T *d;
+};
+
+template <class T>
+Q_INLINE_TEMPLATE InheritedSharedDataPointer<T>::InheritedSharedDataPointer(T *adata) : d(adata)
+{ if (d) d->ref.ref(); }
+
+template <class T>
+Q_OUTOFLINE_TEMPLATE void InheritedSharedDataPointer<T>::detach_helper()
+{
+    T *x = d->createCopy();
+    x->ref.ref();
+#if QT_VERSION < 0x040400
+    x = qAtomicSetPtr(&d, x);
+    if (!x->ref.deref())
+        delete x;
+#else
+    if (!d->ref.deref())
+        delete d;
+    d = x;
+#endif
+}
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/lib.pro
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/lib.pro	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/lib.pro	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,58 @@
+TARGET=phonesim
+CONFIG+=no_tr no_singleexec
+DEFINES+=PHONESIM
+
+VPATH+=$$QTOPIA_DEPOT_PATH/src/libraries/qtopiaphone
+VPATH+=$$QTOPIA_DEPOT_PATH/src/libraries/qtopiacomm
+VPATH+=$$QTOPIA_DEPOT_PATH/src/libraries/qtopiabase
+
+INCLUDEPATH+=$$QPEDIR/include/qtopiacomm
+INCLUDEPATH+=$$QPEDIR/include/qtopiaphone
+INCLUDEPATH+=$$QPEDIR/include/qtopiabase
+INCLUDEPATH+=$$QPEDIR/include/qtopia
+
+PREFIX=PHONESIM
+PHONESIM_HEADERS= phonesim.h server.h hardwaremanipulator.h \
+                  qsmsmessagelist.h \
+                  qsmsmessage.h \
+                  qcbsmessage.h \
+                  callmanager.h \
+                  simfilesystem.h \
+                  simapplication.h \
+                  serial/qgsmcodec.h \
+                  serial/qatutils.h \
+                  serial/qatresultparser.h \
+                  serial/qatresult.h \
+		  wap/qwsppdu.h \
+                  qsimcommand.h \
+                  qsimenvelope.h \
+                  qsimterminalresponse.h \
+                  qsimcontrolevent.h
+PHONESIM_SOURCES= phonesim.cpp server.cpp hardwaremanipulator.cpp \
+                  qsmsmessagelist.cpp \
+		  qsmsmessage.cpp \
+		  qcbsmessage.cpp \
+                  callmanager.cpp \
+                  simfilesystem.cpp \
+                  simapplication.cpp \
+                  serial/qgsmcodec.cpp \
+                  serial/qatutils.cpp \
+                  serial/qatresultparser.cpp \
+                  serial/qatresult.cpp \
+		  wap/qwsppdu.cpp \
+                  qsimcommand.cpp \
+                  qsimenvelope.cpp \
+                  qsimterminalresponse.cpp \
+                  qsimcontrolevent.cpp
+
+phonesim_headers.files=$$PHONESIM_HEADERS
+phonesim_headers.path=/include/phonesim
+phonesim_headers.hint=headers
+
+INSTALLS+=phonesim_headers
+
+TEMPLATE=lib
+QT*=xml network
+HEADERS*=$$PHONESIM_HEADERS
+SOURCES*=$$PHONESIM_SOURCES
+INCLUDEPATH+=serial wap

Added: trunk/src/host/qemu-neo1973/phonesim/lib/phonesim.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/phonesim.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/phonesim.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,1553 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "phonesim.h"
+
+#ifndef PHONESIM_TARGET
+#include "hardwaremanipulator.h"
+#endif
+#include "simfilesystem.h"
+#include "simapplication.h"
+#include "callmanager.h"
+#include <qatutils.h>
+
+#include <qstring.h>
+#include <qbytearray.h>
+#include <qregexp.h>
+#include <qdebug.h>
+
+//#define AT_CHAT_DEBUG 1
+
+SimXmlNode::SimXmlNode( const QString& _tag )
+{
+    parent = 0;
+    next = 0;
+    children = 0;
+    attributes = 0;
+    tag = _tag;
+}
+
+
+SimXmlNode::~SimXmlNode()
+{
+    SimXmlNode *temp1, *temp2;
+    temp1 = children;
+    while ( temp1 ) {
+        temp2 = temp1->next;
+        delete temp1;
+        temp1 = temp2;
+    }
+    temp1 = attributes;
+    while ( temp1 ) {
+        temp2 = temp1->next;
+        delete temp1;
+        temp1 = temp2;
+    }
+}
+
+
+void SimXmlNode::addChild( SimXmlNode *child )
+{
+    SimXmlNode *current = children;
+    SimXmlNode *prev = 0;
+    while ( current ) {
+        prev = current;
+        current = current->next;
+    }
+    if ( prev ) {
+        prev->next = child;
+    } else {
+        children = child;
+    }
+    child->next = 0;
+    child->parent = this;
+}
+
+
+void SimXmlNode::addAttribute( SimXmlNode *child )
+{
+    SimXmlNode *current = attributes;
+    SimXmlNode *prev = 0;
+    while ( current ) {
+        prev = current;
+        current = current->next;
+    }
+    if ( prev ) {
+        prev->next = child;
+    } else {
+        attributes = child;
+    }
+    child->next = 0;
+    child->parent = this;
+}
+
+
+QString SimXmlNode::getAttribute( const QString& name )
+{
+    SimXmlNode *current = attributes;
+    while ( current ) {
+        if ( current->tag == name )
+            return current->contents;
+        current = current->next;
+    }
+    return QString();
+}
+
+
+SimXmlHandler::SimXmlHandler()
+{
+    tree = new SimXmlNode( QString() );
+    current = tree;
+}
+
+
+SimXmlHandler::~SimXmlHandler()
+{
+    delete tree;
+}
+
+
+bool SimXmlHandler::startElement( const QString&, const QString& localName, const QString&, const QXmlAttributes& atts )
+{
+    SimXmlNode *node = new SimXmlNode( localName );
+    SimXmlNode *attr;
+    int index;
+    current->addChild( node );
+    for ( index = 0; index < atts.length(); ++index ) {
+        attr = new SimXmlNode( atts.localName( index ) );
+        attr->contents = atts.value( index );
+        node->addAttribute( attr );
+    }
+    current = node;
+    return true;
+}
+
+
+bool SimXmlHandler::endElement( const QString&, const QString& , const QString&)
+{
+    current = current->parent;
+    return true;
+}
+
+
+bool SimXmlHandler::characters( const QString& ch )
+{
+    current->contents += ch;
+    return true;
+}
+
+
+bool SimXmlHandler::ignorableWhitespace( const QString& ch )
+{
+    current->contents += ch;
+    return true;
+}
+
+
+SimXmlNode *SimXmlHandler::documentElement() const
+{
+    if ( tree->children && tree->children->tag == "simulator" ) {
+        return tree->children;
+    } else {
+        return tree;
+    }
+}
+
+
+SimState::SimState( SimRules *rules, SimXmlNode& e )
+{
+    _rules = rules;
+    if ( e.tag == "state" ) {
+        _name = e.getAttribute( "name" );
+    }
+    SimXmlNode *n = e.children;
+    while ( n != 0 ) {
+        if ( n->tag == "chat" ) {
+
+            // Load a chat response definition.
+            items.append( new SimChat( this, *n ) );
+
+        } else if ( n->tag == "unsolicited" ) {
+
+            // Load an unsolicited response definition.
+            items.append( new SimUnsolicited( this, *n ) );
+
+        }
+        n = n->next;
+    }
+}
+
+
+void SimState::enter()
+{
+    QList<SimItem *>::Iterator iter;
+    for ( iter = items.begin(); iter != items.end(); ++iter ) {
+        (*iter)->enter();
+    }
+}
+
+
+void SimState::leave()
+{
+    QList<SimItem *>::Iterator iter;
+    for ( iter = items.begin(); iter != items.end(); ++iter ) {
+        (*iter)->leave();
+    }
+}
+
+
+bool SimState::command( const QString& cmd )
+{
+    // Search for a "SimChat" item that understands the command.
+    QList<SimItem *>::Iterator iter;
+    for ( iter = items.begin(); iter != items.end(); ++iter ) {
+        if ( (*iter)->command( cmd ) ) {
+            return true;
+        }
+    }
+
+    // Pass unhandled commands to the default state to be processed.
+    SimState *defaultState = rules()->defaultState();
+    if ( defaultState != this ) {
+        return defaultState->command( cmd );
+    } else {
+        return false;
+    }
+}
+
+
+SimChat::SimChat( SimState *state, SimXmlNode& e )
+    : SimItem( state )
+{
+    SimXmlNode *n = e.children;
+    responseDelay = 0;
+    wildcard = false;
+    eol = true;
+    peerConnect = false;
+    peerHangup = false;
+
+    listSMS = false;
+    deleteSMS = false;
+
+    while ( n != 0 ) {
+        if ( n->tag == "command" ) {
+            _command = n->contents;
+            int w=_command.indexOf(QChar('*'));
+            while(w <= 2 && w >= 0)
+                w=_command.indexOf(QChar('*'), w+1);
+            if ( w > 2 ) {
+                wildcard = true;
+            } else {
+                wildcard = false;
+            }
+            QString wc = n->getAttribute( "wildcard" );
+            if ( wc == "true" )
+                wildcard = true;    // Force the use of wildcarding.
+        } else if ( n->tag == "response" ) {
+            QString delay = n->getAttribute( "delay" );
+            response = n->contents;
+            if ( delay != QString() )
+                responseDelay = delay.toInt();
+            else
+                responseDelay = 0;
+            QString eolstr = n->getAttribute( "eol" );
+            eol = (eolstr != "false");
+        } else if ( n->tag == "switch" ) {
+            switchTo = n->getAttribute( "name" );
+        } else if ( n->tag == "set" ) {
+            if ( variable.length() == 0 ) {
+                variable = n->getAttribute( "name" );
+                value = n->getAttribute( "value" );
+            } else {
+                variable2 = n->getAttribute( "name" );
+                value2 = n->getAttribute( "value" );
+            }
+        } else if ( n->tag == "peer" ) {
+            peer = n->contents;
+            QString hangupstr = n->getAttribute( "hangup" );
+            peerHangup = (hangupstr == "true");
+        } else if ( n->tag == "peerconnect" ) {
+            peerConnect = true;
+        } else if ( n->tag == "newcall" ) {
+            newCallVar = n->getAttribute( "name" );
+        } else if ( n->tag == "forgetcall" ) {
+            forgetCallId = n->getAttribute( "id" );
+        }
+          else if ( n->tag == "listSMS" ) {
+            listSMS = true;
+        } else if ( n->tag =="deleteSMS" ) {
+            deleteSMS = true;
+        }
+
+        n = n->next;
+    }
+}
+
+QString PS_toHex( const QByteArray& binary )
+{
+    QString str = "";
+    static char const hexchars[] = "0123456789ABCDEF";
+
+    for ( int i = 0; i < binary.size(); i++ ) {
+        str += (QChar)(hexchars[ (binary[i] >> 4) & 0x0F ]);
+        str += (QChar)(hexchars[ binary[i] & 0x0F ]);
+    }
+
+    return str;
+}
+
+bool SimChat::command( const QString& cmd )
+{
+    QString wild;
+    // command may contain vars, expand them.
+    QString _ecommand = state()->rules()->expand(_command);
+
+    if ( wildcard ) {
+        int s=QRegExp(_ecommand,Qt::CaseSensitive,QRegExp::Wildcard).indexIn(cmd,0);
+        if (s==0) {
+            int w=_ecommand.indexOf(QChar('*'));
+            while(w <= 2 && w >= 0)
+                w=_ecommand.indexOf(QChar('*'),w+1);
+            wild = cmd.mid(w,cmd.length()-_ecommand.length()+1);
+        } else
+            return false;
+    } else if ( !wildcard && cmd == _ecommand ) {
+
+        // Matched the entire command.
+        wild = "";
+
+    } else {
+        return false;
+    }
+
+    // Send the response.
+    state()->rules()->respond( response, responseDelay, eol );
+
+    // Set the variables.
+    if ( variable != QString() ) {
+        if ( value != "*" ) {
+            int index = value.indexOf( "${*}" );
+            if ( index == -1 ) {
+                state()->rules()->setVariable( variable, value );
+            } else {
+                if ( wild.length() > 0 && wild[wild.length() - 1] == 0x1A ) {
+                    // Strip the terminating ^Z from SMS PDU's.
+                    wild = wild.left( wild.length() - 1 );
+                }
+                state()->rules()->setVariable
+                    ( variable, value.left( index ) + wild +
+                    value.mid( index + 4 ) );
+            }
+        } else {
+            state()->rules()->setVariable( variable, wild );
+        }
+    }
+    if ( variable2 != QString() ) {
+        if ( value2 != "*" ) {
+            int index = value2.indexOf( "${*}" );
+            if ( index == -1 ) {
+                state()->rules()->setVariable( variable2, value2 );
+            } else {
+                if ( wild.length() > 0 && wild[wild.length() - 1] == 0x1A ) {
+                    // Strip the terminating ^Z from SMS PDU's.
+                    wild = wild.left( wild.length() - 1 );
+                }
+                state()->rules()->setVariable
+                    ( variable2, value2.left( index ) + wild +
+                    value2.mid( index + 4 ) );
+            }
+        } else {
+            state()->rules()->setVariable( variable2, wild );
+        }
+    }
+
+    // Switch to the new state.
+    if ( switchTo != QString() ) {
+        state()->rules()->switchTo( switchTo );
+    }
+
+    // Send a command to the peer.
+    if ( peer.length() > 0 ) {
+        state()->rules()->peerCommand( peer );
+    }
+
+    // Attempt to connect to a peer if this was a peer dial command.
+    if ( peerConnect ) {
+        QString number = cmd.mid( 3 );
+        if ( number.length() > 0 && number[number.length() - 1] == ';' )
+            number = number.left( number.length() - 1 );
+        if ( state()->rules()->peerConnect( number ) ) {
+            // Disable the automatic "move to connected state" indication.
+            state()->rules()->switchTo( "dialing-peer" );
+        }
+    }
+
+    // Hangup the peer connection if necessary.
+    if ( peerHangup ) {
+        state()->rules()->peerHangup();
+    }
+
+    // Allocate a new call identifier or forget this call identifier.
+    if ( newCallVar.length() > 0 ) {
+        state()->rules()->setVariable
+            ( newCallVar, QString::number( state()->rules()->newCall() ) );
+    }
+    if ( forgetCallId.length() > 0 ) {
+        if ( forgetCallId == "*" )
+            if ( wild.length() == 0 )
+                state()->rules()->forgetAllCalls();
+            else
+                state()->rules()->forgetCall( wild.toInt() );
+        else
+            state()->rules()->forgetCall
+                ( state()->rules()->expand( forgetCallId ).toInt() );
+    }
+#ifndef PHONESIM_TARGET
+    if ( listSMS && state()->rules()->getMachine() ) {
+        QString listSMSResponse;
+        QSMSMessageList &SMSList = state()->rules()->getMachine()->getSMSList();
+        QString status;
+
+        if ( state()->rules()->variable("MSGMEM") == "SM" ) {
+            for ( int i=0; i<SMSList.count(); i++ ) {
+                if ( SMSList.getDeletedFlag(i) == true )
+                    continue;
+
+                status = QString::number(SMSList.getStatus(i));
+                listSMSResponse.append("+CMGL: " + QString::number(i+1) + "," + status + ",10\r\n" +
+                                       PS_toHex( SMSList.readSMS(i) ));// <index> starts at 1, <length>
+                                                                   // is ignored thus set to 10 arbitrarily
+                if( (i+1) < SMSList.count() )  //if not the last message, tag on a <CR><LF> to the response
+                    listSMSResponse.append("\r\n");
+            }
+        }
+
+        listSMSResponse.append("\r\nOK");
+        state()->rules()->respond(listSMSResponse , responseDelay, eol );
+    } else
+#endif
+    if ( listSMS ) {
+        state()->rules()->respond("OK" , responseDelay, eol );
+    }
+
+#ifndef PHONESIM_TARGET
+    if ( deleteSMS && state()->rules()->getMachine() ) {
+        QString deleteSMSResponse;
+        QSMSMessageList &SMSList = state()->rules()->getMachine()->getSMSList();
+        int index = wild.toInt();
+
+        if ( index > SMSList.count() || index <= 0 || (SMSList.getDeletedFlag(index-1) == true) ) {
+            deleteSMSResponse.append("ERROR");
+        } else {
+            SMSList.deleteSMS(index-1);
+            deleteSMSResponse.append("OK");
+        }
+        state()->rules()->respond(deleteSMSResponse , responseDelay, eol );
+    } else
+#endif
+    if ( deleteSMS ) {
+        state()->rules()->respond("OK" , responseDelay, eol );
+    }
+    return true;
+}
+
+
+SimUnsolicited::SimUnsolicited( SimState *state, SimXmlNode& e )
+    : SimItem( state ), done(false)
+{
+    QString delay = e.getAttribute( "delay" );
+    response = e.contents;
+    if ( delay != QString() )
+        responseDelay = delay.toInt();
+    else
+        responseDelay = 0;
+    switchTo = e.getAttribute( "switch" );
+    doOnce = e.getAttribute( "once" ) == "true";
+
+    timer = new QTimer( this );
+    timer->setSingleShot( true );
+    connect( timer, SIGNAL(timeout()), this, SLOT(timeout()) );
+}
+
+
+void SimUnsolicited::enter()
+{
+    if (!doOnce || !done)
+        timer->start( responseDelay );
+}
+
+
+void SimUnsolicited::leave()
+{
+    timer->stop();
+}
+
+
+void SimUnsolicited::timeout()
+{
+    state()->rules()->unsolicited( response );
+
+    if ( switchTo != QString() ) {
+        state()->rules()->switchTo( switchTo );
+    }
+
+    done = true;
+}
+
+class ErrorHandler : public QXmlErrorHandler {
+public:
+    ErrorHandler() { }
+    bool warning( const QXmlParseException& exception )
+    {
+        return error("Fatal",exception);
+    }
+    bool error( const QXmlParseException& exception )
+    {
+        return error("Fatal",exception);
+    }
+    bool fatalError( const QXmlParseException& exception )
+    {
+        return error("Fatal",exception);
+    }
+    bool error( const char* t, const QXmlParseException& exception )
+    {
+        qWarning("%s: %d,%d: %s",t,exception.lineNumber(),exception.columnNumber(),(const char *)exception.message().toLatin1());
+        return false;
+    }
+    QString errorString() const { return "??"; }
+};
+
+SimRules::SimRules( int fd, QObject *p,  const QString& filename, HardwareManipulatorFactory *hmf )
+    : QTcpSocket(p)
+{
+    setSocketDescriptor(fd);
+    machine = 0;
+
+#ifdef PHONESIM_TARGET
+    Q_UNUSED(hmf);
+#else
+    if (hmf)
+        machine = hmf->create(0);
+
+    if (machine) {
+        machine->setWindowTitle("none");
+        if (machine->shouldShow()) machine->show();
+
+        connect(machine, SIGNAL(unsolicitedCommand(QString)),
+                this, SLOT(unsolicited(QString)));
+        connect(machine, SIGNAL(command(QString)),
+                this, SLOT(command(QString)));
+        connect(machine, SIGNAL(variableChanged(QString,QString)),
+                this, SLOT(setVariable(QString,QString)));
+        connect(machine, SIGNAL(switchTo(QString)),
+                this, SLOT(switchTo(QString)));
+    }
+#endif
+
+    _callManager = new CallManager(this);
+    connect( _callManager, SIGNAL(send(QString)),
+             this, SLOT(respond(QString)) );
+    connect( _callManager, SIGNAL(unsolicited(QString)),
+             this, SLOT(unsolicited(QString)) );
+    connect( _callManager, SIGNAL(dialCheck(QString,bool&)),
+             this, SLOT(dialCheck(QString,bool&)) );
+
+#ifndef PHONESIM_TARGET
+    if ( machine ) {
+        connect( machine, SIGNAL(startIncomingCall(QString)),
+                 _callManager, SLOT(startIncomingCall(QString)) );
+    }
+#endif
+
+    connect(this,SIGNAL(readyRead()),
+        this,SLOT(tryReadCommand()));
+    connect(this,SIGNAL(disconnected()),
+        this,SLOT(destruct()));
+    // Initialize the local state.
+    currentState = 0;
+    defState = 0;
+    return_error_string = "";
+    return_error_count = 0;
+    usedCallIds = 0;
+    fileSystem = 0;
+    useGsm0710 = false;
+    currentChannel = 1;
+    incomingUsed = 0;
+    lineUsed = 0;
+    defaultToolkitApp = toolkitApp = new DemoSimApplication( this );
+    toolkitApp->setSimRules( this );
+    connect( _callManager, SIGNAL(controlEvent(QSimControlEvent)),
+             toolkitApp, SLOT(controlEvent(QSimControlEvent)) );
+
+    // Load the simulator rules into memory as a DOM-like tree.
+    SimXmlHandler *handler = new SimXmlHandler();
+    QXmlSimpleReader *reader = new QXmlSimpleReader();
+    reader->setErrorHandler( new ErrorHandler );
+    reader->setContentHandler( handler );
+    QFile f( filename );
+    QXmlInputSource inputSource(&f);
+    if ( !reader->parse( inputSource ) ) {
+        qWarning() << filename << ": could not parse simulator rule file";
+        return;
+    }
+    f.close();
+
+    // Load the default state and set it as current.
+    defState = new SimState( this, *(handler->documentElement()) );
+    states.append( defState );
+
+    initPhoneBooks();
+
+    // Load the other states, and the start state's name (if specified).
+    SimXmlNode *n = handler->documentElement()->children;
+    QString start = QString();
+    while ( n != 0 ) {
+        if ( n->tag == "state" ) {
+
+            // Load a new state definition.
+            SimState *state = new SimState( this, *n );
+            states.append( state );
+
+        } else if ( n->tag == "start" ) {
+
+            // Set a new start state.
+            start = n->getAttribute( "name" );
+
+        } else if ( n->tag == "set" ) {
+
+            // Set the initial value of a variable.
+            QString name = n->getAttribute( "name" );
+            QString value = n->getAttribute( "value" );
+            if ( name != QString() && value != QString() ) {
+                setVariable(name, value);
+            }
+
+        } else if ( n->tag == "peerinfo" ) {
+
+            // Add a phone simulator peer entry.
+            QString number = n->getAttribute( "number" );
+            QString host = n->getAttribute( "host" );
+            if ( number != QString() && host != QString() ) {
+                peers[number] = host;
+            }
+
+        } else if ( n->tag == "filesystem" ) {
+
+            // Load the SIM filesystem.
+            fileSystem = new SimFileSystem( this, *n );
+
+        } else if ( n->tag == "phonebook" ) {
+
+            // Load a phonebook definition.
+            loadPhoneBook( *n );
+
+        }
+        n = n->next;
+    }
+
+    // Clean up the XML reader objects.
+    delete reader;
+    delete handler;
+
+    // Set the start state appropriately.
+    currentState = state( start );
+    if ( !currentState )
+        currentState = defState;
+}
+
+
+#define MAX_GSM0710_FRAME_SIZE      31
+
+
+static const unsigned char crcTable[256] = {
+    0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75,
+    0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
+    0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69,
+    0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
+    0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D,
+    0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
+    0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51,
+    0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
+    0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05,
+    0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
+    0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19,
+    0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
+    0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D,
+    0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
+    0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21,
+    0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
+    0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95,
+    0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
+    0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89,
+    0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
+    0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD,
+    0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
+    0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1,
+    0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
+    0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5,
+    0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
+    0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9,
+    0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
+    0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD,
+    0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
+    0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1,
+    0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
+};
+
+static int computeCrc( const char *data, uint len )
+{
+    int sum = 0xFF;
+    while ( len > 0 ) {
+        sum = crcTable[ ( sum ^ *data++ ) & 0xFF ];
+        --len;
+    }
+    return ((0xFF - sum) & 0xFF);
+}
+
+
+void SimRules::tryReadCommand()
+{
+    int len, posn;
+    int channel, type;
+    int temp, lasteol;
+
+    // Read as much data as possible into "incomingBuffer".
+    len = sizeof(incomingBuffer) - 1 - incomingUsed;
+    len = read( incomingBuffer + incomingUsed, len );
+    if ( len <= 0 ) {
+        // The connection has been closed by the remote end.
+        return;
+    }
+    incomingUsed += len;
+
+    // Split the incoming data into GSM 07.10 packets or text lines.
+    if ( useGsm0710 ) {
+        // Extract GSM 07.10 packets from the incoming buffer.
+        posn = 0;
+        while ( posn < incomingUsed ) {
+            if ( incomingBuffer[posn] == (char)0xF9 ) {
+
+                // Skip additional 0xF9 bytes between frames.
+                while ( ( posn + 1 ) < incomingUsed &&
+                        incomingBuffer[posn + 1] == (char)0xF9 ) {
+                    ++posn;
+                }
+
+                // We need at least 4 bytes for the header.
+                if ( ( posn + 4 ) > incomingUsed )
+                    break;
+
+                // The low bits of the second and fourth bytes should be 1,
+                // which indicates short channel number and length values.
+                if ( ( incomingBuffer[posn + 1] & 0x01 ) == 0 ||
+                     ( incomingBuffer[posn + 3] & 0x01 ) == 0 ) {
+                    ++posn;
+                    continue;
+                }
+
+                // Get the packet length and validate it.
+                len = (incomingBuffer[posn + 3] >> 1) & 0x7F;
+                if ( ( posn + 5 + len ) > incomingUsed )
+                    break;
+
+                // Verify the packet header checksum.
+                if ( ( ( computeCrc( incomingBuffer + posn + 1, 3 ) ^
+                         incomingBuffer[posn + len + 4] ) & 0xFF ) != 0 ) {
+                    qDebug() << "*** GSM 07.10 checksum check failed ***";
+                    posn += len + 5;
+                    continue;
+                }
+
+                // Get the channel number and packet type from the header.
+                channel = (incomingBuffer[posn + 1] >> 2) & 0x3F;
+                type = incomingBuffer[posn + 2] & 0xEF;  // Strip "PF" bit.
+
+                // Dispatch data packets to the appropriate channel.
+                if ( type == 0xEF || type == 0x03 ) {
+                    if ( channel == 0 ) {
+                        if ( len == 2 &&
+                             incomingBuffer[posn + 4] == (char)0xC3 &&
+                             incomingBuffer[posn + 5] == (char)0x01 ) {
+                            // This is the "terminate" commmand, which
+                            // indicates that we should exit GSM 07.10 mode.
+                            useGsm0710 = false;
+                            posn += len + 5;
+                            if ( posn < incomingUsed &&
+                                 incomingBuffer[posn] == (char)0xF9 ) {
+                                // Skip the trailing 0xF9 on the terminate.
+                                ++posn;
+                            }
+                            qDebug() << "GSM 07.10 mode deactivated";
+                            break;
+                        }
+                    } else {
+                        // Ordinary data packet on a specific channel.
+                        memcpy( lineBuffer + lineUsed,
+                                incomingBuffer + posn + 4, len );
+                        lineUsed += len;
+
+                        // Process any complete lines that we have received.
+                        lasteol = 0;
+                        temp = 0;
+                        currentChannel = channel;
+                        while ( temp < lineUsed ) {
+                            if ( lineBuffer[temp] == '\r' ) {
+                                lineBuffer[temp] = '\0';
+                                command( lineBuffer + lasteol );
+                                ++temp;
+                                if ( temp < lineUsed &&
+                                     lineBuffer[temp] == '\n' ) {
+                                    ++temp;
+                                }
+                                lasteol = temp;
+                            } else if ( lineBuffer[temp] == 0x1A ) {
+                                // Probably the terminator on an SMS PDU,
+                                // which may or may not be followed by a CR.
+                                lineBuffer[temp] = '\0';
+                                command( lineBuffer + lasteol );
+                                ++temp;
+                                if ( temp < lineUsed &&
+                                     lineBuffer[temp] == '\r' ) {
+                                    ++temp;
+                                }
+                                lasteol = temp;
+                            } else if ( lineBuffer[temp] == '\n' ) {
+                                lineBuffer[temp] = '\0';
+                                command( lineBuffer + lasteol );
+                                ++temp;
+                                lasteol = temp;
+                            } else {
+                                ++temp;
+                            }
+                        }
+                        currentChannel = 1;
+                        memmove( lineBuffer, lineBuffer + lasteol,
+                                 lineUsed - lasteol );
+                        lineUsed -= lasteol;
+                    }
+                } else if ( type == ( 0x3F & 0xEF ) ) {
+                    // Channel open request.
+#ifdef AT_CHAT_DEBUG
+                    if ( channel == 0 )
+                        qDebug() << "GSM 07.10 control channel opened";
+                    else
+                        qDebug() << "GSM 07.10 channel " << channel << " opened";
+#endif
+                } else if ( type == ( 0x53 & 0xEF ) ) {
+                    // Channel close request.
+#ifdef AT_CHAT_DEBUG
+                    qDebug() << "GSM 07.10 channel " << channel << " closed";
+#endif
+                }
+                posn += len + 5;
+
+            } else {
+                // Skip garbage byte outside of a GSM 07.10 packet.
+                ++posn;
+            }
+        }
+        memmove( incomingBuffer, incomingBuffer + posn, incomingUsed - posn );
+        incomingUsed -= posn;
+        if ( !useGsm0710 )
+            goto processText;   // We've just exited GSM 07.10 mode.
+    } else {
+        // We aren't using multi-plexing yet, so split into text lines.
+    processText:
+        len = 0;
+        while ( len < incomingUsed ) {
+            if ( incomingBuffer[len] == '\r' ) {
+                if ( (len + 1) < incomingUsed &&
+                     incomingBuffer[len + 1] == '\n' ) {
+                    ++len;
+                }
+                lineBuffer[lineUsed] = '\0';
+                if ( lineBuffer[0] != (char)0xF9 ) {
+                    command( lineBuffer );
+                }
+                lineUsed = 0;
+            } else if ( incomingBuffer[len] == 0x1A ) {
+                // Probably the terminator on an SMS PDU,
+                // which may or may not be followed by a CR.
+                if ( (len + 1) < incomingUsed &&
+                     incomingBuffer[len + 1] == '\r' ) {
+                    ++len;
+                }
+                lineBuffer[lineUsed] = '\0';
+                if ( lineBuffer[0] != (char)0xF9 ) {
+                    command( lineBuffer );
+                }
+                lineUsed = 0;
+            } else if ( incomingBuffer[len] == '\n' ) {
+                lineBuffer[lineUsed] = '\0';
+                if ( lineBuffer[0] != (char)0xF9 ) {
+                    command( lineBuffer );
+                }
+                lineUsed = 0;
+            } else if ( lineUsed < (int)( sizeof(lineBuffer) - 1 ) ) {
+                lineBuffer[lineUsed++] = incomingBuffer[len];
+            }
+            ++len;
+        }
+        incomingUsed = 0;
+    }
+}
+
+void SimRules::destruct()
+{
+#ifdef AT_CHAT_DEBUG
+    qDebug() << "connectionclosed";
+#endif
+
+#ifndef PHONESIM_TARGET
+    if (machine) machine->close();
+#endif
+    deleteLater();
+}
+
+void SimRules::setPhoneNumber(const QString &s)
+{
+    mPhoneNumber = s;
+
+#ifndef PHONESIM_TARGET
+    if (machine) machine->setWindowTitle("Phonesim - Number: " + s);
+#endif
+}
+
+HardwareManipulator * SimRules::getMachine() const
+{
+    return machine;
+}
+
+void SimRules::setSimApplication( SimApplication *app )
+{
+    if ( toolkitApp != defaultToolkitApp )
+        delete toolkitApp;
+    toolkitApp = ( app ? app : defaultToolkitApp );
+    toolkitApp->setSimRules( this );
+    toolkitApp->start();
+}
+
+void SimRules::loadPeers( const QString& filename )
+{
+    // Load the peer rules into memory as a DOM-like tree.
+    SimXmlHandler *handler = new SimXmlHandler();
+    QXmlSimpleReader *reader = new QXmlSimpleReader();
+    reader->setContentHandler( handler );
+    QFile f( filename );
+    QXmlInputSource inputSource(&f);
+    if ( !reader->parse( inputSource ) ) {
+        qWarning() << filename << ": could not parse peer rule file";
+        return;
+    }
+    f.close();
+
+    // Load the "peerinfo" tags.
+    SimXmlNode *n = handler->documentElement()->children;
+    while ( n != 0 ) {
+        if ( n->tag == "peerinfo" ) {
+
+            // Add a phone simulator peer entry.
+            QString number = n->getAttribute( "number" );
+            QString host = n->getAttribute( "host" );
+            if ( number != QString() && host != QString() ) {
+                peers[number] = host;
+            }
+
+        }
+        n = n->next;
+    }
+
+    // Clean up the XML reader objects.
+    delete reader;
+    delete handler;
+}
+
+
+void SimRules::switchTo(const QString& name)
+{
+    SimState *newState = state( name );
+    if ( newState ) {
+        if ( currentState )
+            currentState->leave();
+        currentState = newState;
+        currentState->enter();
+    }
+}
+
+
+SimState *SimRules::state( const QString& name ) const
+{
+    if ( name == "default" )
+        return defaultState();
+
+    QList<SimState *>::ConstIterator iter;
+    for ( iter = states.begin(); iter != states.end(); ++iter ) {
+
+        if ( (*iter)->name() == name ) {
+            return *iter;
+        }
+
+    }
+    qWarning() << "Warning: no state called \"" << name << "\" has been defined";
+    return 0;
+}
+
+
+void SimRules::command( const QString& cmd )
+{
+
+#ifndef PHONESIM_TARGET
+    if(getMachine())
+        getMachine()->handleToData(cmd);
+#endif
+
+#ifdef AT_CHAT_DEBUG
+    if ( useGsm0710 )
+        qDebug() << "CMD[" << currentChannel << "]> " << cmd;
+    else
+        qDebug() << "CMD> " << cmd;
+#endif
+
+    // Process call-related commands with the call manager.
+    if ( _callManager->command( cmd ) )
+        return;
+
+    // Process SIM toolkit related commands with the current SIM application.
+    if ( toolkitApp && toolkitApp->execute( cmd ) )
+        return;
+
+    if ( ! currentState->command( cmd ) ) {
+        if ( cmd.startsWith( "AT+CRSM=" ) && fileSystem ) {
+
+            // Process a filesystem access command.
+            fileSystem->crsm( cmd.mid(8) );
+
+        } else if ( cmd.startsWith( "AT+CPBS" ) ||
+                    cmd.startsWith( "AT+CPBR" ) ||
+                    cmd.startsWith( "AT+CPBW" ) ) {
+
+            // Process a phonebook access command.
+            phoneBook( cmd );
+
+        } else if ( cmd.startsWith( "AT+CMUX=0," ) ) {
+
+            // Request to turn on GSM 07.10 multiplexing.
+            respond( "OK" );
+#ifdef AT_CHAT_DEBUG
+            qDebug() << "GSM 07.10 multiplexing enabled";
+#endif
+            useGsm0710 = true;
+
+        } else if ( cmd.startsWith( "AT" ) ) {
+
+            // All other AT commands are not understood.
+            respond( "ERROR" );
+
+        }
+    }
+}
+
+SimPhoneBook::SimPhoneBook( int size, QObject *parent )
+    : QObject( parent )
+{
+    while ( size-- > 0 ) {
+        numbers.append( QString() );
+        names.append( QString() );
+    }
+}
+
+SimPhoneBook::~SimPhoneBook()
+{
+}
+
+int SimPhoneBook::used() const
+{
+    int count = 0;
+    for ( int index = 0; index < numbers.size(); ++index ) {
+        if ( !numbers[index].isEmpty() )
+            ++count;
+    }
+    return count;
+}
+
+QString SimPhoneBook::number( int index ) const
+{
+    if ( index >= 1 && index <= numbers.size() )
+        return numbers[index - 1];
+    else
+        return QString();
+}
+
+QString SimPhoneBook::name( int index ) const
+{
+    if ( index >= 1 && index <= names.size() )
+        return names[index - 1];
+    else
+        return QString();
+}
+
+void SimPhoneBook::setDetails
+        ( int index, const QString& number, const QString& name )
+{
+    if ( index >= 1 && index <= numbers.size() ) {
+        numbers.replace( index - 1, number );
+        names.replace( index - 1, name );
+    }
+}
+
+void SimRules::initPhoneBooks()
+{
+    currentPhoneBook = "SM";
+    phoneBooks.insert( "SM", new SimPhoneBook( 150, this ) );
+}
+
+void SimRules::loadPhoneBook( SimXmlNode& node )
+{
+    QString name = node.getAttribute( "name" );
+    int size = node.getAttribute( "size" ).toInt();
+    if ( !phoneBooks.contains( name ) ) {
+        phoneBooks.insert( name, new SimPhoneBook( size, this ) );
+    }
+    SimPhoneBook *pb = phoneBooks[name];
+    SimXmlNode *n = node.children;
+    while ( n != 0 ) {
+        if ( n->tag == "entry" ) {
+
+            // Load a phone book entry.
+            int index = n->getAttribute( "index" ).toInt();
+            QString number = n->getAttribute( "number" );
+            QString name = n->getAttribute( "name" );
+            pb->setDetails( index, number, name );
+
+        }
+        n = n->next;
+    }
+}
+
+void SimRules::phoneBook( const QString& cmd )
+{
+    SimPhoneBook *pb = currentPB();
+    if ( !pb )
+        return;
+
+    // If the SIM PIN is not ready, then disable the phone books.
+    if ( variable("PINNAME") != "READY" ) {
+        respond( "ERROR" );
+        return;
+    }
+
+    if ( cmd.startsWith( "AT+CPBS=?" ) ) {
+        QStringList names = phoneBooks.keys();
+        QString response = "+CPBS: (";
+        foreach ( QString name, names ) {
+            if ( response.length() > 8 )
+                response += QChar(',');
+            response += "\"" + name + "\"";
+        }
+        response += ")\nOK";
+        respond( response );
+    } else if ( cmd.startsWith( "AT+CPBS?" ) ) {
+        respond( "+CPBS: \"" + currentPhoneBook + "\"," +
+                 QString::number( pb->used() ) + "," +
+                 QString::number( pb->size() ) + "\nOK" );
+    } else if ( cmd.startsWith( "AT+CPBS=\"" ) ) {
+        QString name = cmd.mid(9).left(2);
+        if ( phoneBooks.contains( name ) ) {
+            // If a password is supplied, then check it against PIN2VALUE.
+            int comma = cmd.indexOf( QChar(',') );
+            if ( comma >= 0 ) {
+                QString password = cmd.mid(comma + 1);
+                password.remove( QChar('"') );
+                if ( password != variable( "PIN2VALUE" ) ) {
+                    respond( "ERROR" );
+                    return;
+                }
+            }
+            currentPhoneBook = name;
+            respond( "OK" );
+        } else {
+            // Invalid phone book name.
+            respond( "ERROR" );
+        }
+    } else if ( cmd.startsWith( "AT+CPBR=?" ) ) {
+        respond( "+CPBR: (1-" + QString::number( pb->size() ) + "),32,16\nOK" );
+    } else if ( cmd.startsWith( "AT+CPBR=" ) ) {
+        QString args = cmd.mid(8);
+        int comma = args.indexOf( QChar(',') );
+        int first, last;
+        if ( comma < 0 ) {
+            // Read one entry.
+            first = args.toInt();
+            last = first;
+        } else {
+            // Read a range of entries.
+            first = args.left(comma).toInt();
+            last = args.mid(comma + 1).toInt();
+        }
+        while ( first <= last ) {
+            QString number = pb->number( first );
+            QString name = pb->name( first );
+            if ( !number.isEmpty() ) {
+                respond( "+CPBR: " + QString::number(first) + "," +
+                         QAtUtils::encodeNumber( number ) + ",\"" +
+                         QAtUtils::quote( name ) + "\"" );
+            }
+            ++first;
+        }
+        respond( "OK" );
+    } else if ( cmd.startsWith( "AT+CPBW=" ) ) {
+        uint posn = 8;
+        int index = (int)QAtUtils::parseNumber( cmd, posn );
+        if ( index < 1 || index > pb->size() ) {
+            // Invalid index.
+            respond( "ERROR" );
+            return;
+        }
+        if ( ((int)posn) >= cmd.length() ) {
+            // Delete an entry from the phone book.
+            pb->setDetails( index, QString(), QString() );
+        } else {
+            // Write new details to an entry.
+            QString number = QAtUtils::nextString( cmd, posn );
+            uint type = QAtUtils::parseNumber( cmd, posn );
+            QString name = QAtUtils::nextString( cmd, posn );
+            number = QAtUtils::decodeNumber( number, type );
+            pb->setDetails( index, number, name );
+        }
+        respond( "OK" );
+    } else {
+        respond( "ERROR" );
+    }
+}
+
+SimPhoneBook *SimRules::currentPB() const
+{
+    if ( phoneBooks.contains( currentPhoneBook ) )
+        return phoneBooks[currentPhoneBook];
+    else
+        return 0;
+}
+
+void SimRules::setReturnError( const QString &error, uint repeat )
+{
+    return_error_string = error;
+    return_error_count = repeat;
+}
+
+
+int SimRules::newCall()
+{
+    int id;
+    for( id = 1; id <= 8; ++id ) {
+        if ( ( usedCallIds & (1 << id) ) == 0 ) {
+            break;
+        }
+    }
+    usedCallIds |= (1 << id);
+    return id;
+}
+
+
+void SimRules::forgetCall( int id )
+{
+    usedCallIds &= ~(1 << id);
+}
+
+
+void SimRules::forgetAllCalls()
+{
+    usedCallIds = 0;
+}
+
+QString expandEscapes( const QString& data, bool eol )
+{
+    // Expand escapes and end of line markers in the data.
+    static char const escapes[] = "\a\bcde\fghijklm\nopq\rs\tu\vwxyz";
+    QString res;
+    QByteArray buffer = data.toLatin1();
+    const char *buf = buffer.data();
+    int ch;
+    int prevch = 0;
+    while ( ( ch = *buf++ ) != '\0' ) {
+        if ( ch == '\n' ) {
+            res += ( '\r' );
+            res += ( '\n' );
+        } else if ( ch == '\\' ) {
+            ch = *buf++;
+            if ( ch == '\0' ) {
+                res += ( '\\' );
+                break;
+            } else if ( ch == 'n' ) {
+                res += ( '\r' );
+                res += ( '\n' );
+                ch = '\n';
+            } else if ( ch >= 'a' && ch <= 'z' ) {
+                ch = escapes[ch - 'a'];
+                res += ( ch );
+            } else {
+                res += ( '\\' );
+                res += ( ch );
+            }
+        } else if ( ch != '\r' ) {
+            res += ( ch );
+        }
+        prevch = ch;
+    }
+    if ( prevch != '\n' && eol ) {
+        res += ( '\r' );
+        res += ( '\n' );
+    }
+    return res;
+}
+
+
+void SimRules::respond( const QString& resp, int delay, bool eol )
+{
+    QString r = expand( resp );
+    if (return_error_string != "") {
+        r = return_error_string;
+        if (return_error_count > 0)
+            return_error_count--;
+        if (return_error_count == 0)
+            return_error_string = "";
+    }
+
+
+#ifdef AT_CHAT_DEBUG
+    if ( useGsm0710 )
+        qDebug() << "RSP[" << currentChannel << "]> " << r;
+    else
+        qDebug() << "RSP> " << r;
+#endif
+
+    QByteArray escaped = expandEscapes( r, eol ).toUtf8();
+    if ( !delay ) {
+        writeChatData(escaped.data(), escaped.length());
+        flush();
+    } else {
+        SimDelayTimer *timer = new SimDelayTimer( escaped, currentChannel );
+        timer->setSingleShot( true );
+        connect(timer,SIGNAL(timeout()),this,SLOT(delayTimeout()));
+        timer->start( delay );
+    }
+#ifndef PHONESIM_TARGET
+    if(getMachine())
+        getMachine()->handleFromData(QString(escaped));
+#endif
+}
+
+
+void SimRules::delayTimeout()
+{
+    SimDelayTimer *timer = (SimDelayTimer *)sender();
+    int save = currentChannel;
+    currentChannel = timer->channel;
+    writeChatData(timer->response.toLatin1().data(), timer->response.length());
+    flush();
+    currentChannel = save;
+    delete timer;
+}
+
+
+void SimRules::dialCheck( const QString& number, bool& ok )
+{
+    // Bail out if the fixed-dialing phone book is not active or present.
+    if ( variable("FD") != "1" )
+        return;
+    if ( !phoneBooks.contains( "FD" ) ) {
+        ok = false;
+        return;
+    }
+
+    // The dial is OK if the number starts with an existing number in "FD".
+    for( int i = 1; i <= phoneBooks["FD"]->used(); i++ ){
+        if( number.startsWith(phoneBooks["FD"]->number(i)) ){
+            ok = true;
+            return;
+        }
+        ok = false;
+    }
+
+    // The dial is OK if it is one of the standard emergency numbers.
+    if (number == "112" || number == "911" || number == "08" || number == "000") {
+        ok = true;
+    }
+}
+
+void SimRules::unsolicited( const QString& resp )
+{
+    QString r = expand( resp );
+
+#ifdef AT_CHAT_DEBUG
+    if ( useGsm0710 )
+        qDebug() << "UNS[" << currentChannel << "]> " << r;
+    else
+        qDebug() << "UNS> " << r;
+#endif
+
+    QByteArray escaped = expandEscapes( r, true ).toUtf8();
+    writeChatData( escaped , escaped.length() );
+    flush();
+}
+
+
+void SimRules::writeGsmFrame( int type, const char *data, uint len )
+{
+    char frame[MAX_GSM0710_FRAME_SIZE + 6];
+    frame[0] = (char)0xF9;
+    frame[1] = (char)((currentChannel << 2) | 0x03);
+    frame[2] = (char)type;
+    frame[3] = (char)((len << 1) | 0x01);
+    if ( len > 0 )
+        memcpy( frame + 4, data, len);
+    // Note: GSM 07.10 says that the CRC is only computed over the header.
+    frame[len + 4] = (char)computeCrc( frame + 1, 3 );
+    frame[len + 5] = (char)0xF9;
+    write( frame, len + 6 );
+}
+
+
+void SimRules::writeChatData( const char *data, uint len )
+{
+    if ( !isOpen() )
+        return;
+    if ( !useGsm0710 ) {
+        // We aren't using multi-plexing at present.
+        write( data, len );
+    } else {
+        // Format GSM 07.10 frames and send them via the current channel.
+        uint templen;
+        while ( len > 0 ) {
+            templen = len;
+            if ( templen > MAX_GSM0710_FRAME_SIZE ) {
+                templen = MAX_GSM0710_FRAME_SIZE;
+            }
+            writeGsmFrame( 0xEF, data, templen );
+            data += templen;
+            len -= templen;
+        }
+    }
+}
+
+
+QString SimRules::expand( const QString& s )
+{
+    int prev, index, len, start, end;
+    QString result;
+    QString name;
+
+    index = s.indexOf( QChar('$') );
+    if ( index == -1 )
+        return s;
+
+    prev = 0;
+    len = s.length();
+    do {
+        result += s.mid( prev, index - prev );
+        ++index;
+        if ( index < len && s[index] == '{' ) {
+            ++index;
+            start = index;
+            end = s.indexOf( QChar('}'), index );
+            if ( end == -1 ) {
+                end = len;
+                index = len;
+            } else {
+                index = end + 1;
+            }
+            name = s.mid( start, end - start );
+            result += variable(name);
+        } else {
+            result += "$";
+        }
+        prev = index;
+        index = s.indexOf( QChar('$'), index );
+    } while ( index != -1 );
+    result += s.mid( prev );
+    return result;
+}
+
+void SimRules::queryVariable( const QString &name )
+{
+    emit returnQueryVariable( name, variable(name) );
+}
+
+void SimRules::queryState( )
+{
+    if (currentState)
+        emit returnQueryState( currentState->name() );
+    else
+        emit returnQueryState( QString() );
+}
+
+void SimRules::setVariable( const QString& name, const QString& value )
+{
+        variables[name] = expand(value);
+}
+
+QString SimRules::variable( const QString& name )
+{
+    return variables[name];
+
+}
+
+void SimRules::peerCommand( const QString& )
+{
+}
+
+
+bool SimRules::peerConnect( const QString& )
+{
+    return false;
+}
+
+
+void SimRules::peerHangup()
+{
+}
+
+
+QString SimRules::phoneNumber()
+{
+    char hostname[1024];
+    ::gethostname( hostname, sizeof(hostname) );
+
+    QMap<QString,QString>::Iterator iter;
+    for ( iter = peers.begin(); iter != peers.end(); ++iter ) {
+        if ( iter.value().startsWith( hostname ) ) {
+            return iter.key();
+        }
+    }
+
+    return QString();
+}
+
+
+void SimRules::printPeerNumber()
+{
+#ifdef AT_CHAT_DEBUG
+    QString number = phoneNumber();
+    if ( number != QString() ) {
+        qDebug() << "Your phone number is " << number;
+    }
+#endif
+}
+

Added: trunk/src/host/qemu-neo1973/phonesim/lib/phonesim.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/phonesim.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/phonesim.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef PHONESIM_H
+#define PHONESIM_H
+
+#include <qstring.h>
+#include <qlist.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qxml.h>
+#include <qtcpsocket.h>
+#include <qapplication.h>
+#include <qmap.h>
+#include <qtimer.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/select.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+class SimState;
+class SimItem;
+class SimChat;
+class SimUnsolicited;
+class SimRules;
+class SimFileSystem;
+class CallManager;
+class SimApplication;
+
+
+class SimXmlNode
+{
+public:
+    SimXmlNode( const QString& tag );
+    ~SimXmlNode();
+
+    SimXmlNode *parent, *next, *children, *attributes;
+    QString tag;
+    QString contents;
+
+    void addChild( SimXmlNode *child );
+    void addAttribute( SimXmlNode *child );
+    QString getAttribute( const QString& name );
+};
+
+
+class SimXmlHandler : public QXmlDefaultHandler
+{
+public:
+    SimXmlHandler();
+    ~SimXmlHandler();
+
+    bool startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts );
+    bool endElement( const QString& namespaceURI, const QString& localName, const QString& qName );
+    bool characters( const QString& ch );
+    bool ignorableWhitespace( const QString& ch );
+
+    SimXmlNode *documentElement() const;
+
+private:
+    SimXmlNode *tree;
+    SimXmlNode *current;
+};
+
+
+class SimState
+{
+    friend class SimRules;
+public:
+    SimState( SimRules *rules, SimXmlNode& e );
+    ~SimState() {}
+
+    // Get the rules object that contains this state.
+    SimRules *rules() const { return _rules; }
+
+    // Get the name of this state.
+    QString name() const { return _name; }
+
+    // Enter this state, and enable unsolicited events.
+    void enter();
+
+    // Leave this state, after disabling unsolicited events.
+    void leave();
+
+    // Handle a command.  Returns false if the command was not understood.
+    bool command( const QString& cmd );
+
+private:
+    SimRules *_rules;
+    QString _name;
+    QList<SimItem *> items;
+
+};
+
+
+class SimItem : public QObject
+{
+    Q_OBJECT
+public:
+    SimItem( SimState *state ) { _state = state; }
+    virtual ~SimItem() {}
+
+    // Get the state that contains this item.
+    SimState *state() { return _state; }
+
+    // Receive notification of the item's state being entered.
+    virtual void enter() {}
+
+    // Receive notification of the item's state being left.
+    virtual void leave() {}
+
+    // Attempt to handle a command.  Returns false if not recognised.
+    virtual bool command( const QString& ) { return false; }
+
+private:
+    SimState *_state;
+
+};
+
+
+class SimChat : public SimItem
+{
+    Q_OBJECT
+public:
+    SimChat( SimState *state, SimXmlNode& e );
+    ~SimChat() {}
+
+    virtual bool command( const QString& cmd );
+
+private:
+    QString _command;
+    QString response;
+    int responseDelay;
+    QString switchTo;
+    bool wildcard;
+    bool eol;
+    QString variable;
+    QString value;
+    QString variable2;
+    QString value2;
+    QString peer;
+    bool peerConnect;
+    bool peerHangup;
+    QString newCallVar;
+    QString forgetCallId;
+    bool listSMS;
+    bool deleteSMS;
+};
+
+
+class SimUnsolicited : public SimItem
+{
+    Q_OBJECT
+public:
+    SimUnsolicited( SimState *state, SimXmlNode& e );
+    ~SimUnsolicited() {}
+
+    virtual void enter();
+    virtual void leave();
+
+private:
+    QString response;
+    int responseDelay;
+    QString switchTo;
+    bool doOnce;
+    bool done;
+    QTimer *timer;
+
+private slots:
+    void timeout();
+
+};
+
+
+class SimPhoneBook : public QObject
+{
+    Q_OBJECT
+public:
+    SimPhoneBook( int size, QObject *parent );
+    ~SimPhoneBook();
+
+    int size() const { return numbers.size(); }
+    int used() const;
+
+    QString number( int index ) const;
+    QString name( int index ) const;
+
+    void setDetails( int index, const QString& number, const QString& name );
+
+    bool contains( const QString& number ) const { return numbers.contains( number ); }
+
+private:
+    QStringList numbers;
+    QStringList names;
+};
+
+class HardwareManipulatorFactory;
+class HardwareManipulator;
+class SimRules : public QTcpSocket
+{
+    Q_OBJECT
+public:
+    SimRules(int fd, QObject *parent, const QString& filename, HardwareManipulatorFactory *hmf );
+    ~SimRules() {}
+
+    // get the variable value for.
+    QString variable(const QString &name);
+
+    // Load the peer information from a separate XML file.
+    void loadPeers( const QString& filename );
+
+    // Get the current simulator state.
+    SimState *current() const { return currentState; }
+
+    // Get the default simulator state.
+    SimState *defaultState() const { return defState; }
+
+    // Issue a response to the client.
+    void respond( const QString& resp, int delay, bool eol=true );
+
+    // Expand variable references in a string.
+    QString expand( const QString& s );
+
+    // Send a command to the connected peer, if any.
+    void peerCommand( const QString& cmd );
+
+    // Connect to a phone simulator peer if the number is recognised as a peer.
+    // Returns false if not using a peer.
+    bool peerConnect( const QString& number );
+
+    // Hangup the connected peer, if any.
+    void peerHangup();
+
+    // Get the phone number for this peer.
+    QString phoneNumber();
+
+    // Print the phone number for this peer.
+    void printPeerNumber();
+
+    // force the next returned reply to be 'error'
+    void setReturnError( const QString &error, uint repeat = 0 );
+
+    // Allocate a new call identifier.
+    int newCall();
+
+    // Forget a call identifier.
+    void forgetCall( int id );
+
+    // Forget all call identifiers (global hangup).
+    void forgetAllCalls();
+
+    void setPhoneNumber(const QString &s);
+
+    // Gets the hardware manipulator
+    HardwareManipulator * getMachine() const;
+
+    // Get the call manager for this rule object.
+    CallManager *callManager() const { return _callManager; }
+
+    // Get or set the SIM toolkit application.
+    SimApplication *simApplication() const { return toolkitApp; }
+    void setSimApplication( SimApplication *app );
+
+signals:
+    void returnQueryVariable( const QString&, const QString & );
+    void returnQueryState( const QString& );
+    void modemCommand( const QString& );
+    void modemResponse( const QString& );
+
+public slots:
+    void queryVariable( const QString &name );
+    void queryState( );
+    // Set a variable to a new value.
+    void setVariable( const QString& name, const QString& value );
+
+    // Switch to a new simulator state.
+    void switchTo(const QString& name);
+
+    // Process a command.
+    void command( const QString& cmd );
+
+    // Send an unsolicited response to the client.
+    void unsolicited( const QString& resp );
+
+    // Send a response line.
+    void respond( const QString& resp ) { respond( resp, 0 ); }
+
+private slots:
+    void tryReadCommand();
+    void destruct();
+    void delayTimeout();
+    void dialCheck( const QString& number, bool& ok );
+
+private:
+    SimState *currentState;
+    SimState *defState;
+    QList<SimState *> states;
+    QMap<QString,QString> variables;
+    QMap<QString,QString> peers;
+    int usedCallIds;
+    bool useGsm0710;
+    int currentChannel;
+    char incomingBuffer[1024];
+    int incomingUsed;
+    char lineBuffer[1024];
+    int lineUsed;
+    SimFileSystem *fileSystem;
+    SimApplication *defaultToolkitApp;
+    SimApplication *toolkitApp;
+
+    // Get a particular state object.
+    SimState *state( const QString& name ) const;
+
+    QString return_error_string;
+    uint return_error_count;
+    QString mPhoneNumber;
+    HardwareManipulator *machine;
+
+    void writeGsmFrame( int type, const char *data, uint len );
+    void writeChatData( const char *data, uint len );
+
+    void initPhoneBooks();
+    void phoneBook( const QString& cmd );
+    SimPhoneBook *currentPB() const;
+    void loadPhoneBook( SimXmlNode& node );
+
+    QString currentPhoneBook;
+    QMap< QString, SimPhoneBook * > phoneBooks;
+
+    CallManager *_callManager;
+};
+
+
+class SimDelayTimer : public QTimer
+{
+    Q_OBJECT
+public:
+    SimDelayTimer( const QString& response, int channel )
+        : QTimer() { this->response = response; this->channel = channel; }
+
+public:
+    QString response;
+    int channel;
+};
+
+
+#endif /* PHONESIM_H */

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qcbsmessage.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qcbsmessage.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qcbsmessage.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,466 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qcbsmessage.h>
+#include <qatutils.h>
+#ifdef PHONESIM
+#include "qsmsmessage_p.h"
+#else
+#include <qtopiaphone/private/qsmsmessage_p.h>
+#endif
+#ifdef Q_WS_QWS
+#include <qtopialog.h>
+#else
+#include <qdebug.h>
+#define qLog(dbgcat) if(1); else qDebug()
+#endif
+#include <QTextCodec>
+
+class QCBSMessagePrivate
+{
+public:
+    QCBSMessagePrivate()
+    {
+        mMessageCode = 0;
+        mScope = QCBSMessage::CellWide;
+        mUpdateNumber = 0;
+        mChannel = 0;
+        mLanguage = QCBSMessage::English;
+        mPage = 1;
+        mNumPages = 1;
+    }
+
+    ~QCBSMessagePrivate()
+    {
+    }
+
+    template <typename Stream> void readFromStream( Stream &s )
+    {
+        int val;
+        s >> mMessageCode;
+        s >> val;
+        mScope = (QCBSMessage::GeographicalScope)val;
+        s >> mUpdateNumber;
+        s >> mChannel;
+        s >> val;
+        mLanguage = (QCBSMessage::Language)val;
+        s >> mPage;
+        s >> mNumPages;
+        s >> mText;
+    }
+
+    template <typename Stream> void writeToStream( Stream &s )
+    {
+        s << mMessageCode;
+        s << (int)mScope;
+        s << mUpdateNumber;
+        s << mChannel;
+        s << (int)mLanguage;
+        s << mPage;
+        s << mNumPages;
+        s << mText;
+    }
+
+    uint mMessageCode;
+    QCBSMessage::GeographicalScope mScope;
+    uint mUpdateNumber;
+    uint mChannel;
+    QCBSMessage::Language mLanguage;
+    uint mPage;
+    uint mNumPages;
+    QString mText;
+};
+
+
+/*!
+    \class QCBSMessage
+    \mainclass
+    \brief The QCBSMessage class specifies the contents of a cell broadcast message.
+
+    \ingroup telephony
+
+    Cell broadcast messages arrive asynchronously from the network
+    and are delivered to applications via the QCellBroadcast::broadcast()
+    signal.  The most common use of cell broadcast messages is to
+    display cell location information.
+
+    Cell broadcast messages are uniquely identified by a combination of
+    scope(), messageCode(), and updateNumber().  Together with the cell identifier,
+    QNetworkRegistration::cellId(), and the location area code,
+    QNetworkRegistration::locationAreaCode(), client applications can determine
+    if a message is new, or a repetition of an existing message.
+
+    \sa QCellBroadcast, QNetworkRegistration
+*/
+
+/*!
+    \enum QCBSMessage::GeographicalScope smsmessage.h
+    Describes the geographical scope of a cell broadcast message, which is used to
+    help determine if a cell broadcast message is new.
+
+    \value CellWide The message is specific to the current cell.  If a message
+                    arrives with the same messageCode() and updateNumber() as an
+                    existing message, but QNetworkRegistration::cellId() has changed,
+                    then the message is new rather than a repetition.  Messages with
+                    the \c CellWide scope should be displayed immediately if possible.
+    \value PLMNWide The message is specific to the network operator, regardless of cell.
+    \value LocationAreaWide The message is specific to the location area.  If a message
+                    arrives with the same messageCode() and updateNumber() as an
+                    existing message, but the QNetworkRegistration::locationAreaCode()
+                    has changed, then the message is new rather than a repetition.
+    \value CellWide2 Same as \c CellWide, but the message does not need to be
+                    displayed immediately.
+*/
+
+/*!
+    \enum QCBSMessage::Language smsmessage.h
+    Describes the language that a cell broadcast message is written in.
+
+    \value German The message is written in German.
+    \value English The message is written in English.
+    \value Italian The message is written in Italian.
+    \value French The message is written in French.
+    \value Spanish The message is written in Spanish.
+    \value Dutch The message is written in Dutch.
+    \value Swedish The message is written in Swedish.
+    \value Danish The message is written in Danish.
+    \value Portuguese The message is written in Portuguese.
+    \value Finnish The message is written in Finnish.
+    \value Norwegian The message is written in Norwegian.
+    \value Greek The message is written in Greek.
+    \value Turkish The message is written in Turkish.
+    \value Hungarian The message is written in Hungarian.
+    \value Polish The message is written in Polish.
+    \value Unspecified The language that the message is written in is unspecified.
+*/
+
+/*!
+    Constructs an empty QCBSMessage.
+*/
+QCBSMessage::QCBSMessage()
+{
+    d = new QCBSMessagePrivate();
+}
+
+/*!
+    Constructs a copy of \a msg.
+*/
+QCBSMessage::QCBSMessage(const QCBSMessage &msg)
+{
+    d = 0;
+    *this = msg;
+}
+
+/*!
+    Destructs the QCBSMessage.
+*/
+QCBSMessage::~QCBSMessage()
+{
+    delete d;
+}
+
+/*!
+    Assigns a copy of \a msg to this object.
+*/
+QCBSMessage& QCBSMessage::operator=(const QCBSMessage & msg)
+{
+    if ( this == &msg )
+        return *this;
+
+    if ( d )
+        delete d;
+    d = new QCBSMessagePrivate();
+    *d = *msg.d;
+
+    return *this;
+}
+
+/*!
+    Returns the cell broadcast message code.
+
+    \sa setMessageCode()
+*/
+uint QCBSMessage::messageCode() const
+{
+    return d->mMessageCode;
+}
+
+
+/*!
+    Sets the cell broadcast message code to \a num.
+
+    \sa messageCode()
+*/
+void QCBSMessage::setMessageCode( uint num )
+{
+    d->mMessageCode = num;
+}
+
+/*!
+    Returns the geographical scope of the message.
+
+    \sa setScope()
+*/
+QCBSMessage::GeographicalScope QCBSMessage::scope() const
+{
+    return d->mScope;
+}
+
+/*!
+    Sets the geographical scope of the message to \a scope.
+
+    \sa scope()
+*/
+void QCBSMessage::setScope( QCBSMessage::GeographicalScope scope )
+{
+    d->mScope = scope;
+}
+
+/*!
+    Returns the update number for this cell broadcast message.
+
+    \sa setUpdateNumber()
+*/
+uint QCBSMessage::updateNumber() const
+{
+    return d->mUpdateNumber;
+}
+
+/*!
+    Sets the update number for this cell broadcast message to \a num.
+
+    \sa updateNumber()
+*/
+void QCBSMessage::setUpdateNumber( uint num )
+{
+    d->mUpdateNumber = num;
+}
+
+/*!
+    Returns the channel number for this cell broadcast message.
+    The most common channel number is 50, indicating cell
+    location information.
+
+    \sa setChannel()
+*/
+uint QCBSMessage::channel() const
+{
+    return d->mChannel;
+}
+
+/*!
+    Sets the channel number for this cell broadcast message to \a chan.
+
+    \sa channel()
+*/
+void QCBSMessage::setChannel( uint chan )
+{
+    d->mChannel = chan;
+}
+
+/*!
+    Returns the language that this cell broadcast message is expressed in.
+    This can allow applications to distinguish between multiple copies
+    of the same information in different languages.
+
+    \sa setLanguage()
+*/
+QCBSMessage::Language QCBSMessage::language() const
+{
+    return d->mLanguage;
+}
+
+/*!
+    Sets the language that this cell broadcast message is expressed
+    in to \a lang.
+
+    \sa language()
+*/
+void QCBSMessage::setLanguage( QCBSMessage::Language lang )
+{
+    d->mLanguage = lang;
+}
+
+/*!
+    Returns the page number for this cell broadcast message if the
+    information that it contains is split over multiple pages.
+
+    \sa setPage()
+*/
+uint QCBSMessage::page() const
+{
+    return d->mPage;
+}
+
+/*!
+    Sets the page number for this cell broadcast message to \a page.
+
+    \sa page()
+*/
+void QCBSMessage::setPage( uint page )
+{
+    d->mPage = page;
+}
+
+/*!
+    Returns the number of pages that make up this cell broadcast message.
+
+    \sa setNumPages()
+*/
+uint QCBSMessage::numPages() const
+{
+    return d->mNumPages;
+}
+
+/*!
+    Sets the number of pages in this cell broadcast message to \a npages.
+
+    \sa numPages()
+*/
+void QCBSMessage::setNumPages( uint npages )
+{
+    d->mNumPages = npages;
+}
+
+/*!
+    Sets the text that is contained in this cell broadcast message to \a str.
+
+    \sa text()
+*/
+void QCBSMessage::setText(const QString & str)
+{
+    d->mText = str;
+}
+
+/*!
+    Returns the text that is contained in this cell broadcast message.
+
+    \sa setText()
+*/
+QString QCBSMessage::text() const
+{
+    return d->mText;
+}
+
+/*!
+    \internal
+    \fn void QCBSMessage::deserialize(Stream &stream)
+*/
+template <typename Stream> void QCBSMessage::deserialize(Stream &stream)
+{
+    d->readFromStream( stream );
+}
+
+/*!
+    \internal
+    \fn void QCBSMessage::serialize(Stream &stream) const
+*/
+template <typename Stream> void QCBSMessage::serialize(Stream &stream) const
+{
+    d->writeToStream( stream );
+}
+
+/*!
+    Returns true if this cell broadcast message object is equal to \a other; otherwise returns false.
+*/
+bool QCBSMessage::operator==( const QCBSMessage& other ) const
+{
+    return ( d->mMessageCode == other.d->mMessageCode &&
+             d->mScope == other.d->mScope &&
+             d->mUpdateNumber == other.d->mUpdateNumber &&
+             d->mChannel == other.d->mChannel &&
+             d->mLanguage == other.d->mLanguage &&
+             d->mPage == other.d->mPage &&
+             d->mNumPages == other.d->mNumPages &&
+             d->mText == other.d->mText );
+}
+
+
+/*!
+    Returns true if this cell broadcast message object is equal to \a other; otherwise returns false.
+*/
+bool QCBSMessage::operator!=( const QCBSMessage& other ) const
+{
+    return !( *this == other );
+}
+
+
+/*! \internal
+    Print the contents of this cell broadcast message to the
+    debug message stream.  For internal debugging use only.
+
+*/
+void QCBSMessage::print()
+{
+    qLog(Modem) << "channel=" << channel()
+                  << ", scope=" << (int)scope()
+                  << ", messageCode=" << (int)messageCode()
+                  << ", updateNumber=" << updateNumber()
+                  << ", language=" << language()
+                  << ", page=" << page()
+                  << ", numPages=" << numPages()
+                  << ", text=" << text();
+}
+
+static QSMSDataCodingScheme bestScheme( const QString& body )
+{
+    QTextCodec *codec = QAtUtils::codec( "gsm-noloss" );
+    uint len = body.length();
+    bool gsmSafe;
+
+    // Encode zero-length bodies in the default alphabet.
+    if ( len == 0 )
+        return QSMS_DefaultAlphabet;
+
+    // Check the body for non-GSM characters.
+    gsmSafe = codec->canEncode( body );
+
+    // Use the default alphabet if everything is GSM-compatible.
+    if ( gsmSafe )
+        return QSMS_DefaultAlphabet;
+
+    // Default to the UCS-2 alphabet.
+    return QSMS_UCS2Alphabet;
+}
+
+/*!
+    Convert this CBS message into its binary PDU form, according to
+    3GPP TS 03.41 and 3GPP TS 23.041.
+*/
+QByteArray QCBSMessage::toPdu() const
+{
+    QCBSDeliverMessage deliver;
+    deliver.pack( *this, bestScheme( text() ) );
+    return deliver.toByteArray();
+
+}
+
+/*!
+    Convert a binary \a pdu into a CBS message, according to
+    3GPP TS 03.41 and 3GPP TS 23.041.
+*/
+QCBSMessage QCBSMessage::fromPdu( const QByteArray& pdu )
+{
+    QCBSDeliverMessage deliver( pdu );
+    return deliver.unpack();
+}
+
+Q_IMPLEMENT_USER_METATYPE(QCBSMessage)

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qcbsmessage.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qcbsmessage.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qcbsmessage.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QCBSMESSAGE_H
+#define QCBSMESSAGE_H
+
+#include <qstring.h>
+#include <qdatastream.h>
+#include <qtopiaipcmarshal.h>
+
+class QCBSMessagePrivate;
+
+class QTOPIAPHONE_EXPORT QCBSMessage
+{
+public:
+    QCBSMessage();
+    QCBSMessage(const QCBSMessage &);
+    ~QCBSMessage();
+
+    enum GeographicalScope
+    {
+        CellWide            = 0,
+        PLMNWide            = 1,
+        LocationAreaWide    = 2,
+        CellWide2           = 3
+    };
+
+    enum Language
+    {
+        German      = 0,
+        English     = 1,
+        Italian     = 2,
+        French      = 3,
+        Spanish     = 4,
+        Dutch       = 5,
+        Swedish     = 6,
+        Danish      = 7,
+        Portuguese  = 8,
+        Finnish     = 9,
+        Norwegian   = 10,
+        Greek       = 11,
+        Turkish     = 12,
+        Hungarian   = 13,
+        Polish      = 14,
+        Unspecified = 15
+    };
+
+    QCBSMessage& operator=(const QCBSMessage &);
+
+    uint messageCode() const;
+    void setMessageCode( uint code );
+
+    QCBSMessage::GeographicalScope scope() const;
+    void setScope( QCBSMessage::GeographicalScope scope );
+
+    uint updateNumber() const;
+    void setUpdateNumber( uint num );
+
+    uint channel() const;
+    void setChannel( uint chan );
+
+    QCBSMessage::Language language() const;
+    void setLanguage( QCBSMessage::Language lang );
+
+    uint page() const;
+    void setPage( uint page );
+
+    uint numPages() const;
+    void setNumPages( uint npages );
+
+    void setText(const QString &);
+    QString text() const;
+
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+    bool operator==( const QCBSMessage& other ) const;
+    bool operator!=( const QCBSMessage& other ) const;
+
+    void print();
+
+    QByteArray toPdu() const;
+    static QCBSMessage fromPdu( const QByteArray& pdu );
+
+private:
+    QCBSMessagePrivate *d;
+};
+
+Q_DECLARE_USER_METATYPE(QCBSMessage)
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qcontent.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qcontent.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qcontent.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QCONTENT_H__
+#define QCONTENT_H__
+
+#include <qtopiaglobal.h>
+
+#include <QIcon>
+#include <QFileInfo>
+#include <QSharedDataPointer>
+#include <QIODevice>
+#include <QList>
+#include <QPair>
+#include <QDateTime>
+#include <qtopiaipcadaptor.h>
+#include <qtopiaipcmarshal.h>
+#include <inheritedshareddata.h>
+#include <qdrmrights.h>
+#include <QVariant>
+
+class QContentSet;
+class QContentSetModel;
+class QtopiaApplication;
+class QContentFilter;
+class QContentEngine;
+class QContentStore;
+
+typedef QContentEngine QContentPrivate;
+
+class QMimeType;
+
+typedef quint32 QtopiaDatabaseId;
+// sqlite 3 and mysql both use 8 bytes ints as records
+typedef QPair<QtopiaDatabaseId, quint64> QContentId;
+typedef QList<QContentId> QContentIdList;
+
+class QTOPIA_EXPORT QContent
+{
+public:
+
+    static const QContentId InvalidId;
+
+    QContent();
+    QContent( QContentId );
+    QContent( const QString &fileName, bool store=true );
+    QContent( const QFileInfo &fi, bool store=true );
+    QContent( const QContent &copy );
+    virtual ~QContent();
+
+    bool isValid(bool force=false) const;
+
+    QContentId id() const;
+    QString name() const;
+    void setName(const QString& docname);
+    QString untranslatedName() const;
+    QString type() const;
+    void setType(const QString& doctype);
+    qint64 size() const;     // can be -1 if invalid
+
+    QIcon icon() const;
+    QIcon icon( QDrmRights::Permission permission ) const;
+    void setIcon(const QString& iconpath);
+
+    static QContentId install( const QFileInfo & );
+    static void uninstall( QContentId );
+    static void installBatch( const QList<QFileInfo> & );
+    static void uninstallBatch( const QList<QContentId> & );
+    static void clearErrors();
+    static QContentId execToContent( const QString& );
+
+    enum ChangeType { Added, Removed, Updated };
+    bool commit(){ ChangeType ctype=Updated; return commit(ctype); }
+
+    enum DrmState {
+        Unprotected,
+        Protected
+    };
+
+    DrmState drmState() const;
+
+    enum Role {
+        UnknownUsage,
+        Document,
+        Data,
+        Application,
+        Folder
+    };
+
+    typedef Role UsageMode;
+
+    Role role() const;
+    UsageMode usageMode() const;
+
+    void setRole( Role role );
+
+    QString fileName() const;
+    QString comment() const;
+    void setComment( const QString &commment );
+    QString errorString() const;
+    bool error() const;
+    QDrmRights::Permissions permissions( bool force = true ) const;
+    QDrmRights rights( QDrmRights::Permission permisssion ) const;
+    QString file() const;
+    void setFile( const QString& filename );
+    QString linkFile() const;
+    void setLinkFile( const QString& filename );
+    bool fileKnown() const;
+    bool linkFileKnown() const {return !linkFile().isEmpty();}
+    QList< QDrmRights::Permission > mimeTypePermissions() const;
+    QStringList mimeTypeIcons() const;
+    QStringList mimeTypes() const;
+    void setMimeTypes( const QStringList &mimeTypes );
+    void setMimeTypes( const QStringList &mimeTypes, const QStringList& mimeTypeIcons, const QList< QDrmRights::Permission >& permissions);
+    void execute() const;
+    void execute(const QStringList& args) const;
+    QString iconName() const;
+
+    bool setMedia( const QString &media );
+    QString media() const;
+
+    QStringList categories() const;
+    void setCategories( const QStringList &v );
+
+    bool operator==(const QContent &other) const;
+
+    QContent &operator=(const QContent &other);
+
+    bool isPreloaded() const;
+    QString executableName() const;
+    void setExecutableName(const QString &exec);
+
+    bool isDocument() const;
+
+    enum Property
+    {
+        Album,
+        Artist,
+        Author,
+        Composer,
+        ContentUrl,
+        Copyright,
+        CopyrightUrl,
+        Description,
+        Genre,
+        InformationUrl,
+        PublisherUrl,
+        RightsIssuerUrl,
+        Track,
+        Version
+    };
+
+    void setProperty(const QString& key, const QString& value, const QString &group=QString());
+    void setProperty( Property key, const QString &value );
+    QString property(const QString& key, const QString &group=QString()) const;
+    QString property( Property key ) const;
+
+    void removeFiles();
+    void removeLinkFile();
+
+    QIODevice *open(QIODevice::OpenMode);
+    QIODevice *open() const;
+    bool save(const QByteArray &data);
+    bool load(QByteArray &data) const;
+    bool copyContent(const QContent &from);
+    bool copyTo(const QString &newPath);
+    bool moveTo(const QString &newPath);
+
+    QDateTime lastUpdated() const;
+
+    static QString propertyKey( Property property );
+
+    explicit QContent( QContentEngine *engine );
+
+    bool isDetached() const;
+
+    bool isNull() const;
+
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+    enum DocumentSystemConnection
+    {
+        DocumentSystemDirect,
+        DocumentSystemClient
+    };
+
+    static DocumentSystemConnection documentSystemConnection();
+    static bool setDocumentSystemConnection( DocumentSystemConnection connection );
+
+protected:
+    bool commit(ChangeType &change);
+
+private:
+    InheritedSharedDataPointer<QContentPrivate> d;
+
+    static void updateSets(QContentId id, QContent::ChangeType c);
+
+    friend class QtopiaApplication;
+    friend class QDrmContent;
+    friend class QContentStore;
+    friend QDebug &operator<<(QDebug &debug, const QContent &content);
+};
+
+template <> inline bool qIsDetached<QContent>(QContent &t) { return t.isDetached(); }
+
+typedef QList<QContent> QContentList;
+
+Q_DECLARE_METATYPE(QContentIdList);
+Q_DECLARE_METATYPE(QContentList);
+
+Q_DECLARE_USER_METATYPE(QContent);
+Q_DECLARE_USER_METATYPE_NO_OPERATORS(QContentId);
+Q_DECLARE_USER_METATYPE_TYPEDEF(QContentId,QContentId);
+Q_DECLARE_USER_METATYPE_TYPEDEF(QContentIdList,QContentIdList);
+Q_DECLARE_USER_METATYPE_TYPEDEF(QContentList,QContentList);
+Q_DECLARE_USER_METATYPE_ENUM(QContent::ChangeType);
+Q_DECLARE_USER_METATYPE_ENUM(QContent::Role);
+Q_DECLARE_USER_METATYPE_ENUM(QContent::DrmState);
+
+uint QTOPIA_EXPORT qHash(const QContentId &id);
+
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qcontentfilter.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qcontentfilter.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qcontentfilter.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QCONTENTFILTER_H__
+#define QCONTENTFILTER_H__
+
+#include <QSharedData>
+#include <qcontent.h>
+
+class QCategoryFilter;
+class QContentFilterPrivate;
+
+class QTOPIA_EXPORT QContentFilter
+{
+public:
+
+    enum FilterType {
+        Location,       // storage media, mount, website etc
+        Role,           // Applications, Documents
+        MimeType,       // image/gif etc
+        Directory,      // directory name
+        Category,       // category string from category subsystem
+        DRM,            // drm permissions
+        Property,      // synthetic attributes eg mtime, event
+        FileName,
+        Name,
+        QtopiaType = Role,
+        Synthetic = Property,
+        Unknown=100     // probable error
+    };
+
+    enum Operand
+    {
+        NoOperand,
+        And,
+        Or
+    };
+
+    QContentFilter();
+    QContentFilter( const QContentFilter &other );
+    QContentFilter( FilterType type, const QString &argument );
+    QContentFilter( QContent::Property property, const QString &value );
+    QContentFilter( QContent::Role role );
+    QContentFilter( const QMimeType &mime );
+    QContentFilter( const QCategoryFilter &filter );
+    ~QContentFilter();
+
+    QContentFilter &operator =( const QContentFilter &other );
+
+    QContentFilter operator ~() const;
+
+    QContentFilter operator &( const QContentFilter &other ) const;
+    QContentFilter operator |( const QContentFilter &other ) const;
+
+    QContentFilter &operator &=( const QContentFilter &other );
+    QContentFilter &operator |=( const QContentFilter &other );
+
+    bool operator ==( const QContentFilter &other ) const;
+    bool operator !=( const QContentFilter &other ) const;
+
+    Operand operand() const;
+
+    bool negated() const;
+
+    bool isValid() const;
+
+    void clear();
+
+    QList< FilterType > types() const;
+
+    QStringList arguments( FilterType type ) const;
+
+    QList< QContentFilter > subFilters() const;
+
+    bool test( const QContent &content ) const;
+
+    QStringList argumentMatches( FilterType type, const QString &scope ) const;
+
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+    static QContentFilter mimeType( const QString &mimeType );
+    static QContentFilter category( const QString &categoryId );
+    static QContentFilter name( const QString &name );
+    static QContentFilter fileName( const QString &fileName );
+    static QContentFilter property( const QString &group, const QString &key, const QString &value );
+    static QContentFilter property( const QString &key, const QString &value );
+
+private:
+    QSharedDataPointer< QContentFilterPrivate > d;
+
+    static bool test( const QContent &content, QContentFilter::FilterType type, const QString &argument );
+};
+
+Q_DECLARE_USER_METATYPE(QContentFilter);
+Q_DECLARE_USER_METATYPE_ENUM(QContentFilter::Operand);
+Q_DECLARE_USER_METATYPE_ENUM(QContentFilter::FilterType);
+
+QTOPIA_EXPORT QDebug operator <<( QDebug debug, const QContentFilter &filter );
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qcontentset.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qcontentset.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qcontentset.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QCONTENTSET_H__
+#define QCONTENTSET_H__
+
+#include <QMultiHash>
+#include <qcontent.h>
+#include <qcontentfilter.h>
+
+#include <QAbstractListModel>
+#include <qcontentsortcriteria.h>
+
+class DirectoryScanner;
+class QContentSetModel;
+class QContentSetEngine;
+
+typedef QContentSetEngine QContentSetPrivate;
+
+class QTOPIA_EXPORT QContentSet : public QObject
+{
+    Q_OBJECT
+public:
+
+    enum UpdateMode
+    {
+        Asynchronous,
+        Synchronous
+    };
+
+    explicit QContentSet( QObject *parent = 0 );
+    explicit QContentSet( const QContentFilter &, QObject *parent = 0 );
+    QContentSet( const QContentFilter &, const QStringList &, QObject *parent = 0 );
+    QContentSet( QContentFilter::FilterType, const QString&, QObject *parent = 0 );
+    QContentSet( QContentFilter::FilterType, const QString&, const QStringList &, QObject *parent = 0 );
+    QContentSet( const QContentSet &, QObject *parent = 0 );
+
+    QContentSet( UpdateMode mode, QObject *parent = 0 );
+    QContentSet( const QContentFilter &, UpdateMode mode, QObject *parent = 0 );
+    QContentSet( const QContentFilter &, const QContentSortCriteria &, UpdateMode mode, QObject *parent = 0 );
+
+    virtual ~QContentSet();
+
+    UpdateMode updateMode() const;
+
+    enum Priority { LowPriority, NormalPriority, HighPriority };
+    static void scan( const QString &path, Priority priority=NormalPriority );
+    static void findDocuments(QContentSet* folder, const QString &mimefilter=QString());
+
+
+    bool contains( const QContent &cl ) const;
+
+    void add(const QContent&);
+    void remove(const QContent&);
+    void installContent();
+    void uninstallContent();
+    void clear();
+
+    QContentList items() const;
+    QContentIdList itemIds() const;
+
+    bool isEmpty() const;
+    void appendFrom( QContentSet& other );
+    int count() const;
+    QContent findExecutable( const QString& exec ) const;
+    QContent findFileName( const QString& res ) const;
+    QStringList types() const;
+
+    QContentSet &operator=(const QContentSet&);
+
+    void addCriteria( QContentFilter::FilterType kind, const QString &filter, QContentFilter::Operand operand );
+    void addCriteria(const QContentFilter& filters, QContentFilter::Operand operand );
+    void setCriteria( QContentFilter::FilterType kind, const QString &filter);
+    void setCriteria(const QContentFilter& filters);
+    void clearFilter();
+    QContentFilter filter() const;
+
+    void setSortOrder( const QStringList &sortOrder );
+    QStringList sortOrder() const;
+
+    void setSortCriteria( const QContentSortCriteria &criteria );
+    QContentSortCriteria sortCriteria() const;
+
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+    static int count( const QContentFilter &filter );
+
+signals:
+    void contentAboutToBeInserted( int start, int end );
+    void contentInserted();
+    void contentAboutToBeRemoved( int start, int end );
+    void contentRemoved();
+    void contentChanged( int start, int end );
+    void aboutToSort();
+    void sorted();
+    void changed(const QContentIdList &, QContent::ChangeType);
+    void changed();
+
+protected:
+    void timerEvent(QTimerEvent *e);
+
+private:
+    friend class QContent;
+    friend class ContentLinkPrivate;
+    friend class QContentSetModel;
+    friend class DirectoryScanner;
+    friend class QtopiaSql;
+
+    void init();
+
+    QContentSetPrivate *d;
+};
+
+class QContentSetModelPrivate;
+
+class QTOPIA_EXPORT QContentSetModel : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    explicit QContentSetModel( const QContentSet *, QObject *parent=0 );
+    virtual ~QContentSetModel();
+
+    virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const;
+    virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;
+    virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
+    QContent content( uint ) const;
+    QContentId contentId( uint ) const;
+    QContent content( const QModelIndex & index ) const;
+    QContentId contentId( const QModelIndex & index ) const;
+
+    void setSelectPermission( QDrmRights::Permission permission );
+    QDrmRights::Permission selectPermission() const;
+
+    void setMandatoryPermissions( QDrmRights::Permissions permissions );
+    QDrmRights::Permissions mandatoryPermissions() const;
+
+    bool updateInProgress() const;
+
+signals:
+    void updateStarted();
+    void updateFinished();
+
+private slots:
+    void beginInsertContent( int start, int end );
+    void endInsertContent();
+    void beginRemoveContent( int start, int end );
+    void endRemoveContent();
+    void contentChanged( int start, int end );
+    void clearContentSet();
+    void doReset();
+    void emitLayoutAboutToBeChanged();
+    void emitLayoutChanged();
+private:
+    int rowForContentId(QContentId contentId);
+
+    const QContentSet *contentSet;
+    QContentSetModelPrivate *d;
+
+    friend class QContentSet;
+};
+
+Q_DECLARE_USER_METATYPE(QContentSet);
+Q_DECLARE_USER_METATYPE_ENUM(QContentSet::UpdateMode);
+
+QTOPIA_EXPORT QDataStream &operator <<( QDataStream &ds, const QContentSet &set );
+QTOPIA_EXPORT QDataStream &operator >>( QDataStream &ds, QContentSet &set );
+
+#endif
+

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qcontentsortcriteria.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qcontentsortcriteria.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qcontentsortcriteria.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QCONTENTSORT_H
+#define QCONTENTSORT_H
+#include <qcontentfilter.h>
+#include <QtGlobal>
+
+class QContentSortCriteriaPrivate;
+
+class QTOPIA_EXPORT QContentSortCriteria
+{
+public:
+
+    enum Attribute
+    {
+        Name,
+        MimeType,
+        Property,
+        FileName,
+        LastUpdated
+    };
+
+    QContentSortCriteria();
+    QContentSortCriteria( Attribute attribute, Qt::SortOrder order = Qt::AscendingOrder );
+    QContentSortCriteria( Attribute attribute, const QString &scope, Qt::SortOrder order = Qt::AscendingOrder );
+    QContentSortCriteria( QContent::Property property, Qt::SortOrder order = Qt::AscendingOrder );
+    QContentSortCriteria( const QContentSortCriteria &other );
+
+    ~QContentSortCriteria();
+
+    QContentSortCriteria &operator =( const QContentSortCriteria &other );
+
+    bool operator ==( const QContentSortCriteria &other ) const;
+    bool operator !=( const QContentSortCriteria &other ) const;
+
+    void addSort( Attribute attribute, Qt::SortOrder order = Qt::AscendingOrder );
+    void addSort( Attribute attribute, const QString &scope, Qt::SortOrder order = Qt::AscendingOrder );
+    void addSort( QContent::Property property, Qt::SortOrder order = Qt::AscendingOrder );
+
+    void clear();
+
+    int sortCount() const;
+
+    Attribute attribute( int index ) const;
+    QString scope( int index ) const;
+    Qt::SortOrder order( int index ) const;
+
+    int compare( const QContent &left, const QContent &right ) const;
+
+    bool lessThan( const QContent &left, const QContent &right ) const;
+    bool greaterThan( const QContent &left, const QContent &right ) const;
+
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+private:
+    QSharedDataPointer< QContentSortCriteriaPrivate > d;
+};
+
+Q_DECLARE_USER_METATYPE(QContentSortCriteria);
+Q_DECLARE_USER_METATYPE_ENUM(QContentSortCriteria::Attribute);
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qdrmcontent.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qdrmcontent.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qdrmcontent.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QDRMCONTENT_H
+#define QDRMCONTENT_H
+
+#include <QObject>
+#include <QDateTime>
+#include <qtimestring.h>
+#include <qtopiaipcadaptor.h>
+#include <qtopiaipcmarshal.h>
+#include <qcontent.h>
+
+class QDrmContentPrivate;
+
+class QTOPIA_EXPORT QDrmContent : public QObject
+{
+    Q_OBJECT
+public:
+
+    enum RenderState{ Started, Stopped, Paused };
+
+    enum LicenseOption
+    {
+        NoLicenseOptions = 0x00,
+        Activate         = 0x01,
+        Reactivate       = 0x02,
+        Handover         = 0x04,
+        Default          = Activate | Reactivate,
+    };
+
+    Q_DECLARE_FLAGS( LicenseOptions, LicenseOption );
+
+    explicit QDrmContent( QDrmRights::Permission permission = QDrmRights::Unrestricted,
+                          LicenseOptions options = Default, QObject *parent = 0 );
+
+    virtual ~QDrmContent();
+
+    RenderState renderState() const;
+
+    QDrmRights::Permission permission() const;
+
+    void setPermission( QDrmRights::Permission permission );
+
+    LicenseOptions licenseOptions() const;
+
+    void setLicenseOptions( LicenseOptions options );
+    void enableLicenseOptions( LicenseOptions options );
+    void disableLicenseOptions( LicenseOptions options );
+
+    QWidget *focusWidget() const;
+    void setFocusWidget( QWidget *focus );
+
+    QContent content() const;
+
+    static bool activate( const QContent &content, QWidget *focus = 0 );
+    static bool canActivate( const QContent &content );
+
+    static QStringList supportedTypes();
+    static QList< QPair< QString, QString > > httpHeaders();
+
+public slots:
+    bool requestLicense( const QContent &content );
+    void releaseLicense();
+
+    void renderStarted();
+    void renderStopped();
+    void renderPaused();
+
+signals:
+    void licenseGranted( const QContent &content );
+    void licenseDenied( const QContent &content );
+    void renderStateChanged( const QDrmContent &content );
+    void rightsExpired( const QDrmContent &content );
+
+private:
+    void init( QDrmRights::Permission permission, LicenseOptions options );
+    bool getLicense( const QContent &content, QDrmRights::Permission );
+
+    QDrmContentPrivate *d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS( QDrmContent::LicenseOptions );
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qdrmrights.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qdrmrights.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qdrmrights.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QDRMRIGHTS_H
+#define QDRMRIGHTS_H
+
+#include <qtopiaglobal.h>
+#include <qtopiaipcmarshal.h>
+#include <QSharedData>
+#include <QStringList>
+#include <QFlags>
+#include <QPair>
+
+class QDrmRightsPrivate;
+class QDrmRightsConstraintPrivate;
+
+
+class QTOPIA_EXPORT QDrmRights
+{
+public:
+    enum Status
+    {
+        Invalid,
+        Valid,
+        ValidInFuture
+    };
+
+    enum Permission
+    {
+        NoPermissions     = 0x0000,
+        Play              = 0x0001,
+        Display           = 0x0002,
+        Execute           = 0x0004,
+        Print             = 0x0008,
+        Export            = 0x0010,
+        Distribute        = 0x0020,
+        Preview           = 0x0040,
+        Automated         = 0x0080,
+        BrowseContents    = 0x0100,
+        Unrestricted      = 0x7F00 | Play | Display | Execute | Print | Export | Distribute | Preview | Automated | BrowseContents,
+        InvalidPermission = 0x8000
+    };
+
+    Q_DECLARE_FLAGS( Permissions, Permission );
+
+    class QTOPIA_EXPORT Constraint
+    {
+    public:
+        Constraint();
+        Constraint( const QString &name, const QVariant &value );
+        Constraint( const QString &name, const QVariant &value, const QList< QPair< QString, QVariant > > &attributes );
+        Constraint( const Constraint &other );
+        ~Constraint();
+
+        Constraint &operator =( const Constraint &other );
+
+        QString name() const;
+        QVariant value() const;
+
+        int attributeCount() const;
+        QString attributeName( int index ) const;
+        QVariant attributeValue( int index ) const;
+
+        template <typename Stream> void serialize(Stream &stream) const;
+        template <typename Stream> void deserialize(Stream &stream);
+
+    private:
+        QSharedDataPointer< QDrmRightsConstraintPrivate > d;
+    };
+
+    typedef QList< Constraint > ConstraintList;
+
+    QDrmRights();
+    QDrmRights( Permission permission, Status status, const ConstraintList &constraints = ConstraintList() );
+    QDrmRights( const QDrmRights &other );
+    ~QDrmRights();
+
+    QDrmRights &operator =( const QDrmRights &other );
+
+    Permission permission() const;
+
+    Status status() const;
+
+    ConstraintList constraints() const;
+
+    static QString toString( Permission permission );
+    static QString toString( Permission permission, Status status );
+
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+private:
+    QSharedDataPointer< QDrmRightsPrivate > d;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDrmRights::Permissions);
+Q_DECLARE_USER_METATYPE_ENUM(QDrmRights::Permission);
+Q_DECLARE_USER_METATYPE_ENUM(QDrmRights::Permissions);
+Q_DECLARE_USER_METATYPE_ENUM(QDrmRights::Status);
+Q_DECLARE_USER_METATYPE(QDrmRights);
+Q_DECLARE_USER_METATYPE(QDrmRights::Constraint);
+Q_DECLARE_USER_METATYPE_TYPEDEF(QDrmRightsConstraintList,QDrmRights::ConstraintList);
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qlog.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qlog.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qlog.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QCATEGORIZEDLOG_H
+#define QCATEGORIZEDLOG_H
+
+#include <qdebug.h>
+#include <qtopiaglobal.h>
+
+#ifndef QT_NO_LOG_STREAM
+
+template<class T> inline int qLog_opt(const T &) { return 1; }
+
+enum QLogUncategorized { _QLog=true }; // So "uncategorized" qLog() works.
+
+/* Catch compile time enums (at most one symbol) */
+template<> inline int qLog_opt<int>(const int & v) { return v; }
+
+class QTOPIABASE_EXPORT QLogBase {
+public:
+    static QDebug log(const char*);
+};
+
+# define QLOG_DISABLE(dbgcat) \
+    class dbgcat##_QLog : public QLogBase { \
+    public: \
+        static inline bool enabled() { return 0; }\
+    };
+# define QLOG_ENABLE(dbgcat) \
+    class dbgcat##_QLog : public QLogBase { \
+    public: \
+        static inline bool enabled() { return 1; }\
+    };
+# define QLOG_OPTION_VOLATILE(dbgcat,expr) \
+    class dbgcat##_QLog : public QLogBase { \
+    public: \
+        static inline bool enabled() { return expr; }\
+    };
+# define QLOG_OPTION(dbgcat,expr) \
+    class dbgcat##_QLog : public QLogBase { \
+    public: \
+        static inline bool enabled() { static char mem=0; return (mem ? mem : (mem=(expr)?3:2))&1; } \
+    };
+
+# define qLog(dbgcat) if(!dbgcat##_QLog::enabled()); else dbgcat##_QLog::log(#dbgcat)
+# define qLogEnabled(dbgcat) (dbgcat##_QLog::enabled())
+#else
+# define QLOG_DISABLE(dbgcat)
+# define QLOG_ENABLE(dbgcat)
+# define QLOG_OPTION(dbgcat,expr)
+# define QLOG_OPTION_VOLATILE(dbgcat,expr)
+# define qLog(dbgcat) if(1); else QNoDebug()
+# define qLogEnabled(dbgcat) false
+#endif
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qmimetype.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qmimetype.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qmimetype.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QMIMETYPE_H
+#define QMIMETYPE_H
+
+#include <qtopiaglobal.h>
+#include <qstringlist.h>
+#include <qicon.h>
+#include <qlist.h>
+#include <QMutex>
+
+#include <qdrmcontent.h>
+#include <qcontentset.h>
+
+class QStringList;
+class QMimeTypeData;
+
+class QTOPIA_EXPORT QMimeType
+{
+public:
+    QMimeType();
+    explicit QMimeType( const QString& ext_or_id );
+    explicit QMimeType( const QContent& );
+    QMimeType( const QMimeType &other );
+
+    QMimeType &operator =( const QMimeType &other );
+
+    bool operator ==( const QMimeType &other ) const;
+
+    enum IconType
+    {
+        Default,
+        DrmValid,
+        DrmInvalid
+    };
+
+    QString id() const;
+    QString description() const;
+    QIcon icon( IconType iconType = Default ) const;
+
+    QString extension() const;
+    QStringList extensions() const;
+    QContentList applications() const;
+    QContent application() const;
+
+    QDrmRights::Permission permission() const;
+    QList<QDrmRights::Permission> permissions() const;
+
+    static void updateApplications();
+
+    bool isNull() const;
+
+    static QMimeType fromId( const QString &mimeId );
+    static QMimeType fromExtension( const QString &extension );
+    static QMimeType fromFileName( const QString &fileName );
+
+    static void addAssociation(const QString& mimeType, const QString& application, const QString& icon, QDrmRights::Permission permission);
+    static void removeAssociation(const QString& mimeType, const QString& application);
+    static QContentList applicationsFor(const QContent&);
+    static QContentList applicationsFor(const QMimeType&);
+    static QContent defaultApplicationFor(const QContent&);
+    static QContent defaultApplicationFor(const QMimeType&);
+    static void setDefaultApplicationFor(const QString&, const QContent&);
+
+private:
+    static void clear();
+    static void loadExtensions();
+    static void loadExtensions(const QString&);
+    void init( const QString& ext_or_id );
+    static QMimeTypeData data(const QString& id);
+    QString mimeId;
+    static QMutex staticsGuardMutex;
+
+    friend class QMimeTypeData;
+    friend class QtopiaApplication;
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsimcommand.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsimcommand.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsimcommand.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,3236 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qsimcommand.h>
+#include <qatutils.h>
+#include <qsmsmessage.h>
+#include <qgsmcodec.h>
+#include <qtopialog.h>
+
+
+class QSimMenuItemPrivate
+{
+public:
+    QSimMenuItemPrivate()
+    {
+        identifier = 0;
+        iconId = 0;
+        hasHelp = false;
+        iconSelfExplanatory = false;
+        nextAction = 0;
+    }
+
+    uint identifier;
+    QString label;
+    uint iconId;
+    bool hasHelp;
+    bool iconSelfExplanatory;
+    uint nextAction;
+};
+
+
+class QSimCommandPrivate
+{
+public:
+    QSimCommandPrivate()
+    {
+#if QT_VERSION < 0x040400
+        ref.init(1);
+#else
+        ref = 1;
+#endif
+        commandNumber = 1;
+        type = QSimCommand::NoCommand;
+        sourceDevice = QSimCommand::SIM;
+        destinationDevice = QSimCommand::ME;
+        flags = 0;
+        minimumLength = 0;
+        maximumLength = 255;
+        callClass = QSimCommand::Voice;
+        tone = QSimCommand::ToneNone;
+        duration = 0;
+        defaultItem = 0;
+        iconId = 0;
+        otherIconId = 0;
+        device = -1;
+        qualifier = 0;
+    }
+    QSimCommandPrivate( QSimCommandPrivate *other )
+    {
+#if QT_VERSION < 0x040400
+        ref.init(1);
+#else
+        ref = 1;
+#endif
+        commandNumber = other->commandNumber;
+        type = other->type;
+        sourceDevice = other->sourceDevice;
+        destinationDevice = other->destinationDevice;
+        flags = other->flags;
+        text = other->text;
+        otherText = other->otherText;
+        defaultText = other->defaultText;
+        minimumLength = other->minimumLength;
+        maximumLength = other->maximumLength;
+        number = other->number;
+        subAddress = other->subAddress;
+        callClass = other->callClass;
+        tone = other->tone;
+        duration = other->duration;
+        title = other->title;
+        defaultItem = other->defaultItem;
+        menuItems = other->menuItems;
+        url = other->url;
+        iconId = other->iconId;
+        otherIconId = other->otherIconId;
+        device = other->device;
+        qualifier = other->qualifier;
+        extensionData = other->extensionData;
+    }
+
+    template <typename Stream> int readInt( Stream &stream )
+    {
+        int value;
+        stream >> value;
+        return value;
+    }
+
+    template <typename Stream>  void read( Stream &stream )
+    {
+        commandNumber = readInt( stream );
+        type = (QSimCommand::Type)readInt( stream );
+        sourceDevice = (QSimCommand::Device)readInt( stream );
+        destinationDevice = (QSimCommand::Device)readInt( stream );
+        flags = readInt( stream );
+        stream >> text;
+        stream >> otherText;
+        stream >> defaultText;
+        stream >> minimumLength;
+        stream >> maximumLength;
+        stream >> number;
+        stream >> subAddress;
+        callClass = (QSimCommand::CallClass)readInt( stream );
+        tone = (QSimCommand::Tone)readInt( stream );
+        stream >> duration;
+        stream >> title;
+        stream >> defaultItem;
+        stream >> menuItems;
+        stream >> url;
+        stream >> iconId;
+        stream >> otherIconId;
+        stream >> device;
+        stream >> qualifier;
+        stream >> extensionData;
+    }
+
+    template <typename Stream> void write( Stream &stream )
+    {
+        stream << commandNumber;
+        stream << (int)type;
+        stream << (int)sourceDevice;
+        stream << (int)destinationDevice;
+        stream << flags;
+        stream << text;
+        stream << otherText;
+        stream << defaultText;
+        stream << minimumLength;
+        stream << maximumLength;
+        stream << number;
+        stream << subAddress;
+        stream << (int)callClass;
+        stream << (int)tone;
+        stream << duration;
+        stream << title;
+        stream << defaultItem;
+        stream << menuItems;
+        stream << url;
+        stream << iconId;
+        stream << otherIconId;
+        stream << device;
+        stream << qualifier;
+        stream << extensionData;
+    }
+
+    bool flag( int bit ) const
+    {
+        return ( ( flags & bit ) != 0 );
+    }
+
+    void setFlag( int bit, bool value )
+    {
+        if ( value )
+            flags |= bit;
+        else
+            flags &= ~bit;
+    }
+
+    bool qualifierBit( int bit ) const
+    {
+        return ( ( qualifier & bit ) != 0 );
+    }
+
+    void setQualifierBit( int bit, bool value )
+    {
+        if ( value )
+            qualifier |= bit;
+        else
+            qualifier &= ~bit;
+    }
+
+    #define SC_ImmediateResponse    (1<<0)
+    #define SC_IconSelfExplanatory  (1<<1)
+    #define SC_IconSelfExplanatory2 (1<<2)
+    #define SC_SuppressUserFeedback (1<<3)
+
+#if QT_VERSION < 0x040400
+    QBasicAtomic ref;
+#else
+    QAtomicInt ref;
+#endif
+    int commandNumber;
+    QSimCommand::Type type;
+    QSimCommand::Device sourceDevice;
+    QSimCommand::Device destinationDevice;
+    int flags;
+    QString text;
+    QString otherText;
+    QString defaultText;
+    uint minimumLength;
+    uint maximumLength;
+    QString number;
+    QString subAddress;
+    QSimCommand::CallClass callClass;
+    QSimCommand::Tone tone;
+    uint duration;
+    QString title;
+    uint defaultItem;
+    QList<QSimMenuItem> menuItems;
+    QString url;
+    uint iconId;
+    uint otherIconId;
+    int device;
+    int qualifier;
+    QByteArray extensionData;
+
+};
+
+
+/*!
+    \class QSimMenuItem
+    \mainclass
+    \brief The QSimMenuItem class provides information about a menu item within a SIM toolkit application
+
+    \ingroup telephony
+    \sa QSimCommand, QSimToolkit
+*/
+
+/*!
+    Construct a new menu item with default parameters.
+*/
+QSimMenuItem::QSimMenuItem()
+{
+    d = new QSimMenuItemPrivate();
+}
+
+
+/*!
+    Construct a new menu item as a copy of \a value.
+*/
+QSimMenuItem::QSimMenuItem( const QSimMenuItem& value )
+{
+    d = new QSimMenuItemPrivate();
+    d->identifier = value.d->identifier;
+    d->label = value.d->label;
+    d->iconId = value.d->iconId;
+    d->hasHelp = value.d->hasHelp;
+    d->iconSelfExplanatory = value.d->iconSelfExplanatory;
+    d->nextAction = value.d->nextAction;
+}
+
+
+/*!
+    Destruct a menu item.
+*/
+QSimMenuItem::~QSimMenuItem()
+{
+    delete d;
+}
+
+
+/*!
+    Returns the menu item's numeric identifier.
+
+    \sa setIdentifier()
+*/
+uint QSimMenuItem::identifier() const
+{
+    return d->identifier;
+}
+
+
+/*!
+    Sets the menu item's numeric identifier to \a value.
+
+    \sa identifier()
+*/
+void QSimMenuItem::setIdentifier( uint value )
+{
+    d->identifier = value;
+}
+
+
+/*!
+    Returns the menu item's label.
+
+    \sa setLabel()
+*/
+QString QSimMenuItem::label() const
+{
+    return d->label;
+}
+
+
+/*!
+    Sets the menu item's label to \a value.
+
+    \sa label()
+*/
+void QSimMenuItem::setLabel( const QString& value )
+{
+    d->label = value;
+}
+
+
+/*!
+    Returns true if this menu item has help available; otherwise returns false.
+
+    \sa setHasHelp()
+*/
+bool QSimMenuItem::hasHelp() const
+{
+    return d->hasHelp;
+}
+
+
+/*!
+    Sets the flag that indicates if this menu item has help
+    available to \a value.
+
+    \sa hasHelp()
+*/
+void QSimMenuItem::setHasHelp( bool value )
+{
+    d->hasHelp = value;
+}
+
+
+/*!
+    Returns the icon identifier associated with this menu item.
+    Returns zero if there is no icon.
+
+    \sa setIconId()
+*/
+uint QSimMenuItem::iconId() const
+{
+    return d->iconId;
+}
+
+
+/*!
+    Sets the icon identifier associated with this menu item to \a value.
+
+    \sa iconId()
+*/
+void QSimMenuItem::setIconId( uint value )
+{
+    d->iconId = value;
+}
+
+
+/*!
+    Returns true if the icon specified by iconId() is self-explanatory
+    without the display of label().  If this function returns false,
+    then label() should be displayed next to the icon.  If iconId()
+    returns zero, then iconSelfExplanatory() should be ignored.
+
+    \sa setIconSelfExplanatory()
+*/
+bool QSimMenuItem::iconSelfExplanatory() const
+{
+    return d->iconSelfExplanatory;
+}
+
+
+/*!
+    Sets the self-explanatory flag to \a value.
+
+    \sa iconSelfExplanatory()
+*/
+void QSimMenuItem::setIconSelfExplanatory( bool value )
+{
+    d->iconSelfExplanatory = value;
+}
+
+
+/*!
+    Returns the next action indicator for this menu item.  Next action indicators
+    have the same values as command types from the QSimCommand::Type list.
+    The default value is zero, indicating no next action indicator for this menu item.
+
+    \sa setNextAction()
+*/
+uint QSimMenuItem::nextAction() const
+{
+    return d->nextAction;
+}
+
+
+/*!
+    Sets the next action indicator for this menu item to \a value.  Next action
+    indicators have the same values as command types from the QSimCommand::Type list.
+    The value zero indicates that there is no next action indicator for this menu item.
+
+    \sa nextAction()
+*/
+void QSimMenuItem::setNextAction( uint value )
+{
+    d->nextAction = value;
+}
+
+
+/*!
+    Make a copy of \a value.
+*/
+QSimMenuItem& QSimMenuItem::operator=( const QSimMenuItem & value )
+{
+    d->identifier = value.d->identifier;
+    d->label = value.d->label;
+    d->iconId = value.d->iconId;
+    d->hasHelp = value.d->hasHelp;
+    d->iconSelfExplanatory = value.d->iconSelfExplanatory;
+    d->nextAction = value.d->nextAction;
+    return *this;
+}
+
+
+/*!
+    \fn void QSimMenuItem::deserialize(Stream &value)
+
+    \internal
+
+    Deserializes the QSimMenuItem instance out to a template
+    type \c{Stream} \a stream.
+ */
+
+template <typename Stream> void QSimMenuItem::deserialize(Stream &stream)
+{
+    stream >> d->identifier;
+    stream >> d->label;
+    stream >> d->iconId;
+    int value;
+    stream >> value;
+    d->hasHelp = (value != 0);
+    stream >> value;
+    d->iconSelfExplanatory = (value != 0);
+    stream >> d->nextAction;
+}
+
+/*!
+    \fn void QSimMenuItem::serialize(Stream &value) const
+
+    \internal
+
+    Serializes the QSimMenuItem instance out to a template
+    type \c{Stream} \a stream.
+ */
+
+template <typename Stream> void QSimMenuItem::serialize(Stream &stream) const
+{
+    stream << d->identifier;
+    stream << d->label;
+    stream << d->iconId;
+    stream << (int)(d->hasHelp);
+    stream << (int)(d->iconSelfExplanatory);
+    stream << d->nextAction;
+}
+
+/*!
+    \class QSimCommand
+    \mainclass
+    \brief The QSimCommand class specifies the details of a SIM toolkit command message.
+
+    Applications that run within a SIM send commands to the host program
+    to interact with the user.  These commands might entail choosing an
+    item from a menu, asking if it is OK to dial a phone number, asking
+    for a line of input, displaying text messages, etc.
+
+    The QSimCommand class encapsulates a single SIM toolkit command,
+    containing all of the information about it.  QSimCommand objects
+    are delivered to the host program by way of the QSimToolkit::command() signal.
+
+    In Qtopia, the host program is \c simapp.
+
+    \ingroup telephony
+    \sa QSimToolkit, QSimMenuItem, QSimTerminalResponse
+*/
+
+/*!
+    \enum QSimCommand::Type
+    This enum defines the type of a SIM toolkit message within a
+    QSimCommand object.
+
+    \value NoCommand No command type currently set.
+    \value Timeout Indicate that an operation has timed out.
+    \value Refresh Notification of a SIM refresh.
+    \value MoreTime The SIM toolkit application is asking for more time.
+           This command type is handled automatically by the modem or the
+           modem vendor plugin, so client applications will not see this
+           command type via QSimToolkit::command().
+    \value PollInterval The SIM toolkit application is setting the polling interval
+           for new commands.  This command type is handled automatically by the
+           modem or the modem vendor plugin, so client applications will not see this
+           command type via QSimToolkit::command().
+    \value PollingOff This SIM toolkit application is asking for polling to be turned off.
+           This command type is handled automatically by the modem or the
+           modem vendor plugin, so client applications will not see this
+           command type via QSimToolkit::command().
+    \value SetupEventList Set up the list of events to be reported to the
+           SIM toolkit application.
+    \value SetupCall Set up a phone call to a specific number.
+    \value SendSS Notification that the application is sending a SS message.
+    \value SendSMS Notification that the application is sending a SMS message.
+    \value SendUSSD Notification that the application is sending a USSD message.
+    \value SendDTMF Notification that the application is sending a DTMF tone.
+    \value LaunchBrowser Launch a Web browser on a URL.
+    \value PlayTone Play a tone to the user.
+    \value DisplayText Display a text message.
+    \value GetInkey Get a single key of input.
+    \value GetInput Get a line of input.
+    \value SelectItem Process a submenu within a SIM toolkit application.
+    \value SetupMenu Process the main menu of a SIM toolkit application.
+    \value ProvideLocalInformation The SIM toolkit application is asking for local
+           information to be supplied.  This command type is handled automatically
+           by the modem or the modem vendor plugin, so client applications will
+           not see this command type via QSimToolkit::command().
+    \value TimerManagement The SIM toolkit application is activating or deactivating
+           timers.  This command type is handled automatically by the modem or the
+           modem vendor plugin, so client applications will not see this
+           command type via QSimToolkit::command().
+    \value SetupIdleModeText Set the text to be displayed when the phone is idle.
+    \value PerformCardAPDU Send an APDU to the additional card reader.
+           This command type is handled automatically by the modem or the
+           modem vendor plugin, so client applications will not see this
+           command type via QSimToolkit::command().
+    \value PowerOnCard Power on an additional card reader.
+           This command type is handled automatically by the modem or the
+           modem vendor plugin, so client applications will not see this
+           command type via QSimToolkit::command().
+    \value PowerOffCard Power off an additional card reader.
+           This command type is handled automatically by the modem or the
+           modem vendor plugin, so client applications will not see this
+           command type via QSimToolkit::command().
+    \value GetReaderStatus Get the status of an additional card reader.
+           This command type is handled automatically by the modem or the
+           modem vendor plugin, so client applications will not see this
+           command type via QSimToolkit::command().
+    \value RunATCommand Run an AT command against the modem
+    \value LanguageNotification Inform the user about the language the SIM
+           toolkit application will be displaying messages in.
+    \value OpenChannel Open a data channel.
+    \value CloseChannel Close a data channel.
+    \value ReceiveData Receive data on a data channel.
+    \value SendData Send data on a data channel.
+    \value GetChannelStatus Get the current status of a data channel.
+    \value EndSession Indicate that the SIM toolkit session has ended
+    \value SetupMainMenu Alias for SetupMenu, provided for backwards compatiblity.
+    \value SetupSubMenu Alias for SelectItem, provided for backwards compatiblity.
+*/
+
+/*!
+    \enum QSimCommand::Disposition
+    This enum defines the disposition of other calls when a \c SetupCall
+    command is executed by the SIM toolkit application.
+
+    \value IfNoOtherCalls Perform the setup only if there are no other calls.
+    \value PutOnHold Put other calls on hold when the new call is setup.
+    \value Disconnect Disconnect other calls when the new call is setup.
+*/
+
+/*!
+    \enum QSimCommand::CallClass
+    This enum defines the class of call that is being created by a
+    \c SetupCall command.
+
+    \value Voice Voice call
+    \value Data Data call
+    \value Fax Fax call
+*/
+
+/*!
+    \enum QSimCommand::Tone
+    This enum defines the tones that can be played by a \c PlayTone command.
+
+    \value ToneNone No tone specified.
+    \value ToneDial Currently dialing
+    \value ToneBusy Called party is busy
+    \value ToneCongestion Network is congested
+    \value ToneRadioAck Radio acknowledged
+    \value ToneDropped Connection has been dropped
+    \value ToneError An error occurred
+    \value ToneCallWaiting An incoming call is waiting
+    \value ToneRinging Ring to indicate and incoming call
+    \value ToneGeneralBeep A general beep tone
+    \value TonePositiveBeep A beep indicating a positive outcome
+    \value ToneNegativeBeep A beep indicating a negative outcome
+
+*/
+
+/*!
+    \enum QSimCommand::RefreshType
+    This enum defines the type of refresh that was performed by the SIM.
+
+    \value InitAndFullFileChange SIM initialization and full file
+           change notification.
+    \value FileChange File change notification.
+    \value InitAndFileChange SIM initialization and file change notification.
+    \value Initialization SIM initialization.
+    \value Reset SIM reset.
+*/
+
+/*!
+    \enum QSimCommand::Event
+    This enum defines the types of events that the SIM expects to be reported.
+
+    \value NoEvent No event type specified.
+    \value IdleScreen Report an event when the system is idle.
+    \value UserActivity Report an event when there is user activity.
+    \value Both Report for both system idle and user activity.
+    \value Cancel Cancel event reporting.
+*/
+
+/*!
+    \enum QSimCommand::BrowserLaunchMode
+    This enum defines the launch mode to use when displaying web pages in the browser.
+
+    \value IfNotAlreadyLaunched Launch browser, if not already launched.
+    \value UseExisting Use the existing browser, but not if it is running
+           a secured session.
+    \value CloseExistingAndLaunch Close the existing browser session
+           and launch a new browser session.
+*/
+
+/*!
+    \enum QSimCommand::MenuPresentation
+    This enum defines the type of presentation to use for SIM toolkit menus.
+
+    \value AnyPresentation The user interface may use any presentation it wishes.
+    \value DataValuesPresentation The user interface should present the menu as
+           a choice of several data values.
+    \value NavigationOptionsPresentation The user interface should present the menu
+           as a choice of several navigation options.
+*/
+
+/*!
+    \enum QSimCommand::Device
+    This enum defines the source or destination device for a SIM command, according
+    to 3GPP TS 11.14, section 12.7.
+    
+    \value Keypad Keypad device
+    \value Display Display device
+    \value Earpiece Earpiece device
+    \value CardReader0 Additional card reader 0
+    \value CardReader1 Additional card reader 1
+    \value CardReader2 Additional card reader 2
+    \value CardReader3 Additional card reader 3
+    \value CardReader4 Additional card reader 4
+    \value CardReader5 Additional card reader 5
+    \value CardReader6 Additional card reader 6
+    \value CardReader7 Additional card reader 7
+    \value Channel1 Data channel 1
+    \value Channel2 Data channel 2
+    \value Channel3 Data channel 3
+    \value Channel4 Data channel 4
+    \value Channel5 Data channel 5
+    \value Channel6 Data channel 6
+    \value Channel7 Data channel 7
+    \value SIM SIM device
+    \value ME ME (mobile equipment) device
+    \value Network Source or destination is the network
+*/
+
+/*!
+    Construct a new SIM toolkit command object with default parameters.
+*/
+QSimCommand::QSimCommand()
+{
+    d = new QSimCommandPrivate();
+}
+
+
+/*!
+    Construct a new SIM toolkit command object as a copy of \a value.
+*/
+QSimCommand::QSimCommand( const QSimCommand& value )
+{
+    d = value.d;
+    d->ref.ref();
+}
+
+
+/*!
+    Destruct a SIM toolkit command object.
+*/
+QSimCommand::~QSimCommand()
+{
+    if ( !d->ref.deref() )
+        delete d;
+}
+
+
+/*!
+    Returns the SIM command number.  The default value is 1.  The command number
+    may be something other than 1 if more than one SIM command is being processed
+    simultaneously, but this is a fairly rare occurence.  The main use for
+    command numbers is to match commands and responses.
+
+    Applies to: all commands
+
+    \sa setCommandNumber()
+*/
+int QSimCommand::commandNumber() const
+{
+    return d->commandNumber;
+}
+
+
+/*!
+    Sets the SIM command number to \a value.  The usual value for the command
+    number is 1.  The command number may be set to something other than 1 if more
+    than one SIM command is being processed simultaneously, but this is a fairly
+    rare occurence.  The main use for command numbers is to match commands and responses.
+
+    Applies to: all commands
+
+    \sa commandNumber()
+*/
+void QSimCommand::setCommandNumber( int value )
+{
+    dwrite()->commandNumber = value;
+}
+
+
+/*!
+    Returns the type of this command.  The default value is \c NoCommand.
+
+    Applies to: all commands.
+
+    \sa setType()
+*/
+QSimCommand::Type QSimCommand::type() const
+{
+    return d->type;
+}
+
+
+/*!
+    Sets the type of this command to \a value.
+
+    Applies to: all commands.
+
+    \sa type()
+*/
+void QSimCommand::setType( QSimCommand::Type value )
+{
+    dwrite()->type = value;
+}
+
+
+/*!
+    Returns the source device that originated the command.  The default value is \c SIM.
+
+    Applies to: all commands.
+
+    \sa setSourceDevice()
+*/
+QSimCommand::Device QSimCommand::sourceDevice() const
+{
+    return d->sourceDevice;
+}
+
+
+/*!
+    Sets the source device that originated the command to \a value.  Usually this
+    is \c SIM.
+
+    Applies to: all commands.
+
+    \sa sourceDevice()
+*/
+void QSimCommand::setSourceDevice( QSimCommand::Device value )
+{
+    dwrite()->sourceDevice = value;
+}
+
+
+/*!
+    Returns the destination device for the command.  The default value is \c ME.
+
+    Applies to: all commands.
+
+    \sa setDestinationDevice()
+*/
+QSimCommand::Device QSimCommand::destinationDevice() const
+{
+    return d->destinationDevice;
+}
+
+
+/*!
+    Sets the destination device for the command to \a value.
+
+    Applies to: all commands.
+
+    \sa destinationDevice()
+*/
+void QSimCommand::setDestinationDevice( QSimCommand::Device value )
+{
+    dwrite()->destinationDevice = value;
+}
+
+
+/*!
+    Returns true if there is help available for this command; otherwise returns false.
+    The help flag is the most significant bit of the qualifier() byte.
+
+    Applies to: \c SetupMenu, \c GetInkey, \c GetInput, \c SelectItem.
+
+    \sa setHasHelp()
+*/
+bool QSimCommand::hasHelp() const
+{
+    if ( d->type == QSimCommand::GetInkey ||
+         d->type == QSimCommand::GetInput ||
+         d->type == QSimCommand::SelectItem ||
+         d->type == QSimCommand::SetupMenu )
+        return d->qualifierBit( 0x80 );
+    else
+        return false;
+}
+
+
+/*!
+    Sets the flag that determines if there is help available
+    for this command to \a value.  The help flag is the most significant bit
+    of the qualifier() byte.
+
+    Applies to: \c SetupMenu, \c GetInkey, \c GetInput, \c SelectItem.
+
+    \sa hasHelp()
+*/
+void QSimCommand::setHasHelp( bool value )
+{
+    if ( d->type == QSimCommand::GetInkey ||
+         d->type == QSimCommand::GetInput ||
+         d->type == QSimCommand::SelectItem ||
+         d->type == QSimCommand::SetupMenu )
+        dwrite()->setQualifierBit( 0x80, value );
+}
+
+
+/*!
+    Returns the text to be displayed as either a message, a prompt, or an SMS.
+
+    Applies to: \c DisplayText, \c GetInkey, \c GetInput, \c SendSS, \c SendSMS,
+    \c SendUSSD, \c PlayTone, \c LanguageNotification.
+
+    \sa setText()
+*/
+QString QSimCommand::text() const
+{
+    return d->text;
+}
+
+
+/*!
+    Sets the text to be displayed by this command to \a value.
+
+    Applies to: \c DisplayText, \c GetInkey, \c GetInput, \c SendSS, \c SendSMS,
+    \c SendUSSD, \c PlayTone.
+
+    \sa text()
+*/
+void QSimCommand::setText( const QString& value )
+{
+    dwrite()->text = value;
+}
+
+
+/*!
+    Returns true if user feedback should be suppressed.  The default value is false.
+
+    This option controls what should happen when text() is an empty string for
+    the \c SendSS, \c SendSMS, \c SendUSSD, and \c PlayTone commands.  If
+    suppressUserFeedback() returns true, then the command should be performed
+    without any notification to the user.  If suppressUserFeedback() is false,
+    then generic feedback should be provided to the user to indicate that a
+    command is being performed.
+
+    Applies to: \c SendSS, \c SendSMS, \c SendUSSD, \c PlayTone.
+
+    \sa setSuppressUserFeedback(), text()
+*/
+bool QSimCommand::suppressUserFeedback() const
+{
+    return d->flag( SC_SuppressUserFeedback );
+}
+
+
+/*!
+    Sets the user feedback suppression flag to \a value.
+
+    This option controls what should happen when text() is an empty string for
+    the \c SendSS, \c SendSMS, \c SendUSSD, and \c PlayTone commands.  If
+    \a value is true, then the command should be performed without any notification
+    to the user.  If \a value is false, then generic feedback should be provided to
+    the user to indicate that a command is being performed.
+
+    Applies to: \c SendSS, \c SendSMS, \c SendUSSD, \c PlayTone.
+
+    \sa suppressUserFeedback(), text()
+*/
+void QSimCommand::setSuppressUserFeedback( bool value )
+{
+    dwrite()->setFlag( SC_SuppressUserFeedback, value );
+}
+
+
+/*!
+    Returns the other text to be displayed as a message.  This is typically used
+    with \c SetupCall commands to specify the text to be displayed during the call setup
+    phase, when text() is used for the user confirmation phase.
+
+    Applies to: \c SetupCall
+
+    \sa setOtherText()
+*/
+QString QSimCommand::otherText() const
+{
+    return d->otherText;
+}
+
+
+/*!
+    Sets the other text to be displayed to \a value.  This is typically used
+    with \c SetupCall commands to specify the text to be displayed during the call setup
+    phase, when text() is used for the user confirmation phase.
+
+    Applies to: \c SetupCall
+
+    \sa otherText()
+*/
+void QSimCommand::setOtherText( const QString& value )
+{
+    dwrite()->otherText = value;
+}
+
+
+/*!
+    Returns the default text for \c GetInput commands.
+
+    Applies to: \c GetInput
+
+    \sa setDefaultText()
+*/
+QString QSimCommand::defaultText() const
+{
+    return d->defaultText;
+}
+
+
+/*!
+    Sets the default text for \c GetInput commands to \a value.
+
+    Applies to: \c GetInput
+
+    \sa defaultText()
+*/
+void QSimCommand::setDefaultText( const QString& value )
+{
+    dwrite()->defaultText = value;
+}
+
+
+/*!
+    Returns true if a DisplayText command should attempt to display
+    the text as high priority (true) or normal priority (false).
+    The default value is false.
+
+    Applies to: \c DisplayText.
+
+    \sa setHighPriority()
+*/
+bool QSimCommand::highPriority() const
+{
+    if ( d->type == QSimCommand::DisplayText )
+        return d->qualifierBit( 0x01 );
+    else
+        return false;
+}
+
+
+/*!
+    Sets the high priority text display flag to \a value.  If type() is not DisplayText,
+    then the request is ignored.
+
+    Applies to: \c DisplayText.
+
+    \sa highPriority()
+*/
+void QSimCommand::setHighPriority( bool value )
+{
+    if ( d->type == QSimCommand::DisplayText )
+        dwrite()->setQualifierBit( 0x01, value );
+}
+
+
+/*!
+    Returns true if the text should be automatically cleared after
+    a small delay (usually 3 seconds); otherwise returns false.  If this is false, then
+    the client must call QSimToolkit::clearText() to move on to
+    the next SIM application state.  The default value is true.
+
+    Applies to: \c DisplayText.
+
+    Note: in Qtopia 4.3 and newer, the default value is true.  If Qtopia 4.2 and older,
+    the default value was false.  The change was due to the introduction of the
+    qualifier() value.
+
+    \sa setClearAfterDelay()
+*/
+bool QSimCommand::clearAfterDelay() const
+{
+    if ( d->type == QSimCommand::DisplayText )
+        return !d->qualifierBit( 0x80 );
+    else
+        return true;
+}
+
+
+/*!
+    Sets the clear after delay flag for text display to \a value.  If type() is not
+    DisplayText, the request is ignored.
+
+    Applies to: \c DisplayText.
+
+    \sa clearAfterDelay()
+*/
+void QSimCommand::setClearAfterDelay( bool value )
+{
+    if ( d->type == QSimCommand::DisplayText )
+        dwrite()->setQualifierBit( 0x80, !value );
+}
+
+
+/*!
+    Returns true if a \c DisplayText command should result in an immediate response
+    to the SIM without asking the user to confirm the text first; or false if the
+    user should confirm, or the response should be sent after the usual delay if
+    clearAfterDelay() is set.  The default value is false.
+
+    Applies to: \c DisplayText
+
+    \sa setImmediateResponse(), clearAfterDelay()
+*/
+bool QSimCommand::immediateResponse() const
+{
+    return d->flag( SC_ImmediateResponse );
+}
+
+
+/*!
+    Sets the immediate response flag to \a value.  If \a value is true, then the
+    \c DisplayText command should result in an immediate response to the SIM without
+    asking the user to confirm the text first.  If \a value is false, the user
+    should confirm, or the response should be sent after the usual delay if
+    clearAfterDelay() is set.
+
+    Applies to: \c DisplayText
+
+    \sa immediateResponse(), clearAfterDelay()
+*/
+void QSimCommand::setImmediateResponse( bool value )
+{
+    dwrite()->setFlag( SC_ImmediateResponse, value );
+}
+
+
+/*!
+    Returns true if the \c GetInkey and \c GetInput commands should return UCS2
+    input strings to the SIM; false if the commands should return strings in the
+    default SMS alphabet instead.  The default value is false.
+
+    This setting is ignored if either wantYesNo() returns true, and this setting
+    always overrides packedInput().
+
+    Applies to: \c GetInkey, \c GetInput
+
+    \sa setUcs2Input(), wantYesNo(), packedInput()
+*/
+bool QSimCommand::ucs2Input() const
+{
+    if ( d->type == QSimCommand::GetInkey || d->type == QSimCommand::GetInput )
+        return d->qualifierBit( 0x02 );
+    else
+        return false;
+}
+
+
+/*!
+    Sets the UCS2 input flag to \a value.  If \a value is true, then the
+    \c GetInkey and \c GetInput commands should send UCS2 input strings to the SIM.
+    If \a value is false, then the commands should send strings in the
+    default SMS alphabet instead.
+
+    This setting is ignored if either wantYesNo() returns true, and this setting
+    always overrides packedInput().
+
+    \sa ucs2Input(), wantYesNo(), packedInput()
+*/
+void QSimCommand::setUcs2Input( bool value )
+{
+    if ( d->type == QSimCommand::GetInkey || d->type == QSimCommand::GetInput )
+        dwrite()->setQualifierBit( 0x02, value );
+}
+
+
+/*!
+    Returns true if the \c GetInput command should return packed
+    7-bit input strings to the SIM; false if the commands should return strings in the
+    unpacked 8-bit alphabet instead.  The default value is false.
+
+    This setting is ignored if either wantYesNo() or ucs2Input() returns true.
+
+    Applies to: \c GetInput
+
+    \sa setPackedInput(), wantYesNo(), ucs2Input()
+*/
+bool QSimCommand::packedInput() const
+{
+    if ( d->type == QSimCommand::GetInput )
+        return d->qualifierBit( 0x08 );
+    else
+        return false;
+}
+
+
+/*!
+    Sets the packed input flag to \a value.  If \a value is true, then the
+    \c GetInput command should send packed 7-bit input strings to the SIM.
+    If \a value is false, then the commands should send strings in the
+    unpacked 8-bit alphabet instead.
+
+    This setting is ignored if either wantYesNo() or ucs2Input() returns true,
+    of if type() is not \c GetInput.
+
+    Applies to: \c GetInput
+
+    \sa packedInput(), wantYesNo(), ucs2Input()
+*/
+void QSimCommand::setPackedInput( bool value )
+{
+    if ( d->type == QSimCommand::GetInput )
+        dwrite()->setQualifierBit( 0x08, value );
+}
+
+
+/*!
+    Returns true if \c GetInkey or \c GetInput wants input that consists
+    only of digits (true), or any character combination (false).
+    The allowable digits are 0-9, #, *, and +.  The default value is true.
+
+    Applies to: \c GetInkey, \c GetInput.
+
+    Note: in Qtopia 4.3 and newer, the default value is true.  If Qtopia 4.2 and older,
+    the default value was false.  The change was due to the introduction of the
+    qualifier() value.
+
+    \sa setWantDigits()
+*/
+bool QSimCommand::wantDigits() const
+{
+    if ( d->type == QSimCommand::GetInkey || d->type == QSimCommand::GetInput )
+        return !d->qualifierBit( 0x01 );
+    else
+        return true;
+}
+
+
+/*!
+    Sets the flag that determines if \c GetInkey or \c GetInput wants
+    input that consists only of digits (true), or any character
+    combination (false), to \a value.
+
+    Applies to: \c GetInkey, \c GetInput.
+
+    \sa wantDigits()
+*/
+void QSimCommand::setWantDigits( bool value )
+{
+    if ( d->type == QSimCommand::GetInkey || d->type == QSimCommand::GetInput )
+        dwrite()->setQualifierBit( 0x01, !value );
+}
+
+
+/*!
+    Returns true if \c GetInkey wants input that consists of a \c Yes or
+    \c No answer.  The default value is false.
+
+    Applies to: \c GetInkey
+
+    \sa setWantYesNo()
+*/
+bool QSimCommand::wantYesNo() const
+{
+    if ( d->type == QSimCommand::GetInkey )
+        return d->qualifierBit( 0x04 );
+    else
+        return false;
+}
+
+
+/*!
+    Sets the flag that determines if \c GetInkey wants input that
+    consists of a \c Yes or \c No answer, to \a value.
+
+    Applies to: \c GetInkey
+
+    \sa wantYesNo()
+*/
+void QSimCommand::setWantYesNo( bool value )
+{
+    if ( d->type == QSimCommand::GetInkey )
+        dwrite()->setQualifierBit( 0x04, value );
+}
+
+
+/*!
+    Returns the minimum text length for input.  The default value is 0.
+
+    Applies to: \c GetInput.
+
+    \sa setMinimumLength()
+*/
+uint QSimCommand::minimumLength() const
+{
+    return d->minimumLength;
+}
+
+
+/*!
+    Sets the minimum text length for input to \a value.
+
+    Applies to: \c GetInput.
+
+    \sa minimumLength()
+*/
+void QSimCommand::setMinimumLength( uint value )
+{
+    dwrite()->minimumLength = value;
+}
+
+
+/*!
+    Returns the maximum text length for input.  The default value is 255, which
+    indicates that the text is unlimited in length.
+
+    Applies to: \c GetInput.
+
+    \sa setMaximumLength()
+*/
+uint QSimCommand::maximumLength() const
+{
+    return d->maximumLength;
+}
+
+
+/*!
+    Sets the maximum text length for input to \a value.
+
+    Applies to: \c GetInput.
+
+    \sa maximumLength()
+*/
+void QSimCommand::setMaximumLength( uint value )
+{
+    dwrite()->maximumLength = value;
+}
+
+
+/*!
+    Returns true if input should be echoed; otherwise returns false.
+    The default value is true.
+
+    Applies to: \c GetInput.
+
+    Note: in Qtopia 4.3 and newer, the default value is true.  If Qtopia 4.2 and older,
+    the default value was false.  The change was due to the introduction of the
+    qualifier() value.
+
+    \sa setEcho()
+*/
+bool QSimCommand::echo() const
+{
+    if ( d->type == QSimCommand::GetInput )
+        return !d->qualifierBit( 0x04 );
+    else
+        return true;
+}
+
+
+/*!
+    Sets the flag that determines if input should be echoed to \a value.
+
+    Applies to: \c GetInput.
+
+    \sa echo()
+*/
+void QSimCommand::setEcho( bool value )
+{
+    if ( d->type == QSimCommand::GetInput )
+        dwrite()->setQualifierBit( 0x04, !value );
+}
+
+
+/*!
+    Returns the disposition of other calls when a call setup occurs.
+    The default value is \c IfNoOtherCalls.
+
+    Applies to: \c SetupCall.
+
+    \sa setDisposition()
+*/
+QSimCommand::Disposition QSimCommand::disposition() const
+{
+    if ( d->type == QSimCommand::SetupCall )
+        return (QSimCommand::Disposition)(d->qualifier >> 1);
+    else
+        return IfNoOtherCalls;
+}
+
+
+/*!
+    Sets the disposition of other calls when a call setup occurs to \a value.
+
+    Applies to: \c SetupCall.
+
+    \sa disposition()
+*/
+void QSimCommand::setDisposition( QSimCommand::Disposition value )
+{
+    if ( d->type == QSimCommand::SetupCall )
+        dwrite()->qualifier = (((int)value) << 1) | (d->qualifier & 0x01);
+}
+
+
+/*!
+    Returns true if with-redial modifier is set for call setup disposition();
+    otherwise returns false.  The default value is false.
+
+    Applies to: \c SetupCall.
+
+    \sa setWithRedial()
+*/
+bool QSimCommand::withRedial() const
+{
+    if ( d->type == QSimCommand::SetupCall )
+        return d->qualifierBit( 0x01 );
+    else
+        return false;
+}
+
+/*!
+    Sets the with-redial modifier for call setup disposition to \a value.
+
+    Applies to: \c SetupCall.
+
+    \sa withRedial()
+*/
+void QSimCommand::setWithRedial( bool value )
+{
+    if ( d->type == QSimCommand::SetupCall )
+        dwrite()->setQualifierBit( 0x01, value );
+}
+
+/*!
+    Returns the phone number for \c SetupCall, address for \c SendSMS, the
+    supplementary service string for \c SendSS, the unstructured supplementary
+    service string for \c SendUSSD, or the sequence of DTMF digits for \c SendDTMF.
+
+    Applies to: \c SetupCall, \c SendSMS, \c SendSS, \c SendUSSD, \c SendDTMF.
+
+    \sa setNumber()
+*/
+QString QSimCommand::number() const
+{
+    return d->number;
+}
+
+
+/*!
+    Sets the phone number for \c SetupCall, address for \c SendSMS, the
+    supplementary service string for \c SendSS, unstructured supplementary service
+    string for \c SendUSSD, to \a value, or the sequence of DTMF digits for \c SendDTMF.
+
+    Applies to: \c SetupCall, \c SendSMS, \c SendSS, \c SendUSSD, \c SendDTMF.
+
+    \sa number()
+*/
+void QSimCommand::setNumber( const QString& value )
+{
+    dwrite()->number = value;
+}
+
+
+/*!
+    Returns the sub-address (e.g. extension) for a call setup.
+
+    Applies to: \c SetupCall.
+
+    \sa setSubAddress()
+*/
+QString QSimCommand::subAddress() const
+{
+    return d->subAddress;
+}
+
+
+/*!
+    Sets the sub-address (e.g. extension) for a call setup to \a value.
+
+    Applies to: \c SetupCall.
+
+    \sa subAddress()
+*/
+void QSimCommand::setSubAddress( const QString& value )
+{
+    dwrite()->subAddress = value;
+}
+
+
+/*!
+    Returns the class of call to be setup (Voice, Data, or Fax).
+    The default value is \c Voice.
+
+    Applies to: \c SetupCall.
+
+    \sa setCallClass()
+*/
+QSimCommand::CallClass QSimCommand::callClass() const
+{
+    return d->callClass;
+}
+
+
+/*!
+    Sets the class of call to be setup (Voice, Data, or Fax) to \a value.
+
+    Applies to: \c SetupCall.
+
+    \sa callClass()
+*/
+void QSimCommand::setCallClass( QSimCommand::CallClass value )
+{
+    dwrite()->callClass = value;
+}
+
+
+/*!
+    Returns the tone to be played by a \c PlayTone command.  The default
+    value is \c ToneNone.
+
+    Applies to: \c PlayTone
+
+    \sa setTone(), duration()
+*/
+QSimCommand::Tone QSimCommand::tone() const
+{
+    return d->tone;
+}
+
+
+/*!
+    Sets the tone to be played by a \c PlayTone command to \a value.
+
+    Applies to: \c PlayTone
+
+    \sa tone(), duration()
+*/
+void QSimCommand::setTone( QSimCommand::Tone value )
+{
+    dwrite()->tone = value;
+}
+
+
+/*!
+    Returns the number of milliseconds to play a tone.  The default value is zero,
+    indicating that the default duration for the tone should be used.
+
+    Applies to: \c PlayTone.
+
+    Note: this function is obsoleted by duration(), and will return the same value
+    as duration().
+
+    \sa duration(), setToneTime(), tone()
+*/
+uint QSimCommand::toneTime() const
+{
+    return d->duration;
+}
+
+
+/*!
+    Sets the number of milliseconds to play a tone to \a value.
+
+    Applies to: \c PlayTone.
+
+    Note: this function is obsoleted by setDuration().
+
+    \sa setDuration(), toneTime(), tone()
+*/
+void QSimCommand::setToneTime( uint value )
+{
+    dwrite()->duration = value;
+}
+
+
+/*!
+    Returns the number of milliseconds to play a tone or the poll interval.
+    The default value is zero, indicating that the default duration should be used.
+
+    Applies to: \c PlayTone, \c PollInterval.
+
+    \sa setDuration(), tone()
+*/
+uint QSimCommand::duration() const
+{
+    return d->duration;
+}
+
+/*!
+    Sets the duration of a poll interval or to play a tone to \a value milliseconds.
+
+    Applies to: \c PlayTone, \c PollInterval.
+
+    \sa duration(), tone()
+*/
+void QSimCommand::setDuration( uint value )
+{
+    dwrite()->duration = value;
+}
+
+/*!
+    Returns true if icons for menu items should be displayed on the device's soft keys
+    if the number of icons is less than or equal to the number of soft keys.  If there are
+    more icons than soft keys, then regular menu selection should be used.  Returns false
+    for regular menu selection.  The default value is false.
+
+    Applies to: \c SetupMenu, \c SelectItem.
+
+    \sa setSoftKeysPreferred(), menuPresentation()
+*/
+bool QSimCommand::softKeysPreferred() const
+{
+    if ( d->type == QSimCommand::SetupMenu )
+        return d->qualifierBit( 0x01 );
+    else if ( d->type == QSimCommand::SelectItem )
+        return d->qualifierBit( 0x04 );
+    else
+        return false;
+}
+
+/*!
+    Sets the soft key preferred option to \a value.  If \a value is true then the
+    icons for menu items should be displayed on the device's soft keys if the number
+    of icons is less than or equal to the number of soft keys.  If there are more
+    icons than soft keys, then regular menu selection should be used.  If \a value
+    is false, then regular menu selection is always used.
+
+    Applies to: \c SetupMenu, \c SelectItem.
+
+    \sa softKeysPreferred(), menuPresentation()
+*/
+void QSimCommand::setSoftKeysPreferred( bool value )
+{
+    if ( d->type == QSimCommand::SetupMenu )
+        dwrite()->setQualifierBit( 0x01, value );
+    else if ( d->type == QSimCommand::SelectItem )
+        dwrite()->setQualifierBit( 0x04, value );
+}
+
+/*!
+    Returns the menu presentation type to use for \c SelectItem commands.
+    The default value is \c AnyPresentation.
+
+    Applies to: \c SelectItem.
+
+    \sa setMenuPresentation(), softKeysPreferred()
+*/
+QSimCommand::MenuPresentation QSimCommand::menuPresentation() const
+{
+    if ( d->type == QSimCommand::SelectItem && d->qualifierBit( 0x01 ) != 0 ) {
+        if ( d->qualifierBit( 0x02 ) != 0 )
+            return NavigationOptionsPresentation;
+        else
+            return DataValuesPresentation;
+    } else {
+        return AnyPresentation;
+    }
+}
+
+/*!
+    Sets the menu presentation type to use for \c SelectItem commands
+    to \a value.
+
+    Applies to: \c SelectItem.
+
+    \sa menuPresentation(), softKeysPreferred()
+*/
+void QSimCommand::setMenuPresentation( QSimCommand::MenuPresentation value )
+{
+    if ( d->type == QSimCommand::SelectItem ) {
+        if ( value == NavigationOptionsPresentation ) {
+            dwrite()->setQualifierBit( 0x01, true );
+            dwrite()->setQualifierBit( 0x02, true );
+        } else if ( value == DataValuesPresentation ) {
+            dwrite()->setQualifierBit( 0x01, true );
+            dwrite()->setQualifierBit( 0x02, false );
+        } else {
+            dwrite()->setQualifierBit( 0x01, false );
+            dwrite()->setQualifierBit( 0x02, false );
+        }
+    }
+}
+
+/*!
+    Returns the title to be displayed on a menu.
+
+    Applies to: \c SetupMenu, \c SelectItem.
+
+    \sa setTitle()
+*/
+QString QSimCommand::title() const
+{
+    return d->title;
+}
+
+
+/*!
+    Sets the title to be displayed on a menu to \a value.
+
+    Applies to: \c SetupMenu, \c SelectItem.
+
+    \sa title()
+*/
+void QSimCommand::setTitle( const QString& value )
+{
+    dwrite()->title = value;
+}
+
+
+/*!
+    Returns the index of the default item in the menu, or zero if no default.
+
+    Applies to: \c SelectItem.
+
+    \sa setDefaultItem()
+*/
+uint QSimCommand::defaultItem() const
+{
+    return d->defaultItem;
+}
+
+
+/*!
+    Sets the index of the default item in the menu, or zero if no default,
+    to \a value.
+
+    Applies to: \c SelectItem.
+
+    \sa defaultItem()
+*/
+void QSimCommand::setDefaultItem( uint value )
+{
+    dwrite()->defaultItem = value;
+}
+
+
+/*!
+    Returns the list of menu items in the menu.
+
+    Applies to: \c SetupMenu, \c SelectItem.
+
+    \sa setMenuItems()
+*/
+QList<QSimMenuItem> QSimCommand::menuItems() const
+{
+    return d->menuItems;
+}
+
+
+/*!
+    Sets the list of menu items in the menu to \a value.
+
+    Applies to: \c SetupMenu, \c SelectItem.
+
+    \sa menuItems()
+*/
+void QSimCommand::setMenuItems( const QList<QSimMenuItem>& value )
+{
+    dwrite()->menuItems = value;
+}
+
+
+/*!
+    Returns the type of refresh to that was performed by the SIM.
+    The default value is InitAndFullFileChange.
+
+    Applies to: \c Refresh.
+
+    \sa setRefreshType()
+*/
+QSimCommand::RefreshType QSimCommand::refreshType() const
+{
+    if ( d->type == QSimCommand::Refresh )
+        return (QSimCommand::RefreshType)(d->qualifier);
+    else
+        return InitAndFullFileChange;
+}
+
+
+/*!
+    Sets the type of refresh to that was performed by the SIM to \a value.
+    The request is ignored if type() is not \c Refresh.
+
+    Applies to: \c Refresh.
+
+    \sa refreshType()
+*/
+void QSimCommand::setRefreshType( QSimCommand::RefreshType value )
+{
+    if ( d->type == QSimCommand::Refresh )
+        setQualifier( (int)value );
+}
+
+
+/*!
+    Returns the events to be reported.
+
+    Applies to: \c SetupEventList.
+
+    Note: this function can only return information about \c IdleScreen and \c UserActivity
+    events.  To access information about all SIM toolkit events in the command,
+    use extensionField() with a tag value of 0x99.
+
+    \sa setEvents()
+*/
+QSimCommand::Event QSimCommand::events() const
+{
+    if ( d->type != QSimCommand::SetupEventList )
+        return NoEvent;
+    if ( d->extensionData.isEmpty() )
+        return NoEvent;
+    QByteArray evdata = extensionField( 0x99 );
+    if ( evdata.isEmpty() ) {
+        return Cancel;      // Field is present, but empty, which means "Cancel".
+    } else if ( evdata.contains( (char)0x05 ) ) {
+        if ( evdata.contains( (char)0x04 ) )
+            return Both;
+        else
+            return IdleScreen;
+    } else if ( evdata.contains( (char)0x04 ) ) {
+        return UserActivity;
+    } else {
+        return NoEvent;
+    }
+}
+
+
+/*!
+    Sets the events to be reported to \a value.
+
+    Applies to: \c SetupEventList.
+
+    Note: this function can only set information about \c IdleScreen and \c UserActivity
+    events.  To set information about other SIM toolkit events, use setExtensionField()
+    with a tag value of 0x99.
+
+    \sa events()
+*/
+void QSimCommand::setEvents( QSimCommand::Event value )
+{
+    if ( d->type == QSimCommand::SetupEventList ) {
+        dwrite()->extensionData = QByteArray();
+        switch ( value ) {
+
+            case NoEvent:       break;
+
+            case IdleScreen:
+            {
+                d->extensionData += (char)0x99;
+                d->extensionData += (char)0x01;
+                d->extensionData += (char)0x05;
+            }
+            break;
+
+            case UserActivity:
+            {
+                d->extensionData += (char)0x99;
+                d->extensionData += (char)0x01;
+                d->extensionData += (char)0x04;
+            }
+            break;
+
+            case Both:
+            {
+                d->extensionData += (char)0x99;
+                d->extensionData += (char)0x02;
+                d->extensionData += (char)0x04;
+                d->extensionData += (char)0x05;
+            }
+            break;
+
+            case Cancel:
+            {
+                d->extensionData += (char)0x99;
+                d->extensionData += (char)0x00;
+            }
+            break;
+        }
+    }
+}
+
+
+/*!
+    Returns the browser launch mode.  The default value is IfNotAlreadyLaunched.
+
+    Applies to: \c LaunchBrowser.
+
+    \sa setBrowserLaunchMode()
+*/
+QSimCommand::BrowserLaunchMode QSimCommand::browserLaunchMode() const
+{
+    if ( d->type == QSimCommand::LaunchBrowser )
+        return (QSimCommand::BrowserLaunchMode)(d->qualifier);
+    else
+        return IfNotAlreadyLaunched;
+}
+
+/*!
+    Sets the browser launch mode to \a value.
+
+    Applies to: \c LaunchBrowser.
+
+    \sa browserLaunchMode()
+*/
+void QSimCommand::setBrowserLaunchMode( QSimCommand::BrowserLaunchMode value )
+{
+    if ( d->type == QSimCommand::LaunchBrowser )
+        setQualifier( (int)value );
+}
+
+/*!
+    Returns the URL to launch in the browser.
+
+    Applies to: \c LaunchBrowser.
+
+    \sa setUrl()
+*/
+QString QSimCommand::url() const
+{
+    return d->url;
+}
+
+/*!
+    Sets the URL to launch in the browser to \a value.
+
+    Applies to: \c LaunchBrowser.
+
+    \sa url()
+*/
+void QSimCommand::setUrl( const QString& value )
+{
+    dwrite()->url = value;
+}
+
+/*!
+    Returns the icon identifier associated with this command.
+    Returns zero if there is no icon.
+
+    Applies to: \c DisplayText, \c GetInkey, \c GetInput, \c PlayTone, \c SelectItem,
+    \c SendSMS, \c SendSS, \c SetupCall, \c SetupMenu, \c LaunchBrowser,
+    \c SetupIdleModeText
+
+    \sa setIconId()
+*/
+uint QSimCommand::iconId() const
+{
+    return d->iconId;
+}
+
+/*!
+    Sets the icon identifier associated with this menu item to \a value.
+
+    Applies to: \c DisplayText, \c GetInkey, \c GetInput, \c PlayTone, \c SelectItem,
+    \c SendSMS, \c SendSS, \c SetupCall, \c SetupMenu, \c LaunchBrowser,
+    \c SetupIdleModeText
+
+    \sa iconId()
+*/
+void QSimCommand::setIconId( uint value )
+{
+    dwrite()->iconId = value;
+}
+
+/*!
+    Returns true if the icon specified by iconId() is self-explanatory
+    without the display of text().  If this function returns false,
+    then text() should be displayed next to the icon.  If iconId()
+    returns zero, then iconSelfExplanatory() should be ignored.
+
+    Applies to: \c DisplayText, \c GetInkey, \c GetInput, \c PlayTone, \c SelectItem,
+    \c SendSMS, \c SendSS, \c SetupCall, \c SetupMenu, \c LaunchBrowser,
+    \c SetupIdleModeText
+
+    \sa setIconSelfExplanatory()
+*/
+bool QSimCommand::iconSelfExplanatory() const
+{
+    return d->flag( SC_IconSelfExplanatory );
+}
+
+/*!
+    Sets the self-explanatory flag to \a value.
+
+    Applies to: \c DisplayText, \c GetInkey, \c GetInput, \c PlayTone, \c SelectItem,
+    \c SendSMS, \c SendSS, \c SetupCall, \c SetupMenu, \c LaunchBrowser,
+    \c SetupIdleModeText
+
+    \sa iconSelfExplanatory()
+*/
+void QSimCommand::setIconSelfExplanatory( bool value )
+{
+    dwrite()->setFlag( SC_IconSelfExplanatory, value );
+}
+
+/*!
+    Returns the other icon identifier associated with this command.
+    Returns zero if there is no icon.  This is typically used
+    with \c SetupCall commands to specify the icon to be displayed during the call setup
+    phase, when iconId() is used for the user confirmation phase.
+
+    Applies to: \c SetupCall
+
+    \sa setOtherIconId()
+*/
+uint QSimCommand::otherIconId() const
+{
+    return d->otherIconId;
+}
+
+
+/*!
+    Sets the other icon identifier associated with this menu item to \a value.
+    This is typically used with \c SetupCall commands to specify the icon to be
+    displayed during the call setup phase, when iconId() is used for the user
+    confirmation phase.
+
+    Applies to: \c SetupCall
+
+    \sa otherIconId()
+*/
+void QSimCommand::setOtherIconId( uint value )
+{
+    dwrite()->otherIconId = value;
+}
+
+
+/*!
+    Returns true if the icon specified by otherIconId() is self-explanatory
+    without the display of otherText().  If this function returns false,
+    then otherText() should be displayed next to the icon.  If otherIconId()
+    returns zero, then otherIconSelfExplanatory() should be ignored.
+
+    Applies to: \c SetupCall
+
+    \sa setOtherIconSelfExplanatory()
+*/
+bool QSimCommand::otherIconSelfExplanatory() const
+{
+    return d->flag( SC_IconSelfExplanatory2 );
+}
+
+
+/*!
+    Sets the self-explanatory flag for the icon specified by otherIconId to \a value.
+
+    Applies to: \c SetupCall
+
+    \sa otherIconSelfExplanatory()
+*/
+void QSimCommand::setOtherIconSelfExplanatory( bool value )
+{
+    dwrite()->setFlag( SC_IconSelfExplanatory2, value );
+}
+
+
+/*!
+    Returns true if SMS packing should be performed when sending an SMS message
+    for the \c SendSMS command; or false if packing is not required.  The default
+    value is false.
+
+    Many modems or modem vendor plugins will consume this value and remove it
+    from the SIM command before it reaches the client application layer.  Client
+    applications should not rely upon this value being present.
+
+    Applies to: \c SendSMS
+
+    \sa setSmsPacking()
+*/
+bool QSimCommand::smsPacking() const
+{
+    if ( d->type == QSimCommand::SendSMS )
+        return d->qualifierBit( 0x01 );
+    else
+        return false;
+}
+
+/*!
+    Sets the SMS packing flag to \a value.  If \a value is true, then SMS packing
+    should be performed when sending an SMS message for the \c SendSMS command.
+    If \a value is false, then no packing is required.
+
+    Many modems or modem vendor plugins will consume this value and remove it
+    from the SIM command before it reaches the client application layer.  Client
+    applications should not rely upon this value being present.
+
+    Applies to: \c SendSMS
+
+    \sa smsPacking()
+*/
+void QSimCommand::setSmsPacking( bool value )
+{
+    if ( d->type == QSimCommand::SendSMS )
+        dwrite()->setQualifierBit( 0x01, value );
+}
+
+/*!
+    Copy the QSimCommand object \a value.
+*/
+QSimCommand& QSimCommand::operator=( const QSimCommand & value )
+{
+    if ( d == value.d )
+        return *this;
+
+    if ( !d->ref.deref() )
+        delete d;
+
+    d = value.d;
+    d->ref.ref();
+
+    return *this;
+}
+
+// Read BER tag and length information from a QByteArray.
+// We also need to export this to qsimterminalresponse.cpp and qsimenvelope.cpp.
+void _qtopiaphone_readBer( const QByteArray& binary, uint& posn, uint& tag, uint& length )
+{
+    if ( posn < (uint)binary.size() ) {
+        tag = (uint)(binary[posn] & 0xFF);
+        ++posn;
+    } else {
+        tag = (uint)(-1);
+    }
+    if ( posn < (uint)binary.size() ) {
+        length = (uint)(binary[posn] & 0xFF);
+        ++posn;
+        if ( length == 0x81 ) {
+            // Two-byte length value.
+            if ( posn < (uint)binary.size() ) {
+                length = (uint)(binary[posn] & 0xFF);
+                ++posn;
+            } else {
+                length = 0;
+            }
+        } else if ( length == 0x82 ) {
+            // Three-byte length value.
+            if ( ( posn + 1 ) < (uint)binary.size() ) {
+                length = (((uint)(binary[posn] & 0xFF)) << 8) |
+                         (uint)(binary[posn + 1] & 0xFF);
+                posn += 2;
+            } else {
+                length = 0;
+                posn = (uint)binary.size();
+            }
+        }
+    } else {
+        length = 0;
+    }
+}
+#define readBer _qtopiaphone_readBer
+
+// Decode an EFADN string from a BER field.  GSM 11.11, section 10.5.1.
+// Exported to qsimcontrolevent.cpp.
+QString _qtopiaphone_decodeEFADN( const QByteArray& binary, uint posn, uint length )
+{
+    uint num, page, ch;
+    QString temp;
+    QTextCodec *codec = QAtUtils::codec( "gsm" );
+    if ( length == 0 )
+        return QString("");
+    else if ( binary[posn] == (char)0x80 ) {
+        // UCS-2 coding.
+        ++posn;
+        --length;
+        while ( length >= 2 ) {
+            ch = (((uint)((binary[posn]) & 0xFF)) << 8) |
+                  ((uint)(binary[posn + 1] & 0xFF));
+            if ( ch != 0xFFFF )
+                temp += (QChar)ch;
+            posn += 2;
+            length -= 2;
+        }
+        return temp;
+    } else if ( binary[posn] == (char)0x81 ) {
+        // 8-bit half page index coding.
+        if ( length < 3 )
+            return QString("");
+        num = ((uint)(binary[posn + 1] & 0xFF));
+        page = ((uint)(binary[posn + 2] & 0xFF)) << 7;
+        posn += 3;
+        length -= 3;
+    } else if ( binary[posn] == (char)0x82 ) {
+        // 16-bit half page index coding.
+        if ( length < 4 )
+            return QString("");
+        num = ((uint)(binary[posn + 1] & 0xFF));
+        page = (((uint)(binary[posn + 2] & 0xFF)) << 8) |
+                ((uint)(binary[posn + 3] & 0xFF));
+        posn += 4;
+        length -= 4;
+    } else {
+        // 7-bit GSM default alphabet coding.
+        while ( length > 0 && binary[posn + length - 1] == (char)0xFF ) {
+            // Strip 0xFF bytes from the end of the string first.
+            --length;
+        }
+        return codec->toUnicode( binary.data() + posn, (int)length );
+    }
+    while ( num > 0 && length > 0 ) {
+        ch = ((uint)(binary[posn] & 0xFF));
+        if ( ch < 0x80 ) {
+            temp += QGsmCodec::singleToUnicode( (char)ch );
+        } else {
+            temp += (QChar)( page + (ch & 0x7F) );
+        }
+        ++posn;
+        --length;
+        --num;
+    }
+    return temp;
+}
+#define decodeEFADN _qtopiaphone_decodeEFADN
+
+// Decode an EFADN number from a BER field.  GSM 11.11, section 10.5.1.
+static QString decodeEFADNNumber( const QByteArray& binary,
+                                  uint posn, uint length )
+{
+    static char const digits[] = "0123456789*#pDE";
+    QString temp;
+    uint ch;
+    while ( length > 0 ) {
+        ch = ((uint)(binary[posn] & 0xFF));
+        if ( ( ch & 0x0F ) == 0x0F )
+            break;
+        temp += (QChar)( digits[ch & 0x0F] );
+        if ( ( ch & 0xF0 ) == 0xF0 )
+            break;
+        temp += (QChar)( digits[(ch >> 4) & 0x0F] );
+        ++posn;
+        --length;
+    }
+    return temp;
+}
+
+// Write an EFADN number to a BER field.
+static void writeEFADNNumber( QByteArray& data, const QString& number, int tag = 0x86,
+                              int localTag = 129 )
+{
+    QString num = QAtUtils::stripNumber( number );
+    if ( tag == 0xAC ) {
+        // DTMF strings don't have a type prefix.
+        data += (char)tag;
+        data += (char)((num.length() + 1) / 2);
+    } else if ( num.startsWith( QChar('+') ) ) {
+        num = num.mid(1);
+        data += (char)tag;
+        data += (char)(1 + ((num.length() + 1) / 2));
+        data += (char)145;
+    } else {
+        data += (char)tag;
+        data += (char)(1 + ((num.length() + 1) / 2));
+        data += (char)localTag;
+    }
+    int byte = 0;
+    int nibble = 0;
+    for ( int index = 0; index < num.length(); ++index ) {
+        int ch = num[index].unicode();
+        switch ( ch ) {
+            case '0': case '1': case '2': case '3': case '4':
+            case '5': case '6': case '7': case '8': case '9':   ch -= '0'; break;
+
+            case '*':           ch = 10; break;
+            case '#':           ch = 11; break;
+            case 'p': case 'P': case ',':
+                                ch = 12; break;
+            case 'D': case 'd': ch = 13; break;
+            case 'E': case 'e': ch = 14; break;
+
+            default:            ch = 10; break;
+        }
+        if ( nibble ) {
+            data += (char)(byte | (ch << 4));
+            nibble = 0;
+        } else {
+            byte = ch;
+            nibble = 1;
+        }
+    }
+    if ( nibble ) {
+        data += (char)(byte | 0xF0);
+    }
+}
+
+// Decode a coded string, GSM 11.14, section 12.15.
+QString _qtopiaphone_decodeCodedString( const QByteArray& binary, uint posn, uint length )
+{
+    QString temp;
+    uint ch, byte, bitCount;
+    if ( length == 0 )
+        return QString("");
+    ch = (uint)(binary[posn++] & 0x0C);
+    --length;
+    if ( ch == QSMS_DefaultAlphabet ) {
+        ch = 0;
+        bitCount = 0;
+        while ( length > 0 ) {
+            byte = binary[posn++];
+            --length;
+            for ( int i = 0; i < 8; i++ ) {
+                // test the bit and shift it down again, as i doesn't mark
+                // where we are in the current char, but bitCount does
+                ch |= ( ( byte & (1 << i) ) >> i) << bitCount;
+                bitCount++;
+                if ( bitCount == 7 ) {
+                    bitCount = 0;
+                    temp += QGsmCodec::singleToUnicode( (char)ch );
+                    ch = 0;
+                }
+            }
+        }
+        if ( bitCount == 0 && temp.length() > 0 &&
+             temp[temp.length() - 1] == (char)0x0D ) {
+            // CR used as a padding character in the last byte - strip it.
+            temp = temp.left( temp.length() - 1 );
+        }
+        return temp;
+    } else if ( ch == QSMS_UCS2Alphabet ) {
+        while ( length >= 2 ) {
+            ch = (((uint)((binary[posn]) & 0xFF)) << 8) |
+                  ((uint)(binary[posn + 1] & 0xFF));
+            temp += (QChar)ch;
+            posn += 2;
+            length -= 2;
+        }
+        return temp;
+    } else {
+        return decodeEFADN( binary, posn, length );
+    }
+}
+#define decodeCodedString _qtopiaphone_decodeCodedString
+
+// Decode a subaddress, GSM 11.14, section 12.3.  The actual encoding
+// is specified in GSM 24.008, Annex E.
+static QString decodeSubAddress( const QByteArray& pdu, uint posn, uint length )
+{
+    // Verify that this looks like a BCD-encoded IA5 NSAP subaddress.
+    if ( length < 2 || pdu[posn] != (char)0x80 || pdu[posn + 1] != (char)0x50 )
+        return QString();
+    QString result;
+    posn += 2;
+    length -= 2;
+    while ( length > 0 ) {
+        int bcd = (pdu[posn++] & 0xFF);
+        result += QChar( (bcd >> 4) * 10 + (bcd & 0x0F) + 32 );
+        --length;
+    }
+    return result;
+}
+
+/*!
+    Decode a SIM command from its raw binary \a pdu form, as according
+    to 3GPP TS 11.14.  The binary data is assumed to be in BER form,
+    starting with the command tag.  If the data starts with a
+    "Proactive SIM" BER command wrapper, it will be skipped.
+    Returns the decoded SIM command.
+
+    \sa toPdu()
+*/
+QSimCommand QSimCommand::fromPdu( const QByteArray& pdu )
+{
+    QSimCommand sc;
+    uint posn = 0;
+    uint newPosn;
+    uint tag, length;
+    QList<QSimMenuItem> items;
+    bool seenText = false;
+    bool seenIcon = false;
+
+    // Read the first BER blob, which should be the command details.
+    readBer( pdu, posn, tag, length );
+    if ( tag == 0xD0 ) {
+        // There appears to be a "Proactive SIM" wrapper on the front
+        // of the command details.  Skip over it.
+        readBer( pdu, posn, tag, length );
+    }
+    if ( (tag & 0x7F) != 0x01 ) {
+        // This doesn't appear to be a SIM command at all.
+        return sc;
+    }
+
+    // Process the contents of the SIM command, tag by tag.
+    for (;;) {
+        if ( ( posn + length ) > (uint)pdu.size() ) {
+            break;
+        }
+        newPosn = posn + length;
+        switch ( tag & 0x7F ) {
+
+            case 0x01:
+            {
+                // Main command details blob, GSM 11.14, section 12.6.
+                if ( length < 3 )
+                    break;
+                sc.setCommandNumber( pdu[posn] & 0xFF );
+                sc.setType( (QSimCommand::Type)(pdu[posn + 1] & 0xFF) );
+                sc.setQualifier( pdu[posn + 2] & 0xFF );
+            }
+            break;
+
+            case 0x02:
+            {
+                // Device identities, GSM 11.14, section 12.7.
+                if ( length >= 2 ) {
+                    sc.setSourceDevice( (QSimCommand::Device)( pdu[posn] & 0xFF ) );
+                    sc.setDestinationDevice( (QSimCommand::Device)( pdu[posn + 1] & 0xFF ) );
+                }
+            }
+            break;
+
+            case 0x04:
+            {
+                // Duration for a PlayTone or PollInterval command, GSM 11.14, section 12.8.
+                if ( sc.type() == QSimCommand::OpenChannel ) {
+                    // This is actually part of the network setup parameters,
+                    // so add it to the extension data.
+                    sc.addExtensionField( tag, pdu.mid( posn, length ) );
+                    break;
+                }
+                if ( length < 2 )
+                    break;
+                uint multiplier = 60000;            // Minutes.
+                if ( pdu[posn] == 0x01 )         // Seconds.
+                    multiplier = 1000;
+                else if ( pdu[posn] == 0x02 )    // Tenths of a second.
+                    multiplier = 100;
+                sc.setDuration( multiplier * ( pdu[posn + 1] & 0xFF ) );
+            }
+            break;
+
+            case 0x05:
+            {
+                // Title to display with a menu, or alpha identifier for other commands.
+                // GSM 11.14, section 12.2.
+                if ( sc.type() == SetupMenu || sc.type() == SelectItem ) {
+                    sc.setTitle( decodeEFADN( pdu, posn, length ) );
+                } else if ( seenText ) {
+                    sc.setOtherText( decodeEFADN( pdu, posn, length ) );
+                } else {
+                    sc.setText( decodeEFADN( pdu, posn, length ) );
+                    seenText = true;
+                    if ( length == 0 )
+                        sc.setSuppressUserFeedback( true );
+                }
+            }
+            break;
+
+            case 0x06:
+            case 0x09:
+            {
+                // Address for SetupCall and SendSMS, GSM 11.14, section 12.1.
+                // SS string for SendSS command, GSM 11.14, section 12.14.
+                if ( length < 1 )
+                    break;
+                if ( pdu[posn] == (char)145 ) {
+                    sc.setNumber
+                        ( "+" + decodeEFADNNumber
+                                    ( pdu, posn + 1, length - 1 ) );
+                } else {
+                    sc.setNumber( decodeEFADNNumber
+                                    ( pdu, posn + 1, length - 1 ) );
+                }
+            }
+            break;
+
+            case 0x08:
+            {
+                // Sub-address for SetupCall, GSM 11.14, section 12.3.
+                sc.setSubAddress( decodeSubAddress( pdu, posn, length ) );
+            }
+            break;
+
+            case 0x0D:
+            {
+                // Text string for command, GSM 11.14, section 12.15.
+                if ( sc.type() == QSimCommand::LaunchBrowser ||
+                     sc.type() == QSimCommand::OpenChannel ) {
+                    // This is actually part of the network setup parameters,
+                    // so add it to the extension data.
+                    sc.addExtensionField( tag, pdu.mid( posn, length ) );
+                } else {
+                    sc.setText( decodeCodedString( pdu, posn, length ) );
+                }
+            }
+            break;
+
+            case 0x0A:
+            {
+                // USSD string, GSM 11.14, section 12.17.
+                sc.setNumber( decodeCodedString( pdu, posn, length ) );
+            }
+            break;
+
+            case 0x11:
+            {
+                // Response length, GSM 11.14, section 12.11.
+                if ( length >= 2 ) {
+                    sc.setMinimumLength( pdu[posn] & 0xFF );
+                    sc.setMaximumLength( pdu[posn + 1] & 0xFF );
+                }
+            }
+            break;
+
+            case 0x17:
+            {
+                // Default text string for GET INPUT command, GSM 11.14, section 12.23.
+                sc.setDefaultText( decodeCodedString( pdu, posn, length ) );
+            }
+            break;
+
+            case 0x18:
+            {
+                // Next action indicator list, GSM 11.14, section 12.24.
+                int index = 0;
+                while ( length > 0 && index < items.size() ) {
+                    uint action = (uint)(pdu[posn++] & 0xFF);
+                    items[index].setNextAction( action );
+                    --length;
+                    ++index;
+                }
+            }
+            break;
+
+            case 0x0E:
+            {
+                // Tone code for a PlayTone command, GSM 11.14, section 12.16.
+                if ( length > 0 )
+                    sc.setTone( (QSimCommand::Tone)(pdu[posn] & 0xFF) );
+            }
+            break;
+
+            case 0x0F:
+            {
+                // Menu item for command, GSM 11.14 section, 12.9.
+                if ( !length )
+                    break;      // Zero-length items indicate empty menu.
+                QSimMenuItem item;
+                if ( length > 0 ) {
+                    item.setIdentifier( (uint)(pdu[posn] & 0xFF) );
+                    ++posn;
+                    --length;
+                }
+                item.setLabel( decodeEFADN( pdu, posn, length ) );
+                item.setHasHelp( sc.hasHelp() );
+                items.append( item );
+            }
+            break;
+
+            case 0x10:
+            {
+                // Default menu item identifier, GSM 11.14, section 12.10.
+                if ( length > 0 )
+                    sc.setDefaultItem( (uint)(pdu[posn] & 0xFF) );
+            }
+            break;
+
+            case 0x1E:
+            {
+                // Icon identifier, GSM 11.14, section 12.31.
+                if ( length >= 2 ) {
+                    if ( seenIcon ) {
+                        sc.setOtherIconSelfExplanatory( (pdu[posn] & 0x01) == 0 );
+                        sc.setOtherIconId( (uint)(pdu[posn + 1] & 0xFF) );
+                    } else {
+                        sc.setIconSelfExplanatory( (pdu[posn] & 0x01) == 0 );
+                        sc.setIconId( (uint)(pdu[posn + 1] & 0xFF) );
+                        seenIcon = true;
+                    }
+                }
+            }
+            break;
+
+            case 0x1F:
+            {
+                // Item icon identifier list, GSM 11.14, section 12.32.
+                int index = 0;
+                bool selfExplanatory = true;
+                if ( length > 0 ) {
+                    if ( (pdu[posn] & 0x01) != 0 )
+                        selfExplanatory = false;
+                    ++posn;
+                    --length;
+                }
+                while ( length > 0 && index < items.size() ) {
+                    uint iconId = (uint)(pdu[posn++] & 0xFF);
+                    items[index].setIconId( iconId );
+                    items[index].setIconSelfExplanatory( selfExplanatory );
+                    --length;
+                    ++index;
+                }
+            }
+            break;
+
+            case 0x2B:
+            {
+                // Immediate response block.
+                sc.setImmediateResponse(true);
+            }
+            break;
+
+            case 0x2C:
+            {
+                // DTMF digits for SendDTMF command, GSM 11.14, section 12.44.
+                sc.setNumber( decodeEFADNNumber( pdu, posn, length ) );
+            }
+            break;
+
+            case 0x31:
+            {
+                // URL for LaunchBrowser command, GSM 11.14, section 12.48.
+                sc.setUrl( decodeEFADN( pdu, posn, length ) );
+            }
+            break;
+
+            default:
+            {
+                // Don't know what this is, so add it as an extension field.
+                sc.addExtensionField( tag, pdu.mid( posn, length ) );
+            }
+            break;
+        }
+        posn = newPosn;
+        if ( posn >= (uint)pdu.size() ) {
+            break;
+        }
+        readBer( pdu, posn, tag, length );
+    }
+
+    sc.setMenuItems( items );
+    return sc;
+}
+
+// Write a BER length value.  Exported to qsimterminalresponse.cpp and qsimenvelope.cpp.
+void _qtopiaphone_writeBerLength( QByteArray& binary, int length )
+{
+    int size = binary.size();
+    if ( length < 128 ) {
+        binary.resize( size + 1 );
+        binary[size] = (char)length;
+    } else if ( length < 256 ) {
+        binary.resize( size + 2 );
+        binary[size] = (char)0x81;
+        binary[size + 1] = (char)length;
+    } else {
+        binary.resize( size + 3 );
+        binary[size] = (char)0x82;
+        binary[size + 1] = (char)( length >> 8 );
+        binary[size + 2] = (char)length;
+    }
+}
+#define writeBerLength _qtopiaphone_writeBerLength
+
+// Write a string, encoded in the best possible data coding scheme.
+// We also need to export this to qsimterminalresponse.cpp.
+void _qtopiaphone_writeTextString( QByteArray& binary, const QString& str,
+                                   QSimCommand::ToPduOptions options, int tag = 0x8D );
+void _qtopiaphone_writeTextString( QByteArray& binary, const QString& str,
+                                   QSimCommand::ToPduOptions options, int tag )
+{
+    if ( str.isEmpty() && ( options & QSimCommand::EncodeEmptyStrings ) == 0 ) {
+        // Special form for zero-length strings.
+        binary += (char)tag;
+        binary += (char)0x00;
+        return;
+    }
+    int schemeMask = ((tag & 0xFF00) >> 8);     // For USSD string output.
+    if ( ( options & QSimCommand::UCS2Strings ) == 0 ) {
+        QTextCodec *gsm = QAtUtils::codec( "gsm-noloss" );
+        if ( gsm->canEncode( str ) ) {
+            if ( ( options & QSimCommand::PackedStrings ) != 0 ) {
+                // Use the packed 7-bit GSM alphabet to encode the string.
+                QByteArray packed;
+                int bitCount = 0;
+                int bits = 0;
+                for ( int u = 0; u < str.length(); u++ ) {
+                    unsigned short c = QGsmCodec::twoByteFromUnicode( str[u].unicode() );
+                    if ( c >= 256 ) {
+                        // Encode a two-byte sequence.
+                        for ( int i = 0; i < 7; i++ ) {
+                            if ( bitCount == 8 ) {
+                                bitCount = 0;
+                                packed += (char)bits;
+                                bits = 0;
+                            }
+                            if ( ((1 << (i+8)) & c) != 0 )
+                                bits |= (1 << bitCount);
+                            ++bitCount;
+                        }
+                    }
+                    for ( int i = 0; i < 7; i++ ) {
+                        if ( bitCount == 8 ) {
+                            bitCount = 0;
+                            packed += (char)bits;
+                            bits = 0;
+                        }
+                        if ( ((1 << i) & c) != 0 )
+                            bits |= (1 << bitCount);
+                        ++bitCount;
+                    }
+                }
+                if ( bitCount != 0 ) {
+                    packed += (char)bits;
+                }
+                binary += (char)tag;
+                writeBerLength( binary, packed.length() + 1 );
+                binary += (char)(QSMS_DefaultAlphabet | schemeMask);
+                binary += packed;
+            } else {
+                // Use the unpacked 8-bit GSM alphabet to encode the string.
+                QByteArray unpacked = gsm->fromUnicode( str );
+                binary += (char)tag;
+                writeBerLength( binary, unpacked.length() + 1 );
+                binary += (char)(QSMS_8BitAlphabet | schemeMask);
+                binary += unpacked;
+            }
+            return;
+        }
+    }
+
+    // If we get here, we must use UCS-2 to encode the text string.
+    QByteArray ucs2;
+    const ushort *data = str.utf16();
+    int len = str.length();
+    while ( len-- > 0 ) {
+        ushort ch = *data++;
+        ucs2 += (char)(ch >> 8);
+        ucs2 += (char)ch;
+    }
+    binary += (char)tag;
+    writeBerLength( binary, ucs2.length() + 1 );
+    binary += (char)(QSMS_UCS2Alphabet | schemeMask);
+    binary += ucs2;
+}
+#define writeTextString _qtopiaphone_writeTextString
+
+// Write an EFADN string as a BER field.  GSM 11.11, section 10.5.1.
+// Exported to qsimcontrolevent.cpp.
+void _qtopiaphone_writeEFADN( QByteArray& binary, const QString& str,
+                              QSimCommand::ToPduOptions options, int tag = 0x85 );
+void _qtopiaphone_writeEFADN( QByteArray& binary, const QString& str,
+                              QSimCommand::ToPduOptions options, int tag )
+{
+    // Determine if we can encode the string in the unpacked GSM alphabet encoding.
+    if ( ( options & QSimCommand::UCS2Strings ) == 0 ) {
+        QTextCodec *gsm = QAtUtils::codec( "gsm-noloss" );
+        if ( gsm->canEncode( str ) ) {
+            QByteArray unpacked = gsm->fromUnicode( str );
+            if ( tag != -1 ) {
+                binary += (char)tag;
+                writeBerLength( binary, unpacked.length() );
+            }
+            binary += unpacked;
+            return;
+        }
+    }
+
+    // If we get here, we must use UCS-2 to encode the text string.
+    QByteArray ucs2;
+    const ushort *data = str.utf16();
+    int len = str.length();
+    while ( len-- > 0 ) {
+        ushort ch = *data++;
+        ucs2 += (char)(ch >> 8);
+        ucs2 += (char)ch;
+    }
+    if ( tag != -1 ) {
+        binary += (char)tag;
+        writeBerLength( binary, ucs2.length() + 1 );
+    }
+    binary += (char)0x80;
+    binary += ucs2;
+}
+#define writeEFADN _qtopiaphone_writeEFADN
+
+// Write icon details.
+static void writeIcon( QByteArray& binary, uint iconId, bool selfExplanatory, bool mandatory )
+{
+    if ( iconId ) {
+        binary += (char)( mandatory ? 0x9E : 0x1E );
+        binary += (char)0x02;
+        binary += (char)( selfExplanatory ? 0 : 1 );
+        binary += (char)iconId;
+    }
+}
+
+// Write duration information.  Needs to be exported to qsimterminalresponse.cpp.
+void _qtopiaphone_writeDuration( QByteArray& data, uint time )
+{
+    if ( time != 0 ) {
+        data += (char)0x84;
+        data += (char)0x02;
+        if ( ( time % 1000 ) != 0 && time <= 25500 ) {
+            // Encode in tenths of a second.
+            data += (char)0x02;
+            data += (char)(time / 100);
+        } else if ( ( time % 60000 ) != 0 && time <= 255000 ) {
+            // Encode in seconds.
+            data += (char)0x01;
+            data += (char)(time / 1000);
+        } else if ( time <= 255 * 6000 ) {
+            // Encode in minutes.
+            data += (char)0x00;
+            data += (char)(time / 60000);
+        } else {
+            // Encode maximum time value.
+            data += (char)0x00;
+            data += (char)0xFF;
+        }
+    }
+}
+#define writeDuration _qtopiaphone_writeDuration
+
+// Write a subaddress, GSM 11.14, section 12.3.  The actual encoding
+// is specified in GSM 24.008, Annex E.
+static void writeSubAddress( QByteArray& data, const QString& value )
+{
+    data += (char)0x88;
+    writeBerLength( data, value.length() + 2 );
+    data += (char)0x80;     // NSAP address type
+    data += (char)0x50;     // NSAP address is BCD-encoded IA5 characters
+    foreach ( QChar ch, value ) {
+        int val = ch.unicode() - 32;
+        if ( val > 127 )
+            val = 0;
+        data += (char)(((val / 10) << 4) + (val % 10));
+    }
+}
+
+// Extract an extension field named "tag" from "extData" and write it to "data".
+// The field will be removed from "extData".  Returns false if no such field.
+// Exported to qsimcontrolevent.cpp.
+bool _qtopiaphone_extractAndWriteExtField( QByteArray& data, QByteArray& extData, int tag )
+{
+    uint startposn;
+    uint posn = 0;
+    uint currentTag, length;
+    while ( posn < (uint)( extData.length() ) ) {
+        startposn = posn;
+        readBer( extData, posn, currentTag, length );
+        if ( ( currentTag & 0x7F ) == (uint)( tag & 0x7F ) ) {
+            data += extData.mid( startposn, (posn + length) - startposn );
+            extData = extData.left( startposn ) + extData.mid( posn + length );
+            return true;
+        }
+        posn += length;
+    }
+    return false;
+}
+#define extractAndWriteExtField _qtopiaphone_extractAndWriteExtField
+
+/*!
+    \enum QSimCommand::ToPduOptions
+    This enum defines additional options to use when encoding SIM commands with QSimCommand::toPdu().
+
+    \value NoPduOptions No additional options.
+    \value NoBerWrapper Do not include the outermost BER wrapper around the command parameters.
+    \value PackedStrings Encode text strings in the packed 7-bit GSM alphabet instead
+                         of the unpacked 8-bit GSM alphabet.  If a text string cannot
+                         be encoded with the GSM alphabet, UCS-2 will be used.
+    \value UCS2Strings Encode text strings in the UCS-2 alphabet, even if it could
+                       otherwise be encoded in the packed 7-bit or unpacked 8-bit
+                       GSM alphabet.
+    \value EncodeEmptyStrings Encode empty strings in the actual character set, instead
+                       of using the shorthand encoding.
+*/
+
+/*!
+    Encode a SIM command into its raw binary PDU form, as described
+    in 3GPP TS 11.14.  The resulting PDU form may be modified by the
+    supplied \a options.
+
+    \sa fromPdu()
+*/
+QByteArray QSimCommand::toPdu( QSimCommand::ToPduOptions options ) const
+{
+    QByteArray data;
+
+    // Output the command details.
+    QSimCommand::Type cmd = type();
+    if ( cmd == NoCommand || cmd == Timeout )
+        return QByteArray();
+    int qualifier = d->qualifier;
+    if ( cmd == GetInkey && wantYesNo() ) {
+        // Make sure the "wantDigits" bit is unset if using Yes/No.
+        qualifier &= ~0x01;
+    }
+    data += (char)0x81;
+    data += (char)0x03;
+    data += (char)commandNumber();
+    data += (char)cmd;
+    data += (char)qualifier;
+
+    // Output the device identities (SIM to Display/Keypad/Earpiece/etc).
+    data += (char)0x82;
+    data += (char)0x02;
+    data += (char)sourceDevice();
+    data += (char)destinationDevice();
+
+    // If user feedback suppression is on, then encode empty strings.
+    if ( suppressUserFeedback() )
+        options = (QSimCommand::ToPduOptions)( options | EncodeEmptyStrings );
+
+    // Add the command parameters.
+    QByteArray extData = extensionData();
+    switch ( type() ) {
+        case DisplayText:
+        {
+            writeTextString( data, text(), options );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+            if ( immediateResponse() ) {
+                data += (char)0xAB;
+                data += (char)0x00;
+            }
+        }
+        break;
+
+        case GetInkey:
+        {
+            writeTextString( data, text(), options );
+            writeIcon( data, iconId(), iconSelfExplanatory(), false );
+        }
+        break;
+
+        case GetInput:
+        {
+            writeTextString( data, text(), options );
+            if ( minimumLength() != 0 || maximumLength() != 255 ) {
+                data += (char)0x91;
+                data += (char)0x02;
+                data += (char)minimumLength();
+                data += (char)maximumLength();
+            }
+            if ( !defaultText().isEmpty() ) {
+                writeTextString( data, defaultText(), QSimCommand::NoPduOptions, 0x17 );
+            }
+            writeIcon( data, iconId(), iconSelfExplanatory(), false );
+        }
+        break;
+
+        case PlayTone:
+        {
+            if ( !text().isEmpty() )
+                writeEFADN( data, text(), options );
+            if ( tone() != ToneNone ) {
+                data += (char)0x8E;
+                data += (char)0x01;
+                data += (char)tone();
+            }
+            writeDuration( data, duration() );
+            writeIcon( data, iconId(), iconSelfExplanatory(), false );
+        }
+        break;
+
+        case PollInterval:
+        {
+            writeDuration( data, duration() );
+        }
+        break;
+
+        case SetupMenu:
+        case SelectItem:
+        {
+            if ( type() == SetupMenu || !title().isEmpty() )
+                writeEFADN( data, title(), options );
+            bool hasIcons = false;
+            bool hasNextActions = false;
+            bool selfExplanatory = false;
+            if ( menuItems().size() == 0 ) {
+                data += (char)0x8F;
+                data += (char)0x00;
+            }
+            foreach ( QSimMenuItem item, menuItems() ) {
+                QByteArray contents;
+                contents += (char)item.identifier();
+                writeEFADN( contents, item.label(), options, -1 );
+                data += (char)0x8F;
+                writeBerLength( data, contents.size() );
+                data += contents;
+                if ( item.iconId() != 0 )
+                    hasIcons = true;
+                if ( item.nextAction() != 0 )
+                    hasNextActions = true;
+                if ( item.iconSelfExplanatory() )
+                    selfExplanatory = true;
+            }
+            if ( hasNextActions ) {
+                data += (char)0x18;
+                data += (char)menuItems().size();
+                foreach ( QSimMenuItem item, menuItems() )
+                    data += (char)item.nextAction();
+            }
+            if ( type() == SelectItem && defaultItem() != 0 ) {
+                data += (char)0x90;
+                data += (char)0x01;
+                data += (char)defaultItem();
+            }
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+            if ( hasIcons ) {
+                data += (char)0x9F;
+                data += (char)(menuItems().size() + 1);
+                data += (char)(selfExplanatory ? 0x00 : 0x01);
+                foreach ( QSimMenuItem item, menuItems() )
+                    data += (char)item.iconId();
+            }
+        }
+        break;
+
+        case SendSMS:
+        {
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), options );
+            if ( !number().isEmpty() )
+                writeEFADNNumber( data, number() );
+            extractAndWriteExtField( data, extData, 0x8B );
+            writeIcon( data, iconId(), iconSelfExplanatory(), iconSelfExplanatory() );
+        }
+        break;
+
+        case SendSS:
+        {
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), options );
+            writeEFADNNumber( data, number(), 0x89, 255 );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+        }
+        break;
+
+        case SendUSSD:
+        {
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), QSimCommand::NoPduOptions );
+            if ( ( options & QSimCommand::PackedStrings ) != 0 )
+                writeTextString( data, number(), options, 0xF08A );
+            else
+                writeTextString( data, number(), options, 0x408A );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+        }
+        break;
+
+        case SetupCall:
+        {
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), QSimCommand::NoPduOptions );
+            writeEFADNNumber( data, number() );
+            extractAndWriteExtField( data, extData, 0x87 );
+            if ( !subAddress().isEmpty() )
+                writeSubAddress( data, subAddress() );
+            writeDuration( data, duration() );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+            if ( !otherText().isEmpty() )
+                writeEFADN( data, otherText(), QSimCommand::NoPduOptions );
+            writeIcon( data, otherIconId(), otherIconSelfExplanatory(), true );
+        }
+        break;
+
+        case SetupIdleModeText:
+        {
+            writeTextString( data, text(), options );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+        }
+        break;
+
+        case RunATCommand:
+        {
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), QSimCommand::NoPduOptions );
+            extractAndWriteExtField( data, extData, 0xA8 );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+        }
+        break;
+
+        case SendDTMF:
+        {
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), options );
+            writeEFADNNumber( data, number(), 0xAC );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+        }
+        break;
+
+        case LaunchBrowser:
+        {
+            extractAndWriteExtField( data, extData, 0x30 ); // Browser id
+            writeEFADN( data, url(), QSimCommand::NoPduOptions, 0x31 );
+            data += extData;        // Add all network setup parameters before the text.
+            extData = QByteArray();
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), options, 0x05 );
+            writeIcon( data, iconId(), iconSelfExplanatory(), false );
+        }
+        break;
+
+        case OpenChannel:
+        {
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), options, 0x05 );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+            if ( !number().isEmpty() )
+                writeEFADNNumber( data, number() );
+            if ( !subAddress().isEmpty() )
+                writeSubAddress( data, subAddress() );
+        }
+        break;
+
+        case CloseChannel:
+        case ReceiveData:
+        case SendData:
+        {
+            if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+                writeEFADN( data, text(), options, 0x05 );
+            writeIcon( data, iconId(), iconSelfExplanatory(), true );
+        }
+        break;
+
+        default: break;
+    }
+
+    // Add any remaining extension data that is specified.
+    data += extData;
+
+    // Add the "Proactive SIM" BER command wrapper if required.
+    if ( ( options & NoBerWrapper ) == 0 ) {
+        QByteArray ber;
+        ber += (char)0xD0;
+        writeBerLength( ber, data.size() );
+        ber += data;
+        return ber;
+    } else {
+        return data;
+    }
+}
+
+/*!
+    Returns the qualifier byte from the header of the SIM command.  The qualifier byte
+    contains flags that modify the behavior of the command from its default.  The default
+    value is zero.
+
+    Other functions such as hasHelp(), wantDigits(), highPriority(), etc provide a
+    more convenient method to access the bits within the qualifier byte.
+
+    Applies to: all commands.
+
+    \sa setQualifier()
+*/
+int QSimCommand::qualifier() const
+{
+    return d->qualifier;
+}
+
+/*!
+    Sets the qualifier byte in the header of the SIM command to \a value.
+    The qualifier byte contains flags that modify the behavior of the command
+    from its default.
+
+    Other functions such as setHasHelp(), setWantDigits(), setHighPriority(), etc provide a
+    more convenient method to set the bits within the qualifier byte.
+
+    Applies to: all commands.
+
+    \sa qualifier()
+*/
+void QSimCommand::setQualifier( int value )
+{
+    d->qualifier = value;
+}
+
+/*!
+    Returns the extension data for this SIM command.  The extension data consists of
+    zero or more BER tag-length-value fields for fields that are not otherwise handled
+    by some other method in this class.
+
+    Applies to: all commands.
+
+    \sa setExtensionData(), extensionField()
+*/
+QByteArray QSimCommand::extensionData() const
+{
+    return d->extensionData;
+}
+
+/*!
+    Sets the extension data for this SIM command to \a value.  The extension
+    data consists of zero or more BER tag-length-value fields for fields that are
+    not otherwise handled by some other method in this class.
+
+    Applies to: all commands.
+
+    \sa extensionData(), addExtensionField()
+*/
+void QSimCommand::setExtensionData( QByteArray value )
+{
+    d->extensionData = value;
+}
+
+/*!
+    Returns the contents of an extension field.  The \a tag is an 8-bit value,
+    from 3GPP TS 11.14, that specifies the particular field the caller is
+    interested in.  The most significant bit of \a tag is ignored when searching
+    for the field, as it contains the "must comprehend" status from 3GPP TS 11.14,
+    and is not important for locating the desired field.
+
+    This is a simpler method than extensionData() for accessing values within
+    the extension data.  As an example, the following code extracts the
+    "SMS TPDU" information from a \c SendSMS SIM command:
+
+    \code
+    QSimCommand cmd;
+    ...
+    QByteArray tpdu = cmd.extensionField(0x8B);
+    \endcode
+
+    Applies to: all commands.
+
+    \sa addExtensionField()
+*/
+QByteArray QSimCommand::extensionField( int tag ) const
+{
+    uint posn = 0;
+    uint currentTag, length;
+    while ( posn < (uint)( d->extensionData.length() ) ) {
+        readBer( d->extensionData, posn, currentTag, length );
+        if ( ( currentTag & 0x7F ) == (uint)( tag & 0x7F ) )
+            return d->extensionData.mid( posn, length );
+        posn += length;
+    }
+    return QByteArray();
+}
+
+/*!
+    Adds an extension field to the data from extensionData().  The field will have
+    the specified \a tag and contents given by \a value.
+
+    Applies to: all commands.
+
+    \sa extensionField()
+*/
+void QSimCommand::addExtensionField( int tag, const QByteArray& value )
+{
+    d->extensionData += (char)tag;
+    writeBerLength( d->extensionData, value.size() );
+    d->extensionData += value;
+}
+
+/*!
+    \fn void QSimCommand::deserialize(Stream &value)
+
+    \internal
+
+    Deserializes the QSimCommand instance out to a template
+    type \c{Stream} \a stream.
+ */
+
+template <typename Stream> void QSimCommand::deserialize(Stream &stream)
+{
+    dwrite()->read( stream );
+}
+
+
+/*!
+    \fn void QSimCommand::serialize(Stream &value) const
+
+    \internal
+
+    Serializes the QSimCommand instance out to a template
+    type \c{Stream} \a stream.
+ */
+
+template <typename Stream> void QSimCommand::serialize(Stream &stream) const
+{
+    d->write( stream );
+}
+
+// Get a writable copy of the shared data storage.
+QSimCommandPrivate *QSimCommand::dwrite()
+{
+    // If we are the only user of the private object, return it as-is.
+    if ( d->ref == 1 )
+        return d;
+
+    // Create a new private object and copy the current contents into it.
+    QSimCommandPrivate *newd = new QSimCommandPrivate(d);
+    if ( !d->ref.deref() )
+        delete d;
+    d = newd;
+    return newd;
+}
+
+Q_IMPLEMENT_USER_METATYPE_ENUM(QSimCommand::Type)
+Q_IMPLEMENT_USER_METATYPE(QSimCommand)
+Q_IMPLEMENT_USER_METATYPE(QSimMenuItem)

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsimcommand.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsimcommand.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsimcommand.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QSIMCOMMAND_H
+#define QSIMCOMMAND_H
+
+
+#include <qtopiaipcmarshal.h>
+#include <qlist.h>
+#include <qdatastream.h>
+
+class QSimMenuItemPrivate;
+class QSimCommandPrivate;
+
+
+class QTOPIAPHONE_EXPORT QSimMenuItem
+{
+public:
+    QSimMenuItem();
+    QSimMenuItem( const QSimMenuItem& value );
+    ~QSimMenuItem();
+
+    uint identifier() const;
+    void setIdentifier( uint value );
+
+    QString label() const;
+    void setLabel( const QString& value );
+
+    bool hasHelp() const;
+    void setHasHelp( bool value );
+
+    uint iconId() const;
+    void setIconId( uint value );
+
+    bool iconSelfExplanatory() const;
+    void setIconSelfExplanatory( bool value );
+
+    uint nextAction() const;
+    void setNextAction( uint value );
+
+    QSimMenuItem& operator=( const QSimMenuItem & );
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+private:
+    QSimMenuItemPrivate *d;
+};
+
+class QTOPIAPHONE_EXPORT QSimCommand
+{
+public:
+    QSimCommand();
+    QSimCommand( const QSimCommand& value );
+    ~QSimCommand();
+
+    // Command types.
+    enum Type
+    {
+        NoCommand                   = -1,
+        Timeout                     = -2,
+        Refresh                     = 0x01,
+        MoreTime                    = 0x02,
+        PollInterval                = 0x03,
+        PollingOff                  = 0x04,
+        SetupEventList              = 0x05,
+        SetupCall                   = 0x10,
+        SendSS                      = 0x11,
+        SendUSSD                    = 0x12,
+        SendSMS                     = 0x13,
+        SendDTMF                    = 0x14,
+        LaunchBrowser               = 0x15,
+        PlayTone                    = 0x20,
+        DisplayText                 = 0x21,
+        GetInkey                    = 0x22,
+        GetInput                    = 0x23,
+        SelectItem                  = 0x24,
+        SetupMenu                   = 0x25,
+        ProvideLocalInformation     = 0x26,
+        TimerManagement             = 0x27,
+        SetupIdleModeText           = 0x28,
+        PerformCardAPDU             = 0x30,
+        PowerOnCard                 = 0x31,
+        PowerOffCard                = 0x32,
+        GetReaderStatus             = 0x33,
+        RunATCommand                = 0x34,
+        LanguageNotification        = 0x35,
+        OpenChannel                 = 0x40,
+        CloseChannel                = 0x41,
+        ReceiveData                 = 0x42,
+        SendData                    = 0x43,
+        GetChannelStatus            = 0x44,
+        EndSession                  = 0x81,
+
+        SetupMainMenu               = SetupMenu,
+        SetupSubMenu                = SelectItem
+    };
+
+    // Disposition of other calls during a call setup.
+    enum Disposition
+    {
+        IfNoOtherCalls      = 0,    // Setup if no other calls.
+        PutOnHold           = 1,    // Put other calls on hold first.
+        Disconnect          = 2     // Disconnect other calls first.
+    };
+
+    // Class of call to setup.
+    enum CallClass
+    {
+        Voice               = 0,
+        Data                = 1,
+        Fax                 = 2
+    };
+
+    // Tones that can be played.
+    enum Tone
+    {
+        ToneNone            = -1,
+        ToneDial            = 0x01,
+        ToneBusy            = 0x02,
+        ToneCongestion      = 0x03,
+        ToneRadioAck        = 0x04,
+        ToneDropped         = 0x05,
+        ToneError           = 0x06,
+        ToneCallWaiting     = 0x07,
+        ToneRinging         = 0x08,
+        ToneGeneralBeep     = 0x10,
+        TonePositiveBeep    = 0x11,
+        ToneNegativeBeep    = 0x12
+    };
+
+    // The type of refresh to perform.
+    enum RefreshType
+    {
+        InitAndFullFileChange   = 0,
+        FileChange              = 1,
+        InitAndFileChange       = 2,
+        Initialization          = 3,
+        Reset                   = 4
+    };
+
+    // Event types.
+    enum Event
+    {
+        NoEvent             = 0,
+        IdleScreen          = 1,
+        UserActivity        = 2,
+        Both                = 3,
+        Cancel              = 4
+    };
+
+    // Browser launch mode.
+    enum BrowserLaunchMode
+    {
+        IfNotAlreadyLaunched    = 0,
+        UseExisting             = 2,
+        CloseExistingAndLaunch  = 3
+    };
+
+    // Menu presentation type.
+    enum MenuPresentation
+    {
+        AnyPresentation                 = 0,
+        DataValuesPresentation          = 1,
+        NavigationOptionsPresentation   = 2
+    };
+
+    // Device identities for source and destination of commands.
+    enum Device
+    {
+        Keypad              = 0x01,
+        Display             = 0x02,
+        Earpiece            = 0x03,
+        CardReader0         = 0x10,
+        CardReader1         = 0x11,
+        CardReader2         = 0x12,
+        CardReader3         = 0x13,
+        CardReader4         = 0x14,
+        CardReader5         = 0x15,
+        CardReader6         = 0x16,
+        CardReader7         = 0x17,
+        Channel1            = 0x21,
+        Channel2            = 0x22,
+        Channel3            = 0x23,
+        Channel4            = 0x24,
+        Channel5            = 0x25,
+        Channel6            = 0x26,
+        Channel7            = 0x27,
+        SIM                 = 0x81,
+        ME                  = 0x82,
+        Network             = 0x83
+    };
+
+    int commandNumber() const;
+    void setCommandNumber( int value );
+
+    Type type() const;
+    void setType( QSimCommand::Type value );
+
+    QSimCommand::Device sourceDevice() const;
+    void setSourceDevice( QSimCommand::Device value );
+
+    QSimCommand::Device destinationDevice() const;
+    void setDestinationDevice( QSimCommand::Device value );
+
+    bool hasHelp() const;
+    void setHasHelp( bool value );
+
+    QString text() const;
+    void setText( const QString& value );
+
+    bool suppressUserFeedback() const;
+    void setSuppressUserFeedback( bool value );
+
+    QString otherText() const;
+    void setOtherText( const QString& value );
+
+    QString defaultText() const;
+    void setDefaultText( const QString& value );
+
+    bool highPriority() const;
+    void setHighPriority( bool value );
+
+    bool clearAfterDelay() const;
+    void setClearAfterDelay( bool value );
+
+    bool immediateResponse() const;
+    void setImmediateResponse( bool value );
+
+    bool ucs2Input() const;
+    void setUcs2Input( bool value );
+
+    bool packedInput() const;
+    void setPackedInput( bool value );
+
+    bool wantDigits() const;
+    void setWantDigits( bool value );
+
+    bool wantYesNo() const;
+    void setWantYesNo( bool value );
+
+    uint minimumLength() const;
+    void setMinimumLength( uint value );
+
+    uint maximumLength() const;
+    void setMaximumLength( uint value );
+
+    bool echo() const;
+    void setEcho( bool value );
+
+    QSimCommand::Disposition disposition() const;
+    void setDisposition( QSimCommand::Disposition value );
+
+    bool withRedial() const;
+    void setWithRedial( bool value );
+
+    QString number() const;
+    void setNumber( const QString& value );
+
+    QString subAddress() const;
+    void setSubAddress( const QString& value );
+
+    QSimCommand::CallClass callClass() const;
+    void setCallClass( QSimCommand::CallClass value );
+
+    QSimCommand::Tone tone() const;
+    void setTone( QSimCommand::Tone value );
+
+    uint toneTime() const;
+    void setToneTime( uint value );
+
+    uint duration() const;
+    void setDuration( uint value );
+
+    bool softKeysPreferred() const;
+    void setSoftKeysPreferred( bool value );
+
+    QSimCommand::MenuPresentation menuPresentation() const;
+    void setMenuPresentation( QSimCommand::MenuPresentation value );
+
+    QString title() const;
+    void setTitle( const QString& value );
+
+    uint defaultItem() const;
+    void setDefaultItem( uint value );
+
+    QList<QSimMenuItem> menuItems() const;
+    void setMenuItems( const QList<QSimMenuItem>& value );
+
+    QSimCommand::RefreshType refreshType() const;
+    void setRefreshType( QSimCommand::RefreshType value );
+
+    QSimCommand::Event events() const;
+    void setEvents( QSimCommand::Event value );
+
+    QSimCommand::BrowserLaunchMode browserLaunchMode() const;
+    void setBrowserLaunchMode( QSimCommand::BrowserLaunchMode value );
+
+    QString url() const;
+    void setUrl( const QString& value );
+
+    uint iconId() const;
+    void setIconId( uint value );
+
+    bool iconSelfExplanatory() const;
+    void setIconSelfExplanatory( bool value );
+
+    uint otherIconId() const;
+    void setOtherIconId( uint value );
+
+    bool otherIconSelfExplanatory() const;
+    void setOtherIconSelfExplanatory( bool value );
+
+    bool smsPacking() const;
+    void setSmsPacking( bool value );
+
+    int qualifier() const;
+    void setQualifier( int value );
+
+    QByteArray extensionData() const;
+    void setExtensionData( QByteArray value );
+
+    QByteArray extensionField( int tag ) const;
+    void addExtensionField( int tag, const QByteArray& value );
+
+    enum ToPduOptions
+    {
+        NoPduOptions        = 0x00,
+        NoBerWrapper        = 0x01,
+        PackedStrings       = 0x02,
+        UCS2Strings         = 0x04,
+        EncodeEmptyStrings  = 0x08
+    };
+
+    static QSimCommand fromPdu( const QByteArray& pdu );
+    QByteArray toPdu( QSimCommand::ToPduOptions options = NoPduOptions ) const;
+
+    QSimCommand& operator=( const QSimCommand & );
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+private:
+    QSimCommandPrivate *d;
+
+    QSimCommandPrivate *dwrite();
+};
+
+
+Q_DECLARE_USER_METATYPE(QSimMenuItem)
+Q_DECLARE_USER_METATYPE_ENUM(QSimCommand::Type)
+Q_DECLARE_USER_METATYPE(QSimCommand)
+
+#endif // QSIMCOMMAND_H

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsimcontrolevent.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsimcontrolevent.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsimcontrolevent.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,409 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qsimcontrolevent.h>
+#include <qsimcommand.h>
+
+/*!
+    \class QSimControlEvent
+    \mainclass
+    \brief The QSimControlEvent class specifies the contents of a \c{CALL CONTROL} or \c{MO SHORT MESSAGE CONTROL} result event.
+
+    When the user initiates phone calls or sends SMS messages on a
+    SIM-equippened mobile phone, the SIM can make modifications to
+    the request before it is sent to the network, or deny the request
+    outright.  This process is described in section 9 of 3GPP TS 11.14.
+
+    Once the SIM has determined whether it will allow the operation to
+    proceed or not, an event is sent to the modem indicating the result.
+    This event may include a text() string to be displayed to the user.
+
+    The particular type of SIM control event is specified by the type()
+    function.  Other functions, such as result(), text(), etc, are used
+    to specify type-specific parameters for the event.
+
+    Events are delivered to client applications via the
+    QSimToolkit::controlEvent() signal.
+
+    \ingroup telephony
+    \sa QSimToolkit::controlEvent()
+*/
+
+/*!
+    \enum QSimControlEvent::Type
+    This enum defines the type of SIM control event for QSimControlEvent.
+
+    \value Call The control event refers to a regular call setup or supplementary service.
+    \value Sms The control event refers to a mobile-originated SMS message.
+*/
+
+/*!
+    \enum QSimControlEvent::Result
+    This enum defines the result of a SIM control event.
+
+    \value Allowed The SIM allowed the call setup or SMS message to be processed normally.
+    \value NotAllowed This SIM disallowed the call setup or SMS message.
+    \value AllowedWithModifications The SIM allowed the call setup or SMS message,
+           but made some modifications to the request.
+*/
+
+class QSimControlEventPrivate
+{
+public:
+    QSimControlEventPrivate()
+    {
+        type = QSimControlEvent::Call;
+        result = QSimControlEvent::Allowed;
+    }
+
+    QSimControlEventPrivate( QSimControlEventPrivate *other )
+    {
+        type = other->type;
+        result = other->result;
+        text = other->text;
+        extensionData = other->extensionData;
+    }
+
+    template <typename Stream> int readInt( Stream &stream )
+    {
+        int value;
+        stream >> value;
+        return value;
+    }
+
+    template <typename Stream>  void read( Stream &stream )
+    {
+        type = (QSimControlEvent::Type)readInt( stream );
+        result = (QSimControlEvent::Result)readInt( stream );
+        stream >> text;
+        stream >> extensionData;
+    }
+
+    template <typename Stream> void write( Stream &stream )
+    {
+        stream << (int)type;
+        stream << (int)result;
+        stream << text;
+        stream << extensionData;
+    }
+
+    QSimControlEvent::Type type;
+    QSimControlEvent::Result result;
+    QString text;
+    QByteArray extensionData;
+};
+
+/*!
+    Construct a new SIM control object with default parameters.
+*/
+QSimControlEvent::QSimControlEvent()
+{
+    d = new QSimControlEventPrivate();
+}
+
+/*!
+    Construct a new SIM control object as a copy of \a value.
+*/
+QSimControlEvent::QSimControlEvent( const QSimControlEvent& value )
+{
+    d = new QSimControlEventPrivate( value.d );
+}
+
+/*!
+    Destruct a SIM control object.
+*/
+QSimControlEvent::~QSimControlEvent()
+{
+    delete d;
+}
+
+/*!
+    Returns the type of SIM control event: \c Call or \c Sms.  The default value is \c Call.
+
+    \sa setType()
+*/
+QSimControlEvent::Type QSimControlEvent::type() const
+{
+    return d->type;
+}
+
+/*!
+    Sets the type of this SIM control event to \a value.
+
+    \sa type()
+*/
+void QSimControlEvent::setType( QSimControlEvent::Type value )
+{
+    d->type = value;
+}
+
+/*!
+    Returns the result of this SIM control event.
+
+    \sa setResult()
+*/
+QSimControlEvent::Result QSimControlEvent::result() const
+{
+    return d->result;
+}
+
+/*!
+    Sets the result of this SIM control event to \a value.  The default value is \c Allowed.
+
+    \sa result()
+*/
+void QSimControlEvent::setResult( QSimControlEvent::Result value )
+{
+    d->result = value;
+}
+
+/*!
+    Returns the text string associated with this SIM control event.  If this string
+    is not empty, it should be displayed to the user to inform them of the SIM
+    control operation.
+
+    \sa setText()
+*/
+QString QSimControlEvent::text() const
+{
+    return d->text;
+}
+
+/*!
+    Sets the text string associated with this SIM control event to \a value.
+
+    \sa text()
+*/
+void QSimControlEvent::setText( const QString& value )
+{
+    d->text = value;
+}
+
+/*!
+    Returns the extension data for this SIM control event.  The extension data is
+    appended after all other fields, and consists of zero or more BER tag-length-value
+    field specifications.
+
+    \sa setExtensionData(), extensionField()
+*/
+QByteArray QSimControlEvent::extensionData() const
+{
+    return d->extensionData;
+}
+
+/*!
+    Sets the extension data for this SIM control event to \a value.  The extension
+    data is appended after all other fields, and consists of zero or more BER
+    tag-length-value field specifications.
+
+    \sa extensionData(), addExtensionField()
+*/
+void QSimControlEvent::setExtensionData( QByteArray value )
+{
+    d->extensionData = value;
+}
+
+// Imports from qsimcommand.cpp.
+void _qtopiaphone_readBer( const QByteArray& binary, uint& posn, uint& tag, uint& length );
+void _qtopiaphone_writeBerLength( QByteArray& binary, int length );
+QString _qtopiaphone_decodeEFADN( const QByteArray& binary, uint posn, uint length );
+bool _qtopiaphone_extractAndWriteExtField( QByteArray& data, QByteArray& extData, int tag );
+void _qtopiaphone_writeEFADN( QByteArray& binary, const QString& str,
+                              QSimCommand::ToPduOptions options, int tag = 0x85 );
+#define readBer _qtopiaphone_readBer
+#define writeBerLength _qtopiaphone_writeBerLength
+#define decodeEFADN _qtopiaphone_decodeEFADN
+#define extractAndWriteExtField _qtopiaphone_extractAndWriteExtField
+#define writeEFADN _qtopiaphone_writeEFADN
+
+/*!
+    Returns the contents of an extension field.  The \a tag is an 8-bit value,
+    from 3GPP TS 11.14, that specifies the particular field the caller is
+    interested in.  The most significant bit of \a tag is ignored when searching
+    for the field, as it contains the "must comprehend" status from 3GPP TS 11.14,
+    and is not important for locating the desired field.
+
+    This is a simpler method than extensionData() for accessing values within
+    the extension data.
+
+    \sa addExtensionField()
+*/
+QByteArray QSimControlEvent::extensionField( int tag ) const
+{
+    uint posn = 0;
+    uint currentTag, length;
+    while ( posn < (uint)( d->extensionData.length() ) ) {
+        readBer( d->extensionData, posn, currentTag, length );
+        if ( ( currentTag & 0x7F ) == (uint)( tag & 0x7F ) )
+            return d->extensionData.mid( posn, length );
+        posn += length;
+    }
+    return QByteArray();
+}
+
+/*!
+    Adds an extension field to the data from extensionData().  The field will have
+    the specified \a tag and contents given by \a value.
+
+    \sa extensionField()
+*/
+void QSimControlEvent::addExtensionField( int tag, const QByteArray& value )
+{
+    d->extensionData += (char)tag;
+    writeBerLength( d->extensionData, value.size() );
+    d->extensionData += value;
+}
+
+/*!
+    Returns a SIM control event object corresponding to the data in \a pdu.
+    The \a type indicates the type of SIM control event that is being decoded
+    from \a pdu: \c Call or \c Sms.  The data is decoded as described in 3GPP TS 11.14.
+
+    \sa toPdu()
+*/
+QSimControlEvent QSimControlEvent::fromPdu
+        ( QSimControlEvent::Type type, const QByteArray& pdu )
+{
+    QSimControlEvent ev;
+    QByteArray content;
+    uint posn = 0;
+    uint startPosn;
+    uint newPosn;
+    uint tag, length;
+    ev.setType( type );
+    if ( pdu.size() < 2 ) {
+        // Doesn't appear to be a valid control event.
+        return ev;
+    }
+    readBer( pdu, posn, tag, length );
+    ev.setResult( (QSimControlEvent::Result)tag );
+    content = pdu.mid( posn, length );
+    posn = 0;
+    startPosn = 0;
+    if ( posn >= (uint)content.size() )
+        return ev;
+    readBer( content, posn, tag, length );
+    for (;;) {
+        if ( ( posn + length ) > (uint)content.size() )
+            break;
+        newPosn = posn + length;
+        switch ( tag & 0x7F ) {
+
+            case 0x05:
+            {
+                // Alpha identifier, GSM 11.14, section 12.2.
+                ev.setText( decodeEFADN( content, posn, length ) );
+            }
+            break;
+
+            default:
+            {
+                // Don't know what this is, so add it as an extension field.
+                ev.addExtensionField( tag, content.mid( posn, length ) );
+            }
+            break;
+        }
+        posn = newPosn;
+        if ( posn >= (uint)content.size() )
+            break;
+        startPosn = newPosn;
+        readBer( content, posn, tag, length );
+    }
+    return ev;
+}
+
+/*!
+    Returns the PDU form of this SIM control event, encoded as described in 3GPP TS 11.14.
+
+    \sa fromPdu()
+*/
+QByteArray QSimControlEvent::toPdu() const
+{
+    QByteArray data;
+    QByteArray extData = extensionData();
+
+    // Extract parameters that need to appear before the text string,
+    // according to 3GPP TS 11.14, sections 9.1.6 and 9.2.2.
+    if ( type() == Call ) {
+        extractAndWriteExtField( data, extData, 0x06 );     // Address
+        extractAndWriteExtField( data, extData, 0x09 );     // SS string
+        extractAndWriteExtField( data, extData, 0x0A );     // USSD string
+        extractAndWriteExtField( data, extData, 0x07 );     // Capability configuration 1
+        extractAndWriteExtField( data, extData, 0x08 );     // Subaddress
+    } else {
+        extractAndWriteExtField( data, extData, 0x06 );     // Address 1
+        extractAndWriteExtField( data, extData, 0x06 );     // Address 2
+    }
+
+    // Output the text string.
+    if ( !text().isEmpty() )
+        writeEFADN( data, text(), QSimCommand::NoPduOptions );
+
+    // Add any remaining extension data that is specified.
+    data += extData;
+
+    // Add the outermost tag layer and return.
+    QByteArray outer;
+    outer += (char)result();
+    writeBerLength( outer, data.size() );
+    outer += data;
+    return outer;
+}
+
+/*!
+    Copy the QSimControlEvent \a value.
+*/
+QSimControlEvent& QSimControlEvent::operator=( const QSimControlEvent &value )
+{
+    if ( d == value.d )
+        return *this;
+    delete d;
+    d = new QSimControlEventPrivate( value.d );
+    return *this;
+}
+
+/*!
+    \fn void QSimControlEvent::deserialize(Stream &value)
+
+    \internal
+
+    Deserializes the QSimControlEvent instance out to a template
+    type \c{Stream} \a stream.
+ */
+template <typename Stream> void QSimControlEvent::deserialize(Stream &stream)
+{
+    d->read( stream );
+}
+
+/*!
+    \fn void QSimControlEvent::serialize(Stream &value) const
+
+    \internal
+
+    Serializes the QSimControlEvent instance out to a template
+    type \c{Stream} \a stream.
+ */
+template <typename Stream> void QSimControlEvent::serialize(Stream &stream) const
+{
+    d->write( stream );
+}
+
+Q_IMPLEMENT_USER_METATYPE(QSimControlEvent)

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsimcontrolevent.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsimcontrolevent.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsimcontrolevent.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QSIMCONTROLEVENT_H
+#define QSIMCONTROLEVENT_H
+
+#include <qtopiaipcmarshal.h>
+
+class QSimControlEventPrivate;
+
+class QTOPIAPHONE_EXPORT QSimControlEvent
+{
+public:
+    QSimControlEvent();
+    QSimControlEvent( const QSimControlEvent& value );
+    ~QSimControlEvent();
+
+    enum Type
+    {
+        Call  = 0,
+        Sms   = 1
+    };
+
+    enum Result
+    {
+        Allowed                     = 0,
+        NotAllowed                  = 1,
+        AllowedWithModifications    = 2
+    };
+
+    QSimControlEvent::Type type() const;
+    void setType( QSimControlEvent::Type value );
+
+    QSimControlEvent::Result result() const;
+    void setResult( QSimControlEvent::Result value );
+
+    QString text() const;
+    void setText( const QString& value );
+
+    QByteArray extensionData() const;
+    void setExtensionData( QByteArray value );
+
+    QByteArray extensionField( int tag ) const;
+    void addExtensionField( int tag, const QByteArray& value );
+
+    static QSimControlEvent fromPdu( QSimControlEvent::Type type, const QByteArray& pdu );
+    QByteArray toPdu() const;
+
+    QSimControlEvent& operator=( const QSimControlEvent & );
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+private:
+    QSimControlEventPrivate *d;
+};
+
+Q_DECLARE_USER_METATYPE(QSimControlEvent)
+
+#endif // QSIMCONTROLEVENT_H

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsimenvelope.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsimenvelope.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsimenvelope.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,557 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qsimenvelope.h>
+
+/*!
+    \class QSimEnvelope
+    \mainclass
+    \brief The QSimEnvelope class specifies the contents of a SIM ENVELOPE message.
+
+    Envelopes are specified by 3GPP TS 11.14 and are used for a variety of purposes
+    when communicating with SIM's, including:
+
+    \list
+        \o Menu selections for SIM toolkit applications.
+        \o Downloading items from the network into the SIM.
+        \o Call control and SMS control by the SIM.
+        \o Notifying the SIM of events of interest in the system.
+    \endlist
+
+    The particular type of envelope is specified by the type() function.  Other
+    functions, such as menuItem(), requestHelp(), etc, are used to specify
+    type-specific parameters for the envelope.
+
+    \ingroup telephony
+    \sa QSimToolkit, QSimCommand, QSimTerminalResponse
+*/
+
+class QSimEnvelopePrivate
+{
+public:
+    QSimEnvelopePrivate()
+    {
+        type = QSimEnvelope::NoEnvelope;
+        event = QSimEnvelope::NoEvent;
+        sourceDevice = QSimCommand::ME;
+        destinationDevice = QSimCommand::SIM;
+        menuItem = 0;
+        requestHelp = false;
+    }
+
+    QSimEnvelopePrivate( QSimEnvelopePrivate *other )
+    {
+        type = other->type;
+        event = other->event;
+        sourceDevice = other->sourceDevice;
+        destinationDevice = other->destinationDevice;
+        menuItem = other->menuItem;
+        requestHelp = other->requestHelp;
+        extensionData = other->extensionData;
+    }
+
+    template <typename Stream> int readInt( Stream &stream )
+    {
+        int value;
+        stream >> value;
+        return value;
+    }
+
+    template <typename Stream>  void read( Stream &stream )
+    {
+        type = (QSimEnvelope::Type)readInt( stream );
+        event = (QSimEnvelope::Event)readInt( stream );
+        sourceDevice = (QSimCommand::Device)readInt( stream );
+        destinationDevice = (QSimCommand::Device)readInt( stream );
+        stream >> menuItem;
+        requestHelp = ( readInt( stream ) != 0 );
+        stream >> extensionData;
+    }
+
+    template <typename Stream> void write( Stream &stream )
+    {
+        stream << (int)type;
+        stream << (int)event;
+        stream << (int)sourceDevice;
+        stream << (int)destinationDevice;
+        stream << menuItem;
+        stream << (int)requestHelp;
+        stream << extensionData;
+    }
+
+    QSimEnvelope::Type type;
+    QSimEnvelope::Event event;
+    QSimCommand::Device sourceDevice;
+    QSimCommand::Device destinationDevice;
+    uint menuItem;
+    bool requestHelp;
+    QByteArray extensionData;
+};
+
+/*!
+    \enum QSimEnvelope::Type
+    This enum defines the type of QSimEnvelope request to be sent to a SIM.
+
+    \value NoEnvelope The envelope type has not yet been set.
+    \value SMSPPDownload The envelope is being used for an SMS-PP download.
+    \value CellBroadcastDownload The envelope is being used for a cell broadcast download.
+    \value MenuSelection The envelope is being used for a SIM toolkit menu selection.
+    \value CallControl The envelope is being used for call control.
+    \value MOSMSControl The envelope is being used for mobile-originated short message control.
+    \value EventDownload The envelope is being used for event download.
+    \value TimerExpiration The envelope is being used to report timer expiration.
+*/
+
+/*!
+    \enum QSimEnvelope::Event
+    This enum defines the type of event for a \c EventDownload envelope, according
+    to 3GPP TS 11.14, section 12.25.
+
+    \value NoEvent No event type defined.
+    \value MTCall Mobile-terminated call event.
+    \value CallConnected Call connected event.
+    \value CallDisconnected Call disconnected event.
+    \value LocationStatus Location status event.
+    \value UserActivity User activity event.
+    \value IdleScreenAvailable Idle screen available event.
+    \value CardReaderStatus Additional card reader status event.
+    \value LanguageSelection Language selection event.
+    \value BrowserTermination Browser termination event.
+    \value DataAvailable Channel data available event.
+    \value ChannelStatus Channel status event.
+*/
+
+/*!
+    Construct a new envelope object with default parameters.
+*/
+QSimEnvelope::QSimEnvelope()
+{
+    d = new QSimEnvelopePrivate();
+}
+
+/*!
+    Construct a new envelope object as a copy of \a value.
+*/
+QSimEnvelope::QSimEnvelope( const QSimEnvelope& value )
+{
+    d = new QSimEnvelopePrivate( value.d );
+}
+
+/*!
+    Destruct an envelope object.
+*/
+QSimEnvelope::~QSimEnvelope()
+{
+    delete d;
+}
+
+/*!
+    Returns the type of this envelope.
+
+    \sa setType()
+*/
+QSimEnvelope::Type QSimEnvelope::type() const
+{
+    return d->type;
+}
+
+/*!
+    Sets the type of this envelope to \a value.
+
+    \sa type()
+*/
+void QSimEnvelope::setType( QSimEnvelope::Type value )
+{
+    d->type = value;
+}
+
+/*!
+    Returns the source device that generated the envelope.  The default value is
+    QSimCommand::ME.
+
+    Applies to: all commands.
+
+    \sa setSourceDevice()
+*/
+QSimCommand::Device QSimEnvelope::sourceDevice() const
+{
+    return d->sourceDevice;
+}
+
+/*!
+    Sets the source device that generated the envelope to \a value.
+
+    Applies to: all commands.
+
+    \sa sourceDevice()
+*/
+void QSimEnvelope::setSourceDevice( QSimCommand::Device value )
+{
+    d->sourceDevice = value;
+}
+
+/*!
+    Returns the destination device that will receive the envelope.  The default
+    value is QSimCommand::SIM.
+
+    Applies to: all commands.
+
+    \sa setDestinationDevice()
+*/
+QSimCommand::Device QSimEnvelope::destinationDevice() const
+{
+    return d->destinationDevice;
+}
+
+/*!
+    Sets the destination device that will receive the envelope to \a value.
+
+    Applies to: all commands.
+
+    \sa destinationDevice()
+*/
+void QSimEnvelope::setDestinationDevice( QSimCommand::Device value )
+{
+    d->destinationDevice = value;
+}
+
+/*!
+    Returns the menu item to be selected.  The default value is zero.
+
+    Applies to: \c MenuSelection
+
+    \sa setMenuItem()
+*/
+uint QSimEnvelope::menuItem() const
+{
+    return d->menuItem;
+}
+
+/*!
+    Sets the menu item to be selected to \a value.
+
+    Applies to: \c MenuSelection
+
+    \sa menuItem()
+*/
+void QSimEnvelope::setMenuItem( uint value )
+{
+    d->menuItem = value;
+}
+
+/*!
+    Returns true if help has been requested for this menu selection; false if the
+    menu item is being selected normally.  The default value is false.
+
+    Applies to: \c MenuSelection
+
+    \sa setRequestHelp()
+*/
+bool QSimEnvelope::requestHelp() const
+{
+    return d->requestHelp;
+}
+
+/*!
+    Sets the help request flag to \a value.  If \a value is true, then help has been
+    requested for this menu selection.  If \a value is false, then the menu item
+    is being selected normally.
+
+    Applies to: \c MenuSelection
+
+    \sa requestHelp()
+*/
+void QSimEnvelope::setRequestHelp( bool value )
+{
+    d->requestHelp = value;
+}
+
+/*!
+    Returns the event type for \c EventDownload envelopes.  The default value is \c NoEvent.
+
+    Applies to: \c EventDownload
+
+    \sa setEvent()
+*/
+QSimEnvelope::Event QSimEnvelope::event() const
+{
+    return d->event;
+}
+
+/*!
+    Sets the event type for \c EventDownload envelopes to \a value.
+
+    Applies to: \c EventDownload
+
+    \sa event()
+*/
+void QSimEnvelope::setEvent( QSimEnvelope::Event value )
+{
+    d->event = value;
+}
+
+/*!
+    Returns the extension data for this envelope.  The extension data is
+    appended after all other fields, and consists of zero or more BER tag-length-value
+    field specifications.
+
+    \sa setExtensionData(), extensionField()
+*/
+QByteArray QSimEnvelope::extensionData() const
+{
+    return d->extensionData;
+}
+
+/*!
+    Sets the extension data for this envelope to \a value.  The extension
+    data is appended after all other fields, and consists of zero or more BER
+    tag-length-value field specifications.
+
+    \sa extensionData(), addExtensionField()
+*/
+void QSimEnvelope::setExtensionData( QByteArray value )
+{
+    d->extensionData = value;
+}
+
+// Imports from qsimcommand.cpp.
+void _qtopiaphone_readBer( const QByteArray& binary, uint& posn, uint& tag, uint& length );
+void _qtopiaphone_writeBerLength( QByteArray& binary, int length );
+#define readBer _qtopiaphone_readBer
+#define writeBerLength _qtopiaphone_writeBerLength
+
+/*!
+    Returns the contents of an extension field.  The \a tag is an 8-bit value,
+    from 3GPP TS 11.14, that specifies the particular field the caller is
+    interested in.  The most significant bit of \a tag is ignored when searching
+    for the field, as it contains the "must comprehend" status from 3GPP TS 11.14,
+    and is not important for locating the desired field.
+
+    This is a simpler method than extensionData() for accessing values within
+    the extension data.
+
+    \sa addExtensionField()
+*/
+QByteArray QSimEnvelope::extensionField( int tag ) const
+{
+    uint posn = 0;
+    uint currentTag, length;
+    while ( posn < (uint)( d->extensionData.length() ) ) {
+        readBer( d->extensionData, posn, currentTag, length );
+        if ( ( currentTag & 0x7F ) == (uint)( tag & 0x7F ) )
+            return d->extensionData.mid( posn, length );
+        posn += length;
+    }
+    return QByteArray();
+}
+
+/*!
+    Adds an extension field to the data from extensionData().  The field will have
+    the specified \a tag and contents given by \a value.
+
+    \sa extensionField()
+*/
+void QSimEnvelope::addExtensionField( int tag, const QByteArray& value )
+{
+    d->extensionData += (char)tag;
+    writeBerLength( d->extensionData, value.size() );
+    d->extensionData += value;
+}
+
+/*!
+    Returns an envelope object corresponding to the data in \a pdu.
+    The data is decoded as described in 3GPP TS 11.14.
+
+    \sa toPdu()
+*/
+QSimEnvelope QSimEnvelope::fromPdu( const QByteArray& pdu )
+{
+    QSimEnvelope env;
+    QByteArray content;
+    uint posn = 0;
+    uint startPosn;
+    uint newPosn;
+    uint tag, length;
+    readBer( pdu, posn, tag, length );
+    if ( ( tag & 0xF0 ) != 0xD0 ) {
+        // Doesn't appear to be a valid ENVELOPE.
+        return env;
+    }
+    env.setType( (QSimEnvelope::Type)tag );
+    content = pdu.mid( posn, length );
+    posn = 0;
+    startPosn = 0;
+    readBer( content, posn, tag, length );
+    for (;;) {
+        if ( ( posn + length ) > (uint)content.size() )
+            break;
+        newPosn = posn + length;
+        switch ( tag & 0x7F ) {
+
+            case 0x02:
+            {
+                // Device identities, GSM 11.14, section 12.7.
+                if ( length >= 2 ) {
+                    env.setSourceDevice
+                        ( (QSimCommand::Device)( content[posn] & 0xFF ) );
+                    env.setDestinationDevice
+                        ( (QSimCommand::Device)( content[posn + 1] & 0xFF ) );
+                }
+            }
+            break;
+
+            case 0x10:
+            {
+                // Menu item identifier, GSM 11.14, section 12.10.
+                if ( length > 0 )
+                    env.setMenuItem( (uint)(content[posn] & 0xFF) );
+            }
+            break;
+
+            case 0x15:
+            {
+                // Help requested, GSM 11.14, section 12.21.
+                env.setRequestHelp( true );
+            }
+            break;
+
+            case 0x19:
+            {
+                // Event list, GSM 11.14, section 12.25.
+                if ( length > 0 )
+                    env.setEvent( (QSimEnvelope::Event)( content[posn] & 0xFF ) );
+            }
+            break;
+
+            default:
+            {
+                // Don't know what this is, so add it as an extension field.
+                env.addExtensionField( tag, content.mid( posn, length ) );
+            }
+            break;
+        }
+        posn = newPosn;
+        if ( posn >= (uint)content.size() )
+            break;
+        startPosn = newPosn;
+        readBer( content, posn, tag, length );
+    }
+    return env;
+}
+
+/*!
+    Returns the PDU form of this envelope, encoded as described in 3GPP TS 11.14.
+
+    \sa fromPdu()
+*/
+QByteArray QSimEnvelope::toPdu() const
+{
+    QByteArray data;
+
+    // Output the event list before the device identities.
+    if ( d->type == QSimEnvelope::EventDownload ) {
+        data += (char)0x99;
+        data += (char)0x01;
+        data += (char)(d->event);
+    }
+
+    // Add the device identity section (ME/Keypad/... to SIM).
+    // According to 3GPP TS 51.010-4, the tag should be 0x02 for
+    // MO-SMS control by SIM.
+    if ( d->type == QSimEnvelope::MOSMSControl )
+        data += (char)0x02;
+    else
+        data += (char)0x82;
+    data += (char)0x02;
+    data += (char)sourceDevice();
+    data += (char)destinationDevice();
+
+    // Add parameters specific to this type of envelope.
+    switch ( type() ) {
+
+        case MenuSelection:
+        {
+            data += (char)0x90;
+            data += (char)0x01;
+            data += (char)menuItem();
+            if ( requestHelp() ) {
+                data += (char)0x15;
+                data += (char)0x00;
+            }
+        }
+        break;
+
+        default: break;
+
+    }
+
+    // Add any extension data that is specified.
+    data += extensionData();
+
+    // Add the outermost envelope tag layer and return.
+    QByteArray env;
+    env += (char)type();
+    writeBerLength( env, data.size() );
+    env += data;
+    return env;
+}
+
+/*!
+    Copy the QSimEnvelope \a value.
+*/
+QSimEnvelope& QSimEnvelope::operator=( const QSimEnvelope &value )
+{
+    if ( d != value.d ) {
+        delete d;
+        d = new QSimEnvelopePrivate( value.d );
+    }
+    return *this;
+}
+
+/*!
+    \fn void QSimEnvelope::deserialize(Stream &value)
+
+    \internal
+
+    Deserializes the QSimEnvelope instance out to a template
+    type \c{Stream} \a stream.
+ */
+
+template <typename Stream> void QSimEnvelope::deserialize(Stream &stream)
+{
+    d->read( stream );
+}
+
+/*!
+    \fn void QSimEnvelope::serialize(Stream &value) const
+
+    \internal
+
+    Serializes the QSimEnvelope instance out to a template
+    type \c{Stream} \a stream.
+ */
+
+template <typename Stream> void QSimEnvelope::serialize(Stream &stream) const
+{
+    d->write( stream );
+}
+
+Q_IMPLEMENT_USER_METATYPE(QSimEnvelope)

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsimenvelope.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsimenvelope.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsimenvelope.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QSIMENVELOPE_H
+#define QSIMENVELOPE_H
+
+#include <qsimcommand.h>
+
+class QSimEnvelopePrivate;
+
+class QTOPIAPHONE_EXPORT QSimEnvelope
+{
+public:
+    QSimEnvelope();
+    QSimEnvelope( const QSimEnvelope& value );
+    ~QSimEnvelope();
+
+    enum Type
+    {
+        NoEnvelope              = -1,
+        SMSPPDownload           = 0xD1,
+        CellBroadcastDownload   = 0xD2,
+        MenuSelection           = 0xD3,
+        CallControl             = 0xD4,
+        MOSMSControl            = 0xD5,
+        EventDownload           = 0xD6,
+        TimerExpiration         = 0xD7
+    };
+
+    enum Event
+    {
+        NoEvent                 = -1,
+        MTCall                  = 0,
+        CallConnected           = 1,
+        CallDisconnected        = 2,
+        LocationStatus          = 3,
+        UserActivity            = 4,
+        IdleScreenAvailable     = 5,
+        CardReaderStatus        = 6,
+        LanguageSelection       = 7,
+        BrowserTermination      = 8,
+        DataAvailable           = 9,
+        ChannelStatus           = 10
+    };
+
+    QSimEnvelope::Type type() const;
+    void setType( QSimEnvelope::Type value );
+
+    QSimCommand::Device sourceDevice() const;
+    void setSourceDevice( QSimCommand::Device value );
+
+    QSimCommand::Device destinationDevice() const;
+    void setDestinationDevice( QSimCommand::Device value );
+
+    uint menuItem() const;
+    void setMenuItem( uint value );
+
+    bool requestHelp() const;
+    void setRequestHelp( bool value );
+
+    QSimEnvelope::Event event() const;
+    void setEvent( QSimEnvelope::Event value );
+
+    QByteArray extensionData() const;
+    void setExtensionData( QByteArray value );
+
+    QByteArray extensionField( int tag ) const;
+    void addExtensionField( int tag, const QByteArray& value );
+
+    static QSimEnvelope fromPdu( const QByteArray& pdu );
+    QByteArray toPdu() const;
+
+    QSimEnvelope& operator=( const QSimEnvelope & );
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+private:
+    QSimEnvelopePrivate *d;
+};
+
+Q_DECLARE_USER_METATYPE(QSimEnvelope)
+
+#endif // QSIMENVELOPE_H

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsimterminalresponse.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsimterminalresponse.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsimterminalresponse.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,877 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qsimterminalresponse.h>
+#include <qsmsmessage.h>
+
+/*!
+    \class QSimTerminalResponse
+    \mainclass
+    \brief The QSimTerminalResponse class specifies the contents of a SIM toolkit TERMINAL RESPONSE message.
+
+    Applications that run within a SIM send commands to the host program
+    to interact with the user.  These commands might entail choosing an
+    item from a menu, asking if it is OK to dial a phone number, asking
+    for a line of input, displaying text messages, etc.
+
+    Once the user picks an action, a TERMINAL RESPONSE message is typically sent back
+    to the SIM to communicate the user's intent.  The QSimTerminalResponse class
+    encapsulates a TERMINAL RESPONSE message, containing all of the information about it.
+
+    In Qtopia, the host program is \c simapp.
+
+    \ingroup telephony
+    \sa QSimToolkit, QSimCommand
+*/
+
+/*!
+    \enum QSimTerminalResponse::Result
+    This enum defines the primary response code for a TERMINAL RESPONSE message to a SIM,
+    from 3GPP TS 11.14, section 12.12.
+
+    \value Success Command performed successfully.
+    \value PartialComprehension Command performed with partial comprehension.
+    \value MissingInformation Command performed with missing information.
+    \value RefreshPerformed Refresh performed with additional elementary files read.
+    \value IconNotDisplayed Command performed, but requested icon could not be displayed.
+    \value ModifiedCallControl Command performed, but modified by call control by SIM.
+    \value LimitedService Command performed, limited service.
+    \value WithModification Command performed with modification.
+    \value SessionTerminated Proactive SIM session terminated by the user.
+    \value BackwardMove Backward move in proactive SIM session requested by the user.
+    \value NoResponseFromUser No response from the user.
+    \value HelpInformationRequested Help information requested by the user.
+    \value UssdOrSsTerminatedByUser USSD or SS transaction terminated by the user.
+    \value MEUnableToProcess ME currently unable to process command.
+    \value NetworkUnableToProcess Network currently unable to process command.
+    \value UserDidNotAccept User did not accept the practive command.
+    \value UserClearedDownCall User cleared down call before connection or network release.
+    \value ActionInContradictionWithTimer Action in contradication with the current timer state.
+    \value TemporaryCallControlProblem Interaction with call control by SIM, temporary problem.
+    \value LaunchBrowserError Launch browser generic error code.
+    \value BeyondMECapabilities Command beyond ME's capabilities.
+    \value TypeNotUnderstood Command type not understood by ME.
+    \value DataNotUnderstood Command data not understood by ME.
+    \value NumberNotUnderstood Command number not understood by ME.
+    \value SsReturnError SS Return Error.
+    \value SmsRpError SMS RP-ERROR.
+    \value RequiredValuesMissing Error, required values are missing.
+    \value UssdReturnError USSD Return Error.
+    \value MultipleCardError MultipleCard commands error.
+    \value PermanentCallControlProblem Interaction with call control by SIM or MO short message control by SIM, permanent problem.
+    \value BearerIndependentProtocolProblem Bearer Independent Protocol error.
+*/
+
+/*!
+    \enum QSimTerminalResponse::Cause
+    This enum defines the secondary cause code for a TERMINAL RESPONSE message to a SIM,
+    from 3GPP TS 11.14, section 12.12.
+
+    \value NoSpecificCause No specific cause can be given (applies to all results).
+    \value ScreenIsBusy Screen is busy (applies to \c MEUnableToProcess).
+    \value BusyOnCall ME currently busy on call (applies to \c MEUnableToProcess).
+    \value BusyOnSsTransaction ME currently busy on SS transaction (applies to \c MEUnableToProcess).
+    \value NoService No service (applies to \c MEUnableToProcess).
+    \value AccessControlClassBar Access control class bar (applies to \c MEUnableToProcess).
+    \value RadioResourceNotGranted Radio resource not granted (applies to \c MEUnableToProcess).
+    \value NotInSpeechCall Not in speech call (applies to \c MEUnableToProcess).
+    \value BusyOnUssdTransaction ME currently busy on USSD transaction (applies to \c MEUnableToProcess).
+    \value BusyOnDtmf ME currently busy on SEND DTMF command (applies to \c MEUnableToProcess).
+    \value ActionNotAllowed Action not allowed (applies to \c PermanentCallControlProblem).
+    \value TypeOfRequestHasChanged The type of request has changed (applies to \c PermanentCallControlProblem).
+    \value CardReaderRemovedOrNotPresent Card reader removed or not present (applies to \c MultipleCardError).
+    \value CardRemovedOrNotPresent Card removed or not present (applies to \c MultipleCardError).
+    \value CardReaderBusy Card reader busy (applies to \c MultipleCardError).
+    \value CardPoweredOff Card powered off (applies to \c MultipleCardError).
+    \value CAPDUFormatError C-APDU format error (applies to \c MultipleCardError).
+    \value MuteCard Mute card (applies to \c MultipleCardError).
+    \value TransmissionError Transmission error (applies to \c MultipleCardError).
+    \value ProtocolNotSupported Protocol not supported (applies to \c MultipleCardError).
+    \value SpecifiedReaderNotValid Specified reader not valid (applies to \c MultipleCardError).
+    \value BearerUnavailable Bearer unavailable (applies to \c LaunchBrowserError).
+    \value BrowserUnavailable Browser unavailable (applies to \c LaunchBrowserError).
+    \value UnableToReadProvisioningData ME unable to read the provisioning data (applies to \c LaunchBrowserError).
+    \value NoChannelAvailable No channel available (applies to \c BearerIndependentProtocolProblem).
+    \value ChannelClosed Channel closed (applies to \c BearerIndependentProtocolProblem).
+    \value ChannelIdentifierNotValid Channel identifier not valid (applies to \c BearerIndependentProtocolProblem).
+    \value RequestedBufferSizeNotAvailable Requested buffer size not available (applies to \c BearerIndependentProtocolProblem).
+    \value SecurityError Security error; i.e. unsuccessful authentication (applies to \c BearerIndependentProtocolProblem).
+    \value RequestedTransportNotAvailable Required SIM/ME interface transport level not available (applies to \c BearerIndependentProtocolProblem).
+*/
+
+class QSimTerminalResponsePrivate
+{
+public:
+    QSimTerminalResponsePrivate()
+    {
+        commandPdu = command.toPdu();
+        sourceDevice = QSimCommand::ME;
+        destinationDevice = QSimCommand::SIM;
+        result = QSimTerminalResponse::Success;
+        duration = 0;
+        menuItem = 0;
+        dataCodingScheme = -1;
+    }
+
+    QSimTerminalResponsePrivate( QSimTerminalResponsePrivate *other )
+    {
+        command = other->command;
+        commandPdu = other->commandPdu;
+        sourceDevice = other->sourceDevice;
+        destinationDevice = other->destinationDevice;
+        result = other->result;
+        causeData = other->causeData;
+        text = other->text;
+        duration = other->duration;
+        menuItem = other->menuItem;
+        dataCodingScheme = other->dataCodingScheme;
+        extensionData = other->extensionData;
+    }
+
+    template <typename Stream> int readInt( Stream &stream )
+    {
+        int value;
+        stream >> value;
+        return value;
+    }
+
+    template <typename Stream>  void read( Stream &stream )
+    {
+        stream >> command;
+        stream >> commandPdu;
+        sourceDevice = (QSimCommand::Device)readInt( stream );
+        destinationDevice = (QSimCommand::Device)readInt( stream );
+        result = (QSimTerminalResponse::Result)readInt( stream );
+        stream >> causeData;
+        stream >> text;
+        stream >> duration;
+        stream >> menuItem;
+        stream >> dataCodingScheme;
+        stream >> extensionData;
+    }
+
+    template <typename Stream> void write( Stream &stream )
+    {
+        stream << command;
+        stream << commandPdu;
+        stream << (int)sourceDevice;
+        stream << (int)destinationDevice;
+        stream << (int)result;
+        stream << causeData;
+        stream << text;
+        stream << duration;
+        stream << menuItem;
+        stream << dataCodingScheme;
+        stream << extensionData;
+    }
+
+    QSimCommand command;
+    QByteArray commandPdu;
+    QSimCommand::Device sourceDevice;
+    QSimCommand::Device destinationDevice;
+    QSimTerminalResponse::Result result;
+    QByteArray causeData;
+    QString text;
+    uint duration;
+    uint menuItem;
+    int dataCodingScheme;
+    QByteArray extensionData;
+};
+
+/*!
+    Construct a new SIM terminal response object with default parameters.
+*/
+QSimTerminalResponse::QSimTerminalResponse()
+{
+    d = new QSimTerminalResponsePrivate();
+}
+
+/*!
+    Construct a new SIM terminal response object as a copy of \a value.
+*/
+QSimTerminalResponse::QSimTerminalResponse( const QSimTerminalResponse& value )
+{
+    d = new QSimTerminalResponsePrivate( value.d );
+}
+
+/*!
+    Destruct a SIM terminal response object.
+*/
+QSimTerminalResponse::~QSimTerminalResponse()
+{
+    delete d;
+}
+
+/*!
+    Returns the SIM command that gave rise to this SIM terminal response.
+    The default is a default-constructed QSimCommand.
+
+    \sa setCommand(), commandPdu(), setCommandPdu()
+*/
+QSimCommand QSimTerminalResponse::command() const
+{
+    return d->command;
+}
+
+/*!
+    Sets the SIM command that gave rise to this SIM terminal response to \a value.
+    Calling this function will also affect the result of commandPdu().
+
+    \sa command(), commandPdu(), setCommandPdu()
+*/
+void QSimTerminalResponse::setCommand( const QSimCommand& value )
+{
+    d->command = value;
+    d->commandPdu = value.toPdu();
+}
+
+/*!
+    Returns the PDU form of the SIM command that gave rise to this SIM terminal response.
+    The default is a PDU corresponding to a default-constructed QSimCommand.
+
+    \sa setCommandPdu(), command(), setCommand()
+*/
+QByteArray QSimTerminalResponse::commandPdu() const
+{
+    return d->commandPdu;
+}
+
+/*!
+    Sets the PDU form of the SIM command that gave rise to this SIM terminal response
+    to \a value.  Calling this function will also affect the result of command().
+
+    \sa commandPdu(), command(), setCommand()
+*/
+void QSimTerminalResponse::setCommandPdu( const QByteArray& value )
+{
+    d->commandPdu = value;
+    d->command = QSimCommand::fromPdu( value );
+}
+
+/*!
+    Returns the source device that generated the response.  The default value is
+    QSimCommand::ME.
+
+    \sa setSourceDevice()
+*/
+QSimCommand::Device QSimTerminalResponse::sourceDevice() const
+{
+    return d->sourceDevice;
+}
+
+/*!
+    Sets the source device that generated the response to \a value.
+
+    \sa sourceDevice()
+*/
+void QSimTerminalResponse::setSourceDevice( QSimCommand::Device value )
+{
+    d->sourceDevice = value;
+}
+
+/*!
+    Returns the destination device that will receive the response.  The default
+    value is QSimCommand::SIM.
+
+    \sa setDestinationDevice()
+*/
+QSimCommand::Device QSimTerminalResponse::destinationDevice() const
+{
+    return d->destinationDevice;
+}
+
+/*!
+    Sets the destination device that will receive the response to \a value.
+
+    \sa destinationDevice()
+*/
+void QSimTerminalResponse::setDestinationDevice( QSimCommand::Device value )
+{
+    d->destinationDevice = value;
+}
+
+/*!
+    Returns the result code for this SIM terminal response.  The default value
+    is \c Success.
+
+    The result code may not be sufficient on its own to determine the cause of
+    a failure.  The cause() and causeData() functions provides the additional information.
+
+    \sa setResult(), cause(), causeData()
+*/
+QSimTerminalResponse::Result QSimTerminalResponse::result() const
+{
+    return d->result;
+}
+
+/*!
+    Sets the result code for this SIM terminal response to \a value.
+
+    The result code may not be sufficient on its own to determine the cause of
+    a failure.  The setCause() and setCauseData() functions can be used to provide
+    the additional information.
+
+    \sa result(), setCause(), setCauseData()
+*/
+void QSimTerminalResponse::setResult( QSimTerminalResponse::Result value )
+{
+    d->result = value;
+}
+
+/*!
+    Returns the additional cause information for this SIM terminal response.
+    Returns \c NoSpecificCause if there is no additional cause information.
+
+    The additional cause value is the first byte of causeData(), or
+    \c NoSpecificCause if causeData() is empty.  Thus, cause() should be
+    used only as a convenience function to quickly determine the cause of
+    an error result().
+
+    \sa setCause(), causeData(), result()
+*/
+QSimTerminalResponse::Cause QSimTerminalResponse::cause() const
+{
+    if ( d->causeData.isEmpty() )
+        return NoSpecificCause;
+    else
+        return (QSimTerminalResponse::Cause)(d->causeData[0] & 0xFF);
+}
+
+/*!
+    Sets the additional cause information for this SIM terminal response to \a value.
+    This is equivalent to calling setCauseData() with a QByteArray containing a single
+    byte, \a value.
+
+    \sa cause(), setCauseData(), result()
+*/
+void QSimTerminalResponse::setCause( QSimTerminalResponse::Cause value )
+{
+    d->causeData = QByteArray(1, (char)value);
+}
+
+/*!
+    Returns the additional cause data associated with this SIM terminal response.
+    The default value is an empty QByteArray.
+
+    \sa setCauseData(), cause(), result()
+*/
+QByteArray QSimTerminalResponse::causeData() const
+{
+    return d->causeData;
+}
+
+/*!
+    Sets the additional cause data associated with this SIM terminal response to \a value.
+
+    \sa causeData(), result()
+*/
+void QSimTerminalResponse::setCauseData( const QByteArray& value )
+{
+    d->causeData = value;
+}
+
+/*!
+    Returns the text to be sent along with this terminal response.
+
+    Applies to: \c GetInkey, \c GetInput
+
+    \sa setText()
+*/
+QString QSimTerminalResponse::text() const
+{
+    return d->text;
+}
+
+
+/*!
+    Sets the text to be sent along with this terminal response to \a value.
+
+    Applies to: \c GetInkey, \c GetInput
+
+    \sa text()
+*/
+void QSimTerminalResponse::setText( const QString& value )
+{
+    d->text = value;
+}
+
+/*!
+    Returns the number of milliseconds for the duration of a poll interval.
+    The default value is zero, indicating that the default duration should be used.
+
+    Applies to: \c PollInterval.
+
+    \sa setDuration()
+*/
+uint QSimTerminalResponse::duration() const
+{
+    return d->duration;
+}
+
+/*!
+    Sets the duration of a poll interval to \a value.
+
+    Applies to: \c PollInterval
+
+    \sa duration()
+*/
+void QSimTerminalResponse::setDuration( uint value )
+{
+    d->duration = value;
+}
+
+/*!
+    Returns the menu item to be selected.  The default value is zero.
+
+    Applies to: \c SelectItem
+
+    \sa setMenuItem()
+*/
+uint QSimTerminalResponse::menuItem() const
+{
+    return d->menuItem;
+}
+
+/*!
+    Sets the menu item to be selected to \a value.
+
+    Applies to: \c SelectItem
+
+    \sa menuItem()
+*/
+void QSimTerminalResponse::setMenuItem( uint value )
+{
+    d->menuItem = value;
+}
+
+/*!
+    Returns the recommended data coding scheme for encoding USSD text strings.
+    The default value is -1, which indicates that the best scheme should be chosen
+    based on the contents of the USSD text string.
+
+    \sa setDataCodingScheme()
+*/
+int QSimTerminalResponse::dataCodingScheme() const
+{
+    return d->dataCodingScheme;
+}
+
+/*!
+    Sets the recommended data coding scheme for encoding USSD text strings to \a value.
+    The value -1 indicates that the best scheme should be chosen based on the contents
+    of the USSD text string.
+
+    \sa dataCodingScheme()
+*/
+void QSimTerminalResponse::setDataCodingScheme( int value )
+{
+    d->dataCodingScheme = value;
+}
+
+/*!
+    Returns the extension data for this terminal response.  The extension data is
+    appended after all other fields, and consists of zero or more BER tag-length-value
+    field specifications.
+
+    \sa setExtensionData(), extensionField()
+*/
+QByteArray QSimTerminalResponse::extensionData() const
+{
+    return d->extensionData;
+}
+
+/*!
+    Sets the extension data for this terminal response to \a value.  The extension
+    data is appended after all other fields, and consists of zero or more BER
+    tag-length-value field specifications.
+
+    \sa extensionData(), addExtensionField()
+*/
+void QSimTerminalResponse::setExtensionData( QByteArray value )
+{
+    d->extensionData = value;
+}
+
+// Imports from qsimcommand.cpp.
+void _qtopiaphone_readBer( const QByteArray& binary, uint& posn, uint& tag, uint& length );
+void _qtopiaphone_writeTextString( QByteArray& binary, const QString& str,
+                                   QSimCommand::ToPduOptions options, int tag = 0x8D );
+QString _qtopiaphone_decodeCodedString( const QByteArray& binary, uint posn, uint length );
+void _qtopiaphone_writeDuration( QByteArray& data, uint time );
+void _qtopiaphone_writeBerLength( QByteArray& binary, int length );
+#define readBer _qtopiaphone_readBer
+#define writeTextString _qtopiaphone_writeTextString
+#define decodeCodedString _qtopiaphone_decodeCodedString
+#define writeDuration _qtopiaphone_writeDuration
+#define writeBerLength _qtopiaphone_writeBerLength
+
+/*!
+    Returns the contents of an extension field.  The \a tag is an 8-bit value,
+    from 3GPP TS 11.14, that specifies the particular field the caller is
+    interested in.  The most significant bit of \a tag is ignored when searching
+    for the field, as it contains the "must comprehend" status from 3GPP TS 11.14,
+    and is not important for locating the desired field.
+
+    This is a simpler method than extensionData() for accessing values within
+    the extension data.  As an example, the following code extracts the
+    "answer to reset" information from the response to a \c PowerOnCard SIM command:
+
+    \code
+    QSimTerminalResponse resp;
+    ...
+    QByteArray atr = resp.extensionField(0xA1);
+    \endcode
+
+    \sa addExtensionField()
+*/
+QByteArray QSimTerminalResponse::extensionField( int tag ) const
+{
+    uint posn = 0;
+    uint currentTag, length;
+    while ( posn < (uint)( d->extensionData.length() ) ) {
+        readBer( d->extensionData, posn, currentTag, length );
+        if ( ( currentTag & 0x7F ) == (uint)( tag & 0x7F ) )
+            return d->extensionData.mid( posn, length );
+        posn += length;
+    }
+    return QByteArray();
+}
+
+/*!
+    Adds an extension field to the data from extensionData().  The field will have
+    the specified \a tag and contents given by \a value.
+
+    \sa extensionField()
+*/
+void QSimTerminalResponse::addExtensionField( int tag, const QByteArray& value )
+{
+    d->extensionData += (char)tag;
+    writeBerLength( d->extensionData, value.size() );
+    d->extensionData += value;
+}
+
+/*!
+    Returns a SIM terminal response object corresponding to the data in \a pdu.
+    The data is decoded as described in 3GPP TS 11.14, section 6.8.
+
+    \sa toPdu()
+*/
+QSimTerminalResponse QSimTerminalResponse::fromPdu( const QByteArray& pdu )
+{
+    QSimTerminalResponse resp;
+    uint posn = 0;
+    uint startPosn = 0;
+    uint newPosn;
+    uint tag, length;
+    readBer( pdu, posn, tag, length );
+    if ( ( tag & 0x7F ) != 0x01 ) {
+        // Doesn't appear to be a valid TERMINAL RESPONSE.
+        return resp;
+    }
+    for (;;) {
+        if ( ( posn + length ) > (uint)pdu.size() )
+            break;
+        newPosn = posn + length;
+        switch ( tag & 0x7F ) {
+
+            case 0x01:
+            {
+                // Command details pdu blob.
+                resp.setCommandPdu( pdu.mid( startPosn, posn + length - startPosn ) );
+            }
+            break;
+
+            case 0x02:
+            {
+                // Device identities, GSM 11.14, section 12.7.
+                if ( length >= 2 ) {
+                    resp.setSourceDevice( (QSimCommand::Device)( pdu[posn] & 0xFF ) );
+                    resp.setDestinationDevice( (QSimCommand::Device)( pdu[posn + 1] & 0xFF ) );
+                }
+            }
+            break;
+
+            case 0x03:
+            {
+                // Result information.
+                if ( length < 1 )
+                    break;
+                resp.setResult( (QSimTerminalResponse::Result)(pdu[posn] & 0xFF) );
+                resp.setCauseData( pdu.mid( posn + 1, length - 1 ) );
+            }
+            break;
+
+            case 0x04:
+            {
+                // Duration for a PollInterval command, GSM 11.14, section 12.8.
+                if ( length < 2 )
+                    break;
+                uint multiplier = 60000;            // Minutes.
+                if ( pdu[posn] == 0x01 )         // Seconds.
+                    multiplier = 1000;
+                else if ( pdu[posn] == 0x02 )    // Tenths of a second.
+                    multiplier = 100;
+                resp.setDuration( multiplier * ( pdu[posn + 1] & 0xFF ) );
+            }
+            break;
+
+            case 0x0D:
+            {
+                // Text string for terminal response, GSM 11.14, section 12.15.
+                if ( pdu.length() >= 5 && pdu[3] == (int)QSimCommand::GetInkey &&
+                     (pdu[4] & 0x04) != 0 ) {
+                    // Processing Yes/No responses: convert 0x01/0x00 into Yes/No.
+                    if ( length >= 2 && pdu[posn + 1] != (char)0x00 )
+                        resp.setText( "Yes" );    // No tr
+                    else
+                        resp.setText( "No" );     // No tr
+                } else {
+                    if ( length > 0 )
+                        resp.setDataCodingScheme( pdu[posn] & 0xFF );
+                    resp.setText( decodeCodedString( pdu, posn, length ) );
+                }
+            }
+            break;
+
+            case 0x10:
+            {
+                // Menu item identifier, GSM 11.14, section 12.10.
+                if ( length > 0 )
+                    resp.setMenuItem( (uint)(pdu[posn] & 0xFF) );
+            }
+            break;
+
+            default:
+            {
+                // Don't know what this is, so add it as an extension field.
+                resp.addExtensionField( tag, pdu.mid( posn, length ) );
+            }
+            break;
+        }
+        posn = newPosn;
+        if ( posn >= (uint)pdu.size() )
+            break;
+        startPosn = newPosn;
+        readBer( pdu, posn, tag, length );
+    }
+    return resp;
+}
+
+/*!
+    Returns the PDU form of this SIM terminal response, encoded as described in
+    3GPP TS 11.14, section 6.8.
+
+    \sa fromPdu()
+*/
+QByteArray QSimTerminalResponse::toPdu() const
+{
+    QByteArray data;
+
+    // Extract the command details from the command PDU.
+    QByteArray cmd = d->commandPdu;
+    uint posn = 0;
+    uint startPosn = 0;
+    uint tag, length, qual;
+    readBer( cmd, posn, tag, length );
+    if ( tag == 0xD0 ) {
+        // There appears to be a "Proactive SIM" wrapper on the front
+        // of the command details.  Skip over it.
+        startPosn = posn;
+        readBer( cmd, posn, tag, length );
+    }
+    if ( (tag & 0x7F) == 0x01 ) {
+        data += cmd.mid( startPosn, posn + length - startPosn );
+        if ( length >= 3 ) {
+            tag = (cmd[posn + 1] & 0x7F);
+            qual = (cmd[posn + 2] & 0xFF);
+        } else {
+            tag = 0;
+            qual = 0;
+        }
+    } else {
+        // Could not find the command details, so output default details.
+        data += (char)0x81;
+        data += (char)0x03;
+        data += (char)0x00;
+        data += (char)0x00;
+        data += (char)0x00;
+        tag = 0;
+        qual = 0;
+    }
+
+    // Add the device identity section (ME to SIM).
+    data += (char)0x82;
+    data += (char)0x02;
+    data += (char)sourceDevice();
+    data += (char)destinationDevice();
+
+    // Add the result details.
+    switch ( (QSimCommand::Type)tag ) {
+        case QSimCommand::SendSS:
+            if ( d->result == DataNotUnderstood )
+                data += (char)0x83;
+            else
+                data += (char)0x03;
+            break;
+        default:                        data += (char)0x83; break;
+    }
+    data += (char)(d->causeData.length() + 1);
+    data += (char)(d->result);
+    data += d->causeData;
+
+    // Add other information for specific command response types.
+    switch ( (QSimCommand::Type)tag ) {
+
+        case QSimCommand::GetInkey:
+        {
+            if ( d->result != Success && d->result != IconNotDisplayed )
+                break;
+            if ( ( qual & 0x04 ) != 0 ) {
+                // Encode a Yes/No response.
+                if ( text() == "Yes" ) {      // No tr
+                    data += (char)0x8D;
+                    data += (char)0x02;
+                    data += (char)0x04;
+                    data += (char)0x01;
+                } else {
+                    data += (char)0x8D;
+                    data += (char)0x02;
+                    data += (char)0x04;
+                    data += (char)0x00;
+                }
+            } else if ( ( qual & 0x02 ) != 0 ) {
+                // Use UCS-2 to encode the data.
+                writeTextString( data, text(), QSimCommand::UCS2Strings );
+            } else {
+                // Use the unpacked 8-bit GSM encoding to encode the data.
+                writeTextString( data, text(), QSimCommand::NoPduOptions );
+            }
+        }
+        break;
+
+        case QSimCommand::GetInput:
+        {
+            if ( d->result != Success && d->result != IconNotDisplayed )
+                break;
+            if ( ( qual & 0x02 ) != 0 ) {
+                // Use UCS-2 to encode the data.
+                writeTextString( data, text(), (QSimCommand::ToPduOptions)
+                                                 (QSimCommand::UCS2Strings |
+                                                  QSimCommand::EncodeEmptyStrings) );
+            } else if ( ( qual & 0x08 ) != 0 ) {
+                // Use the packed 7-bit GSM encoding to encode the data.
+                writeTextString( data, text(), (QSimCommand::ToPduOptions)
+                                                 (QSimCommand::PackedStrings |
+                                                  QSimCommand::EncodeEmptyStrings) );
+            } else {
+                // Use the unpacked 8-bit GSM encoding to encode the data.
+                writeTextString( data, text(), QSimCommand::EncodeEmptyStrings );
+            }
+        }
+        break;
+
+        case QSimCommand::PollInterval:
+        {
+            writeDuration( data, duration() );
+        }
+        break;
+
+        case QSimCommand::SelectItem:
+        {
+            if ( menuItem() != 0 ) {
+                data += (char)0x90;
+                data += (char)0x01;
+                data += (char)menuItem();
+            }
+        }
+        break;
+
+        case QSimCommand::SendUSSD:
+        {
+            if ( d->result != Success && d->result != IconNotDisplayed )
+                break;
+            int scheme = dataCodingScheme();
+            QSimCommand::ToPduOptions options = QSimCommand::NoPduOptions;
+            if ( scheme != -1 ) {
+                if ( ( scheme & 0x0C ) == QSMS_DefaultAlphabet )
+                    options = QSimCommand::PackedStrings;
+                else if ( ( scheme & 0x0C ) == QSMS_UCS2Alphabet )
+                    options = QSimCommand::UCS2Strings;
+                scheme &= 0xF3;
+            } else {
+                scheme = 0;
+            }
+            writeTextString( data, text(), options, (scheme << 8) | 0x8D );
+        }
+        break;
+
+        default: break;
+    }
+
+    // Add any extension data that is specified.
+    data += extensionData();
+
+    // Return the final SIM terminal response PDU.
+    return data;
+}
+
+/*!
+    Copy the QSimTerminalResponse object \a value.
+*/
+QSimTerminalResponse& QSimTerminalResponse::operator=( const QSimTerminalResponse &value )
+{
+    if ( d != value.d ) {
+        delete d;
+        d = new QSimTerminalResponsePrivate( value.d );
+    }
+    return *this;
+}
+
+/*!
+    \fn void QSimTerminalResponse::deserialize(Stream &value)
+
+    \internal
+
+    Deserializes the QSimTerminalResponse instance out to a template
+    type \c{Stream} \a stream.
+ */
+
+template <typename Stream> void QSimTerminalResponse::deserialize(Stream &stream)
+{
+    d->read( stream );
+}
+
+
+/*!
+    \fn void QSimTerminalResponse::serialize(Stream &value) const
+
+    \internal
+
+    Serializes the QSimTerminalResponse instance out to a template
+    type \c{Stream} \a stream.
+ */
+
+template <typename Stream> void QSimTerminalResponse::serialize(Stream &stream) const
+{
+    d->write( stream );
+}
+
+Q_IMPLEMENT_USER_METATYPE(QSimTerminalResponse)

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsimterminalresponse.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsimterminalresponse.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsimterminalresponse.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QSIMTERMINALRESPONSE_H
+#define QSIMTERMINALRESPONSE_H
+
+#include <qsimcommand.h>
+
+class QSimTerminalResponsePrivate;
+
+class QTOPIAPHONE_EXPORT QSimTerminalResponse
+{
+public:
+    QSimTerminalResponse();
+    QSimTerminalResponse( const QSimTerminalResponse& value );
+    ~QSimTerminalResponse();
+
+    enum Result
+    {
+        Success                             = 0x00,
+        PartialComprehension                = 0x01,
+        MissingInformation                  = 0x02,
+        RefreshPerformed                    = 0x03,
+        IconNotDisplayed                    = 0x04,
+        ModifiedCallControl                 = 0x05,
+        LimitedService                      = 0x06,
+        WithModification                    = 0x07,
+        SessionTerminated                   = 0x10,
+        BackwardMove                        = 0x11,
+        NoResponseFromUser                  = 0x12,
+        HelpInformationRequested            = 0x13,
+        UssdOrSsTerminatedByUser            = 0x14,
+
+        MEUnableToProcess                   = 0x20,
+        NetworkUnableToProcess              = 0x21,
+        UserDidNotAccept                    = 0x22,
+        UserClearedDownCall                 = 0x23,
+        ActionInContradictionWithTimer      = 0x24,
+        TemporaryCallControlProblem         = 0x25,
+        LaunchBrowserError                  = 0x26,
+
+        BeyondMECapabilities                = 0x30,
+        TypeNotUnderstood                   = 0x31,
+        DataNotUnderstood                   = 0x32,
+        NumberNotUnderstood                 = 0x33,
+        SsReturnError                       = 0x34,
+        SmsRpError                          = 0x35,
+        RequiredValuesMissing               = 0x36,
+        UssdReturnError                     = 0x37,
+        MultipleCardError                   = 0x38,
+        PermanentCallControlProblem         = 0x39,
+        BearerIndependentProtocolProblem    = 0x3A
+    };
+
+    enum Cause
+    {
+        // Common causes.
+        NoSpecificCause                     = 0x00,
+
+        // MEUnableToProcess causes.
+        ScreenIsBusy                        = 0x01,
+        BusyOnCall                          = 0x02,
+        BusyOnSsTransaction                 = 0x03,
+        NoService                           = 0x04,
+        AccessControlClassBar               = 0x05,
+        RadioResourceNotGranted             = 0x06,
+        NotInSpeechCall                     = 0x07,
+        BusyOnUssdTransaction               = 0x08,
+        BusyOnDtmf                          = 0x09,
+
+        // PermanentCallControlProblem causes.
+        ActionNotAllowed                    = 0x01,
+        TypeOfRequestHasChanged             = 0x02,
+
+        // MultipleCardError causes.
+        CardReaderRemovedOrNotPresent       = 0x01,
+        CardRemovedOrNotPresent             = 0x02,
+        CardReaderBusy                      = 0x03,
+        CardPoweredOff                      = 0x04,
+        CAPDUFormatError                    = 0x05,
+        MuteCard                            = 0x06,
+        TransmissionError                   = 0x07,
+        ProtocolNotSupported                = 0x08,
+        SpecifiedReaderNotValid             = 0x09,
+
+        // LaunchBrowserError causes.
+        BearerUnavailable                   = 0x01,
+        BrowserUnavailable                  = 0x02,
+        UnableToReadProvisioningData        = 0x03,
+
+        // BearerIndependentProtocolProblem causes.
+        NoChannelAvailable                  = 0x01,
+        ChannelClosed                       = 0x02,
+        ChannelIdentifierNotValid           = 0x03,
+        RequestedBufferSizeNotAvailable     = 0x04,
+        SecurityError                       = 0x05,
+        RequestedTransportNotAvailable      = 0x06
+    };
+
+    QSimCommand command() const;
+    void setCommand( const QSimCommand& value );
+
+    QByteArray commandPdu() const;
+    void setCommandPdu( const QByteArray& value );
+
+    QSimCommand::Device sourceDevice() const;
+    void setSourceDevice( QSimCommand::Device value );
+
+    QSimCommand::Device destinationDevice() const;
+    void setDestinationDevice( QSimCommand::Device value );
+
+    QSimTerminalResponse::Result result() const;
+    void setResult( QSimTerminalResponse::Result value );
+
+    QSimTerminalResponse::Cause cause() const;
+    void setCause( QSimTerminalResponse::Cause value );
+
+    QByteArray causeData() const;
+    void setCauseData( const QByteArray& value );
+
+    QString text() const;
+    void setText( const QString& value );
+
+    uint duration() const;
+    void setDuration( uint value );
+
+    uint menuItem() const;
+    void setMenuItem( uint value );
+
+    int dataCodingScheme() const;
+    void setDataCodingScheme( int value );
+
+    QByteArray extensionData() const;
+    void setExtensionData( QByteArray value );
+
+    QByteArray extensionField( int tag ) const;
+    void addExtensionField( int tag, const QByteArray& value );
+
+    static QSimTerminalResponse fromPdu( const QByteArray& pdu );
+    QByteArray toPdu() const;
+
+    QSimTerminalResponse& operator=( const QSimTerminalResponse & );
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+private:
+    QSimTerminalResponsePrivate *d;
+};
+
+Q_DECLARE_USER_METATYPE(QSimTerminalResponse)
+
+#endif // QSIMTERMINALRESPONSE_H

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,2620 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <stdlib.h>
+
+#include <qsmsmessage.h>
+#ifdef PHONESIM
+#include "qsmsmessage_p.h"
+#else
+#include <qtopiaphone/private/qsmsmessage_p.h>
+#endif
+#include <qatutils.h>
+#include <qgsmcodec.h>
+#ifdef Q_WS_QWS
+#include <qtopialog.h>
+#else
+#include <qdebug.h>
+#define qLog(dbgcat) if(1); else qDebug()
+#endif
+#include <qstringlist.h>
+
+#include <qtextcodec.h>
+
+const int Unit = 1;
+
+class QSMSMessagePartPrivate
+{
+public:
+    QSMSMessagePartPrivate( const QString& text )
+    {
+        this->isText = true;
+        this->text = text;
+        this->position = 0;
+    }
+    QSMSMessagePartPrivate( const QString& mimeType, const QByteArray& data )
+    {
+        this->isText = false;
+        this->mimeType = mimeType;
+        this->data = data;
+        this->position = 0;
+    }
+    QSMSMessagePartPrivate( const QString& mimeType, const QByteArray& data, uint position )
+    {
+        this->isText = false;
+        this->mimeType = mimeType;
+        this->data = data;
+        this->position = position;
+    }
+    QSMSMessagePartPrivate( const QSMSMessagePartPrivate& part )
+    {
+        this->isText = part.isText;
+        this->text = part.text;
+        this->mimeType = part.mimeType;
+        this->data = part.data;
+        this->position = part.position;
+    }
+
+    bool isText;
+    QString text;
+    QString mimeType;
+    QByteArray data;
+    uint position;
+};
+
+class QSMSMessagePrivate
+{
+public:
+    QSMSMessagePrivate()
+    {
+#if QT_VERSION < 0x040400
+        ref.init(1);
+#else
+        ref = 1;
+#endif
+        mValidity = 2 * 24 * 60;        // 2 days
+        mReplyRequest = false;
+        mStatusReportRequested = false;
+        mMessageType = QSMSMessage::Normal;
+        mCodec = 0;
+        mForceGsm = false;
+        mBestScheme = (QSMSDataCodingScheme)(-1);
+        mDataCodingScheme = -1;
+        mMessageClass = -1;
+        mProtocol = 0;
+    }
+
+    ~QSMSMessagePrivate()
+    {
+    }
+
+    /*  Convert from minutes to GSM 03.40 specification (section 9.2.3.12).
+         * 0-143   = 0 to 12 hours in 5 minute increments (0 = 5 minutes).
+         * 144-167 = 12hrs30min to 24hrs in 30 minute increments.
+         * 168-196 = 2days to 30days in 1 day increments.
+         * 197-255 = 5weeks to 63weeks in 1 week increments.
+    */
+    uint gsmValidityPeriod()
+    {
+        uint mins = mValidity;
+
+        if ( mins < 5 )
+            return 0;
+
+        if ( mins <= 12 * 60 )
+            return ((mins / 5) - 1);
+
+        if ( mins <= 24 * 60 )
+            return ((mins + 29 - (12 * 60 + 30)) / 30) + 144;
+
+        uint days = (mins + (24 * 60 - 1)) / (24 * 60);
+
+        if ( days <= 30 )
+            return days - 2 + 168;
+
+        if ( days <= 63 * 7 )
+            return ((days + 6) / 7) - 5 + 197;
+
+        return 255;
+    }
+
+    void setGsmValidityPeriod(uint value)
+    {
+        if ( value <= 143 )
+            mValidity = (value + 1) * 5;
+        else if ( value <= 167 )
+            mValidity = (value - 143) * 30 + 12 * 60;
+        else if ( value <= 196 )
+            mValidity = (value - 166) * 24 * 60;
+        else
+            mValidity = (value - 192) * 7 * 24 * 60;
+    }
+
+    template <typename Stream> void readFromStream( Stream &s )
+    {
+        QString codec;
+        s >> codec;
+        if ( codec.length() > 0)
+            mCodec = QTextCodec::codecForName( codec.toLatin1() );
+        else
+            mCodec = 0;
+        s >> mServiceCenter;
+        s >> mRecipient;
+        s >> mSender;
+        s >> mTimestamp;
+        s >> mValidity;
+        int val;
+        s >> val;
+        mReplyRequest = (val != 0);
+        s >> val;
+        mStatusReportRequested = (val != 0);
+        s >> val;
+        mForceGsm = (val != 0);
+        s >> val;
+        mMessageType = (QSMSMessage::MessageType)val;
+        s >> val;
+        mBestScheme = (QSMSDataCodingScheme)val;
+        s >> mHeaders;
+        s >> mParts;
+        mCachedBody = QString();
+        s >> mDataCodingScheme;
+        s >> mMessageClass;
+        s >> mProtocol;
+    }
+
+    template <typename Stream> void writeToStream( Stream &s )
+    {
+        if ( mCodec )
+            s << QString( mCodec->name() );
+        else
+            s << QString( "" );
+        s << mServiceCenter;
+        s << mRecipient;
+        s << mSender;
+        s << mTimestamp;
+        s << mValidity;
+        s << (int)mReplyRequest;
+        s << (int)mStatusReportRequested;
+        s << (int)mForceGsm;
+        s << (int)mMessageType;
+        s << (int)mBestScheme;
+        s << mHeaders;
+        s << mParts;
+        s << mDataCodingScheme;
+        s << mMessageClass;
+        s << mProtocol;
+    }
+
+    void copy( QSMSMessagePrivate *from )
+    {
+        *this = *from;
+        mHeaders = from->mHeaders;
+    }
+
+#if QT_VERSION < 0x040400
+    QBasicAtomic ref;
+#else
+    QAtomicInt ref;
+#endif
+    QTextCodec *mCodec;
+    QString mServiceCenter;
+    QString mRecipient;
+    QString mSender;
+    QDateTime mTimestamp;
+    uint mValidity;
+    bool mReplyRequest;
+    bool mStatusReportRequested;
+    bool mForceGsm;
+    QSMSMessage::MessageType mMessageType;
+    QSMSDataCodingScheme mBestScheme;
+    QByteArray mHeaders;
+    QList<QSMSMessagePart> mParts;
+    QString mCachedBody;
+    int mDataCodingScheme;
+    int mMessageClass;
+    int mProtocol;
+};
+
+/*!
+    \enum QSMSMessage::MessageType
+    Defines the type of an SMS message.
+
+    \value Normal The message is a normal SMS message.
+    \value CellBroadCast The message is a cell broadcast message.
+    \value StatusReport The message is an SMS status report message.
+*/
+
+/*!
+    \enum QSMSDataCodingScheme
+    Define the data coding scheme to use to encode SMS message text.
+
+    \value QSMS_Compressed Flag that indicates that the data is compressed
+           (not used at present).
+    \value QSMS_MessageClass Flag that indicates the message class
+           (not used at present).
+    \value QSMS_DefaultAlphabet Use the default 7-bit GSM alphabet.
+    \value QSMS_8BitAlphabet Use the locale-specific 8-bit alphabet.
+    \value QSMS_UCS2Alphabet Use the UCS-2 16-bit alphabet.
+    \value QSMS_ReservedAlphabet Use the reserved alphabet
+           (not used at present).
+*/
+
+/*!
+    \class QSMSMessagePart
+    \mainclass
+    \brief The QSMSMessagePart class specifies a part within an SMS message.
+
+    \ingroup telephony
+    \sa QSMSMessage
+
+    QSMSMessage objects contain zero or more "parts", which describe
+    the contents of the SMS message.  A part may be plain text,
+    or a binary stream tagged by a MIME type.
+*/
+
+/*!
+    Constructs an empty SMS message part.
+*/
+QSMSMessagePart::QSMSMessagePart()
+{
+    d = new QSMSMessagePartPrivate( QString() );
+}
+
+/*!
+    Constructs a new plain text SMS message part from the
+    string \a text.
+*/
+QSMSMessagePart::QSMSMessagePart( const QString& text )
+{
+    d = new QSMSMessagePartPrivate( text );
+}
+
+/*!
+    Constructs a new binary SMS message part with the specified
+    \a mimeType and \a data.
+*/
+QSMSMessagePart::QSMSMessagePart( const QString& mimeType, const QByteArray& data )
+{
+    d = new QSMSMessagePartPrivate( mimeType, data );
+}
+
+/*!
+    Constructs a new binary SMS message part with the specified
+    \a mimeType and \a data.  The part is intended to be displayed
+    at \a position within a subsequent text part.
+*/
+QSMSMessagePart::QSMSMessagePart( const QString& mimeType, const QByteArray& data, uint position )
+{
+    d = new QSMSMessagePartPrivate( mimeType, data, position );
+}
+
+/*!
+    Constructs a copy of \a part.
+*/
+QSMSMessagePart::QSMSMessagePart( const QSMSMessagePart& part )
+{
+    d = new QSMSMessagePartPrivate( *(part.d) );
+}
+
+/*!
+    Destructs the QSMSMessagePart.
+*/
+QSMSMessagePart::~QSMSMessagePart()
+{
+    delete d;
+}
+
+/*!
+    Assigns a copy of \a part to this object.
+*/
+QSMSMessagePart& QSMSMessagePart::operator=( const QSMSMessagePart& part )
+{
+    if ( &part != this ) {
+        delete d;
+        d = new QSMSMessagePartPrivate( *(part.d) );
+    }
+    return *this;
+}
+
+/*!
+    Returns true if this SMS message part is plain text; or false if binary.
+*/
+bool QSMSMessagePart::isText() const
+{
+    return d->isText;
+}
+
+/*!
+    Returns the plain text contents of this SMS message part,
+    or QString() if it is not a text part.
+*/
+QString QSMSMessagePart::text() const
+{
+    return d->text;
+}
+
+/*!
+    Returns the MIME type associated with this SMS message part,
+    or QString() if it is not a binary part.
+*/
+QString QSMSMessagePart::mimeType() const
+{
+    return d->mimeType;
+}
+
+/*!
+    Returns the binary data associated with this SMS message part.
+    Returns and empty QByteArray if it is not a binary part.
+*/
+const QByteArray& QSMSMessagePart::data() const
+{
+    return d->data;
+}
+
+/*!
+    Returns the text position to display this SMS message part at.
+*/
+uint QSMSMessagePart::position() const
+{
+    return d->position;
+}
+
+/*!
+    \internal
+    \fn void QSMSMessagePart::deserialize(Stream &stream)
+*/
+template <typename Stream> void QSMSMessagePart::deserialize(Stream &stream)
+{
+    int flag;
+    stream >> flag;
+    d->isText = (flag != 0);
+    stream >> d->text;
+    stream >> d->mimeType;
+    stream >> d->data;
+    stream >> d->position;
+}
+
+/*!
+    \internal
+    \fn void QSMSMessagePart::serialize(Stream &stream) const
+*/
+template <typename Stream> void QSMSMessagePart::serialize(Stream &stream) const
+{
+    stream << (int)(d->isText);
+    stream << d->text;
+    stream << d->mimeType;
+    stream << d->data;
+    stream << d->position;
+}
+
+/*!
+    \class QSMSMessage
+    \mainclass
+    \brief The QSMSMessage class specifies the contents of an SMS message.
+
+    This class is intended for use with QSMSReader and QSMSSender to process
+    SMS messages according to 3GPP TS 03.40 and 23.040.
+
+    An incoming SMS message from QSMSReader will typically have text() and
+    sender() set.  Other fields such as destinationPort() and
+    applicationData() may be set if the message is a WAP Push or SMS datagram
+    message rather than plain text.
+
+    An outgoing SMS message sent via QSMSSender will need to have at least
+    recipient() and text() set.  If the message is a WAP Push or SMS datagram
+    message rather than plain text, then destinationPort() and applicationData()
+    should also be set.
+
+    Special header fields in SMS messages can be accessed with serviceCenter(),
+    replyRequest(), statusReportRequested(), validityPeriod(), timestamp(),
+    dataCodingScheme(), and protocol().
+
+    \ingroup telephony
+*/
+
+/*!
+    Constructs an empty QSMSMessage.
+*/
+QSMSMessage::QSMSMessage()
+{
+    d = new QSMSMessagePrivate;
+}
+
+/*!
+    Constructs an QSMSMessage that is a copy of \a msg.
+*/
+QSMSMessage::QSMSMessage(const QSMSMessage &msg)
+{
+    d = msg.d;
+    d->ref.ref();
+}
+
+/*!
+    Destructs the QSMSMessage.
+*/
+QSMSMessage::~QSMSMessage()
+{
+    if ( !d->ref.deref() )
+        delete d;
+}
+
+QSMSMessagePrivate *QSMSMessage::dwrite()
+{
+    // If we are the only user of the private object, return it as-is.
+    if ( d->ref == 1 )
+        return d;
+
+    // Create a new private object and copy the current contents into it.
+    QSMSMessagePrivate *newd = new QSMSMessagePrivate();
+    newd->copy( d );
+    if ( !d->ref.deref() )
+        delete d;
+    d = newd;
+    return newd;
+}
+
+/*!
+    Assigns a copy of \a msg to this object.
+*/
+QSMSMessage& QSMSMessage::operator=( const QSMSMessage &msg)
+{
+    if ( d == msg.d )
+        return *this;
+
+    if ( !d->ref.deref() )
+        delete d;
+
+    d = msg.d;
+    d->ref.ref();
+
+    return *this;
+}
+
+/*!
+    Sets the contents of this QSMSMessage to a single plain text
+    body containing \a str.  This is for simple messages only.
+    Complex messages should be constructed part by part using
+    the addPart() method.
+
+    \sa text()
+*/
+void QSMSMessage::setText(const QString &str)
+{
+    clearParts();
+    addPart( QSMSMessagePart( str ) );
+}
+
+/*!
+    Returns the contents of this QSMSMessage as a single plain text string.
+    If the message contains binary parts, they will not appear
+    in the result.  This is for simple message viewers only.
+    Complex message viewers should iterate over the list returned
+    by parts().
+
+    \sa setText()
+*/
+QString QSMSMessage::text() const
+{
+    // Handle the easy cases first.
+    if ( d->mParts.count() == 0 ) {
+        return QString();
+    } else if ( d->mParts.count() == 1 && d->mParts[0].isText() ) {
+        return d->mParts[0].text();
+    } else if ( d->mCachedBody.length() > 0 ) {
+        return d->mCachedBody;
+    }
+
+    // We need the private structure to be writable to cache the body.
+    const_cast<QSMSMessage *>(this)->dwrite();
+
+    // Append all text parts to get the complete body.
+    QString body = QString();
+    for ( int posn = 0; posn < d->mParts.count(); ++posn ) {
+        if ( d->mParts[posn].isText() ) {
+            body += d->mParts[posn].text();
+        }
+    }
+    d->mCachedBody = body;
+    return body;
+}
+
+/*!
+    If the message consists solely of characters in the 7-bit GSM
+    encoding, then the message will be transmitted that way.
+    Otherwise \a codec is used to convert the characters into an
+    appropriate language-specific 8-bit encoding.  If \a codec is
+    set to NULL, then the default UCS-2 encoding for GSM messages
+    is used.
+
+    \sa textCodec()
+*/
+void QSMSMessage::setTextCodec(QTextCodec *codec)
+{
+    dwrite()->mCodec = codec;
+}
+
+/*!
+    Returns the current 8-bit text codec, or NULL if none has
+    been set.
+
+    \sa setTextCodec()
+*/
+QTextCodec *QSMSMessage::textCodec() const
+{
+    return d->mCodec;
+}
+
+/*!
+    If \a force is true, then the codec set by QSMSMessage::setTextCodec
+    is ignored and the 7-bit GSM encoding is always used.  Setting this
+    flag increases the number of characters that can be sent in any
+    given SMS message, but may lose information.
+
+    \sa forceGsm()
+*/
+void QSMSMessage::setForceGsm(bool force)
+{
+    dwrite()->mForceGsm = force;
+}
+
+/*!
+    Returns true if the 7-bit GSM encoding has been forced.
+
+    \sa setForceGsm()
+*/
+bool QSMSMessage::forceGsm() const
+{
+    return d->mForceGsm;
+}
+
+/*!
+    Sets the SMS data coding \a scheme to use for this message.
+    Normally you won't need to call this unless the user has
+    somehow explicitly requested an override.  By default,
+    the QSMSMessage class will choose the best scheme for you.
+    Should be set to one of \c QSMS_DefaultAlphabet,
+    \c QSMS_8BitAlphabet, or \c QSMS_UCS2Alphabet.
+
+    \sa bestScheme()
+*/
+void QSMSMessage::setBestScheme(QSMSDataCodingScheme scheme)
+{
+    dwrite()->mBestScheme = scheme;
+}
+
+
+/*!
+    Returns the best SMS data coding scheme to use for this
+    message, determined by an inspection of the plain text body parts.
+
+    \sa setBestScheme()
+*/
+QSMSDataCodingScheme QSMSMessage::bestScheme() const
+{
+    QTextCodec *codec = QAtUtils::codec( "gsm-noloss" );
+    QString body = text();
+    uint len = body.length();
+    bool gsmSafe;
+
+    // Did the user provide a scheme override?
+    if ( d->mBestScheme != (QSMSDataCodingScheme)(-1) )
+        return d->mBestScheme;
+
+    // Encode zero-length bodies in the default alphabet.
+    if ( len == 0 )
+        return QSMS_DefaultAlphabet;
+
+    // Always use GSM if we are forced to do so.
+    if ( d->mForceGsm )
+        return QSMS_DefaultAlphabet;
+
+    // Check the body for non-GSM characters.
+    gsmSafe = codec->canEncode( body );
+
+    // Use the default alphabet if everything is GSM-compatible.
+    if ( gsmSafe )
+        return QSMS_DefaultAlphabet;
+
+    // See if we can convert to 8-bit using the codec
+    // without losing any information.
+    if ( d->mCodec && d->mCodec->canEncode( body ) )
+        return QSMS_8BitAlphabet;
+
+    // Default to the UCS-2 alphabet.
+    return QSMS_UCS2Alphabet;
+}
+
+/*!
+    Sets the recipient's telephone number to \a txt.
+
+    \sa recipient()
+*/
+void QSMSMessage::setRecipient(const QString &txt)
+{
+    dwrite()->mRecipient = txt;
+}
+
+/*!
+    Returns the recipient's telephone number.  Normally QString()
+    for an incoming message.
+
+    \sa setRecipient()
+*/
+QString QSMSMessage::recipient() const
+{
+    return d->mRecipient;
+}
+
+/*!
+    Sets the sender's telephone number to \a txt.
+
+    \sa sender()
+*/
+void QSMSMessage::setSender(const QString &txt)
+{
+    dwrite()->mSender = txt;
+}
+
+/*!
+    Returns the sender's telephone number.  Normally QString()
+    for an outgoing message.
+
+    \sa setSender()
+*/
+QString QSMSMessage::sender() const
+{
+    return d->mSender;
+}
+
+/*!
+    Sets the service center to use for transmitting this SMS message,
+    or QString() for the default service center, to \a str.
+
+    \sa serviceCenter()
+*/
+void QSMSMessage::setServiceCenter(const QString &str)
+{
+    dwrite()->mServiceCenter = str;
+}
+
+/*!
+    Returns the service center.
+
+    \sa setServiceCenter()
+*/
+QString QSMSMessage::serviceCenter() const
+{
+    return d->mServiceCenter;
+}
+
+/*!
+    Enable or disable the "reply request" flag for this SMS message,
+    according to the value of \a on.
+
+    \sa replyRequest()
+*/
+void QSMSMessage::setReplyRequest(bool on )
+{
+    dwrite()->mReplyRequest = on;
+}
+
+/*!
+    Returns the "reply request" flag.
+
+    \sa setReplyRequest()
+*/
+bool QSMSMessage::replyRequest() const
+{
+    return d->mReplyRequest;
+}
+
+/*!
+    Sets the status report requested flag to \a on.
+
+    \sa statusReportRequested()
+*/
+void QSMSMessage::setStatusReportRequested(bool on)
+{
+    dwrite()->mStatusReportRequested = on;
+}
+
+/*!
+    Returns true if status report requested flag is currently set;otherwise returns false.
+
+    \sa setStatusReportRequested()
+*/
+bool QSMSMessage::statusReportRequested() const
+{
+    return d->mStatusReportRequested;
+}
+
+/*!
+    Sets the validity period to \a minutes.  The default is 2 days.  If the value
+    is set to \c{(uint)(-1)}, it indicates that the message should have no
+    validity period specified.
+
+    \sa validityPeriod(), gsmValidityPeriod()
+*/
+void QSMSMessage::setValidityPeriod(uint minutes)
+{
+    dwrite()->mValidity = minutes;
+}
+
+/*!
+    Returns the validity period in minutes for this message.  The default is 2 days.
+    If the value is \c{(uint)(-1)}, it indicates that the message should have no
+    validity period specified.
+
+    \sa setValidityPeriod(), setGsmValidityPeriod()
+*/
+uint QSMSMessage::validityPeriod() const
+{
+    return d->mValidity;
+}
+
+/*!
+    Sets the GSM validity period to \a value, which must be between
+    0 and 255, inclusive.  The setValidity() method
+    is a friendlier way to set the validity value.
+
+    0 to 143 indicates 0 to 12 hours in 5 minute increments (0 = 5 minutes).
+    144 to 167 indicates 12 hrs 30 min to 24 hrs in 30 minute increments.
+    168 to 196 indicates 2 days to 30 days in 1 day increments.
+    197 to 255 indicates 5 weeks to 63 weeks in 1 week increments.
+
+    \sa gsmValidityPeriod(), validityPeriod()
+*/
+void QSMSMessage::setGsmValidityPeriod(uint value)
+{
+    dwrite()->setGsmValidityPeriod(value);
+}
+
+/*!
+    Returns the GSM validity period value, between 0 and 255, inclusive.
+
+    \sa setGsmValidityPeriod(), setValidityPeriod()
+*/
+uint QSMSMessage::gsmValidityPeriod() const
+{
+    return d->gsmValidityPeriod();
+}
+
+/*!
+    Sets the SMS message's \a timestamp.
+
+    \sa timestamp()
+*/
+void QSMSMessage::setTimestamp(const QDateTime& timestamp)
+{
+    dwrite()->mTimestamp = timestamp;
+}
+
+/*!
+    Returns the SMS message's timestamp, which will be null if the
+    message does not have a timestamp.
+
+    \sa setTimestamp()
+*/
+QDateTime QSMSMessage::timestamp() const
+{
+    return d->mTimestamp;
+}
+
+/*!
+    Returns the SMS message type.
+
+    \sa setMessageType()
+*/
+QSMSMessage::MessageType QSMSMessage::messageType() const
+{
+    return d->mMessageType;
+}
+
+/*!
+    Sets the SMS message type to \a m.  There is rarely any need to
+    set this to something other than QSMSMessage::Normal.
+
+    \sa messageType()
+*/
+void QSMSMessage::setMessageType(MessageType m)
+{
+    dwrite()->mMessageType  = m;
+}
+
+/*!
+    Sets the SMS message's user data headers to \a value.
+
+    \sa headers()
+*/
+void QSMSMessage::setHeaders(const QByteArray& value)
+{
+    dwrite()->mHeaders = value;
+}
+
+/*!
+    Returns the SMS message's user data headers.
+
+    \sa setHeaders()
+*/
+const QByteArray& QSMSMessage::headers() const
+{
+    return d->mHeaders;
+}
+
+/*!
+    Clear all body parts from this SMS message.
+
+    \sa addPart(), addParts(), parts()
+*/
+void QSMSMessage::clearParts()
+{
+    dwrite()->mParts.clear();
+    dwrite()->mCachedBody = QString();
+}
+
+/*!
+    Add a new body \a part to this SMS message.
+
+    \sa clearParts(), addParts(), parts()
+*/
+void QSMSMessage::addPart( const QSMSMessagePart& part )
+{
+    // We need a writable copy.
+    dwrite();
+
+    // Clear the part list if we have one empty text part.
+    if ( d->mParts.count() == 1 &&
+         d->mParts[0].isText() &&
+         d->mParts[0].text().length() == 0 ) {
+        d->mParts.clear();
+    }
+
+    // Append the new part and clear the cached text.
+    d->mParts.append( part );
+    d->mCachedBody = QString();
+}
+
+/*!
+    Add a list of body \a parts to this SMS message.
+
+    \sa clearParts(), addPart(), parts()
+*/
+void QSMSMessage::addParts( const QList<QSMSMessagePart>& parts )
+{
+    // We need a writable copy.
+    dwrite();
+
+    if ( d->mParts.count() == 1 &&
+         d->mParts[0].isText() &&
+         d->mParts[0].text().length() == 0 ) {
+        d->mParts.clear();
+    }
+    d->mParts += parts;
+    d->mCachedBody = QString();
+}
+
+/*!
+    Returns a list of all body parts in this SMS message.
+
+    \sa clearParts(), addParts(), addPart()
+*/
+QList<QSMSMessagePart> QSMSMessage::parts() const
+{
+    return d->mParts;
+}
+
+/*!
+    Compute an estimate for the number of messages that will need
+    to be used to send this SMS message (\a numMessages), and the
+    number of spare characters that are left in the last message
+    before it overflows (\a spaceLeftInLast).
+
+    This function may be useful in user interfaces to indicate to
+    the user that an SMS message needs to be sent in multiple pieces,
+    costing the user more money.
+*/
+void QSMSMessage::computeSize( uint& numMessages, uint& spaceLeftInLast ) const
+{
+    int part = findPart( "application/x-qtopia-wdp-ports" );
+    if ( part != -1 ) {
+        // This is an application datagram, which has its size
+        // computed using a different algorithm.
+        uint headerLen = 3 + d->mParts[(uint)part].data().size();
+        uint dataLen = applicationData().size();
+        if ( ( headerLen + dataLen ) <= 140 ) {
+            numMessages = 1;
+            spaceLeftInLast = 134 - headerLen - dataLen;
+        } else {
+            uint partSize = ( 134 - headerLen );
+            numMessages = ( dataLen + partSize - 1 ) / partSize;
+            spaceLeftInLast = dataLen - numMessages * partSize;
+        }
+        return;
+    }
+
+    QSMSDataCodingScheme scheme = bestScheme();
+    uint len;
+    QString body = text();
+
+    if ( scheme == QSMS_DefaultAlphabet ) {
+
+        // Encode the message using 7-bit GSM.
+        len = body.length();
+        if ( len <= 160 ) {
+            numMessages = 1;
+            spaceLeftInLast = 160 - len;
+        } else {
+            // 153 = 160 - fragment_header_size (7).
+            numMessages = ( len + 152 ) / 153;
+            len %= 153;
+            if ( len != 0 )
+                spaceLeftInLast = 153 - len;
+            else
+                spaceLeftInLast = 0;
+        }
+
+    } else if ( scheme == QSMS_8BitAlphabet ) {
+
+        // Encode the message using an 8-bit character set.
+        QByteArray converted = d->mCodec->fromUnicode( body );
+        len = converted.length();
+        if ( len <= 140 ) {
+            numMessages = 1;
+            spaceLeftInLast = 140 - len;
+        } else {
+            // 134 = 140 - fragment_header_size (6).
+            numMessages = ( len + 133 ) / 134;
+            len %= 134;
+            if ( len != 0 )
+                spaceLeftInLast = 134 - len;
+            else
+                spaceLeftInLast = 0;
+        }
+
+    } else {
+
+        // Encode the message with unicode.
+        len = body.length();
+        if ( len <= 70 ) {
+            numMessages = 1;
+            spaceLeftInLast = 70 - len;
+        } else {
+            // 67 = 70 - fragment_header_size (3).
+            numMessages = ( len + 66 ) / 67;
+            len %= 67;
+            if ( len != 0 )
+                spaceLeftInLast = 67 - len;
+            else
+                spaceLeftInLast = 0;
+        }
+    }
+}
+
+/*!
+    Returns the destination port number if this SMS message contains
+    an application datagram, or -1 if not an application datagram.
+
+    When an SMS message is received that has a destination port
+    number, Qtopia will attempt to find a QDS service that can handle it.
+    Qtopia first looks for a QDS service named \c push for the MIME type
+    \c T from the WAP push header.  Next, it looks for a service named
+    \c push for the MIME type \c{application/x-smsapp-N} where
+    \c N is the port number in decimal.
+
+    If a matching service is found, then the SMS message is
+    sent to the corresponding application via QDS.  The QCop
+    message is that specified in the QDS service definition.
+    Thus, applications can register to receive special SMS messages.
+
+    The following QDS definition, in \c{etc/qds/ContactsPhone} will
+    direct vcard's that are received via WAP to the \c ContactsPhone
+    service.  The \c ContactsPhone service is normally implemented
+    by the \c addressbook program.
+
+    \code
+    [Translation]
+    File=QtopiaServices
+    Context=ContactsPhone
+    [pushVCard]
+    RequestDataType=text/x-vcard
+    ResponseDataType=
+    Attributes="push"
+    Description[]=Receive a vcard via WAP push
+    \endcode
+
+    The \c Attributes must contain \c push and the \c RequestDataType
+    must be the MIME type to be dispatched.  The QCop message that is
+    delivered to the application will have the name
+    \c pushVCard(QDSActionRequest).  The data in the action request
+    will be the payload of the push message.
+
+    The auxilary data in the action request will be a QByteArray
+    containing the full QSMSMessage object, from which the application
+    can extra header information if it needs it.  Use the QSMSMessage
+    datastream operators to extract the QSMSMessage object.
+
+    If the application fails to process an SMS message that is sent to
+    it via QCop, then it will be lost.  It is important that such
+    applications take steps to save the message if necessary.
+
+    If a matching service is not found, then the SMS message
+    will be delivered to the \c qtmail application normally,
+    and then saved by that application.
+
+    \sa setDestinationPort(), sourcePort()
+*/
+int QSMSMessage::destinationPort() const
+{
+    int part = findPart( "application/x-qtopia-wdp-ports" );
+    if ( part == -1 )
+        return -1;
+
+    QByteArray data = d->mParts[(uint)part].data();
+    if ( data.size() == 4 ) {
+
+        return ((((int)(data[0])) & 0xFF) << 8) |
+                (((int)(data[1])) & 0xFF);
+
+    } else if ( data.size() == 2 ) {
+
+        return (((int)(data[0])) & 0xFF);
+    }
+
+    return -1;
+}
+
+/*!
+    Sets the destination port number for an SMS message that contains
+    an application datagram to \a value.
+
+    \sa destinationPort(), sourcePort()
+*/
+void QSMSMessage::setDestinationPort(int value)
+{
+    QByteArray data;
+    int source;
+    int part = findPart( "application/x-qtopia-wdp-ports" );
+    if ( part == -1 ) {
+        data.resize(4);
+        data[0] = (char)(value >> 8);
+        data[1] = (char)value;
+        data[2] = (char)0;
+        data[3] = (char)0;
+    } else {
+        source = sourcePort();
+        data.resize(4);
+        data[0] = (char)(value >> 8);
+        data[1] = (char)value;
+        data[2] = (char)(source >> 8);
+        data[3] = (char)source;
+    }
+    removeParts( "application/x-qtopia-wdp-ports" );
+    addPart( QSMSMessagePart( "application/x-qtopia-wdp-ports", data ) );
+}
+
+/*!
+    Returns the source port number if this SMS message contains
+    an application datagram, or -1 if not an application datagram.
+
+    \sa setSourcePort(), destinationPort()
+*/
+int QSMSMessage::sourcePort() const
+{
+    int part = findPart( "application/x-qtopia-wdp-ports" );
+    if ( part == -1 )
+        return -1;
+
+    QByteArray data = d->mParts[(uint)part].data();
+    if ( data.size() == 4 ) {
+
+        return ((((int)(data[2])) & 0xFF) << 8) |
+                (((int)(data[3])) & 0xFF);
+
+    } else if ( data.size() == 2 ) {
+
+        return (((int)(data[1])) & 0xFF);
+    }
+
+    return -1;
+}
+
+/*!
+    Sets the source port number for an SMS message that contains
+    an application datagram to \a value.
+
+    \sa sourcePort(), destinationPort()
+*/
+void QSMSMessage::setSourcePort(int value)
+{
+    QByteArray data;
+    int dest;
+    int part = findPart( "application/x-qtopia-wdp-ports" );
+    if ( part == -1 ) {
+        data.resize(4);
+        data[0] = (char)0;
+        data[1] = (char)0;
+        data[2] = (char)(value >> 8);
+        data[3] = (char)value;
+    } else {
+        dest = destinationPort();
+        data.resize(4);
+        data[0] = (char)(dest >> 8);
+        data[1] = (char)dest;
+        data[2] = (char)(value >> 8);
+        data[3] = (char)value;
+    }
+    removeParts( "application/x-qtopia-wdp-ports" );
+    addPart( QSMSMessagePart( "application/x-qtopia-wdp-ports", data ) );
+}
+
+/*!
+    Returns the data if this SMS message contains an application datagram.
+    Returns an empty byte array if this message is not a datagram.
+
+    \sa setApplicationData()
+*/
+QByteArray QSMSMessage::applicationData() const
+{
+    QByteArray data;
+    QList<QSMSMessagePart>::ConstIterator iter;
+    uint size;
+    for ( iter = d->mParts.begin(); iter != d->mParts.end(); ++iter ) {
+        if ( (*iter).mimeType() == "application/x-qtopia-wdp" ) {
+            size = data.size();
+            data.resize( size + (*iter).data().size() );
+            memcpy( data.data() + size, (*iter).data().data(),
+                    (*iter).data().size() );
+        }
+    }
+    return data;
+}
+
+/*!
+    Sets the data within an SMS message that contains an application
+    datagram to \a value.
+
+    \sa applicationData()
+*/
+void QSMSMessage::setApplicationData(const QByteArray& value)
+{
+    removeParts( "application/x-qtopia-wdp" );
+    addPart( QSMSMessagePart( "application/x-qtopia-wdp", value ) );
+}
+
+/*!
+    Sets the data coding scheme to use within an SMS message to \a value.
+    If \a value is -1, then the system chooses the best data coding scheme
+    based on the content.
+
+    This method is mainly of use with application datagrams, not text
+    SMS messages.
+
+    \sa dataCodingScheme()
+*/
+void QSMSMessage::setDataCodingScheme(int value)
+{
+    dwrite()->mDataCodingScheme = value;
+}
+
+/*!
+    Returns the data coding scheme to use within an SMS message.
+    If the value is -1, then the system chooses the best data coding scheme
+    based on the content.
+
+    This method is mainly of use with application datagrams, not text
+    SMS messages.
+
+    \sa setDataCodingScheme()
+*/
+int QSMSMessage::dataCodingScheme() const
+{
+    return d->mDataCodingScheme;
+}
+
+/*!
+    Sets the message class for this message to \a value.  The \value should
+    be -1 if the system should choose a default message class.  The message
+    class should otherwise be 0, 1, 2, or 3, according to 3GPP TS 03.38.
+*/
+void QSMSMessage::setMessageClass(int value)
+{
+    dwrite()->mMessageClass = value;
+}
+
+/*!
+    Get the message class for this message, or -1 if the system should
+    choose a default message class.  The message class should otherwise
+    be 0, 1, 2, or 3, according to 3GPP TS 03.38.
+*/
+int QSMSMessage::messageClass() const
+{
+    return d->mMessageClass;
+}
+
+/*!
+    Sets the SMS message's protocol field to \a value.
+
+    \sa protocol()
+*/
+void QSMSMessage::setProtocol(int value)
+{
+    dwrite()->mProtocol = value;
+}
+
+/*!
+    Returns the SMS message's protocol field.
+
+    \sa setProtocol()
+*/
+int QSMSMessage::protocol() const
+{
+    return d->mProtocol;
+}
+
+/*!
+    Returns true if this message needs to be split into multiple messages
+    before being transmitted over a GSM network; otherwise returns false.
+
+    \sa split()
+*/
+bool QSMSMessage::shouldSplit() const
+{
+    uint numMessages, spaceLeftInLast;
+    this->computeSize( numMessages, spaceLeftInLast );
+    return ( numMessages <=1 ? false : true );
+}
+
+/*!
+    Split this message into several messages of smaller size for
+    transmission over a GSM network.
+
+    \sa shouldSplit()
+*/
+QList<QSMSMessage> QSMSMessage::split() const
+{
+    QList<QSMSMessage> list;
+    uint numMessages, spaceLeftInLast;
+    static uint fragmentCounter =0;
+
+    computeSize( numMessages, spaceLeftInLast );
+    if ( numMessages <= 1 ) {
+        // Splitting is not necessary, so return a list with one message.
+        list += *this;
+        return list;
+    }
+
+    // Get the number of characters to transmit in each fragment.
+    int split;
+    QSMSDataCodingScheme scheme = bestScheme();
+    switch ( scheme ) {
+        case QSMS_DefaultAlphabet:  split = 153; break;
+        case QSMS_8BitAlphabet:     split = 134; break;
+        default:                    split = 67; break;
+    }
+
+    // Split the message to create sub-messages and transmit them.
+    int posn = 0;
+    int len;
+    uint number;
+    QSMSMessage tmp;
+    number = 1;
+    if ( destinationPort() == -1 ) {
+        // Splitting a simple text message.
+        QString txt = text();
+        while ( posn < txt.length() ) {
+            tmp = *this;
+            len = txt.length() - posn;
+            if ( len > split ) {
+                len = split;
+            }
+            tmp.setText( txt.mid( posn, len ) );
+            tmp.setFragmentHeader( fragmentCounter, number++,
+                                   numMessages, scheme );
+            posn += len;
+            list.append(tmp);
+        }
+    } else {
+        // Splitting a datagram message.
+        QByteArray data = applicationData();
+        QByteArray part;
+        uint partSize = 134 - 6;
+        while ( posn < data.size() ) {
+            tmp = *this;
+            if ( ( posn + partSize ) <= (uint)data.size() ) {
+                part.resize(partSize);
+                memcpy(part.data(), data.data() + posn, partSize );
+            } else {
+                part.resize(data.size() - posn);
+                memcpy(part.data(), data.data() + posn, data.size() - posn);
+            }
+            tmp.setDestinationPort( destinationPort() );// Force 16-bit ports.
+            tmp.setFragmentHeader( fragmentCounter, number++,
+                                   numMessages, QSMS_8BitAlphabet );
+            tmp.setApplicationData( part );
+            list.append(tmp);
+            posn += partSize;
+        }
+    }
+
+    // Increase the fragment counter for the next multi-part SMS message.
+    fragmentCounter = ( fragmentCounter + 1 ) & 0xFF;
+
+    return list;
+}
+
+/*!
+    Convert this SMS message into its binary PDU form, according to
+    3GPP TS 03.40 and 3GPP TS 23.040.  If the message has a recipient,
+    then a SUBMIT message will be constructed.  If the message does not
+    have a recipient, then a DELIVER message will be constructed.
+
+    \sa fromPdu()
+*/
+QByteArray QSMSMessage::toPdu() const
+{
+    QSMSSubmitMessage submit( *this, recipient().isEmpty() );
+    return submit.toByteArray();
+}
+
+/*!
+    Convert a binary \a pdu into an SMS message, according to
+    3GPP TS 03.40 and 3GPP TS 23.040.
+
+    \sa toPdu()
+*/
+QSMSMessage QSMSMessage::fromPdu( const QByteArray& pdu )
+{
+    QSMSDeliverMessage pdumsg( pdu );
+    return pdumsg.unpack();
+}
+
+/*!
+    Returns the length of the service center address on the start of \a pdu.
+    This is typically used with AT-based GSM modems that need to transmit
+    the length of the pdu, excluding the service center address,
+    along with the \c{AT+CMGS} command.
+*/
+int QSMSMessage::pduAddressLength( const QByteArray& pdu )
+{
+    if( pdu.length() > 0 )
+        return (pdu[0] & 0xFF) + 1;
+    else
+        return 0;
+}
+
+int QSMSMessage::findPart( const QString& mimeType ) const
+{
+    QList<QSMSMessagePart>::ConstIterator iter;
+    int posn = 0;
+    for ( iter = d->mParts.begin(); iter != d->mParts.end(); ++iter ) {
+        if ( (*iter).mimeType() == mimeType )
+            return posn;
+        ++posn;
+    }
+    return -1;
+}
+
+void QSMSMessage::removeParts( const QString& mimeType )
+{
+    dwrite();
+    QList<QSMSMessagePart>::Iterator iter;
+    for ( iter = d->mParts.begin(); iter != d->mParts.end(); ) {
+        if ( (*iter).mimeType() == mimeType ) {
+            iter = d->mParts.erase( iter );
+        } else {
+            ++iter;
+        }
+    }
+}
+
+void QSMSMessage::setFragmentHeader( uint refNum, uint part, uint numParts,
+                                    QSMSDataCodingScheme scheme )
+{
+    dwrite()->mBestScheme = scheme;
+    uint len = d->mHeaders.size();
+    d->mHeaders.resize( len + 5 );
+    d->mHeaders[len++] = 0;         // Type for concatenated short messages.
+    d->mHeaders[len++] = 3;         // Length of header information.
+    d->mHeaders[len++] = (char)refNum;
+    d->mHeaders[len++] = (char)numParts;
+    d->mHeaders[len++] = (char)part;
+}
+
+
+void QSMSMessage::unpackHeaderParts()
+{
+    QByteArray headers = dwrite()->mHeaders;
+    uint posn = 0;
+    uint tag, len;
+    uint temp;
+    QString type;
+    while ( ( posn + 2 ) <= (uint)(headers.size()) ) {
+        tag = (unsigned char)(headers[posn]);
+        len = (unsigned char)(headers[posn + 1]);
+        if ( ( posn + len + 2 ) > (uint)(headers.size()) )
+            break;
+        switch ( (SMSHeaderKind)tag ) {
+
+            case SMS_HK_Predefined_Sound:
+            {
+                // Predefined sound type.
+                if ( len >= 2 ) {
+                    QByteArray data( len - 1, 0 );
+                    memcpy( data.data(), headers.data() + posn + 3, len - 1 );
+                    addPart( QSMSMessagePart
+                        ( "application/x-qtopia-predefined-sound", data,
+                          headers[posn + 2] & 0xFF ) );
+                }
+            }
+            break;
+
+            case SMS_HK_User_Defined_Sound:
+            {
+                // User defined sound type.
+                if ( len >= 2 ) {
+                    QByteArray data( len - 1, 0 );
+                    memcpy( data.data(), headers.data() + posn + 3, len - 1 );
+                    addPart( QSMSMessagePart
+                        ( "audio/imelody", data, headers[posn + 2] & 0xFF ) );
+                }
+            }
+            break;
+
+            case SMS_HK_Predefined_Animation:
+            {
+                // Predefined animation type.
+                if ( len >= 2 ) {
+                    QByteArray data( len - 1, 0 );
+                    memcpy( data.data(), headers.data() + posn + 3, len - 1 );
+                    addPart( QSMSMessagePart
+                        ( "application/x-qtopia-predefined-animation", data,
+                          headers[posn + 2] & 0xFF ) );
+                }
+            }
+            break;
+
+            case SMS_HK_Large_Animation:
+            case SMS_HK_Large_Picture:
+            {
+                // 32x32 monochrome animation or image - turn it into a WBMP.
+                if ( len >= 1 ) {
+                    QByteArray data( len + 3, 0 );
+                    data[0] = 0x00;
+                    data[1] = 0x00;
+                    data[2] = 0x20;
+                    data[3] = 0x20;
+                    for ( temp = 0; temp < (len - 1); ++temp ) {
+                        data[4 + temp] = (char)(~(headers[posn + 3 + temp]));
+                    }
+                    addPart( QSMSMessagePart
+                        ( "image/vnd.wap.wbmp", data,
+                          headers[posn + 2] & 0xFF ) );
+                }
+            }
+            break;
+
+            case SMS_HK_Small_Animation:
+            case SMS_HK_Small_Picture:
+            {
+                // 16x16 monochrome animation or image - turn it into a WBMP.
+                if ( len >= 1 ) {
+                    QByteArray data( len + 3, 0 );
+                    data[0] = 0x00;
+                    data[1] = 0x00;
+                    data[2] = 0x10;
+                    data[3] = 0x10;
+                    for ( temp = 0; temp < (len - 1); ++temp ) {
+                        data[4 + temp] = (char)(~(headers[posn + 3 + temp]));
+                    }
+                    addPart( QSMSMessagePart
+                        ( "image/vnd.wap.wbmp", data,
+                          headers[posn + 2] & 0xFF ) );
+                }
+            }
+            break;
+
+            case SMS_HK_Variable_Picture:
+            {
+                // Variable-sized monochrome image - turn it into a WBMP.
+                if ( len >= 3 ) {
+                    QByteArray data( len - 1, 0 );
+                    data[0] = 0x00;
+                    data[1] = 0x00;
+                    data[2] = headers[posn + 3];
+                    data[3] = headers[posn + 4];
+                    for ( temp = 2; temp < (len - 1); ++temp ) {
+                        data[2 + temp] = (char)(~(headers[posn + 3 + temp]));
+                    }
+                    addPart( QSMSMessagePart
+                        ( "image/vnd.wap.wbmp", data,
+                          headers[posn + 2] & 0xFF ) );
+                }
+            }
+            break;
+
+            case SMS_HK_Concat_8Bit:    break;
+            case SMS_HK_Concat_16Bit:   break;
+
+            case SMS_HK_AppPort_8Bit:
+            case SMS_HK_AppPort_16Bit:
+            {
+                QByteArray data( len, 0 );
+                memcpy( data.data(), headers.data() + posn + 2, len );
+                addPart( QSMSMessagePart
+                    ( "application/x-qtopia-wdp-ports", data ) );
+            }
+            break;
+
+            default:
+            {
+                // Add the unknown part as "application/x-qtopia-sms-N".
+                // Maybe qtmail will know what to do with it.
+                QByteArray data( len, 0 );
+                memcpy( data.data(), headers.data() + posn + 2, len );
+                addPart( QSMSMessagePart( "application/x-qtopia-sms-" +
+                                         QString::number( tag ), data ) );
+            }
+            break;
+        }
+        posn += 2 + len;
+    }
+}
+
+/*!
+    \internal
+    \fn void QSMSMessage::deserialize(Stream &stream)
+*/
+template <typename Stream> void QSMSMessage::deserialize(Stream &stream)
+{
+    dwrite()->readFromStream( stream );
+}
+
+/*!
+    \internal
+    \fn void QSMSMessage::serialize(Stream &stream) const
+*/
+template <typename Stream> void QSMSMessage::serialize(Stream &stream) const
+{
+    d->writeToStream( stream );
+}
+
+QPDUMessage::QPDUMessage()
+{
+    mPosn = 0;
+    mBits = 0;
+}
+
+QPDUMessage::QPDUMessage(const QByteArray &data)
+{
+    mBuffer = data;
+    mPosn = 0;
+    mBits = 0;
+}
+
+QPDUMessage::~QPDUMessage()
+{
+}
+
+QPDUMessage::QPDUMessage(const QPDUMessage &msg)
+{
+    mBuffer = msg.mBuffer;
+    mPosn = msg.mPosn;
+    mBits = msg.mBits;
+}
+
+void QPDUMessage::skipOctet()
+{
+    if ( mPosn < mBuffer.size() )
+        ++mPosn;
+}
+
+QByteArray QPDUMessage::getOctets( uint len )
+{
+    QByteArray result;
+    if ( ( mBuffer.size() - mPosn ) < (int)len ) {
+        result = mBuffer.mid( mPosn );
+        abort();
+    } else {
+        result = mBuffer.mid( mPosn, (int)len );
+        mPosn += len;
+    }
+    return result;
+}
+
+void QPDUMessage::setBit(int b, bool on)
+{
+    if ( on )
+        mBits |= (char)(Unit << b);
+    else
+        mBits &= (char)(~(Unit << b));
+}
+
+void QPDUMessage::setBits(int offset, int len, int val)
+{
+    uint mask = ((Unit << len) - 1) << offset;
+    mBits = (char)((mBits & ~mask) | ((val << offset) & mask));
+}
+
+void QPDUMessage::commitBits()
+{
+    mBuffer += mBits;
+    mBits = 0;
+}
+
+bool QPDUMessage::bit(int b)
+{
+    if ( needOctets(1) )
+        return (mBuffer[mPosn] & (Unit << b));
+    else
+        return 0;
+}
+
+unsigned char QPDUMessage::bits(int offset, int len)
+{
+    if ( needOctets(1) )
+        return (unsigned char)
+            ((mBuffer[mPosn] >> offset) & ((Unit << len) - 1));
+    else
+        return 0;
+}
+
+unsigned char QPDUMessage::getOctet()
+{
+    if ( needOctets(1) )
+        return (unsigned char)(mBuffer[mPosn++]);
+    else
+        return 0;
+}
+
+unsigned char QPDUMessage::peekOctet() const
+{
+    if ( needOctets(1) )
+        return (unsigned char)(mBuffer[mPosn]);
+    else
+        return 0;
+}
+
+// Collapse 8-bit-aligned GSM data to its 7-bit form.
+static QByteArray collapse7Bit( const QByteArray& in )
+{
+    QByteArray out;
+    int byte = 0;
+    int size = 0;
+    for ( int posn = 0; posn < in.length(); ++posn ) {
+        for ( int bit = 0; bit < 7; ++bit ) {
+            if ( ( in[posn] & (1 << bit) ) != 0 )
+                byte |= (1 << size);
+            ++size;
+            if ( size >= 8 ) {
+                out += (char)byte;
+                byte = 0;
+                size = 0;
+            }
+        }
+    }
+    if ( size != 0 ) {
+        out += (char)byte;
+    }
+    return out;
+}
+
+void QPDUMessage::setAddress(const QString &strin, bool SCAddress)
+{
+    SMSAddressType at;
+    int len, digit, octet;
+    int posn;
+    const int maxPhoneNumberLen = 15;
+    QString str( strin );
+    str.truncate( maxPhoneNumberLen );
+
+    // Determine the address type and length.
+    at = SMS_Address_Unknown;
+    len = 0;
+    for ( posn = 0; posn < str.length(); ++posn ) {
+        switch ( str[posn].unicode() ) {
+            case '+':
+                at = SMS_Address_International;
+                break;
+
+            case '0': case '1': case '2': case '3':
+            case '4': case '5': case '6': case '7':
+            case '8': case '9': case '*': case '#':
+            case 'A': case 'B': case 'C': case 'a':
+            case 'b': case 'c':
+                ++len;
+                break;
+
+            default:
+                // Probably an alpha-numeric address.
+                ++len;
+                at = SMS_Address_AlphaNumeric;
+                break;
+        }
+    }
+    if ( SCAddress )
+        len = (len + 1) / 2;
+
+    // Bail out early if the address is zero-length.
+    if ( !len ) {
+        appendOctet(0);
+        return;
+    }
+
+    // Handle alphanumeric address fields.
+    if ( at == SMS_Address_AlphaNumeric ) {
+        // Convert the address and calculate its encoded length.
+        QTextCodec *codec = QAtUtils::codec( "gsm-noloss" );
+        QByteArray bytes = collapse7Bit( codec->fromUnicode( strin ) );
+        len = bytes.size();
+
+        // Need an extra byte for SCAddress fields.
+        if ( SCAddress )
+            len++;
+
+        // Output the length of the encoded address.
+        appendOctet(len);
+
+        // Output the type of number information.
+        setBits(0, 4, SMS_NumberId_Unknown);
+        setBits(4, 3, at);
+        setBit(7, true);
+        commitBits();
+
+        // Output the encoded address and exit.
+        mBuffer += bytes;
+        return;
+    }
+
+    // SCAddress len = octets + type specifier
+    if ( SCAddress )
+        len++;
+
+    appendOctet(len);
+
+    setBits(0, 4, SMS_Phone);
+    setBits(4, 3, at);
+    setBit(7, true);
+    commitBits();
+
+    bool upper4 = false;
+    octet = 0;
+    for ( posn = 0; posn < str.length(); posn++ ) {
+        switch ( str[posn].unicode() ) {
+            case '0':           digit = 0; break;
+            case '1':           digit = 1; break;
+            case '2':           digit = 2; break;
+            case '3':           digit = 3; break;
+            case '4':           digit = 4; break;
+            case '5':           digit = 5; break;
+            case '6':           digit = 6; break;
+            case '7':           digit = 7; break;
+            case '8':           digit = 8; break;
+            case '9':           digit = 9; break;
+            case '*':           digit = 10; break;
+            case '#':           digit = 11; break;
+            case 'A': case 'a': digit = 12; break;
+            case 'B': case 'b': digit = 13; break;
+            case 'C': case 'c': digit = 14; break;
+            default:            digit = -1; break;
+        }
+        if ( digit != -1 ) {
+            if ( !upper4 ) {
+                octet = digit;
+            } else {
+                octet |= (digit << 4);
+                appendOctet( octet );
+            }
+            upper4 = !upper4;
+        }
+    }
+    if ( upper4 ) {
+        appendOctet( octet | 0xF0 );
+    }
+}
+
+// Expand the 7-bit GSM data to 8-bit-aligned characters.
+static QByteArray expand7Bit( const QByteArray& in )
+{
+    QByteArray out;
+    int byte = 0;
+    int size = 0;
+    for ( int posn = 0; posn < in.length(); ++posn ) {
+        for ( int bit = 0; bit < 8; ++bit ) {
+            if ( ( in[posn] & (1 << bit) ) != 0 )
+                byte |= (1 << size);
+            ++size;
+            if ( size >= 7 ) {
+                out += (char)byte;
+                byte = 0;
+                size = 0;
+            }
+        }
+    }
+    return out;
+}
+
+QString QPDUMessage::address(bool SCAddress)
+{
+    QString str = "";
+
+    // Get the address length and validate it.
+    if ( !needOctets(1) )
+        return str;
+    uint len = (((uint)(getOctet())) & 0xFF);
+    if ( !needOctets(len) ) {
+        abort();
+        return str;
+    }
+
+    if ( len ) {
+        SMSAddressType at = (SMSAddressType) bits(4, 3);
+
+        if ( at == SMS_Address_International )
+            str += "+";
+
+        skipOctet();
+        if ( !SCAddress )
+            len = len / 2 + (len % 2);
+        else
+            len--;
+
+        if ( at != SMS_Address_AlphaNumeric ) {
+            unsigned char c;
+            for (int i = 0; i < (int)len; i++) {
+                c = peekOctet() & 0x0F;
+                str += (char) ('0' + c);
+                c = (peekOctet() & 0xF0) >> 4;
+                if ( c != 0xf )
+                    str += (char) ('0' + c);
+                skipOctet();
+            }
+        } else {
+            // Recognize an alphanumeric address in the 7-bit GSM encoding.
+            QTextCodec *codec = QAtUtils::codec( "gsm" );
+            QByteArray bytes = expand7Bit( getOctets( len ) );
+            str += codec->toUnicode( bytes );
+        }
+    }
+
+    return str;
+}
+
+// Return the length of the service centre address.
+uint QPDUMessage::addressLength() const
+{
+    if( mPosn < mBuffer.size() )
+        return (((uint)peekOctet()) & 0xFF) + 1;
+    else
+        return 0;
+}
+
+void QPDUMessage::setTimeStamp(const QDateTime &dt)
+{
+    QDate date = dt.date();
+    int tArr[6];
+    tArr[0] = date.year();
+    tArr[1] = date.month();
+    tArr[2] = date.day();
+
+    QTime t = dt.time();
+    tArr[3] = t.hour();
+    tArr[4] = t.minute();
+    tArr[5] = t.second();
+
+    for ( int i = 0; i < 6; i++) {
+        appendOctet((unsigned char) ( (((tArr[i]/10)%10) & 0x0F) | (((tArr[i]%10) & 0x0F)<<4) ) );
+    }
+
+    appendOctet(0x04); //arbitrary random timezone
+}
+
+QDateTime QPDUMessage::timeStamp()
+{
+    QDateTime d;
+    unsigned char c, c4, date[7];
+
+    if ( !needOctets(7) ) {
+        abort();
+        return d;
+    }
+    for (int i = 0; i < 7; i++) {
+        c = (peekOctet() & 0x0F);
+        c4 = (peekOctet() & 0xF0) >> 4;
+        date[i] = c*10 + c4;
+        skipOctet();
+    }
+
+    if ( date[0] < 80 ) {
+        d.setDate( QDate(2000 + date[0], date[1], date[2]) );
+    } else {
+        d.setDate( QDate(1900 + date[0], date[1], date[2]) );
+    }
+    d.setTime( QTime(date[3], date[4], date[5]) );
+
+    return d;
+}
+
+// Get the length of a string when encoded in the GSM 7-bit alphabet.
+static uint getEncodedLength( const QString& txt, uint size )
+{
+    uint len = 0;
+    for ( int u = 0; u < (int)size; u++ ) {
+        if ( QGsmCodec::twoByteFromUnicode( txt[u].unicode() ) >= 256 )
+            len += 2;
+        else
+            ++len;
+    }
+    return len;
+}
+
+void QPDUMessage::setUserData(const QString &txt, QSMSDataCodingScheme scheme, QTextCodec *codec, const QByteArray& headers, bool implicitLength)
+{
+    uint len = txt.length();
+    uint u;
+    uint encodedLen;
+    uint headerLen = (uint)(headers.size());
+    if ( headerLen )
+        ++headerLen;
+
+    // Strip off everything except the alphabet bits.
+    scheme = (QSMSDataCodingScheme)(scheme & 0x0C);
+
+    if ( scheme == QSMS_DefaultAlphabet ) {
+
+        // Encode the text using the 7-bit GSM alphabet.
+        if ( len > 160 )
+            len = 160;
+        encodedLen = getEncodedLength( txt, len );
+        while ( encodedLen > 160 ) {
+            // Chop off some more characters until it is <= 160.
+            --len;
+            encodedLen = getEncodedLength( txt, len );
+        }
+        if (!implicitLength)
+            appendOctet( encodedLen + ( headerLen * 8 + 6 ) / 7 );
+        int bitCount = 0;
+        unsigned short c;
+        if ( headerLen > 0 ) {
+            // Output the header and align on a septet boundary.
+            bitCount = headerLen * 8;
+            if ((bitCount % 7) != 0)
+                bitCount = 7 - (bitCount % 7);
+            else
+                bitCount = 0;
+            appendOctet( headerLen - 1 );
+            for ( u = 0; u < headerLen - 1; u++ ) {
+                appendOctet( headers[u] );
+            }
+        }
+        for ( u = 0; u < len; u++ ) {
+            c = QGsmCodec::twoByteFromUnicode( txt[u].unicode() );
+            if ( c >= 256 ) {
+                // Encode a two-byte sequence.
+                for ( int i = 0; i < 7; i++ ) {
+                    if ( bitCount == 8 ) {
+                        bitCount = 0;
+                        commitBits();
+                    }
+                    setBit( bitCount++, (Unit << (i+8)) & c );
+                }
+            }
+            for ( int i = 0; i < 7; i++ ) {
+                if ( bitCount == 8 ) {
+                    bitCount = 0;
+                    commitBits();
+                }
+                setBit( bitCount++, (Unit << i) & c );
+            }
+        }
+        if ( bitCount != 0 ) {
+            commitBits();
+        }
+
+    } else if ( scheme == QSMS_8BitAlphabet ) {
+        // Encode the text using the codec's 8-bit alphabet.
+        if ( !codec )
+            codec = QAtUtils::codec( "iso-8859-1" );
+        QByteArray converted = codec->fromUnicode( txt );
+        len = converted.length();
+        if ( len > 140 )
+            len = 140;
+        if (!implicitLength)
+            appendOctet( len + headerLen );
+        if ( headerLen > 0 ) {
+            appendOctet( headerLen - 1 );
+            for ( u = 0; u < headerLen - 1; u++ ) {
+                appendOctet( headers[u] );
+            }
+        }
+        const char *s = (const char *)converted;
+        for ( u = 0; u < len; u++ ) {
+            appendOctet( (unsigned char)(s[u]) );
+        }
+
+    } else {
+
+        // Encode the text using the 16-bit UCS2 alphabet.
+        if ( len > 70 )
+            len = 70;
+        if (!implicitLength)
+            appendOctet( len * 2 + headerLen );
+        if ( headerLen > 0 ) {
+            appendOctet( headerLen - 1 );
+            for ( u = 0; u < headerLen - 1; u++ ) {
+                appendOctet( headers[u] );
+            }
+        }
+        for ( u = 0; u < len; u++ ) {
+            appendOctet( (unsigned char)(txt[u].unicode() >> 8) );
+            appendOctet( (unsigned char)(txt[u].unicode() & 0xFF) );
+        }
+
+    }
+}
+
+// Determine if the headers in an SMS frame indicate that it
+// is an application datagram destinated for a particular port.
+static bool isSMSDatagram( const QByteArray& headers )
+{
+    uint posn = 0;
+    uint tag, len;
+    while ( ( posn + 2 ) <= (uint)(headers.size()) ) {
+        tag = (unsigned char)(headers[posn]);
+        len = (unsigned char)(headers[posn + 1]);
+        if ( ( posn + len + 2 ) > (uint)(headers.size()) )
+            break;
+        if ( tag == (uint)SMS_HK_AppPort_8Bit ||
+             tag == (uint)SMS_HK_AppPort_16Bit ) {
+            return true;
+        }
+        posn += len + 2;
+    }
+    return false;
+}
+
+QString QPDUMessage::userData(QSMSDataCodingScheme scheme, QTextCodec *codec, QByteArray *& headers, bool hasHeaders, bool implicitLength)
+{
+    QString str = "";
+    uint len, headerLen;
+    uint u;
+    uint ch;
+
+    // Reset the header return.
+    headers = 0;
+
+    // Get the length of the user data payload.
+    if ( implicitLength ) {
+        len = mBuffer.size() - mPosn;
+    } else {
+        if ( !needOctets(1) )
+            return str;
+        len = (uint)getOctet();
+    }
+
+    // Strip off everything except the alphabet bits.
+    scheme = (QSMSDataCodingScheme)(scheme & 0x0C);
+
+    if ( scheme == QSMS_DefaultAlphabet ) {
+
+        // Process a sequence in the default 7-bit GSM character set.
+        int bitCount = 0;
+        int startBit = 0;
+        ch = 0;
+        if ( implicitLength )
+            len = len * 8 / 7;      // Convert 8-bit bytes to 7-bit characters.
+        if ( hasHeaders ) {
+            u = ( len * 7 + 7 ) / 8;
+            if ( !u || !needOctets(u) )
+                return str;
+            headerLen = getOctet();
+            if ( headerLen >= u )
+                return str;
+            headers = new QByteArray( getOctets( headerLen ) );
+            if ( isSMSDatagram( *headers ) )
+                return str;
+            u = ((headerLen + 1) * 8 + 6) / 7;
+            len -= u;
+            startBit = (headerLen + 1) * 8;
+            if ((startBit % 7) != 0)
+                startBit = 7 - (startBit % 7);
+            else
+                startBit = 0;
+        }
+        bool prefixed = false;
+        while ( len > 0 ) {
+            if ( !needOctets(1) )
+                return str;
+            for ( int i = startBit; len > 0 && i < 8; i++ ) {
+                // test the bit and shift it down again, as i doesn't mark
+                // where we are in the current char, but bitCount does
+                ch |= ( ( peekOctet() & (Unit << i) ) >> i) << bitCount;
+                bitCount++;
+                if ( bitCount == 7 ) {
+                    bitCount = 0;
+                    if ( ch == 0x1B ) {     // Start of a two-byte encoding.
+                        prefixed = true;
+                    } else if ( prefixed ) {
+                        str += QChar
+                            ( QGsmCodec::twoByteToUnicode( 0x1B00 | ch ) );
+                        prefixed = false;
+                    } else {
+                        str += QGsmCodec::singleToUnicode( (unsigned char)ch );
+                    }
+                    ch = 0;
+                    --len;
+                }
+            }
+            startBit = 0;
+            skipOctet();
+        }
+
+    } else if ( scheme == QSMS_8BitAlphabet && codec ) {
+
+        // Process an 8-bit sequence using the supplied codec.
+        if ( !needOctets(len) ) {
+            abort();
+            return str;
+        }
+        if ( hasHeaders ) {
+            if ( !len || len < (uint)( (peekOctet() & 0xFF) + 1 ) ) {
+                abort();
+                return str;
+            }
+            headerLen = getOctet();
+            headers = new QByteArray( getOctets( headerLen ) );
+            if ( isSMSDatagram( *headers ) )
+                return str;
+            len -= headerLen + 1;
+        }
+        str = codec->toUnicode( getOctets( len ) );
+
+    } else if ( scheme == QSMS_UCS2Alphabet ) {
+
+        // Process a UCS2 sequence.
+        if ( !needOctets(len) ) {
+            abort();
+            return str;
+        }
+        if ( hasHeaders ) {
+            if ( !len || len < (uint)( (peekOctet() & 0xFF) + 1 ) ) {
+                abort();
+                return str;
+            }
+            headerLen = getOctet();
+            headers = new QByteArray( getOctets( headerLen ) );
+            len -= headerLen + 1;
+        }
+        len /= 2;
+        for ( u = 0; u < len; ++u ) {
+            ch = (((uint)(getOctet() & 0xFF)) << 8);
+            ch |= ((uint)(getOctet() & 0xFF));
+            str += (QChar)ch;
+        }
+
+    } else {
+
+        // Assume 8-bit for any other coding scheme value.
+
+        // Process an 8-bit sequence using the default Latin1 codec.
+        if ( len > (uint)(mBuffer.size() - mPosn) ) {
+            // The length field is invalid - use the actual size.
+            len = mBuffer.size() - mPosn;
+        }
+        if ( hasHeaders ) {
+            if ( !len || len < (uint)( (peekOctet() & 0xFF) + 1 ) ) {
+                abort();
+                return str;
+            }
+            headerLen = getOctet();
+            headers = new QByteArray( getOctets( headerLen ) );
+            if ( isSMSDatagram( *headers ) )
+                return str;
+            len -= headerLen + 1;
+        }
+        for ( u = 0; u < len; ++u ) {
+            str += (QChar)(getOctet() & 0xFF);
+        }
+
+    }
+
+    return str;
+}
+
+/*  Note that the meaning of messageType is also dependant on
+    the direction of the message (orig. location) */
+SMSMessageType QPDUMessage::messageType()
+{
+    if ( mBuffer.size() >= 1 &&
+         mBuffer.size() >= ((mBuffer[0] & 0xFF) + 2) ) {
+
+        const char *ptr = mBuffer.constData();
+        ptr += (*ptr & 0xFF) + 1;
+        unsigned char c = *ptr & 3;
+        return (SMSMessageType) c;
+
+    }
+    return (SMSMessageType)0;
+}
+
+QSMSSubmitMessage::QSMSSubmitMessage(const QSMSMessage &m, bool isDeliver)
+    : QPDUMessage()
+{
+    // Clear the pdu before we start.
+    mBuffer = QByteArray();
+    mPosn = 0;
+    mBits = 0;
+
+    setAddress( m.serviceCenter(), true );
+
+    // If there is port and application data information, then
+    // create header parts for them.  This is for sending datagram
+    // based messages.
+    QByteArray headers = m.headers();
+    QSMSDataCodingScheme scheme = m.bestScheme();
+    int part = m.findPart( "application/x-qtopia-wdp-ports" );
+    if ( part != -1 ) {
+        QByteArray portData = m.parts()[(uint)part].data();
+        uint size = headers.size();
+        headers.resize(size + portData.size() + 2);
+        if ( portData.size() == 4 ) {
+            headers[size++] = (char)SMS_HK_AppPort_16Bit;
+        } else {
+            headers[size++] = (char)SMS_HK_AppPort_8Bit;
+        }
+        headers[size++] = (char)(portData.size());
+        memcpy(headers.data() + size, portData.data(), portData.size());
+        int dataScheme = m.dataCodingScheme(); // User-supplied override.
+        if ( dataScheme == -1 )
+            dataScheme = 0xF5;      // Special value for datagrams.
+        scheme = (QSMSDataCodingScheme)dataScheme;
+    } else if ( m.messageClass() != -1 ) {
+        scheme = (QSMSDataCodingScheme)
+                    (scheme | QSMS_MessageClass | m.messageClass());
+        int dataScheme = m.dataCodingScheme(); // User-supplied override.
+        if ( dataScheme != -1 )
+            scheme = (QSMSDataCodingScheme)dataScheme;
+    } else {
+        int dataScheme = m.dataCodingScheme(); // User-supplied override.
+        if ( dataScheme != -1 )
+            scheme = (QSMSDataCodingScheme)dataScheme;
+    }
+
+    if ( !isDeliver )
+        setBits(0, 2, SMS_Submit);
+    else
+        setBits(0, 2, SMS_Deliver);
+
+    setBit(2, false);                   // TP-Reject-Duplicates
+    if ( !isDeliver && m.validityPeriod() == (uint)(-1) )
+        setBits(3, 2, SMS_VF_NoPresent);
+    else
+        setBits(3, 2, SMS_VF_Relative);
+    setBit(5, m.statusReportRequested());// TP-Status-Report-Requested;
+    setBit(6, headers.size() != 0);     // TP-User-Data Header
+    setBit(7, m.replyRequest());        // TP-Reply-Path
+
+    commitBits();       // first octet done
+
+    //second octet TP-MR (Message reference
+    if( !isDeliver )
+        appendOctet(0);
+
+    if ( !isDeliver ) {
+        //third octet TP-DA (Destination Address)
+        //len must be done later
+        setAddress( m.recipient(), false );
+    } else {
+        setAddress( m.sender(), false);
+    }
+
+
+    //nth octet, TP-PID (protocol identifier)
+    if ( !isDeliver )
+        appendOctet(m.protocol());
+    else
+        appendOctet(1); //arbitrary protocol for deliver
+
+    // TP-DCS ( Data coding scheme )
+    appendOctet(scheme);
+
+    if ( !isDeliver ) {
+        // TP-VP ( Validity Period )
+        if ( m.validityPeriod() != (uint)(-1) )
+            appendOctet(m.gsmValidityPeriod());
+    }  else {
+        setTimeStamp(m.timestamp());
+    }
+
+    // Set the user data field.
+    if ( part == -1 ) {
+        setUserData(m.text(), scheme, m.textCodec(), headers);
+    } else {
+        // The applicationData() is the text to be sent in the datagram.
+        QByteArray appData = m.applicationData();
+        uint len = appData.size();
+        if ( ( len + headers.size() + 1 ) > 140 )
+            len = 140 - headers.size() - 1;
+        appendOctet( len + headers.size() + 1 );
+        appendOctet( headers.size() );
+        uint u;
+        for ( u = 0; u < (uint)headers.size(); u++ ) {
+            appendOctet( headers[u] );
+        }
+        for ( u = 0; u < len; u++ ) {
+            appendOctet( appData[u] );
+        }
+    }
+}
+
+QSMSDeliverMessage::QSMSDeliverMessage(const QByteArray &pdu)
+    : QPDUMessage(pdu)
+{
+}
+
+// Unpack a message that has a "//SCKL" header in its text body.
+// This is a standard to interoperate with networks and phones
+// that do not support user data headers properly.
+static void unpackSckl( QSMSMessage& m, const QString& text )
+{
+    // Split into header and body, separated by a space.
+    int index = text.indexOf( QChar(' ') );
+    if ( index == -1 ) {
+        m.addPart( QSMSMessagePart( text ) );
+        return;
+    }
+    QString head = text.mid( 6, index - 6 );
+    QString body = text.mid( index + 1 );
+
+    // Convert the header from hex into raw binary and then
+    // copy its details into the real message header fields.
+    QByteArray header = QAtUtils::fromHex( head );
+    int len;
+    if ( header.size() < 4 ) {
+        len = header.size();
+    } else {
+        len = 4;
+    }
+    QByteArray ports( len, '\0' );
+    memcpy( ports.data(), header.data(), len );
+    m.addPart( QSMSMessagePart( "application/x-qtopia-wdp-ports", ports ) );
+    if ( header.size() > 4 ) {
+        QByteArray fragments( header.size() - 4 + 2, '\0' );
+        fragments[0] = (char)( SMS_HK_Concat_8Bit );
+        fragments[1] = (char)( header.size() - 4 );
+        memcpy( fragments.data() + 2, header.data() + 4, header.size() - 4 );
+        m.setHeaders( fragments );
+    }
+
+    // Is the body text or binary?
+    int port = m.destinationPort();
+    if ( port == 226 || port == 9204 ||     // vCard port numbers.
+         port == 228 || port == 9205 ) {    // vCalendar port numbers.
+        m.setApplicationData( body.toLatin1() );
+    } else {
+        m.setApplicationData( QAtUtils::fromHex( body ) );
+    }
+}
+
+QSMSMessage QSMSDeliverMessage::unpack(QTextCodec *codec)
+{
+    QSMSMessage m;
+    bool moreMessages;
+    bool statusReport;
+    bool userDataHeader;
+    bool replyPath;
+    bool rejectDuplicates;
+    unsigned char protocol;
+    unsigned char scheme;
+    uint msgType;
+    uint validityFormat;
+
+    // Start from the beginning of the PDU.
+    reset();
+
+    // Extract the service center address.
+    m.setServiceCenter( address(true) );
+
+    // Pull apart the message header.  We handle both deliver and
+    // submit messages, because we may have pulled a submit out
+    // of the phone's outgoing SMS queue.
+    if ( !needOctets(1) )
+        return m;
+    msgType = bits(0, 2);
+    if ( msgType == SMS_Deliver ) {
+        moreMessages = bit(2);
+        // Bits 3 and 4 are unused for deliver messages.
+        statusReport = bit(5);
+        userDataHeader = bit(6);
+        replyPath = bit(7);
+        rejectDuplicates = false;
+        validityFormat = SMS_VF_NoPresent;
+    } else if ( msgType == SMS_Submit ) {
+        moreMessages = false;
+        rejectDuplicates = bit(2);
+        validityFormat = bits(3, 2);
+        statusReport = bit(5);
+        userDataHeader = bit(6);
+        replyPath = bit(7);
+    } else {
+        // Probably a delivery report, which we don't process.
+        return m;
+    }
+    skipOctet();
+
+    // Remember the status and reply bits.
+    m.setStatusReportRequested(statusReport);
+    m.setReplyRequest(replyPath);
+
+    // Skip the message reference (submit messages only).
+    if ( msgType == SMS_Submit ) {
+        if ( !needOctets(1) )
+            return m;
+        skipOctet();
+    }
+
+    // Get the address of the sender (delivery) or recipient (submit).
+    if ( msgType == SMS_Deliver ) {
+        m.setSender( address(false) );
+    } else {
+        m.setRecipient( address(false) );
+    }
+
+    // Get the protocol identifier and data coding scheme.
+    if ( !needOctets(2) )
+        return m;
+    protocol = getOctet();
+    scheme = getOctet();
+    m.setProtocol( protocol );
+    m.setDataCodingScheme( scheme );
+    if ( ( scheme & QSMS_MessageClass ) != 0 )
+        m.setMessageClass( scheme & 0x03 );
+    else
+        m.setMessageClass( -1 );
+
+    // Get the timestamp (deliver) or validity period (submit) information.
+    if ( msgType == SMS_Deliver ) {
+        m.setTimestamp( timeStamp() );
+    } else {
+        if ( validityFormat == SMS_VF_Relative ) {
+            if ( !needOctets(1) )
+                return m;
+            m.setGsmValidityPeriod( bits(0, 8) );
+            skipOctet();
+        } else if (validityFormat == SMS_VF_Absolute ) {
+            m.setTimestamp( timeStamp() );
+        } else if (validityFormat == SMS_VF_Enhanced ) {
+            // Not supported yet - skip the octets.
+            if ( !needOctets(7) )
+                return m;
+            mPosn += 7;
+        } else {
+            m.setValidityPeriod( (uint)(-1) );
+        }
+    }
+
+    // Read the user data field.
+    QByteArray *headers = 0;
+    QString text;
+    text = userData( (QSMSDataCodingScheme)scheme, codec,
+                     headers, userDataHeader, false );
+    if ( !headers && text.startsWith( "//SCKL" ) ) {
+        unpackSckl( m, text );
+        return m;
+    }
+    if ( headers ) {
+        m.setHeaders( *headers );
+        delete headers;
+        m.unpackHeaderParts();
+        if ( isSMSDatagram( m.d->mHeaders ) && mPosn <= mBuffer.size() ) {
+            // The rest of the PDU is assumed to be the application payload.
+            QByteArray array = mBuffer.mid( mPosn );
+            m.addPart( QSMSMessagePart( "application/x-qtopia-wdp", array ) );
+        }
+    }
+    if ( text.length() > 0 ) {
+        m.addPart( QSMSMessagePart( text ) );
+    }
+
+    // Return the completed message to the caller.
+    return m;
+}
+
+
+QCBSDeliverMessage::QCBSDeliverMessage()
+    : QPDUMessage()
+{
+    // Nothing to do here.
+}
+
+
+QCBSDeliverMessage::QCBSDeliverMessage(const QByteArray &pdu)
+    : QPDUMessage(pdu)
+{
+    // Nothing to do here.
+}
+
+
+QCBSMessage QCBSDeliverMessage::unpack(QTextCodec *codec)
+{
+    QCBSMessage m;
+    unsigned char scheme;
+    uint len;
+
+    // Start from the beginning of the PDU.
+    reset();
+
+    // Extract the header fields.
+    if ( !needOctets(6) )
+        return m;
+
+    const char *mOffset = mBuffer.constData() + mPosn;
+    m.setMessageCode( ((mOffset[0] & 0xFC) << 2) | (mOffset[1] & 0x0F) );
+    m.setScope( (QCBSMessage::GeographicalScope)(mOffset[0] & 0x03) );
+    m.setUpdateNumber( (mOffset[1] >> 4) & 0x0F );
+    m.setChannel( ((mOffset[2] & 0xFF) << 8) | (mOffset[3] & 0xFF) );
+    scheme = (unsigned char)((mOffset[4] >> 4) & 0x0F);
+    m.setLanguage( (QCBSMessage::Language)(mOffset[4] & 0x0F) );
+    m.setNumPages( (uint)((mOffset[5] >> 4) & 0x0F) );
+    m.setPage( (uint)(mOffset[5] & 0x0F) );
+    mPosn += 6;
+
+    // Read the user data field and strip CR's, LF's, and NUL's from the end.
+    QByteArray *headers = 0;
+    QString text = userData
+        ( (QSMSDataCodingScheme)scheme, codec, headers, false, true );
+    len = text.length();
+    while ( len > 0 && ( text[len - 1] == '\r' || text[len - 1] == '\n' ||
+                         text[len - 1] == '\0' ) ) {
+        --len;
+    }
+    m.setText( text.left( len ) );
+
+    // Return the completed message to the caller.
+    return m;
+}
+
+void QCBSDeliverMessage::pack(const QCBSMessage &m, QSMSDataCodingScheme scheme)
+{
+    // Clear the pdu before we start.
+    mBuffer = QByteArray();
+    mPosn = 0;
+    mBits = 0;
+
+    scheme = QSMS_8BitAlphabet; // Only 8-bit works at present.
+    QByteArray data;
+    mBuffer.append( (char)( ((m.messageCode() & 0x000003F0)>>2) | (m.scope() & 0x03)) );
+    mBuffer.append( (char)((m.messageCode() & 0x0000000F) | (m.updateNumber() & 0x0000000F)<<4) );
+    mBuffer.append( (char)((m.channel() & 0x0000FF00) >> 8) );
+    mBuffer.append( (char)(m.channel() & 0x000000FF) );
+    mBuffer.append( (char)( ((scheme & 0x0F)<<4) | (m.language() & 0x0F)) );
+    mBuffer.append( (char)( ((m.numPages() & 0x0F)<<4) | (m.page() & 0x0F)) );
+
+    QTextCodec *codec = QAtUtils::codec( "gsm" );
+    QByteArray header;
+    setUserData(m.text(), scheme, codec, header,true);
+    int numPad = 88 - (m.text().length()  + data.size());
+
+    for ( int i=0; i<numPad; i++ )
+        appendOctet(0x0D);
+}
+
+Q_IMPLEMENT_USER_METATYPE(QSMSMessage)
+Q_IMPLEMENT_USER_METATYPE(QSMSMessagePart)

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef SMS_MESSAGE_H
+#define SMS_MESSAGE_H
+
+#include <qstring.h>
+#include <qdatetime.h>
+#include <qdatastream.h>
+#include <qlist.h>
+#include <quuid.h>
+#include <qtopiaipcadaptor.h>
+#include <qtopiaipcmarshal.h>
+
+class QSMSMessagePartPrivate;
+class QSMSMessagePrivate;
+class QTextCodec;
+
+
+class QTOPIAPHONE_EXPORT QSMSMessagePart
+{
+public:
+    QSMSMessagePart();
+    explicit QSMSMessagePart( const QString& text );
+    QSMSMessagePart( const QString& mimeType, const QByteArray& data );
+    QSMSMessagePart( const QString& mimeType, const QByteArray& data, uint position );
+    QSMSMessagePart( const QSMSMessagePart& part );
+    ~QSMSMessagePart();
+
+    QSMSMessagePart& operator=( const QSMSMessagePart& part );
+
+    bool isText() const;
+    QString text() const;
+    QString mimeType() const;
+    const QByteArray& data() const;
+    uint position() const;
+
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+private:
+    QSMSMessagePartPrivate *d;
+};
+
+Q_DECLARE_USER_METATYPE(QSMSMessagePart)
+
+enum QSMSDataCodingScheme {
+    QSMS_Compressed      = 0x0020,
+    QSMS_MessageClass    = 0x0010,
+    QSMS_DefaultAlphabet = 0x0000,
+    QSMS_8BitAlphabet    = 0x0004,
+    QSMS_UCS2Alphabet    = 0x0008,
+    QSMS_ReservedAlphabet= 0x000C
+};
+
+class QTOPIAPHONE_EXPORT QSMSMessage
+{
+    friend class QSMSSubmitMessage;
+    friend class QSMSDeliverMessage;
+public:
+    QSMSMessage();
+    QSMSMessage(const QSMSMessage &);
+    ~QSMSMessage();
+
+    QSMSMessage& operator=(const QSMSMessage &);
+
+    void setText(const QString &);
+    QString text() const;
+
+    void setTextCodec(QTextCodec *codec);
+    QTextCodec *textCodec() const;
+
+    void setForceGsm(bool force);
+    bool forceGsm() const;
+
+    void setBestScheme(QSMSDataCodingScheme);
+    QSMSDataCodingScheme bestScheme() const;
+
+    void setRecipient(const QString &);
+    QString recipient() const;
+
+    void setSender(const QString &);
+    QString sender() const;
+
+    void setServiceCenter(const QString &);
+    QString serviceCenter() const;
+
+    void setReplyRequest(bool on );
+    bool replyRequest() const;
+
+    void setStatusReportRequested(bool on );
+    bool statusReportRequested() const;
+
+    void setValidityPeriod(uint minutes);
+    uint validityPeriod() const;
+
+    void setGsmValidityPeriod(uint value);
+    uint gsmValidityPeriod() const;
+
+    void setTimestamp(const QDateTime &);
+    QDateTime timestamp() const;
+
+    void setHeaders(const QByteArray& value);
+    const QByteArray& headers() const;
+
+    void clearParts();
+    void addPart( const QSMSMessagePart& part );
+    void addParts( const QList<QSMSMessagePart>& parts );
+    QList<QSMSMessagePart> parts() const;
+
+    enum MessageType {
+        Normal, CellBroadCast, StatusReport
+    };
+
+    MessageType messageType() const;
+
+    void computeSize( uint& numMessages, uint& spaceLeftInLast ) const;
+
+    int destinationPort() const;
+    void setDestinationPort(int value);
+
+    int sourcePort() const;
+    void setSourcePort(int value);
+
+    QByteArray applicationData() const;
+    void setApplicationData(const QByteArray& value);
+
+    void setDataCodingScheme(int);
+    int dataCodingScheme() const;
+
+    void setMessageClass(int);
+    int messageClass() const;
+
+    void setProtocol(int);
+    int protocol() const;
+
+    bool shouldSplit() const;
+
+    QList<QSMSMessage> split() const;
+
+    QByteArray toPdu() const;
+    static QSMSMessage fromPdu( const QByteArray& pdu );
+    static int pduAddressLength( const QByteArray& pdu );
+
+    template <typename Stream> void serialize(Stream &stream) const;
+    template <typename Stream> void deserialize(Stream &stream);
+
+protected:
+    void setMessageType(MessageType);
+
+private:
+    mutable QSMSMessagePrivate *d;
+
+    QSMSMessagePrivate *dwrite();
+
+    int findPart( const QString& mimeType ) const;
+    void removeParts( const QString& mimeType );
+    void setFragmentHeader( uint refNum, uint part, uint numParts,
+                            QSMSDataCodingScheme scheme );
+    void unpackHeaderParts();
+};
+
+Q_DECLARE_USER_METATYPE(QSMSMessage)
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage_p.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage_p.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessage_p.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef SMS_MESSAGE_P_H
+#define SMS_MESSAGE_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qtopia API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qsmsmessage.h>
+#include <qcbsmessage.h>
+
+// Values are their bit reprensentation (defined in GSM-03.40 Section 9)
+// bits 6 5 4 ( shl 4 )
+enum SMSAddressType {
+    SMS_Address_Unknown         = 0,
+    SMS_Address_International   = 1,
+    SMS_Address_National        = 2,
+    SMS_Address_NetworkSpecific = 3,
+    SMS_Address_SubscriberNmb   = 4,
+    SMS_Address_AlphaNumeric    = 5,
+    SMS_Address_Abbreviated     = 6,
+    SMS_Address_Reserved        = 7
+};
+
+// Values are their bit reprensentation (defined in GSM-03.40 Section 9)
+// bits 3 2 1 0 ( shl 0 )
+enum SMSNumbering {
+    SMS_NumberId_Unknown            = 0,
+    SMS_Phone               = 1
+    // .. 6 more defined though.
+};
+
+// TP-MTI (2 bits)
+enum SMSMessageType {
+    SMS_Deliver             = 0,
+    SMS_DeliverReport       = 0,
+    SMS_StatusReport        = 2,
+    SMS_Command             = 2,
+    SMS_Submit              = 1,
+    SMS_SubmitReport        = 1,
+    SMS_Reserved            = 3
+};
+
+// TP_VPF (2 bits);
+enum SMSValidityFormat {
+    SMS_VF_NoPresent        = 0,
+    SMS_VF_Relative         = 2,
+    SMS_VF_Enhanced         = 1,
+    SMS_VF_Absolute         = 3
+};
+
+// User data header kinds from GSM 03.40 and GSM 23.040.
+enum SMSHeaderKind {
+    SMS_HK_Concat_8Bit                  = 0x00,
+    SMS_HK_Special_Msg_Indic            = 0x01,
+    SMS_HK_AppPort_8Bit                 = 0x04,
+    SMS_HK_AppPort_16Bit                = 0x05,
+    SMS_HK_Control_Parameters           = 0x06,
+    SMS_HK_UDH_Source_Indic             = 0x07,
+    SMS_HK_Concat_16Bit                 = 0x08,
+    SMS_HK_WCMP                         = 0x09,
+    SMS_HK_Text_Formatting              = 0x0A,
+    SMS_HK_Predefined_Sound             = 0x0B,
+    SMS_HK_User_Defined_Sound           = 0x0C,
+    SMS_HK_Predefined_Animation         = 0x0D,
+    SMS_HK_Large_Animation              = 0x0E,
+    SMS_HK_Small_Animation              = 0x0F,
+    SMS_HK_Large_Picture                = 0x10,
+    SMS_HK_Small_Picture                = 0x11,
+    SMS_HK_Variable_Picture             = 0x12,
+    SMS_HK_User_Prompt_Indic            = 0x13,
+    SMS_HK_Extended_Object              = 0x14,
+    SMS_HK_Reused_Extended_Object       = 0x15,
+    SMS_HK_Compression_Control          = 0x16,
+    SMS_HK_Object_Dist_Indic            = 0x17,
+    SMS_HK_Standard_WVG_Object          = 0x18,
+    SMS_HK_Char_Size_WVG_Object         = 0x19,
+    SMS_HK_Data_Request_Command         = 0x1A,
+    SMS_HK_RFC_822_Header               = 0x20,
+    SMS_HK_Hyperlink_Format_Element     = 0x21,
+    SMS_HK_Reply_Address_Element        = 0x22
+};
+
+class QPDUMessage
+{
+public:
+    QPDUMessage();
+    explicit QPDUMessage(const QByteArray &);
+    ~QPDUMessage();
+    QPDUMessage(const QPDUMessage &);
+
+    QByteArray toByteArray() const { return mBuffer; }
+
+    void setBit(int b, bool on);
+    void setBits(int offset, int len, int val);
+    void commitBits();
+    void appendOctet(uchar c) { mBuffer += (char)c; }
+
+    bool bit(int b);
+    unsigned char bits(int offset, int len);
+    unsigned char getOctet();
+    unsigned char peekOctet() const;
+    void skipOctet();
+    void abort() { mPosn = mBuffer.size(); }
+
+    QByteArray getOctets( uint len );
+
+    void setAddress(const QString &, bool SCAddress);
+    QString address(bool SCAddress);
+
+    uint addressLength() const;
+
+    void setTimeStamp(const QDateTime &);
+    QDateTime timeStamp();
+
+    void setUserData(const QString &txt, QSMSDataCodingScheme scheme, QTextCodec *codec, const QByteArray& headers, bool implicitLength = false);
+    QString userData(QSMSDataCodingScheme scheme, QTextCodec *codec, QByteArray *& headers, bool hasHeaders, bool implicitLength = false);
+
+    SMSMessageType messageType();
+
+    void reset() { mPosn = 0; }
+
+    bool needOctets( uint num ) const
+        { return ((uint)(mBuffer.size() - mPosn) >= num); }
+
+protected:
+    QByteArray mBuffer;
+    int mPosn;
+    char mBits;
+};
+
+
+class QSMSSubmitMessage: public QPDUMessage
+{
+public:
+    explicit QSMSSubmitMessage(const QSMSMessage &m, bool isDeliver=false);
+};
+
+class QSMSDeliverMessage: public QPDUMessage
+{
+public:
+    explicit QSMSDeliverMessage(const QByteArray &pdu);
+
+    QSMSMessage unpack(QTextCodec *codec=0);
+};
+
+class QCBSDeliverMessage: public QPDUMessage
+{
+public:
+    QCBSDeliverMessage();
+    explicit QCBSDeliverMessage(const QByteArray &pdu);
+
+    QCBSMessage unpack(QTextCodec *codec=0);
+    void pack(const QCBSMessage &m, QSMSDataCodingScheme scheme);
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessagelist.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessagelist.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessagelist.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "qsmsmessagelist.h"
+#include <qdebug.h>
+
+QSMSMessageList::QSMSMessageList()
+{
+SMSList.clear();
+statusList.clear();
+deletedFlagList.clear();
+}
+
+QSMSMessageList::~QSMSMessageList()
+{
+}
+
+void QSMSMessageList::appendSMS( const QByteArray &m )
+{
+    SMSList.append(m);
+    statusList.append(QSMSMessageList::REC_UNREAD);
+    deletedFlagList.append(false);
+}
+
+
+void QSMSMessageList::deleteSMS( int i )
+{
+    deletedFlagList[i] = true;
+}
+
+int QSMSMessageList::count() const
+{
+    return SMSList.count();
+}
+
+QSMSMessageList::SMSStatus QSMSMessageList::getStatus( int i ) const
+{
+   return statusList[i];
+}
+
+void QSMSMessageList::setStatus( const SMSStatus &s, int i )
+{
+    statusList[i] = s;
+}
+
+
+bool QSMSMessageList::getDeletedFlag( int i ) const
+{
+    return deletedFlagList[i];
+}
+
+void QSMSMessageList::setDeletedFlag( bool b, int i )
+{
+    deletedFlagList[i] = b;
+}
+
+QByteArray & QSMSMessageList::readSMS( int i )
+{
+   if ( statusList[i] == QSMSMessageList::REC_UNREAD ) {
+        statusList[i] = QSMSMessageList::REC_READ;
+  }
+
+   return SMSList[i];
+}
+
+QByteArray & QSMSMessageList::operator[]( int i )
+{
+    return SMSList[i];
+
+}
+
+
+

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessagelist.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessagelist.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qsmsmessagelist.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QSMSMESSAGELIST_H
+#define QSMSMESSAGELIST_H
+
+#include <QList>
+#include <QByteArray>
+
+class QSMSMessageList
+{
+public:
+    enum SMSStatus{
+        REC_UNREAD  =0,
+        REC_READ    =1,
+        STO_UNSENT  =2,
+        STO_SENT    =3
+    };
+
+    QSMSMessageList();
+    ~QSMSMessageList();
+
+    void appendSMS( const QByteArray & );
+    void deleteSMS( int );  //note SMS's are not actually physically deleted. A flag is set
+
+    int count() const; //returns the total number, even those that are 'deleted'
+
+    SMSStatus getStatus( int ) const;
+    void  setStatus( const SMSStatus &, int );
+
+    bool getDeletedFlag( int ) const;
+    void setDeletedFlag( bool, int );
+
+    QByteArray & readSMS( int );//returns and sets the status of an SMS
+    QByteArray & operator[]( int );//only returns an SMS, does not set status
+
+private:
+    QList<QByteArray> SMSList;
+    QList<SMSStatus> statusList;
+    QList<bool> deletedFlagList;
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qtimestring.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qtimestring.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qtimestring.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef _TIMESTRING_H_
+#define _TIMESTRING_H_
+
+#include <QDateTime>
+#include <QString>
+
+#include <qtopiaglobal.h>
+
+class QTOPIA_EXPORT QTimeString
+{
+public:
+    enum Length { Short, Medium, Long };
+    static QString nameOfWeekDay( int day, Length len = Medium);
+    static QString nameOfMonth( int month, Length len = Medium);
+
+    static QString numberDateString( const QDate &d, Length len = Medium );
+
+    static QString currentFormat();
+    static QStringList formatOptions();
+
+    static QString localH( int hour );
+    static QString localHM( const QTime &t, Length len = Medium );
+    static QString localHMS( const QTime &t, Length len = Medium );
+    static QString localHMDayOfWeek( const QDateTime &dt, Length len = Medium);
+    static QString localHMSDayOfWeek( const QDateTime &dt, Length len = Medium);
+    static QString localMD( const QDate &d, Length len = Medium );
+    static QString localYMD( const QDate &d, Length len = Medium );
+    static QString localYMDHMS( const QDateTime &d, Length len = Medium );
+    static QString localDayOfWeek( const QDate &d, Length len = Medium );
+
+    static bool currentAMPM();
+private:
+    friend class QtopiaApplication;
+    static void updateFormats();
+
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaglobal.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaglobal.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaglobal.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QPE_GLOBAL_H
+#define QPE_GLOBAL_H
+
+#include <qglobal.h>
+#include <qplugin.h>
+
+// The _EXPORT macros...
+
+#if defined(QT_VISIBILITY_AVAILABLE)
+#   define QTOPIA_VISIBILITY __attribute__((visibility("default")))
+#else
+#   define QTOPIA_VISIBILITY
+#endif
+
+
+#ifndef QTOPIABASE_EXPORT
+#   define QTOPIABASE_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIA_EXPORT
+#   define QTOPIA_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAPIM_EXPORT
+#   define QTOPIAPIM_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAMAIL_EXPORT
+#   define QTOPIAMAIL_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIA_PLUGIN_EXPORT
+#   define QTOPIA_PLUGIN_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIACOMM_EXPORT
+#   define QTOPIACOMM_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAPHONE_EXPORT
+#   define QTOPIAPHONE_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAPHONEMODEM_EXPORT
+#   define QTOPIAPHONEMODEM_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIASECURITY_EXPORT
+#   define QTOPIASECURITY_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAHW_EXPORT
+#   define QTOPIAHW_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAAUDIO_EXPORT
+#   define QTOPIAAUDIO_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAMEDIA_EXPORT
+#   define QTOPIAMEDIA_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAWAP_EXPORT
+#   define QTOPIAWAP_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIASMIL_EXPORT
+#   define QTOPIASMIL_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAOMADRM_EXPORT
+#   define QTOPIAOMADRM_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIAPRINTING_EXPORT
+#   define QTOPIAPRINTING_EXPORT QTOPIA_VISIBILITY
+#endif
+#ifndef QTOPIATEST_EXPORT
+#   define QTOPIATEST_EXPORT QTOPIA_VISIBILITY
+#endif
+
+// This macro exports symbols only when building a test-enabled build.
+// Use this to make private classes available for test.
+
+#ifdef QTOPIA_TEST_EXTRA_SYMBOLS
+#   ifndef QTOPIA_AUTOTEST_EXPORT
+#       define QTOPIA_AUTOTEST_EXPORT QTOPIA_VISIBILITY
+#   endif
+#else
+#   ifndef QTOPIA_AUTOTEST_EXPORT
+#       define QTOPIA_AUTOTEST_EXPORT
+#   endif
+#endif
+
+// This is the magic that lets Qt and Qtopia plugins be compiled for singleexec
+
+#ifndef SINGLE_EXEC
+#define QTOPIA_EXPORT_PLUGIN(IMPLEMENTATION) Q_EXPORT_PLUGIN(IMPLEMENTATION)
+#define QTOPIA_EXPORT_QT_PLUGIN(IMPLEMENTATION) Q_EXPORT_PLUGIN(IMPLEMENTATION)
+#else
+class QObject;
+typedef QObject *(*qtopiaPluginCreateFunc_t)();
+extern void registerPlugin(const char *name, const char *type, qtopiaPluginCreateFunc_t createFunc);
+#define QTOPIA_EXPORT_PLUGIN(IMPLEMENTATION) \
+    static QObject *create_ ## IMPLEMENTATION() \
+        { return new IMPLEMENTATION(); } \
+    static qtopiaPluginCreateFunc_t append_ ## IMPLEMENTATION() \
+        { registerPlugin(QTOPIA_TARGET, QTOPIA_PLUGIN_TYPE, create_ ##IMPLEMENTATION); \
+            return create_ ##IMPLEMENTATION; } \
+    static qtopiaPluginCreateFunc_t dummy_ ## IMPLEMENTATION = \
+        append_ ## IMPLEMENTATION();
+#define QTOPIA_EXPORT_QT_PLUGIN(IMPLEMENTATION)\
+    Q_EXPORT_PLUGIN(IMPLEMENTATION)\
+    Q_IMPORT_PLUGIN(IMPLEMENTATION)
+#endif
+
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaipcadaptor.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaipcadaptor.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaipcadaptor.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef __QTOPIAIPCADAPTOR_H__
+#define __QTOPIAIPCADAPTOR_H__
+
+#include <qtopiaglobal.h>
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qbytearray.h>
+#include <qvariant.h>
+#include <qmetatype.h>
+#include <qdatastream.h>
+#include <qatomic.h>
+#include <qstringlist.h>
+
+class QtopiaIpcAdaptorPrivate;
+class QtopiaIpcSendEnvelopePrivate;
+
+class QTOPIABASE_EXPORT QtopiaIpcSendEnvelope
+{
+    friend class QtopiaIpcAdaptor;
+private:
+    QtopiaIpcSendEnvelope( const QStringList& channels, const QString& message );
+
+public:
+    QtopiaIpcSendEnvelope();
+    QtopiaIpcSendEnvelope( const QtopiaIpcSendEnvelope& value );
+    ~QtopiaIpcSendEnvelope();
+
+    QtopiaIpcSendEnvelope& operator=( const QtopiaIpcSendEnvelope& value );
+    template <class T>
+    QtopiaIpcSendEnvelope& operator<<( const T &value );
+
+    inline QtopiaIpcSendEnvelope& operator<<( const char *value )
+    {
+        addArgument(QVariant( QString( value ) ));
+        return *this;
+    }
+
+private:
+    QtopiaIpcSendEnvelopePrivate *d;
+
+    void addArgument( const QVariant& value );
+};
+
+class QTOPIABASE_EXPORT QtopiaIpcAdaptor : public QObject
+{
+    Q_OBJECT
+    friend class QtopiaIpcSignalIntercepter;
+    friend class QtopiaIpcSendEnvelope;
+public:
+    explicit QtopiaIpcAdaptor( const QString& channel, QObject *parent = 0 );
+    ~QtopiaIpcAdaptor();
+
+    enum ChannelSelector
+    {
+        AutoDetect,
+        SenderIsChannel,
+        ReceiverIsChannel
+    };
+
+    static bool connect( QObject *sender, const QByteArray& signal,
+                         QObject *receiver, const QByteArray& member,
+                         QtopiaIpcAdaptor::ChannelSelector selector = AutoDetect );
+
+    QtopiaIpcSendEnvelope send( const QByteArray& member );
+    void send( const QByteArray& member, const QVariant &arg1 );
+    void send( const QByteArray& member, const QVariant &arg1, const QVariant &arg2 );
+    void send( const QByteArray& member, const QVariant &arg1, const QVariant &arg2,
+               const QVariant &arg3 );
+    void send( const QByteArray& member, const QList<QVariant>& args );
+
+    bool isConnected( const QByteArray& signal );
+
+protected:
+    enum PublishType
+    {
+        Signals,
+        Slots,
+        SignalsAndSlots
+    };
+    bool publish( const QByteArray& member );
+    void publishAll( QtopiaIpcAdaptor::PublishType type );
+    virtual QString memberToMessage( const QByteArray& member );
+    virtual QStringList sendChannels( const QString& channel );
+    virtual QString receiveChannel( const QString& channel );
+
+private slots:
+    void received( const QString& msg, const QByteArray& data );
+
+private:
+    QtopiaIpcAdaptorPrivate *d;
+
+    bool connectLocalToRemote( QObject *sender, const QByteArray& signal,
+                               const QByteArray& member );
+    bool connectRemoteToLocal( const QByteArray& signal, QObject *receiver,
+                               const QByteArray& member );
+    void sendMessage( const QString& msg, const QList<QVariant>& args );
+    static void send( const QStringList& channels,
+                      const QString& msg, const QList<QVariant>& args );
+};
+
+template<class T>
+QtopiaIpcSendEnvelope& QtopiaIpcSendEnvelope::operator<<( const T &value )
+{
+    addArgument(qVariantFromValue(value));
+    return *this;
+}
+
+// Useful alias to make it clearer when connecting to messages on a channel.
+#define MESSAGE(x)      SIGNAL(x)
+
+#endif /* __QTOPIAIPCADAPTOR_H__ */

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaipcmarshal.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaipcmarshal.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qtopiaipcmarshal.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef __QTOPIAIPCMARSHAL__H__
+#define __QTOPIAIPCMARSHAL__H__
+
+#include <qtopiaglobal.h>
+
+#include <qvariant.h>
+#include <qmetatype.h>
+#include <qdatastream.h>
+#include <qatomic.h>
+#include <quuid.h>
+
+#if defined(QTOPIA_DBUS_IPC)
+#include <qtdbus/qdbusmetatype.h>
+#include <qtdbus/qdbusargument.h>
+#endif
+
+template <typename T>
+struct QMetaTypeRegister
+{
+    static int registerType() { return 1; }
+};
+
+#if QT_VERSION < 0x040400
+#define _QATOMIC_ONCE() \
+    static QAtomic once; \
+    if ( once.exchange(1) ) \
+        return 1
+#else
+#define _QATOMIC_ONCE() \
+    static QAtomicInt once; \
+    if ( once.fetchAndStoreOrdered(1) ) \
+        return 1
+#endif
+
+#if defined(QTOPIA_DBUS_IPC)
+#define Q_DECLARE_USER_METATYPE_NO_OPERATORS(TYPE) \
+    Q_DECLARE_METATYPE(TYPE) \
+    template<> \
+    struct QMetaTypeRegister< TYPE > \
+    { \
+        static int registerType() \
+        { \
+            _QATOMIC_ONCE(); \
+            int id = qMetaTypeId( reinterpret_cast<TYPE *>(0) ); \
+            if ( id >= static_cast<int>(QMetaType::User) ) {\
+                qRegisterMetaTypeStreamOperators< TYPE >( #TYPE ); \
+                qDBusRegisterMetaType< TYPE >(); \
+            } \
+            return 1; \
+        } \
+        static int __init_variable__; \
+    };
+#else
+#define Q_DECLARE_USER_METATYPE_NO_OPERATORS(TYPE) \
+    Q_DECLARE_METATYPE(TYPE) \
+    template<> \
+    struct QMetaTypeRegister< TYPE > \
+    { \
+        static int registerType() \
+        { \
+            _QATOMIC_ONCE(); \
+            int id = qMetaTypeId( reinterpret_cast<TYPE *>(0) ); \
+            if ( id >= static_cast<int>(QMetaType::User) ) \
+                qRegisterMetaTypeStreamOperators< TYPE >( #TYPE ); \
+            return 1; \
+        } \
+        static int __init_variable__; \
+    };
+#endif
+
+#if defined(QTOPIA_DBUS_IPC)
+#define Q_DECLARE_USER_METATYPE(TYPE) \
+    Q_DECLARE_USER_METATYPE_NO_OPERATORS(TYPE) \
+    QTOPIABASE_EXPORT QDataStream &operator<<(QDataStream &stream, const TYPE &var); \
+    QTOPIABASE_EXPORT QDataStream &operator>>( QDataStream &stream, TYPE &var ); \
+    QTOPIABASE_EXPORT QDBusArgument &operator<<(QDBusArgument &stream, const TYPE &var); \
+    QTOPIABASE_EXPORT const QDBusArgument &operator>>(const QDBusArgument &stream, TYPE &var );
+#else
+#define Q_DECLARE_USER_METATYPE(TYPE) \
+    Q_DECLARE_USER_METATYPE_NO_OPERATORS(TYPE) \
+    QTOPIABASE_EXPORT QDataStream &operator<<(QDataStream &stream, const TYPE &var); \
+    QTOPIABASE_EXPORT QDataStream &operator>>( QDataStream &stream, TYPE &var );
+#endif
+
+#if defined(QTOPIA_DBUS_IPC)
+#define Q_DECLARE_USER_METATYPE_TYPEDEF(TAG,TYPE)       \
+    template <typename T> \
+    struct QMetaTypeRegister##TAG \
+    { \
+        static int registerType() { return 1; } \
+    }; \
+    template<> struct QMetaTypeRegister##TAG< TYPE > { \
+        static int registerType() { \
+            _QATOMIC_ONCE(); \
+            int id = qRegisterMetaType< TYPE >( #TYPE ); \
+            qRegisterMetaTypeStreamOperators< TYPE >( #TYPE ); \
+            void (*mf)(QDBusArgument &, const TYPE *) = qDBusMarshallHelper<TYPE>; \
+            void (*df)(const QDBusArgument &, TYPE *) = qDBusDemarshallHelper<TYPE>;\
+            QDBusMetaType::registerMarshallOperators(id, \
+                reinterpret_cast<QDBusMetaType::MarshallFunction>(mf), \
+                reinterpret_cast<QDBusMetaType::DemarshallFunction>(df)); \
+            return 1; \
+        } \
+        static int __init_variable__; \
+    };
+#else
+#define Q_DECLARE_USER_METATYPE_TYPEDEF(TAG,TYPE)       \
+    template <typename T> \
+    struct QMetaTypeRegister##TAG \
+    { \
+        static int registerType() { return 1; } \
+    }; \
+    template<> struct QMetaTypeRegister##TAG< TYPE > { \
+        static int registerType() { \
+            _QATOMIC_ONCE(); \
+            qRegisterMetaType< TYPE >( #TYPE ); \
+            qRegisterMetaTypeStreamOperators< TYPE >( #TYPE ); \
+            return 1; \
+        } \
+        static int __init_variable__; \
+    };
+#endif
+
+#define Q_DECLARE_USER_METATYPE_ENUM(TYPE)      \
+    Q_DECLARE_USER_METATYPE(TYPE)
+
+#define Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(TYPE) \
+    int QMetaTypeRegister< TYPE >::__init_variable__ = \
+        QMetaTypeRegister< TYPE >::registerType();
+
+#if defined(QTOPIA_DBUS_IPC)
+#define Q_IMPLEMENT_USER_METATYPE(TYPE) \
+    QDataStream &operator<<(QDataStream &stream, const TYPE &var) \
+    { \
+        var.serialize(stream); \
+        return stream; \
+    } \
+    QDataStream &operator>>( QDataStream &stream, TYPE &var ) \
+    { \
+        var.deserialize(stream); \
+        return stream; \
+    } \
+    QDBusArgument &operator<<(QDBusArgument &stream, const TYPE &var) \
+    { \
+        stream.beginStructure(); \
+        var.serialize(stream); \
+        stream.endStructure(); \
+        return stream; \
+    } \
+    const QDBusArgument &operator>>(const QDBusArgument &stream, TYPE &var ) \
+    { \
+        stream.beginStructure(); \
+        var.deserialize(stream); \
+        stream.endStructure(); \
+        return stream; \
+    } \
+    Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(TYPE)
+#else
+#define Q_IMPLEMENT_USER_METATYPE(TYPE) \
+    QDataStream &operator<<(QDataStream &stream, const TYPE &var) \
+    { \
+        var.serialize(stream); \
+        return stream; \
+    } \
+    \
+    QDataStream &operator>>( QDataStream &stream, TYPE &var ) \
+    { \
+        var.deserialize(stream); \
+        return stream; \
+    } \
+    Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(TYPE)
+#endif
+
+#define Q_IMPLEMENT_USER_METATYPE_TYPEDEF(TAG,TYPE)     \
+    int QMetaTypeRegister##TAG< TYPE >::__init_variable__ = \
+        QMetaTypeRegister##TAG< TYPE >::registerType();
+
+#if defined(QTOPIA_DBUS_IPC)
+#define Q_IMPLEMENT_USER_METATYPE_ENUM(TYPE)    \
+    QTOPIABASE_EXPORT QDataStream& operator<<( QDataStream& stream, const TYPE &v ) \
+    { \
+        stream << static_cast<qint32>(v); \
+        return stream; \
+    } \
+    QTOPIABASE_EXPORT QDataStream& operator>>( QDataStream& stream, TYPE& v ) \
+    { \
+        qint32 _v; \
+        stream >> _v; \
+        v = static_cast<TYPE>(_v); \
+        return stream; \
+    } \
+    QTOPIABASE_EXPORT QDBusArgument &operator<<(QDBusArgument &a, TYPE v) \
+    { \
+        a << static_cast<qint32>(v); \
+        return a; \
+    } \
+    QTOPIABASE_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, TYPE &v) \
+    { \
+        qint32 _v; \
+        a >> _v; \
+        v = static_cast<TYPE>(_v); \
+        return a; \
+    } \
+    Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(TYPE)
+#else
+#define Q_IMPLEMENT_USER_METATYPE_ENUM(TYPE)    \
+    QDataStream& operator<<( QDataStream& stream, const TYPE &v ) \
+    { \
+        stream << static_cast<qint32>(v); \
+        return stream; \
+    } \
+    QDataStream& operator>>( QDataStream& stream, TYPE& v ) \
+    { \
+        qint32 _v; \
+        stream >> _v; \
+        v = static_cast<TYPE>(_v); \
+        return stream; \
+    } \
+    Q_IMPLEMENT_USER_METATYPE_NO_OPERATORS(TYPE)
+#endif
+
+#define Q_REGISTER_USER_METATYPE(TYPE)  \
+    QMetaTypeRegister< TYPE >::registerType()
+
+Q_DECLARE_USER_METATYPE_NO_OPERATORS(QUuid)
+
+// Special variant class that can perform QDataStream operations
+// without the QVariant header information.
+class QtopiaIpcAdaptorVariant : public QVariant
+{
+    public:
+        QtopiaIpcAdaptorVariant() : QVariant() {}
+        explicit QtopiaIpcAdaptorVariant( const QVariant& value ) : QVariant( value ) {}
+
+        void load( QDataStream& stream, int typeOrMetaType )
+        {
+            clear();
+            create( typeOrMetaType, 0 );
+            d.is_null = false;
+            QMetaType::load
+                ( stream, d.type, const_cast<void *>(constData()) );
+        }
+        void save( QDataStream& stream ) const
+        {
+            QMetaType::save( stream, d.type, constData() );
+        }
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qtopialog-config.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qtopialog-config.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qtopialog-config.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+// Do not #ifndef-protect this header (see qtopialog.cpp)
+
+// Use one of:
+//    QTOPIA_LOG_OPTION  - if the logging can be controlled at run time
+//    QLOG_DISABLE       - if the logging should be always off
+//    QLOG_ENABLE        - if the logging should be always on
+
+QLOG_ENABLE() // enable uncategorized
+QTOPIA_LOG_OPTION(I18n)
+QTOPIA_LOG_OPTION(Bluetooth)
+QTOPIA_LOG_OPTION(Infrared)
+QTOPIA_LOG_OPTION(Obex)
+QTOPIA_LOG_OPTION(UI)
+QTOPIA_LOG_OPTION(Modem)
+QTOPIA_LOG_OPTION(AtChat)
+QTOPIA_LOG_OPTION(Mux)
+QTOPIA_LOG_OPTION(STK)
+QTOPIA_LOG_OPTION(Network)
+QTOPIA_LOG_OPTION(SXE)
+QTOPIA_LOG_OPTION(Resource)
+QTOPIA_LOG_OPTION(Support)
+QTOPIA_LOG_OPTION(Help)
+QTOPIA_LOG_OPTION(Sql)
+QTOPIA_LOG_OPTION(Input)
+QTOPIA_LOG_OPTION(SharedMemCache)
+QTOPIA_LOG_OPTION(DocAPI)
+QTOPIA_LOG_OPTION(DRMAgent)
+QTOPIA_LOG_OPTION(VPN)
+QTOPIA_LOG_OPTION(QtopiaServer)
+QTOPIA_LOG_OPTION(ApplicationLauncher)
+QTOPIA_LOG_OPTION(Time)
+QTOPIA_LOG_OPTION(QSS)
+QTOPIA_LOG_OPTION(Media)
+QTOPIA_LOG_OPTION(ModemEmulator)
+QTOPIA_LOG_OPTION(Package)
+QTOPIA_LOG_OPTION(Quicklauncher)
+QTOPIA_LOG_OPTION(Messaging)
+QTOPIA_LOG_OPTION(DataSharing)
+QTOPIA_LOG_OPTION(DataLinking)
+QTOPIA_LOG_OPTION(Sip)
+QTOPIA_LOG_OPTION(SipAudioData)
+QTOPIA_LOG_OPTION(SxeMonitor)
+QTOPIA_LOG_OPTION(Hardware)
+QTOPIA_LOG_OPTION(Camera)
+QTOPIA_LOG_OPTION(CleanupWizard)
+QTOPIA_LOG_OPTION(DBUS)
+QTOPIA_LOG_OPTION(Services)
+QTOPIA_LOG_OPTION(ApplicationLayer)
+QTOPIA_LOG_OPTION(IniLayer)
+QTOPIA_LOG_OPTION(ILFramework)
+QTOPIA_LOG_OPTION(PowerManagement)
+QTOPIA_LOG_OPTION(VoIP)
+QTOPIA_LOG_OPTION(OOM)
+QTOPIA_LOG_OPTION(Performance)
+QTOPIA_LOG_OPTION(QAudioInput)
+QTOPIA_LOG_OPTION(QAudioOutput)
+QTOPIA_LOG_OPTION(AudioState)
+QTOPIA_LOG_OPTION(Synchronization)
+QTOPIA_LOG_OPTION(Qtopiatest)

Added: trunk/src/host/qemu-neo1973/phonesim/lib/qtopialog.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/qtopialog.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/qtopialog.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#include <qlog.h>
+
+#ifndef QTOPIA_LOG_H
+#define QTOPIA_LOG_H
+
+#include <qtopiaglobal.h>
+
+QTOPIABASE_EXPORT bool qtopiaLogRequested( const char* );
+QTOPIABASE_EXPORT bool qtopiaLogEnabled( const char* );
+QTOPIABASE_EXPORT bool qtopiaLogOptional( const char* );
+
+#define QTOPIA_LOG_OPTION(x) QLOG_OPTION(x,qtopiaLogRequested(#x))
+
+#include <qtopialog-config.h>
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresult.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresult.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresult.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,601 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qatresult.h>
+
+/*!
+    \class QAtResult
+    \mainclass
+    \brief The QAtResult class provides access to the results of AT modem commands and unsolicited notifications
+    \ingroup telephony::serial
+
+    AT commands that are sent to a modem with QAtChat::chat() result in a QAtResult
+    object being made available to describe the result of the command when it completes.
+
+    The resultCode() method can be used to determine the exact cause of an AT
+    modem command failure.  The content() method can be used to access the
+    response content that was returned from the command.  For complex response
+    contents, the QAtResultParser class can be used to decode the response.
+
+    \sa QAtChat, QAtResultParser
+*/
+
+class QAtResultPrivate
+{
+public:
+    QAtResultPrivate()
+    {
+        result = "OK";
+        resultCode = QAtResult::OK;
+        verbose = true;
+        userData = 0;
+    }
+    ~QAtResultPrivate()
+    {
+        if ( userData )
+            delete userData;
+    }
+
+    QString result;
+    QString content;
+    QAtResult::ResultCode resultCode;
+    bool verbose;
+    QAtResult::UserData *userData;
+};
+
+/*!
+    \enum QAtResult::ResultCode
+    Result codes for AT modem commands.
+
+    \value OK Command responded with \c{OK}
+    \value Connect Command responded with \c{CONNECT}
+    \value NoCarrier Command responded with \c{NO CARRIER}
+    \value Error Command responded with \c{ERROR}
+    \value NoDialtone Command responded with \c{NO DIALTONE}
+    \value Busy Command responded with \c{BUSY}
+    \value NoAnswer Command responded with \c{NO ANSWER}
+    \value Dead The link is dead
+    \value PhoneFailure GSM 27.07 code 0: phone failure
+    \value NoConnectionToPhone GSM 27.07 code 1: no connection to phone
+    \value PhoneAdapterLinkReserved GSM 27.07 code 2: phone-adaptor link reserved
+    \value OperationNotAllowed GSM 27.07 code 3: operation not allowed
+    \value OperationNotSupported GSM 27.07 code 4: operation not supported
+    \value PhSimPinRequired GSM 27.07 code 5: PH-SIM PIN required
+    \value PhFSimPinRequired GSM 27.07 code 6: PH-FSIM PIN required
+    \value PhFSimPukRequired GSM 27.07 code 7: PH-FSIM PUK required
+    \value SimNotInserted GSM 27.07 code 10: SIM not inserted
+    \value SimPinRequired GSM 27.07 code 11: SIM PIN required
+    \value SimPukRequired GSM 27.07 code 12: SIM PUK required
+    \value SimFailure GSM 27.07 code 13: SIM failure
+    \value SimBusy GSM 27.07 code 14: SIM busy
+    \value SimWrong GSM 27.07 code 15: SIM wrong
+    \value IncorrectPassword GSM 27.07 code 16: incorrect password
+    \value SimPin2Required GSM 27.07 code 17: SIM PIN2 required
+    \value SimPuk2Required GSM 27.07 code 18: SIM PUK2 required
+    \value MemoryFull GSM 27.07 code 20: memory full
+    \value InvalidIndex GSM 27.07 code 21: invalid index
+    \value NotFound GSM 27.07 code 22: not found
+    \value MemoryFailure GSM 27.07 code 23: memory failure
+    \value TextStringTooLong GSM 27.07 code 24: text string too long
+    \value InvalidCharsInTextString GSM 27.07 code 25: invalid characters in text string
+    \value DialStringTooLong GSM 27.07 code 26: dial string too long
+    \value InvalidCharsInDialString GSM 27.07 code 27: invalid characters in dial string
+    \value NoNetworkService GSM 27.07 code 30: no network service
+    \value NetworkTimeout GSM 27.07 code 31: network timeout
+    \value NetworkNotAllowed GSM 27.07 code 32: network not allowed - emergency calls only
+    \value NetPersPinRequired GSM 27.07 code 40: network personalization PIN required
+    \value NetPersPukRequired GSM 27.07 code 41: network personalization PUK required
+    \value NetSubsetPersPinRequired GSM 27.07 code 42: network subset personalization PIN required
+    \value NetSubsetPersPukRequired GSM 27.07 code 43: network subset personalization PUK required
+    \value ServProvPersPinRequired GSM 27.07 code 44: service provider personalization PIN required
+    \value ServProvPersPukRequired GSM 27.07 code 45: service provider personalization PUK required
+    \value CorpPersPinRequired GSM 27.07 code 46: corporate personalization PIN required
+    \value CorpPersPukRequired GSM 27.07 code 47: corporate personalization PUK required
+    \value HiddenKeyRequired GSM 27.07 code 48: hidden key required
+    \value Unknown GSM 27.07 code 100: unknown
+    \value IllegalMS GSM 27.07 code 103: Illegal MS
+    \value IllegalME GSM 27.07 code 106: Illegal ME
+    \value GPRSServicesNotAllowed GSM 27.07 code 107: GPRS services not allowed
+    \value PLMNNotAllowed GSM 27.07 code 111: PLMN not allowed
+    \value LocationAreaNotAllowed GSM 27.07 code 112: Location area not allowed
+    \value RoamingNotAllowed GSM 27.07 code 113: Roaming not allowed in this location area
+    \value ServiceOptionNotSupported GSM 27.07 code 132: service option not supported
+    \value ServiceOptionNotSubscribed GSM 27.07 code 133: service option not subscribed
+    \value ServiceOptionOutOfOrder GSM 27.07 code 134: service option temporarily out of order
+    \value UnspecifiedGPRSError GSM 27.07 code 148: unspecified GPRS error
+    \value PDPAuthenticationFailure GSM 27.07 code 149: PDP authentication failure
+    \value InvalidMobileClass GSM 27.07 code 150: invalid mobile class
+    \value VBSVGCSNotSupported GSM 27.07 code 151: VBS/VGCS not supported by the network
+    \value NoServiceSubscriptionOnSim GSM 27.07 code 152: No service subscription on SIM
+    \value NoSubscriptionForGroupId GSM 27.07 code 153: No subscription for group ID
+    \value GroupIdNotActivatedOnSim GSM 27.07 code 154: Group Id not activated on SIM
+    \value NoMatchingNotification GSM 27.07 code 155: No matching notification
+    \value VBSVGCSCallAlreadyPresent GSM 27.07 code 156: VBS/VGCS call already present
+    \value Congestion GSM 27.07 code 157: Congestion
+    \value NetworkFailure GSM 27.07 code 158: Network failure
+    \value UplinkBusy GSM 27.07 code 159: Uplink busy
+    \value NoAccessRightsForSimFile GSM 27.07 code 160: No access rights for SIM file
+    \value NoSubscriptionForPriority GSM 27.07 code 161: No subscription for priority
+    \value OperationNotApplicable GSM 27.07 code 162: operation not applicable or not possible
+    \value MEFailure GSM 27.05 code 300: ME failure
+    \value SMSServiceOfMEReserved GSM 27.05 code 301: SMS service of ME reserved
+    \value SMSOperationNotAllowed GSM 27.05 code 302: operation not allowed
+    \value SMSOperationNotSupported GSM 27.05 code 303: operation not supported
+    \value InvalidPDUModeParameter GSM 27.05 code 304: invalid PDU mode parameter
+    \value InvalidTextModeParameter GSM 27.05 code 305: invalid text mode parameter
+    \value USimNotInserted GSM 27.05 code 310: (U)SIM not inserted
+    \value USimPinRequired GSM 27.05 code 311: (U)SIM PIN required
+    \value PHUSimPinRequired GSM 27.05 code 312: PH-(U)SIM PIN required
+    \value USimFailure GSM 27.05 code 313: (U)SIM failure
+    \value USimBusy GSM 27.05 code 314: (U)SIM busy
+    \value USimWrong GSM 27.05 code 315: (U)SIM wrong
+    \value USimPukRequired GSM 27.05 code 316: (U)SIM PUK required
+    \value USimPin2Required GSM 27.05 code 317: (U)SIM PIN2 required
+    \value USimPuk2Required GSM 27.05 code 318: (U)SIM PUK2 required
+    \value SMSMemoryFailure GSM 27.05 code 320: memory failure
+    \value InvalidMemoryIndex GSM 27.05 code 321: invalid memory index
+    \value SMSMemoryFull GSM 27.05 code 322: memory full
+    \value SMSCAddressUnknown GSM 27.05 code 330: SMSC address unknown
+    \value SMSNoNetworkService GSM 27.05 code 331: no network service
+    \value SMSNetworkTimeout GSM 27.05 code 332: network timeout
+    \value NoCNMAAckExpected GSM 27.05 code 340: no +CNMA acknowledgment expected
+    \value UnknownError GSM 27.05 code 500: unknown error
+*/
+
+/*!
+    \class QAtResult::UserData
+    \mainclass
+    \brief Provides a mechanism to add user data to a result object via QAtChat::chat().
+
+    Usually this class will be inherited, with extra fields added to hold the user data.
+
+    \sa QAtChat::chat()
+*/
+
+/*!
+    \fn QAtResult::UserData::~UserData()
+
+    Destructs a user data object.
+*/
+
+/*!
+    Construct a new QAtResult object.  The result() will be \c{OK},
+    and the content() empty.
+*/
+QAtResult::QAtResult()
+{
+    d = new QAtResultPrivate();
+}
+
+/*!
+    Construct a copy of \a other.
+*/
+QAtResult::QAtResult( const QAtResult& other )
+{
+    d = new QAtResultPrivate();
+    *this = other;
+}
+
+/*!
+    Destruct this QAtResult object.
+*/
+QAtResult::~QAtResult()
+{
+    delete d;
+}
+
+/*!
+    Assign the contents of \a other to this object.
+*/
+QAtResult& QAtResult::operator=( const QAtResult& other )
+{
+    if ( this != &other ) {
+        d->result = other.d->result;
+        d->content = other.d->content;
+        d->resultCode = other.d->resultCode;
+    }
+    return *this;
+}
+
+/*!
+    Returns the result line that terminated the command's response.
+    This is usually a string such as \c{OK}, \c{ERROR}, \c{+CME ERROR: N},
+    and so on.
+
+    The resultCode() function is a better way to determine why a command
+    failed, but sometimes it is necessary to parse the text result line.
+    For example, for \c{CONNECT baudrate}, the caller may be interested in
+    the baud rate.
+
+    \sa resultCode(), ok()
+*/
+QString QAtResult::result() const
+{
+    return d->result;
+}
+
+/*!
+    Sets the result line that terminated the command's response to \a value.
+    This will also update resultCode() to reflect the appropriate code.
+
+    \sa result(), resultCode()
+*/
+void QAtResult::setResult( const QString& value )
+{
+    d->result = value;
+    resultToCode( value );
+}
+
+/*!
+    Returns the content that was returned with an AT command's result.
+
+    \sa setContent(), append()
+*/
+QString QAtResult::content() const
+{
+    return d->content;
+}
+
+/*!
+    Sets the content that was returned with an AT command's result to \a value.
+
+    \sa content(), append()
+*/
+void QAtResult::setContent( const QString& value )
+{
+    d->content = value;
+}
+
+/*!
+    Append \a value to the current content, after a line terminator.
+
+    \sa content(), setContent()
+*/
+void QAtResult::append( const QString& value )
+{
+    if ( d->content.isEmpty() )
+        d->content = value;
+    else
+        d->content = d->content + "\n" + value;
+}
+
+/*!
+    Returns the numeric result code associated with result().
+
+    Extended error codes are only possible if the appropriate modem error
+    mode has been enabled (e.g. with the \c{AT+CMEE=1} command).  Otherwise
+    most errors will simply be reported as QAtResult::Error.
+
+    \sa setResultCode(), result(), ok()
+*/
+QAtResult::ResultCode QAtResult::resultCode() const
+{
+    return d->resultCode;
+}
+
+/*!
+    Sets the numeric result code to \a value, and update result()
+    to reflect the value.
+
+    \sa resultCode(), result()
+*/
+void QAtResult::setResultCode( QAtResult::ResultCode value )
+{
+    d->resultCode = value;
+    d->result = codeToResult( QString() );
+    d->verbose = true;
+}
+
+/*!
+    Returns true if this result indicates a successful command; false otherwise.
+    Success is indicated when resultCode() returns either
+    QAtResult::OK or QAtResult::Connect.  All other result
+    codes indicate failure.
+
+    \sa resultCode()
+*/
+bool QAtResult::ok() const
+{
+    return ( d->resultCode == QAtResult::OK ||
+             d->resultCode == QAtResult::Connect );
+}
+
+/*!
+    Returns a more verbose version of result(), suitable for debug output.
+    Many modems report extended errors by number (e.g. \c{+CME ERROR: 4}),
+    which can be difficult to use when diagnosing problems.  This function
+    returns a string that is more suitable for diagnostic output than result().
+    If result() is already verbose, it will be returned as-is.
+
+    \sa result()
+*/
+QString QAtResult::verboseResult() const
+{
+    if ( d->verbose )
+        return d->result;
+    else
+        return codeToResult( d->result );
+}
+
+/*!
+    Returns the user data associated with this result object.
+
+    \sa setUserData()
+*/
+QAtResult::UserData *QAtResult::userData() const
+{
+    return d->userData;
+}
+
+/*!
+    Sets the user data associated with this result object to \a value.
+
+    \sa userData()
+*/
+void QAtResult::setUserData( QAtResult::UserData *value )
+{
+    if ( d->userData && d->userData != value )
+        delete d->userData;
+    d->userData = value;
+}
+
+// Table of result codes.  Note: these strings are not translatable,
+// as they are used to parse values on the wire.
+struct QAtCodeInfo
+{
+    QAtResult::ResultCode   code;
+    const char             *name;
+};
+static QAtCodeInfo const basic_codes[] = {
+    {QAtResult::OK,                         "OK"},      // no tr
+    {QAtResult::OK,                         "0"},       // no tr
+    {QAtResult::Connect,                    "CONNECT"},     // no tr
+    {QAtResult::Connect,                    "1"},       // no tr
+    {QAtResult::NoCarrier,                  "NO CARRIER"},      // no tr
+    {QAtResult::NoCarrier,                  "3"},       // no tr
+    {QAtResult::Error,                      "ERROR"},       // no tr
+    {QAtResult::Error,                      "4"},       // no tr
+    {QAtResult::NoDialtone,                 "NO DIALTONE"},     // no tr
+    {QAtResult::NoDialtone,                 "6"},       // no tr
+    {QAtResult::Busy,                       "BUSY"},        // no tr
+    {QAtResult::Busy,                       "7"},       // no tr
+    {QAtResult::NoAnswer,                   "NO ANSWER"},       // no tr
+    {QAtResult::NoAnswer,                   "8"}        // no tr
+};
+static QAtCodeInfo const ext_codes[] = {
+    {QAtResult::PhoneFailure,               "phone failure"},       // no tr
+    {QAtResult::NoConnectionToPhone,        "no connection to phone"},      // no tr
+    {QAtResult::PhoneAdapterLinkReserved,   "phone-adaptor link reserved"},     // no tr
+    {QAtResult::OperationNotAllowed,        "operation not allowed"},       // no tr
+    {QAtResult::OperationNotSupported,      "operation not supported"},     // no tr
+    {QAtResult::PhSimPinRequired,           "PH-SIM PIN required"},     // no tr
+    {QAtResult::PhFSimPinRequired,          "PH-FSIM PIN required"},        // no tr
+    {QAtResult::PhFSimPukRequired,          "PH-FSIM PUK required"},        // no tr
+    {QAtResult::SimNotInserted,             "SIM not inserted"},        // no tr
+    {QAtResult::SimPinRequired,             "SIM PIN required"},        // no tr
+    {QAtResult::SimPukRequired,             "SIM PUK required"},        // no tr
+    {QAtResult::SimFailure,                 "SIM failure"},     // no tr
+    {QAtResult::SimBusy,                    "SIM busy"},        // no tr
+    {QAtResult::SimWrong,                   "SIM wrong"},       // no tr
+    {QAtResult::IncorrectPassword,          "incorrect password"},      // no tr
+    {QAtResult::SimPin2Required,            "SIM PIN2 required"},       // no tr
+    {QAtResult::SimPuk2Required,            "SIM PUK2 required"},       // no tr
+    {QAtResult::MemoryFull,                 "memory full"},     // no tr
+    {QAtResult::InvalidIndex,               "invalid index"},       // no tr
+    {QAtResult::NotFound,                   "not found"},   // no tr
+    {QAtResult::MemoryFailure,              "memory failure"},  // no tr
+    {QAtResult::TextStringTooLong,          "text string too long"},    // no tr
+    {QAtResult::InvalidCharsInTextString,   "invalid characters in text string"},   // no tr
+    {QAtResult::DialStringTooLong,          "dial string too long"},    // no tr
+    {QAtResult::InvalidCharsInDialString,   "invalid characters in dial string"},   // no tr
+    {QAtResult::NoNetworkService,           "no network service"},  // no tr
+    {QAtResult::NetworkTimeout,             "network timeout"}, // no tr
+    {QAtResult::NetworkNotAllowed,          "network not allowed - emergency calls only"},  // no tr
+    {QAtResult::NetPersPinRequired,         "network personalization PIN required"},    // no tr
+    {QAtResult::NetPersPukRequired,         "network personalization PUK required"},    // no tr
+    {QAtResult::NetSubsetPersPinRequired,   "network subset personalization PIN required"}, // no tr
+    {QAtResult::NetSubsetPersPukRequired,   "network subset personalization PUK required"}, // no tr
+    {QAtResult::ServProvPersPinRequired,    "service provider personalization PIN required"},   // no tr
+    {QAtResult::ServProvPersPukRequired,    "service provider personalization PUK required"},   // no tr
+    {QAtResult::CorpPersPinRequired,        "corporate personalization PIN required"},  // no tr
+    {QAtResult::CorpPersPukRequired,        "corporate personalization PUK required"},  // no tr
+    {QAtResult::HiddenKeyRequired,          "hidden key required"}, // no tr
+    {QAtResult::Unknown,                    "unknown"}, // no tr
+
+    {QAtResult::IllegalMS,                  "Illegal MS"},  // no tr
+    {QAtResult::IllegalME,                  "Illegal ME"},  // no tr
+    {QAtResult::GPRSServicesNotAllowed  ,   "GPRS services not allowed"},   // no tr
+    {QAtResult::PLMNNotAllowed,             "PLMN not allowed"},    // no tr
+    {QAtResult::LocationAreaNotAllowed,     "Location area not allowed"},   // no tr
+    {QAtResult::RoamingNotAllowed,          "Roaming not allowed in this location area"},   // no tr
+    {QAtResult::ServiceOptionNotSupported,  "service option not supported"},    // no tr
+    {QAtResult::ServiceOptionNotSubscribed, "requested service option not subscribed"}, // no tr
+    {QAtResult::ServiceOptionOutOfOrder,    "service option temporarily out of order"}, // no tr
+    {QAtResult::UnspecifiedGPRSError,       "unspecified GPRS error"},  // no tr
+    {QAtResult::PDPAuthenticationFailure,   "PDP authentication failure"},  // no tr
+    {QAtResult::InvalidMobileClass,         "invalid mobile class"},    // no tr
+    // no tr
+    {QAtResult::VBSVGCSNotSupported,        "VBS/VGCS not supported by the network"},   // no tr
+    {QAtResult::NoServiceSubscriptionOnSim, "No service subscription on SIM"},  // no tr
+    {QAtResult::NoSubscriptionForGroupId,   "No subscription for group ID"},    // no tr
+    {QAtResult::GroupIdNotActivatedOnSim,   "Group Id not activated on SIM"},   // no tr
+    {QAtResult::NoMatchingNotification,     "No matching notification"},    // no tr
+    {QAtResult::VBSVGCSCallAlreadyPresent,  "VBS/VGCS call already present"},   // no tr
+    {QAtResult::Congestion,                 "Congestion"},  // no tr
+    {QAtResult::NetworkFailure,             "Network failure"}, // no tr
+    {QAtResult::UplinkBusy,                 "Uplink busy"}, // no tr
+    {QAtResult::NoAccessRightsForSimFile,   "No access rights for SIM file"},   // no tr
+    {QAtResult::NoSubscriptionForPriority,  "No subscription for priority"},    // no tr
+    {QAtResult::OperationNotApplicable,     "operation not applicable or not possible"},    // no tr
+
+    {QAtResult::MEFailure,                  "ME failure"},  // no tr
+    {QAtResult::SMSServiceOfMEReserved,     "SMS service of ME reserved"},  // no tr
+    {QAtResult::SMSOperationNotAllowed,     "operation not allowed"},   // no tr
+    {QAtResult::SMSOperationNotSupported,   "operation not supported"}, // no tr
+    {QAtResult::InvalidPDUModeParameter,    "invalid PDU mode parameter"},  // no tr
+    {QAtResult::InvalidTextModeParameter,   "invalid text mode parameter"}, // no tr
+    {QAtResult::USimNotInserted,            "(U)SIM not inserted"}, // no tr
+    {QAtResult::USimPinRequired,            "(U)SIM PIN required"}, // no tr
+    {QAtResult::PHUSimPinRequired,          "PH-(U)SIM PIN required"},  // no tr
+    {QAtResult::USimFailure,                "(U)SIM failure"},  // no tr
+    {QAtResult::USimBusy,                   "(U)SIM busy"}, // no tr
+    {QAtResult::USimWrong,                  "(U)SIM wrong"},    // no tr
+    {QAtResult::USimPukRequired,            "(U)SIM PUK required"}, // no tr
+    {QAtResult::USimPin2Required,           "(U)SIM PIN2 required"},    // no tr
+    {QAtResult::USimPuk2Required,           "(U)SIM PUK2 required"},    // no tr
+    {QAtResult::SMSMemoryFailure,           "memory failure"},  // no tr
+    {QAtResult::InvalidMemoryIndex,         "invalid memory index"},    // no tr
+    {QAtResult::MemoryFull,                 "memory full"}, // no tr
+    {QAtResult::SMSCAddressUnknown,         "SMSC address unknown"},    // no tr
+    {QAtResult::SMSNoNetworkService,        "no network service"},  // no tr
+    {QAtResult::SMSNetworkTimeout,          "network timeout"}, // no tr
+    {QAtResult::NoCNMAAckExpected,          "no +CNMA acknowledgement expected"},   // no tr
+    {QAtResult::UnknownError,               "unknown error"}    // no tr
+};
+#define num_basic_codes   ((int)( sizeof(basic_codes) / sizeof(QAtCodeInfo) ))
+#define num_ext_codes     ((int)( sizeof(ext_codes) / sizeof(QAtCodeInfo) ))
+
+// Extract a numeric error code from the front of "value", or -1 if not.
+static int numeric( const QString& value )
+{
+    int posn = 0;
+    if ( posn >= value.length() || value[posn] < '0' || value[posn] > '9' )
+        return -1;
+    int number = 0;
+    while ( posn < value.length() && value[posn] >= '0' && value[posn] <= '9' )
+        number = number * 10 + (int)(value[posn++].unicode() - '0');
+    return number;
+}
+
+// Determine if we have a prefix match, ignoring case.
+static bool match( const QString& value, const char *prefix )
+{
+    int posn = 0;
+    while ( posn < value.length() && *prefix != '\0' ) {
+        int ch1 = value[posn++].unicode();
+        int ch2 = *prefix++;
+        if ( ch1 >= 'A' && ch1 <= 'Z' )
+            ch1 = ch1 - 'A' + 'a';
+        if ( ch2 >= 'A' && ch2 <= 'Z' )
+            ch2 = ch2 - 'A' + 'a';
+        if ( ch1 != ch2 )
+            return false;
+    }
+    if ( *prefix != '\0' )
+        return false;
+    return ( posn >= value.length() || value[posn] == ' ' );
+}
+
+void QAtResult::resultToCode( const QString& value )
+{
+    QString val;
+    int index;
+
+    // Determine what kind of error report we have.
+    if ( value.startsWith( "+CME ERROR:", Qt::CaseInsensitive ) ||
+         value.startsWith( "+EXT ERROR:", Qt::CaseInsensitive ) ) {
+
+        // Extended or GPRS error report.
+        val = value.mid( 11 ).trimmed();
+        index = numeric( val );
+        if ( index >= 0 ) {
+            d->resultCode = (QAtResult::ResultCode)index;
+            d->verbose = false;
+            return;
+        }
+
+    } else if ( value.startsWith( "+CMS ERROR:", Qt::CaseInsensitive ) ) {
+
+        // Check the SMS codes before the main codes, as there is
+        // some overlap in the message names.
+        val = value.mid( 11 ).trimmed();
+        index = numeric( val );
+        if ( index >= 0 ) {
+            d->resultCode = (QAtResult::ResultCode)index;
+            d->verbose = false;
+            return;
+        }
+        index = 0;
+        while ( ext_codes[index].code != QAtResult::MEFailure )
+            ++index;
+        while ( index < num_ext_codes ) {
+            if ( match( val, ext_codes[index].name ) ) {
+                d->resultCode = ext_codes[index].code;
+                d->verbose = true;
+                return;
+            }
+            ++index;
+        }
+
+    } else {
+
+        // Probably something like OK, ERROR, etc.  Scan the basic codes only.
+        for ( index = 0; index < num_basic_codes; ++index ) {
+            if ( match( value, basic_codes[index].name ) ) {
+                d->resultCode = basic_codes[index].code;
+                d->verbose = true;
+                return;
+            }
+        }
+        d->resultCode = QAtResult::UnknownError;
+        d->verbose = true;
+
+    }
+
+    // Scan the extended code list for a match.
+    for ( index = 0; index < num_ext_codes; ++index ) {
+        if ( match( val, ext_codes[index].name ) ) {
+            d->resultCode = ext_codes[index].code;
+            d->verbose = true;
+            return;
+        }
+    }
+    d->resultCode = QAtResult::UnknownError;
+    d->verbose = true;
+}
+
+QString QAtResult::codeToResult( const QString& defaultValue ) const
+{
+    int index;
+    for ( index = 0; index < num_basic_codes; ++index ) {
+        if ( basic_codes[index].code == d->resultCode ) {
+            return basic_codes[index].name;
+        }
+    }
+    for ( index = 0; index < num_ext_codes; ++index ) {
+        if ( ext_codes[index].code == d->resultCode ) {
+            if ( d->resultCode >= 300 && d->resultCode <= 500 )
+                return QString( "+CMS ERROR: " ) + ext_codes[index].name;
+            else
+                return QString( "+CME ERROR: " ) + ext_codes[index].name;
+        }
+    }
+    if ( defaultValue.isEmpty() ) {
+        if ( ((int)d->resultCode) >= 300 &&
+             ((int)d->resultCode) <= 500 ) {
+            return "+CMS ERROR: " + QString::number( d->resultCode );
+        } else {
+            return "+CME ERROR: " + QString::number( d->resultCode );
+        }
+    } else {
+        return defaultValue;
+    }
+}

Added: trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresult.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresult.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresult.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QATRESULT_H
+#define QATRESULT_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+#include <qtopiaglobal.h>
+
+class QAtResultPrivate;
+
+class QTOPIACOMM_EXPORT QAtResult
+{
+public:
+    enum ResultCode
+    {
+        OK                          = -1,
+        Connect                     = -2,
+        NoCarrier                   = -3,
+        Error                       = -4,
+        NoDialtone                  = -5,
+        Busy                        = -6,
+        NoAnswer                    = -7,
+        Dead                        = -8,
+
+        // General errors (GSM 27.07, section 9.2.1).
+        PhoneFailure                = 0,
+        NoConnectionToPhone         = 1,
+        PhoneAdapterLinkReserved    = 2,
+        OperationNotAllowed         = 3,
+        OperationNotSupported       = 4,
+        PhSimPinRequired            = 5,
+        PhFSimPinRequired           = 6,
+        PhFSimPukRequired           = 7,
+        SimNotInserted              = 10,
+        SimPinRequired              = 11,
+        SimPukRequired              = 12,
+        SimFailure                  = 13,
+        SimBusy                     = 14,
+        SimWrong                    = 15,
+        IncorrectPassword           = 16,
+        SimPin2Required             = 17,
+        SimPuk2Required             = 18,
+        MemoryFull                  = 20,
+        InvalidIndex                = 21,
+        NotFound                    = 22,
+        MemoryFailure               = 23,
+        TextStringTooLong           = 24,
+        InvalidCharsInTextString    = 25,
+        DialStringTooLong           = 26,
+        InvalidCharsInDialString    = 27,
+        NoNetworkService            = 30,
+        NetworkTimeout              = 31,
+        NetworkNotAllowed           = 32,
+        NetPersPinRequired          = 40,
+        NetPersPukRequired          = 41,
+        NetSubsetPersPinRequired    = 42,
+        NetSubsetPersPukRequired    = 43,
+        ServProvPersPinRequired     = 44,
+        ServProvPersPukRequired     = 45,
+        CorpPersPinRequired         = 46,
+        CorpPersPukRequired         = 47,   // 23 according to spec ???
+        HiddenKeyRequired           = 48,   // 24 according to spec ???
+        Unknown                     = 100,
+
+        // GPRS-related errors (GSM 27.07, section 9.2.2).
+        IllegalMS                   = 103,
+        IllegalME                   = 106,
+        GPRSServicesNotAllowed      = 107,
+        PLMNNotAllowed              = 111,
+        LocationAreaNotAllowed      = 112,
+        RoamingNotAllowed           = 113,
+        ServiceOptionNotSupported   = 132,
+        ServiceOptionNotSubscribed  = 133,
+        ServiceOptionOutOfOrder     = 134,
+        UnspecifiedGPRSError        = 148,
+        PDPAuthenticationFailure    = 149,
+        InvalidMobileClass          = 150,
+
+        // VBS/VGCS and eMLPP errors (GSM 27.07, section 9.2.3).
+        VBSVGCSNotSupported         = 151,
+        NoServiceSubscriptionOnSim  = 152,
+        NoSubscriptionForGroupId    = 153,
+        GroupIdNotActivatedOnSim    = 154,
+        NoMatchingNotification      = 155,
+        VBSVGCSCallAlreadyPresent   = 156,
+        Congestion                  = 157,
+        NetworkFailure              = 158,
+        UplinkBusy                  = 159,
+        NoAccessRightsForSimFile    = 160,
+        NoSubscriptionForPriority   = 161,
+        OperationNotApplicable      = 162,
+
+        // SMS errors (GSM 27.05, section 3.2.5).
+        MEFailure                   = 300,
+        SMSServiceOfMEReserved      = 301,
+        SMSOperationNotAllowed      = 302,
+        SMSOperationNotSupported    = 303,
+        InvalidPDUModeParameter     = 304,
+        InvalidTextModeParameter    = 305,
+        USimNotInserted             = 310,
+        USimPinRequired             = 311,
+        PHUSimPinRequired           = 312,
+        USimFailure                 = 313,
+        USimBusy                    = 314,
+        USimWrong                   = 315,
+        USimPukRequired             = 316,
+        USimPin2Required            = 317,
+        USimPuk2Required            = 318,
+        SMSMemoryFailure            = 320,
+        InvalidMemoryIndex          = 321,
+        SMSMemoryFull               = 322,
+        SMSCAddressUnknown          = 330,
+        SMSNoNetworkService         = 331,
+        SMSNetworkTimeout           = 332,
+        NoCNMAAckExpected           = 340,
+        UnknownError                = 500
+    };
+
+    class UserData
+    {
+    public:
+        virtual ~UserData() {}
+    };
+
+    QAtResult();
+    QAtResult( const QAtResult& other );
+    ~QAtResult();
+
+    QAtResult& operator=( const QAtResult& other );
+
+    QString result() const;
+    void setResult( const QString& value );
+
+    QString content() const;
+    void setContent( const QString& value );
+    void append( const QString& value );
+
+    QAtResult::ResultCode resultCode() const;
+    void setResultCode( QAtResult::ResultCode value );
+
+    bool ok() const;
+
+    QString verboseResult() const;
+
+    QAtResult::UserData *userData() const;
+    void setUserData( QAtResult::UserData *value );
+
+private:
+    QAtResultPrivate *d;
+
+    void resultToCode( const QString& value );
+    QString codeToResult( const QString& defaultValue ) const;
+};
+
+#endif // QATRESULT_H

Added: trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresultparser.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresultparser.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresultparser.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,446 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qatresultparser.h>
+#include <qatresult.h>
+#include <qatutils.h>
+
+/*!
+    \class QAtResultParser
+    \mainclass
+    \brief The QAtResultParser class provides support for parsing the response to AT modem commands and unsolicited notifications.
+    \ingroup telephony::serial
+
+    The following example demonstrates how to parse the response to a
+    \c{AT+CPOL} (preferred operator list) query:
+
+    \code
+        QAtResultParser parser( result );
+        while ( parser.next( "+CPOL:" ) ) {
+            uint index = parser.readNumeric();
+            uint format = parser.readNumeric();
+            QString name;
+            if ( format == 2 )  // Numeric format.
+                name = QString::number( parser.readNumeric() );
+            else                // String format.
+                name = parser.readString();
+        }
+    \endcode
+
+    \sa QAtResult
+*/
+
+class QAtResultParserPrivate
+{
+public:
+    QAtResultParserPrivate( const QString& content )
+    {
+        response = content;
+        posn = 0;
+        linePosn = 0;
+        notification = false;
+    }
+
+    QString response;
+    QString line;
+    int posn;
+    int linePosn;
+    bool notification;
+};
+
+/*!
+    Construct an AT modem result parser to parse the content of \a result.
+    The caller will typically follow this with a call to next() to position
+    the parser on the first line of relevant result data.
+*/
+QAtResultParser::QAtResultParser( const QAtResult& result )
+{
+    d = new QAtResultParserPrivate( result.content() );
+}
+
+/*!
+    Construct an AT modem result parser and initialize it to parse
+    the specified unsolicited \a notification.  Notifications are
+    expected to have the format \c{NAME: VALUE}.  The next() function
+    will be called internally to position the parser at \c{VALUE}.
+*/
+QAtResultParser::QAtResultParser( const QString& notification )
+{
+    d = new QAtResultParserPrivate( notification );
+    int posn = 0;
+    while ( posn < notification.length() && notification[posn] != ':' ) {
+        ++posn;
+    }
+    if ( posn < notification.length() )
+        ++posn;     // Account for the colon.
+    next( notification.left( posn ) );
+    d->notification = true;
+}
+
+/*!
+    Destruct this AT modem result parser.
+*/
+QAtResultParser::~QAtResultParser()
+{
+    delete d;
+}
+
+/*!
+    Reset this AT modem result parser to the beginning of the content.
+*/
+void QAtResultParser::reset()
+{
+    if ( d->notification ) {
+        d->linePosn = 0;
+    } else {
+        d->line = QString();
+        d->posn = 0;
+        d->linePosn = 0;
+    }
+}
+
+/*!
+    Position this AT modem result parser on the next line that begins
+    with \a prefix. Returns true on success; otherwise returns false.
+
+    \sa line(), lines(), readNumeric(), readString()
+*/
+bool QAtResultParser::next( const QString& prefix )
+{
+    while ( d->posn < d->response.length() ) {
+
+        // Extract the next line.
+        d->line = "";
+        d->linePosn = 0;
+        while ( d->posn < d->response.length() &&
+                d->response[d->posn] != '\n' ) {
+            d->line += d->response[(d->posn)++];
+        }
+        if ( d->posn < d->response.length() ) {
+            ++(d->posn);
+        }
+
+        // Bail out if the line starts with the expected prefix.
+        if ( d->line.startsWith( prefix ) ) {
+            d->linePosn = prefix.length();
+            while ( d->linePosn < d->line.length() &&
+                    d->line[d->linePosn] == ' ' ) {
+                ++(d->linePosn);
+            }
+            d->line = d->line.mid( d->linePosn );
+            d->linePosn = 0;
+            return true;
+        }
+
+    }
+    return false;
+}
+
+/*!
+    Returns the full content of the line that next() positioned us on.
+    The line's prefix is not included in the return value.
+
+    \sa next(), readNumeric(), readString()
+*/
+QString QAtResultParser::line()
+{
+    return d->line;
+}
+
+/*!
+    Read a numeric value from the current line.
+
+    \sa readString(), skip()
+*/
+uint QAtResultParser::readNumeric()
+{
+    uint value = 0;
+    while ( d->linePosn < d->line.length() &&
+            d->line[d->linePosn] >= '0' && d->line[d->linePosn] <= '9' ) {
+        value = value * 10 + (uint)(d->line[d->linePosn].unicode() - '0');
+        ++(d->linePosn);
+    }
+    if ( d->linePosn < d->line.length() && d->line[d->linePosn] == ',' ) {
+        ++(d->linePosn);
+    }
+    while ( d->linePosn < d->line.length() && d->line[d->linePosn] == ' ' ) {
+        ++(d->linePosn);
+    }
+    return value;
+}
+
+static QString nextString( const QString& buf, int& posn )
+{
+    uint posn2 = (uint)posn;
+    QString result = QAtUtils::nextString( buf, posn2 );
+    posn = (int)posn2;
+    return result;
+}
+
+/*!
+    Read a string from the current line.
+
+    \sa readNumeric(), skip()
+*/
+QString QAtResultParser::readString()
+{
+    QString value = nextString( d->line, d->linePosn );
+    if ( d->linePosn < d->line.length() && d->line[d->linePosn] == ',' ) {
+        ++(d->linePosn);
+    }
+    while ( d->linePosn < d->line.length() && d->line[d->linePosn] == ' ' ) {
+        ++(d->linePosn);
+    }
+    return value;
+}
+
+/*!
+    Skip the contents of a comma-separated field in the current line.
+
+    \sa readNumeric(), readString()
+*/
+void QAtResultParser::skip()
+{
+    if ( d->linePosn < d->line.length() && d->line[d->linePosn] == ',' ) {
+        ++(d->linePosn);
+    }
+    while ( d->linePosn < d->line.length() && d->line[d->linePosn] != ',' ) {
+        ++(d->linePosn);
+    }
+}
+
+/*!
+    Read the next line of input as literal text, without looking for a prefix.
+    This is for results from commands such as \c{AT+CMGL} which place the
+    PDU on a line of its own.
+*/
+QString QAtResultParser::readNextLine()
+{
+    QString line = "";
+
+    while ( d->posn < d->response.length() &&
+            d->response[d->posn] != '\n' ) {
+        line += d->response[(d->posn)++];
+    }
+    if ( d->posn < d->response.length() ) {
+        ++(d->posn);
+    }
+
+    return line;
+}
+
+/*!
+    Returns the content of all lines that begin with \a prefix starting
+    at the current position.
+
+    \sa next()
+*/
+QStringList QAtResultParser::lines( const QString& prefix )
+{
+    QStringList result;
+    while ( next( prefix ) ) {
+        result << d->line;
+    }
+    return result;
+}
+
+/*!
+    Read a list of values surrounded by parentheses.  This is for
+    complex command results that cannot be parsed with readNumeric()
+    and readString().
+*/
+QList<QAtResultParser::Node> QAtResultParser::readList()
+{
+    QList<QAtResultParser::Node> list;
+    if ( d->linePosn < d->line.length() && d->line[d->linePosn] == '(' ) {
+        ++(d->linePosn);
+        while ( d->linePosn < d->line.length() &&
+                d->line[d->linePosn] != ')' ) {
+            uint ch = d->line[d->linePosn].unicode();
+            if ( ch >= '0' && ch <= '9' ) {
+                // Parse a number or range.
+                uint number = readNumeric();
+                if ( d->linePosn < d->line.length() &&
+                     d->line[d->linePosn] == '-' ) {
+                    ++(d->linePosn);
+                    uint last = readNumeric();
+                    list.append( QAtResultParser::Node( number, last ) );
+                } else {
+                    list.append( QAtResultParser::Node( number ) );
+                }
+            } else if ( ch == '"' ) {
+                // Parse a string.
+                list.append( QAtResultParser::Node( readString() ) );
+            } else {
+                // Encountered something unknown - bail out at this point.
+                d->linePosn = d->line.length();
+                return list;
+            }
+        }
+        if ( d->linePosn < d->line.length() ) {
+            // Skip the ')' at the end of the list.
+            ++(d->linePosn);
+            if ( d->linePosn < d->line.length() &&
+                 d->line[d->linePosn] == ',' ) {
+                // Skip a trailing comma.
+                ++(d->linePosn);
+            }
+            while ( d->linePosn < d->line.length() &&
+                 d->line[d->linePosn] == ' ' ) {
+                // Skip trailing white space.
+                ++(d->linePosn);
+            }
+        }
+    }
+    return list;
+}
+
+/*!
+    \class QAtResultParser::Node
+    \mainclass
+    \brief Provides access to a generic value parsed from an AT command list.
+
+    Instances of this class are returned from the QAtResultParser::readList() function.
+
+    \sa QAtResultParser::readList()
+*/
+
+QAtResultParser::Node::Node( uint number )
+{
+    _kind = Number;
+    _number = number;
+    _list = 0;
+}
+
+QAtResultParser::Node::Node( uint first, uint last )
+{
+    _kind = Range;
+    _number = first;
+    _last = last;
+    _list = 0;
+}
+
+QAtResultParser::Node::Node( const QString& str )
+{
+    _kind = String;
+    _str = str;
+    _list = 0;
+}
+
+QAtResultParser::Node::Node( QList<Node> *list )
+{
+    _kind = List;
+    _list = list;
+}
+
+/*!
+    Create a new result list node from \a other.
+*/
+QAtResultParser::Node::Node( const Node& other )
+{
+    _kind = other._kind;
+    _number = other._number;
+    _last = other._last;
+    _str = other._str;
+    _list = ( other._list ? new QList<Node>( *other._list ) : 0 );
+}
+
+/*!
+    Destruct this node.
+*/
+QAtResultParser::Node::~Node()
+{
+    if ( _list )
+        delete _list;
+}
+
+/*!
+    \fn bool QAtResultParser::Node::isNumber() const
+
+    Returns true of if this node contains a number; otherwise returns false.
+
+    \sa asNumber()
+*/
+
+/*!
+    \fn bool QAtResultParser::Node::isRange() const
+
+    Returns true if this node contains a range; otherwise returns false.
+
+    \sa asFirst(), asLast()
+*/
+
+/*!
+    \fn bool QAtResultParser::Node::isString() const
+
+    Returns true if this node contains a string; otherwise returns false.
+
+    \sa asString()
+*/
+
+/*!
+    \fn bool QAtResultParser::Node::isList() const
+
+    Returns true if this node contains a list; otherwise returns false.
+
+    \sa asList()
+*/
+
+/*!
+    \fn uint QAtResultParser::Node::asNumber() const
+
+    Returns the number contained within this node, or return zero if node not a number.
+
+    \sa isNumber()
+*/
+
+/*!
+    \fn uint QAtResultParser::Node::asFirst() const
+
+    Returns the first number in a range that is contained within this node; otherwise returns zero if not a range.
+
+    \sa isRange(), asLast()
+*/
+
+/*!
+    \fn uint QAtResultParser::Node::asLast() const
+
+    Returns the last number in a range that is contained within this node; otherwise returns zero if not a range.
+
+    \sa isRange(), asFirst()
+*/
+
+/*!
+    \fn QString QAtResultParser::Node::asString() const
+
+    Returns the string contained within this node; otherwise returns null if not a string.
+
+    \sa isString()
+*/
+
+/*!
+    \fn QList<QAtResultParser::Node> QAtResultParser::Node::asList() const
+
+    Returns the list contained within this node, or returns an empty list if this
+    node does not contain a list.
+
+    \sa isList()
+*/

Added: trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresultparser.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresultparser.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatresultparser.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QATRESULTPARSER_H
+#define QATRESULTPARSER_H
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qlist.h>
+#include <qtopiaglobal.h>
+
+class QAtResultParserPrivate;
+class QAtResult;
+
+class QTOPIACOMM_EXPORT QAtResultParser
+{
+public:
+    QAtResultParser( const QAtResult& result );
+    QAtResultParser( const QString& notification );
+    ~QAtResultParser();
+
+    class QTOPIACOMM_EXPORT Node
+    {
+        friend class QAtResultParser;
+    private:
+        enum Kind { Number, Range, String, List };
+
+        Node( uint number );
+        Node( uint first, uint last );
+        Node( const QString& str );
+        Node( QList<Node> *list );
+    public:
+        Node( const Node& other );
+        ~Node();
+
+        bool isNumber() const { return ( _kind == Number ); }
+        bool isRange() const { return ( _kind == Range ); }
+        bool isString() const { return ( _kind == String ); }
+        bool isList() const { return ( _kind == List ); }
+
+        uint asNumber() const { return ( _kind == Number ? _number : 0 ); }
+        uint asFirst() const { return ( _kind == Range ? _number : 0 ); }
+        uint asLast() const { return ( _kind == Range ? _last : 0 ); }
+        QString asString() const { return _str; }
+        QList<QAtResultParser::Node> asList() const
+            { return ( _list ? *_list : QList<QAtResultParser::Node>() ); }
+
+    private:
+        Kind _kind;
+        uint _number;
+        uint _last;
+        QString _str;
+        QList<QAtResultParser::Node> *_list;
+    };
+
+    void reset();
+    bool next( const QString& prefix );
+    QString line();
+    uint readNumeric();
+    QString readString();
+    void skip();
+    QString readNextLine();
+    QStringList lines( const QString& prefix );
+    QList<QAtResultParser::Node> readList();
+
+private:
+    QAtResultParserPrivate *d;
+};
+
+#endif // QATRESULTPARSER_H

Added: trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,1127 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qatutils.h>
+#include <qatresultparser.h>
+#include <qgsmcodec.h>
+#include <qtextcodec.h>
+
+/*!
+    \class QAtUtils
+    \mainclass
+    \brief The QAtUtils class provides several utility functions that assist with interfacing to AT-based modems.
+    \ingroup telephony::serial
+*/
+
+static const char hexchars[] = "0123456789ABCDEF";
+static bool octalEscapesFlag = false;
+
+/*!
+    Quote \a str so that it is suitable to be sent as an AT
+    command argument.  The caller will need to add double
+    quotes to the start and end of the return value to complete
+    the AT command argument.
+*/
+QString QAtUtils::quote( const QString& str )
+{
+    // Bail out if the string does not need to be quoted.
+    if ( str.indexOf( QChar('"') ) == -1 && str.indexOf( QChar('\\') ) == -1 &&
+         str.indexOf( QChar('\r') ) == -1 && str.indexOf( QChar('\n') ) == -1 ) {
+        return str;
+    }
+
+    // Build the quoted result.
+    QString result = "";
+    int posn = 0;
+    uint ch;
+    while ( posn < str.length() ) {
+        ch = str[posn++].unicode();
+        if ( ch == '"' || ch == '\\' || ch == '\r' || ch == '\n' ) {
+            result += (QChar)'\\';
+            result += (QChar)(hexchars[(ch >> 4) & 0x0F]);
+            result += (QChar)(hexchars[ch & 0x0F]);
+        } else {
+            result += (QChar)ch;
+        }
+    }
+    return result;
+}
+
+/*!
+    Convert the byte array, \a binary, into a hexadecimal string.
+
+    \sa fromHex()
+*/
+QString QAtUtils::toHex( const QByteArray& binary )
+{
+    QString str = "";
+    static char const hexchars[] = "0123456789ABCDEF";
+
+    for ( int i = 0; i < binary.size(); i++ ) {
+        str += (QChar)(hexchars[ (binary[i] >> 4) & 0x0F ]);
+        str += (QChar)(hexchars[ binary[i] & 0x0F ]);
+    }
+
+    return str;
+}
+
+/*!
+    Convert a hexadecimal string, \a hex, into a byte array.
+
+    \sa toHex()
+*/
+QByteArray QAtUtils::fromHex( const QString& hex )
+{
+    QByteArray bytes;
+    uint ch;
+    int posn;
+    int nibble, value, flag, size;
+
+    flag = 0;
+    value = 0;
+    size = 0;
+    for ( posn = 0; posn < hex.length(); ++posn ) {
+        ch = (uint)( hex[posn].unicode() );
+        if ( ch >= '0' && ch <= '9' ) {
+            nibble = ch - '0';
+        } else if ( ch >= 'A' && ch <= 'F' ) {
+            nibble = ch - 'A' + 10;
+        } else if ( ch >= 'a' && ch <= 'f' ) {
+            nibble = ch - 'a' + 10;
+        } else {
+            continue;
+        }
+        value = (value << 4) | nibble;
+        flag = !flag;
+        if ( !flag ) {
+            bytes.resize( size + 1 );
+            bytes[size++] = (char)value;
+            value = 0;
+        }
+    }
+
+    return bytes;
+}
+
+/*!
+    Decode a phone number from \a value and \a type.  The \a type is
+    a type of address octet, usually 145 for international numbers
+    and 129 for local numbers.  The return will normalize the
+    value to include the \c{+} prefix for international numbers.
+
+    \sa encodeNumber()
+*/
+QString QAtUtils::decodeNumber( const QString& value, uint type )
+{
+    if ( type == 145 && value.length() != 0 && value[0] != '+' )
+        return "+" + value;
+    else
+        return value;
+}
+
+/*!
+    Read a string field and a numeric field from \a parser and
+    then decode them into a properly normalized phone number.
+
+    \sa encodeNumber()
+*/
+QString QAtUtils::decodeNumber( QAtResultParser& parser )
+{
+    QString value = parser.readString();
+    uint type = parser.readNumeric();
+    return decodeNumber( value, type );
+}
+
+/*!
+    Encode the phone number in \a value into a string plus a
+    type of address octet.  International numbers that start
+    with \c{+} become \c{"number",145}, and local numbers
+    become \c{"number",129}.  If \a keepPlus is true,
+    then the \c{+} will be left on the resulting number,
+    even if the type is 145.
+
+    \sa decodeNumber()
+*/
+QString QAtUtils::encodeNumber( const QString& value, bool keepPlus )
+{
+    if ( value.length() > 0 && value[0] == '+' ) {
+        if ( keepPlus )
+            return "\"" + quote( value ) + "\",145";
+        else
+            return "\"" + quote( value.mid(1) ) + "\",145";
+    } else {
+        return "\"" + quote( value ) + "\",129";
+    }
+}
+
+static int FromHexDigit( uint ch )
+{
+    if ( ch >= '0' && ch <= '9' ) {
+        return (int)( ch - '0' );
+    } else if ( ch >= 'A' && ch <= 'F' ) {
+        return (int)( ch - 'A' + 10 );
+    } else if ( ch >= 'a' && ch <= 'f' ) {
+        return (int)( ch - 'a' + 10 );
+    } else {
+        return -1;
+    }
+}
+
+static int FromOctalDigit( uint ch )
+{
+    if ( ch >= '0' && ch <= '7' ) {
+        return (int)( ch - '0' );
+    } else {
+        return -1;
+    }
+}
+
+/*!
+    Extract the next quoted string from \a buf, starting at
+    \a posn.
+
+    \sa parseNumber(), skipField()
+*/
+QString QAtUtils::nextString( const QString& buf, uint& posn )
+{
+    QString result = "";
+    uint ch;
+    int digit, digit2, digit3;
+    while ( posn < (uint)(buf.length()) && buf[posn] != '"' ) {
+        ++posn;
+    }
+    if ( posn >= (uint)(buf.length()) ) {
+        return result;
+    }
+    ++posn;
+    while ( posn < (uint)(buf.length()) && ( ch = buf[posn].unicode() ) != '"' ) {
+        ++posn;
+        if ( ch == '\\' ) {
+            if ( !octalEscapesFlag ) {
+                // Hex-quoted character.
+                if ( posn >= (uint)buf.length() )
+                    break;
+                digit = FromHexDigit( buf[posn].unicode() );
+                if ( digit == -1 ) {
+                    result += (QChar)'\\';
+                    continue;
+                }
+                if ( ( posn + 1 ) >= (uint)buf.length() ) {
+                    ch = (uint)digit;
+                    ++posn;
+                } else {
+                    digit2 = FromHexDigit( buf[posn + 1].unicode() );
+                    if ( digit2 == -1 ) {
+                        ch = (uint)digit;
+                        ++posn;
+                    } else {
+                        ch = (uint)(digit * 16 + digit2);
+                        posn += 2;
+                    }
+                }
+            } else {
+                // Octal-quoted character.
+                if ( posn >= (uint)buf.length() )
+                    break;
+                digit = FromOctalDigit( buf[posn].unicode() );
+                if ( digit == -1 ) {
+                    result += (QChar)'\\';
+                    continue;
+                }
+                if ( ( posn + 1 ) >= (uint)buf.length() ) {
+                    ch = (uint)digit;
+                    ++posn;
+                } else {
+                    digit2 = FromOctalDigit( buf[posn + 1].unicode() );
+                    if ( digit2 == -1 ) {
+                        ch = (uint)digit;
+                        ++posn;
+                    } else {
+                        if ( ( posn + 2 ) >= (uint)buf.length() ) {
+                            ch = (uint)(digit * 8 + digit2);
+                            posn += 2;
+                        } else {
+                            digit3 = FromOctalDigit( buf[posn + 2].unicode() );
+                            if ( digit3 == -1 ) {
+                                ch = (uint)(digit * 8 + digit2);
+                                posn += 2;
+                            } else {
+                                ch = (uint)(digit * 64 + digit2 * 8 + digit3);
+                                posn += 3;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        result += (QChar)ch;
+    }
+    if ( posn < (uint)buf.length() ) {
+        ++posn;
+    }
+    return result;
+}
+
+/*!
+    Utility function for parsing a number from position \a posn in \a str.
+
+    \sa nextString(), skipField()
+*/
+uint QAtUtils::parseNumber( const QString& str, uint& posn )
+{
+    uint num = 0;
+    while ( posn < (uint)str.length() && ( str[posn] == ' ' || str[posn] == ',' ) ) {
+        ++posn;
+    }
+    while ( posn < (uint)str.length() && str[posn] >= '0' && str[posn] <= '9' ) {
+        num = num * 10 + (uint)(str[posn].unicode() - '0');
+        ++posn;
+    }
+    return num;
+}
+
+/*!
+    Utility function for skipping a comma-delimited field starting
+    at \a posn within \a str.
+
+    \sa nextString(), parseNumber()
+*/
+void QAtUtils::skipField( const QString& str, uint& posn )
+{
+    if ( posn < (uint)str.length() && str[posn] == ',' ) {
+        ++posn;
+    }
+    while ( posn < (uint)str.length() && str[posn] != ',' ) {
+        ++posn;
+    }
+}
+
+class QGsmHexCodec : public QTextCodec
+{
+public:
+    QGsmHexCodec();
+    ~QGsmHexCodec();
+
+    QByteArray name() const;
+    int mibEnum() const;
+
+protected:
+    QString convertToUnicode(const char *in, int length, ConverterState *state) const;
+    QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const;
+};
+
+QGsmHexCodec::QGsmHexCodec()
+{
+}
+
+QGsmHexCodec::~QGsmHexCodec()
+{
+}
+
+QByteArray QGsmHexCodec::name() const
+{
+    return QByteArray( "gsm-hex" );
+}
+
+int QGsmHexCodec::mibEnum() const
+{
+    return 61239;
+}
+
+QString QGsmHexCodec::convertToUnicode(const char *in, int length, ConverterState *) const
+{
+    QString str;
+    int nibble = 0;
+    int value = 0;
+    int digit;
+    bool secondByte = false;
+    while ( length-- > 0 ) {
+        char ch = *in++;
+        if ( ch >= '0' && ch <= '9' )
+            digit = ch - '0';
+        else if ( ch >= 'A' && ch <= 'F' )
+            digit = ch - 'A' + 10;
+        else if ( ch >= 'a' && ch <= 'f' )
+            digit = ch - 'a' + 10;
+        else
+            continue;
+        if ( !nibble ) {
+            value = digit * 16;
+            nibble = 1;
+        } else {
+            value += digit;
+            if ( !secondByte ) {
+                if ( value != 0x1B ) {
+                    str += QGsmCodec::twoByteToUnicode( (unsigned short)value );
+                } else {
+                    secondByte = true;
+                }
+            } else {
+                value += 0x1B00;
+                str += QGsmCodec::twoByteToUnicode( (unsigned short)value );
+                secondByte = false;
+            }
+            nibble = 0;
+        }
+    }
+    return str;
+}
+
+QByteArray QGsmHexCodec::convertFromUnicode(const QChar *in, int length, ConverterState *) const
+{
+    QByteArray buf;
+    while ( length-- > 0 ) {
+        unsigned short ch = QGsmCodec::twoByteFromUnicode( *in++ );
+        if ( ch >= 256 ) {
+            buf += hexchars[ (ch >> 12) & 0x0F ];
+            buf += hexchars[ (ch >> 8) & 0x0F ];
+        }
+        buf += hexchars[ (ch >> 4) & 0x0F ];
+        buf += hexchars[ ch & 0x0F ];
+    }
+    return buf;
+}
+
+class QUcs2HexCodec : public QTextCodec
+{
+public:
+    QUcs2HexCodec();
+    ~QUcs2HexCodec();
+
+    QByteArray name() const;
+    int mibEnum() const;
+
+protected:
+    QString convertToUnicode(const char *in, int length, ConverterState *state) const;
+    QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const;
+};
+
+QUcs2HexCodec::QUcs2HexCodec()
+{
+}
+
+QUcs2HexCodec::~QUcs2HexCodec()
+{
+}
+
+QByteArray QUcs2HexCodec::name() const
+{
+    return "ucs2-hex";
+}
+
+int QUcs2HexCodec::mibEnum() const
+{
+    return 61240;
+}
+
+QString QUcs2HexCodec::convertToUnicode(const char *in, int length, ConverterState *) const
+{
+    QString str;
+    int nibble = 0;
+    int value = 0;
+    int digit;
+    while ( length-- > 0 ) {
+        char ch = *in++;
+        if ( ch >= '0' && ch <= '9' )
+            digit = ch - '0';
+        else if ( ch >= 'A' && ch <= 'F' )
+            digit = ch - 'A' + 10;
+        else if ( ch >= 'a' && ch <= 'f' )
+            digit = ch - 'a' + 10;
+        else
+            continue;
+        value = value * 16 + digit;
+        ++nibble;
+        if ( nibble >= 4 ) {
+            str += QChar( (ushort)value );
+            nibble = 0;
+            value = 0;
+        }
+    }
+    return str;
+}
+
+QByteArray QUcs2HexCodec::convertFromUnicode(const QChar *in, int length, ConverterState *) const
+{
+    QByteArray buf;
+    while ( length-- > 0 ) {
+        uint ch = in->unicode();
+        ++in;
+        buf += hexchars[ (ch >> 12) & 0x0F ];
+        buf += hexchars[ (ch >> 8) & 0x0F ];
+        buf += hexchars[ (ch >> 4) & 0x0F ];
+        buf += hexchars[ ch & 0x0F ];
+    }
+    return buf;
+}
+
+class QCodePage437Codec : public QTextCodec
+{
+public:
+    QCodePage437Codec();
+    ~QCodePage437Codec();
+
+    QByteArray name() const;
+    QList<QByteArray> aliases() const;
+    int mibEnum() const;
+
+protected:
+    QString convertToUnicode(const char *in, int length, ConverterState *state) const;
+    QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const;
+};
+
+// Convert IBM437 character codes 0x00 - 0xFF into Unicode.
+static ushort const cp437ToUnicode[256] =
+   {0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+    0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+    0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+    0x0018, 0x0019, 0x001c, 0x001b, 0x007f, 0x001d, 0x001e, 0x001f,
+    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+    0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+    0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x001a,
+    0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+    0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+    0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+    0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
+    0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
+    0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+    0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
+    0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
+    0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
+    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
+    0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
+    0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x03bc, 0x03c4,
+    0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
+    0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
+    0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0};
+
+
+
+// Convert Unicode 0x0000 - 0x00FF into IBM437.
+static unsigned char const cp437FromUnicode[256] =
+   {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x7f, 0x1b, 0x1a, 0x1d, 0x1e, 0x1f,
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x1c,
+    '?' , '?' , '?' , '?' , '?' , '?' , '?' , '?' ,
+    '?' , '?' , '?' , '?' , '?' , '?' , '?' , '?' ,
+    '?' , '?' , '?' , '?' , '?' , '?' , '?' , '?' ,
+    '?' , '?' , '?' , '?' , '?' , '?' , '?' , '?' ,
+    0xff, 0xad, 0x9b, 0x9c, '?' , 0x9d, '?' , 0x15,
+    '?' , '?' , 0xa6, 0xae, 0xaa, '?' , '?' , '?' ,
+    0xf8, 0xf1, 0xfd, '?' , '?' , '?' , 0x14, 0xfa,
+    '?' , '?' , 0xa7, 0xaf, 0xac, 0xab, '?' , 0xa8,
+    '?' , '?' , '?' , '?' , 0x8e, 0x8f, 0x92, 0x80,
+    '?' , 0x90, '?' , '?' , '?' , '?' , '?' , '?' ,
+    '?' , 0xa5, '?' , '?' , '?' , '?' , 0x99, '?' ,
+    '?' , '?' , '?' , '?' , 0x9a, '?' , '?' , 0xe1,
+    0x85, 0xa0, 0x83, '?' , 0x84, 0x86, 0x91, 0x87,
+    0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
+    '?' , 0xa4, 0x95, 0xa2, 0x93, '?' , 0x94, 0xf6,
+    '?' , 0x97, 0xa3, 0x96, 0x81, '?' , '?' , 0x98};
+
+QCodePage437Codec::QCodePage437Codec()
+{
+}
+
+QCodePage437Codec::~QCodePage437Codec()
+{
+}
+
+QByteArray QCodePage437Codec::name() const
+{
+    return "IBM437";
+}
+
+QList<QByteArray> QCodePage437Codec::aliases() const
+{
+    QList<QByteArray> list;
+    list << "CP437";
+    return list;
+}
+
+int QCodePage437Codec::mibEnum() const
+{
+    return 437;
+}
+
+QString QCodePage437Codec::convertToUnicode(const char *in, int length, ConverterState *) const
+{
+    QString str;
+    if ( length >= 6 && in[0] == '8' && in[1] == '0' &&
+         in[length - 4] == 'F' && in[length - 3] == 'F' &&
+         in[length - 2] == 'F' && in[length - 1] == 'F') {
+
+        // UCS-2 string embedded within a 437-encoded string.
+        int nibble = 0;
+        int value = 0;
+        int digit;
+        in += 2;
+        length -= 6;
+        while ( length-- > 0 ) {
+            char ch = *in++;
+            if ( ch >= '0' && ch <= '9' )
+                digit = ch - '0';
+            else if ( ch >= 'A' && ch <= 'F' )
+                digit = ch - 'A' + 10;
+            else if ( ch >= 'a' && ch <= 'f' )
+                digit = ch - 'a' + 10;
+            else
+                continue;
+            value = value * 16 + digit;
+            ++nibble;
+            if ( nibble >= 4 ) {
+                str += QChar( (ushort)value );
+                nibble = 0;
+                value = 0;
+            }
+        }
+
+    } else {
+
+        // Regular 437-encoded string.
+        while ( length-- > 0 )
+            str += QChar((unsigned int)cp437ToUnicode[*in++ & 0xFF]);
+
+    }
+    return str;
+}
+
+QByteArray QCodePage437Codec::convertFromUnicode(const QChar *in, int length, ConverterState *) const
+{
+    QByteArray result;
+    unsigned int ch;
+    char *out;
+
+    // Determine if the string should be encoded using the UCS-2 hack.
+    bool non437 = false;
+    for ( int posn = 0; !non437 && posn < length; ++posn ) {
+        ch = in[posn].unicode();
+        if ( ch >= 0x0100 )
+            non437 = true;
+        else if ( cp437FromUnicode[ch] == '?' && ch != '?' )
+            non437 = true;
+    }
+    if ( non437 ) {
+        // There is a non CP437 character in this string, so use UCS-2.
+        result.resize( length * 4 + 6 );
+        out = result.data();
+        *out++ = '8';
+        *out++ = '0';
+        while ( length-- > 0 ) {
+            uint ch = in->unicode();
+            ++in;
+            *out++ = hexchars[ (ch >> 12) & 0x0F ];
+            *out++ = hexchars[ (ch >> 8) & 0x0F ];
+            *out++ = hexchars[ (ch >> 4) & 0x0F ];
+            *out++ = hexchars[ ch & 0x0F ];
+        }
+        *out++ = 'F';
+        *out++ = 'F';
+        *out++ = 'F';
+        *out   = 'F';
+        return result;
+    }
+
+    // If we get here, we can guarantee that the string only contains
+    // valid CP437 code points between 0x0000 and 0x00FF.
+    result.resize( length );
+    out = result.data();
+    while ( length-- > 0 ) {
+        *out++ = (char)cp437FromUnicode[in->unicode()];
+        ++in;
+    }
+    return result;
+}
+
+class QCodePage850Codec : public QTextCodec
+{
+public:
+    QCodePage850Codec();
+    ~QCodePage850Codec();
+
+    QByteArray name() const;
+    QList<QByteArray> aliases() const;
+    int mibEnum() const;
+
+protected:
+    QString convertToUnicode(const char *in, int length, ConverterState *state) const;
+    QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const;
+};
+
+// Convert IBM850 character codes 0x00 - 0xFF into Unicode.
+static ushort const cp850ToUnicode[256] = {
+    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 
+    0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 
+    0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 
+    0x0018, 0x0019, 0x001c, 0x001b, 0x007f, 0x001d, 0x001e, 0x001f, 
+    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 
+    0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 
+    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 
+    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 
+    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 
+    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, 
+    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 
+    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 
+    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 
+    0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 
+    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 
+    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x001a, 
+    0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 
+    0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5, 
+    0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 
+    0x00ff, 0x00d6, 0x00dc, 0x00f8, 0x00a3, 0x00d8, 0x00d7, 0x0192, 
+    0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 
+    0x00bf, 0x00ae, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb, 
+    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00c1, 0x00c2, 0x00c0, 
+    0x00a9, 0x2563, 0x2551, 0x2557, 0x255d, 0x00a2, 0x00a5, 0x2510, 
+    0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x00e3, 0x00c3, 
+    0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x00a4, 
+    0x00f0, 0x00d0, 0x00ca, 0x00cb, 0x00c8, 0x0131, 0x00cd, 0x00ce, 
+    0x00cf, 0x2518, 0x250c, 0x2588, 0x2584, 0x00a6, 0x00cc, 0x2580, 
+    0x00d3, 0x00df, 0x00d4, 0x00d2, 0x00f5, 0x00d5, 0x00b5, 0x00fe, 
+    0x00de, 0x00da, 0x00db, 0x00d9, 0x00fd, 0x00dd, 0x00af, 0x00b4, 
+    0x00ad, 0x00b1, 0x2017, 0x00be, 0x00b6, 0x00a7, 0x00f7, 0x00b8, 
+    0x00b0, 0x00a8, 0x00b7, 0x00b9, 0x00b3, 0x00b2, 0x25a0, 0x00a0,
+};
+
+// Convert Unicode 0x0000 - 0x00FF into IBM850.
+static unsigned char const cp850FromUnicode[256] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+    0x18, 0x19, 0x7f, 0x1b, 0x1a, 0x1d, 0x1e, 0x1f, 
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 
+    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 
+    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
+    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
+    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 
+    0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 
+    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
+    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
+    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
+    0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x1c, 
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 
+    0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 
+    0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 
+    0xff, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, 
+    0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, 
+    0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, 
+    0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, 
+    0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, 
+    0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, 
+    0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, 
+    0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, 
+    0x85, 0xa0, 0x83, 0xc6, 0x84, 0x86, 0x91, 0x87, 
+    0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, 
+    0xd0, 0xa4, 0x95, 0xa2, 0x93, 0xe4, 0x94, 0xf6, 
+    0x9b, 0x97, 0xa3, 0x96, 0x81, 0xec, 0xe7, 0x98
+};
+
+// Compact mapping table for converting Unicode 0x0100 - 0xFFFF into IBM850.
+static ushort const cp850MappingInput[] = {
+    0x0110, 0x0131, 0x0192, 0x2017, 0x2022, 0x203c, 0x203e, 0x2190, 
+    0x2191, 0x2192, 0x2193, 0x2194, 0x2195, 0x21a8, 0x221f, 0x2302, 
+    0x2500, 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 
+    0x252c, 0x2534, 0x253c, 0x2550, 0x2551, 0x2554, 0x2557, 0x255a, 
+    0x255d, 0x2560, 0x2563, 0x2566, 0x2569, 0x256c, 0x2580, 0x2584, 
+    0x2588, 0x2591, 0x2592, 0x2593, 0x25a0, 0x25ac, 0x25b2, 0x25ba, 
+    0x25bc, 0x25c4, 0x25cb, 0x25d8, 0x25d9, 0x263a, 0x263b, 0x263c, 
+    0x2640, 0x2642, 0x2660, 0x2663, 0x2665, 0x2666, 0x266a, 0x266c, 
+    0xff01, 0xff02, 0xff03, 0xff04, 0xff05, 0xff06, 0xff07, 0xff08, 
+    0xff09, 0xff0a, 0xff0b, 0xff0c, 0xff0d, 0xff0e, 0xff0f, 0xff10, 
+    0xff11, 0xff12, 0xff13, 0xff14, 0xff15, 0xff16, 0xff17, 0xff18, 
+    0xff19, 0xff1a, 0xff1b, 0xff1c, 0xff1d, 0xff1e, 0xff1f, 0xff20, 
+    0xff21, 0xff22, 0xff23, 0xff24, 0xff25, 0xff26, 0xff27, 0xff28, 
+    0xff29, 0xff2a, 0xff2b, 0xff2c, 0xff2d, 0xff2e, 0xff2f, 0xff30, 
+    0xff31, 0xff32, 0xff33, 0xff34, 0xff35, 0xff36, 0xff37, 0xff38, 
+    0xff39, 0xff3a, 0xff3b, 0xff3c, 0xff3d, 0xff3e, 0xff3f, 0xff40, 
+    0xff41, 0xff42, 0xff43, 0xff44, 0xff45, 0xff46, 0xff47, 0xff48, 
+    0xff49, 0xff4a, 0xff4b, 0xff4c, 0xff4d, 0xff4e, 0xff4f, 0xff50, 
+    0xff51, 0xff52, 0xff53, 0xff54, 0xff55, 0xff56, 0xff57, 0xff58, 
+    0xff59, 0xff5a, 0xff5b, 0xff5c, 0xff5d, 0xff5e, 0xffe8, 0xffe9, 
+    0xffea, 0xffeb, 0xffec, 0xffed, 0xffee
+};
+static unsigned char const cp850MappingOutput[] = {
+    0xd1, 0xd5, 0x9f, 0xf2, 0x07, 0x13, 0xee, 0x1b, 
+    0x18, 0x1a, 0x19, 0x1d, 0x12, 0x17, 0x1c, 0x7f, 
+    0xc4, 0xb3, 0xda, 0xbf, 0xc0, 0xd9, 0xc3, 0xb4, 
+    0xc2, 0xc1, 0xc5, 0xcd, 0xba, 0xc9, 0xbb, 0xc8, 
+    0xbc, 0xcc, 0xb9, 0xcb, 0xca, 0xce, 0xdf, 0xdc, 
+    0xdb, 0xb0, 0xb1, 0xb2, 0xfe, 0x16, 0x1e, 0x10, 
+    0x1f, 0x11, 0x09, 0x08, 0x0a, 0x01, 0x02, 0x0f, 
+    0x0c, 0x0b, 0x06, 0x05, 0x03, 0x04, 0x0d, 0x0e, 
+    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 
+    0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 
+    0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 
+    0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 
+    0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 
+    0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 
+    0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 
+    0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 
+    0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 
+    0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 
+    0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 
+    0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0xb3, 0x1b, 
+    0x18, 0x1a, 0x19, 0xfe, 0x09
+};
+#define cp850MappingSize ((int)sizeof(cp850MappingInput))
+
+QCodePage850Codec::QCodePage850Codec()
+{
+}
+
+QCodePage850Codec::~QCodePage850Codec()
+{
+}
+
+QByteArray QCodePage850Codec::name() const
+{
+    return "IBM850";
+}
+
+QList<QByteArray> QCodePage850Codec::aliases() const
+{
+    QList<QByteArray> list;
+    list << "CP850";
+    return list;
+}
+
+int QCodePage850Codec::mibEnum() const
+{
+    return 2009;
+}
+
+QString QCodePage850Codec::convertToUnicode(const char *in, int length, ConverterState *) const
+{
+    QString str;
+    while ( length-- > 0 )
+        str += QChar((unsigned int)cp850ToUnicode[*in++ & 0xFF]);
+    return str;
+}
+
+QByteArray QCodePage850Codec::convertFromUnicode(const QChar *in, int length, ConverterState *) const
+{
+    QByteArray result;
+    unsigned int ch;
+    char *out;
+    result.resize( length );
+    out = result.data();
+    while ( length-- > 0 ) {
+        ch = in->unicode();
+        ++in;
+        if ( ch < 0x0100 ) {
+            *out++ = (char)cp850FromUnicode[ch];
+        } else {
+            // Perform a binary search on the sparse mapping table.
+            int left = 0;
+            int right = cp850MappingSize - 1;
+            int middle;
+            while ( left <= right ) {
+                middle = (left + right) / 2;
+                if ( ch < cp850MappingInput[middle] ) {
+                    right = middle - 1;
+                } else if ( ch > cp850MappingInput[middle] ) {
+                    left = middle + 1;
+                } else {
+                    *out++ = (char)cp850MappingOutput[middle];
+                    break;
+                }
+            }
+            if ( left > right ) {
+                *out++ = '?';
+            }
+        }
+    }
+    return result;
+}
+
+/*!
+    Returns the text codec for the GSM character set identifier \a gsmCharset.
+    The returned object should not be deleted.
+
+    The following standard GSM character sets from 3GPP TS 27.007 are recognized:
+
+    \table
+        \row \o \c GSM \o 7-bit default GSM alphabet.  There may be some loss of information
+                          where multiple Unicode characters map to the same 7-bit encoding.
+        \row \o \c HEX \o Hex encoding of the 7-bit default GSM alphabet.
+        \row \o \c UCS2 \o Hex encoding of UCS-2.
+        \row \o \c IRA \o International reference alphabet (i.e. ASCII).
+        \row \o \c PCCPxxx \o PC character set code page \c xxx.  Code pages 437 and 850
+                        are guaranteed to be supported.  Other code pages depend upon
+                        the codecs installed with QTextCodec.
+        \row \o \c PCDN \o PC Danish/Norwegian character set (same as \c PCCP850).
+        \row \o \c UTF-8 \o 8-bit encoding of Unicode.
+        \row \o \c 8859-n \o ISO 8859 Latin-n character set.
+        \row \o \c 8859-C \o ISO 8859 Latin/Cyrillic character set (same as \c 8859-5).
+        \row \o \c 8859-A \o ISO 8859 Latin/Arabic character set (same as \c 8859-6).
+        \row \o \c 8859-G \o ISO 8859 Latin/Greek character set (same as \c 8859-7).
+        \row \o \c 8859-H \o ISO 8859 Latin/Hebrew character set (same as \c 8859-8).
+    \endtable
+
+    This implementation also supports the following character sets, beyond those
+    mandated by 3GPP TS 27.007:
+
+    \table
+        \row \o \c gsm-noloss \o 7-bit default GSM alphabet, with no loss of information.
+        \row \o \c xxx \o Any codec \c xxx that is supported by QTextCodec::codecForName().
+    \endtable
+
+    \sa QTextCodec, QGsmCodec
+*/
+QTextCodec *QAtUtils::codec( const QString& gsmCharset )
+{
+    QString cs = gsmCharset.toLower();
+    QTextCodec *codec = 0;
+
+    // Convert the name into an appropriate codec.
+    if ( cs == "gsm" ) {
+        // 7-bit GSM character set.
+        static QTextCodec *gsm = 0;
+        if ( !gsm )
+            gsm = new QGsmCodec();
+        codec = gsm;
+    } else if ( cs == "gsm-noloss" ) {
+        // 7-bit GSM character set, with no loss of quality.
+        static QTextCodec *gsmNoLoss = 0;
+        if ( !gsmNoLoss )
+            gsmNoLoss = new QGsmCodec( true );
+        codec = gsmNoLoss;
+    } else if ( cs == "hex" ) {
+        // Direct hex character set.  The underlying character set could
+        // be anything according to the specification, but we need to pick
+        // something.  We assume that it is 7-bit GSM, as that is the most
+        // likely value.
+        static QTextCodec *hex = 0;
+        if ( !hex )
+            hex = new QGsmHexCodec();
+        codec = hex;
+    } else if ( cs == "ucs2" ) {
+        // Hex-encoded UCS2 character set.
+        static QTextCodec *ucs2 = 0;
+        if ( !ucs2 )
+            ucs2 = new QUcs2HexCodec();
+        codec = ucs2;
+    } else if ( cs == "ira" ) {
+        // International Reference Alphabet (i.e. ASCII).  Use Latin-1 codec.
+        codec = QTextCodec::codecForName( "ISO-8859-1" );
+    } else if ( cs == "pccp437" ) {
+        // PC DOS code page 437, which isn't standard in Qt,
+        // but which is the default charset for Wavecom modems.
+        //
+        // Wavecom also has a horrible hack in its PCCP437 implementation
+        // to handle embedded UCS-2 character strings.  A hex UCS-2 string
+        // will start with "80" and end with "FFFF".  If the string does
+        // not have this format, it is interpreted as code page 437.
+        static QTextCodec *cp437 = 0;
+        if ( !cp437 )
+            cp437 = new QCodePage437Codec();
+        codec = cp437;
+    } else if ( cs == "pcdn" || cs == "pccp850" ) {
+        // PC Danish/Norwegian character set.  Map to PC code page 850.
+        codec = QTextCodec::codecForName( "CP850" );
+        if ( !codec ) {
+            // Qt does not have CP850 (i.e. QT_NO_CODECS is defined),
+            // so we need to provide our own implementation.  The next
+            // time we are called, codecForName( "CP850" ) will return
+            // this object, so we won't need to allocate again.
+            codec = new QCodePage850Codec();
+        }
+    } else if ( cs.startsWith( "pccp" ) ) {
+        // Some other PC DOS code page.
+        codec = QTextCodec::codecForName( "CP" + cs.mid(4).toLatin1() );
+    } else if ( cs == "8859-c" ) {
+        // ISO 8859 Latin/Cyrillic - same as ISO-8859-5.
+        codec = QTextCodec::codecForName( "ISO-8859-5" );
+    } else if ( cs == "8859-a" ) {
+        // ISO 8859 Latin/Arabic - same as ISO-8859-6.
+        codec = QTextCodec::codecForName( "ISO-8859-6" );
+    } else if ( cs == "8859-g" ) {
+        // ISO 8859 Latin/Greek - same as ISO-8859-7.
+        codec = QTextCodec::codecForName( "ISO-8859-7" );
+    } else if ( cs == "8859-h" ) {
+        // ISO 8859 Latin/Hebrew - same as ISO-8859-8.
+        codec = QTextCodec::codecForName( "ISO-8859-8" );
+    } else if ( cs.startsWith( "8859-" ) ) {
+        // ISO-8859-n character set.
+        codec = QTextCodec::codecForName( "ISO-" + cs.toLatin1() );
+    } else {
+        // Not one of the standard GSM charset specifiers.  Look it up as-is.
+        codec = QTextCodec::codecForName( gsmCharset.toLatin1() );
+    }
+
+    // Return the codec that we found, or bail out with Latin1 if unknown.
+    if ( codec )
+        return codec;
+    else
+        return QTextCodec::codecForName( "ISO-8859-1" );
+}
+
+/*!
+    Quote \a str so that it is suitable to be sent as an AT
+    command argument and use \a codec to encode the string.
+    The caller will need to add double quotes to the start and
+    end of the return value to complete the AT command argument.
+*/
+QString QAtUtils::quote( const QString& str, QTextCodec *codec )
+{
+    // Convert the string into raw bytes.
+    QByteArray bytes;
+    if ( codec )
+        bytes = codec->fromUnicode( str );
+    else
+        bytes = str.toLatin1();
+
+    // Determine if we need to apply quoting to the string.
+    if ( bytes.indexOf( '"' ) == -1 && bytes.indexOf( '\\' ) == -1 &&
+         bytes.indexOf( '\r' ) == -1 && bytes.indexOf( '\n' ) == -1 ) {
+        return QString::fromLatin1( bytes.data(), bytes.length() );
+    }
+
+    // Create a new string for the quoted form.  The result is suitable
+    // for converting to bytes again with toLatin1 in QAtChat::writeLine().
+    QString result = "";
+    int posn = 0;
+    int ch;
+    while ( posn < bytes.length() ) {
+        ch = bytes[posn++] & 0xFF;
+        if ( ch == '"' || ch == '\\' || ch == '\r' || ch == '\n' ) {
+            result += (QChar)'\\';
+            result += (QChar)(hexchars[(ch >> 4) & 0x0F]);
+            result += (QChar)(hexchars[ch & 0x0F]);
+        } else {
+            result += (QChar)ch;
+        }
+    }
+    return result;
+}
+
+/*!
+    Decode \a str according to \a codec.  The string is assumed to have
+    been retrieved from an AT modem using the facilities in QAtChat
+    and QAtResultParser.
+*/
+QString QAtUtils::decode( const QString& str, QTextCodec *codec )
+{
+    if ( codec )
+        return codec->toUnicode( str.toLatin1() );
+    else
+        return str;
+}
+
+/*!
+    Strip non-digit characters from \a number and normalize special
+    characters.  The digit and special characters are normalized as follows:
+
+    \table
+        \header \o Input \o Normalized \o Meaning
+        \row \o \c 0..9 \o \c 0..9 \o Numeric dialing digits
+        \row \o \c ABCD \o \c ABCD \o Alphabetic dialing digits
+        \row \o \c abcd \o \c ABCD \o Alphabetic dialing digits
+        \row \o \c ,pPxX \o \c , \o Short pause or extension separator
+        \row \o \c wW \o \c W \o Wait for dial tone
+        \row \o \c ! \o \c ! \o Hook flash
+        \row \o \c @ \o \c @ \o Wait for silence
+    \endtable
+
+    All other characters are stripped from \a number.
+
+    \sa QPhoneNumber::resolveLetters()
+*/
+QString QAtUtils::stripNumber( const QString& number )
+{
+    QString n = "";
+    int posn;
+    uint ch;
+    for ( posn = 0; posn < number.length(); ++posn ) {
+        ch = number[posn].unicode();
+        if ( ch >= '0' && ch <= '9' ) {
+            n += (QChar)ch;
+        } else if ( ch == '+' || ch == '#' || ch == '*' ) {
+            n += (QChar)ch;
+        } else if ( ch == 'A' || ch == 'B' || ch == 'C' || ch == 'D' ) {
+            // ABCD can actually be digits!
+            n += (QChar)ch;
+        } else if ( ch == 'a' || ch == 'b' || ch == 'c' || ch == 'd' ) {
+            n += (QChar)( ch - 'a' + 'A' );
+        } else if ( ch == ',' || ch == 'p' || ch == 'P' || ch == 'X' || ch == 'x' ) {
+            // Comma and 'p' mean a short pause.
+            // 'x' means an extension, which for now is the same as a pause.
+            n += (QChar)',';
+        } else if ( ch == 'w' || ch == 'W' ) {
+            // 'w' means wait for dial tone.
+            n += (QChar)'W';
+        } else if ( ch == '!' || ch == '@' ) {
+            // '!' = hook flash, '@' = wait for silence.
+            n += (QChar)ch;
+        }
+    }
+    return n;
+}
+
+/*!
+    Returns true if nextString() should parse backslash escape
+    sequences in octal rather than the default of hexadecimal; otherwise returns false.
+
+    \sa setOctalEscapes()
+*/
+bool QAtUtils::octalEscapes()
+{
+    return octalEscapesFlag;
+}
+
+/*!
+    Indicate that nextString() should parse backslash escape
+    sequences in octal if \a value is true, rather than the
+    default of hexadecimal (\a value is false).
+
+    \sa octalEscapes()
+*/
+void QAtUtils::setOctalEscapes( bool value )
+{
+    octalEscapesFlag = value;
+}

Added: trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/serial/qatutils.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QATUTILS_P_H
+#define QATUTILS_P_H
+
+#include <qtopiaglobal.h>
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qbytearray.h>
+
+class QAtResultParser;
+class QTextCodec;
+
+class QTOPIACOMM_EXPORT QAtUtils
+{
+private:
+    QAtUtils() {}
+
+public:
+
+    static QString quote( const QString& str );
+    static QString quote( const QString& str, QTextCodec *codec );
+    static QString decode( const QString& str, QTextCodec *codec );
+    static QTextCodec *codec( const QString& gsmCharset );
+    static QString toHex( const QByteArray& binary );
+    static QByteArray fromHex( const QString& hex );
+    static QString decodeNumber( const QString& value, uint type );
+    static QString decodeNumber( QAtResultParser& parser );
+    static QString encodeNumber( const QString& value, bool keepPlus = false );
+    static QString nextString( const QString& buf, uint& posn );
+    static uint parseNumber( const QString& str, uint& posn );
+    static void skipField( const QString& str, uint& posn );
+    static QString stripNumber( const QString& number );
+    static bool octalEscapes();
+    static void setOctalEscapes( bool value );
+
+};
+
+#endif // QATUTILS_P_H

Added: trunk/src/host/qemu-neo1973/phonesim/lib/serial/qgsmcodec.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/serial/qgsmcodec.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/serial/qgsmcodec.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qgsmcodec.h>
+
+const unsigned short GUC = 0x10;     // GSM Undefined character
+
+// Table from GSM 07.05, Annex A, combined with the extension table
+// from GSM 03.38, Section 6.2.1.1.
+static const unsigned short latin1GSMTable[256]=
+{
+//     0      1     2     3     4     5     6     7
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,    // 0x07
+      GUC,  GUC, 0x0a,  GUC,  GUC, 0x0d,  GUC,  GUC,    // 0x0f
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+     0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27,
+     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+     0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+     0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+     0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+     0x58, 0x59, 0x5a, 0x1b3c, 0x1b2f, 0x1b3e, 0x1b14, 0x11,
+      GUC, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+     0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+     0x78, 0x79, 0x7a, 0x1b28, 0x1b40, 0x1b29, 0x1b3d,  GUC,  // 0x7f
+
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  // 0x8f
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  // 0x9f
+      GUC, 0x40,  GUC, 0x01, 0x24, 0x03,  GUC, 0x5f,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC, 0x60,
+     0x41, 0x41, 0x41, 0x41, 0x5b, 0x0e, 0x1c, 0x09,
+     0x45, 0x1f, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, // 0xcf
+      GUC, 0x5d, 0x4f, 0x4f, 0x4f, 0x4f, 0x5c,  GUC,
+     0x0b, 0x55, 0x55, 0x55, 0x5e, 0x59,  GUC, 0x1e,
+     0x7f, 0x61, 0x61, 0x61, 0x7b, 0x0f, 0x1d, 0x09,
+     0x04, 0x05, 0x65, 0x65, 0x07, 0x69, 0x69, 0x69,
+      GUC, 0x7d, 0x08, 0x6f, 0x6f, 0x6f, 0x7c,  GUC,
+     0x0c, 0x06, 0x75, 0x75, 0x7e, 0x79,  GUC, 0x79
+};
+
+// Same as above, but with no loss of information due to two
+// Latin1 characters mapping to the same thing.
+static const unsigned short latin1GSMNoLossTable[256]=
+{
+//     0      1     2     3     4     5     6     7
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,    // 0x07
+      GUC,  GUC, 0x0a,  GUC,  GUC, 0x0d,  GUC,  GUC,    // 0x0f
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+     0x20, 0x21, 0x22, 0x23, 0x02, 0x25, 0x26, 0x27,
+     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+     0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+     0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+     0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+     0x58, 0x59, 0x5a, 0x1b3c, 0x1b2f, 0x1b3e, 0x1b14, 0x11,
+      GUC, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+     0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+     0x78, 0x79, 0x7a, 0x1b28, 0x1b40, 0x1b29, 0x1b3d,  GUC,  // 0x7f
+
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  // 0x8f
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  // 0x9f
+      GUC, 0x40,  GUC, 0x01, 0x24, 0x03,  GUC, 0x5f,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC,
+      GUC,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC, 0x60,
+      GUC,  GUC,  GUC,  GUC, 0x5b, 0x0e, 0x1c, 0x09,
+      GUC, 0x1f,  GUC,  GUC,  GUC,  GUC,  GUC,  GUC, // 0xcf
+      GUC, 0x5d,  GUC,  GUC,  GUC,  GUC, 0x5c,  GUC,
+     0x0b,  GUC,  GUC,  GUC, 0x5e,  GUC,  GUC, 0x1e,
+     0x7f,  GUC,  GUC,  GUC, 0x7b, 0x0f, 0x1d,  GUC,
+     0x04, 0x05,  GUC,  GUC, 0x07,  GUC,  GUC,  GUC,
+      GUC, 0x7d, 0x08,  GUC,  GUC,  GUC, 0x7c,  GUC,
+     0x0c, 0x06,  GUC,  GUC, 0x7e,  GUC,  GUC,  GUC
+};
+
+// Conversion table for Greek Unicode code points 0x0390 - 0x03AF.
+static const unsigned short greekGSMTable[32]=
+{
+    GUC, GUC, GUC, 0x13, 0x10, GUC, GUC, GUC,
+    0x19, GUC, GUC, 0x14, GUC, GUC, 0x1a, GUC,
+    0x16, GUC, GUC, 0x18, GUC, GUC, 0x12, GUC,
+    0x17, 0x15, GUC, GUC, GUC, GUC, GUC, GUC
+};
+
+const unsigned short UUC = 0xFFFE;     // Unicode Undefined character
+
+// Reversed version of latin1GSMTable.
+static const unsigned short gsmLatin1Table[256] =
+{
+    0x40, 0xa3, 0x24, 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
+    0xf2, 0xc7, 0x0a, 0xd8, 0xf8, 0x0d, 0xc5, 0xe5,
+    0x0394, 0x5f, 0x03a6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
+    0x03A3, 0x0398, 0x039E, 0x20, 0xc6, 0xe6, 0xdf, 0xc9,
+    0x20, 0x21, 0x22, 0x23, 0xa4, 0x25, 0x26, 0x27,
+    0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+    0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+    0xa1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+    0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+    0x58, 0x59, 0x5a, 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
+    0xbf, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+    0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+    0x78, 0x79, 0x7a, 0xe4, 0xf6, 0xf1, 0xfc, 0xe0,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC
+};
+static const unsigned short extensionLatin1Table[256] =
+{
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC, 0x5e,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC, 0x20,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+    0x7b, 0x7d,  UUC,  UUC,  UUC,  UUC,  UUC, 0x5c,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC, 0x5b, 0x7e, 0x5d,  UUC,
+    0x7c,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC, 0x20ac,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,
+     UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC,  UUC
+};
+
+/*!
+    \class QGsmCodec
+    \mainclass
+    \brief The QGsmCodec class represents the text codec for the GSM 7-bit encoding of Latin-1
+    \ingroup telephony::serial
+
+    The GSM specifications for SMS use a compact 7-bit encoding to represent
+    Latin-1 characters, compared to the more usual 8-bit ISO-8859-1 encoding
+    used on many computer systems.
+
+    The QGsmCodec class enables conversion back and forth between the GSM
+    encoding and the normal Unicode encoding used by Qtopia.
+
+    Application programs will rarely need to use this class, because
+    the QSMSMessage class automatically converts between 7-bit and Unicode
+    encodings as necessary.
+
+    If an application program does need to use this class, it should call
+    QAtUtils::codec() to obtain an instance of the codec.  Constructing
+    QGsmCodec objects directly is not recommended, due to how QTextCodec
+    registers and deregisters codec implementations.
+
+    The following example converts the \c input string into the compact
+    7-bit encoding within \c output.
+
+    \code
+    QString input = "...";
+    QByteArray output = QAtUtils::codec("gsm")->fromUnicode(input);
+    \endcode
+
+    This codec implementation conforms to 3GPP TS 03.38 and 3GPP TS 07.05,
+    including the extension tables from 3GPP TS 03.38.
+
+    \sa QSMSMessage, QAtUtils::codec()
+*/
+
+/*!
+    Construct a new GSM text codec.  If \a noLoss is true, then the
+    codec should not encode characters that may result in an
+    ambiguous decoding.
+
+    This constructor should not be used directly.  Instead, call QAtUtils::codec()
+    to obtain an instance of this codec implementation.  This is due to how
+    QTextCodec registers and deregisters codec implementations.  The codec names
+    to use with QAtUtils::codec() are \c gsm and \c gsm-noloss, for the regular
+    and no-loss versions of the codec.
+
+    \sa QAtUtils::codec()
+*/
+QGsmCodec::QGsmCodec( bool noLoss )
+{
+    this->noLoss = noLoss;
+}
+
+/*!
+    Destruct a GSM text codec.  This should not be used directly by
+    application programs.
+*/
+QGsmCodec::~QGsmCodec()
+{
+}
+
+/*!
+    Returns the name of this codec.
+*/
+QByteArray QGsmCodec::name() const
+{
+    if ( noLoss )
+        return QByteArray( "gsm-noloss" );
+    else
+        return QByteArray( "gsm" );
+}
+
+/*!
+    Returns the MIB value associated with this codec.
+*/
+int QGsmCodec::mibEnum() const
+{
+    if ( noLoss )
+        return 61237;
+    else
+        return 61238;
+}
+
+/*!
+    Convert a single Unicode character \a c into GSM 7-bit.
+    Returns 0x10 if the character cannot be mapped.  Use of this
+    function is discouraged.
+
+    Note: this will not work for two-byte GSM encodings.  Use
+    twoByteFromUnicode() instead.
+
+    \sa singleToUnicode(), twoByteFromUnicode()
+*/
+char QGsmCodec::singleFromUnicode(QChar c)
+{
+    unsigned int ch = c.unicode();
+    if ( ch < 256 )
+        return (char)(latin1GSMTable[ch]);
+    else if ( ch >= 0x0390 && ch <= 0x03AF )
+        return (char)(greekGSMTable[ch - 0x0390]);
+    else
+        return (char)GUC;
+}
+
+/*!
+    Convert a single GSM 7-bit character \a ch into Unicode.  Use of this
+    function is discouraged.
+
+    Note: this will not work for two-byte GSM encodings.  Use
+    twoByteToUnicode() instead.
+
+    \sa singleFromUnicode(), twoByteToUnicode()
+*/
+QChar QGsmCodec::singleToUnicode(char ch)
+{
+    return QChar((unsigned int)(gsmLatin1Table[((int)ch) & 0xFF]));
+}
+
+/*!
+    Convert a Unicode character \a ch into its GSM-encoded counterpart.
+    The return value will be greater than 256 if the Unicode character
+    should be encoded as two bytes.
+
+    \sa twoByteToUnicode()
+*/
+unsigned short QGsmCodec::twoByteFromUnicode(QChar ch)
+{
+    unsigned short c = ch.unicode();
+    if ( c == 0x20AC )  // Euro
+        return 0x1b65;
+    else if ( c < 256 )
+        return latin1GSMTable[c];
+    else if ( c >= 0x0390 && c <= 0x03AF )
+        return (char)(greekGSMTable[c - 0x0390]);
+    else
+        return GUC;
+}
+
+/*!
+    Convert a single GSM-encoded character into its Unicode counterpart.
+    If \a ch is greater than 256, then it represents a two-byte sequence.
+
+    \sa twoByteFromUnicode()
+*/
+QChar QGsmCodec::twoByteToUnicode(unsigned short ch)
+{
+    if ( ch < 256 )
+        return QChar( gsmLatin1Table[ch] );
+    else if ( ( ch & 0xFF00 ) != 0x1B00 )
+        return QChar( 0 );
+    else {
+        unsigned short mapping = extensionLatin1Table[ch & 0xFF];
+        if ( mapping != UUC )
+            return QChar( mapping );
+        else
+            return QChar( gsmLatin1Table[ch & 0xFF] );
+    }
+}
+
+/*!
+    Convert the \a length bytes at \a in into Unicode.  The \c invalidChars
+    field of \a state will be incremented if there are invalid characters
+    within \a in.
+
+    \sa convertFromUnicode()
+*/
+QString QGsmCodec::convertToUnicode(const char *in, int length, ConverterState *state) const
+{
+    QString str;
+    unsigned short ch;
+    while ( length > 0 ) {
+        if ( *in == 0x1B ) {
+            // Two-byte GSM sequence.
+            ++in;
+            --length;
+            if ( length <= 0 ) {
+                if ( state )
+                    (state->invalidChars)++;
+                break;
+            }
+            ch = extensionLatin1Table[((int)(*in)) & 0xFF];
+            if ( ch != UUC ) {
+                str += QChar((unsigned int)ch);
+            } else {
+                str += QChar(gsmLatin1Table[((int)(*in)) & 0xFF]);
+                if ( state )
+                    (state->invalidChars)++;
+            }
+        } else {
+            ch = gsmLatin1Table[((int)(*in)) & 0xFF];
+            if ( ch != UUC )
+                str += QChar((unsigned int)ch);
+            else if ( state )
+                (state->invalidChars)++;
+        }
+        ++in;
+        --length;
+    }
+    return str;
+}
+
+/*!
+    Convert the \a length characters at \a in into 7-bit GSM.  The \c invalidChars
+    field of \a state will be incremented if there are invalid characters
+    within \a in.
+
+    \sa convertToUnicode()
+*/
+QByteArray QGsmCodec::convertFromUnicode(const QChar *in, int length, ConverterState *state) const
+{
+    QByteArray result;
+    unsigned int unicode;
+    if ( noLoss ) {
+        while ( length > 0 ) {
+            unicode = (*in).unicode();
+            if ( unicode == 0x20AC ) {    // Euro
+                result += (char)0x1B;
+                result += (char)0x65;
+            } else if ( unicode < 256 ) {
+                unsigned short code = latin1GSMNoLossTable[unicode];
+                if ( code < 256 ) {
+                    if(((char)code == GUC) && state)
+                        (state->invalidChars)++;
+                    result += (char)code;
+                } else {
+                    result += (char)(code >> 8);
+                    result += (char)code;
+                }
+            } else if ( unicode >= 0x0390 && unicode <= 0x03AF ) {
+                char c = (char)(greekGSMTable[unicode - 0x0390]);
+                result += c;
+                if ( c == (char)GUC && unicode != 0x0394 && state )
+                    (state->invalidChars)++;
+            } else {
+                result += (char)GUC;
+                if ( state )
+                    (state->invalidChars)++;
+            }
+            ++in;
+            --length;
+        }
+    } else {
+        while ( length > 0 ) {
+            unicode = (*in).unicode();
+            if ( unicode == 0x20AC ) {    // Euro
+                result += (char)0x1B;
+                result += (char)0x65;
+            } else if ( unicode < 256 ) {
+                unsigned short code = latin1GSMTable[unicode];
+                if ( code < 256 ) {
+                    result += (char)code;
+                } else {
+                    result += (char)(code >> 8);
+                    result += (char)code;
+                }
+            } else if ( unicode >= 0x0390 && unicode <= 0x03AF ) {
+                char c = (char)(greekGSMTable[unicode - 0x0390]);
+                result += c;
+                if ( c == (char)GUC && unicode != 0x0394 && state )
+                    (state->invalidChars)++;
+            } else {
+                result += (char)GUC;
+                if ( state )
+                    (state->invalidChars)++;
+            }
+            ++in;
+            --length;
+        }
+    }
+    return result;
+}
+

Added: trunk/src/host/qemu-neo1973/phonesim/lib/serial/qgsmcodec.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/serial/qgsmcodec.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/serial/qgsmcodec.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef GSM_CODEC
+#define GSM_CODEC
+
+#include <qtopiaglobal.h>
+
+#include <qstring.h>
+#include <qtextcodec.h>
+
+class QTOPIACOMM_EXPORT QGsmCodec : public QTextCodec
+{
+public:
+    explicit QGsmCodec( bool noLoss=false );
+    ~QGsmCodec();
+
+    QByteArray name() const;
+    int mibEnum() const;
+
+    static char singleFromUnicode(QChar ch);
+    static QChar singleToUnicode(char ch);
+
+    static unsigned short twoByteFromUnicode(QChar ch);
+    static QChar twoByteToUnicode(unsigned short ch);
+
+protected:
+    QString convertToUnicode(const char *in, int length, ConverterState *state) const;
+    QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const;
+
+private:
+    bool noLoss;
+};
+
+#endif

Added: trunk/src/host/qemu-neo1973/phonesim/lib/server.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/server.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/server.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "server.h"
+#include "phonesim.h"
+#include "hardwaremanipulator.h"
+#include <qdebug.h>
+
+static int phonenumber = 555000;
+
+PhoneSimServer::PhoneSimServer(const QString &f, quint16 port, QObject *parent)
+    : QTcpServer(parent), fact(0)
+{
+    listen( QHostAddress::Any, port );
+    filename = f;
+    // Parse the "peers.xml" file.
+    QFileInfo info( filename );
+    QString peerFile = info.absolutePath() + "/peers.xml";
+}
+
+PhoneSimServer::~PhoneSimServer()
+{
+    setHardwareManipulator(0);
+}
+
+void PhoneSimServer::setHardwareManipulator(HardwareManipulatorFactory *f)
+{
+    delete fact;
+    fact = f;
+    if (f)
+        f->setRuleFile(filename);
+}
+
+void PhoneSimServer::incomingConnection(int s)
+{
+  SimRules *sr = new SimRules(s, this, filename, fact);
+    if ( QFile::exists( peerFile ) )
+        sr->loadPeers( peerFile );
+    sr->setPhoneNumber(QString::number(phonenumber));
+    phonenumber++;
+    currentRules = sr;
+}

Added: trunk/src/host/qemu-neo1973/phonesim/lib/server.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/server.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/server.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef PHONESIMSERVER_H
+#define PHONESIMSERVER_H
+
+#include <qtcpserver.h>
+#include <qtcpsocket.h>
+#include <qpointer.h>
+
+#include "phonesim.h"
+
+class PhoneTestServer;
+class HardwareManipulatorFactory;
+
+class PhoneSimServer : public QTcpServer
+{
+public:
+    PhoneSimServer(const QString &, quint16 port, QObject *parent = 0);
+    ~PhoneSimServer();
+
+    void setHardwareManipulator(HardwareManipulatorFactory *f);
+
+    SimRules *rules() const { return currentRules; }
+
+protected:
+    void incomingConnection(int s);
+
+private:
+    QString filename;
+    QString peerFile;
+
+    HardwareManipulatorFactory *fact;
+    QPointer<SimRules> currentRules;
+};
+
+#endif
+

Added: trunk/src/host/qemu-neo1973/phonesim/lib/simapplication.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/simapplication.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/simapplication.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,742 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "simapplication.h"
+#include <qatutils.h>
+#include <qdebug.h>
+
+class SimApplicationPrivate
+{
+public:
+    SimApplicationPrivate()
+    {
+        rules = 0;
+        expectedType = QSimCommand::NoCommand;
+        target = 0;
+        slot = 0;
+        inResponse = false;
+    }
+
+    SimRules   *rules;
+    QSimCommand::Type expectedType;
+    QByteArray  currentCommand;
+    QObject    *target;
+    const char *slot;
+    bool inResponse;
+};
+
+SimApplication::SimApplication( QObject *parent )
+    : QObject( parent )
+{
+    d = new SimApplicationPrivate();
+}
+
+SimApplication::~SimApplication()
+{
+    delete d;
+}
+
+/*!
+    Sends a proactive SIM command, \a cmd, to the ME, and instructs
+    SimApplication to invoke \a slot on \a target when the response
+    arrives back.  The \a options provides extra information about
+    how the command should be transmitted to the ME in PDU form.
+
+    For \c SetupMenu commands, \a target and \a slot should be null.
+    When the user responds to the main menu, mainMenuSelection() or
+    mainMenuHelpRequest() will be invoked.
+
+    \sa mainMenuSelection(), mainMenuHelpRequest()
+*/
+void SimApplication::command( const QSimCommand& cmd,
+                              QObject *target, const char *slot,
+                              QSimCommand::ToPduOptions options )
+{
+    // Record the command details, together with the type of
+    // TERMINAL RESPONSE or ENVELOPE that we expect in answer.
+    d->currentCommand = cmd.toPdu( options );
+    d->expectedType = cmd.type();
+    d->target = target;
+    d->slot = slot;
+
+    // Send an unsolicited notification to indicate that a new
+    // proactive SIM command is available.  If we are already in
+    // the middle of processing a TERMINAL RESPONSE or ENVELOPE,
+    // then delay the unsolicited notification until later.
+    if ( d->rules && !d->inResponse ) {
+        d->rules->unsolicited
+            ( "*TCMD: " + QString::number( d->currentCommand.size() ) );
+    }
+}
+
+/*!
+    Sends a call control \a event to the ME.
+*/
+void SimApplication::controlEvent( const QSimControlEvent& event )
+{
+    if ( d->rules ) {
+        d->rules->unsolicited
+            ( "*TCC: " + QString::number( (int)(event.type()) ) +
+              "," + QAtUtils::toHex( event.toPdu() ) );
+    }
+}
+
+/*!
+    Starts the SIM application.  The default implementation calls mainMenu().
+
+    \sa abort(), mainMenu()
+*/
+void SimApplication::start()
+{
+    mainMenu();
+}
+
+/*!
+    Aborts the SIM application and forces it to return to the main menu.
+    The default implementation clears the pending command for FETCH
+    and then calls mainMenu().
+
+    This function is called whenever a \c{TERMINAL PROFILE} command is
+    received from the ME.
+
+    \sa start(), mainMenu()
+*/
+void SimApplication::abort()
+{
+    d->expectedType = QSimCommand::NoCommand;
+    d->currentCommand = QByteArray();
+    d->target = 0;
+    d->slot = 0;
+    mainMenu();
+}
+
+/*!
+    \fn void SimApplication::mainMenu()
+
+    Builds and sends the main menu to the ME using the command() method.
+
+    \sa mainMenuSelection(), mainMenuHelpRequest()
+*/
+
+/*!
+    Indicates that the main menu item with the identifier \a id
+    has been selected.  The default implementation re-sends
+    the main menu.
+
+    \sa mainMenu(), mainMenuHelpRequest()
+*/
+void SimApplication::mainMenuSelection( int id )
+{
+    Q_UNUSED(id);
+    mainMenu();
+}
+
+/*!
+    Indicates that help has been requested for the main menu item
+    with the identifier \a id.  The default implementation
+    re-sends the main menu.
+
+    \sa mainMenu(), mainMenuSelection()
+*/
+void SimApplication::mainMenuHelpRequest( int id )
+{
+    Q_UNUSED(id);
+    mainMenu();
+}
+
+void SimApplication::setSimRules( SimRules *rules )
+{
+    d->rules = rules;
+}
+
+bool SimApplication::execute( const QString& cmd )
+{
+    // Process SIM toolkit begin and end commands by forcing the app back to the main menu.
+    if ( cmd == "AT*TSTB" || cmd == "AT*TSTE") {
+        d->rules->respond( "OK" );
+        abort();
+        return true;
+    }
+
+    // If not AT+CSIM, then this is not a SIM toolkit command.
+    if ( !cmd.startsWith( "AT+CSIM=" ) )
+        return false;
+
+    // Extract the binary payload of the AT+CSIM command.
+    int comma = cmd.indexOf( QChar(',') );
+    if ( comma < 0 )
+        return false;
+    QByteArray param = QAtUtils::fromHex( cmd.mid(comma + 1) );
+    if ( param.length() < 5 || param[0] != (char)0xA0 )
+        return false;
+
+    // Check for TERMINAL PROFILE, FETCH, TERMINAL RESPONSE,
+    // and ENVELOPE packets.
+    if ( param[1] == (char)0x10 ) {
+        // Download of a TERMINAL PROFILE.  We respond with a simple OK,
+        // on the assumption that what we were sent was valid.
+        d->rules->respond( "+CSIM: 4,9000\nOK" );
+
+        // Abort the SIM application and force it to return to the main menu.
+        abort();
+    } else if ( param[1] == (char)0x12 ) {
+        // Fetch the current command contents.
+        QByteArray resp = d->currentCommand;
+        if ( resp.isEmpty() ) {
+            // We weren't expecting a FETCH.
+            d->rules->respond( "+CSIM: 4,6F00\nOK" );
+            return true;
+        }
+        resp += (char)0x90;
+        resp += (char)0x00;
+        d->rules->respond( "+CSIM: " + QString::number( resp.size() * 2 ) + "," +
+                           QAtUtils::toHex( resp ) + "\nOK" );
+    } else if ( param[1] == (char)0x14 ) {
+        // Process a TERMINAL RESPONSE message.
+        QSimTerminalResponse resp;
+        resp = QSimTerminalResponse::fromPdu( param.mid(5) );
+        if ( resp.command().type() != QSimCommand::NoCommand &&
+             resp.command().type() != d->expectedType ) {
+            // Response to the wrong type of command.
+            d->rules->respond( "+CSIM: 4,6F00\nOK" );
+            return true;
+        }
+        response( resp );
+    } else if ( param[1] == (char)0xC2 ) {
+        // Process a menu selection ENVELOPE message.  We turn it into a
+        // QSimTerminalResponse to make it easier to process.
+        QSimEnvelope env;
+        env = QSimEnvelope::fromPdu( param.mid(5) );
+        if ( env.type() == QSimEnvelope::EventDownload ) {
+            d->rules->respond( "+CSIM: 4,9000\nOK" );
+            return true;
+        }
+        if ( env.type() != QSimEnvelope::MenuSelection )
+            return false;
+        if ( d->expectedType != QSimCommand::SetupMenu ) {
+            // Envelope sent for the wrong type of command.
+            d->rules->respond( "+CSIM: 4,6F00\nOK" );
+            return true;
+        }
+        d->rules->respond( "+CSIM: 4,9000\nOK" );
+        d->expectedType = QSimCommand::NoCommand;
+        d->currentCommand = QByteArray();
+        d->target = 0;
+        d->slot = 0;
+        if ( env.requestHelp() )
+            mainMenuHelpRequest( env.menuItem() );
+        else
+            mainMenuSelection( env.menuItem() );
+    } else {
+        // This SIM command is not related to SIM toolkit - ignore it.
+        return false;
+    }
+
+    return true;
+}
+
+void SimApplication::response( const QSimTerminalResponse& resp )
+{
+    // Save the target information.
+    QObject *target = d->target;
+    const char *slot = d->slot;
+
+    // Clear the command details, in preparation for a new command.
+    if ( resp.command().type() != QSimCommand::SetupMenu ) {
+        d->expectedType = QSimCommand::NoCommand;
+        d->currentCommand = QByteArray();
+    }
+    d->target = 0;
+    d->slot = 0;
+
+    // Process the response.
+    d->inResponse = true;
+    if ( target && slot ) {
+        // Invoke the slot and pass "resp" to it.
+        QByteArray name( slot + 1 );
+        name = QMetaObject::normalizedSignature( name.constData() );
+        int index = target->metaObject()->indexOfMethod( name.constData() );
+        if ( index != -1 ) {
+            void *args[2];
+            args[0] = 0;
+            args[1] = (void *)&resp;
+            target->qt_metacall
+                ( QMetaObject::InvokeMetaMethod, index, args );
+        }
+    }
+    d->inResponse = false;
+
+    // Answer the AT+CSIM command and send notification of the new command.
+    if ( !d->rules )
+        return;
+    if ( d->currentCommand.isEmpty() || resp.command().type() == QSimCommand::SetupMenu ) {
+        // No new command, so respond with a simple OK.
+        d->rules->respond( "+CSIM: 4,9000\nOK" );
+    } else {
+        // There is a new command, so send back 91XX to the TERMINAL RESPONSE
+        // or ENVELOPE request to indicate that we have another command to
+        // be fetched.  Then send the unsolicited "*TCMD" notification.
+        QByteArray data;
+        data += (char)0x91;
+        data += (char)(d->currentCommand.size());
+        d->rules->respond( "+CSIM: " + QString::number( data.size() * 2 ) + "," +
+                           QAtUtils::toHex( data ) + "\nOK" );
+        d->rules->unsolicited
+            ( "*TCMD: " + QString::number( d->currentCommand.size() ) );
+    }
+}
+
+DemoSimApplication::DemoSimApplication( QObject *parent )
+    : SimApplication( parent )
+{
+}
+
+DemoSimApplication::~DemoSimApplication()
+{
+}
+
+#define MainMenu_News       1
+#define MainMenu_Sports     2
+#define MainMenu_Time       3
+#define MainMenu_SticksGame 4
+#define MainMenu_Tones      5
+#define MainMenu_Icons      6
+#define MainMenu_IconsSE    7
+
+#define SportsMenu_Chess        1
+#define SportsMenu_Painting     2
+#define SportsMenu_Snakes       3
+#define SportsMenu_Main         4
+
+void DemoSimApplication::mainMenu()
+{
+    QSimCommand cmd;
+    QSimMenuItem item;
+    QList<QSimMenuItem> items;
+
+    cmd.setType( QSimCommand::SetupMenu );
+
+    item.setIdentifier( MainMenu_News );
+    item.setLabel( "News" );
+    items += item;
+
+    item.setIdentifier( MainMenu_Sports );
+    item.setLabel( "Sports" );
+    items += item;
+
+    item.setIdentifier( MainMenu_Time );
+    item.setLabel( "Time" );
+    items += item;
+
+    item.setIdentifier( MainMenu_SticksGame );
+    item.setLabel( "Sticks Game" );
+    items += item;
+
+    item.setIdentifier( MainMenu_Tones );
+    item.setLabel( "Tones" );
+    items += item;
+
+    item.setIdentifier( MainMenu_Icons );
+    item.setLabel( "Icons (not self-explanatory)" );
+    items += item;
+
+    item.setIdentifier( MainMenu_IconsSE );
+    item.setLabel( "Icons (self-explanatory)" );
+    items += item;
+
+    cmd.setMenuItems( items );
+
+    command( cmd, 0, 0 );
+}
+
+void DemoSimApplication::mainMenuSelection( int id )
+{
+    QSimCommand cmd;
+
+    switch ( id ) {
+
+        case MainMenu_News:
+        {
+            // Display a text string and then go back to the main menu once the
+            // text is accepted by the user.
+            cmd.setType( QSimCommand::DisplayText );
+            cmd.setDestinationDevice( QSimCommand::Display );
+            cmd.setText( "Police today arrested a man on suspicion "
+                         "of making phone calls while intoxicated.  Witnesses claimed "
+                         "that they heard the man exclaim \"I washent dwinkn!\" as "
+                         "officers escorted him away." );
+            command( cmd, this, SLOT(mainMenu()) );
+        }
+        break;
+
+        case MainMenu_Sports:
+        {
+            sendSportsMenu();
+        }
+        break;
+
+        case MainMenu_Time:
+        {
+            cmd.setType( QSimCommand::SetupCall );
+            cmd.setNumber( "1194" );
+            cmd.setText( "Dialing the Time Guy ..." );
+            command( cmd, this, SLOT(mainMenu()) );
+        }
+        break;
+
+        case MainMenu_SticksGame:
+        {
+            startSticksGame();
+        }
+        break;
+
+        case MainMenu_Tones:
+        {
+            sendToneMenu();
+        }
+        break;
+
+        case MainMenu_Icons:
+        {
+            sendIconMenu();
+        }
+        break;
+
+        case MainMenu_IconsSE:
+        {
+            sendIconSEMenu();
+        }
+        break;
+
+        default:
+        {
+            // Don't know what this item is, so just re-display the main menu.
+            mainMenu();
+        }
+        break;
+    }
+}
+
+void DemoSimApplication::sendSportsMenu()
+{
+    QSimCommand cmd;
+    QSimMenuItem item;
+    QList<QSimMenuItem> items;
+
+    cmd.setType( QSimCommand::SelectItem );
+    cmd.setTitle( "Sports" );
+
+    item.setIdentifier( SportsMenu_Chess );
+    item.setLabel( "Chess" );
+    items += item;
+
+    item.setIdentifier( SportsMenu_Painting );
+    item.setLabel( "Finger Painting" );
+    items += item;
+
+    item.setIdentifier( SportsMenu_Snakes );
+    item.setLabel( "Snakes and Ladders" );
+    items += item;
+
+    item.setIdentifier( SportsMenu_Main );
+    item.setLabel( "Return to main menu" );
+    items += item;
+
+    cmd.setMenuItems( items );
+
+    command( cmd, this, SLOT(sportsMenu(QSimTerminalResponse)) );
+}
+
+void DemoSimApplication::sportsMenu( const QSimTerminalResponse& resp )
+{
+    QSimCommand cmd;
+
+    if ( resp.result() == QSimTerminalResponse::Success ) {
+        // Item selected.
+        switch ( resp.menuItem() ) {
+
+            case SportsMenu_Chess:
+            {
+                cmd.setType( QSimCommand::DisplayText );
+                cmd.setDestinationDevice( QSimCommand::Display );
+                cmd.setText( "Kasparov 3, Deep Blue 4" );
+                command( cmd, this, SLOT(sendSportsMenu()) );
+            }
+            break;
+
+            case SportsMenu_Painting:
+            {
+                cmd.setType( QSimCommand::DisplayText );
+                cmd.setDestinationDevice( QSimCommand::Display );
+                cmd.setText( "Little Johnny 4, Little Sally 6" );
+                command( cmd, this, SLOT(sendSportsMenu()) );
+            }
+            break;
+
+            case SportsMenu_Snakes:
+            {
+                cmd.setType( QSimCommand::DisplayText );
+                cmd.setDestinationDevice( QSimCommand::Display );
+                cmd.setText( "Little Johnny 0, Little Sally 2" );
+                cmd.setClearAfterDelay( true );
+                command( cmd, this, SLOT(sendSportsMenu()) );
+            }
+            break;
+
+            default:    mainMenu(); break;
+        }
+    } else if ( resp.result() == QSimTerminalResponse::BackwardMove ) {
+        // Request to move backward.
+        mainMenu();
+    } else {
+        // Unknown response - just go back to the main menu.
+        mainMenu();
+    }
+}
+
+void DemoSimApplication::startSticksGame()
+{
+    sticksLeft = 21;
+    sticksGameShow();
+}
+
+void DemoSimApplication::sticksGameShow()
+{
+    QSimCommand cmd;
+    if ( sticksLeft == 1 ) {
+        cmd.setType( QSimCommand::GetInkey );
+        cmd.setText( "There is only 1 stick left.  You lose.  Play again?" );
+        cmd.setWantYesNo( true );
+        command( cmd, this, SLOT(sticksGamePlayAgain(QSimTerminalResponse)) );
+    } else {
+        cmd.setType( QSimCommand::GetInkey );
+        cmd.setText( "There are 21 sticks left.  How many do you take (1, 2, or 3)?" );
+        cmd.setWantDigits( true );
+        if ( sticksLeft == 21 )
+            cmd.setHasHelp( true );
+        command( cmd, this, SLOT(sticksGameLoop(QSimTerminalResponse)) );
+    }
+}
+
+void DemoSimApplication::sticksGameLoop( const QSimTerminalResponse& resp )
+{
+    QSimCommand cmd;
+    if ( resp.result() == QSimTerminalResponse::Success ) {
+        // User has selected the number of sticks they want.
+        int taken = 0;
+        if ( resp.text() == "1" ) {
+            taken = 1;
+        } else if ( resp.text() == "2" ) {
+            taken = 2;
+        } else if ( resp.text() == "3" ) {
+            taken = 3;
+        } else {
+            cmd.setType( QSimCommand::GetInkey );
+            cmd.setText( "Must be 1, 2, or 3.  There are " + QString::number( sticksLeft ) +
+                         " sticks left.  How many sticks do you take?" );
+            cmd.setWantDigits( true );
+            command( cmd, this, SLOT(sticksGameLoop(QSimTerminalResponse)) );
+            return;
+        }
+        cmd.setType( QSimCommand::DisplayText );
+        cmd.setDestinationDevice( QSimCommand::Display );
+        cmd.setText( "I take " + QString::number( 4 - taken ) + " sticks." );
+        cmd.setClearAfterDelay( true );
+        sticksLeft -= 4;
+        command( cmd, this, SLOT(sticksGameShow()) );
+    } else if ( resp.result() == QSimTerminalResponse::HelpInformationRequested ) {
+        // Display help for the game.
+        cmd.setType( QSimCommand::DisplayText );
+        cmd.setDestinationDevice( QSimCommand::Display );
+        cmd.setText( "Starting with 21 sticks, players pick up 1, 2, or 3 sticks at a time.  "
+                     "The loser is the player who has to pick up the last stick." );
+        command( cmd, this, SLOT(startSticksGame()) );
+    } else {
+        // Probably aborted.
+        mainMenu();
+    }
+}
+
+void DemoSimApplication::sticksGamePlayAgain( const QSimTerminalResponse& resp )
+{
+    if ( resp.text() == "Yes" )
+        startSticksGame();
+    else
+        mainMenu();
+}
+
+void DemoSimApplication::sendToneMenu()
+{
+    QSimCommand cmd;
+    QSimMenuItem item;
+    QList<QSimMenuItem> items;
+
+    cmd.setType( QSimCommand::SelectItem );
+    cmd.setTitle( "Tones" );
+
+    item.setIdentifier( (uint)QSimCommand::ToneDial );
+    item.setLabel( "Dial" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::ToneBusy );
+    item.setLabel( "Busy" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::ToneCongestion );
+    item.setLabel( "Congestion" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::ToneRadioAck );
+    item.setLabel( "Radio Ack" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::ToneDropped );
+    item.setLabel( "Dropped" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::ToneError );
+    item.setLabel( "Error" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::ToneCallWaiting );
+    item.setLabel( "Call Waiting" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::ToneGeneralBeep );
+    item.setLabel( "General Beep" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::TonePositiveBeep );
+    item.setLabel( "Positive Beep" );
+    items += item;
+
+    item.setIdentifier( (uint)QSimCommand::ToneNegativeBeep );
+    item.setLabel( "Negative Beep" );
+    items += item;
+
+    cmd.setMenuItems( items );
+
+    command( cmd, this, SLOT(toneMenu(QSimTerminalResponse)) );
+}
+
+void DemoSimApplication::toneMenu( const QSimTerminalResponse& resp )
+{
+    QSimCommand cmd;
+
+    if ( resp.result() == QSimTerminalResponse::Success ) {
+        // Item selected.
+        cmd.setType( QSimCommand::PlayTone );
+        cmd.setDestinationDevice( QSimCommand::Earpiece );
+        cmd.setTone( (QSimCommand::Tone)( resp.menuItem() ) );
+        if ( cmd.tone() == QSimCommand::ToneDial )
+            cmd.setDuration( 5000 );
+        else if ( cmd.tone() == QSimCommand::ToneGeneralBeep ||
+                  cmd.tone() == QSimCommand::TonePositiveBeep ||
+                  cmd.tone() == QSimCommand::ToneNegativeBeep )
+            cmd.setDuration( 1000 );
+        else
+            cmd.setDuration( 3000 );
+        command( cmd, this, SLOT(sendToneMenu()) );
+    } else if ( resp.result() == QSimTerminalResponse::BackwardMove ) {
+        // Request to move backward.
+        mainMenu();
+    } else {
+        // Unknown response - just go back to the main menu.
+        mainMenu();
+    }
+}
+
+void DemoSimApplication::sendIconMenu()
+{
+    QSimCommand cmd;
+    QSimMenuItem item;
+    QList<QSimMenuItem> items;
+
+    cmd.setType( QSimCommand::SelectItem );
+    cmd.setTitle( "Icons" );
+
+    item.setIdentifier( 1 );
+    item.setLabel( "Basic Icon" );
+    item.setIconId( 1 );
+    items += item;
+
+    item.setIdentifier( 2 );
+    item.setLabel( "Color Icon" );
+    item.setIconId( 2 );
+    items += item;
+
+    item.setIdentifier( 3 );
+    item.setLabel( "Bad Icon" );
+    item.setIconId( 70 );
+    items += item;
+
+    cmd.setMenuItems( items );
+
+    command( cmd, this, SLOT(iconMenu(QSimTerminalResponse)) );
+}
+
+void DemoSimApplication::sendIconSEMenu()
+{
+    QSimCommand cmd;
+    QSimMenuItem item;
+    QList<QSimMenuItem> items;
+
+    cmd.setType( QSimCommand::SelectItem );
+    cmd.setTitle( "Icons SE" );
+
+    item.setIdentifier( 1 );
+    item.setLabel( "Basic Icon" );
+    item.setIconId( 1 );
+    item.setIconSelfExplanatory( true );
+    items += item;
+
+    item.setIdentifier( 2 );
+    item.setLabel( "Color Icon" );
+    item.setIconId( 2 );
+    item.setIconSelfExplanatory( true );
+    items += item;
+
+    item.setIdentifier( 3 );
+    item.setLabel( "Bad Icon" );
+    item.setIconId( 70 );
+    item.setIconSelfExplanatory( true );
+    items += item;
+
+    cmd.setMenuItems( items );
+
+    command( cmd, this, SLOT(iconSEMenu(QSimTerminalResponse)) );
+}
+
+void DemoSimApplication::iconMenu( const QSimTerminalResponse& resp )
+{
+    if ( resp.result() == QSimTerminalResponse::Success )
+        sendIconMenu();
+    else
+        mainMenu();
+}
+
+void DemoSimApplication::iconSEMenu( const QSimTerminalResponse& resp )
+{
+    if ( resp.result() == QSimTerminalResponse::Success )
+        sendIconSEMenu();
+    else
+        mainMenu();
+}

Added: trunk/src/host/qemu-neo1973/phonesim/lib/simapplication.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/simapplication.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/simapplication.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef SIMAPPLICATION_H
+#define SIMAPPLICATION_H
+
+#include "phonesim.h"
+#include <qsimcommand.h>
+#include <qsimterminalresponse.h>
+#include <qsimenvelope.h>
+#include <qsimcontrolevent.h>
+
+class SimApplicationPrivate;
+
+class SimApplication : public QObject
+{
+    Q_OBJECT
+    friend class SimRules;
+public:
+    SimApplication( QObject *parent = 0 );
+    ~SimApplication();
+
+    void command( const QSimCommand& cmd,
+                  QObject *target, const char *slot,
+                  QSimCommand::ToPduOptions options
+                        = QSimCommand::NoPduOptions );
+
+public slots:
+    void controlEvent( const QSimControlEvent& event );
+    virtual void start();
+    virtual void abort();
+
+protected slots:
+    virtual void mainMenu() = 0;
+    virtual void mainMenuSelection( int id );
+    virtual void mainMenuHelpRequest( int id );
+
+private:
+    SimApplicationPrivate *d;
+
+    void setSimRules( SimRules *rules );
+    bool execute( const QString& cmd );
+    void response( const QSimTerminalResponse& resp );
+};
+
+class DemoSimApplication : public SimApplication
+{
+    Q_OBJECT
+public:
+    DemoSimApplication( QObject *parent = 0 );
+    ~DemoSimApplication();
+
+protected slots:
+    void mainMenu();
+    void mainMenuSelection( int id );
+    void sendSportsMenu();
+    void sportsMenu( const QSimTerminalResponse& resp );
+    void startSticksGame();
+    void sticksGameShow();
+    void sticksGameLoop( const QSimTerminalResponse& resp );
+    void sticksGamePlayAgain( const QSimTerminalResponse& resp );
+    void sendToneMenu();
+    void toneMenu( const QSimTerminalResponse& resp );
+    void sendIconMenu();
+    void iconMenu( const QSimTerminalResponse& resp );
+    void sendIconSEMenu();
+    void iconSEMenu( const QSimTerminalResponse& resp );
+
+private:
+    int sticksLeft;
+};
+
+#endif /* SIMAPPLICATION_H */

Added: trunk/src/host/qemu-neo1973/phonesim/lib/simfilesystem.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/simfilesystem.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/simfilesystem.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,488 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include "simfilesystem.h"
+#include <qatutils.h>
+#include <qdebug.h>
+
+// Known files, their parent directories, and names.
+// This list comes from 3GPP TS 11.11 and 3GPP TS 51.011.
+typedef struct
+{
+    const char *fileid;
+    const char *parent;
+    const char *name;
+
+} SimFileInfo;
+static SimFileInfo const knownFiles[] =
+{
+    {"3F00",        0,          "MF"},
+
+    {"2FE2",        "3F00",     "EFiccid"},
+    {"2F05",        "3F00",     "EFelp"},
+
+    {"7F10",        "3F00",     "DFtelecom"},
+    {"6F3A",        "7F10",     "EFadn"},
+    {"6F3B",        "7F10",     "EFfdn"},
+    {"6F3C",        "7F10",     "EFsms"},
+    {"6F3D",        "7F10",     "EFccp"},
+    {"6F40",        "7F10",     "EFmsisdn"},
+    {"6F42",        "7F10",     "EFsmsp"},
+    {"6F43",        "7F10",     "EFsmss"},
+    {"6F44",        "7F10",     "EFlnd"},
+    {"6F47",        "7F10",     "EFsmsr"},
+    {"6F49",        "7F10",     "EFsdn"},
+    {"6F4A",        "7F10",     "EFext1"},
+    {"6F4B",        "7F10",     "EFext2"},
+    {"6F4C",        "7F10",     "EFext3"},
+    {"6F4D",        "7F10",     "EFbdn"},
+    {"6F4E",        "7F10",     "EFext4"},
+    {"6F4F",        "7F10",     "EFeccp"},          // 51.011
+    {"6F58",        "7F10",     "EFcmi"},           // 51.011
+
+    {"5F50",        "7F10",     "DFgraphics"},
+    {"4F20",        "5F50",     "EFimg"},
+    {"4F01",        "5F50",     "EFimg1"},          // Usual names of
+    {"4F02",        "5F50",     "EFimg2"},          // Image data files.
+    {"4F03",        "5F50",     "EFimg3"},
+    {"4F04",        "5F50",     "EFimg4"},
+    {"4F05",        "5F50",     "EFimg5"},
+
+    {"7F20",        "3F00",     "DFgsm"},
+    {"6F05",        "7F20",     "EFlp"},
+    {"6F07",        "7F20",     "EFimsi"},
+    {"6F20",        "7F20",     "EFkc"},
+    {"6F2C",        "7F20",     "EFdck"},           // 51.011
+    {"6F30",        "7F20",     "EFplmnsel"},
+    {"6F31",        "7F20",     "EFhpplmn"},
+    {"6F32",        "7F20",     "EFcnl"},           // 51.011
+    {"6F37",        "7F20",     "EFacmmax"},
+    {"6F38",        "7F20",     "EFsst"},
+    {"6F39",        "7F20",     "EFacm"},
+    {"6F3E",        "7F20",     "EFgid1"},
+    {"6F3F",        "7F20",     "EFgid2"},
+    {"6F41",        "7F20",     "EFpuct"},
+    {"6F45",        "7F20",     "EFcbmi"},
+    {"6F46",        "7F20",     "EFspn"},
+    {"6F48",        "7F20",     "EFcbmid"},
+    {"6F50",        "7F20",     "EFcbmir"},
+    {"6F51",        "7F20",     "EFnia"},
+    {"6F52",        "7F20",     "EFkcgprs"},
+    {"6F53",        "7F20",     "EFlocigprs"},
+    {"6F54",        "7F20",     "EFsume"},
+    {"6F60",        "7F20",     "EFplmnwact"},
+    {"6F61",        "7F20",     "EFoplmnwact"},
+    {"6F62",        "7F20",     "EFhplmnwact"},
+    {"6F63",        "7F20",     "EFcpbcch"},
+    {"6F64",        "7F20",     "EFinvscan"},
+    {"6F74",        "7F20",     "EFbcch"},
+    {"6F78",        "7F20",     "EFacc"},
+    {"6F7B",        "7F20",     "EFfplmn"},
+    {"6F7E",        "7F20",     "EFloci"},
+    {"6FAD",        "7F20",     "EFad"},
+    {"6FAE",        "7F20",     "EFphase"},
+    {"6FB1",        "7F20",     "EFvgcs"},
+    {"6FB2",        "7F20",     "EFvgcss"},
+    {"6FB3",        "7F20",     "EFvbs"},
+    {"6FB4",        "7F20",     "EFvbss"},
+    {"6FB5",        "7F20",     "EFemlpp"},
+    {"6FB6",        "7F20",     "EFaaem"},
+    {"6FB7",        "7F20",     "EFecc"},
+    {"6FC5",        "7F20",     "EFpnn"},           // 51.011
+    {"6FC6",        "7F20",     "EFopl"},           // 51.011
+    {"6FC7",        "7F20",     "EFmbdn"},          // 51.011
+    {"6FC8",        "7F20",     "EFext6"},          // 51.011
+    {"6FC9",        "7F20",     "EFmbi"},           // 51.011
+    {"6FCA",        "7F20",     "EFmwis"},          // 51.011
+    {"6FCB",        "7F20",     "EFcfis"},          // 51.011
+    {"6FCC",        "7F20",     "EFext7"},          // 51.011
+    {"6FCD",        "7F20",     "EFspdi"},          // 51.011
+    {"6FCE",        "7F20",     "EFmmsn"},          // 51.011
+    {"6FCF",        "7F20",     "EFext8"},          // 51.011
+    {"6FD0",        "7F20",     "EFmmsicp"},        // 51.011
+    {"6FD1",        "7F20",     "EFmmsup"},         // 51.011
+    {"6FD2",        "7F20",     "EFmmsucp"},        // 51.011
+
+    {"5F30",        "7F20",     "DFiridium"},
+    {"5F31",        "7F20",     "DFglobst"},
+    {"5F32",        "7F20",     "DFico"},
+    {"5F33",        "7F20",     "DFaces"},
+
+    {"5F40",        "7F20",     "DFeia/tia-553"},
+    {"4F80",        "5F40",     "EFsid"},           // 51.011
+    {"4F81",        "5F40",     "EFgpi"},           // 51.011
+    {"4F82",        "5F40",     "EFipc"},           // 51.011
+    {"4F83",        "5F40",     "EFcount"},         // 51.011
+    {"4F84",        "5F40",     "EFnsid"},          // 51.011
+    {"4F85",        "5F40",     "EFpsid"},          // 51.011
+    {"4F86",        "5F40",     "EFnetsel"},        // 51.011
+    {"4F87",        "5F40",     "EFspl"},           // 51.011
+    {"4F88",        "5F40",     "EFmin"},           // 51.011
+    {"4F89",        "5F40",     "EFaccolc"},        // 51.011
+    {"4F8A",        "5F40",     "EFfc1"},           // 51.011
+    {"4F8B",        "5F40",     "EFs-esn"},         // 51.011
+    {"4F8C",        "5F40",     "EFcsid"},          // 51.011
+    {"4F8D",        "5F40",     "EFreg-thresh"},    // 51.011
+    {"4F8E",        "5F40",     "EFccch"},          // 51.011
+    {"4F8F",        "5F40",     "EFldcc"},          // 51.011
+    {"4F90",        "5F40",     "EFgsm-recon"},     // 51.011
+    {"4F91",        "5F40",     "EFamps-2-gsm"},    // 51.011
+    {"4F93",        "5F40",     "EFamps-ui"},       // 51.011
+
+    {"5F60",        "7F20",     "DFcts"},
+
+    {"5F70",        "7F20",     "DFsolsa"},
+    {"4F30",        "5F70",     "EFsai"},
+    {"4F31",        "5F70",     "EFsll"},
+
+    {"5F3C",        "7F20",     "DFmexe"},
+    {"4F40",        "5F3C",     "EFmexe-st"},
+    {"4F41",        "5F3C",     "EForpk"},
+    {"4F42",        "5F3C",     "EFarpk"},
+    {"4F43",        "5F3C",     "EFtprpk"},
+
+    {"7F22",        "3F00",     "DFis41"},
+
+    {"7F23",        "3F00",     "DFfp-cts"},
+
+    {0,             0,          0}
+};
+
+SimFileSystem::SimFileSystem( SimRules *rules, SimXmlNode& e )
+    : QObject( rules )
+{
+    this->rules = rules;
+    rootItem = new SimFileItem( "3F00", 0 );
+    currentItem = rootItem;
+
+    // Create all of the standard directories.
+    const SimFileInfo *info = knownFiles;
+    SimFileItem *dirItem = 0;
+    while ( info->fileid ) {
+        QString fileid = info->fileid;
+        if ( fileid.startsWith( "7F" ) ) {
+            dirItem = new SimFileItem( fileid, rootItem );
+        } else if ( fileid.startsWith( "5F" ) ) {
+            new SimFileItem( fileid, dirItem );
+        }
+        ++info;
+    }
+
+    // Load the file definitions.
+    SimXmlNode *child = e.children;
+    while ( child ) {
+        if ( child->tag == "file" ) {
+            QString name = child->getAttribute( "name" );
+            QByteArray data = QAtUtils::fromHex( child->contents );
+            QString fileid = resolveFileId( name );
+            SimFileItem *parent = findItemParent( fileid );
+            if ( parent ) {
+                SimFileItem *item;
+                item = findItem( fileid.right(4) );
+                if ( !item )
+                    item = new SimFileItem( fileid.right(4), parent );
+                else
+                    qDebug() << "File" << name << "defined multiple times";
+                item->setContents( data );
+                QString size = child->getAttribute( "recordsize" );
+                if ( !size.isEmpty() )
+                    item->setRecordSize( size.toInt() );
+            } else {
+                qDebug() << "Could not find parent for" << name;
+            }
+        } else {
+            qDebug() << "Unknown filesystem command <" << child->tag << ">";
+        }
+        child = child->next;
+    }
+}
+
+SimFileSystem::~SimFileSystem()
+{
+    delete rootItem;
+}
+
+void SimFileSystem::crsm( const QString& args )
+{
+    // Extract the arguments to the command.
+    uint posn = 0;
+    uint command = QAtUtils::parseNumber( args, posn );
+    QString fileid =
+        QString::number( QAtUtils::parseNumber( args, posn ), 16 ).toUpper();
+    uint p1 = QAtUtils::parseNumber( args, posn );
+    uint p2 = QAtUtils::parseNumber( args, posn );
+    uint p3 = QAtUtils::parseNumber( args, posn );
+    QString data = QAtUtils::fromHex( args.mid( (int)posn ) );
+
+    // Determine how to execute the command.
+    bool ok = true;
+    SimFileItem *item;
+    QString response;
+    int sw1 = 0;
+    int sw2 = 0;
+    int offset, length;
+    QByteArray contents;
+    switch ( command ) {
+
+        case 176:       // READ BINARY
+        {
+            offset = (int)((p1 << 8) + p2);
+            length = (int)p3;
+            item = findItemRelative( fileid );
+            if ( item ) {
+                contents = item->contents();
+                if ( ( offset + length ) > contents.size() ) {
+                    sw1 = 0x94;
+                    sw2 = 0x02;
+                } else {
+                    sw1 = 0x9F;
+                    sw2 = length;
+                    response =
+                        QAtUtils::toHex( contents.mid( offset, length ) );
+                }
+            } else {
+                sw1 = 0x94;
+                sw2 = 0x04;
+            }
+        }
+        break;
+
+        case 178:       // READ RECORD
+        {
+            offset = (int)(p1 - 1);
+            length = (int)p3;
+            item = findItemRelative( fileid );
+            if ( p2 == 0x04 && item ) { // Only absolute reads are supported.
+                offset *= item->recordSize();
+                contents = item->contents();
+                if ( ( offset + length ) > contents.size() ) {
+                    sw1 = 0x94;
+                    sw2 = 0x02;
+                } else {
+                    sw1 = 0x9F;
+                    sw2 = length;
+                    response =
+                        QAtUtils::toHex( contents.mid( offset, length ) );
+                }
+            } else {
+                sw1 = 0x94;
+                sw2 = 0x08;
+            }
+        }
+        break;
+
+        case 192:       // GET RESPONSE
+        {
+            if ( !findItemRelative( fileid ) ) {
+                sw1 = 0x94;
+                sw2 = 0x04;
+                break;
+            }
+        }
+        // Fall through to the next case.
+
+        case 242:       // STATUS
+        {
+            // Format the status response according to GSM 51.011, 9.2.1.
+            char status[15];
+            status[0] = 0x00;           // RFU
+            status[1] = 0x00;
+            int size = currentItem->contents().size();
+            status[2] = (char)(size >> 8);
+            status[3] = (char)size;
+            status[4] = fileid.left(2).toInt(0, 16);
+            status[5] = fileid.right(2).toInt(0, 16);
+            if ( currentItem == rootItem ) {
+                status[6] = 0x01;
+            } if ( currentItem->isDirectory() ) {
+                status[6] = 0x02;
+            } else {
+                status[6] = 0x04;
+            }
+            status[7] = 0x00;           // RFU
+            status[8] = 0x00;
+            status[9] = 0x00;
+            status[10] = 0x00;
+            status[11] = 0x00;
+            status[12] = 2;             // Size of data that follows.
+            if ( currentItem->isDirectory() ) {
+                status[13] = 0x00;
+                status[14] = 0x00;
+            } else if ( currentItem->recordSize() > 1 ) {
+                status[13] = 0x01;
+                status[14] = (char)( currentItem->recordSize() );
+            } else {
+                status[13] = 0x00;
+                status[14] = 0x00;
+            }
+            sw1 = 0x90;
+            sw2 = 0x00;
+            response = QAtUtils::toHex( QByteArray( status, 15 ) );
+        }
+        break;
+
+        case 214:       // UPDATE BINARY
+        {
+            // Not implemented yet.
+            sw1 = 0x94;
+            sw2 = 0x08;
+        }
+        break;
+
+        case 220:       // UPDATE RECORD
+        {
+            // Not implemented yet.
+            sw1 = 0x94;
+            sw2 = 0x08;
+        }
+        break;
+
+        default: ok = false; break;
+    }
+
+    // Send the response information.
+    if ( sw1 != 0 ) {
+        QString resp;
+        resp = "+CRSM: " + QString::number(sw1) + "," + QString::number(sw2);
+        if ( !response.isEmpty() )
+            resp += "," + response;
+        rules->respond( resp );
+    }
+    if ( ok )
+        rules->respond( "OK" );
+    else
+        rules->respond( "ERROR" );
+}
+
+SimFileItem *SimFileSystem::findItem( const QString& fileid ) const
+{
+    return rootItem->findItem( fileid );
+}
+
+SimFileItem *SimFileSystem::findItemParent( const QString& fileid ) const
+{
+    QString parent = fileid.left( fileid.length() - 4 );
+    if ( parent.isEmpty() )
+        return rootItem;
+    else
+        return findItem( parent.right(4) );
+}
+
+SimFileItem *SimFileSystem::findItemRelative( const QString& fileid )
+{
+    SimFileItem *item;
+    if ( fileid == "3F00" ) {
+        // We can always find the root directory no matter where we are.
+        item = rootItem;
+    } else if ( currentItem->fileid() == fileid ) {
+        // We can always find where we currently are.
+        item = currentItem;
+    } else if ( currentItem->parentDir() &&
+                currentItem->parentDir()->fileid() == fileid ) {
+        // We can always find our parent directory.
+        item = currentItem->parentDir();
+    } else {
+        // Search the current item's immediate children.
+        QList<SimFileItem *> children = currentItem->children();
+        item = 0;
+        foreach( SimFileItem *temp, children ) {
+            if ( temp->fileid() == fileid ) {
+                item = temp;
+                break;
+            }
+        }
+        if ( !item )
+            return 0;
+    }
+    currentItem = item;
+    return item;
+}
+
+QString SimFileSystem::resolveFileId( const QString& _fileid ) const
+{
+    QString fileid = _fileid;
+
+    // Convert alphabetic names into their numeric equivalents.
+    const SimFileInfo *info = knownFiles;
+    while ( info->fileid ) {
+        if ( fileid == info->name ) {
+            fileid = info->fileid;
+            break;
+        }
+        ++info;
+    }
+
+    // Determine if the fileid is already a full path.
+    if ( fileid.startsWith( "3F" ) ||       // MF root directory.
+         fileid.startsWith( "7F" ) ||       // First-level DF directory.
+         fileid.startsWith( "2F" ) )        // First-level EF file.
+        return fileid;
+
+    // Extract the first component and search for a path back to the root.
+    QString newId = fileid;
+    QString first = fileid.left(4);
+    for(;;) {
+        info = knownFiles;
+        while ( info->fileid ) {
+            if ( first == info->fileid && info->parent ) {
+                first = info->parent;
+                newId = first + newId;
+                if ( first.startsWith( "3F" ) || first.startsWith( "7F" ) )
+                    return newId;
+                break;
+            }
+            ++info;
+        }
+        if ( !info->fileid ) {
+            // We could not find a suitable parent directory, so bail out.
+            return newId;
+        }
+    }
+}
+
+SimFileItem::SimFileItem( const QString& fileid, SimFileItem *parentDir )
+    : QObject( parentDir )
+{
+    _fileid = fileid;
+    _parentDir = parentDir;
+    _recordSize = 1;
+    _isDirectory = false;
+    if ( parentDir ) {
+        parentDir->_isDirectory = true;
+        parentDir->_children.append( this );
+    }
+}
+
+SimFileItem::~SimFileItem()
+{
+}
+
+SimFileItem *SimFileItem::findItem( const QString& fileid )
+{
+    if ( fileid == _fileid )
+        return this;
+    foreach ( SimFileItem *item, _children ) {
+        SimFileItem *temp = item->findItem( fileid );
+        if ( temp )
+            return temp;
+    }
+    return 0;
+}

Added: trunk/src/host/qemu-neo1973/phonesim/lib/simfilesystem.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/simfilesystem.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/simfilesystem.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef SIMFILESYSTEM_H
+#define SIMFILESYSTEM_H
+
+#include "phonesim.h"
+
+class SimFileItem;
+
+class SimFileSystem : public QObject
+{
+    Q_OBJECT
+public:
+    SimFileSystem( SimRules *rules, SimXmlNode& e );
+    ~SimFileSystem();
+
+    // Execute an AT+CRSM command against the filesystem.
+    void crsm( const QString& args );
+
+    // Find an item with a specific id.
+    SimFileItem *findItem( const QString& fileid ) const;
+
+    // Find the parent of an item with a specific id even if the
+    // item itself does not exist.  The parameter should be fully qualified.
+    SimFileItem *findItemParent( const QString& fileid ) const;
+
+    // Find an item relative to the current item and update current item.
+    SimFileItem *findItemRelative( const QString& fileid );
+
+    // Resolve a file identifier to its full path from the root directory.
+    QString resolveFileId( const QString& fileid ) const;
+
+private:
+    SimRules *rules;
+    SimFileItem *rootItem;
+    SimFileItem *currentItem;
+};
+
+class SimFileItem : public QObject
+{
+    Q_OBJECT
+public:
+    SimFileItem( const QString& fileid, SimFileItem *parentDir );
+    ~SimFileItem();
+
+    QString fileid() const { return _fileid; }
+    SimFileItem *parentDir() const { return _parentDir; }
+
+    QByteArray contents() const { return _contents; }
+    void setContents( const QByteArray& value ) { _contents = value; }
+
+    int recordSize() const { return _recordSize; }
+    void setRecordSize( int value ) { _recordSize = value; }
+
+    bool isDirectory() const { return _isDirectory; }
+    void setIsDirectory( bool value ) { _isDirectory = value; }
+
+    QList<SimFileItem *> children() const { return _children; }
+
+    SimFileItem *findItem( const QString& fileid );
+
+private:
+    QString _fileid;
+    SimFileItem *_parentDir;
+    QByteArray _contents;
+    int _recordSize;
+    bool _isDirectory;
+    QList<SimFileItem *> _children;
+};
+
+
+#endif /* SIMFILESYSTEM_H */

Added: trunk/src/host/qemu-neo1973/phonesim/lib/wap/qwsppdu.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/wap/qwsppdu.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/wap/qwsppdu.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,2431 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <qwsppdu.h>
+#include <qmimetype.h>
+#include <qtextcodec.h>
+#include <qdatetime.h>
+#include <qiodevice.h>
+#include <qbuffer.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+
+// Uncomment to turn on expanded WSP debugging.
+//#define WSP_DEBUG   1
+
+// Reference: WAP-230-WSP
+//            Wireless Application Protocol
+//            Wirelesss Session Protocol Specification
+// See also: http://www.wapforum.org/wina/wsp-content-type.htm
+
+static const char * const contentTypeAssignments[] = {
+    "*/*",
+    "text/*",
+    "text/html",
+    "text/plain",
+    "text/x-hdml",
+    "text/x-ttml",
+    "text/x-vCalendar",
+    "text/x-vCard",
+    "text/vnd.wap.wml",
+    "text/vnd.wap.wmlscript",
+    "text/vnd.wap.channel",
+    "Multipart/*",
+    "Multipart/mixed",
+    "Multipart/form-data",
+    "Multipart/byteranges",
+    "multipart/alternative",
+    "application/*",
+    "application/java-vm",
+    "application/x-www-form-urlencoded",
+    "application/x-hdmlc",
+    "application/vnd.wap.wmlc",
+    "application/vnd.wap.wmlscriptc",
+    "application/vnd.wap.channelc",
+    "application/vnd.wap.uaprof",
+    "application/vnd.wap.wtls-ca-certificate",
+    "application/vnd.wap.wtls-user-certificate",
+    "application/x-x509-ca-cert",
+    "application/x-x509-user-cert",
+    "image/*",
+    "image/gif",
+    "image/jpeg",
+    "image/tiff",
+    "image/png",
+    "image/vnd.wap.wbmp",
+    "application/vnd.wap.multipart.*",
+    "application/vnd.wap.multipart.mixed",
+    "application/vnd.wap.multipart.form-data",
+    "application/vnd.wap.multipart.byteranges",
+    "application/vnd.wap.multipart.alternative",
+    "application/xml",
+    "text/xml",
+    "application/vnd.wap.wbxml",
+    "application/x-x968-cross-cert",
+    "application/x-x968-ca-cert",
+    "application/x-x968-user-cert",
+    "text/vnd.wap.si",
+    "application/vnd.wap.sic",
+    "text/vnd.wap.sl",
+    "application/vnd.wap.slc",
+    "text/vnd.wap.co",
+    "application/vnd.wap.coc",
+    "application/vnd.wap.multipart.related",
+    "application/vnd.wap.sia",
+    "text/vnd.wap.connectivity-xml",
+    "application/vnd.wap.connectivity-wbxml",
+    "application/pkcs7-mime",
+    "application/vnd.wap.hashed-certificate",
+    "application/vnd.wap.signed-certificate",
+    "application/vnd.wap.cert-response",
+    "application/xhtml+xml",
+    "application/wml+xml",
+    "text/css",
+    "application/vnd.wap.mms-message",
+    "application/vnd.wap.rollover-certificate",
+    "application/vnd.wap.locc+wbxml",
+    "application/vnd.wap.loc+xml",
+    "application/vnd.syncml.dm+wbxml",
+    "application/vnd.syncml.dm+xml",
+    "application/vnd.syncml.notification",
+    "application/vnd.wap.xhtml+xml",
+    "application/vnd.wv.csp.cir",
+    "application/vnd.oma.dd+xml",
+    "application/vnd.oma.drm.message",
+    "application/vnd.oma.drm.content",
+    "application/vnd.oma.drm.rights+xml",
+    "application/vnd.oma.drm.rights+wbxml",
+    0
+};
+#define numContentTypes (int)((sizeof(contentTypeAssignments) / \
+                               sizeof(char *)) - 1)
+
+struct CharsetAssignment {
+    quint32 number;
+    char *charset;
+};
+
+static const CharsetAssignment charsetAssignments[] = {
+    { 0x07EA, "big5" },
+    { 0x03E8, "iso-10646-ucs-2" },
+    { 0x04, "iso-8859-1" },
+    { 0x05, "iso-8859-2" },
+    { 0x06, "iso-8859-3" },
+    { 0x07, "iso-8859-4" },
+    { 0x08, "iso-8859-5" },
+    { 0x09, "iso-8859-6" },
+    { 0x0A, "iso-8859-7" },
+    { 0x0B, "iso-8859-8" },
+    { 0x0C, "iso-8859-9" },
+    { 0x11, "shift_JIS" },
+    { 0x03, "us-ascii" },
+    { 0x6A, "utf-8" },
+    { 0x00, "" }
+};
+
+QWspHeaderCodec::~QWspHeaderCodec()
+{
+}
+
+class QWspDefaultCodec : public QWspHeaderCodec
+{
+public:
+    QWspDefaultCodec() {}
+
+    enum Type { Accept, AcceptLanguage, AcceptRanges, Age, Allow,
+                Authorization, Connection, ContentBase, ContentEncoding,
+                ContentLanguage, ContentLength, ContentLocation, ContentMD5,
+                ContentType, Date, ETag, Expires, From, Host,
+                IfModifiedSince, IfMatch, IfNoneMatch, IfRange,
+                IfUnmodifiedSince, Location, LastModified, MaxForwards, Pragma,
+                ProxyAuthenticate, ProxyAuthorization, Public, Range,
+                Referer, RetryAfter, Server, TransferEncoding, Upgrade,
+                UserAgent, Vary, Via, Warning, WWWAuthenticate,
+                ContentDisposition, XWapApplicationId, XWapContentURI,
+                XWapInitiatorURI, AcceptApplication, BearerIndication,
+                PushFlag, Profile, ProfileDiff, ProfileWarning, Expect,
+                TE, Trailer, AcceptCharset, AcceptEncoding, CacheControl,
+                ContentRange, XWapTod, ContentID, SetCookie, Cookie,
+                EncodingVersion
+    };
+
+    virtual QWspField decode(QWspPduDecoder &);
+    virtual bool encode(QWspPduEncoder&, const QWspField&);
+    virtual quint8 codePage() const { return 1; }
+
+private:
+    int fieldFromNumber(quint8 id);
+    int numberFromField(const QString &str);
+};
+
+struct WAPHeaderField {
+    quint8 number;
+    int version;
+    char *name;
+    QWspDefaultCodec::Type type;
+};
+
+static const WAPHeaderField headerFieldNameAssignments[] = {
+    { 0x00, 11, "Accept", QWspDefaultCodec::Accept },
+    { 0x01, 11, "Accept-Charset", QWspDefaultCodec::AcceptCharset },
+    { 0x02, 11, "Accept-Encoding", QWspDefaultCodec::AcceptEncoding },
+    { 0x03, 11, "Accept-Language", QWspDefaultCodec::AcceptLanguage },
+    { 0x04, 11, "Accept-Ranges", QWspDefaultCodec::AcceptRanges },
+    { 0x05, 11, "Age", QWspDefaultCodec::Age },
+    { 0x06, 11, "Allow", QWspDefaultCodec::Allow },
+    { 0x07, 11, "Authorization", QWspDefaultCodec::Authorization },
+    { 0x08, 11, "Cache-Control", QWspDefaultCodec::CacheControl },
+    { 0x09, 11, "Connection", QWspDefaultCodec::Connection },
+    { 0x0A, 11, "Content-Base", QWspDefaultCodec::ContentBase },
+    { 0x0B, 11, "Content-Encoding", QWspDefaultCodec::ContentEncoding },
+    { 0x0C, 11, "Content-Language", QWspDefaultCodec::ContentLanguage },
+    { 0x0D, 11, "Content-Length", QWspDefaultCodec::ContentLength },
+    { 0x0E, 11, "Content-Location", QWspDefaultCodec::ContentLocation },
+    { 0x0F, 11, "Content-MD5", QWspDefaultCodec::ContentMD5 },
+    { 0x10, 11, "Content-Range", QWspDefaultCodec::ContentRange },
+    { 0x11, 11, "Content-Type", QWspDefaultCodec::ContentType },
+    { 0x12, 11, "Date", QWspDefaultCodec::Date },
+    { 0x13, 11, "Etag", QWspDefaultCodec::ETag },
+    { 0x14, 11, "Expires", QWspDefaultCodec::Expires },
+    { 0x15, 11, "From", QWspDefaultCodec::From },
+    { 0x16, 11, "Host", QWspDefaultCodec::Host },
+    { 0x17, 11, "If-Modified-Since", QWspDefaultCodec::IfModifiedSince },
+    { 0x18, 11, "If-Match", QWspDefaultCodec::IfMatch },
+    { 0x19, 11, "If-None-Match", QWspDefaultCodec::IfNoneMatch },
+    { 0x1A, 11, "If-Range", QWspDefaultCodec::IfRange },
+    { 0x1B, 11, "If-Unmodified-Since", QWspDefaultCodec::IfUnmodifiedSince },
+    { 0x1C, 11, "Location", QWspDefaultCodec::Location },
+    { 0x1D, 11, "Last-Modified", QWspDefaultCodec::LastModified },
+    { 0x1E, 11, "Max-Forwards", QWspDefaultCodec::MaxForwards },
+    { 0x1F, 11, "Pragma", QWspDefaultCodec::Pragma },
+    { 0x20, 11, "Proxy-Authenticate", QWspDefaultCodec::ProxyAuthenticate },
+    { 0x21, 11, "Proxy-Authorization", QWspDefaultCodec::ProxyAuthorization },
+    { 0x22, 11, "Public", QWspDefaultCodec::Public },
+    { 0x23, 11, "Range", QWspDefaultCodec::Range },
+    { 0x24, 11, "Referer", QWspDefaultCodec::Referer },
+    { 0x25, 11, "Retry-After", QWspDefaultCodec::RetryAfter },
+    { 0x26, 11, "Server", QWspDefaultCodec::Server },
+    { 0x27, 11, "Transfer-Encoding", QWspDefaultCodec::TransferEncoding },
+    { 0x28, 11, "Upgrade", QWspDefaultCodec::Upgrade },
+    { 0x29, 11, "User-Agent", QWspDefaultCodec::UserAgent },
+    { 0x2A, 11, "Vary", QWspDefaultCodec::Vary },
+    { 0x2B, 11, "Via", QWspDefaultCodec::Via },
+    { 0x2C, 11, "Warning", QWspDefaultCodec::Warning },
+    { 0x2D, 11, "WWW-Authenticate", QWspDefaultCodec::WWWAuthenticate },
+    { 0x2E, 11, "Content-Disposition", QWspDefaultCodec::ContentDisposition },
+    { 0x2F, 12, "X-Wap-Application-Id", QWspDefaultCodec::XWapApplicationId },
+    { 0x30, 12, "X-Wap-Content-URI", QWspDefaultCodec::XWapContentURI },
+    { 0x31, 12, "X-Wap-Initiator-URI", QWspDefaultCodec::XWapInitiatorURI },
+    { 0x32, 12, "Accept-Application", QWspDefaultCodec::AcceptApplication },
+    { 0x33, 12, "Bearer-Indication", QWspDefaultCodec::BearerIndication },
+    { 0x34, 12, "Push-Flag", QWspDefaultCodec::PushFlag },
+    { 0x35, 12, "Profile", QWspDefaultCodec::Profile },
+    { 0x36, 12, "Profile-Diff", QWspDefaultCodec::ProfileDiff },
+    { 0x37, 12, "Profile-Warning", QWspDefaultCodec::ProfileWarning },
+    { 0x38, 13, "Expect", QWspDefaultCodec::Expect },
+    { 0x39, 13, "TE", QWspDefaultCodec::TE },
+    { 0x3A, 13, "Trailer", QWspDefaultCodec::Trailer },
+    { 0x3B, 13, "Accept-Charset", QWspDefaultCodec::AcceptCharset },
+    { 0x3C, 13, "Accept-Encoding", QWspDefaultCodec::AcceptEncoding },
+    { 0x3D, 13, "Cache-Control", QWspDefaultCodec::CacheControl },
+    { 0x3E, 13, "Content-Range", QWspDefaultCodec::ContentRange },
+    { 0x3F, 13, "X-Wap-Tod", QWspDefaultCodec::XWapTod },
+    { 0x40, 13, "Content-ID", QWspDefaultCodec::ContentID },
+    { 0x41, 13, "Set-Cookie", QWspDefaultCodec::SetCookie },
+    { 0x42, 13, "Cookie", QWspDefaultCodec::Cookie },
+    { 0x43, 13, "Encoding-Version", QWspDefaultCodec::EncodingVersion },
+    { 0x80, 13, "", QWspDefaultCodec::Accept }
+};
+
+static QString token(QString str, QChar c1, QChar c2, int *index)
+{
+    int start, stop;
+    start = str.indexOf(c1, *index, Qt::CaseInsensitive);
+    if (start == -1)
+        return QString();
+    stop = str.indexOf(c2, ++start, Qt::CaseInsensitive);
+    if (stop == -1)
+        return QString();
+
+    *index = stop + 1;
+    return str.mid(start, stop - start);
+}
+
+//changing timezones are slow, cache info in this var
+static int utcTimeZoneDiff = -1;
+
+/*  Returns the difference between local time and GMT time in seconds   */
+static int timeZoneDiff()
+{
+    if ( utcTimeZoneDiff == -1 ) {
+        QDateTime gmt, current = QDateTime::currentDateTime();
+        QString tz = getenv("TZ");
+        if ( !tz.isEmpty() && (setenv("TZ", "GMT", true) == 0) ) {
+            gmt = QDateTime::currentDateTime();
+        } else return 0;
+
+        QByteArray tzcstr = tz.toLatin1();
+        setenv("TZ", tzcstr.constData(), true );
+
+        utcTimeZoneDiff = gmt.secsTo( current );
+    }
+
+    return utcTimeZoneDiff;
+}
+
+static QString secsToUTC(int seconds)
+{
+    QString str;
+
+    int h = seconds / 3600;
+    int m = ( abs(seconds) - abs(h * 3600) ) / 60;
+    str.sprintf("%+.2d%.2d", h, m );
+
+    return str;
+}
+
+static int UTCToSecs(QString utc)
+{
+    if ( utc.length() != 5 )
+        return 0;
+
+    bool result;
+    int h = utc.left(3).toInt(&result);
+    if ( !result)
+        return 0;
+
+    int m = utc.right(2).toInt(&result);
+    if ( !result)
+        return 0;
+
+    return (h*3600 + m*60);
+}
+
+
+/*!
+  \class QWspDateTime
+  \mainclass
+  \brief The QWspDateTime class provides functions for converting between the WSP date time formats and standard date time formats.
+  \ingroup time
+  \ingroup telephony
+
+  The QWspDateTime class provides functions for converting between the WSP
+  date time formats and standard date time formats.
+*/
+
+/*!
+    Parses the HTTP date format within \a in.
+
+    \sa dateString()
+*/
+QDateTime QWspDateTime::parseDate(QString in)
+{
+    const QString Months("janfebmaraprmayjunjulaugsepoctnovdec");
+    QDateTime dateTime;
+    QString str, org;
+    int month = -1, day = -1, year = -1;
+    bool ok;
+    int x, index;
+    uint len;
+    QString time, timeDiff;
+
+    for (int z = 0; z < in.length(); z++) {
+        if (in[(int)z] != ',') {
+            org += in[(int)z];
+        } else {
+            org += " ";
+        }
+    }
+
+    org = org.simplified();
+    org += " ";
+
+    index = org.indexOf(' ');
+    str = org.left((uint) index);
+    while ( str != QString() ) {
+        len = str.length();
+        index--;
+        if ( (day == -1) && (len <= 2) ) {
+            x = str.toInt(&ok);
+            if ( ok )
+                day = x;
+        } else if ( (month == -1) && (len == 3) ) {
+            x = Months.indexOf( str.toLower() );
+            if ( x >= 0 )
+                month = (x + 3) / 3;
+        } else if ( (year == -1) && (len == 4) ) {
+            x = str.toInt(&ok);
+            if ( ok )
+                year = x;
+        } else if ( time.isEmpty() && len == 8 ) {      // time part: 14:22:22
+            time = str;
+        } else if ( timeDiff.isEmpty() && len == 5 ) {  // time localizer: +1000
+            timeDiff = str;
+        }
+
+        str = token(org, ' ', ' ', &index);
+    }
+
+    if ( (day != -1) && (month != -1) && (year != -1) ) {
+        dateTime.setDate( QDate(year, month, day) );
+
+        if ( !time.isEmpty() ) {
+            int h = time.left(2).toInt();
+            int m = time.mid(3, 2).toInt();
+            int senderLocal = UTCToSecs( timeDiff );
+
+            //adjust sender local time to our local time
+            int localDiff = timeZoneDiff() - senderLocal;
+
+            //we add seconds after adding time, as it may change the date
+            dateTime.setTime( QTime(h, m) );
+            dateTime = dateTime.addSecs( localDiff);
+        }
+    }
+
+    return dateTime;
+}
+
+/*!
+    Convert \a d into the HTTP date time format.
+
+    \sa parseDate()
+*/
+QString QWspDateTime::dateString(QDateTime d)
+{
+    QDate date = d.date();
+    QTime time = d.time();
+    QString str;
+    QByteArray dayName = date.shortDayName(date.dayOfWeek()).toUtf8();
+    QByteArray monthName = date.shortMonthName(date.month()).toUtf8();
+    QByteArray utcOffs = secsToUTC(timeZoneDiff()).toUtf8();
+    str.sprintf("%s, %.2d %s %d %.2d:%.2d:%.2d %s",
+            dayName.constData(),
+            date.day(),
+            monthName.constData(),
+            date.year(),
+            time.hour(),
+            time.minute(),
+            time.second(),
+            utcOffs.constData());
+
+    return str;
+}
+
+/*!
+    Convert the GMT time \a t into a QDateTime value.
+
+    \sa toTime_t(), toGmtTime_t()
+*/
+QDateTime QWspDateTime::fromGmtTime_t(quint32 t)
+{
+    QDateTime dt;
+    dt.setTime_t(t + timeZoneDiff());
+    return dt;
+}
+
+/*!
+    Convert \a dt into a seconds value in local time.
+
+    \sa fromGmtTime_t(), toGmtTime_t()
+*/
+quint32 QWspDateTime::toTime_t(const QDateTime &dt)
+{
+    QDateTime st(QDate(1970, 1, 1));
+    return st.secsTo(dt) - timeZoneDiff();
+}
+
+/*!
+    Convert \a dt into a seconds value in GMT time.
+
+    \sa fromGmtTime_t(), toTime_t()
+*/
+quint32 QWspDateTime::toGmtTime_t(const QDateTime &dt)
+{
+    QDateTime st(QDate(1970, 1, 1));
+    return st.secsTo(dt) - 2*timeZoneDiff();
+}
+
+//===========================================================================
+
+/*!
+  \class QWspField
+  \mainclass
+  \brief The QWspField class provides an encapsulation of a field name and value.
+  \ingroup telephony
+
+  The QWspField class provides an encapsulation of a field name and value.
+*/
+
+/*!
+    Construct an empty WSP field.
+*/
+QWspField::QWspField()
+{
+}
+
+/*!
+    Construct a copy of \a field.
+*/
+QWspField::QWspField( const QWspField& field )
+{
+    name = field.name;
+    value = field.value;
+}
+
+/*!
+    Destruct this WSP field.
+*/
+QWspField::~QWspField()
+{
+}
+
+/*!
+    Copy the contents of \a field into this object.
+*/
+QWspField& QWspField::operator=( const QWspField& field )
+{
+    if ( this != &field ) {
+        name = field.name;
+        value = field.value;
+    }
+    return *this;
+}
+
+//===========================================================================
+
+/*!
+  \class QWspPduDecoder
+  \mainclass
+  \brief The QWspPduDecoder class provides facilities for parsing WSP PDU's.
+  \ingroup telephony
+
+  The QWspPduDecoder class provides facilities for parsing WSP PDU's.
+*/
+
+
+/*!
+    Construct a WSP PDU decoder to decode the data from \a d.
+*/
+QWspPduDecoder::QWspPduDecoder(QIODevice *d)
+    : dev(d), stat(OK)
+{
+    headerCodec = defaultCodec = new QWspDefaultCodec;
+}
+
+/*!
+    Destroy this WSP PDU decoder.
+*/
+QWspPduDecoder::~QWspPduDecoder()
+{
+}
+
+/*!
+    Peek at the next octet in the input data stream.
+*/
+quint8 QWspPduDecoder::peekOctet()
+{
+    char o;
+    if ( dev->getChar(&o) ) {
+        dev->ungetChar(o);
+        return (quint8)o;
+    } else {
+        return (quint8)0;
+    }
+}
+
+/*!
+    Decode the next octet from the input data stream.
+*/
+quint8 QWspPduDecoder::decodeOctet()
+{
+    char o;
+    if (dev->atEnd()) {
+        stat = Eof;
+        return (quint8)0;
+    } else if ( dev->getChar(&o) ) {
+        return (quint8)o;
+    } else {
+        stat = Eof;
+        return (quint8)0;
+    }
+}
+
+/*!
+    Decode an unsigned 8-bit integer from the input data stream.
+*/
+quint8 QWspPduDecoder::decodeUInt8()
+{
+    return decodeOctet();
+}
+
+/*!
+    Decode an unsigned 16-bit integer from the input data stream.
+*/
+quint16 QWspPduDecoder::decodeUInt16()
+{
+    quint16 d;
+    d = quint16(decodeOctet()) << 8;
+    d |= quint16(decodeOctet());
+
+    return d;
+}
+
+/*!
+    Decode an unsigned 32-bit integer from the input data stream.
+*/
+quint32 QWspPduDecoder::decodeUInt32()
+{
+    quint32 d;
+    d = quint32(decodeOctet()) << 24;
+    d |= quint32(decodeOctet()) << 16;
+    d |= quint32(decodeOctet()) << 8;
+    d |= quint32(decodeOctet());
+
+    return d;
+}
+
+/*!
+    Decode an unsigned 32-bit integer from the input data stream
+    that is encoded with the variable-length WSP encoding.
+*/
+quint32 QWspPduDecoder::decodeUIntVar()
+{
+    unsigned char d[5];
+    int count = 0;
+    quint8 o = decodeOctet();
+    while (o & 0x80 && count < 4) {
+        d[count++] = o & 0x7F;
+        o = decodeOctet();
+    }
+    d[count++] = o;
+
+    quint32 v = 0;
+    for (int i = 0; i < count; i++) {
+        v |= (quint32)d[i] << ((count-i-1)*7);
+    }
+
+    return v;
+}
+
+/*!
+    Decode a short integer value from the input data stream.
+    Short integers are between 0 and 127, and have the high bit set
+    to indicate "short".
+*/
+quint8 QWspPduDecoder::decodeShortInteger()
+{
+    return decodeUInt8() & 0x7F;
+}
+
+/*!
+    Decode a long integer value from the input data stream.
+    Long integers start with a byte indicating the length of
+    the integer encoding, followed by that many bytes from
+    most significant onwards.
+*/
+quint32 QWspPduDecoder::decodeLongInteger()
+{
+    quint8 len = decodeUInt8();    // short length
+    quint32 v = 0;
+    for (int i = 0; i < len && !dev->atEnd(); i++) {
+        v |= (quint32)decodeOctet() << ((len-i-1)*8);
+    }
+    return v;
+}
+
+/*!
+    Decode either a short integer or a long integer, depending
+    upon whether the first byte has the high bit set (short)
+    or unset (long).
+
+    \sa decodeShortInteger(), decodeLongInteger()
+*/
+quint32 QWspPduDecoder::decodeInteger()
+{
+    if (peekOctet() & 0x80)
+        return decodeShortInteger();
+    else
+        return decodeLongInteger();
+}
+
+/*!
+    Decode a length value from the input data stream.  Leading byte
+    values between 0 and 30 indicate an explicit length.  A leading
+    byte value of 31 indicates that a variable-length integer follows.
+
+    \sa decodeUIntVar()
+*/
+quint32 QWspPduDecoder::decodeLength()
+{
+    quint32 len = 0;
+    quint8 o = peekOctet();
+    if (o < 31) {
+        len = (quint32)decodeOctet();
+    } else if (o == 31) {
+        decodeOctet();
+        len = decodeUIntVar();
+    }
+
+    return len;
+}
+
+/*!
+    Decode a text string from the input data stream.
+*/
+QString QWspPduDecoder::decodeTextString()
+{
+    QString str;
+    quint8 o = decodeOctet();
+    if (o == '\"')
+        o = decodeOctet();
+    while (o != 0 && !dev->atEnd()) {
+        str += o;
+        o = decodeOctet();
+    }
+
+    int l = str.length();
+    if ((l > 0) && (str[l-1] == '\"'))
+        str.chop(1);
+
+    return str;
+}
+
+QString QWspPduDecoder::decodeTextBlock(int length)
+{
+    QString result;
+    for(int i = 0; i < length; ++i)
+        result += decodeOctet();
+    return result;
+}
+
+int QWspPduDecoder::decodeMIBEnum(quint32& num)
+{
+    num = 0;
+    //length
+    quint32 len = decodeOctet();
+    if(len == 1)
+        num = decodeOctet();
+    else if(len == 2)
+        num = decodeUInt16();
+    return len;
+}
+
+/*!
+    Decode an encoded string from the input data stream.
+*/
+QString QWspPduDecoder::decodeEncodedString()
+{
+    quint8 o = peekOctet();
+    if (o >= 32 && o <= 127)
+        return decodeTextString();
+
+    quint32 len = decodeLength();
+    QString encText;
+    if(len)
+    {
+        quint32 mib = 0;
+        quint32 miblen = decodeMIBEnum(mib);
+        int textlen = len-miblen-1;
+        if(peekOctet() == '\"') //ignore quote
+        {
+            decodeOctet();
+            --textlen;
+        }
+        QString encText = decodeTextBlock(textlen);
+        return decodeCharset(encText, mib);
+    }
+    return encText;
+}
+
+/*!
+    Decode a token text value from the input data stream.
+*/
+QString QWspPduDecoder::decodeTokenText()
+{
+    return decodeTextString();
+}
+
+/*!
+    Decode a version indicator from the input data stream.
+*/
+QString QWspPduDecoder::decodeVersion()
+{
+    QString version;
+    quint8 octet = peekOctet();
+    if (octet & 0x80) {
+        int v = decodeShortInteger();
+        version = QString::number((v & 0x70) >> 4);
+        v &= 0x0F;
+        if (v != 0x0F)
+            version += "." + QString::number(v);
+    } else {
+        version = decodeTextString();
+    }
+
+    return version;
+}
+
+/*!
+    Decode a content type value from the input data stream.
+*/
+QString QWspPduDecoder::decodeContentType()
+{
+    QString type;
+    // Content-type-value = Constrained-Media | Content-general-form
+    // Constrained-Media = Constrained-encoding
+    // Constrained-encoding = Extension-Media | Short-integer
+    // Extension-Media *Text End-of-string
+    // Content-general-form = Value-length Media-type
+    // Media-type = (Well-known-media | Extension-Media) *(Parameter)
+    // Well-known-media = Integer-value
+    quint8 o = peekOctet();
+#ifdef WSP_DEBUG
+    qDebug("decodeContentType: %d", o);
+#endif
+    if (o <= 31) {
+        // Content-general-form
+        quint32 len = decodeLength();
+#ifdef WSP_DEBUG
+        qDebug("Content type len: %d", len);
+#endif
+        int endByte = (int)(dev->pos()+len);
+        // decode media type
+        o = peekOctet();
+        if (o & 0x80) {
+            // Well-known-media
+            quint8 enc = decodeInteger();
+            if (enc < numContentTypes) {
+                type = contentTypeAssignments[enc];
+            } else {
+                qWarning("Unknown content type: %d", enc);
+                stat = Unhandled;
+            }
+        } else {
+            // Extension-Media
+            o = decodeOctet();
+            while (o != 0) {
+                type += o;
+                o = decodeOctet();
+            }
+        }
+        while (endByte > ((int)(dev->pos())) && !dev->atEnd()) {
+            // read parameters
+#ifdef WSP_DEBUG
+            qDebug("Decode parameter");
+#endif
+            QString p = decodeParameter();
+            if (!p.isEmpty())
+                type += "; " + p;
+        }
+    } else if (o & 0x80 ) {
+        // Constrained-encoding = Short-integer
+        quint8 enc = decodeShortInteger();
+        if (enc < numContentTypes) {
+            type = contentTypeAssignments[enc];
+        } else {
+            qWarning("Unknown content type: %d", enc);
+            stat = Unhandled;
+        }
+    } else {
+        // Constrained-encoding = Extension-Media
+        o = decodeOctet();
+        while (o != 0) {
+            type += o;
+            o = decodeOctet();
+        }
+    }
+
+    return type;
+}
+
+/*!
+    Decode a field declaration consisting of a name and a value
+    from the input data stream.
+*/
+QWspField QWspPduDecoder::decodeField()
+{
+    quint8 octet = peekOctet();
+    if (octet == 127 || (octet >= 1 && octet <= 31)) {
+        decodeOctet();
+        if (octet == 127) {
+            // Shift-delimiter Page-identity
+            octet = decodeOctet(); // == code page
+        }
+        if (octet == 1)
+            setHeaderCodec(defaultCodec);
+        else
+            emit selectCodePage(octet);
+        octet = peekOctet();
+    }
+
+    QWspField fld;
+    if (octet & 0x80) {
+        // Well-known-header
+        fld = headerCodec->decode(*this);
+#ifdef WSP_DEBUG
+        qDebug("decoded well-known-header: %s=%s", fld.name.toLatin1().constData(), fld.value.toLatin1().constData());
+#endif
+    } else {
+        // Application-header
+        fld.name = decodeTokenText();
+        fld.value = decodeTextString();
+    }
+
+    return fld;
+}
+
+/*!
+    Decode a parameter value from the input data stream.
+*/
+QString QWspPduDecoder::decodeParameter()
+{
+    QString p;
+    quint8 octet = peekOctet();
+
+    if (octet <= 31 || octet & 0x80) {
+        // Typed-parameter = Well-known-parameter-token Typed-value
+        quint32 parm = decodeInteger();
+        octet = peekOctet();
+        switch (parm) {
+            case 0x00: // Q
+                {
+                    p = "q=";
+                    quint32 q = decodeUIntVar();
+                    quint32 q1 = q - (q <= 100 ? 1 : 100);
+                    QString v = "00" + QString::number(q1);
+                    p += "0." + v.right(q <= 100 ? 2 : 3);
+                }
+                break;
+            case 0x01: // charset
+                p = "charset=";
+                if (octet == 128) {
+                    p += "\"*\"";
+                } else {
+                    quint32 c = decodeInteger();
+                    int i = 0;
+                    while (charsetAssignments[i].number) {
+                        if (charsetAssignments[i].number == c)
+                            p += charsetAssignments[i].charset;
+                        i++;
+                    }
+                    if (!charsetAssignments[i].number)
+                        p += "\"*\"";
+                }
+                break;
+            case 0x02: // level
+                p = "level=" + decodeVersion();
+                break;
+            case 0x03:
+                p = "type=" + QString::number(decodeInteger());
+                break;
+            case 0x05:
+                p = "name=\"" + decodeTextString() + '\"';
+                break;
+            case 0x06:
+                p = "filename=\"" + decodeTextString() + '\"';
+                break;
+            case 0x07:
+                p = "differences=";
+                if (octet & 0x80)
+                    p += QString::number((int)decodeShortInteger());
+                else
+                    p += '\"' + decodeTokenText() + '\"';
+                break;
+            case 0x08:
+                p = "padding=" + QString::number((int)decodeShortInteger());
+                break;
+            case 0x09:
+                p = "type=";
+                if (octet & 0x80 ) {
+                    // Constrained-encoding = Short-integer
+                    quint8 enc = decodeShortInteger();
+                    if (enc < numContentTypes)
+                        p += contentTypeAssignments[enc];
+                    else
+                        qWarning("Unknown content type: %d", enc);
+                } else {
+                    // Constrained-encoding = Extension-Media
+                    p += '\"' + decodeTextString() + '\"';
+                }
+                break;
+            case 0x0A:
+                p = "start=\"" + decodeTextString() + '\"';
+                break;
+            case 0x0B:
+                p = "start-info=\"" + decodeTextString() + '\"';
+                break;
+            case 0x0C:
+                p = "comment=\"" + decodeTextString() + '\"';
+                break;
+            case 0x0D:
+                p = "domain=\"" + decodeTextString() + '\"';
+                break;
+            case 0x0E:
+                {
+                    p = "max-age=";
+                    QDateTime dt = QWspDateTime::fromGmtTime_t(decodeInteger());
+                    p += '\"' + QWspDateTime::dateString(dt) + '\"';
+                }
+                break;
+            case 0x0F:
+                p = "path=\"" + decodeTextString() + '\"';
+                break;
+            case 0x10:
+                p = "secure";
+                break;
+            default:
+                qWarning("Unknown parameter type: %d", parm);
+                stat = Fatal;
+                break;
+        }
+    } else {
+        // Untyped-parameter
+        p = decodeTokenText() + "=";
+        octet = peekOctet();
+        if (octet <= 31 || octet & 0x80) {
+            p += decodeInteger();
+        } else {
+            // Extension-Media
+            p += '\"';
+            octet = decodeOctet();
+            while (octet != 0 && !dev->atEnd()) {
+                p += octet;
+                octet = decodeOctet();
+            }
+            p += '\"';
+        }
+    }
+
+#ifdef WSP_DEBUG
+    qDebug("Parameter: %s", p.toLatin1().constData());
+#endif
+
+    return p;
+}
+
+/*!
+    Decode a multipart content block from the input data stream.
+*/
+QWspMultipart QWspPduDecoder::decodeMultipart()
+{
+    QWspMultipart mp;
+    quint32 count = decodeUIntVar();
+#ifdef WSP_DEBUG
+    qDebug("%d parts", count);
+#endif
+    for (unsigned int i = 0; i < count; i++) {
+        mp.addPart(decodePart());
+    }
+
+    return mp;
+}
+
+/*!
+    Decode the content type and headers from the input data stream.
+    The \a hdrLen parameter indicates the number of bytes within
+    the block that holds the content type and headers.  The \a part
+    parameter indicates the object to place the content type and
+    header information into.
+*/
+void QWspPduDecoder::decodeContentTypeAndHeaders(QWspPart& part, quint32 hdrLen)
+{
+    int curByte = (int)(dev->pos());
+    int afterHeader = curByte + (int)hdrLen;
+    QWspField field;
+    field.name = "Content-Type";
+#ifdef WSP_DEBUG
+    qDebug("header len: %d", hdrLen);
+#endif
+    field.value = decodeContentType();
+    part.addHeader(field);
+#ifdef WSP_DEBUG
+    qDebug("ContentType: %s", field.value.toLatin1().constData());
+#endif
+    hdrLen -= ((int)(dev->pos())) - curByte;
+
+    int dataByte = ((int)(dev->pos())) + hdrLen;
+    while (((int)(dev->pos())) < dataByte && !dev->atEnd()) {
+        field = decodeField();
+        part.addHeader(field);
+#ifdef WSP_DEBUG
+        qDebug(" Read field: %s = %s", field.name.toLatin1().constData(), field.value.toLatin1().constData());
+#endif
+    }
+
+    dev->seek(afterHeader);
+}
+
+/*!
+    Decode a single WSP part from an input data stream.
+*/
+QWspPart QWspPduDecoder::decodePart()
+{
+    quint32 hdrLen = decodeUIntVar();
+    quint32 dataLen = decodeUIntVar();
+
+    QWspPart part;
+
+    decodeContentTypeAndHeaders(part, hdrLen);
+
+#ifdef WSP_DEBUG
+    qDebug("data len: %d", dataLen);
+#endif
+    part.readData(dev, dataLen);
+
+    QString d(part.data());
+#ifdef WSP_DEBUG
+    qDebug("data: %s", d.toLatin1().constData());
+#endif
+
+    return part;
+}
+
+/*!
+    Decode a WSP push datagram from an input data stream.
+*/
+QWspPush QWspPduDecoder::decodePush()
+{
+    QWspPush part;
+
+    part.setIdentifier(decodeOctet());
+    part.setPduType(decodeOctet());
+
+    quint32 hdrLen = decodeUIntVar();
+
+    decodeContentTypeAndHeaders(part, hdrLen);
+
+    part.readData(dev, ((int)dev->size()) - ((int)(dev->pos())));
+
+    return part;
+}
+
+/*!
+    \fn void QWspPduDecoder::setHeaderCodec(QWspHeaderCodec *c)
+
+    Set the header codec, that converts byte values into string names, to \a c.
+*/
+
+/*!
+    \enum QWspPduDecoder::Status
+    This enumeration defines the status of the input dats stream.
+
+    \value OK The stream is OK.
+    \value Unhandled The stream contains data that cannot be handled.
+    \value Eof End of file was reached before the real end of the message.
+    \value Fatal The stream contains data that caused a fatal parse error.
+*/
+
+/*!
+    \fn QWspPduDecoder::Status QWspPduDecoder::status() const
+
+    Get the current status of the input stream.
+*/
+
+/*!
+    \fn void QWspPduDecoder::setStatus(Status s)
+
+    Set the status of the input stream to \a s.
+*/
+
+/*!
+    \fn QIODevice *QWspPduDecoder::device()
+
+    Get the device that this WSP PDU decoder is reading from.
+*/
+
+/*!
+    \fn void QWspPduDecoder::selectCodePage(quint8 page)
+
+    Signal that is emitted when the WSP PDU decoder wants to change
+    the header code \a page.  Slots that are connected to this signal
+    should call setHeaderCodec() to select the correct codec.
+*/
+
+QString QWspPduDecoder::decodeCharset( const QString &encoded, quint32 mib)
+{
+    // Get the codec that is associated with the character set.
+    QTextCodec *codec = QTextCodec::codecForMib( mib );
+    if ( !codec )
+        return encoded;
+
+    // Convert the input body into a byte array.
+    QByteArray bytes( encoded.length(), 0 );
+
+
+    // network byte order for unicode
+    if(mib == 1000)
+    {
+        for(int x = 1; x < encoded.length(); x+=2)
+        {
+            bytes[x-1] = (char)encoded[x].unicode();
+            bytes[x] = (char)encoded[x-1].unicode();
+        }
+    }
+    else
+    {
+        int posn = (int)encoded.length();
+        while ( posn > 0 ) {
+            --posn;
+            bytes[posn] = (char)( encoded[posn].unicode() );
+        }
+    }
+
+    // Convert the byte array into Unicode and return it.
+    return codec->toUnicode( bytes );
+}
+
+//===========================================================================
+
+/*!
+  \class QWspPduEncoder
+  \mainclass
+  \brief The QWspPduEncoder class provides facilities for writing WSP PDU's.
+  \ingroup telephony
+
+  The QWspPduEncoder class provides facilities for writing WSP PDU's.
+*/
+
+
+/*!
+    Create a WSP PDU encoder that writes the the output data stream \a d.
+*/
+QWspPduEncoder::QWspPduEncoder(QIODevice *d)
+    : dev(d)
+{
+    headerCodec = defaultCodec = new QWspDefaultCodec;
+}
+
+/*!
+    Destroy this WSP PDU encoder.
+*/
+QWspPduEncoder::~QWspPduEncoder()
+{
+}
+
+/*!
+    Encode an \a octet to the output data stream.
+*/
+void QWspPduEncoder::encodeOctet(quint8 octet)
+{
+    dev->putChar((char)octet);
+}
+
+/*!
+    Encode an unsigned 8-bit \a octet to the output data stream.
+*/
+void QWspPduEncoder::encodeUInt8(quint8 octet)
+{
+    dev->putChar((char)octet);
+}
+
+/*!
+    Encode an unsigned 16-bit value \a d to the output data stream.
+*/
+void QWspPduEncoder::encodeUInt16(quint16 d)
+{
+    dev->putChar((char)(d >> 8));
+    dev->putChar((char)(d & 0x0f));
+}
+
+/*!
+    Encode an unsigned 32-bit value \a d to the output data stream.
+*/
+void QWspPduEncoder::encodeUInt32(quint32 d)
+{
+    dev->putChar((char)((d >> 24) & 0x0f));
+    dev->putChar((char)((d >> 16) & 0x0f));
+    dev->putChar((char)((d >> 8) & 0x0f));
+    dev->putChar((char)(d & 0x0f));
+}
+
+/*!
+    Encode an unsigned variable length integer value \a iv
+    to the output data stream.
+*/
+void QWspPduEncoder::encodeUIntVar(quint32 iv)
+{
+    unsigned char d[5];
+    int count = 0;
+    while (iv || !count) {
+        d[count++] = iv & 0x7F;
+        iv = iv >> 7;
+    }
+
+    while (count) {
+        count--;
+        int val = d[count];
+        if (count)
+            val |= 0x80;
+        dev->putChar((char)val);
+    }
+}
+
+/*!
+    Encode a short integer value \a d to the output data stream.
+*/
+void QWspPduEncoder::encodeShortInteger(quint8 d)
+{
+    dev->putChar((char)(d | 0x80));
+}
+
+/*!
+    Encode a long integer value \a iv to the output data stream.
+*/
+void QWspPduEncoder::encodeLongInteger(quint32 iv)
+{
+    unsigned char d[5];
+    int count = 0;
+    while (iv || !count) {
+        d[count++] = iv & 0xFF;
+        iv = iv >> 8;
+    }
+
+    encodeUInt8(count);
+    while (count) {
+        count--;
+        dev->putChar((char)(d[count]));
+    }
+}
+
+/*!
+    Encode a short or long integer value \a d to the output data stream.
+*/
+void QWspPduEncoder::encodeInteger(quint32 d)
+{
+    if (d < 128)
+        encodeShortInteger(d);
+    else
+        encodeLongInteger(d);
+}
+
+/*!
+    Encode a length value \a d to the output data stream.
+*/
+void QWspPduEncoder::encodeLength(quint32 d)
+{
+    if (d <= 30) {
+        encodeOctet(d);
+    } else {
+        encodeOctet(31);
+        encodeUIntVar(d);
+    }
+}
+
+/*!
+    Encode a text string \a str to the output data stream.
+*/
+void QWspPduEncoder::encodeTextString(const QString &str)
+{
+    if ((uchar)str[0].toLatin1() >= 128)
+        dev->putChar('\"');
+
+    for (int i = 0; i < str.length(); i++)
+        dev->putChar((char)(str[i].toLatin1()));
+
+    if ((uchar)str[0].toLatin1() >= 128)
+        dev->putChar('\"');
+
+    dev->putChar(0);
+}
+
+/*!
+    Encode an encoded string \a str to the output data stream.
+*/
+void QWspPduEncoder::encodeEncodedString(const QString &str)
+{
+    encodeTextString(str);
+}
+
+/*!
+    Encode a token text string \a str to the output data stream.
+*/
+void QWspPduEncoder::encodeTokenText(const QString &str)
+{
+    encodeTextString(str);
+}
+
+/*!
+    Encode a version \a value to the output data stream.
+*/
+void QWspPduEncoder::encodeVersion(const QString &value)
+{
+    int dot = value.indexOf(QChar('.'));
+    int major = 0;
+    int minor = 0;
+    if (dot > 0) {
+        major = value.left(dot).toInt();
+        minor = value.mid(dot+1).toInt();
+    } else {
+        major = value.toInt();
+    }
+#ifdef WSP_DEBUG
+    qDebug("Major: %d  Minor: %d", major, minor);
+#endif
+    if (major >= 1 && major <= 7 && minor <= 14){
+        quint8 encVal;
+        if (dot)
+            encVal = (major << 4) | minor;
+        else
+            encVal = (major << 4) | 0x0F;
+        encodeShortInteger(encVal);
+    } else {
+        encodeTextString(value);
+    }
+}
+
+/*!
+    Encode a \a field consisting of a name and value to the output data stream.
+*/
+void QWspPduEncoder::encodeField(const QWspField &field)
+{
+#ifdef WSP_DEBUG
+    qDebug("Encode field: %s=%s", field.name.toLatin1().constData(), field.value.toLatin1().constData());
+#endif
+    if (!headerCodec->encode(*this, field)) {
+        encodeTokenText(field.name);
+        encodeTextString(field.value);
+    }
+}
+
+/*!
+    Encode a parameter value \a p to the output data stream.
+*/
+void QWspPduEncoder::encodeParameter(const QString &p)
+{
+    QString param = p;
+    while (param.length() && param[0].isSpace())
+        param = param.mid(1);
+    while (param.length() && param[param.length()-1].isSpace())
+        param.truncate(param.length()-1);
+#ifdef WSP_DEBUG
+    qDebug("Encoding parameter: %s", param.toLatin1().constData());
+#endif
+    if (param.indexOf("q=") == 0) {
+        QString value = param.mid(2);
+        int dot = value.indexOf(QChar('.'));
+        if (dot >= 0)
+            value = value.mid(dot+1);
+        if (value.length() <= 2) {
+            quint32 q = value.toUInt() * 100 + 1;
+            encodeInteger(0x00);
+            encodeUIntVar(q);
+        } else if (value.length() == 3) {
+            quint32 q = value.toUInt() * 1000 + 1;
+            encodeInteger(0x00);
+            encodeUIntVar(q);
+        }
+    } else if (param.indexOf("charset=") == 0) {
+        encodeInteger(0x01);
+        QString value = unquoteString(param.mid(8));
+        if (value == "*") {
+            encodeOctet(128);
+        } else {
+            int i = 0;
+            while (charsetAssignments[i].number) {
+                if (charsetAssignments[i].charset == value)
+                    break;
+                i++;
+            }
+            if (charsetAssignments[i].number)
+                encodeInteger(charsetAssignments[i].number);
+            else
+                qWarning("Unknown charset");    //### unrecoverable
+        }
+    } else if (param.indexOf("level=") == 0) {
+        encodeInteger(0x02);
+        QString value = param.mid(6);
+        int dot = value.indexOf(QChar('.'));
+        int major = 0;
+        int minor = 0;
+        if (dot > 0) {
+            major = value.left(dot).toInt();
+            minor = value.mid(dot+1).toInt();
+        } else {
+            major = value.toInt();
+        }
+#ifdef WSP_DEBUG
+        qDebug("Major: %d  Minor: %d", major, minor);
+#endif
+        if (major >= 1 && major <= 7 && minor <= 14){
+            quint8 encVal;
+            if (dot)
+                encVal = (major << 4) | minor;
+            else
+                encVal = (major << 4) | 0x0F;
+            encodeShortInteger(encVal);
+        } else {
+            encodeTextString(value);
+        }
+    } else if (param.indexOf("type=") == 0) {
+        bool ok;
+        quint32 d = param.mid(5).toUInt(&ok);
+        if (ok) {
+            encodeInteger(0x03);
+            encodeInteger(d);
+        } else {
+#ifdef WSP_DEBUG
+            qDebug("handling type param");
+#endif
+            encodeInteger(0x09);
+            QString value = unquoteString(param.mid(5));
+            int idx = 0;
+            while (contentTypeAssignments[idx]) {
+                if (value == contentTypeAssignments[idx])
+                    break;
+                idx++;
+            }
+
+            if (contentTypeAssignments[idx]) {
+                encodeShortInteger(idx);
+            } else {
+                encodeTextString(value);
+            }
+        }
+    } else if (param.indexOf("name=") == 0) {
+        encodeInteger(0x05);
+        encodeTextString(unquoteString(param.mid(5)));
+    } else if (param.indexOf("filename=") == 0) {
+        encodeInteger(0x06);
+        encodeTextString(unquoteString(param.mid(9)));
+    } else if (param.indexOf("differences=") == 0) {
+        encodeInteger(0x07);
+        QString value = unquoteString(param.mid(12));
+        bool ok;
+        quint32 d = value.toUInt(&ok);
+        if (ok) {
+            encodeShortInteger(d);
+        } else {
+            encodeTokenText(value);
+        }
+    } else if (param.indexOf("padding=") == 0) {
+        encodeInteger(0x08);
+        encodeShortInteger(param.mid(7).toUInt());
+    } else if (param.indexOf("start=") == 0) {
+        encodeInteger(0x0A);
+        encodeTextString(unquoteString(param.mid(6)));
+    } else if (param.indexOf("start-info=") == 0) {
+        encodeInteger(0x0B);
+        encodeTextString(unquoteString(param.mid(11)));
+    } else if (param.indexOf("comment=") == 0) {
+        encodeInteger(0x0C);
+        encodeTextString(unquoteString(param.mid(8)));
+    } else if (param.indexOf("domain=") == 0) {
+        encodeInteger(0x0D);
+        encodeTextString(unquoteString(param.mid(7)));
+    } else if (param.indexOf("max-age=") == 0) {
+        encodeInteger(0x0E);
+        QDateTime dt = QWspDateTime::parseDate(param.mid(8));
+        encodeLongInteger(QWspDateTime::toGmtTime_t(dt));
+    } else if (param.indexOf("path=") == 0) {
+        encodeInteger(0x0F);
+        encodeTextString(unquoteString(param.mid(5)));
+    } else if (param == "secure") {
+        encodeInteger(0x10);
+    } else {
+        int equal = param.indexOf('=');
+        if (equal > 0) {
+            encodeTokenText(param.left(equal));
+            QString value = unquoteString(param.mid(equal+1));
+            bool ok;
+            quint32 d = value.toUInt(&ok);
+            if (ok)
+                encodeInteger(d);
+            else
+                encodeTextString(value);
+        }
+    }
+}
+
+/*!
+    Encode a content type value \a str to the output data stream.
+*/
+void QWspPduEncoder::encodeContentType(const QString &str)
+{
+    // Content-type-value = Constrained-Media | Content-general-form
+    // Constrained-Media = Constrained-encoding
+    // Constrained-encoding = Extension-Media | Short-integer
+    // Extension-Media *Text End-of-string
+    // Content-general-form = Value-length Media-type
+    // Media-type = (Well-known-media | Extension-Media) *(Parameter)
+    // Well-known-media = Integer-value
+    QStringList params = str.split(QChar(';'));
+
+    int idx = 0;
+    while (contentTypeAssignments[idx]) {
+        if (params[0] == contentTypeAssignments[idx])
+            break;
+        idx++;
+    }
+
+    if (params.count() == 1) {
+        // Constrained-Media
+        if (contentTypeAssignments[idx]) {
+            encodeShortInteger(idx);
+        } else {
+            encodeTextString(params[0]);
+        }
+    } else {
+        // Content-general-form
+        // Make a local encoding buffer so that we can find the length
+        QBuffer buffer;
+        buffer.open(QIODevice::WriteOnly);
+        QWspPduEncoder bufEnc(&buffer);
+        if (contentTypeAssignments[idx]) {
+            // Well-known-media
+            bufEnc.encodeInteger(idx);
+        } else {
+            // Extension-Media
+            bufEnc.encodeTextString(params[0]);
+        }
+        // parameters
+        for (int i = 1; i < params.count(); i++) {
+            bufEnc.encodeParameter(params[i]);
+        }
+
+        // copy encBuf to dev.
+        buffer.close();
+        encodeLength(buffer.buffer().size());
+#ifdef WSP_DEBUG
+        qDebug("content type length = %d", buffer.buffer().size());
+#endif
+        dev->write(buffer.buffer());
+    }
+}
+
+/*!
+    Encode a multipart content block \a mp to the output data stream.
+*/
+void QWspPduEncoder::encodeMultipart(const QWspMultipart &mp)
+{
+    encodeUIntVar(mp.count());
+#ifdef WSP_DEBUG
+    qDebug("%d parts", mp.count());
+#endif
+    for (int i = 0; i < mp.count(); i++) {
+        encodePart(mp.part(i));
+    }
+}
+
+/*!
+    Encode a WSP \a part content block to the output data stream.
+*/
+void QWspPduEncoder::encodePart(const QWspPart &part)
+{
+    QBuffer buffer;
+    buffer.open(QIODevice::WriteOnly);
+    QWspPduEncoder bufEnc(&buffer);
+
+    const QWspField *f = part.header("Content-Type");
+    if (f) {
+        bufEnc.encodeContentType(f->value);
+#ifndef PHONESIM
+    } else {
+        f = part.header("Content-Location");
+        if (f) {
+            QMimeType mime(f->value);
+            bufEnc.encodeContentType(mime.id());
+        } else {
+            bufEnc.encodeContentType("*/*");    // last resort
+        }
+#endif
+    }
+
+    QList<QWspField>::ConstIterator it;
+    for (it = part.headers().begin(); it != part.headers().end(); ++it) {
+        if ((*it).name != "Content-Type")
+            bufEnc.encodeField(*it);
+    }
+
+    quint32 hdrLen = buffer.buffer().size();
+
+    encodeUIntVar(hdrLen);
+    encodeUIntVar(part.data().size());
+    buffer.close();
+
+    dev->write(buffer.buffer());
+
+    part.writeData(dev);
+}
+
+/*!
+    Encode a WSP PDU PDU \a part to the output data stream.
+*/
+void QWspPduEncoder::encodePush(const QWspPush &part)
+{
+    QBuffer buffer;
+    buffer.open(QIODevice::WriteOnly);
+    QWspPduEncoder bufEnc(&buffer);
+
+    const QWspField *f = part.header("Content-Type");
+    if (f) {
+        bufEnc.encodeContentType(f->value);
+#ifndef PHONESIM
+    } else {
+        f = part.header("Content-Location");
+        if (f) {
+            QMimeType mime(f->value);
+            bufEnc.encodeContentType(mime.id());
+        } else {
+            bufEnc.encodeContentType("*/*");    // last resort
+        }
+#endif
+    }
+
+    QList<QWspField>::ConstIterator it;
+    for (it = part.headers().begin(); it != part.headers().end(); ++it) {
+        if ((*it).name != "Content-Type")
+            bufEnc.encodeField(*it);
+    }
+
+    quint32 hdrLen = buffer.buffer().size();
+
+    encodeOctet((quint8)(part.identifier()));
+    encodeOctet((quint8)(part.pduType()));
+    encodeUIntVar(hdrLen);
+    buffer.close();
+
+    dev->write(buffer.buffer());
+
+    part.writeData(dev);
+}
+
+QString QWspPduEncoder::unquoteString(const QString &str)
+{
+    QString tmp(str);
+
+    if ( tmp[0] == '\"' )
+        tmp = tmp.right( tmp.length() - 1 );
+    if ( tmp[(int)tmp.length() - 1] == '\"' )
+        tmp = tmp.left( tmp.length() - 1 );
+
+    return tmp;
+}
+
+/*!
+    Get the number of bytes that will be needed to encode \a iv
+    as a long integer.
+*/
+int QWspPduEncoder::longIntegerLength(quint32 iv)
+{
+    int count = 0;
+    while (iv || !count) {
+        iv = iv >> 8;
+        count++;
+    }
+
+    return count+1;
+}
+
+/*!
+    Get the number of bytes that will be needed to encode \a d
+    as either a short or long integer.
+*/
+int QWspPduEncoder::integerLength(quint32 d)
+{
+    if (d < 128)
+        return 1;
+    else
+        return longIntegerLength(d);
+}
+
+/*!
+    \fn void QWspPduEncoder::setHeaderCodec(QWspHeaderCodec *c)
+
+    Set the header codec, that converts string names into byte values, to \a c.
+*/
+
+//===========================================================================
+
+/*!
+  \class QWspPart
+  \mainclass
+  \brief The QWspPart class represents a single part within a WSP message.
+  \ingroup telephony
+
+  The QWspPart class represents a single part within a WSP message.
+*/
+
+/*!
+    Construct an empty WSP part structure.
+*/
+QWspPart::QWspPart()
+{
+}
+
+/*!
+    Construct a WSP part structure that is a copy of \a part.
+*/
+QWspPart::QWspPart( const QWspPart& part )
+{
+    hdr = part.hdr;
+    ba = part.ba;
+}
+
+/*!
+    Destruct this WSP part.
+*/
+QWspPart::~QWspPart()
+{
+}
+
+/*!
+    Copy the contents of \a part into this object.
+*/
+QWspPart& QWspPart::operator=( const QWspPart& part )
+{
+    if ( this != &part ) {
+        hdr = part.hdr;
+        ba = part.ba;
+    }
+    return *this;
+}
+
+/*!
+    \fn const QList<QWspField>& QWspPart::headers() const
+
+    Return the list of headers associated with this WSP part.
+*/
+
+/*!
+    Find the header called \a name and return its field block.
+    Returns null if there is no such header.
+*/
+const QWspField *QWspPart::header(const QString &name) const
+{
+    QList<QWspField>::ConstIterator it;
+    for (it = hdr.begin(); it != hdr.end(); ++it) {
+        if ((*it).name == name)
+            return &(*it);
+    }
+
+    return 0;
+}
+
+/*!
+    Add header \a h to this WSP part.
+*/
+void QWspPart::addHeader(const QWspField &h)
+{
+    hdr.append(h);
+}
+
+/*!
+    Add a header with the specified \a name and \a value to this WSP part.
+*/
+void QWspPart::addHeader(const QString &name, const QString &value)
+{
+    QWspField field;
+    field.name = name;
+    field.value = value;
+    hdr.append(field);
+}
+
+/*!
+    \fn const QByteArray& QWspPart::data() const
+
+    Return the data body associated with this WSP part.
+*/
+
+/*!
+    Set the data body of this WSP part to the \a l bytes from
+    the array \a d.
+*/
+void QWspPart::setData(const char *d, int l)
+{
+    ba = QByteArray(d, l);
+}
+
+/*!
+    Read \a l bytes from \a d and make them the body of this WSP part.
+*/
+void QWspPart::readData(QIODevice *d, int l)
+{
+    // Sanity-check the length, just in case something invalid was supplied.
+    if ( l >= 0 && ( (d->isSequential() && l < 2097152) || (!d->isSequential() && l <= d->size() - d->pos()) ) ) {
+        ba.resize(l);
+        d->read(ba.data(), l);
+    } else {
+#ifdef WSP_DEBUG
+        qDebug("QWspPart::readData: bad attempt to read data of length %d", l);
+#endif
+    }
+}
+
+/*!
+    Write the body of this WSP part to \a d.
+*/
+void QWspPart::writeData(QIODevice *d) const
+{
+    d->write(ba.data(), ba.size());
+}
+
+/*!
+  \class QWspMultipart
+  \mainclass
+  \brief The QWspMultipart class represents a collection of parts from a WSP message.
+  \ingroup telephony
+
+  The QWspMultipart class represents a collection of parts from a WSP message.
+*/
+
+/*!
+    Construct an empty WSP multipart structure.
+*/
+QWspMultipart::QWspMultipart()
+{
+}
+
+/*!
+    Construct a WSP multipart structure that is a copy of \a mpart.
+*/
+QWspMultipart::QWspMultipart( const QWspMultipart& mpart )
+{
+    parts = mpart.parts;
+}
+
+/*!
+    Destruct this WSP multipart structure.
+*/
+QWspMultipart::~QWspMultipart()
+{
+}
+
+/*!
+    Copy the contents of \a mpart into this object.
+*/
+QWspMultipart& QWspMultipart::operator=( const QWspMultipart& mpart )
+{
+    if ( this != &mpart ) {
+        parts = mpart.parts;
+    }
+    return *this;
+}
+
+/*!
+    \fn int QWspMultipart::count() const
+
+    Return the number of parts in this object.
+*/
+
+/*!
+    Add part \a p to this object.
+*/
+void QWspMultipart::addPart(const QWspPart &p)
+{
+    parts.append(p);
+}
+
+/*!
+    \fn const QWspPart & QWspMultipart::part(int idx) const
+
+    Return the part at index \a idx within this object.
+*/
+
+/*!
+  \class QWspPush
+  \mainclass
+  \brief The QWspPush class represents the contents of a WSP Push PDU.
+  \ingroup telephony
+
+  The QWspPush class represents the contents of a WSP Push PDU.
+*/
+
+/*!
+    Construct an empty WSP Push PDU.
+*/
+QWspPush::QWspPush()
+{
+    ident = 0;
+    pdu = 0x06;     // Unconfirmed push PDU type.
+}
+
+/*!
+    Construct a WSP Push PDU that is a copy of \a push.
+*/
+QWspPush::QWspPush( const QWspPush& push )
+    : QWspPart( push )
+{
+    ident = push.ident;
+    pdu = push.pdu;
+}
+
+/*!
+    Destruct this WSP Push PDU.
+*/
+QWspPush::~QWspPush()
+{
+}
+
+/*!
+    Copy the contents of \a push into this object.
+*/
+QWspPush& QWspPush::operator=( const QWspPush& push )
+{
+    QWspPart::operator=( push );
+    if ( this != &push ) {
+        ident = push.ident;
+        pdu = push.pdu;
+    }
+    return *this;
+}
+
+/*!
+    \fn int QWspPush::identifier() const
+
+    Get the identifier associated with this PDU.
+*/
+
+/*!
+    \fn int QWspPush::pduType() const
+
+    Get the PDU type associated with this PDU.
+*/
+
+/*!
+    \fn void QWspPush::setIdentifier( int value )
+
+    Set the identifier associated with this PDU to \a value.
+*/
+
+/*!
+    \fn void QWspPush::setPduType( int value )
+
+    Set the PDU type associated with this PDU to \a value.
+*/
+
+/*!
+    Decode the content type from the push PDU in \a data.
+    This is quicker than using QWspPduDecoder::decodePush()
+    and is suitable for quickly determining how to dispatch a
+    push PDU.
+*/
+QString QWspPush::quickContentType( const QByteArray& data )
+{
+    uint posn = 0;
+    uint size = data.size();
+    int ch;
+    QString type;
+
+    // Skip the identifier.
+    ++posn;
+
+    // Check that the PDU type is 0x06 (indicating WSP-PUSH).
+    if ( posn >= size || data[posn] != 0x06 )
+        return QString();
+    ++posn;
+
+    // Skip the header length.
+    while ( posn < size ) {
+        ch = data[posn++];
+        if ( (ch & 0x80) == 0 )
+            break;
+    }
+    if ( posn >= size )
+        return QString();
+
+    // Decode the content type according to WAP-230.
+    ch = data[posn] & 0xFF;
+    if ( ch <= 31 ) {
+        ++posn;
+        if ( ch == 31 ) {
+            while ( posn < size ) {
+                ch = data[posn++];
+                if ( (ch & 0x80) == 0 )
+                    break;
+            }
+        }
+        if ( posn >= size )
+            return QString();
+        ch = data[posn] & 0xFF;
+        if ( (ch & 0x80) != 0 ) {
+            ch &= 0x7F;
+            if ( ch < numContentTypes )
+                type = contentTypeAssignments[ch];
+        } else {
+            while ( ch != 0 ) {
+                type += (QChar)ch;
+                ++posn;
+                if ( posn < size )
+                    ch = data[posn] & 0xFF;
+                else
+                    ch = 0;
+            }
+        }
+    } else if ( (ch & 0x80) != 0 ) {
+        ch &= 0x7F;
+        if ( ch < numContentTypes )
+            type = contentTypeAssignments[ch];
+    } else {
+        while ( ch != 0 ) {
+            type += (QChar)ch;
+            ++posn;
+            if ( posn < size )
+                ch = data[posn] & 0xFF;
+            else
+                ch = 0;
+        }
+    }
+    if ( type.isEmpty() )
+        return QString();
+
+    // Make sure that the content type does not contain
+    // invalid characters, to protect the filesystem.
+    for ( posn = 0; posn < (uint)(type.length()); ++posn ) {
+        ch = (int)(type[posn].unicode());
+        if ( ch >= 'A' && ch <= 'Z' )
+            continue;
+        if ( ch >= 'a' && ch <= 'z' )
+            continue;
+        if ( ch >= '0' && ch <= '9' )
+            continue;
+        if ( ch == '-' || ch == '.' || ch == '_' || ch == '+' )
+            continue;
+        if ( ch == '/' ) {
+            // If the '/' is followed by '.', it may be an attempt
+            // to do "xyz/..", which would be bad.
+            if ( (posn + 1) < (uint)(type.length()) && type[posn + 1] == '.' )
+                return QString();
+
+            // Cannot use '/' at the start of a MIME type.
+            if ( posn == 0 )
+                return QString();
+
+            // This '/' is OK to use.
+            continue;
+        }
+        return QString();
+    }
+    return type;
+}
+
+//===========================================================================
+
+
+
+QWspField QWspDefaultCodec::decode(QWspPduDecoder &dec)
+{
+    QWspField wapField;
+    quint8 field = dec.decodeShortInteger();
+    int idx = fieldFromNumber(field);
+    if (idx >= 0) {
+        const WAPHeaderField &fld = headerFieldNameAssignments[idx];
+        wapField.name = fld.name;
+        switch (fld.type) {
+            case ContentBase:
+            case ContentLocation:
+            case ETag:
+            case From:
+            case Host:
+            case IfMatch:
+            case IfNoneMatch:
+            case Location:
+            case Referer:
+            case Server:
+            case Upgrade:
+            case UserAgent:
+            case Via:
+            case XWapContentURI:
+            case XWapInitiatorURI:
+            case Profile:
+            case ContentID:
+                wapField.value = dec.decodeTextString();
+                break;
+            case Allow:
+            case PushFlag:
+                wapField.value = QString::number(dec.decodeShortInteger());
+                break;
+            case Date:
+            case Expires:
+            case IfModifiedSince:
+            case IfUnmodifiedSince:
+            case LastModified:
+            case XWapTod:
+                {
+                    quint32 d = dec.decodeLongInteger();
+                    QDateTime dt = QWspDateTime::fromGmtTime_t(d);
+                    wapField.value = QWspDateTime::dateString(dt);
+                }
+                break;
+            case Age:
+            case ContentLength:
+            case MaxForwards:
+            case BearerIndication:
+                wapField.value = QString::number(dec.decodeInteger());
+                break;
+            case ContentEncoding:
+                {
+                    if (dec.peekOctet() & 0x80) {
+                        switch (dec.decodeOctet()) {
+                            case 128:
+                                wapField.value = "Gzip";
+                                break;
+                            case 129:
+                                wapField.value = "Compress";
+                                break;
+                            case 130:
+                                wapField.value = "Deflate";
+                                break;
+                            default:
+                                qWarning("Unknown Content-encoding");
+                                break;
+                        }
+                    } else {
+                        wapField.value = dec.decodeTokenText();
+                    }
+                }
+                break;
+            case ContentLanguage:
+                {
+                    quint8 octet = dec.peekOctet();
+                    if (octet == 128) {
+                        dec.decodeOctet();
+                        wapField.value = "*";
+                    } else if (octet & 0x80) {
+                        wapField.value = QString::number(dec.decodeInteger()); //### should decode
+                    } else {
+                        wapField.value = dec.decodeTokenText();
+                    }
+                }
+                break;
+            case ContentType:
+                wapField.value = dec.decodeContentType();
+                break;
+            case XWapApplicationId:
+                {
+                    quint8 octet = dec.peekOctet();
+                    if (octet & 0x80 || octet <= 31) {
+                        wapField.value = QString::number(dec.decodeInteger());
+                    } else {
+                        wapField.value = dec.decodeTokenText();
+                    }
+                }
+                break;
+            case AcceptRanges:
+                {
+                    quint8 octet = dec.peekOctet();
+                    if (octet == 128) {
+                        wapField.value = "None";
+                    } else if (octet == 129) {
+                        wapField.value = "Bytes";
+                    } else {
+                        wapField.value = dec.decodeTokenText();
+                    }
+                }
+                break;
+            // ### None of these handled
+            case Accept:
+            case AcceptLanguage:
+            case Authorization:
+            case Connection:
+            case ContentMD5:
+            case IfRange:
+            case Pragma:
+            case ProxyAuthenticate:
+            case ProxyAuthorization:
+            case Public:
+            case Range:
+            case RetryAfter:
+            case TransferEncoding:
+            case Vary:
+            case Warning:
+            case WWWAuthenticate:
+            case ContentDisposition:
+            case AcceptApplication:
+            case ProfileDiff:
+            case ProfileWarning:
+            case Expect:
+            case TE:
+            case Trailer:
+            case AcceptCharset:
+            case AcceptEncoding:
+            case CacheControl:
+            case ContentRange:
+            case SetCookie:
+            case Cookie:
+            case EncodingVersion:
+            default:
+                {
+                    qWarning("Unhandled WSP header: %s", fld.name);
+                    quint8 octet = dec.peekOctet();
+                    if (octet <= 31) {
+                        quint32 len = dec.decodeLength();
+                        while (len-- && !dec.device()->atEnd())
+                            dec.decodeOctet();
+                    } else if (octet & 0x80) {
+                        dec.decodeOctet();
+                    } else {
+                        dec.decodeTokenText();
+                    }
+                    dec.setStatus(QWspPduDecoder::Unhandled);
+                }
+                break;
+        }
+    } else {
+        qWarning("Cannot decode header field: %d", field);
+    }
+
+    return wapField;
+}
+
+bool QWspDefaultCodec::encode(QWspPduEncoder &enc, const QWspField &field)
+{
+    int idx = numberFromField(field.name);
+    if (idx < 0)
+        return false;
+
+    const WAPHeaderField &fld = headerFieldNameAssignments[idx];
+    if (fld.version > 12)   // ### We will only encode upto version 1.2
+        return false;
+
+    switch (fld.type) {
+        case ContentBase:
+        case ContentLocation:
+        case ETag:
+        case From:
+        case Host:
+        case IfMatch:
+        case IfNoneMatch:
+        case Location:
+        case Referer:
+        case Server:
+        case Upgrade:
+        case UserAgent:
+        case Via:
+        case XWapContentURI:
+        case XWapInitiatorURI:
+        case Profile:
+        case ContentID:
+            enc.encodeShortInteger(fld.number);
+            enc.encodeTextString(field.value);
+            break;
+        case Allow:
+        case PushFlag:
+            enc.encodeShortInteger(fld.number);
+            enc.encodeShortInteger(field.value.toUInt());
+            break;
+        case Date:
+        case Expires:
+        case IfModifiedSince:
+        case IfUnmodifiedSince:
+        case LastModified:
+        case XWapTod:
+            {
+                enc.encodeShortInteger(fld.number);
+                QDateTime dt = QWspDateTime::parseDate(field.value);
+                enc.encodeLongInteger(QWspDateTime::toGmtTime_t(dt));
+            }
+            break;
+        case Age:
+        case ContentLength:
+        case MaxForwards:
+        case BearerIndication:
+            enc.encodeShortInteger(fld.number);
+            enc.encodeInteger(field.value.toUInt());
+            break;
+        case ContentEncoding:
+            enc.encodeShortInteger(fld.number);
+            if (field.value == "Gzip")
+                enc.encodeOctet(128);
+            else if (field.value == "Compress")
+                enc.encodeOctet(129);
+            else if (field.value == "Deflate")
+                enc.encodeOctet(130);
+            else
+                enc.encodeTokenText(field.value);
+            break;
+        case ContentLanguage:
+            //### Should encode
+            enc.encodeShortInteger(fld.number);
+            if (field.value == "*")
+                enc.encodeOctet(128);
+            else
+                enc.encodeTokenText(field.value);
+            break;
+        case ContentType:
+            enc.encodeShortInteger(fld.number);
+            enc.encodeContentType(field.value);
+            break;
+        // ### None of these handled
+        case Accept:
+        case AcceptLanguage:
+        case AcceptRanges:
+        case Authorization:
+        case Connection:
+        case ContentMD5:
+        case IfRange:
+        case Pragma:
+        case ProxyAuthenticate:
+        case ProxyAuthorization:
+        case Public:
+        case Range:
+        case RetryAfter:
+        case TransferEncoding:
+        case Vary:
+        case Warning:
+        case WWWAuthenticate:
+        case ContentDisposition:
+        case XWapApplicationId:
+        case AcceptApplication:
+        case ProfileDiff:
+        case ProfileWarning:
+        case Expect:
+        case TE:
+        case Trailer:
+        case AcceptCharset:
+        case AcceptEncoding:
+        case CacheControl:
+        case ContentRange:
+        case SetCookie:
+        case Cookie:
+        case EncodingVersion:
+        default:
+            qWarning("Unhandled WSP header: %s", fld.name);
+            return false;
+    }
+
+    return true;
+}
+
+int QWspDefaultCodec::fieldFromNumber(quint8 id)
+{
+    int i = 0;
+    while (!(headerFieldNameAssignments[i].number & 0x80)) {
+        if (headerFieldNameAssignments[i].number == id)
+            return i;
+        i++;
+    }
+
+    return -1;
+}
+
+int QWspDefaultCodec::numberFromField(const QString &str)
+{
+    int i = 0;
+    while (!(headerFieldNameAssignments[i].number & 0x80)) {
+        if (headerFieldNameAssignments[i].name == str)
+            return i;
+        i++;
+    }
+
+    return -1;
+}
+

Added: trunk/src/host/qemu-neo1973/phonesim/lib/wap/qwsppdu.h
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/lib/wap/qwsppdu.h	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/lib/wap/qwsppdu.h	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#ifndef QWSPPDU_H
+#define QWSPPDU_H
+
+#include <qstring.h>
+#include <qobject.h>
+#include <qdatetime.h>
+
+#include <qtopiaglobal.h>
+
+class QIODevice;
+
+class QTOPIAPHONE_EXPORT QWspField
+{
+public:
+    QWspField();
+    QWspField( const QWspField& field );
+    ~QWspField();
+
+    QWspField& operator=( const QWspField& field );
+
+    QString name;
+    QString value;
+};
+
+class QTOPIAPHONE_EXPORT QWspDateTime
+{
+public:
+    static QDateTime parseDate(QString in);
+    static QString dateString(QDateTime d);
+    static QDateTime fromGmtTime_t(quint32);
+    static quint32 toTime_t(const QDateTime &);
+    static quint32 toGmtTime_t(const QDateTime &);
+};
+
+class QWspPduDecoder;
+class QWspPduEncoder;
+
+class QTOPIAPHONE_EXPORT QWspHeaderCodec
+{
+public:
+    virtual ~QWspHeaderCodec();
+    virtual QWspField decode(QWspPduDecoder &) = 0;
+    virtual bool encode(QWspPduEncoder &, const QWspField &) = 0;
+    virtual quint8 codePage() const = 0;
+};
+
+class QTOPIAPHONE_EXPORT QWspPart
+{
+public:
+    QWspPart();
+    QWspPart( const QWspPart& part );
+    ~QWspPart();
+
+    QWspPart& operator=( const QWspPart& part );
+
+    const QList<QWspField> &headers() const { return hdr; }
+    const QWspField *header(const QString &name) const;
+    void addHeader(const QWspField &);
+    void addHeader(const QString &name, const QString &value);
+
+    const QByteArray &data() const { return ba; }
+    void setData(const char *d, int l);
+    void readData(QIODevice *d, int l);
+    void writeData(QIODevice *d) const;
+
+private:
+    QList<QWspField> hdr;
+    QByteArray ba;
+};
+
+class QTOPIAPHONE_EXPORT QWspMultipart
+{
+public:
+    QWspMultipart();
+    QWspMultipart( const QWspMultipart& mpart );
+    ~QWspMultipart();
+
+    QWspMultipart& operator=( const QWspMultipart& mpart );
+
+    int count() const { return parts.count(); }
+    void addPart(const QWspPart &);
+    const QWspPart &part(int idx) const { return parts[idx]; }
+
+private:
+    QList<QWspPart> parts;
+};
+
+class QTOPIAPHONE_EXPORT QWspPush : public QWspPart
+{
+public:
+    QWspPush();
+    QWspPush( const QWspPush& push );
+    ~QWspPush();
+
+    QWspPush& operator=( const QWspPush& push );
+
+    int identifier() const { return ident; }
+    int pduType() const { return pdu; }
+
+    void setIdentifier( int value ) { ident = value; }
+    void setPduType( int value ) { pdu = value; }
+
+    static QString quickContentType( const QByteArray& data );
+
+private:
+    int ident;
+    int pdu;
+};
+
+class QTOPIAPHONE_EXPORT QWspPduDecoder : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QWspPduDecoder(QIODevice *);
+    ~QWspPduDecoder();
+
+    quint8 peekOctet();
+    quint8 decodeOctet();
+    quint8 decodeUInt8();
+    quint16 decodeUInt16();
+    quint32 decodeUInt32();
+    quint32 decodeUIntVar();
+    quint8 decodeShortInteger();
+    quint32 decodeLongInteger();
+    quint32 decodeInteger();
+    quint32 decodeLength();
+    QString decodeTextString();
+    QString decodeEncodedString();
+    QString decodeTokenText();
+    QString decodeVersion();
+    QString decodeContentType();
+    QWspField decodeField();
+    QString decodeParameter();
+    QWspMultipart decodeMultipart();
+    void decodeContentTypeAndHeaders(QWspPart& part, quint32 hdrLen);
+    QWspPart decodePart();
+    QWspPush decodePush();
+
+    void setHeaderCodec(QWspHeaderCodec *c) {
+        if (c)
+            headerCodec = c;
+        else
+            headerCodec = defaultCodec;
+    }
+
+    enum Status { OK, Unhandled, Eof, Fatal };
+    Status status() const { return stat; }
+    void setStatus(Status s) { stat = s; }
+
+    QIODevice *device() { return dev; }
+
+signals:
+    void selectCodePage(quint8);
+
+private:
+    QString decodeCharset( const QString &encoded, quint32 mib);
+    QString decodeTextBlock(int length);
+    int decodeMIBEnum(quint32& num);
+private:
+    QIODevice *dev;
+    QWspHeaderCodec *headerCodec;
+    QWspHeaderCodec *defaultCodec;
+    Status stat;
+};
+
+class QTOPIAPHONE_EXPORT QWspPduEncoder : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QWspPduEncoder(QIODevice *);
+    ~QWspPduEncoder();
+
+    void encodeOctet(quint8);
+    void encodeUInt8(quint8);
+    void encodeUInt16(quint16);
+    void encodeUInt32(quint32);
+    void encodeUIntVar(quint32);
+    void encodeShortInteger(quint8);
+    void encodeLongInteger(quint32);
+    void encodeInteger(quint32);
+    void encodeLength(quint32);
+    void encodeTextString(const QString &str);
+    void encodeEncodedString(const QString &str);
+    void encodeVersion(const QString &);
+    void encodeTokenText(const QString &str);
+    void encodeContentType(const QString &str);
+    void encodeField(const QWspField &);
+    void encodeParameter(const QString &);
+    void encodeMultipart(const QWspMultipart &);
+    void encodePart(const QWspPart &);
+    void encodePush(const QWspPush &);
+
+    int longIntegerLength(quint32 d);
+    int integerLength(quint32 d);
+
+    void setHeaderCodec(QWspHeaderCodec *c) {
+        if (c)
+            headerCodec = c;
+        else
+            headerCodec = defaultCodec;
+    }
+
+//    void setCodePage(quint8);
+
+private:
+    QString unquoteString(const QString &str);
+
+private:
+    QIODevice *dev;
+    QWspHeaderCodec *headerCodec;
+    QWspHeaderCodec *defaultCodec;
+};
+
+#endif // QWSPPDU_H

Added: trunk/src/host/qemu-neo1973/phonesim/main.cpp
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/main.cpp	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/main.cpp	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2000-2007 TROLLTECH ASA. All rights reserved.
+**
+** This file is part of the Opensource Edition of the Qtopia Toolkit.
+**
+** This software is licensed under the terms of the GNU General Public
+** License (GPL) version 2.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info at trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <lib/server.h>
+#ifndef PHONESIM_TARGET
+    #include "control.h"
+    #include <qapplication.h>
+#else
+    #include <qcoreapplication.h>
+#endif
+#include <qstring.h>
+#include <qdebug.h>
+#include <stdlib.h>
+
+static void usage( const QString& progname )
+{
+    qWarning() << "Usage: "<< progname << " [-p port] [-gui] filename";
+    exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+#ifndef PHONESIM_TARGET
+    QApplication app(argc, argv);
+#else
+    QCoreApplication app(argc, argv);
+#endif
+    QString filename;
+    int port = 12345;
+    int index;
+    bool with_gui = false;
+
+    // Parse the command-line.
+    index = 1;
+    for (index = 1; index < argc; index++) {
+        if (strcmp(argv[index],"-p") == 0) {
+            index++;
+            if (index >= argc) {
+                usage( app.applicationName() );
+            } else {
+                port = atoi(argv[index]);
+            }
+        } else if (strcmp(argv[index],"-gui") == 0) {
+            // turn on gui option
+            with_gui = true;
+        } else if ( strcmp(argv[index],"-h") == 0
+                || strcmp(argv[index],"-help") == 0 ) {
+            usage( argv[0] );
+        } else {
+            // must be filename.  SHOULD be last argument.
+            if (index != argc-1) {
+                usage( app.applicationName() );
+            }
+            filename = argv[index];
+        }
+
+    }
+
+    PhoneSimServer *pss = new PhoneSimServer(filename, port, 0);
+
+#ifndef PHONESIM_TARGET
+    if (with_gui)
+        pss->setHardwareManipulator(new ControlFactory);
+#else
+    Q_UNUSED(pss);
+#endif
+
+    return app.exec();
+}
+

Added: trunk/src/host/qemu-neo1973/phonesim/peers.xml
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/peers.xml	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/peers.xml	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<simulator>
+
+<!-- Numbers of the form 5550nnn can be used to dial another
+     phone simulator in "peer connect" mode. -->
+
+<peerinfo number="5550001" host="ice.trolltech.com.au"/>
+<peerinfo number="5550002" host="bippy.trolltech.com.au"/>
+<peerinfo number="5550003" host="billabong.trolltech.com.au"/>
+<peerinfo number="5550004" host="drumstick.trolltech.com.au"/>
+<peerinfo number="5550005" host="pebble.trolltech.com.au"/>
+<peerinfo number="5550006" host="katherine.trolltech.com.au"/>
+<peerinfo number="5550007" host="hail.trolltech.com.au"/>
+<peerinfo number="5550008" host="igloo.trolltech.com.au"/>
+<peerinfo number="5550009" host="snowflake.trolltech.com.au"/>
+<peerinfo number="5550010" host="esky.trolltech.com.au"/>
+<peerinfo number="5550011" host="rain.trolltech.com.au"/>
+<peerinfo number="5550012" host="osprey.trolltech.com.au"/>
+<peerinfo number="5550013" host="tundra.trolltech.com.au"/>
+<peerinfo number="5550014" host="glacier.trolltech.com.au"/>
+<peerinfo number="5550015" host="qnx4.trolltech.com.au"/>
+<peerinfo number="5550016" host="stumpy.trolltech.com.au"/>
+<peerinfo number="5550017" host="heather.trolltech.com.au"/>
+<peerinfo number="5550018" host="guildenstern.trolltech.com.au"/>
+<peerinfo number="5550019" host="mclite.trolltech.com.au"/>
+<peerinfo number="5550020" host="bakingsoda.trolltech.com.au"/>
+<peerinfo number="5550021" host="yeti.trolltech.com.au"/>
+<peerinfo number="5550022" host="sled.trolltech.com.au"/>
+<peerinfo number="5550023" host="tibet.trolltech.com.au"/>
+<peerinfo number="5550024" host="gusto.trolltech.com.au"/>
+<peerinfo number="5550026" host="penguin.trolltech.com.au"/>
+<peerinfo number="5550027" host="frost.trolltech.com.au"/>
+<peerinfo number="5550028" host="icecave.trolltech.com.au"/>
+<peerinfo number="5550029" host="igloo2000.trolltech.com.au"/>
+<peerinfo number="5550030" host="snowfall.trolltech.com.au"/>
+<peerinfo number="5550031" host="hercules.trolltech.com.au"/>
+<peerinfo number="5550032" host="avalanche.trolltech.com.au"/>
+<peerinfo number="5550033" host="sleet.trolltech.com.au"/>
+<peerinfo number="5550034" host="rosencrantz.trolltech.com.au"/>
+<peerinfo number="5550035" host="blizzard.trolltech.com.au"/>
+<peerinfo number="5550036" host="skidoo.trolltech.com.au"/>
+<peerinfo number="5550037" host="royaob.trolltech.com.au"/>
+<peerinfo number="5550038" host="slushy.trolltech.com.au"/>
+<peerinfo number="5550039" host="seal.trolltech.com.au"/>
+<peerinfo number="5550040" host="aurochs.trolltech.com.au"/>
+<peerinfo number="5550041" host="fracture.trolltech.com.au"/>
+<peerinfo number="5550042" host="sasquatch.trolltech.com.au"/>
+<peerinfo number="5550043" host="iceghost.trolltech.com.au"/>
+<peerinfo number="5550044" host="kryl.trolltech.com.au"/>
+<peerinfo number="5550045" host="everest.trolltech.com.au"/>
+<peerinfo number="5550046" host="snow.trolltech.com.au"/>
+<peerinfo number="5550047" host="zen.trolltech.com.au"/>
+<peerinfo number="5550048" host="polarbear.trolltech.com.au"/>
+<peerinfo number="5550099" host="nonexist.trolltech.com.au"/>
+<peerinfo number="5550100" host="willow.trolltech.com.au"/>
+
+</simulator>

Added: trunk/src/host/qemu-neo1973/phonesim/phonesim.pro
===================================================================
--- trunk/src/host/qemu-neo1973/phonesim/phonesim.pro	2007-10-26 14:08:07 UTC (rev 3287)
+++ trunk/src/host/qemu-neo1973/phonesim/phonesim.pro	2007-10-26 17:27:58 UTC (rev 3288)
@@ -0,0 +1,6 @@
+FORMS*=controlbase.ui
+HEADERS*=control.h attranslator.h gsmspec.h gsmitem.h 
+SOURCES*=main.cpp control.cpp attranslator.cpp gsmspec.cpp gsmitem.cpp
+TEMPLATE=app
+QT*=core gui network xml
+LIBS+=-Llib -lphonesim





More information about the commitlog mailing list