Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using hcitool to set ad packets

There is a well known blog post going around on how to set a usb bluetooth 4 dongle to be an iBeacon. It boils down to this magical command:

sudo hcitool -i hci0 cmd 0x08 0x0008 1e 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 00 00 00 00 00 00 00 00 00 00 00 00 00

The issue with this example is that it is so opaque it's hard to use it in any more general format. I've been able to break it apart a bit:

sudo hcitool -i hci0 cmd

sends an hci command to the hci0 device

0x08 0x0008 

is just magic to set the ad package, other stackoverflow commands have said "just use it, don't ask

1e

is the length of the ENTIRE following data packet in bytes

02 01 1a 1a

Are flags to set up the ad packet (details on request)

ff 4c 00 ...

is the 'company specific data' that encodes the iBeacon info

What I've tried to do is replace the "FF ..." bytes with the opcodes for setting the NAME parameter "04 09 41 42 43" (which should set it to ABC) but that doesn't work.

I'm surprised the hcitool doesn't give us some examples on how to set the ad packet as this would be very useful in setting all sorts of other params (like TEMP or POWER). Has anyone else had any experience in using hcitool to set things like NAME?

like image 787
ScottJenson Avatar asked May 05 '14 22:05

ScottJenson


4 Answers

Late reply, but somebody might find this useful. I found it as I was looking around for solutions myself when using hcitool.

If you use hcitool cmd --help it will tell you something like this cmd <ogf> <ocf> .... It helps to look at the Bluetooth Core Specification to find out what 0x08 and 0x0008 would be for OGF and OCF. Specifically Vol. 2, Part E, 7.8

For the LE Controller Commands, the OGF code is defined as 0x08

and for the OCF of 0x0008

Advertising_Data_Length, Advertising_Data

So basically, with 0x08 0x0008 you say you are setting (in the LE Controller) the length of the data that is sent. As for the name, since the length of the BLE advertisement packet is 31 bytes (1E), you need to send the whole 31 bytes. So if you only have ABC as the name, setting 04 09 41 42 43 is correct, but that's only five bytes. For 31 you need to add 00 26 times. Just be careful you don't add too much or too little.

Also, I wasn't under the impression that BLE ad. packets are of fixed 31 byte size, but they are at least for hcitool. It doesn't work when you specifically set the outgoing size to something smaller than 1E.

like image 107
nomve Avatar answered Nov 09 '22 22:11

nomve


No. None of this answers is correct and clean.

1) BLE have a separate command set. "LE Set Advertising Data" command must be used (see 7.8.7 vol 2 part E).

2) LE Set Advertising Data is much complex than what explained above. There are at least 2 1-octet length fields, packet must be 32 bytes length, zero padded, but the first length byte must not be 0x1e (31) but the length of the significant used part, containing one or more headers. Each header still contains a length, one AS Type byte (0x09 for set local name) and the name.

SET LE LOCAL NAME:

hciconfig hci0 down
hciconfig hci0 up
hcitool -i hci0 cmd 0x08 0x0008 0c 0b 09 6c 69 6e 6b 6d 6f 74 69 6f 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
hciconfig hci0 leadv 0

0x0c : length of the following group of headers 0x0b : length of this header 0x09 : AD Type for complete name rest 0x0a length is the name

like image 37
Angelo Dureghello Avatar answered Nov 09 '22 22:11

Angelo Dureghello


Check out this answer to a similar question. It basically describes how you can download the giant Bluetooth Core Spec document, and read through all the commands that it offers you. You can use the hcitool command to execute any of these commands if you can just figure out the right format (and figure out what the commands actually do!)

Major caveat: I have not tried setting the name myself, but glancing at the spec, it looks like this is described on page 482 of the spec in section "7.3.11 Write Local Name Command". According to this the command consists of:

OCF: 0x0013
Name (up to 248 bytes)

So I would try a command like this:

hcitool -i hci0 cmd 0x08 0x0013 41 42 43

One other tip: When you issue commands like this, try running hcidump & so the command executes in the background. Then, you can enter experimental hcitool commands (or even hciconfig commands) and see annotated details about what (human readable) commands executed and what errors occurred, if any.

Using the above tip, you can also try executing hciconfig name abc to set the local name using that command line tool, while you are executing a hcidump & in the background. This should show you the proper hcitool command values to use.

like image 4
davidgyoung Avatar answered Nov 09 '22 22:11

davidgyoung


It would appear you need to use two commands rather than one. The iBeacon data is contained in the "LE Set Advertising Data" data and has been mentioned elsewhere in this post. To see a BLE friendly name you can use an additional command "LE Set Scan Response Data", this requires the receiver to scan your device (rather than passively read the advertising packet). So you can combine Angelo's example with this one to set the device as an iBeacon and set the "friendly name" which is the Scan Response data

sudo hcitool -i hci0 cmd 0x08 0x0008 1E 02 01 1A 1A FF 4C 00 02 15 E2 0A 39 F4 73 F5 4B C4 A1 2F 17 D1 AD 07 A9 61 00 00 00 00 C8 00
sudo hcitool -i hci0 cmd 0x08 0x0009 0c 0b 09 6c 69 6e 6b 6d 6f 74 69 6f 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

This worked for me using an Ubuntu box with a BLE dongle and then scanning for the beacon using this android BLE scanning app

like image 2
Matt Young Avatar answered Nov 09 '22 22:11

Matt Young