Previous Page Table of Contents Index Next Page

Palm OS Programmer's Companion


Palm Logo 9 Serial Communication

The Palm OS® serial communications software provides high-performance serial communications capabilities, including byte-level serial I/O, best-effort packet-based I/O with CRC-16, reliable data transport with retries and acknowledgments, connection management, and modem dialing capabilities.

This chapter helps you understand the different parts of the serial communications system and explains how to use them, discussing these topics:

Serial Hardware

The Palm Computing® platform device serial port is used for implementing desktop PC connectivity or other external communication. The serial communication is fully interrupt-driven for receiving data. Currently, interrupt-driven transmission of data is not implemented in software, but the hardware does support it. Five external signals are used for this communication:

The Palm Computing platform device has an external connector that provides:

Palm Computing publishes information designed to assist hardware developers in creating devices to interface with the serial communications port on Palm Computing platform products. You can obtain this information by joining the Solution Provider Program and enrolling in the Serial Port & Modem Casing Program. For more information about this program and the serial port hardware, see the Palm developer web page at:
http://www.palmos.com/dev/tech/hardware.

Byte Ordering

By convention, all data coming from and going to the Palm OS device use Motorola byte ordering. That is, data of compound types such as UInt16 (2 bytes) and UInt32 (4 bytes), as well as their integral counterparts, are packaged with the most-significant byte at the lowest address. This contrasts with Intel byte ordering.

Serial Communications Architecture Hierarchy

The serial communications software has multiple layers. Higher layers depend on more primitive functionality provided by lower layers. Applications can use functionality of all layers. The software consists of the following layers, described in more detail below:

Figure 9.1 illustrates the communications layers.

Figure 9.1 Palm OS Serial Communications Architecture

The Serial Manager

The Palm OS serial manager is responsible for byte-level serial I/O and control of the RS232 signals.

In order to prolong battery life, the serial manager must be very efficient in its use of processing power. To reach this goal, the serial manager receiver is interrupt-driven. In the present implementation, the serial manager uses the polling mode to send data.

Using the Serial Manager

Before using the serial manager, call SysLibFind, passing "Serial Library" for the library name to get the serial library reference number. This reference number is used with all subsequent serial manager calls. The system software automatically installs the serial library during system initialization.

To open the serial port, call SerOpen, passing the serial library reference number (returned by SysLibFind), 0 (zero) for the port number, and the desired baud rate. An error code of 0 (zero) or -serErrAlreadyOpen indicates that the port was successfully opened.

If the serial port is already open when SerOpen is called, the port's open count is incremented and an error code of serErrAlreadyOpen is returned. This ability to open the serial port multiple times allows cooperating tasks to share the serial port.

All other applications must refrain from sharing the serial port and close it by calling SerClose when serErrAlreadyOpen is returned. Error codes other than 0 (zero) or serErrAlreadyOpen indicate failure. The application must open the serial port before making other serial manager calls.

To close the serial port, call SerClose. Every successful call to SerOpen must eventually be paired with a call to SerClose. Because an open serial port consumes more energy from the device's batteries, it is essential not to keep the port open any longer than necessary.

To change serial port settings, such as the baud rate, CTS timeout, number of data and stop bits, parity options, and handshaking options, call SerSetSettings. For baud rates above 19200, use of hardware handshaking is advised.

To retrieve the current serial port settings, call SerGetStatus.

To retrieve the current line error status, call SerGetStatus, which returns the cumulative status of all line errors being monitored. This includes parity, hardware and software overrun, framing, break detection, and handshake errors.

To reset the serial port error status, call SerClearErr, which resets the serial port's line error status. Other serial manager functions, such as SerReceive, immediately return with the error code serErrLineErr if any line errors are pending. Applications should therefore check the result of serial manager function calls and call SerClearErr if line error(s) occurred.

To send a stream of bytes, call SerSend. In the present implementation, SerSend blocks until all data are transferred to the UART or a timeout error (if CTS handshaking is enabled) occurs. If your software needs to detect when all data has been transmitted, consider calling SerSendWait.


NOTE:  

