Skip to content

Instantly share code, notes, and snippets.

@KaneCheshire
Last active August 13, 2020 16:13
Show Gist options
  • Save KaneCheshire/1bf5dbf27f510fb1c9d4db5d6714a3cd to your computer and use it in GitHub Desktop.
Save KaneCheshire/1bf5dbf27f510fb1c9d4db5d6714a3cd to your computer and use it in GitHub Desktop.
Boosted Board Remote Advertising Details
****************************************************************************************************************
* This document has been moved to https://github.com/KaneCheshire/remotely which has accompanying Android code *
****************************************************************************************************************
* This document is now out of date *
****************************************************************************************************************
When the remote is not in pairing mode, it advertises the following data
Note: it's all just one array of bytes, I've just sectioned them up with brackets for readability.
Flags DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL (reversed) DATA_TYPE_MANUFACTURER_SPECIFIC_DATA DATA_TYPE_MANUFACTURER_SPECIFIC_DATA DATA_TYPE_LOCAL_NAME_COMPLETE
[(02) 01 06] [(11) 06 66 7C 50 17 55 5E 22 8D E6 11 56 00 2C 77 C4 F4] [(09) FF 00 00 03 03 02 FF FF FF] [(08) FF 00 C6 11 AF 99 FF FF]. [(13) 09 42 6F 6F 73 74 65 64 52 6D 74 39 39 41 46 31 31 43 36] [00 00]
When the remote is in pairing mode, the data is almost entirely the same except for one of the
manufacturer specific datas, which has 0x2 instead of 0x0 at the start. I'm guessing this is how the board knows to try and pair with the remote.
Flags DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL (reversed) DATA_TYPE_MANUFACTURER_SPECIFIC_DATA DATA_TYPE_MANUFACTURER_SPECIFIC_DATA DATA_TYPE_LOCAL_NAME_COMPLETE
[(02) 01 06] [(11) 06 66 7C 50 17 55 5E 22 8D E6 11 56 00 2C 77 C4 F4] [(09) FF 02 00 03 03 02 FF FF FF] [(08) FF 00 C6 11 AF 99 FF FF]. [(13) 09 42 6F 6F 73 74 65 64 52 6D 74 39 39 41 46 31 31 43 36] [00 00]
The first bytes in each section (each byte is separated by a space) indicates the length of the section + a byte for the length indicator.
E.g. the flags section is 2 bytes long (3 bytes including the length indicator byte).
The second byte in each section indicates the type of section.
E.g the type in the flags section 0x01 means "flags".
Note: the values are hex values, not decimal. So in the second section, 11 is not 11 in decimal, it's 17 in decimal.
See further down for an explanation of each section + the flags meaning.
---
Using Android Bluetooth APIs I was almost able to completely replicate the same advertising data for non-pairing:
Flags DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE (reversed) DATA_TYPE_MANUFACTURER_SPECIFIC_DATA DATA_TYPE_MANUFACTURER_SPECIFIC_DATA DATA_TYPE_LOCAL_NAME_COMPLETE
[02 01 02] [11 07 66 7C 50 17 55 5E 22 8D E6 11 56 00 2C 77 C4 F4] [09 FF 00 00 03 03 02 FF FF FF] [08 FF 00 C6 11 AF 99 FF FF] [13 09 42 6F 6F 73 74 65 64 52 6D 74 39 39 41 46 31 31 43 36] [00 00]
Note that the value for the flag in my app is 0x02 not 0x06, and that the type indicator in the second section
is 0x07 not 0x06, meaning DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE not DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL like from the remote.
Everything else is exactly the same, sadly I can't find a way to control those last two bits of data since they're set by the system :(
The same goes for pretending to be pairing:
Flags DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE (reversed) DATA_TYPE_MANUFACTURER_SPECIFIC_DATA DATA_TYPE_MANUFACTURER_SPECIFIC_DATA DATA_TYPE_LOCAL_NAME_COMPLETE
[02 01 02] [11 07 66 7C 50 17 55 5E 22 8D E6 11 56 00 2C 77 C4 F4] [09 FF 02 00 03 03 02 FF FF FF] [08 FF 00 C6 11 AF 99 FF FF] [13 09 42 6F 6F 73 74 65 64 52 6D 74 39 39 41 46 31 31 43 36] [00 00]
I can't even get the board to "see" or connect to the app,
even when advertising in the pairing mode which is almost identical to the remote, bar the flags and slightly different COMPLETE data type.
If you're wondering, it's not even worth trying on iOS because you can't control the manufacturer data at all.
---
So what do all the sections mean?
Flags:
The value here is a possible combination of various flags (defined here: https://devzone.nordicsemi.com/f/nordic-q-a/29083/ble-advertising-data-flags-field-and-discovery)
If you bitwise-and the remote's flags (0x6) it's saying it's a general LE type of device but doesn't support BREDR.
If you biwise-and the app's flags (0x2) it's saying it's just a general LE type of device and doesn't indicate anything else.
I can't see that being a reason the board can't see the app as a remote, but maybe it expects the value to be exact.
Data type:
This section is identifying the type of service UUIDs that are advertised.
Even though the actual uuid bytes are the same, Android creates the advertisement data with the flag DATA_TYPE_SERVICE_UUIDS_128_BIT_COMPLETE (0x7)
and the remote creates it with DATA_TYPE_SERVICE_UUIDS_128_BIT_PARTIAL (0x6).
The bluetooth specification requires the bytes to be reversed, for some reason. So if you reverse the bytes (after removing the length and type indicators)
it's just the uuid for the bluetooth service "F4C4772C-0056-11E6-8D22-5E5517507C66".
Manufacturer specific data:
This is where manufacturers (or devs) can put what bytes they want into the advertisement data that they know what to do with,
in the remote's case it's got two different ones that we can assume the board knows how to use.
It's not clear exactly what the bytes mean, even though the second one uses the same bytes as some of the remote's name (see below).
When you put the remote into pairing mode, the first byte of the first manufacturer data changes for 0x0 to 0x2, the rest stays the same.
I assume this is how the board knows when to initiate pairing with the remote or not.
You can add as many manufacturer specific datas you want to an advertisement data bundle
but you cannot exceed the limit of total bytes (including all the extra stuff like length and type indicators), which is a maximum
of 31 bytes.
Local name:
Self explanatory, this is the name of the device doing the advertising. In this case, the hex values mean "BoostedRmt99AF11C6".
As with the manufacturer specific datas, you cannot let this make the entire bundle of data exceed 31 bytes.
Note that if you add up all the bytes above, they do exceed 31 bytes. The way the remote and the app work around this is by splitting
up the data into the advertising packet and a scan response (the data that gets sent back to a device once it scans it).
This tripped me up at first! This effectively means you can advertise 62 bytes of data if you section it up properly.
The two final 0x0 bytes are padding bytes for the scan response, I'm assuming the Bluetooth specification means that the data needs
to exactly match 31 bytes, even if the bytes are zero/empty.
---
One final note, I noticed that the name of my remote is:
BoostedRmt99AF11C6
If you're eagled eyed like I was, you'll see that the last digits after "BoostedRmt" are actually hex values
which correspond with the second manufacturing data, but in reverse. Just in case the board also looks for this,
I set my phone's name to that and that's how I got the advertiement raw data bytes so closely matched.
Sadly, even after a day of playing around trying to get the board to pair with my phone as a remote, I couldn't get it to
connect automatically. Sad face.
Still, I learnt a lot about how advertising works in Bluetooth LE.
@KaneCheshire
Copy link
Author

I can easily share an Android studio project which sets the app up to advertise the way I got the bytes similar if people want :) the code is messssyyyy right now though.

@0xD34D
Copy link

0xD34D commented Aug 13, 2020

I can easily share an Android studio project which sets the app up to advertise the way I got the bytes similar if people want :) the code is messssyyyy right now though.

If you have that project and could pass it on, I'd be willing to play around with it. It's possible there might be some hidden APIs or maybe some lower level ways to access the BLE stack to get those two troublesome bytes correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment