Merge pull request #5927 from tannewt/esp_ble_scan

Add BLE scanning for S3 and C3.
This commit is contained in:
Dan Halbert 2022-01-27 13:05:24 -05:00 committed by GitHub
commit fff68c9f86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 2582 additions and 55 deletions

View File

@ -35,7 +35,6 @@
#include "hci.h" #include "hci.h"
void bleio_hci_background(void); void bleio_hci_background(void);
void bleio_reset(void);
typedef struct { typedef struct {
// ble_gap_enc_key_t own_enc; // ble_gap_enc_key_t own_enc;

View File

@ -6,7 +6,7 @@ set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf)
# The component list here determines what options we get in menuconfig and what the ninja file # The component list here determines what options we get in menuconfig and what the ninja file
# can build. # can build.
set(COMPONENTS esptool_py soc driver log main esp-tls mbedtls esp_event esp_adc_cal esp_netif esp_wifi lwip wpa_supplicant freertos) set(COMPONENTS esptool_py soc driver log main esp-tls mbedtls esp_event esp_adc_cal esp_netif esp_wifi lwip wpa_supplicant freertos bt)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(circuitpython) project(circuitpython)

View File

@ -86,6 +86,14 @@ INC += \
-isystem esp-idf \ -isystem esp-idf \
-isystem esp-idf/components/app_update/include \ -isystem esp-idf/components/app_update/include \
-isystem esp-idf/components/bootloader_support/include \ -isystem esp-idf/components/bootloader_support/include \
-isystem esp-idf/components/bt/host/nimble/esp-hci/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 \
-isystem esp-idf/components/bt/host/nimble/nimble/nimble/host/util/include \
-isystem esp-idf/components/bt/host/nimble/nimble/porting/nimble/include \
-isystem esp-idf/components/bt/host/nimble/nimble/porting/npl/freertos/include \
-isystem esp-idf/components/bt/host/nimble/port/include \
-isystem esp-idf/components/driver/include \ -isystem esp-idf/components/driver/include \
-isystem esp-idf/components/driver/$(IDF_TARGET)/include \ -isystem esp-idf/components/driver/$(IDF_TARGET)/include \
-isystem esp-idf/components/$(IDF_TARGET)/include \ -isystem esp-idf/components/$(IDF_TARGET)/include \
@ -133,6 +141,7 @@ endif
CFLAGS += \ CFLAGS += \
-DHAVE_CONFIG_H \ -DHAVE_CONFIG_H \
-DESP_PLATFORM=1 \
-DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" \ -DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" \
-DUNITY_INCLUDE_CONFIG_H -DWITH_POSIX -DUNITY_INCLUDE_CONFIG_H -DWITH_POSIX
@ -148,7 +157,12 @@ ifeq ($(DEBUG), 1)
# CFLAGS += -fno-inline -fno-ipa-sra # CFLAGS += -fno-inline -fno-ipa-sra
else else
CFLAGS += -DNDEBUG -ggdb3 CFLAGS += -DNDEBUG -ggdb3
OPTIMIZATION_FLAGS ?= -O2 ifeq ($(IDF_TARGET_ARCH),xtensa)
OPTIMIZATION_FLAGS ?= -O2
else
# RISC-V is larger than xtensa so do -Os for it
OPTIMIZATION_FLAGS ?= -Os
endif
# TODO: Test with -flto # TODO: Test with -flto
### CFLAGS += -flto ### CFLAGS += -flto
endif endif
@ -298,8 +312,10 @@ else
DEBUG_SDKCONFIG = esp-idf-config/sdkconfig-opt.defaults DEBUG_SDKCONFIG = esp-idf-config/sdkconfig-opt.defaults
endif endif
SDKCONFIGS = esp-idf-config/sdkconfig.defaults;$(DEBUG_SDKCONFIG);$(FLASH_SDKCONFIG);$(TARGET_SDKCONFIG);boards/$(BOARD)/sdkconfig SDKCONFIGS := esp-idf-config/sdkconfig.defaults;$(DEBUG_SDKCONFIG);$(FLASH_SDKCONFIG);$(TARGET_SDKCONFIG);boards/$(BOARD)/sdkconfig
ifneq ($(CIRCUITPY_BLEIO),0)
SDKCONFIGS := esp-idf-config/sdkconfig-ble.defaults;$(SDKCONFIGS)
endif
# create the config headers # create the config headers
$(BUILD)/esp-idf/config/sdkconfig.h: boards/$(BOARD)/sdkconfig | $(BUILD)/esp-idf $(BUILD)/esp-idf/config/sdkconfig.h: boards/$(BOARD)/sdkconfig | $(BUILD)/esp-idf
IDF_PATH=$(IDF_PATH) cmake -S . -B $(BUILD)/esp-idf -DSDKCONFIG=$(BUILD)/esp-idf/sdkconfig -DSDKCONFIG_DEFAULTS="$(SDKCONFIGS)" -DCMAKE_TOOLCHAIN_FILE=$(IDF_PATH)/tools/cmake/toolchain-$(IDF_TARGET).cmake -DIDF_TARGET=$(IDF_TARGET) -GNinja IDF_PATH=$(IDF_PATH) cmake -S . -B $(BUILD)/esp-idf -DSDKCONFIG=$(BUILD)/esp-idf/sdkconfig -DSDKCONFIG_DEFAULTS="$(SDKCONFIGS)" -DCMAKE_TOOLCHAIN_FILE=$(IDF_PATH)/tools/cmake/toolchain-$(IDF_TARGET).cmake -DIDF_TARGET=$(IDF_TARGET) -GNinja
@ -332,6 +348,12 @@ BINARY_WIFI_BLOBS = libcoexist.a libcore.a libespnow.a libmesh.a libnet80211.a l
BINARY_BLOBS = esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libphy.a $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, $(BINARY_WIFI_BLOBS)) BINARY_BLOBS = esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libphy.a $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, $(BINARY_WIFI_BLOBS))
ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) app_update bootloader_support driver efuse esp_adc_cal esp_common esp_event esp_hw_support esp_ipc esp_netif esp_pm esp_phy esp_ringbuf esp_rom esp_system esp_timer esp-tls esp_wifi freertos hal heap log lwip mbedtls newlib nvs_flash pthread soc spi_flash vfs wpa_supplicant ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) app_update bootloader_support driver efuse esp_adc_cal esp_common esp_event esp_hw_support esp_ipc esp_netif esp_pm esp_phy esp_ringbuf esp_rom esp_system esp_timer esp-tls esp_wifi freertos hal heap log lwip mbedtls newlib nvs_flash pthread soc spi_flash vfs wpa_supplicant
ifneq ($(CIRCUITPY_BLEIO),0)
ESP_IDF_COMPONENTS_LINK += bt
BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libbtbb.a \
esp-idf/components/bt/controller/lib_esp32c3_family/$(IDF_TARGET)/libbtdm_app.a
endif
ESP_IDF_COMPONENTS_EXPANDED = $(foreach component, $(ESP_IDF_COMPONENTS_LINK), $(BUILD)/esp-idf/esp-idf/$(component)/lib$(component).a) ESP_IDF_COMPONENTS_EXPANDED = $(foreach component, $(ESP_IDF_COMPONENTS_LINK), $(BUILD)/esp-idf/esp-idf/$(component)/lib$(component).a)
MBEDTLS_COMPONENTS_LINK = crypto tls x509 MBEDTLS_COMPONENTS_LINK = crypto tls x509
@ -350,6 +372,11 @@ else
BOOTLOADER_OFFSET = 0x1000 BOOTLOADER_OFFSET = 0x1000
endif endif
IDF_CMAKE_TARGETS = \
bootloader/bootloader.bin \
esp-idf/esp_system/__ldgen_output_sections.ld \
$(foreach component, $(ESP_IDF_COMPONENTS_LINK), esp-idf/$(component)/lib$(component).a)
PARTITION_TABLE_OFFSET = 0x8000 PARTITION_TABLE_OFFSET = 0x8000
FIRMWARE_OFFSET = 0x10000 FIRMWARE_OFFSET = 0x10000
@ -367,41 +394,7 @@ endif
.PHONY: esp-idf-stamp .PHONY: esp-idf-stamp
esp-idf-stamp: $(BUILD)/esp-idf/config/sdkconfig.h esp-idf-stamp: $(BUILD)/esp-idf/config/sdkconfig.h
$(Q)ninja -C $(BUILD)/esp-idf \ $(Q)ninja -C $(BUILD)/esp-idf $(IDF_CMAKE_TARGETS)
bootloader/bootloader.bin \
esp-idf/esp_system/__ldgen_output_sections.ld \
esp-idf/app_update/libapp_update.a \
esp-idf/bootloader_support/libbootloader_support.a \
esp-idf/driver/libdriver.a \
esp-idf/efuse/libefuse.a \
esp-idf/esp_adc_cal/libesp_adc_cal.a \
esp-idf/esp_common/libesp_common.a \
esp-idf/esp_event/libesp_event.a \
esp-idf/esp_hw_support/libesp_hw_support.a \
esp-idf/esp_ipc/libesp_ipc.a \
esp-idf/esp_netif/libesp_netif.a \
esp-idf/esp_phy/libesp_phy.a \
esp-idf/esp_pm/libesp_pm.a \
esp-idf/esp_ringbuf/libesp_ringbuf.a \
esp-idf/esp_rom/libesp_rom.a \
esp-idf/esp_system/libesp_system.a \
esp-idf/esp_timer/libesp_timer.a \
esp-idf/esp-tls/libesp-tls.a \
esp-idf/esp_wifi/libesp_wifi.a \
esp-idf/freertos/libfreertos.a \
esp-idf/hal/libhal.a \
esp-idf/heap/libheap.a \
esp-idf/log/liblog.a \
esp-idf/lwip/liblwip.a \
esp-idf/mbedtls/libmbedtls.a \
esp-idf/newlib/libnewlib.a \
esp-idf/nvs_flash/libnvs_flash.a \
esp-idf/pthread/libpthread.a \
esp-idf/soc/libsoc.a \
esp-idf/spi_flash/libspi_flash.a \
esp-idf/vfs/libvfs.a \
esp-idf/wpa_supplicant/libwpa_supplicant.a \
esp-idf/$(IDF_TARGET_ARCH)/lib$(IDF_TARGET_ARCH).a
$(BUILD)/firmware.elf: $(OBJ) | esp-idf-stamp $(BUILD)/firmware.elf: $(OBJ) | esp-idf-stamp
$(STEPECHO) "LINK $@" $(STEPECHO) "LINK $@"

