Chapter 8

Using the Palm OS for Bluetooth Applications

Introduction

Of all the PDAs on the market, it is probably Palm, Inc.’s devices that have made the most use of short-range communications. Previously, this has been limited to line of sight beaming via the infrared (IR) interface, but with version 4.0 Palm OS support was in place for Bluetooth wireless technology and line of sight limitations became a thing of the past. Palm, Inc. has said that it will begin to ship Bluetooth accessories in the near future (some are already available to developers), and it plans to integrate Bluetooth technology into its handheld devices before too long. A number of Palm OS licensees have also expressed interest in shipping a Bluetooth solution.

However convenient handhelds may be, it’s undeniably awkward trying to juggle more than one device while you’re on the move. Adding Bluetooth wireless technology to a Palm device frees users from the necessity of trying to physically line up two devices while they’re mobile. It also allows up to eight devices to communicate at once. The Bluetooth system is omni-directional and its radio waves can pass straight through solid objects.

Bluetooth technology includes traditional Palm OS applications like Internet usage and “beaming” easier in mobile environments, but it also creates interesting opportunities for new applications. Object push opens up the possibility of spontaneous communication: you only need to walk into range of a server to see its information pop up on your Palm device’s display. Of course with new communication channels come new security and user experience concerns. Security and ease of use are prime concerns of the new Bluetooth support.

This chapter will give you an insight into Palm OS Bluetooth support, enabling you to port your existing Palm OS applications to use Bluetooth technology, or explore a whole new vista of applications which were not practical with previous communication technologies. Examples make it clear exactly how things are done, so you can start using Palm OS for Bluetooth applications right away.

What You Need to Get Started

Before you start work on your first Palm OS Bluetooth application, there are a few tools you will need. Fortunately, if you are currently a Palm OS developer, you probably have many of these tools already, and those you don’t have are easily available from the Palm, Inc. Web site at www.palmos.com.

Bluetooth support in the Palm OS is an extension to Palm OS 4.0, and is made up of several Palm Application files (.prc files) that may be included in a device’s ROM image, or may be installed with the HotSync install tool and run from RAM. In order to begin using Bluetooth technology, you will need to have a Palm OS device with at least 4 MB of memory that is running Palm OS version 4.0 or greater. Alternatively, if you wish to develop using the Palm OS Emulator, often the easiest and fastest way to create new application, you can obtain a 4.0 ROM image, and the 4.0 Software Development Kit (SDK), from the Palm Resource Pavilion at www.palmos.com/alliance/join. The Palm OS Emulator is available for download from the Development Support area of the Palm, Inc. Web site at www.palmos.com/dev/tech/emulator. You may also find it useful to download the Palm Reporter application, which allows you to see real-time traces from your application.

In addition to a Palm 4.0 device, you will need to have the Bluetooth Support Package installed. The Bluetooth Support Package consists of several .prc files that work together. For the moment, don’t worry about understanding what each individual piece does, simply make sure that you have them all installed. The easiest way to know if your Palm device has Bluetooth support installed is to go into the “Preferences” application and check to see if “Bluetooth” appears in the list of preference screens in the upper-right corner. This indicates that at least part of the Bluetooth Support Package has been installed. If you find that you have trouble using Bluetooth technology later on, you may wish to double-check that all the files in the package are installed by going to the Info screen in the launcher (from the menu, choose “App” then “Info”) or by simply reinstalling all of the .prc files in the package. Unless the device you are using has Bluetooth technology built-in, it is unlikely that the installed ROM image will include Bluetooth support. The latest version of the Bluetooth support .prc files, along with the Bluetooth header files and several pieces of example code, can be found in the Bluetooth area of the Palm Resource Pavilion at www.palmos.com/dev/tech/bluetooth. Developers can also find information on how to obtain early releases of Palm OS Bluetooth development hardware at this site.

In addition to the tools listed here, you will also want to have a copy of the Palm OS 4.0 SDK documentation, also available on the Palm, Inc. Web site. You may find that it is useful to have the 4.0 documentation on hand as you read through this chapter, since there may be references to Palm OS functions calls and data structures with which you are not yet familiar.

Finally, before you get started, you should know that the function definitions and data structures used in the code examples in this chapter are not final. As this text is being written, the Palm OS Bluetooth solution is still in the alpha phase, and while the overall model and methods are not expected to change, some characteristics and arguments of individual API calls, along with some file names, may vary from what is presented here. The code examples presented here should be seen as a basis from which to work, but may require slight modification in order to compile. Refer to the Palm OS documentation and header files for the final word on the API.

Understanding Palm OS Profiles

This section will present an overview of the different profiles supported in the Palm OS Bluetooth Support Package. If you are not familiar with the general concept of profiles, you way wish to go back and review Chapter 2 before continuing.

The Palm OS currently supports five Bluetooth profiles defined in the Bluetooth 1.1 Specification. As shown in Figure 8.1, these profiles are:

image

Figure 8.1 Bluetooth Profiles Supported by the Palm OS

image Generic Access Profile

image Serial Port Profile

image Dial-up Networking Profile

image LAN Access Profile

image Object Push Profile

All the profiles help to ensure interoperability by providing common rules that all Bluetooth devices follow. It is vital to follow these rules as they form part of the Bluetooth qualification process. (Products must pass qualification to obtain the free license to use Bluetooth technology.)

Of these profiles, the Generic Access Profile (GAP) is unique. Unlike the other profiles, which describe a method for accomplishing a specific user goal, the GAP is a general look at the overall process of carrying out a Bluetooth transaction without regard to the nature of that transaction, and is background for all the other profiles. As such, there is no one place in the Bluetooth Support Package that the GAP is exposed, rather the values and language specified by the GAP are built into the Bluetooth Library and other Bluetooth components. GAP’s main goal is to create a friendly and consistent user experience, a goal that is also considered critical in the Palm OS. We will see how the Bluetooth Support Package tries to help application developers maintain easy and consistent experience across applications.

The Bluetooth Support Package includes a new virtual serial driver (a VDRV for short), similar to the IrComm virtual serial driver you may already be familiar with, which provides support for the Serial Port Profile. Both Device A and Device B roles of the profile are supported. Existing OS components that make use of serial services such as Point-to-Point Protocol (PPP), HotSync, and the Telephony Manager are ready to take advantage of the Bluetooth VDRV, and other serial-based applications can easily be updated to make use of the Bluetooth VDRV. We will explore the use of the Bluetooth VDRV in great depth later in this chapter.

The Network Library (NetLib) supports the Data Terminal role of both the Dial-up Networking and LAN Access Profiles. After installing the Bluetooth Support Package, you’ll notice that the Connection panel in the preferences application will allow users to choose Bluetooth technology as a transport when configuring a connection to a local network, phone, modem, or PC. The OS uses these settings to determine which profile to use when NetLib is opened. Since applications that use NetLib are unconcerned with how it creates its underlying transport, the use of the Dial-up Networking and LAN Access Profile is transparent to NetLib-based applications. An e-mail application, for example, that was developed using NetLib running over a normal modem can be used with Bluetooth technology when the user configures the Network panel to use a Bluetooth device. Since the application is unaware of the use of the Dial-up Networking and LAN Access Profiles, we will not spend too much time talking about them.

image Debugging …

Using NetLib with Bluetooth Technology

The Bluetooth protocol stack uses a good bit more heap space than a simple serial driver does. Because of this additional heap usage, you may run into problems if your application is already on the edge of causing a stack overflow, or running out of heap space. Running out of heap space will most likely cause your application to receive NULL back from a memory allocation operation. A well-written operation will always test for failure when allocating memory, and fail gracefully if the needed memory chunk can’t be allocated. Testing with the Palm OS Emulator is a good way to watch for stack overflow conditions; the emulator will tell you when your application is running close to stack boundary conditions.

The Bluetooth Support Package also includes the Bluetooth Exchange Library. This new Exchange Library implements the Object Push Profile, much in the same way that the Exchange Manager supports IR-based Object Exchange Protocol (OBEX) push. You may have noticed that the Exchange Manager in OS 4.0 has been extended to handle multiple transports. Using these new features, it is easy to update legacy Exchange Manager-based code to take advantage of Bluetooth technology (in some cases by changing only a single line of code). New functions allow Bluetooth savvy applications to better handle multiple recipients, and create a better user experience. We will spend a bit of time going over some of these new functions and give some suggestions on how to update your application.

Choosing Services through the Service Discovery Protocol

You may have noticed that support for the Service Discovery Application Profile, a major part of many platforms’ user experience, is absent from the Palm OS’s list of supported profiles. It is important to note that supporting the Service Discovery Application Profile is very different from supporting the Service Discovery Protocol (SDP), which the Bluetooth specification mandates and for which Palm OS offers full support. The aim of the Service Discovery Application Profile is to define how information gained through the Service Discovery Protocol might be presented to the user, and presents two basic usage models: Service Browsing and Service Searching.

In the Service Browsing model, the user would see a list of available devices (the result of a inquiry) and be able to open each device and look through the list of services that that device presents. After browsing, the user would presumably pick the device and service that they wish to utilize. Palm, Inc. does not endorse this model because they believe that the application, not the end user, should be responsible for knowing which service it needs to communicate with, and for being able to find that service. When I sit down at a PC, for example, and type an IP address into an application, I don’t get a list of all of the possible services I can connect to on the remote server as well as a query about which one I wish to connect to. Rather, the application knows that it is a Web browser or a Ping application, and it knows how to find and connect to the appropriate service; if the host does not offer the service, I get an appropriate error message. The same should be true with Bluetooth technology; applications should be responsible for knowing which services they want to use and for knowing how to connect to them.