Both SerSend and SerReceive were enhanced in version 2.0 of the system. See the function descriptions for more information. The older versions are still available as SerSend10 and SerReceive10.

To wait until all data queued up for transmission has been transmitted, call SerSendWait. SerSendWait blocks until all pending data is transmitted or a CTS timeout error occurs (if CTS handshaking is enabled).

To flush all bytes from the transmission queue, call SerSendFlush. This routine discards any data not yet transferred to the UART for transmission.

To receive a stream of bytes from the serial port, call SerReceive, specifying a buffer, the number of bytes desired, and the interbyte time out. This call blocks until all the requested data have been received or an error occurs.

To read bytes already in the receive queue, call SerReceiveCheck (see below) to get the number of bytes presently in the receive queue and then call SerReceive, specifying the number of bytes desired. Because SerReceive returns immediately without any data if line errors are pending, it is important to acknowledge the detection of line errors by calling SerClearErr.

To wait for a specific number of bytes to be queued up in the receive queue, call SerReceiveWait, passing the desired number of bytes and an interbyte timeout. This call blocks until the desired number of bytes have accumulated in the receive queue or an error occurs. The desired number of bytes must be less than the current receive queue size. The default queue size is 512 bytes. Because this call returns immediately if line errors are pending, applications have to call SerClearErr to detect any line errors. See also SerReceiveCheck and SerSetReceiveBuffer.

To check how many bytes are presently in the receive queue, call SerReceiveCheck.

To discard all data presently in the receive queue and to flush bytes coming into the serial port, call SerReceiveFlush, specifying the interbyte timeout. This call blocks until a time out occurs waiting for the next byte to arrive.

To replace the default receive queue, call SerSetReceiveBuffer, specifying the pointer to the buffer to be used for the receive queue and its size. The default receive queue must be restored before the serial port is closed. To restore the default receive queue, call SerSetReceiveBuffer, passing 0 (zero) for the buffer size. The serial manager does not free the custom receive queue.

To avoid having the system go to sleep while it's waiting to receive data, an application should call EvtResetAutoOffTimer periodically. For example, the serial link manager automatically calls EvtResetAutoOffTimer each time a new packet is received. Note that this facility is not part of the serial manager but part of the event manager. For more information, see "Auto-Off Control" .

To perform a control function, applications can call SerControl. This function performs one of the control operations specified by SerCtlEnum, whose elements are described in Table 9.1.

Table 9.1 SerCtlEnum Elements 

Element Description
serCtlFirstReserved = 0 Reserve 0
serCtlStartBreak Turn RS232 break signal on. Applications have to make sure that the break is set long enough to generate a value BREAK! valueP = 0; valueLenP = 0
serCtlStopBreak Turn RS232 break signal off: valueP = 0; valueLenP = 0
serCtlBreakStatus Get RS232 break signal status (on or off): valueP = pointer to UInt16 for returning status (0 = off, !0 = on)

*valueLenP = sizeof(UInt16)

serCtlStartLocalLoopback Start local loopback test; valueP = 0, valueLenP = 0
serCtlStopLocalLoopback Stop local loopback test valueP = 0, valueLenP = 0
serCtlMaxBaud valueP = pointer to UInt32 for returned baud *valueLenP = sizeof(UInt32)
serCtlHandshakeThreshold Retrieve HW handshake threshold; this is the maximum baud rate that does not require hardware handshaking valueP = pointer to UInt32 for returned baud *valueLenP = sizeof(UInt32)
serCtlEmuSetBlockingHook Set a blocking hook routine.

WARNING!

For use with the Simulator on Mac OS only. NOT SUPPORTED ON THE PALM DEVICE.

valueP = pointer to SerCallbackEntryType *valueLenP=sizeof(SerCallbackEntryType) Returns the old settings in the first argument.

The New Serial Manager

The new serial manager is capable of managing multiple serial connections within a Palm device.

This section describes the new serial manager and the new capability to write serial drivers that it can use.

The new serial manager is the preferred serial manager API and the Palm OS will eventually phase out support for the original serial manager API.

NOTE:  

The new serial manager is not available on all Palm devices. It is available by flash ROM update on Palm III and upgraded PalmPilot devices and some later devices. Before making any new serial manager calls, you must ensure that it is present.

