While I was testing some basic HCI commands using python's socket
library, it seems that in order to get any socket traffic using AF_BLUETOOTH
and BTPROTO_HCI
a "pass all" filter needs to be set in the socket options:
from socket import socket, AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI, SOL_HCI, HCI_FILTER
from struct import pack
PASS_ALL = pack("IIIh2x", 0xffffffff, 0xffffffff, 0xffffffff, 0)
def open_socket_with_hci(dev_id: int):
hci = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)
hci.bind((dev_id,))
hci.setsockopt(SOL_HCI, HCI_FILTER, PASS_ALL)
return hci
I found hci_filter struct defined as:
struct hci_filter {
uint32_t type_mask;
uint32_t event_mask[2];
uint16_t opcode;
};
The opcode mask is straight forward enough. I'm assuming type_mask
is a mask on values (code from hci.h):
/* HCI data types */
#define HCI_COMMAND_PKT 0x01
#define HCI_ACLDATA_PKT 0x02
#define HCI_SCODATA_PKT 0x03
#define HCI_EVENT_PKT 0x04
#define HCI_DIAG_PKT 0xf0
#define HCI_VENDOR_PKT 0xff
But could someone please explain the 2x event_mask
s? Is the 1st for HCI Event Type and the 2nd for Subevent Type (i.e. LE Meta Event)?
So, I was looking through the noble source and found this:
Hci.prototype.setSocketFilter = function() {
var filter = new Buffer(14);
var typeMask = (1 << HCI_COMMAND_PKT) | (1 << HCI_EVENT_PKT) | (1 << HCI_ACLDATA_PKT);
var eventMask1 = (1 << EVT_DISCONN_COMPLETE) | (1 << EVT_ENCRYPT_CHANGE) | (1 << EVT_CMD_COMPLETE) | (1 << EVT_CMD_STATUS);
var eventMask2 = (1 << (EVT_LE_META_EVENT - 32));
var opcode = 0;
filter.writeUInt32LE(typeMask, 0);
filter.writeUInt32LE(eventMask1, 4);
filter.writeUInt32LE(eventMask2, 8);
filter.writeUInt16LE(opcode, 12);
debug('setting filter to: ' + filter.toString('hex'));
this._socket.setFilter(filter);
};
So the mask is defined as the bit shifted left by the constant's value defined in the Bluetooth Core Volume 2, Part E, Section 5 & 7.
User contributions licensed under CC BY-SA 3.0