Documentation  |   Table of Contents   |  < Previous   |  Next >   |  Index

10    Telephony Manager

Palm OS® Programmer's Companion

Volume II Communications

You can use the Palm OS® Telephony Manager to communicate between a handheld and a phone or to access telephony services in an application intended for a smartphone. This chapter contains the following sections that describe how to use the Palm OS Telephony API:

For detailed information about the Telephony Manager data types, constants, and functions, see the following chapters in the Palm OS Programmer's API Reference:

The "Telephony Basic Services" chapter describes the basic services and provides a map to the other functions.

Telephony Service Types ^TOP^

The telephony API organizes functions within sets called service sets. Each service set contains a related set of functions that may or may not be available on a particular mobile device or network. You can use the TelIs<ServiceSet>Available macro to determine if a service set is supported in the current environment, and you can use the TelIs<FunctionName>Supported macro to determine if a specific function is supported in the current environment.


NOTE: Sometimes a service set is supported, but not all of the functions in that service set are supported. See Testing the Telephony Environment for more information.

Each function in the telephony API is prefixed with Tel; each telephony service set adds an addition 3 characters to the prefix. Table 10.1 describes the telephony service sets.

Table 10.1  Telephony API service sets 

Service set

Functionality

Service prefix

Basic

Basic functions that are always available

Tel

Configuration

Services that allow you to configure phones, including SMS configuration

TelCfg

Data calls

Data call handling

TelDtc

Emergency calls

Emergency call handling

TelEmc

Information

Functions to retrieve information about the current phone

TelInf

Network

Functions the provide network-oriented services, including authorized networks, current network, signal level, and search mode information

TelNwk

OEM

Functions that allow hardware manufacturers to extend the Telephony Manager. Each manufacturer can provide a specific set of OEM functions for a particular device

TelOem

Phone book

Functions to access the phone's SIM and address book, including the ability to create, view, and delete phone book entries

TelPhb

Power

Power supply level functions

TelPow

Security

Functions that provide PIN code management and related services for phone and SIM security-related features

TelSty

Short Message Service

Services to handle Short Message Service (SMS) and to enable the reading, sending, and deleting of short messages

TelSms

Sound

Phone sound management, including the playing of key tones and muting.

TelSnd

Speech calls

Functions to handle the sending and receiving of speech calls. This service also includes functions that handle DTMF

TelSpc

Using the Telephony API ^TOP^

This section provides examples excerpted from the Phone Book Application (PhBkApp) sample program, which provides the following capabilities:

  • creates, modifies, and deletes entries on a phone, using the SIM and built-in storage on the phone device
  • imports entries from the Address Book application
  • exports entries to the Address Book application

The PhBkApp program opens and accesses the Telephony Manager library and makes a number of calls into the library. It provides an excellent example of using telephony services in your applications.

Accessing the Telephony Manager Library ^TOP^

Before you can use the Telephony Manager library, you must load the library and obtain a reference number for it. Each of the functions in the library requires a reference number argument, which is used with the system code to access a shared library.

Each of the functions in the library also requires an application attachment identifier, which you can obtain by calling the TelOpen function.

The example function LoadTelMgrLibrary, which is shown in Listing 10.1, makes sure that the Telephony Manager library is loaded, obtains an application attachment identifier, and returns a reference number for it.

Listing 10.1  Loading the Telephony Manager library


Err LoadTelMgrLibrary(UInt16 *telRefNumP, UInt16 *telAppIdP) 
{ 
   Err err; 
    
   err = SysLibFind(kTelMgrLibName, telRefNumP); 
   if (err != errNone) 
   { 
      err = SysLibLoad(kTelMgrDatabaseType, 
                    kTelMgrDatabaseCreator, telRefNumP); 
      if (err) 
         return err; 
   } 
    
   err = TelOpen(*telRefNumP, kTelMgrVersion, telAppIdP); 
   return err; 
} 

The LoadTelMgrLibrary function first calls the SysLibFind function to determine if the library has already been loaded, which might be the case if your code has been called by another application that has already loaded the library.

If the library has not already been loaded, LoadTelMgrLibrary calls the SysLibLoad function to load the library and obtain a reference number for it.

After obtaining a reference number for the library, LoadTelMgrLibrary calls the TelOpen function to open the loaded library. TelOpen opens the Telephony library using the currently selected Connection Manager profile. If you need to use a specific profile, call TelOpenProfile instead.