View File

@ -0,0 +1,356 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2016 Glenn Ruben Bakke
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "py/gc.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "supervisor/shared/bluetooth/bluetooth.h"
#include "supervisor/shared/safe_mode.h"
#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Address.h"
#include "shared-bindings/nvm/ByteArray.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/ScanEntry.h"
#include "shared-bindings/time/__init__.h"
#include "nimble/hci_common.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_gap.h"
#include "host/util/util.h"
#include "services/gap/ble_svc_gap.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) {
// supervisor_bluetooth_background();
// bleio_background();
// }
bool ble_active = false;
static void nimble_host_task(void *param) {
nimble_port_run();
nimble_port_freertos_deinit();
}
static TaskHandle_t cp_task = NULL;
static void _on_sync(void) {
int rc = ble_hs_util_ensure_addr(0);
assert(rc == 0);
xTaskNotifyGive(cp_task);
}
void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) {
const bool is_enabled = common_hal_bleio_adapter_get_enabled(self);
// Don't enable or disable twice
if (is_enabled == enabled) {
return;
}
if (enabled) {
esp_nimble_hci_and_controller_init();
nimble_port_init();
// ble_hs_cfg.reset_cb = blecent_on_reset;
ble_hs_cfg.sync_cb = _on_sync;
// ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
ble_svc_gap_device_name_set("CIRCUITPY");
cp_task = xTaskGetCurrentTaskHandle();
nimble_port_freertos_init(nimble_host_task);
// Wait for sync.
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(200));
} else {
nimble_port_stop();
}
}
bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) {
return xTaskGetHandle("ble") != NULL;
}
bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) {
uint8_t address_bytes[6];
uint8_t address_type = BLE_ADDR_RANDOM;
ble_hs_id_infer_auto(0, &address_type);
int result = ble_hs_id_copy_addr(address_type, address_bytes, NULL);
if (result != 0) {
return NULL;
}
bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
address->base.type = &bleio_address_type;
common_hal_bleio_address_construct(address, address_bytes, BLEIO_ADDRESS_TYPE_RANDOM_STATIC);
return address;
}
bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_address_obj_t *address) {
if (address->type != BLEIO_ADDRESS_TYPE_RANDOM_STATIC) {
return false;
}
mp_buffer_info_t bufinfo;
if (!mp_get_buffer(address->bytes, &bufinfo, MP_BUFFER_READ)) {
return false;
}
int result = ble_hs_id_set_rnd(bufinfo.buf);
return result == 0;
}
mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) {
const char *name = ble_svc_gap_device_name();
return mp_obj_new_str(name, strlen(name));
}
void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char *name) {
ble_svc_gap_device_name_set(name);
}
static int _scan_event(struct ble_gap_event *event, void *scan_results_in) {
bleio_scanresults_obj_t *scan_results = (bleio_scanresults_obj_t *)scan_results_in;
if (event->type == BLE_GAP_EVENT_DISC_COMPLETE) {
shared_module_bleio_scanresults_set_done(scan_results, true);
return 0;
}
if (event->type != BLE_GAP_EVENT_DISC && event->type != BLE_GAP_EVENT_EXT_DISC) {
ESP_LOGI(TAG, "unsupported scan event %d", event->type);
return 0;
}
if (event->type == BLE_GAP_EVENT_DISC) {
// Legacy advertisement
struct ble_gap_disc_desc *disc = &event->disc;
bool connectable = disc->event_type == BLE_HCI_ADV_RPT_EVTYPE_ADV_IND ||
disc->event_type == BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
shared_module_bleio_scanresults_append(scan_results,
supervisor_ticks_ms64(),
connectable,
disc->event_type == BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP,
disc->rssi,
disc->addr.val,
disc->addr.type,
disc->data,
disc->length_data);
} else {
// Extended advertisement
struct ble_gap_ext_disc_desc *disc = &event->ext_disc;
shared_module_bleio_scanresults_append(scan_results,
supervisor_ticks_ms64(),
(disc->props & BLE_HCI_ADV_CONN_MASK) != 0,
(disc->props & BLE_HCI_ADV_SCAN_MASK) != 0,
disc->rssi,
disc->addr.val,
disc->addr.type,
disc->data,
disc->length_data);
}
return 0;
}
mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t *prefixes,
size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout,
mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) {
if (self->scan_results != NULL) {
if (!shared_module_bleio_scanresults_get_done(self->scan_results)) {
mp_raise_bleio_BluetoothError(translate("Scan already in progess. Stop with stop_scan."));
}
self->scan_results = NULL;
}
self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi);
// size_t max_packet_size = extended ? BLE_HCI_MAX_EXT_ADV_DATA_LEN : BLE_HCI_MAX_ADV_DATA_LEN;
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.
}
disc_params.filter_duplicates = 0;
disc_params.passive = !active;
disc_params.itvl = interval / 0.625;
disc_params.window = window / 0.625;
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);
}
return MP_OBJ_FROM_PTR(self->scan_results);
}
void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) {
if (self->scan_results == NULL) {
return;
}
ble_gap_disc_cancel();
shared_module_bleio_scanresults_set_done(self->scan_results, true);
self->scan_results = NULL;
}
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);
mp_raise_bleio_BluetoothError(translate("Failed to connect: internal error"));
return mp_const_none;
}
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;
}
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);
}
void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) {
mp_raise_NotImplementedError(NULL);
}
bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) {
return self->current_advertising_data != NULL;
}
bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) {
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
if (connection->conn_handle != BLEIO_HANDLE_INVALID) {
return true;
}
}
return false;
}
mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) {
if (self->connection_objs != NULL) {
return self->connection_objs;
}
size_t total_connected = 0;
mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT];
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
if (connection->conn_handle != BLEIO_HANDLE_INVALID) {
if (connection->connection_obj == mp_const_none) {
connection->connection_obj = bleio_connection_new_from_internal(connection);
}
items[total_connected] = connection->connection_obj;
total_connected++;
}
}
self->connection_objs = mp_obj_new_tuple(total_connected, items);
return self->connection_objs;
}
void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) {
mp_raise_NotImplementedError(NULL);
// bonding_erase_storage();
}
bool common_hal_bleio_adapter_is_bonded_to_central(bleio_adapter_obj_t *self) {
mp_raise_NotImplementedError(NULL);
// return bonding_peripheral_bond_count() > 0;
return false;
}
void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) {
// We divide by size_t so that we can scan each 32-bit aligned value to see
// if it is a pointer. This allows us to change the structs without worrying
// about collecting new pointers.
gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / (sizeof(size_t)));
gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / (sizeof(size_t)));
}
void bleio_adapter_reset(bleio_adapter_obj_t *adapter) {
common_hal_bleio_adapter_stop_scan(adapter);
if (adapter->current_advertising_data != NULL) {
common_hal_bleio_adapter_stop_advertising(adapter);
}
adapter->connection_objs = NULL;
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
// Disconnect all connections cleanly.
if (connection->conn_handle != BLEIO_HANDLE_INVALID) {
common_hal_bleio_connection_disconnect(connection);
}
connection->connection_obj = mp_const_none;
}
// Wait up to 125 ms (128 ticks) for disconnect to complete. This should be
// greater than most connection intervals.
bool any_connected = false;
uint64_t start_ticks = supervisor_ticks_ms64();
while (any_connected && supervisor_ticks_ms64() - start_ticks < 128) {
any_connected = false;
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
any_connected |= connection->conn_handle != BLEIO_HANDLE_INVALID;
}
}
}

View File

@ -0,0 +1,65 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_ADAPTER_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_ADAPTER_H
#include "py/obj.h"
#include "py/objtuple.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/ScanResults.h"
#include "supervisor/background_callback.h"
#ifndef BLEIO_TOTAL_CONNECTION_COUNT
#define BLEIO_TOTAL_CONNECTION_COUNT 5
#endif
#define BLEIO_HANDLE_INVALID 0xffff
extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT];
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;
background_callback_t background_callback;
bool user_advertising;
} bleio_adapter_obj_t;
void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter);
void bleio_adapter_reset(bleio_adapter_obj_t *adapter);
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_ADAPTER_H

View File

@ -0,0 +1,29 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/_bleio/Attribute.h"
// Convert a _bleio security mode to a ble_gap_conn_sec_mode_t setting.

View File

@ -0,0 +1,32 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_ATTRIBUTE_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_ATTRIBUTE_H
#include "shared-module/_bleio/Attribute.h"
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_ATTRIBUTE_H

View File