In the Service Searching model, the user (or application) selects which service they wish to use and then are presented with a list of available devices that present that service. From a user-experience point of view, this is clearly a better model. Unfortunately, this model still causes a problem. The most obvious time to do a service search is during the discovery process, an operation which most users find takes too long already. You could conceivably cache the service lists of remote devices, but this cache would need to be quite large to be useful and it would be difficult to know when your cache was out-of-date. On a large device that has lots of CPU time and battery power to waste making regular inquiries in the background, Service Searching might be a good model, but on a small device it seems like overkill. Rather, it seems to make more sense to use the Class of Device (CoD) information returned during inquiry to do the same kind of service-based filtering. While the information in the CoD is less specific than the information available through SDP, using CoD is probably sufficient in most cases and can actually shorten the total discovery time since devices can be eliminated before a name request is done. As we will see later on, the Palm OS offers a robust model for CoD-based filtering during discovery. Finally, if a developer decides that he or she really wants to use the Service Discovery Application Profile, all of the tools necessary to implement the desired parts of the profile are available to the application.

If none of the profiles cover what you are trying to do, don’t despair. The Palm OS also provides a robust API that allows you direct access to the SDP, RFCOMM, and Logical Link and Control Adaptation Protocol (L2CAP) layers of the Bluetooth stack, along with calls to allow you to manage the Bluetooth-specific concerns like discovery and piconet creation.

Updating Palm OS Applications Using the Bluetooth Virtual Serial Driver

Using the Bluetooth Virtual Serial Driver allows existing serial-based applications to quickly be updated to take advantage of Bluetooth technology, and is an easy way to create new Bluetooth-enabled applications. Virtual serial drivers in the Palm OS are individual .prc files of type vdrv and are used throughout the new Serial Manager interface, much the same way as traditional physical serial ports are used. The Bluetooth VDRV is included with the Palm OS Bluetooth Support Package. This section will focus on the unique aspects of using the Bluetooth VDRV; for information on the general use of the new Serial Manager, refer to the Palm OS documentation directly. Figure 8.2 shows a basic overview of how Bluetooth technology fits into the Palm OS communications architecture.

image

Figure 8.2 How Bluetooth Technology Fits into the Palm OS Communications Architecture

The Bluetooth VDRV, in accordance with the Serial Port Profile, runs on top of the RFCOMM protocol layer. It is worth noting that the VDRV does not implement RFCOMM itself. The RFCOMM protocol layer is implemented in the Bluetooth Library and can be accessed directly through the Bluetooth Library API (discussed in depth later in the chapter). The VDRV itself is “glue code” that allows Bluetooth functionality to be accessed though a more traditional API. Using the VDRV also gives you an advantage in writing multi-transport applications. Since there are only a few differences between using the IrComm VDRV and the Bluetooth VDRV, much of your code will not need to be altered in order to use both transports.

Gluing new technology underneath an old interface always presents some challenges and there are a few limitations to using the Bluetooth VDRV that you should be aware of. In order to achieve certain performance optimizations, the Bluetooth VDRV opens the Bluetooth Library with a slightly different configuration than is normally used when an application opens the Library. As such, the Bluetooth VDRV and the Bluetooth Library cannot be opened by the application at the same time. Since NetLib and the Telephony Manager can be configured to use the Bluetooth VDRV, the Bluetooth Library and the VDRV may not be available when these other components are in use. Applications are also limited to using a single instance of the Bluetooth VDRV at any given time.

One of the challenges of mapping Bluetooth underneath a traditional serial API is that traditional serial ports are single-channel and non-addressed in nature, while the Bluetooth system is a multiplexing, address-based protocol stack. A traditional serial port driver can simply initialize its local hardware, start talking and hope that there is a cable in place and someone listening on the other side, while Bluetooth technology needs to know which device and which service on that device it is going to talk to; it must also actively create the underlying baseband connection. Since most Bluetooth radios are not capable of simultaneously listening for an inbound connection and trying to create an outbound connection, an instance of the Bluetooth VDRV also needs to know whether it is initiating or accepting the connection.

Since a traditional serial API does not present a mechanism for passing all of this extra information, Palm OS 4.0 has added a new call, SrmExtOpen() (found in SerialMgr.h), to the New Serial Manager API. The SrmExtOpen() call allows an application to pass down additional configuration data, along with a driver-specific configuration structure. SrmExtOpen() must be used to initialize the Bluetooth VRDV—passing the Bluetooth VDRV into the older SrmOpen() call will simply cause the call to fail.

The top level configuration structure that is passed into the SrmExtOpen() function for the Bluetooth VDRV is defined in the SerialMgr.h file as the following:

image

When using the Bluetooth VDRV, the drvrDataP element should be filled in with a pointer to an instance of the RfVdOpenParams structure. This is a Bluetooth VDRV-specific structure, and applications should be sure that they are dealing with the Bluetooth VDRV before passing the pointer. The RfVdOpenParams structure, along with several supporting structures, is defined in RfCommVdrv.h. Later, we’ll see examples of how these structures are used. First, let’s take a look at the structures themselves.

image

image

As mentioned earlier, most Bluetooth radios are not capable of receiving inbound connections while trying to create outbound connections. For this reason, it is necessary for an application to indicate whether it wishes to initiate or accept the Asynchronous Connectionless Link (ACL) and RFCOMM connections. Palm OS refers to these roles as the client role and the server role, respectively. The application indicates its preference by setting the corresponding value for the role element in the RfVdOpenParams structure and filling the appropriate role-specific parameter structure inside the union. The authenticate and encrypt values are used to specify the security requirements for the link; if these requirements cannot be met, the link will be dropped.

image

When the VDRV is opened in the server configuration, it will register for an RFCOMM channel and advertise that channel via SDP. This creates a simple service record utilizing the Unique Universal Identifier (UUID) and name string defined in the RfVdOpenParamsServer. If the application wants to create a more robust service record, it should use RFCOMM and SDP directly through the Bluetooth Library (BtLib) API.

UUIDs are used to uniquely identify an application, or more specifically, the protocol the application expects to communicate with. If the application is willing to handle the possibility that it may get a connection to an incompatible application, and the application will only be used between two Palm OS devices, the uuid can be set to 0. This will cause the VDRV to use a predefined UUID unique to the Palm OS. If the server chooses to set the uuid to 0, the client should do so as well.

Since all actions involved in a server open are local, the open call should only fail if there is a resource conflict.

image

To open the VDRV in the client configuration, a more complex structure must be passed in to SrmExtOpen(). The remoteDevAddr parameter indicates the 48-bit Bluetooth device address of the remote device the VDRV should connect to. The application might determine what address to use by making a call to BtLibDiscoverSingle() in the BtLib API (discussed later), or by taking an address from a Connection Manager Profile that uses Bluetooth technology. If remoteDevAddr is set to 0, the VDRV will perform a device discovery and ask the user to specify a remote device during the open. After creating an ACL connection to the remote device, the VDRV attempts to establish an RFCOMM connection. The application must indicate which RFCOMM channel the VDRV should use. The channel is determined by using SDP to look up the Channel ID of the remote service. While the application is welcome to use the SDP function calls in the BtLib API to obtain the Channel ID (and the rfVdUseChannelId method to pass in), the VDRV presents an easier method. By using the rfVdUseUuidList method, the application can simply pass in the UUID of the service it wishes to utilize. Passing in more than one UUID will cause the VDRV to run through the list until it finds a service it can use. The VDRV will look for a service record with the given service UUID, and if a record is found, it will then search for the RFCOMM Channel in the record’s protocol descriptor list (if multiple protocol descriptor lists are contained in the record, the VDRV will use the first RFCOMM channel it comes across). Setting the method to rfVdUseUuidList and setting len to 0 will cause the VDRV to look for the predefined Palm OS UUID (discussed earlier).

Since a client-open may block for several seconds while the ACL connection is brought up, the VDRV may display some UI to allow the user to see the connection progress.

Creating a VDRV Client-Only Application

Let’s move on to looking at a real VDRV client-only application. Such an application might be useful when you know that the Palm device will always be playing a client-based role, and therefore never need to accept a connection. Let’s imagine that we are creating an application for controlling home appliances, using the (entirely imaginary) Bluetooth Based Blender Remote Control Profile (B3RCP for short). Since, as we all know, B3RCP is based on the serial port profile, it is appropriate to use the VDRV. Furthermore, since we know that the Palm device will always initiate the connection to the blender (after all, appliances don’t generally initiate contact with the remote control), the Blender-control application is a good example of a client-only application. For the purpose of this example, we will assume that the B3RCP is a well-known protocol, and that a UUID of 07004F16-3776-11D5-83CE-0030657C543C has been established as a service ID for B3RCP services. For your own applications, you will need to use established UUIDs for the profile you are using, or create a new UUID yourself using one of the many UUID (sometimes called GUID) generation tools that are commonly available on the Web.

Let’s look at the code fragment that performs the VDRV open call.

image

The structure BtLibSdpUUIDType consists of a size indicator and an array of bytes that form the UUID itself. The size of all UUIDs not declared directly in the Bluetooth specification is btLibUuidSize128.

image

image

image

image WARNING

Applications and the VDRV use the Bluetooth Library in different modes. Because of this difference, the VDRV will not be able to open while the application is holding the Bluetooth stack open.

The main application block can now be coded to make a call to OpenPortAsClient(). If the call returns without error, the port is open and can be used as any normal serial port might be used. Closing the port will cause the RFCOMM and ACL connections to be dropped. In general, protocols that run over standard serial ports are responsible for defining their own stay-alive and timeout conditions. In general, this is true for Bluetooth VDRV ports as well, though if the ACL link is lost before SrmClose() is called, the SrmSend() call will return serErrLineErr.

Now, let’s look at the problem from the other side.

Creating a VDRV Server-Only Application

As an employee of Frappé.com, you have been made the lead software engineer on the iBlend, the world’s first Palm-device powered blender. Since the iBlend is a state-of-the-art home appliance, its feature set will clearly need to include support for B3RCP, allowing the user to make a margarita without the inconvenience of having to walk across the room. The iBlend will need to open the virtual serial port in the server role, which will require a slightly different open call.

image

image

The OpenPortAsServer() call will take care of setting up the server serial port for the main application on your iBlend. Note that setting up the port as a server does not cause the driver to go out and create an ACL or RFCOMM connection, it merely sets the port up as a listener. Like a normal serial port, the VDRV will not alert the application when an incoming connection is established, the application will simply begin to receive data from the port. Like any protocol that runs over a serial port, B3RCP must handle session establishment and termination. The port will also accept the first inbound connection it receives, as long as that connection meets the security requirements set in the RfVdOpenParams structure. If the protocol or application above the serial port requires additional security, it’s up to that layer to implement it.

Now we have seen an example of both a client-only and a server-only use of the VDRV. At this point, you may be saying to yourself, “That’s all great and everything, but I’m writing a Palm-to-Palm application. I need to be able to be both client and server!” Fortunately, this is easy. The simplest way to handle this case is to open the serial port as a server when your application is opened. When the user does something that requires a connection (i.e., pushes a start button, starts to generate input, and so on), close the serial port and reopen it as a client. You will have to somehow convey to your users that only one person should start the connection, but this is a commonplace enough idea that most users should get it without too much hassle.

Once the port has been opened, it behaves like any other Palm OS serial port. This means that you can use the same code and Serial Manager calls that you use with your existing serial application. By adding a few simple routines to open the port, you can make your legacy application Bluetooth-aware.

You should now know everything you need to know to create your first Palm OS Bluetooth application. Alternatively, you may have found that the VDRV doesn’t suit your Bluetooth technology needs—it is, after all, only an emulation layer. The rest of the chapter will cover the use of the Exchange Manager and the Bluetooth API.

Using Bluetooth Technology with Exchange Manager

If you’re interested in using Bluetooth technology to transfer records, or if having a constant data flow is not important to your application (as in a turn-based game), the Bluetooth Exchange Library might be the perfect tool for you to use. The Exchange Library allows applications to send data blocks without having to worry too much about the underlying transport. Unlike sockets and virtual serial drivers, the Exchange Manager is a concept unique to Palm OS. Gavin Peacock, the engineer at Palm, Inc. who came up with the Exchange Manager, explains that the need for the Exchange Manager comes from the lack of a file system in the OS (OS 4 does support a file system for use with expansion cards, but the user is unaware of it). In other OSs, if the user wants to send a file over a given transport, they save the file somewhere and then go to the application responsible for that transport (i.e., the e-mail application, the IR exchange application, and so forth) and specify the file they want to send. In Palm OS, the Exchange Manager creates a singular API that brings all of the available transports to each application, avoiding the need to deal with file systems and transport-specific applications. The Palm OS SDK documents go into the use of the Exchange Manager in great detail; we’ll concentrate here on new issues that are of particular relevance to using the Bluetooth Exchange Library.

The Bluetooth Exchange Library is so easy to use, your application might already be set up to use it. The Exchange Manager in Palm OS 4.0 introduced a new URL send scheme, known as the exgSendScheme. Rather than referring to a specific transport, the send scheme instructs the Exchange Manager to allow the user to pick which of the installed transports they wish to utilize. The Bluetooth Exchange Library registers itself for the exgSendScheme, so if you’ve already updated your application to take advantage of the exgSendScheme, it should work with Bluetooth technology as soon as you have installed the Bluetooth .prc files. If you haven’t yet updated your application to use send, the Address Book code in the SDK contains a good example of how exgSendScheme is used. If you know that your application only wants to use Bluetooth technology, you can indicate this by using the btExgScheme (“_btObex”) instead of the exgSendScheme. The result will be the same as using the exgSendScheme, except that the user won’t be offered a choice of transports.

Once the Bluetooth system has been chosen as the transport, the Exchange Library will automatically perform a discovery in order to determine the address of the remote device it should connect to. If you already know the Bluetooth device address you wish to connect to, you can indicate this in the URL by sticking the address in the URL you pass in with the exchange socket as follows:

Char *urlBase =“_btObex://12.34.56.78.9A.BC/filename.ext”

In reality, you would probably build this URL string dynamically, instead of hard coding it. The first section of the URL defines the scheme, as discussed earlier. The second section of the URL is a character representation of the Bluetooth device address of the target device. If you have the device address stored in a BtLibDeviceAddressType structure, you can easily convert the address to a string by calling BtLibAddrBtdToA() (this function can be called without first opening the Bluetooth Library). This kind of usage might be useful in situations where the application keeps some kind of “buddy list” of devices, making a discovery unnecessary. In addition to a single device address, the second section of the URL can also use the meta-addresses “_single” and “_multi”, which indicate that the Exchange Library should perform a discovery and prompt the user to select one or multiple devices, respectively. For multiple recipients, the URL addressing convention is to separate the recipient’s Bluetooth device addresses with a comma, as follows:

image

The last section of the URL is the name and extension you wish the file to have when it is sent to the remote device.

In some applications, such as a chess game, you may wish to have a discovery occur on the first move, but then always use the same device address for each move afterwards. This can be accomplished using a new ExgMgr call control call named exgLibCtlGetURL. The Bluetooth Exchange Lib is the first to implement this control, but it is expected that other Exchange Libraries that use addresses (such as SMS) will be updated to use it soon. The purpose of the exgLibCtlGetURL control is to allow the application to retrieve an exchange sockets URL after the Exchange Library has filled it out. The call can be made any time after a successful ExgPut(), ExgConnect() or ExgAccept() call, and before ExgDisconnect() is called.

When invoking the exgLibCtlGetURL control, the valueP parameter passed to ExgControl() should be a pointer to a ExgCtlGerURLType structure, which is defined as:

image

Obviously, socketP is a pointer to the ExgSocket you are trying to get the URL for, URLP is a pointer to the character buffer where the URL will be stored, and URLsize is the size of the buffer. If the call is successful, the URL buffer will be filled in, and so will the length of the URL (including the mandatory NULL terminator). If the application wants to dynamically allocate the URL buffer space, it can first make the call with the URLP set to NULL and the URLSize parameter set to 0. In this case, the call will simply return the URL size so that the application can allocate an appropriately-sized buffer to retrieve the URL with. Once the application has retrieved the URL, it can utilize the same URL with future ExgSockets to indicate that it wants to use the same exchange scheme and remote device. The Tic-Tac-Toe application in the Palm OS Bluetooth developer kit provides an excellent example of an application that makes use of the Bluetooth Exchange Libraries’ URL scheme to create a two-player game.

On the receiving side, the application is generally unaware of which exchange transport is being used.

In certain scenarios, such as the chess game just described, the receiving app may wish to grab the sender’s address from the URL for use in subsequent moves.

Creating Bluetooth-Aware Palm OS Applications

The VDRV and Exchange Manager simplify using Bluetooth technology by encapsulating it inside familiar and easy-to-use interfaces, but the simplification also hides functionality and increases overhead. If the Exchange Manager or the VDRV suit your needs, then you should certainly use them, but if your application requires direct access to Bluetooth protocol layers or management functions, then you will need to make use of the Bluetooth Library (BtLib) API. This section will cover the use of the Library and provide some examples of good coding practices.

The Bluetooth Library API is fairly large, consisting of over sixty calls, and can generally be divided into six sections:

1. Common Library calls Calls common to all libraries: Open, Close, Sleep, and Wake.

2. Management calls Used for Discovery, managing ACL links, and global Bluetooth settings.

3. Socket calls Used to manage RFCOMM, L2CAP, and SDP communications.

4. SDP calls Used to create and advertise service records to remote devices and to discover services available on remote devices.

5. Service calls Allows application developers to create persistent Bluetooth services (daemons).

6. Security calls Used for managing the Trusted (Bonded) Device database.

This section focuses on the Management and Socket sections of the API, with a brief discussion of how to advertise your application using SDP. You should find that the Bluetooth API offers extensive access to Bluetooth functionality while managing to keep things relatively simple. Using the Bluetooth Library directly requires a better understanding of Bluetooth technology than using the VDRV or the Exchange Library, but the Library handles most of the minutiae of the Bluetooth protocols.

Like many communications interfaces, the Bluetooth API is made up of both synchronous and asynchronous calls. The synchronous calls block while they do their work and return a result when they are complete. These calls are used when the operations involved are purely local, not involving the radio or remote Bluetooth devices, and thus can be assured to complete in a reasonable time frame. Asynchronous calls are used whenever the operation involves talking to an external entity such as the radio or a remote Bluetooth device. This is done because most Palm OS developers work in a single thread, and thus should not be blocked for a long period of time while waiting for a call to return. Asynchronous calls return almost immediately and then report their results through a callback that the application must register to receive. The header files identify the asynchronous calls by noting that they return a “Pending” result and by listing the events that you can expect the call to generate. You may notice that a few of the asynchronous calls, such as BtLibStartInquiry(), generate multiple events.

