Bluetooth Service Discovery Protocol – bluez programming course

Bluetooth Service Discovery Protocol (SDP)
How Bluetooth devices find and talk to each other’s services
9
Service Attributes
7
SDP Transactions
2
Discovery Methods

What is SDP?

When two Bluetooth devices connect, how does one know what services the other offers? That’s exactly what SDP (Service Discovery Protocol) handles. Think of SDP like a Yellow Pages directory built right into your Bluetooth device. One device acts as the server (it lists its services), and the other acts as the client (it looks up what’s available).

For example, when your phone connects to a Bluetooth headset, your phone uses SDP to ask: “Do you support A2DP audio streaming?” The headset replies with a yes and the technical details needed to start streaming.

Key Terms to Know

SDP Client SDP Server Service Record UUID PDU Service Handle BlueZ Stack A2DP AVDTP L2CAP RFCOMM Browse vs Search

📋 Section 1 — Service Attributes

Every service on a Bluetooth device is stored as a service record. A service record is a collection of attributes that describe the service — its name, what protocol it uses, who made it, and so on.

Two attributes are mandatory in every service record. All others are optional.

Mandatory Attributes

Attribute Name What It Does
ServiceRecordHandle A unique ID number for this service record on the server. Clients use this handle to reference a specific service.
ServiceClassIDList A list of UUIDs telling you what type of service this is. Example: “Headset Audio Gateway” or “Dial Up Networking”.

Optional Attributes

Attribute Name What It Does
ServiceRecordState A version counter. Whenever the service record is changed (any attribute added, removed, or updated), this value changes. Clients can check this to know if they need to re-fetch the record.
ServiceID A UUID that uniquely identifies this specific instance of a service (not just the type).
ProtocolDescriptorList Tells the client which protocol stack to use to actually connect to this service. Example: L2CAP → RFCOMM.
BluetoothProfileDescriptorList Lists the Bluetooth profiles this service follows, along with their version numbers.
ServiceName A human-readable name of the service. Example: “Dialup Networking”.
ServiceDescription A brief description of what the service does.
ProviderName The name of the person or organization that is offering this service.

🔍 Section 2 — Two Ways to Discover Services

The SDP client has two ways to get service information from the server:

🔎 Search for Services

The client already knows what it is looking for. It builds a service search pattern — a list of UUIDs for the service type it wants. This pattern is sent to the server. The server checks each of its service records to see if all the UUIDs in the pattern are present. If a match is found, the server sends back the handle of that service record.

Use case: Your phone knows it needs an A2DP headset, so it directly searches for the A2DP UUID.

📂 Browse for Services

The client does not know what services the server has. Instead of searching for something specific, the client requests a full list of all available services. The server responds with all its service records.

Use case: You’re connecting to a new unknown device and want to see everything it can do.

BlueZ sdptool — Browsing SDP Services on a Smartphone (Linux)
# Command to browse all SDP services on a remote device
$ sdptool browse 68:ED:43:25:0E:99
Browsing 68:ED:43:25:0E:99 …
┌─── Service Record 1 ───────────────────────────────────┐
│ Service Name: Dialup Networking │
│ Service RecHandle: 0x10000 │
│ Service Class IDs: │
│ “Dialup Networking” (0x1103) │
│ “Generic Networking” (0x1201) │
│ Protocol Stack: │
│ L2CAP (0x0100) │
│ RFCOMM (0x0003) → Channel: 1 │
│ Profile: Dialup Networking v1.0 │
└─────────────────────────────────────────────────────────┘
┌─── Service Record 2 ───────────────────────────────────┐
│ Service Name: Voice Gateway │
│ Service RecHandle: 0x10001 │
│ Service Class IDs: │
│ “Headset Audio Gateway” (0x1112) │
│ “Generic Audio” (0x1203) │
│ Protocol Stack: │
│ L2CAP (0x0100) │
│ RFCOMM (0x0003) → Channel: 2 │
│ Profile: Headset v1.0 │
└─────────────────────────────────────────────────────────┘
┌─── Service Record 3 ───────────────────────────────────┐
│ Service Name: Hands-free │
│ Service RecHandle: 0x10002 │
│ Service Class IDs: │
│ “Handsfree Audio Gateway” (0x111f) │
│ “Generic Audio” (0x1203) │
│ Protocol Stack: │
│ L2CAP (0x0100) │
│ RFCOMM (0x0003) → Channel: 3 │
│ Profile: Handsfree v1.05 │
└─────────────────────────────────────────────────────────┘

Notice how each service record returned by sdptool browse contains the service name, handle, what class it belongs to, which protocols are used, and which profile it follows — exactly the attributes from Table 4.4 in action.

🔄 Section 3 — SDP Transactions (PDUs)

SDP uses a request/response model. The client sends one request and waits for the response before sending the next. Only one request can be in-flight at a time. This keeps things simple for both the client and the server.

Each request and response is called a PDU (Protocol Data Unit). Here are all the SDP transactions:

PDU ID Transaction Name Who Sends It What It Does
0x00 Reserved Reserved for future use.
0x01 SDP_ErrorResponse Server Sent when the server cannot process the request. For example, if the client sent wrong parameters.
0x02 SDP_ServiceSearchRequest Client Client sends a list of UUIDs to search for matching service records on the server.
0x03 SDP_ServiceSearchResponse Server Server replies with the handles of all matching service records.
0x04 SDP_ServiceAttributeRequest Client Client already has a service record handle (from step 0x02/0x03). Now it asks for specific attributes from that record.
0x05 SDP_ServiceAttributeResponse Server Server replies with the (Attribute ID, Attribute Value) pairs the client requested.
0x06 SDP_ServiceSearchAttributeRequest Client Combines 0x02 + 0x04. The client sends the UUID search pattern AND the list of attributes it wants — all in one go. This is the most commonly used transaction.
0x07 SDP_ServiceSearchAttributeResponse Server Server replies with all (Attribute ID, Attribute Value) pairs from all matching service records.