@ -0,0 +1,127 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/Service.h"
#include "common-hal/_bleio/Adapter.h"
// #include "common-hal/_bleio/bonding.h"
void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service,
uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props,
bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm,
mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo,
const char *user_description) {
mp_raise_NotImplementedError(NULL);
self->service = service;
self->uuid = uuid;
self->handle = BLEIO_HANDLE_INVALID;
self->props = props;
self->read_perm = read_perm;
self->write_perm = write_perm;
self->initial_value_len = 0;
self->initial_value = NULL;
if (initial_value_bufinfo != NULL) {
// Copy the initial value if it's on the heap. Otherwise it's internal and we may not be able
// to allocate.
self->initial_value_len = initial_value_bufinfo->len;
if (gc_alloc_possible()) {
if (gc_nbytes(initial_value_bufinfo->buf) > 0) {
uint8_t *initial_value = m_malloc(self->initial_value_len, false);
memcpy(initial_value, initial_value_bufinfo->buf, self->initial_value_len);
self->initial_value = initial_value;
} else {
self->initial_value = initial_value_bufinfo->buf;
}
self->descriptor_list = mp_obj_new_list(0, NULL);
} else {
self->initial_value = initial_value_bufinfo->buf;
self->descriptor_list = NULL;
}
}
// const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
// if (max_length < 0 || max_length > max_length_max) {
// mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
// max_length_max, fixed_length ? "True" : "False");
// }
// TODO: Implement this.
self->max_length = max_length;
self->fixed_length = fixed_length;
if (service->is_remote) {
self->handle = handle;
} else {
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo, user_description);
}
}
mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) {
if (self->descriptor_list == NULL) {
return mp_const_empty_tuple;
}
return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items);
}
bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) {
return self->service;
}
size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t *buf, size_t len) {
// TODO: Implement this.
return 0;
}
size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristic_obj_t *self) {
return self->max_length;
}
void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
// TODO: Implement this.
}
bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) {
return self->uuid;
}
bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) {
return self->props;
}
void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) {
// TODO: Implement this.
}
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
// TODO: Implement this.
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
#include "shared-bindings/_bleio/Attribute.h"
#include "common-hal/_bleio/Descriptor.h"
#include "shared-module/_bleio/Characteristic.h"
#include "common-hal/_bleio/Service.h"
#include "common-hal/_bleio/UUID.h"
typedef struct _bleio_characteristic_obj {
mp_obj_base_t base;
// Will be MP_OBJ_NULL before being assigned to a Service.
bleio_service_obj_t *service;
bleio_uuid_obj_t *uuid;
const uint8_t *initial_value;
uint16_t initial_value_len;
uint16_t max_length;
uint16_t handle;
bleio_characteristic_properties_t props;
bleio_attribute_security_mode_t read_perm;
bleio_attribute_security_mode_t write_perm;
mp_obj_list_t *descriptor_list;
uint16_t user_desc_handle;
uint16_t cccd_handle;
uint16_t sccd_handle;
bool fixed_length;
} bleio_characteristic_obj_t;
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CHARACTERISTIC_H

View File

@ -0,0 +1,95 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#include "shared/runtime/interrupt_char.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Connection.h"
#include "supervisor/shared/tick.h"
#include "common-hal/_bleio/CharacteristicBuffer.h"
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
void _common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self,
bleio_characteristic_obj_t *characteristic,
mp_float_t timeout,
uint8_t *buffer, size_t buffer_size,
void *static_handler_entry) {
mp_raise_NotImplementedError(NULL);
self->characteristic = characteristic;
self->timeout_ms = timeout * 1000;
self->ringbuf.buf = (uint8_t *)buffer;
self->ringbuf.size = buffer_size;
self->ringbuf.iget = 0;
self->ringbuf.iput = 0;
}
// Assumes that timeout and buffer_size have been validated before call.
void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self,
bleio_characteristic_obj_t *characteristic,
mp_float_t timeout,
size_t buffer_size) {
uint8_t *buffer = m_malloc(buffer_size, true);
_common_hal_bleio_characteristic_buffer_construct(self, characteristic, timeout, buffer, buffer_size, NULL);
}
uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
// TODO: Implement this.
return 0;
}
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
// TODO: Implement this.
return 0;
}
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) {
// TODO: Implement this.
}
bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) {
return self->characteristic == NULL;
}
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
// TODO: Implement this.
}
bool common_hal_bleio_characteristic_buffer_connected(bleio_characteristic_buffer_obj_t *self) {
return self->characteristic != NULL &&
self->characteristic->service != NULL &&
(!self->characteristic->service->is_remote ||
(self->characteristic->service->connection != MP_OBJ_NULL &&
common_hal_bleio_connection_get_connected(self->characteristic->service->connection)));
}

View File

@ -0,0 +1,41 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
#include "py/ringbuf.h"
#include "shared-bindings/_bleio/Characteristic.h"
typedef struct {
mp_obj_base_t base;
bleio_characteristic_obj_t *characteristic;
uint32_t timeout_ms;
// Ring buffer storing consecutive incoming values.
ringbuf_t ringbuf;
} bleio_characteristic_buffer_obj_t;
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H

View File

@ -0,0 +1,134 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "shared-bindings/_bleio/Connection.h"
#include <string.h>
#include <stdio.h>
#include "shared/runtime/interrupt_char.h"
#include "py/gc.h"
#include "py/objlist.h"
#include "py/objstr.h"
#include "py/qstr.h"
#include "py/runtime.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Attribute.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
#include "supervisor/shared/tick.h"
// #include "common-hal/_bleio/bonding.h"
#include "host/ble_att.h"
bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self) {
if (self->connection == NULL) {
return false;
}
return self->connection->pair_status == PAIR_PAIRED;
}
bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) {
if (self->connection == NULL) {
return false;
}
return self->connection->conn_handle != BLEIO_HANDLE_INVALID;
}
void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) {
// TODO: Implement this.
}
void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond) {
// TODO: Implement this.
}
mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self) {
// TODO: Implement this.
while (self->conn_params_updating && !mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
return 0;
}
// Return the current negotiated MTU length, minus overhead.
mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self) {
return (self->mtu == 0 ? BLE_ATT_MTU_DFLT : self->mtu) - 3;
}
void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval) {
self->conn_params_updating = true;
// TODO: Implement this.
}
mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) {
bleio_connection_ensure_connected(self);
// Convert to a tuple and then clear the list so the callee will take ownership.
mp_obj_tuple_t *services_tuple =
mp_obj_new_tuple(self->connection->remote_service_list->len,
self->connection->remote_service_list->items);
mp_obj_list_clear(MP_OBJ_FROM_PTR(self->connection->remote_service_list));
// TODO: Implement this.
return services_tuple;
}
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) {
if (self == NULL || self->connection == NULL) {
return BLEIO_HANDLE_INVALID;
}
return self->connection->conn_handle;
}
mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *internal) {
if (internal->connection_obj != mp_const_none) {
return internal->connection_obj;
}
bleio_connection_obj_t *connection = m_new_obj(bleio_connection_obj_t);
connection->base.type = &bleio_connection_type;
connection->connection = internal;
internal->connection_obj = connection;
return MP_OBJ_FROM_PTR(connection);
}
// Find the connection that uses the given conn_handle. Return NULL if not found.
bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle) {
bleio_connection_internal_t *connection;
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
connection = &bleio_connections[i];
if (connection->conn_handle == conn_handle) {
return connection;
}
}
return NULL;
}

View File

@ -0,0 +1,88 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CONNECTION_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CONNECTION_H
#include <stdbool.h>
#include "py/obj.h"
#include "py/objlist.h"
#include "common-hal/_bleio/__init__.h"
// #include "common-hal/_bleio/bonding.h"
#include "shared-module/_bleio/Address.h"
#include "common-hal/_bleio/Service.h"
typedef enum {
PAIR_NOT_PAIRED,
PAIR_WAITING,
PAIR_PAIRED,
} pair_status_t;
// We split the Connection object into two so that the internal mechanics can live outside of the
// VM. If it were one object, then we'd risk user code seeing a connection object of theirs be
// reused.
typedef struct {
uint16_t conn_handle;
bool is_central;
// Remote services discovered when this peripheral is acting as a client.
mp_obj_list_t *remote_service_list;
// The advertising data and scan response buffers are held by us, not by the SD, so we must
// maintain them and not change it. If we need to change the contents during advertising,
// there are tricks to get the SD to notice (see DevZone - TBS).
// bonding_keys_t bonding_keys;
// EDIV: Encrypted Diversifier: Identifies LTK during legacy pairing.
uint16_t ediv;
volatile pair_status_t pair_status;
uint8_t sec_status; // Internal security status.
mp_obj_t connection_obj;
volatile bool conn_params_updating;
uint16_t mtu;
// Request that CCCD values for this connection be saved, using sys_attr values.
volatile bool do_bond_cccds;
// Request that security key info for this connection be saved.
volatile bool do_bond_keys;
// Time of setting do_bond_ccds: we delay a bit to consolidate multiple CCCD changes
// into one write. Time is currently in ticks_ms.
uint64_t do_bond_cccds_request_time;
} bleio_connection_internal_t;
typedef struct {
mp_obj_base_t base;
bleio_connection_internal_t *connection;
// The HCI disconnect reason.
uint8_t disconnect_reason;
} bleio_connection_obj_t;
void bleio_connection_clear(bleio_connection_internal_t *self);
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);
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_CONNECTION_H

View File

@ -0,0 +1,97 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
#include "host/ble_att.h"
void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) {
mp_raise_NotImplementedError(NULL);
self->characteristic = characteristic;
self->uuid = uuid;
self->handle = BLEIO_HANDLE_INVALID;
self->read_perm = read_perm;
self->write_perm = write_perm;
self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
const mp_int_t max_length_max = BLE_ATT_ATTR_MAX_LEN;
if (max_length < 0 || max_length > max_length_max) {
mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"),
max_length_max, fixed_length ? "True" : "False");
}
self->max_length = max_length;
self->fixed_length = fixed_length;
}
bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
return self->uuid;
}
bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) {
return self->characteristic;
}
size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t *buf, size_t len) {
// Do GATT operations only if this descriptor has been registered
if (self->handle != BLEIO_HANDLE_INVALID) {
uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection);
(void)conn_handle;
}
// TODO: Implement this.
return 0;
}
void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) {
// TODO: Implement this.
// Do GATT operations only if this descriptor has been registered.
if (self->handle != BLEIO_HANDLE_INVALID) {
// uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection);
if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
// false means WRITE_REQ, not write-no-response
// common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false);
} else {
// Validate data length for local descriptors only.
if (self->fixed_length && bufinfo->len != self->max_length) {
mp_raise_ValueError(translate("Value length != required fixed length"));
}
if (bufinfo->len > self->max_length) {
mp_raise_ValueError(translate("Value length > max_length"));
}
// common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo);
}
}
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_DESCRIPTOR_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_DESCRIPTOR_H
#include "py/obj.h"
#include "common-hal/_bleio/UUID.h"
// Forward declare characteristic because it includes a Descriptor.
struct _bleio_characteristic_obj;
typedef struct _bleio_descriptor_obj {
mp_obj_base_t base;
// Will be MP_OBJ_NULL before being assigned to a Characteristic.
struct _bleio_characteristic_obj *characteristic;
bleio_uuid_obj_t *uuid;
mp_obj_t initial_value;
uint16_t max_length;
bool fixed_length;
uint16_t handle;
bleio_attribute_security_mode_t read_perm;
bleio_attribute_security_mode_t write_perm;
} bleio_descriptor_obj_t;
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_DESCRIPTOR_H