There are two types of events: management events, which contain the results of management API activities, and socket events, which contain information about activity on a particular L2CAP, RFCOMM, or SDP socket. Management events are sent to a management callback, which the application should register after opening the Library. Socket events are passed to the callback that is passed in when the socket is created. While these data structures are termed “ManagementEvents” and “SocketEvents,” they should not be confused with the general Palm OS events type used in the application event loop; the Bluetooth Library events are separate and unrelated to Palm OS events or notifications.

image NOTE

It is worth noting that there are a few things that a Palm OS application cannot do even when using the Bluetooth Library directly. The Library does not currently allow applications to put the Palm device or the remote device into park, hold, or sniff modes. While an application can request that a given link be authenticated or encrypted, for security reasons the application is not allowed to specify the authentication passkey or insist that a device be added to a list of trusted (or bonded) devices.

Using Basic ACL Links

Before you can use the Bluetooth Library, you must find the Library and open it. Opening the Library will cause the OS to initialize the Bluetooth stack and radio. Stack initialization is an asynchronous function, so immediately after opening the stack, you should register a management callback. When the initialization is complete (this requires about 50ms for most radios), the callback will receive a btLibManagementEventRadioState event, whose status field will indicate whether the initialization was successful. Most of the calls to the Bluetooth Library require that the radio be initialized, and making these calls before the btLibManagementEventRadioState event is received will result in an error. The Bluetooth stack supports re-entry from the callback, so any additional configuration you wish to do can be done from the callback when the radio state event is received. Here is a quick example of how to open and close the Library:

image

image

image

If your application is going to receive inbound connections, you should check to make sure that the radio’s accessibility mode has been set to allow connection and (if desired) discovery. The current accessibility mode can be obtained by calling BtLibGeneralPreferenceGet() and passing the btLibPref_UnconnectedAccessible value for the preference type. The accessible state of the device is determined by the user’s settings in the Bluetooth Preferences Panel, and the application should never override this state without first asking the user’s permission. If the application does get the user’s permission to change the state, it can do so by making a call to BtLibSetGeneralPreference(). Calling BtLibSetGeneralPreference() does not change the user-defined preferences, but rather only temporarily overrides them; nonetheless, the application should record the original radio settings, and restore them before exiting. If the user has set Bluetooth technology to be OFF in the Preferences panel, the Library itself will prompt the user before allowing an application to change settings that affect the radio. The application should never attempt to override the OFF setting.

If you plan to have your application create outbound Bluetooth connections, you will probably want to perform a device discovery in order to allow the user to select the remote device(s) with which she wished to create a connection. The Bluetooth Library offers two similar calls that handle the entire discovery experience, including inquiry, name retrieval, and user selection. BtLibDiscoverSingleDevice() and BtLibDiscoverMultipleDevices() differ only in that the number of the devices the UI will allow the user to select, and the fact that BtLibDiscoverSingleDevice() returns the selected device directly while BtLibDiscoverMultipleDevices() returns the number of devices selected, which can then be retrieved by passing an appropriately sized array to BtLibGetSelectedDevices().

The discovery calls are designed to create a standardized user experience while still offering enough flexibility to be useful to a wide range of applications. Some of these things are quite simple, like letting the application specify the instruction text on the user selection screen. A chess game might pass, for example, the string Choose an opponent while a printing application might want to ask the user to “Select a printer.” One of the most useful features of the discovery calls is the ability to filter out any devices that do not belong to one of the classes specified by the application. Using this feature, a Palm-to-Palm game could prevent non-PDA devices from showing up in the list of discovered devices, thus limiting the users’ choices to the appropriate class of device. If an application passes in multiple CoD descriptions, the application will show devices that fit any of the indicated classes. The following is an example of a discovery call that will display all smart phones and all classes of computers:

image

image

You may have noticed that the discovery call contains two arguments that haven’t yet been mentioned, the last two arguments: addressAsName and showLastList. The addressAsName argument instructs the Library to skip name retrieval and instead display the numeric Bluetooth device addresses of each of the devices. This is mainly useful as a debug tool, since in general we try to shield the user from long dealing with long numeric addresses. The showLastList argument causes the Library to skip the inquiry phase and instead show the same list as the last discovery. These two discovery calls should be flexible enough to handle most applications’ needs; if for some reason, however, an application requires something outside of the discovery calls supported activities, the application can implement it’s own discovery procedure using the BtLibStartInquiry() and BtLibGetRemoteDeviceName() calls detailed in the BtLib.h file. Once the application has set the appropriate accessibility mode and gained the address of a remote device (or devices) it wishes to connect to, it can begin the process of establishing ACL connections.

Bluetooth piconets have a star formation; one master connected to up to seven active slaves. The Bluetooth specification talks about overlapping networks of two or more piconets called scatternets (see Figure 8.3). These, however, are not well-defined and none of the Bluetooth radios currently available are capable of creating or managing scatternet formations.

image

Figure 8.3 Piconets and Scatternets

In single connection applications, where applications participate only in one-to-one connections or as a slave in one-to-many connections, ACL establishment is very simple. To receive an inbound ACL connection, the application should simply wait for the Management Callback to receive a btLibManagementEventACLConnectInbound event. This event will contain the address of the remote device, if the application wishes to reject the connection, it can call BtLibLinkDisconnect() in the callback. To create an outbound link, the application should call BtLibLinkConnect() with the address of the device it wishes to connect to, and wait for a btLibManagementEventACLConnectComplete to indicate whether the connection attempt was successful. By default, the initiator of a link is the master and the recipient of the link is the slave. When there is only one ACL connection, the role of the local device is unimportant, and the Palm OS will allow the master/slave switch to be performed. The OS will also change the accessibility mode to disable page scanning and inquiry scanning while a connection is in place, which will prevent unwanted connection attempts and increase the bandwidth available to the application.

If the application wishes to allow multiple connections, it should use the piconet calls found in BtLib.h:

image Err BtLibPiconetCreate(UInt16 btLibRefNum, Boolean unlockInbound, Boolean discoverable)

image Err BtLibPiconetDestroy(UInt16 btLibRefNum)

image Err BtLibPiconetUnlockInbound(UInt16 btLibRefNum, Boolean discoverable)

image Err BtLibPiconetLockInbound(UInt16 btLibRefNum)

The applications must first call BtLibPiconetCreate(). This call indicates to the Library that you want to create a multiple device piconet, and changes some of the policies that the OS uses. In order to have multiple ACL connections, a device must be the master of its piconet. Calling BtLibPiconetCreate() changes the OS policies to disable the master/slave switch on outbound connections (so that it remains master) and forces the master/slave switch on inbound connections (so that it becomes the master). If the device is already a slave in an ACL connection when BtLibPiconetCreate() is called, the call will return a pending response, and attempt to become the master of the link. The Bluetooth Lib will then generate a btLibManagementEventPiconetComplete event to inform the application whether or not the piconet creation was successful. If the device is a master in an ACL connection, or there are no ACL connections in place to begin with, BtLibPiconetCreate() will return a success response and no event will be generated.

Once a successful BtLibPiconetCreate() call has been made, up to seven simultaneous ACL connections can be established. Depending upon the usage model for your application, you may wish to have the piconet master actively create outbound connections, wait for inbound connections from remote devices, or both.

Outbound connections can be created at any time, simply by having the application call BtLibLinkConnect() with the address of each remote device with which it wishes to form a connection. Each call to BtLibLinkConnect() will generate a btLibManagementEventACLConnectComplete event with the result of the connection attempt in the status field. Similarly, calling BtLibLinkDisconnect() will cause the radio to disconnect an ACL link. Whenever a link is dropped, perhaps as the result of having called BtLibLinkDisconnect() or as the result of an action on the remote device or from range or interference problems, a btLibManagementEventACLDisconnect event will be generated. The status field of the event will give the reason for the disconnection.

In order to allow inbound connections, the piconet must be unlocked for inbound connections. Locking and unlocking the piconet affects the accessibility state of the radio. Unlocking the piconet causes the radio to periodically scan for inbound connections (a state called Page Scan mode in the Bluetooth core specification, or “connectable” in the Generic Access profile). When unlocking a piconet, the application can also specify that the radio should scan for and respond to discovery requests (called Inquiry Scan mode in the Bluetooth core specification or “discoverable” in the Generic Access Profile). Locking the piconets will make the device non-connectable and non-discoverable. If the piconet is full (i.e., if seven ACL connections are in place), the OS will also make the radio non-connectable and non-discoverable, even if the piconet is unlocked, until one of the ACL connections is dropped. After BtLibPiconetCreate() is called, the lock/unlock state of the piconet overrides the user’s accessibility preferences or the accessibility mode set with BtLibSetGeneralPreference(). When the application calls BtLibPiconetDestroy(), the OS will return, sever all ACL connections and set the accessibility mode back to its original state. While the application is free to leave the piconet unlocked all of the time, you should be aware that since the radio will periodically have to spend time performing page and inquiry scans, the throughput on the ACL links of an unlocked piconet will be lower than the throughput of the links on a locked piconet. Bandwidth-conscious applications should leave the piconet locked most of the time.

Creating L2CAP and RFCOMM Connections

The L2CAP and RFCOMM protocol layers are exposed in the Bluetooth API through a sockets-based interface. The SDP interface uses the sockets-based API as well, but that will be discussed further in the following section. The application creates a socket by calling BtLibSocketCreate(), which allocates a socket structure and associates it with a protocol. BtLibSocketCreate() also takes a callback function pointer as an argument; this callback is associated with the socket and will receive all of the events for that socket. After a socket is created, it needs to be assigned a role. The application can make the socket into a listener for inbound connections by calling BtLibSocketListen(), or create an outbound connection by calling BtLibSocketConnect(). When an inbound connection occurs, a listener socket will spawn a new socket for that connection. It’s worth noting that the ability to create and receive RFCOMM and L2CAP connections is entirely independent of the device’s role in a piconet; a device that receives an inbound ACL connection may create an outbound L2CAP connection. It’s really up to the profile or the application you are working with. In this section, we’ll look at how to create and use sockets for L2CAP and RFCOMM communication.

