abandonware / node-bluetooth-hci-socket

MIT License
41 stars 47 forks source link

Incompatible with newest kernels ? #60

Open Peekayy opened 1 month ago

Peekayy commented 1 month ago

Hi i'm using Arch linux and after upgrading to 6.9.3 kernel, my script using @abandonware/noble stopped working.

After some investigations I managed to easily reproduce the issue by simply running examples/le-scan-test.js And here's the result:

$ sudo node le-scan-test.js
Error: EINVAL, Invalid argument
    at setFilter (/tmp/a/node-bluetooth-hci-socket/examples/le-scan-test.js:83:22)
    at Object.<anonymous> (/tmp/a/node-bluetooth-hci-socket/examples/le-scan-test.js:124:1)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  errno: 22,
  code: 'EINVAL',
  syscall: 'setsockopt'
}

Exact kernel : Linux 6.9.3-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 31 May 2024 15:14:45 +0000 x86_64 GNU/Linux

I unfortunately have no time to try to rollback to older kernels and find where it broke.

mayfield commented 2 weeks ago

I'm having issues with 6.9 as well. I use bleno, which just hangs, but the examples/le-scan-test.js fails the same way as @Peekayy sees.

mayfield commented 2 weeks ago

I couldn't do a proper bisection, but 6.8 fails and 6.5 works on my FC39 system.

mayfield commented 2 weeks ago

Running examples/le-advertisement-test.js has some more interesting output when paired with bluetoothd -d -n.

Output from bluetoothd...