View File

@ -0,0 +1,275 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019-2020 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include <stdio.h>
#include "shared/runtime/interrupt_char.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/PacketBuffer.h"
#include "supervisor/shared/tick.h"
#include "supervisor/shared/bluetooth/serial.h"
#include "host/ble_att.h"
void _common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
uint32_t *incoming_buffer, size_t incoming_buffer_size,
uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t max_packet_size,
void *static_handler_entry) {
mp_raise_NotImplementedError(NULL);
self->characteristic = characteristic;
self->client = self->characteristic->service->is_remote;
self->max_packet_size = max_packet_size;
bleio_characteristic_properties_t incoming = self->characteristic->props & (CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE);
bleio_characteristic_properties_t outgoing = self->characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE);
if (self->client) {
// Swap if we're the client.
bleio_characteristic_properties_t temp = incoming;
incoming = outgoing;
outgoing = temp;
self->conn_handle = bleio_connection_get_conn_handle(MP_OBJ_TO_PTR(self->characteristic->service->connection));
} else {
self->conn_handle = BLEIO_HANDLE_INVALID;
}
if (incoming) {
self->ringbuf.buf = (uint8_t *)incoming_buffer;
self->ringbuf.size = incoming_buffer_size;
self->ringbuf.iget = 0;
self->ringbuf.iput = 0;
}
self->packet_queued = false;
self->pending_index = 0;
self->pending_size = 0;
self->outgoing[0] = outgoing_buffer1;
self->outgoing[1] = outgoing_buffer2;
}
void common_hal_bleio_packet_buffer_construct(
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
size_t buffer_size, size_t max_packet_size) {
// Cap the packet size to our implementation limits.
max_packet_size = MIN(max_packet_size, BLE_ATT_ATTR_MAX_LEN - 3);
bleio_characteristic_properties_t incoming = characteristic->props & (CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE);
bleio_characteristic_properties_t outgoing = characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE);
if (characteristic->service->is_remote) {
// Swap if we're the client.
bleio_characteristic_properties_t temp = incoming;
incoming = outgoing;
outgoing = temp;
}
size_t incoming_buffer_size = 0;
uint32_t *incoming_buffer = NULL;
if (incoming) {
incoming_buffer_size = buffer_size * (sizeof(uint16_t) + max_packet_size);
incoming_buffer = m_malloc(incoming_buffer_size, false);
}
uint32_t *outgoing1 = NULL;
uint32_t *outgoing2 = NULL;
if (outgoing) {
outgoing1 = m_malloc(max_packet_size, false);
outgoing2 = m_malloc(max_packet_size, false);
}
_common_hal_bleio_packet_buffer_construct(self, characteristic,
incoming_buffer, incoming_buffer_size,
outgoing1, outgoing2, max_packet_size,
NULL);
}
mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) {
if (ringbuf_num_filled(&self->ringbuf) < 2) {
return 0;
}
// Copy received data. Lock out write interrupt handler while copying.
// TODO: Implement this.
return 0;
}
mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, const uint8_t *data, size_t len, uint8_t *header, size_t header_len) {
if (self->outgoing[0] == NULL) {
mp_raise_bleio_BluetoothError(translate("Writes not supported on Characteristic"));
}
if (self->conn_handle == BLEIO_HANDLE_INVALID) {
return -1;
}
mp_int_t outgoing_packet_length = common_hal_bleio_packet_buffer_get_outgoing_packet_length(self);
if (outgoing_packet_length < 0) {
return -1;
}
mp_int_t total_len = len + header_len;
if (total_len > outgoing_packet_length) {
// Supplied data will not fit in a single BLE packet.
mp_raise_ValueError_varg(translate("Total data to write is larger than %q"), MP_QSTR_outgoing_packet_length);
}
if (total_len > self->max_packet_size) {
// Supplied data will not fit in a single BLE packet.
mp_raise_ValueError_varg(translate("Total data to write is larger than %q"), MP_QSTR_max_packet_size);
}
outgoing_packet_length = MIN(outgoing_packet_length, self->max_packet_size);
if (len + self->pending_size > (size_t)outgoing_packet_length) {
// No room to append len bytes to packet. Wait until we get a free buffer,
// and keep checking that we haven't been disconnected.
while (self->pending_size != 0 &&
self->conn_handle != BLEIO_HANDLE_INVALID &&
!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
}
if (self->conn_handle == BLEIO_HANDLE_INVALID ||
mp_hal_is_interrupted()) {
return -1;
}
size_t num_bytes_written = 0;
uint32_t *pending = self->outgoing[self->pending_index];
if (self->pending_size == 0) {
memcpy(pending, header, header_len);
self->pending_size += header_len;
num_bytes_written += header_len;
}
memcpy(((uint8_t *)pending) + self->pending_size, data, len);
self->pending_size += len;
num_bytes_written += len;
// TODO: Implement this.
// If no writes are queued then sneak in this data.
if (!self->packet_queued) {
}
return num_bytes_written;
}
mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self) {
// If this PacketBuffer is coming from a remote service via NOTIFY or INDICATE
// the maximum size is what can be sent in one
// BLE packet. But we must be connected to know that value.
//
// Otherwise it can be as long as the characteristic
// will permit, whether or not we're connected.
if (self->characteristic == NULL) {
return -1;
}
if (self->characteristic->service != NULL &&
self->characteristic->service->is_remote &&
(common_hal_bleio_characteristic_get_properties(self->characteristic) &
(CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY))) {
// We are talking to a remote service, and data is arriving via NOTIFY or INDICATE.
if (self->conn_handle != BLEIO_HANDLE_INVALID) {
bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle);
if (connection) {
return common_hal_bleio_connection_get_max_packet_length(connection);
}
}
// There's no current connection, so we don't know the MTU, and
// we can't tell what the largest incoming packet length would be.
return -1;
}
return self->characteristic->max_length;
}
mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_buffer_obj_t *self) {
// If we are sending data via NOTIFY or INDICATE, the maximum size
// is what can be sent in one BLE packet. But we must be connected
// to know that value.
//
// Otherwise it can be as long as the characteristic
// will permit, whether or not we're connected.
if (self->characteristic == NULL) {
return -1;
}
if (self->characteristic->service != NULL &&
!self->characteristic->service->is_remote &&
(common_hal_bleio_characteristic_get_properties(self->characteristic) &
(CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY))) {
// We are sending to a client, via NOTIFY or INDICATE.
if (self->conn_handle != BLEIO_HANDLE_INVALID) {
bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle);
if (connection) {
return MIN(MIN(common_hal_bleio_connection_get_max_packet_length(connection),
self->max_packet_size),
self->characteristic->max_length);
}
}
// There's no current connection, so we don't know the MTU, and
// we can't tell what the largest outgoing packet length would be.
return -1;
}
// If we are talking to a remote service, we'll be bound by the MTU. (We don't actually
// know the max size of the remote characteristic.)
if (self->characteristic->service != NULL &&
self->characteristic->service->is_remote) {
// We are talking to a remote service so we're writing.
if (self->conn_handle != BLEIO_HANDLE_INVALID) {
bleio_connection_internal_t *connection = bleio_conn_handle_to_connection(self->conn_handle);
if (connection) {
return MIN(common_hal_bleio_connection_get_max_packet_length(connection),
self->max_packet_size);
}
}
}
return MIN(self->characteristic->max_length, self->max_packet_size);
}
void common_hal_bleio_packet_buffer_flush(bleio_packet_buffer_obj_t *self) {
while ((self->pending_size != 0 ||
self->packet_queued) &&
self->conn_handle != BLEIO_HANDLE_INVALID &&
!mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
}
}
bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {
return self->characteristic == NULL;
}
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) {
if (!common_hal_bleio_packet_buffer_deinited(self)) {
}
// TODO: Implement this.
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019-2020 Scott Shawcroft for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_PACKETBUFFER_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_PACKETBUFFER_H
#include "py/ringbuf.h"
#include "shared-bindings/_bleio/Characteristic.h"
typedef struct {
mp_obj_base_t base;
bleio_characteristic_obj_t *characteristic;
// Ring buffer storing consecutive incoming values.
ringbuf_t ringbuf;
// Two outgoing buffers to alternate between. One will be queued for transmission by the SD and
// the other is waiting to be queued and can be extended.
uint32_t *outgoing[2];
volatile uint16_t pending_size;
// We remember the conn_handle so we can do a NOTIFY/INDICATE to a client.
// We can find out the conn_handle on a Characteristic write or a CCCD write (but not a read).
volatile uint16_t conn_handle;
uint16_t max_packet_size;
uint8_t pending_index;
uint8_t write_type;
bool client;
bool packet_queued;
} bleio_packet_buffer_obj_t;
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_PACKETBUFFER_H

View File

@ -0,0 +1,94 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "common-hal/_bleio/__init__.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "host/ble_gatt.h"
uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t *characteristic_list) {
self->handle = 0xFFFF;
self->uuid = uuid;
self->characteristic_list = characteristic_list;
self->is_remote = false;
self->connection = NULL;
self->is_secondary = is_secondary;
// uint8_t service_type = BLE_GATT_SVC_TYPE_PRIMARY;
// if (is_secondary) {
// service_type = BLE_GATT_SVC_TYPE_SECONDARY;
// }
return 0;
}
void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) {
mp_raise_NotImplementedError(NULL);
_common_hal_bleio_service_construct(self, uuid, is_secondary,
mp_obj_new_list(0, NULL));
}
void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection) {
self->handle = 0xFFFF;
self->uuid = NULL;
self->characteristic_list = mp_obj_new_list(0, NULL);
self->is_remote = true;
self->is_secondary = false;
self->connection = connection;
}
bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
return self->uuid;
}
mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self) {
return mp_obj_new_tuple(self->characteristic_list->len, self->characteristic_list->items);
}
bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) {
return self->is_remote;
}
bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
return self->is_secondary;
}
void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
bleio_characteristic_obj_t *characteristic,
mp_buffer_info_t *initial_value_bufinfo,
const char *user_description) {
#if CIRCUITPY_VERBOSE_BLE
mp_printf(&mp_plat_print, "Char handle %x user %x cccd %x sccd %x\n", characteristic->handle, characteristic->user_desc_handle, characteristic->cccd_handle, characteristic->sccd_handle);
#endif
mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_SERVICE_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_SERVICE_H
#include "py/objlist.h"
#include "common-hal/_bleio/UUID.h"
typedef struct bleio_service_obj {
mp_obj_base_t base;
// Handle for the local service.
uint16_t handle;
// True if created during discovery.
bool is_remote;
bool is_secondary;
bleio_uuid_obj_t *uuid;
// The connection object is set only when this is a remote service.
// A local service doesn't know the connection.
mp_obj_t connection;
mp_obj_list_t *characteristic_list;
// Range of attribute handles of this remote service.
uint16_t start_handle;
uint16_t end_handle;
} bleio_service_obj_t;
void bleio_service_from_connection(bleio_service_obj_t *self, mp_obj_t connection);
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_SERVICE_H

View File

@ -0,0 +1,67 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#include "common-hal/_bleio/UUID.h"
#include "shared-bindings/_bleio/UUID.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
// If uuid128 is NULL, this is a Bluetooth SIG 16-bit UUID.
// If uuid128 is not NULL, it's a 128-bit (16-byte) UUID, with bytes 12 and 13 zero'd out, where
// the 16-bit part goes. Those 16 bits are passed in uuid16.
void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[16]) {
if (uuid128 == NULL) {
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);
}
}
uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) {
return self->nimble_ble_uuid.u.type == BLE_UUID_TYPE_16 ? 16 : 128;
}
uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) {
return self->nimble_ble_uuid.u16.value;
}
void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) {
memcpy(uuid128, self->nimble_ble_uuid.u128.value, 16);
}
void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t *buf) {
if (self->nimble_ble_uuid.u.type == BLE_UUID_TYPE_16) {
buf[0] = self->nimble_ble_uuid.u16.value & 0xff;
buf[1] = self->nimble_ble_uuid.u16.value >> 8;
} else {
common_hal_bleio_uuid_get_uuid128(self, buf);
}
}

