Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2004-502
$eventId
ID of event: wwdc2004
$eventContentId
ID of session without event part: 502
$eventShortId
Shortened ID of event: wwdc04
$year
Year of session: 2004
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC04 • Session 502

Developing Bluetooth Applications

Hardware • 50:02

Apple is leading the way in popularizing Bluetooth by making this wireless technology available on all Mac systems. This session will outline the variety of methods that applications can use to access Bluetooth devices. Topics will include how to detect when Bluetooth devices are present as well as best practices when using Bluetooth serial ports, headsets, cell phones, and HID devices.

Speakers: Eric Brown, Jason Giles

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good morning. Thanks for coming, everybody. I am Eric Brown, the Bluetooth Software Manager at Apple, and I'm here to talk to you a little bit about developing Bluetooth applications. So let's go ahead and start off talking about Bluetooth industry developments in the past year and kind of look to the future a little bit. In the past year, we've seen Bluetooth version 1.2 introduced by the Bluetooth SIG. A couple of notes about 1.2. It is fully backwards compatible with previous versions, so it should be fully interoperable with all of the Bluetooth hardware out there.

They've introduced a new function called Adaptive Frequency Hopping, or AFH for short. You might have seen it in some of the Apple literature. But what it does is it allows Bluetooth to avoid interfering with other 2.4 gigahertz wireless technologies. So the way that it works, it actually pays attention to where it notices interference and then just avoids communicating over those frequencies.

So technologies like airports, your -- and his team will be sharing the latest updates on the latest features and features that Also in Bluetooth 1.2 is a new Fast Connect capability which between two devices that are both 1.2 compliant, it allows greatly reduced connection times to speed up communicating between the two devices.

We've also added a new enhanced SCO capability which improves the voice quality when talking with headsets. In the past year, we've introduced Bluetooth firmware update 1.1 that adds support for the Bluetooth 1.2 spec, and we definitely encourage developers of new hardware to adhere to the 1.2 spec. We're definitely focused on that going forward.

Now there's a number of new hardware features coming in the next year. I can only talk about one of them, but we think it's going to be a pretty big, pretty important feature, and that's what the Bluetooth SIG is calling Enhanced Data Rate. They announced it earlier this month, and it actually improves transfer speed three times, so upwards of 2.1 megabits per second over the Bluetooth wireless link.

In addition, the Enhanced Data Rate actually allows for lower power consumption between devices, so that should improve battery life of your battery-powered devices. Unfortunately, because it is a new design and enhancement over the way that Bluetooth communicates over the air, it will require new hardware. So hopefully later this year we'll see this new Enhanced Data Rate ratified by the Bluetooth SIG, and we'll definitely be looking to see exactly where that goes. Okay.

Back in January, the Bluetooth SIG announced that at that point, other companies were selling more than 1 million Bluetooth devices each week. Well, as it turns out... Thank you for joining us. I'm Eric Brown, CEO of Apple. I'm here to talk about the latest technology that's been coming out in the world. It's a new technology that's finally getting out to the masses.

So now let's take a look at over the past year we've added a number of new features to Panther. We've added support for Bluetooth headsets, Bluetooth printing, and as I just mentioned, the 1.2 spec. I'm going to talk a little bit in detail about exactly what these features are and how they work.

In February, we released a Bluetooth 1.5 software update, which was later rolled into Mac OS X 10.3.3. The headset support is implemented pretty straightforward. Set up a headset with a Bluetooth setup assistant, and it shows up as any other audio device on the system. Any application that does audio input or audio output can take advantage of it.

As part of the headset profile and the Bluetooth spec, they define two different roles. There's the headset role and the gateway role. Headset role obviously applies to headset devices. Gateway applies to things like your phone and the Mac. In our case, we've only implemented the gateway portion of the profile.

So what that means is with the existing headset support, for example, your phone can't communicate with the Mac because both are gateway devices. As well, the headset support is actually integrated into a SCO audio driver. So it isn't really generic SCO support per se, but rather all integrated together.

