Search code examples
bluetoothbluetooth-lowenergybluezhcibtle

How to check if BLE advertisement is already enabled (HCI)


BLE advertising can be enabled using HCI_LE_Set_Advertising_Enable[1] command which returns status 0x00 if HCI_LE_Set_Advertising_Enable command succeeded or status code 0x01 to 0xFF[2] if the command failed.

If the advertisement is already enabled (e.g. calling this command for the second time with Advertising_Enable parameter set to 0x01) then this or HCI_LE_Set_Advertising_Data commands will return status 0x0C (Command Disallowed).

There are (at least) two problems with this:

  • Enabling advertising when it is already enabled can cause the random address to change. Disabling advertising when it is already disabled has no effect. [1]

  • BlueZ stack contains the following piece of code at the end of most HCI library functions:
        if (status) {
            errno = EIO;
            return -1;
        }
    
    which causes e.g. hci_le_set_advertise_enable function to return generic fail code -1 and set errno to EIO, which is indistinguishable from any other BlueZ error, HCI error or an actual IO error (HCI layer uses UART).

How to check if the LE advertisement is already enabled to be able to perform safe/strict error handling? I cannot find any command for Get Advertising Status in the BT Core Specs. I cannot rely on something like

if ((rc == -1) && (errno == EIO)) {
    /* Actually OK, advertising is already enabled */
    return 0;
}

Thank you.

References:

  • [1] BT CS 5.2 [Vol 4] Part E, Section 7.8.9
  • [2] BT CS 5.2 [Vol 1] Part F, Controller Error Codes

Solution

  • The idea is that the Bluetooth stack on the host side should know if it has started advertising or not. That's how it should work. If you manually bypass the Bluetooth stack on the host side (which you shouldn't do unless you are debugging or something), sending your own hci command, then you can't know.