Checking for the New Serial Manager

Because not all Palm devices will (or even can) have the new serial manager installed, it's important that you check for its existence before making any new serial manager calls. You can check by calling FtrGet as follows:

err = FtrGet(sysFileCSerialMgr, sysFtrNewSerialPresent, &value);

If the new serial manager is installed, the value parameter will be non-zero and the returned error should also be zero (for no error).

If the new serial manager is installed, it replaces the original serial manager. However, it includes a compatibility layer so that applications that use the original serial manager functions will continue to operate as expected. The compatibility layer simply translates the original serial manager calls into equivalent new serial manager functions.

If you are writing new application code, best performance is achieved by using the new serial library functions directly, assuming the new serial manager is installed on the unit on which your code is executing.

What's New About the New Serial Manager

The main difference between the new serial manager and previous versions is that the new serial manager supports multiple physical serial hardware devices and virtual serial devices, the detailed operation of which is abstracted from the main serial management code. Physical serial drivers manage communication with the hardware as needed, and virtual drivers manage blocks of data to be sent to some sort of block-based serial code.

In addition to this big change, a few new functions have been added and there are widespread, minor changes to data structures and API details.

About the New Serial Manager

The new serial manager manages multiple serial devices with minimal duplication of hardware drivers and data structures. In older Palm systems, the serial library managed any and all connections to the serial hardware in the 68328 (Dragonball) processor, which was the only serial device in the system. Newer systems contain additional serial devices, such as an IR port.

The figure below shows the layering of communication software with the new serial manager and hardware drivers.

Figure 9.2 Serial Communications Architecture with New Serial Manager

The new serial manager maintains a database of installed hardware and currently open connections. Applications, libraries, or other serial communication tasks open different pieces of serial hardware by specifying a logical port number or a four-character code identifying the exact piece of serial hardware that a task wishes to open a connection with. The new serial manager then performs the proper actions on the hardware via small hardware drivers that are opened dynamically when the port is needed. One hardware driver is needed for each serial communication hardware device available to the Palm unit.

At system restart, the new serial manager searches for all serial drivers on the Palm device. Serial drivers are independent .prc files with a code resource and a version resource and are of type `sdrv' or `vdrv'. Once a driver is found, it is asked to locate its associated hardware and provide information on the capabilities of that hardware. This is done for each driver found and the new serial manager always maintains a list of hardware currently on the device.

Once a port is opened, the new serial manager allocates a structure for maintaining the current information and settings of the particular port. The task or application that opens the port is returned a port ID and must supply the port ID to refer to this port when other new serial manager functions are called.

Upon closing the port, the new serial manager deallocates the open port structure and unlocks the driver code resource to prevent memory fragmentation.

Note that applications can use the connection manager to obtain the proper port ID and other serial port parameters that the user has stored in connection profiles for different connection types. For more information, see the section "The Connection Manager" .

Using the New Serial Manager

The new serial manager is installed when the device is booted. Upon opening a new serial manager connection, the calling application receives a unique ID that must be used to refer to this specific connection for all subsequent calls to the new serial manager.

Opening a Connection

Opening a serial connection requires that the application enable the serial hardware by calling the SrmOpen function and specifying the port ID (logical number or port name) and the initial baud rate of the UART.

The SrmOpen call returns a unique port ID for the open port. This port ID is required to perform any other new serial manager functions. If the returned port ID is NULL or an error is returned by the SrmOpen function, the returned port ID should be considered invalid. Once the SrmOpen call is made successfully, it indicates that the new serial manager has successfully allocated internal structures to maintain the port and has successfully loaded the serial driver for this port.

A port may be opened with either a foreground connection (SrmOpen) or background connection (SrmOpenBackground). A foreground connection makes an active connection to the port and controls usage of the port until the connection is closed. A background connection opens the port but relinquishes control to any other task requesting a foreground connection. Background connections are provided to support tasks (such as a keyboard driver) that want to use a serial device to receive data only when no other task is using the port.

Note that background ports have limited functionality: they can only receive data and notify owning clients of what data has been received.