image Developing & Deploying …

RFCOMM versus L2CAP

Before we get too far into the Palm OS specific handling of L2CAP and RFCOMM, let’s take moment to examine the two layers themselves. As you will have noticed by now, the RFCOMM is built on top of the L2CAP layer. In general, when we see protocols layered on top of each other, we assume that the upper layer protocol somehow extends the functionality of the protocol layer below it. For example, most of us are familiar with the fact that the IP layer of the TCP/IP stack is responsible for routing and delivering packets through a network, and that the TCP layer builds on top of IP to offer reliability and in-order delivery. This is not really the case for RFCOMM and L2CAP, however. RFCOMM and L2CAP are both what the OSI model describe as Data-Link layer protocols; which is to say that both are concerned with reliably delivering packets of data between two linked devices: in our case, a master and a slave. Neither L2CAP nor RFCOMM offer any kind of networking or routing functions. They are only capable of delivering data to devices with which there is a direct ACL link. Given these similarities, many people have wondered why both protocols exist in the Bluetooth stack. This is a very good question, without a very good answer. The short answer is that RFCOMM is a legacy of the original goal of Bluetooth technology: to create a wireless replacement for serial cables. If you look in the RFCOMM specification, you will see that the protocol deals heavily with physical line simulation, giving upper layers the ability to set and poll individual line states, just as they would with a physical serial port. In reality, however, very little use is made of these serial port emulation features of the protocol, and in general, it is treated as a simple packet-based data-link layer. While most of the profiles in the 1.1 specification make use of the RFCOMM layer, over time I think we will see most new usage models run directly over L2CAP.

There are, however, a few differences between L2CAP and RFCOMM that may influence which one you decide to use. Since RFCOMM runs on top of L2CAP, RFCOMM has a slightly higher header overhead than L2CAP does (about 5 extra bytes), which decreases RFCOMM’s total data throughput and MTU size. A more important difference is that RFCOMM provides flow control, while L2CAP does not. This means that an L2CAP channel is capable of pushing data at you as fast as the remote device can send it, and there is no way for the application to flow the L2CAP channel off. This is not really a problem; it simply means that applications or protocols that run on top of L2CAP must be able to handle the flow control themselves, while applications that run on top of RFCOMM can make use of its built-in flow control. Another important difference between RFCOMM and L2CAP is the way that inbound connections to listeners are handled. We will talk in more detail about the differences between L2CAP and RFCOMM listener sockets in a moment, but the main divergence to note is that an RFCOMM listener is only capable of supporting one connection at a time, while a L2CAP listener can receive an unlimited number of connections. For applications that only make use of single ACL links, the difference is probably not important, but for an application that wants to be a server in a seven-slave piconet, having to only register and advertise one socket can be a big convenience.

Of course, if your application involves functionality covered by a Bluetooth profile you will not have to make a choice of which layer to use as the profiles provide guidance on how to use the Bluetooth protocol stack.

To create a listener socket, first allocate a socket with your desired protocol by calling BtLibSocketCreate(), then register the socket as a listener by calling BtLibSocketListen(). Since listener sockets do not need to specify a remote device, they can be created any time after opening the Library, whether or not there are any ACL links in place. The listenInfo argument to BtLibSocketListen() is a pointer to a structure of type BtLibSocketListenInfoType, which contains protocol-specific listening information.

image

image

The BtLibSocketListenInfoType structure is interpreted based upon the protocol assigned to the socket that is becoming a listener. As you can see, slightly different information is used to register an RFCOMM listener than to register an L2CAP listener. L2CAP identifies available listeners by a Protocol Service Multiplexor (PSM), which can be thought of as being similar to an IP port. PSM values up to 0x1000 are reserved for use by the Bluetooth SIG. Values above 0x1000 can be used by applications, as long as the ninth bit (0x0100) is set to zero (the ninth bit is an escape bit to indicate a PSM longer than 16 bits, which the Palm OS does not currently support). While you are welcome to define your own PSM, the fact that there is no central registry for PSM values means that you cannot be assured you will be able to avoid conflicts with other applications on the device. A better idea is to pass in BT_L2CAP_RANDOM_PSM, which will cause the OS to assign an available PSM value to the listener. You can let remote applications know which PSM to connect to by advertising the PSM value with SDP, discussed in the next section.

The localMtu and minRemoteMtu values are used by L2CAP to negotiate the maximum packet size from the connection. Both localMtu and minRemoteMtu must be between BT_L2CAP_MAX_MTU and BT_L2CAP_MIN_MTU and minRemoteMtu must be less than or equal to localMtu.

The RFCOMM protocol uses a simple enumeration called a Server ID to distinguish its listeners. Unlike the L2CAP PSM value, an RFCOMM listener socket’s Server ID cannot be chosen by an application. Rather, Server IDs are sequentially assigned by the OS. Like L2CAP listener socket’s PSM values, after an application has created an RFCOMM listener socket, it should advertise the listener socket’s Server ID using SDP. The RFCOMM listen parameters also include a maxFrameSize that defines the maximum frame size allowed for the channel, and should be between BT_RF_MIN_FRAMESIZE and BT_RF_MAX_FRAMESIZE. The RFCOMM listen parameters also contain an advanceCredit field that allows an application to specify a default amount of credit a remote device should be advanced upon connection (more on RFCOMM credit-based flow control in a moment).

Once a listener socket has been created, it will wait for connection attempts until the socket is closed with the BtLibSocketClose() call or until the Library is closed (as a precaution, applications should always close all sockets before they close the Library, since another application may hold the Library open even after you close it). When an L2CAP or RFCOMM connection attempt is made, the appropriate listener socket’s callback will be sent a btLibSocketEventConnectRequest event. The socket must call BtLibSocketRespondToConnection() during the callback to accept or reject the inbound connection. After responding, the listener socket will receive a btLibSocketEventConnectedInbound event; the status field indicates whether or not the connection was successfully negotiated. If the connection was successful, the listener socket will spawn a new connection socket, which will be identified in the btLibSocketEventConnectedInbound event structure. The new connection socket will share a callback with its parent listener socket (you can identify which socket an event is for by looking at the socket field of the event structure).

To create an outbound connection, the application should first allocate a socket by calling BtLibSocketCreate(), and then create a connection with that socket by calling BtLibSocketConnect(). Like BtLibSocketListen(), BtLibSocketConnect() takes a pointer to a structure that indicates protocol-specific parameters.

image

As you can see, most of the information contained in the BtLibSocketConnectInfoType is analogous to information in the BtLibSocketListenInfoType, and like the BtLibSocketListenInfoType is interpreted based upon the protocol of the socket passed to the BtLibSocketConnect() call. The minRemoteMtu, localMtu, and maxFrameSize fields are used by the lower layers to negotiate the maximum packet size for the connection, and the advancedCredit is used by RFCOMM to automatically advance flow control credits upon connection. The remotePsm and remoteService, for L2CAP and RFCOMM sockets respectively, are used to determine which listener socket to connect to on the remote device. If the desired service on the remote device has a statically assigned L2CAP PSM value (not recommended, see earlier), the PSM value can be defined directly in the application. In most cases, you will want to use SDP to find the PSM or Server ID for the remote service. After BtLibSocketConnect() has been called, the socket callback will receive a btLibSocketEventConnectedOutbound event, with a status field that indicates whether or not the connection was successful.

Once a connection socket, inbound or outbound, has successfully been established, data can begin to flow. The application can send data by calling BtLibSocketSend(), and will receive data through btLibSocketEventData events sent to the sockets callback. BtLibSocketSend() will cause a btLibSocketEventSendComplete event to be generated when the data has been successfully transmitted. In order to minimize memory consumption and processing time, the Bluetooth Library does not buffer outbound or inbound data. This means that applications are responsible for handling their own buffering. When an application calls BtLibSocketSend(), it should consider the memory block indicated by the data pointer to be owned by the Bluetooth Library until the application receives a btLibSocketEventSendComplete event. Changing or freeing the memory block during this time can corrupt the data being sent, or even crash the device. Since the Library does not buffer data, only one call to BtLibSocketSend() can be pending at any given time; additional calls will result in a “busy” error. Since the Library does not buffer inbound data, the application must handle the data indicated in a btLibSocketEventData immediately, either by processing the data immediately or by copying and storing it for future processing. Once the btLibSocketEventData callback has returned, the event data pointer is no longer valid.

In the case of RFCOMM connection sockets, in order to receive data, the application must first advance credits by calling BtLibSocketAdvanceCredit(). Each RFCOMM flow control credit represents one packet on that channel. Advancing 10 credits indicates to the remote device that your application is ready to receive up to ten packets. Credit advances are cumulative, so making three calls to BtLibSocketAdvanceCredit() with a value of 5 credits would extend a total of 15 credits to the remote device. The credit count for a socket is decremented each time that the socket receives a packet. When the credit count reaches zero, the remote device is blocked from sending data on the channel. You should look at the total available buffer space your application has available and divide by the channel’s maximum receivable packet size (that is, the Maximum Receivable Unit [MRU]) for the socket (found by calling BtLibSocketGetInfa()), and rounding down to find the number of credits your application should initially advance. When your application has processed data from its buffer, it can advance credits corresponding to the size of the processed data divided by the channel MRU. A maximum of 256 total credits can be advanced at any given time.