View File

@ -0,0 +1,49 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_UUID_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_UUID_H
#include "py/obj.h"
#include "host/ble_uuid.h"
typedef struct {
mp_obj_base_t base;
// Use the native way of storing UUID's:
// - ble_uuid_t.uuid is a 16-bit uuid.
// - ble_uuid_t.type is BLE_UUID_TYPE_BLE if it's a 16-bit Bluetooth SIG UUID.
// or is BLE_UUID_TYPE_VENDOR_BEGIN and higher, which indexes into a table of registered
// 128-bit UUIDs.
ble_uuid_any_t nimble_ble_uuid;
} bleio_uuid_obj_t;
void bleio_uuid_construct_from_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_uuid);
void bleio_uuid_convert_to_nrf_ble_uuid(bleio_uuid_obj_t *self, ble_uuid_t *nrf_uuid);
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_UUID_H

View File

@ -0,0 +1,67 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2016 Glenn Ruben Bakke
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/_bleio/Characteristic.h"
#include "shared-bindings/_bleio/Connection.h"
#include "shared-bindings/_bleio/Descriptor.h"
#include "shared-bindings/_bleio/Service.h"
#include "shared-bindings/_bleio/UUID.h"
#include "supervisor/shared/bluetooth/bluetooth.h"
#include "common-hal/_bleio/__init__.h"
// #include "common-hal/_bleio/bonding.h"
// Turn off BLE on a reset or reload.
void bleio_reset() {
// Set this explicitly to save data.
common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type;
if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) {
return;
}
supervisor_stop_bluetooth();
bleio_adapter_reset(&common_hal_bleio_adapter_obj);
common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false);
supervisor_start_bluetooth();
}
// The singleton _bleio.Adapter object, bound to _bleio.adapter
// It currently only has properties and no state. Inited by bleio_reset
bleio_adapter_obj_t common_hal_bleio_adapter_obj;
void bleio_background(void) {
}
void common_hal_bleio_gc_collect(void) {
bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_INIT_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_INIT_H
void bleio_background(void);
// typedef struct {
// ble_gap_enc_key_t own_enc;
// ble_gap_enc_key_t peer_enc;
// ble_gap_id_key_t peer_id;
// } bonding_keys_t;
// We assume variable length data.
// 20 bytes max (23 - 3).
#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3)
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_INIT_H

View File

@ -0,0 +1,372 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
#include "shared-bindings/nvm/ByteArray.h"
#include "supervisor/shared/tick.h"
#include "bonding.h"
// Internal flash area reserved for bonding storage.
#define BONDING_PAGES_START_ADDR CIRCUITPY_BLE_CONFIG_START_ADDR
#define BONDING_PAGES_END_ADDR (CIRCUITPY_BLE_CONFIG_START_ADDR + CIRCUITPY_BLE_CONFIG_SIZE)
// First and last four bytes are magic bytes for id and version. Data is in between.
// 'BD01'
const uint32_t BONDING_FLAG = ('1' | '0' << 8 | 'D' << 16 | 'B' << 24);
#define BONDING_DATA_START_ADDR (BONDING_PAGES_START_ADDR + sizeof(BONDING_FLAG))
#define BONDING_DATA_END_ADDR (BONDING_PAGES_END_ADDR - sizeof(BONDING_FLAG))
#define BONDING_START_FLAG_ADDR BONDING_PAGES_START_ADDR
#define BONDING_END_FLAG_ADDR BONDING_DATA_END_ADDR
// Save both system and user service info.
#define SYS_ATTR_FLAGS (BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS | BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS)
#if BONDING_DEBUG
void bonding_print_block(bonding_block_t *block) {
printf("at 0x%08lx: is_central: %1d, type: 0x%x, ediv: 0x%04x, data_length: %d\n",
(uint32_t)block, block->is_central, block->type, block->ediv, block->data_length);
}
void bonding_print_keys(bonding_keys_t *keys) {
for (size_t i = 0; i < sizeof(bonding_keys_t); i++) {
printf("%x", ((uint8_t *)keys)[i]);
}
printf("\n");
}
#endif
STATIC size_t compute_block_size(uint16_t data_length) {
// Round data size up to the nearest 32-bit address.
return sizeof(bonding_block_t) + ((data_length + 3) & ~0x3);
}
void bonding_erase_storage(void) {
// Erase all pages in the bonding area.
for (uint32_t page_address = BONDING_PAGES_START_ADDR;
page_address < BONDING_PAGES_END_ADDR;
page_address += FLASH_PAGE_SIZE) {
// Argument is page number, not address.
sd_flash_page_erase_sync(page_address / FLASH_PAGE_SIZE);
}
// Write marker words at the beginning and the end of the bonding area.
uint32_t flag = BONDING_FLAG;
sd_flash_write_sync((uint32_t *)BONDING_START_FLAG_ADDR, &flag, 1);
sd_flash_write_sync((uint32_t *)BONDING_END_FLAG_ADDR, &flag, 1);
}
// Given NULL to start or block address, return the address of the next valid block.
// The last block returned is the unused block at the end.
// Return NULL if we have run off the end of the bonding space.
STATIC bonding_block_t *next_block(bonding_block_t *block) {
while (1) {
// Advance to next block.
if (block == NULL) {
return (bonding_block_t *)BONDING_DATA_START_ADDR;
} else if (block->type == BLOCK_UNUSED) {
// Already at last block (the unused block).
return NULL;
}
// Advance to next block.
block = (bonding_block_t *)((uint8_t *)block + compute_block_size(block->data_length));
if (block >= (bonding_block_t *)BONDING_DATA_END_ADDR) {
// Went past end of bonding space.
return NULL;
}
if (block->type != BLOCK_INVALID) {
// Found an empty or a valid block.
return block;
}
// Invalid block (was erased); try again.
}
}
// Find the block with given is_central, type and ediv value.
// If type == BLOCK_UNUSED, ediv is ignored and the the sole unused block at the end is returned.
// If not found, return NULL.
STATIC bonding_block_t *find_existing_block(bool is_central, bonding_block_type_t type, uint16_t ediv) {
bonding_block_t *block = NULL;
while (1) {
block = next_block(block);
if (block == NULL) {
return NULL;
}
// If types match, and block is unused, just return it.
// Otherwise check that is_central and ediv match.
if (type == block->type) {
if (type == BLOCK_UNUSED ||
(is_central == block->is_central && ediv == block->ediv)) {
return block;
}
}
}
}
size_t bonding_peripheral_bond_count(void) {
bonding_block_t *block = NULL;
size_t count = 0;
while (1) {
block = next_block(block);
if (block == NULL) {
return count;
}
if (block->type != BLOCK_UNUSED && block->type != BLOCK_INVALID && !block->is_central) {
count++;
}
}
}
// Get an empty block large enough to store data_length data.
STATIC bonding_block_t *find_unused_block(uint16_t data_length) {
bonding_block_t *unused_block = find_existing_block(true, BLOCK_UNUSED, EDIV_INVALID);
// If no more room, erase all existing blocks and start over.
if (!unused_block ||
(uint8_t *)unused_block + compute_block_size(data_length) >= (uint8_t *)BONDING_DATA_END_ADDR) {
bonding_erase_storage();
unused_block = (bonding_block_t *)BONDING_DATA_START_ADDR;
}
return unused_block;
}
// Set the header word to all 0's, to mark the block as invalid.
// We don't change data_length, so we can still skip over this block.
STATIC void invalidate_block(bonding_block_t *block) {
uint32_t zero = 0;
sd_flash_write_sync((uint32_t *)block, &zero, 1);
}
// Write bonding block header.
STATIC void write_block_header(bonding_block_t *dest_block, bonding_block_t *source_block_header) {
sd_flash_write_sync((uint32_t *)dest_block, (uint32_t *)source_block_header, sizeof(bonding_block_t) / 4);
}
// Write variable-length data at end of bonding block.
STATIC void write_block_data(bonding_block_t *dest_block, uint8_t *data, uint16_t data_length) {
// Minimize the number of writes. Datasheet says no more than two writes per word before erasing again.
// Start writing after the current header.
uint32_t *flash_word_p = (uint32_t *)((uint8_t *)dest_block + sizeof(bonding_block_t));
while (1) {
uint32_t word = 0xffffffff;
memcpy(&word, data, data_length >= 4 ? 4 : data_length);
sd_flash_write_sync(flash_word_p, &word, 1);
if (data_length <= 4) {
break;
}
data_length -= 4;
data += 4;
// Increment by word size.
flash_word_p++;
}
}
STATIC void write_sys_attr_block(bleio_connection_internal_t *connection) {
uint16_t length = 0;
// First find out how big a buffer we need, then fetch the data.
if (sd_ble_gatts_sys_attr_get(connection->conn_handle, NULL, &length, SYS_ATTR_FLAGS) != NRF_SUCCESS) {
return;
}
uint8_t sys_attr[length];
if (sd_ble_gatts_sys_attr_get(connection->conn_handle, sys_attr, &length, SYS_ATTR_FLAGS) != NRF_SUCCESS) {
return;
}
// Is there an existing sys_attr block that matches the current sys_attr data?
bonding_block_t *existing_block =
find_existing_block(connection->is_central, BLOCK_SYS_ATTR, connection->ediv);
if (existing_block) {
if (length == existing_block->data_length &&
memcmp(sys_attr, existing_block->data, length) == 0) {
// Identical block found. No need to store again.
return;
}
// Data doesn't match. Invalidate block and store a new one.
invalidate_block(existing_block);
}
bonding_block_t block_header = {
.is_central = connection->is_central,
.type = BLOCK_SYS_ATTR,
.ediv = connection->ediv,
.conn_handle = connection->conn_handle,
.data_length = length,
};
bonding_block_t *new_block = find_unused_block(length);
write_block_header(new_block, &block_header);
write_block_data(new_block, sys_attr, length);
return;
}
STATIC void write_keys_block(bleio_connection_internal_t *connection) {
uint16_t const ediv = connection->is_central
? connection->bonding_keys.peer_enc.master_id.ediv
: connection->bonding_keys.own_enc.master_id.ediv;
// Is there an existing keys block that matches the ediv?
bonding_block_t *existing_block = find_existing_block(connection->is_central, BLOCK_KEYS, ediv);
if (existing_block) {
if (existing_block->data_length == sizeof(bonding_keys_t) &&
memcmp(existing_block->data, &connection->bonding_keys, sizeof(bonding_keys_t)) == 0) {
// Identical block found. No need to store again.
return;
}
// Data doesn't match. Invalidate block and store a new one.
invalidate_block(existing_block);
}
// Invalidate any existing blocks that match the peer address.
existing_block = next_block(NULL);
while (existing_block != NULL) {
if (existing_block->type == BLOCK_KEYS && connection->is_central == existing_block->is_central &&
existing_block->data_length == sizeof(bonding_keys_t)) {
const ble_gap_addr_t *existing_peer = &((const bonding_keys_t *)existing_block->data)->peer_id.id_addr_info;
const ble_gap_addr_t *connecting_peer = &connection->bonding_keys.peer_id.id_addr_info;
if (memcmp(existing_peer->addr, connecting_peer->addr, 6) == 0 &&
memcmp(existing_block->data, &connection->bonding_keys, sizeof(bonding_keys_t)) != 0) {
// Mismatched block found. Invalidate it.
invalidate_block(existing_block);
}
}
existing_block = next_block(existing_block);
}
bonding_block_t block_header = {
.is_central = connection->is_central,
.type = BLOCK_KEYS,
.ediv = ediv,
.conn_handle = connection->conn_handle,
.data_length = sizeof(bonding_keys_t),
};
bonding_block_t *new_block = find_unused_block(sizeof(bonding_keys_t));
write_block_header(new_block, &block_header);
write_block_data(new_block, (uint8_t *)&connection->bonding_keys, sizeof(bonding_keys_t));
}
void bonding_clear_keys(bonding_keys_t *bonding_keys) {
memset((uint8_t *)bonding_keys, 0, sizeof(bonding_keys_t));
}
void bonding_reset(void) {
if (BONDING_FLAG != *((uint32_t *)BONDING_START_FLAG_ADDR) ||
BONDING_FLAG != *((uint32_t *)BONDING_END_FLAG_ADDR)) {
bonding_erase_storage();
}
}
// Write bonding blocks to flash. Requests have been queued during evt handlers.
void bonding_background(void) {
// A paired connection will request that its keys and CCCD values be stored.
// The CCCD store whenever a CCCD value is written.
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
bleio_connection_internal_t *connection = &bleio_connections[i];
// Wait at least one second before saving CCCD, to consolidate
// writes that involve multiple CCCDs. For instance, for HID,
// three CCCD's are set in short succession by the HID client.
if (connection->do_bond_cccds) {
uint64_t current_ticks_ms = supervisor_ticks_ms64();
if (current_ticks_ms - connection->do_bond_cccds_request_time >= 1000) {
write_sys_attr_block(connection);
connection->do_bond_cccds = false;
}
}
if (connection->do_bond_keys) {
write_keys_block(connection);
connection->do_bond_keys = false;
}
}
}
bool bonding_load_cccd_info(bool is_central, uint16_t conn_handle, uint16_t ediv) {
bonding_block_t *block = find_existing_block(is_central, BLOCK_SYS_ATTR, ediv);
if (block == NULL) {
return false;
}
return NRF_SUCCESS ==
sd_ble_gatts_sys_attr_set(conn_handle, block->data, block->data_length, SYS_ATTR_FLAGS);
}
bool bonding_load_keys(bool is_central, uint16_t ediv, bonding_keys_t *bonding_keys) {
bonding_block_t *block = find_existing_block(is_central, BLOCK_KEYS, ediv);
if (block == NULL) {
return false;
}
if (sizeof(bonding_keys_t) != block->data_length) {
// bonding_keys_t is a fixed length, so lengths should match.
return false;
}
memcpy(bonding_keys, block->data, block->data_length);
return true;
}
size_t bonding_load_identities(bool is_central, const ble_gap_id_key_t **keys, size_t max_length) {
bonding_block_t *block = NULL;
size_t len = 0;
while (len < max_length) {
block = next_block(block);
if (block == NULL) {
return len;
}
if (block->type != BLOCK_UNUSED &&
block->type != BLOCK_INVALID &&
block->is_central == is_central) {
if (sizeof(bonding_keys_t) != block->data_length) {
// bonding_keys_t is a fixed length, so lengths should match.
return len;
}
const bonding_keys_t *key_set = (const bonding_keys_t *)block->data;
keys[len] = &key_set->peer_id;
len++;
}
}
return len;
}
const ble_gap_enc_key_t *bonding_load_peer_encryption_key(bool is_central, const ble_gap_addr_t *peer) {
bonding_block_t *block = next_block(NULL);
while (block != NULL) {
if (block->type == BLOCK_KEYS && block->is_central == is_central) {
const bonding_keys_t *key_set = (const bonding_keys_t *)block->data;
if (memcmp(key_set->peer_id.id_addr_info.addr, peer->addr, 6) == 0) {
return &key_set->peer_enc;
}
}
block = next_block(block);
}
return NULL;
}