Note that if you are writing an application for a handheld to communicate with a phone, you do not need to establish a network connection between the two. After the Telephony library is successfully opened, each call to the Telephony Manager opens a connection to the phone, performs the necessary operation, and then closes the connection. If you are going to make several calls in succession, use TelOpenPhoneConnection to open the connection to the phone and leave it open. Then use TelClosePhoneConnection when you are done.

Closing the Telephony Manager Library ^TOP^

When you are done with the library, you should close it by calling the TelClose function, which releases any resources associated with your use of the Telephony Manager.

As shown in Listing 10.2, you must test the return value of the TelClose function; if the result is not telErrLibStillInUse, you must unload the shared library by calling the SysLibRemove function.

Listing 10.2  Closing the Telephony Manager library


Err UnloadTelMgrLibrary(UInt16 telRefNum, UInt16 telAppId) 
{ 
   if ((TelClose(telRefNum, telAppId)!= telErrLibStillInUse)) 
      SysLibRemove(telRefNum); 
  
   return errNone; 
} 

Testing the Telephony Environment ^TOP^

Before running your application, you need to verify that the environment in which it is running (the Palm Powered handheld and the telephone device) supports the facilities that your application needs. The Telephony Manager allows you to determine if a specific service set is available, and also allows you to determine if a specific function call is supported.

The code excerpt in Listing 10.3 shows how the PhBkApp program verifies that the environment supports the capabilities that it needs, which include all of the phone book-related features of the Telephony Manager. The PhBkApp program first tests for the availability of the phone book services, and then determines if several specific functions are supported. Note that the PhBkApp refuses to run if any of the capabilities it is using are not available.

Listing 10.3  Testing for the presence of specific capabilities


   err = TelIsPhbServiceAvailable(gDataP->refNum, gDataP->appId, NULL); 
      // Test if phone book capabilities are present 
   if (err != errNone) 
      return err; 
  
      // Check that this phone supports adding entry services 
   err = TelIsPhbAddEntrySupported(gDataP->refNum, gDataP->appId, NULL); 
   if (err != errNone) 
      return err; 
  
      // Check that this phone supports selecting a phone book 
   err = TelIsPhbSelectPhonebookSupported(gDataP->refNum, gDataP->appId, NULL); 
   if (err != errNone) 
      return err; 
  
      // Check that this phone supports getting entries 
   err = TelIsPhbGetEntriesSupported(gDataP->refNum, gDataP->appId, NULL); 
   if (err != errNone) 
      return err; 
  
      // Check that this phone supports getting entry count 
   err = TelIsPhbGetEntryCountSupported(gDataP->refNum, gDataP->appId, NULL); 
   if (err != errNone) 
      return err; 
  
   // Check that this phone supports deleting an entry 
   err = TelIsPhbDeleteEntrySupported(gDataP->refNum, gDataP->appId, NULL); 
   return err; 

For a complete list of the service availability macros, see TelIs<ServiceSet>Available in Chapter 73, "Telephony Basic Services," in Palm OS Programmer's API Reference.

For more information about determining if a specific function is supported, see TelIs<FunctionName>Supported in Chapter 73, "Telephony Basic Services," in Palm OS Programmer's API Reference.

Using Synchronous and Asynchronous Calls ^TOP^

Almost all of the telephony API functions can be called either synchronously or asynchronously. If you call a function asynchronously, your application receives an event to notify it that the function has completed; the event that you receive contains status and other information returned by the function.

This section provides a simple example of calling the TelPhbAddEntry function both synchronously and asynchronously to illustrate the difference.

When you call a function synchronously, you need to test the result value returned by the function to determine if the call was successful. For example, the code in Listing 10.4 calls the TelPhAddEntry function synchronously.

Listing 10.4  Calling a function synchronously


   err = TelPhbAddEntry(gTelRefNum, gTelAppID, &gEntry,  
      NULL); 
   printf("Result of adding entry is %d", err); 

To call the same function asynchronously, you must do the following (see Listing 10.5):

  • Pass a pointer to an unsigned integer as the last argument to the call instead of passing NULL.

    An asynchronous function call returns immediately. Upon return, the last argument contains an ID to identify this particular operation (the transaction ID).

  • In your application's main event loop, use TelGetEvent instead of EvtGetEvent to get the next event.

    TelGetEvent checks both the Telephony Manager's asynchronous reply queue and the system event queue. If a telephony event is available, it returns that. If not, it returns the first event in the system event queue.

    If you're operating outside of the event loop and are only interested in telephony events, you can call TelGetTelephonyEvent instead. TelGetTelephonyEvent returns only telephony events.

  • Check for the kTelephonyEvent event type.

    When the function call completes, TelGetEvent returns a TelEventType structure with the event type set to kTelephonyEvent. If the event type is not equal to this event, the normal event loop should process it.

  • Check the functionId and optionally the transId field of the TelEventType structure.

    The functionId field is a constant that tells you which Telephony Manager call has completed. The transId field tells you which instance of the call completed in case you have made two or more asynchronous calls to the same function.