At the same time that we introduced the 1.5 Bluetooth update, there was an iChat beta release of 2.1 that supported the Bluetooth headsets. Additionally, a couple things to note about the way that the SCO links work is that currently hardware limitations restrict us to one SCO link at a time.

So just as a little bit of background, the SCO link is the type of connection used between the headset and your Mac to communicate the audio data. However, again, since only one link is supported at a time, that restricts our ability to support things like multiple headsets at once or looking in the future, maybe using your Mac, talking to your phone and your headset at the same time.

An additional limitation is that speech recognition isn't supported for Bluetooth headsets. Unfortunately, it requires 22 kilohertz 16-bit audio, whereas the Bluetooth SCO audio support only provides for 8 kilohertz 16-bit audio. Unfortunately, it's just a limitation in the technology. Eric Brown, Jason Giles In the same software update, the Bluetooth 1.5 update, we added support for Bluetooth printing. Now, this was done through what's called HCRP, or the Hard Cable Replacement Profile. Again, in addition to being able to configure new printers with the Bluetooth Setup Assistant, Bluetooth support is integrated into the print panel and the printer setup utility.

Now the way that the support was added, it's just a straightforward CUPS backend that talks Bluetooth to the Bluetooth hardware. We definitely recommend that printer manufacturers that are looking to add Bluetooth support to their printers do so using HCRP. It should just be plug-and-play with, or rather unplug-and-play with the Bluetooth wireless technology with our support.

One thing to note is that in order to guarantee that a particular printer works properly over Bluetooth, the printer manufacturers must provide a Bluetooth-certified driver. So typically that just means testing it and providing the driver with the necessary information embedded in it saying that it is Bluetooth-certified, but that just avoids cases where printers might appear to work but don't.

Finally, as I mentioned, over the past year we added support for the Bluetooth 1.2 specification in the hardware. There was a Bluetooth firmware update version 1.1. That supports both Apple built-in modules as well as the external D-Link modules. Now, one thing to be aware of, there have been several different revisions of the D-Link modules. So it only supports the dbt120 with revision B2 or later. So you definitely want to make sure of that before trying the firmware update. The new firmware adds support for the 1.2 baseband specification.

So now let's move on to Tiger. It's what you're all here to see about. We've added a number of new APIs and developer applications that should hopefully be of interest to a lot of you. As far as APIs go, we've added a new device inquiry API in the form of IO Bluetooth Device Inquiry Object. We've added a new OBEX Transfer Services Object to provide some generic OBEX file transfer capabilities, as well as then a set of SCO audio services to enable third parties to use the SCO capabilities that we've built in.

That Bluetooth device inquiry object performs two basic services. It will perform the inquiries and notify you about devices that are in range and discoverable, as well as part of the process, it will fetch the names of the newly discovered devices. Now one big warning here, and this is the primary reason why this is the first time we've introduced a Bluetooth inquiry API, is that inquiries are definitely expensive.

They take bandwidth away from other Bluetooth connections, and they have the potential to degrade 802.11 performance as well as interfere with other 2.4 GHz wireless technologies. So it's really not something that's designed to run all of the time and just continuously look for other devices because it will have a negative impact on other things going on.

Now as a result of this, we've actually implemented throttling support so that inquiries will be throttled if they are tempted to be performed for too long a period of time. Now typically if you just need to perform one or two to present the user with a list of devices in the area, you won't be affected by the throttling. But if you do try to just perform inquiry over and over again, over time, the amount of time that you'll be able to perform an inquiry for will be decreased.

Now the Bluetooth device inquiry object is fully asynchronous as well with full C versions of the API available. There's a new header file that this API is now available in the TigerSeed. There's a new header file, bluetootdeviceinquiry.h, that has the full API. So basically what the device inquiry gives you is more or less the full functionality of the Bluetooth device selector minus the UI, of course.