View File

@ -0,0 +1,91 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_BONDING_H
#define MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_BONDING_H
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "common-hal/_bleio/__init__.h"
#define EDIV_INVALID (0xffff)
#define BONDING_DEBUG (1)
#if BONDING_DEBUG
#define BONDING_DEBUG_PRINTF(...) printf(__VA_ARGS__)
#define BONDING_DEBUG_PRINT_BLOCK(block) bonding_print_block(block)
#define BONDING_DEBUG_PRINT_KEYS(keys) bonding_print_keys(keys)
#else
#define BONDING_DEBUG_PRINTF(...)
#define BONDING_DEBUG_PRINT_BLOCK(block)
#define BONDING_DEBUG_PRINT_KEYS(keys)
#endif
// Bonding data is stored in variable-length blocks consecutively in
// erased flash (all 1's). The blocks are 32-bit aligned, though the
// data may be any number of bytes. We hop through the blocks using
// the size field to find the next block. When we hit a word that is
// all 1's, we have reached the end of the blocks. We can write a new
// block there.
typedef enum {
BLOCK_INVALID = 0, // Ignore this block
BLOCK_KEYS = 1, // Block contains bonding keys.
BLOCK_SYS_ATTR = 2, // Block contains sys_attr values (CCCD settings, etc.).
BLOCK_UNUSED = 0xff, // Initial erased value.
} bonding_block_type_t;
typedef struct {
bool is_central : 1; // 1 if data is for a central role.
uint16_t reserved : 7; // Not currently used
bonding_block_type_t type : 8; // What kind of data is stored in.
uint16_t ediv; // ediv value; used as a lookup key.
uint16_t conn_handle; // Connection handle: used when a BLOCK_SYS_ATTR is queued to write.
// Not used as a key, etc.
uint16_t data_length; // Length of data in bytes, including ediv, not including padding.
// End of block header. 32-bit boundary here.
uint8_t data[]; // Rest of data in the block. Needs to be 32-bit aligned.
// Block is padded to 32-bit alignment.
} bonding_block_t;
void bonding_background(void);
void bonding_erase_storage(void);
void bonding_reset(void);
void bonding_clear_keys(bonding_keys_t *bonding_keys);
bool bonding_load_cccd_info(bool is_central, uint16_t conn_handle, uint16_t ediv);
bool bonding_load_keys(bool is_central, uint16_t ediv, bonding_keys_t *bonding_keys);
const ble_gap_enc_key_t *bonding_load_peer_encryption_key(bool is_central, const ble_gap_addr_t *peer);
size_t bonding_load_identities(bool is_central, const ble_gap_id_key_t **keys, size_t max_length);
size_t bonding_peripheral_bond_count(void);
#if BONDING_DEBUG
void bonding_print_block(bonding_block_t *);
void bonding_print_keys(bonding_keys_t *);
#endif
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_BLEIO_BONDING_H

