From 75413aac3da41acf2fd8f6f66b586e7a41d741da Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Tue, 16 Aug 2022 14:28:40 +1000 Subject: [PATCH 1/2] stm32/rfcore: Add stm.rfcore_ble_hci function for raw BLE HCI comms. Signed-off-by: Andrew Leech --- docs/library/stm.rst | 11 ++++++++++ ports/stm32/modstm.c | 1 + ports/stm32/rfcore.c | 52 ++++++++++++++++++++++++++++++++++++++++---- ports/stm32/rfcore.h | 1 + 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/docs/library/stm.rst b/docs/library/stm.rst index 970ab188344a5..94ac3b554fc93 100644 --- a/docs/library/stm.rst +++ b/docs/library/stm.rst @@ -103,6 +103,17 @@ the second CPU, the RF core. Returns a bytes object with the result of the SYS command. +.. function:: rfcore_ble_hci(command[, response_buf]) + + Execute a HCI command on the BLE channel. The execution is synchronous. + + Takes a *command* byte/bytearray with pre-formatted HCI packet. + + Optionally takes a pre-allocated bytearray buffer for the response packet. + + Returns response length if *response_buf* is provided, else a bytes object with the + response HCI packet. + Functions specific to STM32WLxx MCUs ------------------------------------ diff --git a/ports/stm32/modstm.c b/ports/stm32/modstm.c index 4f26dce790f43..184380bbc42f0 100644 --- a/ports/stm32/modstm.c +++ b/ports/stm32/modstm.c @@ -53,6 +53,7 @@ static const mp_rom_map_elem_t stm_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_rfcore_status), MP_ROM_PTR(&rfcore_status_obj) }, { MP_ROM_QSTR(MP_QSTR_rfcore_fw_version), MP_ROM_PTR(&rfcore_fw_version_obj) }, { MP_ROM_QSTR(MP_QSTR_rfcore_sys_hci), MP_ROM_PTR(&rfcore_sys_hci_obj) }, + { MP_ROM_QSTR(MP_QSTR_rfcore_ble_hci), MP_ROM_PTR(&rfcore_ble_hci_obj) }, #endif #if defined(STM32WL) diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c index 2d99a3410baaa..cb1589026ae60 100644 --- a/ports/stm32/rfcore.c +++ b/ports/stm32/rfcore.c @@ -503,7 +503,7 @@ static ssize_t tl_sys_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t l return tl_sys_wait_ack(ipcc_membuf_sys_cmd_buf, timeout_ms); } -static int tl_ble_wait_resp(void) { +static size_t tl_ble_wait_resp(parse_hci_info_t *parse) { uint32_t t0 = mp_hal_ticks_ms(); while (!LL_C2_IPCC_IsActiveFlag_CHx(IPCC, IPCC_CH_BLE)) { if (mp_hal_ticks_ms() - t0 > BLE_ACK_TIMEOUT_MS) { @@ -513,8 +513,7 @@ static int tl_ble_wait_resp(void) { } // C2 set IPCC flag -- process the data, clear the flag, and re-enable IRQs. - tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, NULL); - return 0; + return tl_check_msg(&ipcc_mem_ble_evt_queue, IPCC_CH_BLE, parse); } // Synchronously send a BLE command. @@ -522,7 +521,7 @@ static void tl_ble_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t len) // Poll for completion rather than wait for IRQ->scheduler. LL_C1_IPCC_DisableReceiveChannel(IPCC, IPCC_CH_BLE); tl_hci_cmd(ipcc_membuf_ble_cmd_buf, IPCC_CH_BLE, HCI_KIND_BT_CMD, opcode, buf, len); - tl_ble_wait_resp(); + tl_ble_wait_resp(NULL); } /******************************************************************************/ @@ -797,4 +796,49 @@ static mp_obj_t rfcore_sys_hci(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_sys_hci_obj, 3, 4, rfcore_sys_hci); +static void rfcore_ble_hci_response_to_buffer(void *env, const uint8_t *buf, size_t len) { + DEBUG_printf("rfcore_ble_hci_response_to_buffer len 0x%x\n", len); + mp_obj_t *rsp = (mp_obj_t *)env; + if (*rsp == mp_const_none) { + *rsp = mp_obj_new_bytes(buf, len); + } else { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(*rsp, &bufinfo, MP_BUFFER_WRITE); + if (bufinfo.len < len) { + mp_raise_OSError(-len); + } + memcpy(bufinfo.buf, buf, len); + } +} + +static mp_obj_t rfcore_ble_hci(size_t n_args, const mp_obj_t *args) { + if (ipcc_mem_dev_info_tab.fus.table_state == MAGIC_IPCC_MEM_INCORRECT) { + mp_raise_OSError(MP_EINVAL); + } + mp_obj_t cmd = args[0]; + mp_obj_t rsp = mp_const_none; + bool return_len = false; + if (n_args == 2) { + rsp = args[1]; + // response buffer passed in, so return rsp length. + return_len = true; + } + + mp_buffer_info_t bufinfo = {0}; + mp_get_buffer_raise(cmd, &bufinfo, MP_BUFFER_READ); + + // Poll for completion rather than wait for IRQ->scheduler. Is re-enabled in tl_check_msg. + LL_C1_IPCC_DisableReceiveChannel(IPCC, IPCC_CH_BLE); + + rfcore_ble_hci_cmd(bufinfo.len, bufinfo.buf); + + parse_hci_info_t parse = { rfcore_ble_hci_response_to_buffer, &rsp, false }; + size_t ret_len = tl_ble_wait_resp(&parse); + if (return_len) { + return MP_OBJ_NEW_SMALL_INT(ret_len); + } + return rsp; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_ble_hci_obj, 1, 2, rfcore_ble_hci); + #endif // defined(STM32WB) diff --git a/ports/stm32/rfcore.h b/ports/stm32/rfcore.h index 39267b325ec4d..bac14a843ffc4 100644 --- a/ports/stm32/rfcore.h +++ b/ports/stm32/rfcore.h @@ -44,5 +44,6 @@ void rfcore_end_flash_erase(void); MP_DECLARE_CONST_FUN_OBJ_0(rfcore_status_obj); MP_DECLARE_CONST_FUN_OBJ_1(rfcore_fw_version_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_sys_hci_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_ble_hci_obj); #endif // MICROPY_INCLUDED_STM32_RFCORE_H From d787d49dc903c44c148b6721c00a2239075e8831 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 26 May 2025 12:04:39 +1000 Subject: [PATCH 2/2] docs/library/bluetooth: Add details about optional BLE.hci_cmd(). Signed-off-by: Andrew Leech --- docs/library/bluetooth.rst | 116 +++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/docs/library/bluetooth.rst b/docs/library/bluetooth.rst index b09c370abd46d..92647c862d80b 100644 --- a/docs/library/bluetooth.rst +++ b/docs/library/bluetooth.rst @@ -765,3 +765,119 @@ Constructor - A 16-bit integer. e.g. ``0x2908``. - A 128-bit UUID string. e.g. ``'6E400001-B5A3-F393-E0A9-E50E24DCCA9E'``. + + +HCI Commands +----------- + +Some ports optionally support direct access to the Bluetooth controller via Host Controller Interface (HCI) commands. +This is an advanced feature that allows for more direct manipulation of the Bluetooth stack. + +.. method:: BLE.hci_cmd(ogf, ocf, request_data, response_data, /) + + Send a raw HCI command to the Bluetooth controller and receive a response. + + This function is only available when the ``MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD`` + define is enabled during build. + + **Parameters:** + + - *ogf* (int): Opcode Group Field, indicating the command group. + - *ocf* (int): Opcode Command Field, indicating the specific command within the group. + - *request_data* (buffer): Data to send to the controller (must implement the buffer protocol). + - *response_data* (buffer): Buffer to receive the response into (must implement the buffer protocol). + + **Return Value:** + + Returns the HCI status code from the command (0 for success, or a specific error code). + + **Example:** + + .. code-block:: python + + import bluetooth + import struct + + # Initialize the BLE interface + ble = bluetooth.BLE() + ble.active(True) + + # Read Local Version Information + cmd_buf = bytearray(0) # Empty payload + resp_buf = bytearray(20) # Buffer for response + + # OGF=0x04 (Information Parameters) + # OCF=0x0001 (Read Local Version Information) + status = ble.hci_cmd(0x04, 0x0001, cmd_buf, resp_buf) + + if status == 0: + # Parse the response + hci_version = resp_buf[0] + hci_revision = struct.unpack(" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy