summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extmod/modbluetooth.c20
-rw-r--r--extmod/modbluetooth.h10
-rw-r--r--extmod/nimble/modbluetooth_nimble.c23
3 files changed, 52 insertions, 1 deletions
diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c
index caaf872e7..8870a21c4 100644
--- a/extmod/modbluetooth.c
+++ b/extmod/modbluetooth.c
@@ -884,6 +884,23 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_l2cap_recvinto_obj, 4,
#endif // MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
+#if MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD
+
+STATIC mp_obj_t bluetooth_ble_hci_cmd(size_t n_args, const mp_obj_t *args) {
+ mp_int_t ogf = mp_obj_get_int(args[1]);
+ mp_int_t ocf = mp_obj_get_int(args[2]);
+ mp_buffer_info_t bufinfo_request = {0};
+ mp_buffer_info_t bufinfo_response = {0};
+ mp_get_buffer_raise(args[3], &bufinfo_request, MP_BUFFER_READ);
+ mp_get_buffer_raise(args[4], &bufinfo_response, MP_BUFFER_WRITE);
+ uint8_t status = 0;
+ bluetooth_handle_errno(mp_bluetooth_hci_cmd(ogf, ocf, bufinfo_request.buf, bufinfo_request.len, bufinfo_response.buf, bufinfo_response.len, &status));
+ return MP_OBJ_NEW_SMALL_INT(status);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_hci_cmd_obj, 5, 5, bluetooth_ble_hci_cmd);
+
+#endif // MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD
+
// ----------------------------------------------------------------------------
// Bluetooth object: Definition
// ----------------------------------------------------------------------------
@@ -927,6 +944,9 @@ STATIC const mp_rom_map_elem_t bluetooth_ble_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_l2cap_send), MP_ROM_PTR(&bluetooth_ble_l2cap_send_obj) },
{ MP_ROM_QSTR(MP_QSTR_l2cap_recvinto), MP_ROM_PTR(&bluetooth_ble_l2cap_recvinto_obj) },
#endif
+ #if MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD
+ { MP_ROM_QSTR(MP_QSTR_hci_cmd), MP_ROM_PTR(&bluetooth_ble_hci_cmd_obj) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(bluetooth_ble_locals_dict, bluetooth_ble_locals_dict_table);
diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h
index f14033de3..c96427fcb 100644
--- a/extmod/modbluetooth.h
+++ b/extmod/modbluetooth.h
@@ -60,6 +60,12 @@
#define MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING (0)
#endif
+// Optionally enable support for the `hci_cmd` function allowing
+// Python to directly low-level HCI commands.
+#ifndef MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD
+#define MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD (0)
+#endif
+
// This is used to protect the ringbuffer.
// A port may no-op this if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS is enabled.
#ifndef MICROPY_PY_BLUETOOTH_ENTER
@@ -387,6 +393,10 @@ int mp_bluetooth_l2cap_send(uint16_t conn_handle, uint16_t cid, const uint8_t *b
int mp_bluetooth_l2cap_recvinto(uint16_t conn_handle, uint16_t cid, uint8_t *buf, size_t *len);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
+#if MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD
+int mp_bluetooth_hci_cmd(uint16_t ogf, uint16_t ocf, const uint8_t *req, size_t req_len, uint8_t *resp, size_t resp_len, uint8_t *status);
+#endif // MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD
+
/////////////////////////////////////////////////////////////////////////////
// API implemented by modbluetooth (called by port-specific implementations):
diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c
index 9ceeab7d7..8bead890d 100644
--- a/extmod/nimble/modbluetooth_nimble.c
+++ b/extmod/nimble/modbluetooth_nimble.c
@@ -81,9 +81,11 @@ STATIC int ble_hs_err_to_errno(int err) {
return 0;
}
if (err >= 0 && (unsigned)err < MP_ARRAY_SIZE(ble_hs_err_to_errno_table) && ble_hs_err_to_errno_table[err]) {
+ // Return an MP_Exxx error code.
return ble_hs_err_to_errno_table[err];
} else {
- return MP_EIO;
+ // Pass through the BLE error code.
+ return -err;
}
}
@@ -1660,6 +1662,25 @@ int mp_bluetooth_l2cap_recvinto(uint16_t conn_handle, uint16_t cid, uint8_t *buf
#endif // MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
+#if MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD
+
+// For ble_hs_hci_cmd_tx
+#include "nimble/host/src/ble_hs_hci_priv.h"
+
+int mp_bluetooth_hci_cmd(uint16_t ogf, uint16_t ocf, const uint8_t *req, size_t req_len, uint8_t *resp, size_t resp_len, uint8_t *status) {
+ int rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(ogf, ocf), req, req_len, resp, resp_len);
+ if (rc < BLE_HS_ERR_HCI_BASE || rc >= BLE_HS_ERR_HCI_BASE + 0x100) {
+ // The controller didn't handle the command (e.g. HCI timeout).
+ return ble_hs_err_to_errno(rc);
+ } else {
+ // The command executed, but had an error (i.e. invalid parameter).
+ *status = rc - BLE_HS_ERR_HCI_BASE;
+ return 0;
+ }
+}
+
+#endif // MICROPY_PY_BLUETOOTH_ENABLE_HCI_CMD
+
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
STATIC int ble_store_ram_read(int obj_type, const union ble_store_key *key, union ble_store_value *value) {