So you should be able to do everything that the Bluetooth device selector does but embed it in your own code. Now, we still highly recommend if you need to allow the user to select a device or to provide the user with a list of devices in range that you actually use the built-in Bluetooth device selector because it really provides a consistent user experience across multiple applications.

Let's take a quick look at the API itself. It's a class method to create a new inquiry object. Now, a delegate is required. Because the API is fully asynchronous, the delegate is needed to provide the callbacks of when the different phases of the inquiry are taking place. You can control the length of the inquiry through set inquiry length.

You can control whether the inquiry process will update the device names or not. Now, if you're presenting them the list to the users, you will very likely want the inquiry object to fetch the names for you. There are some restrictions depending on what hardware you're running on, on exactly when the names can be fetched compared to when the inquiry can run. So we've actually embedded all of that logic, knowing about what the hardware capabilities are, into this object. So if you use the capability, or if you use the name update facility, you'll automatically take advantage of all that knowledge built in.

Then you also have the expected start and stop routines to start and stop the inquiry. Now the inquiry will stop on its own when the length of time that it's supposed to be running has hit. Additionally, once you call start, the inquiry might not actually start immediately. If the throttling code has been engaged, it may take some amount of time before the inquiry will actually begin.

Because there's a delegate and the API is asynchronous, there are a number of delegate methods that get called during various stages of the inquiry. So you get notified when the inquiry is started. That way you can know the amount of time between you call start and it actually starts.

Now if it can start right away, you might get the inquiry started routine called immediately. There's a notification when a new device gets found, there's a notification when the name update process begins, notification when each name is actually fetched, and then a notification once the inquiry is completed.

So let's go ahead and take a look at kind of a sample timeline and what's going to go on when using the device inquiry object. So your application is going to create a new one. It's going to go ahead and call start to start the inquiry. Maybe immediately, maybe sometime in the future, you'll get the device inquiry started notification.

At that point, the discovery process is ongoing. So for each device found, you get a result, device inquiry, device found, that tells you the device address, the class of device so you know, are you talking with a keyboard, are you talking with a phone, etc. But at that point, you won't have the name unless the system has previously fetched it and cached the name. Eric Brown, Jason Giles Once the actual discovery process completes, it will begin the name discovery. So at that point you get update device names, tells you how many devices are left to have their names fetched.

And then during the name discovery process, you go ahead and get notified each time a device name has been fetched. So that way, one by one, you'll know exactly what the names are for each device that have been discovered. And then finally, you get the inquiry complete when that's finished.

Another new API we've added in Tiger is a new OBEX file transfer services. That's the name of an Objective-C object in, again, in Tiger, in the Tiger seed, new header file for it. What it does is it provides a simplified API on top of OBEX for kind of the generic object exchange functionality. Basically provides a raw implementation of the object push profile and the file transfer profile.

provides all the basic low-level file manipulation primitives you'd expect: put and get, change directories, folder listings, manipulate the remote file system by adding and removing folders and files. As with the device inquiry object, the file transfer services object is fully asynchronous with C versions available. So basically with this new API, outside of the UI, you get the full functionality of the Bluetooth file exchange, including the object push and file transfer services.

So let's just take a quick run through the API. I'm not going to spend a whole lot of time on it. It's a little more detailed than the device inquiry, but you have the basic methods for creating a new object with an OBEX session. Again, as with the inquiry object, it takes a delegate for all the callbacks. There's methods for accessing the current stake and the current path, notifying whether the connection is busy or not, whether it's connected.

API for connecting/disconnecting, depending on what type of service you're using, connect to FTP or connect to object push services, as well as then the disconnect operation. API for sending and receiving files. as well as then the remote manipulation, adding, removing folders and files, changing directories, as well as then the capability to abort an operation that's in progress and retrieve the current folder listings.

Delegate methods, again, there's quite a number of them. There's basically a completion for each action that can be performed. So, for example, when you tell the API to connect to a service, it's going to go ahead and call the connection complete method when it's done. Pretty much the same for all of these, although there are a couple of things to note here. There are two APIs for actually transferring files for sending and receiving.

