From 95844c4f15705d006873f40d382894df38916543 Mon Sep 17 00:00:00 2001 From: vighnesh-sawant Date: Wed, 17 Jun 2026 21:10:47 +0530 Subject: [PATCH] Bluetooth: Add hooks for SCO and HCI commands Change-Id: Ib8ec5c7a7dc6245c4f69c7b2d4596bd5aca9b493 Reviewed-on: https://review.haiku-os.org/c/haiku/+/11146 Reviewed-by: waddlesplash Tested-by: Commit checker robot --- headers/os/bluetooth/HCI/btHCI_transport.h | 3 +- .../kernel/bluetooth/hci/bluetooth.cpp | 46 +++++++++++++++---- .../bluetooth/h2/h2generic/h2generic.cpp | 30 +++++++++--- 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/headers/os/bluetooth/HCI/btHCI_transport.h b/headers/os/bluetooth/HCI/btHCI_transport.h index b02eafb901..2796d39bbf 100644 --- a/headers/os/bluetooth/HCI/btHCI_transport.h +++ b/headers/os/bluetooth/HCI/btHCI_transport.h @@ -98,7 +98,7 @@ typedef struct bt_hci_device { */ typedef struct bt_hci_transport_hooks { // to be filled by driver - status_t (*SendCommand)(hci_id hciId, void* command); + status_t (*SendCommand)(hci_id hciId, net_buffer* nbuf); status_t (*SendACL)(hci_id hciId, net_buffer* nbuf); status_t (*SendSCO)(hci_id hciId, net_buffer* nbuf); status_t (*SendESCO)(hci_id hciId, net_buffer* nbuf); @@ -153,6 +153,7 @@ typedef struct bt_hci_module_info { void* data, size_t count); // To be called from upper layers + status_t (*PostCommand)(hci_id hid, net_buffer* buffer); status_t (*PostACL)(hci_id hciId, net_buffer* buffer); status_t (*PostSCO)(hci_id hciId, net_buffer* buffer); status_t (*PostESCO)(hci_id hciId, net_buffer* buffer); diff --git a/src/add-ons/kernel/bluetooth/hci/bluetooth.cpp b/src/add-ons/kernel/bluetooth/hci/bluetooth.cpp index 6929bb3d5d..d3ceae1c5d 100644 --- a/src/add-ons/kernel/bluetooth/hci/bluetooth.cpp +++ b/src/add-ons/kernel/bluetooth/hci/bluetooth.cpp @@ -295,6 +295,24 @@ UnregisterDriver(hci_id id) } +status_t +PostCommand(hci_id hciId, net_buffer* buffer) +{ + if (buffer == NULL) + panic("passing null buffer"); + + bluetooth_device* device = FindDeviceByID(hciId); + if (device == NULL) { + ERROR("%s: No device 0x%" B_PRIx32 "\n", __func__, hciId); + return B_ERROR; + } + + buffer->protocol = BT_COMMAND; + + return device->hooks->SendCommand(hciId, buffer); +} + + // PostACL status_t PostACL(hci_id hciId, net_buffer* buffer) @@ -360,7 +378,16 @@ PostACL(hci_id hciId, net_buffer* buffer) status_t PostSCO(hci_id hciId, net_buffer* buffer) { - return B_ERROR; + bluetooth_device* device = FindDeviceByID(hciId); + + if (device == NULL) { + ERROR("%s: No device 0x%" B_PRIx32 "\n", __func__, hciId); + return B_ERROR; + } + + buffer->protocol = BT_SCO; + + return device->hooks->SendSCO(hciId, buffer); } @@ -465,16 +492,17 @@ bluetooth_std_ops(int32 op, ...) bt_hci_module_info sBluetoothModule = { { - BT_HCI_MODULE_NAME, - B_KEEP_LOADED, + BT_HCI_MODULE_NAME, + B_KEEP_LOADED, bluetooth_std_ops - }, - RegisterDriver, + }, + RegisterDriver, UnregisterDriver, - FindDeviceByID, - PostTransportPacket, - PostACL, - PostSCO, + FindDeviceByID, + PostTransportPacket, + PostCommand, + PostACL, + PostSCO, PostESCO }; diff --git a/src/add-ons/kernel/drivers/bluetooth/h2/h2generic/h2generic.cpp b/src/add-ons/kernel/drivers/bluetooth/h2/h2generic/h2generic.cpp index b2af51d3a7..0f8bbfad75 100644 --- a/src/add-ons/kernel/drivers/bluetooth/h2/h2generic/h2generic.cpp +++ b/src/add-ons/kernel/drivers/bluetooth/h2/h2generic/h2generic.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -441,11 +442,11 @@ device_removed(void* cookie) static bt_hci_transport_hooks bluetooth_hooks = { - NULL, - &submit_nbuffer, - &submit_nbuffer, - NULL, - NULL, + &submit_nbuffer, + &submit_nbuffer, + &submit_nbuffer, + NULL, + NULL, H2 }; @@ -477,8 +478,23 @@ submit_nbuffer(hci_id hid, net_buffer* nbuf) return submit_tx_sco(bdev, nbuf); break; case BT_COMMAND: - // not issued this way - break; + { + snet_buffer* snbuf = snb_fetch(&bdev->snetBufferRecycleTrash, nbuf->size); + if (snbuf == NULL) + return B_NO_MEMORY; + + BStackOrHeapArray data(nbuf->size); + if (!data.IsValid()) { + snb_park(&bdev->snetBufferRecycleTrash, snbuf); + return B_NO_MEMORY; + } + + nb->read(nbuf, 0, data, nbuf->size); + snb_put(snbuf, data, nbuf->size); + + return submit_tx_command(bdev, snbuf); + break; + } case BT_ACL: return submit_tx_acl(bdev, nbuf);