Handling your own buffering is not as much work as it might seem. In most cases, a few simple queue structures will suffice. The following is an example buffering code from a shared white board application. In this case, the application keeps only one queue for buffering outbound data; inbound data does not need to be buffered since it is handled immediately by drawing to the screen. Since space is limited, instead of giving the source code for an entire Palm application, this section will focus on a few important functions that can be used in a Bluetooth-aware application. For example, instead of putting in an entire OS event loop, the example only shows a pen event handler, which is called from the main event loop. For the purpose of this example, we will assume the existence of some standard queue functions that allow us to create and manage a normal first-in-first-out queue. We will also assume that the application has already managed to open the Library and create an L2CAP connection.

image

image

image

image

image

image

Pushing the buffering back to the application ensures that memory usage is as efficient as possible for any given application, without adding too much burden to the application developer.

The application should close the socket by calling BtLibSocketClose() when it is ready to close the socket connection, or when it receives a btLibSocketEventDisconnected event (at this point the connection is already lost, so the close call simply frees the socket). If the ACL connection is lost, a btLibSocketEventDisconnected event will automatically be generated. Applications should be sure to close all sockets before closing the Bluetooth Library.

Using the Service Discovery Protocol

In the previous section, we discussed the need to use Service Discovery Protocol to find an application’s PSM or Service ID, rather than relying on hard-coded values. The Bluetooth Library offers an extensive set of APIs for working with SDP. In this section, we will concentrate on the calls needed to advertise a basic service record for an L2CAP or RFCOMM listener socket and to retrieve connection information about L2CAP and RFCOMM listeners on a remote device.

image Developing & Deploying …

About UUIDs

UUIDs are 128-bit values that are guaranteed to be unique across time and space without the need for a central registry. In the Service Discovery Protocol, UUIDs are used to represent services, types, or attributes. Bluetooth Profiles specify UUID values to identify the services that they describe; new Bluetooth applications will need to specify their own service UUID. A number of UUID (also called GUID) generators are available on the Web. One point of confusion that sometimes occurs with UUIDs involves the Bluetooth specification’s reference to 16-bit and 32-bit UUID values. All UUIDs are in fact 128-bit values, but the Bluetooth specification has reserved a range of UUID values. Since all values in this range have the same base address, the specification uses 16-bit and 32-bit values as a shorthand method to represent 128-bit values within the reserved range. The Bluetooth Library allows applications to specify 16- and 32-bit UUID values and handles the conversion and comparison between the different representations. It’s worth noting that only the Bluetooth specification is allowed to specify 16- and 32-bit UUID values—all other applications must use 128-bit UUID values.

As we noted earlier in the chapter, the Palm OS does not support a service-browsing usage model; applications are expected to know what kind of service they want to communicate with. Services in Bluetooth technology are identified by one or more UUID values. When a service advertises more than one service class UUID, the various UUIDs are assumed to have a hierarchical nature. If you are writing an application that will only talk to other instances of itself (a game, for example), a single service UUID for the application is probably sufficient.

Advertising a Basic Service Record for an RFCOMM or L2CAP Listener Socket

Let’s begin by looking at what we need to do in order to create and advertise a basic service record for an RFCOMM or L2CAP listener socket. We’ll assume that the application has already opened the Bluetooth Library and created a listener socket (the socket’s protocol is unimportant). A new application needs to declare a new service UUID, so we’ll use a UUID generation tool to generate one, in this case 7FD82E36-47E8-11D5-83CE-0030657C543C.

image

image

That’s all there is to it! The BtLibSdpServiceRecordSetAttributesForSocket() really does all the work for us, filling in the record with Service UUID, protocol listener information, and service name. There are, of course, a lot of other attributes that can be contained in a service record (see the BtLibSdpAttributeIDType), and we can add attributes to the record before advertising it by calling BtLibSdpServiceRecordSetAttribute(). Before closing the Bluetooth Library, the application should stop advertising the SDP record by calling BtLibSdpServiceRecordStopAdvertising() and then free the service record by calling BtLibSdpServiceRecordDestroy().

Retrieving Connection Information about L2CAP and RFCOMM Listeners on a Remote Device

Now let’s look at the other side of the picture: retrieving L2CAP or RFCOMM connection information from a remote device. In order to get SDP information from a remote device, we need to have established an ACL link to that device. Retrieving SDP information is an asynchronous operation, so we need to provide the Bluetooth Library with a callback with which it can return the SDP query results. The Bluetooth Library uses an SDP socket to specify the callback that should be used to return information. Although the same API calls are used to create SDP sockets as to create L2CAP and RFCOMM sockets, SDP sockets have very little in common with L2CAP or RFCOMM sockets; they can not be set up as listeners, or used to create connections. SDP sockets are really just a convenient way for the Bluetooth Library to manage information about SDP calls. A single SDP socket can handle one pending SDP request at a time, if your application does not need to have multiple simultaneous SDP queries pending, you can use a single SDP socket for all your SDP queries. The SDP socket should be closed before closing the Bluetooth Library.

Let’s look at an example function that gets the L2CAP PSM for a service advertised with the same UUID that we used in the preceding example (in this case, we are assuming that the listener socket being advertised was an L2CAP socket).

image

image

As you can see, retrieving remote RFCOMM and L2CAP listener information is pretty straightforward. If BtLibSdpGetPsmByUUID() or BtLibSdpGetServerChannelByUUID() are called with multiple items in the UUID list, the call will search for a service record that contains all of the service UUIDs in the list, although it will not insist that they appear in the same order in the record as they do in the list. If multiple records with the required UUIDs are found, the call will return the first one that it comes across.

These two cases should handle most applications’ SDP requirements. However, if your application needs to make more extensive use of SDP, the Bluetooth Library contains calls that allow you to make more specific searches, retrieve and set any attribute value defined in the Bluetooth Specification, and, for the very gung-ho, deal with SDP records as raw data.

Using Bluetooth Security on Palm OS

Palm OS provides full support for Bluetooth authentication and encryption. What level of Bluetooth security is required for a link is up to each individual application, which corresponds to Bluetooth Security Level 2. Applications can cause link authentication or encryption to occur by calling BtLibLinkSetState() with btLibLinkPref_Authenticated or btLibLinkPref_Encrypted, which will generate a btLibManagementEventAuthenticationComplete or btLibManagementEventEncryptionChange event, respectively. It is up to an application to decide what to do if an authentication or encryption request fails. The OS will handle any pairing producers (such as asking the user for a passkey) that are necessary for authentication to occur.

It is worth noting that Bluetooth security is link level security and does not take the place of application level security (except perhaps on single application devices, which Palm OS devices are not). Bluetooth authentication simply ensures that the user is connected to the device they think they are connected to—it does not ensure that the remote device is authorized to use your service. Bluetooth encryption ensures that the data can not be sniffed over the air. It uses 128-bit encryption keys, but if this is not sufficient for your application, you are free to add an extra layer of security to your application, as some writers of financial software have indicated they are likely to do.

Writing Persistent Bluetooth Services for Palm OS

In general, a service, or server daemon, is a program that has a persistent presence on a device, performing its function as needed, often in the background. Unlike a client application, which normally begins operation directly in response to a user action, services generally initiate action in response to a non-user event: in our case, a communication event. In a resource-rich environment, such as a PC, services often run continuously in their own process. While this approach has advantages, particularly in terms of response performance, it means that the resources needed by these services are always in use. Having just a few services on a Palm device can quickly eat away at the device’s limited resources.

image Developing & Deploying …

Services and Bluetooth-Aware Applications

As with the Palm OS IR stack, the Bluetooth stack is not available for services while it is in use by an application. Although Bluetooth technology is a multiplexing protocol, our services will follow the same model as IR. Service notifications are simply not generated when the Bluetooth Library has been opened by an application. If an application opens the stack while a service is in use, the OS will generate an “all shutdown” message for the services. The decision not to allow services and applications to use the stack at the same time was made because, despite Bluetooth’s multiplexing capability, there are complications that arise with remote device management when more then one application tries to use Bluetooth technology at the same time.

In order to avoid the problems associated with having truly persistent services, Palm, Inc. has had to rethink the services model in the Palm OS, allowing services to run on a more as-needed basis. Palm, Inc. took such an approach when implementing the OBEX service in the IR implementation. While the client side of OBEX starts up in response to a user action (the “beam” command), the service side of OBEX is brought up by the OS when an inbound IR connection is detected.

Using this mechanism, the IR implementation is able to avoid the overhead of the OBEX service and IR stack when they are not in use. This model has been highly successful, despite the tight timing requirements for responding to an IR connection request. The only hitch in IR service implementation is that, since the inbound connection triggers the OBEX service directly, third parties have been unable to develop new IR-based services. Since Palm, Inc. forged the way in the IR world, and thus set the usage direction, this has not been a major hindrance. However, given the diversity of usage expected for Bluetooth technology, support for multiple services has become an important part of providing a robust Bluetooth solution. The Bluetooth Services API attempts to take this logic a step farther and allow third parties to create Bluetooth applications with a persistent presence.

In order to efficiently support multiple persistent services at the same time, certain restrictions must be made. The principle restriction will be that only one service may be in-session at a time. In other words, although multiple services can be registered, once a given service begins a session, the other services become unavailable until it completes its session. When used in conjunction with some reasonable coding guidelines for the services, this restriction should allow the availability of multiple services without a significant impact on memory usage. The restriction has the added benefit of avoiding potential problems in which two services simultaneously attempt to display UI.