Specifying the portID Parameter

With the new serial manager, ports must be specified using one of the following two methods:

Generally, it is best to use logical port ID's rather than specifying the port hardware directly. When you specify a logical port ID, the device selects the appropriate hardware.

Closing a Connection

Once an application is finished with the serial port, it must close it using the SrmClose function. If SrmClose returns no error, it indicates that the new serial manager has successfully closed the driver and deallocated the data structures used for maintaining the port.

Sending and Receiving Data

Sending data is performed synchronously (for example, the process of writing bytes to the serial hardware's transmit FIFO). To send data, the application only needs to have an open connection with a port that has been configured properly and then specify a buffer to send. The larger the buffer to send, the longer the send function operates before returning to the calling application. The SrmSend function returns the actual number of bytes that were sent.

The SrmSendCheck function can be used to check and determine if the FIFO is empty. The SrmSendWait function can be used to wait for the UART to send the contents of its FIFO. The SrmSendFlush function can be used to flush remaining bytes in the FIFO that have not been sent.

Receiving data is a more involved process because it depends on the receiving application actually listening for data from the port. The SrmReceiveWait function allows the application to periodically check the serial port to see if data has been received. In this function, you specify a number of bytes to wait for and a timeout value (in ticks). When SrmReceiveWait returns, you can call SrmReceive to receive the data.

Applications should not loop indefinitely on the SrmReceiveCheck and SrmReceiveWait functions, waiting for serial data to arrive on the port, without allowing the Palm OS to obtain time to execute other tasks running in the same thread (by calling EvtGetEvent and SysHandleEvent). Virtual devices often run in the same thread as applications and this can prevent virtual devices and other serial related code from properly handling received data.

Receive Buffer Handling

Functions are provided to support directly changing or accessing the new serial manager's receive queue. This allows substitution of a larger receive buffer to replace the 512-byte default buffer and allows fast access to this buffer to reduce buffer copying. These functions include SrmSetReceiveBuffer, SrmReceiveWindowOpen, and SrmReceiveWindowClose.

Receive Data Notification

The SrmSetWakeupHandler and SrmPrimeWakeupHandler functions are used to install a notification function (WakeupHandlerProc) that gets called after some number of bytes are received by the new serial manager's interrupt function.

Because wakeup handlers are called during interrupt time, they cannot call any Palm OS system functions that may block the system in any way. Wakeup handlers should also be very short so as to reduce interrupt latency.

Obtaining Information about Serial Hardware

The SrmGetDeviceCount and SrmGetDeviceInfo functions can be used by applications to obtain information about all serial devices currently available to the OS. Applications can obtain the number of available serial hardware devices and then get information for those devices by iterating through the list using the SrmGetDeviceInfo call, until an error is returned.

The SrmGetStatus function can be used to get status information about the current hardware and return line errors. Typically, SrmGetStatus is called to retrieve the line errors for the port if some of the send and receive functions return a serErrLineErr error code. SrmClearErr clears line errors.

Handling Custom Operations

The new serial manager handles custom operations via the SrmControl function. To extend this functionality to the serial drivers, an additional set of control functions has been added (see the SdrvControl and VdrvControl functions). These are unique to the serial driver and should be called only by the new serial manager itself. This allows functions that access the hardware directly to go through the same switching mechanism in the driver for both public and private control function operation codes.

New Serial Manager Example

The example code in this section shows how to receive (Listing 9.1) large blocks of data using the new serial manager.

Listing 9.1 Receiving Data Using the New Serial Manager


#include <Pilot.h> // all the system toolbox headers
#include <SerialMgr.h>
#define k2KBytes 2048
/************************************************************
*
* FUNCTION: RcvSerialData
*
* DESCRIPTION: An example of how to receive a large chunk of data
* from the Serial Manager. This function is useful if the app
* knows it must receive all this data before moving on. The
* YourDrainEventQueue() function is a chance for the application
* to call EvtGetEvent and handle other application events.
* Receiving data whenever it's available during idle events
* might be done differently than this sample.
*
* PARAMETERS:
* thePort -> valid portID for an open serial port.
* rcvDataP -> pointer to a buffer to put the received data.
* bufSize <-> pointer to the size of rcvBuffer and returns
* the number of bytes read.
*
*************************************************************/
Err RcvSerialData(UInt16 thePort, UInt8 *rcvDataP, UInt32 *bufSizeP)
{
UInt32 bytesLeft, maxRcvBlkSize, bytesRcvd, waitTime, totalRcvBytes = 0;
UInt8 *newRcvBuffer;
UInt16 dataLen = sizeof(UInt32);
Err* error;

    // The default receive buffer is only 512 bytes; increase it if
    // necessary. The following lines are just an example of how to
    // do it, but its necessity depends on the ability of the code
    // to retrieve data in a timely manner.
    newRcvBuffer = MemPtrNew(k2KBytes); // Allocate new rcv buffer.
    if (newRcvBuffer)
    // Set new rcv buffer.
    error = SrmSetReceiveBuffer(thePort, newRcvBuffer, k2KBytes);
    if (error)
    goto Exit;
    else
    return memErrNotEnoughSpace;

    // Initialize the maximum bytes to receive at one time.
    maxRcvBlkSize = k2KBytes;
    // Remember how many bytes are left to receive.
    bytesLeft = *bufSizeP;
    // Only wait 1/5 of a second for bytes to arrive.
    waitTime = SysTicksPerSecond() / 5;
   
    // Now loop while getting blocks of data and filling the buffer.
    do {
    // Is the max size larger then the number of bytes left?
    if (bytesLeft < maxRcvBlkSize)
    // Yes, so change the rcv block amount.
    maxRcvBlkSize = bytesLeft;
    // Try to receive as much data as possible,
    // but wait only one second for it.
    bytesRcvd = SrmReceive(thePort, rcvDataP, maxRcvBlkSize, waitTime, &error);
    // Remember the total number of bytes received.
    totalRcvBytes += bytesRcvd;
    // Figure how many bytes are left to receive.
    bytesLeft -= bytesRcvd;
    rcvDataP += bytesRcvd; // Advance the rcvDataP.
    // If there was a timeout and no data came through...
    if ((error == serErrTimeOut) && (bytesRcvd == 0))
    goto Exit; // ...bail out and report the error.
    // If there's some other error, bail out.
    if ((error) && (error != serErrTimeOut))
    goto Exit;

    // Call a function to handle any pending events because
    // someone might press the cancel button.
    // YourDrainEventQueue();
    // Continue receiving data until all data has been received.
    } while (bytesLeft);
   
    // Clearing the receive buffer can also be done right before
    // the port is to be closed.
    // Set back the default buffer when we're done.
    SrmSetReceiveBuffer(thePort, 0L, 0);
    MemPtrFree(newRcvBuffer); // Free the space.

    Exit:
    *bufSizeP = totalRcvBytes;
    return error;
}


Writing a Serial or Virtual Device Driver

The new serial manager supports the ability to add other serial hardware device drivers to the system. It also supports adding virtual device drivers, which transmit and receive data in blocks, instead of a byte at a time. The following sections discuss writing serial and virtual device drivers, which are installed as code resources on the Palm device.

Serial Driver (sdrv) Code Resources

A serial driver (sdrv) is a code resource (ID = 0) that is independently compiled and installed on a Palm device. It provides a hardware abstraction layer (HAL) for the serial hardware (the UART). Serial driver .prc files are of file type `sdrv' and their creator type is chosen by the developer (and must be registered with Palm Computing) to denote the type of hardware (for example, the 68328 UART driver has creator `u328'). When the new serial manager is installed, it searches the database manager for code resources of the `sdrv' file type and then calls the driver's entry point function to determine if the hardware that the driver supports is present and, if so, to get information about the features and capabilities of the hardware.

NOTE:  

Creator types with all lowercase letters are reserved by Palm Computing. For more information about assigning and registering creator types, see "Assigning a Creator ID" .

Serial drivers are responsible for installing and removing their interrupt handlers. In addition, they must be aware of other hardware that may share the IRQ line and be sure to pass along the interrupt to other installed handlers, if required. See the SdrvOpen function for details.

Serial Driver Functions

There are eight functions that each serial driver must minimally support in order to work with the new serial manager. These functions are briefly described in this section. For details on the exact operations each function must perform, see the function descriptions in the Palm OS SDK Reference.

The functions a serial driver must implement include:

Virtual Driver (vdrv) Code Resources

A Virtual Driver is a code resource (ID=0) that is independently compiled and installed on a Palm device. Virtual driver .prc files are of file type `vdrv' and their creator type is chosen by the developer (and must be registered with Palm Computing). When the new serial manager is installed, it searches the database manager for code resources of the `vdrv' type and then calls the driver's entry point function to get information about the features and capabilities of this virtual device. Unlike serial device drivers, virtual device drivers send and receive data in blocks instead of transferring one byte at a time. Their purpose is to abstract a level of communication protocol away from serial devices without forcing applications to work through a different API than the serial manager that may already be used for normal RS-232 serial communication.

Virtual Driver Functions

There are six functions that each virtual driver must minimally support in order to work with the new serial manager. These functions are briefly described in this section. For details on the exact operations each function must perform, see the function descriptions in the Palm OS SDK Reference.

The functions a virtual driver must implement include:

Note that there is no virtual read function in the current implementation. Virtual devices must save received data by using the functions provided in the DrvrRcvQType when they are notified that data is available via some callback mechanism.

The Connection Manager

The connection manager allows other applications to access, add, and delete connection pro\xde les contained in the Connection preferences panel. The Connection panel replaces the original Modem panel on the Palm device. A connection profile includes information on the hardware port to be used for a particular connection and the port details (speed, flow control, modem initialization string, etc.).

Because there are many more connection choices available to users (serial cable, IR, modem, network, etc.), the connection manager was developed to manage connection profiles that save preferences for various connection types.

The connection manager provides functions that list the saved connection profiles (CncGetProfileList), return details for a specific profile (CncGetProfileInfo), add a profile (CncAddProfile), and delete a profile (CncDeleteProfile).

NOTE:  

The connection manager is not available on all Palm devices. It is available by flash ROM update on Palm III and upgraded PalmPilot devices and some later devices. Before making any connection manager calls, you must ensure that it is present.

Because not all Palm devices will (or even can) have the connection manager installed, it's important that you check for its existence before making any connection manager calls. You can check by checking for the existence of the new serial manager, as described in the section "Checking for the New Serial Manager" . These managers work together and so are always installed together.

The Serial Link Protocol

The Serial Link Protocol (SLP) provides an efficient packet send and receive mechanism that is used by the Palm desktop software and debugger. SLP provides robust error detection with CRC-16. SLP is a best-effort protocol; it does not guarantee packet delivery (packet delivery is left to the higher-level protocols). For enhanced error detection and implementation convenience of higher-level protocols, SLP specifies packet type, source, destination, and transaction ID information as an integral part of its data packet structure.

SLP Packet Structures

The following sections describe:

SLP Packet Format

Each SLP packet consists of a packet header, client data of variable size, and a packet footer, as shown in Figure 9.3.

Figure 9.3 Structure of a Serial Link Packet

Packet Type Assignment

Packet type values in the range of 0x00 through 0x7F are reserved for use by the system software. The following packet type assignments are currently implemented:

0x00 Remote Debugger, Remote Console, and System Remote Procedure Call packets.
0x02 PADP packets.
0x03 Loop-back test packets.

Socket ID Assignment

Socket IDs are divided into two categories: static and dynamic. The static socket IDs are "well-known" socket ID values that are reserved by the components of the system software. The dynamic socket IDs are assigned at runtime when requested by clients of SLP. Static socket ID values in the ranges 0x00 through 0x03 and 0xE0 through 0xFF are reserved for use by the system software. The following static socket IDs are currently implemented or reserved:

0x00 Remote Debugger socket.
0x01 Remote Console socket.
0x02 Remote UI socket.
0x03 Desktop Link Server socket.
0x04 -0xCF Reserved for dynamic assignment.
0xD0 - 0xDF Reserved for testing.

Transaction ID Assignment

Transaction ID values are not interpreted by the Serial Link Protocol and are for the sole benefit of the higher-level protocols. The following transaction ID values are currently reserved:

0x00 and 0xFF Reserved for use by the system software.
0x00 Reserved by the Palm OS implementation of SLP to request automatic transaction ID generation.
0xFF Reserved for the connection manager's WakeUp packets.

Transmitting an SLP Packet

This section provides an overview of the steps involved in transmitting an SLP packet. The next section describes the implementation.

Transmission of an SLP packet consists of these steps:
Fill in the packet header and compute its checksum. Compute the CRC-16 of the packet header and client data. Transmit the packet header, client data, and packet footer. Return an error code to the client.

Receiving an SLP Packet

Receiving an SLP packet consists of these steps:
Scan the serial input until the packet header signature is matched. Read in the rest of the packet header and validate its checksum. Read in the client data. Read in the packet footer and validate the packet CRC. Dispatch/return an error code and the packet (if successful) to the client.

The Serial Link Manager

The serial link manager is the Palm OS implementation of the Serial Link Protocol.

Serial link manager provides the mechanisms for managing multiple client sockets, sending packets, and receiving packets both synchronously and asynchronously. It also provides support for the Remote Debugger and Remote Procedure Calls (RPC).

Using the Serial Link Manager

Before an application can use the services of the serial link manager, the application must open the manager by calling SlkOpen. Success is indicated by error codes of 0 (zero) or slkErrAlreadyOpen. The return value slkErrAlreadyOpen indicates that the serial link manager has already been opened (most likely by another task). Other error codes indicate failure.

When you finish using the serial link manager, call SlkClose. SlkClose may be called only if SlkOpen returned 0 (zero) or slkErrAlreadyOpen. When the open count reaches zero, SlkClose frees resources allocated by SlkOpen.

To use the serial link manager socket services, open a Serial Link socket by calling SlkOpenSocket. Pass a reference number or port ID (for the new serial manager) of an opened and initialized communications library (see SlkClose), a pointer to a memory location for returning the socket ID, and a Boolean indicating whether the socket is static or dynamic. If a static socket is being opened, the memory location for the socket ID must contain the desired socket number. If opening a dynamic socket, the new socket ID is returned in the passed memory location. Sharing of sockets is not supported. Success is indicated by an error code of 0 (zero). For information about static and dynamic socket IDs, see "Socket ID Assignment" .

When you have finished using a Serial Link socket, close it by calling SlkCloseSocket. This releases system resources allocated for this socket by the serial link manager.

To obtain the communications library reference number for a particular socket, call SlkSocketRefNum. The socket must already be open. To obtain the port ID for a socket, if you are using the new serial manager, call SlkSocketPortID.

To set the interbyte packet receive timeout for a particular socket, call SlkSocketSetTimeout.

To flush the receive stream for a particular socket, call SlkFlushSocket, passing the socket number and the interbyte timeout.

To register a socket listener for a particular socket, call SlkSetSocketListener, passing the socket number of an open socket and a pointer to the SlkSocketListenType structure. Because the serial link manager does not make a copy of the SlkSocketListenType structure but instead saves the pointer passed to it, the structure may not be an automatic variable (that is, allocated on the stack). The SlkSocketListenType structure may be a global variable in an application or a locked chunk allocated from the dynamic heap. The SlkSocketListenType structure specifies pointers to the socket listener procedure and the data buffers for dispatching packets destined for this socket. Pointers to two buffers must be specified:

Both buffers can be application global variables or locked chunks allocated from the dynamic heap.

The socket listener procedure is called when a valid packet is received for the socket. Pointers to the packet header buffer and the packet body buffer are passed as parameters to the socket listener procedure. The serial link manager does not free the SlkSocketListenType structure or the buffers when the socket is closed; freeing them is the responsibility of the application. For this mechanism to function, some task needs to assume the responsibility to "drive" the serial link manager receiver by periodically calling SlkReceivePacket.

To send a packet, call SlkSendPacket, passing a pointer to the packet header (SlkPktHeaderType) and a pointer to an array of SlkWriteDataType structures. SlkSendPacket stuffs the signature, client data size, and the checksum fields of the packet header. The caller must fill in all other packet header fields. If the transaction ID field is set to 0 (zero), the serial link manager automatically generates and stuffs a new non-zero transaction ID. The array of SlkWriteDataType structures enables the caller to specify the client data part of the packet as a list of noncontiguous blocks. The end of list is indicated by an array element with the size field set to 0 (zero). Listing 3.1 incorporates the processes described in this section.

Listing 9.2 Sending a Serial Link Packet


Err err;
SlkPktHeaderType sendHdr;
    //serial link packet header
SlkWriteDataType writeList[2];
    //serial link write data segments
UInt8 body[20];
    //packet body(example packet body)
   
    // Initialize packet body
    ...

// Compose the packet header
sendHdr.dest = slkSocketDLP;
sendHdr.src = slkSocketDLP;
sendHdr.type = slkPktTypeSystem;
sendHdr.transId = 0;
    // let Serial Link Manager set the transId
// Specify packet body
writeList[0].size = sizeof(body);
    // first data block size
writeList[0].dataP = body;
    // first data block pointer
writeList[1].size = 0;
    // no more data blocks
   
// Send the packet
err = SlkSendPacket( &sendHdr, writeList );
    ...
}