🎧 Section 4 — Real Example: Phone Connecting to A2DP Headset

Let’s walk through a real SDP conversation between a mobile phone and an A2DP Bluetooth headset. This is what happens invisibly whenever you pair your phone with wireless headphones.

Step 1 — Phone Sends: SDP_ServiceSearchAttributeRequest

The phone asks the headset: “Do you support these services? And if yes, give me your ProtocolDescriptorList, BluetoothProfileDescriptorList, and SupportedFeatures.”

SDP_ServiceSearchAttributeRequest — Mobile Phone → A2DP Headset
PDU: SDP_ServiceSearchAttributeRequest (0x06)
Transaction ID: 0x0000
Parameter Length: 25 bytes
List of Services Being Searched:
├── UUID: Audio Sink ← Is this an A2DP audio receiver?
├── UUID: L2CAP ← Does it use L2CAP protocol?
└── UUID: AVDTP ← Does it support Audio/Video Distribution?
Max Attribute Data to Return:
100 bytes
List of Attributes Requested:
├── ProtocolDescriptorList
├── BluetoothProfileDescriptorList
└── SupportedFeatures

Step 2 — Headset Replies: SDP_ServiceSearchAttributeResponse

The A2DP headset confirms: “Yes, I support these. Here are my details.”

SDP_ServiceSearchAttributeResponse — A2DP Headset → Mobile Phone
PDU: SDP_ServiceSearchAttributeResponse (0x07)
Transaction ID: 0x0001
Attribute: ProtocolDescriptorList
├── Protocol: L2CAP
│ PSM: 0x0019 ← Port number AVDTP will use on L2CAP
└── Protocol: AVDTP
Version: 1.0
Attribute: BluetoothProfileDescriptorList
└── Profile: A2DP (Advanced Audio Distribution)
Version: 1.0
Attribute: SupportedFeatures
└── Sink (headset can receive audio)

After this exchange, the phone knows exactly how to connect to the headset and start streaming music using AVDTP over L2CAP channel 0x0019.

📊 Section 5 — Full SDP Flow: How Everything Fits Together
Complete SDP Interaction Flow — Client to Server
SDP CLIENT (Mobile Phone) SDP SERVER (A2DP Headset) ══════════════════════════ ═══════════════════════════
[1] Build UUID search pattern
(Audio Sink, L2CAP, AVDTP)
SDP_ServiceSearchAttributeRequest (0x06)
──────────────────────────────────────────────────────────────►
[2] Search all service records
for matching UUIDs
Match found → A2DP record
SDP_ServiceSearchAttributeResponse (0x07)
◄──────────────────────────────────────────────────────────────
[3] Parse response:
– AVDTP uses PSM 0x0019 on L2CAP
– Profile: A2DP v1.0
– Device is an Audio Sink (receiver)
[4] Now connect using L2CAP + AVDTP
on PSM 0x0019 to start audio streaming
▼ ✓ Music plays on headset!
Two-Step Alternative: Search First, Then Fetch Attributes
CLIENT SERVER ══════ ══════
Step A: SDP_ServiceSearchRequest (0x02)
[Send: UUID list]
──────────────────────────────────────────────────────────────►
SDP_ServiceSearchResponse (0x03)
[Reply: Service Record Handles]
◄──────────────────────────────────────────────────────────────
Step B: SDP_ServiceAttributeRequest (0x04)
[Send: Handle + Attribute IDs wanted]
──────────────────────────────────────────────────────────────►
SDP_ServiceAttributeResponse (0x05)
[Reply: Attribute ID + Value pairs]
◄──────────────────────────────────────────────────────────────

NOTE:

SDP_ServiceSearchAttributeRequest (0x06) combines Step A + Step B into a single round-trip.

That’s why it is preferred in most real-world implementations.

✅ Section 6 — Key Takeaways

SDP is a directory service

It lets devices advertise what services they offer and lets clients look up those services before connecting.

Two mandatory attributes

Every service record must have ServiceRecordHandle and ServiceClassIDList. Everything else is optional.

Search vs Browse

Search when you know what you want (UUID pattern). Browse when you want to see everything the server offers.

PDU 0x06 is the workhorse

SDP_ServiceSearchAttributeRequest combines search + attribute fetch in one step. Real devices like phones and headsets use this.

One request at a time

SDP is strictly request/response. The client must wait for a reply before sending the next request.

BlueZ sdptool browse

On Linux, you can see SDP in action using sdptool browse <MAC>. It lists all services of a remote Bluetooth device.

BlueZ Reference — Useful Commands

BlueZ is the official Bluetooth stack for Linux. Here are commands related to SDP:


# Browse all SDP services on a remote device
sdptool browse <MAC_ADDRESS>

# Example
sdptool browse 68:ED:43:25:0E:99

# Search for a specific service (by UUID name)
sdptool search --bdaddr <MAC> DUN        # Dial-Up Networking
sdptool search --bdaddr <MAC> A2DP       # Advanced Audio Distribution
sdptool search --bdaddr <MAC> HF         # Hands-Free Profile

# Add an SDP service record to local device
sdptool add SP        # Serial Port Profile
sdptool add DUN       # Dial-Up Networking

# List services registered on local machine
sdptool browse local
    

Leave a Reply

Your email address will not be published. Required fields are marked *