Merge pull request #5936 from tannewt/esp_ble_advertise
Support BLE advertising on ESP
This commit is contained in:
commit
14ed33c99d
@ -446,6 +446,7 @@ msgstr ""
|
||||
msgid "All timers in use"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Adapter.c
|
||||
#: ports/nrf/common-hal/_bleio/Adapter.c
|
||||
msgid "Already advertising."
|
||||
msgstr ""
|
||||
@ -908,10 +909,12 @@ msgstr ""
|
||||
msgid "Data chunk must follow fmt chunk"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Adapter.c
|
||||
#: ports/nrf/common-hal/_bleio/Adapter.c
|
||||
msgid "Data not supported with directed advertising"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Adapter.c
|
||||
#: ports/nrf/common-hal/_bleio/Adapter.c
|
||||
msgid "Data too large for advertisement packet"
|
||||
msgstr ""
|
||||
@ -992,6 +995,7 @@ msgstr ""
|
||||
msgid "Expected tuple of length %d, got %d"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Adapter.c
|
||||
#: ports/nrf/common-hal/_bleio/Adapter.c
|
||||
msgid "Extended advertisements with scan response not supported."
|
||||
msgstr ""
|
||||
@ -1045,6 +1049,7 @@ msgstr ""
|
||||
msgid "Failed to buffer the sample"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Adapter.c
|
||||
#: ports/nrf/common-hal/_bleio/Adapter.c
|
||||
msgid "Failed to connect: internal error"
|
||||
msgstr ""
|
||||
@ -1276,6 +1281,7 @@ msgstr ""
|
||||
msgid "Invalid AuthMode"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/__init__.c
|
||||
#: ports/nrf/common-hal/_bleio/__init__.c
|
||||
msgid "Invalid BLE parameter"
|
||||
msgstr ""
|
||||
@ -1584,6 +1590,10 @@ msgstr ""
|
||||
msgid "Name too long"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/__init__.c
|
||||
msgid "Nimble out of memory"
|
||||
msgstr ""
|
||||
|
||||
#: ports/nrf/common-hal/_bleio/Characteristic.c
|
||||
msgid "No CCCD for this Characteristic"
|
||||
msgstr ""
|
||||
@ -1731,6 +1741,7 @@ msgstr ""
|
||||
msgid "Not a valid IP string"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/__init__.c
|
||||
#: ports/nrf/common-hal/_bleio/__init__.c
|
||||
#: shared-bindings/_bleio/CharacteristicBuffer.c
|
||||
msgid "Not connected"
|
||||
@ -2110,6 +2121,7 @@ msgstr ""
|
||||
msgid "Scale dimensions must divide by 3"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Adapter.c
|
||||
#: ports/nrf/common-hal/_bleio/Adapter.c
|
||||
msgid "Scan already in progess. Stop with stop_scan."
|
||||
msgstr ""
|
||||
@ -2268,6 +2280,7 @@ msgstr ""
|
||||
msgid "Time is in the past."
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Adapter.c
|
||||
#: ports/nrf/common-hal/_bleio/Adapter.c
|
||||
#, c-format
|
||||
msgid "Timeout is too long: Maximum timeout length is %d seconds"
|
||||
@ -2290,6 +2303,7 @@ msgstr ""
|
||||
msgid "Too many displays"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/PacketBuffer.c
|
||||
#: ports/nrf/common-hal/_bleio/PacketBuffer.c
|
||||
msgid "Total data to write is larger than %q"
|
||||
msgstr ""
|
||||
@ -2421,11 +2435,21 @@ msgstr ""
|
||||
msgid "Unknown security error: 0x%04x"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/__init__.c
|
||||
#, c-format
|
||||
msgid "Unknown system firmware error at %s:%d: %d"
|
||||
msgstr ""
|
||||
|
||||
#: ports/nrf/common-hal/_bleio/__init__.c
|
||||
#, c-format
|
||||
msgid "Unknown system firmware error: %04x"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/__init__.c
|
||||
#, c-format
|
||||
msgid "Unknown system firmware error: %d"
|
||||
msgstr ""
|
||||
|
||||
#: shared-bindings/adafruit_pixelbuf/PixelBuf.c
|
||||
#, c-format
|
||||
msgid "Unmatched number of items on RHS (expected %d, got %d)."
|
||||
@ -2463,11 +2487,13 @@ msgstr ""
|
||||
msgid "Update Failed"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Descriptor.c
|
||||
#: ports/nrf/common-hal/_bleio/Characteristic.c
|
||||
#: ports/nrf/common-hal/_bleio/Descriptor.c
|
||||
msgid "Value length != required fixed length"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Descriptor.c
|
||||
#: ports/nrf/common-hal/_bleio/Characteristic.c
|
||||
#: ports/nrf/common-hal/_bleio/Descriptor.c
|
||||
msgid "Value length > max_length"
|
||||
@ -2525,6 +2551,7 @@ msgstr ""
|
||||
msgid "Woken up by alarm.\n"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/PacketBuffer.c
|
||||
#: ports/nrf/common-hal/_bleio/PacketBuffer.c
|
||||
msgid "Writes not supported on Characteristic"
|
||||
msgstr ""
|
||||
@ -3592,6 +3619,7 @@ msgstr ""
|
||||
msgid "matrix is not positive definite"
|
||||
msgstr ""
|
||||
|
||||
#: ports/espressif/common-hal/_bleio/Descriptor.c
|
||||
#: ports/nrf/common-hal/_bleio/Characteristic.c
|
||||
#: ports/nrf/common-hal/_bleio/Descriptor.c
|
||||
#, c-format
|
||||
|
@ -86,7 +86,9 @@ INC += \
|
||||
-isystem esp-idf \
|
||||
-isystem esp-idf/components/app_update/include \
|
||||
-isystem esp-idf/components/bootloader_support/include \
|
||||
-isystem esp-idf/components/bt/include/$(IDF_TARGET)/include \
|
||||
-isystem esp-idf/components/bt/host/nimble/esp-hci/include \
|
||||
-isystem esp-idf/components/bt/host/nimble/nimble/nimble/controller/include \
|
||||
-isystem esp-idf/components/bt/host/nimble/nimble/nimble/host/include \
|
||||
-isystem esp-idf/components/bt/host/nimble/nimble/nimble/host/services/gap/include \
|
||||
-isystem esp-idf/components/bt/host/nimble/nimble/nimble/include \
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "shared-bindings/_bleio/ScanEntry.h"
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
|
||||
#include "controller/ble_ll_adv.h"
|
||||
#include "nimble/hci_common.h"
|
||||
#include "nimble/nimble_port.h"
|
||||
#include "nimble/nimble_port_freertos.h"
|
||||
@ -53,12 +54,11 @@
|
||||
#include "host/util/util.h"
|
||||
#include "services/gap/ble_svc_gap.h"
|
||||
|
||||
#include "common-hal/_bleio/Connection.h"
|
||||
|
||||
#include "esp_bt.h"
|
||||
#include "esp_nimble_hci.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
const char *TAG = "BLE adapter";
|
||||
|
||||
bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
|
||||
|
||||
// static void bluetooth_adapter_background(void *data) {
|
||||
@ -98,6 +98,13 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable
|
||||
// ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
||||
ble_svc_gap_device_name_set("CIRCUITPY");
|
||||
|
||||
// Clear all of the internal connection objects.
|
||||
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
bleio_connection_internal_t *connection = &bleio_connections[i];
|
||||
// Reset connection.
|
||||
connection->conn_handle = BLEIO_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
cp_task = xTaskGetCurrentTaskHandle();
|
||||
|
||||
nimble_port_freertos_init(nimble_host_task);
|
||||
@ -158,7 +165,9 @@ static int _scan_event(struct ble_gap_event *event, void *scan_results_in) {
|
||||
}
|
||||
|
||||
if (event->type != BLE_GAP_EVENT_DISC && event->type != BLE_GAP_EVENT_EXT_DISC) {
|
||||
ESP_LOGI(TAG, "unsupported scan event %d", event->type);
|
||||
#if CIRCUITPY_VERBOSE_BLE
|
||||
mp_printf(&mp_plat_print, "Unsupported scan event %d\n", event->type);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -208,16 +217,10 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t
|
||||
|
||||
uint8_t own_addr_type;
|
||||
struct ble_gap_disc_params disc_params;
|
||||
int rc;
|
||||
|
||||
/* Figure out address to use while advertising (no privacy for now) */
|
||||
int privacy = 0;
|
||||
rc = ble_hs_id_infer_auto(privacy, &own_addr_type);
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "id error");
|
||||
// Error. TODO: Make function to translate into exceptions.
|
||||
}
|
||||
|
||||
CHECK_NIMBLE_ERROR(ble_hs_id_infer_auto(privacy, &own_addr_type));
|
||||
|
||||
disc_params.filter_duplicates = 0;
|
||||
disc_params.passive = !active;
|
||||
@ -226,11 +229,8 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t
|
||||
disc_params.filter_policy = 0;
|
||||
disc_params.limited = 0;
|
||||
|
||||
rc = ble_gap_disc(own_addr_type, timeout * 1000, &disc_params,
|
||||
_scan_event, self->scan_results);
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "scan error %d", rc);
|
||||
}
|
||||
CHECK_NIMBLE_ERROR(ble_gap_disc(own_addr_type, timeout * 1000, &disc_params,
|
||||
_scan_event, self->scan_results));
|
||||
|
||||
return MP_OBJ_FROM_PTR(self->scan_results);
|
||||
}
|
||||
@ -244,6 +244,36 @@ void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) {
|
||||
self->scan_results = NULL;
|
||||
}
|
||||
|
||||
STATIC void _convert_address(const bleio_address_obj_t *address, ble_addr_t *nimble_address) {
|
||||
nimble_address->type = address->type;
|
||||
mp_buffer_info_t address_buf_info;
|
||||
mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ);
|
||||
memcpy(nimble_address->val, (uint8_t *)address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
|
||||
}
|
||||
|
||||
STATIC void _new_connection(uint16_t conn_handle) {
|
||||
// Set the tx_power for the connection higher than the advertisement.
|
||||
esp_ble_tx_power_set(conn_handle, ESP_PWR_LVL_N0);
|
||||
|
||||
|
||||
// Find an empty connection. One must always be available because the SD has the same
|
||||
// total connection limit.
|
||||
bleio_connection_internal_t *connection;
|
||||
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
connection = &bleio_connections[i];
|
||||
if (connection->conn_handle == BLEIO_HANDLE_INVALID) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
connection->conn_handle = conn_handle;
|
||||
connection->connection_obj = mp_const_none;
|
||||
connection->pair_status = PAIR_NOT_PAIRED;
|
||||
connection->mtu = 0;
|
||||
|
||||
// Change the callback for the connection.
|
||||
ble_gap_set_event_cb(conn_handle, bleio_connection_event_cb, connection);
|
||||
}
|
||||
|
||||
mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) {
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
|
||||
@ -252,29 +282,210 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
struct os_mbuf mbuf;
|
||||
struct os_mbuf_pkthdr hdr;
|
||||
} os_mbuf_t;
|
||||
|
||||
STATIC void _wrap_in_mbuf(const uint8_t *data, uint16_t len, os_mbuf_t *buf) {
|
||||
struct os_mbuf *mbuf = &buf->mbuf;
|
||||
mbuf->om_data = (uint8_t *)data,
|
||||
mbuf->om_flags = 0;
|
||||
mbuf->om_pkthdr_len = 0;
|
||||
mbuf->om_len = len;
|
||||
mbuf->om_next.sle_next = NULL;
|
||||
|
||||
buf->hdr.omp_len = len;
|
||||
|
||||
// Setting the pool to NULL will cause frees to fail. Hopefully that failure
|
||||
// is ignored.
|
||||
mbuf->om_omp = NULL;
|
||||
}
|
||||
|
||||
static int _advertising_event(struct ble_gap_event *event, void *self_in) {
|
||||
bleio_adapter_obj_t *self = (bleio_adapter_obj_t *)self_in;
|
||||
|
||||
#if CIRCUITPY_VERBOSE_BLE
|
||||
mp_printf(&mp_plat_print, "Advertising event: %d\n", event->type);
|
||||
#endif
|
||||
switch (event->type) {
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
// Spurious connect events can happen.
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVENT_ADV_COMPLETE:
|
||||
if (event->adv_complete.reason == NIMBLE_OK) {
|
||||
_new_connection(event->adv_complete.conn_handle);
|
||||
// Set connections objs back to NULL since we have a new
|
||||
// connection and need a new tuple.
|
||||
self->connection_objs = NULL;
|
||||
}
|
||||
// Other statuses indicate timeout or preemption.
|
||||
common_hal_bleio_adapter_stop_advertising(self);
|
||||
break;
|
||||
|
||||
default:
|
||||
#if CIRCUITPY_VERBOSE_BLE
|
||||
// For debugging.
|
||||
mp_printf(&mp_plat_print, "Unhandled advertising event: %d\n", event->type);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
||||
bool connectable, bool anonymous, uint32_t timeout, float interval,
|
||||
const uint8_t *advertising_data, uint16_t advertising_data_len,
|
||||
const uint8_t *scan_response_data, uint16_t scan_response_data_len,
|
||||
mp_int_t tx_power, const bleio_address_obj_t *directed_to) {
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
return -1;
|
||||
|
||||
if (ble_gap_adv_active() && !self->user_advertising) {
|
||||
return BLE_HS_EBUSY;
|
||||
}
|
||||
|
||||
uint32_t rc;
|
||||
bool extended = advertising_data_len > BLE_ADV_LEGACY_DATA_MAX_LEN ||
|
||||
scan_response_data_len > BLE_ADV_LEGACY_DATA_MAX_LEN;
|
||||
|
||||
ble_addr_t peer;
|
||||
if (directed_to != NULL) {
|
||||
_convert_address(directed_to, &peer);
|
||||
}
|
||||
|
||||
uint8_t own_addr_type;
|
||||
// Anonymous addresses are still resolvable. (Following what the NRF
|
||||
// implementation does.)
|
||||
rc = ble_hs_id_infer_auto(anonymous, &own_addr_type);
|
||||
if (rc != NIMBLE_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool high_duty_directed = directed_to != NULL && interval <= 3.5 && timeout <= 1.3;
|
||||
|
||||
struct ble_gap_ext_adv_params adv_params = {
|
||||
.connectable = connectable,
|
||||
.scannable = scan_response_data_len > 0,
|
||||
.directed = directed_to != NULL,
|
||||
.high_duty_directed = high_duty_directed,
|
||||
.legacy_pdu = !extended,
|
||||
.anonymous = anonymous,
|
||||
.include_tx_power = extended,
|
||||
.scan_req_notif = false,
|
||||
.itvl_min = SEC_TO_UNITS(interval, UNIT_0_625_MS) + 0.5f,
|
||||
.itvl_max = SEC_TO_UNITS(interval, UNIT_0_625_MS) + 0.5f,
|
||||
.channel_map = 0,
|
||||
.own_addr_type = own_addr_type,
|
||||
.peer = peer,
|
||||
.filter_policy = BLE_HCI_CONN_FILT_NO_WL,
|
||||
.primary_phy = BLE_HCI_LE_PHY_1M,
|
||||
.secondary_phy = BLE_HCI_LE_PHY_1M,
|
||||
.tx_power = tx_power,
|
||||
.sid = 0,
|
||||
};
|
||||
|
||||
// Configure must come before setting payloads.
|
||||
rc = ble_gap_ext_adv_configure(0,
|
||||
&adv_params,
|
||||
NULL,
|
||||
_advertising_event, self);
|
||||
if (rc != NIMBLE_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
os_mbuf_t buf;
|
||||
_wrap_in_mbuf(advertising_data, advertising_data_len, &buf);
|
||||
// This copies the advertising data into buffers to send to the controller.
|
||||
// Therefore, we don't need to worry about the lifetime of our copy.
|
||||
rc = ble_gap_ext_adv_set_data(0, &buf.mbuf);
|
||||
if (rc != NIMBLE_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (scan_response_data_len > 0) {
|
||||
_wrap_in_mbuf(scan_response_data, scan_response_data_len, &buf);
|
||||
// This copies the advertising data into buffers to send to the controller.
|
||||
// Therefore, we don't need to worry about the lifetime of our copy.
|
||||
rc = ble_gap_ext_adv_rsp_set_data(0, &buf.mbuf);
|
||||
if (rc != NIMBLE_OK) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ble_gap_ext_adv_start(0, timeout / 10, 0);
|
||||
if (rc != NIMBLE_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return NIMBLE_OK;
|
||||
}
|
||||
|
||||
STATIC void check_data_fit(size_t data_len, bool connectable) {
|
||||
if (data_len > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE) ||
|
||||
(connectable && data_len > MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE))) {
|
||||
mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool connectable,
|
||||
bool anonymous, uint32_t timeout, mp_float_t interval,
|
||||
mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo,
|
||||
mp_int_t tx_power, const bleio_address_obj_t *directed_to) {
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
if (self->user_advertising) {
|
||||
mp_raise_bleio_BluetoothError(translate("Already advertising."));
|
||||
} else {
|
||||
// If the user isn't advertising, then the background is. So, stop the
|
||||
// background advertising so the user can.
|
||||
common_hal_bleio_adapter_stop_advertising(self);
|
||||
}
|
||||
// interval value has already been validated.
|
||||
|
||||
check_data_fit(advertising_data_bufinfo->len, connectable);
|
||||
check_data_fit(scan_response_data_bufinfo->len, connectable);
|
||||
|
||||
if (advertising_data_bufinfo->len > 31 && scan_response_data_bufinfo->len > 0) {
|
||||
mp_raise_bleio_BluetoothError(translate("Extended advertisements with scan response not supported."));
|
||||
}
|
||||
|
||||
|
||||
if (advertising_data_bufinfo->len > 0 && directed_to != NULL) {
|
||||
mp_raise_bleio_BluetoothError(translate("Data not supported with directed advertising"));
|
||||
}
|
||||
|
||||
if (anonymous) {
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
timeout = BLE_HS_FOREVER;
|
||||
} else if (timeout > INT32_MAX) {
|
||||
mp_raise_bleio_BluetoothError(translate("Timeout is too long: Maximum timeout length is %d seconds"),
|
||||
INT32_MAX / 1000);
|
||||
}
|
||||
|
||||
CHECK_NIMBLE_ERROR(_common_hal_bleio_adapter_start_advertising(self, connectable, anonymous, timeout, interval,
|
||||
advertising_data_bufinfo->buf,
|
||||
advertising_data_bufinfo->len,
|
||||
scan_response_data_bufinfo->buf,
|
||||
scan_response_data_bufinfo->len,
|
||||
tx_power,
|
||||
directed_to));
|
||||
self->user_advertising = true;
|
||||
}
|
||||
|
||||
void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
|
||||
mp_raise_NotImplementedError(NULL);
|
||||
int err_code = ble_gap_ext_adv_stop(0);
|
||||
self->user_advertising = false;
|
||||
|
||||
if ((err_code != NIMBLE_OK) &&
|
||||
(err_code != BLE_HS_EALREADY) &&
|
||||
(err_code != BLE_HS_EINVAL)) {
|
||||
CHECK_NIMBLE_ERROR(err_code);
|
||||
}
|
||||
}
|
||||
|
||||
bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) {
|
||||
return self->current_advertising_data != NULL;
|
||||
return ble_gap_adv_active();
|
||||
}
|
||||
|
||||
bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) {
|
||||
@ -328,7 +539,7 @@ void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) {
|
||||
|
||||
void bleio_adapter_reset(bleio_adapter_obj_t *adapter) {
|
||||
common_hal_bleio_adapter_stop_scan(adapter);
|
||||
if (adapter->current_advertising_data != NULL) {
|
||||
if (common_hal_bleio_adapter_get_advertising(adapter)) {
|
||||
common_hal_bleio_adapter_stop_advertising(adapter);
|
||||
}
|
||||
|
||||
|
@ -47,11 +47,6 @@ extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUN
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
// Pointer to buffers we maintain so that the data is long lived.
|
||||
uint8_t *advertising_data;
|
||||
uint8_t *scan_response_data;
|
||||
// Pointer to current data.
|
||||
const uint8_t *current_advertising_data;
|
||||
bleio_scanresults_obj_t *scan_results;
|
||||
mp_obj_t name;
|
||||
mp_obj_tuple_t *connection_objs;
|
||||
|
@ -48,6 +48,38 @@
|
||||
|
||||
#include "host/ble_att.h"
|
||||
|
||||
int bleio_connection_event_cb(struct ble_gap_event *event, void *connection_in) {
|
||||
bleio_connection_internal_t *connection = (bleio_connection_internal_t *)connection_in;
|
||||
|
||||
switch (event->type) {
|
||||
case BLE_GAP_EVENT_DISCONNECT: {
|
||||
connection->conn_handle = BLEIO_HANDLE_INVALID;
|
||||
connection->pair_status = PAIR_NOT_PAIRED;
|
||||
|
||||
#if CIRCUITPY_VERBOSE_BLE
|
||||
mp_printf(&mp_plat_print, "disconnected %02x\n", event->disconnect.reason);
|
||||
#endif
|
||||
if (connection->connection_obj != mp_const_none) {
|
||||
bleio_connection_obj_t *obj = connection->connection_obj;
|
||||
obj->connection = NULL;
|
||||
obj->disconnect_reason = event->disconnect.reason;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVENT_PHY_UPDATE_COMPLETE: {
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
#if CIRCUITPY_VERBOSE_BLE
|
||||
mp_printf(&mp_plat_print, "Unhandled connection event: %d\n", event->type);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self) {
|
||||
if (self->connection == NULL) {
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include "shared-module/_bleio/Address.h"
|
||||
#include "common-hal/_bleio/Service.h"
|
||||
|
||||
#include "host/ble_gap.h"
|
||||
|
||||
typedef enum {
|
||||
PAIR_NOT_PAIRED,
|
||||
PAIR_WAITING,
|
||||
@ -81,6 +83,8 @@ typedef struct {
|
||||
|
||||
void bleio_connection_clear(bleio_connection_internal_t *self);
|
||||
|
||||
int bleio_connection_event_cb(struct ble_gap_event *event, void *connection_in);
|
||||
|
||||
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self);
|
||||
mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection);
|
||||
bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle);
|
||||
|
@ -42,6 +42,8 @@ void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, co
|
||||
ble_uuid_init_from_buf(&self->nimble_ble_uuid, (uint8_t *)&uuid16, 2);
|
||||
} else {
|
||||
ble_uuid_init_from_buf(&self->nimble_ble_uuid, uuid128, 16);
|
||||
self->nimble_ble_uuid.u128.value[12] = uuid16 & 0xff;
|
||||
self->nimble_ble_uuid.u128.value[13] = (uuid16 >> 8) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,3 +65,35 @@ void bleio_background(void) {
|
||||
void common_hal_bleio_gc_collect(void) {
|
||||
bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
|
||||
}
|
||||
|
||||
void check_nimble_error(int rc, const char *file, size_t line) {
|
||||
if (rc == NIMBLE_OK) {
|
||||
return;
|
||||
}
|
||||
switch (rc) {
|
||||
case BLE_HS_ENOMEM:
|
||||
mp_raise_msg(&mp_type_MemoryError, translate("Nimble out of memory"));
|
||||
return;
|
||||
case BLE_HS_ETIMEOUT:
|
||||
mp_raise_msg(&mp_type_TimeoutError, NULL);
|
||||
return;
|
||||
case BLE_HS_EINVAL:
|
||||
mp_raise_ValueError(translate("Invalid BLE parameter"));
|
||||
return;
|
||||
case BLE_HS_ENOTCONN:
|
||||
mp_raise_ConnectionError(translate("Not connected"));
|
||||
return;
|
||||
default:
|
||||
#if CIRCUITPY_VERBOSE_BLE
|
||||
if (file) {
|
||||
mp_raise_bleio_BluetoothError(translate("Unknown system firmware error at %s:%d: %d"), file, line, rc);
|
||||
}
|
||||
#else
|
||||
(void)file;
|
||||
(void)line;
|
||||
mp_raise_bleio_BluetoothError(translate("Unknown system firmware error: %d"), rc);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -39,4 +39,19 @@ void bleio_background(void);
|
||||
// 20 bytes max (23 - 3).
|
||||
#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3)
|
||||
|
||||
#define NIMBLE_OK (0)
|
||||
|
||||
void check_nimble_error(int rc, const char *file, size_t line);
|
||||
#define CHECK_NIMBLE_ERROR(rc) check_nimble_error(rc, __FILE__, __LINE__)
|
||||
|
||||
#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION))
|
||||
#define SEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000000) / (RESOLUTION))
|
||||
#define UNITS_TO_SEC(TIME, RESOLUTION) (((TIME)*(RESOLUTION)) / 1000000)
|
||||
// 0.625 msecs (625 usecs)
|
||||
#define ADV_INTERVAL_UNIT_FLOAT_SECS (0.000625)
|
||||
// Microseconds is the base unit. The macros above know that.
|
||||
#define UNIT_0_625_MS (625)
|
||||
#define UNIT_1_25_MS (1250)
|
||||
#define UNIT_10_MS (10000)
|
||||
|
||||
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_INIT_H
|
||||
|
Loading…
Reference in New Issue
Block a user