View File

@ -0,0 +1,171 @@
#
# Bluetooth
#
CONFIG_BT_ENABLED=y
# end of Bluetooth
CONFIG_BT_CTRL_MODE_EFF=1
#
# Bluetooth controller
#
CONFIG_BT_CTRL_BLE_MAX_ACT=10
CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=10
CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0
CONFIG_BT_CTRL_PINNED_TO_CORE_0=y
# CONFIG_BT_CTRL_PINNED_TO_CORE_1 is not set
CONFIG_BT_CTRL_PINNED_TO_CORE=0
CONFIG_BT_CTRL_HCI_MODE_VHCI=y
# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set
CONFIG_BT_CTRL_HCI_TL=1
CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30
# CONFIG_BT_CTRL_HW_CCA is not set
CONFIG_BT_CTRL_HW_CCA_EFF=0
CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y
# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set
# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set
CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0
CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y
# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set
CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0
CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y
# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set
CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N27 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set
CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3=y
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set
# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set
CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=10
CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y
CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100
CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20
# CONFIG_BT_CTRL_BLE_SCAN_DUPL is not set
# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set
CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y
CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0
# end of Bluetooth controller
# CONFIG_BT_CTRL_MODEM_SLEEP is not set
#
# Bluetooth controller
#
CONFIG_BT_CTRL_SLEEP_MODE_EFF=0
CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0
CONFIG_BT_CTRL_HCI_TL_EFF=1
# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set
# end of Bluetooth controller
# CONFIG_BT_BLUEDROID_ENABLED is not set
#
# Bluetooth
#
CONFIG_BT_NIMBLE_ENABLED=y
# CONFIG_BT_CONTROLLER_ONLY is not set
# end of Bluetooth
CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL=y
#
# NimBLE Options
#
# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT is not set
# CONFIG_BT_NIMBLE_LOG_LEVEL_NONE is not set
# CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR is not set
# CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING is not set
CONFIG_BT_NIMBLE_LOG_LEVEL_INFO=y
# CONFIG_BT_NIMBLE_LOG_LEVEL_DEBUG is not set
CONFIG_BT_NIMBLE_LOG_LEVEL=1
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=3
CONFIG_BT_NIMBLE_MAX_BONDS=3
CONFIG_BT_NIMBLE_MAX_CCCDS=8
CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=0
# CONFIG_BT_NIMBLE_PINNED_TO_CORE_0 is not set
CONFIG_BT_NIMBLE_PINNED_TO_CORE_1=y
CONFIG_BT_NIMBLE_PINNED_TO_CORE=1
CONFIG_BT_NIMBLE_TASK_STACK_SIZE=4096
CONFIG_BT_NIMBLE_ROLE_CENTRAL=y
CONFIG_BT_NIMBLE_ROLE_PERIPHERAL=y
CONFIG_BT_NIMBLE_ROLE_BROADCASTER=y
CONFIG_BT_NIMBLE_ROLE_OBSERVER=y
CONFIG_BT_NIMBLE_NVS_PERSIST=y
CONFIG_BT_NIMBLE_SM_LEGACY=y
CONFIG_BT_NIMBLE_SM_SC=y
# CONFIG_BT_NIMBLE_DEBUG is not set
# CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS is not set
CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="nimble"
CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=256
CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE=0
CONFIG_BT_NIMBLE_ACL_BUF_COUNT=20
CONFIG_BT_NIMBLE_ACL_BUF_SIZE=255
CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=30
CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8
CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT=12
# CONFIG_BT_NIMBLE_HS_FLOW_CTRL is not set
CONFIG_BT_NIMBLE_RPA_TIMEOUT=900
# CONFIG_BT_NIMBLE_MESH is not set
CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS=y
CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS=2000
# CONFIG_BT_NIMBLE_HOST_BASED_PRIVACY is not set
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=y
CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT=3
CONFIG_BT_NIMBLE_EXT_ADV=y
CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=1
CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN=1650
CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV=y
CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS=1
# CONFIG_BT_NIMBLE_BLUFI_ENABLE is not set
CONFIG_BT_NIMBLE_USE_ESP_TIMER=y
# end of NimBLE Options
# CONFIG_BLUEDROID_ENABLED is not set
#
# Deprecated options for backward compatibility
#
CONFIG_NIMBLE_ENABLED=y
CONFIG_NIMBLE_MEM_ALLOC_MODE_INTERNAL=y
# CONFIG_NIMBLE_MEM_ALLOC_MODE_DEFAULT is not set
CONFIG_NIMBLE_MAX_CONNECTIONS=3
CONFIG_NIMBLE_MAX_BONDS=3
CONFIG_NIMBLE_MAX_CCCDS=8
CONFIG_NIMBLE_L2CAP_COC_MAX_NUM=0
CONFIG_NIMBLE_PINNED_TO_CORE_0=y
# CONFIG_NIMBLE_PINNED_TO_CORE_1 is not set
CONFIG_NIMBLE_PINNED_TO_CORE=0
CONFIG_NIMBLE_TASK_STACK_SIZE=4096
CONFIG_NIMBLE_ROLE_CENTRAL=y
CONFIG_NIMBLE_ROLE_PERIPHERAL=y
CONFIG_NIMBLE_ROLE_BROADCASTER=y
CONFIG_NIMBLE_ROLE_OBSERVER=y
CONFIG_NIMBLE_NVS_PERSIST=y
CONFIG_NIMBLE_SM_LEGACY=y
CONFIG_NIMBLE_SM_SC=y
# CONFIG_NIMBLE_DEBUG is not set
# CONFIG_NIMBLE_SM_SC_DEBUG_KEYS is not set
CONFIG_NIMBLE_SVC_GAP_DEVICE_NAME="nimble"
CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31
CONFIG_NIMBLE_ATT_PREFERRED_MTU=256
CONFIG_NIMBLE_SVC_GAP_APPEARANCE=0
CONFIG_NIMBLE_ACL_BUF_COUNT=20
CONFIG_NIMBLE_ACL_BUF_SIZE=255
CONFIG_NIMBLE_HCI_EVT_BUF_SIZE=70
CONFIG_NIMBLE_HCI_EVT_HI_BUF_COUNT=30
CONFIG_NIMBLE_HCI_EVT_LO_BUF_COUNT=8
CONFIG_NIMBLE_MSYS1_BLOCK_COUNT=12
# CONFIG_NIMBLE_HS_FLOW_CTRL is not set
CONFIG_NIMBLE_RPA_TIMEOUT=900
# CONFIG_NIMBLE_MESH is not set
CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS=y
CONFIG_SW_COEXIST_ENABLE=y
# end of Deprecated options for backward compatibility

View File

@ -14,7 +14,7 @@ CONFIG_SDK_TOOLPREFIX="xtensa-esp32s3-elf-"
CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0
# end of Bootloader config # end of Bootloader config
# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set CONFIG_BT_SOC_SUPPORT_5_0=y
# #
# ESP32S3-Specific # ESP32S3-Specific
# #

View File

@ -36,6 +36,8 @@ CIRCUITPY_MODULE ?= none
ifeq ($(IDF_TARGET),esp32c3) ifeq ($(IDF_TARGET),esp32c3)
CIRCUITPY_USB = 0 CIRCUITPY_USB = 0
CIRCUITPY_ALARM = 0 CIRCUITPY_ALARM = 0
CIRCUITPY_BLEIO = 1
CIRCUITPY_BLEIO_HCI = 0
CIRCUITPY_COUNTIO = 0 CIRCUITPY_COUNTIO = 0
CIRCUITPY_ROTARYIO = 0 CIRCUITPY_ROTARYIO = 0
CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_AUDIOBUSIO = 0
@ -45,8 +47,14 @@ CIRCUITPY_PARALLELDISPLAY = 0
CIRCUITPY_TOUCHIO ?= 1 CIRCUITPY_TOUCHIO ?= 1
CIRCUITPY_TOUCHIO_USE_NATIVE = 0 CIRCUITPY_TOUCHIO_USE_NATIVE = 0
else ifeq ($(IDF_TARGET),esp32s3) else ifeq ($(IDF_TARGET),esp32s3)
CIRCUITPY_BLEIO = 1
CIRCUITPY_BLEIO_HCI = 0
CIRCUITPY_IMAGECAPTURE = 0 CIRCUITPY_IMAGECAPTURE = 0
CIRCUITPY_PARALLELDISPLAY = 0 CIRCUITPY_PARALLELDISPLAY = 0
else ifeq ($(IDF_TARGET),esp32s2)
# No BLE on S2
CIRCUITPY_BLEIO = 0
CIRCUITPY_BLEIO_HCI = 0
endif endif
# From ESP32-S2/S3 Technical Reference Manual: # From ESP32-S2/S3 Technical Reference Manual:

View File