Each one of those contains a transfer progress method as delegate method as well as a transfer complete method. Now, the progress includes a number of useful bits of information. In addition to just the amount of data that's been transferred and how much is left, it includes the elapsed time as well as estimated time remaining and instantaneous transfer rate calculations. So, that should actually make it pretty easy to wire that information into your... UI.

So let's just take a quick run through a sample object push operation. You're going to create the new OBEX File Transfer Services object, and then call, in this case, connect to object push service. That's going to go ahead, send a message to the remote device to connect up. Once that completes, you get the connection complete message. If there was an error, you'll be notified at that point.

Once the connection is complete, it's okay to perform any of the operations. In this case, since we're only using Object Push, Send File is the only facility that we have available to us. So we're going to go ahead and call Send File. Then as the file transfers, you'll continuously, at regular intervals, get the Send File progress with the transfer progress so you can know exactly how far the transfer is completed.

Once that's finished, you go ahead and get a send file complete with the error code as well. So if an error occurred during the time, this is the notification that you'll get. Once the transfer is complete, you actually have the option of you can perform another operation or go ahead and disconnect. Once the disconnection is finished, you'll get disconnection complete method.

So now let's move on to the new Skull Audio API that we've added in Tiger. Now, in Panther, we really had limited SCO support. We did have built-in support for Bluetooth headsets, but there was really no API to customize the SCO behavior or to tap into the SCO functionality. Additionally, core audio was the only means to access that data, so that was the only communication that any external developer had with a Sko, with a headset or other Sko audio device.

In Tiger now, we're adding this new SCO Audio API that really provides full control over the SCO link. So you control exactly when the SCO link is created. It provides an audio driver and the ability to configure exactly how that driver appears. So you can say exactly how many audio controls are created.

Does it have a volume control? Does it have a mute control? What is the volume range, et cetera? The new API supports both incoming and outgoing connections, so again, which you have control over, so depending on exactly what type of device you're talking to, what profile you're using, you can implement it exactly the way that's intended. As part of the API, a SCO Audio driver is created, but instead of having, as with Panther, all of the support for communicating with headsets built in, it just provides audio I.O. services.

As far as the API goes, we've actually split it here. You have the iBluetooth framework for all the standard Bluetooth services. So, for example, in the case of the headset profile, it needs to use an RFCOM channel to communicate with the headset to indicate things like ring, button press, volume changes, etc. So, again, the Bluetooth framework is where you're going to communicate over any of the standard Bluetooth services.

Then Core Audio is the API to be used both for audio I.O. as well as to communicate with the driver in terms of being notified about applications on the system wanting to create an audio connection and being able to control exactly when those Go links get created and being informed of any audio-related errors.

The API itself on the surface appears pretty simple. There's just two functions, although it does get a bit more complex than that. There's the basic two functions. I have Bluetooth Add SCO Audio Device. I have Bluetooth Remove SCO Audio Device. The Add function basically will create a SCO Audio driver for your device.

As part of the API, a configuration dictionary parameter is provided, and that's really what provides the core of the customizable features in the audio API. So it's that configuration dictionary that allows you to specify exactly what audio controls are created and how they appear in the system, specify behavior on new connections, among others.

Now the caller of this API is responsible basically to create any new Bluetooth services. So for example, if the audio support you're adding allows the device to connect back up to the host, you'll very likely need to add a Bluetooth SDP service record that matches the service that you're providing so the device knows exactly how to connect up and how to talk to you.

Additionally, any non-SCO data, again, like L2CAP, RFCOM, needs to be handled by the client in this case. The system will not do it for you. The iBluetooth Remove SCO Audio Device API simply will remove that driver from the system. So the add functionality adds it, remove removes it. It's basically up to the client to do everything else.

In addition to those new APIs, we've created a couple of new applications that should help you develop applications for Bluetooth applications for Mac OS X. We've added a new packet logger tool and Bluetooth Explorer utility. PacketLogger is pretty much a completely rebuilt version of the previous PacketCoder 2 application with a lot of new functionality.