bluetoothd[8761]: src/shared/mgmt.c:can_read_data() [0x0000] event 0x000b
bluetoothd[8761]: src/adapter.c:connected_callback() hci0 device F4:D4:88:6B:6E:14 connected eir_len 0
bluetoothd[8761]: src/gatt-database.c:connect_cb() New incoming LE ATT connection
bluetoothd[8761]: attrib/gattrib.c:g_attrib_ref() 0x5568e0406160: g_attrib_ref=1 
bluetoothd[8761]: src/device.c:load_gatt_db() Restoring F4:D4:88:6B:6E:14 gatt database from file
bluetoothd[8761]: src/settings.c:load_service() loading service: 0x0001, end: 0x0005, uuid: 00001800-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_service() loading service: 0x0006, end: 0x0009, uuid: 00001801-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_service() loading service: 0x000a, end: 0x000e, uuid: 0000180a-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_service() loading service: 0x000f, end: 0x0013, uuid: d0611e78-bbb4-4591-a5f8-487910ae4366
bluetoothd[8761]: src/settings.c:load_service() loading service: 0x0014, end: 0x0018, uuid: 9fa480e0-4967-4542-9390-d343dc5d04ae
bluetoothd[8761]: src/settings.c:load_chrc() loading characteristic handle: 0x0002, value handle: 0x0003, properties 0x0002 value:  uuid: 00002a00-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_chrc() loading characteristic handle: 0x0004, value handle: 0x0005, properties 0x0002 value:  uuid: 00002a01-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_chrc() loading characteristic handle: 0x0007, value handle: 0x0008, properties 0x0020 value:  uuid: 00002a05-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_desc() loading descriptor handle: 0x0009, value: 0x0000, value uuid: 00002902-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_chrc() loading characteristic handle: 0x000b, value handle: 0x000c, properties 0x0002 value:  uuid: 00002a29-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_chrc() loading characteristic handle: 0x000d, value handle: 0x000e, properties 0x0002 value:  uuid: 00002a24-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_chrc() loading characteristic handle: 0x0010, value handle: 0x0011, properties 0x0098 value:  uuid: 8667556c-9a37-4c91-84ed-54ee27d90049
bluetoothd[8761]: src/settings.c:load_desc() loading descriptor handle: 0x0012, value: 0x0001, value uuid: 00002900-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_desc() loading descriptor handle: 0x0013, value: 0x0000, value uuid: 00002902-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_chrc() loading characteristic handle: 0x0015, value handle: 0x0016, properties 0x0098 value:  uuid: af0badb1-5b99-43cd-917a-a77bc549e3cc
bluetoothd[8761]: src/settings.c:load_desc() loading descriptor handle: 0x0017, value: 0x0001, value uuid: 00002900-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/settings.c:load_desc() loading descriptor handle: 0x0018, value: 0x0000, value uuid: 00002902-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/device.c:device_accept_gatt_profiles() initiator false
bluetoothd[8761]: profiles/gap/gas.c:gap_accept() GAP profile accept (F4:D4:88:6B:6E:14)
bluetoothd[8761]: src/service.c:change_state() 0x5568e0400270: device F4:D4:88:6B:6E:14 profile gap-profile state changed: disconnected -> connected (0)
bluetoothd[8761]: profiles/deviceinfo/deviceinfo.c:deviceinfo_accept() deviceinfo profile accept (F4:D4:88:6B:6E:14)
bluetoothd[8761]: profiles/deviceinfo/deviceinfo.c:handle_characteristic() Unsupported characteristic: 00002a29-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: profiles/deviceinfo/deviceinfo.c:handle_characteristic() Unsupported characteristic: 00002a24-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: src/service.c:change_state() 0x5568e04002b0: device F4:D4:88:6B:6E:14 profile deviceinfo state changed: disconnected -> connected (0)
bluetoothd[8761]: src/gatt-client.c:btd_gatt_client_connected() Device connected.
bluetoothd[8761]: [0x5568e041ea10] src/shared/gatt-client.c:exchange_mtu_cb() MTU exchange complete, with MTU: 517
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x10
bluetoothd[8761]: src/shared/gatt-server.c:read_by_grp_type_cb() Read By Grp Type - start: 0x0001 end: 0xffff
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x10
bluetoothd[8761]: src/shared/gatt-server.c:read_by_grp_type_cb() Read By Grp Type - start: 0x0015 end: 0xffff
bluetoothd[8761]: profiles/gap/gas.c:read_device_name_cb() GAP Device Name: Mac
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x08
bluetoothd[8761]: src/shared/gatt-server.c:read_by_type_cb() Read By Type - start: 0x0008 end: 0x0011
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x08
bluetoothd[8761]: src/shared/gatt-server.c:read_by_type_cb() Read By Type - start: 0x0010 end: 0x0011
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x04
bluetoothd[8761]: src/shared/gatt-server.c:find_info_cb() Find Info - start: 0x000b end: 0x0011
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x04
bluetoothd[8761]: src/shared/gatt-server.c:find_info_cb() Find Info - start: 0x0010 end: 0x0011
bluetoothd[8761]: [0x5568e041ea10] src/shared/gatt-client.c:discover_primary_cb() Primary services found: 5
bluetoothd[8761]: [0x5568e041ea10] src/shared/gatt-client.c:discovery_parse_services() start: 0x0001, end: 0x0005, uuid: 00001800-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: [0x5568e041ea10] src/shared/gatt-client.c:discovery_parse_services() start: 0x0006, end: 0x0009, uuid: 00001801-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: [0x5568e041ea10] src/shared/gatt-client.c:discovery_parse_services() start: 0x000a, end: 0x000e, uuid: 0000180a-0000-1000-8000-00805f9b34fb
bluetoothd[8761]: [0x5568e041ea10] src/shared/gatt-client.c:discovery_parse_services() start: 0x000f, end: 0x0013, uuid: d0611e78-bbb4-4591-a5f8-487910ae4366
bluetoothd[8761]: [0x5568e041ea10] src/shared/gatt-client.c:discovery_parse_services() start: 0x0014, end: 0x0018, uuid: 9fa480e0-4967-4542-9390-d343dc5d04ae
bluetoothd[8761]: src/device.c:gatt_client_ready_cb() status: success, error: 10
bluetoothd[8761]: src/gatt-client.c:btd_gatt_client_ready() GATT client ready
bluetoothd[8761]: src/gatt-client.c:create_services() Exporting objects for GATT services: F4:D4:88:6B:6E:14
bluetoothd[8761]: src/gatt-client.c:service_create() Exported GATT service: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service0006
bluetoothd[8761]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service0006/char0007
bluetoothd[8761]: src/gatt-client.c:descriptor_create() Exported GATT characteristic descriptor: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service0006/char0007/desc0009
bluetoothd[8761]: src/gatt-client.c:service_create() Exported GATT service: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service000a
bluetoothd[8761]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service000a/char000b
bluetoothd[8761]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service000a/char000d
bluetoothd[8761]: src/gatt-client.c:service_create() Exported GATT service: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service000f
bluetoothd[8761]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service000f/char0010
bluetoothd[8761]: src/gatt-client.c:descriptor_create() Exported GATT characteristic descriptor: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service000f/char0010/desc0012
bluetoothd[8761]: src/gatt-client.c:descriptor_create() Exported GATT characteristic descriptor: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service000f/char0010/desc0013
bluetoothd[8761]: src/gatt-client.c:service_create() Exported GATT service: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service0014
bluetoothd[8761]: src/gatt-client.c:characteristic_create() Exported GATT characteristic: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service0014/char0015
bluetoothd[8761]: src/gatt-client.c:descriptor_create() Exported GATT characteristic descriptor: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service0014/char0015/desc0017
bluetoothd[8761]: src/gatt-client.c:descriptor_create() Exported GATT characteristic descriptor: /org/bluez/hci0/dev_F4_D4_88_6B_6E_14/service0014/char0015/desc0018
bluetoothd[8761]: src/gatt-client.c:btd_gatt_client_ready() Features 0x00
bluetoothd[8761]: src/gatt-client.c:btd_gatt_client_ready() Update Features 0x00
bluetoothd[8761]: src/device.c:device_svc_resolved() /org/bluez/hci0/dev_F4_D4_88_6B_6E_14 err 0
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x12
bluetoothd[8761]: src/shared/gatt-server.c:write_cb() Write Req - handle: 0x000b
bluetoothd[8761]: src/gatt-database.c:gatt_ccc_write_cb() CCC write called for handle: 0x000b
bluetoothd[8761]: src/shared/gatt-server.c:write_complete_cb() Write Complete: err 0
bluetoothd[8761]: [0x5568e041ea10] src/shared/gatt-client.c:service_changed_register_cb() Registered handler for "Service Changed": 1
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x08
bluetoothd[8761]: src/shared/gatt-server.c:read_by_type_cb() Read By Type - start: 0x0012 end: 0x0014
bluetoothd[8761]: src/shared/att.c:can_read_data() (chan 0x5568e04051a0) ATT PDU received: 0x08
bluetoothd[8761]: src/shared/gatt-server.c:read_by_type_cb() Read By Type - start: 0x0001 end: 0x0007
bluetoothd[8761]: src/gatt-database.c:gap_device_name_read_cb() GAP Device Name read request
: mayfield@jm [abandonware/node-bluetooth-hci-socket()] project/node-bluetooth-hci-socket ;
:; sudo DEBUG='*' node ./examples/le-advertisement-test.js 
Error: EINVAL, Invalid argument
    at setFilter (/home/mayfield/project/node-bluetooth-hci-socket/examples/le-advertisement-test.js:130:22)
    at Object.<anonymous> (/home/mayfield/project/node-bluetooth-hci-socket/examples/le-advertisement-test.js:215:1)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Module.load (node:internal/modules/cjs/loader:1206:32)
    at Module._load (node:internal/modules/cjs/loader:1022:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at node:internal/main/run_main_module:28:49 {
  errno: 22,
  code: 'EINVAL',
  syscall: 'setsockopt'
}
isDevUp = true
write: 010a200100
write: 0106200fa000a0000000000000000000000700
write: 01092020190909657374696d6f74650e160a182eb8855fb5ddb601000200000000000000
write: 010820201e0201061aff4c000215b9407f30f5f8466eaff925556b57fe6d00010002b600
write: 010a200101

I am extremely far from a BLE expert so I'm just putting this here for someone that can infer more meaning from it. :)

mayfield commented 1 week ago

I think the issue is related to this linux change: https://github.com/torvalds/linux/commit/b2186061d6043d6345a97100460363e990af0d46

The AF_BLUETOOTH setsockopt kernel handler validates the len of the struct hci_filter options now. However, it expects the struct to be unpacked/padded as per the host system. I suppose this could be arch dependent so I don't know what the correct fix would look like. TBH it seems like this module should maybe push the setsockopt argument handling into the C code and directly use the header files from bluez to be safest but that would be a design change.

With respect to my specific platform (amd64 linux) I can fix this issue by simply zero padding the hci_filter struct to 16 bytes so it's 32 bit aligned. For example...

diff --git a/examples/le-scan-test.js b/examples/le-scan-test.js
index 813fc4d..f52fe9d 100644
--- a/examples/le-scan-test.js
+++ b/examples/le-scan-test.js
@@ -69,7 +69,7 @@ var LE_SET_SCAN_ENABLE_CMD = OCF_LE_SET_SCAN_ENABLE | OGF_LE_CTL << 10;
 var HCI_SUCCESS = 0;

 function setFilter() {
-  var filter = Buffer.alloc(14);
+  var filter = Buffer.alloc(16);
   var typeMask = (1 << HCI_EVENT_PKT);
   var eventMask1 = (1 << EVT_CMD_COMPLETE) | (1 << EVT_CMD_STATUS);
   var eventMask2 = (1 << (EVT_LE_META_EVENT - 32));