12 Days of Bluetooth – #2 Discovery

Continuing the series, today’s post looks at how we discover and identify Bluetooth devices.

I’m Not a Number

Every Bluetooth device has a unique numerical address baked into the hardware – like a MAC address for a network adaptor. It is 48 bits long and is often displayed in hexadecimal form, usually with colon separators between each byte e.g. XX:XX:XX:XX:XX:XX. Prior to Bluetooth 4.0 devices would expose a fixed address which meant it was easy to track a device between multiple locations by logging the arrival and departure of a specific address.

With the introduction of Bluetooth Low Energy there is the possibility to expose random addresses which can either last between device boots or rotate on a timer. The device shares an Identity Resolving Key when paired with other devices which allows the other device to identify the device from its new random address.

Finally, a non-resolvable address is a random 46 bits and cannot be tracked. This type is quite rare.

What’s In a Name

Beyond the address each device also can expose a display name – this is really for the user’s benefit as it can be displayed during discovery and pairing and can either be baked into the device as a model name or customisable like “Keith’s iPhone”. The name can theoretically contain up to 248 bytes but considering you may be listing items on a small screen you have to think about a short and snappy way to identify the device. Sometimes where you might have a large number of the same device (think Barcode scanners in a warehouse) the display name may incorporate the last few digits of the address to help differentiate them.

Show Some Class

For Bluetooth Classic there are some additional hints as to the identity of the device. A Class of Device (CoD) contains a bitmask of a major and minor device class e.g. Computer / Desktop. There are classes defined for mainstream devices like phones, headsets etc as well as toys and medical devices. Another bitmask within this CoD defines a ServiceClass which hints and the kind of capabilities of the device while being separate from actual services supported. So if the device specifies Audio it gives us an idea of the kind of device but doesn’t specify which audio services it might support.

Service Please!

To actually determine whether we can use a device we have to know if it supports a specific service and for this we have Service Discovery Protocol (SDP). Each service has a unique UUID which is defined by the developer. For services which are adopted and managed by the Bluetooth SIG these have a 16-bit short identifier and a fixed “suffix” which is the same for all these services. For example Service Discovery Server can be referred to with the short id 0x1000 or the full UUID {00001000-0000-1000-8000-00805F9B34FB}. For the purposes of .NET the UUID is 128-bit so maps to the System.Guid type. Any custom UUID you create for a bespoke service must not overlap the official Bluetooth identifiers. If you want to implement one of the standard services you’ll need to follow the specifications so that the behaviour is consistent and other devices can use your service.

Each active service runs on a specific channel and part of the purpose of SDP is to lookup the channel to make a connection. You shouldn’t hard-code the channel number because this may change. SDP exposes all of the services exposed by a device and parameters for specific services. Most device APIs provide only a mechanism to open a connect to a classic service using the UUID and handle the channel lookup internally.

Coming Up

Next time we’ll take a deeper dive into a particular service and how it can be used.

By Peter Freeman Foot

Microsoft Windows Development MVP