Example #1
0
void tst_QSimToolkit::testDeliverEventDownload()
{
    QFETCH( QByteArray, data );
    QFETCH( QByteArray, payload );
    QFETCH( int, event );
    QFETCH( int, sourceDevice );

    // Output a dummy line to give some indication of which test we are currently running.
    qDebug() << "";

    // Clear the client/server state.
    server->clear();
    deliveredCommand = QSimCommand();

    // Compose and send the envelope.
    QSimEnvelope env;
    env.setType( QSimEnvelope::EventDownload );
    env.setSourceDevice( (QSimCommand::Device)sourceDevice );
    env.setEvent( (QSimEnvelope::Event)event );
    env.setExtensionData( payload );
    client->sendEnvelope( env );

    // Wait for the envelope to be received.
    QVERIFY( QFutureSignal::wait( server, SIGNAL(envelopeSeen()), 100 ) );

    // Check that the envelope is what we expected to get and that we didn't
    // get any terminal responses yet.
    QCOMPARE( server->responseCount(), 0 );
    QCOMPARE( server->envelopeCount(), 1 );
    QByteArray lastenv = server->lastEnvelope();
    lastenv[2] = data[2];      // Handle 0x19 vs 0x99 discrepancy.
    QCOMPARE( lastenv, data );
}
Example #2
0
void SimApp::keyPressEvent(QKeyEvent *ke)
{
    if (ke->key() == Qt::Key_Context1) {
        if (view) {
            if (view->command().hasHelp()) {
                // help requested
                if (view->command().type() == QSimCommand::SetupMenu) {
                    QSimEnvelope env;
                    env.setType(QSimEnvelope::MenuSelection);
                    env.setSourceDevice(QSimCommand::Keypad);
                    env.setMenuItem(view->helpIdentifier());
                    env.setRequestHelp(true);
                    sendEnvelope( env );
                } else {
                    QSimTerminalResponse resp;
                    resp.setCommand(view->command());
                    resp.setResult(QSimTerminalResponse::HelpInformationRequested);
                    resp.setMenuItem(view->helpIdentifier());
                    sendResponse( resp );
                }
            }
        }
    }
    QMainWindow::keyPressEvent(ke);
}
Example #3
0
/*!
    Sends an \c{ENVELOPE} \a env to the SIM toolkit application.  This is typically
    used for selecting items from the main menu.

    The implementation in QModemSimToolkit sends the envelope to the SIM using the
    \c{AT+CSIM} command.  This will need to be overridden by the modem vendor plugin
    if the modem uses some other mechanism for sending envelopes to the SIM.

    \sa sendResponse(), command()
*/
void QModemSimToolkit::sendEnvelope( const QSimEnvelope& env )
{
    QByteArray cmd;
    QByteArray pdu = env.toPdu();
    cmd += (char)0xA0;
    cmd += (char)0xC2;
    cmd += (char)0x00;
    cmd += (char)0x00;
    cmd += (char)pdu.size();
    cmd += pdu;
    service()->chat( "AT+CSIM=" + QString::number( cmd.size() * 2 ) + "," + 
                     QAtUtils::toHex( cmd ) );
}
Example #4
0
void tst_QSimToolkit::testEncodeEventDownload()
{
    QFETCH( QByteArray, data );
    QFETCH( QByteArray, payload );
    QFETCH( int, event );
    QFETCH( int, sourceDevice );

    // Output a dummy line to give some indication of which test we are currently running.
    qDebug() << "";

    // Check that the envelope PDU can be parsed correctly.
    QSimEnvelope decodedEnv = QSimEnvelope::fromPdu(data);
    QVERIFY( decodedEnv.type() == QSimEnvelope::EventDownload );
    QVERIFY( decodedEnv.sourceDevice() == (QSimCommand::Device)sourceDevice );
    QCOMPARE( (int)decodedEnv.event(), event );
    QCOMPARE( decodedEnv.extensionData(), payload );

    // Check that the original envelope PDU can be reconstructed correctly.
    QByteArray pdu = decodedEnv.toPdu();
    pdu[2] = data[2];      // Handle 0x19 vs 0x99 discrepancy.
    QCOMPARE( pdu, data );
}
Example #5
0
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;
}
/*!
    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 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;
    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;
        readBer( content, posn, tag, length );
    }
    return env;
}
Example #7
0
void NeoSimToolkit::sendEnvelope( const QSimEnvelope& env )
{
    service()->primaryAtChat()->chat
        ( "AT%SATE=\"" + QAtUtils::toHex( env.toPdu() ) + "\"" );
}