The implementation of the 3GPP AT command specifications (3GPP TS 27.007 and 3GPP TS 27.005) varies between modems, with most modems supporting proprietary AT commands for special features.
Qt Extended supports vendor-specific modem commands through the use of plug-ins to the Qt Extended Phone Modem Library. The vendor-specific code is placed in the device-specific directory devices/DEVNAME/src/plugins/phonevendors/DEVNAME, where DEVNAME is the manufacturer's name for the device.
Qt Extended will load every vendor plug-in that is installed and query each one to see which is capable of handling the modem. The QTOPIA_PHONE_VENDOR macro in custom.h can be used to force Qt Extended to load only that plug-in, ignoring any others that may be present in the system. For example, setting QTOPIA_PHONE_VENDOR to wavecom will instruct Qt Extended to load libwavecomvendor.so to provide vendor-specific AT commands. The QTOPIA_PHONE_VENDOR value can also be set as an environment variable.
3GPP TS 07.10 multiplexing can also be a source of problems when supporting a new modem. During initial testing it can be disabled by setting the QTOPIA_PHONE_MUX environment variable to no. Qt Extended will still function, but you will be unable to make GPRS calls without multiplexing support.
If your modem does not support 3GPP TS 07.10 multiplexing, or you need to modify the 3GPP TS 07.10 parameters, it will be necessary to write a multiplexer plug-in. See Writing a Multiplexer Plug-in for more information on how to do this.
Outline of a Modem Vendor Plugin
There are two sample implementations under src/plugins/phonevendors/ericsson and src/plugins/phonevendors/wavecom. This section reviews the major components of the wavecom plugin to demonstrate how to write such a plug-in.
The plug-in inherits from the QModemServicePlugin class, which provides modem detection and service creation functions.
#include <qmodemserviceplugin.h>
class WavecomPluginImpl : public QModemServicePlugin
{
Q_OBJECT
public:
WavecomPluginImpl();
virtual ~WavecomPluginImpl();
bool supports( const QString& manufacturer );
QModemService *create( const QString& service,
QSerialIODeviceMultiplexer *mux,
QObject *parent );
};
The plug-in declares two functions, supports() and create(), which should be implemented as follows:
QTOPIA_EXPORT_PLUGIN( WavecomPluginImpl )
WavecomPluginImpl::WavecomPluginImpl() {}
WavecomPluginImpl::~WavecomPluginImpl() {}
bool WavecomPluginImpl::supports( const QString& manufacturer )
{
return manufacturer.contains( "WAVECOM" );
}
QModemService *WavecomPluginImpl::create
( const QString& service, QSerialIODeviceMultiplexer *mux, QObject *parent )
{
return new WavecomModemService( service, mux, parent );
}
The supports() function checks the manufacturer string from the AT+CGMI command against the expected value. The first plug-in that returns true from supports() will used.
The create() function creates a QModemService instance to handle the modem specifics. It is passed the name of the service (usually modem), the multiplexing object that is used to communicate with the modem, and the parent QObject to attach the modem service to.
The modem service implementation inherits from QModemService and should override initialize() to create the vendor-specific functionality handlers:
#include <qmodemservice.h>
class WavecomModemService : public QModemService
{
Q_OBJECT
public:
WavecomModemService
( const QString& service, QSerialIODeviceMultiplexer *mux,
QObject *parent = 0 );
~WavecomModemService();
void initialize();
...
};
WavecomModemService::WavecomModemService
( const QString& service, QSerialIODeviceMultiplexer *mux,
QObject *parent )
: QModemService( service, mux, parent )
{
...
}
WavecomModemService::~WavecomModemService() {}
void WavecomModemService::initialize()
{
if ( !supports<QSimInfo>() )
addInterface( new WavecomSimInfo( this ) );
if ( !supports<QSimToolkit>() )
addInterface( new WavecomSimToolkit( this ) );
if ( !supports<QPhoneBook>() )
addInterface( new WavecomPhoneBook( this ) );
if ( !supports<QPhoneRfFunctionality>() )
addInterface( new WavecomRfFunctionality( this ) );
if ( !supports<QTelephonyConfiguration>() )
addInterface( new WavecomConfiguration( this ) );
if ( !callProvider() )
setCallProvider( new WavecomCallProvider( this ) );
QModemService::initialize();
}
Modem services within Qt Extended are split up into several handlers, one for each functionality area (phone calls, network registration, SMS, SIM toolkit, phone books, etc).
The QModemService class creates default implementations based on the 3GPP TS 27.007 and 3GPP TS 27.005 specifications. The modem vendor plug-in overrides those handlers that are different from the standard, and only those that are different. When QModemService::initialize() is called, the missing handlers will be created automatically.
The handlers mentioned above inherit from the following standard classes:
A complete list of classes for accessing AT-based modems can be found on the Modem Classes page.
Modem Porting Sequence
To support a modem the following sequence may be used as a guide:
- Check the AT Commands that Qt Extended requires and determine which ones your modem supports.
- Determine the appropriate alternative AT commands suited to your modem and write the vendor-specific plug-in to issue these commands.
- Run Qt Extended with the QTOPIA_PHONE_MUX environment variable set to no and with the AtChat and Modem logging categories enabled.
- Check the error/message log for commands that are reported as being in error.
- Using the error log, modify the plug-in and/or the phone library so that the modem-supported AT command parameters are used.
- Repeat from the second step until phone calls are possible and SIM details are being read.
- Write a multiplexer plug-in if your modem does not support 3GPP TS 07.10, or the 07.10 parameters need to be adjusted.
- Enable multiplexing by setting the QTOPIA_PHONE_MUX environment variable to yes.
- Re-test Qt Extended, especially the GPRS features, until the multiplexer is functioning correctly. Verbose multiplexer debugging can be enabled with the Mux logging category.
Modem Emulator
Most modern phones have an external serial interface, which is used to connect to a computer for the purposes of data calls, FAX transmissions, or synchronization with desktop applications. The Modem Emulator assists with supporting such interfaces.
To enable the modem emulator to use an external serial interface, the Phone.conf file should be placed under the etc/default/Trolltech directory on the vendor system, with contents such as the following:
[SerialDevices]
ExternalAccessDevice=/dev/ttyS1:115200
where /dev/ttyS1 should be replaced with the name of the serial device to listen to, and 115200 should be replaced with the desired baud rate.
If this option is configured, the modem emulator will be launched automatically once the phone server has been initialized. If this option is not configured, then the modem emulator will only be launched when other components in the system request it (for example, Bluetooth hands-free kits).