Search code examples
bluetoothbluez

Distinction Between Manufacturing Data, Service Data and Advertising Data in Bluetooth LE


In terms of BLE, I'm getting a little confused between the terms and their usage in BlueZ:

  • Manufacturer Data
  • Service Data
  • Advertising Data

I'm going to try to sum up what I understand and where that falls apart.

From here there is a payload in the Advertising Packet that is 31 bytes long that can be used for User Defined Data.

However, BlueZ in its advertising API have a different notion of data. It takes a dict which is of <type> <byte array> from the docs.

Looking a little more you can come across this table which seems to be of the same two byte type and data structure.

It has user defined payload in terms of:

0xFF    «Manufacturer Specific Data»    Bluetooth Core Specification:Vol. 3, Part C, section 8.1.4 (v2.1 + EDR, 3.0 + HS and 4.0)Vol. 3, Part C, sections 11.1.4 and 18.11 (v4.0)Core Specification Supplement, Part A, section 1.4

So I downloaded the spec to try to read up on the distinction, which leads me to this sentence that I don't quite follow:

The data is sent in advertising or periodic advertising events. Host Advertising data is placed in the AdvData field of ADV_IND, ADV_NONCONN_IND, ADV_SCAN_IND, AUX_ADV_IND, and AUX_CHAIN_IND PDUs. Additional Controller Advertising Data is placed in the ACAD field of AUX_ADV_IND, AUX_SYNC_IND, and AUX_SCAN_RSP PDUs. Periodic Advertising data is placed in the AdvData field of AUX_SYNC_IND and AUX_CHAIN_IND PDUs. Scan Response data is sent in the ScanRspData field of SCAN_RSP PDUs or the AdvData field of AUX_SCAN_RSP PDUs. If the complete data cannot fit in the AdvData field of an AUX_ADV_IND, AUX_SYNC_IND, or AUX_SCAN_RSP PDU, AUX_CHAIN_IND PDUs are used to send the remaining fragments of the data. An AD Structure may be fragmented over two or more PDUs

Also when I look in the BlueZ implementation of their own DBUS API, I see they provide a way to fill in manufacturing data but no way to change the type of advertising (ADV_NONCONN vs ADV_CONN) .

They also do have an adv_data type but it's only 25 bytes? Why can I not get the full 31 bytes?

https://github.com/bluez/bluez/blob/cbbb0c2ead89ed19280ecd94e8a2fb0d22216bb6/client/advertising.c#L55


Actual Questions:

  1. When implementing a BT peripheral using BlueZ do I have 31 or 25 bytes. Can I fill in both Service Data and Manufacturer Data for a total of 50 bytes??
  2. Is Manufacturer Data an abstraction over Advertising Data? If so how can I access the underlying Advertising Data? If not, can I theoretically fill in both Advertising and Manufacturer data?

Solution

  • The image below created by Jos Ryke might be helpful to visualise what is happening.

    As shown in the image, ADV FLAGS and Advertisement data make up the 31 bytes advertising payload, but there are only 26 bytes for data available. The image contains examples of Manufacturer Data (type = FF) and Service Data (type = 16)

    Beacon Cheat Sheet

    In the D-Bus API, to change the type of advertising (ADV_NONCONN vs ADV_CONN) use the type property: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/advertising-api.txt#n37

    broadcast = ADV_NONCONN

    You can have both service and manufacturer data in the same advertisement (see example https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/test/example-advertisement#n141) but it cannot be longer than 31 bytes. With BlueZ, you can register (if I remember correctly) up to four advertisements that will be sent as different packets.

    So in summary, service data and manufacturer data are sub elements types within advertising payload. BlueZ allows you to build up the different data types you want in your advertisement and then register it for broadcast.