Listing 10.5  Calling a function asynchronously


   err = TelPhbAddEntry(gTelRefNum, gTelAppID, &gEntry,  
      &transId); 
...  
  
 
static void ProcessTelephonyEvent(TelEventType *eventP) 
{ 
   switch(eventP->functionId) { 
   ... 
      case kTelPhbAddEntryMessage: 
         printf("Result of adding entry is %d",  
                 eventP->returnCode); 
         break; 
   ... 
} 
 
static void AppEventLoop(void) 
{ 
   UInt16 error; 
   EventType event; 
 
   do { 
      TelGetEvent(gTelRefNum, gTelAppId,  
         (TelEventType *)&event, evtWaitForever); 
 
      if (event->eType == kTelephonyEvent) { 
         ProcessTelephonyEvent((TelEventType *)&event); 
      } else { 
      if (! SysHandleEvent(&event)) 
         if (! MenuHandleEvent(0, &event, &error)) 
            if (! AppHandleEvent(&event)) 
               FrmDispatchEvent(&event); 
 
   } while (event.eType != appStopEvent); 
} 

Registering for Notifications ^TOP^

If you need to receive events from the Telephony Manager when your application is not the current application, you should register for the kTelTelephonyNotification. For example, if you are writing an application that should handle incoming phone calls or receive SMS messages, it is likely that your application will not be the active application when the call or SMS is received. For these types of events, the Telephony Manager posts a kTelTelephonyNotification.

If you've registered for the notification, your application receives a sysAppLaunchCmdNotify launch code for every telephony event. The notifyDetailsP field of this notification's parameter block points to a TelNotificationType structure. The notificationId field of this structure identifies which specific telephony event has occurred.

Listing 10.6 shows how to register for and receive incoming SMS message notifications.

Listing 10.6  Receiving an SMS message


UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, 
   UInt16 launchFlags) 
{ 
   Err error; 
   switch (cmd) { 
      //Register for the notification when we are first 
      //installed and upon each system reset.  
      case sysAppLaunchCmdSyncNotify: 
      case sysAppLaunchCmdReset: 
         error = SysCurrentAppDatabase(&gCardNo, &gAppID); 
         if (error) return error; 
         SysNotifyRegister(gCarNo, gAppID,  
            kTelephonyNotification, NULL, 
            sysNotifyNormalPriority, NULL); 
      break; 
 
      //Once registered, we receive incoming SMS message 
      //notifications as a sysAppLaunchCmdNotify launch code  
      case sysAppLaunchCmdNotify: 
         if((SysNotifyParamType *)cmdPBP->notifyType ==  
            kTelephonyNotification) && ((SysNotifyParamType*) 
            cmdPBP->notifyDetailsP->notificationId == 
            kTelSmsLaunchCmdIncomingMessage)) 
               ProcessIncomingSms(cmdPBP->notifyDetailsP); 
   } 
} 

Using Data Structures With Variably-sized Fields ^TOP^

Many of the telephony functions use data structures that have variably-sized buffer fields. For example, the TelPhbGetEntry() function uses the TelPhbEntryType structure, which contains two such fields.


typedef struct _TelPhbEntryType 
{ 
   UInt16   phoneIndex; 
   Char*    fullName; 
   UInt8    fullNameSize;  
   Char*    dialNumber; 
   UInt8    dialNumberSize; 
} TelPhbEntryType; 

The fullName and dialNumber buffers are variable-sized strings that you allocate in the heap. When you initialize one of these structures to pass to the TelPhbGetEntry() function, you must preallocate the buffers and store the allocated size in the corresponding size fields.

Listing 10.7 initializes a TelPhbEntryType data structure and passes it to the TelPhbGetEntry function to retrieve an entry from the phone book.

Listing 10.7  Initializing a TelPhbEntrypType structure


#define maxNameSize         45 
#define maxNumSize          20 
TelPhbEntryType myEntry; 
UInt16 theIndex = 1; 
  
