This document explains how applications written to use SMS over GSM on previous versions of Symbian OS can be changed to support SMS over CDMA. It contains the following sections:
Overview describes the architectural changes made to support SMS over CDMA.
Comparing GSM SMS and CDMA SMS describes some key differences between the SMS standards on GSM and CDMA.
CDMA SMS MTM classes provides a brief overview of the API, and identifies the new classes.
CSmsMessage fields analyses
how to move from the low-level GSM SMS stack CSmsMessage
class to
the messaging MTM API.
GSM SMS stack sockets describes how to move from using the sockets client with the GSM SMS stack to the messaging MTM API
Send As describes compatibility between GSM and CDMA for SendAs API users
MTM API change summary summarises the changes between the CDMA SMS MTM and the GSM SMS MTM.
In previous versions of Symbian OS, the GSM SMS standard (ETSI, ETS 300 536 (GSM 03.40)) was supported through three components:
The ETel multimode API, for low-level access to the phone drivers
The SMS (narrow band protocols) stack subsystem, which offered an encapsulation of a GSM SMS message, together with the ability to send and receive messages
The messaging SMS MTM, which integrated SMS into the messaging architecture, so that SMS could be used in a messaging client in a similar way to email, fax, etc.
CDMA also supports an SMS standard, defined by the 3GPP2, in standard C.S0015-A, derived from the TIA/EIA standard, TIA/EIA-637-B. The GSM and CDMA standards define broadly similiar functionality, but are different in architecture and in data structures. To add support for CDMA SMS to Symbian OS has required the following changes:
A new, additional SMS stack for CDMA. This provides an encapsulation of a CDMA SMS message, and message sending and receiving.
A new messaging SMS MTM that supports CDMA SMS.
In order not to break existing GSM SMS messaging applications, the new
CDMA MTM maintains API compatibility with the previous GSM SMS MTM, despite
this API having elements that are specific to GSM. In particular, the GSM SMS
MTM CSmsHeader
class exposes the GSM SMS stack class
CSmsMessage
to clients. The new MTM maintains
compatibility with the old API by translating features that are common to both
GSM and CDMA into CDMA. GSM-specific features are ignored.
The MTM also offers a new interface, created by extending some existing classes and adding some new classes, that provides:
a single interface to the functionality that GSM and CDMA SMS have in common.
extensions to the common interface that allows access to GSM and CDMA specific functionality.
The new interface does not expose either of the underlying GSM or CDMA SMS stacks, and is intended to be the primary API for SMS CDMA applications, rather than the lower-level SMS CDMA stack. Using the MTM API offers a simpler future approach to maintaining common application code between GSM and CDMA phones. This means that applications that previously used the GSM SMS stack API will need considerable changes to use the now preferred MTM API. Applications that previously used the GSM SMS MTM will need smaller changes to update to use the MTM's new classes.
For further information on the SMS standards and related Symbian OS components, see:
SMS Stack
SMS standard on ETSI website (requires registration).
The following table provides a quick comparison of the GSM SMS and CDMA SMS standards.
|
The following diagram shows the key classes in the CDMA SMS MTM:
Classes that existed in the GSM SMS MTM are in yellow; classes that are new are in blue; significant classes from components other than the MTM are in grey. The following table summarises the classes:
|
CSmsMessage
is the GSM SMS stack class that allows
access to message properties such as addressing information, the message text
itself, and to individual PDUs. Applications may previously have used
CSmsMessage
either directly with the GSM SMS stack API, or
in conjunction with the GMS SMS MTM API. Both categories of application should
now prefer to use only APIs offered by the CDMA MTM API.
The following table maps the CSmsMessage
functions to
equivalents in the MTM API. Sometimes there is no equivalent, either because
the function is too low-level to have an appropriate equivalent in messaging,
such as phone slot information, or because the function is concerned with
GSM-specific features that have not been addressed in the current release of
the MTM.
|
TSmsUserDataSettings
|
The GSM SMS stack API has two libraries:
gsmu.lib
, which provides the message encapsulation
class CSmsMessage
and PDU classes.
The CSmsMessage
class is discussed in the
CSmsMessage
fields table above.
smsu.lib
, which provides utility classes that allow
clients to use the sockets client API to send and receive SMS messages and give
commands related to the SIM.
This section explains how to change from using the sockets client API to the MTM API to send and receive messages.
Before you can do any operations with the MTM, your program must perform a couple of set up steps:
Connect to the message server: the messaging framework is based
around a server program, to which a connection (a session) must be made before
anything else with messaging can be done. The session class is called
CMsvSession
, and message client applications typically
create an instance of this class upon start-up.
// Create message server session
iMsvSession = CMsvSession::OpenSyncL(*this);
The OpenSyncL()
method takes a parameter of type
MMsvSessionObserver
, so, for this code to work, the
containing class must implement this observer interface. It enables the server
to call the client to inform it of significant events, such as new MTMs being
registered.
Get the SMS Client MTM: an application cannot directly create a
CSmsClientMtm
object. Instead, it must ask the message
server to create the object for it. A record of all the MTM components
installed on a machine is held in a dedicated registry file managed by the
message server. Registry classes use this registration data to allow MTM
components to be identified and instantiated.
To get a SMS client MTM object, use
CClientMtmRegistry
as follows:
// Create client registry object
iClientMtmRegistry = CClientMtmRegistry::NewL(*iMsvSession);
// Request MMS client MTM object
iSmsClientMtm = (CSmsClientMtm *)iClientMtmRegistry->NewMtmL(KUidMsgTypeSMS);
The registry NewMtmL()
function returns a pointer to
the client MTM base class, CBaseMtm
, so I cast it to the
SMS client class, CSmsClientMtm
.
If you use the GSM SMS stack API, your program will probably follow a procedure such as this to send an SMS:
Set up a message to send in a CSmsMessage
object:
create a CSmsBuffer
buffer, and store in
it the message text
create a CSmsMessage
to encapsulate the
message
set the message properties, such as user data settings,
destination address, and service center address, using
CSmsMessage
functions
Prepare a socket to send the message:
open a socket of the KSMSAddrFamily
protocol type
create a TSmsAddr
with address family
ESmsAddrSendOnly
, and bind this to the socket
open a write stream RSmsSocketWriteStream
on the socket, write the CSmsMessage
to this stream, and
commit the stream
Send the message by issuing an socket ioctl command
KIoctlSendSmsMessage
The comparable procedure for a program using the messaging API is:
Create a CMsvEntry
message entry, and
initialising it appropriately. For details, see
Message creation in
How to use the CDMA SMS MTM.
You can also create new messages by forwarding or replying to an
existing SMS message, through CSmsClientMtm::ForwardL()
and CSmsClientMtm::ReplyL()
respectively. In these cases,
the new message is created for you, with the appropriate content copied into it
from the original message.
Set the message content and properties using
CSmsClientMtm
, and where necessary,
CSmsHeader
, and for CDMA-specific fields,
TMsvMessageCdma
. The following sets the message text, adds
an address, and sets the (CDMA-specific) priority field.
// set body text
CRichText& body = iSmsClientMtm->Body();
_LIT(KMsgText,"message text");
body.InsertL(0,KMsgText);
// set recipients
_LIT(KNum,"6238263876");
iSmsClientMtm->AddAddresseeL(KNum);
// set any protocol-specific fields
TMsvMessageCdma& cdma = iSmsClientMtm->SmsHeader().CdmaMessage();
cdma.SetPriorityIndicatorL(tia637::KBdUrgent);
// save message before sending
iSmsClientMtm->SaveMessageL();
Send the message: once a message has been set up, it can be sent by
copying the message to the SMS service. This can be done using
CMsvEntry::CopyL()
. The following copies the message, whose ID is
obtained using iSmsClientMtm->Entry().EntryId()
, to the
service, whose ID can be got from the MTM using ServiceId()
.
iSendOperation = ent->CopyL(iSmsClientMtm->Entry().EntryId(), iSmsClientMtm->ServiceId(), iStatus);
The function returns a CMsvOperation
object,
which can be used to monitor the sending progress
(TSmsProgress
) and to obtain any error information.
As well as sending messages, both the GSM SMS stack API and the MTM API can be used to get incoming messages. As a reminder, the GSM SMS stack procedure to get incoming messages is:
Prepare a socket to get incoming messages:
open a socket of the KSMSAddrFamily
protocol type
create a TSmsAddr
, and set its address family to a
method of recognizing which incoming messages should be handled. A typical
method is match a text pattern against the incoming message. Bind the address
to the socket.
start listening for messages by issuing a socket ioctl command
KIoctlSelect
When a message that matches the handling criterion is received:
create an empty buffer (CSmsBuffer
) and
message (CSmsMessage
) object
read the message into the message object using
RSmsSocketReadStream
.
acknowledge that the message has been received successfully by
issuing a socket ioctl command KIoctlReadMessageSucceeded
(or
KIoctlReadMessageFailed
on failure)
Messaging receives SMS messages through a number of watcher components that listen to the CDMA stack for incoming messages that belong to particular teleservices (WMT, WEMT, VMN, WPT). When an incoming message belonging to one of these teleservices is received, its contents are read, and a new entry for the message is created in the message server's store (in the global inbox folder). The usual case is that these messages will then be read by the user through the email application, but other messaging clients can receive notifications when a new message is created in the store, and process the message if appropriate.
To do this, a class must must implement the session observer interface
MMsvSessionObserver
. The interface has just one function:
void HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3)=0;
When a new message is created in the store, the framework calls this
function with aEvent
set to EMsvEntriesCreated
, and
aArg1
is set to a CMsvEntrySelection*
that specifies
the IDs of the entries that have been created. The following checks the event
type, and gets the entry ID selection:
void CClientApp::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* , TAny* )
{
CMsvEntrySelection* entries = NULL;
switch (aEvent)
{
case EMsvEntriesCreated:
entries = static_castCMsvEntrySelection*>(aArg1);
break;
default:
break;
}
The observer will receive notifications for all types of entry, not
just SMS, so it's necessary to read the message properties to check that the
entry is appropriate to process. The following code first checks the index
entry to see if the entry is an SMS message, and then reads the message's
CSmsHeader
to see if it is of the Deliver (i.e. incoming) type.
Further checks, e.g. for particular message content, could be made. If you
determine that your application should process the message, you can prevent the
user from seeing the message in the Inbox of the standard messaging
application. To do this, set the message entry's visible flag to false, using
TMsvEntry::SetVisible(EFalse)
.
if (entries != NULL)
{
TInt count = entries->Count();
// check each entry to see if we want to process it
while (count--)
{
// get the index entry
const TMsvId id = (*entries)[count];
iEntry->SetEntryL(id);
const TMsvEntry& entry = iEntry->Entry();
// if the entry is an SMS message
if (entry.iMtm == KUidMsgTypeSMS && entry.iType == KUidMsvMessageEntry)
{
// and if it's an incoming message
iSmsClientMtm->SwitchCurrentEntryL(id);
CSmsHeader& header = iSmsClientMtm->SmsHeader();
if (header.MessageType() == KSmsTypeDeliver)
{
// make the entry invisible
TMsvEntry changeEnt(entry);
changeEnt.SetVisible(EFalse);
iEntry->ChangeL(changeEnt);
// do something with the message
HandleReceivedMessageL(id);
}
}
}
}
The GSM SMS MTM offered a range of extension commands called through
CSmsClientMtm::InvokeAsyncFunctionL()
to copy/move
messages between a phone store and the message store. The CDMA SMS MTM uses the
same commands to manage message storage on the phone store or R-UIM. A new
class TMsvSmsSimOperationParams
is defined to specify
parameters for the commands.
SMS messages can be created using the messaging Send As API in the same way for the CDMA SMS MTM as for the GSM SMS MTM. No changes to calling code are required.
For CDMA-only phones, the message is created as a generic SMS Text, and sent as a Wireless Messaging Teleservice (WMT) message. Other settings are taken from the defaults specified by the current service and message settings (see SMS services).
This section summarises the API differences between the GSM SMS MTM and the CDMA SMS MTM.
The following headers are new in the CDMA SMS MTM:
|
The following types have had items or values added relative to the GSM SMS MTM:
CSmsHeader
|
CSmsSettings
|
CSmsNumber
|