It's actually really nice. It helps a lot when developing applications. So it supports multiple PacketLog windows. The previous application had only a single window where you could either view the current log of the system or one loaded in file, where the new one allows as many open documents as you want.

We've added improved decoding and searching support so that what you see in the packet log is a little bit more verbose. It provides a little more of the information that you're likely to need. And then the searching capabilities allows you to quickly type in a particular block of data that you're looking for, whether textually or using hex.

There's also a couple of new data views. In addition to the decoded view, like you're used to seeing, there's a raw view that provides just the basic raw data. If that's the way that you want to look at it, if that's what you're used to seeing, you can go ahead and see exactly what's being sent and received over the Bluetooth link.

And it also provides a new flow data view, which kind of provides a summary by connection of exactly what packets are on the system. So basically, all of the connection and disconnection events are summarized, and so you can choose what connection you're interested in, what L2CAP channel, what RFCOM channel, and it will just then restrict the packets that it lists to those associated with that channel.

We've added support for data markers, so if there are certain parts of the log that you want to mark and come back to later, you can do that. We provided some additional auto backup support. Previously in the Packet Decoder 2 application, it would automatically, assuming you choose to do so, it will automatically save the current packet log to disk.

But every time you started and stopped the decoder, it would overwrite the previous log, so it's real easy to accidentally lose an important log. So this new Packet Logger application will actually support multiple backup files and won't overwrite the previous one. Instead, it will create a new one.

And then finally, this hopefully would be helpful for a lot of people, is that there's no SDK required in order to run the packet logger tool. Before, you had to install an SDK with a custom build of the Bluetooth family text, where now it's just built in. The logger tool itself will just require authentication. Then once you've authenticated, you can go ahead and capture Bluetooth data on any system.

The other application we've added is a new Bluetooth Explorer utility, which provides kind of a snapshot of the Bluetooth stack and the Bluetooth hardware. provides active inquiry information, so if there's an ongoing inquiry, it will show exactly what devices are in the area and the relevant information about them.

It provides detailed information about the hardware on your system, including all of the Bluetooth features that it supports, the device address, specific versions of the various Bluetooth technologies that it implements, etc. We've added new support for the device cache being managed. So you can actually view the current cache devices on the system as well as delete them.

There's also a panel that allows you to switch between multiple controllers. So if you have a built-in Bluetooth module and say you have an external one that you want to test out to make sure it works with your hardware, for example, you can simply insert that, go to the Bluetooth controller setup, and switch to that module and the system will just automatically switch over to using it. Then finally, there's Connection Monitor functionality, which basically is the old Bluetooth monitor application just integrated into the new Bluetooth Explorer. So now I'd like to invite one of the Bluetooth software engineers, Jason Giles, up here to go ahead and demo some of the new applications for you.

Thanks, Eric. So let's check out these applications that Eric just talked about. Can I get demo one? Okay, so the first one I'd like to show is the Bluetooth Explorer application. This application, as Eric mentioned, is the reworked Bluetooth monitor, and we've added a whole bunch of new features that we think will help make your developing lives easier. So, the first thing I'd like to show is the local device information panel.

And as you can see here, you get a snapshot of the hardware that is currently in use in the Bluetooth system. And as you can see, it has the general hardware information, including the device address, the manufacturer of the part, HCI and LMP version information, as well as the Bluetooth specification hardware features, such as three-slot packets, etc. So, as you can see, the ones in black are the ones that are supported on this particular dongle.

The ones in gray are not supported. If we had a different dongle, we would probably see different attributes highlighted. We also have the version. We have the version easily accessible for you. So, if you're going to send us a bug report, we highly recommend that you send us the stack version, because that really helps us determine what exactly is going on in the system.

This panel, or this tab, is the Class of Device tab. This is a representation of how other devices sees your computer. So, other devices can see what services it has or what device class it shows. So, the system automatically determines what major and minor device class and services are on your system.

