| /**************************************************************************** |
| ** |
| ** This file is part of the Qt Extended Opensource Package. |
| ** |
| ** Copyright (C) 2009 Trolltech ASA. |
| ** |
| ** Contact: Qt Extended Information ([email protected]) |
| ** |
| ** This file may be used under the terms of the GNU General Public License |
| ** version 2.0 as published by the Free Software Foundation and appearing |
| ** in the file LICENSE.GPL included in the packaging of this file. |
| ** |
| ** Please review the following information to ensure GNU General Public |
| ** Licensing requirements will be met: |
| ** http://www.fsf.org/licensing/licenses/info/GPLv2.html. |
| ** |
| ** |
| ****************************************************************************/ |
| |
| #include <qsimcontrolevent.h> |
| #include <qsimcommand.h> |
| |
| /*! |
| \class QSimControlEvent |
| \inpublicgroup QtTelephonyModule |
| |
| \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-equipped 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; |
| } |
| |
| 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 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; |
| 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; |
| 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; |
| } |