Creating a service is actually pretty straightforward. Essentially, services are simply pieces of code that register for and respond to Bluetooth service notification. Bluetooth service notifications are normal Service Manager notifications of type BtLibServiceNotifyType (btsv). The easiest way to create a service is by packaging the service in a normal application. When the application is launched in the “normal” manner (i.e., with sysAppLaunchCmdNormalLaunch), the application can display controls that allow the user to enable and disable the service, which can correspond to registering and unregistering for the Bluetooth service notification. It is best to register for the notification to be delivered be a launch command, rather than by a callback, since this avoids the need for locking the code resource (remember, the service notifications may be delivered while your application is not running).

The details pointer of a Bluetooth service notification is a pointer to a BtLibServiceNofityDetailType structure, which is defined as:

image

The event element of the BtLibServiceNofityDetailType contains the event information that will allow your service to start up and shut down correctly. The state diagram in Figure 8.4 shows the basic flow for a service.

image

Figure 8.4 Service States

In general, a service sits in an uninitialized state, waiting for a btLibNotifyServiceStartup notification. This notification is generated when the OS detects an inbound ACL link, and the Bluetooth Library is currently not in use by an application. The btLibNotifyServiceStartup notification is basically an instruction to that service to initialize itself. Initialization should include allocating essential globals, opening the Bluetooth Library with the BtLibServiceOpen() call, registering for an L2CAP or RFCOMM listener socket, and advertising that socket via SDP. Since services are running in the context of another application, it is important to make sure that the owner ID of the services’ globals is set to 0 (the system ID) using MemPtrSetOwner(). If the owner ID is not set, the memory will have the current application as its owner, and will be cleaned by the system if the current foreground application exits. It is also important that the service performs all its initialization during the notification callback or sub-launch, since the OS will allow the ACL connection to proceed once the notification is complete. During the startup phase, all of the registered services will be launched, which can place a strain on the system resources. In order to avoid overwhelming the system stack, services should initially allocate only the globals necessary to create and register a listener socket; additional memory can be allocated later when the service is actually in session. This helps avoid creating a big bump in memory usage during service initialization. During initialization, services should avoid displaying any UI, since multiple services may be running. Once the service is initialized and listening, several things can happen.

The service may receive a btLibNotfyServiceAllShutdown notification, which means that the service has timed out (the OS only allows the remote device to hang around for a limited amount of time without connecting to a service), the ACL link has been dropped (probably because the remote device didn’t find the service it wanted in the SDP database), the device power has been cycled, or the foreground application has opened the Bluetooth Library (applications take precedence over services). The reason for the notification is not really important, but you can check the err parameter of the notification details if you really want to know. Whatever the reason, however, the service’s response to the btLibNotfyServiceAllShutdown notification should be the same; the service should remove all of its advertised records, close its sockets, call BtLibServiceClose(), and free its allocated memory.

Alternatively, the service might receive a connection request on one of its listener’s sockets. If this happens, the service is considered “in session” and should call BtLibServiceInSession(). Calling BtLibServiceInSession() causes the btLibNotfyServiceNotInSessionShutdown notification to be sent out. This notification instructs the services that did not call BtLibServiceInSession() to shut down, just as if they had received a btLibNotfyServiceAllShutdown notification. It’s important to note that all services will receive the btLibNotfyServiceNotInSessionShutdown notification, so before calling BtLibServiceInSession() a service should set a value to remind itself that it is in session and should not respond to the btLibnotfyServiceNotInSessionShutdown notification. Once a service is in session, it can go ahead and allocate additional memory and display UI, if necessary. When a service’s session is complete, it should clean up and call BtLibServiceClose().

image Developing & Deploying …

Creating New Services

While it is tempting to create a new service to solve a problem, in general you should avoid creating a new service unless it is absolutely necessary. When possible, it is always better to use an existing service. This approach decreases complexity and resource usage and probably makes your code a good bit simpler. For example, an instant-messaging type application is more easily created by registering with the Exchange Manager than by creating a new service. If you want to be able to invite people nearby to join your game, this is probably also more easily done with an Exchange Manager interaction than by creating a whole new service. New services should be restricted to applications that are not easily handled by existing services, like creating a Bluetooth keyboard driver or other applications where using OBEX is simply not possible.

The Future of Palm OS Bluetooth Support

Bluetooth is, of course, a very young technology, and will certainly see a fair amount of evolution over the next few years. Similarly, Palm OS’s Bluetooth support will likely continue to evolve alongside the technology. In the near future, Bluetooth devices will address the issues of Layer 3 (Network level) support in the Bluetooth communication protocol stack. New specifications will define a network layer for communications between all the members of a piconet (not just master to slave), as well as inter-piconet communication issues. Roaming and scatternets will also be addressed. The eventual goal is the creation of true ad-hoc networks, self-configuring network groupings that grow and change as the user’s environment changes. For Bluetooth technology to succeed in the long run, it will also need to address issues like discovery time (currently far too slow) and maximum throughput (to align with 3G technologies).

As much as possible, these changes will be integrated seamlessly into the Palm OS Bluetooth Library. New editions of the library will expand the Palm OS’s Bluetooth capabilities, without compromising existing applications.

Summary

With version 4.0, Palm OS support has been put in place for Bluetooth wireless technology and line of sight limitations have become a thing of the past. Adding Bluetooth wireless technology to a Palm device frees users from the necessity of trying to physically line up two devices while they’re on the road. Bluetooth technology makes traditional Palm OS applications like Internet usage and “beaming” easier in mobile environments and introduces opportunities for applications using object push communication.

The Palm OS Bluetooth Support Package currently supports five Bluetooth profiles that are defined in the Bluetooth 1.1 Specification: the Generic Access Profile (GAP), the Serial Port Profile, the Dial-up Networking Profile, the LAN Access Profile, and the Object Push Profile. The values and language specified by the GAP are built into the Bluetooth Library and other Bluetooth components. GAP’s main goal is to create a friendly and consistent user experience, a goal that is also considered critical in the Palm OS. The other profiles describe a method for accomplishing a specific user goal.

The Bluetooth Support Package includes a new virtual serial driver (VDRV), which provides support for the Serial Port Profile. Using the Bluetooth VDRV allows existing serial-based applications to quickly be updated to take advantage of Bluetooth technology, and is an easy way to create new Bluetooth-enabled applications. The Bluetooth VDRV runs on top of the RFCOMM protocol layer (it does not implement RFCOMM itself—the RFCOMM protocol layer is implemented in the Bluetooth Library and can be accessed directly through the Bluetooth Library API).

One of the challenges of mapping Bluetooth technology underneath a traditional serial API is that traditional serial ports are single-channel and non-addressed in nature, while the Bluetooth system is a multiplexing, address-based protocol stack. Bluetooth technology needs to know which device and which service on that device it is going to talk to; it must also actively create the underlying baseband connection. Most Bluetooth radios are not capable of receiving inbound connections while trying to create outbound connections. For this reason, it is necessary for an application to indicate whether it wishes to initiate or accept the Asynchronous Connectionless Link (ACL) and RFCOMM connections. Palm OS refers to these roles as the client role and the server role, respectively. The application indicates its preference by setting the corresponding value for the role element in the RfVdOpenParams structure and filling the appropriate role-specific parameter structure inside the union.

When the VDRV is opened in the server configuration, it will register for an RFCOMM channel and advertise that channel via SDP. This creates a simple service record utilizing the Unique Universal Identifier (UUID) and name string defined in the RfVdOpenParamsServer. To open the VDRV in the client configuration, a more complex structure must be passed in to SrmExtOpen(). The remoteDevAddr parameter indicates the 48-bit Bluetooth device address of the remote device the VDRV should connect to. After creating an ACL connection to the remote device, the VDRV attempts to establish an RFCOMM connection. The application must indicate which RFCOMM channel the VDRV should use.

When a constant data flow is not important to your application (as in a turn-based game), the Bluetooth Exchange Library allows applications to send data blocks without concern for the underlying transport. Unlike sockets and virtual serial drivers, the Exchange Manager is a concept unique to Palm OS. Rather than referring to a specific transport, the new exgSendScheme send scheme of Exchange Manager in Palm OS 4.0 allows the user to pick which of the installed transports they wish to utilize. Once Bluetooth technology has been chosen as the transport, the Exchange Library will automatically perform a discovery in order to determine the address of the remote device it should connect to.

Palm OS provides full support for Bluetooth authentication and encryption. What level of Bluetooth security is required for a link is up to each individual application, which corresponds to Bluetooth Security Level 2. Bluetooth security is link level security and does not take the place of application level security. Bluetooth authentication simply ensures that the user is connected to the device they think they are connected to—it does not ensure the remote device is authorized to use your service.

Given the diversity of usage expected for Bluetooth technology, support for multiple services has become an important part of providing a robust Bluetooth solution. Having just a few services on a Palm device, however, can quickly eat away at the device’s limited resources. Palm OS’s new services model allows services to run on an as-needed basis, implementing the OBEX service in the IR implementation, the principle restriction being that only one service may be insession at a time. Services are simply pieces of code that register for and respond to Bluetooth service notifications. New services should be restricted to applications that are not easily handled by existing services, or applications where using OBEX is simply not possible.

This chapter provides a comprehensive introduction to developing Bluetooth-aware software for Palm OS devices. From information on where to get the tools you need to get started, to advanced techniques for creating Bluetooth services, this chapter walks developers through the new Bluetooth libraries in the Palm OS, and revisits existing communications APIs that have been enhanced with new Bluetooth-based capabilities. Developers learned tricks for using Bluetooth technology with the Serial and Exchange Manager APIs, as well as how to work directly with the Bluetooth Library.