But if you had a need to spoof a different kind of device on a computer, like let's say you wanted this computer to be a cellular phone, you could just select phone and choose what type of phone for the minor class. Now, if you set that class of device on the system, all other devices, your phones, other computers, would see this computer as a phone. So, that's an interesting thing that might be useful. So, that's something that might be useful to you if you had that need.

Finally, there's a Services tab that shows you the installed services on the Bluetooth system. So, on this system, we have the Bluetooth PDA sync service as well as the OBEX object push service. If you're installing your own service on the system, it would show up in this panel. If it does not show up here, it's probably not installed correctly, and the system, the Bluetooth system is not seeing that service, code and check for errors.

So the next thing we've added is the HCI controller selector. And this allows you to actually have multiple Bluetooth hardware dongles installed on your machine. And you could use different ones if you wanted to test your software out with different vendors' hardware. So on this particular system, I have set up a Broadcom dongle as well as a CSR dongle. As you can see over here, we're currently using the Broadcom dongle.

If we switch to the CSR one and make that active, this is an administration operation, so it requests or asks for your password. Type that in. Go over to refresh. And as you can see now, we're using the CSR part to do Bluetooth activity. This is not persistent. If you restart your machine, it will reset itself to the default HCI controller, and you will have to go back here to select a different one.

So there's other things that the Bluetooth Explorer offers. We invite you to check it out on the tiger seed. So the next one I'd like to show is the packet logger. And you'll notice on launch the first thing it asks you is to authenticate. And that is because it doesn't require the SDK anymore, but it does require administration access to get to the data. So here we have a live packet decoder window. And if we go over to the preferences file, system preferences panel, it generates some Bluetooth traffic there you see. And so here we have 13 packets. And there we go. No SDK build and we've received Bluetooth packets.

So the next thing I'd like to show you is a file that I've recorded doing an FTP transfer from a mobile phone to our computer. And as Eric pointed out, there's three views to the packet logger window now. There's the Dakota view, the Flow view, and the Raw view.

So if we were interested in seeing, let's say, this SDP packet here, as it relates to other pieces of the system, we could go over to the Flow view and see that here's the SDP information packets that have been sent and received. This is the one that I selected. And here it shows its relation to the L2CAP layer. So these packets were generated based on this connection response and this connection in L2CAP. And then we can keep going back further and see that all of this L2CAP traffic was generated based on this HCI connection.

This is great when you have multiple connections to different devices in the same packet or even the same device. For example, in this case, we have on this device, we've requested SDP information, but we've also and a different connection done RF-COM traffic. And then you can even go into this RF-COM connection, for example, on channel 7 and note that these are all the packets that were transferred over this channel. And then finally we have the raw view. So if I was interested in this packet here and seeing what the raw bytes were sent over received to and from the Bluetooth hardware, I can switch to the raw view and see the actual bytes that were sent.

So now I'd like to demonstrate the markers capability that we've added. Clicking the M button brings up the markers panel. And as you can see here, I've already established two markers in this file. The first FTP folder listing, we can go to that.

[Transcript missing]

And if we go back to our marker, we can see that the packet that we were showing before is now decoded in OBEX. And if we twist that down, we can see that we see the type header and the connection ID header.

The next marker I have set is the first get JPEG command that we send to actually receive a file, to request a file from the FTP server that we've connected to. So if, for example, you received a connection refused or request refused or bad request error, you could actually twist this down and see, okay, here's my request that I actually sent out. Here's the picture 3 file that we requested and the connection ID.

If something was wrong, we could see that, oh, you know, we didn't send the name properly or something like that. We can also see that the data is embedded throughout the whole Bluetooth stack. So, for example, this is an OBEX packet. Now we can see that the RFCOM packet is right here. And we can look at the details of that RFCOM packet. And then from there, we can go into the L2CAP. All the way down to the ACL layer. So you can see all of the data top to bottom really quickly.

