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
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. |
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.
Browsing 68:ED:43:25:0E:99 …
│ 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 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 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.
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. |
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.”
Parameter Length: 25 bytes
├── UUID: L2CAP ← Does it use L2CAP protocol?
└── UUID: AVDTP ← Does it support Audio/Video Distribution?
├── BluetoothProfileDescriptorList
└── SupportedFeatures
Step 2 — Headset Replies: SDP_ServiceSearchAttributeResponse
The A2DP headset confirms: “Yes, I support these. Here are my details.”
│ PSM: 0x0019 ← Port number AVDTP will use on L2CAP
└── Protocol: AVDTP
Version: 1.0
Version: 1.0
After this exchange, the phone knows exactly how to connect to the headset and start streaming music using AVDTP over L2CAP channel 0x0019.
(Audio Sink, L2CAP, AVDTP)
for matching UUIDs
Match found → A2DP record
– AVDTP uses PSM 0x0019 on L2CAP
– Profile: A2DP v1.0
– Device is an Audio Sink (receiver)
on PSM 0x0019 to start audio streaming
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.
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