myEntry.phoneIndex =             theIndex; 
myEntry.fullName =               MemPtrNew(maxNameSize); 
myEntry.fullNameSize =           maxNameSize; 
myEntry.dialNumber =             MemPtrNew(maxNumSize); 
myEntry.dialNumberSize =         maxNumSize; 
  
err = TelPhbGetEntry(gPrefs->telRefNum, gPrefsP->telAppId, 
                          &myEntry, NULL); 

Note that you can call the TelPhbGetEntryMaxSizes() function to retrieve the maximum name size (in addition to other information) instead of hardcoding it, as done in the above example.

Upon return from the function, the buffer fields are filled in, and the size fields contain the actual number of bytes that were stored into the buffer fields.

If the allocated size of a buffer is not large enough to contain the entire value, the command function does the following:

  • Returns the telErrBufferSize error.
  • Fills the buffer with as much data as it can, and truncates the data that does not fit. If the data ends with a null terminator and is truncated, the null terminator is retained.
  • Sets the value of the size field to the actual size required to contain all of the data.

Note that for string buffers, the size includes the byte required for the null terminator character.


NOTE: When you call a function asynchronously, the telErrBufferSize error is returned in the returnCode field of the event you receive upon completion of the function's execution.

Also, when you call a function asynchronously, it is your responsibility to ensure that any data structure used by the function remains in memory until you receive the completion event.

Summary of Telephony Manager ^TOP^

Telephony Manager Functions

Basic Functions

TelCancel

TelIsPhoneConnected

TelClose

TelIsPowServiceAvailable

TelClosePhoneConnection

TelIsSmsServiceAvailable

TelGetCallState

TelIsSndServiceAvailable

TelGetEvent

TelIsSpcServiceAvailable

TelGetTelephonyEvent

TelIsStyServiceAvailable

TelInfGetInformation

TelMatchPhoneDriver

TelIsCfgServiceAvailable

TelOemCall

TelIsDtcServiceAvailable

TelOpen

TelIsEmcServiceAvailable

TelOpenProfile

TelIsInfServiceAvailable

TelOpenPhoneConnection

TelIsNwkServiceAvailable

TelSendCommandString

TelIsOemServiceAvailable

TelIs<FunctionName>Supported

TelIsPhbServiceAvailable

TelIs<ServiceSet>Available

Data Calls

TelDtcCallNumber

TelDtcReceiveData

TelDtcCloseLine

TelDtcSendData

Emergency Calls

TelEmcCall

TelEmcGetNumberCount

TelEmcCloseLine

TelEmcSelectNumber

TelEmcGetNumber

TelEmcSetNumber

Network Interface

TelNwkGetLocation

TelNwkGetSelectedNetwork

TelNwkGetNetworkName

TelNwkGetSignalLevel

TelNwkGetNetworks

TelNwkSelectNetwork

TelNwkGetNetworkType

TelNwkSetSearchMode

TelNwkGetSearchMode

Phone Book

TelPhbAddEntry

TelPhbGetEntryCount

TelPhbDeleteEntry

TelPhbGetEntryMaxSizes

TelPhbGetAvailablePhonebooks

TelPhbGetSelectedPhonebook

TelPhbGetEntries

TelPhbSelectPhonebook

TelPhbGetEntry

Power Management

TelPowGetBatteryStatus

TelPowSetPhonePower

TelPowGetPowerLevel

Security

TelStyChangeAuthenticationType

TelStyGetAuthenticationState

TelStyEnterAuthenticationCode

Short Message Services

TelCfgGetSmsCenter

TelSmsReadMessages

TelCfgSetSmsCenter

TelSmsReadReport

TelSmsDeleteMessage

TelSmsReadReports

TelSmsGetAvailableStorage

TelSmsReadSubmittedMessage

TelSmsGetDataMaxSize

TelSmsReadSubmittedMessages

TelSmsGetMessageCount

TelSmsSelectStorage

TelSmsGetSelectedStorage

TelSmsSendManualAcknowledge

TelSmsGetUniquePartId

TelSmsSendMessage

TelSmsReadMessage

Sound

TelSndMute

TelSndStopKeyTone

TelSndPlayKeyTone

Speech Calls

TelSpcAcceptCall

TelSpcRejectCall

TelSpcCallNumber

TelSpcRetrieveHeldLine

TelSpcCloseLine

TelSpcSelectLine

TelSpcConference

TelSpcSendBurstDTMF

TelSpcGetCallerNumber

TelSpcStartContinuousDTMF

TelSpcHoldLine

TelSpcStopContinuousDTMF

TelSpcPlayDTMF