You can think of a connection to a remote Bluetooth device as a vertical slice through the Bluetooth protocol stack (shown in Figure 2-1). Depending on precisely which protocols are involved, the connection is built of pieces from the appropriate layers. View these pieces as objects and you can see how a Bluetooth connection might be modeled.
This section describes the roles of the Bluetooth framework objects in Bluetooth connections. Bear in mind that many of these objects are automatically created by other objects. When a Bluetooth-enabled device is discovered, low-level drivers and higher-level managers create objects to represent it. Most applications, therefore, never need to create directly many of these objects to perform their functions.
Note: Remember that Bluetooth objects are also accessible from C and C++ applications using references of the form ObjectNameRef.
For more information on how to use these objects in a Bluetooth application, see “Developing Bluetooth Applications.”
The Root Object
Objects as Data Conduits
Objects in OBEX Connections
A Device-Discovery Object
Objects Related to Service Discovery
The IOBluetoothDevice object is the root object of every Bluetooth connection. You use this root object to create connections to the device, including the initial baseband connection. For example, you can open L2CAP and RFCOMM channels using methods of the IOBluetoothDevice object. You can also use its methods to perform SDP service searches.
The IOBluetoothDevice object is the only object in the Bluetooth stack that can be created without a concrete connection behind it. In other words, it can exist even before you create the baseband connection to the device. You might, for example, know a device’s address from an earlier device search. Using this device address, you can instantiate an IOBluetoothDevice object to represent the device. You can then access cached information about the device, such as device name and SDP attributes, while deferring the creation of the baseband connection until the user selects that device.
In Mac OS X version 10.2.4 and later, the IOBluetoothDevice object includes API to support device categorization based on user-selected criteria. The new methods and functions allow you “mark” a device as a recently accessed device or as a user-designated favorite. Your application can use these new device attributes to display to the user only those devices in a specific category. For more information on the use of these attributes, see “Filtering and Validation.”
The IOBluetoothL2CAPChannel object represents the data conduit between a local and a remote device and is a required component in every Bluetooth connection. This is because the L2CAP layer provides the facilities higher-layer protocols need to communicate across a Bluetooth link. An IOBluetoothL2CAPChannel object provides methods to read from and write to the channel. It also provides a setDelegate: method that allows a client to register itself as a client of the L2CAP channel.
An IOBluetoothL2CAPChannel object can also exist in the absence of a concrete channel. Unlike an IOBluetoothDevice object, however, it can be created only when an IOBluetoothDevice object opens an L2CAP channel. An IOBluetoothL2CAPChannel object can persist after the closure of its associated L2CAP channel, but it will return errors for any calls it receives.
The IOBluetoothRFCOMMChannel object represents an RFCOMM channel. Like the IOBluetoothL2CAPChannel object, the IOBluetoothRFCOMMChannel object provides API to open and close the channel and read from and write to the channel. In addition, an RFCOMMChannel object makes available methods to receive event notifications.
An OBEXSession object represents an OBEX connection to a remote device. Because it handles the commands typical of an OBEX session, the object itself is agnostic about the type of transport underlying the connection. The object’s usefulness lies in the methods it provides the object of a transport-specific subclass, such as the RFCOMM-based IOBluetoothOBEXSession class. Thus, your Bluetooth application will never create or access a raw OBEXSession object. Instead, it will get an OBEXSession subclass object, like an IOBluetoothOBEXSession object. With this object, it can override some of the OBEXSession class’s methods to manipulate the OBEX session.
The IOBluetoothOBEXSession object represents an OBEX session using a Bluetooth RFCOMM channel as the transport. If your application acts as an OBEX server or client over an RFCOMM channel, you first create an IOBluetoothOBEXSession object. Then, you use its methods (and some of its superclass’s) to open and close the transport connection and send and receive data.
Beginning in Mac OS X version 10.4, if your application needs to perform FTP or object push operations over OBEX, you can use a valid IOBluetoothOBEXSession object to create an OBEXFileTransferServices object. Note that the IOBluetoothOBEXSession does not have to be connected to a remote server to successfully create an OBEXFileTransferServices object. The connection can be made explicitly, using one of the OBEXFileTransferServices connection methods or implicitly, when you call any of its file-transfer methods.
Although most applications can perform discovery of in-range devices using the APIs in the Bluetooth UI framework, some must perform non-GUI inquiries. If your application is running in Mac OS X version 10.4 or later, you can use the IOBluetoothDeviceInquiry object to find devices in proximity to the computer and, optionally, retrieve name information from them.
It’s important to realize that the device inquiry process, although it is supported by the Bluetooth specification, can negatively affect other devices in the vicinity. For this reason, you are encouraged to use the GUI-based device discovery methods the Bluetooth UI framework provides. For more information on the problems that can arise from device inquiries and pages, see “Inquiring and Paging.”
If your application cannot use the GUI-based device discovery methods, you can use the methods of the IOBluetoothDeviceInquiry object. Before you use this object, however, it is essential that you are aware of both its built-in restrictions and the limits your application must observe when using it. For specific information on using the IOBluetoothDeviceInquiry object, see “Performing Device Inquiries.”
There are four objects that support SDP-related tasks:
IOBluetoothSDPServiceRecord
IOBluetoothSDPServiceAttribute
IOBluetoothSDPDataElement
IOBluetoothSDPUUID
The IOBluetoothSDPServiceRecord object represents a service offered by a Bluetooth device. A Bluetooth device can make several services available; each is described by an instance of IOBluetoothSDPServiceRecord in its SDP database. Each IOBluetoothSDPServiceRecord object contains two elements that, together, describe the service:
A reference to the device offering the service.
An NSDictionary of service attributes.
When an SDP client (a device that is looking for a particular service) performs an SDP query, it looks for a service record that contains one or more specific attributes.
The IOBluetoothSDPServiceAttribute object represents a single SDP service attribute. An IOBluetoothSDPServiceRecord object can contain several IOBluetoothSDPServiceAttribute objects in its instance of NSDictionary. Each IOBluetoothSDPServiceAttribute object contains an attribute ID (an unsigned 16-bit integer) and an instance of IOBluetoothSDPDataElement that describes one of the service’s attributes. The Bluetooth specification defines a large number of attributes a profile can use to describe a service, in addition to those the profile defines. Examples of attributes are the service’s name, list of supported Bluetooth profiles, and service ID.
An IOBluetoothSDPDataElement object represents a single SDP data element. To alert a device to what type and size of data it is about to receive in a data element, the IOBluetoothSDPDataElement object provides this information along with the data itself. An IOBluetoothSDPDataElement object contains:
A data element type descriptor
A data element size descriptor (calculated from the actual size of the data element)
The size of the data element
The data element value itself
The Bluetooth specification defines nine types of data elements, including unsigned integer, URL, and text string. Apple has mapped these types onto appropriate Foundation classes such as NSNumber and NSString. In addition, Apple has defined the class IOBluetoothSDPUUID to describe the UUID (universally unique ID) data element type. An IOBluetoothSDPUUID object can represent a UUID of any valid size (16, 32, or 128 bits) and contains methods to compare UUIDs and convert a smaller UUID to a larger one.
Because Mac OS X automatically creates IOBluetoothSDPDataElement objects for most client and server operations, your application should never need to explicitly create them. The exception to this is if you plan to define a new SDP service and make it available to the system. In this case, you will appreciate Apple’s decision to use Foundation classes to represent both the collection of service attributes and the types of data elements.
Instead of writing a lot of code to build up a service record, you can define your new service with a collection of key-value pairs in a property list (plist) file. You can then import this file into your application, using the IOBluetoothAddServiceDict function to create a new IOBluetoothSDPServiceRecord object. The IOBluetoothAddServiceDict function uses the properties in your plist file to populate the IOBluetoothSDPServiceRecord’s NSDictionary of service attributes. For more information on how to do this, see “Providing a New Service.”
Last updated: 2007-12-11