Solutions Fast Track

What You Need to Get Started

image In order to begin using Bluetooth technology, you will need to have a Palm OS device with at least 4MB of memory that is running Palm OS version 4.0 or greater. Alternatively, you may wish to develop using the Palm OS Emulator, often the easiest and fastest way to create new application.

image In addition to a Palm 4.0 device, you will need to have the Bluetooth Support Package installed. The Bluetooth Support Package consists of several .prc files that work together. The latest version of the Bluetooth support .prc files, along with the Bluetooth header files and several pieces of example code, can be found in the Bluetooth area of the Palm Resource Pavilion at www.palmos.com/dev/tech/bluetooth.

image In addition, you will also want to have a copy of the Palm OS 4.0 SDK documentation, also available on the Palm, Inc. Web site.

Understanding Palm OS Profiles

image The Palm OS currently supports five Bluetooth profiles defined in the Bluetooth 1.1 Specification: the Generic Access Profile, the Serial Port Profile, the Dial-up Networking Profile, the LAN Access Profile, and the Object Push Profile.

image Generic Access Profile (GAP) is a general look at the overall process of carrying out a Bluetooth transaction without regard to the nature of that transaction, and is background for all the other profiles.

image The new virtual serial driver (VDRV) in the Bluetooth Support Package provides support for the Serial Port Profile.

image The Network Library (NetLib) supports the Data Terminal role of both the Dial-up Networking and LAN Access Profiles.

image The new Bluetooth Exchange Library implements the Object Push Profile, much in the same way that the Exchange Manager supports IR-based Object Exchange Protocol (OBEX) push.

image If none of the profiles cover what you are trying to do, don’t despair—the Palm OS also provides a robust API that allows you direct access to the SDP, RFCOMM, and Logical Link and Control Adaptation Protocol (L2CAP) layers of the Bluetooth stack, along with calls to allow you to manage the Bluetooth-specific concerns like discovery and piconet creation.

Updating Palm OS Applications Using the Bluetooth Virtual Serial Driver

image Using the Bluetooth Virtual Serial Driver allows existing serial-based applications to quickly be updated to take advantage of Bluetooth technology. The VDRV itself is “glue code” that allows Bluetooth functionality to be accessed though a more traditional API. Using the VDRV also gives you an advantage in writing multi-transport applications.

image Virtual Serial Drivers in the Palm OS are individual .prc files of type vdrv and are used throughout the new Serial Manager interface, much the same way as traditional physical serial ports are used.

image Since most Bluetooth radios are not capable of simultaneously listening for an inbound connection and trying to create an outbound connection, an instance of the Bluetooth VDRV also needs to know whether it is initiating or accepting the connection. Since a traditional serial API does not present a mechanism for passing all of this extra information, Palm OS 4.0 has added a new call, SrmExtOpen() (found in SerialMgr.h), to the new Serial Manager API.

image A VDRV client-only application might be useful when you know that the Palm device will always be playing a client-based role, and therefore never need to accept a connection.

image Applications and the VDRV use the Bluetooth Library in different modes. Because of this difference, the VDRV will not be able to open while the application is holding the Bluetooth stack open.

image Setting up the serial port as a server does not cause the driver to go out and create an ACL or RFCOMM connection, it merely sets up the port as a listener. Like a normal serial port, the VDRV will not alert the application when an incoming connection is established, the application will simply begin to receive data from the port.

Using Bluetooth Technology with Exchange Manager

image You can make an Exchange Manager-based application Bluetooth-aware with just a few lines of code. The Bluetooth Exchange Library registers itself for the exgSendScheme, so if you’ve already updated your application to take advantage of the exgSendScheme, it should work with Bluetooth technology as soon as you have installed the Bluetooth .prc files.

image The Exchange Library allows applications to send data blocks without having to worry too much about the underlying transport.

image The VDRV and Exchange Manager simplify using Bluetooth technology by encapsulating it inside familiar and easy to use interfaces, but the simplification also hides functionality and increases overhead.

Creating Bluetooth-Aware Palm OS Applications

image If your application requires direct access to Bluetooth protocol layers or management functions, then you will need to make use of the Bluetooth Library (BtLib) API.

image Even when using the Bluetooth Library directly, a Palm OS application cannot put the Palm device or the remote device into park, hold, or sniff modes. Also, while an application can request that a given link be authenticated or encrypted, for security reasons the application is not allowed to specify the authentication passkey or insist that a device be added to a list of trusted (or bonded) devices.

image The Bluetooth Library API is fairly large, and can generally be divided into six sections: Common Library calls, management calls, socket calls, SDP calls, services calls, and security calls.

image If your application is going to receive inbound connections, you should check to make sure the radio’s accessibility mode has been set to allow connection and (if desired) discovery. The accessible state of the device is determined by the user’s settings in the Bluetooth Preferences Panel.

image If you plan to have your application create outbound Bluetooth connections, you will probably want to perform a device discovery in order to allow the user to select the remote device(s) with which she wished to create a connection. The Bluetooth Library offers two similar calls that handle the entire discovery experience, including inquiry, name retrieval, and user selection, BtLibDiscoverSingleDevice() and BtLibDiscoverMuhipleDevices().

image Bluetooth piconets have a star formation: one master connected to up to seven active slaves. Once a successful call BtLibPiconetCreate() call has been made, up to seven simultaneous ACL connections can be established. Depending upon the usage model for your application, you may wish to have the piconet master actively create outbound connections, wait for inbound connections from remote devices, or both.

image The L2CAP and RFCOMM protocol layers are exposed in the Bluetooth API through a sockets-based interface. The ability to create and receive RFCOMM and L2CAP connections is entirely independent of the device’s role in a piconet.

image Applications or protocols that run on top of L2CAP must be able to handle the flow control themselves, while applications that run on top of RFCOMM can make use of its built-in flow control. Also, an RFCOMM listener is only capable of supporting one connection at a time, while a L2CAP listener can receive an unlimited number of connections. If your application involves functionality covered by a Bluetooth profile, you will not have to make a choice of which layer to use, as the profiles provide guidance on how to use the Bluetooth protocol stack.

image L2CAP identifies available listeners by a Protocol Service Multiplexor (PSM), which can be thought of as similar to an IP port. The RFCOMM protocol uses a simple enumeration called a Server ID to distinguish its listeners. You can let remote applications know which PSM and Server ID to connect to by advertising them with SDP.

image The Bluetooth Library offers an extensive set of APIs for working with SDP.

Writing Persistent Bluetooth Services for Palm OS

image The Palm OS allows services to run on an as-needed basis by implementing the OBEX service in the IR implementation. While the client side of OBEX starts up in response to a user action (the “beam” command), the service side of OBEX is brought up by the OS when an inbound IR connection is detected. Palm OS’s IR service implementation is able to avoid the overhead of the OBEX service and IR stack when they are not in use.

image Although multiple services can be registered, once a given service begins a session, the other services become unavailable until it completes its session.

image Services are simply pieces of code that register for and respond to Bluetooth service notifications, normal Service Manager notifications of type BtLibServiceNotifyType (btsv). When the application is launched in the normal manner, it displays controls that allow the user to enable and disable the service, which can correspond to registering and unregistering for the Bluetooth service notification.

The Future of Palm OS Bluetooth Support

image In the near future, Bluetooth technology will address the issues of Layer 3 (Network level) support in the Bluetooth communication protocol stack. New specifications will define a network layer for communications between all the members of a piconet (not just master to slave), as well as inter-piconet communication issues.

image Roaming and scatternets will also be addressed.

image The eventual goal is the creation of true ad-hoc networks, self-configuring network groupings that grow and change as the user’s environment changes.

image New editions of the Palm OS Bluetooth Library will expand the Palm OS’s Bluetooth capabilities without compromising existing applications.

Frequently Asked Questions

The following Frequently Asked Questions, answered by the authors of this book, are designed to both measure your understanding of the concepts presented in this chapter and to assist you with real-life implementation of these concepts. To have your questions about this chapter answered by the author, browse to www.syngress.com/solutions and click on the “Ask the Author” form.

Q: How does RFCOMM credit-based flow control work with pre-Bluetooth Specification v.1.1 devices, since credit-based flow control was not mandatory before the 1.1 release?

A: When the Bluetooth Library cannot negotiate RFCOMM credit-based flow control, it will try to use the aggregate flow control defined in the earlier versions of the specification to emulate credit-based flow control behavior. In most cases, this technique is highly successful, but due to a design bug in the pre-1.1 specification, it is possible for an application communicating with a pre-1.1 device to receive more data than it has advanced credit for.

Q: Am I allowed to make calls back into the Bluetooth Library from within a library callback? In other words, does the Library allow re-entry?

A: Yes, but you will not get any more callbacks until the initial callback is released. In other words, don’t block a callback waiting for another callback, because the second callback will not come until the first callback is allowed to return.

Q: I’ve noticed that the passkey request mechanism does not work properly sometimes when I am using the Telephony Manager over Bluetooth technology. What’s going on?

A: When use you the Telephony Manager in synchronous mode, it completely blocks the UI thread, preventing the Bluetooth Library from requesting a passkey when necessary, and causing authentication to fail. This can be avoided by using the Telephony Manager in asynchronous mode, especially during the open, when an authentication is most likely to occur.

Q: Where can I get help with problems or report bugs that I find?

A: There is a Palm OS developer’s mailing list set up for Bluetooth-specific concerns. You can find out more information on the Palm, Inc. Web site at www.palmos.com/dev/tech/support.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.67.166