Merge pull request #5927 from tannewt/esp_ble_scan
Add BLE scanning for S3 and C3.
This commit is contained in:
commit
fff68c9f86
|
@ -35,7 +35,6 @@
|
|||
#include "hci.h"
|
||||
|
||||
void bleio_hci_background(void);
|
||||
void bleio_reset(void);
|
||||
|
||||
typedef struct {
|
||||
// ble_gap_enc_key_t own_enc;
|
||||
|
|
|
@ -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
|
||||
# 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)
|
||||
project(circuitpython)
|
||||
|
|
|
@ -86,6 +86,14 @@ INC += \
|
|||
-isystem esp-idf \
|
||||
-isystem esp-idf/components/app_update/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/$(IDF_TARGET)/include \
|
||||
-isystem esp-idf/components/$(IDF_TARGET)/include \
|
||||
|
@ -133,6 +141,7 @@ endif
|
|||
|
||||
CFLAGS += \
|
||||
-DHAVE_CONFIG_H \
|
||||
-DESP_PLATFORM=1 \
|
||||
-DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" \
|
||||
-DUNITY_INCLUDE_CONFIG_H -DWITH_POSIX
|
||||
|
||||
|
@ -148,7 +157,12 @@ ifeq ($(DEBUG), 1)
|
|||
# CFLAGS += -fno-inline -fno-ipa-sra
|
||||
else
|
||||
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
|
||||
### CFLAGS += -flto
|
||||
endif
|
||||
|
@ -298,8 +312,10 @@ else
|
|||
DEBUG_SDKCONFIG = esp-idf-config/sdkconfig-opt.defaults
|
||||
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
|
||||
$(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
|
||||
|
@ -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))
|
||||
|
||||
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)
|
||||
|
||||
MBEDTLS_COMPONENTS_LINK = crypto tls x509
|
||||
|
@ -350,6 +372,11 @@ else
|
|||
BOOTLOADER_OFFSET = 0x1000
|
||||
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
|
||||
FIRMWARE_OFFSET = 0x10000
|
||||
|
||||
|
@ -367,41 +394,7 @@ endif
|
|||
|
||||
.PHONY: esp-idf-stamp
|
||||
esp-idf-stamp: $(BUILD)/esp-idf/config/sdkconfig.h
|
||||
$(Q)ninja -C $(BUILD)/esp-idf \
|
||||
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
|
||||
$(Q)ninja -C $(BUILD)/esp-idf $(IDF_CMAKE_TARGETS)
|
||||
|
||||
$(BUILD)/firmware.elf: $(OBJ) | esp-idf-stamp
|
||||
$(STEPECHO) "LINK $@"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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.
|
||||
}
|
|
@ -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
|
|
@ -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)));
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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.
|
||||
}
|
|
@ -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
|
|
@ -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));
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -14,7 +14,7 @@ CONFIG_SDK_TOOLPREFIX="xtensa-esp32s3-elf-"
|
|||
CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0
|
||||
# end of Bootloader config
|
||||
|
||||
# CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80 is not set
|
||||
CONFIG_BT_SOC_SUPPORT_5_0=y
|
||||
#
|
||||
# ESP32S3-Specific
|
||||
#
|
||||
|
|
|
@ -36,6 +36,8 @@ CIRCUITPY_MODULE ?= none
|
|||
ifeq ($(IDF_TARGET),esp32c3)
|
||||
CIRCUITPY_USB = 0
|
||||
CIRCUITPY_ALARM = 0
|
||||
CIRCUITPY_BLEIO = 1
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
CIRCUITPY_COUNTIO = 0
|
||||
CIRCUITPY_ROTARYIO = 0
|
||||
CIRCUITPY_AUDIOBUSIO = 0
|
||||
|
@ -45,8 +47,14 @@ CIRCUITPY_PARALLELDISPLAY = 0
|
|||
CIRCUITPY_TOUCHIO ?= 1
|
||||
CIRCUITPY_TOUCHIO_USE_NATIVE = 0
|
||||
else ifeq ($(IDF_TARGET),esp32s3)
|
||||
CIRCUITPY_BLEIO = 1
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
CIRCUITPY_IMAGECAPTURE = 0
|
||||
CIRCUITPY_PARALLELDISPLAY = 0
|
||||
else ifeq ($(IDF_TARGET),esp32s2)
|
||||
# No BLE on S2
|
||||
CIRCUITPY_BLEIO = 0
|
||||
CIRCUITPY_BLEIO_HCI = 0
|
||||
endif
|
||||
|
||||
# From ESP32-S2/S3 Technical Reference Manual:
|
||||
|
|
|
@ -70,6 +70,10 @@
|
|||
#include "common-hal/audiobusio/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_BLEIO
|
||||
#include "shared-bindings/_bleio/__init__.h"
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_IMAGECAPTURE
|
||||
#include "cam.h"
|
||||
#endif
|
||||
|
@ -279,6 +283,10 @@ void reset_port(void) {
|
|||
watchdog_reset();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_BLEIO
|
||||
bleio_reset();
|
||||
#endif
|
||||
|
||||
#if CIRCUITPY_WIFI
|
||||
wifi_reset();
|
||||
#endif
|
||||
|
|
|
@ -49,6 +49,7 @@ TARGET_SETTINGS = [
|
|||
"CONFIG_TOOLPREFIX",
|
||||
"ESP_SLEEP_GPIO_RESET_WORKAROUND",
|
||||
"CONFIG_ESP_PHY_ENABLE_USB",
|
||||
"CONFIG_BT_SOC_SUPPORT_5_0",
|
||||
]
|
||||
|
||||
BOARD_SETTINGS = [
|
||||
|
@ -65,6 +66,8 @@ FLASH_SETTINGS = [
|
|||
"CONFIG_PARTITION_TABLE_FILENAME",
|
||||
]
|
||||
|
||||
BLE_SETTINGS = ["CONFIG_BT_", "CONFIG_BLUEDROID_", "CONFIG_NIMBLE_", "CONFIG_SW_COEXIST_ENABLE"]
|
||||
|
||||
# boards/lilygo_ttgo_t8_s2_st7789/sdkconfig
|
||||
# CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y
|
||||
|
||||
|
@ -80,16 +83,17 @@ def matches_group(line, 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:
|
||||
lines.append("# end of " + last_group)
|
||||
lines.append("")
|
||||
return None
|
||||
if current_group:
|
||||
lines.append("#")
|
||||
lines.append("# " + current_group)
|
||||
lines.append("# " + current_group[-1])
|
||||
lines.append("#")
|
||||
return current_group
|
||||
return current_group[-1]
|
||||
return last_group
|
||||
|
||||
|
||||
|
@ -120,12 +124,14 @@ def update(debug, board, update_all):
|
|||
opt_config = pathlib.Path("esp-idf-config/sdkconfig-opt.defaults")
|
||||
flash_config = pathlib.Path(f"esp-idf-config/sdkconfig-{flash}.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")
|
||||
|
||||
defaults = default_config.read_text().split("\n")
|
||||
defaults.extend(opt_config.read_text().split("\n"))
|
||||
defaults.extend(flash_config.read_text().split("\n"))
|
||||
defaults.extend(target_config.read_text().split("\n"))
|
||||
defaults.extend(ble_config.read_text().split("\n"))
|
||||
|
||||
board_settings = []
|
||||
last_board_group = None
|
||||
|
@ -135,15 +141,17 @@ def update(debug, board, update_all):
|
|||
last_opt_group = None
|
||||
target_settings = []
|
||||
last_target_group = None
|
||||
ble_settings = []
|
||||
last_ble_group = None
|
||||
default_settings = []
|
||||
last_default_group = None
|
||||
current_group = None
|
||||
current_group = []
|
||||
for line in input_config.read_text().split("\n"):
|
||||
if line.startswith("# ") and "CONFIG_" not in line and len(line) > 3:
|
||||
if line.startswith("# end of"):
|
||||
current_group = None
|
||||
current_group.pop()
|
||||
else:
|
||||
current_group = line[2:]
|
||||
current_group.append(line[2:])
|
||||
elif (not update_all and line not in defaults) or (
|
||||
update_all and matches_group(line, BOARD_SETTINGS)
|
||||
):
|
||||
|
@ -159,6 +167,9 @@ def update(debug, board, update_all):
|
|||
elif matches_group(line, TARGET_SETTINGS):
|
||||
last_target_group = add_group(target_settings, last_target_group, current_group)
|
||||
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:
|
||||
last_default_group = add_group(default_settings, last_default_group, current_group)
|
||||
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(flash_settings, last_flash_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)
|
||||
|
||||
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))
|
||||
default_config.write_text("\n".join(default_settings))
|
||||
target_config.write_text("\n".join(target_settings))
|
||||
ble_config.write_text("\n".join(ble_settings))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
|
||||
|
||||
void bleio_background(void);
|
||||
void bleio_reset(void);
|
||||
|
||||
typedef struct {
|
||||
ble_gap_enc_key_t own_enc;
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "nrf_nvic.h"
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
#include "common-hal/_bleio/__init__.h"
|
||||
#include "common-hal/alarm/time/TimeAlarm.h"
|
||||
#include "common-hal/analogio/AnalogIn.h"
|
||||
#include "common-hal/busio/I2C.h"
|
||||
|
@ -59,6 +58,7 @@
|
|||
#include "common-hal/watchdog/WatchDogTimer.h"
|
||||
#include "common-hal/alarm/__init__.h"
|
||||
|
||||
#include "shared-bindings/_bleio/__init__.h"
|
||||
#include "shared-bindings/microcontroller/__init__.h"
|
||||
#include "shared-bindings/rtc/__init__.h"
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ size_t ringbuf_num_filled(ringbuf_t *r) {
|
|||
|
||||
// If the ring buffer fills up, not all bytes will be 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++) {
|
||||
if (ringbuf_put(r, buf[i]) < 0) {
|
||||
// If ringbuf is full, give up and return how many bytes
|
||||
|
|
|
@ -52,7 +52,7 @@ int ringbuf_put(ringbuf_t *r, uint8_t v);
|
|||
void ringbuf_clear(ringbuf_t *r);
|
||||
size_t ringbuf_num_empty(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);
|
||||
|
||||
// Note: big-endian. No-op if not enough room available for both bytes.
|
||||
|
|
|
@ -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_SecurityError;
|
||||
|
||||
void bleio_reset(void);
|
||||
|
||||
extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj);
|
||||
|
||||
NORETURN void mp_raise_bleio_BluetoothError(const compressed_string_t *msg, ...);
|
||||
|
|
|
@ -91,9 +91,9 @@ void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t *self,
|
|||
bool connectable,
|
||||
bool scan_response,
|
||||
int8_t rssi,
|
||||
uint8_t *peer_addr,
|
||||
const uint8_t *peer_addr,
|
||||
uint8_t addr_type,
|
||||
uint8_t *data,
|
||||
const uint8_t *data,
|
||||
uint16_t len) {
|
||||
int32_t packet_size = sizeof(uint8_t) + sizeof(ticks_ms) + sizeof(rssi) + NUM_BLEIO_ADDRESS_BYTES +
|
||||
sizeof(addr_type) + sizeof(len) + len;
|
||||
|
|
|
@ -56,9 +56,9 @@ void shared_module_bleio_scanresults_append(bleio_scanresults_obj_t *self,
|
|||
bool connectable,
|
||||
bool scan_result,
|
||||
int8_t rssi,
|
||||
uint8_t *peer_addr,
|
||||
const uint8_t *peer_addr,
|
||||
uint8_t addr_type,
|
||||
uint8_t *data,
|
||||
const uint8_t *data,
|
||||
uint16_t len);
|
||||
|
||||
#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANRESULTS_H
|
||||
|
|
Loading…
Reference in New Issue