Skip to content

Commit 089df60

Browse files
sylvioalveskartben
authored andcommitted
bluetooth: esp32: fix VHCI semaphore misuse in HCI send path
The TX flow control semaphore was initialized with a count of 1 and released again after every bt_esp32_send() call. This broke the VHCI flow control contract and could allow sending more packets than the controller advertised. This prevents host/controller overruns and ensures proper synchronization with the ESP32 VHCI interface. Signed-off-by: Sylvio Alves <[email protected]>
1 parent 71be3c2 commit 089df60

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

drivers/bluetooth/hci/hci_esp32.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ struct bt_esp32_data {
2525
bt_hci_recv_t recv;
2626
};
2727

28-
static K_SEM_DEFINE(hci_send_sem, 1, 1);
28+
/* VHCI notifies when exactly one more HCI packet can be sent */
29+
static K_SEM_DEFINE(hci_send_sem, 0, 1);
2930

3031
static bool is_hci_event_discardable(const uint8_t *evt_data)
3132
{
@@ -64,7 +65,7 @@ static struct net_buf *bt_esp_evt_recv(uint8_t *data, size_t remaining)
6465
return NULL;
6566
}
6667

67-
discardable = is_hci_event_discardable(data);
68+
discardable = is_hci_event_discardable(data, remaining);
6869

6970
memcpy((void *)&hdr, data, sizeof(hdr));
7071
data += sizeof(hdr);
@@ -242,22 +243,21 @@ static int bt_esp32_send(const struct device *dev, struct net_buf *buf)
242243

243244
LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:");
244245

245-
if (!esp_vhci_host_check_send_available()) {
246-
LOG_WRN("Controller not ready to receive packets");
247-
}
248-
249-
if (k_sem_take(&hci_send_sem, HCI_BT_ESP32_TIMEOUT) == 0) {
250-
esp_vhci_host_send_packet(buf->data, buf->len);
251-
} else {
246+
/* Wait for controller credit (callback gives the semaphore) */
247+
if (k_sem_take(&hci_send_sem, HCI_BT_ESP32_TIMEOUT) != 0) {
252248
LOG_ERR("Send packet timeout error");
253249
err = -ETIMEDOUT;
250+
} else {
251+
if (!esp_vhci_host_check_send_available()) {
252+
LOG_WRN("VHCI not available, sending anyway");
253+
}
254+
esp_vhci_host_send_packet(buf->data, buf->len);
254255
}
255256

256257
if (!err) {
257258
net_buf_unref(buf);
258259
}
259260

260-
k_sem_give(&hci_send_sem);
261261

262262
return err;
263263
}
@@ -291,6 +291,10 @@ static int bt_esp32_ble_init(void)
291291

292292
esp_vhci_host_register_callback(&vhci_host_cb);
293293

294+
if (esp_vhci_host_check_send_available()) {
295+
k_sem_give(&hci_send_sem);
296+
}
297+
294298
return 0;
295299
}
296300

@@ -318,6 +322,8 @@ static int bt_esp32_open(const struct device *dev, bt_hci_recv_t recv)
318322
struct bt_esp32_data *hci = dev->data;
319323
int err;
320324

325+
k_sem_reset(&hci_send_sem);
326+
321327
err = bt_esp32_ble_init();
322328
if (err) {
323329
return err;

0 commit comments

Comments
 (0)