@ -70,6 +70,10 @@
#include "common-hal/audiobusio/__init__.h" #include "common-hal/audiobusio/__init__.h"
#endif #endif
#if CIRCUITPY_BLEIO
#include "shared-bindings/_bleio/__init__.h"
#endif
#if CIRCUITPY_IMAGECAPTURE #if CIRCUITPY_IMAGECAPTURE
#include "cam.h" #include "cam.h"
#endif #endif
@ -279,6 +283,10 @@ void reset_port(void) {
watchdog_reset(); watchdog_reset();
#endif #endif
#if CIRCUITPY_BLEIO
bleio_reset();
#endif
#if CIRCUITPY_WIFI #if CIRCUITPY_WIFI
wifi_reset(); wifi_reset();
#endif #endif

View File

@ -49,6 +49,7 @@ TARGET_SETTINGS = [
"CONFIG_TOOLPREFIX", "CONFIG_TOOLPREFIX",
"ESP_SLEEP_GPIO_RESET_WORKAROUND", "ESP_SLEEP_GPIO_RESET_WORKAROUND",
"CONFIG_ESP_PHY_ENABLE_USB", "CONFIG_ESP_PHY_ENABLE_USB",
"CONFIG_BT_SOC_SUPPORT_5_0",
] ]
BOARD_SETTINGS = [ BOARD_SETTINGS = [
@ -65,6 +66,8 @@ FLASH_SETTINGS = [
"CONFIG_PARTITION_TABLE_FILENAME", "CONFIG_PARTITION_TABLE_FILENAME",
] ]
BLE_SETTINGS = ["CONFIG_BT_", "CONFIG_BLUEDROID_", "CONFIG_NIMBLE_", "CONFIG_SW_COEXIST_ENABLE"]
# boards/lilygo_ttgo_t8_s2_st7789/sdkconfig # boards/lilygo_ttgo_t8_s2_st7789/sdkconfig
# CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y # CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y
@ -80,16 +83,17 @@ def matches_group(line, group):
def add_group(lines, last_group, current_group): def add_group(lines, last_group, current_group):
if last_group != current_group: # TODO: Properly handle nested groups
if last_group != current_group[-1]:
if last_group: if last_group:
lines.append("# end of " + last_group) lines.append("# end of " + last_group)
lines.append("") lines.append("")
return None return None
if current_group: if current_group:
lines.append("#") lines.append("#")
lines.append("# " + current_group) lines.append("# " + current_group[-1])
lines.append("#") lines.append("#")
return current_group return current_group[-1]
return last_group return last_group
@ -120,12 +124,14 @@ def update(debug, board, update_all):
opt_config = pathlib.Path("esp-idf-config/sdkconfig-opt.defaults") opt_config = pathlib.Path("esp-idf-config/sdkconfig-opt.defaults")
flash_config = pathlib.Path(f"esp-idf-config/sdkconfig-{flash}.defaults") flash_config = pathlib.Path(f"esp-idf-config/sdkconfig-{flash}.defaults")
target_config = pathlib.Path(f"esp-idf-config/sdkconfig-{target}.defaults") target_config = pathlib.Path(f"esp-idf-config/sdkconfig-{target}.defaults")
ble_config = pathlib.Path(f"esp-idf-config/sdkconfig-ble.defaults")
board_config = pathlib.Path(f"boards/{board}/sdkconfig") board_config = pathlib.Path(f"boards/{board}/sdkconfig")
defaults = default_config.read_text().split("\n") defaults = default_config.read_text().split("\n")
defaults.extend(opt_config.read_text().split("\n")) defaults.extend(opt_config.read_text().split("\n"))
defaults.extend(flash_config.read_text().split("\n")) defaults.extend(flash_config.read_text().split("\n"))
defaults.extend(target_config.read_text().split("\n")) defaults.extend(target_config.read_text().split("\n"))
defaults.extend(ble_config.read_text().split("\n"))
board_settings = [] board_settings = []
last_board_group = None last_board_group = None
@ -135,15 +141,17 @@ def update(debug, board, update_all):
last_opt_group = None last_opt_group = None
target_settings = [] target_settings = []
last_target_group = None last_target_group = None
ble_settings = []
last_ble_group = None
default_settings = [] default_settings = []
last_default_group = None last_default_group = None
current_group = None current_group = []
for line in input_config.read_text().split("\n"): for line in input_config.read_text().split("\n"):
if line.startswith("# ") and "CONFIG_" not in line and len(line) > 3: if line.startswith("# ") and "CONFIG_" not in line and len(line) > 3:
if line.startswith("# end of"): if line.startswith("# end of"):
current_group = None current_group.pop()
else: else:
current_group = line[2:] current_group.append(line[2:])
elif (not update_all and line not in defaults) or ( elif (not update_all and line not in defaults) or (
update_all and matches_group(line, BOARD_SETTINGS) update_all and matches_group(line, BOARD_SETTINGS)
): ):
@ -159,6 +167,9 @@ def update(debug, board, update_all):
elif matches_group(line, TARGET_SETTINGS): elif matches_group(line, TARGET_SETTINGS):
last_target_group = add_group(target_settings, last_target_group, current_group) last_target_group = add_group(target_settings, last_target_group, current_group)
target_settings.append(line) target_settings.append(line)
elif matches_group(line, BLE_SETTINGS):
last_ble_group = add_group(ble_settings, last_ble_group, current_group)
ble_settings.append(line)
elif "CONFIG_" in line: elif "CONFIG_" in line:
last_default_group = add_group(default_settings, last_default_group, current_group) last_default_group = add_group(default_settings, last_default_group, current_group)
default_settings.append(line) default_settings.append(line)
@ -167,6 +178,7 @@ def update(debug, board, update_all):
add_group(opt_settings, last_opt_group, current_group) add_group(opt_settings, last_opt_group, current_group)
add_group(flash_settings, last_flash_group, current_group) add_group(flash_settings, last_flash_group, current_group)
add_group(target_settings, last_target_group, current_group) add_group(target_settings, last_target_group, current_group)
add_group(ble_settings, last_ble_group, current_group)
add_group(default_settings, last_default_group, current_group) add_group(default_settings, last_default_group, current_group)
board_config.write_text("\n".join(board_settings)) board_config.write_text("\n".join(board_settings))
@ -175,6 +187,7 @@ def update(debug, board, update_all):
opt_config.write_text("\n".join(opt_settings)) opt_config.write_text("\n".join(opt_settings))
default_config.write_text("\n".join(default_settings)) default_config.write_text("\n".join(default_settings))
target_config.write_text("\n".join(target_settings)) target_config.write_text("\n".join(target_settings))
ble_config.write_text("\n".join(ble_settings))
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -28,7 +28,6 @@
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
void bleio_background(void); void bleio_background(void);
void bleio_reset(void);
typedef struct { typedef struct {
ble_gap_enc_key_t own_enc; ble_gap_enc_key_t own_enc;

View File

@ -45,7 +45,6 @@
#include "nrf_nvic.h" #include "nrf_nvic.h"
#include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Pin.h"
#include "common-hal/_bleio/__init__.h"
#include "common-hal/alarm/time/TimeAlarm.h" #include "common-hal/alarm/time/TimeAlarm.h"
#include "common-hal/analogio/AnalogIn.h" #include "common-hal/analogio/AnalogIn.h"
#include "common-hal/busio/I2C.h" #include "common-hal/busio/I2C.h"
@ -59,6 +58,7 @@
#include "common-hal/watchdog/WatchDogTimer.h" #include "common-hal/watchdog/WatchDogTimer.h"
#include "common-hal/alarm/__init__.h" #include "common-hal/alarm/__init__.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/rtc/__init__.h" #include "shared-bindings/rtc/__init__.h"

View File

@ -114,7 +114,7 @@ size_t ringbuf_num_filled(ringbuf_t *r) {
// If the ring buffer fills up, not all bytes will be written. // If the ring buffer fills up, not all bytes will be written.
// Returns how many bytes were successfully written. // Returns how many bytes were successfully written.
size_t ringbuf_put_n(ringbuf_t *r, uint8_t *buf, size_t bufsize) { size_t ringbuf_put_n(ringbuf_t *r, const uint8_t *buf, size_t bufsize) {
for (size_t i = 0; i < bufsize; i++) { for (size_t i = 0; i < bufsize; i++) {
if (ringbuf_put(r, buf[i]) < 0) { if (ringbuf_put(r, buf[i]) < 0) {
// If ringbuf is full, give up and return how many bytes // If ringbuf is full, give up and return how many bytes

View File

@ -52,7 +52,7 @@ int ringbuf_put(ringbuf_t *r, uint8_t v);
void ringbuf_clear(ringbuf_t *r); void ringbuf_clear(ringbuf_t *r);
size_t ringbuf_num_empty(ringbuf_t *r); size_t ringbuf_num_empty(ringbuf_t *r);
size_t ringbuf_num_filled(ringbuf_t *r); size_t ringbuf_num_filled(ringbuf_t *r);
size_t ringbuf_put_n(ringbuf_t *r, uint8_t *buf, size_t bufsize); size_t ringbuf_put_n(ringbuf_t *r, const uint8_t *buf, size_t bufsize);
size_t ringbuf_get_n(ringbuf_t *r, uint8_t *buf, size_t bufsize); size_t ringbuf_get_n(ringbuf_t *r, uint8_t *buf, size_t bufsize);
// Note: big-endian. No-op if not enough room available for both bytes. // Note: big-endian. No-op if not enough room available for both bytes.

View File

@ -54,6 +54,8 @@ extern const mp_obj_type_t mp_type_bleio_BluetoothError;
extern const mp_obj_type_t mp_type_bleio_RoleError; extern const mp_obj_type_t mp_type_bleio_RoleError;
extern const mp_obj_type_t mp_type_bleio_SecurityError; extern const mp_obj_type_t mp_type_bleio_SecurityError;
void bleio_reset(void);
extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj); extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj);
NORETURN void mp_raise_bleio_BluetoothError(const compressed_string_t *msg, ...); NORETURN void mp_raise_bleio_BluetoothError(const compressed_string_t *msg, ...);

View File

@ -91,9 +91,9 @@ void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t *self,
bool connectable, bool connectable,
bool scan_response, bool scan_response,
int8_t rssi, int8_t rssi,
uint8_t *peer_addr, const uint8_t *peer_addr,
uint8_t addr_type, uint8_t addr_type,
uint8_t *data, const uint8_t *data,
uint16_t len) { uint16_t len) {
int32_t packet_size = sizeof(uint8_t) + sizeof(ticks_ms) + sizeof(rssi) + NUM_BLEIO_ADDRESS_BYTES + int32_t packet_size = sizeof(uint8_t) + sizeof(ticks_ms) + sizeof(rssi) + NUM_BLEIO_ADDRESS_BYTES +
sizeof(addr_type) + sizeof(len) + len; sizeof(addr_type) + sizeof(len) + len;

View File

@ -56,9 +56,9 @@ void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t *self,
bool connectable, bool connectable,
bool scan_result, bool scan_result,
int8_t rssi, int8_t rssi,
uint8_t *peer_addr, const uint8_t *peer_addr,
uint8_t addr_type, uint8_t addr_type,
uint8_t *data, const uint8_t *data,
uint16_t len); uint16_t len);
#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H