Another thing that we've added is a find panel. So if you're interested in a particular command that you've sent, like let's say an OBEX command disconnect because you suspect there's something wrong with the disconnect. This will bring up all the packets that are related or that have the search keywords. You can do operator keyword characters as well. If you put in an or character or an and character, you can actually do and/or searches. So if we click on this, we are quickly taken to the appropriate packet.

If we wanted to add a marker to that particular packet for someone else to see, This is a description field. We can put in a description. This is the... Eric Brown, Jason Giles: We're going to add that marker. And now once we save the changes into our document, you can go quickly back, refer quickly back to that spot at any time.

Last thing I'd like to show you is the Inspector Panel. This is a very simple way For you to look at the top-down data structure as well.

[Transcript missing]

Let's go ahead and move on to the next topic. I want to talk about asynchronous application design. It's kind of a mouthful, and it--

[Transcript missing]

The asynchronous API basics. So all asynchronous operations use callbacks. Typically, the callback will be made when the operation completes. Seems pretty obvious, but it isn't always, and the documentation isn't always totally clear about that.

Additionally, the callback that gets made as a result of a particular operation may actually be called after that operation returns. That's what actually causes a lot of the trouble when developing an application using these type of APIs. A lot of times you want to execute a number of operations synchronously that typically you just go execute them one right after another on the same block of code. Unfortunately, now that the first operation might not complete until after. The initial function returns, you now have to go and move that second call into the callback for the first and then maybe move the third call into the callback from the second.

All of the Bluetooth operations have asynchronous versions. Additionally, some of our APIs, especially just a couple of new ones that we saw today, the device inquiry and OBEX file transfer services, are only asynchronous. So you're pretty much forced to actually develop your application that way. An additional note here is that the OWL Bluetooth framework is not thread safe, so you can't just simply fire off another thread to go ahead and perform the asynchronous operation, do 1, 2, 3, etc. because all of the Bluetooth calls must be made from the same thread.

So why do we even create these asynchronous APIs and why should you use them? Well, primarily, Bluetooth itself is asynchronous. We send a command, then we have to wait for the device to respond, both the local hardware and the remote device. So our implementation really is based on that design. That's how it works.

Additionally, and many times, it can be less complex than using multiple threads. There's no locking to worry about. You don't have to deal with multi-thread issues like that. And it's really similar to the Cocoa Delegate model. So a lot of you that have done Cocoa work, it should be very familiar.

So there's definitely a number of pros and cons associated with it. On the pro side, the operations don't block. So your UI doesn't lock up. It provides for a much better user experience when doing those things. The user doesn't click a button and then wait, wait, wait, watching the cursor spin as some long-running operation takes place.

It also provides the developer with the ability to implement UI that allows a user to cancel the operations. So it's a lot more user-friendly in that way. Unfortunately, while asynchronous design can make it simpler in that you don't have the multiple thread issues, it also can be more complicated because the sequential operations that you might want to do can't be all implemented at once.

So let's take a look at basically some sample asynchronous behavior, kind of what goes on within the Bluetooth stack. So what first happens is based on the first call into the Bluetooth framework, the Bluetooth framework itself will create a number of run-loop event sources to handle the asynchronous callbacks from the various parts of the system, the kernel and the daemon, the BlueD process. So go ahead, it'll create those run-loop event sources.

Now, one thing to note here is that the run loop for the thread that first calls into the stack is the run loop that will be used for all of the asynchronous callbacks. So that thread has to have a run loop run on it after the Bluetooth calls are made. And from that point on is the only thread that you can make calls into the Bluetooth stack.

So none of the other threads can actually make the calls. Now, you might try it and it might work, but it's not guaranteed to work. There's no locking in there. It's very easy for multiple threads to step on one another and have really unpredictable results. An additional note is that if you're performing UI operations through the Bluetooth UI framework, that only the main thread can be used to make the Bluetooth calls. Now that's because typically all the UI operations have to occur on the main thread.