Listing 9.3 Generating a New Transaction ID


//
// Example: Generating a new transaction ID given the previous
// transaction ID. Can start with any seed value.
//

UInt8 NextTransactionID (UInt8 previousTransactionID)
{
    UInt8 nextTransactionID;
   
    // Generate a new transaction id, avoid the
    // reserved values (0x00 and 0xFF)
    if ( previousTransactionID >= (UInt8)0xFE )
    nextTransactionID = 1; // wrap around
    else
    nextTransactionID = previousTransactionID + 1;
    // increment
   
    return nextTransactionID;
}


To receive a packet, call SlkReceivePacket. You may request a packet for the passed socket ID only, or for any open socket that does not have a socket listener. The parameters also specify buffers for the packet header and client data, and a timeout. The timeout indicates how long the receiver should wait for a packet to begin arriving before timing out. A timeout value of (-1) means "wait forever." If a packet is received for a socket with a registered socket listener, the packet is dispatched via its socket listener procedure.

Summary of Serial Communications

Serial Manager Functions New Serial Manager Functions
SerClearErr
SerClose
SerControl
SerGetSettings
SerGetStatus
SerOpen
SerReceive
SerReceiveCheck
SerReceiveFlush
SerReceiveWait
SerSend
SerSendFlush
SerSendWait
SerSetReceiveBuffer
SerSetSettings
SrmClearErr
SrmClose
SrmControl
SrmGetDeviceCount
SrmGetDeviceInfo
SrmGetStatus
SrmOpen
SrmOpenBackground
SrmPrimeWakeupHandler
SrmReceive
SrmReceiveCheck
SrmReceiveFlush
SrmReceiveWait
SrmReceiveWindowClose
SrmReceiveWindowOpen
SrmSend
SrmSendCheck
SrmSendFlush
SrmSendWait
SrmSetReceiveBuffer
SrmSetWakeupHandler
WakeupHandlerProc

Serial Driver Functions Virtual Driver Functions
DrvEntryPoint
SdrvClose
SdrvControl
SdrvISP
SdrvOpen
SdrvReadChar
SdrvStatus
SdrvWriteChar
DrvEntryPoint
GetSize
GetSpace
VdrvControl
VdrvOpen
VdrvStatus
VdrvWrite
WriteBlock
WriteByte

Connection Manager Functions Serial Link Manager Functions
CncAddProfile
CncDeleteProfile
CncGetProfileInfo
CncGetProfileList
SlkClose
SlkCloseSocket
SlkFlushSocket
SlkOpen
SlkOpenSocket
SlkReceivePacket
SlkSendPacket
SlkSetSocketListener
SlkSocketPortID
SlkSocketSetTimeout



Palm OS Programmer's Companion

  Previous Page Table of Contents Index Next Page  

This is page 78 of 85 in this book

Palm Computing Platform Development Zone
Copyright © 2000, Palm, Inc. All rights reserved.