So let's take a look a little more detail about how a Bluetooth connection operation will work within this model. So the first thing that happens is your application is just going to call Bluetooth device open connection. It's going to pass in itself the callback. So that's going to go into the Bluetooth framework.

At that point, the framework is going to turn around and make a call into the kernel to go ahead and perform that connection operation. So it makes a call down into the kernel. Now we're still on the original thread, although it's executing in the kernel. The kernel is going to go ahead and take a look at the callback information provided by your client. It's going to go ahead and then store that away so that when the operation actually completes, it knows who made the call and who needs to get notified.

At that point, depending on the state of the system, the kernel may actually send the HCI command to create the connection, or it might queue it up for later, depending on if the hardware is busy or not. So in this case, we'll go see it sends the command.

And then at that point, this particular operation is done. The client thread's going to return. Your run loop's going to be free to run, process user events, et cetera. So the system is just now waiting for this operation to complete. If you have a UI application, the user is free to go ahead and perform other tasks.

Once the operation is complete, we'll actually see the command complete event coming in from the device. This gets run. The callback into the kernel is done on a kernel thread. So I'll see the hardware notify the kernel with the command complete event. At that point, the kernel says, "Okay, let me try and find to see if there was an asynchronous call that did the original connection." So it's going to go ahead, look up the callback information. In this case, it finds information about our client application so it knows exactly which application made the call and which needs the callback. At that point, the kernel will then just send a message to the framework in the application using that RunLoop event source that was created.

At this point, the kernel is done. The kernel thread is finished and is off doing other things. The application thread now, the RunLoop event source will go ahead and receive the kernel message. The framework will extract the callback information and then just call the original caller, notifying it that the command has completed.

Now, that seems pretty simple, but there are definitely a number of design considerations that I need to keep in mind. So, for example, when you have multiple operations to perform, your application really is to keep track of. It may do multiple things at once. It needs to know exactly what's outstanding, be able to deal with errors that come up at any time.

If there are future operations that it needs to perform once certain events complete, it needs to keep track of exactly what it needs to do next. So, depending on exactly what you're doing, you may need to implement some kind of queuing mechanism or state machine to keep track of what's going on and what should be done next. That's really where the complexity comes in.

An additional point to note is that your UI will be active while the operation is pending. So the user is free to go ahead and perform any operation that's available to them. As a result, it's really recommended that you disable any controls that shouldn't be accessed while this particular operation is outstanding.

We also really recommend that you provide some kind of status and potentially a progress notification that a particular operation is going on as well. and then as much as possible, providing UI to be able to cancel an operation that may be long running really is a lot more friendly to the end user.

And then lastly, really pay attention to the error codes. They are definitely there for a reason. All of the Bluetooth API returns error codes. All of the callbacks include error codes. Typically, if an error is returned from an API call itself, it means that the operation, that the callback itself will not be called, that the operation failed during the initial phase.

If you get an error in the callback, again, it usually means that that operation failed to complete. So if you had the next operation that depended on the first one completing successfully, you don't want to call that because it won't succeed either. Now, there may be some exceptions to those. There are a couple of error codes that actually indicate success, but the system may be in a state other than what was expected. In those cases, those codes will be documented.

So now we've got a number of avenues that you can go to for more information. Our IO Technology Evangelist is Craig Keithley, and he is pretty much the main contact for any developer relations issues as well as going through just the standard developer support. We've also provided a Bluetooth developer mailing list that you can get to. I believe any ADC member is free to join the developer mail list. Is that right, Craig? Okay, well, anybody can join the mailing list. And it's kind of the traffic comes and goes, but feel free to join. Look at the traffic going on.

See what kind of questions people are asking. Feel free to ask your own. The Bluetooth engineers at Apple, we do monitor that list regularly. We don't always have, we can't guarantee that we're going to be able to respond to every question, but we do try to pay attention and answer where we can. I've also got sample code and documentation written as well. So there's working with Bluetooth devices documentation, Bluetooth device access, and Bluetooth user interface that are all in the installed Tiger documentation.