From 6f5b5d5483712393a14c12257cc11257e2fd760f Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 3 Apr 2017 14:28:47 -0700 Subject: [PATCH 01/98] esp32/Makefile: Initial changes for bluetooth esp32/network_bluetooth.c: Initial changes for bluetooth esp32/network_bluetooth.h: Initial changes for bluetooth --- esp32/Makefile | 1 + esp32/network_bluetooth.c | 122 ++++++++++++++++++++++++++++++++++++++ esp32/network_bluetooth.h | 36 +++++++++++ 3 files changed, 159 insertions(+) create mode 100644 esp32/network_bluetooth.c create mode 100644 esp32/network_bluetooth.h diff --git a/esp32/Makefile b/esp32/Makefile index 895fe29e7..4e82a89df 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -128,6 +128,7 @@ SRC_C = \ modsocket.c \ modesp.c \ espneopixel.c \ + network_bluetooth.c \ $(SRC_MOD) STM_SRC_C = $(addprefix stmhal/,\ diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c new file mode 100644 index 000000000..5fbb85697 --- /dev/null +++ b/esp32/network_bluetooth.c @@ -0,0 +1,122 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * + * 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 +#include +#include + +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mphal.h" +#include "modmachine.h" + + + +/******************************************************************************/ +// MicroPython bindings for hw_spi + +STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "Bluetooth()"); +} + + +STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { + /* + ARG_bits, + ARG_firstbit, + ARG_sck, + ARG_mosi, + ARG_miso + */ + }; + static const mp_arg_t allowed_args[] = { + /* + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} }, + { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + */ + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + machine_hw_spi_obj_t *self = m_new_obj(machine_hw_spi_obj_t); + self->base.type = &machine_hw_spi_type; + + initialize( + self, + args[ARG_id].u_int, + args[ARG_baudrate].u_int, + args[ARG_polarity].u_int, + args[ARG_phase].u_int, + args[ARG_bits].u_int, + args[ARG_firstbit].u_int, + args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj), + args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj), + args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj)); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t network_bluetooth_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_bluetooth_init_obj, network_bluetooth_init); + +STATIC mp_obj_t network_bluetooth_deinit(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_bluetooth_deinit_obj, network_bluetooth_deinit); + +STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, + + // class constants + /* + { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, + { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) }, + { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, + { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, + */ +}; + +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_locals_dict, network_bluetooth_locals_dict_table); + +const mp_obj_type_t network_bluetooth_type = { + { &mp_type_type }, + .name = MP_QSTR_Bluetooth, + .print = network_bluetooth_print, + .make_new = network_bluetooth_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_locals_dict, +}; diff --git a/esp32/network_bluetooth.h b/esp32/network_bluetooth.h new file mode 100644 index 000000000..dbc0ead7b --- /dev/null +++ b/esp32/network_bluetooth.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 "Eric Poulsen" + * + * 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_ESP32_NETWORK_BLUETOOTH_H +#define MICROPY_INCLUDED_ESP32_NETWORK_BLUETOOTH_H + +#include "py/obj.h" + +typdef struct { + mp_obj_type_t base; +} network_bluetooth_obj_t; + +#endif // MICROPY_INCLUDED_ESP32_NETWORK_BLUETOOTH_H From fef2158e96aad1b3f7e1456b2d64643bb11a2c15 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 3 Apr 2017 16:07:15 -0700 Subject: [PATCH 02/98] esp32/Makefile: Updated to include BT code from ESP-IDF esp32/modnetwork.c: Added a Bluetooth object esp32/network_bluetooth.*: Early development; some test code esp32/skdconfig: Added define to enable BT --- esp32/Makefile | 9 +++- esp32/modnetwork.c | 6 ++- esp32/network_bluetooth.c | 98 +++++++++++++++++++++++++++------------ esp32/network_bluetooth.h | 6 ++- esp32/sdkconfig.h | 1 + 5 files changed, 86 insertions(+), 34 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index 4e82a89df..1e21b965a 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -16,7 +16,7 @@ include ../py/py.mk PORT ?= /dev/ttyUSB0 BAUD ?= 460800 -FLASH_MODE ?= qio +FLASH_MODE ?= dio FLASH_FREQ ?= 40m FLASH_SIZE ?= 4MB CROSS_COMPILE ?= xtensa-esp32-elf- @@ -79,6 +79,7 @@ INC += -I$(ESPCOMP)/wpa_supplicant/include INC += -I$(ESPCOMP)/wpa_supplicant/port/include INC += -I$(ESPCOMP)/ethernet/include INC += -I$(ESPCOMP)/tcpip_adapter/include +INC += -I$(ESPCOMP)/bt/include CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM $(INC) CFLAGS += -DIDF_VER=\"$(IDF_VER)\" @@ -239,6 +240,10 @@ ESPIDF_ETHERNET_O = $(addprefix $(ESPCOMP)/ethernet/,\ emac_main.o \ ) +ESPIDF_BLUETOOTH_O = $(addprefix $(ESPCOMP)/bt/,\ + bt.o \ + ) + $(BUILD)/$(ESPCOMP)/expat/%.o: CFLAGS += -Wno-unused-function ESPIDF_EXPAT_O = $(addprefix $(ESPCOMP)/expat/,\ library/xmltok_ns.o \ @@ -518,6 +523,7 @@ ESPIDF_WPA_SUPPLICANT_O = $(addprefix $(ESPCOMP)/wpa_supplicant/,\ ) OBJ_ESPIDF = +OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_BLUETOOTH_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NEWLIB_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_DRIVER_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ESP32_O)) @@ -572,6 +578,7 @@ APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++ APP_LD_ARGS += $(ESPCOMP)/newlib/lib/libc.a APP_LD_ARGS += $(ESPCOMP)/newlib/lib/libm.a APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a +APP_LD_ARGS += $(ESPCOMP)/bt/lib/libbtdm_app.a APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lnet80211 -lphy -lrtc -lrtc_clk -lrtc_pm -lpp -lwpa -lsmartconfig -lcoexist APP_LD_ARGS += $(OBJ) APP_LD_ARGS += --end-group diff --git a/esp32/modnetwork.c b/esp32/modnetwork.c index bb42defd0..09745ec81 100644 --- a/esp32/modnetwork.c +++ b/esp32/modnetwork.c @@ -48,6 +48,8 @@ #include "lwip/dns.h" #include "tcpip_adapter.h" +#include "network_bluetooth.h" + #define MODNETWORK_INCLUDE_CONSTANTS (1) NORETURN void _esp_exceptions(esp_err_t e) { @@ -514,12 +516,14 @@ STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode); -STATIC const mp_map_elem_t mp_module_network_globals_table[] = { +STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) }, { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_initialize_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj }, + { MP_ROM_QSTR(MP_QSTR_Bluetooth), MP_ROM_PTR(&network_bluetooth_type) }, + #if MODNETWORK_INCLUDE_CONSTANTS { MP_OBJ_NEW_QSTR(MP_QSTR_STA_IF), MP_OBJ_NEW_SMALL_INT(WIFI_IF_STA)}, diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 5fbb85697..cf403b44c 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -33,19 +33,28 @@ #include "py/mphal.h" #include "modmachine.h" +#include "bt.h" +#include "network_bluetooth.h" + + +#define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) /******************************************************************************/ -// MicroPython bindings for hw_spi +// MicroPython bindings for network_bluetooth + +const mp_obj_type_t network_bluetooth_type; STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "Bluetooth()"); + mp_printf(print, "Bluetooth(%p)", self); } STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new\n"); enum { + ARG_id, /* ARG_bits, ARG_firstbit, @@ -66,49 +75,78 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type, size_t n_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - machine_hw_spi_obj_t *self = m_new_obj(machine_hw_spi_obj_t); - self->base.type = &machine_hw_spi_type; - - initialize( - self, - args[ARG_id].u_int, - args[ARG_baudrate].u_int, - args[ARG_polarity].u_int, - args[ARG_phase].u_int, - args[ARG_bits].u_int, - args[ARG_firstbit].u_int, - args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj), - args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj), - args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj)); + network_bluetooth_obj_t *self = m_new_obj(network_bluetooth_obj_t); + self->base.type = &network_bluetooth_type; + + /* + initialize( + self, + args[ARG_id].u_int, + args[ARG_baudrate].u_int, + args[ARG_polarity].u_int, + args[ARG_phase].u_int, + args[ARG_bits].u_int, + args[ARG_firstbit].u_int, + args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj), + args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj), + args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj)); + */ return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t network_bluetooth_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_init\n"); + (void)self_in; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_bluetooth_init_obj, network_bluetooth_init); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_init); + +STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); + +STATIC mp_obj_t network_bluetooth_test(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_test\n"); + + { // make_new code + esp_bt_controller_init(); +#if 0 + esp_err_t ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); + + switch(ret) { + case ESP_OK: + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization ok\n"); + break; + default: + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization failed, code: %d\n", ret); + } +#endif + } + -STATIC mp_obj_t network_bluetooth_deinit(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_bluetooth_deinit_obj, network_bluetooth_deinit); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_test_obj, network_bluetooth_test); STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_test), MP_ROM_PTR(&network_bluetooth_test_obj) }, // class constants /* - { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, - { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) }, - { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, - { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP_ONLY) }, - { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN_ONLY) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, - */ + { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, + { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) }, + { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, + { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, + { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, + */ }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_locals_dict, network_bluetooth_locals_dict_table); diff --git a/esp32/network_bluetooth.h b/esp32/network_bluetooth.h index dbc0ead7b..1c304729b 100644 --- a/esp32/network_bluetooth.h +++ b/esp32/network_bluetooth.h @@ -29,8 +29,10 @@ #include "py/obj.h" -typdef struct { - mp_obj_type_t base; +typedef struct { + mp_obj_base_t base; } network_bluetooth_obj_t; +extern const mp_obj_type_t network_bluetooth_type; + #endif // MICROPY_INCLUDED_ESP32_NETWORK_BLUETOOTH_H diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index a7084dfb2..e3c8f4e25 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -53,6 +53,7 @@ #define CONFIG_NEWLIB_STDOUT_ADDCR 1 #define CONFIG_PHY_ENABLED 1 #define CONFIG_WIFI_ENABLED 1 +#define CONFIG_BT_ENABLED 1 #define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 #define CONFIG_MEMMAP_SMP 1 From b53cb3c7bb8c9facd8277ac3d7360c1cc2f8da09 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 5 Apr 2017 10:16:39 -0700 Subject: [PATCH 03/98] esp32/main.c: reduced heap to 64k esp32/network_bluetooth.c: incremental changes esp32/sdconfig.h: Enabled bluetooth --- esp32/main.c | 2 +- esp32/network_bluetooth.c | 4 ++-- esp32/sdkconfig.h | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/esp32/main.c b/esp32/main.c index c20897a7b..e8f8ef29f 100644 --- a/esp32/main.c +++ b/esp32/main.c @@ -51,7 +51,7 @@ #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) #define MP_TASK_STACK_SIZE (16 * 1024) #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) -#define MP_TASK_HEAP_SIZE (96 * 1024) +#define MP_TASK_HEAP_SIZE (64 * 1024) //STATIC StaticTask_t mp_task_tcb; //STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8))); diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index cf403b44c..ccef266da 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -112,8 +112,9 @@ STATIC mp_obj_t network_bluetooth_test(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_test\n"); { // make_new code + printf("Before esp_bt_controller_init()\n"); esp_bt_controller_init(); -#if 0 + printf("After esp_bt_controller_init()\n"); esp_err_t ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); switch(ret) { @@ -123,7 +124,6 @@ STATIC mp_obj_t network_bluetooth_test(mp_obj_t self_in) { default: NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization failed, code: %d\n", ret); } -#endif } diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index e3c8f4e25..bc471bf58 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -1,5 +1,4 @@ #define CONFIG_TRACEMEM_RESERVE_DRAM 0x0 -#define CONFIG_BT_RESERVE_DRAM 0x0 #define CONFIG_ULP_COPROC_RESERVE_MEM 0 #define CONFIG_PHY_DATA_OFFSET 0xf000 #define CONFIG_APP_OFFSET 0x10000 @@ -54,6 +53,8 @@ #define CONFIG_PHY_ENABLED 1 #define CONFIG_WIFI_ENABLED 1 #define CONFIG_BT_ENABLED 1 +#define CONFIG_BLUEDROID_ENABLED 1 +#define CONFIG_BT_RESERVE_DRAM 0x10000 #define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 #define CONFIG_MEMMAP_SMP 1 @@ -89,3 +90,6 @@ #define CONFIG_TOOLPREFIX "xtensa-esp32-elf-" #define CONFIG_PYTHON "python2" + + + From 6690be053de1c185eb3fe659fc07acb1b3357d1c Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 6 Apr 2017 15:32:07 -0700 Subject: [PATCH 04/98] esp32/Makefile: added includes for bluetooth --- esp32/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/esp32/Makefile b/esp32/Makefile index f54bf1a58..a3cbf4f87 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -79,6 +79,7 @@ INC += -I$(ESPCOMP)/wpa_supplicant/port/include INC += -I$(ESPCOMP)/ethernet/include INC += -I$(ESPCOMP)/tcpip_adapter/include INC += -I$(ESPCOMP)/bt/include +INC += -I$(ESPCOMP)/bt/bluedroid/api/include/ CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM $(INC) CFLAGS += -DIDF_VER=\"$(IDF_VER)\" From 5ab9967ecf3f151ca4236196725fc7cfc524d12d Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 6 Apr 2017 15:32:24 -0700 Subject: [PATCH 05/98] esp32/modnetwork: added declaration for bluetooth object --- esp32/modnetwork.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/modnetwork.c b/esp32/modnetwork.c index 09745ec81..e5f17c863 100644 --- a/esp32/modnetwork.c +++ b/esp32/modnetwork.c @@ -48,7 +48,7 @@ #include "lwip/dns.h" #include "tcpip_adapter.h" -#include "network_bluetooth.h" +extern const mp_obj_type_t network_bluetooth_type; #define MODNETWORK_INCLUDE_CONSTANTS (1) From d6e775596fe7b699c9469ffec1a98fadc94d3917 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 6 Apr 2017 15:33:04 -0700 Subject: [PATCH 06/98] esp32/network_bluetooth.h: removed this unnecessary header --- esp32/network_bluetooth.h | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 esp32/network_bluetooth.h diff --git a/esp32/network_bluetooth.h b/esp32/network_bluetooth.h deleted file mode 100644 index 1c304729b..000000000 --- a/esp32/network_bluetooth.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 "Eric Poulsen" - * - * 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_ESP32_NETWORK_BLUETOOTH_H -#define MICROPY_INCLUDED_ESP32_NETWORK_BLUETOOTH_H - -#include "py/obj.h" - -typedef struct { - mp_obj_base_t base; -} network_bluetooth_obj_t; - -extern const mp_obj_type_t network_bluetooth_type; - -#endif // MICROPY_INCLUDED_ESP32_NETWORK_BLUETOOTH_H From 5dfb5990675d0566c06fd0a35033621d816fe180 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 6 Apr 2017 15:33:32 -0700 Subject: [PATCH 07/98] esp32/network_bluetooth.c: Added init, and params setting Currently broken, as the call to network_bluetooth_set_ble_adv_param in network_bluetooth_init_helper to set defaults causes a segfault --- esp32/network_bluetooth.c | 273 +++++++++++++++++++++++++++++++++++--- 1 file changed, 251 insertions(+), 22 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index ccef266da..c02e19cae 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -28,17 +28,165 @@ #include #include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + #include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" #include "modmachine.h" #include "bt.h" +#include "esp_gap_ble_api.h" + +#define HCI_GRP_HOST_CONT_BASEBAND_CMDS 0x03 +#define HCI_GRP_BLE_CMDS 0x08 + +#define H4_TYPE_COMMAND 0x01 +#define H4_TYPE_ACL 0x02 +#define H4_TYPE_SCO 0x03 +#define H4_TYPE_EVENT 0x04 + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +#define MAKE_OPCODE(OGF, OCF) (((OGF) << 10) | (OCF)) +#define MAKE_OPCODE_BYTES(OGF, OCF) { (MAKE_OPCODE(OGF, OCF) & 0xff), (MAKE_OPCODE(OGF, OCF) >> 8) } + +#define BD_ADDR_LEN (6) /* Device address length */ +typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ + +#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);} +#define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);} +#define BDADDR_TO_STREAM(p, a) {int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - ijk];} +#define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} + -#include "network_bluetooth.h" +typedef struct { + mp_obj_base_t base; + enum { + NETWORK_BLUETOOTH_STATE_DEINIT, + NETWORK_BLUETOOTH_STATE_INIT, + } state; + esp_ble_adv_params_t params; +} network_bluetooth_obj_t; + + +typedef struct { + union { + uint8_t preamble[3]; + struct { + uint8_t opcode[2]; + uint8_t param_size; + }; + }; +} hci_cmd_def_t; + +hci_cmd_def_t hci_commands[4] = { + { + .opcode = MAKE_OPCODE_BYTES(HCI_GRP_HOST_CONT_BASEBAND_CMDS, 0x03), // HCI_RESET + .param_size = 0x00, + }, + { + .opcode = MAKE_OPCODE_BYTES(HCI_GRP_BLE_CMDS, 0x0A), // HCI_BLE_WRITE_ADV_ENABLE + .param_size = 0x01, + }, + { + .opcode = MAKE_OPCODE_BYTES(HCI_GRP_BLE_CMDS, 0x06), // HCI_BLE_WRITE_ADV_PARAMS + .param_size = 0x0f, + }, + { + .opcode = MAKE_OPCODE_BYTES(HCI_GRP_BLE_CMDS, 0x08), // HCI_BLE_WRITE_ADV_DATA + .param_size = 0x1f, + }, +}; + +enum { + HCI_CMD_RESET = 0, + HCI_CMD_BLE_WRITE_ADV_ENABLE = 1, + HCI_CMD_BLE_WRITE_ADV_PARAMS = 2, + HCI_CMD_BLE_WRITE_ADV_DATA = 3 +} hci_cmd_t; + +STATIC mp_obj_t network_bluetooth_set_ble_adv_param(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); #define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) +#define CREATE_HCI_HOST_COMMAND(cmd)\ + size_t param_size = hci_commands[(cmd)].param_size;\ + size_t buf_size = 1 + sizeof(hci_cmd_def_t) + param_size;\ + uint8_t buf[buf_size];\ + uint8_t *param = buf + buf_size - param_size;\ + memset(buf, 0, buf_size);\ + buf[0] = H4_TYPE_COMMAND;\ + memcpy(buf + 1, &hci_commands[(cmd)], sizeof(hci_cmd_def_t)); + +STATIC void dumpBuf(const uint8_t *buf, size_t len) { + while(len--) + printf("%02X ", *buf++); + printf("\n"); +} + +STATIC void network_bluetooth_send_data(uint8_t *buf, size_t buf_size) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_send_data\n"); + int tries = 3; + bool ready; + + // FIXME: A somewhat naïve approach; look into using esp_vhci_host_callback + while(((ready = esp_vhci_host_check_send_available()) == false) && tries--) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_send_data: waiting for host to be ready\n"); + vTaskDelay((10 / portTICK_PERIOD_MS) || 1); + } + printf("Sending: "); + dumpBuf(buf, buf_size); + + esp_vhci_host_send_packet(buf, buf_size); +} + +static void network_bluetooth_send_hci_reset() { + CREATE_HCI_HOST_COMMAND(HCI_CMD_RESET); + (void)param; + network_bluetooth_send_data(buf, buf_size); +} + +STATIC void network_bluetooth_init_helper(network_bluetooth_obj_t *self) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_init_helper\n"); + if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); + + esp_bt_controller_init(); + esp_err_t ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); + + switch(ret) { + case ESP_OK: + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization ok\n"); + break; + default: + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization failed, code: %d\n", ret); + } + network_bluetooth_send_hci_reset(); + + // Set defaults for BLE ADV params + mp_map_t kw_args = { + .all_keys_are_qstrs = 0, + .is_fixed = 1, + .is_ordered = 1, + .used = 0, + .alloc = 0, + .table = NULL, + }; + + mango; // FIXME; this crashes -- why? + network_bluetooth_set_ble_adv_param(1, (mp_obj_t*)self, &kw_args); + + self->state = NETWORK_BLUETOOTH_STATE_INIT; + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); + } + + //return mp_const_none; + return; +} /******************************************************************************/ // MicroPython bindings for network_bluetooth @@ -47,11 +195,35 @@ const mp_obj_type_t network_bluetooth_type; STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "Bluetooth(%p)", self); + mp_printf(print, "Bluetooth(params=())", self); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "adv_int_min = %u, " + "adv_int_max = %u, " + "adv_type = %u, " + "own_addr_type = %u, " + "peer_addr = %02X:%02X:%02X:%02X:%02X:%02X, " + "peer_addr_type = %u, " + "channel_map = %u, " + "adv_filter_policy = %u, \n" + , + (unsigned int)(self->params.adv_int_min / 1.6), + (unsigned int)(self->params.adv_int_max / 1.6), + self->params.adv_type, + self->params.own_addr_type, + self->params.peer_addr[0], + self->params.peer_addr[1], + self->params.peer_addr[2], + self->params.peer_addr[3], + self->params.peer_addr[4], + self->params.peer_addr[5], + self->params.peer_addr_type, + self->params.channel_map, + self->params.adv_filter_policy + ); } -STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { +STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new\n"); enum { ARG_id, @@ -78,6 +250,8 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type, size_t n_a network_bluetooth_obj_t *self = m_new_obj(network_bluetooth_obj_t); self->base.type = &network_bluetooth_type; + network_bluetooth_init_helper(self); + /* initialize( self, @@ -96,50 +270,105 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type, size_t n_a } STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_init\n"); - (void)self_in; + network_bluetooth_init_helper((network_bluetooth_obj_t*) self_in); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_init); STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); + // FIXME return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); -STATIC mp_obj_t network_bluetooth_test(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_test\n"); +STATIC mp_obj_t network_bluetooth_set_ble_adv_param(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + network_bluetooth_obj_t *self = pos_args[0]; - { // make_new code - printf("Before esp_bt_controller_init()\n"); - esp_bt_controller_init(); - printf("After esp_bt_controller_init()\n"); - esp_err_t ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); + enum { + ARG_int_min, + ARG_int_max, + ARG_type, + ARG_own_addr_type, + ARG_peer_addr, + ARG_peer_addr_type, + ARG_channel_map, + ARG_filter_policy + }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1280} }, + { MP_QSTR_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1280} }, + { MP_QSTR_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_TYPE_IND }}, + { MP_QSTR_own_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BLE_ADDR_TYPE_PUBLIC }}, + { MP_QSTR_peer_addr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_peer_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BLE_ADDR_TYPE_PUBLIC }}, + { MP_QSTR_channel_map, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_CHNL_ALL }}, + { MP_QSTR_filter_policy, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY }}, + }; - switch(ret) { - case ESP_OK: - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization ok\n"); - break; - default: - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization failed, code: %d\n", ret); - } + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), + allowed_args, args); + + if (mp_obj_get_type(args[ARG_peer_addr].u_obj) != &mp_type_bytearray) { + mp_raise_ValueError("peer_addr must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); } + self->params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count + self->params.adv_int_max = args[ARG_int_max].u_int * 1.6; + self->params.adv_type = args[ARG_type].u_int; + self->params.own_addr_type = args[ARG_own_addr_type].u_int; + self->params.peer_addr_type = args[ARG_peer_addr_type].u_int; + self->params.channel_map = args[ARG_channel_map].u_int; + self->params.adv_filter_policy = args[ARG_filter_policy].u_int; + mp_buffer_info_t bufinfo; + mp_get_buffer(args[ARG_peer_addr].u_obj, &bufinfo, MP_BUFFER_READ); + if (bufinfo.len != ESP_BD_ADDR_LEN) { + mp_raise_ValueError("peer_addr must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); + } + memcpy(self->params.peer_addr, bufinfo.buf, ESP_BD_ADDR_LEN); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_test_obj, network_bluetooth_test); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_set_ble_adv_param_obj, 1, network_bluetooth_set_ble_adv_param); STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_test), MP_ROM_PTR(&network_bluetooth_test_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_ble_adv_param), MP_ROM_PTR(&network_bluetooth_set_ble_adv_param_obj) }, // class constants + + // esp_ble_adv_type_t + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, + + // esp_ble_addr_type_t + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, + + // esp_ble_adv_channel_t + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, + + // esp_ble_adv_filter_t + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) }, /* - { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) }, { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) }, { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP_ONLY) }, From aa66352242ca2a62515cf377d6927f2cd2dce5b4 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 10 Apr 2017 15:21:27 -0700 Subject: [PATCH 08/98] esp32/Makefile: added a bunch more objects and headers for bluetooth --- esp32/Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/esp32/Makefile b/esp32/Makefile index a3cbf4f87..a5f389909 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -79,7 +79,15 @@ INC += -I$(ESPCOMP)/wpa_supplicant/port/include INC += -I$(ESPCOMP)/ethernet/include INC += -I$(ESPCOMP)/tcpip_adapter/include INC += -I$(ESPCOMP)/bt/include +INC += -I$(ESPCOMP)/bt/bluedroid/include/ INC += -I$(ESPCOMP)/bt/bluedroid/api/include/ +INC += -I$(ESPCOMP)/bt/bluedroid/osi/include/ +INC += -I$(ESPCOMP)/bt/bluedroid/gki/include/ +INC += -I$(ESPCOMP)/bt/bluedroid/stack/include/ +INC += -I$(ESPCOMP)/bt/bluedroid/bta/include/ +INC += -I$(ESPCOMP)/bt/bluedroid/btc/include/ +INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/std/include +INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/esp/include CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM $(INC) CFLAGS += -DIDF_VER=\"$(IDF_VER)\" @@ -244,6 +252,10 @@ ESPIDF_ETHERNET_O = $(addprefix $(ESPCOMP)/ethernet/,\ ESPIDF_BLUETOOTH_O = $(addprefix $(ESPCOMP)/bt/,\ bt.o \ + bluedroid/api/esp_gap_ble_api.o \ + bluedroid/api/esp_bt_main.o \ + bluedroid/btc/core/btc_task.o \ + bluedroid/gki/gki_buffer.o \ ) $(BUILD)/$(ESPCOMP)/expat/%.o: CFLAGS += -Wno-unused-function From 430ab74753bb0da41e285e6a7b6dcde05c1b44a9 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 10 Apr 2017 15:21:51 -0700 Subject: [PATCH 09/98] esp32/network_bluetooth.c: Power through adding more options for ble --- esp32/network_bluetooth.c | 406 +++++++++++++++++++++++--------------- 1 file changed, 249 insertions(+), 157 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index c02e19cae..b325d17ef 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -34,6 +34,7 @@ #include "py/runtime.h" #include "py/stream.h" #include "py/mphal.h" +#include "py/objstr.h" #include "modmachine.h" #include "bt.h" @@ -61,17 +62,46 @@ typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ #define BDADDR_TO_STREAM(p, a) {int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - ijk];} #define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} +const mp_obj_type_t network_bluetooth_type; typedef struct { mp_obj_base_t base; enum { NETWORK_BLUETOOTH_STATE_DEINIT, - NETWORK_BLUETOOTH_STATE_INIT, + NETWORK_BLUETOOTH_STATE_INIT } state; esp_ble_adv_params_t params; + esp_ble_adv_data_t data; } network_bluetooth_obj_t; +STATIC network_bluetooth_obj_t network_bluetooth_singleton = { + .base = { &network_bluetooth_type }, + .params = { + .adv_int_min = 1280 * 1.6, + .adv_int_max = 1280 * 1.6, + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, + .peer_addr = { 0,0,0,0,0,0 }, + .peer_addr_type = BLE_ADDR_TYPE_PUBLIC, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + }, + .data = { + .set_scan_rsp = false, + .include_name = false, + .include_txpower = false, + .min_interval = 1280 * 1.6, + .max_interval = 1280 * 1.6, + .appearance = 0, + .p_manufacturer_data = NULL, + .manufacturer_len = 0, + .p_service_data = NULL, + .service_data_len = 0, + .p_service_uuid = 0, + .flag = 0 + }, +}; typedef struct { union { @@ -109,8 +139,6 @@ enum { HCI_CMD_BLE_WRITE_ADV_DATA = 3 } hci_cmd_t; -STATIC mp_obj_t network_bluetooth_set_ble_adv_param(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); - #define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) #define CREATE_HCI_HOST_COMMAND(cmd)\ size_t param_size = hci_commands[(cmd)].param_size;\ @@ -131,12 +159,13 @@ STATIC void network_bluetooth_send_data(uint8_t *buf, size_t buf_size) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_send_data\n"); int tries = 3; bool ready; - + // FIXME: A somewhat naïve approach; look into using esp_vhci_host_callback while(((ready = esp_vhci_host_check_send_available()) == false) && tries--) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_send_data: waiting for host to be ready\n"); vTaskDelay((10 / portTICK_PERIOD_MS) || 1); } + //FIXME printf("Sending: "); dumpBuf(buf, buf_size); @@ -149,54 +178,16 @@ static void network_bluetooth_send_hci_reset() { network_bluetooth_send_data(buf, buf_size); } -STATIC void network_bluetooth_init_helper(network_bluetooth_obj_t *self) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_init_helper\n"); - if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); - - esp_bt_controller_init(); - esp_err_t ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); - - switch(ret) { - case ESP_OK: - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization ok\n"); - break; - default: - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization failed, code: %d\n", ret); - } - network_bluetooth_send_hci_reset(); - - // Set defaults for BLE ADV params - mp_map_t kw_args = { - .all_keys_are_qstrs = 0, - .is_fixed = 1, - .is_ordered = 1, - .used = 0, - .alloc = 0, - .table = NULL, - }; - - mango; // FIXME; this crashes -- why? - network_bluetooth_set_ble_adv_param(1, (mp_obj_t*)self, &kw_args); - - self->state = NETWORK_BLUETOOTH_STATE_INIT; - } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); - } - - //return mp_const_none; - return; -} /******************************************************************************/ // MicroPython bindings for network_bluetooth -const mp_obj_type_t network_bluetooth_type; STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "Bluetooth(params=())", self); NETWORK_BLUETOOTH_DEBUG_PRINTF( + "Bluetooth(params = (" "adv_int_min = %u, " "adv_int_max = %u, " "adv_type = %u, " @@ -204,7 +195,9 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m "peer_addr = %02X:%02X:%02X:%02X:%02X:%02X, " "peer_addr_type = %u, " "channel_map = %u, " - "adv_filter_policy = %u, \n" + "adv_filter_policy = %u" + ")" + ")\n" , (unsigned int)(self->params.adv_int_min / 1.6), (unsigned int)(self->params.adv_int_max / 1.6), @@ -223,69 +216,40 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m } -STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new\n"); - enum { - ARG_id, - /* - ARG_bits, - ARG_firstbit, - ARG_sck, - ARG_mosi, - ARG_miso - */ - }; - static const mp_arg_t allowed_args[] = { - /* - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, - { MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} }, - { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - */ - }; - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - network_bluetooth_obj_t *self = m_new_obj(network_bluetooth_obj_t); - self->base.type = &network_bluetooth_type; - - network_bluetooth_init_helper(self); - - /* - initialize( - self, - args[ARG_id].u_int, - args[ARG_baudrate].u_int, - args[ARG_polarity].u_int, - args[ARG_phase].u_int, - args[ARG_bits].u_int, - args[ARG_firstbit].u_int, - args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj), - args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj), - args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj)); - */ +STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { + network_bluetooth_obj_t * self = (network_bluetooth_obj_t*)self_in; + if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); - return MP_OBJ_FROM_PTR(self); -} + esp_bt_controller_init(); + esp_err_t ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); -STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { - network_bluetooth_init_helper((network_bluetooth_obj_t*) self_in); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_init); + switch(ret) { + case ESP_OK: + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization ok\n"); + break; + default: + mp_raise_msg(&mp_type_OSError, "BT initialization failed"); -STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); - // FIXME + } + network_bluetooth_send_hci_reset(); + + self->state = NETWORK_BLUETOOTH_STATE_INIT; + + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); + } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_init); -STATIC mp_obj_t network_bluetooth_set_ble_adv_param(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - network_bluetooth_obj_t *self = pos_args[0]; +STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { + network_bluetooth_obj_t *self = &network_bluetooth_singleton; + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_ble_settings(self = %p) n_args = %d\n", self, n_args); + bool changed = false; enum { + // params ARG_int_min, ARG_int_max, ARG_type, @@ -293,89 +257,217 @@ STATIC mp_obj_t network_bluetooth_set_ble_adv_param(size_t n_args, const mp_obj_ ARG_peer_addr, ARG_peer_addr_type, ARG_channel_map, - ARG_filter_policy + ARG_filter_policy, + + // data + ARG_adv_is_scan_rsp, + ARG_adv_dev_name, + ARG_adv_man_name, + ARG_adv_inc_txpower, + ARG_adv_int_min, + ARG_adv_int_max, + ARG_adv_appearance, + ARG_adv_uuid, + ARG_adv_flags }; + static const mp_arg_t allowed_args[] = { - { MP_QSTR_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1280} }, - { MP_QSTR_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1280} }, - { MP_QSTR_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_TYPE_IND }}, - { MP_QSTR_own_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BLE_ADDR_TYPE_PUBLIC }}, - { MP_QSTR_peer_addr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, - { MP_QSTR_peer_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = BLE_ADDR_TYPE_PUBLIC }}, - { MP_QSTR_channel_map, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_CHNL_ALL }}, - { MP_QSTR_filter_policy, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY }}, + { MP_QSTR_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_own_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_peer_addr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_peer_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_channel_map, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_filter_policy, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + + { MP_QSTR_adv_is_scan_rsp, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_adv_dev_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_adv_man_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_adv_inc_tx_power, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_adv_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_adv_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_adv_appearance, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_adv_uuid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, + { MP_QSTR_adv_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NULL }}, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), - allowed_args, args); + mp_arg_parse_all(0, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t peer_addr_buf = { 0 }; + mp_buffer_info_t adv_man_name_buf = { 0 }; + mp_buffer_info_t adv_dev_name_buf = { 0 }; + + + // pre-check complex types + if (args[ARG_peer_addr].u_obj != MP_OBJ_NULL) { + if (mp_obj_get_type(args[ARG_peer_addr].u_obj) != &mp_type_bytearray) { + goto network_bluetooth_bad_byte_array; + } + + mp_get_buffer(args[ARG_peer_addr].u_obj, &peer_addr_buf, MP_BUFFER_READ); + if (peer_addr_buf.len != ESP_BD_ADDR_LEN) { + goto network_bluetooth_bad_byte_array; + } + } + + if (args[ARG_adv_man_name].u_obj != MP_OBJ_NULL) { + if (mp_obj_get_type(args[ARG_adv_man_name].u_obj) == mp_const_none) { + self->data.manufacturer_len = 0; + if (self->data.p_manufacturer_data != NULL) { + m_free(self->data.p_manufacturer_data); + self->data.p_manufacturer_data = NULL; + } + } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_adv_man_name].u_obj)) { + mp_raise_ValueError("adv_man_name must be type str or bytes"); + } + mp_obj_str_get_buffer(args[ARG_peer_addr].u_obj, &adv_man_name_buf, MP_BUFFER_READ); + } - if (mp_obj_get_type(args[ARG_peer_addr].u_obj) != &mp_type_bytearray) { - mp_raise_ValueError("peer_addr must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); + if (args[ARG_adv_dev_name].u_obj != MP_OBJ_NULL) { + if (mp_obj_get_type(args[ARG_adv_dev_name].u_obj) == mp_const_none) { + esp_ble_gap_set_device_name(""); + self->data.include_name = false; + } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_adv_dev_name].u_obj)) { + mp_raise_ValueError("adv_dev_name must be type str or bytes"); + } + mp_obj_str_get_buffer(args[ARG_peer_addr].u_obj, &adv_dev_name_buf, MP_BUFFER_READ); + } + + + // update esp_ble_adv_params_t + + if (args[ARG_int_min].u_int != -1) { + self->params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count + changed = true; + } + if (args[ARG_int_max].u_int != -1) { + self->params.adv_int_max = args[ARG_int_max].u_int * 1.6; + changed = true; + } + if (args[ARG_type].u_int != -1) { + self->params.adv_type = args[ARG_type].u_int; + changed = true; + } + if (args[ARG_own_addr_type].u_int != -1) { + self->params.own_addr_type = args[ARG_own_addr_type].u_int; + changed = true; } - self->params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count - self->params.adv_int_max = args[ARG_int_max].u_int * 1.6; - self->params.adv_type = args[ARG_type].u_int; - self->params.own_addr_type = args[ARG_own_addr_type].u_int; - self->params.peer_addr_type = args[ARG_peer_addr_type].u_int; - self->params.channel_map = args[ARG_channel_map].u_int; - self->params.adv_filter_policy = args[ARG_filter_policy].u_int; - - mp_buffer_info_t bufinfo; - mp_get_buffer(args[ARG_peer_addr].u_obj, &bufinfo, MP_BUFFER_READ); - if (bufinfo.len != ESP_BD_ADDR_LEN) { - mp_raise_ValueError("peer_addr must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); + if (peer_addr_buf.buf != NULL) { + memcpy(self->params.peer_addr, peer_addr_buf.buf, ESP_BD_ADDR_LEN); + changed = true; } - memcpy(self->params.peer_addr, bufinfo.buf, ESP_BD_ADDR_LEN); + + if (args[ARG_peer_addr_type].u_int != -1) { + self->params.peer_addr_type = args[ARG_peer_addr_type].u_int; + changed = true; + } + if (args[ARG_channel_map].u_int != -1) { + self->params.channel_map = args[ARG_channel_map].u_int; + changed = true; + } + if (args[ARG_filter_policy].u_int != -1) { + self->params.adv_filter_policy = args[ARG_filter_policy].u_int; + changed = true; + } + + + // update esp_ble_adv_data_t + // + + if (args[ARG_adv_is_scan_rsp].u_int != -1) { + self->data.set_scan_rsp = mp + + } + + if (adv_dev_name_buf.buf != NULL) { + esp_ble_gap_set_device_name(adv_dev_name_buf.buf); + self->data.include_name = adv_dev_name_buf.len > 0; + changed = true; + } + + if (adv_man_name_buf.buf != NULL) { + + self->data.manufacturer_len = 0; + if (self->data.p_manufacturer_data != NULL) { + m_free(self->data.p_manufacturer_data); + self->data.p_manufacturer_data = NULL; + } + + if (buffer.len > 0) { + self->data.p_manufacturer_data = m_malloc(adv_man_name_buf.len); + memcpy(self->data.p_manufacturer_data, buffer.buf, buffer.len); + self->data.include_name = adv_man_name_buf.len > 0; + self->data.manufacturer_len = 0; + } + changed = true; + } + return mp_const_none; + +network_bluetooth_bad_byte_array: + mp_raise_ValueError("peer_addr must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_set_ble_adv_param_obj, 1, network_bluetooth_set_ble_adv_param); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_ble_settings_obj, 1, network_bluetooth_ble_settings); + +STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + + network_bluetooth_obj_t *self = &network_bluetooth_singleton; + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new, self = %p, n_args = %d, n_kw = %d\n", self, n_args, n_kw ); + if (n_args != 0 || n_kw != 0) { + mp_raise_TypeError("Constructor takes no arguments"); + } + + network_bluetooth_init(self); + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); + // FIXME + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); + STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // instance methods + { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_set_ble_adv_param), MP_ROM_PTR(&network_bluetooth_set_ble_adv_param_obj) }, // class constants - + // esp_ble_adv_type_t - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, // esp_ble_addr_type_t - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, // esp_ble_adv_channel_t - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, // esp_ble_adv_filter_t - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) }, - /* - { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) }, - { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) }, - { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP_ONLY) }, - { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN_ONLY) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) }, - { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) }, - */ + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_locals_dict, network_bluetooth_locals_dict_table); From aa689ccd8848820bbea4e080dfee8d96d79cf72b Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 10 Apr 2017 15:34:38 -0700 Subject: [PATCH 10/98] esp32/network_bluetooth.c: Power through adding more options for ble --- esp32/network_bluetooth.c | 73 +++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 14 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index b325d17ef..37534971d 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -48,6 +48,8 @@ #define H4_TYPE_SCO 0x03 #define H4_TYPE_EVENT 0x04 +#define NETWORK_BLUETOOTH_ADV_UUID_LEN 16 + #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -281,10 +283,10 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po { MP_QSTR_channel_map, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, { MP_QSTR_filter_policy, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, - { MP_QSTR_adv_is_scan_rsp, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_adv_is_scan_rsp, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = NULL}}, { MP_QSTR_adv_dev_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, { MP_QSTR_adv_man_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, - { MP_QSTR_adv_inc_tx_power, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_adv_inc_tx_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = NULL }}, { MP_QSTR_adv_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, { MP_QSTR_adv_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, { MP_QSTR_adv_appearance, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, @@ -298,17 +300,18 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po mp_buffer_info_t peer_addr_buf = { 0 }; mp_buffer_info_t adv_man_name_buf = { 0 }; mp_buffer_info_t adv_dev_name_buf = { 0 }; + mp_buffer_info_t adv_uuid_buf = { 0 }; // pre-check complex types if (args[ARG_peer_addr].u_obj != MP_OBJ_NULL) { if (mp_obj_get_type(args[ARG_peer_addr].u_obj) != &mp_type_bytearray) { - goto network_bluetooth_bad_byte_array; + goto network_bluetooth_bad_peer; } mp_get_buffer(args[ARG_peer_addr].u_obj, &peer_addr_buf, MP_BUFFER_READ); if (peer_addr_buf.len != ESP_BD_ADDR_LEN) { - goto network_bluetooth_bad_byte_array; + goto network_bluetooth_bad_peer; } } @@ -335,6 +338,17 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po mp_obj_str_get_buffer(args[ARG_peer_addr].u_obj, &adv_dev_name_buf, MP_BUFFER_READ); } + if (args[ARG_adv_uuid].u_obj != MP_OBJ_NULL) { + if (mp_obj_get_type(args[ARG_adv_uuid].u_obj) != &mp_type_bytearray) { + goto NETWORK_BLUETOOTH_BAD_UUID; + } + + mp_get_buffer(args[ARG_adv_uuid].u_obj, &adv_uuid_buf, MP_BUFFER_READ); + if (adv_uuid_buf.len != NETWORK_BLUETOOTH_ADV_UUID_LEN) { + goto NETWORK_BLUETOOTH_BAD_UUID; + } + } + // update esp_ble_adv_params_t @@ -377,9 +391,9 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po // update esp_ble_adv_data_t // - if (args[ARG_adv_is_scan_rsp].u_int != -1) { - self->data.set_scan_rsp = mp - + if (args[ARG_adv_is_scan_rsp].u_obj != NULL) { + self->data.set_scan_rsp = mp_obj_is_true(args[ARG_adv_is_scan_rsp].u_obj); + changed = true; } if (adv_dev_name_buf.buf != NULL) { @@ -389,26 +403,57 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po } if (adv_man_name_buf.buf != NULL) { - - self->data.manufacturer_len = 0; + self->data.manufacturer_len = adv_man_name_buf.len; if (self->data.p_manufacturer_data != NULL) { m_free(self->data.p_manufacturer_data); self->data.p_manufacturer_data = NULL; } - if (buffer.len > 0) { + if (adv_man_name_buf.len > 0) { self->data.p_manufacturer_data = m_malloc(adv_man_name_buf.len); - memcpy(self->data.p_manufacturer_data, buffer.buf, buffer.len); - self->data.include_name = adv_man_name_buf.len > 0; - self->data.manufacturer_len = 0; + memcpy(self->data.p_manufacturer_data, adv_man_name_buf.buf, adv_man_name_buf.len); } + + changed = true; + } + + if (args[ARG_adv_inc_txpower].u_obj != NULL) { + self->data.include_txpower = mp_obj_is_true(args[ARG_adv_inc_txpower].u_obj); + changed = true; + } + + if (args[ARG_adv_int_min].u_int != NULL) { + self->data.min_interval = args[ARG_adv_int_min].u_int; + changed = true; + } + + if (args[ARG_adv_int_max].u_int != NULL) { + self->data.max_interval = args[ARG_adv_int_max].u_int; + changed = true; + } + + if (args[ARG_adv_appearance].u_int != NULL) { + self->data.appearance = args[ARG_adv_appearance].u_int; + changed = true; + } + + if (adv_dev_name_buf.buf != NULL) { + esp_ble_gap_set_device_name(adv_dev_name_buf.buf); + self->data.include_name = adv_dev_name_buf.len > 0; + changed = true; + } + + if (args[ARG_adv_flags].u_int != NULL) { + self->data.flag = args[ARG_adv_flags].u_int; changed = true; } return mp_const_none; -network_bluetooth_bad_byte_array: +NETWORK_BLUETOOTH_BAD_PEER: mp_raise_ValueError("peer_addr must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); +NETWORK_BLUETOOTH_BAD_UUID: + mp_raise_ValueError("adv_uuid must be bytearray(" TOSTRING(NETWORK_BLUETOOTH_ADV_UUID_LEN ) ")"); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_ble_settings_obj, 1, network_bluetooth_ble_settings); From b3f9f9f6f395329d649c05c0e8916f65e8a115b7 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 10 Apr 2017 15:35:57 -0700 Subject: [PATCH 11/98] esp32/network_bluetooth.c: Power through adding more options for ble --- esp32/network_bluetooth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 37534971d..f80ef7037 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -437,9 +437,9 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po changed = true; } - if (adv_dev_name_buf.buf != NULL) { - esp_ble_gap_set_device_name(adv_dev_name_buf.buf); - self->data.include_name = adv_dev_name_buf.len > 0; + if (adv_uuid_buf.buf != NULL) { + mango; // FIXME -- finish doing uuid like man name + self->data.include_name = adv_uuid_buf.len > 0; changed = true; } From b30b9b0686ddf963dc0836941680ec101877e095 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 11 Apr 2017 16:07:31 -0700 Subject: [PATCH 12/98] esp32/Makefile: Added a whole bunch of BT objects --- esp32/Makefile | 160 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 148 insertions(+), 12 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index a5f389909..d4d76ece4 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -2,6 +2,7 @@ include ../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h +QSTR_GEN_EXTRA_CFLAGS += $(BT_INC) MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 @@ -78,16 +79,38 @@ INC += -I$(ESPCOMP)/wpa_supplicant/include INC += -I$(ESPCOMP)/wpa_supplicant/port/include INC += -I$(ESPCOMP)/ethernet/include INC += -I$(ESPCOMP)/tcpip_adapter/include -INC += -I$(ESPCOMP)/bt/include -INC += -I$(ESPCOMP)/bt/bluedroid/include/ -INC += -I$(ESPCOMP)/bt/bluedroid/api/include/ -INC += -I$(ESPCOMP)/bt/bluedroid/osi/include/ -INC += -I$(ESPCOMP)/bt/bluedroid/gki/include/ -INC += -I$(ESPCOMP)/bt/bluedroid/stack/include/ -INC += -I$(ESPCOMP)/bt/bluedroid/bta/include/ -INC += -I$(ESPCOMP)/bt/bluedroid/btc/include/ -INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/std/include -INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/esp/include + + +# Bluetooth includes have to be separate because +# esp-idf/components/bt/bluedroid/osi/include/list.h +# somehow interferes with compiling FreeRTOS, as it +# makes List_t "not defined." +# +# This is why we have separate build rules for +# objects in the /bt/ directory, and for +# the MicroPython esp32/network_bluetooth.c + +BT_INC = +BT_INC += -I$(ESPCOMP)/bt/bluedroid/api/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/bta/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/bta/sys/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/btc/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/esp/blufi/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/esp/include +BT_INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/std/include +BT_INC += -I$(ESPCOMP)/bt/bluedroid/btcore/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/device/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/gki/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/hci/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/osi/include/ # Causes problems with List_t in FreeRTOS +BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/gap/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/gatt/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/l2cap/include/ +BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/smp/include/ +BT_INC += -I$(ESPCOMP)/bt/include +BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/sdp/include/ CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM $(INC) CFLAGS += -DIDF_VER=\"$(IDF_VER)\" @@ -250,14 +273,124 @@ ESPIDF_ETHERNET_O = $(addprefix $(ESPCOMP)/ethernet/,\ emac_main.o \ ) +$(BUILD)/$(ESPCOMP)/bt/%.o: CFLAGS += $(BT_INC) +$(BUILD)/$(ESPCOMP)/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.o: CFLAGS += -Wno-error=strict-aliasing +$(BUILD)/$(ESPCOMP)/bt/bluedroid/stack/btu/btu_task.o: CFLAGS += -Wno-error=strict-aliasing + ESPIDF_BLUETOOTH_O = $(addprefix $(ESPCOMP)/bt/,\ - bt.o \ - bluedroid/api/esp_gap_ble_api.o \ bluedroid/api/esp_bt_main.o \ + bluedroid/api/esp_gap_ble_api.o \ + bluedroid/bta/dm/bta_dm_act.o \ + bluedroid/bta/dm/bta_dm_api.o \ + bluedroid/bta/dm/bta_dm_cfg.o \ + bluedroid/bta/dm/bta_dm_ci.o \ + bluedroid/bta/dm/bta_dm_main.o \ + bluedroid/bta/dm/bta_dm_pm.o \ + bluedroid/bta/gatt/bta_gattc_act.o \ + bluedroid/bta/gatt/bta_gattc_api.o \ + bluedroid/bta/gatt/bta_gattc_cache.o \ + bluedroid/bta/gatt/bta_gattc_ci.o \ + bluedroid/bta/gatt/bta_gattc_main.o \ + bluedroid/bta/gatt/bta_gattc_utils.o \ + bluedroid/bta/gatt/bta_gatts_act.o \ + bluedroid/bta/gatt/bta_gatts_api.o \ + bluedroid/bta/gatt/bta_gatts_main.o \ + bluedroid/bta/gatt/bta_gatts_utils.o \ + bluedroid/bta/sys/bta_sys_conn.o \ + bluedroid/bta/sys/bta_sys_main.o \ + bluedroid/bta/sys/utl.o \ + bluedroid/btc/core/btc_main.o \ + bluedroid/btc/core/btc_manage.o \ bluedroid/btc/core/btc_task.o \ + bluedroid/btc/profile/esp/blufi/blufi_prf.o \ + bluedroid/btc/profile/esp/blufi/blufi_protocol.o \ + bluedroid/btc/profile/std/gap/btc_gap_ble.o \ + bluedroid/btc/profile/std/gatt/btc_gatt_util.o \ + bluedroid/btc/profile/std/gatt/btc_gattc.o \ + bluedroid/btc/profile/std/gatt/btc_gatts.o \ + bluedroid/btcore/bdaddr.o \ + bluedroid/btif/bta_dm_co.o \ + bluedroid/btif/bta_gattc_co.o \ + bluedroid/btif/bta_gatts_co.o \ + bluedroid/device/controller.o \ + bluedroid/device/interop.o \ bluedroid/gki/gki_buffer.o \ + bluedroid/gki/gki_ulinux.o \ + bluedroid/hci/buffer_allocator.o \ + bluedroid/hci/hci_hal_h4.o \ + bluedroid/hci/hci_layer.o \ + bluedroid/hci/hci_packet_factory.o \ + bluedroid/hci/hci_packet_parser.o \ + bluedroid/hci/packet_fragmenter.o \ + bluedroid/main/bte_init.o \ + bluedroid/main/bte_main.o \ + bluedroid/osi/alarm.o \ + bluedroid/osi/allocator.o \ + bluedroid/osi/fixed_queue.o \ + bluedroid/osi/future.o \ + bluedroid/osi/hash_functions.o \ + bluedroid/osi/hash_map.o \ + bluedroid/osi/list.o \ + bluedroid/osi/osi_arch.o \ + bluedroid/stack/btm/btm_acl.o \ + bluedroid/stack/btm/btm_ble.o \ + bluedroid/stack/btm/btm_ble_addr.o \ + bluedroid/stack/btm/btm_ble_adv_filter.o \ + bluedroid/stack/btm/btm_ble_batchscan.o \ + bluedroid/stack/btm/btm_ble_bgconn.o \ + bluedroid/stack/btm/btm_ble_cont_energy.o \ + bluedroid/stack/btm/btm_ble_gap.o \ + bluedroid/stack/btm/btm_ble_multi_adv.o \ + bluedroid/stack/btm/btm_ble_privacy.o \ + bluedroid/stack/btm/btm_dev.o \ + bluedroid/stack/btm/btm_devctl.o \ + bluedroid/stack/btm/btm_inq.o \ + bluedroid/stack/btm/btm_main.o \ + bluedroid/stack/btm/btm_pm.o \ + bluedroid/stack/btm/btm_sec.o \ + bluedroid/stack/btu/btu_hcif.o \ + bluedroid/stack/btu/btu_init.o \ + bluedroid/stack/btu/btu_task.o \ + bluedroid/stack/gap/gap_api.o \ + bluedroid/stack/gap/gap_ble.o \ + bluedroid/stack/gap/gap_conn.o \ + bluedroid/stack/gatt/att_protocol.o \ + bluedroid/stack/gatt/gatt_api.o \ + bluedroid/stack/gatt/gatt_attr.o \ + bluedroid/stack/gatt/gatt_auth.o \ + bluedroid/stack/gatt/gatt_cl.o \ + bluedroid/stack/gatt/gatt_db.o \ + bluedroid/stack/gatt/gatt_main.o \ + bluedroid/stack/gatt/gatt_sr.o \ + bluedroid/stack/gatt/gatt_utils.o \ + bluedroid/stack/hcic/hciblecmds.o \ + bluedroid/stack/hcic/hcicmds.o \ + bluedroid/stack/l2cap/l2c_api.o \ + bluedroid/stack/l2cap/l2c_ble.o \ + bluedroid/stack/l2cap/l2c_csm.o \ + bluedroid/stack/l2cap/l2c_fcr.o \ + bluedroid/stack/l2cap/l2c_link.o \ + bluedroid/stack/l2cap/l2c_main.o \ + bluedroid/stack/l2cap/l2c_utils.o \ + bluedroid/stack/sdp/sdp_api.o \ + bluedroid/stack/sdp/sdp_db.o \ + bluedroid/stack/sdp/sdp_utils.o \ + bluedroid/stack/smp/aes.o \ + bluedroid/stack/smp/p_256_curvepara.o \ + bluedroid/stack/smp/p_256_ecc_pp.o \ + bluedroid/stack/smp/p_256_multprecision.o \ + bluedroid/stack/smp/smp_act.o \ + bluedroid/stack/smp/smp_api.o \ + bluedroid/stack/smp/smp_br_main.o \ + bluedroid/stack/smp/smp_cmac.o \ + bluedroid/stack/smp/smp_keys.o \ + bluedroid/stack/smp/smp_l2c.o \ + bluedroid/stack/smp/smp_main.o \ + bluedroid/stack/smp/smp_utils.o \ + bt.o \ ) + $(BUILD)/$(ESPCOMP)/expat/%.o: CFLAGS += -Wno-unused-function ESPIDF_EXPAT_O = $(addprefix $(ESPCOMP)/expat/,\ library/xmltok_ns.o \ @@ -537,6 +670,7 @@ ESPIDF_WPA_SUPPLICANT_O = $(addprefix $(ESPCOMP)/wpa_supplicant/,\ port/os_xtensa.o \ ) + OBJ_ESPIDF = OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_BLUETOOTH_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NEWLIB_O)) @@ -601,10 +735,12 @@ APP_LD_ARGS += --end-group $(BUILD)/esp32_out.ld: sdkconfig.h $(Q)$(CC) -I. -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@ +$(BUILD)/network_bluetooth.o: CFLAGS += $(BT_INC) $(BUILD)/application.bin: $(BUILD)/application.elf $(ECHO) "Create $@" $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< + $(BUILD)/application.elf: $(OBJ) $(BUILD)/esp32_out.ld $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $(APP_LD_ARGS) From 39b25b3f5da3d4f6edb0f3615ddf27b62ffeafc8 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 11 Apr 2017 16:08:35 -0700 Subject: [PATCH 13/98] esp32/network_bluetooth.c: Many, many changes, as it's early days --- esp32/network_bluetooth.c | 180 ++++++++++++++++++++++++++++++-------- 1 file changed, 143 insertions(+), 37 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index f80ef7037..ee54cd176 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -39,6 +39,7 @@ #include "bt.h" #include "esp_gap_ble_api.h" +#include "esp_bt_main.h" #define HCI_GRP_HOST_CONT_BASEBAND_CMDS 0x03 #define HCI_GRP_BLE_CMDS 0x08 @@ -64,6 +65,8 @@ typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ #define BDADDR_TO_STREAM(p, a) {int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - ijk];} #define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} +#define CUTOUT +#warning FIXME -- REMOVE THIS CUTOUT BUSINESS const mp_obj_type_t network_bluetooth_type; typedef struct { @@ -72,6 +75,7 @@ typedef struct { NETWORK_BLUETOOTH_STATE_DEINIT, NETWORK_BLUETOOTH_STATE_INIT } state; + bool advertising; esp_ble_adv_params_t params; esp_ble_adv_data_t data; @@ -79,6 +83,8 @@ typedef struct { STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .base = { &network_bluetooth_type }, + .state = NETWORK_BLUETOOTH_STATE_DEINIT, + .advertising = false, .params = { .adv_int_min = 1280 * 1.6, .adv_int_max = 1280 * 1.6, @@ -154,7 +160,6 @@ enum { STATIC void dumpBuf(const uint8_t *buf, size_t len) { while(len--) printf("%02X ", *buf++); - printf("\n"); } STATIC void network_bluetooth_send_data(uint8_t *buf, size_t buf_size) { @@ -170,17 +175,47 @@ STATIC void network_bluetooth_send_data(uint8_t *buf, size_t buf_size) { //FIXME printf("Sending: "); dumpBuf(buf, buf_size); + printf("\n"); esp_vhci_host_send_packet(buf, buf_size); } -static void network_bluetooth_send_hci_reset() { - CREATE_HCI_HOST_COMMAND(HCI_CMD_RESET); - (void)param; - network_bluetooth_send_data(buf, buf_size); +static void network_bluetooth_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + NETWORK_BLUETOOTH_DEBUG_PRINTF("entering network_bluetooth_gap_event_handler()\n"); + network_bluetooth_obj_t* self = &network_bluetooth_singleton; + +#ifndef CUTOUT + switch (event) { + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: + esp_ble_gap_start_advertising(&self->params); + break; + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + //advertising start complete event to indicate advertising start successfully or failed + if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + NETWORK_BLUETOOTH_DEBUG_PRINTF( "Advertising start failed\n"); + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Advertising start successful\n"); + } + + break; + default: + break; + } +#endif } +STATIC void network_bluetooth_advertising_start_or_restart() { + network_bluetooth_obj_t* self = &network_bluetooth_singleton; +#ifndef CUTOUT + if (self->advertising) { + esp_ble_gap_stop_advertising(); + } + esp_ble_gap_config_adv_data(&self->data); +#endif +} + /******************************************************************************/ // MicroPython bindings for network_bluetooth @@ -188,18 +223,18 @@ static void network_bluetooth_send_hci_reset() { STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "Bluetooth(params=())", self); +#define NETWORK_BLUETOOTH_LF "\n" NETWORK_BLUETOOTH_DEBUG_PRINTF( "Bluetooth(params = (" - "adv_int_min = %u, " - "adv_int_max = %u, " - "adv_type = %u, " - "own_addr_type = %u, " - "peer_addr = %02X:%02X:%02X:%02X:%02X:%02X, " - "peer_addr_type = %u, " - "channel_map = %u, " - "adv_filter_policy = %u" + "adv_int_min = %u, " NETWORK_BLUETOOTH_LF + "adv_int_max = %u, " NETWORK_BLUETOOTH_LF + "adv_type = %u, " NETWORK_BLUETOOTH_LF + "own_addr_type = %u, " NETWORK_BLUETOOTH_LF + "peer_addr = %02X:%02X:%02X:%02X:%02X:%02X, " NETWORK_BLUETOOTH_LF + "peer_addr_type = %u, " NETWORK_BLUETOOTH_LF + "channel_map = %u, " NETWORK_BLUETOOTH_LF + "adv_filter_policy = %u" NETWORK_BLUETOOTH_LF ")" - ")\n" , (unsigned int)(self->params.adv_int_min / 1.6), (unsigned int)(self->params.adv_int_max / 1.6), @@ -215,6 +250,38 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m self->params.channel_map, self->params.adv_filter_policy ); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", data = (" + "set_scan_rsp = %s, " NETWORK_BLUETOOTH_LF + "include_name = %s, " NETWORK_BLUETOOTH_LF + "include_txpower = %s, " NETWORK_BLUETOOTH_LF + "min_interval = %d, " NETWORK_BLUETOOTH_LF + "max_interval = %d, " NETWORK_BLUETOOTH_LF + "appearance = %d, " NETWORK_BLUETOOTH_LF + "manufacturer_len = %d, " NETWORK_BLUETOOTH_LF + "p_manufacturer_data = %s, " NETWORK_BLUETOOTH_LF + "service_data_len = %d, " NETWORK_BLUETOOTH_LF + "p_service_data = ", + self->data.set_scan_rsp ? "true" : "false", + self->data.include_name ? "true" : "false", + self->data.include_txpower ? "true" : "false", + self->data.min_interval, + self->data.max_interval, + self->data.appearance, + self->data.manufacturer_len, + self->data.p_manufacturer_data ? (const char *)self->data.p_manufacturer_data : "nil", + self->data.service_data_len); + if (self->data.p_service_data != NULL) { + dumpBuf(self->data.p_service_data, self->data.service_data_len); + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("nil"); + } + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", " NETWORK_BLUETOOTH_LF "flag = %d" NETWORK_BLUETOOTH_LF , self->data.flag); + + + NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); + } @@ -223,21 +290,41 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); +#ifndef CUTOUT esp_bt_controller_init(); - esp_err_t ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); - switch(ret) { + switch(esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { + case ESP_OK: + NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_bt_controller_enable() OK\n"); + break; + default: + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); + break; + } + + switch(esp_bluedroid_init()) { case ESP_OK: - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT initialization ok\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_bluedroid_init() OK\nn"); break; default: - mp_raise_msg(&mp_type_OSError, "BT initialization failed"); + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_init() failed"); + break; } - network_bluetooth_send_hci_reset(); + switch(esp_bluedroid_enable()) { + case ESP_OK: + NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_bluedroid_enable() OK\nn"); + break; + default: + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_enable() failed"); + break; + } + + esp_ble_gap_register_callback(network_bluetooth_gap_event_handler); self->state = NETWORK_BLUETOOTH_STATE_INIT; +#endif } else { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); } @@ -304,41 +391,45 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po // pre-check complex types - if (args[ARG_peer_addr].u_obj != MP_OBJ_NULL) { + if (args[ARG_peer_addr].u_obj != NULL) { if (mp_obj_get_type(args[ARG_peer_addr].u_obj) != &mp_type_bytearray) { - goto network_bluetooth_bad_peer; + goto NETWORK_BLUETOOTH_BAD_PEER; } mp_get_buffer(args[ARG_peer_addr].u_obj, &peer_addr_buf, MP_BUFFER_READ); if (peer_addr_buf.len != ESP_BD_ADDR_LEN) { - goto network_bluetooth_bad_peer; + goto NETWORK_BLUETOOTH_BAD_PEER; } } - if (args[ARG_adv_man_name].u_obj != MP_OBJ_NULL) { + if (args[ARG_adv_man_name].u_obj != NULL) { if (mp_obj_get_type(args[ARG_adv_man_name].u_obj) == mp_const_none) { self->data.manufacturer_len = 0; if (self->data.p_manufacturer_data != NULL) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("About to free p_manufacturer_data\n"); m_free(self->data.p_manufacturer_data); self->data.p_manufacturer_data = NULL; } } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_adv_man_name].u_obj)) { mp_raise_ValueError("adv_man_name must be type str or bytes"); } - mp_obj_str_get_buffer(args[ARG_peer_addr].u_obj, &adv_man_name_buf, MP_BUFFER_READ); + NETWORK_BLUETOOTH_DEBUG_PRINTF("About to get adv_man_name_buf\n"); + mp_obj_str_get_buffer(args[ARG_adv_man_name].u_obj, &adv_man_name_buf, MP_BUFFER_READ); } - if (args[ARG_adv_dev_name].u_obj != MP_OBJ_NULL) { + if (args[ARG_adv_dev_name].u_obj != NULL) { if (mp_obj_get_type(args[ARG_adv_dev_name].u_obj) == mp_const_none) { +#ifndef CUTOUT esp_ble_gap_set_device_name(""); +#endif self->data.include_name = false; } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_adv_dev_name].u_obj)) { mp_raise_ValueError("adv_dev_name must be type str or bytes"); } - mp_obj_str_get_buffer(args[ARG_peer_addr].u_obj, &adv_dev_name_buf, MP_BUFFER_READ); + mp_obj_str_get_buffer(args[ARG_adv_dev_name].u_obj, &adv_dev_name_buf, MP_BUFFER_READ); } - if (args[ARG_adv_uuid].u_obj != MP_OBJ_NULL) { + if (args[ARG_adv_uuid].u_obj != NULL) { if (mp_obj_get_type(args[ARG_adv_uuid].u_obj) != &mp_type_bytearray) { goto NETWORK_BLUETOOTH_BAD_UUID; } @@ -349,9 +440,8 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po } } - // update esp_ble_adv_params_t - + if (args[ARG_int_min].u_int != -1) { self->params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count changed = true; @@ -387,17 +477,18 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po changed = true; } - // update esp_ble_adv_data_t // - + if (args[ARG_adv_is_scan_rsp].u_obj != NULL) { self->data.set_scan_rsp = mp_obj_is_true(args[ARG_adv_is_scan_rsp].u_obj); changed = true; } if (adv_dev_name_buf.buf != NULL) { +#ifndef CUTOUT esp_ble_gap_set_device_name(adv_dev_name_buf.buf); +#endif self->data.include_name = adv_dev_name_buf.len > 0; changed = true; } @@ -405,11 +496,13 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po if (adv_man_name_buf.buf != NULL) { self->data.manufacturer_len = adv_man_name_buf.len; if (self->data.p_manufacturer_data != NULL) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("About to free p_manufacturer_data (2)\n"); m_free(self->data.p_manufacturer_data); self->data.p_manufacturer_data = NULL; } if (adv_man_name_buf.len > 0) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("About to call malloc for p_manufacturer_data\n"); self->data.p_manufacturer_data = m_malloc(adv_man_name_buf.len); memcpy(self->data.p_manufacturer_data, adv_man_name_buf.buf, adv_man_name_buf.len); } @@ -422,32 +515,45 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po changed = true; } - if (args[ARG_adv_int_min].u_int != NULL) { + if (args[ARG_adv_int_min].u_int != -1) { self->data.min_interval = args[ARG_adv_int_min].u_int; changed = true; } - if (args[ARG_adv_int_max].u_int != NULL) { + if (args[ARG_adv_int_max].u_int != -1) { self->data.max_interval = args[ARG_adv_int_max].u_int; changed = true; } - if (args[ARG_adv_appearance].u_int != NULL) { + if (args[ARG_adv_appearance].u_int != -1) { self->data.appearance = args[ARG_adv_appearance].u_int; changed = true; } if (adv_uuid_buf.buf != NULL) { - mango; // FIXME -- finish doing uuid like man name - self->data.include_name = adv_uuid_buf.len > 0; + self->data.service_uuid_len = adv_uuid_buf.len; + if (self->data.p_service_uuid != NULL) { + m_free(self->data.p_service_uuid ); + self->data.p_service_uuid = NULL; + } + + if (adv_uuid_buf.len > 0) { + self->data.p_service_uuid = m_malloc(adv_uuid_buf.len); + memcpy(self->data.p_service_uuid, adv_uuid_buf.buf, adv_uuid_buf.len); + } + changed = true; } - if (args[ARG_adv_flags].u_int != NULL) { + if (args[ARG_adv_flags].u_int != -1) { self->data.flag = args[ARG_adv_flags].u_int; changed = true; } + if (changed) { + network_bluetooth_advertising_start_or_restart(); + } + return mp_const_none; NETWORK_BLUETOOTH_BAD_PEER: From 4f0b56bd436d2cb42c778578bbd9ee1765c0107e Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 12 Apr 2017 12:26:22 -0700 Subject: [PATCH 14/98] esp32/network_bluetooth.c: Ensured all params checked --- esp32/network_bluetooth.c | 86 +++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index ee54cd176..61c5d776a 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -65,8 +65,9 @@ typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ #define BDADDR_TO_STREAM(p, a) {int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - ijk];} #define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} + #define CUTOUT -#warning FIXME -- REMOVE THIS CUTOUT BUSINESS + const mp_obj_type_t network_bluetooth_type; typedef struct { @@ -162,30 +163,14 @@ STATIC void dumpBuf(const uint8_t *buf, size_t len) { printf("%02X ", *buf++); } -STATIC void network_bluetooth_send_data(uint8_t *buf, size_t buf_size) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_send_data\n"); - int tries = 3; - bool ready; - - // FIXME: A somewhat naïve approach; look into using esp_vhci_host_callback - while(((ready = esp_vhci_host_check_send_available()) == false) && tries--) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_send_data: waiting for host to be ready\n"); - vTaskDelay((10 / portTICK_PERIOD_MS) || 1); - } - //FIXME - printf("Sending: "); - dumpBuf(buf, buf_size); - printf("\n"); - - esp_vhci_host_send_packet(buf, buf_size); -} +/* static void network_bluetooth_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("entering network_bluetooth_gap_event_handler()\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF("entering network_bluetooth_gap_event_handler()\n"); network_bluetooth_obj_t* self = &network_bluetooth_singleton; - #ifndef CUTOUT + switch (event) { case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: esp_ble_gap_start_advertising(&self->params); @@ -206,13 +191,16 @@ static void network_bluetooth_gap_event_handler(esp_gap_ble_cb_event_t event, es } -STATIC void network_bluetooth_advertising_start_or_restart() { +STATIC void network_bluetooth_adv_updated() { network_bluetooth_obj_t* self = &network_bluetooth_singleton; #ifndef CUTOUT if (self->advertising) { esp_ble_gap_stop_advertising(); } esp_ble_gap_config_adv_data(&self->data); + if (self->advertising) { + esp_ble_gap_start_advertising(&self->params); + } #endif } @@ -323,8 +311,8 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { esp_ble_gap_register_callback(network_bluetooth_gap_event_handler); self->state = NETWORK_BLUETOOTH_STATE_INIT; - #endif + } else { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); } @@ -337,6 +325,10 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_ble_settings(self = %p) n_args = %d\n", self, n_args); bool changed = false; + bool unset_adv_man_name = false; + bool unset_adv_dev_name = false; + bool unset_adv_uuid = false; + enum { // params ARG_int_min, @@ -390,7 +382,11 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po mp_buffer_info_t adv_uuid_buf = { 0 }; + // pre-check complex types + + + // peer_addr if (args[ARG_peer_addr].u_obj != NULL) { if (mp_obj_get_type(args[ARG_peer_addr].u_obj) != &mp_type_bytearray) { goto NETWORK_BLUETOOTH_BAD_PEER; @@ -402,40 +398,37 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po } } + // adv_man_name if (args[ARG_adv_man_name].u_obj != NULL) { if (mp_obj_get_type(args[ARG_adv_man_name].u_obj) == mp_const_none) { - self->data.manufacturer_len = 0; - if (self->data.p_manufacturer_data != NULL) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("About to free p_manufacturer_data\n"); - m_free(self->data.p_manufacturer_data); - self->data.p_manufacturer_data = NULL; - } + unset_adv_man_name = true; } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_adv_man_name].u_obj)) { mp_raise_ValueError("adv_man_name must be type str or bytes"); } - NETWORK_BLUETOOTH_DEBUG_PRINTF("About to get adv_man_name_buf\n"); mp_obj_str_get_buffer(args[ARG_adv_man_name].u_obj, &adv_man_name_buf, MP_BUFFER_READ); } + // adv_dev_name if (args[ARG_adv_dev_name].u_obj != NULL) { if (mp_obj_get_type(args[ARG_adv_dev_name].u_obj) == mp_const_none) { -#ifndef CUTOUT - esp_ble_gap_set_device_name(""); -#endif - self->data.include_name = false; + unset_adv_dev_name = true; } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_adv_dev_name].u_obj)) { mp_raise_ValueError("adv_dev_name must be type str or bytes"); } mp_obj_str_get_buffer(args[ARG_adv_dev_name].u_obj, &adv_dev_name_buf, MP_BUFFER_READ); } + // adv_uuid if (args[ARG_adv_uuid].u_obj != NULL) { - if (mp_obj_get_type(args[ARG_adv_uuid].u_obj) != &mp_type_bytearray) { + if (mp_obj_get_type(args[ARG_adv_uuid].u_obj) == mp_const_none) { + unset_adv_uuid = true; + } else if (mp_obj_get_type(args[ARG_adv_uuid].u_obj) != &mp_type_bytearray) { goto NETWORK_BLUETOOTH_BAD_UUID; } mp_get_buffer(args[ARG_adv_uuid].u_obj, &adv_uuid_buf, MP_BUFFER_READ); if (adv_uuid_buf.len != NETWORK_BLUETOOTH_ADV_UUID_LEN) { + // FIXME: Is length really a fixed amount? goto NETWORK_BLUETOOTH_BAD_UUID; } } @@ -446,14 +439,17 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po self->params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count changed = true; } + if (args[ARG_int_max].u_int != -1) { self->params.adv_int_max = args[ARG_int_max].u_int * 1.6; changed = true; } + if (args[ARG_type].u_int != -1) { self->params.adv_type = args[ARG_type].u_int; changed = true; } + if (args[ARG_own_addr_type].u_int != -1) { self->params.own_addr_type = args[ARG_own_addr_type].u_int; changed = true; @@ -468,10 +464,12 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po self->params.peer_addr_type = args[ARG_peer_addr_type].u_int; changed = true; } + if (args[ARG_channel_map].u_int != -1) { self->params.channel_map = args[ARG_channel_map].u_int; changed = true; } + if (args[ARG_filter_policy].u_int != -1) { self->params.adv_filter_policy = args[ARG_filter_policy].u_int; changed = true; @@ -485,28 +483,30 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po changed = true; } - if (adv_dev_name_buf.buf != NULL) { #ifndef CUTOUT + if (unset_adv_dev_name) { + esp_ble_gap_set_device_name(""); + self->data.include_name = false; + } else if (adv_dev_name_buf.buf != NULL) { esp_ble_gap_set_device_name(adv_dev_name_buf.buf); -#endif self->data.include_name = adv_dev_name_buf.len > 0; changed = true; } +#endif - if (adv_man_name_buf.buf != NULL) { - self->data.manufacturer_len = adv_man_name_buf.len; + if (unset_adv_man_name || adv_man_name_buf.buf != NULL) { if (self->data.p_manufacturer_data != NULL) { NETWORK_BLUETOOTH_DEBUG_PRINTF("About to free p_manufacturer_data (2)\n"); m_free(self->data.p_manufacturer_data); self->data.p_manufacturer_data = NULL; } + self->data.manufacturer_len = adv_man_name_buf.len; if (adv_man_name_buf.len > 0) { NETWORK_BLUETOOTH_DEBUG_PRINTF("About to call malloc for p_manufacturer_data\n"); self->data.p_manufacturer_data = m_malloc(adv_man_name_buf.len); memcpy(self->data.p_manufacturer_data, adv_man_name_buf.buf, adv_man_name_buf.len); } - changed = true; } @@ -530,18 +530,18 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po changed = true; } - if (adv_uuid_buf.buf != NULL) { - self->data.service_uuid_len = adv_uuid_buf.len; + if (unset_adv_uuid || adv_uuid_buf.buf != NULL) { + if (self->data.p_service_uuid != NULL) { m_free(self->data.p_service_uuid ); self->data.p_service_uuid = NULL; } + self->data.service_uuid_len = adv_uuid_buf.len; if (adv_uuid_buf.len > 0) { self->data.p_service_uuid = m_malloc(adv_uuid_buf.len); memcpy(self->data.p_service_uuid, adv_uuid_buf.buf, adv_uuid_buf.len); } - changed = true; } @@ -551,7 +551,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po } if (changed) { - network_bluetooth_advertising_start_or_restart(); + network_bluetooth_adv_updated(); } return mp_const_none; From 2550151e639b93a18847950e61e48bb9d45aa104 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 12 Apr 2017 12:29:47 -0700 Subject: [PATCH 15/98] esp32/network_bluetooth.c: Removed errant comment --- esp32/network_bluetooth.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 61c5d776a..0a426a20b 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -163,8 +163,6 @@ STATIC void dumpBuf(const uint8_t *buf, size_t len) { printf("%02X ", *buf++); } -/* - static void network_bluetooth_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { NETWORK_BLUETOOTH_DEBUG_PRINTF("entering network_bluetooth_gap_event_handler()\n"); From 1ee50185e0b219fd6eb13f4924e46f2202f81466 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 12 Apr 2017 12:37:14 -0700 Subject: [PATCH 16/98] esp32/modesp.c: moved FAT fs to 0x200000 --- esp32/modesp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/modesp.c b/esp32/modesp.c index 1e9e65f31..805002655 100644 --- a/esp32/modesp.c +++ b/esp32/modesp.c @@ -77,7 +77,7 @@ STATIC mp_obj_t esp_flash_size(void) { STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size); STATIC mp_obj_t esp_flash_user_start(void) { - return MP_OBJ_NEW_SMALL_INT(0x100000); + return MP_OBJ_NEW_SMALL_INT(0x200000); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start); From 63aa7ad2bed730be5d22b65817f495bfc8231bc7 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 12 Apr 2017 12:38:08 -0700 Subject: [PATCH 17/98] esp32/modules/flashbdev.py: Increased FAT FS to 2MiB --- esp32/modules/flashbdev.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/modules/flashbdev.py b/esp32/modules/flashbdev.py index 621b79194..935f5342f 100644 --- a/esp32/modules/flashbdev.py +++ b/esp32/modules/flashbdev.py @@ -31,4 +31,4 @@ def ioctl(self, op, arg): bdev = None else: # for now we use a fixed size for the filesystem - bdev = FlashBdev(256 * 1024 // FlashBdev.SEC_SIZE) + bdev = FlashBdev(2048 * 1024 // FlashBdev.SEC_SIZE) From 7e2ce6a9e8b5e8bdad3633c96c130f9be67bf953 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 12 Apr 2017 12:52:49 -0700 Subject: [PATCH 18/98] esp32/Makefile: Default FLASH_MODE to dio for WROOM-32 --- esp32/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/Makefile b/esp32/Makefile index 5b42e479c..3cbf0b308 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -16,7 +16,7 @@ include ../py/py.mk PORT ?= /dev/ttyUSB0 BAUD ?= 460800 -FLASH_MODE ?= qio +FLASH_MODE ?= dio FLASH_FREQ ?= 40m FLASH_SIZE ?= 4MB CROSS_COMPILE ?= xtensa-esp32-elf- From 0c3ec627cc060a72c64dd9a7d338683761aaa534 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 12 Apr 2017 15:05:55 -0700 Subject: [PATCH 19/98] esp32/main.c: Lowered heap to 16K ... =( --- esp32/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/main.c b/esp32/main.c index f5bdc8bda..245534b81 100644 --- a/esp32/main.c +++ b/esp32/main.c @@ -53,7 +53,7 @@ #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) #define MP_TASK_STACK_SIZE (16 * 1024) #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) -#define MP_TASK_HEAP_SIZE (64 * 1024) +#define MP_TASK_HEAP_SIZE (16 * 1024) STATIC StaticTask_t mp_task_tcb; STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8))); From 6ad57e0b812e12f012b67e68aba7db848174454a Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 12 Apr 2017 15:06:21 -0700 Subject: [PATCH 20/98] esp32/sdkconfig.h: Added new needed config for BT --- esp32/sdkconfig.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index b6861c861..7c27c25f0 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -57,6 +57,7 @@ #define CONFIG_BT_ENABLED 1 #define CONFIG_BLUEDROID_ENABLED 1 #define CONFIG_BT_RESERVE_DRAM 0x10000 +#define CONFIG_BTDM_CONTROLLER_RUN_CPU 0 #define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 #define CONFIG_MEMMAP_SMP 1 From 31218f560d734686e1e6762ab072a369710da835 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 12 Apr 2017 15:06:41 -0700 Subject: [PATCH 21/98] esp32/network_bluetooth.c: Added ble_adv_enable function --- esp32/network_bluetooth.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 0a426a20b..41a6a76ea 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -66,7 +66,7 @@ typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ #define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} -#define CUTOUT +//#define CUTOUT const mp_obj_type_t network_bluetooth_type; @@ -171,6 +171,8 @@ static void network_bluetooth_gap_event_handler(esp_gap_ble_cb_event_t event, es switch (event) { case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: + NETWORK_BLUETOOTH_DEBUG_PRINTF( "adv data setting complete\n"); + mango; // FIXME -- why are we starting here? esp_ble_gap_start_advertising(&self->params); break; case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: @@ -277,7 +279,11 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); #ifndef CUTOUT - esp_bt_controller_init(); + esp_bt_controller_config_t config = { + .hci_uart_no = 1, + .hci_uart_baudrate = 115200, + }; + esp_bt_controller_init(&config); switch(esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { case ESP_OK: @@ -561,6 +567,14 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_ble_settings_obj, 1, network_bluetooth_ble_settings); +STATIC mp_obj_t network_bluetooth_ble_adv_enable(mp_obj_t self_in, mp_obj_t enable) { + network_bluetooth_obj_t * self = MP_OBJ_TO_PTR(self_in); + self->advertising = mp_obj_is_true(enable); + network_bluetooth_adv_updated(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_ble_adv_enable_obj, network_bluetooth_ble_adv_enable); + STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = &network_bluetooth_singleton; @@ -584,6 +598,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, + { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, From f1d0fec9a3a7168b215d438255d45755a9c48b00 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 18 Apr 2017 14:20:45 -0700 Subject: [PATCH 22/98] esp32/Makefile: added another BT object file --- esp32/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/esp32/Makefile b/esp32/Makefile index 637c14c45..2c0816f1a 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -281,6 +281,7 @@ $(BUILD)/$(ESPCOMP)/bt/bluedroid/stack/btu/btu_task.o: CFLAGS += -Wno-error=stri ESPIDF_BLUETOOTH_O = $(addprefix $(ESPCOMP)/bt/,\ bluedroid/api/esp_bt_main.o \ bluedroid/api/esp_gap_ble_api.o \ + bluedroid/api/esp_gatts_api.o \ bluedroid/bta/dm/bta_dm_act.o \ bluedroid/bta/dm/bta_dm_api.o \ bluedroid/bta/dm/bta_dm_cfg.o \ From 2e9749cb7dede5616ff3bf5f06a1e7940f061eae Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 18 Apr 2017 14:21:27 -0700 Subject: [PATCH 23/98] esp32/network_bluetooth: Added services, characteristics, cleanup Nowhere near ready for prime time --- esp32/network_bluetooth.c | 758 ++++++++++++++++++++++++++++++++++---- 1 file changed, 692 insertions(+), 66 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 41a6a76ea..8478f885e 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -40,6 +40,7 @@ #include "bt.h" #include "esp_gap_ble_api.h" #include "esp_bt_main.h" +#include "esp_gatts_api.h" #define HCI_GRP_HOST_CONT_BASEBAND_CMDS 0x03 #define HCI_GRP_BLE_CMDS 0x08 @@ -49,7 +50,6 @@ #define H4_TYPE_SCO 0x03 #define H4_TYPE_EVENT 0x04 -#define NETWORK_BLUETOOTH_ADV_UUID_LEN 16 #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -65,11 +65,38 @@ typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ #define BDADDR_TO_STREAM(p, a) {int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - ijk];} #define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} +#define UUID_LEN 16 //#define CUTOUT const mp_obj_type_t network_bluetooth_type; +const mp_obj_type_t network_bluetooth_service_type; +const mp_obj_type_t network_bluetooth_characteristic_type; + +// SERVICE +typedef struct { + mp_obj_base_t base; + + esp_gatt_srvc_id_t service_id; + mp_obj_t _chars; // list +} network_bluetooth_service_obj_t; + + +// CHARACTERISTIC + +typedef struct { + mp_obj_base_t base; + esp_bt_uuid_t uuid; + esp_gatt_perm_t perm; + esp_gatt_char_prop_t prop; + esp_attr_control_t control; + + mp_obj_t value; + +} network_bluetooth_characteristic_obj_t; + +// Declaration typedef struct { mp_obj_base_t base; enum { @@ -82,6 +109,7 @@ typedef struct { } network_bluetooth_obj_t; +// Singleton STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .base = { &network_bluetooth_type }, .state = NETWORK_BLUETOOTH_STATE_DEINIT, @@ -112,41 +140,6 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { }, }; -typedef struct { - union { - uint8_t preamble[3]; - struct { - uint8_t opcode[2]; - uint8_t param_size; - }; - }; -} hci_cmd_def_t; - -hci_cmd_def_t hci_commands[4] = { - { - .opcode = MAKE_OPCODE_BYTES(HCI_GRP_HOST_CONT_BASEBAND_CMDS, 0x03), // HCI_RESET - .param_size = 0x00, - }, - { - .opcode = MAKE_OPCODE_BYTES(HCI_GRP_BLE_CMDS, 0x0A), // HCI_BLE_WRITE_ADV_ENABLE - .param_size = 0x01, - }, - { - .opcode = MAKE_OPCODE_BYTES(HCI_GRP_BLE_CMDS, 0x06), // HCI_BLE_WRITE_ADV_PARAMS - .param_size = 0x0f, - }, - { - .opcode = MAKE_OPCODE_BYTES(HCI_GRP_BLE_CMDS, 0x08), // HCI_BLE_WRITE_ADV_DATA - .param_size = 0x1f, - }, -}; - -enum { - HCI_CMD_RESET = 0, - HCI_CMD_BLE_WRITE_ADV_ENABLE = 1, - HCI_CMD_BLE_WRITE_ADV_PARAMS = 2, - HCI_CMD_BLE_WRITE_ADV_DATA = 3 -} hci_cmd_t; #define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) #define CREATE_HCI_HOST_COMMAND(cmd)\ @@ -163,8 +156,472 @@ STATIC void dumpBuf(const uint8_t *buf, size_t len) { printf("%02X ", *buf++); } -static void network_bluetooth_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) -{ +STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { + + if (MP_OBJ_IS_INT(src)) { + uint32_t arg_uuid = mp_obj_get_int(src); + target->len = arg_uuid == (arg_uuid & 0xFFFF) ? sizeof(uint16_t) : sizeof(uint32_t); + uint8_t * uuid_ptr = (uint8_t*)&target->uuid.uuid128; + for(int i = 0; i < target->len; i++) { + // LSB first + *uuid_ptr++ = arg_uuid & 0xff; + arg_uuid >>= 8; + } + } else if (mp_obj_get_type(src) != &mp_type_bytearray) { + goto PARSE_UUID_BAD; + } else { + mp_buffer_info_t buf; + mp_get_buffer(src, &buf, MP_BUFFER_READ); + if (buf.len != UUID_LEN) { + goto PARSE_UUID_BAD; + } + target->len = UUID_LEN; + memcpy(&target->uuid.uuid128, buf.buf, buf.len); + } + + return; +PARSE_UUID_BAD: + mp_raise_ValueError("uuid must be integer or bytearray(16)"); +} + + +STATIC void gatts_event_dump( + esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) { + + const char * event_names[] = { + "REG", + "READ", + "WRITE", + "EXEC_WRITE", + "MTU", + "CONF", + "UNREG", + "CREATE", + "ADD_INCL_SRVC", + "ADD_CHAR", + "ADD_CHAR_DESCR", + "DELETE", + "START", + "STOP", + "CONNECT", + "DISCONNECT", + "OPEN", + "CANCEL_OPEN", + "CLOSE", + "LISTEN", + "CONGEST", + "RESPONSE", + "CREAT_ATTR_TAB", + "SET_ATTR_VAL", + }; + + typedef struct { + uint8_t id; + const char * name; + } status_name_t; + + const status_name_t status_names[] = { + {0x0, "OK | ENCRYPED_MITM"}, + {0x01, "INVALID_HANDLE"}, + {0x02, "READ_NOT_PERMIT"}, + {0x03, "WRITE_NOT_PERMIT"}, + {0x04, "INVALID_PDU"}, + {0x05, "INSUF_AUTHENTICATION"}, + {0x06, "REQ_NOT_SUPPORTED"}, + {0x07, "INVALID_OFFSET"}, + {0x08, "INSUF_AUTHORIZATION"}, + {0x09, "PREPARE_Q_FULL"}, + {0x0a, "NOT_FOUND"}, + {0x0b, "NOT_LONG"}, + {0x0c, "INSUF_KEY_SIZE"}, + {0x0d, "INVALID_ATTR_LEN"}, + {0x0e, "ERR_UNLIKELY"}, + {0x0f, "INSUF_ENCRYPTION"}, + {0x10, "UNSUPPORT_GRP_TYPE"}, + {0x11, "INSUF_RESOURCE"}, + {0x80, "NO_RESOURCES"}, + {0x81, "INTERNAL_ERROR"}, + {0x82, "WRONG_STATE"}, + {0x83, "DB_FULL"}, + {0x84, "BUSY"}, + {0x85, "ERROR"}, + {0x86, "CMD_STARTED"}, + {0x87, "ILLEGAL_PARAMETER"}, + {0x88, "PENDING"}, + {0x89, "AUTH_FAIL"}, + {0x8a, "MORE"}, + {0x8b, "INVALID_CFG"}, + {0x8c, "SERVICE_STARTED"}, + {0x8d, "ENCRYPED_NO_MITM"}, + {0x8e, "NOT_ENCRYPTED"}, + {0x8f, "CONGESTED"}, + {0x90, "DUP_REG"}, + {0x91, "ALREADY_OPEN"}, + {0x92, "CANCEL"}, + {0xfd, "CCC_CFG_ERR"}, + {0xfe, "PRC_IN_PROGRESS"}, + {0xff, "OUT_OF_RANGE"}, + {0x00, NULL}, + }; + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "network_bluetooth_gatts_event_handler(" + "event = %02X / %s" + ", if = %02X", + event, event_names[event], gatts_if + ); + + NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); + +#define PRINT_STATUS(STATUS) { \ + bool found = false; \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("status = %02X / ", (STATUS)); \ + for(int i = 0; status_names[i].name != NULL; i++) { \ + if (status_names[i].id == (STATUS)) { \ + found = true; \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("%s", status_names[i].name); \ + break; \ + } \ + } \ + if (!found) { \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("???"); \ + } \ +} + + switch(event) { + case ESP_GATTS_REG_EVT: + { + PRINT_STATUS(param->reg.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", app_id = %04X", + param->reg.app_id + ); + } + break; + + case ESP_GATTS_READ_EVT: + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", trans_id = %08X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->read.conn_id, + param->read.trans_id, + param->read.bda[0], + param->read.bda[1], + param->read.bda[2], + param->read.bda[3], + param->read.bda[4], + param->read.bda[5] + ); + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", handle = %04X" + ", offset = %04X" + ", is_long = %s" + ", need_resp = %s", + param->read.handle, + param->read.offset, + param->read.is_long ? "true" : "false", + param->read.need_rsp ? "true" : "false"); + + break; + + case ESP_GATTS_WRITE_EVT: + { + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", trans_id = %08X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->write.conn_id, + param->write.trans_id, + param->write.bda[0], + param->write.bda[1], + param->write.bda[2], + param->write.bda[3], + param->write.bda[4], + param->write.bda[5] + ); + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", handle = %04X" + ", offset = %04X" + ", need_resp = %s" + ", is_prep = %s" + ", len = %04X", + param->write.handle, + param->write.offset, + param->write.need_rsp ? "true" : "false", + param->write.is_prep ? "true" : "false", + param->write.len); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", data = "); + dumpBuf(param->write.value, param->write.len); + } + break; + + case ESP_GATTS_EXEC_WRITE_EVT: + { + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", trans_id = %08X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X" + ", exec_write_flag = %02X", + param->exec_write.conn_id, + param->exec_write.trans_id, + param->exec_write.bda[0], + param->exec_write.bda[1], + param->exec_write.bda[2], + param->exec_write.bda[3], + param->exec_write.bda[4], + param->exec_write.bda[5], + param->exec_write.exec_write_flag); + } + break; + + case ESP_GATTS_MTU_EVT: + { + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", mtu = %04X", + param->mtu.conn_id, + param->mtu.mtu); + } + break; + + case ESP_GATTS_CONF_EVT: + { + PRINT_STATUS(param->conf.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", conn_id = %04X", + param->conf.conn_id + ); + } + break; + + case ESP_GATTS_UNREG_EVT: + // No params? + break; + + case ESP_GATTS_CREATE_EVT: + { + PRINT_STATUS(param->create.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_handle = %04X", param->create.service_handle); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->create.service_id.id.uuid.uuid, param->create.service_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->create.service_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF("is_primary = %s", param->create.service_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + } + + break; + + case ESP_GATTS_ADD_INCL_SRVC_EVT: + { + PRINT_STATUS(param->add_incl_srvc.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", attr_handle = %04X" + ", service_handle = %04X", + param->add_incl_srvc.attr_handle, + param->add_incl_srvc.service_handle); + } + break; + + case ESP_GATTS_ADD_CHAR_EVT: + { + PRINT_STATUS(param->add_char.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", attr_handle = %04X" + ", service_handle = %04X", + param->add_char.attr_handle, + param->add_char.service_handle); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", uuid = "); + dumpBuf((uint8_t*)¶m->add_char.char_uuid.uuid, param->add_char.char_uuid.len); + } + break; + + case ESP_GATTS_ADD_CHAR_DESCR_EVT: + { + PRINT_STATUS(param->add_char_descr.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", attr_handle = %04X" + ", service_handle = %04X", + param->add_char_descr.attr_handle, + param->add_char_descr.service_handle); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", uuid = "); + dumpBuf((uint8_t*)¶m->add_char_descr.char_uuid.uuid, param->add_char_descr.char_uuid.len); + } + break; + + case ESP_GATTS_DELETE_EVT: + { + PRINT_STATUS(param->del.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", service_handle = %04X", + param->del.service_handle); + } + break; + + case ESP_GATTS_START_EVT: + { + PRINT_STATUS(param->start.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", service_handle = %04X", + param->start.service_handle); + } + break; + + case ESP_GATTS_STOP_EVT: + { + PRINT_STATUS(param->stop.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", service_handle = %04X", + param->stop.service_handle); + } + break; + + case ESP_GATTS_CONNECT_EVT: + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", remote_bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", is_connected = %s", + param->connect.conn_id, + param->connect.remote_bda[0], + param->connect.remote_bda[1], + param->connect.remote_bda[2], + param->connect.remote_bda[3], + param->connect.remote_bda[4], + param->connect.remote_bda[5], + param->connect.is_connected ? "true" : "false"); + break; + + case ESP_GATTS_DISCONNECT_EVT: + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", remote_bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", is_connected = %s", + param->disconnect.conn_id, + param->disconnect.remote_bda[0], + param->disconnect.remote_bda[1], + param->disconnect.remote_bda[2], + param->disconnect.remote_bda[3], + param->disconnect.remote_bda[4], + param->disconnect.remote_bda[5], + param->disconnect.is_connected ? "true" : "false"); + break; + + case ESP_GATTS_OPEN_EVT: + // no param? + break; + + case ESP_GATTS_CANCEL_OPEN_EVT: + // no param? + break; + + case ESP_GATTS_CLOSE_EVT: + // no param? + break; + + case ESP_GATTS_LISTEN_EVT: + // no param? + break; + + case ESP_GATTS_CONGEST_EVT: + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", congested = %s", + param->congest.conn_id, + param->congest.congested ? "true" : "false"); + break; + + case ESP_GATTS_RESPONSE_EVT: + { + PRINT_STATUS(param->rsp.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", handle = %04X", + param->rsp.handle); + } + break; + + case ESP_GATTS_CREAT_ATTR_TAB_EVT: + { + PRINT_STATUS(param->add_attr_tab.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_uuid = "); + dumpBuf((uint8_t*)¶m->add_attr_tab.svc_uuid.uuid, param->add_attr_tab.svc_uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", num_handle = %04X", param->add_attr_tab.num_handle); + for(int i = 0; i < param->add_attr_tab.num_handle; i++) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("%04X ", param->add_attr_tab.handles[i]); + } + } + break; + + case ESP_GATTS_SET_ATTR_VAL_EVT: + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "srvc_handle = %04X" + ", attr_handle = %04X", + param->set_attr_val.srvc_handle, + param->set_attr_val.attr_handle); + PRINT_STATUS(param->set_attr_val.status); + + break; + + } +NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); + + + +} + +STATIC void network_bluetooth_gatts_event_handler( + esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) { + + gatts_event_dump(event, gatts_if, param); + + switch (event) { + case ESP_GATTS_REG_EVT: + /* esp_ble_gatts_create_service( + gatts_if, + &gl_profile_tab[PROFILE_B_APP_ID].service_id, + GATTS_NUM_HANDLE_TEST_B); + */ + + break; + case ESP_GATTS_CREATE_EVT: + /* + gl_profile_tab[PROFILE_B_APP_ID].service_handle = param->create.service_handle; + gl_profile_tab[PROFILE_B_APP_ID].char_uuid.len = ESP_UUID_LEN_16; + gl_profile_tab[PROFILE_B_APP_ID].char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_TEST_B; + + esp_ble_gatts_start_service(gl_profile_tab[PROFILE_B_APP_ID].service_handle); + + esp_ble_gatts_add_char( + gl_profile_tab[PROFILE_B_APP_ID].service_handle, &gl_profile_tab[PROFILE_B_APP_ID].char_uuid, + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY, + NULL, NULL); + */ + + default: + // Nothing, intentionally + break; + + } + +} + +STATIC void network_bluetooth_gap_event_handler( + esp_gap_ble_cb_event_t event, + esp_ble_gap_cb_param_t *param) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("entering network_bluetooth_gap_event_handler()\n"); network_bluetooth_obj_t* self = &network_bluetooth_singleton; #ifndef CUTOUT @@ -172,8 +629,10 @@ static void network_bluetooth_gap_event_handler(esp_gap_ble_cb_event_t event, es switch (event) { case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: NETWORK_BLUETOOTH_DEBUG_PRINTF( "adv data setting complete\n"); - mango; // FIXME -- why are we starting here? - esp_ble_gap_start_advertising(&self->params); + if (self->advertising) { + NETWORK_BLUETOOTH_DEBUG_PRINTF( "calling esp_ble_gap_start_advertising()\n"); + esp_ble_gap_start_advertising(&self->params); + } break; case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: //advertising start complete event to indicate advertising start successfully or failed @@ -194,19 +653,45 @@ static void network_bluetooth_gap_event_handler(esp_gap_ble_cb_event_t event, es STATIC void network_bluetooth_adv_updated() { network_bluetooth_obj_t* self = &network_bluetooth_singleton; #ifndef CUTOUT - if (self->advertising) { - esp_ble_gap_stop_advertising(); - } + esp_ble_gap_stop_advertising(); esp_ble_gap_config_adv_data(&self->data); - if (self->advertising) { - esp_ble_gap_start_advertising(&self->params); - } + + // Restart will be handled in network_bluetooth_gap_event_handler + #endif } /******************************************************************************/ // MicroPython bindings for network_bluetooth +// + +STATIC void network_bluetooth_uuid_print(const mp_print_t *print, esp_bt_uuid_t* uuid) { + for(int i = 0; i < uuid->len; i++) { + mp_printf(print, "%02X", uuid->uuid.uuid128[i]); + if (uuid->len > 4 && (i == 3 || i == 5 || i == 7 || i == 9)) { + mp_printf(print, "-"); + } + } +} + +STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + network_bluetooth_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "BTChar(uuid = "); + network_bluetooth_uuid_print(print, &self->uuid); + mp_printf(print, ", perm = %02X, prop = %02X", self->perm, self->prop); + mp_printf(print, ", value = "); + mp_obj_type_t *type = mp_obj_get_type(self->value); + if (type->print != NULL) { + type->print(print, self->value, kind); + } + mp_printf(print, ")"); +} + +STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "Service(FIXME)", self); +} STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -312,8 +797,19 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { break; } + esp_ble_gatts_register_callback(network_bluetooth_gatts_event_handler); esp_ble_gap_register_callback(network_bluetooth_gap_event_handler); + // FIXME, this is hardcoded + switch(esp_ble_gatts_app_register(0)) { + case ESP_OK: + NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gatts_app_register success\n"); + break; + + default: + NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gatts_app_register ERROR\n"); + break; + } self->state = NETWORK_BLUETOOTH_STATE_INIT; #endif @@ -392,7 +888,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po // peer_addr if (args[ARG_peer_addr].u_obj != NULL) { - if (mp_obj_get_type(args[ARG_peer_addr].u_obj) != &mp_type_bytearray) { + if(!MP_OBJ_IS_TYPE(args[ARG_peer_addr].u_obj, &mp_type_bytearray)) { goto NETWORK_BLUETOOTH_BAD_PEER; } @@ -426,12 +922,12 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po if (args[ARG_adv_uuid].u_obj != NULL) { if (mp_obj_get_type(args[ARG_adv_uuid].u_obj) == mp_const_none) { unset_adv_uuid = true; - } else if (mp_obj_get_type(args[ARG_adv_uuid].u_obj) != &mp_type_bytearray) { + } else if (!MP_OBJ_IS_TYPE(mp_obj_get_type(args[ARG_adv_uuid].u_obj), &mp_type_bytearray)) { goto NETWORK_BLUETOOTH_BAD_UUID; } mp_get_buffer(args[ARG_adv_uuid].u_obj, &adv_uuid_buf, MP_BUFFER_READ); - if (adv_uuid_buf.len != NETWORK_BLUETOOTH_ADV_UUID_LEN) { + if (adv_uuid_buf.len != UUID_LEN) { // FIXME: Is length really a fixed amount? goto NETWORK_BLUETOOTH_BAD_UUID; } @@ -563,8 +1059,9 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po NETWORK_BLUETOOTH_BAD_PEER: mp_raise_ValueError("peer_addr must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); NETWORK_BLUETOOTH_BAD_UUID: - mp_raise_ValueError("adv_uuid must be bytearray(" TOSTRING(NETWORK_BLUETOOTH_ADV_UUID_LEN ) ")"); + mp_raise_ValueError("adv_uuid must be bytearray(" TOSTRING(UUID_LEN ) ")"); } + STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_ble_settings_obj, 1, network_bluetooth_ble_settings); STATIC mp_obj_t network_bluetooth_ble_adv_enable(mp_obj_t self_in, mp_obj_t enable) { @@ -575,9 +1072,7 @@ STATIC mp_obj_t network_bluetooth_ble_adv_enable(mp_obj_t self_in, mp_obj_t enab } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_ble_adv_enable_obj, network_bluetooth_ble_adv_enable); -STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - - network_bluetooth_obj_t *self = &network_bluetooth_singleton; +STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = &network_bluetooth_singleton; NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new, self = %p, n_args = %d, n_kw = %d\n", self, n_args, n_kw ); if (n_args != 0 || n_kw != 0) { mp_raise_TypeError("Constructor takes no arguments"); @@ -587,6 +1082,77 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t return MP_OBJ_FROM_PTR(self); } +mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum {ARG_uuid, ARG_isPrimary}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_isPrimary, MP_ARG_OBJ, {.u_obj = mp_const_true } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + network_bluetooth_service_obj_t *self = m_new_obj(network_bluetooth_service_obj_t ); + self->base.type = type; + + parse_uuid(args[ARG_uuid].u_obj, &self->service_id.id.uuid); + self->service_id.is_primary = mp_obj_is_true(args[ARG_isPrimary].u_obj); + self->_chars = mp_obj_new_list(0, NULL); + + return MP_OBJ_FROM_PTR(self); +} + +mp_obj_t network_bluetooth_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum {ARG_uuid, ARG_value, ARG_perm, ARG_prop}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_value, MP_ARG_OBJ, {.u_obj = mp_const_none }}, + { MP_QSTR_perm, MP_ARG_INT, {.u_int = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE } }, + { MP_QSTR_prop, MP_ARG_INT, {.u_int = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + network_bluetooth_characteristic_obj_t *self = m_new_obj(network_bluetooth_characteristic_obj_t ); + self->base.type = type; + + if (args[ARG_value].u_obj != mp_const_none && !MP_OBJ_IS_STR_OR_BYTES(args[ARG_value].u_obj)) { + mp_raise_ValueError("value must be string, bytearray or None"); + } + parse_uuid(args[ARG_uuid].u_obj, &self->uuid); + + self->value = args[ARG_value].u_obj; + self->perm = args[ARG_perm].u_int; + self->prop = args[ARG_prop].u_int; + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t network_bluetooth_service_add_characteristic(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_stop() FIXME unimplemented\n"); + //FIXME + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_add_characteristic_obj, network_bluetooth_service_add_characteristic); + +STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_start() FIXME unimplemented\n"); + + //FIXME + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_start_obj, network_bluetooth_service_start); + +STATIC mp_obj_t network_bluetooth_service_stop(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_stop() FIXME unimplemented\n"); + //FIXME + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_stop_obj, network_bluetooth_service_stop); + + + + + STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); // FIXME @@ -594,34 +1160,59 @@ STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); +// BLUETOOTH OBJECTS STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, + { MP_ROM_QSTR(MP_QSTR_Char), MP_ROM_PTR(&network_bluetooth_characteristic_type) }, // class constants // esp_ble_adv_type_t - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, // esp_ble_addr_type_t - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, // esp_ble_adv_channel_t - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, + + // exp_gatt_perm_t + { MP_ROM_QSTR(MP_QSTR_PERM_READ), MP_ROM_INT(ESP_GATT_PERM_READ) }, + { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_READ_ENCRYPTED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_READ_ENC_MITM) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE), MP_ROM_INT(ESP_GATT_PERM_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENCRYPTED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENC_MITM) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED_MITM) }, + + // esp_gatt_char_prop_t + + { MP_ROM_QSTR(MP_QSTR_PROP_BROADCAST), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_BROADCAST) }, + { MP_ROM_QSTR(MP_QSTR_PROP_READ), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_READ) }, + { MP_ROM_QSTR(MP_QSTR_PROP_WRITE_NR), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE_NR) }, + { MP_ROM_QSTR(MP_QSTR_PROP_WRITE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_PROP_NOTIFY), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_NOTIFY) }, + { MP_ROM_QSTR(MP_QSTR_PROP_INDICATE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_INDICATE) }, + { MP_ROM_QSTR(MP_QSTR_PROP_AUTH), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_AUTH) }, + { MP_ROM_QSTR(MP_QSTR_PROP_EXT_PROP), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_EXT_PROP) }, // esp_ble_adv_filter_t { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), @@ -643,3 +1234,38 @@ const mp_obj_type_t network_bluetooth_type = { .make_new = network_bluetooth_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_locals_dict, }; + + +// SERVICE OBJECTS + +STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_add_characteristic), MP_ROM_PTR(&network_bluetooth_service_add_characteristic_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_service_locals_dict, network_bluetooth_service_locals_dict_table); + +const mp_obj_type_t network_bluetooth_service_type = { + { &mp_type_type }, + .name = MP_QSTR_Service, + .print = network_bluetooth_service_print, + .make_new = network_bluetooth_service_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_service_locals_dict, +}; + +// CHARACTERISTIC OBJECTS + + +STATIC const mp_rom_map_elem_t network_bluetooth_characteristic_locals_dict_table[] = { +}; + +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_characteristic_locals_dict, network_bluetooth_characteristic_locals_dict_table); + +const mp_obj_type_t network_bluetooth_characteristic_type = { + { &mp_type_type }, + .name = MP_QSTR_Char, + .print = network_bluetooth_characteristic_print, + .make_new = network_bluetooth_characteristic_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_characteristic_locals_dict, +}; From 01077353db91b471bf8beabe74f11742c0ca8617 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 20 Apr 2017 11:35:16 -0700 Subject: [PATCH 24/98] esp32/network_bluetooth.c: API now more like https://goo.gl/Djt044 --- esp32/network_bluetooth.c | 109 ++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 27 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 8478f885e..0a8773c23 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -78,11 +78,13 @@ const mp_obj_type_t network_bluetooth_characteristic_type; typedef struct { mp_obj_base_t base; + bool started; esp_gatt_srvc_id_t service_id; - mp_obj_t _chars; // list + mp_obj_t chars; // list } network_bluetooth_service_obj_t; + // CHARACTERISTIC typedef struct { @@ -98,14 +100,15 @@ typedef struct { // Declaration typedef struct { - mp_obj_base_t base; + mp_obj_base_t base; enum { NETWORK_BLUETOOTH_STATE_DEINIT, NETWORK_BLUETOOTH_STATE_INIT - } state; - bool advertising; - esp_ble_adv_params_t params; - esp_ble_adv_data_t data; + } state; + bool advertising; + esp_gatt_if_t interface; + esp_ble_adv_params_t params; + esp_ble_adv_data_t data; } network_bluetooth_obj_t; @@ -114,6 +117,7 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .base = { &network_bluetooth_type }, .state = NETWORK_BLUETOOTH_STATE_DEINIT, .advertising = false, + .interface = ESP_GATT_IF_NONE, .params = { .adv_int_min = 1280 * 1.6, .adv_int_max = 1280 * 1.6, @@ -151,6 +155,10 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { buf[0] = H4_TYPE_COMMAND;\ memcpy(buf + 1, &hci_commands[(cmd)], sizeof(hci_cmd_def_t)); +STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { + return &network_bluetooth_singleton; +} + STATIC void dumpBuf(const uint8_t *buf, size_t len) { while(len--) printf("%02X ", *buf++); @@ -223,7 +231,7 @@ STATIC void gatts_event_dump( } status_name_t; const status_name_t status_names[] = { - {0x0, "OK | ENCRYPED_MITM"}, + {0x00, "OK"}, {0x01, "INVALID_HANDLE"}, {0x02, "READ_NOT_PERMIT"}, {0x03, "WRITE_NOT_PERMIT"}, @@ -414,7 +422,7 @@ STATIC void gatts_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); dumpBuf((uint8_t*)¶m->create.service_id.id.uuid.uuid, param->create.service_id.id.uuid.len); NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->create.service_id.id.inst_id); - NETWORK_BLUETOOTH_DEBUG_PRINTF("is_primary = %s", param->create.service_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->create.service_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } @@ -584,18 +592,22 @@ STATIC void network_bluetooth_gatts_event_handler( esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { + network_bluetooth_obj_t* self = &network_bluetooth_singleton; + gatts_event_dump(event, gatts_if, param); switch (event) { case ESP_GATTS_REG_EVT: - /* esp_ble_gatts_create_service( - gatts_if, - &gl_profile_tab[PROFILE_B_APP_ID].service_id, - GATTS_NUM_HANDLE_TEST_B); - */ - + self->interface = gatts_if; break; + case ESP_GATTS_CREATE_EVT: + + + NETWORK_BLUETOOTH_DEBUG_PRINTF("ESP_GATTS_CREATE_EVT: FIXME, what to do with service_handle?\n"); + + esp_ble_gatts_start_service(param->create.service_handle); + /* gl_profile_tab[PROFILE_B_APP_ID].service_handle = param->create.service_handle; gl_profile_tab[PROFILE_B_APP_ID].char_uuid.len = ESP_UUID_LEN_16; @@ -651,7 +663,7 @@ STATIC void network_bluetooth_gap_event_handler( STATIC void network_bluetooth_adv_updated() { - network_bluetooth_obj_t* self = &network_bluetooth_singleton; + network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); #ifndef CUTOUT esp_ble_gap_stop_advertising(); esp_ble_gap_config_adv_data(&self->data); @@ -821,7 +833,7 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_init); STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { - network_bluetooth_obj_t *self = &network_bluetooth_singleton; + network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_ble_settings(self = %p) n_args = %d\n", self, n_args); bool changed = false; @@ -1072,7 +1084,8 @@ STATIC mp_obj_t network_bluetooth_ble_adv_enable(mp_obj_t self_in, mp_obj_t enab } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_ble_adv_enable_obj, network_bluetooth_ble_adv_enable); -STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = &network_bluetooth_singleton; +STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new, self = %p, n_args = %d, n_kw = %d\n", self, n_args, n_kw ); if (n_args != 0 || n_kw != 0) { mp_raise_TypeError("Constructor takes no arguments"); @@ -1096,7 +1109,8 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ parse_uuid(args[ARG_uuid].u_obj, &self->service_id.id.uuid); self->service_id.is_primary = mp_obj_is_true(args[ARG_isPrimary].u_obj); - self->_chars = mp_obj_new_list(0, NULL); + self->chars = mp_obj_new_list(0, NULL); + self->started = false; return MP_OBJ_FROM_PTR(self); } @@ -1127,29 +1141,70 @@ mp_obj_t network_bluetooth_characteristic_make_new(const mp_obj_type_t *type, si return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t network_bluetooth_service_add_characteristic(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_stop() FIXME unimplemented\n"); - //FIXME - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_add_characteristic_obj, network_bluetooth_service_add_characteristic); STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_start() FIXME unimplemented\n"); + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; + if (self->started) { + return mp_const_none; + } - //FIXME + mp_obj_t item; + mp_obj_t iterable = mp_getiter(self->chars, NULL); + while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (!MP_OBJ_IS_TYPE(item, &network_bluetooth_characteristic_type)){ + mp_raise_ValueError("chars must contain only Char objects"); + } + } + + esp_ble_gatts_create_service(bluetooth->interface, &self->service_id, mp_obj_get_int(mp_obj_len(self->chars)) + 1); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_start_obj, network_bluetooth_service_start); STATIC mp_obj_t network_bluetooth_service_stop(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_stop() FIXME unimplemented\n"); + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; + + if (!self->started) { + return mp_const_none; + } + //FIXME return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_stop_obj, network_bluetooth_service_stop); +// service attribute handler +STATIC void network_bluetooth_service__attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; + switch(attr) { + case MP_QSTR_chars: + if (dest[0] == MP_OBJ_NULL) { // load + dest[0] = self->chars; + } else if (dest[1] != MP_OBJ_NULL) { // store + if (MP_OBJ_IS_TYPE(dest[1], &mp_type_list) || MP_OBJ_IS_TYPE(dest[1], &mp_type_tuple)) { + self->chars = dest[1]; + dest[0] = MP_OBJ_NULL; + } else { + mp_raise_ValueError("value must be list or tuple"); + } + } + break; + case MP_QSTR_start: + if (dest[0] == MP_OBJ_NULL) { + dest[0] = mp_obj_new_bound_meth(MP_OBJ_FROM_PTR(&network_bluetooth_service_start_obj), self); + } + break; + case MP_QSTR_stop: + if (dest[0] == MP_OBJ_NULL) { + dest[0] = mp_obj_new_bound_meth(MP_OBJ_FROM_PTR(&network_bluetooth_service_stop_obj), self); + } + break; + } +} @@ -1241,7 +1296,6 @@ const mp_obj_type_t network_bluetooth_type = { STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_add_characteristic), MP_ROM_PTR(&network_bluetooth_service_add_characteristic_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_service_locals_dict, network_bluetooth_service_locals_dict_table); @@ -1252,6 +1306,7 @@ const mp_obj_type_t network_bluetooth_service_type = { .print = network_bluetooth_service_print, .make_new = network_bluetooth_service_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_service_locals_dict, + .attr = network_bluetooth_service__attr, }; // CHARACTERISTIC OBJECTS From da2e704a13d4fadc0ef42093194a0416cd3a491e Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 21 Apr 2017 14:31:20 -0700 Subject: [PATCH 25/98] esp32/network_bluetooth.c: More changes as the API evolves --- esp32/network_bluetooth.c | 310 +++++++++++++++++++++++++------------- 1 file changed, 208 insertions(+), 102 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 0a8773c23..cb5193132 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -32,6 +32,7 @@ #include "freertos/task.h" #include "py/runtime.h" +#include "py/runtime0.h" #include "py/stream.h" #include "py/mphal.h" #include "py/objstr.h" @@ -45,26 +46,12 @@ #define HCI_GRP_HOST_CONT_BASEBAND_CMDS 0x03 #define HCI_GRP_BLE_CMDS 0x08 -#define H4_TYPE_COMMAND 0x01 -#define H4_TYPE_ACL 0x02 -#define H4_TYPE_SCO 0x03 -#define H4_TYPE_EVENT 0x04 - - #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) #define MAKE_OPCODE(OGF, OCF) (((OGF) << 10) | (OCF)) #define MAKE_OPCODE_BYTES(OGF, OCF) { (MAKE_OPCODE(OGF, OCF) & 0xff), (MAKE_OPCODE(OGF, OCF) >> 8) } -#define BD_ADDR_LEN (6) /* Device address length */ -typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ - -#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);} -#define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);} -#define BDADDR_TO_STREAM(p, a) {int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - ijk];} -#define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} - #define UUID_LEN 16 //#define CUTOUT @@ -77,15 +64,19 @@ const mp_obj_type_t network_bluetooth_characteristic_type; // SERVICE typedef struct { mp_obj_base_t base; - - bool started; esp_gatt_srvc_id_t service_id; + + uint16_t handle; + mp_obj_t chars; // list + bool started; + bool closed; + } network_bluetooth_service_obj_t; -// CHARACTERISTIC +// CHARACTERISTI typedef struct { mp_obj_base_t base; @@ -110,6 +101,7 @@ typedef struct { esp_ble_adv_params_t params; esp_ble_adv_data_t data; + mp_obj_t services; } network_bluetooth_obj_t; // Singleton @@ -142,6 +134,7 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .p_service_uuid = 0, .flag = 0 }, + .services = MP_OBJ_NULL, }; @@ -164,6 +157,7 @@ STATIC void dumpBuf(const uint8_t *buf, size_t len) { printf("%02X ", *buf++); } + STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { if (MP_OBJ_IS_INT(src)) { @@ -192,6 +186,77 @@ STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { mp_raise_ValueError("uuid must be integer or bytearray(16)"); } +STATIC bool uuid_eq(const esp_bt_uuid_t* a, const esp_bt_uuid_t* b) { + if (a->len != b->len) { + return false; + } + return memcmp(&a->uuid.uuid128, &b->uuid.uuid128, a->len) == 0; +} + +STATIC network_bluetooth_service_obj_t* find_servicex(esp_bt_uuid_t* uuid) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("find_servicex\n"); + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth = %p\n", bluetooth); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = %p\n", uuid); + + + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(bluetooth->services, &iter_buf); + NETWORK_BLUETOOTH_DEBUG_PRINTF("iterable = %p\n", iterable); + mp_obj_t item; + NETWORK_BLUETOOTH_DEBUG_PRINTF("before mp_iternext\n"); + item = mp_iternext(iterable); + NETWORK_BLUETOOTH_DEBUG_PRINTF("after mp_iternext\n"); + + return MP_OBJ_NULL; +} +STATIC network_bluetooth_service_obj_t* find_service(esp_bt_uuid_t* uuid) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("find_service\n"); + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth = %p\n", bluetooth); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = %p\n", uuid); + + + mp_obj_t iterable = mp_getiter(bluetooth->services, NULL); + NETWORK_BLUETOOTH_DEBUG_PRINTF("iterable = %p\n", iterable); + mp_obj_t item; + while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("inside while\n"); + network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) item; + NETWORK_BLUETOOTH_DEBUG_PRINTF("before cmpare\n"); + if(uuid_eq(uuid, &service->service_id.id.uuid)) { + return service; + } + } + return MP_OBJ_NULL; +} + +STATIC network_bluetooth_characteristic_obj_t* find_service_char(network_bluetooth_service_obj_t* service, esp_bt_uuid_t* uuid) { + mp_obj_t iterable = mp_getiter(service->chars, NULL); + mp_obj_t item; + while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) item; + if(uuid_eq(uuid, &chr->uuid)) { + return chr; + } + } + return NULL; +} + +STATIC bool check_locals_dict(mp_obj_t self, qstr attr, mp_obj_t *dest) { + mp_obj_type_t *type = mp_obj_get_type(self); + + if (type->locals_dict != NULL) { + mp_map_t *locals_map = &type->locals_dict->map; + mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); + if (elem != NULL && elem->value != NULL) { + mp_convert_member_lookup(self, type, elem->value, dest); + return true; + } + } + return false; +} + STATIC void gatts_event_dump( esp_gatts_cb_event_t event, @@ -592,35 +657,33 @@ STATIC void network_bluetooth_gatts_event_handler( esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { - network_bluetooth_obj_t* self = &network_bluetooth_singleton; + network_bluetooth_obj_t* bluetooth = &network_bluetooth_singleton; gatts_event_dump(event, gatts_if, param); switch (event) { case ESP_GATTS_REG_EVT: - self->interface = gatts_if; + bluetooth->interface = gatts_if; break; case ESP_GATTS_CREATE_EVT: - - - NETWORK_BLUETOOTH_DEBUG_PRINTF("ESP_GATTS_CREATE_EVT: FIXME, what to do with service_handle?\n"); - - esp_ble_gatts_start_service(param->create.service_handle); - - /* - gl_profile_tab[PROFILE_B_APP_ID].service_handle = param->create.service_handle; - gl_profile_tab[PROFILE_B_APP_ID].char_uuid.len = ESP_UUID_LEN_16; - gl_profile_tab[PROFILE_B_APP_ID].char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_TEST_B; - - esp_ble_gatts_start_service(gl_profile_tab[PROFILE_B_APP_ID].service_handle); - - esp_ble_gatts_add_char( - gl_profile_tab[PROFILE_B_APP_ID].service_handle, &gl_profile_tab[PROFILE_B_APP_ID].char_uuid, - ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, - ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY, - NULL, NULL); - */ + NETWORK_BLUETOOTH_DEBUG_PRINTF("ESP_GATTS_CREATE_EVT\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF("before find_service\n"); + network_bluetooth_service_obj_t* service = find_servicex(¶m->create.service_id.id.uuid); + NETWORK_BLUETOOTH_DEBUG_PRINTF("after find_service %p\n", service); + + if (service != MP_OBJ_NULL) { + service->handle = param->create.service_handle; + service->service_id = param->create.service_id; + esp_ble_gatts_start_service(service->handle); + + mp_obj_t iterable = mp_getiter(service->chars, NULL); + mp_obj_t item; + while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*)item; + esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); + } + } default: // Nothing, intentionally @@ -702,7 +765,10 @@ STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_o STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "Service(FIXME)", self); + // FIXME + mp_printf(print, "Service(uuid = "); + network_bluetooth_uuid_print(print, &self->service_id.id.uuid); + mp_printf(print, ")"); } STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -770,8 +836,15 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m } -STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { +STATIC void network_bluetooth_init(mp_obj_t self_in) { network_bluetooth_obj_t * self = (network_bluetooth_obj_t*)self_in; + + if (self->services == MP_OBJ_NULL) { + self->services = mp_obj_new_list(0, NULL); + } + + NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth services pointer: %p", self->services); + if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); @@ -828,9 +901,7 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { } else { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); } - return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_init); STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); @@ -1096,113 +1167,147 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t } mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum {ARG_uuid, ARG_isPrimary}; + + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_make_new\n"); + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + + enum {ARG_uuid, ARG_primary}; static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_isPrimary, MP_ARG_OBJ, {.u_obj = mp_const_true } }, + { MP_QSTR_primary, MP_ARG_OBJ, {.u_obj = mp_const_true } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - network_bluetooth_service_obj_t *self = m_new_obj(network_bluetooth_service_obj_t ); + esp_bt_uuid_t uuid; + parse_uuid(args[ARG_uuid].u_obj, &uuid); + network_bluetooth_service_obj_t *self = find_service(&uuid); + + NETWORK_BLUETOOTH_DEBUG_PRINTF("find_service returned %p\n", self); + if (self != MP_OBJ_NULL) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Returning extant service for that UUID\n"); + return MP_OBJ_FROM_PTR(self); + } + NETWORK_BLUETOOTH_DEBUG_PRINTF("Making a new service object\n"); + self = m_new_obj(network_bluetooth_service_obj_t); self->base.type = type; + self->service_id.id.uuid = uuid; parse_uuid(args[ARG_uuid].u_obj, &self->service_id.id.uuid); - self->service_id.is_primary = mp_obj_is_true(args[ARG_isPrimary].u_obj); + self->service_id.is_primary = mp_obj_is_true(args[ARG_primary].u_obj); self->chars = mp_obj_new_list(0, NULL); - self->started = false; + + mp_obj_list_append(bluetooth->services, MP_OBJ_FROM_PTR(self)); return MP_OBJ_FROM_PTR(self); } -mp_obj_t network_bluetooth_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum {ARG_uuid, ARG_value, ARG_perm, ARG_prop}; +mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_characteristic_make_new()\n"); + + enum {ARG_service, ARG_uuid, ARG_value, ARG_perm, ARG_prop}; static const mp_arg_t allowed_args[] = { + { MP_QSTR_service, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_value, MP_ARG_OBJ, {.u_obj = mp_const_none }}, { MP_QSTR_perm, MP_ARG_INT, {.u_int = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE } }, { MP_QSTR_prop, MP_ARG_INT, {.u_int = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_arg_parse_all(2, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*)args[ARG_service].u_obj; - network_bluetooth_characteristic_obj_t *self = m_new_obj(network_bluetooth_characteristic_obj_t ); - self->base.type = type; + esp_bt_uuid_t uuid; + parse_uuid(args[ARG_uuid].u_obj, &uuid); + network_bluetooth_characteristic_obj_t *self = find_service_char(service, &uuid); + + if (self != MP_OBJ_NULL) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Returning extant char for that UUID\n"); + return MP_OBJ_FROM_PTR(self); + } + + NETWORK_BLUETOOTH_DEBUG_PRINTF("Making a new char object\n"); + self = m_new_obj(network_bluetooth_characteristic_obj_t); + self->base.type = &network_bluetooth_characteristic_type; if (args[ARG_value].u_obj != mp_const_none && !MP_OBJ_IS_STR_OR_BYTES(args[ARG_value].u_obj)) { mp_raise_ValueError("value must be string, bytearray or None"); } - parse_uuid(args[ARG_uuid].u_obj, &self->uuid); + self->uuid = uuid; self->value = args[ARG_value].u_obj; self->perm = args[ARG_perm].u_int; self->prop = args[ARG_prop].u_int; + mp_obj_list_append(service->chars, self); + return MP_OBJ_FROM_PTR(self); } +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_characteristic_make_new_obj, 2, network_bluetooth_characteristic_make_new); STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_start()\n"); network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; - if (self->started) { - return mp_const_none; - } + mp_int_t numChars = mp_obj_get_int(mp_obj_len(self->chars)); - mp_obj_t item; - mp_obj_t iterable = mp_getiter(self->chars, NULL); - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - if (!MP_OBJ_IS_TYPE(item, &network_bluetooth_characteristic_type)){ - mp_raise_ValueError("chars must contain only Char objects"); - } - } - - esp_ble_gatts_create_service(bluetooth->interface, &self->service_id, mp_obj_get_int(mp_obj_len(self->chars)) + 1); + esp_ble_gatts_create_service(bluetooth->interface, &self->service_id, numChars + 1); return mp_const_none; } + STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_start_obj, network_bluetooth_service_start); STATIC mp_obj_t network_bluetooth_service_stop(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_stop() FIXME unimplemented\n"); - network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; - - if (!self->started) { - return mp_const_none; - } - - //FIXME + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_stop()\n"); + // FIXME return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_stop_obj, network_bluetooth_service_stop); +STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_close()\n"); + // FIXME + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); + // service attribute handler -STATIC void network_bluetooth_service__attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; - switch(attr) { - case MP_QSTR_chars: - if (dest[0] == MP_OBJ_NULL) { // load - dest[0] = self->chars; - } else if (dest[1] != MP_OBJ_NULL) { // store - if (MP_OBJ_IS_TYPE(dest[1], &mp_type_list) || MP_OBJ_IS_TYPE(dest[1], &mp_type_tuple)) { - self->chars = dest[1]; - dest[0] = MP_OBJ_NULL; - } else { - mp_raise_ValueError("value must be list or tuple"); - } - } - break; - case MP_QSTR_start: - if (dest[0] == MP_OBJ_NULL) { - dest[0] = mp_obj_new_bound_meth(MP_OBJ_FROM_PTR(&network_bluetooth_service_start_obj), self); + if (!check_locals_dict(self, attr, dest)) { + + // ATTENTION: All the switches below are for read-only attribs! + if (dest[0] == MP_OBJ_NULL) { + switch(attr) { + case MP_QSTR_Char: + dest[0] = mp_obj_new_bound_meth(MP_OBJ_FROM_PTR(&network_bluetooth_characteristic_make_new_obj), self); + + break; + case MP_QSTR_chars: + dest[0] = self->chars; + break; } - break; - case MP_QSTR_stop: - if (dest[0] == MP_OBJ_NULL) { - dest[0] = mp_obj_new_bound_meth(MP_OBJ_FROM_PTR(&network_bluetooth_service_stop_obj), self); - } - break; + } + } +} + +// bluetooth attribute handler +STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + network_bluetooth_obj_t* self = (network_bluetooth_obj_t*) self_in; + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_attr\n"); + + if (!check_locals_dict(self, attr, dest)) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_attr inside switch\n"); + + switch(attr) { + case MP_QSTR_services: + if (dest[0] == MP_OBJ_NULL) { // load + dest[0] = self->services; + } + break; + } } } @@ -1221,11 +1326,9 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, - { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, - { MP_ROM_QSTR(MP_QSTR_Char), MP_ROM_PTR(&network_bluetooth_characteristic_type) }, + { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr // class constants @@ -1288,14 +1391,18 @@ const mp_obj_type_t network_bluetooth_type = { .print = network_bluetooth_print, .make_new = network_bluetooth_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_locals_dict, + .attr = network_bluetooth_attr, }; // SERVICE OBJECTS STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_Char), NULL }, + { MP_ROM_QSTR(MP_QSTR_chars), NULL }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&network_bluetooth_service_close_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_service_locals_dict, network_bluetooth_service_locals_dict_table); @@ -1306,7 +1413,7 @@ const mp_obj_type_t network_bluetooth_service_type = { .print = network_bluetooth_service_print, .make_new = network_bluetooth_service_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_service_locals_dict, - .attr = network_bluetooth_service__attr, + .attr = network_bluetooth_service_attr, }; // CHARACTERISTIC OBJECTS @@ -1321,6 +1428,5 @@ const mp_obj_type_t network_bluetooth_characteristic_type = { { &mp_type_type }, .name = MP_QSTR_Char, .print = network_bluetooth_characteristic_print, - .make_new = network_bluetooth_characteristic_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_characteristic_locals_dict, }; From d42bb04880a9eb0351e0e7c4ade20f8178ddb8c2 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 24 Apr 2017 10:10:31 -0700 Subject: [PATCH 26/98] esp32/network_bluetooth.c: Got past exception in callback --- esp32/network_bluetooth.c | 184 +++++++++++++++++++++++--------------- 1 file changed, 114 insertions(+), 70 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index cb5193132..9ca3c2aa5 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -76,7 +76,7 @@ typedef struct { -// CHARACTERISTI +// CHARACTERISTIC typedef struct { mp_obj_base_t base; @@ -85,6 +85,8 @@ typedef struct { esp_gatt_char_prop_t prop; esp_attr_control_t control; + uint16_t handle; + mp_obj_t value; } network_bluetooth_characteristic_obj_t; @@ -193,56 +195,59 @@ STATIC bool uuid_eq(const esp_bt_uuid_t* a, const esp_bt_uuid_t* b) { return memcmp(&a->uuid.uuid128, &b->uuid.uuid128, a->len) == 0; } -STATIC network_bluetooth_service_obj_t* find_servicex(esp_bt_uuid_t* uuid) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("find_servicex\n"); - network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth = %p\n", bluetooth); - NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = %p\n", uuid); - - - mp_obj_iter_buf_t iter_buf; - mp_obj_t iterable = mp_getiter(bluetooth->services, &iter_buf); - NETWORK_BLUETOOTH_DEBUG_PRINTF("iterable = %p\n", iterable); - mp_obj_t item; - NETWORK_BLUETOOTH_DEBUG_PRINTF("before mp_iternext\n"); - item = mp_iternext(iterable); - NETWORK_BLUETOOTH_DEBUG_PRINTF("after mp_iternext\n"); - - return MP_OBJ_NULL; -} -STATIC network_bluetooth_service_obj_t* find_service(esp_bt_uuid_t* uuid) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("find_service\n"); - network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth = %p\n", bluetooth); - NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = %p\n", uuid); - - - mp_obj_t iterable = mp_getiter(bluetooth->services, NULL); - NETWORK_BLUETOOTH_DEBUG_PRINTF("iterable = %p\n", iterable); - mp_obj_t item; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("inside while\n"); - network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) item; - NETWORK_BLUETOOTH_DEBUG_PRINTF("before cmpare\n"); - if(uuid_eq(uuid, &service->service_id.id.uuid)) { - return service; +STATIC void network_bluetooth_uuid_print(const mp_print_t *print, esp_bt_uuid_t* uuid) { + for(int i = 0; i < uuid->len; i++) { + if (print != NULL) { + mp_printf(print, "%02X", uuid->uuid.uuid128[i]); + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("%02X", uuid->uuid.uuid128[i]); + } + if (uuid->len > 4 && (i == 3 || i == 5 || i == 7 || i == 9)) { + if (print != NULL) { + mp_printf(print, "-"); + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("-"); + } } } - return MP_OBJ_NULL; } -STATIC network_bluetooth_characteristic_obj_t* find_service_char(network_bluetooth_service_obj_t* service, esp_bt_uuid_t* uuid) { - mp_obj_t iterable = mp_getiter(service->chars, NULL); - mp_obj_t item; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) item; - if(uuid_eq(uuid, &chr->uuid)) { - return chr; +typedef enum { + NETWORK_BLUETOOTH_FIND_SERVICE, + NETWORK_BLUETOOTH_FIND_CHAR, +} item_type_t; + + +STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle, item_type_t kind) { + + size_t len; + mp_obj_t *items; + mp_obj_get_array(list, &len, &items); + for(int i = 0; i < len; i++) { + switch(kind) { + case NETWORK_BLUETOOTH_FIND_SERVICE: + { + network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; + if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || service->handle == handle) + return service; + } + break; + + case NETWORK_BLUETOOTH_FIND_CHAR: + { + network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) items[i]; + if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || chr->handle == handle) { + return chr; + } + } + + break; } } - return NULL; + return MP_OBJ_NULL; } + STATIC bool check_locals_dict(mp_obj_t self, qstr attr, mp_obj_t *dest) { mp_obj_type_t *type = mp_obj_get_type(self); @@ -657,7 +662,7 @@ STATIC void network_bluetooth_gatts_event_handler( esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { - network_bluetooth_obj_t* bluetooth = &network_bluetooth_singleton; + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); gatts_event_dump(event, gatts_if, param); @@ -667,24 +672,71 @@ STATIC void network_bluetooth_gatts_event_handler( break; case ESP_GATTS_CREATE_EVT: - NETWORK_BLUETOOTH_DEBUG_PRINTF("ESP_GATTS_CREATE_EVT\n"); - NETWORK_BLUETOOTH_DEBUG_PRINTF("before find_service\n"); - network_bluetooth_service_obj_t* service = find_servicex(¶m->create.service_id.id.uuid); - NETWORK_BLUETOOTH_DEBUG_PRINTF("after find_service %p\n", service); - - if (service != MP_OBJ_NULL) { - service->handle = param->create.service_handle; - service->service_id = param->create.service_id; - esp_ble_gatts_start_service(service->handle); - - mp_obj_t iterable = mp_getiter(service->chars, NULL); - mp_obj_t item; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*)item; - esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); + { + network_bluetooth_service_obj_t* service = network_bluetooth_find_item(bluetooth->services, ¶m->create.service_id.id.uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); + + if (service != MP_OBJ_NULL) { + service->handle = param->create.service_handle; + service->service_id = param->create.service_id; + esp_ble_gatts_start_service(service->handle); + + /* + size_t len; + mp_obj_t *items; + mp_obj_get_array(service->chars, &len, &items); + + for (int i = 0; i < len; i++) { + network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) items[i]; + esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); + } + */ } } + break; + + + case ESP_GATTS_START_EVT: + { + network_bluetooth_service_obj_t* service = network_bluetooth_find_item(bluetooth->services, NULL, param->start.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); + + if (service != MP_OBJ_NULL) { + size_t len; + mp_obj_t *items; + mp_obj_get_array(service->chars, &len, &items); + + for (int i = 0; i < len; i++) { + network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) items[i]; + NETWORK_BLUETOOTH_DEBUG_PRINTF("adding char for service %04X", service->handle); + NETWORK_BLUETOOTH_DEBUG_PRINTF(" char uuid "); + network_bluetooth_uuid_print(NULL, &chr->uuid); + NETWORK_BLUETOOTH_DEBUG_PRINTF(" perm = %02X, prop = %02X", chr->perm, chr->prop); + NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); + + esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); + } + } + } + + break; + + + + + case ESP_GATTS_ADD_CHAR_EVT: + { + network_bluetooth_service_obj_t* service = network_bluetooth_find_item(bluetooth->services, NULL, param->add_char.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); + if (service != MP_OBJ_NULL) { + network_bluetooth_characteristic_obj_t* chr = network_bluetooth_find_item(service->chars, ¶m->add_char.char_uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); + chr->handle = param->add_char.attr_handle; + NETWORK_BLUETOOTH_DEBUG_PRINTF("Setting char handle to %04X, from service handle %04X\n", param->add_char.attr_handle, param->add_char.service_handle); + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Service handle %d NOT FOUND\n", param->add_char.service_handle); + } + } + + break; + default: // Nothing, intentionally break; @@ -698,7 +750,7 @@ STATIC void network_bluetooth_gap_event_handler( esp_ble_gap_cb_param_t *param) { NETWORK_BLUETOOTH_DEBUG_PRINTF("entering network_bluetooth_gap_event_handler()\n"); - network_bluetooth_obj_t* self = &network_bluetooth_singleton; + network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); #ifndef CUTOUT switch (event) { @@ -740,14 +792,6 @@ STATIC void network_bluetooth_adv_updated() { // MicroPython bindings for network_bluetooth // -STATIC void network_bluetooth_uuid_print(const mp_print_t *print, esp_bt_uuid_t* uuid) { - for(int i = 0; i < uuid->len; i++) { - mp_printf(print, "%02X", uuid->uuid.uuid128[i]); - if (uuid->len > 4 && (i == 3 || i == 5 || i == 7 || i == 9)) { - mp_printf(print, "-"); - } - } -} STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -1181,7 +1225,7 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_service_obj_t *self = find_service(&uuid); + network_bluetooth_service_obj_t *self = network_bluetooth_find_item(bluetooth->services, &uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); NETWORK_BLUETOOTH_DEBUG_PRINTF("find_service returned %p\n", self); if (self != MP_OBJ_NULL) { @@ -1219,7 +1263,7 @@ mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_characteristic_obj_t *self = find_service_char(service, &uuid); + network_bluetooth_characteristic_obj_t *self = network_bluetooth_find_item(service->chars, &uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); if (self != MP_OBJ_NULL) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Returning extant char for that UUID\n"); From 9b049247de64f8b56edc947cc988c155d2d15d92 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 24 Apr 2017 11:21:09 -0700 Subject: [PATCH 27/98] esp32/Makefile: many changes for new IDF; headers were clashing --- esp32/Makefile | 146 ++++++++++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 63 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index 519101f55..7a890ba9e 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -2,7 +2,7 @@ include ../py/mkenv.mk # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h -QSTR_GEN_EXTRA_CFLAGS += $(BT_INC) +QSTR_GEN_EXTRA_CFLAGS += $(INC_BT) MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 @@ -44,42 +44,47 @@ endif # pretty format of ESP IDF version, used internally by the IDF IDF_VER := $(shell git -C $(ESPIDF) describe) -INC += -I. -INC += -I.. -INC += -I../lib/mp-readline -INC += -I../lib/netutils -INC += -I../lib/timeutils -INC += -I$(BUILD) -INC += -I$(ESPCOMP)/bootloader_support/include -INC += -I$(ESPCOMP)/driver/include -INC += -I$(ESPCOMP)/driver/include/driver -INC += -I$(ESPCOMP)/nghttp/port/include -INC += -I$(ESPCOMP)/nghttp/include -INC += -I$(ESPCOMP)/esp32/include -INC += -I$(ESPCOMP)/soc/esp32/include -INC += -I$(ESPCOMP)/ethernet/include -INC += -I$(ESPCOMP)/expat/include/expat -INC += -I$(ESPCOMP)/expat/port/include -INC += -I$(ESPCOMP)/json/include -INC += -I$(ESPCOMP)/json/port/include -INC += -I$(ESPCOMP)/log/include -INC += -I$(ESPCOMP)/newlib/include -INC += -I$(ESPCOMP)/nvs_flash/include -INC += -I$(ESPCOMP)/freertos/include -INC += -I$(ESPCOMP)/tcpip_adapter/include -INC += -I$(ESPCOMP)/lwip/include/lwip -INC += -I$(ESPCOMP)/lwip/include/lwip/port -INC += -I$(ESPCOMP)/lwip/include/lwip/posix -INC += -I$(ESPCOMP)/mbedtls/include -INC += -I$(ESPCOMP)/mbedtls/port/include -INC += -I$(ESPCOMP)/spi_flash/include -INC += -I$(ESPCOMP)/vfs/include -INC += -I$(ESPCOMP)/newlib/platform_include -INC += -I$(ESPCOMP)/xtensa-debug-module/include -INC += -I$(ESPCOMP)/wpa_supplicant/include -INC += -I$(ESPCOMP)/wpa_supplicant/port/include -INC += -I$(ESPCOMP)/ethernet/include -INC += -I$(ESPCOMP)/tcpip_adapter/include + +# Include dirs for both BT and MAIN +INC_COMMON = -I. +INC_COMMON += -I.. +INC_COMMON += -I$(ESPCOMP)/log/include +INC_COMMON += -I$(ESPCOMP)/esp32/include +INC_COMMON += -I$(ESPCOMP)/soc/esp32/include +INC_COMMON += -I$(ESPCOMP)/freertos/include +INC_COMMON += -I$(ESPCOMP)/tcpip_adapter/include +INC_COMMON += -I$(ESPCOMP)/lwip/include/lwip +INC_COMMON += -I$(ESPCOMP)/lwip/include/lwip/port +INC_COMMON += -I$(ESPCOMP)/driver/include/driver +INC_COMMON += -I$(ESPCOMP)/driver/include +INC_COMMON += -I$(ESPCOMP)/nvs_flash/include +INC_COMMON += -I$(ESPCOMP)/spi_flash/include +INC_COMMON += -I$(BUILD) + +# Include dirs for main code base, excluding BT +INC_MAIN += -I../lib/mp-readline +INC_MAIN += -I../lib/netutils +INC_MAIN += -I../lib/timeutils +INC_MAIN += -I$(ESPCOMP)/bootloader_support/include +INC_MAIN += -I$(ESPCOMP)/nghttp/port/include +INC_MAIN += -I$(ESPCOMP)/nghttp/include +INC_MAIN += -I$(ESPCOMP)/ethernet/include +INC_MAIN += -I$(ESPCOMP)/expat/include/expat +INC_MAIN += -I$(ESPCOMP)/expat/port/include +INC_MAIN += -I$(ESPCOMP)/json/include +INC_MAIN += -I$(ESPCOMP)/json/port/include +INC_MAIN += -I$(ESPCOMP)/newlib/include +INC_MAIN += -I$(ESPCOMP)/lwip/include/lwip/port +INC_MAIN += -I$(ESPCOMP)/lwip/include/lwip/posix +INC_MAIN += -I$(ESPCOMP)/mbedtls/include +INC_MAIN += -I$(ESPCOMP)/mbedtls/port/include +INC_MAIN += -I$(ESPCOMP)/vfs/include +INC_MAIN += -I$(ESPCOMP)/newlib/platform_include +INC_MAIN += -I$(ESPCOMP)/xtensa-debug-module/include +INC_MAIN += -I$(ESPCOMP)/wpa_supplicant/include +INC_MAIN += -I$(ESPCOMP)/wpa_supplicant/port/include +INC_MAIN += -I$(ESPCOMP)/ethernet/include +INC_MAIN += -I$(ESPCOMP)/tcpip_adapter/include # Bluetooth includes have to be separate because @@ -91,34 +96,37 @@ INC += -I$(ESPCOMP)/tcpip_adapter/include # objects in the /bt/ directory, and for # the MicroPython esp32/network_bluetooth.c -BT_INC = -BT_INC += -I$(ESPCOMP)/bt/bluedroid/api/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/bta/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/bta/sys/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/btc/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/esp/blufi/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/esp/include -BT_INC += -I$(ESPCOMP)/bt/bluedroid/btc/profile/std/include -BT_INC += -I$(ESPCOMP)/bt/bluedroid/btcore/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/device/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/gki/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/hci/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/osi/include/ # Causes problems with List_t in FreeRTOS -BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/gap/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/gatt/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/l2cap/include/ -BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/smp/include/ -BT_INC += -I$(ESPCOMP)/bt/include -BT_INC += -I$(ESPCOMP)/bt/bluedroid/stack/sdp/include/ - -CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM $(INC) +# Include dirs for BT components +INC_BT = +INC_BT += -I$(ESPCOMP)/bt/bluedroid/api/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/bta/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/bta/sys/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/btc/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/btc/profile/esp/blufi/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/btc/profile/esp/include +INC_BT += -I$(ESPCOMP)/bt/bluedroid/btc/profile/std/include +INC_BT += -I$(ESPCOMP)/bt/bluedroid/btcore/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/device/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/gki/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/hci/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/osi/include/ # Causes problems with List_t in FreeRTOS +INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/gap/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/gatt/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/l2cap/include/ +INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/smp/include/ +INC_BT += -I$(ESPCOMP)/bt/include +INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/sdp/include/ + +CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM + CFLAGS += -DIDF_VER=\"$(IDF_VER)\" CFLAGS += $(CFLAGS_MOD) +#CFLAGS += -H # this is what ESPIDF uses for c++ compilation -CXXFLAGS = -std=gnu++11 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DESP_PLATFORM $(INC) +CXXFLAGS = -std=gnu++11 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DESP_PLATFORM $(INC_COMMON) $(INC_MAIN) LDFLAGS = -nostdlib -Map=$(@:.elf=.map) --cref LDFLAGS += --gc-sections -static -EL @@ -139,6 +147,9 @@ COPT += -Os -DNDEBUG #LDFLAGS += --gc-sections endif +CFLAGS_BT := $(CFLAGS) $(INC_COMMON) $(INC_BT) +CFLAGS += $(INC_COMMON) $(INC_MAIN) + ################################################################################ # List of MicroPython source and object files @@ -286,11 +297,12 @@ ESPIDF_ETHERNET_O = $(addprefix $(ESPCOMP)/ethernet/,\ emac_main.o \ ) -$(BUILD)/$(ESPCOMP)/bt/%.o: CFLAGS += $(BT_INC) +$(BUILD)/$(ESPCOMP)/bt/%.o: CFLAGS = $(CFLAGS_BT) $(BUILD)/$(ESPCOMP)/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.o: CFLAGS += -Wno-error=strict-aliasing $(BUILD)/$(ESPCOMP)/bt/bluedroid/stack/btu/btu_task.o: CFLAGS += -Wno-error=strict-aliasing ESPIDF_BLUETOOTH_O = $(addprefix $(ESPCOMP)/bt/,\ + bluedroid/api/esp_bt_device.o \ bluedroid/api/esp_bt_main.o \ bluedroid/api/esp_gap_ble_api.o \ bluedroid/api/esp_gatts_api.o \ @@ -313,9 +325,16 @@ ESPIDF_BLUETOOTH_O = $(addprefix $(ESPCOMP)/bt/,\ bluedroid/bta/sys/bta_sys_conn.o \ bluedroid/bta/sys/bta_sys_main.o \ bluedroid/bta/sys/utl.o \ + bluedroid/btc/core/btc_alarm.o \ + bluedroid/btc/core/btc_ble_storage.o \ + bluedroid/btc/core/btc_config.o \ + bluedroid/btc/core/btc_dev.o \ + bluedroid/btc/core/btc_dm.o \ bluedroid/btc/core/btc_main.o \ bluedroid/btc/core/btc_manage.o \ + bluedroid/btc/core/btc_storage.o \ bluedroid/btc/core/btc_task.o \ + bluedroid/btc/core/btc_util.o \ bluedroid/btc/profile/esp/blufi/blufi_prf.o \ bluedroid/btc/profile/esp/blufi/blufi_protocol.o \ bluedroid/btc/profile/std/gap/btc_gap_ble.o \ @@ -340,6 +359,7 @@ ESPIDF_BLUETOOTH_O = $(addprefix $(ESPCOMP)/bt/,\ bluedroid/main/bte_main.o \ bluedroid/osi/alarm.o \ bluedroid/osi/allocator.o \ + bluedroid/osi/config.o \ bluedroid/osi/fixed_queue.o \ bluedroid/osi/future.o \ bluedroid/osi/hash_functions.o \ @@ -749,7 +769,7 @@ APP_LD_ARGS += --end-group $(BUILD)/esp32_out.ld: sdkconfig.h $(Q)$(CC) -I. -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@ -$(BUILD)/network_bluetooth.o: CFLAGS += $(BT_INC) +$(BUILD)/network_bluetooth.o: CFLAGS = $(CFLAGS_BT) $(BUILD)/application.bin: $(BUILD)/application.elf $(ECHO) "Create $@" $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< From 7595b382fabda1e17a6498c787ca7203ef9a9d74 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 24 Apr 2017 11:25:02 -0700 Subject: [PATCH 28/98] esp32/Makefile: spi_flash/include --> INC_MAIN --- esp32/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index 7a890ba9e..cc8d1032e 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -48,6 +48,7 @@ IDF_VER := $(shell git -C $(ESPIDF) describe) # Include dirs for both BT and MAIN INC_COMMON = -I. INC_COMMON += -I.. +INC_COMMON += -I$(BUILD) INC_COMMON += -I$(ESPCOMP)/log/include INC_COMMON += -I$(ESPCOMP)/esp32/include INC_COMMON += -I$(ESPCOMP)/soc/esp32/include @@ -58,13 +59,12 @@ INC_COMMON += -I$(ESPCOMP)/lwip/include/lwip/port INC_COMMON += -I$(ESPCOMP)/driver/include/driver INC_COMMON += -I$(ESPCOMP)/driver/include INC_COMMON += -I$(ESPCOMP)/nvs_flash/include -INC_COMMON += -I$(ESPCOMP)/spi_flash/include -INC_COMMON += -I$(BUILD) # Include dirs for main code base, excluding BT INC_MAIN += -I../lib/mp-readline INC_MAIN += -I../lib/netutils INC_MAIN += -I../lib/timeutils +INC_MAIN += -I$(ESPCOMP)/spi_flash/include INC_MAIN += -I$(ESPCOMP)/bootloader_support/include INC_MAIN += -I$(ESPCOMP)/nghttp/port/include INC_MAIN += -I$(ESPCOMP)/nghttp/include From 46134940043512b192028746f06168b59828e130 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 24 Apr 2017 15:24:48 -0700 Subject: [PATCH 29/98] esp32/network_bluetooth.c: Services working, added Bluetooth.callback() --- esp32/network_bluetooth.c | 323 ++++++++++++++++++++++---------------- 1 file changed, 188 insertions(+), 135 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 9ca3c2aa5..9161562b8 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -54,7 +54,16 @@ #define UUID_LEN 16 -//#define CUTOUT +#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40 + +uint8_t char1_str[] = {0x11,0x22,0x33}; +esp_attr_value_t gatts_demo_char1_val = +{ + .attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX, + .attr_len = sizeof(char1_str), + .attr_value = char1_str, +}; + const mp_obj_type_t network_bluetooth_type; const mp_obj_type_t network_bluetooth_service_type; @@ -89,6 +98,7 @@ typedef struct { mp_obj_t value; + } network_bluetooth_characteristic_obj_t; // Declaration @@ -104,6 +114,9 @@ typedef struct { esp_ble_adv_data_t data; mp_obj_t services; + + mp_obj_t callback; + mp_obj_t callback_userdata; } network_bluetooth_obj_t; // Singleton @@ -136,7 +149,9 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .p_service_uuid = 0, .flag = 0 }, - .services = MP_OBJ_NULL, + .services = MP_OBJ_NULL, + .callback = MP_OBJ_NULL, + .callback_userdata = MP_OBJ_NULL, }; @@ -681,15 +696,15 @@ STATIC void network_bluetooth_gatts_event_handler( esp_ble_gatts_start_service(service->handle); /* - size_t len; - mp_obj_t *items; - mp_obj_get_array(service->chars, &len, &items); - - for (int i = 0; i < len; i++) { - network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) items[i]; - esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); - } - */ + size_t len; + mp_obj_t *items; + mp_obj_get_array(service->chars, &len, &items); + + for (int i = 0; i < len; i++) { + network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) items[i]; + esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); + } + */ } } @@ -711,18 +726,17 @@ STATIC void network_bluetooth_gatts_event_handler( NETWORK_BLUETOOTH_DEBUG_PRINTF(" char uuid "); network_bluetooth_uuid_print(NULL, &chr->uuid); NETWORK_BLUETOOTH_DEBUG_PRINTF(" perm = %02X, prop = %02X", chr->perm, chr->prop); + NETWORK_BLUETOOTH_DEBUG_PRINTF(" with value!"); NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); - esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); + esp_err_t ret = esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, &gatts_demo_char1_val, NULL); + NETWORK_BLUETOOTH_DEBUG_PRINTF("add char ret value: %d\n", ret); } } } break; - - - case ESP_GATTS_ADD_CHAR_EVT: { network_bluetooth_service_obj_t* service = network_bluetooth_find_item(bluetooth->services, NULL, param->add_char.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); @@ -737,6 +751,10 @@ STATIC void network_bluetooth_gatts_event_handler( break; + case ESP_GATTS_READ_EVT: + case ESP_GATTS_WRITE_EVT: + + default: // Nothing, intentionally break; @@ -751,7 +769,6 @@ STATIC void network_bluetooth_gap_event_handler( NETWORK_BLUETOOTH_DEBUG_PRINTF("entering network_bluetooth_gap_event_handler()\n"); network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); -#ifndef CUTOUT switch (event) { case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: @@ -769,23 +786,29 @@ STATIC void network_bluetooth_gap_event_handler( NETWORK_BLUETOOTH_DEBUG_PRINTF("Advertising start successful\n"); } + break; + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Advertising stop failed\n"); + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Advertising stop successful\n"); + } + break; default: break; } -#endif } STATIC void network_bluetooth_adv_updated() { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_adv_updated()\n"); network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); -#ifndef CUTOUT esp_ble_gap_stop_advertising(); esp_ble_gap_config_adv_data(&self->data); // Restart will be handled in network_bluetooth_gap_event_handler -#endif } /******************************************************************************/ @@ -892,12 +915,8 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); -#ifndef CUTOUT - esp_bt_controller_config_t config = { - .hci_uart_no = 1, - .hci_uart_baudrate = 115200, - }; - esp_bt_controller_init(&config); + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + esp_bt_controller_init(&bt_cfg); switch(esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { case ESP_OK: @@ -940,7 +959,6 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { break; } self->state = NETWORK_BLUETOOTH_STATE_INIT; -#endif } else { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); @@ -1110,7 +1128,6 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po changed = true; } -#ifndef CUTOUT if (unset_adv_dev_name) { esp_ble_gap_set_device_name(""); self->data.include_name = false; @@ -1119,7 +1136,6 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po self->data.include_name = adv_dev_name_buf.len > 0; changed = true; } -#endif if (unset_adv_man_name || adv_man_name_buf.buf != NULL) { if (self->data.p_manufacturer_data != NULL) { @@ -1199,6 +1215,25 @@ STATIC mp_obj_t network_bluetooth_ble_adv_enable(mp_obj_t self_in, mp_obj_t enab } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_ble_adv_enable_obj, network_bluetooth_ble_adv_enable); +STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { + network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); + if (n_args > 1) { + if (mp_obj_is_callable(args[1])) { + self->callback = args[1]; + } else { + mp_raise_ValueError("parameter must be callable"); + } + } + if (n_args > 2) { + self->callback_userdata = args[2]; + } + mp_obj_t items[2] = {self->callback, self->callback_userdata}; + mp_obj_t tuple = mp_obj_new_tuple(2, items); + + return tuple; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_callback_obj, 1, 3, network_bluetooth_callback); + STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new, self = %p, n_args = %d, n_kw = %d\n", self, n_args, n_kw ); @@ -1290,13 +1325,31 @@ mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_characteristic_make_new_obj, 2, network_bluetooth_characteristic_make_new); + STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_start()\n"); network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; mp_int_t numChars = mp_obj_get_int(mp_obj_len(self->chars)); + uint32_t then = mp_hal_ticks_ms(); + + // Wait for registration + while(bluetooth->interface == ESP_GATT_IF_NONE && mp_hal_ticks_ms() - then < 1000) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Waiting for BT interface registration ...\n"); + mp_hal_delay_ms(100); + } + + if (bluetooth->interface == ESP_GATT_IF_NONE) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() has failed"); + } - esp_ble_gatts_create_service(bluetooth->interface, &self->service_id, numChars + 1); + + // Handle calculation: + // + // 1 for 2800/2801 Service declaration + // 1x for each 2803 Char declaration + // 1x for each Char desc declaration --- not used + esp_ble_gatts_create_service(bluetooth->interface, &self->service_id, 1 + numChars * 2); return mp_const_none; } @@ -1353,124 +1406,124 @@ STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) break; } } -} -STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); - // FIXME - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); - -// BLUETOOTH OBJECTS - -STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { - // instance methods - { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, - { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, - { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr - - // class constants - - // esp_ble_adv_type_t - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, - - // esp_ble_addr_type_t - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, - - // esp_ble_adv_channel_t - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, - - // exp_gatt_perm_t - { MP_ROM_QSTR(MP_QSTR_PERM_READ), MP_ROM_INT(ESP_GATT_PERM_READ) }, - { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_READ_ENCRYPTED) }, - { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_READ_ENC_MITM) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE), MP_ROM_INT(ESP_GATT_PERM_WRITE) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENCRYPTED) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENC_MITM) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED_MITM) }, - - // esp_gatt_char_prop_t - - { MP_ROM_QSTR(MP_QSTR_PROP_BROADCAST), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_BROADCAST) }, - { MP_ROM_QSTR(MP_QSTR_PROP_READ), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_READ) }, - { MP_ROM_QSTR(MP_QSTR_PROP_WRITE_NR), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE_NR) }, - { MP_ROM_QSTR(MP_QSTR_PROP_WRITE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE) }, - { MP_ROM_QSTR(MP_QSTR_PROP_NOTIFY), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_NOTIFY) }, - { MP_ROM_QSTR(MP_QSTR_PROP_INDICATE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_INDICATE) }, - { MP_ROM_QSTR(MP_QSTR_PROP_AUTH), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_AUTH) }, - { MP_ROM_QSTR(MP_QSTR_PROP_EXT_PROP), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_EXT_PROP) }, - - // esp_ble_adv_filter_t - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) }, -}; + STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); + // FIXME + return mp_const_none; + } + STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); + + // BLUETOOTH OBJECTS + + STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, + { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, + { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, + + // class constants + + // esp_ble_adv_type_t + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, + + // esp_ble_addr_type_t + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, + + // esp_ble_adv_channel_t + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, + + // exp_gatt_perm_t + { MP_ROM_QSTR(MP_QSTR_PERM_READ), MP_ROM_INT(ESP_GATT_PERM_READ) }, + { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_READ_ENCRYPTED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_READ_ENC_MITM) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE), MP_ROM_INT(ESP_GATT_PERM_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENCRYPTED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENC_MITM) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED_MITM) }, + + // esp_gatt_char_prop_t + + { MP_ROM_QSTR(MP_QSTR_PROP_BROADCAST), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_BROADCAST) }, + { MP_ROM_QSTR(MP_QSTR_PROP_READ), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_READ) }, + { MP_ROM_QSTR(MP_QSTR_PROP_WRITE_NR), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE_NR) }, + { MP_ROM_QSTR(MP_QSTR_PROP_WRITE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_PROP_NOTIFY), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_NOTIFY) }, + { MP_ROM_QSTR(MP_QSTR_PROP_INDICATE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_INDICATE) }, + { MP_ROM_QSTR(MP_QSTR_PROP_AUTH), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_AUTH) }, + { MP_ROM_QSTR(MP_QSTR_PROP_EXT_PROP), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_EXT_PROP) }, + + // esp_ble_adv_filter_t + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) }, + }; -STATIC MP_DEFINE_CONST_DICT(network_bluetooth_locals_dict, network_bluetooth_locals_dict_table); + STATIC MP_DEFINE_CONST_DICT(network_bluetooth_locals_dict, network_bluetooth_locals_dict_table); -const mp_obj_type_t network_bluetooth_type = { - { &mp_type_type }, - .name = MP_QSTR_Bluetooth, - .print = network_bluetooth_print, - .make_new = network_bluetooth_make_new, - .locals_dict = (mp_obj_dict_t*)&network_bluetooth_locals_dict, - .attr = network_bluetooth_attr, -}; + const mp_obj_type_t network_bluetooth_type = { + { &mp_type_type }, + .name = MP_QSTR_Bluetooth, + .print = network_bluetooth_print, + .make_new = network_bluetooth_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_locals_dict, + .attr = network_bluetooth_attr, + }; -// SERVICE OBJECTS + // SERVICE OBJECTS -STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_Char), NULL }, - { MP_ROM_QSTR(MP_QSTR_chars), NULL }, - { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&network_bluetooth_service_close_obj) }, -}; + STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_Char), NULL }, + { MP_ROM_QSTR(MP_QSTR_chars), NULL }, + { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&network_bluetooth_service_close_obj) }, + }; -STATIC MP_DEFINE_CONST_DICT(network_bluetooth_service_locals_dict, network_bluetooth_service_locals_dict_table); + STATIC MP_DEFINE_CONST_DICT(network_bluetooth_service_locals_dict, network_bluetooth_service_locals_dict_table); -const mp_obj_type_t network_bluetooth_service_type = { - { &mp_type_type }, - .name = MP_QSTR_Service, - .print = network_bluetooth_service_print, - .make_new = network_bluetooth_service_make_new, - .locals_dict = (mp_obj_dict_t*)&network_bluetooth_service_locals_dict, - .attr = network_bluetooth_service_attr, -}; + const mp_obj_type_t network_bluetooth_service_type = { + { &mp_type_type }, + .name = MP_QSTR_Service, + .print = network_bluetooth_service_print, + .make_new = network_bluetooth_service_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_service_locals_dict, + .attr = network_bluetooth_service_attr, + }; -// CHARACTERISTIC OBJECTS + // CHARACTERISTIC OBJECTS -STATIC const mp_rom_map_elem_t network_bluetooth_characteristic_locals_dict_table[] = { -}; + STATIC const mp_rom_map_elem_t network_bluetooth_characteristic_locals_dict_table[] = { + }; -STATIC MP_DEFINE_CONST_DICT(network_bluetooth_characteristic_locals_dict, network_bluetooth_characteristic_locals_dict_table); + STATIC MP_DEFINE_CONST_DICT(network_bluetooth_characteristic_locals_dict, network_bluetooth_characteristic_locals_dict_table); -const mp_obj_type_t network_bluetooth_characteristic_type = { - { &mp_type_type }, - .name = MP_QSTR_Char, - .print = network_bluetooth_characteristic_print, - .locals_dict = (mp_obj_dict_t*)&network_bluetooth_characteristic_locals_dict, -}; + const mp_obj_type_t network_bluetooth_characteristic_type = { + { &mp_type_type }, + .name = MP_QSTR_Char, + .print = network_bluetooth_characteristic_print, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_characteristic_locals_dict, + }; From fa8b776f0af4ad1faa335fa5d3d65ad04c1f2f36 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 25 Apr 2017 16:10:54 -0700 Subject: [PATCH 30/98] esp32:network_bluetooth.c: Just got characteristic callbacks working Needs more testing --- esp32/network_bluetooth.c | 487 +++++++++++++++++++++++++------------- 1 file changed, 327 insertions(+), 160 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 9161562b8..ac42c8b1c 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -28,8 +28,10 @@ #include #include + #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/semphr.h" #include "py/runtime.h" #include "py/runtime0.h" @@ -54,23 +56,21 @@ #define UUID_LEN 16 -#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40 - -uint8_t char1_str[] = {0x11,0x22,0x33}; -esp_attr_value_t gatts_demo_char1_val = -{ - .attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX, - .attr_len = sizeof(char1_str), - .attr_value = char1_str, -}; - const mp_obj_type_t network_bluetooth_type; const mp_obj_type_t network_bluetooth_service_type; const mp_obj_type_t network_bluetooth_characteristic_type; +// FIXME, this is probably too high +#define MUTEX_WAIT_MS 3000 -// SERVICE +SemaphoreHandle_t mut; +mp_obj_t callback_queue; // implemented as a list + +#define CRIT_BEGIN() xSemaphoreTakeRecursive(mut, MUTEX_WAIT_MS / portTICK_PERIOD_MS) +#define CRIT_END() xSemaphoreGiveRecursive(mut) + +// "Service" typedef struct { mp_obj_base_t base; esp_gatt_srvc_id_t service_id; @@ -85,7 +85,7 @@ typedef struct { -// CHARACTERISTIC +// "Char" typedef struct { mp_obj_base_t base; @@ -96,12 +96,14 @@ typedef struct { uint16_t handle; - mp_obj_t value; + mp_obj_t callback; + mp_obj_t callback_userdata; + mp_obj_t value; -} network_bluetooth_characteristic_obj_t; +} network_bluetooth_char_obj_t; -// Declaration +// "Bluetooth" Declaration typedef struct { mp_obj_base_t base; enum { @@ -113,10 +115,11 @@ typedef struct { esp_ble_adv_params_t params; esp_ble_adv_data_t data; - mp_obj_t services; + mp_obj_t services; // implemented as a list mp_obj_t callback; mp_obj_t callback_userdata; + } network_bluetooth_obj_t; // Singleton @@ -150,8 +153,10 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .flag = 0 }, .services = MP_OBJ_NULL, - .callback = MP_OBJ_NULL, - .callback_userdata = MP_OBJ_NULL, + .callback = mp_const_none, + .callback_userdata = mp_const_none, + + }; @@ -235,6 +240,8 @@ typedef enum { STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle, item_type_t kind) { + CRIT_BEGIN(); + mp_obj_t ret = MP_OBJ_NULL; size_t len; mp_obj_t *items; mp_obj_get_array(list, &len, &items); @@ -243,23 +250,27 @@ STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, case NETWORK_BLUETOOTH_FIND_SERVICE: { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; - if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || service->handle == handle) - return service; + if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || service->handle == handle) { + ret = service; + goto NETWORK_BLUETOOTH_FIND_ITEM_END; + } } break; case NETWORK_BLUETOOTH_FIND_CHAR: { - network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) items[i]; + network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || chr->handle == handle) { - return chr; + ret = chr; + goto NETWORK_BLUETOOTH_FIND_ITEM_END; } } - break; } } - return MP_OBJ_NULL; +NETWORK_BLUETOOTH_FIND_ITEM_END: + CRIT_END(); + return ret; } @@ -667,11 +678,90 @@ STATIC void gatts_event_dump( } NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); +} +STATIC mp_obj_t network_bluetooth_callback_data_handler (mp_obj_t arg) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + network_bluetooth_char_obj_t *self; + + NETWORK_BLUETOOTH_DEBUG_PRINTF("In data handler\n"); + + + size_t queue_len; + mp_obj_t* queue_items; + + size_t len; + mp_obj_t *items; + size_t service_len; + mp_obj_t *service_items; + + CRIT_BEGIN(); + mp_obj_get_array(callback_queue, &queue_len, &queue_items); + NETWORK_BLUETOOTH_DEBUG_PRINTF("Found %u queue items\n", queue_len); + + for(int i = 0; i < queue_len; i++) { + mp_obj_get_array(queue_items[i], &len, &items); + + assert(len == 6); + esp_gatts_cb_event_t event = mp_obj_get_int(items[0]); + uint16_t handle = mp_obj_get_int(items[1]); + mp_obj_t write_value = items[2]; + uint16_t conn_id = mp_obj_get_int(items[3]); + uint32_t trans_id = mp_obj_get_int(items[4]); + bool need_rsp = mp_obj_is_true(items[5]); + + + mp_obj_get_array(bluetooth->services, &service_len, &service_items); + for(int j = 0; j < service_len; j++) { + network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; + self = network_bluetooth_find_item(service->chars, NULL, handle, NETWORK_BLUETOOTH_FIND_CHAR); + if (self != MP_OBJ_NULL) { + goto NETWORK_BLUETOOTH_CALLBACK_DATA_HANDLER_CHAR_FOUND; + } + } + continue; + +NETWORK_BLUETOOTH_CALLBACK_DATA_HANDLER_CHAR_FOUND: + + { + mp_obj_t value = event == ESP_GATTS_READ_EVT ? self->value : write_value; + if (self->callback != mp_const_none) { + mp_obj_t args[] = {self, items[0], value, self->callback_userdata }; + value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); + } else if (event == ESP_GATTS_WRITE_EVT) { + self->value = value; + } + + if (need_rsp) { + esp_gatt_rsp_t rsp; + memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); + + mp_buffer_info_t buf; + memset(&buf, 0, sizeof(mp_buffer_info_t)); + + if(MP_OBJ_IS_STR_OR_BYTES(value)) { + mp_get_buffer(value, &buf, MP_BUFFER_READ); + } + + size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); + + rsp.attr_value.handle = handle; + rsp.attr_value.len = len; + memcpy(rsp.attr_value.value, buf.buf, len); + esp_ble_gatts_send_response(bluetooth->interface, conn_id, trans_id, ESP_GATT_OK, &rsp); + + } + } + } + + mp_obj_list_set_len(callback_queue, 0); + CRIT_END(); + return mp_const_none; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_callback_data_handler_obj, network_bluetooth_callback_data_handler); STATIC void network_bluetooth_gatts_event_handler( esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, @@ -701,7 +791,7 @@ STATIC void network_bluetooth_gatts_event_handler( mp_obj_get_array(service->chars, &len, &items); for (int i = 0; i < len; i++) { - network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) items[i]; + network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); } */ @@ -721,16 +811,12 @@ STATIC void network_bluetooth_gatts_event_handler( mp_obj_get_array(service->chars, &len, &items); for (int i = 0; i < len; i++) { - network_bluetooth_characteristic_obj_t* chr = (network_bluetooth_characteristic_obj_t*) items[i]; + network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; NETWORK_BLUETOOTH_DEBUG_PRINTF("adding char for service %04X", service->handle); NETWORK_BLUETOOTH_DEBUG_PRINTF(" char uuid "); network_bluetooth_uuid_print(NULL, &chr->uuid); - NETWORK_BLUETOOTH_DEBUG_PRINTF(" perm = %02X, prop = %02X", chr->perm, chr->prop); - NETWORK_BLUETOOTH_DEBUG_PRINTF(" with value!"); - NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); - - esp_err_t ret = esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, &gatts_demo_char1_val, NULL); - NETWORK_BLUETOOTH_DEBUG_PRINTF("add char ret value: %d\n", ret); + NETWORK_BLUETOOTH_DEBUG_PRINTF(" perm = %02X, prop = %02X\n", chr->perm, chr->prop); + esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); } } } @@ -741,7 +827,7 @@ STATIC void network_bluetooth_gatts_event_handler( { network_bluetooth_service_obj_t* service = network_bluetooth_find_item(bluetooth->services, NULL, param->add_char.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); if (service != MP_OBJ_NULL) { - network_bluetooth_characteristic_obj_t* chr = network_bluetooth_find_item(service->chars, ¶m->add_char.char_uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); + network_bluetooth_char_obj_t* chr = network_bluetooth_find_item(service->chars, ¶m->add_char.char_uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); chr->handle = param->add_char.attr_handle; NETWORK_BLUETOOTH_DEBUG_PRINTF("Setting char handle to %04X, from service handle %04X\n", param->add_char.attr_handle, param->add_char.service_handle); } else { @@ -753,6 +839,38 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_READ_EVT: case ESP_GATTS_WRITE_EVT: + { + + // We rely on the fact that the `read` and `write` unions + // are the same for the first few fields, thus all the references to + // param->read + + + mp_obj_t write_value = event == ESP_GATTS_WRITE_EVT ? mp_obj_new_bytearray(param->write.len, param->write.value) : MP_OBJ_NULL; + + // event, handle, write_value, conn_id, trans_id, need_rsp + // -------------------------------------------------------- + // int int MP_OBJ_NULL int int bool + // or bytearray + + mp_obj_t args[] = { + MP_OBJ_NEW_SMALL_INT(event), + MP_OBJ_NEW_SMALL_INT(param->read.handle), + write_value, + mp_obj_new_int(param->read.conn_id), + mp_obj_new_int(param->read.trans_id), + event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp) ? mp_const_true : mp_const_false }; + + CRIT_BEGIN(); + mp_obj_list_append(callback_queue, mp_obj_new_list(MP_ARRAY_SIZE(args), args)); + CRIT_END(); + mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_data_handler_obj), MP_OBJ_NULL); + + + NETWORK_BLUETOOTH_DEBUG_PRINTF("data pushed\n"); + + } + break; default: @@ -763,6 +881,8 @@ STATIC void network_bluetooth_gatts_event_handler( } + + STATIC void network_bluetooth_gap_event_handler( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { @@ -817,17 +937,10 @@ STATIC void network_bluetooth_adv_updated() { STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - network_bluetooth_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + network_bluetooth_char_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "BTChar(uuid = "); network_bluetooth_uuid_print(print, &self->uuid); - mp_printf(print, ", perm = %02X, prop = %02X", self->perm, self->prop); - mp_printf(print, ", value = "); - - mp_obj_type_t *type = mp_obj_get_type(self->value); - if (type->print != NULL) { - type->print(print, self->value, kind); - } - mp_printf(print, ")"); + mp_printf(print, ", perm = %02X, prop = %02X)", self->perm, self->prop); } STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -910,6 +1023,14 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { self->services = mp_obj_new_list(0, NULL); } + if (callback_queue == MP_OBJ_NULL) { + callback_queue = mp_obj_new_list(0, NULL); + } + + if (mut == NULL) { + mut = xSemaphoreCreateRecursiveMutex(); + } + NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth services pointer: %p", self->services); if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { @@ -1215,25 +1336,37 @@ STATIC mp_obj_t network_bluetooth_ble_adv_enable(mp_obj_t self_in, mp_obj_t enab } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_ble_adv_enable_obj, network_bluetooth_ble_adv_enable); -STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { - network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); +STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* callback_userdata, size_t n_args, const mp_obj_t *args) { if (n_args > 1) { - if (mp_obj_is_callable(args[1])) { - self->callback = args[1]; + if (mp_obj_is_callable(args[1]) || args[1] == mp_const_none) { + *callback = args[1]; } else { - mp_raise_ValueError("parameter must be callable"); + mp_raise_ValueError("parameter must be callable, or None"); } + + *callback_userdata = n_args > 2 ? args[2] : mp_const_none; } - if (n_args > 2) { - self->callback_userdata = args[2]; - } - mp_obj_t items[2] = {self->callback, self->callback_userdata}; + + NETWORK_BLUETOOTH_DEBUG_PRINTF("Callback ptr is %p\n", callback); + mp_obj_t items[2] = {*callback, *callback_userdata}; mp_obj_t tuple = mp_obj_new_tuple(2, items); return tuple; } + + +STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { + network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); + return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); +} STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_callback_obj, 1, 3, network_bluetooth_callback); +STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *args) { + network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) args[0]; + return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_callback_obj, 1, 3, network_bluetooth_char_callback); + STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new, self = %p, n_args = %d, n_kw = %d\n", self, n_args, n_kw ); @@ -1276,7 +1409,9 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ self->service_id.is_primary = mp_obj_is_true(args[ARG_primary].u_obj); self->chars = mp_obj_new_list(0, NULL); + CRIT_BEGIN(); mp_obj_list_append(bluetooth->services, MP_OBJ_FROM_PTR(self)); + CRIT_END(); return MP_OBJ_FROM_PTR(self); } @@ -1298,21 +1433,23 @@ mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_characteristic_obj_t *self = network_bluetooth_find_item(service->chars, &uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); + network_bluetooth_char_obj_t *self = network_bluetooth_find_item(service->chars, &uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); if (self != MP_OBJ_NULL) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Returning extant char for that UUID\n"); return MP_OBJ_FROM_PTR(self); } - NETWORK_BLUETOOTH_DEBUG_PRINTF("Making a new char object\n"); - self = m_new_obj(network_bluetooth_characteristic_obj_t); + self = m_new_obj(network_bluetooth_char_obj_t); self->base.type = &network_bluetooth_characteristic_type; + NETWORK_BLUETOOTH_DEBUG_PRINTF("Making a new char object %p\n", self); if (args[ARG_value].u_obj != mp_const_none && !MP_OBJ_IS_STR_OR_BYTES(args[ARG_value].u_obj)) { mp_raise_ValueError("value must be string, bytearray or None"); } + self->callback = mp_const_none; + self->uuid = uuid; self->value = args[ARG_value].u_obj; self->perm = args[ARG_perm].u_int; @@ -1370,6 +1507,26 @@ STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); +// char attribute handler +STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) self_in; + if (!check_locals_dict(self, attr, dest)) { + + switch(attr) { + case MP_QSTR_value: + if (dest[0] == MP_OBJ_NULL) { // load + dest[0] = self->value; + } else if (dest[1] != MP_OBJ_NULL) { // store + if (!MP_OBJ_IS_STR_OR_BYTES(dest[1])) { + mp_raise_ValueError("value must be bytearray or string"); + } + self->value = dest[1]; + dest[0] = MP_OBJ_NULL; + } + } + } +} + // service attribute handler STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; @@ -1406,124 +1563,134 @@ STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) break; } } +} - STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); - // FIXME - return mp_const_none; - } - STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); - - // BLUETOOTH OBJECTS - - STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { - // instance methods - { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, - { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, - { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr - { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, - - // class constants - - // esp_ble_adv_type_t - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, - { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, - - // esp_ble_addr_type_t - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, - - // esp_ble_adv_channel_t - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, - { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, - - // exp_gatt_perm_t - { MP_ROM_QSTR(MP_QSTR_PERM_READ), MP_ROM_INT(ESP_GATT_PERM_READ) }, - { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_READ_ENCRYPTED) }, - { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_READ_ENC_MITM) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE), MP_ROM_INT(ESP_GATT_PERM_WRITE) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENCRYPTED) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENC_MITM) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED) }, - { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED_MITM) }, - - // esp_gatt_char_prop_t - - { MP_ROM_QSTR(MP_QSTR_PROP_BROADCAST), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_BROADCAST) }, - { MP_ROM_QSTR(MP_QSTR_PROP_READ), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_READ) }, - { MP_ROM_QSTR(MP_QSTR_PROP_WRITE_NR), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE_NR) }, - { MP_ROM_QSTR(MP_QSTR_PROP_WRITE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE) }, - { MP_ROM_QSTR(MP_QSTR_PROP_NOTIFY), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_NOTIFY) }, - { MP_ROM_QSTR(MP_QSTR_PROP_INDICATE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_INDICATE) }, - { MP_ROM_QSTR(MP_QSTR_PROP_AUTH), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_AUTH) }, - { MP_ROM_QSTR(MP_QSTR_PROP_EXT_PROP), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_EXT_PROP) }, - - // esp_ble_adv_filter_t - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) }, - }; +STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); + // FIXME + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); + +// BLUETOOTH OBJECTS + +STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, + { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, + { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, + + // class constants + + // Callback types + { MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(ESP_GATTS_CONNECT_EVT) }, + { MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(ESP_GATTS_DISCONNECT_EVT) }, + { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(ESP_GATTS_READ_EVT) }, + { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(ESP_GATTS_WRITE_EVT) }, + + // esp_ble_adv_type_t + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_HIGH), MP_ROM_INT(ADV_TYPE_DIRECT_IND_HIGH) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_SCAN_IND), MP_ROM_INT(ADV_TYPE_SCAN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_NONCONN_IND), MP_ROM_INT(ADV_TYPE_NONCONN_IND) }, + { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_DIRECT_IND_LOW), MP_ROM_INT(ADV_TYPE_DIRECT_IND_LOW) }, + + // esp_ble_addr_type_t + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, + + // esp_ble_adv_channel_t + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, + { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, + + // exp_gatt_perm_t + { MP_ROM_QSTR(MP_QSTR_PERM_READ), MP_ROM_INT(ESP_GATT_PERM_READ) }, + { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_READ_ENCRYPTED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_READ_ENC_MITM) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE), MP_ROM_INT(ESP_GATT_PERM_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENCRYPTED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_ENC_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_ENC_MITM) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED) }, + { MP_ROM_QSTR(MP_QSTR_PERM_WRITE_SIGNED_MITM), MP_ROM_INT(ESP_GATT_PERM_WRITE_SIGNED_MITM) }, + + // esp_gatt_char_prop_t + + { MP_ROM_QSTR(MP_QSTR_PROP_BROADCAST), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_BROADCAST) }, + { MP_ROM_QSTR(MP_QSTR_PROP_READ), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_READ) }, + { MP_ROM_QSTR(MP_QSTR_PROP_WRITE_NR), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE_NR) }, + { MP_ROM_QSTR(MP_QSTR_PROP_WRITE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_PROP_NOTIFY), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_NOTIFY) }, + { MP_ROM_QSTR(MP_QSTR_PROP_INDICATE), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_INDICATE) }, + { MP_ROM_QSTR(MP_QSTR_PROP_AUTH), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_AUTH) }, + { MP_ROM_QSTR(MP_QSTR_PROP_EXT_PROP), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_EXT_PROP) }, + + // esp_ble_adv_filter_t + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) }, +}; - STATIC MP_DEFINE_CONST_DICT(network_bluetooth_locals_dict, network_bluetooth_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_locals_dict, network_bluetooth_locals_dict_table); - const mp_obj_type_t network_bluetooth_type = { - { &mp_type_type }, - .name = MP_QSTR_Bluetooth, - .print = network_bluetooth_print, - .make_new = network_bluetooth_make_new, - .locals_dict = (mp_obj_dict_t*)&network_bluetooth_locals_dict, - .attr = network_bluetooth_attr, - }; +const mp_obj_type_t network_bluetooth_type = { + { &mp_type_type }, + .name = MP_QSTR_Bluetooth, + .print = network_bluetooth_print, + .make_new = network_bluetooth_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_locals_dict, + .attr = network_bluetooth_attr, +}; - // SERVICE OBJECTS +// SERVICE OBJECTS - STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_Char), NULL }, - { MP_ROM_QSTR(MP_QSTR_chars), NULL }, - { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&network_bluetooth_service_close_obj) }, - }; +STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_Char), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&network_bluetooth_service_close_obj) }, +}; - STATIC MP_DEFINE_CONST_DICT(network_bluetooth_service_locals_dict, network_bluetooth_service_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_service_locals_dict, network_bluetooth_service_locals_dict_table); - const mp_obj_type_t network_bluetooth_service_type = { - { &mp_type_type }, - .name = MP_QSTR_Service, - .print = network_bluetooth_service_print, - .make_new = network_bluetooth_service_make_new, - .locals_dict = (mp_obj_dict_t*)&network_bluetooth_service_locals_dict, - .attr = network_bluetooth_service_attr, - }; +const mp_obj_type_t network_bluetooth_service_type = { + { &mp_type_type }, + .name = MP_QSTR_Service, + .print = network_bluetooth_service_print, + .make_new = network_bluetooth_service_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_service_locals_dict, + .attr = network_bluetooth_service_attr, +}; - // CHARACTERISTIC OBJECTS +// CHARACTERISTIC OBJECTS - STATIC const mp_rom_map_elem_t network_bluetooth_characteristic_locals_dict_table[] = { - }; +STATIC const mp_rom_map_elem_t network_bluetooth_characteristic_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), NULL }, // handled by attr handler +}; - STATIC MP_DEFINE_CONST_DICT(network_bluetooth_characteristic_locals_dict, network_bluetooth_characteristic_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_characteristic_locals_dict, network_bluetooth_characteristic_locals_dict_table); - const mp_obj_type_t network_bluetooth_characteristic_type = { - { &mp_type_type }, - .name = MP_QSTR_Char, - .print = network_bluetooth_characteristic_print, - .locals_dict = (mp_obj_dict_t*)&network_bluetooth_characteristic_locals_dict, - }; +const mp_obj_type_t network_bluetooth_characteristic_type = { + { &mp_type_type }, + .name = MP_QSTR_Char, + .print = network_bluetooth_characteristic_print, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_characteristic_locals_dict, + .attr = network_bluetooth_char_attr, +}; From 64fee586222301c74c2610258b2a69eb72ccd8f0 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 26 Apr 2017 09:32:26 -0700 Subject: [PATCH 31/98] esp32/network_bluetooth.c: Fixed bug in network_bluetooth_find_item Thanks to @mahanet on Github --- esp32/network_bluetooth.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index ac42c8b1c..54cba4502 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -250,7 +250,7 @@ STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, case NETWORK_BLUETOOTH_FIND_SERVICE: { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; - if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || service->handle == handle) { + if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || (uuid == NULL && service->handle == handle)) { ret = service; goto NETWORK_BLUETOOTH_FIND_ITEM_END; } @@ -260,7 +260,7 @@ STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, case NETWORK_BLUETOOTH_FIND_CHAR: { network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; - if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || chr->handle == handle) { + if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle)) { ret = chr; goto NETWORK_BLUETOOTH_FIND_ITEM_END; } @@ -940,7 +940,7 @@ STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_o network_bluetooth_char_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "BTChar(uuid = "); network_bluetooth_uuid_print(print, &self->uuid); - mp_printf(print, ", perm = %02X, prop = %02X)", self->perm, self->prop); + mp_printf(print, ", perm = %02X, prop = %02X, handle = %04X)", self->perm, self->prop, self->handle); } STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -948,7 +948,7 @@ STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t se // FIXME mp_printf(print, "Service(uuid = "); network_bluetooth_uuid_print(print, &self->service_id.id.uuid); - mp_printf(print, ")"); + mp_printf(print, ", handle = %04X)", self->handle); } STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { From bbb40cd4498623b8f14dbfa7544f411e5de89031 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 26 Apr 2017 11:21:21 -0700 Subject: [PATCH 32/98] esp32/network_bluetooth.c: Added connect/disconnect callback --- esp32/network_bluetooth.c | 179 ++++++++++++++++++++++---------------- 1 file changed, 105 insertions(+), 74 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 54cba4502..edbfcb6ea 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -111,7 +111,11 @@ typedef struct { NETWORK_BLUETOOTH_STATE_INIT } state; bool advertising; + + bool connected; + uint16_t conn_id; esp_gatt_if_t interface; + esp_ble_adv_params_t params; esp_ble_adv_data_t data; @@ -127,6 +131,8 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .base = { &network_bluetooth_type }, .state = NETWORK_BLUETOOTH_STATE_DEINIT, .advertising = false, + .connected = false, + .conn_id = 0, .interface = ESP_GATT_IF_NONE, .params = { .adv_int_min = 1280 * 1.6, @@ -704,55 +710,81 @@ STATIC mp_obj_t network_bluetooth_callback_data_handler (mp_obj_t arg) { for(int i = 0; i < queue_len; i++) { mp_obj_get_array(queue_items[i], &len, &items); - assert(len == 6); esp_gatts_cb_event_t event = mp_obj_get_int(items[0]); - uint16_t handle = mp_obj_get_int(items[1]); - mp_obj_t write_value = items[2]; - uint16_t conn_id = mp_obj_get_int(items[3]); - uint32_t trans_id = mp_obj_get_int(items[4]); - bool need_rsp = mp_obj_is_true(items[5]); - - - mp_obj_get_array(bluetooth->services, &service_len, &service_items); - for(int j = 0; j < service_len; j++) { - network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; - self = network_bluetooth_find_item(service->chars, NULL, handle, NETWORK_BLUETOOTH_FIND_CHAR); - if (self != MP_OBJ_NULL) { - goto NETWORK_BLUETOOTH_CALLBACK_DATA_HANDLER_CHAR_FOUND; - } - } - continue; + switch (event) { + + case ESP_GATTS_READ_EVT: + case ESP_GATTS_WRITE_EVT: + + { + assert(len == 6); + uint16_t handle = mp_obj_get_int(items[1]); + mp_obj_t write_value = items[2]; + uint16_t conn_id = mp_obj_get_int(items[3]); + uint32_t trans_id = mp_obj_get_int(items[4]); + bool need_rsp = mp_obj_is_true(items[5]); + + + mp_obj_get_array(bluetooth->services, &service_len, &service_items); + for(int j = 0; j < service_len; j++) { + network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; + self = network_bluetooth_find_item(service->chars, NULL, handle, NETWORK_BLUETOOTH_FIND_CHAR); + if (self != MP_OBJ_NULL) { + goto NETWORK_BLUETOOTH_CALLBACK_DATA_HANDLER_CHAR_FOUND; + } + } + continue; NETWORK_BLUETOOTH_CALLBACK_DATA_HANDLER_CHAR_FOUND: - { - mp_obj_t value = event == ESP_GATTS_READ_EVT ? self->value : write_value; - if (self->callback != mp_const_none) { - mp_obj_t args[] = {self, items[0], value, self->callback_userdata }; - value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); - } else if (event == ESP_GATTS_WRITE_EVT) { - self->value = value; - } + { + mp_obj_t value = event == ESP_GATTS_READ_EVT ? self->value : write_value; + if (self->callback != mp_const_none) { + mp_obj_t args[] = {self, items[0], value, self->callback_userdata }; + value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); + } else if (event == ESP_GATTS_WRITE_EVT) { + self->value = value; + } - if (need_rsp) { - esp_gatt_rsp_t rsp; - memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); + if (need_rsp) { + esp_gatt_rsp_t rsp; + memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); - mp_buffer_info_t buf; - memset(&buf, 0, sizeof(mp_buffer_info_t)); + mp_buffer_info_t buf; + memset(&buf, 0, sizeof(mp_buffer_info_t)); - if(MP_OBJ_IS_STR_OR_BYTES(value)) { - mp_get_buffer(value, &buf, MP_BUFFER_READ); - } + if(MP_OBJ_IS_STR_OR_BYTES(value)) { + mp_get_buffer(value, &buf, MP_BUFFER_READ); + } - size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); + size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); - rsp.attr_value.handle = handle; - rsp.attr_value.len = len; - memcpy(rsp.attr_value.value, buf.buf, len); - esp_ble_gatts_send_response(bluetooth->interface, conn_id, trans_id, ESP_GATT_OK, &rsp); + rsp.attr_value.handle = handle; + rsp.attr_value.len = len; + memcpy(rsp.attr_value.value, buf.buf, len); + esp_ble_gatts_send_response(bluetooth->interface, conn_id, trans_id, ESP_GATT_OK, &rsp); - } + } + } + } + break; + + case ESP_GATTS_CONNECT_EVT: + case ESP_GATTS_DISCONNECT_EVT: + { + assert(len == 2); + if (bluetooth->callback != mp_const_none) { + // items[0] is event + // items[1] is remote address + mp_obj_t args[] = {bluetooth, items[0], items[1], bluetooth->callback_userdata }; + mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); + } + break; + + } + default: + // do nothing, intentionally + break; } } @@ -760,8 +792,8 @@ STATIC mp_obj_t network_bluetooth_callback_data_handler (mp_obj_t arg) { CRIT_END(); return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_callback_data_handler_obj, network_bluetooth_callback_data_handler); + STATIC void network_bluetooth_gatts_event_handler( esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, @@ -784,17 +816,6 @@ STATIC void network_bluetooth_gatts_event_handler( service->handle = param->create.service_handle; service->service_id = param->create.service_id; esp_ble_gatts_start_service(service->handle); - - /* - size_t len; - mp_obj_t *items; - mp_obj_get_array(service->chars, &len, &items); - - for (int i = 0; i < len; i++) { - network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; - esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); - } - */ } } @@ -812,10 +833,6 @@ STATIC void network_bluetooth_gatts_event_handler( for (int i = 0; i < len; i++) { network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; - NETWORK_BLUETOOTH_DEBUG_PRINTF("adding char for service %04X", service->handle); - NETWORK_BLUETOOTH_DEBUG_PRINTF(" char uuid "); - network_bluetooth_uuid_print(NULL, &chr->uuid); - NETWORK_BLUETOOTH_DEBUG_PRINTF(" perm = %02X, prop = %02X\n", chr->perm, chr->prop); esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); } } @@ -839,36 +856,48 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_READ_EVT: case ESP_GATTS_WRITE_EVT: + case ESP_GATTS_CONNECT_EVT: + case ESP_GATTS_DISCONNECT_EVT: { // We rely on the fact that the `read` and `write` unions // are the same for the first few fields, thus all the references to // param->read - - mp_obj_t write_value = event == ESP_GATTS_WRITE_EVT ? mp_obj_new_bytearray(param->write.len, param->write.value) : MP_OBJ_NULL; - - // event, handle, write_value, conn_id, trans_id, need_rsp - // -------------------------------------------------------- + // event, handle, write_value, conn_id, trans_id, need_rsp <-- For READ/WRite // int int MP_OBJ_NULL int int bool // or bytearray + // + // event, remote adx <-- For connect/disconnect + // -------------------------------------------------------- + // int, bytearray + + mp_obj_t args = MP_OBJ_NULL; + if (event == ESP_GATTS_REG_EVT || event == ESP_GATTS_WRITE_EVT) { + mp_obj_t rw_args[] = { + MP_OBJ_NEW_SMALL_INT(event), + MP_OBJ_NEW_SMALL_INT(param->read.handle), + event == ESP_GATTS_WRITE_EVT ? mp_obj_new_bytearray(param->write.len, param->write.value) : MP_OBJ_NULL, + mp_obj_new_int(param->read.conn_id), + mp_obj_new_int(param->read.trans_id), + event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp) ? mp_const_true : mp_const_false}; + args = mp_obj_new_list(MP_ARRAY_SIZE(rw_args), rw_args); + + } else if (event == ESP_GATTS_CONNECT_EVT || event == ESP_GATTS_DISCONNECT_EVT) { + mp_obj_t cd_args [] = { + MP_OBJ_NEW_SMALL_INT(event), + mp_obj_new_bytearray(sizeof(param->connect.remote_bda), ¶m->connect.remote_bda), }; + args = mp_obj_new_list(MP_ARRAY_SIZE(cd_args), cd_args); + bluetooth->conn_id = param->connect.conn_id; + bluetooth->connected = event == ESP_GATTS_CONNECT_EVT; + } + - mp_obj_t args[] = { - MP_OBJ_NEW_SMALL_INT(event), - MP_OBJ_NEW_SMALL_INT(param->read.handle), - write_value, - mp_obj_new_int(param->read.conn_id), - mp_obj_new_int(param->read.trans_id), - event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp) ? mp_const_true : mp_const_false }; CRIT_BEGIN(); - mp_obj_list_append(callback_queue, mp_obj_new_list(MP_ARRAY_SIZE(args), args)); + mp_obj_list_append(callback_queue, args); CRIT_END(); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_data_handler_obj), MP_OBJ_NULL); - - - NETWORK_BLUETOOTH_DEBUG_PRINTF("data pushed\n"); - } break; @@ -956,7 +985,8 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m mp_printf(print, "Bluetooth(params=())", self); #define NETWORK_BLUETOOTH_LF "\n" NETWORK_BLUETOOTH_DEBUG_PRINTF( - "Bluetooth(params = (" + "Bluetooth(conn_id = %04X, connected = %s" + ", params = (" "adv_int_min = %u, " NETWORK_BLUETOOTH_LF "adv_int_max = %u, " NETWORK_BLUETOOTH_LF "adv_type = %u, " NETWORK_BLUETOOTH_LF @@ -967,6 +997,8 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m "adv_filter_policy = %u" NETWORK_BLUETOOTH_LF ")" , + self->conn_id, + self->connected ? "True" : "False", (unsigned int)(self->params.adv_int_min / 1.6), (unsigned int)(self->params.adv_int_max / 1.6), self->params.adv_type, @@ -1506,7 +1538,6 @@ STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); - // char attribute handler STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) self_in; From ce8d26a811323051920ce239d698c7a44f798774 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 26 Apr 2017 14:57:18 -0700 Subject: [PATCH 33/98] esp32/Makefile: added GATTC headers/objects --- esp32/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/esp32/Makefile b/esp32/Makefile index cc8d1032e..ee472ec65 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -305,6 +305,7 @@ ESPIDF_BLUETOOTH_O = $(addprefix $(ESPCOMP)/bt/,\ bluedroid/api/esp_bt_device.o \ bluedroid/api/esp_bt_main.o \ bluedroid/api/esp_gap_ble_api.o \ + bluedroid/api/esp_gattc_api.o \ bluedroid/api/esp_gatts_api.o \ bluedroid/bta/dm/bta_dm_act.o \ bluedroid/bta/dm/bta_dm_api.o \ From 7773bdf2ab88fa5d236950200f9f48d5509d18ee Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 26 Apr 2017 14:58:08 -0700 Subject: [PATCH 34/98] esp32/network_bluetooth.c: Updated event debug, added gattc scanning It just dumps logs of scan results; I'm getting weird stuff from the IDF somtimes. Needs work --- esp32/network_bluetooth.c | 745 ++++++++++++++++++++++++++++++++++---- 1 file changed, 668 insertions(+), 77 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index edbfcb6ea..15c547c4a 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -44,6 +44,7 @@ #include "esp_gap_ble_api.h" #include "esp_bt_main.h" #include "esp_gatts_api.h" +#include "esp_gattc_api.h" #define HCI_GRP_HOST_CONT_BASEBAND_CMDS 0x03 #define HCI_GRP_BLE_CMDS 0x08 @@ -51,8 +52,7 @@ #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -#define MAKE_OPCODE(OGF, OCF) (((OGF) << 10) | (OCF)) -#define MAKE_OPCODE_BYTES(OGF, OCF) { (MAKE_OPCODE(OGF, OCF) & 0xff), (MAKE_OPCODE(OGF, OCF) >> 8) } +#define EVENT_DEBUG #define UUID_LEN 16 @@ -294,45 +294,13 @@ STATIC bool check_locals_dict(mp_obj_t self, qstr attr, mp_obj_t *dest) { return false; } - -STATIC void gatts_event_dump( - esp_gatts_cb_event_t event, - esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t *param) { - - const char * event_names[] = { - "REG", - "READ", - "WRITE", - "EXEC_WRITE", - "MTU", - "CONF", - "UNREG", - "CREATE", - "ADD_INCL_SRVC", - "ADD_CHAR", - "ADD_CHAR_DESCR", - "DELETE", - "START", - "STOP", - "CONNECT", - "DISCONNECT", - "OPEN", - "CANCEL_OPEN", - "CLOSE", - "LISTEN", - "CONGEST", - "RESPONSE", - "CREAT_ATTR_TAB", - "SET_ATTR_VAL", - }; +#ifdef EVENT_DEBUG typedef struct { uint8_t id; const char * name; - } status_name_t; - - const status_name_t status_names[] = { + } gatt_status_name_t; +STATIC const gatt_status_name_t gatt_status_names[] = { {0x00, "OK"}, {0x01, "INVALID_HANDLE"}, {0x02, "READ_NOT_PERMIT"}, @@ -376,22 +344,13 @@ STATIC void gatts_event_dump( {0x00, NULL}, }; - NETWORK_BLUETOOTH_DEBUG_PRINTF( - "network_bluetooth_gatts_event_handler(" - "event = %02X / %s" - ", if = %02X", - event, event_names[event], gatts_if - ); - - NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); - #define PRINT_STATUS(STATUS) { \ bool found = false; \ NETWORK_BLUETOOTH_DEBUG_PRINTF("status = %02X / ", (STATUS)); \ - for(int i = 0; status_names[i].name != NULL; i++) { \ - if (status_names[i].id == (STATUS)) { \ + for(int i = 0; gatt_status_names[i].name != NULL; i++) { \ + if (gatt_status_names[i].id == (STATUS)) { \ found = true; \ - NETWORK_BLUETOOTH_DEBUG_PRINTF("%s", status_names[i].name); \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("%s", gatt_status_names[i].name); \ break; \ } \ } \ @@ -400,6 +359,472 @@ STATIC void gatts_event_dump( } \ } + +STATIC void gattc_event_dump( + esp_gattc_cb_event_t event, + esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) { + const char * event_names[] = { + "REG", + "UNREG", + "OPEN", + "READ_CHAR", + "WRITE_CHAR", + "CLOSE", + "SEARCH_CMPL", + "SEARCH_RES", + "READ_DESCR", + "WRITE_DESCR", + "NOTIFY", + "PREP_WRITE", + "EXEC", + "ACL", + "CANCEL_OPEN", + "SRVC_CHG", + "ENC_CMPL_CB", + "CFG_MTU", + "ADV_DATA", + "MULT_ADV_ENB", + "MULT_ADV_UPD", + "MULT_ADV_DATA", + "MULT_ADV_DIS", + "CONGEST", + "BTH_SCAN_ENB", + "BTH_SCAN_CFG", + "BTH_SCAN_RD", + "BTH_SCAN_THR", + "BTH_SCAN_PARAM", + "BTH_SCAN_DIS", + "SCAN_FLT_CFG", + "SCAN_FLT_PARAM", + "SCAN_FLT_STATUS", + "ADV_VSC", + "GET_CHAR", + "GET_DESCR", + "GET_INCL_SRVC", + "REG_FOR_NOTIFY", + "UNREG_FOR_NOTIFY" + }; + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "network_bluetooth_gattc_event_handler(" + "event = %02X / %s" + ", if = %02X", + event, event_names[event], gattc_if + ); + + NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); + + switch(event) { + case ESP_GATTC_REG_EVT: + { + PRINT_STATUS(param->reg.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", app_id = %04X", + param->reg.app_id + ); + } + break; + + case ESP_GATTC_OPEN_EVT: + { + PRINT_STATUS(param->open.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X" + ", mtu = %04X", + param->open.conn_id, + param->open.remote_bda[0], + param->open.remote_bda[1], + param->open.remote_bda[2], + param->open.remote_bda[3], + param->open.remote_bda[4], + param->open.remote_bda[5], + param->open.mtu); + } + break; + + case ESP_GATTC_CLOSE_EVT: + { + PRINT_STATUS(param->close.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X" + ", reason = ", + param->close.conn_id, + param->close.remote_bda[0], + param->close.remote_bda[1], + param->close.remote_bda[2], + param->close.remote_bda[3], + param->close.remote_bda[4], + param->close.remote_bda[5]); + switch(param->close.reason) { + case ESP_GATT_CONN_UNKNOWN: + NETWORK_BLUETOOTH_DEBUG_PRINTF("UNKNOWN"); + break; + case ESP_GATT_CONN_L2C_FAILURE: + NETWORK_BLUETOOTH_DEBUG_PRINTF("L2C_FAILURE"); + break; + case ESP_GATT_CONN_TIMEOUT: + NETWORK_BLUETOOTH_DEBUG_PRINTF("TIMEOUT"); + break; + case ESP_GATT_CONN_TERMINATE_PEER_USER: + NETWORK_BLUETOOTH_DEBUG_PRINTF("TERMINATE_PEER_USER"); + break; + case ESP_GATT_CONN_TERMINATE_LOCAL_HOST: + NETWORK_BLUETOOTH_DEBUG_PRINTF("TERMINATE_LOCAL_HOST"); + break; + case ESP_GATT_CONN_FAIL_ESTABLISH: + NETWORK_BLUETOOTH_DEBUG_PRINTF("FAIL_ESTABLISH"); + break; + case ESP_GATT_CONN_LMP_TIMEOUT: + NETWORK_BLUETOOTH_DEBUG_PRINTF("LMP_TIMEOUT"); + break; + case ESP_GATT_CONN_CONN_CANCEL: + NETWORK_BLUETOOTH_DEBUG_PRINTF("CONN_CANCEL"); + break; + case ESP_GATT_CONN_NONE: + NETWORK_BLUETOOTH_DEBUG_PRINTF("NONE"); + break; + + } + } + break; + + case ESP_GATTC_CFG_MTU_EVT: + { + PRINT_STATUS(param->open.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", mtu = %04X", + param->cfg_mtu.conn_id, + param->cfg_mtu.mtu); + } + break; + + case ESP_GATTC_SEARCH_CMPL_EVT: + { + PRINT_STATUS(param->search_cmpl.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X", + param->search_cmpl.conn_id); + } + break; + + case ESP_GATTC_SEARCH_RES_EVT: + { + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X", + param->search_res.conn_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->search_res.srvc_id.id.uuid.uuid, param->search_res.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->search_res.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->search_res.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + } + break; + + case ESP_GATTC_READ_CHAR_EVT: + case ESP_GATTC_READ_DESCR_EVT: + { + PRINT_STATUS(param->read.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X", param->read.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->read.srvc_id.id.uuid.uuid, param->read.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->read.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->read.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->read.char_id.uuid.uuid, param->read.char_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->read.char_id.inst_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->read.descr_id.uuid.uuid, param->read.descr_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->read.descr_id.inst_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", value = ("); + dumpBuf(param->read.value, param->read.value_len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", value_len = %d " + ", value_type = %X", + param->read.value_len, + param->read.value_type); + } + break; + + case ESP_GATTC_WRITE_CHAR_EVT: + case ESP_GATTC_PREP_WRITE_EVT: + case ESP_GATTC_WRITE_DESCR_EVT: + { + PRINT_STATUS(param->write.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF("conn_id = %04X", param->read.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->write.srvc_id.id.uuid.uuid, param->write.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->write.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->write.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->write.char_id.uuid.uuid, param->write.char_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->write.char_id.inst_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->write.descr_id.uuid.uuid, param->write.descr_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->write.descr_id.inst_id); + } + break; + + case ESP_GATTC_EXEC_EVT: + { + PRINT_STATUS(param->exec_cmpl.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF("conn_id = %04X", param->exec_cmpl.conn_id); + } + break; + + case ESP_GATTC_NOTIFY_EVT: + { + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->notify.conn_id, + param->notify.remote_bda[0], + param->notify.remote_bda[1], + param->notify.remote_bda[2], + param->notify.remote_bda[3], + param->notify.remote_bda[4], + param->notify.remote_bda[5]); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->notify.srvc_id.id.uuid.uuid, param->notify.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->notify.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->notify.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->notify.char_id.uuid.uuid, param->notify.char_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->notify.char_id.inst_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->notify.descr_id.uuid.uuid, param->notify.descr_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->notify.descr_id.inst_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", value = ("); + dumpBuf(param->notify.value, param->notify.value_len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", value_len = %d " + ", %s", + param->notify.value_len, + param->notify.is_notify ? "NOTIFY" : "INDICATE"); + + } + break; + + + case ESP_GATTC_SRVC_CHG_EVT: + { + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->srvc_chg.remote_bda[0], + param->srvc_chg.remote_bda[1], + param->srvc_chg.remote_bda[2], + param->srvc_chg.remote_bda[3], + param->srvc_chg.remote_bda[4], + param->srvc_chg.remote_bda[5]); + + } + break; + + case ESP_GATTC_CONGEST_EVT: + { + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "conn_id = %04X, %s CONGESTED", + param->congest.conn_id, + param->congest.congested ? "" : "NOT"); + } + break; + + case ESP_GATTC_GET_CHAR_EVT: + { + PRINT_STATUS(param->get_char.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X", param->get_char.conn_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->get_char.srvc_id.id.uuid.uuid, param->get_char.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_char.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_char.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->get_char.char_id.uuid.uuid, param->get_char.char_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_char.char_id.inst_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_props = "); + const char * char_props[] = { "BROADCAST", "READ", "WRITE_NR", "WRITE", "NOTIFY", "INDICATE", "AUTH", "EXT_PROP" }; + bool printed = false; + for(int i = 0; i < 7; i ++) { + if (param->get_char.char_prop & (1<get_descr.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X", param->get_descr.conn_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->get_descr.srvc_id.id.uuid.uuid, param->get_descr.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_descr.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_descr.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->get_descr.char_id.uuid.uuid, param->get_descr.char_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_descr.char_id.inst_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->get_descr.descr_id.uuid.uuid, param->get_descr.descr_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_descr.descr_id.inst_id); + } + break; + + case ESP_GATTC_GET_INCL_SRVC_EVT: + { + PRINT_STATUS(param->get_incl_srvc.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X", param->get_incl_srvc.conn_id); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->get_incl_srvc.srvc_id.id.uuid.uuid, param->get_incl_srvc.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_incl_srvc.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", incl_srvc_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->get_incl_srvc.srvc_id.id.uuid.uuid, param->get_incl_srvc.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_incl_srvc.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + } + break; + + case ESP_GATTC_REG_FOR_NOTIFY_EVT: + { + PRINT_STATUS(param->reg_for_notify.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->reg_for_notify.srvc_id.id.uuid.uuid, param->reg_for_notify.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->reg_for_notify.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->reg_for_notify.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->reg_for_notify.char_id.uuid.uuid, param->reg_for_notify.char_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->reg_for_notify.char_id.inst_id); + } + break; + + case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: + { + PRINT_STATUS(param->unreg_for_notify.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->unreg_for_notify.srvc_id.id.uuid.uuid, param->unreg_for_notify.srvc_id.id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->unreg_for_notify.srvc_id.id.inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->unreg_for_notify.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); + + NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); + dumpBuf((uint8_t*)¶m->unreg_for_notify.char_id.uuid.uuid, param->unreg_for_notify.char_id.uuid.len); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->unreg_for_notify.char_id.inst_id); + } + default: + // Rest of events have no printable data + // do nothing, intentionally + break; + } +} + +STATIC void gatts_event_dump( + esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) { + + const char * event_names[] = { + "REG", + "READ", + "WRITE", + "EXEC_WRITE", + "MTU", + "CONF", + "UNREG", + "CREATE", + "ADD_INCL_SRVC", + "ADD_CHAR", + "ADD_CHAR_DESCR", + "DELETE", + "START", + "STOP", + "CONNECT", + "DISCONNECT", + "OPEN", + "CANCEL_OPEN", + "CLOSE", + "LISTEN", + "CONGEST", + "RESPONSE", + "CREAT_ATTR_TAB", + "SET_ATTR_VAL", + }; + + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "network_bluetooth_gatts_event_handler(" + "event = %02X / %s" + ", if = %02X", + event, event_names[event], gatts_if + ); + + NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); + switch(event) { case ESP_GATTS_REG_EVT: { @@ -526,7 +951,6 @@ STATIC void gatts_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->create.service_id.id.inst_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->create.service_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); - } break; @@ -686,7 +1110,143 @@ STATIC void gatts_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); } -STATIC mp_obj_t network_bluetooth_callback_data_handler (mp_obj_t arg) { +STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { + const char * event_names[] = { + "ADV_DATA_SET_COMPLETE", + "SCAN_RSP_DATA_SET_COMPLETE", + "SCAN_PARAM_SET_COMPLETE", + "SCAN_RESULT", + "ADV_DATA_RAW_SET_COMPLETE", + "SCAN_RSP_DATA_RAW_SET_COMPLETE", + "ADV_START_COMPLETE", + "SCAN_START_COMPLETE", + "AUTH_CMPL", + "KEY", + "SEC_REQ", + "PASSKEY_NOTIF", + "PASSKEY_REQ", + "OOB_REQ", + "LOCAL_IR", + "LOCAL_ER", + "NC_REQ", + "ADV_STOP_COMPLETE", + "SCAN_STOP_COMPLETE"}; + + + + NETWORK_BLUETOOTH_DEBUG_PRINTF(" in gap_event_dump\n"); // FIXME + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_gap_event_handler(event = %02X / %s", event, event_names[event]); + NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF( "\n"); // FIXME + switch(event) { + + case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT: + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: + { + PRINT_STATUS(param->adv_data_cmpl.status); + } + break; + + case ESP_GAP_BLE_SCAN_RESULT_EVT: + { + const char * search_events[7] = { + "INQ_RES_EVT", + "INQ_CMPL_EVT", + "DISC_RES_EVT", + "DISC_BLE_RES_EVT", + "DISC_CMPL_EVT", + "DI_DISC_CMPL_EVT", + "SEARCH_CANCEL_CMPL_EVT" + }; + + const char * dev_types[] = { "", "BREDR", "BLE", "DUMO" }; + const char * addr_types[] = { "PUBLIC", "RANDOM", "RPA_PUBLIC", "RPA_RANDOM" }; + + NETWORK_BLUETOOTH_DEBUG_PRINTF(" EXTRAFIXME %d %d %d\n", + param->scan_rst.search_evt, + param->scan_rst.dev_type, + param->scan_rst.ble_addr_type); + + + if ( + param->scan_rst.search_evt <= 6 && + param->scan_rst.dev_type <= 3 && + param->scan_rst.ble_addr_type <=3 ) { + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "search_evt = %s" + ", dev_type = %s" + ", ble_addr_type = %s" + ", rssi = %d" , + search_events[param->scan_rst.search_evt], + dev_types[param->scan_rst.dev_type], + addr_types[param->scan_rst.ble_addr_type], + param->scan_rst.rssi + + ); + NETWORK_BLUETOOTH_DEBUG_PRINTF( "\n"); // FIXME + } + + if (param->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { + + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", adv_data_len = %u" + ", scan_rsp_len = %u" , + param->scan_rst.bda[0], + param->scan_rst.bda[1], + param->scan_rst.bda[2], + param->scan_rst.bda[3], + param->scan_rst.bda[4], + param->scan_rst.bda[5], + param->scan_rst.adv_data_len, + param->scan_rst.scan_rsp_len); + + NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); // FIXME + + NETWORK_BLUETOOTH_DEBUG_PRINTF("before esp_ble_resolve_adv_data\n"); // FIXME + uint8_t * adv_name; + uint8_t adv_name_len = 0; + adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, + ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); + + NETWORK_BLUETOOTH_DEBUG_PRINTF("after esp_ble_resolve_adv_data\n"); // FIXME + NETWORK_BLUETOOTH_DEBUG_PRINTF(", adv_name = "); + for (int j = 0; j < adv_name_len; j++) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("%c", adv_name[j]); + } + NETWORK_BLUETOOTH_DEBUG_PRINTF("(%d bytes)", adv_name_len); + } + } + break; + + case ESP_GAP_BLE_AUTH_CMPL_EVT: break; + case ESP_GAP_BLE_KEY_EVT: break; + case ESP_GAP_BLE_SEC_REQ_EVT: break; + case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: break; + case ESP_GAP_BLE_PASSKEY_REQ_EVT: break; + case ESP_GAP_BLE_OOB_REQ_EVT: break; + case ESP_GAP_BLE_LOCAL_IR_EVT: break; + case ESP_GAP_BLE_LOCAL_ER_EVT: break; + case ESP_GAP_BLE_NC_REQ_EVT: break; + } + +NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); + +} + + + +#endif // EVENT_DEBUG + +STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); network_bluetooth_char_obj_t *self; @@ -730,12 +1290,12 @@ STATIC mp_obj_t network_bluetooth_callback_data_handler (mp_obj_t arg) { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; self = network_bluetooth_find_item(service->chars, NULL, handle, NETWORK_BLUETOOTH_FIND_CHAR); if (self != MP_OBJ_NULL) { - goto NETWORK_BLUETOOTH_CALLBACK_DATA_HANDLER_CHAR_FOUND; + goto NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND; } } continue; -NETWORK_BLUETOOTH_CALLBACK_DATA_HANDLER_CHAR_FOUND: +NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND: { mp_obj_t value = event == ESP_GATTS_READ_EVT ? self->value : write_value; @@ -792,7 +1352,16 @@ STATIC mp_obj_t network_bluetooth_callback_data_handler (mp_obj_t arg) { CRIT_END(); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_callback_data_handler_obj, network_bluetooth_callback_data_handler); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_callback_queue_handler_obj, network_bluetooth_callback_queue_handler); + +STATIC void network_bluetooth_gattc_event_handler( + esp_gattc_cb_event_t event, + esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) { +#ifdef EVENT_DEBUG + gattc_event_dump(event, gattc_if, param); +#endif +} STATIC void network_bluetooth_gatts_event_handler( esp_gatts_cb_event_t event, @@ -801,7 +1370,9 @@ STATIC void network_bluetooth_gatts_event_handler( network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); +#ifdef EVENT_DEBUG gatts_event_dump(event, gatts_if, param); +#endif switch (event) { case ESP_GATTS_REG_EVT: @@ -897,7 +1468,7 @@ STATIC void network_bluetooth_gatts_event_handler( CRIT_BEGIN(); mp_obj_list_append(callback_queue, args); CRIT_END(); - mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_data_handler_obj), MP_OBJ_NULL); + mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } break; @@ -916,36 +1487,19 @@ STATIC void network_bluetooth_gap_event_handler( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("entering network_bluetooth_gap_event_handler()\n"); +#ifdef EVENT_DEBUG + gap_event_dump(event, param); +#endif + network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); switch (event) { case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: - NETWORK_BLUETOOTH_DEBUG_PRINTF( "adv data setting complete\n"); if (self->advertising) { - NETWORK_BLUETOOTH_DEBUG_PRINTF( "calling esp_ble_gap_start_advertising()\n"); esp_ble_gap_start_advertising(&self->params); } break; - case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: - //advertising start complete event to indicate advertising start successfully or failed - if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { - NETWORK_BLUETOOTH_DEBUG_PRINTF( "Advertising start failed\n"); - } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Advertising start successful\n"); - } - - break; - case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: - if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Advertising stop failed\n"); - } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Advertising stop successful\n"); - } - - break; - default: - break; + default: break; } } @@ -1099,6 +1653,7 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { } esp_ble_gatts_register_callback(network_bluetooth_gatts_event_handler); + esp_ble_gattc_register_callback(network_bluetooth_gattc_event_handler); esp_ble_gap_register_callback(network_bluetooth_gap_event_handler); // FIXME, this is hardcoded @@ -1111,6 +1666,16 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gatts_app_register ERROR\n"); break; } + // FIXME, this is hardcoded + switch(esp_ble_gattc_app_register(1)) { + case ESP_OK: + NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gattc_app_register success\n"); + break; + + default: + NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gattc_app_register ERROR\n"); + break; + } self->state = NETWORK_BLUETOOTH_STATE_INIT; } else { @@ -1387,6 +1952,30 @@ STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* } +STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_arg) { + (void)self_in; + mp_int_t timeout = mp_obj_get_int(timeout_arg); + + static esp_ble_scan_params_t params = { + .scan_type = BLE_SCAN_TYPE_ACTIVE, + .own_addr_type = ESP_PUBLIC_ADDR, + .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, + .scan_interval = 0x50, + .scan_window = 0x30 + }; + assert(esp_ble_gap_set_scan_params(¶ms) == ESP_OK); + assert(esp_ble_gap_start_scanning(timeout) == ESP_OK); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_scan_start_obj, network_bluetooth_scan_start); + +STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { + (void)self_in; + assert(esp_ble_gap_stop_scanning() == ESP_OK); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_scan_stop_obj, network_bluetooth_scan_stop); + STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); @@ -1615,6 +2204,8 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&network_bluetooth_scan_stop_obj) }, // class constants From 7bb0328827a72485ad0027c39a20197104d552b2 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 27 Apr 2017 14:20:35 -0700 Subject: [PATCH 35/98] esp32/network_bluetooth.c: Added callbacks for scanning Very broken right now; getting crashes in the IDF handler. --- esp32/network_bluetooth.c | 353 +++++++++++++++++++++++--------------- 1 file changed, 216 insertions(+), 137 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 15c547c4a..12cb48573 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -1,5 +1,4 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ +/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * @@ -46,8 +45,6 @@ #include "esp_gatts_api.h" #include "esp_gattc_api.h" -#define HCI_GRP_HOST_CONT_BASEBAND_CMDS 0x03 -#define HCI_GRP_BLE_CMDS 0x08 #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -61,14 +58,42 @@ const mp_obj_type_t network_bluetooth_type; const mp_obj_type_t network_bluetooth_service_type; const mp_obj_type_t network_bluetooth_characteristic_type; -// FIXME, this is probably too high -#define MUTEX_WAIT_MS 3000 +SemaphoreHandle_t callback_queue_mut; +SemaphoreHandle_t find_item_mut; -SemaphoreHandle_t mut; mp_obj_t callback_queue; // implemented as a list -#define CRIT_BEGIN() xSemaphoreTakeRecursive(mut, MUTEX_WAIT_MS / portTICK_PERIOD_MS) -#define CRIT_END() xSemaphoreGiveRecursive(mut) +#define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) + +#define CALLBACK_QUEUE_BEGIN() \ + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> cbQ Take\n"); \ + assert(xSemaphoreTake(callback_queue_mut, portMAX_DELAY) == pdTRUE); \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< cbQ Take\n"); + +#define CALLBACK_QUEUE_END() \ + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< cbQ Give\n"); \ + xSemaphoreGive(callback_queue_mut); \ + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> cbQ Give\n"); + +#define FIND_ITEM_BEGIN() assert(xSemaphoreTake(find_item_mut, portMAX_DELAY) == pdTRUE) +#define FIND_ITEM_END() xSemaphoreGive(find_item_mut) + +// CONSTANTS + +typedef enum { + // GAP / GATTC events + NETWORK_BLUETOOTH_CONNECT, + NETWORK_BLUETOOTH_DISCONNECT, + NETWORK_BLUETOOTH_SCAN_DATA, + NETWORK_BLUETOOTH_SCAN_CMPL, + NETWORK_BLUETOOTH_OPEN_RESULT, + + // characteristic events + NETWORK_BLUETOOTH_READ, + NETWORK_BLUETOOTH_WRITE, +} network_bluetooth_event_t; + + // "Service" typedef struct { @@ -81,8 +106,7 @@ typedef struct { bool started; bool closed; -} network_bluetooth_service_obj_t; - +} network_bluetooth_service_obj_t; // "Char" @@ -111,13 +135,15 @@ typedef struct { NETWORK_BLUETOOTH_STATE_INIT } state; bool advertising; - + bool scanning; bool connected; + uint16_t conn_id; esp_gatt_if_t interface; - esp_ble_adv_params_t params; - esp_ble_adv_data_t data; + + esp_ble_adv_params_t adv_params; + esp_ble_adv_data_t adv_data; mp_obj_t services; // implemented as a list @@ -134,7 +160,7 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .connected = false, .conn_id = 0, .interface = ESP_GATT_IF_NONE, - .params = { + .adv_params = { .adv_int_min = 1280 * 1.6, .adv_int_max = 1280 * 1.6, .adv_type = ADV_TYPE_IND, @@ -144,7 +170,7 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .channel_map = ADV_CHNL_ALL, .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, }, - .data = { + .adv_data = { .set_scan_rsp = false, .include_name = false, .include_txpower = false, @@ -166,15 +192,6 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { }; -#define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) -#define CREATE_HCI_HOST_COMMAND(cmd)\ - size_t param_size = hci_commands[(cmd)].param_size;\ - size_t buf_size = 1 + sizeof(hci_cmd_def_t) + param_size;\ - uint8_t buf[buf_size];\ - uint8_t *param = buf + buf_size - param_size;\ - memset(buf, 0, buf_size);\ - buf[0] = H4_TYPE_COMMAND;\ - memcpy(buf + 1, &hci_commands[(cmd)], sizeof(hci_cmd_def_t)); STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { return &network_bluetooth_singleton; @@ -246,7 +263,7 @@ typedef enum { STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle, item_type_t kind) { - CRIT_BEGIN(); + FIND_ITEM_BEGIN(); mp_obj_t ret = MP_OBJ_NULL; size_t len; mp_obj_t *items; @@ -275,7 +292,7 @@ STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, } } NETWORK_BLUETOOTH_FIND_ITEM_END: - CRIT_END(); + FIND_ITEM_END(); return ret; } @@ -1132,12 +1149,8 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t "ADV_STOP_COMPLETE", "SCAN_STOP_COMPLETE"}; - - - NETWORK_BLUETOOTH_DEBUG_PRINTF(" in gap_event_dump\n"); // FIXME NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_gap_event_handler(event = %02X / %s", event, event_names[event]); NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); - NETWORK_BLUETOOTH_DEBUG_PRINTF( "\n"); // FIXME switch(event) { case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: @@ -1169,29 +1182,22 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t const char * dev_types[] = { "", "BREDR", "BLE", "DUMO" }; const char * addr_types[] = { "PUBLIC", "RANDOM", "RPA_PUBLIC", "RPA_RANDOM" }; - NETWORK_BLUETOOTH_DEBUG_PRINTF(" EXTRAFIXME %d %d %d\n", - param->scan_rst.search_evt, - param->scan_rst.dev_type, - param->scan_rst.ble_addr_type); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "search_evt = %s", + search_events[param->scan_rst.search_evt]); - if ( - param->scan_rst.search_evt <= 6 && - param->scan_rst.dev_type <= 3 && - param->scan_rst.ble_addr_type <=3 ) { + if ( param->scan_rst.dev_type <= 3 && param->scan_rst.ble_addr_type <=3 ) { NETWORK_BLUETOOTH_DEBUG_PRINTF( - "search_evt = %s" ", dev_type = %s" ", ble_addr_type = %s" ", rssi = %d" , - search_events[param->scan_rst.search_evt], dev_types[param->scan_rst.dev_type], addr_types[param->scan_rst.ble_addr_type], param->scan_rst.rssi ); - NETWORK_BLUETOOTH_DEBUG_PRINTF( "\n"); // FIXME } if (param->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { @@ -1209,15 +1215,12 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t param->scan_rst.adv_data_len, param->scan_rst.scan_rsp_len); - NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); // FIXME - NETWORK_BLUETOOTH_DEBUG_PRINTF("before esp_ble_resolve_adv_data\n"); // FIXME uint8_t * adv_name; uint8_t adv_name_len = 0; adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); - NETWORK_BLUETOOTH_DEBUG_PRINTF("after esp_ble_resolve_adv_data\n"); // FIXME NETWORK_BLUETOOTH_DEBUG_PRINTF(", adv_name = "); for (int j = 0; j < adv_name_len; j++) { NETWORK_BLUETOOTH_DEBUG_PRINTF("%c", adv_name[j]); @@ -1250,8 +1253,6 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); network_bluetooth_char_obj_t *self; - NETWORK_BLUETOOTH_DEBUG_PRINTF("In data handler\n"); - size_t queue_len; mp_obj_t* queue_items; @@ -1263,19 +1264,21 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { mp_obj_t *service_items; - CRIT_BEGIN(); + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> handler\n"); + CALLBACK_QUEUE_BEGIN(); + + //NETWORK_BLUETOOTH_DEBUG_PRINTF("Before get array\n"); mp_obj_get_array(callback_queue, &queue_len, &queue_items); - NETWORK_BLUETOOTH_DEBUG_PRINTF("Found %u queue items\n", queue_len); + //NETWORK_BLUETOOTH_DEBUG_PRINTF("Found %u queue items\n", queue_len); for(int i = 0; i < queue_len; i++) { mp_obj_get_array(queue_items[i], &len, &items); - esp_gatts_cb_event_t event = mp_obj_get_int(items[0]); + network_bluetooth_event_t event = mp_obj_get_int(items[0]); switch (event) { - case ESP_GATTS_READ_EVT: - case ESP_GATTS_WRITE_EVT: - + case NETWORK_BLUETOOTH_READ: + case NETWORK_BLUETOOTH_WRITE: { assert(len == 6); uint16_t handle = mp_obj_get_int(items[1]); @@ -1298,11 +1301,11 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND: { - mp_obj_t value = event == ESP_GATTS_READ_EVT ? self->value : write_value; + mp_obj_t value = event == NETWORK_BLUETOOTH_READ ? self->value : write_value; if (self->callback != mp_const_none) { mp_obj_t args[] = {self, items[0], value, self->callback_userdata }; value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); - } else if (event == ESP_GATTS_WRITE_EVT) { + } else if (event == NETWORK_BLUETOOTH_WRITE) { self->value = value; } @@ -1329,8 +1332,8 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { } break; - case ESP_GATTS_CONNECT_EVT: - case ESP_GATTS_DISCONNECT_EVT: + case NETWORK_BLUETOOTH_CONNECT: + case NETWORK_BLUETOOTH_DISCONNECT: { assert(len == 2); if (bluetooth->callback != mp_const_none) { @@ -1340,8 +1343,23 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); } break; - } + case NETWORK_BLUETOOTH_SCAN_CMPL: + case NETWORK_BLUETOOTH_SCAN_DATA: + if (bluetooth->callback != mp_const_none) { + mp_obj_t args[] = { + bluetooth, + items[0], + + // FIXME! + //event == NETWORK_BLUETOOTH_SCAN_DATA ? mp_obj_new_tuple(2, items + 1) : mp_const_none, + mp_const_none, + + bluetooth->callback_userdata }; + mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); + } + break; + default: // do nothing, intentionally break; @@ -1349,7 +1367,8 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { } mp_obj_list_set_len(callback_queue, 0); - CRIT_END(); + CALLBACK_QUEUE_END(); + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< handler\n"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_callback_queue_handler_obj, network_bluetooth_callback_queue_handler); @@ -1359,7 +1378,7 @@ STATIC void network_bluetooth_gattc_event_handler( esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) { #ifdef EVENT_DEBUG - gattc_event_dump(event, gattc_if, param); + gattc_event_dump(event, gattc_if, param); #endif } @@ -1444,9 +1463,9 @@ STATIC void network_bluetooth_gatts_event_handler( // int, bytearray mp_obj_t args = MP_OBJ_NULL; - if (event == ESP_GATTS_REG_EVT || event == ESP_GATTS_WRITE_EVT) { + if (event == ESP_GATTS_READ_EVT || event == ESP_GATTS_WRITE_EVT) { mp_obj_t rw_args[] = { - MP_OBJ_NEW_SMALL_INT(event), + MP_OBJ_NEW_SMALL_INT(event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE ), MP_OBJ_NEW_SMALL_INT(param->read.handle), event == ESP_GATTS_WRITE_EVT ? mp_obj_new_bytearray(param->write.len, param->write.value) : MP_OBJ_NULL, mp_obj_new_int(param->read.conn_id), @@ -1456,7 +1475,7 @@ STATIC void network_bluetooth_gatts_event_handler( } else if (event == ESP_GATTS_CONNECT_EVT || event == ESP_GATTS_DISCONNECT_EVT) { mp_obj_t cd_args [] = { - MP_OBJ_NEW_SMALL_INT(event), + MP_OBJ_NEW_SMALL_INT(event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT), mp_obj_new_bytearray(sizeof(param->connect.remote_bda), ¶m->connect.remote_bda), }; args = mp_obj_new_list(MP_ARRAY_SIZE(cd_args), cd_args); bluetooth->conn_id = param->connect.conn_id; @@ -1464,10 +1483,11 @@ STATIC void network_bluetooth_gatts_event_handler( } - - CRIT_BEGIN(); + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gatts append\n"); + CALLBACK_QUEUE_BEGIN(); mp_obj_list_append(callback_queue, args); - CRIT_END(); + CALLBACK_QUEUE_END(); + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gatts append\n"); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } break; @@ -1488,15 +1508,69 @@ STATIC void network_bluetooth_gap_event_handler( esp_ble_gap_cb_param_t *param) { #ifdef EVENT_DEBUG - gap_event_dump(event, param); + // gap_event_dump(event, param); #endif - network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); switch (event) { + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: + bluetooth-> scanning = true; + break; + + case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: + // doesn't seem we ever get this, in practice + bluetooth-> scanning = false; + break; + + case ESP_GAP_BLE_SCAN_RESULT_EVT: + { + + mp_obj_t args = MP_OBJ_NULL; + switch(param->scan_rst.search_evt) { + case ESP_GAP_SEARCH_INQ_RES_EVT: + { + uint8_t* adv_name; + uint8_t adv_name_len; + adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); + + mp_obj_t res_args[] = { + MP_OBJ_NEW_SMALL_INT(NETWORK_BLUETOOTH_SCAN_DATA), + mp_obj_new_bytearray(sizeof(param->scan_rst.bda), ¶m->scan_rst.bda), + mp_obj_new_str((const char *)adv_name, adv_name_len, false), + }; + args = mp_obj_new_list(MP_ARRAY_SIZE(res_args), res_args); + } + break; + + case ESP_GAP_SEARCH_INQ_CMPL_EVT: // scanning done + { + bluetooth->scanning = false; + mp_obj_t cmpl_args[] = {MP_OBJ_NEW_SMALL_INT(NETWORK_BLUETOOTH_SCAN_CMPL)}; + args = mp_obj_new_list(MP_ARRAY_SIZE(cmpl_args), cmpl_args); + } + break; + + default: + // Do nothing, intentionally + break; + } + + if (args != MP_OBJ_NULL) { + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gap append len: %u\n",((mp_obj_list_t *)callback_queue)->len); + CALLBACK_QUEUE_BEGIN(); + mp_obj_list_append(callback_queue, args); + CALLBACK_QUEUE_END(); + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gap append len: %u\n", ((mp_obj_list_t *)callback_queue)->len); + mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); + } + + } + break; + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: - if (self->advertising) { - esp_ble_gap_start_advertising(&self->params); + if (bluetooth->advertising) { + esp_ble_gap_start_advertising(&bluetooth->adv_params); } break; default: break; @@ -1508,7 +1582,7 @@ STATIC void network_bluetooth_adv_updated() { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_adv_updated()\n"); network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); esp_ble_gap_stop_advertising(); - esp_ble_gap_config_adv_data(&self->data); + esp_ble_gap_config_adv_data(&self->adv_data); // Restart will be handled in network_bluetooth_gap_event_handler @@ -1540,7 +1614,7 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m #define NETWORK_BLUETOOTH_LF "\n" NETWORK_BLUETOOTH_DEBUG_PRINTF( "Bluetooth(conn_id = %04X, connected = %s" - ", params = (" + ", adv_params = (" "adv_int_min = %u, " NETWORK_BLUETOOTH_LF "adv_int_max = %u, " NETWORK_BLUETOOTH_LF "adv_type = %u, " NETWORK_BLUETOOTH_LF @@ -1553,19 +1627,19 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m , self->conn_id, self->connected ? "True" : "False", - (unsigned int)(self->params.adv_int_min / 1.6), - (unsigned int)(self->params.adv_int_max / 1.6), - self->params.adv_type, - self->params.own_addr_type, - self->params.peer_addr[0], - self->params.peer_addr[1], - self->params.peer_addr[2], - self->params.peer_addr[3], - self->params.peer_addr[4], - self->params.peer_addr[5], - self->params.peer_addr_type, - self->params.channel_map, - self->params.adv_filter_policy + (unsigned int)(self->adv_params.adv_int_min / 1.6), + (unsigned int)(self->adv_params.adv_int_max / 1.6), + self->adv_params.adv_type, + self->adv_params.own_addr_type, + self->adv_params.peer_addr[0], + self->adv_params.peer_addr[1], + self->adv_params.peer_addr[2], + self->adv_params.peer_addr[3], + self->adv_params.peer_addr[4], + self->adv_params.peer_addr[5], + self->adv_params.peer_addr_type, + self->adv_params.channel_map, + self->adv_params.adv_filter_policy ); NETWORK_BLUETOOTH_DEBUG_PRINTF( ", data = (" @@ -1579,22 +1653,22 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m "p_manufacturer_data = %s, " NETWORK_BLUETOOTH_LF "service_data_len = %d, " NETWORK_BLUETOOTH_LF "p_service_data = ", - self->data.set_scan_rsp ? "true" : "false", - self->data.include_name ? "true" : "false", - self->data.include_txpower ? "true" : "false", - self->data.min_interval, - self->data.max_interval, - self->data.appearance, - self->data.manufacturer_len, - self->data.p_manufacturer_data ? (const char *)self->data.p_manufacturer_data : "nil", - self->data.service_data_len); - if (self->data.p_service_data != NULL) { - dumpBuf(self->data.p_service_data, self->data.service_data_len); + self->adv_data.set_scan_rsp ? "true" : "false", + self->adv_data.include_name ? "true" : "false", + self->adv_data.include_txpower ? "true" : "false", + self->adv_data.min_interval, + self->adv_data.max_interval, + self->adv_data.appearance, + self->adv_data.manufacturer_len, + self->adv_data.p_manufacturer_data ? (const char *)self->adv_data.p_manufacturer_data : "nil", + self->adv_data.service_data_len); + if (self->adv_data.p_service_data != NULL) { + dumpBuf(self->adv_data.p_service_data, self->adv_data.service_data_len); } else { NETWORK_BLUETOOTH_DEBUG_PRINTF("nil"); } - NETWORK_BLUETOOTH_DEBUG_PRINTF(", " NETWORK_BLUETOOTH_LF "flag = %d" NETWORK_BLUETOOTH_LF , self->data.flag); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", " NETWORK_BLUETOOTH_LF "flag = %d" NETWORK_BLUETOOTH_LF , self->adv_data.flag); NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); @@ -1613,8 +1687,14 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { callback_queue = mp_obj_new_list(0, NULL); } - if (mut == NULL) { - mut = xSemaphoreCreateRecursiveMutex(); + if (callback_queue_mut == NULL) { + //callback_queue_mut = xSemaphoreCreateBinary(); + //find_item_mut = xSemaphoreCreateBinary(); + callback_queue_mut = xSemaphoreCreateMutex(); + find_item_mut = xSemaphoreCreateMutex(); + + xSemaphoreGive(callback_queue_mut); + xSemaphoreGive(find_item_mut); } NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth services pointer: %p", self->services); @@ -1799,42 +1879,42 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po // update esp_ble_adv_params_t if (args[ARG_int_min].u_int != -1) { - self->params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count + self->adv_params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count changed = true; } if (args[ARG_int_max].u_int != -1) { - self->params.adv_int_max = args[ARG_int_max].u_int * 1.6; + self->adv_params.adv_int_max = args[ARG_int_max].u_int * 1.6; changed = true; } if (args[ARG_type].u_int != -1) { - self->params.adv_type = args[ARG_type].u_int; + self->adv_params.adv_type = args[ARG_type].u_int; changed = true; } if (args[ARG_own_addr_type].u_int != -1) { - self->params.own_addr_type = args[ARG_own_addr_type].u_int; + self->adv_params.own_addr_type = args[ARG_own_addr_type].u_int; changed = true; } if (peer_addr_buf.buf != NULL) { - memcpy(self->params.peer_addr, peer_addr_buf.buf, ESP_BD_ADDR_LEN); + memcpy(self->adv_params.peer_addr, peer_addr_buf.buf, ESP_BD_ADDR_LEN); changed = true; } if (args[ARG_peer_addr_type].u_int != -1) { - self->params.peer_addr_type = args[ARG_peer_addr_type].u_int; + self->adv_params.peer_addr_type = args[ARG_peer_addr_type].u_int; changed = true; } if (args[ARG_channel_map].u_int != -1) { - self->params.channel_map = args[ARG_channel_map].u_int; + self->adv_params.channel_map = args[ARG_channel_map].u_int; changed = true; } if (args[ARG_filter_policy].u_int != -1) { - self->params.adv_filter_policy = args[ARG_filter_policy].u_int; + self->adv_params.adv_filter_policy = args[ARG_filter_policy].u_int; changed = true; } @@ -1842,72 +1922,72 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po // if (args[ARG_adv_is_scan_rsp].u_obj != NULL) { - self->data.set_scan_rsp = mp_obj_is_true(args[ARG_adv_is_scan_rsp].u_obj); + self->adv_data.set_scan_rsp = mp_obj_is_true(args[ARG_adv_is_scan_rsp].u_obj); changed = true; } if (unset_adv_dev_name) { esp_ble_gap_set_device_name(""); - self->data.include_name = false; + self->adv_data.include_name = false; } else if (adv_dev_name_buf.buf != NULL) { esp_ble_gap_set_device_name(adv_dev_name_buf.buf); - self->data.include_name = adv_dev_name_buf.len > 0; + self->adv_data.include_name = adv_dev_name_buf.len > 0; changed = true; } if (unset_adv_man_name || adv_man_name_buf.buf != NULL) { - if (self->data.p_manufacturer_data != NULL) { + if (self->adv_data.p_manufacturer_data != NULL) { NETWORK_BLUETOOTH_DEBUG_PRINTF("About to free p_manufacturer_data (2)\n"); - m_free(self->data.p_manufacturer_data); - self->data.p_manufacturer_data = NULL; + m_free(self->adv_data.p_manufacturer_data); + self->adv_data.p_manufacturer_data = NULL; } - self->data.manufacturer_len = adv_man_name_buf.len; + self->adv_data.manufacturer_len = adv_man_name_buf.len; if (adv_man_name_buf.len > 0) { NETWORK_BLUETOOTH_DEBUG_PRINTF("About to call malloc for p_manufacturer_data\n"); - self->data.p_manufacturer_data = m_malloc(adv_man_name_buf.len); - memcpy(self->data.p_manufacturer_data, adv_man_name_buf.buf, adv_man_name_buf.len); + self->adv_data.p_manufacturer_data = m_malloc(adv_man_name_buf.len); + memcpy(self->adv_data.p_manufacturer_data, adv_man_name_buf.buf, adv_man_name_buf.len); } changed = true; } if (args[ARG_adv_inc_txpower].u_obj != NULL) { - self->data.include_txpower = mp_obj_is_true(args[ARG_adv_inc_txpower].u_obj); + self->adv_data.include_txpower = mp_obj_is_true(args[ARG_adv_inc_txpower].u_obj); changed = true; } if (args[ARG_adv_int_min].u_int != -1) { - self->data.min_interval = args[ARG_adv_int_min].u_int; + self->adv_data.min_interval = args[ARG_adv_int_min].u_int; changed = true; } if (args[ARG_adv_int_max].u_int != -1) { - self->data.max_interval = args[ARG_adv_int_max].u_int; + self->adv_data.max_interval = args[ARG_adv_int_max].u_int; changed = true; } if (args[ARG_adv_appearance].u_int != -1) { - self->data.appearance = args[ARG_adv_appearance].u_int; + self->adv_data.appearance = args[ARG_adv_appearance].u_int; changed = true; } if (unset_adv_uuid || adv_uuid_buf.buf != NULL) { - if (self->data.p_service_uuid != NULL) { - m_free(self->data.p_service_uuid ); - self->data.p_service_uuid = NULL; + if (self->adv_data.p_service_uuid != NULL) { + m_free(self->adv_data.p_service_uuid ); + self->adv_data.p_service_uuid = NULL; } - self->data.service_uuid_len = adv_uuid_buf.len; + self->adv_data.service_uuid_len = adv_uuid_buf.len; if (adv_uuid_buf.len > 0) { - self->data.p_service_uuid = m_malloc(adv_uuid_buf.len); - memcpy(self->data.p_service_uuid, adv_uuid_buf.buf, adv_uuid_buf.len); + self->adv_data.p_service_uuid = m_malloc(adv_uuid_buf.len); + memcpy(self->adv_data.p_service_uuid, adv_uuid_buf.buf, adv_uuid_buf.len); } changed = true; } if (args[ARG_adv_flags].u_int != -1) { - self->data.flag = args[ARG_adv_flags].u_int; + self->adv_data.flag = args[ARG_adv_flags].u_int; changed = true; } @@ -1944,7 +2024,6 @@ STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* *callback_userdata = n_args > 2 ? args[2] : mp_const_none; } - NETWORK_BLUETOOTH_DEBUG_PRINTF("Callback ptr is %p\n", callback); mp_obj_t items[2] = {*callback, *callback_userdata}; mp_obj_t tuple = mp_obj_new_tuple(2, items); @@ -2030,9 +2109,9 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ self->service_id.is_primary = mp_obj_is_true(args[ARG_primary].u_obj); self->chars = mp_obj_new_list(0, NULL); - CRIT_BEGIN(); + FIND_ITEM_BEGIN(); mp_obj_list_append(bluetooth->services, MP_OBJ_FROM_PTR(self)); - CRIT_END(); + FIND_ITEM_END(); return MP_OBJ_FROM_PTR(self); } @@ -2170,11 +2249,8 @@ STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t // bluetooth attribute handler STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { network_bluetooth_obj_t* self = (network_bluetooth_obj_t*) self_in; - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_attr\n"); if (!check_locals_dict(self, attr, dest)) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_attr inside switch\n"); - switch(attr) { case MP_QSTR_services: if (dest[0] == MP_OBJ_NULL) { // load @@ -2206,14 +2282,17 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&network_bluetooth_scan_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_scanning), NULL }, // handle by attr // class constants // Callback types - { MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(ESP_GATTS_CONNECT_EVT) }, - { MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(ESP_GATTS_DISCONNECT_EVT) }, - { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(ESP_GATTS_READ_EVT) }, - { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(ESP_GATTS_WRITE_EVT) }, + { MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_CONNECT) }, + { MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_DISCONNECT) }, + { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(NETWORK_BLUETOOTH_READ) }, + { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(NETWORK_BLUETOOTH_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_DATA), MP_ROM_INT(NETWORK_BLUETOOTH_SCAN_DATA) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_CMPL), MP_ROM_INT(NETWORK_BLUETOOTH_SCAN_CMPL) }, // esp_ble_adv_type_t { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, From f608a6edd3ccb51dd0bdea4446804b5e0c815878 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 28 Apr 2017 08:37:28 -0700 Subject: [PATCH 36/98] esp32/network_bluetooth.c: Doing callback as a ring buffer --- esp32/network_bluetooth.c | 357 +++++++++++++++++++++++--------------- 1 file changed, 217 insertions(+), 140 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 12cb48573..378584b73 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -61,7 +61,7 @@ const mp_obj_type_t network_bluetooth_characteristic_type; SemaphoreHandle_t callback_queue_mut; SemaphoreHandle_t find_item_mut; -mp_obj_t callback_queue; // implemented as a list + #define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) @@ -94,6 +94,86 @@ typedef enum { } network_bluetooth_event_t; +typedef struct { + network_bluetooth_event_t event; + union { + struct { + uint16_t conn_id; + esp_bd_addr_t bda; + } connect; + + struct { + uint16_t conn_id; + esp_bd_addr_t bda; + } disconnect; + + struct { + esp_bd_addr_t bda; + uint8_t* adv_data; // Need to free this! + uint8_t adv_data_len; + } scan_data; + + struct { + uint16_t handle; + uint16_t conn_id; + uint32_t trans_id; + bool need_rsp; + } read; + + struct { + uint16_t handle; + uint16_t conn_id; + uint32_t trans_id; + bool need_rsp; + uint8_t* value; + size_t value_len; + } write; + }; + +} network_bluetooth_callback_data_t; + +//mp_obj_t callback_queue; // implemented as a list + + +#define CBQ_CAPACITY 10 +typedef struct { + network_bluetooth_callback_data_t q[CBQ_CAPACITY]; + size_t head; + size_t tail; + size_t count; +} cbq_t; + +cbq_t callback_queue = { + .head = 0, + .tail = 0, + .count = 0 +}; + + +STATIC bool cbq_push (const network_bluetooth_callback_data_t* data) { + if (callback_queue.count == CBQ_CAPACITY) { + return false; + } + callback_queue.q[callback_queue.head++] = *data; + callback_queue.head %= CBQ_CAPACITY; + callback_queue.count++; + return true; +} + +STATIC bool cbq_pop (network_bluetooth_callback_data_t* data) { + if (callback_queue.count == 0) { + return false; + } + *data = callback_queue.q[callback_queue.tail++]; + callback_queue.tail %= CBQ_CAPACITY; + callback_queue.count--; + return true; +} + +STATIC bool cbq_empty() { + return callback_queue.count == 0; +} + // "Service" typedef struct { @@ -136,7 +216,7 @@ typedef struct { } state; bool advertising; bool scanning; - bool connected; + bool gatts_connected; uint16_t conn_id; esp_gatt_if_t interface; @@ -157,7 +237,7 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .base = { &network_bluetooth_type }, .state = NETWORK_BLUETOOTH_STATE_DEINIT, .advertising = false, - .connected = false, + .gatts_connected = false, .conn_id = 0, .interface = ESP_GATT_IF_NONE, .adv_params = { @@ -317,6 +397,7 @@ STATIC bool check_locals_dict(mp_obj_t self, qstr attr, mp_obj_t *dest) { uint8_t id; const char * name; } gatt_status_name_t; + STATIC const gatt_status_name_t gatt_status_names[] = { {0x00, "OK"}, {0x01, "INVALID_HANDLE"}, @@ -1253,122 +1334,108 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); network_bluetooth_char_obj_t *self; - - size_t queue_len; - mp_obj_t* queue_items; - - size_t len; - mp_obj_t *items; - size_t service_len; mp_obj_t *service_items; + network_bluetooth_callback_data_t cbdata; NETWORK_BLUETOOTH_DEBUG_PRINTF(">> handler\n"); CALLBACK_QUEUE_BEGIN(); + if (cbq_empty()) { + return mp_const_none; + } + cbq_pop(&cbdata); + CALLBACK_QUEUE_END(); - //NETWORK_BLUETOOTH_DEBUG_PRINTF("Before get array\n"); - mp_obj_get_array(callback_queue, &queue_len, &queue_items); - //NETWORK_BLUETOOTH_DEBUG_PRINTF("Found %u queue items\n", queue_len); - - for(int i = 0; i < queue_len; i++) { - mp_obj_get_array(queue_items[i], &len, &items); - network_bluetooth_event_t event = mp_obj_get_int(items[0]); - switch (event) { + switch (cbdata.event) { - case NETWORK_BLUETOOTH_READ: - case NETWORK_BLUETOOTH_WRITE: - { - assert(len == 6); - uint16_t handle = mp_obj_get_int(items[1]); - mp_obj_t write_value = items[2]; - uint16_t conn_id = mp_obj_get_int(items[3]); - uint32_t trans_id = mp_obj_get_int(items[4]); - bool need_rsp = mp_obj_is_true(items[5]); - - - mp_obj_get_array(bluetooth->services, &service_len, &service_items); - for(int j = 0; j < service_len; j++) { - network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; - self = network_bluetooth_find_item(service->chars, NULL, handle, NETWORK_BLUETOOTH_FIND_CHAR); - if (self != MP_OBJ_NULL) { - goto NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND; - } + case NETWORK_BLUETOOTH_READ: + case NETWORK_BLUETOOTH_WRITE: + { + /* + assert(len == 6); + uint16_t handle = mp_obj_get_int(items[1]); + mp_obj_t write_value = items[2]; + uint16_t conn_id = mp_obj_get_int(items[3]); + uint32_t trans_id = mp_obj_get_int(items[4]); + bool need_rsp = mp_obj_is_true(items[5]); + */ + + + mp_obj_get_array(bluetooth->services, &service_len, &service_items); + for(int j = 0; j < service_len; j++) { + network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; + self = network_bluetooth_find_item(service->chars, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR); + if (self != MP_OBJ_NULL) { + goto NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND; } - continue; + } + return mp_const_none; NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND: - { - mp_obj_t value = event == NETWORK_BLUETOOTH_READ ? self->value : write_value; - if (self->callback != mp_const_none) { - mp_obj_t args[] = {self, items[0], value, self->callback_userdata }; - value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); - } else if (event == NETWORK_BLUETOOTH_WRITE) { - self->value = value; - } + { + mp_obj_t value = cbdata.event == NETWORK_BLUETOOTH_READ ? self->value : mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value); + if (self->callback != mp_const_none) { + mp_obj_t args[] = {self, MP_OBJ_NEW_SMALL_INT(cbdata.event), value, self->callback_userdata }; + value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); + } else if (cbdata.event == NETWORK_BLUETOOTH_WRITE) { + self->value = value; + } - if (need_rsp) { - esp_gatt_rsp_t rsp; - memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); + if (cbdata.read.need_rsp) { + esp_gatt_rsp_t rsp; + memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); - mp_buffer_info_t buf; - memset(&buf, 0, sizeof(mp_buffer_info_t)); + mp_buffer_info_t buf; + memset(&buf, 0, sizeof(mp_buffer_info_t)); - if(MP_OBJ_IS_STR_OR_BYTES(value)) { - mp_get_buffer(value, &buf, MP_BUFFER_READ); - } + if(MP_OBJ_IS_STR_OR_BYTES(value)) { + mp_get_buffer(value, &buf, MP_BUFFER_READ); + } - size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); + size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); - rsp.attr_value.handle = handle; - rsp.attr_value.len = len; - memcpy(rsp.attr_value.value, buf.buf, len); - esp_ble_gatts_send_response(bluetooth->interface, conn_id, trans_id, ESP_GATT_OK, &rsp); + rsp.attr_value.handle = cbdata.read.handle; + rsp.attr_value.len = len; + memcpy(rsp.attr_value.value, buf.buf, len); + esp_ble_gatts_send_response(bluetooth->interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); - } } } - break; + } + break; - case NETWORK_BLUETOOTH_CONNECT: - case NETWORK_BLUETOOTH_DISCONNECT: - { - assert(len == 2); - if (bluetooth->callback != mp_const_none) { - // items[0] is event - // items[1] is remote address - mp_obj_t args[] = {bluetooth, items[0], items[1], bluetooth->callback_userdata }; - mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); - } - break; - } - case NETWORK_BLUETOOTH_SCAN_CMPL: - case NETWORK_BLUETOOTH_SCAN_DATA: + case NETWORK_BLUETOOTH_CONNECT: + case NETWORK_BLUETOOTH_DISCONNECT: + { if (bluetooth->callback != mp_const_none) { - mp_obj_t args[] = { - bluetooth, - items[0], - - // FIXME! - //event == NETWORK_BLUETOOTH_SCAN_DATA ? mp_obj_new_tuple(2, items + 1) : mp_const_none, - mp_const_none, - - bluetooth->callback_userdata }; + // items[0] is event + // items[1] is remote address + mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.connect.bda), bluetooth->callback_userdata }; mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); } break; + } + case NETWORK_BLUETOOTH_SCAN_CMPL: + case NETWORK_BLUETOOTH_SCAN_DATA: + if (bluetooth->callback != mp_const_none) { + mp_obj_t data = mp_const_none; + if (cbdata.event == NETWORK_BLUETOOTH_SCAN_DATA) { + mp_obj_t scan_data_args[] = {mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.scan_data.bda), mp_obj_new_bytearray(cbdata.scan_data.adv_data_len, cbdata.scan_data.adv_data) } ; + data = mp_obj_new_tuple(2, scan_data_args); + } - default: - // do nothing, intentionally - break; - } - } + mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), data, bluetooth->callback_userdata }; + mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); + } + break; - mp_obj_list_set_len(callback_queue, 0); - CALLBACK_QUEUE_END(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< handler\n"); + default: + // do nothing, intentionally + break; + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_callback_queue_handler_obj, network_bluetooth_callback_queue_handler); @@ -1378,7 +1445,7 @@ STATIC void network_bluetooth_gattc_event_handler( esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) { #ifdef EVENT_DEBUG - gattc_event_dump(event, gattc_if, param); + gattc_event_dump(event, gattc_if, param); #endif } @@ -1449,43 +1516,55 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_CONNECT_EVT: case ESP_GATTS_DISCONNECT_EVT: { + network_bluetooth_callback_data_t cbdata; + if (event == ESP_GATTS_READ_EVT || event == ESP_GATTS_WRITE_EVT) { - // We rely on the fact that the `read` and `write` unions - // are the same for the first few fields, thus all the references to - // param->read + cbdata.event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; + + cbdata.read.handle = param->read.handle; + cbdata.read.conn_id = param->read.conn_id; + cbdata.read.trans_id = param->read.trans_id; + cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); + cbdata.write.value_len = param->write.len; + // FIXME -- is m_malloc gonna work here? + cbdata.write.value = m_malloc(param->write.len); // Returns NULL when len == 0 - // event, handle, write_value, conn_id, trans_id, need_rsp <-- For READ/WRite - // int int MP_OBJ_NULL int int bool - // or bytearray - // - // event, remote adx <-- For connect/disconnect - // -------------------------------------------------------- - // int, bytearray - mp_obj_t args = MP_OBJ_NULL; - if (event == ESP_GATTS_READ_EVT || event == ESP_GATTS_WRITE_EVT) { - mp_obj_t rw_args[] = { - MP_OBJ_NEW_SMALL_INT(event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE ), - MP_OBJ_NEW_SMALL_INT(param->read.handle), - event == ESP_GATTS_WRITE_EVT ? mp_obj_new_bytearray(param->write.len, param->write.value) : MP_OBJ_NULL, - mp_obj_new_int(param->read.conn_id), - mp_obj_new_int(param->read.trans_id), - event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp) ? mp_const_true : mp_const_false}; - args = mp_obj_new_list(MP_ARRAY_SIZE(rw_args), rw_args); + + /* + mp_obj_t rw_args[] = { + MP_OBJ_NEW_SMALL_INT(event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE ), + MP_OBJ_NEW_SMALL_INT(param->read.handle), + event == ESP_GATTS_WRITE_EVT ? mp_obj_new_bytearray(param->write.len, param->write.value) : MP_OBJ_NULL, + mp_obj_new_int(param->read.conn_id), + mp_obj_new_int(param->read.trans_id), + event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp) ? mp_const_true : mp_const_false}; + args = mp_obj_new_list(MP_ARRAY_SIZE(rw_args), rw_args); + */ } else if (event == ESP_GATTS_CONNECT_EVT || event == ESP_GATTS_DISCONNECT_EVT) { - mp_obj_t cd_args [] = { - MP_OBJ_NEW_SMALL_INT(event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT), - mp_obj_new_bytearray(sizeof(param->connect.remote_bda), ¶m->connect.remote_bda), }; - args = mp_obj_new_list(MP_ARRAY_SIZE(cd_args), cd_args); + + + + cbdata.event = event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT; + cbdata.connect.conn_id = param->connect.conn_id; + memcpy(cbdata.connect.bda, param->connect.remote_bda, ESP_BD_ADDR_LEN); bluetooth->conn_id = param->connect.conn_id; - bluetooth->connected = event == ESP_GATTS_CONNECT_EVT; + bluetooth->gatts_connected = event == ESP_GATTS_CONNECT_EVT; + + /* + mp_obj_t cd_args [] = { + MP_OBJ_NEW_SMALL_INT(event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT), + mp_obj_new_bytearray(sizeof(param->connect.remote_bda), ¶m->connect.remote_bda), }; + args = mp_obj_new_list(MP_ARRAY_SIZE(cd_args), cd_args); + */ } NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gatts append\n"); CALLBACK_QUEUE_BEGIN(); - mp_obj_list_append(callback_queue, args); + assert(cbq_push(&cbdata) == true); + //mp_obj_list_append(callback_queue, args); CALLBACK_QUEUE_END(); NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gatts append\n"); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); @@ -1526,7 +1605,8 @@ STATIC void network_bluetooth_gap_event_handler( case ESP_GAP_BLE_SCAN_RESULT_EVT: { - mp_obj_t args = MP_OBJ_NULL; + network_bluetooth_callback_data_t cbdata; + bool nq = false; switch(param->scan_rst.search_evt) { case ESP_GAP_SEARCH_INQ_RES_EVT: { @@ -1534,20 +1614,23 @@ STATIC void network_bluetooth_gap_event_handler( uint8_t adv_name_len; adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); - mp_obj_t res_args[] = { - MP_OBJ_NEW_SMALL_INT(NETWORK_BLUETOOTH_SCAN_DATA), - mp_obj_new_bytearray(sizeof(param->scan_rst.bda), ¶m->scan_rst.bda), - mp_obj_new_str((const char *)adv_name, adv_name_len, false), - }; - args = mp_obj_new_list(MP_ARRAY_SIZE(res_args), res_args); + memcpy(cbdata.scan_data.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); + cbdata.scan_data.adv_data = m_malloc(adv_name_len); + cbdata.scan_data.adv_data_len = adv_name_len; + cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; + if (adv_name_len > 0) { + memcpy(cbdata.scan_data.adv_data, adv_name, adv_name_len); + } + nq = true; } break; case ESP_GAP_SEARCH_INQ_CMPL_EVT: // scanning done { bluetooth->scanning = false; - mp_obj_t cmpl_args[] = {MP_OBJ_NEW_SMALL_INT(NETWORK_BLUETOOTH_SCAN_CMPL)}; - args = mp_obj_new_list(MP_ARRAY_SIZE(cmpl_args), cmpl_args); + cbdata.event = NETWORK_BLUETOOTH_SCAN_CMPL; + nq = true; + } break; @@ -1556,18 +1639,16 @@ STATIC void network_bluetooth_gap_event_handler( break; } - if (args != MP_OBJ_NULL) { - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gap append len: %u\n",((mp_obj_list_t *)callback_queue)->len); + if (nq) { + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gap append\n"); CALLBACK_QUEUE_BEGIN(); - mp_obj_list_append(callback_queue, args); + assert(cbq_push(&cbdata) == true); CALLBACK_QUEUE_END(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gap append len: %u\n", ((mp_obj_list_t *)callback_queue)->len); - mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gap append\n"); } - } break; - + case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: if (bluetooth->advertising) { esp_ble_gap_start_advertising(&bluetooth->adv_params); @@ -1613,7 +1694,7 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m mp_printf(print, "Bluetooth(params=())", self); #define NETWORK_BLUETOOTH_LF "\n" NETWORK_BLUETOOTH_DEBUG_PRINTF( - "Bluetooth(conn_id = %04X, connected = %s" + "Bluetooth(conn_id = %04X, gatts_connected = %s" ", adv_params = (" "adv_int_min = %u, " NETWORK_BLUETOOTH_LF "adv_int_max = %u, " NETWORK_BLUETOOTH_LF @@ -1626,7 +1707,7 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m ")" , self->conn_id, - self->connected ? "True" : "False", + self->gatts_connected ? "True" : "False", (unsigned int)(self->adv_params.adv_int_min / 1.6), (unsigned int)(self->adv_params.adv_int_max / 1.6), self->adv_params.adv_type, @@ -1683,10 +1764,6 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { self->services = mp_obj_new_list(0, NULL); } - if (callback_queue == MP_OBJ_NULL) { - callback_queue = mp_obj_new_list(0, NULL); - } - if (callback_queue_mut == NULL) { //callback_queue_mut = xSemaphoreCreateBinary(); //find_item_mut = xSemaphoreCreateBinary(); From c505d56583b2199951c925941fdb5654c3c7c3d2 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 28 Apr 2017 12:41:38 -0700 Subject: [PATCH 37/98] esp32/network_bluetooth.c: Added GIL for mallocs in IDF callback Thanks @dpgeorge --- esp32/network_bluetooth.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 378584b73..ce0074245 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -1526,8 +1526,10 @@ STATIC void network_bluetooth_gatts_event_handler( cbdata.read.trans_id = param->read.trans_id; cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); cbdata.write.value_len = param->write.len; - // FIXME -- is m_malloc gonna work here? + + MP_THREAD_GIL_ENTER(); cbdata.write.value = m_malloc(param->write.len); // Returns NULL when len == 0 + MP_THREAD_GIL_EXIT(); @@ -1615,7 +1617,9 @@ STATIC void network_bluetooth_gap_event_handler( adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); memcpy(cbdata.scan_data.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); + MP_THREAD_GIL_ENTER(); cbdata.scan_data.adv_data = m_malloc(adv_name_len); + MP_THREAD_GIL_EXIT(); cbdata.scan_data.adv_data_len = adv_name_len; cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; if (adv_name_len > 0) { @@ -1645,6 +1649,7 @@ STATIC void network_bluetooth_gap_event_handler( assert(cbq_push(&cbdata) == true); CALLBACK_QUEUE_END(); NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gap append\n"); + mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } } break; @@ -2109,7 +2114,10 @@ STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_arg) { - (void)self_in; + network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->scanning) { + mp_raise_msg(&mp_type_OSError, "already scanning"); + } mp_int_t timeout = mp_obj_get_int(timeout_arg); static esp_ble_scan_params_t params = { @@ -2312,9 +2320,10 @@ STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t if (dest[0] == MP_OBJ_NULL) { switch(attr) { case MP_QSTR_Char: - dest[0] = mp_obj_new_bound_meth(MP_OBJ_FROM_PTR(&network_bluetooth_characteristic_make_new_obj), self); - + dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_characteristic_make_new_obj); + dest[1] = self; break; + case MP_QSTR_chars: dest[0] = self->chars; break; @@ -2329,10 +2338,19 @@ STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) if (!check_locals_dict(self, attr, dest)) { switch(attr) { + case MP_QSTR_is_scanning: + if (dest[0] == MP_OBJ_NULL) { + dest[0] = self->scanning ? mp_const_true : mp_const_false; + } else { + dest[0] = MP_OBJ_NULL; + } + break; case MP_QSTR_services: if (dest[0] == MP_OBJ_NULL) { // load dest[0] = self->services; - } + } else { + dest[0] = MP_OBJ_NULL; + } break; } } From 797c2cd99315732677cc7a05373efa7124be064a Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Sat, 29 Apr 2017 21:18:36 -0700 Subject: [PATCH 38/98] esp32/network_bluetooth.c: Chars() constructor now takes kw args --- esp32/network_bluetooth.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index ce0074245..61152e60d 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -62,6 +62,7 @@ SemaphoreHandle_t callback_queue_mut; SemaphoreHandle_t find_item_mut; +#define MP_OBJ_IS_BT_DATATYPE(O) (MP_OBJ_IS_STR_OR_BYTES(O) || MP_OBJ_IS_TYPE(O, &mp_type_bytearray) || (O == mp_const_none)) #define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) @@ -1391,7 +1392,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { mp_buffer_info_t buf; memset(&buf, 0, sizeof(mp_buffer_info_t)); - if(MP_OBJ_IS_STR_OR_BYTES(value)) { + if(MP_OBJ_IS_BT_DATATYPE(value)) { mp_get_buffer(value, &buf, MP_BUFFER_READ); } @@ -2201,20 +2202,20 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ return MP_OBJ_FROM_PTR(self); } -mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { +STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_characteristic_make_new()\n"); - enum {ARG_service, ARG_uuid, ARG_value, ARG_perm, ARG_prop}; + enum {ARG_uuid, ARG_value, ARG_perm, ARG_prop}; static const mp_arg_t allowed_args[] = { - { MP_QSTR_service, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_value, MP_ARG_OBJ, {.u_obj = mp_const_none }}, { MP_QSTR_perm, MP_ARG_INT, {.u_int = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE } }, { MP_QSTR_prop, MP_ARG_INT, {.u_int = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(2, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*)args[ARG_service].u_obj; + network_bluetooth_service_obj_t* service = MP_OBJ_TO_PTR(pos_args[0]); + + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); @@ -2229,8 +2230,8 @@ mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t self->base.type = &network_bluetooth_characteristic_type; NETWORK_BLUETOOTH_DEBUG_PRINTF("Making a new char object %p\n", self); - if (args[ARG_value].u_obj != mp_const_none && !MP_OBJ_IS_STR_OR_BYTES(args[ARG_value].u_obj)) { - mp_raise_ValueError("value must be string, bytearray or None"); + if (!MP_OBJ_IS_BT_DATATYPE(args[ARG_value].u_obj)) { + mp_raise_ValueError("value must be str, bytes, bytearray, or None"); } self->callback = mp_const_none; @@ -2245,7 +2246,7 @@ mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t return MP_OBJ_FROM_PTR(self); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_characteristic_make_new_obj, 2, network_bluetooth_characteristic_make_new); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_characteristic_make_new_obj, 1, network_bluetooth_characteristic_make_new); STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { @@ -2301,8 +2302,8 @@ STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *d if (dest[0] == MP_OBJ_NULL) { // load dest[0] = self->value; } else if (dest[1] != MP_OBJ_NULL) { // store - if (!MP_OBJ_IS_STR_OR_BYTES(dest[1])) { - mp_raise_ValueError("value must be bytearray or string"); + if (!MP_OBJ_IS_BT_DATATYPE(dest[1])) { + mp_raise_ValueError("value must be string, bytes, bytearray, or None"); } self->value = dest[1]; dest[0] = MP_OBJ_NULL; From cc14148d26edafad407b680ce2e31c368fc726b2 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 1 May 2017 08:41:00 -0700 Subject: [PATCH 39/98] esp32/network_bluetooth.c: Fixed callback handler for char write --- esp32/network_bluetooth.c | 41 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 61152e60d..864785311 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -1526,41 +1526,24 @@ STATIC void network_bluetooth_gatts_event_handler( cbdata.read.conn_id = param->read.conn_id; cbdata.read.trans_id = param->read.trans_id; cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); - cbdata.write.value_len = param->write.len; - - MP_THREAD_GIL_ENTER(); - cbdata.write.value = m_malloc(param->write.len); // Returns NULL when len == 0 - MP_THREAD_GIL_EXIT(); - - - - /* - mp_obj_t rw_args[] = { - MP_OBJ_NEW_SMALL_INT(event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE ), - MP_OBJ_NEW_SMALL_INT(param->read.handle), - event == ESP_GATTS_WRITE_EVT ? mp_obj_new_bytearray(param->write.len, param->write.value) : MP_OBJ_NULL, - mp_obj_new_int(param->read.conn_id), - mp_obj_new_int(param->read.trans_id), - event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp) ? mp_const_true : mp_const_false}; - args = mp_obj_new_list(MP_ARRAY_SIZE(rw_args), rw_args); - */ - + if (event == ESP_GATTS_WRITE_EVT) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Write param len: %d, data: '%*s'\n", param->write.len, param->write.len, param->write.value ); + MP_THREAD_GIL_ENTER(); + cbdata.write.value = m_malloc(param->write.len); // Returns NULL when len == 0 + MP_THREAD_GIL_EXIT(); + if (cbdata.write.value != NULL) { + cbdata.write.value_len = param->write.len; + memcpy(cbdata.write.value, param->write.value, param->write.len); + } else { + cbdata.write.value_len = 0; + } + } } else if (event == ESP_GATTS_CONNECT_EVT || event == ESP_GATTS_DISCONNECT_EVT) { - - - cbdata.event = event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT; cbdata.connect.conn_id = param->connect.conn_id; memcpy(cbdata.connect.bda, param->connect.remote_bda, ESP_BD_ADDR_LEN); bluetooth->conn_id = param->connect.conn_id; bluetooth->gatts_connected = event == ESP_GATTS_CONNECT_EVT; - - /* - mp_obj_t cd_args [] = { - MP_OBJ_NEW_SMALL_INT(event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT), - mp_obj_new_bytearray(sizeof(param->connect.remote_bda), ¶m->connect.remote_bda), }; - args = mp_obj_new_list(MP_ARRAY_SIZE(cd_args), cd_args); - */ } From 3706cca584d34de05cf4f59a3491c5fead482a90 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 1 May 2017 10:14:44 -0700 Subject: [PATCH 40/98] esp32/network_bluetooth.c: start/stop/close service is now working --- esp32/bluetooth_api_proposal.txt | 151 +++++++++++++++++++++++++++++++ esp32/network_bluetooth.c | 103 ++++++++++++++------- 2 files changed, 220 insertions(+), 34 deletions(-) create mode 100644 esp32/bluetooth_api_proposal.txt diff --git a/esp32/bluetooth_api_proposal.txt b/esp32/bluetooth_api_proposal.txt new file mode 100644 index 000000000..bcd79a17a --- /dev/null +++ b/esp32/bluetooth_api_proposal.txt @@ -0,0 +1,151 @@ + + +### Start the BT stack +```python +import network +b = network.Bluetooth() +``` + +### Services & Characteristics + + +###### Service constructor +```python +service = b.Service(uuid, primary = True) +``` + +Services with the same UUID are the same object. Constructing a second +service with the same UUID will return the same service object. The exception +are services that have been closed (via the `.close()` method) -- this +deallocates the service from the BLE stack. + +###### Characteristic constructor +```python +char service.Char(uuid, value = None, permissions = b.PERM_READ | b.PERM_WRITE, properties = b.PROP_READ | b.PROP_WRITE | b.PROP_NOTIFY) +``` + +Characteristics are associated with services. + +###### Start or stop service +```python +service.start() + +# stuff +service.stop() + +# services can be restarted: +service.start() + +``` + +###### Closing a service +```python +service.close() # Will call stop() + +service.start() # Runtime error; service is no longer usable +``` + +Closed service objects are completely "forgotten" by the BLE stack, you +needn't keep reference. You will no longer receive callbacks characteristics attached to the service. + +###### Get a list of current services +```python +currentServices = b.services() +``` + +###### Get a list of service characteristics +```python +chars = service.chars() +``` + + +### Callbacks + +##### Bluetooth Callback + +```python +def bt_callback(btObj, event, data, userdata): + print ("Bluetooth object", btObj) + if event == btObj.CONNECTED: + print ("connected") + if event == btObj.DISCONNECTED: + print ("disconnected") + + +Bluetooth.callback(bt_callback, "hello") +``` + +`Bluetooth.callback` takes two parameters: The callback function itself, and an optional userdata value to be passed in on callbacks. It returns the current callback function and usedata as tuple. + +`cb_function` can be None, which disables callbacks. `cb_function` is called with four parameters; the bluetooth object, event, event data, and the userdata. + +Event values: +* `Bluetooth.CONNECT` Data param is remote addr +* `Bluetooth.DISCONNECT` +* `Bluetooth.SCAN_RES` Scan data +* `Bluetooth.SCAN_CMPL` Scan complete + +##### Characteristic Callbacks + +```python +def char_callback(charObj, event, value, userdata): + print ("Char object", charObj) + if event == btObj.CONNECT: + print ("connected") + if event == btObj.DISCONNECT: + print ("disconnected") + +Char.callback(cb_function, userdata) +``` + +`Char.callback` takes two parameters: The callback function itself, and an optional userdata value to be passed in on callbacks. It returns the current callback function and userdata as tuple. + +`cb_function` can be None, which disables callbacks. `cb_function` is called with four parameters; the characteristic object, the event type, the event value (the sent value for `WRITE` or the current characteristic value for `READ`), and userdata. + +The event type will be one of `Bluetooth.READ` or `Bluetooth.WRITE`. + +Characteristics have an internal value, which is _not_ used and _not_ updated when there is a callback, though the callback is free to update or use the value as it sees fit. For `READ` operations (or `WRITE` operations that require a return value) the return value of the callback is sent, which must be a `bytearray`, `str`, or `None`. + +###### Value behavior without a callback + +If there is no callback defined for a characteristic, it's internal value will be used for `READ` or `WRITE` events, and `WRITE` events that expect a response will simply return the just-written value. + + + + +### Advertising +##### BLE settings + +```python +b.ble_settings( + int_min = 1280, + int_max = 1280, + type b.ADV_TYPE_IND, + own_addr_type = b.BLE_ADDR_TYPE_PUBLIC, + peer_addr = bytearray([0 for x in range(6)]), + peer_addr_type = b.BLE_ADDR_TYPE_PUBLIC, + channel_map = b.ADV_CHNL_ALL, + filter_policy = b.ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + adv_is_scan_rsp = False, + adv_dev_name = None, + adv_man_name = None, + adv_inc_txpower = False, + adv_int_min = 1280, + adv_int_max = 1280, + adv_appearance = 0, + adv_uuid = None, + adv_flags = 0) + +b.adv_enable(True) +``` + +### Scanning + +###### Scan start: + +Advertising and scanning cannot be run at the same time + +`Bluetooth.scan_start(timeout)` + +###### Scan stop: +`Bluetooth.scan_stop()` diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 864785311..fcb99dbac 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -59,7 +59,7 @@ const mp_obj_type_t network_bluetooth_service_type; const mp_obj_type_t network_bluetooth_characteristic_type; SemaphoreHandle_t callback_queue_mut; -SemaphoreHandle_t find_item_mut; +SemaphoreHandle_t item_mut; #define MP_OBJ_IS_BT_DATATYPE(O) (MP_OBJ_IS_STR_OR_BYTES(O) || MP_OBJ_IS_TYPE(O, &mp_type_bytearray) || (O == mp_const_none)) @@ -76,8 +76,8 @@ SemaphoreHandle_t find_item_mut; xSemaphoreGive(callback_queue_mut); \ NETWORK_BLUETOOTH_DEBUG_PRINTF(">> cbQ Give\n"); -#define FIND_ITEM_BEGIN() assert(xSemaphoreTake(find_item_mut, portMAX_DELAY) == pdTRUE) -#define FIND_ITEM_END() xSemaphoreGive(find_item_mut) +#define ITEM_BEGIN() assert(xSemaphoreTake(item_mut, portMAX_DELAY) == pdTRUE) +#define ITEM_END() xSemaphoreGive(item_mut) // CONSTANTS @@ -185,7 +185,6 @@ typedef struct { mp_obj_t chars; // list bool started; - bool closed; } network_bluetooth_service_obj_t; @@ -339,12 +338,13 @@ STATIC void network_bluetooth_uuid_print(const mp_print_t *print, esp_bt_uuid_t* typedef enum { NETWORK_BLUETOOTH_FIND_SERVICE, NETWORK_BLUETOOTH_FIND_CHAR, -} item_type_t; + NETWORK_BLUETOOTH_DEL_SERVICE, +} item_op_t; -STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle, item_type_t kind) { +STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle, item_op_t kind) { - FIND_ITEM_BEGIN(); + ITEM_BEGIN(); mp_obj_t ret = MP_OBJ_NULL; size_t len; mp_obj_t *items; @@ -352,11 +352,17 @@ STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, for(int i = 0; i < len; i++) { switch(kind) { case NETWORK_BLUETOOTH_FIND_SERVICE: + case NETWORK_BLUETOOTH_DEL_SERVICE: { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || (uuid == NULL && service->handle == handle)) { ret = service; - goto NETWORK_BLUETOOTH_FIND_ITEM_END; + if (kind == NETWORK_BLUETOOTH_DEL_SERVICE) { + // a bit ineffecient, but + // list_pop() is static + mp_obj_list_remove(list, ret); + } + goto NETWORK_BLUETOOTH_ITEM_END; } } break; @@ -366,14 +372,14 @@ STATIC mp_obj_t network_bluetooth_find_item(mp_obj_t list, esp_bt_uuid_t* uuid, network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle)) { ret = chr; - goto NETWORK_BLUETOOTH_FIND_ITEM_END; + goto NETWORK_BLUETOOTH_ITEM_END; } } break; } } -NETWORK_BLUETOOTH_FIND_ITEM_END: - FIND_ITEM_END(); +NETWORK_BLUETOOTH_ITEM_END: + ITEM_END(); return ret; } @@ -1367,7 +1373,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { mp_obj_get_array(bluetooth->services, &service_len, &service_items); for(int j = 0; j < service_len; j++) { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; - self = network_bluetooth_find_item(service->chars, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR); + self = network_bluetooth_item_op(service->chars, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR); if (self != MP_OBJ_NULL) { goto NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND; } @@ -1468,7 +1474,7 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_CREATE_EVT: { - network_bluetooth_service_obj_t* service = network_bluetooth_find_item(bluetooth->services, ¶m->create.service_id.id.uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); + network_bluetooth_service_obj_t* service = network_bluetooth_item_op(bluetooth->services, ¶m->create.service_id.id.uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); if (service != MP_OBJ_NULL) { service->handle = param->create.service_handle; @@ -1481,28 +1487,43 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_START_EVT: + case ESP_GATTS_STOP_EVT: { - network_bluetooth_service_obj_t* service = network_bluetooth_find_item(bluetooth->services, NULL, param->start.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); + network_bluetooth_service_obj_t* service = network_bluetooth_item_op(bluetooth->services, NULL, param->start.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); + if (service == MP_OBJ_NULL) { + break; + } - if (service != MP_OBJ_NULL) { - size_t len; - mp_obj_t *items; - mp_obj_get_array(service->chars, &len, &items); + switch(event) { + case ESP_GATTS_START_EVT: + service->started = true; - for (int i = 0; i < len; i++) { - network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; - esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); - } + size_t len; + mp_obj_t *items; + mp_obj_get_array(service->chars, &len, &items); + + for (int i = 0; i < len; i++) { + network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; + esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); + } + break; + case ESP_GATTS_STOP_EVT: + service->started = false; + esp_ble_gatts_delete_service(service->handle); + break; + default: + // Nothing, intentionally + break; } - } + } break; case ESP_GATTS_ADD_CHAR_EVT: { - network_bluetooth_service_obj_t* service = network_bluetooth_find_item(bluetooth->services, NULL, param->add_char.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); + network_bluetooth_service_obj_t* service = network_bluetooth_item_op(bluetooth->services, NULL, param->add_char.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); if (service != MP_OBJ_NULL) { - network_bluetooth_char_obj_t* chr = network_bluetooth_find_item(service->chars, ¶m->add_char.char_uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); + network_bluetooth_char_obj_t* chr = network_bluetooth_item_op(service->chars, ¶m->add_char.char_uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); chr->handle = param->add_char.attr_handle; NETWORK_BLUETOOTH_DEBUG_PRINTF("Setting char handle to %04X, from service handle %04X\n", param->add_char.attr_handle, param->add_char.service_handle); } else { @@ -1755,12 +1776,12 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { if (callback_queue_mut == NULL) { //callback_queue_mut = xSemaphoreCreateBinary(); - //find_item_mut = xSemaphoreCreateBinary(); + //item_mut = xSemaphoreCreateBinary(); callback_queue_mut = xSemaphoreCreateMutex(); - find_item_mut = xSemaphoreCreateMutex(); + item_mut = xSemaphoreCreateMutex(); xSemaphoreGive(callback_queue_mut); - xSemaphoreGive(find_item_mut); + xSemaphoreGive(item_mut); } NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth services pointer: %p", self->services); @@ -2162,7 +2183,7 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_service_obj_t *self = network_bluetooth_find_item(bluetooth->services, &uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); + network_bluetooth_service_obj_t *self = network_bluetooth_item_op(bluetooth->services, &uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); NETWORK_BLUETOOTH_DEBUG_PRINTF("find_service returned %p\n", self); if (self != MP_OBJ_NULL) { @@ -2178,9 +2199,9 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ self->service_id.is_primary = mp_obj_is_true(args[ARG_primary].u_obj); self->chars = mp_obj_new_list(0, NULL); - FIND_ITEM_BEGIN(); + ITEM_BEGIN(); mp_obj_list_append(bluetooth->services, MP_OBJ_FROM_PTR(self)); - FIND_ITEM_END(); + ITEM_END(); return MP_OBJ_FROM_PTR(self); } @@ -2202,7 +2223,7 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_char_obj_t *self = network_bluetooth_find_item(service->chars, &uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); + network_bluetooth_char_obj_t *self = network_bluetooth_item_op(service->chars, &uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); if (self != MP_OBJ_NULL) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Returning extant char for that UUID\n"); @@ -2236,6 +2257,11 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_start()\n"); network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; + + if (self->started) { + return mp_const_none; + } + mp_int_t numChars = mp_obj_get_int(mp_obj_len(self->chars)); uint32_t then = mp_hal_ticks_ms(); @@ -2263,14 +2289,23 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_start_obj, network_bl STATIC mp_obj_t network_bluetooth_service_stop(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_stop()\n"); - // FIXME + network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (!self->started || self->handle == 0) { + return mp_const_none; + } + esp_ble_gatts_stop_service(self->handle); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_stop_obj, network_bluetooth_service_stop); STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_close()\n"); - // FIXME + network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + network_bluetooth_item_op(bluetooth->services, &self->service_id.id.uuid, 0, NETWORK_BLUETOOTH_DEL_SERVICE); + if (self->handle != 0) { + esp_ble_gatts_delete_service(self->handle); + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); From 90d377da9d6c29b917b9c6da3518e3e333e84a0d Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 1 May 2017 10:57:07 -0700 Subject: [PATCH 41/98] esp32/network_bluetooth.c: Added indication/notification to chars --- esp32/network_bluetooth.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index fcb99dbac..3a6abe6ea 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2157,6 +2157,36 @@ STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *a } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_callback_obj, 1, 3, network_bluetooth_char_callback); +STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_char_indicate()\n"); + network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); + network_bluetooth_char_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); + + enum {ARG_value, ARG_need_confirm}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_value, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL }}, + { MP_QSTR_need_confirm, MP_ARG_BOOL, { .u_bool = false } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + if (args[ARG_value].u_obj != MP_OBJ_NULL) { + if (!MP_OBJ_IS_BT_DATATYPE(args[ARG_value].u_obj)) { + mp_raise_ValueError("value must be string, bytes, bytearray, or None"); + } + } else { + args[ARG_value].u_obj = self->value; + } + + NETWORK_BLUETOOTH_DEBUG_PRINTF("need confirmations: %s\n", args[ARG_need_confirm].u_bool ? "True" : "False"); + mp_buffer_info_t buf; + mp_get_buffer(args[ARG_value].u_obj, &buf, MP_BUFFER_READ); + esp_ble_gatts_send_indicate(bluetooth->interface, bluetooth->conn_id, self->handle, buf.len, buf.buf, args[ARG_need_confirm].u_bool); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_indicate_obj, 1, network_bluetooth_char_indicate); + STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new, self = %p, n_args = %d, n_kw = %d\n", self, n_args, n_kw ); @@ -2309,7 +2339,6 @@ STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); - // char attribute handler STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) self_in; @@ -2497,6 +2526,7 @@ const mp_obj_type_t network_bluetooth_service_type = { STATIC const mp_rom_map_elem_t network_bluetooth_characteristic_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&network_bluetooth_char_indicate_obj) }, { MP_ROM_QSTR(MP_QSTR_value), NULL }, // handled by attr handler }; From eb69763b7e6e6a21f903c87bfbc999a8bdbfff53 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 1 May 2017 15:07:57 -0700 Subject: [PATCH 42/98] esp32/network_bluetooth.c: event ringbuffer --> linked list, having GC issues --- esp32/network_bluetooth.c | 377 +++++++++++++++++++++++++------------- 1 file changed, 246 insertions(+), 131 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 3a6abe6ea..774a20c86 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -1,4 +1,5 @@ -/* * This file is part of the MicroPython project, http://micropython.org/ +/* + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * @@ -131,43 +132,86 @@ typedef struct { } write; }; -} network_bluetooth_callback_data_t; +} callback_data_t; + +typedef struct _callback_node_t { + struct _callback_node_t* prev; + struct _callback_node_t* next; + callback_data_t data; +} callback_node_t; //mp_obj_t callback_queue; // implemented as a list -#define CBQ_CAPACITY 10 +#define CBQ_MAX_CAPACITY 1000 typedef struct { - network_bluetooth_callback_data_t q[CBQ_CAPACITY]; - size_t head; - size_t tail; - size_t count; + callback_node_t* head; + callback_node_t* tail; + mp_set_t seen; + size_t count; } cbq_t; cbq_t callback_queue = { - .head = 0, - .tail = 0, + .head = NULL, + .tail = NULL, .count = 0 + }; -STATIC bool cbq_push (const network_bluetooth_callback_data_t* data) { - if (callback_queue.count == CBQ_CAPACITY) { +// Caller has to ensure these are locked + +STATIC callback_data_t* cbq_push () { + if (callback_queue.count == CBQ_MAX_CAPACITY) { + return NULL; + } + callback_node_t* item = m_malloc(sizeof(callback_node_t)); + + if (item == NULL) { return false; } - callback_queue.q[callback_queue.head++] = *data; - callback_queue.head %= CBQ_CAPACITY; + + item->prev = NULL; + item->next = callback_queue.head; + + if(callback_queue.head != NULL) { + callback_queue.head->prev = item; + } else { + // if head is NULL, then tail is NULL, + // and the list is empty + callback_queue.tail = item; + } + callback_queue.head = item; callback_queue.count++; - return true; + + return &item->data; } -STATIC bool cbq_pop (network_bluetooth_callback_data_t* data) { +STATIC callback_data_t* cbq_tail() { + if (callback_queue.count == 0) { + return NULL; + } + return &callback_queue.tail->data; +} + +STATIC bool cbq_pop () { if (callback_queue.count == 0) { return false; } - *data = callback_queue.q[callback_queue.tail++]; - callback_queue.tail %= CBQ_CAPACITY; + callback_node_t* old_tail = callback_queue.tail; + + if (callback_queue.head->next == NULL) { + callback_queue.head = NULL; + } else { + callback_queue.tail->prev->next = NULL; + } + callback_queue.tail = callback_queue.tail->prev; + callback_queue.count--; + + NETWORK_BLUETOOTH_DEBUG_PRINTF("cbq_pop, about to free: %p\n", old_tail); + // yay, garbage collection + //m_free(old_tail); return true; } @@ -175,6 +219,17 @@ STATIC bool cbq_empty() { return callback_queue.count == 0; } +//FIXME remove +STATIC void cbq_dump() { + NETWORK_BLUETOOTH_DEBUG_PRINTF("CBQ head = %p, tail = %p, count = %u \n", callback_queue.head, callback_queue.tail, callback_queue.count); + int cnt = 0; + for(callback_node_t* cur = callback_queue.head; cur; cur = cur->next) { + NETWORK_BLUETOOTH_DEBUG_PRINTF(" %p: prev = %p, next = %p\n", cur, cur->prev, cur->next); + if (++cnt > 50) + break; + } +} + // "Service" typedef struct { @@ -237,6 +292,7 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { .base = { &network_bluetooth_type }, .state = NETWORK_BLUETOOTH_STATE_DEINIT, .advertising = false, + .scanning = false, .gatts_connected = false, .conn_id = 0, .interface = ESP_GATT_IF_NONE, @@ -1344,104 +1400,111 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { size_t service_len; mp_obj_t *service_items; - network_bluetooth_callback_data_t cbdata; + callback_data_t cbdata; - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> handler\n"); - CALLBACK_QUEUE_BEGIN(); - if (cbq_empty()) { - return mp_const_none; - } - cbq_pop(&cbdata); - CALLBACK_QUEUE_END(); + while(true) { + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> handler, q size before pop: %u\n", callback_queue.count); + cbq_dump(); + CALLBACK_QUEUE_BEGIN(); + if (cbq_empty()) { + CALLBACK_QUEUE_END(); + return mp_const_none; + } + cbdata = *cbq_tail(); + cbq_pop(); + cbq_dump(); + NETWORK_BLUETOOTH_DEBUG_PRINTF(" handler, q size after pop: %u\n", callback_queue.count); + CALLBACK_QUEUE_END(); - switch (cbdata.event) { + switch (cbdata.event) { - case NETWORK_BLUETOOTH_READ: - case NETWORK_BLUETOOTH_WRITE: - { - /* - assert(len == 6); - uint16_t handle = mp_obj_get_int(items[1]); - mp_obj_t write_value = items[2]; - uint16_t conn_id = mp_obj_get_int(items[3]); - uint32_t trans_id = mp_obj_get_int(items[4]); - bool need_rsp = mp_obj_is_true(items[5]); - */ - - - mp_obj_get_array(bluetooth->services, &service_len, &service_items); - for(int j = 0; j < service_len; j++) { - network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; - self = network_bluetooth_item_op(service->chars, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR); - if (self != MP_OBJ_NULL) { - goto NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND; + case NETWORK_BLUETOOTH_READ: + case NETWORK_BLUETOOTH_WRITE: + { + /* + assert(len == 6); + uint16_t handle = mp_obj_get_int(items[1]); + mp_obj_t write_value = items[2]; + uint16_t conn_id = mp_obj_get_int(items[3]); + uint32_t trans_id = mp_obj_get_int(items[4]); + bool need_rsp = mp_obj_is_true(items[5]); + */ + + + mp_obj_get_array(bluetooth->services, &service_len, &service_items); + for(int j = 0; j < service_len; j++) { + network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; + self = network_bluetooth_item_op(service->chars, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR); + if (self != MP_OBJ_NULL) { + goto NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND; + } } - } - return mp_const_none; + return mp_const_none; NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND: - { - mp_obj_t value = cbdata.event == NETWORK_BLUETOOTH_READ ? self->value : mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value); - if (self->callback != mp_const_none) { - mp_obj_t args[] = {self, MP_OBJ_NEW_SMALL_INT(cbdata.event), value, self->callback_userdata }; - value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); - } else if (cbdata.event == NETWORK_BLUETOOTH_WRITE) { - self->value = value; - } + { + mp_obj_t value = cbdata.event == NETWORK_BLUETOOTH_READ ? self->value : mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value); + if (self->callback != mp_const_none) { + mp_obj_t args[] = {self, MP_OBJ_NEW_SMALL_INT(cbdata.event), value, self->callback_userdata }; + value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); + } else if (cbdata.event == NETWORK_BLUETOOTH_WRITE) { + self->value = value; + } - if (cbdata.read.need_rsp) { - esp_gatt_rsp_t rsp; - memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); + if (cbdata.read.need_rsp) { + esp_gatt_rsp_t rsp; + memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); - mp_buffer_info_t buf; - memset(&buf, 0, sizeof(mp_buffer_info_t)); + mp_buffer_info_t buf; + memset(&buf, 0, sizeof(mp_buffer_info_t)); - if(MP_OBJ_IS_BT_DATATYPE(value)) { - mp_get_buffer(value, &buf, MP_BUFFER_READ); - } + if(MP_OBJ_IS_BT_DATATYPE(value)) { + mp_get_buffer(value, &buf, MP_BUFFER_READ); + } - size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); + size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); - rsp.attr_value.handle = cbdata.read.handle; - rsp.attr_value.len = len; - memcpy(rsp.attr_value.value, buf.buf, len); - esp_ble_gatts_send_response(bluetooth->interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); + rsp.attr_value.handle = cbdata.read.handle; + rsp.attr_value.len = len; + memcpy(rsp.attr_value.value, buf.buf, len); + esp_ble_gatts_send_response(bluetooth->interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); + } } } - } - break; + break; - case NETWORK_BLUETOOTH_CONNECT: - case NETWORK_BLUETOOTH_DISCONNECT: - { + case NETWORK_BLUETOOTH_CONNECT: + case NETWORK_BLUETOOTH_DISCONNECT: + { + if (bluetooth->callback != mp_const_none) { + // items[0] is event + // items[1] is remote address + mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.connect.bda), bluetooth->callback_userdata }; + mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); + } + break; + } + case NETWORK_BLUETOOTH_SCAN_CMPL: + case NETWORK_BLUETOOTH_SCAN_DATA: if (bluetooth->callback != mp_const_none) { - // items[0] is event - // items[1] is remote address - mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.connect.bda), bluetooth->callback_userdata }; + mp_obj_t data = mp_const_none; + if (cbdata.event == NETWORK_BLUETOOTH_SCAN_DATA) { + mp_obj_t scan_data_args[] = {mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.scan_data.bda), mp_obj_new_bytearray(cbdata.scan_data.adv_data_len, cbdata.scan_data.adv_data) } ; + data = mp_obj_new_tuple(2, scan_data_args); + } + + mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), data, bluetooth->callback_userdata }; mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); } break; - } - case NETWORK_BLUETOOTH_SCAN_CMPL: - case NETWORK_BLUETOOTH_SCAN_DATA: - if (bluetooth->callback != mp_const_none) { - mp_obj_t data = mp_const_none; - if (cbdata.event == NETWORK_BLUETOOTH_SCAN_DATA) { - mp_obj_t scan_data_args[] = {mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.scan_data.bda), mp_obj_new_bytearray(cbdata.scan_data.adv_data_len, cbdata.scan_data.adv_data) } ; - data = mp_obj_new_tuple(2, scan_data_args); - } - - mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), data, bluetooth->callback_userdata }; - mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); - } - break; - default: - // do nothing, intentionally - break; + default: + // do nothing, intentionally + break; + } } return mp_const_none; } @@ -1538,40 +1601,41 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_CONNECT_EVT: case ESP_GATTS_DISCONNECT_EVT: { - network_bluetooth_callback_data_t cbdata; + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gatts append, q size: %u\n", callback_queue.count); + CALLBACK_QUEUE_BEGIN(); + MP_THREAD_GIL_ENTER(); + callback_data_t* cbdata = cbq_push(); + MP_THREAD_GIL_EXIT(); + assert(cbdata != NULL); + if (event == ESP_GATTS_READ_EVT || event == ESP_GATTS_WRITE_EVT) { - cbdata.event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; + cbdata->event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; - cbdata.read.handle = param->read.handle; - cbdata.read.conn_id = param->read.conn_id; - cbdata.read.trans_id = param->read.trans_id; - cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); + cbdata->read.handle = param->read.handle; + cbdata->read.conn_id = param->read.conn_id; + cbdata->read.trans_id = param->read.trans_id; + cbdata->read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); if (event == ESP_GATTS_WRITE_EVT) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Write param len: %d, data: '%*s'\n", param->write.len, param->write.len, param->write.value ); MP_THREAD_GIL_ENTER(); - cbdata.write.value = m_malloc(param->write.len); // Returns NULL when len == 0 + cbdata->write.value = m_malloc(param->write.len); // Returns NULL when len == 0 MP_THREAD_GIL_EXIT(); - if (cbdata.write.value != NULL) { - cbdata.write.value_len = param->write.len; - memcpy(cbdata.write.value, param->write.value, param->write.len); + if (cbdata->write.value != NULL) { + cbdata->write.value_len = param->write.len; + memcpy(cbdata->write.value, param->write.value, param->write.len); } else { - cbdata.write.value_len = 0; + cbdata->write.value_len = 0; } } } else if (event == ESP_GATTS_CONNECT_EVT || event == ESP_GATTS_DISCONNECT_EVT) { - cbdata.event = event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT; - cbdata.connect.conn_id = param->connect.conn_id; - memcpy(cbdata.connect.bda, param->connect.remote_bda, ESP_BD_ADDR_LEN); + cbdata->event = event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT; + cbdata->connect.conn_id = param->connect.conn_id; + memcpy(cbdata->connect.bda, param->connect.remote_bda, ESP_BD_ADDR_LEN); bluetooth->conn_id = param->connect.conn_id; bluetooth->gatts_connected = event == ESP_GATTS_CONNECT_EVT; } - - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gatts append\n"); - CALLBACK_QUEUE_BEGIN(); - assert(cbq_push(&cbdata) == true); - //mp_obj_list_append(callback_queue, args); CALLBACK_QUEUE_END(); NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gatts append\n"); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); @@ -1594,52 +1658,67 @@ STATIC void network_bluetooth_gap_event_handler( esp_ble_gap_cb_param_t *param) { #ifdef EVENT_DEBUG - // gap_event_dump(event, param); + gap_event_dump(event, param); #endif network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); switch (event) { case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: - bluetooth-> scanning = true; + if (param->adv_start_cmpl.status == ESP_BT_STATUS_SUCCESS) { + bluetooth->scanning = true; + } break; case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: // doesn't seem we ever get this, in practice - bluetooth-> scanning = false; + if (param->adv_stop_cmpl.status == ESP_BT_STATUS_SUCCESS) { + bluetooth->scanning = false; + } break; case ESP_GAP_BLE_SCAN_RESULT_EVT: { - network_bluetooth_callback_data_t cbdata; + callback_data_t cbdata; bool nq = false; switch(param->scan_rst.search_evt) { case ESP_GAP_SEARCH_INQ_RES_EVT: { - uint8_t* adv_name; - uint8_t adv_name_len; - adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); - memcpy(cbdata.scan_data.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); MP_THREAD_GIL_ENTER(); - cbdata.scan_data.adv_data = m_malloc(adv_name_len); + mp_obj_t bda = mp_obj_new_str((const char *)param->scan_rst.bda, ESP_BD_ADDR_LEN, false); + mp_obj_t res = mp_set_lookup(&callback_queue.seen, bda, MP_MAP_LOOKUP); MP_THREAD_GIL_EXIT(); - cbdata.scan_data.adv_data_len = adv_name_len; - cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; - if (adv_name_len > 0) { - memcpy(cbdata.scan_data.adv_data, adv_name, adv_name_len); - } - nq = true; - } + if (res == MP_OBJ_NULL) { + MP_THREAD_GIL_ENTER(); + mp_set_lookup(&callback_queue.seen, bda, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); + MP_THREAD_GIL_EXIT(); + uint8_t* adv_name; + uint8_t adv_name_len; + adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); + + memcpy(cbdata.scan_data.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); + MP_THREAD_GIL_ENTER(); + cbdata.scan_data.adv_data = m_malloc(adv_name_len); + MP_THREAD_GIL_EXIT(); + cbdata.scan_data.adv_data_len = adv_name_len; + cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; + if (adv_name_len > 0) { + memcpy(cbdata.scan_data.adv_data, adv_name, adv_name_len); + } + nq = true; + } } break; case ESP_GAP_SEARCH_INQ_CMPL_EVT: // scanning done { bluetooth->scanning = false; cbdata.event = NETWORK_BLUETOOTH_SCAN_CMPL; + MP_THREAD_GIL_ENTER(); + mp_set_clear(&callback_queue.seen); + MP_THREAD_GIL_EXIT(); nq = true; - } break; @@ -1649,9 +1728,13 @@ STATIC void network_bluetooth_gap_event_handler( } if (nq) { - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gap append\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gap append, q size: %u\n", callback_queue.count); CALLBACK_QUEUE_BEGIN(); - assert(cbq_push(&cbdata) == true); + MP_THREAD_GIL_ENTER(); + callback_data_t* q_data = cbq_push(); + MP_THREAD_GIL_EXIT(); + assert(q_data != NULL); + *q_data = cbdata; CALLBACK_QUEUE_END(); NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gap append\n"); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); @@ -2132,12 +2215,14 @@ STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_ .scan_interval = 0x50, .scan_window = 0x30 }; + assert(esp_ble_gap_set_scan_params(¶ms) == ESP_OK); assert(esp_ble_gap_start_scanning(timeout) == ESP_OK); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_scan_start_obj, network_bluetooth_scan_start); + STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { (void)self_in; assert(esp_ble_gap_stop_scanning() == ESP_OK); @@ -2145,6 +2230,31 @@ STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_scan_stop_obj, network_bluetooth_scan_stop); + + +STATIC mp_obj_t network_bluetooth_dump(mp_obj_t self_in) { + (void)self_in; + cbq_dump(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_dump_obj, network_bluetooth_dump); + +STATIC mp_obj_t network_bluetooth_push(mp_obj_t self_in) { + (void)self_in; + cbq_push(); + cbq_dump(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_push_obj, network_bluetooth_push); + +STATIC mp_obj_t network_bluetooth_pop(mp_obj_t self_in) { + (void)self_in; + cbq_pop(); + cbq_dump(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_pop_obj, network_bluetooth_pop); + STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); @@ -2194,6 +2304,7 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t mp_raise_TypeError("Constructor takes no arguments"); } + mp_set_init(&callback_queue.seen, 0); network_bluetooth_init(self); return MP_OBJ_FROM_PTR(self); } @@ -2426,6 +2537,10 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&network_bluetooth_scan_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_is_scanning), NULL }, // handle by attr + // FIXME remove these from production + { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&network_bluetooth_push_obj) }, + { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&network_bluetooth_dump_obj) }, + { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&network_bluetooth_pop_obj) }, // class constants From 61fc0ad855f67522ffdbb36522378e3a2220fc70 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 2 May 2017 12:46:29 -0700 Subject: [PATCH 43/98] esp32/main.c: heap 16Kib -> 12kIb --- esp32/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/main.c b/esp32/main.c index 245534b81..85f37d646 100644 --- a/esp32/main.c +++ b/esp32/main.c @@ -53,7 +53,7 @@ #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) #define MP_TASK_STACK_SIZE (16 * 1024) #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) -#define MP_TASK_HEAP_SIZE (16 * 1024) +#define MP_TASK_HEAP_SIZE (12 * 1024) STATIC StaticTask_t mp_task_tcb; STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8))); From 2f523c956e3fa62cf399f6a9e875d702108fa77f Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 2 May 2017 12:49:38 -0700 Subject: [PATCH 44/98] esp32/network_bluetooth.c: now using FreeRTOS queues for callback data --- esp32/network_bluetooth.c | 498 +++++++++++++++----------------------- 1 file changed, 191 insertions(+), 307 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 774a20c86..093e0b5e8 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "freertos/FreeRTOS.h" @@ -59,7 +60,6 @@ const mp_obj_type_t network_bluetooth_type; const mp_obj_type_t network_bluetooth_service_type; const mp_obj_type_t network_bluetooth_characteristic_type; -SemaphoreHandle_t callback_queue_mut; SemaphoreHandle_t item_mut; @@ -67,16 +67,6 @@ SemaphoreHandle_t item_mut; #define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) -#define CALLBACK_QUEUE_BEGIN() \ - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> cbQ Take\n"); \ - assert(xSemaphoreTake(callback_queue_mut, portMAX_DELAY) == pdTRUE); \ - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< cbQ Take\n"); - -#define CALLBACK_QUEUE_END() \ - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< cbQ Give\n"); \ - xSemaphoreGive(callback_queue_mut); \ - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> cbQ Give\n"); - #define ITEM_BEGIN() assert(xSemaphoreTake(item_mut, portMAX_DELAY) == pdTRUE) #define ITEM_END() xSemaphoreGive(item_mut) @@ -95,142 +85,6 @@ typedef enum { NETWORK_BLUETOOTH_WRITE, } network_bluetooth_event_t; - -typedef struct { - network_bluetooth_event_t event; - union { - struct { - uint16_t conn_id; - esp_bd_addr_t bda; - } connect; - - struct { - uint16_t conn_id; - esp_bd_addr_t bda; - } disconnect; - - struct { - esp_bd_addr_t bda; - uint8_t* adv_data; // Need to free this! - uint8_t adv_data_len; - } scan_data; - - struct { - uint16_t handle; - uint16_t conn_id; - uint32_t trans_id; - bool need_rsp; - } read; - - struct { - uint16_t handle; - uint16_t conn_id; - uint32_t trans_id; - bool need_rsp; - uint8_t* value; - size_t value_len; - } write; - }; - -} callback_data_t; - -typedef struct _callback_node_t { - struct _callback_node_t* prev; - struct _callback_node_t* next; - callback_data_t data; -} callback_node_t; - -//mp_obj_t callback_queue; // implemented as a list - - -#define CBQ_MAX_CAPACITY 1000 -typedef struct { - callback_node_t* head; - callback_node_t* tail; - mp_set_t seen; - size_t count; -} cbq_t; - -cbq_t callback_queue = { - .head = NULL, - .tail = NULL, - .count = 0 - -}; - - -// Caller has to ensure these are locked - -STATIC callback_data_t* cbq_push () { - if (callback_queue.count == CBQ_MAX_CAPACITY) { - return NULL; - } - callback_node_t* item = m_malloc(sizeof(callback_node_t)); - - if (item == NULL) { - return false; - } - - item->prev = NULL; - item->next = callback_queue.head; - - if(callback_queue.head != NULL) { - callback_queue.head->prev = item; - } else { - // if head is NULL, then tail is NULL, - // and the list is empty - callback_queue.tail = item; - } - callback_queue.head = item; - callback_queue.count++; - - return &item->data; -} - -STATIC callback_data_t* cbq_tail() { - if (callback_queue.count == 0) { - return NULL; - } - return &callback_queue.tail->data; -} - -STATIC bool cbq_pop () { - if (callback_queue.count == 0) { - return false; - } - callback_node_t* old_tail = callback_queue.tail; - - if (callback_queue.head->next == NULL) { - callback_queue.head = NULL; - } else { - callback_queue.tail->prev->next = NULL; - } - callback_queue.tail = callback_queue.tail->prev; - - callback_queue.count--; - - NETWORK_BLUETOOTH_DEBUG_PRINTF("cbq_pop, about to free: %p\n", old_tail); - // yay, garbage collection - //m_free(old_tail); - return true; -} - -STATIC bool cbq_empty() { - return callback_queue.count == 0; -} - -//FIXME remove -STATIC void cbq_dump() { - NETWORK_BLUETOOTH_DEBUG_PRINTF("CBQ head = %p, tail = %p, count = %u \n", callback_queue.head, callback_queue.tail, callback_queue.count); - int cnt = 0; - for(callback_node_t* cur = callback_queue.head; cur; cur = cur->next) { - NETWORK_BLUETOOTH_DEBUG_PRINTF(" %p: prev = %p, next = %p\n", cur, cur->prev, cur->next); - if (++cnt > 50) - break; - } -} - - // "Service" typedef struct { mp_obj_base_t base; @@ -285,6 +139,7 @@ typedef struct { mp_obj_t callback; mp_obj_t callback_userdata; + } network_bluetooth_obj_t; // Singleton @@ -327,18 +182,72 @@ STATIC network_bluetooth_obj_t network_bluetooth_singleton = { }; - - STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { return &network_bluetooth_singleton; } +typedef struct { + network_bluetooth_event_t event; + union { + struct { + uint16_t conn_id; + esp_bd_addr_t bda; + } connect; + + struct { + uint16_t conn_id; + esp_bd_addr_t bda; + } disconnect; + + struct { + esp_bd_addr_t bda; + uint8_t* adv_data; // Need to free this! + uint8_t adv_data_len; + } scan_data; + + struct { + uint16_t handle; + uint16_t conn_id; + uint32_t trans_id; + bool need_rsp; + } read; + + struct { + uint16_t handle; + uint16_t conn_id; + uint32_t trans_id; + bool need_rsp; + uint8_t* value; + size_t value_len; + } write; + }; + +} callback_data_t; + +#define CALLBACK_QUEUE_SIZE 10 +STATIC QueueHandle_t callback_q = NULL; +STATIC uint8_t callback_q_buf[sizeof(callback_data_t) * CALLBACK_QUEUE_SIZE]; +STATIC StaticQueue_t callback_q_data; + +STATIC bool cbq_push (const callback_data_t* data, bool block) { + return xQueueSend(callback_q, data, block ? portMAX_DELAY : 10 / portTICK_PERIOD_MS) == pdPASS; +} + +STATIC bool cbq_pop (callback_data_t* data) { + return xQueueReceive(callback_q, data, 0) == pdPASS; +} + +/* FIXME -- not used? +STATIC size_t cbq_count() { + return uxQueueMessagesWaiting(callback_q); +} +*/ + STATIC void dumpBuf(const uint8_t *buf, size_t len) { while(len--) printf("%02X ", *buf++); } - STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { if (MP_OBJ_IS_INT(src)) { @@ -349,7 +258,7 @@ STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { // LSB first *uuid_ptr++ = arg_uuid & 0xff; arg_uuid >>= 8; - } + } } else if (mp_obj_get_type(src) != &mp_type_bytearray) { goto PARSE_UUID_BAD; } else { @@ -367,6 +276,30 @@ STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { mp_raise_ValueError("uuid must be integer or bytearray(16)"); } +static void uuid_to_uuid128(const esp_bt_uuid_t* in, esp_bt_uuid_t* out) { + + static const uint8_t base_uuid[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; + + if (in->len == 16) { + *out = *in; + return; + } + + out->len = 16; + memcpy(out->uuid.uuid128, base_uuid, MP_ARRAY_SIZE(base_uuid)); + + if (in->len == 2) { + uint16_t t = htons(in->uuid.uuid16); + memcpy(out->uuid.uuid128 + sizeof(t), &t, sizeof(t)); + } else { + uint32_t t = htonl(in->uuid.uuid32); + memcpy(out->uuid.uuid128, &t, sizeof(t)); + } + +} + STATIC bool uuid_eq(const esp_bt_uuid_t* a, const esp_bt_uuid_t* b) { if (a->len != b->len) { return false; @@ -374,14 +307,16 @@ STATIC bool uuid_eq(const esp_bt_uuid_t* a, const esp_bt_uuid_t* b) { return memcmp(&a->uuid.uuid128, &b->uuid.uuid128, a->len) == 0; } -STATIC void network_bluetooth_uuid_print(const mp_print_t *print, esp_bt_uuid_t* uuid) { - for(int i = 0; i < uuid->len; i++) { +STATIC void network_bluetooth_uuid_print(const mp_print_t *print, const esp_bt_uuid_t* uuid) { + esp_bt_uuid_t uuid128; + uuid_to_uuid128(uuid, &uuid128); + for(int i = 0; i < uuid128.len; i++) { if (print != NULL) { - mp_printf(print, "%02X", uuid->uuid.uuid128[i]); + mp_printf(print, "%02X", uuid128.uuid.uuid128[i]); } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("%02X", uuid->uuid.uuid128[i]); + NETWORK_BLUETOOTH_DEBUG_PRINTF("%02X", uuid128.uuid.uuid128[i]); } - if (uuid->len > 4 && (i == 3 || i == 5 || i == 7 || i == 9)) { + if (i == 3 || i == 5 || i == 7 || i == 9) { if (print != NULL) { mp_printf(print, "-"); } else { @@ -394,29 +329,47 @@ STATIC void network_bluetooth_uuid_print(const mp_print_t *print, esp_bt_uuid_t* typedef enum { NETWORK_BLUETOOTH_FIND_SERVICE, NETWORK_BLUETOOTH_FIND_CHAR, + NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES, NETWORK_BLUETOOTH_DEL_SERVICE, } item_op_t; STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle, item_op_t kind) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_item_op, list is %p\n", list); ITEM_BEGIN(); mp_obj_t ret = MP_OBJ_NULL; + size_t len; mp_obj_t *items; mp_obj_get_array(list, &len, &items); for(int i = 0; i < len; i++) { switch(kind) { case NETWORK_BLUETOOTH_FIND_SERVICE: + case NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES: case NETWORK_BLUETOOTH_DEL_SERVICE: { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; - if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || (uuid == NULL && service->handle == handle)) { + + if (kind == NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES) { + size_t char_len; + mp_obj_t *char_items; + mp_obj_get_array(service->chars, &char_len, &char_items); + for(int j = 0; j < char_len; j++) { + network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) char_items[j]; + if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle)) { + ret = chr; + goto NETWORK_BLUETOOTH_ITEM_END; + } + } + + } else if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || (uuid == NULL && service->handle == handle)) { ret = service; + if (kind == NETWORK_BLUETOOTH_DEL_SERVICE) { // a bit ineffecient, but // list_pop() is static - mp_obj_list_remove(list, ret); + mp_obj_list_remove(list, service); } goto NETWORK_BLUETOOTH_ITEM_END; } @@ -1395,57 +1348,29 @@ NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - network_bluetooth_char_obj_t *self; - - size_t service_len; - mp_obj_t *service_items; callback_data_t cbdata; while(true) { - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> handler, q size before pop: %u\n", callback_queue.count); - cbq_dump(); - CALLBACK_QUEUE_BEGIN(); - if (cbq_empty()) { - CALLBACK_QUEUE_END(); + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> cbq_pop\n"); + bool got_data = cbq_pop(&cbdata); + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< cbq_pop\n"); + if (!got_data) { return mp_const_none; } - cbdata = *cbq_tail(); - cbq_pop(); - cbq_dump(); - NETWORK_BLUETOOTH_DEBUG_PRINTF(" handler, q size after pop: %u\n", callback_queue.count); - CALLBACK_QUEUE_END(); - switch (cbdata.event) { case NETWORK_BLUETOOTH_READ: case NETWORK_BLUETOOTH_WRITE: { - /* - assert(len == 6); - uint16_t handle = mp_obj_get_int(items[1]); - mp_obj_t write_value = items[2]; - uint16_t conn_id = mp_obj_get_int(items[3]); - uint32_t trans_id = mp_obj_get_int(items[4]); - bool need_rsp = mp_obj_is_true(items[5]); - */ - - - mp_obj_get_array(bluetooth->services, &service_len, &service_items); - for(int j = 0; j < service_len; j++) { - network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) service_items[j]; - self = network_bluetooth_item_op(service->chars, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR); - if (self != MP_OBJ_NULL) { - goto NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND; - } - } - return mp_const_none; + network_bluetooth_char_obj_t* self = network_bluetooth_item_op(bluetooth->services, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES); + NETWORK_BLUETOOTH_DEBUG_PRINTF("MP_OBJ_NULL: %p, chr: %p\n", MP_OBJ_NULL, self); + + if (self != MP_OBJ_NULL) { -NETWORK_BLUETOOTH_CALLBACK_QUEUE_HANDLER_CHAR_FOUND: + mp_obj_t value = cbdata.event == NETWORK_BLUETOOTH_WRITE ? mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value) : self->value; - { - mp_obj_t value = cbdata.event == NETWORK_BLUETOOTH_READ ? self->value : mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value); if (self->callback != mp_const_none) { mp_obj_t args[] = {self, MP_OBJ_NEW_SMALL_INT(cbdata.event), value, self->callback_userdata }; value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); @@ -1470,7 +1395,10 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { rsp.attr_value.len = len; memcpy(rsp.attr_value.value, buf.buf, len); esp_ble_gatts_send_response(bluetooth->interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); - + } + if (cbdata.event == NETWORK_BLUETOOTH_WRITE) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Freeing using vPortFree(%p)\n", cbdata.write.value); + vPortFree(cbdata.write.value); } } } @@ -1478,15 +1406,13 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { case NETWORK_BLUETOOTH_CONNECT: case NETWORK_BLUETOOTH_DISCONNECT: - { - if (bluetooth->callback != mp_const_none) { - // items[0] is event - // items[1] is remote address - mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.connect.bda), bluetooth->callback_userdata }; - mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); - } - break; + if (bluetooth->callback != mp_const_none) { + // items[0] is event + // items[1] is remote address + mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.connect.bda), bluetooth->callback_userdata }; + mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); } + break; case NETWORK_BLUETOOTH_SCAN_CMPL: case NETWORK_BLUETOOTH_SCAN_DATA: if (bluetooth->callback != mp_const_none) { @@ -1545,10 +1471,8 @@ STATIC void network_bluetooth_gatts_event_handler( esp_ble_gatts_start_service(service->handle); } } - break; - case ESP_GATTS_START_EVT: case ESP_GATTS_STOP_EVT: { @@ -1561,6 +1485,7 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_START_EVT: service->started = true; + ITEM_BEGIN(); size_t len; mp_obj_t *items; mp_obj_get_array(service->chars, &len, &items); @@ -1569,6 +1494,7 @@ STATIC void network_bluetooth_gatts_event_handler( network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); } + ITEM_END(); break; case ESP_GATTS_STOP_EVT: service->started = false; @@ -1587,8 +1513,9 @@ STATIC void network_bluetooth_gatts_event_handler( network_bluetooth_service_obj_t* service = network_bluetooth_item_op(bluetooth->services, NULL, param->add_char.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); if (service != MP_OBJ_NULL) { network_bluetooth_char_obj_t* chr = network_bluetooth_item_op(service->chars, ¶m->add_char.char_uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); - chr->handle = param->add_char.attr_handle; - NETWORK_BLUETOOTH_DEBUG_PRINTF("Setting char handle to %04X, from service handle %04X\n", param->add_char.attr_handle, param->add_char.service_handle); + if (chr != MP_OBJ_NULL) { + chr->handle = param->add_char.attr_handle; + } } else { NETWORK_BLUETOOTH_DEBUG_PRINTF("Service handle %d NOT FOUND\n", param->add_char.service_handle); } @@ -1601,43 +1528,36 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_CONNECT_EVT: case ESP_GATTS_DISCONNECT_EVT: { - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gatts append, q size: %u\n", callback_queue.count); - CALLBACK_QUEUE_BEGIN(); - MP_THREAD_GIL_ENTER(); - callback_data_t* cbdata = cbq_push(); - MP_THREAD_GIL_EXIT(); - assert(cbdata != NULL); + callback_data_t cbdata; if (event == ESP_GATTS_READ_EVT || event == ESP_GATTS_WRITE_EVT) { - cbdata->event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; + cbdata.event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; - cbdata->read.handle = param->read.handle; - cbdata->read.conn_id = param->read.conn_id; - cbdata->read.trans_id = param->read.trans_id; - cbdata->read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); + cbdata.read.handle = param->read.handle; + cbdata.read.conn_id = param->read.conn_id; + cbdata.read.trans_id = param->read.trans_id; + cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); if (event == ESP_GATTS_WRITE_EVT) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Write param len: %d, data: '%*s'\n", param->write.len, param->write.len, param->write.value ); - MP_THREAD_GIL_ENTER(); - cbdata->write.value = m_malloc(param->write.len); // Returns NULL when len == 0 - MP_THREAD_GIL_EXIT(); - if (cbdata->write.value != NULL) { - cbdata->write.value_len = param->write.len; - memcpy(cbdata->write.value, param->write.value, param->write.len); + cbdata.write.value = pvPortMalloc(param->write.len); // Returns NULL when len == 0 + if (cbdata.write.value != NULL) { + cbdata.write.value_len = param->write.len; + memcpy(cbdata.write.value, param->write.value, param->write.len); } else { - cbdata->write.value_len = 0; + cbdata.write.value_len = 0; } } } else if (event == ESP_GATTS_CONNECT_EVT || event == ESP_GATTS_DISCONNECT_EVT) { - cbdata->event = event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT; - cbdata->connect.conn_id = param->connect.conn_id; - memcpy(cbdata->connect.bda, param->connect.remote_bda, ESP_BD_ADDR_LEN); + cbdata.event = event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT; + cbdata.connect.conn_id = param->connect.conn_id; + memcpy(cbdata.connect.bda, param->connect.remote_bda, ESP_BD_ADDR_LEN); bluetooth->conn_id = param->connect.conn_id; bluetooth->gatts_connected = event == ESP_GATTS_CONNECT_EVT; } - CALLBACK_QUEUE_END(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gatts append\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gatts cbq_push\n"); + cbq_push(&cbdata, true); + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gatts cbq_push\n"); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } break; @@ -1682,43 +1602,31 @@ STATIC void network_bluetooth_gap_event_handler( callback_data_t cbdata; bool nq = false; + bool block = false; switch(param->scan_rst.search_evt) { case ESP_GAP_SEARCH_INQ_RES_EVT: { - - MP_THREAD_GIL_ENTER(); - mp_obj_t bda = mp_obj_new_str((const char *)param->scan_rst.bda, ESP_BD_ADDR_LEN, false); - mp_obj_t res = mp_set_lookup(&callback_queue.seen, bda, MP_MAP_LOOKUP); - MP_THREAD_GIL_EXIT(); - if (res == MP_OBJ_NULL) { - MP_THREAD_GIL_ENTER(); - mp_set_lookup(&callback_queue.seen, bda, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); - MP_THREAD_GIL_EXIT(); - uint8_t* adv_name; - uint8_t adv_name_len; - adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); - - memcpy(cbdata.scan_data.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); - MP_THREAD_GIL_ENTER(); - cbdata.scan_data.adv_data = m_malloc(adv_name_len); - MP_THREAD_GIL_EXIT(); - cbdata.scan_data.adv_data_len = adv_name_len; - cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; - if (adv_name_len > 0) { - memcpy(cbdata.scan_data.adv_data, adv_name, adv_name_len); - } - nq = true; - } } - break; + uint8_t* adv_name; + uint8_t adv_name_len; + adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); + + memcpy(cbdata.scan_data.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); + cbdata.scan_data.adv_data = pvPortMalloc(adv_name_len); + cbdata.scan_data.adv_data_len = adv_name_len; + cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; + if (adv_name_len > 0) { + memcpy(cbdata.scan_data.adv_data, adv_name, adv_name_len); + } + nq = true; + break; + } case ESP_GAP_SEARCH_INQ_CMPL_EVT: // scanning done { bluetooth->scanning = false; cbdata.event = NETWORK_BLUETOOTH_SCAN_CMPL; - MP_THREAD_GIL_ENTER(); - mp_set_clear(&callback_queue.seen); - MP_THREAD_GIL_EXIT(); nq = true; + block = true; } break; @@ -1728,15 +1636,9 @@ STATIC void network_bluetooth_gap_event_handler( } if (nq) { - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gap append, q size: %u\n", callback_queue.count); - CALLBACK_QUEUE_BEGIN(); - MP_THREAD_GIL_ENTER(); - callback_data_t* q_data = cbq_push(); - MP_THREAD_GIL_EXIT(); - assert(q_data != NULL); - *q_data = cbdata; - CALLBACK_QUEUE_END(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gap append\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gap cbq_push\n"); + cbq_push(&cbdata, block); + NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gap cbq_push\n"); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } } @@ -1771,7 +1673,9 @@ STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_o network_bluetooth_char_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "BTChar(uuid = "); network_bluetooth_uuid_print(print, &self->uuid); - mp_printf(print, ", perm = %02X, prop = %02X, handle = %04X)", self->perm, self->prop, self->handle); + mp_printf(print, ", perm = %02X, prop = %02X, handle = %04X, value = ", self->perm, self->prop, self->handle); + mp_obj_print_helper(print, self->value, PRINT_REPR); + mp_printf(print, ")"); } STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -1857,16 +1761,24 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { self->services = mp_obj_new_list(0, NULL); } - if (callback_queue_mut == NULL) { - //callback_queue_mut = xSemaphoreCreateBinary(); - //item_mut = xSemaphoreCreateBinary(); - callback_queue_mut = xSemaphoreCreateMutex(); + if (item_mut == NULL) { item_mut = xSemaphoreCreateMutex(); - - xSemaphoreGive(callback_queue_mut); xSemaphoreGive(item_mut); } +#if 1 + if (callback_q == NULL) { + callback_q = xQueueCreateStatic(CALLBACK_QUEUE_SIZE, sizeof(callback_data_t), callback_q_buf, &callback_q_data); + if (callback_q == NULL) { + mp_raise_msg(&mp_type_OSError, "unable to create callback queue"); + } + } else { + xQueueReset(callback_q); + } +#endif + + + NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth services pointer: %p", self->services); if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { @@ -2230,31 +2142,6 @@ STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_scan_stop_obj, network_bluetooth_scan_stop); - - -STATIC mp_obj_t network_bluetooth_dump(mp_obj_t self_in) { - (void)self_in; - cbq_dump(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_dump_obj, network_bluetooth_dump); - -STATIC mp_obj_t network_bluetooth_push(mp_obj_t self_in) { - (void)self_in; - cbq_push(); - cbq_dump(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_push_obj, network_bluetooth_push); - -STATIC mp_obj_t network_bluetooth_pop(mp_obj_t self_in) { - (void)self_in; - cbq_pop(); - cbq_dump(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_pop_obj, network_bluetooth_pop); - STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); @@ -2304,7 +2191,6 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t mp_raise_TypeError("Constructor takes no arguments"); } - mp_set_init(&callback_queue.seen, 0); network_bluetooth_init(self); return MP_OBJ_FROM_PTR(self); } @@ -2324,7 +2210,7 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_service_obj_t *self = network_bluetooth_item_op(bluetooth->services, &uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); + network_bluetooth_service_obj_t *self = network_bluetooth_item_op(bluetooth->services, &uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); NETWORK_BLUETOOTH_DEBUG_PRINTF("find_service returned %p\n", self); if (self != MP_OBJ_NULL) { @@ -2386,7 +2272,9 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m self->perm = args[ARG_perm].u_int; self->prop = args[ARG_prop].u_int; + ITEM_BEGIN(); mp_obj_list_append(service->chars, self); + ITEM_END(); return MP_OBJ_FROM_PTR(self); } @@ -2537,10 +2425,6 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&network_bluetooth_scan_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_is_scanning), NULL }, // handle by attr - // FIXME remove these from production - { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&network_bluetooth_push_obj) }, - { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&network_bluetooth_dump_obj) }, - { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&network_bluetooth_pop_obj) }, // class constants From 717a24c5f08a22b4c76b848d042c8ae6170d8646 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 2 May 2017 12:51:43 -0700 Subject: [PATCH 45/98] esp32/bluetooth_api_proposal.txt: updated to reflect current development --- esp32/bluetooth_api_proposal.txt | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/esp32/bluetooth_api_proposal.txt b/esp32/bluetooth_api_proposal.txt index bcd79a17a..342946e42 100644 --- a/esp32/bluetooth_api_proposal.txt +++ b/esp32/bluetooth_api_proposal.txt @@ -50,12 +50,12 @@ needn't keep reference. You will no longer receive callbacks characteristics att ###### Get a list of current services ```python -currentServices = b.services() +currentServices = b.services ``` ###### Get a list of service characteristics ```python -chars = service.chars() +chars = service.chars ``` @@ -66,9 +66,9 @@ chars = service.chars() ```python def bt_callback(btObj, event, data, userdata): print ("Bluetooth object", btObj) - if event == btObj.CONNECTED: + if event == btObj.CONNECT: print ("connected") - if event == btObj.DISCONNECTED: + if event == btObj.DISCONNECT: print ("disconnected") @@ -82,18 +82,19 @@ Bluetooth.callback(bt_callback, "hello") Event values: * `Bluetooth.CONNECT` Data param is remote addr * `Bluetooth.DISCONNECT` -* `Bluetooth.SCAN_RES` Scan data +* `Bluetooth.SCAN_DATA` Scan data * `Bluetooth.SCAN_CMPL` Scan complete ##### Characteristic Callbacks ```python def char_callback(charObj, event, value, userdata): - print ("Char object", charObj) - if event == btObj.CONNECT: - print ("connected") - if event == btObj.DISCONNECT: - print ("disconnected") + print('charcb ', cb, userdata,' ', end='') + if event == b.READ: + print('Read') + return 'ABCDEFG' + elif event == b.WRITE: + print ('Write', value) Char.callback(cb_function, userdata) ``` @@ -104,7 +105,7 @@ Char.callback(cb_function, userdata) The event type will be one of `Bluetooth.READ` or `Bluetooth.WRITE`. -Characteristics have an internal value, which is _not_ used and _not_ updated when there is a callback, though the callback is free to update or use the value as it sees fit. For `READ` operations (or `WRITE` operations that require a return value) the return value of the callback is sent, which must be a `bytearray`, `str`, or `None`. +Characteristics have an internal value, which is _not_ used and _not_ updated when there is a callback, though the callback is free to update or use the value as it sees fit. For `READ` operations (or `WRITE` operations that require a return value) the return value of the callback is sent, which must be a `bytearray`, `str`, `bytes`, or `None`. ###### Value behavior without a callback @@ -149,3 +150,11 @@ Advertising and scanning cannot be run at the same time ###### Scan stop: `Bluetooth.scan_stop()` + + +###### Scan callback data + +The Bluetooth callback will receive: + +* `Bluetooth.SCAN_DATA` Data will be a 2-tuple of `(remote_address, adv_name)` +* `Bluetooth.SCAN_CMPL` Scan has completed; data will be None From 6e3dfd63fc3e36751bd3b6335b79ca3fec190374 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 3 May 2017 15:49:50 -0700 Subject: [PATCH 46/98] esp32/main.c: heap size back to 32Kib --- esp32/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/main.c b/esp32/main.c index 85f37d646..44cf29434 100644 --- a/esp32/main.c +++ b/esp32/main.c @@ -53,7 +53,7 @@ #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) #define MP_TASK_STACK_SIZE (16 * 1024) #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) -#define MP_TASK_HEAP_SIZE (12 * 1024) +#define MP_TASK_HEAP_SIZE (32 * 1024) STATIC StaticTask_t mp_task_tcb; STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8))); From 71fae46012a45efaef9720ff94a7a69f016ff63e Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 3 May 2017 15:52:27 -0700 Subject: [PATCH 47/98] esp32/network_bluetooth.c: Many changes, much more stable now --- esp32/network_bluetooth.c | 420 +++++++++++++++++++++++++------------- 1 file changed, 274 insertions(+), 146 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 093e0b5e8..ec8d5648f 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -51,21 +51,29 @@ #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -#define EVENT_DEBUG +// #define EVENT_DEBUG #define UUID_LEN 16 +#define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) +#if 1 +# define MALLOC(x) pvPortMalloc(x) +# define FREE(x) vPortFree(x) +#else +# define MALLOC(x) NULL +# define FREE(x) +#endif const mp_obj_type_t network_bluetooth_type; const mp_obj_type_t network_bluetooth_service_type; const mp_obj_type_t network_bluetooth_characteristic_type; -SemaphoreHandle_t item_mut; +STATIC SemaphoreHandle_t item_mut; +STATIC bool network_bluetooth_bt_controller_enabled = false; #define MP_OBJ_IS_BT_DATATYPE(O) (MP_OBJ_IS_STR_OR_BYTES(O) || MP_OBJ_IS_TYPE(O, &mp_type_bytearray) || (O == mp_const_none)) -#define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) #define ITEM_BEGIN() assert(xSemaphoreTake(item_mut, portMAX_DELAY) == pdTRUE) #define ITEM_END() xSemaphoreGive(item_mut) @@ -94,6 +102,7 @@ typedef struct { mp_obj_t chars; // list bool started; + bool valid; } network_bluetooth_service_obj_t; @@ -103,6 +112,7 @@ typedef struct { typedef struct { mp_obj_base_t base; esp_bt_uuid_t uuid; + esp_gatt_perm_t perm; esp_gatt_char_prop_t prop; esp_attr_control_t control; @@ -126,9 +136,11 @@ typedef struct { bool advertising; bool scanning; bool gatts_connected; + bool gattc_connected; uint16_t conn_id; - esp_gatt_if_t interface; + esp_gatt_if_t gatts_interface; + esp_gatt_if_t gattc_interface; esp_ble_adv_params_t adv_params; @@ -143,47 +155,51 @@ typedef struct { } network_bluetooth_obj_t; // Singleton -STATIC network_bluetooth_obj_t network_bluetooth_singleton = { - .base = { &network_bluetooth_type }, - .state = NETWORK_BLUETOOTH_STATE_DEINIT, - .advertising = false, - .scanning = false, - .gatts_connected = false, - .conn_id = 0, - .interface = ESP_GATT_IF_NONE, - .adv_params = { - .adv_int_min = 1280 * 1.6, - .adv_int_max = 1280 * 1.6, - .adv_type = ADV_TYPE_IND, - .own_addr_type = BLE_ADDR_TYPE_PUBLIC, - .peer_addr = { 0,0,0,0,0,0 }, - .peer_addr_type = BLE_ADDR_TYPE_PUBLIC, - .channel_map = ADV_CHNL_ALL, - .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, - }, - .adv_data = { - .set_scan_rsp = false, - .include_name = false, - .include_txpower = false, - .min_interval = 1280 * 1.6, - .max_interval = 1280 * 1.6, - .appearance = 0, - .p_manufacturer_data = NULL, - .manufacturer_len = 0, - .p_service_data = NULL, - .service_data_len = 0, - .p_service_uuid = 0, - .flag = 0 - }, - .services = MP_OBJ_NULL, - .callback = mp_const_none, - .callback_userdata = mp_const_none, - - -}; +STATIC network_bluetooth_obj_t* network_bluetooth_singleton = NULL; + STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { - return &network_bluetooth_singleton; + + if (network_bluetooth_singleton == NULL) { + network_bluetooth_singleton = m_new_obj(network_bluetooth_obj_t); + + network_bluetooth_singleton->base.type = &network_bluetooth_type; + + network_bluetooth_singleton->state = NETWORK_BLUETOOTH_STATE_DEINIT; + network_bluetooth_singleton->advertising = false; + network_bluetooth_singleton->scanning = false; + network_bluetooth_singleton->gatts_connected = false; + network_bluetooth_singleton->gattc_connected = false; + network_bluetooth_singleton->conn_id = 0; + network_bluetooth_singleton->gatts_interface = ESP_GATT_IF_NONE; + network_bluetooth_singleton->gattc_interface = ESP_GATT_IF_NONE; + network_bluetooth_singleton->adv_params.adv_int_min = 1280 * 1.6; + network_bluetooth_singleton->adv_params.adv_int_max = 1280 * 1.6; + network_bluetooth_singleton->adv_params.adv_type = ADV_TYPE_IND; + network_bluetooth_singleton->adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC; + network_bluetooth_singleton->adv_params.peer_addr_type = BLE_ADDR_TYPE_PUBLIC; + network_bluetooth_singleton->adv_params.channel_map = ADV_CHNL_ALL; + network_bluetooth_singleton->adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY; + network_bluetooth_singleton->adv_data.set_scan_rsp = false; + network_bluetooth_singleton->adv_data.include_name = false; + network_bluetooth_singleton->adv_data.include_txpower = false; + network_bluetooth_singleton->adv_data.min_interval = 1280 * 1.6; + network_bluetooth_singleton->adv_data.max_interval = 1280 * 1.6; + network_bluetooth_singleton->adv_data.appearance = 0; + network_bluetooth_singleton->adv_data.p_manufacturer_data = NULL; + network_bluetooth_singleton->adv_data.manufacturer_len = 0; + network_bluetooth_singleton->adv_data.p_service_data = NULL; + network_bluetooth_singleton->adv_data.service_data_len = 0; + network_bluetooth_singleton->adv_data.p_service_uuid = 0; + network_bluetooth_singleton->adv_data.flag = 0; + + network_bluetooth_singleton->callback = mp_const_none; + network_bluetooth_singleton->callback_userdata = mp_const_none; + + network_bluetooth_singleton->services = mp_obj_new_list(0, NULL); + memset(network_bluetooth_singleton->adv_params.peer_addr, 0, sizeof(network_bluetooth_singleton->adv_params.peer_addr)); + } + return network_bluetooth_singleton; } typedef struct { @@ -217,7 +233,7 @@ typedef struct { uint16_t conn_id; uint32_t trans_id; bool need_rsp; - uint8_t* value; + uint8_t* value; // Need to free this! size_t value_len; } write; }; @@ -225,11 +241,16 @@ typedef struct { } callback_data_t; #define CALLBACK_QUEUE_SIZE 10 + STATIC QueueHandle_t callback_q = NULL; -STATIC uint8_t callback_q_buf[sizeof(callback_data_t) * CALLBACK_QUEUE_SIZE]; -STATIC StaticQueue_t callback_q_data; + +STATIC size_t cbq_count() { + return uxQueueMessagesWaiting(callback_q); +} + STATIC bool cbq_push (const callback_data_t* data, bool block) { + NETWORK_BLUETOOTH_DEBUG_PRINTF("push: Qsize: %u\n", cbq_count()); return xQueueSend(callback_q, data, block ? portMAX_DELAY : 10 / portTICK_PERIOD_MS) == pdPASS; } @@ -237,12 +258,6 @@ STATIC bool cbq_pop (callback_data_t* data) { return xQueueReceive(callback_q, data, 0) == pdPASS; } -/* FIXME -- not used? -STATIC size_t cbq_count() { - return uxQueueMessagesWaiting(callback_q); -} -*/ - STATIC void dumpBuf(const uint8_t *buf, size_t len) { while(len--) printf("%02X ", *buf++); @@ -1267,13 +1282,13 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t case ESP_GAP_BLE_SCAN_RESULT_EVT: { const char * search_events[7] = { - "INQ_RES_EVT", - "INQ_CMPL_EVT", - "DISC_RES_EVT", - "DISC_BLE_RES_EVT", - "DISC_CMPL_EVT", - "DI_DISC_CMPL_EVT", - "SEARCH_CANCEL_CMPL_EVT" + "INQ_RES", + "INQ_CMPL", + "DISC_RES", + "DISC_BLE_RES", + "DISC_CMPL", + "DI_DISC_CMPL", + "SEARCH_CANCEL_CMPL" }; const char * dev_types[] = { "", "BREDR", "BLE", "DUMO" }; @@ -1348,13 +1363,14 @@ NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + return mp_const_none; + } callback_data_t cbdata; while(true) { - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> cbq_pop\n"); bool got_data = cbq_pop(&cbdata); - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< cbq_pop\n"); if (!got_data) { return mp_const_none; } @@ -1365,7 +1381,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { case NETWORK_BLUETOOTH_WRITE: { network_bluetooth_char_obj_t* self = network_bluetooth_item_op(bluetooth->services, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES); - NETWORK_BLUETOOTH_DEBUG_PRINTF("MP_OBJ_NULL: %p, chr: %p\n", MP_OBJ_NULL, self); + if (self != MP_OBJ_NULL) { @@ -1397,8 +1413,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { esp_ble_gatts_send_response(bluetooth->interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); } if (cbdata.event == NETWORK_BLUETOOTH_WRITE) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Freeing using vPortFree(%p)\n", cbdata.write.value); - vPortFree(cbdata.write.value); + FREE(cbdata.write.value); } } } @@ -1420,6 +1435,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { if (cbdata.event == NETWORK_BLUETOOTH_SCAN_DATA) { mp_obj_t scan_data_args[] = {mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.scan_data.bda), mp_obj_new_bytearray(cbdata.scan_data.adv_data_len, cbdata.scan_data.adv_data) } ; data = mp_obj_new_tuple(2, scan_data_args); + FREE(cbdata.scan_data.adv_data); } mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), data, bluetooth->callback_userdata }; @@ -1440,9 +1456,31 @@ STATIC void network_bluetooth_gattc_event_handler( esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) { + + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + return; + } #ifdef EVENT_DEBUG gattc_event_dump(event, gattc_if, param); #endif + switch(event) { + case ESP_GATTC_REG_EVT: + bluetooth->gattc_interface = gattc_if; + break; + + case ESP_GATTS_CANCEL_OPEN_EVT: + { + bluetooth->gattc_connected = true; + } + break; + + case ESP_GATTS_CANCEL_CLOSE_EVT: + { + bluetooth->gattc_connected = false; + } + break; + } } STATIC void network_bluetooth_gatts_event_handler( @@ -1451,6 +1489,9 @@ STATIC void network_bluetooth_gatts_event_handler( esp_ble_gatts_cb_param_t *param) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + return; + } #ifdef EVENT_DEBUG gatts_event_dump(event, gatts_if, param); @@ -1539,7 +1580,8 @@ STATIC void network_bluetooth_gatts_event_handler( cbdata.read.trans_id = param->read.trans_id; cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); if (event == ESP_GATTS_WRITE_EVT) { - cbdata.write.value = pvPortMalloc(param->write.len); // Returns NULL when len == 0 + cbdata.write.value = MALLOC(param->write.len); // Returns NULL when len == 0 + if (cbdata.write.value != NULL) { cbdata.write.value_len = param->write.len; memcpy(cbdata.write.value, param->write.value, param->write.len); @@ -1555,9 +1597,7 @@ STATIC void network_bluetooth_gatts_event_handler( bluetooth->gatts_connected = event == ESP_GATTS_CONNECT_EVT; } - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gatts cbq_push\n"); cbq_push(&cbdata, true); - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gatts cbq_push\n"); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } break; @@ -1582,6 +1622,9 @@ STATIC void network_bluetooth_gap_event_handler( #endif network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + return; + } switch (event) { case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: @@ -1591,7 +1634,7 @@ STATIC void network_bluetooth_gap_event_handler( break; case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: - // doesn't seem we ever get this, in practice + // FIXME -- send event? if (param->adv_stop_cmpl.status == ESP_BT_STATUS_SUCCESS) { bluetooth->scanning = false; } @@ -1608,15 +1651,20 @@ STATIC void network_bluetooth_gap_event_handler( { uint8_t* adv_name; uint8_t adv_name_len; + + cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); memcpy(cbdata.scan_data.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); - cbdata.scan_data.adv_data = pvPortMalloc(adv_name_len); - cbdata.scan_data.adv_data_len = adv_name_len; - cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; - if (adv_name_len > 0) { + cbdata.scan_data.adv_data = MALLOC(adv_name_len); + + if (cbdata.scan_data.adv_data != NULL) { + cbdata.scan_data.adv_data_len = adv_name_len; memcpy(cbdata.scan_data.adv_data, adv_name, adv_name_len); + } else { + cbdata.scan_data.adv_data_len = 0; } + nq = true; break; } @@ -1636,9 +1684,7 @@ STATIC void network_bluetooth_gap_event_handler( } if (nq) { - NETWORK_BLUETOOTH_DEBUG_PRINTF(">> gap cbq_push\n"); cbq_push(&cbdata, block); - NETWORK_BLUETOOTH_DEBUG_PRINTF("<< gap cbq_push\n"); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } } @@ -1655,7 +1701,6 @@ STATIC void network_bluetooth_gap_event_handler( STATIC void network_bluetooth_adv_updated() { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_adv_updated()\n"); network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); esp_ble_gap_stop_advertising(); esp_ble_gap_config_adv_data(&self->adv_data); @@ -1754,51 +1799,51 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m } -STATIC void network_bluetooth_init(mp_obj_t self_in) { +STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { network_bluetooth_obj_t * self = (network_bluetooth_obj_t*)self_in; - if (self->services == MP_OBJ_NULL) { - self->services = mp_obj_new_list(0, NULL); - } - if (item_mut == NULL) { item_mut = xSemaphoreCreateMutex(); xSemaphoreGive(item_mut); } -#if 1 if (callback_q == NULL) { - callback_q = xQueueCreateStatic(CALLBACK_QUEUE_SIZE, sizeof(callback_data_t), callback_q_buf, &callback_q_data); + callback_q = xQueueCreate(CALLBACK_QUEUE_SIZE, sizeof(callback_data_t)); if (callback_q == NULL) { mp_raise_msg(&mp_type_OSError, "unable to create callback queue"); } } else { xQueueReset(callback_q); } -#endif - - - NETWORK_BLUETOOTH_DEBUG_PRINTF("bluetooth services pointer: %p", self->services); - if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); esp_bt_controller_init(&bt_cfg); - switch(esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { - case ESP_OK: - NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_bt_controller_enable() OK\n"); - break; - default: - mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); - break; + // FIXME + // + // Looks like this needs to be globally idempotent + // because: + // 1) You can't disable BT once enabled + // 2) You can't call this twice for enabling + // + // https://github.com/espressif/esp-idf/issues/405#issuecomment-299045124 + + if (!network_bluetooth_bt_controller_enabled) { + network_bluetooth_bt_controller_enabled = true; + switch(esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { + case ESP_OK: + break; + default: + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); + break; + } } switch(esp_bluedroid_init()) { case ESP_OK: - NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_bluedroid_init() OK\nn"); break; default: mp_raise_msg(&mp_type_OSError, "esp_bluedroid_init() failed"); @@ -1807,7 +1852,6 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { } switch(esp_bluedroid_enable()) { case ESP_OK: - NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_bluedroid_enable() OK\nn"); break; default: mp_raise_msg(&mp_type_OSError, "esp_bluedroid_enable() failed"); @@ -1821,21 +1865,19 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { // FIXME, this is hardcoded switch(esp_ble_gatts_app_register(0)) { case ESP_OK: - NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gatts_app_register success\n"); break; default: - NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gatts_app_register ERROR\n"); + mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() failed"); break; } // FIXME, this is hardcoded switch(esp_ble_gattc_app_register(1)) { case ESP_OK: - NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gattc_app_register success\n"); break; default: - NETWORK_BLUETOOTH_DEBUG_PRINTF("esp_ble_gattc_app_register ERROR\n"); + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_register() failed"); break; } self->state = NETWORK_BLUETOOTH_STATE_INIT; @@ -1843,11 +1885,18 @@ STATIC void network_bluetooth_init(mp_obj_t self_in) { } else { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); } + return mp_const_none; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_init); STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { - network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_ble_settings(self = %p) n_args = %d\n", self, n_args); + network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); + NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_ble_settings(self = %p) n_args = %d\n", bluetooth, n_args); + + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); + } + bool changed = false; bool unset_adv_man_name = false; @@ -1958,45 +2007,46 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po } } + // update esp_ble_adv_params_t if (args[ARG_int_min].u_int != -1) { - self->adv_params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count + bluetooth->adv_params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count changed = true; } if (args[ARG_int_max].u_int != -1) { - self->adv_params.adv_int_max = args[ARG_int_max].u_int * 1.6; + bluetooth->adv_params.adv_int_max = args[ARG_int_max].u_int * 1.6; changed = true; } if (args[ARG_type].u_int != -1) { - self->adv_params.adv_type = args[ARG_type].u_int; + bluetooth->adv_params.adv_type = args[ARG_type].u_int; changed = true; } if (args[ARG_own_addr_type].u_int != -1) { - self->adv_params.own_addr_type = args[ARG_own_addr_type].u_int; + bluetooth->adv_params.own_addr_type = args[ARG_own_addr_type].u_int; changed = true; } if (peer_addr_buf.buf != NULL) { - memcpy(self->adv_params.peer_addr, peer_addr_buf.buf, ESP_BD_ADDR_LEN); + memcpy(bluetooth->adv_params.peer_addr, peer_addr_buf.buf, ESP_BD_ADDR_LEN); changed = true; } if (args[ARG_peer_addr_type].u_int != -1) { - self->adv_params.peer_addr_type = args[ARG_peer_addr_type].u_int; + bluetooth->adv_params.peer_addr_type = args[ARG_peer_addr_type].u_int; changed = true; } if (args[ARG_channel_map].u_int != -1) { - self->adv_params.channel_map = args[ARG_channel_map].u_int; + bluetooth->adv_params.channel_map = args[ARG_channel_map].u_int; changed = true; } if (args[ARG_filter_policy].u_int != -1) { - self->adv_params.adv_filter_policy = args[ARG_filter_policy].u_int; + bluetooth->adv_params.adv_filter_policy = args[ARG_filter_policy].u_int; changed = true; } @@ -2004,72 +2054,72 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po // if (args[ARG_adv_is_scan_rsp].u_obj != NULL) { - self->adv_data.set_scan_rsp = mp_obj_is_true(args[ARG_adv_is_scan_rsp].u_obj); + bluetooth->adv_data.set_scan_rsp = mp_obj_is_true(args[ARG_adv_is_scan_rsp].u_obj); changed = true; } if (unset_adv_dev_name) { esp_ble_gap_set_device_name(""); - self->adv_data.include_name = false; + bluetooth->adv_data.include_name = false; } else if (adv_dev_name_buf.buf != NULL) { esp_ble_gap_set_device_name(adv_dev_name_buf.buf); - self->adv_data.include_name = adv_dev_name_buf.len > 0; + bluetooth->adv_data.include_name = adv_dev_name_buf.len > 0; changed = true; } if (unset_adv_man_name || adv_man_name_buf.buf != NULL) { - if (self->adv_data.p_manufacturer_data != NULL) { + if (bluetooth->adv_data.p_manufacturer_data != NULL) { NETWORK_BLUETOOTH_DEBUG_PRINTF("About to free p_manufacturer_data (2)\n"); - m_free(self->adv_data.p_manufacturer_data); - self->adv_data.p_manufacturer_data = NULL; + FREE(bluetooth->adv_data.p_manufacturer_data); + bluetooth->adv_data.p_manufacturer_data = NULL; } - self->adv_data.manufacturer_len = adv_man_name_buf.len; + bluetooth->adv_data.manufacturer_len = adv_man_name_buf.len; if (adv_man_name_buf.len > 0) { NETWORK_BLUETOOTH_DEBUG_PRINTF("About to call malloc for p_manufacturer_data\n"); - self->adv_data.p_manufacturer_data = m_malloc(adv_man_name_buf.len); - memcpy(self->adv_data.p_manufacturer_data, adv_man_name_buf.buf, adv_man_name_buf.len); + bluetooth->adv_data.p_manufacturer_data = MALLOC(adv_man_name_buf.len); + memcpy(bluetooth->adv_data.p_manufacturer_data, adv_man_name_buf.buf, adv_man_name_buf.len); } changed = true; } if (args[ARG_adv_inc_txpower].u_obj != NULL) { - self->adv_data.include_txpower = mp_obj_is_true(args[ARG_adv_inc_txpower].u_obj); + bluetooth->adv_data.include_txpower = mp_obj_is_true(args[ARG_adv_inc_txpower].u_obj); changed = true; } if (args[ARG_adv_int_min].u_int != -1) { - self->adv_data.min_interval = args[ARG_adv_int_min].u_int; + bluetooth->adv_data.min_interval = args[ARG_adv_int_min].u_int; changed = true; } if (args[ARG_adv_int_max].u_int != -1) { - self->adv_data.max_interval = args[ARG_adv_int_max].u_int; + bluetooth->adv_data.max_interval = args[ARG_adv_int_max].u_int; changed = true; } if (args[ARG_adv_appearance].u_int != -1) { - self->adv_data.appearance = args[ARG_adv_appearance].u_int; + bluetooth->adv_data.appearance = args[ARG_adv_appearance].u_int; changed = true; } if (unset_adv_uuid || adv_uuid_buf.buf != NULL) { - if (self->adv_data.p_service_uuid != NULL) { - m_free(self->adv_data.p_service_uuid ); - self->adv_data.p_service_uuid = NULL; + if (bluetooth->adv_data.p_service_uuid != NULL) { + FREE(bluetooth->adv_data.p_service_uuid ); + bluetooth->adv_data.p_service_uuid = NULL; } - self->adv_data.service_uuid_len = adv_uuid_buf.len; + bluetooth->adv_data.service_uuid_len = adv_uuid_buf.len; if (adv_uuid_buf.len > 0) { - self->adv_data.p_service_uuid = m_malloc(adv_uuid_buf.len); - memcpy(self->adv_data.p_service_uuid, adv_uuid_buf.buf, adv_uuid_buf.len); + bluetooth->adv_data.p_service_uuid = MALLOC(adv_uuid_buf.len); + memcpy(bluetooth->adv_data.p_service_uuid, adv_uuid_buf.buf, adv_uuid_buf.len); } changed = true; } if (args[ARG_adv_flags].u_int != -1) { - self->adv_data.flag = args[ARG_adv_flags].u_int; + bluetooth->adv_data.flag = args[ARG_adv_flags].u_int; changed = true; } @@ -2114,8 +2164,13 @@ STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_arg) { - network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->scanning) { + network_bluetooth_obj_t *bluetooth = MP_OBJ_TO_PTR(self_in); + + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); + } + + if (bluetooth->scanning) { mp_raise_msg(&mp_type_OSError, "already scanning"); } mp_int_t timeout = mp_obj_get_int(timeout_arg); @@ -2156,7 +2211,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_callback_obj, STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_char_indicate()\n"); + network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); + } network_bluetooth_char_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); enum {ARG_value, ARG_need_confirm}; @@ -2186,7 +2245,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_indicate_obj, 1, networ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_make_new, self = %p, n_args = %d, n_kw = %d\n", self, n_args, n_kw ); if (n_args != 0 || n_kw != 0) { mp_raise_TypeError("Constructor takes no arguments"); } @@ -2195,11 +2253,14 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t return MP_OBJ_FROM_PTR(self); } -mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { +STATIC mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_make_new\n"); network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); + } + enum {ARG_uuid, ARG_primary}; static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -2212,15 +2273,13 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ parse_uuid(args[ARG_uuid].u_obj, &uuid); network_bluetooth_service_obj_t *self = network_bluetooth_item_op(bluetooth->services, &uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); - NETWORK_BLUETOOTH_DEBUG_PRINTF("find_service returned %p\n", self); if (self != MP_OBJ_NULL) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Returning extant service for that UUID\n"); return MP_OBJ_FROM_PTR(self); } - NETWORK_BLUETOOTH_DEBUG_PRINTF("Making a new service object\n"); self = m_new_obj(network_bluetooth_service_obj_t); self->base.type = type; self->service_id.id.uuid = uuid; + self->valid = true; parse_uuid(args[ARG_uuid].u_obj, &self->service_id.id.uuid); self->service_id.is_primary = mp_obj_is_true(args[ARG_primary].u_obj); @@ -2234,7 +2293,6 @@ mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_ } STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_characteristic_make_new()\n"); enum {ARG_uuid, ARG_value, ARG_perm, ARG_prop}; static const mp_arg_t allowed_args[] = { @@ -2253,14 +2311,12 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m network_bluetooth_char_obj_t *self = network_bluetooth_item_op(service->chars, &uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); if (self != MP_OBJ_NULL) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Returning extant char for that UUID\n"); return MP_OBJ_FROM_PTR(self); } self = m_new_obj(network_bluetooth_char_obj_t); self->base.type = &network_bluetooth_characteristic_type; - NETWORK_BLUETOOTH_DEBUG_PRINTF("Making a new char object %p\n", self); if (!MP_OBJ_IS_BT_DATATYPE(args[ARG_value].u_obj)) { mp_raise_ValueError("value must be str, bytes, bytearray, or None"); } @@ -2283,10 +2339,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_characteristic_make_new_obj, STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_start()\n"); network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); + } network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; + if (!self->valid) { + mp_raise_msg(&mp_type_OSError, "service invalid"); + } + if (self->started) { return mp_const_none; } @@ -2317,8 +2379,11 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_start_obj, network_bluetooth_service_start); STATIC mp_obj_t network_bluetooth_service_stop(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_stop()\n"); network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!self->valid) { + mp_raise_msg(&mp_type_OSError, "service invalid"); + } if (!self->started || self->handle == 0) { return mp_const_none; } @@ -2328,10 +2393,18 @@ STATIC mp_obj_t network_bluetooth_service_stop(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_stop_obj, network_bluetooth_service_stop); STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_service_close()\n"); - network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); + } + + network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (!self->valid) { + mp_raise_msg(&mp_type_OSError, "service invalid"); + } + network_bluetooth_item_op(bluetooth->services, &self->service_id.id.uuid, 0, NETWORK_BLUETOOTH_DEL_SERVICE); + self->valid = false; if (self->handle != 0) { esp_ble_gatts_delete_service(self->handle); } @@ -2407,7 +2480,61 @@ STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); - // FIXME + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + + if (bluetooth->state == NETWORK_BLUETOOTH_STATE_INIT) { + + bluetooth->state = NETWORK_BLUETOOTH_STATE_DEINIT; + + size_t len; + mp_obj_t *items; + mp_obj_get_array(bluetooth->services, &len, &items); + for(int i = 0; i < len; i++) { + network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; + if (service->handle != 0) { + esp_ble_gatts_delete_service(service->handle); + } + service->valid = false; + } + bluetooth->services = mp_obj_new_list(0, NULL); + + if (bluetooth->gattc_interface != ESP_GATT_IF_NONE) { + esp_ble_gattc_app_unregister(bluetooth->gattc_interface); + } + + if (bluetooth->gatts_interface != ESP_GATT_IF_NONE) { + esp_ble_gatts_app_unregister(bluetooth->gatts_interface); + } + + switch(esp_bluedroid_disable()) { + case ESP_OK: + break; + default: + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_disable() failed"); + break; + } + switch(esp_bluedroid_deinit()) { + case ESP_OK: + break; + default: + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_deinit() failed"); + break; + + } + // FIXME: This fails, with the present IDF + +#if 0 + mp_hal_delay_ms(300); + switch(esp_bt_controller_enable(ESP_BT_MODE_IDLE)) { + case ESP_OK: + break; + default: + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable(idle) failed"); + break; + } +#endif + } + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); @@ -2419,6 +2546,7 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&network_bluetooth_ble_settings_obj) }, { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, From 7e3214a8fe77b2aa1c0c37d3b790794865b4e506 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 5 May 2017 10:15:00 -0700 Subject: [PATCH 48/98] esp32/network_bluetooth.c: Working on adding GATTC connections --- esp32/network_bluetooth.c | 196 ++++++++++++++++++++++++++++++++------ 1 file changed, 165 insertions(+), 31 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index ec8d5648f..3d3c46c22 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -51,7 +51,14 @@ #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -// #define EVENT_DEBUG +#define EVENT_DEBUG + + +#ifdef EVENT_DEBUG +# define EVENT_DEBUG_GATTC +# define EVENT_DEBUG_GATTS +# define EVENT_DEBUG_GAP +#endif #define UUID_LEN 16 #define NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args) @@ -65,7 +72,9 @@ #endif const mp_obj_type_t network_bluetooth_type; -const mp_obj_type_t network_bluetooth_service_type; +const mp_obj_type_t network_bluetooth_connection_type; +const mp_obj_type_t network_bluetooth_gatts_service_type; +const mp_obj_type_t network_bluetooth_gattc_service_type; const mp_obj_type_t network_bluetooth_characteristic_type; STATIC SemaphoreHandle_t item_mut; @@ -86,7 +95,6 @@ typedef enum { NETWORK_BLUETOOTH_DISCONNECT, NETWORK_BLUETOOTH_SCAN_DATA, NETWORK_BLUETOOTH_SCAN_CMPL, - NETWORK_BLUETOOTH_OPEN_RESULT, // characteristic events NETWORK_BLUETOOTH_READ, @@ -94,10 +102,11 @@ typedef enum { } network_bluetooth_event_t; // "Service" +// Structure used for both GATTS and GATTC typedef struct { mp_obj_base_t base; - esp_gatt_srvc_id_t service_id; + esp_gatt_srvc_id_t service_id; uint16_t handle; mp_obj_t chars; // list @@ -107,6 +116,18 @@ typedef struct { } network_bluetooth_service_obj_t; +// "Connection" + +typedef struct { + mp_obj_base_t base; + esp_bd_addr_t bda; + uint16_t conn_id; + uint16_t mtu; + mp_obj_t services; + bool connected; + +} network_bluetooth_connection_obj_t; + // "Char" typedef struct { @@ -136,7 +157,6 @@ typedef struct { bool advertising; bool scanning; bool gatts_connected; - bool gattc_connected; uint16_t conn_id; esp_gatt_if_t gatts_interface; @@ -169,7 +189,6 @@ STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { network_bluetooth_singleton->advertising = false; network_bluetooth_singleton->scanning = false; network_bluetooth_singleton->gatts_connected = false; - network_bluetooth_singleton->gattc_connected = false; network_bluetooth_singleton->conn_id = 0; network_bluetooth_singleton->gatts_interface = ESP_GATT_IF_NONE; network_bluetooth_singleton->gattc_interface = ESP_GATT_IF_NONE; @@ -250,7 +269,7 @@ STATIC size_t cbq_count() { STATIC bool cbq_push (const callback_data_t* data, bool block) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("push: Qsize: %u\n", cbq_count()); + //NETWORK_BLUETOOTH_DEBUG_PRINTF("push: Qsize: %u\n", cbq_count()); return xQueueSend(callback_q, data, block ? portMAX_DELAY : 10 / portTICK_PERIOD_MS) == pdPASS; } @@ -559,7 +578,7 @@ STATIC void gattc_event_dump( { PRINT_STATUS(param->open.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" + ", conn_id = %04X" ", addr = %02X:%02X:%02X:%02X:%02X:%02X" ", mtu = %04X", param->open.conn_id, @@ -910,6 +929,7 @@ STATIC void gattc_event_dump( // do nothing, intentionally break; } +NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); } STATIC void gatts_event_dump( @@ -1410,7 +1430,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { rsp.attr_value.handle = cbdata.read.handle; rsp.attr_value.len = len; memcpy(rsp.attr_value.value, buf.buf, len); - esp_ble_gatts_send_response(bluetooth->interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); + esp_ble_gatts_send_response(bluetooth->gatts_interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); } if (cbdata.event == NETWORK_BLUETOOTH_WRITE) { FREE(cbdata.write.value); @@ -1461,7 +1481,7 @@ STATIC void network_bluetooth_gattc_event_handler( if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { return; } -#ifdef EVENT_DEBUG +#ifdef EVENT_DEBUG_GATTC gattc_event_dump(event, gattc_if, param); #endif switch(event) { @@ -1469,17 +1489,18 @@ STATIC void network_bluetooth_gattc_event_handler( bluetooth->gattc_interface = gattc_if; break; - case ESP_GATTS_CANCEL_OPEN_EVT: + case ESP_GATTC_OPEN_EVT: { - bluetooth->gattc_connected = true; } break; - case ESP_GATTS_CANCEL_CLOSE_EVT: + case ESP_GATTC_CLOSE_EVT: { - bluetooth->gattc_connected = false; } break; + default: + // do nothing, intentionally + break; } } @@ -1493,13 +1514,13 @@ STATIC void network_bluetooth_gatts_event_handler( return; } -#ifdef EVENT_DEBUG +#ifdef EVENT_DEBUG_GATTS gatts_event_dump(event, gatts_if, param); #endif switch (event) { case ESP_GATTS_REG_EVT: - bluetooth->interface = gatts_if; + bluetooth->gatts_interface = gatts_if; break; case ESP_GATTS_CREATE_EVT: @@ -1617,7 +1638,7 @@ STATIC void network_bluetooth_gap_event_handler( esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { -#ifdef EVENT_DEBUG +#ifdef EVENT_DEBUG_GAP gap_event_dump(event, param); #endif @@ -1723,6 +1744,21 @@ STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_o mp_printf(print, ")"); } +STATIC void network_bluetooth_print_bda(const mp_print_t *print, esp_bd_addr_t bda) { + mp_printf(print, "%02X:%02X:%02X:%02X:%02X:%02X", + bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); +} + +STATIC void network_bluetooth_connection_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + + network_bluetooth_connection_obj_t *connection = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "Connection(bda = "); + network_bluetooth_print_bda(print, connection->bda); + mp_printf(print, ", connected = %s", connection->connected ? "True" : "False"); + mp_printf(print, ")"); +} + + STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); // FIXME @@ -1731,12 +1767,16 @@ STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t se mp_printf(print, ", handle = %04X)", self->handle); } + STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "Bluetooth(params=())", self); #define NETWORK_BLUETOOTH_LF "\n" NETWORK_BLUETOOTH_DEBUG_PRINTF( - "Bluetooth(conn_id = %04X, gatts_connected = %s" + "Bluetooth(conn_id = %04X" NETWORK_BLUETOOTH_LF + ", gatts_connected = %s" NETWORK_BLUETOOTH_LF + ", gatts_if = %u" NETWORK_BLUETOOTH_LF + ", gattc_if = %u" NETWORK_BLUETOOTH_LF ", adv_params = (" "adv_int_min = %u, " NETWORK_BLUETOOTH_LF "adv_int_max = %u, " NETWORK_BLUETOOTH_LF @@ -1750,6 +1790,8 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m , self->conn_id, self->gatts_connected ? "True" : "False", + self->gatts_interface, + self->gattc_interface, (unsigned int)(self->adv_params.adv_int_min / 1.6), (unsigned int)(self->adv_params.adv_int_max / 1.6), self->adv_params.adv_type, @@ -2197,6 +2239,50 @@ STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_scan_stop_obj, network_bluetooth_scan_stop); +STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { + network_bluetooth_obj_t * bluetooth = (network_bluetooth_obj_t *)self_in; + mp_buffer_info_t bda_buf = { 0 }; + + if (!MP_OBJ_IS_TYPE(bda, &mp_type_bytearray)) { + goto NETWORK_BLUETOOTH_connect_BAD_ADX; + } + mp_get_buffer(bda, &bda_buf, MP_BUFFER_READ); + if (bda_buf.len != ESP_BD_ADDR_LEN) { + goto NETWORK_BLUETOOTH_connect_BAD_ADX; + } + + network_bluetooth_connection_obj_t* connection = m_new_obj(network_bluetooth_connection_obj_t); + memset(connection, 0, sizeof(network_bluetooth_connection_obj_t)); + connection->base.type = &network_bluetooth_connection_type; + memcpy(connection->bda, bda_buf.buf, ESP_BD_ADDR_LEN); + + + NETWORK_BLUETOOTH_DEBUG_PRINTF("Calling open with IF=%u\n", bluetooth->gattc_interface); + esp_ble_gattc_open(bluetooth->gattc_interface, connection->bda, true); + + return connection; + +NETWORK_BLUETOOTH_connect_BAD_ADX: + mp_raise_ValueError("bda must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_connect_obj, network_bluetooth_connect); + + +STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; + if (!check_locals_dict(connection, attr, dest)) { + switch(attr) { + case MP_QSTR_is_connected: + if (dest[0] == MP_OBJ_NULL) { // load + dest[0] = connection->connected ? mp_const_true : mp_const_false; + } else if (dest[1] != MP_OBJ_NULL) { // store + dest[0] = MP_OBJ_NULL; + } + } + } +} + + STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); @@ -2238,7 +2324,7 @@ STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *p NETWORK_BLUETOOTH_DEBUG_PRINTF("need confirmations: %s\n", args[ARG_need_confirm].u_bool ? "True" : "False"); mp_buffer_info_t buf; mp_get_buffer(args[ARG_value].u_obj, &buf, MP_BUFFER_READ); - esp_ble_gatts_send_indicate(bluetooth->interface, bluetooth->conn_id, self->handle, buf.len, buf.buf, args[ARG_need_confirm].u_bool); + esp_ble_gatts_send_indicate(bluetooth->gatts_interface, bluetooth->conn_id, self->handle, buf.len, buf.buf, args[ARG_need_confirm].u_bool); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_indicate_obj, 1, network_bluetooth_char_indicate); @@ -2357,12 +2443,12 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { uint32_t then = mp_hal_ticks_ms(); // Wait for registration - while(bluetooth->interface == ESP_GATT_IF_NONE && mp_hal_ticks_ms() - then < 1000) { + while(bluetooth->gatts_interface == ESP_GATT_IF_NONE && mp_hal_ticks_ms() - then < 1000) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Waiting for BT interface registration ...\n"); mp_hal_delay_ms(100); } - if (bluetooth->interface == ESP_GATT_IF_NONE) { + if (bluetooth->gatts_interface == ESP_GATT_IF_NONE) { mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() has failed"); } @@ -2372,7 +2458,7 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { // 1 for 2800/2801 Service declaration // 1x for each 2803 Char declaration // 1x for each Char desc declaration --- not used - esp_ble_gatts_create_service(bluetooth->interface, &self->service_id, 1 + numChars * 2); + esp_ble_gatts_create_service(bluetooth->gatts_interface, &self->service_id, 1 + numChars * 2); return mp_const_none; } @@ -2539,7 +2625,9 @@ STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_deinit_obj, network_bluetooth_deinit); +// // BLUETOOTH OBJECTS +// STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // instance methods @@ -2547,7 +2635,8 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&network_bluetooth_ble_adv_enable_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_bluetooth_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_service_type) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_bluetooth_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_gatts_service_type) }, { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, @@ -2574,8 +2663,7 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // esp_ble_addr_type_t { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, // esp_ble_adv_channel_t { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, @@ -2627,9 +2715,31 @@ const mp_obj_type_t network_bluetooth_type = { }; -// SERVICE OBJECTS +// +// CONNECTION OBJECTS +// + +STATIC const mp_rom_map_elem_t network_bluetooth_connection_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method +}; + +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_connection_locals_dict, network_bluetooth_connection_locals_dict_table); + + +const mp_obj_type_t network_bluetooth_connection_type = { + { &mp_type_type }, + .name = MP_QSTR_Connection, + .print = network_bluetooth_connection_print, + //.make_new = network_bluetooth_service_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_connection_locals_dict, + .attr = network_bluetooth_connection_attr, +}; -STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { +// +// GATTS SERVICE OBJECTS +// + +STATIC const mp_rom_map_elem_t network_bluetooth_gatts_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_Char), NULL }, // Handled by attr method { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, @@ -2637,18 +2747,42 @@ STATIC const mp_rom_map_elem_t network_bluetooth_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&network_bluetooth_service_close_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(network_bluetooth_service_locals_dict, network_bluetooth_service_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gatts_service_locals_dict, network_bluetooth_gatts_service_locals_dict_table); + +const mp_obj_type_t network_bluetooth_gatts_service_type = { + { &mp_type_type }, + .name = MP_QSTR_GATTSService, + .print = network_bluetooth_service_print, + .make_new = network_bluetooth_service_make_new, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gatts_service_locals_dict, + .attr = network_bluetooth_service_attr, +}; + + +// +// GATTC SERVICE OBJECTS +// + +STATIC const mp_rom_map_elem_t network_bluetooth_gattc_service_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method +}; + +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_service_locals_dict, network_bluetooth_gattc_service_locals_dict_table); + -const mp_obj_type_t network_bluetooth_service_type = { +const mp_obj_type_t network_bluetooth_gattc_service_type = { { &mp_type_type }, - .name = MP_QSTR_Service, + .name = MP_QSTR_GATTCService, .print = network_bluetooth_service_print, .make_new = network_bluetooth_service_make_new, - .locals_dict = (mp_obj_dict_t*)&network_bluetooth_service_locals_dict, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gattc_service_locals_dict, .attr = network_bluetooth_service_attr, }; + +// // CHARACTERISTIC OBJECTS +// STATIC const mp_rom_map_elem_t network_bluetooth_characteristic_locals_dict_table[] = { From 0dc0adbf04c76dc53c3220984f1bafdc3f5cad8f Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 5 May 2017 16:07:44 -0700 Subject: [PATCH 49/98] esp32/bluetooth_api_proposal.txt: Updated api --- esp32/bluetooth_api_proposal.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/bluetooth_api_proposal.txt b/esp32/bluetooth_api_proposal.txt index 342946e42..e184a32fb 100644 --- a/esp32/bluetooth_api_proposal.txt +++ b/esp32/bluetooth_api_proposal.txt @@ -130,7 +130,7 @@ b.ble_settings( adv_is_scan_rsp = False, adv_dev_name = None, adv_man_name = None, - adv_inc_txpower = False, + adv_inc_tx_power = False, adv_int_min = 1280, adv_int_max = 1280, adv_appearance = 0, From 0307f1fdde68e0913a80aeb305e600959cc3c9a0 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 5 May 2017 16:09:05 -0700 Subject: [PATCH 50/98] esp32/network_bluetooth.c: Many changes WRT GATTC --- esp32/network_bluetooth.c | 675 ++++++++++++++++++++++++++------------ 1 file changed, 469 insertions(+), 206 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 3d3c46c22..326741e0b 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -90,17 +90,105 @@ STATIC bool network_bluetooth_bt_controller_enabled = false; // CONSTANTS typedef enum { + + // GATTS + NETWORK_BLUETOOTH_GATTS_CONNECT, + NETWORK_BLUETOOTH_GATTS_DISCONNECT, + + NETWORK_BLUETOOTH_GATTS_CREATE, + NETWORK_BLUETOOTH_GATTS_START, + NETWORK_BLUETOOTH_GATTS_STOP, + NETWORK_BLUETOOTH_GATTS_ADD_CHAR, + // GAP / GATTC events - NETWORK_BLUETOOTH_CONNECT, - NETWORK_BLUETOOTH_DISCONNECT, - NETWORK_BLUETOOTH_SCAN_DATA, - NETWORK_BLUETOOTH_SCAN_CMPL, + NETWORK_BLUETOOTH_GATTC_SCAN_RES, + NETWORK_BLUETOOTH_GATTC_SCAN_CMPL, // Found GATT servers + NETWORK_BLUETOOTH_GATTC_SEARCH_RES, // Found GATTS services + + + NETWORK_BLUETOOTH_GATTC_GET_CHAR, + + NETWORK_BLUETOOTH_GATTC_OPEN, // characteristic events NETWORK_BLUETOOTH_READ, NETWORK_BLUETOOTH_WRITE, + } network_bluetooth_event_t; +typedef struct { + network_bluetooth_event_t event; + union { + + struct { + uint16_t handle; + esp_gatt_srvc_id_t service_id; + } gatts_create; + + struct { + uint16_t service_handle; + } gatts_start_stop; + + struct { + uint16_t service_handle; + uint16_t char_handle; + esp_bt_uuid_t char_uuid; + } gatts_add_char; + + struct { + uint16_t conn_id; + esp_bd_addr_t bda; + } gatts_connect_disconnect; + + struct { + esp_bd_addr_t bda; + uint8_t* adv_data; // Need to free this! + uint8_t adv_data_len; + } gattc_scan_res; + + struct { + uint16_t conn_id; + esp_gatt_srvc_id_t service_id; + } gattc_search_res; + + struct { + uint16_t conn_id; + esp_gatt_srvc_id_t service_id; + esp_gatt_id_t char_id; + esp_gatt_char_prop_t props; + } gattc_get_char; + + struct { + uint16_t conn_id; + uint16_t mtu; + esp_bd_addr_t bda; + + } gattc_open; + + struct { + uint16_t conn_id; + uint16_t handle; + uint32_t trans_id; + bool need_rsp; + } read; + + struct { + uint16_t conn_id; + uint16_t handle; + uint32_t trans_id; + bool need_rsp; + + // Following fields _must_ + // come after the first four above, + // which _must_ match the read struct + + uint8_t* value; // Need to free this! + size_t value_len; + } write; + }; + +} callback_data_t; + // "Service" // Structure used for both GATTS and GATTC typedef struct { @@ -145,7 +233,7 @@ typedef struct { mp_obj_t value; -} network_bluetooth_char_obj_t; +} network_bluetooth_gatts_char_obj_t; // "Bluetooth" Declaration typedef struct { @@ -166,7 +254,9 @@ typedef struct { esp_ble_adv_params_t adv_params; esp_ble_adv_data_t adv_data; - mp_obj_t services; // implemented as a list + mp_obj_t services; // GATTS, implemented as a list + + mp_obj_t connections; // GATTC, implemented as a list mp_obj_t callback; mp_obj_t callback_userdata; @@ -216,49 +306,12 @@ STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { network_bluetooth_singleton->callback_userdata = mp_const_none; network_bluetooth_singleton->services = mp_obj_new_list(0, NULL); + network_bluetooth_singleton->connections = mp_obj_new_list(0, NULL); memset(network_bluetooth_singleton->adv_params.peer_addr, 0, sizeof(network_bluetooth_singleton->adv_params.peer_addr)); } return network_bluetooth_singleton; } -typedef struct { - network_bluetooth_event_t event; - union { - struct { - uint16_t conn_id; - esp_bd_addr_t bda; - } connect; - - struct { - uint16_t conn_id; - esp_bd_addr_t bda; - } disconnect; - - struct { - esp_bd_addr_t bda; - uint8_t* adv_data; // Need to free this! - uint8_t adv_data_len; - } scan_data; - - struct { - uint16_t handle; - uint16_t conn_id; - uint32_t trans_id; - bool need_rsp; - } read; - - struct { - uint16_t handle; - uint16_t conn_id; - uint32_t trans_id; - bool need_rsp; - uint8_t* value; // Need to free this! - size_t value_len; - } write; - }; - -} callback_data_t; - #define CALLBACK_QUEUE_SIZE 10 STATIC QueueHandle_t callback_q = NULL; @@ -268,9 +321,9 @@ STATIC size_t cbq_count() { } -STATIC bool cbq_push (const callback_data_t* data, bool block) { +STATIC bool cbq_push (const callback_data_t* data) { //NETWORK_BLUETOOTH_DEBUG_PRINTF("push: Qsize: %u\n", cbq_count()); - return xQueueSend(callback_q, data, block ? portMAX_DELAY : 10 / portTICK_PERIOD_MS) == pdPASS; + return xQueueSend(callback_q, data, portMAX_DELAY) == pdPASS; } STATIC bool cbq_pop (callback_data_t* data) { @@ -362,14 +415,15 @@ STATIC void network_bluetooth_uuid_print(const mp_print_t *print, const esp_bt_u typedef enum { NETWORK_BLUETOOTH_FIND_SERVICE, + NETWORK_BLUETOOTH_FIND_CONNECTION, + NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE, NETWORK_BLUETOOTH_FIND_CHAR, - NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES, NETWORK_BLUETOOTH_DEL_SERVICE, } item_op_t; -STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle, item_op_t kind) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_item_op, list is %p\n", list); +STATIC mp_obj_t network_bluetooth_item_opx(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle_or_conn_id, esp_bd_addr_t bda, item_op_t kind) { + //NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_item_op, list is %p\n", list); ITEM_BEGIN(); mp_obj_t ret = MP_OBJ_NULL; @@ -379,25 +433,26 @@ STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, ui mp_obj_get_array(list, &len, &items); for(int i = 0; i < len; i++) { switch(kind) { + // These all search a services list case NETWORK_BLUETOOTH_FIND_SERVICE: - case NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES: + case NETWORK_BLUETOOTH_FIND_CHAR: case NETWORK_BLUETOOTH_DEL_SERVICE: { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; - if (kind == NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES) { + if (kind == NETWORK_BLUETOOTH_FIND_CHAR) { size_t char_len; mp_obj_t *char_items; mp_obj_get_array(service->chars, &char_len, &char_items); for(int j = 0; j < char_len; j++) { - network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) char_items[j]; - if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle)) { + network_bluetooth_gatts_char_obj_t* chr = (network_bluetooth_gatts_char_obj_t*) char_items[j]; + if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { ret = chr; goto NETWORK_BLUETOOTH_ITEM_END; } } - } else if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || (uuid == NULL && service->handle == handle)) { + } else if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || (uuid == NULL && service->handle == handle_or_conn_id)) { ret = service; if (kind == NETWORK_BLUETOOTH_DEL_SERVICE) { @@ -410,15 +465,35 @@ STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, ui } break; - case NETWORK_BLUETOOTH_FIND_CHAR: + case NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE: { - network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; - if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle)) { + network_bluetooth_gatts_char_obj_t* chr = (network_bluetooth_gatts_char_obj_t*) items[i]; + if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { ret = chr; goto NETWORK_BLUETOOTH_ITEM_END; } } break; + + case NETWORK_BLUETOOTH_FIND_CONNECTION: + { + network_bluetooth_connection_obj_t* conn = (network_bluetooth_connection_obj_t*) items[i]; +#if 0 + { + int res = memcmp(conn->bda, bda, ESP_BD_ADDR_LEN); + NETWORK_BLUETOOTH_DEBUG_PRINTF("compare "); + network_bluetooth_print_bda(NULL, con->bda); + NETWORK_BLUETOOTH_DEBUG_PRINTF(" to "); + network_bluetooth_print_bda(NULL, bda); + NETWORK_BLUETOOTH_DEBUG_PRINTF(" got %d\n", result); + } +#endif + if ((bda != NULL && memcmp(conn->bda, bda, ESP_BD_ADDR_LEN) == 0) || (bda == NULL && conn->conn_id == handle_or_conn_id)) { + ret = conn; + goto NETWORK_BLUETOOTH_ITEM_END; + } + } + break; } } NETWORK_BLUETOOTH_ITEM_END: @@ -426,6 +501,51 @@ STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, ui return ret; } +STATIC mp_obj_t network_bluetooth_find_service_by_handle(uint16_t handle) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return network_bluetooth_item_opx(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); +} + +STATIC mp_obj_t network_bluetooth_find_connection_by_bda(esp_bd_addr_t bda) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return network_bluetooth_item_opx(bluetooth->connections, NULL, 0, bda, NETWORK_BLUETOOTH_FIND_CONNECTION); +} + +STATIC mp_obj_t network_bluetooth_find_connection_by_conn_id(uint16_t conn_id) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return network_bluetooth_item_opx(bluetooth->connections, NULL, conn_id, NULL, NETWORK_BLUETOOTH_FIND_CONNECTION); +} + +STATIC mp_obj_t network_bluetooth_find_service_by_uuid(esp_bt_uuid_t* uuid) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return network_bluetooth_item_opx(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); +} + +STATIC mp_obj_t network_bluetooth_find_service_in_connection_by_uuid(network_bluetooth_connection_obj_t* connection, esp_bt_uuid_t* uuid) { + return network_bluetooth_item_opx(connection->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); +} + +STATIC mp_obj_t network_bluetooth_find_char_by_handle(uint16_t handle) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return network_bluetooth_item_opx(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_CHAR); +} + +STATIC mp_obj_t network_bluetooth_find_char_in_service_by_uuid(network_bluetooth_service_obj_t* service, esp_bt_uuid_t* uuid) { + return network_bluetooth_item_opx(service->chars, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE); +} + +STATIC mp_obj_t network_bluetooth_del_service_by_uuid(esp_bt_uuid_t* uuid) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return network_bluetooth_item_opx(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_DEL_SERVICE); +} + +STATIC void network_bluetooth_print_bda(const mp_print_t *print, esp_bd_addr_t bda) { + if (print != NULL) { + mp_printf(print, "%02X:%02X:%02X:%02X:%02X:%02X", bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + } else { + printf("%02X:%02X:%02X:%02X:%02X:%02X", bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + } +} STATIC bool check_locals_dict(mp_obj_t self, qstr attr, mp_obj_t *dest) { mp_obj_type_t *type = mp_obj_get_type(self); @@ -529,6 +649,7 @@ STATIC void gattc_event_dump( "ACL", "CANCEL_OPEN", "SRVC_CHG", + "" "ENC_CMPL_CB", "CFG_MTU", "ADV_DATA", @@ -643,7 +764,7 @@ STATIC void gattc_event_dump( { PRINT_STATUS(param->open.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" + ", conn_id = %04X" ", mtu = %04X", param->cfg_mtu.conn_id, param->cfg_mtu.mtu); @@ -654,7 +775,7 @@ STATIC void gattc_event_dump( { PRINT_STATUS(param->search_cmpl.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X", + ", conn_id = %04X", param->search_cmpl.conn_id); } break; @@ -668,7 +789,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->search_res.srvc_id.id.uuid.uuid, param->search_res.srvc_id.id.uuid.len); + network_bluetooth_uuid_print(NULL,¶m->search_res.srvc_id.id.uuid); NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->search_res.srvc_id.id.inst_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->search_res.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); @@ -679,7 +800,7 @@ STATIC void gattc_event_dump( case ESP_GATTC_READ_DESCR_EVT: { PRINT_STATUS(param->read.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X", param->read.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->read.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); @@ -715,7 +836,7 @@ STATIC void gattc_event_dump( case ESP_GATTC_WRITE_DESCR_EVT: { PRINT_STATUS(param->write.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF("conn_id = %04X", param->read.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->read.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); @@ -739,7 +860,7 @@ STATIC void gattc_event_dump( case ESP_GATTC_EXEC_EVT: { PRINT_STATUS(param->exec_cmpl.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF("conn_id = %04X", param->exec_cmpl.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->exec_cmpl.conn_id); } break; @@ -814,19 +935,19 @@ STATIC void gattc_event_dump( case ESP_GATTC_GET_CHAR_EVT: { PRINT_STATUS(param->get_char.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X", param->get_char.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_char.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->get_char.srvc_id.id.uuid.uuid, param->get_char.srvc_id.id.uuid.len); + network_bluetooth_uuid_print(NULL,¶m->get_char.srvc_id.id.uuid); NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_char.srvc_id.id.inst_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_char.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->get_char.char_id.uuid.uuid, param->get_char.char_id.uuid.len); + network_bluetooth_uuid_print(NULL,¶m->get_char.char_id.uuid); NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_char.char_id.inst_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_props = "); @@ -844,7 +965,7 @@ STATIC void gattc_event_dump( case ESP_GATTC_GET_DESCR_EVT: { PRINT_STATUS(param->get_descr.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X", param->get_descr.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_descr.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); @@ -869,7 +990,7 @@ STATIC void gattc_event_dump( case ESP_GATTC_GET_INCL_SRVC_EVT: { PRINT_STATUS(param->get_incl_srvc.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X", param->get_incl_srvc.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_incl_srvc.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); @@ -1378,11 +1499,11 @@ NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); } - #endif // EVENT_DEBUG STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + //NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_callback_queue_handler \n"); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { return mp_const_none; } @@ -1391,17 +1512,82 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { while(true) { bool got_data = cbq_pop(&cbdata); + //NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_callback_queue_handler pop: %s \n", got_data ? "HIT" : "MISS"); if (!got_data) { return mp_const_none; } switch (cbdata.event) { + case NETWORK_BLUETOOTH_GATTS_CREATE: + { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_uuid(&cbdata.gatts_create.service_id.id.uuid); + + if (service != MP_OBJ_NULL) { + service->handle = cbdata.gatts_create.handle; + service->service_id = cbdata.gatts_create.service_id; + esp_ble_gatts_start_service(service->handle); + } + } + break; + + case NETWORK_BLUETOOTH_GATTS_STOP: + case NETWORK_BLUETOOTH_GATTS_START: + { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_start_stop.service_handle); + if (service == MP_OBJ_NULL) { + break; + } + + switch(cbdata.event) { + case NETWORK_BLUETOOTH_GATTS_START: + service->started = true; + + ITEM_BEGIN(); + size_t len; + mp_obj_t *items; + mp_obj_get_array(service->chars, &len, &items); + + for (int i = 0; i < len; i++) { + network_bluetooth_gatts_char_obj_t* chr = (network_bluetooth_gatts_char_obj_t*) items[i]; + esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); + } + ITEM_END(); + break; + + case NETWORK_BLUETOOTH_GATTS_STOP: + service->started = false; + esp_ble_gatts_delete_service(service->handle); + break; + default: + // Nothing, intentionally + break; + } + + } + break; + + + case NETWORK_BLUETOOTH_GATTS_ADD_CHAR: + { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_add_char.service_handle); + if (service != MP_OBJ_NULL) { + network_bluetooth_gatts_char_obj_t* chr = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.gatts_add_char.char_uuid); + if (chr != MP_OBJ_NULL) { + chr->handle = cbdata.gatts_add_char.char_handle; + } + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Service handle %d NOT FOUND\n", cbdata.gatts_add_char.service_handle); + } + } + break; + + + case NETWORK_BLUETOOTH_READ: case NETWORK_BLUETOOTH_WRITE: { - network_bluetooth_char_obj_t* self = network_bluetooth_item_op(bluetooth->services, NULL, cbdata.read.handle, NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICES); - + network_bluetooth_gatts_char_obj_t* self = network_bluetooth_find_char_by_handle(cbdata.read.handle); if (self != MP_OBJ_NULL) { @@ -1439,23 +1625,24 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { } break; - case NETWORK_BLUETOOTH_CONNECT: - case NETWORK_BLUETOOTH_DISCONNECT: + case NETWORK_BLUETOOTH_GATTS_CONNECT: + case NETWORK_BLUETOOTH_GATTS_DISCONNECT: if (bluetooth->callback != mp_const_none) { // items[0] is event // items[1] is remote address - mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.connect.bda), bluetooth->callback_userdata }; + mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.gatts_connect_disconnect.bda), bluetooth->callback_userdata }; mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); } break; - case NETWORK_BLUETOOTH_SCAN_CMPL: - case NETWORK_BLUETOOTH_SCAN_DATA: + + case NETWORK_BLUETOOTH_GATTC_SCAN_CMPL: + case NETWORK_BLUETOOTH_GATTC_SCAN_RES: if (bluetooth->callback != mp_const_none) { mp_obj_t data = mp_const_none; - if (cbdata.event == NETWORK_BLUETOOTH_SCAN_DATA) { - mp_obj_t scan_data_args[] = {mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.scan_data.bda), mp_obj_new_bytearray(cbdata.scan_data.adv_data_len, cbdata.scan_data.adv_data) } ; - data = mp_obj_new_tuple(2, scan_data_args); - FREE(cbdata.scan_data.adv_data); + if (cbdata.event == NETWORK_BLUETOOTH_GATTC_SCAN_RES) { + mp_obj_t scan_res_args[] = {mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), mp_obj_new_bytearray(cbdata.gattc_scan_res.adv_data_len, cbdata.gattc_scan_res.adv_data) } ; + data = mp_obj_new_tuple(2, scan_res_args); + FREE(cbdata.gattc_scan_res.adv_data); } mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), data, bluetooth->callback_userdata }; @@ -1463,6 +1650,53 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { } break; + case NETWORK_BLUETOOTH_GATTC_OPEN: + { + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_bda(cbdata.gattc_open.bda); + +#if 0 + NETWORK_BLUETOOTH_DEBUG_PRINTF("got bda:"); + network_bluetooth_print_bda(NULL, cbdata.gattc_open.bda); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn obj = %p\n", conn); +#endif + if (conn != MP_OBJ_NULL) { + conn->conn_id = cbdata.gattc_open.conn_id; + conn->mtu = cbdata.gattc_open.mtu; + conn->connected = true; + esp_ble_gattc_search_service(bluetooth->gattc_interface, cbdata.gattc_open.conn_id, NULL); + } + } + break; + + case NETWORK_BLUETOOTH_GATTC_SEARCH_RES: + { + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_search_res.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF("search res for connid: %u, conn obj = %p", cbdata.gattc_search_res.conn_id, conn); + network_bluetooth_uuid_print(NULL, &cbdata.gattc_search_res.service_id.id.uuid); + NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); + if (conn != MP_OBJ_NULL) { + network_bluetooth_service_obj_t *service = m_new_obj(network_bluetooth_service_obj_t); + service->base.type = &network_bluetooth_gattc_service_type; + service->valid = true; + service->service_id = cbdata.gattc_search_res.service_id; + mp_obj_list_append(conn->services, service); + esp_ble_gattc_get_characteristic(bluetooth->gattc_interface, conn->conn_id, &service->service_id, NULL); + } + } + break; + + case NETWORK_BLUETOOTH_GATTC_GET_CHAR: + { + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_search_res.conn_id); + if (conn != MP_OBJ_NULL) { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_char.service_id.id.uuid); + if (service != MP_OBJ_NULL) { + network_bluetooth_service_obj_t *char = m_new_obj(network_bluetooth_service_obj_t); + } + } + + } + break; default: // do nothing, intentionally break; @@ -1484,24 +1718,57 @@ STATIC void network_bluetooth_gattc_event_handler( #ifdef EVENT_DEBUG_GATTC gattc_event_dump(event, gattc_if, param); #endif + + callback_data_t cbdata; + bool nq = true; switch(event) { case ESP_GATTC_REG_EVT: bluetooth->gattc_interface = gattc_if; + nq = false; break; case ESP_GATTC_OPEN_EVT: { + cbdata.event = NETWORK_BLUETOOTH_GATTC_OPEN; + cbdata.gattc_open.conn_id = param->open.conn_id; + cbdata.gattc_open.mtu = param->open.mtu; + memcpy(cbdata.gattc_open.bda, param->open.remote_bda, ESP_BD_ADDR_LEN); + } + break; + + case ESP_GATTC_SEARCH_RES_EVT: + { + cbdata.event = NETWORK_BLUETOOTH_GATTC_SEARCH_RES; + cbdata.gattc_search_res.conn_id = param->search_res.conn_id; + cbdata.gattc_search_res.service_id = param->search_res.srvc_id; } break; + case ESP_GATTC_GET_CHAR_EVT: + { + cbdata.event = NETWORK_BLUETOOTH_GATTC_GET_CHAR; + cbdata.gattc_get_char.conn_id = param->get_char.conn_id; + cbdata.gattc_get_char.service_id = param->get_char.srvc_id; + cbdata.gattc_get_char.char_id = param->get_char.char_id; + cbdata.gattc_get_char.props = param->get_char.char_prop; + + } + break; case ESP_GATTC_CLOSE_EVT: { + nq = false; // FIXME remove } break; + default: - // do nothing, intentionally + nq = false; break; } + + if (nq) { + cbq_push(&cbdata); + mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); + } } STATIC void network_bluetooth_gatts_event_handler( @@ -1518,116 +1785,83 @@ STATIC void network_bluetooth_gatts_event_handler( gatts_event_dump(event, gatts_if, param); #endif + callback_data_t cbdata; + bool nq = true; + switch (event) { case ESP_GATTS_REG_EVT: bluetooth->gatts_interface = gatts_if; + nq = false; break; case ESP_GATTS_CREATE_EVT: { - network_bluetooth_service_obj_t* service = network_bluetooth_item_op(bluetooth->services, ¶m->create.service_id.id.uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); - - if (service != MP_OBJ_NULL) { - service->handle = param->create.service_handle; - service->service_id = param->create.service_id; - esp_ble_gatts_start_service(service->handle); - } + cbdata.event = NETWORK_BLUETOOTH_GATTS_CREATE; + cbdata.gatts_create.handle = param->create.service_handle; + cbdata.gatts_create.service_id = param->create.service_id; } break; case ESP_GATTS_START_EVT: case ESP_GATTS_STOP_EVT: { - network_bluetooth_service_obj_t* service = network_bluetooth_item_op(bluetooth->services, NULL, param->start.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); - if (service == MP_OBJ_NULL) { - break; - } - - switch(event) { - case ESP_GATTS_START_EVT: - service->started = true; - - ITEM_BEGIN(); - size_t len; - mp_obj_t *items; - mp_obj_get_array(service->chars, &len, &items); - - for (int i = 0; i < len; i++) { - network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; - esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); - } - ITEM_END(); - break; - case ESP_GATTS_STOP_EVT: - service->started = false; - esp_ble_gatts_delete_service(service->handle); - break; - default: - // Nothing, intentionally - break; - } - + cbdata.event = event == ESP_GATTS_STOP_EVT ? NETWORK_BLUETOOTH_GATTS_STOP : NETWORK_BLUETOOTH_GATTS_START; + cbdata.gatts_start_stop.service_handle = param->start.service_handle; } break; case ESP_GATTS_ADD_CHAR_EVT: { - network_bluetooth_service_obj_t* service = network_bluetooth_item_op(bluetooth->services, NULL, param->add_char.service_handle, NETWORK_BLUETOOTH_FIND_SERVICE); - if (service != MP_OBJ_NULL) { - network_bluetooth_char_obj_t* chr = network_bluetooth_item_op(service->chars, ¶m->add_char.char_uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); - if (chr != MP_OBJ_NULL) { - chr->handle = param->add_char.attr_handle; - } - } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Service handle %d NOT FOUND\n", param->add_char.service_handle); - } + cbdata.event = NETWORK_BLUETOOTH_GATTS_ADD_CHAR; + cbdata.gatts_add_char.service_handle = param->add_char.service_handle; + cbdata.gatts_add_char.char_handle = param->add_char.attr_handle; + cbdata.gatts_add_char.char_uuid = param->add_char.char_uuid; } - break; - case ESP_GATTS_READ_EVT: case ESP_GATTS_WRITE_EVT: - case ESP_GATTS_CONNECT_EVT: - case ESP_GATTS_DISCONNECT_EVT: - { - callback_data_t cbdata; - - if (event == ESP_GATTS_READ_EVT || event == ESP_GATTS_WRITE_EVT) { + cbdata.write.value = MALLOC(param->write.len); // Returns NULL when len == 0 - cbdata.event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; + if (cbdata.write.value != NULL) { + cbdata.write.value_len = param->write.len; + memcpy(cbdata.write.value, param->write.value, param->write.len); + } else { + cbdata.write.value_len = 0; + } - cbdata.read.handle = param->read.handle; - cbdata.read.conn_id = param->read.conn_id; - cbdata.read.trans_id = param->read.trans_id; - cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); - if (event == ESP_GATTS_WRITE_EVT) { - cbdata.write.value = MALLOC(param->write.len); // Returns NULL when len == 0 + // fallthrough intentional + + case ESP_GATTS_READ_EVT: + { + cbdata.event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; - if (cbdata.write.value != NULL) { - cbdata.write.value_len = param->write.len; - memcpy(cbdata.write.value, param->write.value, param->write.len); - } else { - cbdata.write.value_len = 0; - } - } - } else if (event == ESP_GATTS_CONNECT_EVT || event == ESP_GATTS_DISCONNECT_EVT) { - cbdata.event = event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_CONNECT : NETWORK_BLUETOOTH_DISCONNECT; - cbdata.connect.conn_id = param->connect.conn_id; - memcpy(cbdata.connect.bda, param->connect.remote_bda, ESP_BD_ADDR_LEN); - bluetooth->conn_id = param->connect.conn_id; - bluetooth->gatts_connected = event == ESP_GATTS_CONNECT_EVT; - } + cbdata.read.handle = param->read.handle; + cbdata.read.conn_id = param->read.conn_id; + cbdata.read.trans_id = param->read.trans_id; + cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); + } + break; - cbq_push(&cbdata, true); - mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); + case ESP_GATTS_CONNECT_EVT: + case ESP_GATTS_DISCONNECT_EVT: + { + cbdata.event = event == ESP_GATTS_CONNECT_EVT ? NETWORK_BLUETOOTH_GATTS_CONNECT : NETWORK_BLUETOOTH_GATTS_DISCONNECT; + cbdata.gatts_connect_disconnect.conn_id = param->connect.conn_id; + memcpy(cbdata.gatts_connect_disconnect.bda, param->connect.remote_bda, ESP_BD_ADDR_LEN); + bluetooth->conn_id = param->connect.conn_id; + bluetooth->gatts_connected = event == ESP_GATTS_CONNECT_EVT; } break; default: - // Nothing, intentionally + nq = false; break; + } + if (nq) { + cbq_push(&cbdata); + mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } } @@ -1665,47 +1899,43 @@ STATIC void network_bluetooth_gap_event_handler( { callback_data_t cbdata; - bool nq = false; - bool block = false; + bool nq = true; switch(param->scan_rst.search_evt) { case ESP_GAP_SEARCH_INQ_RES_EVT: { uint8_t* adv_name; uint8_t adv_name_len; - cbdata.event = NETWORK_BLUETOOTH_SCAN_DATA; + cbdata.event = NETWORK_BLUETOOTH_GATTC_SCAN_RES; adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); - memcpy(cbdata.scan_data.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); - cbdata.scan_data.adv_data = MALLOC(adv_name_len); + memcpy(cbdata.gattc_scan_res.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); + cbdata.gattc_scan_res.adv_data = MALLOC(adv_name_len); - if (cbdata.scan_data.adv_data != NULL) { - cbdata.scan_data.adv_data_len = adv_name_len; - memcpy(cbdata.scan_data.adv_data, adv_name, adv_name_len); + if (cbdata.gattc_scan_res.adv_data != NULL) { + cbdata.gattc_scan_res.adv_data_len = adv_name_len; + memcpy(cbdata.gattc_scan_res.adv_data, adv_name, adv_name_len); } else { - cbdata.scan_data.adv_data_len = 0; + cbdata.gattc_scan_res.adv_data_len = 0; } - nq = true; break; } case ESP_GAP_SEARCH_INQ_CMPL_EVT: // scanning done { bluetooth->scanning = false; - cbdata.event = NETWORK_BLUETOOTH_SCAN_CMPL; - nq = true; - block = true; + cbdata.event = NETWORK_BLUETOOTH_GATTC_SCAN_CMPL; } break; default: - // Do nothing, intentionally + nq = false; break; } if (nq) { - cbq_push(&cbdata, block); + cbq_push(&cbdata); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } } @@ -1736,7 +1966,7 @@ STATIC void network_bluetooth_adv_updated() { STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - network_bluetooth_char_obj_t *self = MP_OBJ_TO_PTR(self_in); + network_bluetooth_gatts_char_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "BTChar(uuid = "); network_bluetooth_uuid_print(print, &self->uuid); mp_printf(print, ", perm = %02X, prop = %02X, handle = %04X, value = ", self->perm, self->prop, self->handle); @@ -1744,10 +1974,6 @@ STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_o mp_printf(print, ")"); } -STATIC void network_bluetooth_print_bda(const mp_print_t *print, esp_bd_addr_t bda) { - mp_printf(print, "%02X:%02X:%02X:%02X:%02X:%02X", - bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); -} STATIC void network_bluetooth_connection_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -1761,10 +1987,19 @@ STATIC void network_bluetooth_connection_print(const mp_print_t *print, mp_obj_t STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); - // FIXME - mp_printf(print, "Service(uuid = "); + bool gatts = MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_service_type); + if (gatts) { + mp_printf(print, "GATTSService(uuid = "); + } else { + mp_printf(print, "GATTCService(uuid = "); + } network_bluetooth_uuid_print(print, &self->service_id.id.uuid); - mp_printf(print, ", handle = %04X)", self->handle); + + mp_printf(print, ", primary = %s", self->service_id.is_primary ? "True" : "False"); + if (gatts) { + mp_printf(print, ", handle = %04X", self->handle); + } + mp_printf(print, ")"); } @@ -2254,8 +2489,10 @@ STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { network_bluetooth_connection_obj_t* connection = m_new_obj(network_bluetooth_connection_obj_t); memset(connection, 0, sizeof(network_bluetooth_connection_obj_t)); connection->base.type = &network_bluetooth_connection_type; + connection->services = mp_obj_new_list(0, NULL); memcpy(connection->bda, bda_buf.buf, ESP_BD_ADDR_LEN); + mp_obj_list_append(bluetooth->connections, connection); NETWORK_BLUETOOTH_DEBUG_PRINTF("Calling open with IF=%u\n", bluetooth->gattc_interface); esp_ble_gattc_open(bluetooth->gattc_interface, connection->bda, true); @@ -2272,12 +2509,20 @@ STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_ob network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; if (!check_locals_dict(connection, attr, dest)) { switch(attr) { + case MP_QSTR_services: + if (dest[0] == MP_OBJ_NULL) { // load + dest[0] = connection->services; + } else if (dest[1] != MP_OBJ_NULL) { // store + dest[0] = MP_OBJ_NULL; + } + break; case MP_QSTR_is_connected: if (dest[0] == MP_OBJ_NULL) { // load dest[0] = connection->connected ? mp_const_true : mp_const_false; } else if (dest[1] != MP_OBJ_NULL) { // store dest[0] = MP_OBJ_NULL; } + break; } } } @@ -2290,7 +2535,7 @@ STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_callback_obj, 1, 3, network_bluetooth_callback); STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *args) { - network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) args[0]; + network_bluetooth_gatts_char_obj_t* self = (network_bluetooth_gatts_char_obj_t*) args[0]; return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_callback_obj, 1, 3, network_bluetooth_char_callback); @@ -2302,7 +2547,7 @@ STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *p if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); } - network_bluetooth_char_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); + network_bluetooth_gatts_char_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); enum {ARG_value, ARG_need_confirm}; static const mp_arg_t allowed_args[] = { @@ -2314,8 +2559,10 @@ STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *p mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_value].u_obj != MP_OBJ_NULL) { - if (!MP_OBJ_IS_BT_DATATYPE(args[ARG_value].u_obj)) { - mp_raise_ValueError("value must be string, bytes, bytearray, or None"); + if ( !MP_OBJ_IS_STR_OR_BYTES(args[ARG_value].u_obj) && + !MP_OBJ_IS_TYPE(args[ARG_value].u_obj, &mp_type_bytearray) + ) { + mp_raise_ValueError("value must be string, bytes, bytearray"); } } else { args[ARG_value].u_obj = self->value; @@ -2324,7 +2571,9 @@ STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *p NETWORK_BLUETOOTH_DEBUG_PRINTF("need confirmations: %s\n", args[ARG_need_confirm].u_bool ? "True" : "False"); mp_buffer_info_t buf; mp_get_buffer(args[ARG_value].u_obj, &buf, MP_BUFFER_READ); - esp_ble_gatts_send_indicate(bluetooth->gatts_interface, bluetooth->conn_id, self->handle, buf.len, buf.buf, args[ARG_need_confirm].u_bool); + if (buf.len > 0) { + esp_ble_gatts_send_indicate(bluetooth->gatts_interface, bluetooth->conn_id, self->handle, buf.len, buf.buf, args[ARG_need_confirm].u_bool); + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_indicate_obj, 1, network_bluetooth_char_indicate); @@ -2357,17 +2606,16 @@ STATIC mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, si esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_service_obj_t *self = network_bluetooth_item_op(bluetooth->services, &uuid, 0, NETWORK_BLUETOOTH_FIND_SERVICE); + network_bluetooth_service_obj_t *self = network_bluetooth_find_service_by_uuid(&uuid); if (self != MP_OBJ_NULL) { return MP_OBJ_FROM_PTR(self); } self = m_new_obj(network_bluetooth_service_obj_t); self->base.type = type; - self->service_id.id.uuid = uuid; self->valid = true; + self->service_id.id.uuid = uuid; - parse_uuid(args[ARG_uuid].u_obj, &self->service_id.id.uuid); self->service_id.is_primary = mp_obj_is_true(args[ARG_primary].u_obj); self->chars = mp_obj_new_list(0, NULL); @@ -2392,21 +2640,21 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + if (!MP_OBJ_IS_BT_DATATYPE(args[ARG_value].u_obj)) { + mp_raise_ValueError("value must be str, bytes, bytearray, or None"); + } + esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_char_obj_t *self = network_bluetooth_item_op(service->chars, &uuid, 0, NETWORK_BLUETOOTH_FIND_CHAR); + network_bluetooth_gatts_char_obj_t *self = network_bluetooth_find_char_in_service_by_uuid(service, &uuid); if (self != MP_OBJ_NULL) { return MP_OBJ_FROM_PTR(self); } - self = m_new_obj(network_bluetooth_char_obj_t); + self = m_new_obj(network_bluetooth_gatts_char_obj_t); self->base.type = &network_bluetooth_characteristic_type; - if (!MP_OBJ_IS_BT_DATATYPE(args[ARG_value].u_obj)) { - mp_raise_ValueError("value must be str, bytes, bytearray, or None"); - } - self->callback = mp_const_none; self->uuid = uuid; @@ -2489,7 +2737,7 @@ STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { mp_raise_msg(&mp_type_OSError, "service invalid"); } - network_bluetooth_item_op(bluetooth->services, &self->service_id.id.uuid, 0, NETWORK_BLUETOOTH_DEL_SERVICE); + network_bluetooth_del_service_by_uuid(&self->service_id.id.uuid); self->valid = false; if (self->handle != 0) { esp_ble_gatts_delete_service(self->handle); @@ -2499,7 +2747,7 @@ STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); // char attribute handler STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) self_in; + network_bluetooth_gatts_char_obj_t* self = (network_bluetooth_gatts_char_obj_t*) self_in; if (!check_locals_dict(self, attr, dest)) { switch(attr) { @@ -2524,15 +2772,27 @@ STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t // ATTENTION: All the switches below are for read-only attribs! if (dest[0] == MP_OBJ_NULL) { + + // Attributes of GATTS objects only + if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_service_type)) { + switch(attr) { + case MP_QSTR_Char: + dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_characteristic_make_new_obj); + dest[1] = self; + break; + } + } + + // Attributes common to GATTS and GATTC switch(attr) { - case MP_QSTR_Char: - dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_characteristic_make_new_obj); - dest[1] = self; - break; case MP_QSTR_chars: dest[0] = self->chars; break; + + case MP_QSTR_is_primary: + dest[0] = self->service_id.is_primary ? mp_const_true : mp_const_false ; + break; } } } @@ -2646,12 +2906,12 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // class constants // Callback types - { MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_CONNECT) }, - { MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_DISCONNECT) }, + { MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_GATTS_CONNECT) }, + { MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_GATTS_DISCONNECT) }, { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(NETWORK_BLUETOOTH_READ) }, { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(NETWORK_BLUETOOTH_WRITE) }, - { MP_ROM_QSTR(MP_QSTR_SCAN_DATA), MP_ROM_INT(NETWORK_BLUETOOTH_SCAN_DATA) }, - { MP_ROM_QSTR(MP_QSTR_SCAN_CMPL), MP_ROM_INT(NETWORK_BLUETOOTH_SCAN_CMPL) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_RES), MP_ROM_INT(NETWORK_BLUETOOTH_GATTC_SCAN_RES) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_CMPL), MP_ROM_INT(NETWORK_BLUETOOTH_GATTC_SCAN_CMPL) }, // esp_ble_adv_type_t { MP_ROM_QSTR(MP_QSTR_ADV_TYPE_IND), MP_ROM_INT(ADV_TYPE_IND) }, @@ -2720,7 +2980,8 @@ const mp_obj_type_t network_bluetooth_type = { // STATIC const mp_rom_map_elem_t network_bluetooth_connection_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_is_connected), NULL }, // Handled by attr method }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_connection_locals_dict, network_bluetooth_connection_locals_dict_table); @@ -2742,6 +3003,7 @@ const mp_obj_type_t network_bluetooth_connection_type = { STATIC const mp_rom_map_elem_t network_bluetooth_gatts_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_Char), NULL }, // Handled by attr method { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_is_primary), NULL }, // Handled by attr method { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&network_bluetooth_service_close_obj) }, @@ -2765,6 +3027,7 @@ const mp_obj_type_t network_bluetooth_gatts_service_type = { STATIC const mp_rom_map_elem_t network_bluetooth_gattc_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_is_primary), NULL }, // Handled by attr method }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_service_locals_dict, network_bluetooth_gattc_service_locals_dict_table); From 32f29e91b464fcd688f96f82665f18eb7f38a965 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 8 May 2017 15:23:56 -0700 Subject: [PATCH 51/98] esp32/network_bluetooth.c: GATTC nearly done; notifications still broken --- esp32/network_bluetooth.c | 983 +++++++++++++++++++++++++++----------- 1 file changed, 708 insertions(+), 275 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 326741e0b..ea8d0505e 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -75,7 +75,9 @@ const mp_obj_type_t network_bluetooth_type; const mp_obj_type_t network_bluetooth_connection_type; const mp_obj_type_t network_bluetooth_gatts_service_type; const mp_obj_type_t network_bluetooth_gattc_service_type; -const mp_obj_type_t network_bluetooth_characteristic_type; +const mp_obj_type_t network_bluetooth_gatts_char_type; +const mp_obj_type_t network_bluetooth_gattc_char_type; +const mp_obj_type_t network_bluetooth_gattc_descr_type; STATIC SemaphoreHandle_t item_mut; STATIC bool network_bluetooth_bt_controller_enabled = false; @@ -94,7 +96,7 @@ typedef enum { // GATTS NETWORK_BLUETOOTH_GATTS_CONNECT, NETWORK_BLUETOOTH_GATTS_DISCONNECT, - + NETWORK_BLUETOOTH_GATTS_CREATE, NETWORK_BLUETOOTH_GATTS_START, NETWORK_BLUETOOTH_GATTS_STOP, @@ -107,12 +109,14 @@ typedef enum { NETWORK_BLUETOOTH_GATTC_GET_CHAR, + NETWORK_BLUETOOTH_GATTC_GET_DESCR, NETWORK_BLUETOOTH_GATTC_OPEN, // characteristic events NETWORK_BLUETOOTH_READ, NETWORK_BLUETOOTH_WRITE, + NETWORK_BLUETOOTH_NOTIFY, } network_bluetooth_event_t; @@ -124,7 +128,7 @@ typedef struct { uint16_t handle; esp_gatt_srvc_id_t service_id; } gatts_create; - + struct { uint16_t service_handle; } gatts_start_stop; @@ -158,6 +162,13 @@ typedef struct { esp_gatt_char_prop_t props; } gattc_get_char; + struct { + uint16_t conn_id; + esp_gatt_srvc_id_t service_id; + esp_gatt_id_t char_id; + esp_gatt_id_t descr_id; + } gattc_get_descr; + struct { uint16_t conn_id; uint16_t mtu; @@ -181,19 +192,37 @@ typedef struct { // Following fields _must_ // come after the first four above, // which _must_ match the read struct - + uint8_t* value; // Need to free this! size_t value_len; } write; + + struct { + uint16_t conn_id; + + esp_gatt_srvc_id_t service_id; + esp_gatt_id_t char_id; + esp_gatt_id_t descr_id; + bool need_rsp; + + uint8_t* value; // Need to free this! + size_t value_len; + } notify; }; } callback_data_t; +typedef struct { + uint8_t* value; // Need to free this! + size_t value_len; +} read_write_data_t; + // "Service" // Structure used for both GATTS and GATTC typedef struct { mp_obj_base_t base; + mp_obj_t connection; esp_gatt_srvc_id_t service_id; uint16_t handle; @@ -220,20 +249,31 @@ typedef struct { typedef struct { mp_obj_base_t base; - esp_bt_uuid_t uuid; + mp_obj_t service; - esp_gatt_perm_t perm; - esp_gatt_char_prop_t prop; - esp_attr_control_t control; + esp_gatt_id_t char_id; // common + esp_gatt_char_prop_t prop; // common - uint16_t handle; + mp_obj_t descriptors; // GATTC - mp_obj_t callback; - mp_obj_t callback_userdata; + esp_gatt_perm_t perm; // GATTS - mp_obj_t value; + uint16_t handle; // GATTS + mp_obj_t value; // GATTS -} network_bluetooth_gatts_char_obj_t; + mp_obj_t callback; // common + mp_obj_t callback_userdata; // common + +} network_bluetooth_char_obj_t; + +// "Descriptor" + +typedef struct { + mp_obj_base_t base; + mp_obj_t chr; + + esp_gatt_id_t descr_id; // common +} network_bluetooth_descr_obj_t; // "Bluetooth" Declaration typedef struct { @@ -301,7 +341,7 @@ STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { network_bluetooth_singleton->adv_data.service_data_len = 0; network_bluetooth_singleton->adv_data.p_service_uuid = 0; network_bluetooth_singleton->adv_data.flag = 0; - + network_bluetooth_singleton->callback = mp_const_none; network_bluetooth_singleton->callback_userdata = mp_const_none; @@ -315,6 +355,7 @@ STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { #define CALLBACK_QUEUE_SIZE 10 STATIC QueueHandle_t callback_q = NULL; +STATIC QueueHandle_t read_write_q = NULL; STATIC size_t cbq_count() { return uxQueueMessagesWaiting(callback_q); @@ -345,7 +386,7 @@ STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { // LSB first *uuid_ptr++ = arg_uuid & 0xff; arg_uuid >>= 8; - } + } } else if (mp_obj_get_type(src) != &mp_type_bytearray) { goto PARSE_UUID_BAD; } else { @@ -368,12 +409,12 @@ static void uuid_to_uuid128(const esp_bt_uuid_t* in, esp_bt_uuid_t* out) { static const uint8_t base_uuid[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; - + if (in->len == 16) { *out = *in; return; } - + out->len = 16; memcpy(out->uuid.uuid128, base_uuid, MP_ARRAY_SIZE(base_uuid)); @@ -394,9 +435,9 @@ STATIC bool uuid_eq(const esp_bt_uuid_t* a, const esp_bt_uuid_t* b) { return memcmp(&a->uuid.uuid128, &b->uuid.uuid128, a->len) == 0; } -STATIC void network_bluetooth_uuid_print(const mp_print_t *print, const esp_bt_uuid_t* uuid) { +STATIC void network_bluetooth_gatt_id_print(const mp_print_t *print, const esp_gatt_id_t* gatt_id) { esp_bt_uuid_t uuid128; - uuid_to_uuid128(uuid, &uuid128); + uuid_to_uuid128(&gatt_id->uuid, &uuid128); for(int i = 0; i < uuid128.len; i++) { if (print != NULL) { mp_printf(print, "%02X", uuid128.uuid.uuid128[i]); @@ -411,6 +452,12 @@ STATIC void network_bluetooth_uuid_print(const mp_print_t *print, const esp_bt_u } } } + if (print != NULL) { + mp_printf(print, ", inst_id = %02X ", gatt_id->inst_id); + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X ", gatt_id->inst_id); + } + } typedef enum { @@ -445,8 +492,8 @@ STATIC mp_obj_t network_bluetooth_item_opx(mp_obj_t list, esp_bt_uuid_t* uuid, u mp_obj_t *char_items; mp_obj_get_array(service->chars, &char_len, &char_items); for(int j = 0; j < char_len; j++) { - network_bluetooth_gatts_char_obj_t* chr = (network_bluetooth_gatts_char_obj_t*) char_items[j]; - if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { + network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) char_items[j]; + if ((uuid != NULL && uuid_eq(&chr->char_id.uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { ret = chr; goto NETWORK_BLUETOOTH_ITEM_END; } @@ -467,8 +514,8 @@ STATIC mp_obj_t network_bluetooth_item_opx(mp_obj_t list, esp_bt_uuid_t* uuid, u case NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE: { - network_bluetooth_gatts_char_obj_t* chr = (network_bluetooth_gatts_char_obj_t*) items[i]; - if ((uuid != NULL && uuid_eq(&chr->uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { + network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; + if ((uuid != NULL && uuid_eq(&chr->char_id.uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { ret = chr; goto NETWORK_BLUETOOTH_ITEM_END; } @@ -525,6 +572,11 @@ STATIC mp_obj_t network_bluetooth_find_service_in_connection_by_uuid(network_blu return network_bluetooth_item_opx(connection->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); } +STATIC mp_obj_t network_bluetooth_find_char_by_uuid(esp_bt_uuid_t* uuid) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return network_bluetooth_item_opx(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR); +} + STATIC mp_obj_t network_bluetooth_find_char_by_handle(uint16_t handle) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); return network_bluetooth_item_opx(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_CHAR); @@ -563,54 +615,54 @@ STATIC bool check_locals_dict(mp_obj_t self, qstr attr, mp_obj_t *dest) { #ifdef EVENT_DEBUG - typedef struct { - uint8_t id; - const char * name; - } gatt_status_name_t; +typedef struct { + uint8_t id; + const char * name; +} gatt_status_name_t; STATIC const gatt_status_name_t gatt_status_names[] = { - {0x00, "OK"}, - {0x01, "INVALID_HANDLE"}, - {0x02, "READ_NOT_PERMIT"}, - {0x03, "WRITE_NOT_PERMIT"}, - {0x04, "INVALID_PDU"}, - {0x05, "INSUF_AUTHENTICATION"}, - {0x06, "REQ_NOT_SUPPORTED"}, - {0x07, "INVALID_OFFSET"}, - {0x08, "INSUF_AUTHORIZATION"}, - {0x09, "PREPARE_Q_FULL"}, - {0x0a, "NOT_FOUND"}, - {0x0b, "NOT_LONG"}, - {0x0c, "INSUF_KEY_SIZE"}, - {0x0d, "INVALID_ATTR_LEN"}, - {0x0e, "ERR_UNLIKELY"}, - {0x0f, "INSUF_ENCRYPTION"}, - {0x10, "UNSUPPORT_GRP_TYPE"}, - {0x11, "INSUF_RESOURCE"}, - {0x80, "NO_RESOURCES"}, - {0x81, "INTERNAL_ERROR"}, - {0x82, "WRONG_STATE"}, - {0x83, "DB_FULL"}, - {0x84, "BUSY"}, - {0x85, "ERROR"}, - {0x86, "CMD_STARTED"}, - {0x87, "ILLEGAL_PARAMETER"}, - {0x88, "PENDING"}, - {0x89, "AUTH_FAIL"}, - {0x8a, "MORE"}, - {0x8b, "INVALID_CFG"}, - {0x8c, "SERVICE_STARTED"}, - {0x8d, "ENCRYPED_NO_MITM"}, - {0x8e, "NOT_ENCRYPTED"}, - {0x8f, "CONGESTED"}, - {0x90, "DUP_REG"}, - {0x91, "ALREADY_OPEN"}, - {0x92, "CANCEL"}, - {0xfd, "CCC_CFG_ERR"}, - {0xfe, "PRC_IN_PROGRESS"}, - {0xff, "OUT_OF_RANGE"}, - {0x00, NULL}, - }; + {0x00, "OK"}, + {0x01, "INVALID_HANDLE"}, + {0x02, "READ_NOT_PERMIT"}, + {0x03, "WRITE_NOT_PERMIT"}, + {0x04, "INVALID_PDU"}, + {0x05, "INSUF_AUTHENTICATION"}, + {0x06, "REQ_NOT_SUPPORTED"}, + {0x07, "INVALID_OFFSET"}, + {0x08, "INSUF_AUTHORIZATION"}, + {0x09, "PREPARE_Q_FULL"}, + {0x0a, "NOT_FOUND"}, + {0x0b, "NOT_LONG"}, + {0x0c, "INSUF_KEY_SIZE"}, + {0x0d, "INVALID_ATTR_LEN"}, + {0x0e, "ERR_UNLIKELY"}, + {0x0f, "INSUF_ENCRYPTION"}, + {0x10, "UNSUPPORT_GRP_TYPE"}, + {0x11, "INSUF_RESOURCE"}, + {0x80, "NO_RESOURCES"}, + {0x81, "INTERNAL_ERROR"}, + {0x82, "WRONG_STATE"}, + {0x83, "DB_FULL"}, + {0x84, "BUSY"}, + {0x85, "ERROR"}, + {0x86, "CMD_STARTED"}, + {0x87, "ILLEGAL_PARAMETER"}, + {0x88, "PENDING"}, + {0x89, "AUTH_FAIL"}, + {0x8a, "MORE"}, + {0x8b, "INVALID_CFG"}, + {0x8c, "SERVICE_STARTED"}, + {0x8d, "ENCRYPED_NO_MITM"}, + {0x8e, "NOT_ENCRYPTED"}, + {0x8f, "CONGESTED"}, + {0x90, "DUP_REG"}, + {0x91, "ALREADY_OPEN"}, + {0x92, "CANCEL"}, + {0xfd, "CCC_CFG_ERR"}, + {0xfe, "PRC_IN_PROGRESS"}, + {0xff, "OUT_OF_RANGE"}, + {0x00, NULL}, +}; #define PRINT_STATUS(STATUS) { \ bool found = false; \ @@ -633,7 +685,7 @@ STATIC void gattc_event_dump( esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param) { const char * event_names[] = { - "REG", + "REG", // 0x00 "UNREG", "OPEN", "READ_CHAR", @@ -649,7 +701,7 @@ STATIC void gattc_event_dump( "ACL", "CANCEL_OPEN", "SRVC_CHG", - "" + "", // 0x10 "ENC_CMPL_CB", "CFG_MTU", "ADV_DATA", @@ -665,10 +717,10 @@ STATIC void gattc_event_dump( "BTH_SCAN_PARAM", "BTH_SCAN_DIS", "SCAN_FLT_CFG", - "SCAN_FLT_PARAM", - "SCAN_FLT_STATUS", - "ADV_VSC", - "GET_CHAR", + "SCAN_FLT_PARAM", // 0x20 + "SCAN_FLT_STATUS", // 0x21 + "ADV_VSC", // 0x22 + "GET_CHAR", // 0x23 "GET_DESCR", "GET_INCL_SRVC", "REG_FOR_NOTIFY", @@ -698,18 +750,18 @@ STATIC void gattc_event_dump( case ESP_GATTC_OPEN_EVT: { PRINT_STATUS(param->open.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", conn_id = %04X" - ", addr = %02X:%02X:%02X:%02X:%02X:%02X" - ", mtu = %04X", - param->open.conn_id, - param->open.remote_bda[0], - param->open.remote_bda[1], - param->open.remote_bda[2], - param->open.remote_bda[3], - param->open.remote_bda[4], - param->open.remote_bda[5], - param->open.mtu); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X" + ", mtu = %04X", + param->open.conn_id, + param->open.remote_bda[0], + param->open.remote_bda[1], + param->open.remote_bda[2], + param->open.remote_bda[3], + param->open.remote_bda[4], + param->open.remote_bda[5], + param->open.mtu); } break; @@ -763,11 +815,11 @@ STATIC void gattc_event_dump( case ESP_GATTC_CFG_MTU_EVT: { PRINT_STATUS(param->open.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", conn_id = %04X" - ", mtu = %04X", - param->cfg_mtu.conn_id, - param->cfg_mtu.mtu); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", conn_id = %04X" + ", mtu = %04X", + param->cfg_mtu.conn_id, + param->cfg_mtu.mtu); } break; @@ -789,8 +841,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_uuid_print(NULL,¶m->search_res.srvc_id.id.uuid); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->search_res.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->search_res.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->search_res.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } @@ -804,20 +855,19 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->read.srvc_id.id.uuid.uuid, param->read.srvc_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->read.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->read.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->read.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->read.char_id.uuid.uuid, param->read.char_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->read.char_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->read.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); dumpBuf((uint8_t*)¶m->read.descr_id.uuid.uuid, param->read.descr_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->read.descr_id.inst_id); + + network_bluetooth_gatt_id_print(NULL,¶m->read.descr_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", value = ("); dumpBuf(param->read.value, param->read.value_len); @@ -831,40 +881,37 @@ STATIC void gattc_event_dump( } break; - case ESP_GATTC_WRITE_CHAR_EVT: - case ESP_GATTC_PREP_WRITE_EVT: - case ESP_GATTC_WRITE_DESCR_EVT: + case ESP_GATTC_WRITE_CHAR_EVT: + case ESP_GATTC_PREP_WRITE_EVT: + case ESP_GATTC_WRITE_DESCR_EVT: { PRINT_STATUS(param->write.status); NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->read.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->write.srvc_id.id.uuid.uuid, param->write.srvc_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->write.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->write.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->write.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->write.char_id.uuid.uuid, param->write.char_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->write.char_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->write.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->write.descr_id.uuid.uuid, param->write.descr_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->write.descr_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->write.descr_id); } break; - case ESP_GATTC_EXEC_EVT: + case ESP_GATTC_EXEC_EVT: { PRINT_STATUS(param->exec_cmpl.status); NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->exec_cmpl.conn_id); } break; - case ESP_GATTC_NOTIFY_EVT: + case ESP_GATTC_NOTIFY_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X" @@ -880,20 +927,17 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->notify.srvc_id.id.uuid.uuid, param->notify.srvc_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->notify.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->notify.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->notify.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->notify.char_id.uuid.uuid, param->notify.char_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->notify.char_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->notify.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->notify.descr_id.uuid.uuid, param->notify.descr_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->notify.descr_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->notify.descr_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", value = ("); dumpBuf(param->notify.value, param->notify.value_len); @@ -909,7 +953,7 @@ STATIC void gattc_event_dump( break; - case ESP_GATTC_SRVC_CHG_EVT: + case ESP_GATTC_SRVC_CHG_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( "addr = %02X:%02X:%02X:%02X:%02X:%02X", @@ -923,7 +967,7 @@ STATIC void gattc_event_dump( } break; - case ESP_GATTC_CONGEST_EVT: + case ESP_GATTC_CONGEST_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( "conn_id = %04X, %s CONGESTED", @@ -932,7 +976,7 @@ STATIC void gattc_event_dump( } break; - case ESP_GATTC_GET_CHAR_EVT: + case ESP_GATTC_GET_CHAR_EVT: { PRINT_STATUS(param->get_char.status); NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_char.conn_id); @@ -940,15 +984,13 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_uuid_print(NULL,¶m->get_char.srvc_id.id.uuid); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_char.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->get_char.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_char.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_uuid_print(NULL,¶m->get_char.char_id.uuid); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_char.char_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->get_char.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_props = "); const char * char_props[] = { "BROADCAST", "READ", "WRITE_NR", "WRITE", "NOTIFY", "INDICATE", "AUTH", "EXT_PROP" }; @@ -962,7 +1004,7 @@ STATIC void gattc_event_dump( } break; - case ESP_GATTC_GET_DESCR_EVT: + case ESP_GATTC_GET_DESCR_EVT: { PRINT_STATUS(param->get_descr.status); NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_descr.conn_id); @@ -970,24 +1012,21 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->get_descr.srvc_id.id.uuid.uuid, param->get_descr.srvc_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_descr.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->get_descr.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_descr.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->get_descr.char_id.uuid.uuid, param->get_descr.char_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_descr.char_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->get_descr.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->get_descr.descr_id.uuid.uuid, param->get_descr.descr_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_descr.descr_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->get_descr.descr_id); } break; - case ESP_GATTC_GET_INCL_SRVC_EVT: + case ESP_GATTC_GET_INCL_SRVC_EVT: { PRINT_STATUS(param->get_incl_srvc.status); NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_incl_srvc.conn_id); @@ -995,62 +1034,56 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->get_incl_srvc.srvc_id.id.uuid.uuid, param->get_incl_srvc.srvc_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_incl_srvc.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->get_incl_srvc.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", incl_srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->get_incl_srvc.srvc_id.id.uuid.uuid, param->get_incl_srvc.srvc_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->get_incl_srvc.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->get_incl_srvc.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } break; - case ESP_GATTC_REG_FOR_NOTIFY_EVT: + case ESP_GATTC_REG_FOR_NOTIFY_EVT: { PRINT_STATUS(param->reg_for_notify.status); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->reg_for_notify.srvc_id.id.uuid.uuid, param->reg_for_notify.srvc_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->reg_for_notify.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->reg_for_notify.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->reg_for_notify.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->reg_for_notify.char_id.uuid.uuid, param->reg_for_notify.char_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->reg_for_notify.char_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->reg_for_notify.char_id); } break; - case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: + case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: { PRINT_STATUS(param->unreg_for_notify.status); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->unreg_for_notify.srvc_id.id.uuid.uuid, param->unreg_for_notify.srvc_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->unreg_for_notify.srvc_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->unreg_for_notify.srvc_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->unreg_for_notify.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->unreg_for_notify.char_id.uuid.uuid, param->unreg_for_notify.char_id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->unreg_for_notify.char_id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->unreg_for_notify.char_id); } - default: + default: // Rest of events have no printable data // do nothing, intentionally break; } -NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); } STATIC void gatts_event_dump( @@ -1217,8 +1250,7 @@ STATIC void gatts_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - dumpBuf((uint8_t*)¶m->create.service_id.id.uuid.uuid, param->create.service_id.id.uuid.len); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X)", param->create.service_id.id.inst_id); + network_bluetooth_gatt_id_print(NULL,¶m->create.service_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->create.service_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } @@ -1377,7 +1409,7 @@ STATIC void gatts_event_dump( break; } -NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); } STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { @@ -1436,10 +1468,10 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t const char * addr_types[] = { "PUBLIC", "RANDOM", "RPA_PUBLIC", "RPA_RANDOM" }; - NETWORK_BLUETOOTH_DEBUG_PRINTF( - "search_evt = %s", - search_events[param->scan_rst.search_evt]); - + NETWORK_BLUETOOTH_DEBUG_PRINTF( + "search_evt = %s", + search_events[param->scan_rst.search_evt]); + if ( param->scan_rst.dev_type <= 3 && param->scan_rst.ble_addr_type <=3 ) { NETWORK_BLUETOOTH_DEBUG_PRINTF( @@ -1468,7 +1500,7 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t param->scan_rst.adv_data_len, param->scan_rst.scan_rsp_len); - + uint8_t * adv_name; uint8_t adv_name_len = 0; adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, @@ -1494,7 +1526,7 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t case ESP_GAP_BLE_NC_REQ_EVT: break; } -NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); } @@ -1529,70 +1561,97 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { esp_ble_gatts_start_service(service->handle); } } - break; + break; case NETWORK_BLUETOOTH_GATTS_STOP: case NETWORK_BLUETOOTH_GATTS_START: - { - network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_start_stop.service_handle); - if (service == MP_OBJ_NULL) { - break; - } + { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_start_stop.service_handle); + if (service == MP_OBJ_NULL) { + break; + } - switch(cbdata.event) { - case NETWORK_BLUETOOTH_GATTS_START: - service->started = true; + switch(cbdata.event) { + case NETWORK_BLUETOOTH_GATTS_START: + service->started = true; - ITEM_BEGIN(); - size_t len; - mp_obj_t *items; - mp_obj_get_array(service->chars, &len, &items); + ITEM_BEGIN(); + size_t len; + mp_obj_t *items; + mp_obj_get_array(service->chars, &len, &items); - for (int i = 0; i < len; i++) { - network_bluetooth_gatts_char_obj_t* chr = (network_bluetooth_gatts_char_obj_t*) items[i]; - esp_ble_gatts_add_char(service->handle, &chr->uuid, chr->perm, chr->prop, NULL, NULL); - } - ITEM_END(); - break; + for (int i = 0; i < len; i++) { + network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; + esp_ble_gatts_add_char(service->handle, &chr->char_id.uuid, chr->perm, chr->prop, NULL, NULL); + } + ITEM_END(); + break; - case NETWORK_BLUETOOTH_GATTS_STOP: - service->started = false; - esp_ble_gatts_delete_service(service->handle); - break; - default: - // Nothing, intentionally - break; - } + case NETWORK_BLUETOOTH_GATTS_STOP: + service->started = false; + esp_ble_gatts_delete_service(service->handle); + break; + default: + // Nothing, intentionally + break; + } - } - break; + } + break; case NETWORK_BLUETOOTH_GATTS_ADD_CHAR: - { - network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_add_char.service_handle); - if (service != MP_OBJ_NULL) { - network_bluetooth_gatts_char_obj_t* chr = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.gatts_add_char.char_uuid); - if (chr != MP_OBJ_NULL) { - chr->handle = cbdata.gatts_add_char.char_handle; + { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_add_char.service_handle); + if (service != MP_OBJ_NULL) { + network_bluetooth_char_obj_t* chr = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.gatts_add_char.char_uuid); + if (chr != MP_OBJ_NULL) { + chr->handle = cbdata.gatts_add_char.char_handle; + } + } else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Service handle %d NOT FOUND\n", cbdata.gatts_add_char.service_handle); } - } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Service handle %d NOT FOUND\n", cbdata.gatts_add_char.service_handle); } - } - break; + break; + - case NETWORK_BLUETOOTH_READ: case NETWORK_BLUETOOTH_WRITE: + case NETWORK_BLUETOOTH_NOTIFY: { - network_bluetooth_gatts_char_obj_t* self = network_bluetooth_find_char_by_handle(cbdata.read.handle); + network_bluetooth_char_obj_t* self = MP_OBJ_NULL; + + mp_obj_t value = mp_const_none; + bool need_rsp = false; + + switch(cbdata.event) { + case NETWORK_BLUETOOTH_NOTIFY: + value = mp_obj_new_bytearray(cbdata.notify.value_len, cbdata.notify.value); + self = network_bluetooth_find_char_by_uuid(&cbdata.notify.char_id.uuid); + NETWORK_BLUETOOTH_DEBUG_PRINTF("Notify: Looking for char "); + network_bluetooth_gatt_id_print(NULL, &cbdata.notify.char_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); + FREE(cbdata.notify.value); + need_rsp = cbdata.notify.need_rsp; + break; + case NETWORK_BLUETOOTH_READ: + value = self->value; + self = network_bluetooth_find_char_by_handle(cbdata.read.handle); + break; + case NETWORK_BLUETOOTH_WRITE: + self = network_bluetooth_find_char_by_handle(cbdata.write.handle); + value = mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value); + need_rsp = cbdata.write.need_rsp; + FREE(cbdata.write.value); + break; + default: + // nothing, intentionally + break; + } if (self != MP_OBJ_NULL) { - mp_obj_t value = cbdata.event == NETWORK_BLUETOOTH_WRITE ? mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value) : self->value; - if (self->callback != mp_const_none) { mp_obj_t args[] = {self, MP_OBJ_NEW_SMALL_INT(cbdata.event), value, self->callback_userdata }; value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); @@ -1600,7 +1659,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { self->value = value; } - if (cbdata.read.need_rsp) { + if (need_rsp) { esp_gatt_rsp_t rsp; memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); @@ -1613,15 +1672,29 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); - rsp.attr_value.handle = cbdata.read.handle; - rsp.attr_value.len = len; - memcpy(rsp.attr_value.value, buf.buf, len); - esp_ble_gatts_send_response(bluetooth->gatts_interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); - } - if (cbdata.event == NETWORK_BLUETOOTH_WRITE) { - FREE(cbdata.write.value); + switch(cbdata.event) { + + case NETWORK_BLUETOOTH_WRITE: + case NETWORK_BLUETOOTH_READ: + rsp.attr_value.handle = cbdata.read.handle; + rsp.attr_value.len = len; + memcpy(rsp.attr_value.value, buf.buf, len); + esp_ble_gatts_send_response(bluetooth->gatts_interface, cbdata.read.conn_id, cbdata.read.trans_id, ESP_GATT_OK, &rsp); + break; + case NETWORK_BLUETOOTH_NOTIFY: + // FIXME, How do you respond to a notify?? + break; + + default: + // nothing, intentionally + break; + } } + } + else { + NETWORK_BLUETOOTH_DEBUG_PRINTF("Could not find characteristic\n"); } + } break; @@ -1671,15 +1744,18 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { case NETWORK_BLUETOOTH_GATTC_SEARCH_RES: { network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_search_res.conn_id); - NETWORK_BLUETOOTH_DEBUG_PRINTF("search res for connid: %u, conn obj = %p", cbdata.gattc_search_res.conn_id, conn); - network_bluetooth_uuid_print(NULL, &cbdata.gattc_search_res.service_id.id.uuid); + NETWORK_BLUETOOTH_DEBUG_PRINTF("search res for connid: %u, conn obj = %p, uuid =", cbdata.gattc_search_res.conn_id, conn); + network_bluetooth_gatt_id_print(NULL, &cbdata.gattc_search_res.service_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); if (conn != MP_OBJ_NULL) { network_bluetooth_service_obj_t *service = m_new_obj(network_bluetooth_service_obj_t); service->base.type = &network_bluetooth_gattc_service_type; service->valid = true; service->service_id = cbdata.gattc_search_res.service_id; + service->chars = mp_obj_new_list(0, NULL); + service->connection = conn; mp_obj_list_append(conn->services, service); + NETWORK_BLUETOOTH_DEBUG_PRINTF("Appended to connection services, len: %u\n", mp_obj_get_int(mp_obj_len(conn->services))); esp_ble_gattc_get_characteristic(bluetooth->gattc_interface, conn->conn_id, &service->service_id, NULL); } } @@ -1687,16 +1763,44 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { case NETWORK_BLUETOOTH_GATTC_GET_CHAR: { - network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_search_res.conn_id); - if (conn != MP_OBJ_NULL) { - network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_char.service_id.id.uuid); - if (service != MP_OBJ_NULL) { - network_bluetooth_service_obj_t *char = m_new_obj(network_bluetooth_service_obj_t); - } + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_get_char.conn_id); + if (conn != MP_OBJ_NULL) { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_char.service_id.id.uuid); + if (service != MP_OBJ_NULL) { + network_bluetooth_char_obj_t *chr = m_new_obj(network_bluetooth_char_obj_t); + chr->base.type = &network_bluetooth_gattc_char_type; + chr->char_id = cbdata.gattc_get_char.char_id; + chr->prop = cbdata.gattc_get_char.props; + chr->service = service; + chr->descriptors = mp_obj_new_list(0, NULL); + + mp_obj_list_append(service->chars, chr); + esp_ble_gattc_get_descriptor(bluetooth->gattc_interface, conn->conn_id, &service->service_id, &chr->char_id, NULL); + } } + } + break; + case NETWORK_BLUETOOTH_GATTC_GET_DESCR: + { + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_get_descr.conn_id); + if (conn != MP_OBJ_NULL) { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_descr.service_id.id.uuid); + if (service != MP_OBJ_NULL) { + + network_bluetooth_char_obj_t *chr = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.gattc_get_descr.char_id.uuid); + if (chr != NULL) { + network_bluetooth_descr_obj_t* descr = m_new_obj(network_bluetooth_descr_obj_t); + descr->base.type = &network_bluetooth_gattc_descr_type; + descr->chr = chr; + descr->descr_id = cbdata.gattc_get_descr.descr_id; + mp_obj_list_append(chr->descriptors, descr); + } + } + } } break; + default: // do nothing, intentionally break; @@ -1719,6 +1823,7 @@ STATIC void network_bluetooth_gattc_event_handler( gattc_event_dump(event, gattc_if, param); #endif + read_write_data_t read_data; callback_data_t cbdata; bool nq = true; switch(event) { @@ -1744,16 +1849,61 @@ STATIC void network_bluetooth_gattc_event_handler( } break; - case ESP_GATTC_GET_CHAR_EVT: + case ESP_GATTC_GET_CHAR_EVT: { cbdata.event = NETWORK_BLUETOOTH_GATTC_GET_CHAR; cbdata.gattc_get_char.conn_id = param->get_char.conn_id; cbdata.gattc_get_char.service_id = param->get_char.srvc_id; cbdata.gattc_get_char.char_id = param->get_char.char_id; cbdata.gattc_get_char.props = param->get_char.char_prop; + } + break; + + + case ESP_GATTC_GET_DESCR_EVT: + { + if (param->get_descr.status == ESP_GATT_OK) { + cbdata.event = NETWORK_BLUETOOTH_GATTC_GET_DESCR; + cbdata.gattc_get_descr.conn_id = param->get_descr.conn_id; + cbdata.gattc_get_descr.service_id = param->get_descr.srvc_id; + cbdata.gattc_get_descr.char_id = param->get_descr.char_id; + cbdata.gattc_get_descr.descr_id = param->get_descr.descr_id; + } + } + break; + + case ESP_GATTC_READ_CHAR_EVT: + read_data.value = MALLOC(param->read.value_len); + read_data.value_len = param->read.value_len; + if (read_data.value != NULL) { + memcpy(read_data.value, param->read.value, param->read.value_len); } + + // fallthrough intentional + case ESP_GATTC_WRITE_CHAR_EVT: + xQueueSend(read_write_q, &read_data, portMAX_DELAY); break; + + case ESP_GATTC_NOTIFY_EVT: + { + + cbdata.notify.value = MALLOC(param->notify.value_len); // Returns NULL when len == 0 + cbdata.notify.value_len = param->notify.value_len; + + if (cbdata.notify.value != NULL) { + memcpy(cbdata.notify.value, param->notify.value, param->notify.value_len); + } + + cbdata.event = NETWORK_BLUETOOTH_NOTIFY; + + cbdata.notify.conn_id = param->notify.conn_id; + cbdata.notify.service_id = param->notify.srvc_id; + cbdata.notify.char_id = param->notify.char_id; + cbdata.notify.need_rsp = !param->notify.is_notify; + } + break; + case ESP_GATTC_CLOSE_EVT: { nq = false; // FIXME remove @@ -1830,7 +1980,7 @@ STATIC void network_bluetooth_gatts_event_handler( } // fallthrough intentional - + case ESP_GATTS_READ_EVT: { cbdata.event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; @@ -1966,11 +2116,23 @@ STATIC void network_bluetooth_adv_updated() { STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - network_bluetooth_gatts_char_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "BTChar(uuid = "); - network_bluetooth_uuid_print(print, &self->uuid); - mp_printf(print, ", perm = %02X, prop = %02X, handle = %04X, value = ", self->perm, self->prop, self->handle); - mp_obj_print_helper(print, self->value, PRINT_REPR); + if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gattc_descr_type)) { + network_bluetooth_descr_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "GATTCDescr(uuid = "); + network_bluetooth_gatt_id_print(print, &self->descr_id); + } else { + network_bluetooth_char_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type)) { + mp_printf(print, "GATTSChar(uuid = "); + network_bluetooth_gatt_id_print(print, &self->char_id); + mp_printf(print, ", handle = %04X, perm = %02X, value = ", self->handle, self->perm); + mp_obj_print_helper(print, self->value, PRINT_REPR); + } else { + mp_printf(print, "GATTCChar(uuid = "); + } + network_bluetooth_gatt_id_print(print, &self->char_id); + mp_printf(print, ", prop = %02X",self->prop); + } mp_printf(print, ")"); } @@ -1993,7 +2155,7 @@ STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t se } else { mp_printf(print, "GATTCService(uuid = "); } - network_bluetooth_uuid_print(print, &self->service_id.id.uuid); + network_bluetooth_gatt_id_print(print, &self->service_id.id); mp_printf(print, ", primary = %s", self->service_id.is_primary ? "True" : "False"); if (gatts) { @@ -2092,7 +2254,16 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { } else { xQueueReset(callback_q); } - + + if (read_write_q == NULL) { + read_write_q = xQueueCreate(1, sizeof(read_write_data_t)); + if (read_write_q == NULL) { + mp_raise_msg(&mp_type_OSError, "unable to create read queue"); + } + } else { + xQueueReset(read_write_q); + } + if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); @@ -2107,7 +2278,7 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { // 2) You can't call this twice for enabling // // https://github.com/espressif/esp-idf/issues/405#issuecomment-299045124 - + if (!network_bluetooth_bt_controller_enabled) { network_bluetooth_bt_controller_enabled = true; switch(esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { @@ -2442,7 +2613,7 @@ STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_arg) { network_bluetooth_obj_t *bluetooth = MP_OBJ_TO_PTR(self_in); - + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); } @@ -2496,7 +2667,8 @@ STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Calling open with IF=%u\n", bluetooth->gattc_interface); esp_ble_gattc_open(bluetooth->gattc_interface, connection->bda, true); - + NETWORK_BLUETOOTH_DEBUG_PRINTF("AFTER Calling open with IF=%u\n", bluetooth->gattc_interface); + return connection; NETWORK_BLUETOOTH_connect_BAD_ADX: @@ -2510,18 +2682,10 @@ STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_ob if (!check_locals_dict(connection, attr, dest)) { switch(attr) { case MP_QSTR_services: - if (dest[0] == MP_OBJ_NULL) { // load - dest[0] = connection->services; - } else if (dest[1] != MP_OBJ_NULL) { // store - dest[0] = MP_OBJ_NULL; - } + dest[0] = connection->services; break; case MP_QSTR_is_connected: - if (dest[0] == MP_OBJ_NULL) { // load - dest[0] = connection->connected ? mp_const_true : mp_const_false; - } else if (dest[1] != MP_OBJ_NULL) { // store - dest[0] = MP_OBJ_NULL; - } + dest[0] = connection->connected ? mp_const_true : mp_const_false; break; } } @@ -2535,11 +2699,181 @@ STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_callback_obj, 1, 3, network_bluetooth_callback); STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *args) { - network_bluetooth_gatts_char_obj_t* self = (network_bluetooth_gatts_char_obj_t*) args[0]; - return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); + mp_obj_t ret; + network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) args[0]; + network_bluetooth_service_obj_t *service = self->service; + network_bluetooth_connection_obj_t *connection = service->connection; + network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); + + assert(self != MP_OBJ_NULL); + assert(service != MP_OBJ_NULL); + + ret = network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); + if (n_args > 1 && MP_OBJ_IS_TYPE(self, &network_bluetooth_gattc_char_type)) { + assert(connection != MP_OBJ_NULL); + NETWORK_BLUETOOTH_DEBUG_PRINTF("(un)registering for notify\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF("interface: %02X\n", bluetooth->gattc_interface); + NETWORK_BLUETOOTH_DEBUG_PRINTF("bda: "); + network_bluetooth_print_bda(NULL, connection->bda); + NETWORK_BLUETOOTH_DEBUG_PRINTF("\nservice: "); + network_bluetooth_gatt_id_print(NULL, &service->service_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); + NETWORK_BLUETOOTH_DEBUG_PRINTF("char: "); + network_bluetooth_gatt_id_print(NULL, &self->char_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); + if (self->callback != mp_const_none) { + if (esp_ble_gattc_register_for_notify(bluetooth->gattc_interface, connection->bda, &service->service_id, &self->char_id) != ESP_OK) { + goto NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR; + } + } else { + if (esp_ble_gattc_unregister_for_notify( bluetooth->gattc_interface, connection->bda, &service->service_id, &self->char_id) != ESP_OK) { + goto NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR; + } + } + } + + return ret; + +NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR: + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_(un)register_for_notify() call failed"); } + STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_callback_obj, 1, 3, network_bluetooth_char_callback); +STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) { + bool is_chr; + network_bluetooth_char_obj_t *chr; + network_bluetooth_descr_obj_t *descr; + esp_err_t result; + + + if (MP_OBJ_IS_TYPE(args[0], &network_bluetooth_gattc_char_type)) { + is_chr = true; + chr = MP_OBJ_TO_PTR(args[0]); + descr = MP_OBJ_NULL; + } else { + is_chr = false; + descr = MP_OBJ_TO_PTR(args[0]); + chr = descr->chr; + } + + network_bluetooth_service_obj_t *service = chr->service; + network_bluetooth_connection_obj_t *connection = service->connection; + network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); + + assert(chr != MP_OBJ_NULL); + assert(service != MP_OBJ_NULL); + assert(connection != MP_OBJ_NULL); + + read_write_data_t read_data; + + // clear out any stale data + if(xQueueReceive(read_write_q, &read_data, 0) == pdTRUE) { + FREE(read_data.value); + } + xQueueReset(read_write_q); + + if (is_chr) { + result = esp_ble_gattc_read_char(bluetooth->gattc_interface, connection->conn_id, &service->service_id, &chr->char_id, ESP_GATT_AUTH_REQ_NONE); + } else { + result = esp_ble_gattc_read_char_descr(bluetooth->gattc_interface, connection->conn_id, &service->service_id, &chr->char_id, &descr->descr_id, ESP_GATT_AUTH_REQ_NONE); + } + + if (result != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "read call failed"); + } + + TickType_t ticks = portMAX_DELAY; + if (n_args > 1) { + mp_float_t timeout = mp_obj_get_float(args[1]); + if (timeout >= 0) { + ticks = (TickType_t)timeout * 1000.0 / portTICK_PERIOD_MS; + } + } + + + if (xQueueReceive(read_write_q, &read_data, ticks) == pdTRUE) { + + mp_obj_t res = mp_obj_new_bytearray(read_data.value_len, read_data.value); + FREE(read_data.value); + return res; + } + mp_raise_msg(&mp_type_OSError, "timed out"); + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_read_obj,1,2, network_bluetooth_char_read); + +STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { + bool is_chr; + network_bluetooth_char_obj_t *chr; + network_bluetooth_descr_obj_t *descr; + esp_err_t result; + + + if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gattc_char_type)) { + is_chr = true; + chr = MP_OBJ_TO_PTR(self_in); + descr = MP_OBJ_NULL; + } else { + is_chr = false; + descr = MP_OBJ_TO_PTR(self_in); + chr = descr->chr; + } + + network_bluetooth_service_obj_t *service = chr->service; + network_bluetooth_connection_obj_t *connection = service->connection; + network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); + + assert(chr != MP_OBJ_NULL); + assert(service != MP_OBJ_NULL); + assert(connection != MP_OBJ_NULL); + + read_write_data_t read_data; + + // clear out any stale data + if(xQueueReceive(read_write_q, &read_data, 0) == pdTRUE) { + FREE(read_data.value); + } + xQueueReset(read_write_q); + + + mp_buffer_info_t buf; + mp_get_buffer_raise(value, &buf, MP_BUFFER_READ); + + if (is_chr) { + result = + esp_ble_gattc_write_char( + bluetooth->gattc_interface, + connection->conn_id, + &service->service_id, + &chr->char_id, + buf.len, + buf.buf, + ESP_GATT_WRITE_TYPE_NO_RSP, + ESP_GATT_AUTH_REQ_NONE); + } else { + result = + esp_ble_gattc_write_char_descr( + bluetooth->gattc_interface, + connection->conn_id, + &service->service_id, + &chr->char_id, + &descr->descr_id, + buf.len, + buf.buf, + ESP_GATT_WRITE_TYPE_NO_RSP, + ESP_GATT_AUTH_REQ_NONE); + } + + if (result != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_read_char() call failed"); + } + + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_char_write_obj, network_bluetooth_char_write); + STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_char_indicate()\n"); @@ -2547,7 +2881,7 @@ STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *p if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); } - network_bluetooth_gatts_char_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); + network_bluetooth_char_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); enum {ARG_value, ARG_need_confirm}; static const mp_arg_t allowed_args[] = { @@ -2560,7 +2894,7 @@ STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *p if (args[ARG_value].u_obj != MP_OBJ_NULL) { if ( !MP_OBJ_IS_STR_OR_BYTES(args[ARG_value].u_obj) && - !MP_OBJ_IS_TYPE(args[ARG_value].u_obj, &mp_type_bytearray) + !MP_OBJ_IS_TYPE(args[ARG_value].u_obj, &mp_type_bytearray) ) { mp_raise_ValueError("value must be string, bytes, bytearray"); } @@ -2618,6 +2952,7 @@ STATIC mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, si self->service_id.is_primary = mp_obj_is_true(args[ARG_primary].u_obj); self->chars = mp_obj_new_list(0, NULL); + self->connection = MP_OBJ_NULL; ITEM_BEGIN(); mp_obj_list_append(bluetooth->services, MP_OBJ_FROM_PTR(self)); @@ -2646,18 +2981,19 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_gatts_char_obj_t *self = network_bluetooth_find_char_in_service_by_uuid(service, &uuid); + network_bluetooth_char_obj_t *self = network_bluetooth_find_char_in_service_by_uuid(service, &uuid); if (self != MP_OBJ_NULL) { return MP_OBJ_FROM_PTR(self); } - self = m_new_obj(network_bluetooth_gatts_char_obj_t); - self->base.type = &network_bluetooth_characteristic_type; + self = m_new_obj(network_bluetooth_char_obj_t); + self->base.type = &network_bluetooth_gatts_char_type; + self->service = service; self->callback = mp_const_none; - self->uuid = uuid; + self->char_id.uuid = uuid; self->value = args[ARG_value].u_obj; self->perm = args[ARG_perm].u_int; self->prop = args[ARG_prop].u_int; @@ -2745,22 +3081,80 @@ STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); -// char attribute handler + +STATIC void network_bluetooth_descr_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + network_bluetooth_descr_obj_t* self = (network_bluetooth_descr_obj_t*) self_in; + if (!check_locals_dict(self, attr, dest)) { + switch (attr) { + case MP_QSTR_char: + dest[0] = self->chr; + break; + + case MP_QSTR_uuid: + { + esp_bt_uuid_t uuid128; + uuid_to_uuid128(&self->descr_id.uuid, &uuid128); + dest[0] = mp_obj_new_bytearray(uuid128.len, uuid128.uuid.uuid128); + } + break; + } + } +} + STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - network_bluetooth_gatts_char_obj_t* self = (network_bluetooth_gatts_char_obj_t*) self_in; + network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) self_in; if (!check_locals_dict(self, attr, dest)) { - switch(attr) { - case MP_QSTR_value: - if (dest[0] == MP_OBJ_NULL) { // load - dest[0] = self->value; - } else if (dest[1] != MP_OBJ_NULL) { // store - if (!MP_OBJ_IS_BT_DATATYPE(dest[1])) { - mp_raise_ValueError("value must be string, bytes, bytearray, or None"); + if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type)) { + + switch(attr) { + case MP_QSTR_service: + dest[0] = self->service; + break; + case MP_QSTR_uuid: + { + esp_bt_uuid_t uuid128; + uuid_to_uuid128(&self->char_id.uuid, &uuid128); + dest[0] = mp_obj_new_bytearray(uuid128.len, uuid128.uuid.uuid128); } - self->value = dest[1]; - dest[0] = MP_OBJ_NULL; - } + break; + case MP_QSTR_value: + if (dest[0] == MP_OBJ_NULL) { // load + dest[0] = self->value; + } else if (dest[1] != MP_OBJ_NULL) { // store + if (!MP_OBJ_IS_BT_DATATYPE(dest[1])) { + mp_raise_ValueError("value must be string, bytes, bytearray, or None"); + } + self->value = dest[1]; + dest[0] = MP_OBJ_NULL; + } + } + } else { + switch(attr) { + case MP_QSTR_service: + dest[0] = self->service; + break; + + case MP_QSTR_descriptors: + dest[0] = self->descriptors; + break; + + case MP_QSTR_uuid: + { + esp_bt_uuid_t uuid128; + uuid_to_uuid128(&self->char_id.uuid, &uuid128); + dest[0] = mp_obj_new_bytearray(uuid128.len, uuid128.uuid.uuid128); + } + break; + + case MP_QSTR_instance: + dest[0] = MP_OBJ_NEW_SMALL_INT(self->char_id.inst_id); + break; + + case MP_QSTR_prop: + dest[0] = MP_OBJ_NEW_SMALL_INT(self->prop); + break; + } } } } @@ -2805,18 +3199,10 @@ STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) if (!check_locals_dict(self, attr, dest)) { switch(attr) { case MP_QSTR_is_scanning: - if (dest[0] == MP_OBJ_NULL) { - dest[0] = self->scanning ? mp_const_true : mp_const_false; - } else { - dest[0] = MP_OBJ_NULL; - } + dest[0] = self->scanning ? mp_const_true : mp_const_false; break; case MP_QSTR_services: - if (dest[0] == MP_OBJ_NULL) { // load - dest[0] = self->services; - } else { - dest[0] = MP_OBJ_NULL; - } + dest[0] = self->services; break; } } @@ -2827,7 +3213,7 @@ STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - + if (bluetooth->state == NETWORK_BLUETOOTH_STATE_INIT) { bluetooth->state = NETWORK_BLUETOOTH_STATE_DEINIT; @@ -2868,7 +3254,7 @@ STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { } // FIXME: This fails, with the present IDF - + #if 0 mp_hal_delay_ms(300); switch(esp_bt_controller_enable(ESP_BT_MODE_IDLE)) { @@ -2909,7 +3295,8 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_GATTS_CONNECT) }, { MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_GATTS_DISCONNECT) }, { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(NETWORK_BLUETOOTH_READ) }, - { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(NETWORK_BLUETOOTH_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(NETWORK_BLUETOOTH_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_NOTIFY), MP_ROM_INT(NETWORK_BLUETOOTH_NOTIFY) }, { MP_ROM_QSTR(MP_QSTR_SCAN_RES), MP_ROM_INT(NETWORK_BLUETOOTH_GATTC_SCAN_RES) }, { MP_ROM_QSTR(MP_QSTR_SCAN_CMPL), MP_ROM_INT(NETWORK_BLUETOOTH_GATTC_SCAN_CMPL) }, @@ -3044,22 +3431,68 @@ const mp_obj_type_t network_bluetooth_gattc_service_type = { // -// CHARACTERISTIC OBJECTS +// GATTS CHAR OBJECTS // -STATIC const mp_rom_map_elem_t network_bluetooth_characteristic_locals_dict_table[] = { +STATIC const mp_rom_map_elem_t network_bluetooth_gatts_char_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&network_bluetooth_char_indicate_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_value), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_service), NULL }, // handled by attr handler +}; + +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gatts_char_locals_dict, network_bluetooth_gatts_char_locals_dict_table); + +const mp_obj_type_t network_bluetooth_gatts_char_type = { + { &mp_type_type }, + .name = MP_QSTR_Char, + .print = network_bluetooth_characteristic_print, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gatts_char_locals_dict, + .attr = network_bluetooth_char_attr, }; -STATIC MP_DEFINE_CONST_DICT(network_bluetooth_characteristic_locals_dict, network_bluetooth_characteristic_locals_dict_table); +// +// GATTC CHAR OBJECTS +// -const mp_obj_type_t network_bluetooth_characteristic_type = { +STATIC const mp_rom_map_elem_t network_bluetooth_gattc_char_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&network_bluetooth_char_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_service), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_descriptors), NULL }, // handled by attr handler +}; + +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_char_locals_dict, network_bluetooth_gattc_char_locals_dict_table); + +const mp_obj_type_t network_bluetooth_gattc_char_type = { { &mp_type_type }, .name = MP_QSTR_Char, .print = network_bluetooth_characteristic_print, - .locals_dict = (mp_obj_dict_t*)&network_bluetooth_characteristic_locals_dict, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gattc_char_locals_dict, .attr = network_bluetooth_char_attr, }; + +// +// GATTC DESCR OBJECTS +// + +STATIC const mp_rom_map_elem_t network_bluetooth_gattc_descr_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&network_bluetooth_char_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_char), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler +}; + +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_descr_locals_dict, network_bluetooth_gattc_descr_locals_dict_table); + +const mp_obj_type_t network_bluetooth_gattc_descr_type = { + { &mp_type_type }, + .name = MP_QSTR_Descr, + .print = network_bluetooth_characteristic_print, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gattc_descr_locals_dict, + .attr = network_bluetooth_descr_attr, +}; From 8fb8b61fffbfae5c2e54f9cb741b0453f6515b4a Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 9 May 2017 13:00:46 -0700 Subject: [PATCH 52/98] esp32/main.c: heap now 48K --- esp32/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/main.c b/esp32/main.c index 44cf29434..857ee187e 100644 --- a/esp32/main.c +++ b/esp32/main.c @@ -53,7 +53,7 @@ #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) #define MP_TASK_STACK_SIZE (16 * 1024) #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) -#define MP_TASK_HEAP_SIZE (32 * 1024) +#define MP_TASK_HEAP_SIZE (48 * 1024) STATIC StaticTask_t mp_task_tcb; STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8))); From 7bcf664be467b527b2d340fa08bf821c4b34269e Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 9 May 2017 13:01:29 -0700 Subject: [PATCH 53/98] esp32/sdkconfig.h: added #define CONFIG_BT_DRAM_RELEASE 1 --- esp32/sdkconfig.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index ac7a2c8d1..cc23b4436 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -3,6 +3,8 @@ #define CONFIG_PHY_DATA_OFFSET 0xf000 #define CONFIG_APP_OFFSET 0x10000 +#define CONFIG_BT_DRAM_RELEASE 1 + #define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 #define CONFIG_ESP32_APPTRACE_DEST_NONE 1 From a2cfc9533de22e77580b1baaf4eababc0ff835b3 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 9 May 2017 13:02:52 -0700 Subject: [PATCH 54/98] esp32/network_bluetooth.c: Finished up GATTC --- esp32/network_bluetooth.c | 107 ++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 44 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index ea8d0505e..15180cd23 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -51,13 +51,13 @@ #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -#define EVENT_DEBUG +//#define EVENT_DEBUG #ifdef EVENT_DEBUG # define EVENT_DEBUG_GATTC # define EVENT_DEBUG_GATTS -# define EVENT_DEBUG_GAP +//# define EVENT_DEBUG_GAP #endif #define UUID_LEN 16 @@ -112,6 +112,7 @@ typedef enum { NETWORK_BLUETOOTH_GATTC_GET_DESCR, NETWORK_BLUETOOTH_GATTC_OPEN, + NETWORK_BLUETOOTH_GATTC_CLOSE, // characteristic events NETWORK_BLUETOOTH_READ, @@ -174,7 +175,7 @@ typedef struct { uint16_t mtu; esp_bd_addr_t bda; - } gattc_open; + } gattc_open_close; struct { uint16_t conn_id; @@ -238,10 +239,9 @@ typedef struct { typedef struct { mp_obj_base_t base; esp_bd_addr_t bda; - uint16_t conn_id; + int32_t conn_id; // int32_t, so we can store -1 for disconnected. uint16_t mtu; mp_obj_t services; - bool connected; } network_bluetooth_connection_obj_t; @@ -1628,23 +1628,32 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { switch(cbdata.event) { case NETWORK_BLUETOOTH_NOTIFY: value = mp_obj_new_bytearray(cbdata.notify.value_len, cbdata.notify.value); - self = network_bluetooth_find_char_by_uuid(&cbdata.notify.char_id.uuid); - NETWORK_BLUETOOTH_DEBUG_PRINTF("Notify: Looking for char "); - network_bluetooth_gatt_id_print(NULL, &cbdata.notify.char_id); - NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); FREE(cbdata.notify.value); + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.notify.conn_id); + if (conn != MP_OBJ_NULL) { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.notify.service_id.id.uuid); + if (service != MP_OBJ_NULL) { + self = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.notify.char_id.uuid); + } + } need_rsp = cbdata.notify.need_rsp; break; + case NETWORK_BLUETOOTH_READ: - value = self->value; self = network_bluetooth_find_char_by_handle(cbdata.read.handle); + if (self != MP_OBJ_NULL) { + value = self->value; + } + need_rsp = true; break; + case NETWORK_BLUETOOTH_WRITE: self = network_bluetooth_find_char_by_handle(cbdata.write.handle); value = mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value); need_rsp = cbdata.write.need_rsp; FREE(cbdata.write.value); break; + default: // nothing, intentionally break; @@ -1713,7 +1722,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { if (bluetooth->callback != mp_const_none) { mp_obj_t data = mp_const_none; if (cbdata.event == NETWORK_BLUETOOTH_GATTC_SCAN_RES) { - mp_obj_t scan_res_args[] = {mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), mp_obj_new_bytearray(cbdata.gattc_scan_res.adv_data_len, cbdata.gattc_scan_res.adv_data) } ; + mp_obj_t scan_res_args[] = { mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), mp_obj_new_bytearray(cbdata.gattc_scan_res.adv_data_len, cbdata.gattc_scan_res.adv_data) } ; data = mp_obj_new_tuple(2, scan_res_args); FREE(cbdata.gattc_scan_res.adv_data); } @@ -1723,20 +1732,22 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { } break; + case NETWORK_BLUETOOTH_GATTC_CLOSE: + { + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_open_close.conn_id); + if (conn != MP_OBJ_NULL) { + conn->conn_id = -1; + } + } + break; case NETWORK_BLUETOOTH_GATTC_OPEN: { - network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_bda(cbdata.gattc_open.bda); + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_bda(cbdata.gattc_open_close.bda); -#if 0 - NETWORK_BLUETOOTH_DEBUG_PRINTF("got bda:"); - network_bluetooth_print_bda(NULL, cbdata.gattc_open.bda); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn obj = %p\n", conn); -#endif if (conn != MP_OBJ_NULL) { - conn->conn_id = cbdata.gattc_open.conn_id; - conn->mtu = cbdata.gattc_open.mtu; - conn->connected = true; - esp_ble_gattc_search_service(bluetooth->gattc_interface, cbdata.gattc_open.conn_id, NULL); + conn->conn_id = cbdata.gattc_open_close.conn_id; + conn->mtu = cbdata.gattc_open_close.mtu; + esp_ble_gattc_search_service(bluetooth->gattc_interface, cbdata.gattc_open_close.conn_id, NULL); } } break; @@ -1744,9 +1755,11 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { case NETWORK_BLUETOOTH_GATTC_SEARCH_RES: { network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_search_res.conn_id); +#if 0 NETWORK_BLUETOOTH_DEBUG_PRINTF("search res for connid: %u, conn obj = %p, uuid =", cbdata.gattc_search_res.conn_id, conn); network_bluetooth_gatt_id_print(NULL, &cbdata.gattc_search_res.service_id.id); NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); +#endif if (conn != MP_OBJ_NULL) { network_bluetooth_service_obj_t *service = m_new_obj(network_bluetooth_service_obj_t); service->base.type = &network_bluetooth_gattc_service_type; @@ -1755,7 +1768,6 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { service->chars = mp_obj_new_list(0, NULL); service->connection = conn; mp_obj_list_append(conn->services, service); - NETWORK_BLUETOOTH_DEBUG_PRINTF("Appended to connection services, len: %u\n", mp_obj_get_int(mp_obj_len(conn->services))); esp_ble_gattc_get_characteristic(bluetooth->gattc_interface, conn->conn_id, &service->service_id, NULL); } } @@ -1835,9 +1847,16 @@ STATIC void network_bluetooth_gattc_event_handler( case ESP_GATTC_OPEN_EVT: { cbdata.event = NETWORK_BLUETOOTH_GATTC_OPEN; - cbdata.gattc_open.conn_id = param->open.conn_id; - cbdata.gattc_open.mtu = param->open.mtu; - memcpy(cbdata.gattc_open.bda, param->open.remote_bda, ESP_BD_ADDR_LEN); + cbdata.gattc_open_close.conn_id = param->open.conn_id; + cbdata.gattc_open_close.mtu = param->open.mtu; + memcpy(cbdata.gattc_open_close.bda, param->open.remote_bda, ESP_BD_ADDR_LEN); + } + break; + case ESP_GATTC_CLOSE_EVT: + { + cbdata.event = NETWORK_BLUETOOTH_GATTC_CLOSE; + cbdata.gattc_open_close.conn_id = param->close.conn_id; + memcpy(cbdata.gattc_open_close.bda, param->open.remote_bda, ESP_BD_ADDR_LEN); } break; @@ -1904,11 +1923,6 @@ STATIC void network_bluetooth_gattc_event_handler( } break; - case ESP_GATTC_CLOSE_EVT: - { - nq = false; // FIXME remove - } - break; default: nq = false; @@ -2142,7 +2156,7 @@ STATIC void network_bluetooth_connection_print(const mp_print_t *print, mp_obj_t network_bluetooth_connection_obj_t *connection = MP_OBJ_TO_PTR(self_in); mp_printf(print, "Connection(bda = "); network_bluetooth_print_bda(print, connection->bda); - mp_printf(print, ", connected = %s", connection->connected ? "True" : "False"); + mp_printf(print, ", connected = %s", connection->conn_id == -1 ? "False" : "True"); mp_printf(print, ")"); } @@ -2339,7 +2353,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_i STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_ble_settings(self = %p) n_args = %d\n", bluetooth, n_args); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); @@ -2517,14 +2530,12 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po if (unset_adv_man_name || adv_man_name_buf.buf != NULL) { if (bluetooth->adv_data.p_manufacturer_data != NULL) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("About to free p_manufacturer_data (2)\n"); FREE(bluetooth->adv_data.p_manufacturer_data); bluetooth->adv_data.p_manufacturer_data = NULL; } bluetooth->adv_data.manufacturer_len = adv_man_name_buf.len; if (adv_man_name_buf.len > 0) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("About to call malloc for p_manufacturer_data\n"); bluetooth->adv_data.p_manufacturer_data = MALLOC(adv_man_name_buf.len); memcpy(bluetooth->adv_data.p_manufacturer_data, adv_man_name_buf.buf, adv_man_name_buf.len); } @@ -2661,6 +2672,7 @@ STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { memset(connection, 0, sizeof(network_bluetooth_connection_obj_t)); connection->base.type = &network_bluetooth_connection_type; connection->services = mp_obj_new_list(0, NULL); + connection->conn_id = -1; memcpy(connection->bda, bda_buf.buf, ESP_BD_ADDR_LEN); mp_obj_list_append(bluetooth->connections, connection); @@ -2685,7 +2697,7 @@ STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_ob dest[0] = connection->services; break; case MP_QSTR_is_connected: - dest[0] = connection->connected ? mp_const_true : mp_const_false; + dest[0] = connection->conn_id == -1 ? mp_const_false : mp_const_true; break; } } @@ -2711,6 +2723,7 @@ STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *a ret = network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); if (n_args > 1 && MP_OBJ_IS_TYPE(self, &network_bluetooth_gattc_char_type)) { assert(connection != MP_OBJ_NULL); +#if 0 NETWORK_BLUETOOTH_DEBUG_PRINTF("(un)registering for notify\n"); NETWORK_BLUETOOTH_DEBUG_PRINTF("interface: %02X\n", bluetooth->gattc_interface); NETWORK_BLUETOOTH_DEBUG_PRINTF("bda: "); @@ -2721,6 +2734,7 @@ STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *a NETWORK_BLUETOOTH_DEBUG_PRINTF("char: "); network_bluetooth_gatt_id_print(NULL, &self->char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); +#endif if (self->callback != mp_const_none) { if (esp_ble_gattc_register_for_notify(bluetooth->gattc_interface, connection->bda, &service->service_id, &self->char_id) != ESP_OK) { goto NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR; @@ -2874,8 +2888,7 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_char_write_obj, network_bluetooth_char_write); -STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_char_indicate()\n"); +STATIC mp_obj_t network_bluetooth_char_notify_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args, bool need_confirm) { network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { @@ -2883,10 +2896,9 @@ STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *p } network_bluetooth_char_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); - enum {ARG_value, ARG_need_confirm}; + enum {ARG_value}; static const mp_arg_t allowed_args[] = { { MP_QSTR_value, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL }}, - { MP_QSTR_need_confirm, MP_ARG_BOOL, { .u_bool = false } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -2902,14 +2914,20 @@ STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *p args[ARG_value].u_obj = self->value; } - NETWORK_BLUETOOTH_DEBUG_PRINTF("need confirmations: %s\n", args[ARG_need_confirm].u_bool ? "True" : "False"); - mp_buffer_info_t buf; + mp_buffer_info_t buf = {0}; mp_get_buffer(args[ARG_value].u_obj, &buf, MP_BUFFER_READ); - if (buf.len > 0) { - esp_ble_gatts_send_indicate(bluetooth->gatts_interface, bluetooth->conn_id, self->handle, buf.len, buf.buf, args[ARG_need_confirm].u_bool); - } + esp_ble_gatts_send_indicate(bluetooth->gatts_interface, bluetooth->conn_id, self->handle, buf.len, buf.buf, need_confirm); return mp_const_none; } + +STATIC mp_obj_t network_bluetooth_char_notify(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { + return network_bluetooth_char_notify_helper(n_args, pos_args, kw_args, false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_notify_obj, 1, network_bluetooth_char_notify); + +STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { + return network_bluetooth_char_notify_helper(n_args, pos_args, kw_args, true); +} STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_indicate_obj, 1, network_bluetooth_char_indicate); STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { @@ -3438,6 +3456,7 @@ const mp_obj_type_t network_bluetooth_gattc_service_type = { STATIC const mp_rom_map_elem_t network_bluetooth_gatts_char_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&network_bluetooth_char_indicate_obj) }, + { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&network_bluetooth_char_notify_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_value), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_service), NULL }, // handled by attr handler From 261fb5d3dfe1d5c0e43e8cf34a9597347ebe01b2 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 9 May 2017 16:58:56 -0700 Subject: [PATCH 55/98] esp32/bluetooth_api_proposal.txt: Removed esp32/bluetooth_docs.md: Replaces removed proposal --- esp32/bluetooth_api_proposal.txt | 160 ------------ esp32/bluetooth_docs.md | 415 +++++++++++++++++++++++++++++++ 2 files changed, 415 insertions(+), 160 deletions(-) delete mode 100644 esp32/bluetooth_api_proposal.txt create mode 100644 esp32/bluetooth_docs.md diff --git a/esp32/bluetooth_api_proposal.txt b/esp32/bluetooth_api_proposal.txt deleted file mode 100644 index e184a32fb..000000000 --- a/esp32/bluetooth_api_proposal.txt +++ /dev/null @@ -1,160 +0,0 @@ - - -### Start the BT stack -```python -import network -b = network.Bluetooth() -``` - -### Services & Characteristics - - -###### Service constructor -```python -service = b.Service(uuid, primary = True) -``` - -Services with the same UUID are the same object. Constructing a second -service with the same UUID will return the same service object. The exception -are services that have been closed (via the `.close()` method) -- this -deallocates the service from the BLE stack. - -###### Characteristic constructor -```python -char service.Char(uuid, value = None, permissions = b.PERM_READ | b.PERM_WRITE, properties = b.PROP_READ | b.PROP_WRITE | b.PROP_NOTIFY) -``` - -Characteristics are associated with services. - -###### Start or stop service -```python -service.start() - -# stuff -service.stop() - -# services can be restarted: -service.start() - -``` - -###### Closing a service -```python -service.close() # Will call stop() - -service.start() # Runtime error; service is no longer usable -``` - -Closed service objects are completely "forgotten" by the BLE stack, you -needn't keep reference. You will no longer receive callbacks characteristics attached to the service. - -###### Get a list of current services -```python -currentServices = b.services -``` - -###### Get a list of service characteristics -```python -chars = service.chars -``` - - -### Callbacks - -##### Bluetooth Callback - -```python -def bt_callback(btObj, event, data, userdata): - print ("Bluetooth object", btObj) - if event == btObj.CONNECT: - print ("connected") - if event == btObj.DISCONNECT: - print ("disconnected") - - -Bluetooth.callback(bt_callback, "hello") -``` - -`Bluetooth.callback` takes two parameters: The callback function itself, and an optional userdata value to be passed in on callbacks. It returns the current callback function and usedata as tuple. - -`cb_function` can be None, which disables callbacks. `cb_function` is called with four parameters; the bluetooth object, event, event data, and the userdata. - -Event values: -* `Bluetooth.CONNECT` Data param is remote addr -* `Bluetooth.DISCONNECT` -* `Bluetooth.SCAN_DATA` Scan data -* `Bluetooth.SCAN_CMPL` Scan complete - -##### Characteristic Callbacks - -```python -def char_callback(charObj, event, value, userdata): - print('charcb ', cb, userdata,' ', end='') - if event == b.READ: - print('Read') - return 'ABCDEFG' - elif event == b.WRITE: - print ('Write', value) - -Char.callback(cb_function, userdata) -``` - -`Char.callback` takes two parameters: The callback function itself, and an optional userdata value to be passed in on callbacks. It returns the current callback function and userdata as tuple. - -`cb_function` can be None, which disables callbacks. `cb_function` is called with four parameters; the characteristic object, the event type, the event value (the sent value for `WRITE` or the current characteristic value for `READ`), and userdata. - -The event type will be one of `Bluetooth.READ` or `Bluetooth.WRITE`. - -Characteristics have an internal value, which is _not_ used and _not_ updated when there is a callback, though the callback is free to update or use the value as it sees fit. For `READ` operations (or `WRITE` operations that require a return value) the return value of the callback is sent, which must be a `bytearray`, `str`, `bytes`, or `None`. - -###### Value behavior without a callback - -If there is no callback defined for a characteristic, it's internal value will be used for `READ` or `WRITE` events, and `WRITE` events that expect a response will simply return the just-written value. - - - - -### Advertising -##### BLE settings - -```python -b.ble_settings( - int_min = 1280, - int_max = 1280, - type b.ADV_TYPE_IND, - own_addr_type = b.BLE_ADDR_TYPE_PUBLIC, - peer_addr = bytearray([0 for x in range(6)]), - peer_addr_type = b.BLE_ADDR_TYPE_PUBLIC, - channel_map = b.ADV_CHNL_ALL, - filter_policy = b.ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, - adv_is_scan_rsp = False, - adv_dev_name = None, - adv_man_name = None, - adv_inc_tx_power = False, - adv_int_min = 1280, - adv_int_max = 1280, - adv_appearance = 0, - adv_uuid = None, - adv_flags = 0) - -b.adv_enable(True) -``` - -### Scanning - -###### Scan start: - -Advertising and scanning cannot be run at the same time - -`Bluetooth.scan_start(timeout)` - -###### Scan stop: -`Bluetooth.scan_stop()` - - -###### Scan callback data - -The Bluetooth callback will receive: - -* `Bluetooth.SCAN_DATA` Data will be a 2-tuple of `(remote_address, adv_name)` -* `Bluetooth.SCAN_CMPL` Scan has completed; data will be None diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md new file mode 100644 index 000000000..ed17059c5 --- /dev/null +++ b/esp32/bluetooth_docs.md @@ -0,0 +1,415 @@ + +### Abbreviations + +* GATT: Generic Attribute Profile +* GAP: Generic Access Profile (advertising, mostly) +* GATTS: GATT Server +* GATTC: GATT Client + + +### Brief introduction: + +**GATTS** is a BLE device like a heart rate monitor. It can have a single connection from a GATTC device. +**GATTS** is a BLE "central device" (e.g. a phone, tablet, or computer). +**GAP** is used for GATTS devices to advertise their presence. + +## General + +### Bluetooth Objects + +The Bluetooth object is a global singleton. + +```python +import network +bluetooth = network.Bluetooth() +``` + + +Note that these defaults are set when you create the Bluetooth object. You needn't call `ble_settings` unless you need to change one of these. + +```python +bluetooth.ble_settings(int_min = 1280, int_max = 1280, + adv_type = bluetooth.ADV_TYPE_IND, + own_addr_type = bluetooth.BLE_ADDR_TYPE_PUBLIC, + peer_addr = bytearray([0] * 6)), a + peer_addr_type = bluetooth.BLE_ADDR_TYPE_PUBLIC, + channel_map = bluetooth.ADV_CHNL_ALL, + filter_policy = blueooth.ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + adv_is_scan_rsp = False, + adv_dev_name = None, + adv_man_name = None, + adv_inc_tx_power = False, + adv_int_min = 1280, + adv_int_max = 1280, + adv_appearance = 0, + adv_uuid = None, + adv_flags = 0) +``` + +`adv_type` is one of: + + * `bluetooth.ADV_TYPE_IND` + * `bluetooth.ADV_TYPE_DIRECT_IND_HIGH` + * `bluetooth.ADV_TYPE_SCAN_IND` + * `bluetooth.ADV_TYPE_NONCONN_IND` + * `bluetooth.ADV_TYPE_DIRECT_IND_LOW` + +`own_addr_type` and `peer_addr_type` is one of: +* `bluetooth.BLE_ADDR_TYPE_PUBLIC` +* `bluetooth.BLE_ADDR_TYPE_RANDOM` +* `bluetooth.BLE_ADDR_TYPE_RPA_PUBLIC` +* `bluetooth.BLE_ADDR_TYPE_RPA_RANDOM` + +`peer_addr` is a `bytearray(6)` or `bytes` representing the peer address. + +`channel_map` is a binary OR of: + +* `bluetooth.ADV_CHNL_37` +* `bluetooth.ADV_CHNL_38` +* `bluetooth.ADV_CHNL_39` +* `bluetooth.ADV_CHNL_ALL` + +`filter_policy` is one of: + +* `bluetooth.ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY` +* `bluetooth.ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY` +* `bluetooth.ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST` +* `bluetooth.ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST` + +`adv_is_scan_rsp` indicates in the advertising information is a scan response. + +`adv_dev_name` is the advertised device name. + +`adv_man_name` is the advertised manufacturer name. + +`adv_inc_tx_power` to include the transmission power in the advertisement. + +`adv_int_min` and `adv_int_max` for the advertised intervals, in milliseconds. + +`adv_appearance` is an integer representing the appearance of the device. + +`adv_uuid` the advertising uuid. + +`adv_flags` is a binary or of: + +* `bluetooth.BLE_ADV_FLAG_LIMIT_DISC` +* `bluetooth.BLE_ADV_FLAG_GEN_DISC` +* `bluetooth.BLE_ADV_FLAG_BREDR_NOT_SPT` +* `bluetooth.BLE_ADV_FLAG_DMT_CONTROLLER_SPT` +* `bluetooth.BLE_ADV_FLAG_DMT_HOST_SPT` +* `bluetooth.BLE_ADV_FLAG_NON_LIMIT_DISC` + +`bluetooth.init()` enable the bluetooth subsystem. The first call to the Bluetooth constructor will call this. You only need to call `init()` if you've called `deinit()`. + +`bluetooth.deinit()` shutdown Bluetooth. Due to present limitations in the IDF, this does _not_ return the BT stack to a lower powered state. + +`bluetooth.connect(bda)` GATTC - connect to a remote GATTS server. BDA is the remote address, as a `bytearray(6)`. See [GATTC](#gattc) for more information + +`bluetooth.Service(uuid, is_primary = True)` GATTS - create a new GATTSService object. `uuid` is either an integer or a bytearray(16). UUIDs are globally unique with in GATTS. If you attempt to create a service with a UUID that is the same as an existing (but not closed) service, you will receive the same service object, and no new service will be created. + +`bluetooth.services` GATTS - returns the existing GATTS services. + +`bluetooth.callback(, )` used to set the callback function for bluetooth-object-level callbacks. `` can be set to None. If `` is not specified, it will be set to None. Always returns a 2-tuple of the present `` and ``. If called with no parameters, the values remain unchanged. `` will be called with 4 parameters: + +1. The `bluetooth` object +2. The event, which is one of: + * `bluetooth.CONNECT` when a GATTS or GATTC connection occurs + * `bluetooth.DISCONNECT` when a GATTS or GATTC disconnect occurs + * `bluetooth.SCAN_RES` for GATTC scan results + * `bluetooth.SCAN_CMPL` when GATTC scan is complete +3. Event data: + * For `bluetooth.CONNECT`, `bluetooth.DISCONNECT` events, this will be a bytearray represeting the remote address. + * For `bluetooth.SCAN_RES` this will be a 2-tuple of `(, )` + * For `bluetooth.SCAN_CMPL` this will be `None`. +4. The `)` GATTC - begin scanning for hosts. + +`bluetooth.scan_stop()` GATTC - terminate scanning early. If called before the scan timeout, you will _not_ receive a `bluetooth.SCAN_CMPL` event. + +`bluetooth.is_scanning` GATTC - returns `True` if the scan is still active + +## GATTS + +### GATTSService Objects + +GATTSService objects are created by calling the `bluetooth.Service()` constructor. + + +`service.Char(uuid, value = None, perm = bluetooth.PERM_READ | bluetooth.PERM_WRITE, prop = bluetooth.PROP_READ | bluetooth.PROP_WRITE | bluetooth.PROPR_NOTIFY)` Create a new characteristic for this service. Characteristic UUIDS are unique for a particular service, and an attempt to create another characteristic with the same UUID will simply return the existing `GATTSChar` object. + +`perm` is a binary OR of the following: + +* `bluetooth.PERM_READ` +* `bluetooth.PERM_READ_ENCRYPTED` +* `bluetooth.PERM_READ_ENC_MITM` +* `bluetooth.PERM_WRITE` +* `bluetooth.PERM_WRITE_ENCRYPTED` +* `bluetooth.PERM_WRITE_ENC_MITM` +* `bluetooth.PERM_WRITE_SIGNED` +* `bluetooth.PERM_WRITE_SIGNED_MITM` + +`prop` is a binary OR of the following: + +* `bluetooth.PROP_BROADCAST` +* `bluetooth.PROP_READ` +* `bluetooth.PROP_WRITE_NR` +* `bluetooth.PROP_WRITE` +* `bluetooth.PROP_NOTIFY` +* `bluetooth.PROP_INDICATE` +* `bluetooth.PROP_AUTH` +* `bluetooth.PROP_EXT_PROP` + +`service.chars` Get the characteristics attached to this service. + +`service.is_primary` Get the value of the srvice `primary` flag. + +`char.uuid` Get the service UUID. + +`service.start()` Start the service; it will be visible to any connecting GATTC. + +`service.stop()` Stop the service. + +`service.close()` Delete this service from the GATTS. You can no longer use this service object. + +### GATTSChar objects + +GATTSChar objects are created by calling the `service.Char()` constructor, and they are associated with that service. + +`char.callback(, )` Sets the callback function for this service. It operates the same way as the `bluetooth.callback()` function. `` will be called with 4 parameters: + +1. The `GATTSChar` object +2. The event that occured, which is one of: + * `bluetooth.READ` when a GATTC issues a read command for that characteristic. + * `bluetooth.WRITE` when a GATTC issues a write command for that characteristic. +3. The value. For `bluetooth.READ`, this is the current stored value of the characteristic. For `bluetooth.WRITE` this is the value written by the GATTC. +4. the `` + +For `bluetooth.READ` events, the return value of the callback is what is returned to the GATTC. When there is a callback for a characteristic, the characteristic value is not modified or otherwise used. It's up to the callback to do whatever is necessary with the write data, or to return the proper data for a read. + +In the absence of a callback, then the characteristic value is return for a read, and it is updated for a write. + + +`char.indicate()` Send an indicate value. `` is `string`, `bytearray`, `bytes` or `None`. + +`char.notify()` Send a notify value. `` is `string`, `bytearray`, `bytes` or `None`. + +`char.uuid` Get the characteristic UUID. + +`char.value` Get or set the characteristic value. + +`char.service` Get the service this characteristic is attached to. + + +## GATTC + +Use `bluetooth.scan_start()`, to find GATTS devices. You'll need to set up a Bluetooth object callback to get scan results. You can then use `bluetooth.connect()` to connec to a GATTS device: + +`bluetooth.connect()` Returns a `GATTCConn` object. + +### GATTCConn objects + +`conn.services` Returns the services associated with the connection. This is a list of [`GATTCService`](#gattcservice-objects) objects. + +`conn.is_connected` Returns whether the connection is active or not. + +### GATTCService objects + +`service.is_primary` Returns a boolean indicating if the service is a primary service or not. + +`service.uuid` Returns the service UUID + +`service.chars` Returns a list of [`GATTCChar`](#gattcchar-objects) objects associated with this service + +### GATTCChar objects + +`char.callback(, ` + +`char.descriptors` Returns a list of [`GATTCDescr`](#gattcdescr-objects) associated with this characteristic. + +`char.read()` Read the characteristic value + +`char.write()` Write a value to the characteristic. `` can be `str`, `bytearray`, `bytes`, or `None` + +### GATTCDescr objects + +`GATTCChar` objects often have associated BLE desriptor objects. These can be obtained by accessing the `char.descriptors` property of [`GATTCChar`](#gattcchar-objects) objects. + +`descr.read()` Read from the descriptor. + +`descr.write()` Write a value to the characteristic. `` can be `str`, `bytearray`, `bytes`, or `None` + +`descr.uuid` Get the descriptor UUID. + +`descr.char` Get the [`GATTCChar`](#gattcchar-objects) the descriptor is attached to + + +------------------ + +### GATT Server + +A GATT server is a device like a heart rate monitor. A GATT *client* would be a device +like a smart phone or tablet. + +#### GATT Services + + +###### Constructor +```python +service = bluetooth.Service(uuid, primary = True) +``` + +Services with the same UUID are the same object. Constructing a second +service with the same UUID will return the same service object. The exception +are services that have been closed (via the `.close()` method) -- this +deallocates the service from the BLE stack. + +The only way to remove a service is the `close()` method of service objects. + +###### Characteristic constructor +```python +char = service.Char(uuid, value = None, permissions = b.PERM_READ | b.PERM_WRITE, properties = b.PROP_READ | b.PROP_WRITE | b.PROP_NOTIFY) +``` + +Characteristics are associated with services. + +###### Start or stop service +```python +service.start() + +# stuff +service.stop() + +# services can be restarted: +service.start() + +``` + +###### Closing a service +```python +service.close() # Will call stop() + +service.start() # Runtime error; service is no longer usable +``` + +Closed service objects are completely "forgotten" by the BLE stack, you +needn't keep reference. You will no longer receive callbacks characteristics attached to the service. + +###### Get a list of current services +```python +currentServices = b.services +``` + +###### Get a list of service characteristics +```python +chars = service.chars +``` + + +### Callbacks + +##### Bluetooth Callback + +```python +def bt_callback(btObj, event, data, userdata): + print ("Bluetooth object", btObj) + if event == btObj.CONNECT: + print ("connected") + if event == btObj.DISCONNECT: + print ("disconnected") + + +Bluetooth.callback(bt_callback, "hello") +``` + +`Bluetooth.callback` takes two parameters: The callback function itself, and an optional userdata value to be passed in on callbacks. It returns the current callback function and usedata as tuple. + +`cb_function` can be None, which disables callbacks. `cb_function` is called with four parameters; the bluetooth object, event, event data, and the userdata. + +Event values: +* `Bluetooth.CONNECT` Data param is remote addr +* `Bluetooth.DISCONNECT` +* `Bluetooth.SCAN_DATA` Scan data +* `Bluetooth.SCAN_CMPL` Scan complete + +##### Characteristic Callbacks + +```python +def char_callback(charObj, event, value, userdata): + print('charcb ', cb, userdata,' ', end='') + if event == b.READ: + print('Read') + return 'ABCDEFG' + elif event == b.WRITE: + print ('Write', value) + +Char.callback(cb_function, userdata) +``` + +`Char.callback` takes two parameters: The callback function itself, and an optional userdata value to be passed in on callbacks. It returns the current callback function and userdata as tuple. + +`cb_function` can be None, which disables callbacks. `cb_function` is called with four parameters; the characteristic object, the event type, the event value (the sent value for `WRITE` or the current characteristic value for `READ`), and userdata. + +The event type will be one of `Bluetooth.READ` or `Bluetooth.WRITE`. + +Characteristics have an internal value, which is _not_ used and _not_ updated when there is a callback, though the callback is free to update or use the value as it sees fit. For `READ` operations (or `WRITE` operations that require a return value) the return value of the callback is sent, which must be a `bytearray`, `str`, `bytes`, or `None`. + +###### Value behavior without a callback + +If there is no callback defined for a characteristic, it's internal value will be used for `READ` or `WRITE` events, and `WRITE` events that expect a response will simply return the just-written value. + + + + +### Advertising +##### BLE settings + +```python +b.ble_settings( + int_min = 1280, + int_max = 1280, + type b.ADV_TYPE_IND, + own_addr_type = b.BLE_ADDR_TYPE_PUBLIC, + peer_addr = bytearray([0 for x in range(6)]), + peer_addr_type = b.BLE_ADDR_TYPE_PUBLIC, + channel_map = b.ADV_CHNL_ALL, + filter_policy = b.ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, + adv_is_scan_rsp = False, + adv_dev_name = None, + adv_man_name = None, + adv_inc_tx_power = False, + adv_int_min = 1280, + adv_int_max = 1280, + adv_appearance = 0, + adv_uuid = None, + adv_flags = 0) + +b.adv_enable(True) +``` + +### Scanning + +###### Scan start: + +Advertising and scanning cannot be run at the same time + +`Bluetooth.scan_start(timeout)` + +###### Scan stop: +`Bluetooth.scan_stop()` + + +###### Scan callback data + +The Bluetooth callback will receive: + +* `Bluetooth.SCAN_DATA` Data will be a 2-tuple of `(remote_address, adv_name)` +* `Bluetooth.SCAN_CMPL` Scan has completed; data will be None From 48c0c6ad6c1ce66670ffc951641837d662f9118a Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 9 May 2017 17:01:22 -0700 Subject: [PATCH 56/98] esp32/network_bluetooth.c: Added some final constants, other tweaks --- esp32/network_bluetooth.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 15180cd23..d6e5c82ff 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2154,7 +2154,7 @@ STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_o STATIC void network_bluetooth_connection_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_connection_obj_t *connection = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "Connection(bda = "); + mp_printf(print, "GATTCConn(bda = "); network_bluetooth_print_bda(print, connection->bda); mp_printf(print, ", connected = %s", connection->conn_id == -1 ? "False" : "True"); mp_printf(print, ")"); @@ -2390,7 +2390,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po static const mp_arg_t allowed_args[] = { { MP_QSTR_int_min, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_int_max, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, + { MP_QSTR_adv_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, { MP_QSTR_own_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, { MP_QSTR_peer_addr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }}, { MP_QSTR_peer_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }}, @@ -3202,6 +3202,14 @@ STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t dest[0] = self->chars; break; + case MP_QSTR_uuid: + { + esp_bt_uuid_t uuid128; + uuid_to_uuid128(&self->service_id.id.uuid, &uuid128); + dest[0] = mp_obj_new_bytearray(uuid128.len, uuid128.uuid.uuid128); + } + break; + case MP_QSTR_is_primary: dest[0] = self->service_id.is_primary ? mp_const_true : mp_const_false ; break; @@ -3335,6 +3343,15 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, + + // BLE_ADV_DATA_FLAG + + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_LIMIT_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_LIMIT_DISC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_GEN_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_GEN_DISC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_BREDR_NOT_SPT), MP_ROM_INT(ESP_BLE_ADV_FLAG_BREDR_NOT_SPT) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_DMT_CONTROLLER_SPT), MP_ROM_INT(ESP_BLE_ADV_FLAG_DMT_CONTROLLER_SPT) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_DMT_HOST_SPT), MP_ROM_INT(ESP_BLE_ADV_FLAG_DMT_HOST_SPT) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_NON_LIMIT_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_NON_LIMIT_DISC) }, // exp_gatt_perm_t { MP_ROM_QSTR(MP_QSTR_PERM_READ), MP_ROM_INT(ESP_GATT_PERM_READ) }, @@ -3394,7 +3411,7 @@ STATIC MP_DEFINE_CONST_DICT(network_bluetooth_connection_locals_dict, network_bl const mp_obj_type_t network_bluetooth_connection_type = { { &mp_type_type }, - .name = MP_QSTR_Connection, + .name = MP_QSTR_GATTCConn, .print = network_bluetooth_connection_print, //.make_new = network_bluetooth_service_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_connection_locals_dict, From 8eaacc10752104105d73cfc7bbc601ccf0546a17 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 10 May 2017 13:53:07 -0700 Subject: [PATCH 57/98] reformatted, many minor fixes --- esp32/network_bluetooth.c | 1281 ++++++++++++++++++------------------- 1 file changed, 611 insertions(+), 670 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index d6e5c82ff..660a65692 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -1,4 +1,4 @@ -/* +/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) @@ -57,7 +57,7 @@ #ifdef EVENT_DEBUG # define EVENT_DEBUG_GATTC # define EVENT_DEBUG_GATTS -//# define EVENT_DEBUG_GAP +# define EVENT_DEBUG_GAP #endif #define UUID_LEN 16 @@ -68,9 +68,11 @@ # define FREE(x) vPortFree(x) #else # define MALLOC(x) NULL -# define FREE(x) +# define FREE(x) #endif +#define MP_OBJ_NEW_BYTES(len, data) mp_obj_new_str_of_type(&mp_type_bytes, data, len) + const mp_obj_type_t network_bluetooth_type; const mp_obj_type_t network_bluetooth_connection_type; const mp_obj_type_t network_bluetooth_gatts_service_type; @@ -80,11 +82,8 @@ const mp_obj_type_t network_bluetooth_gattc_char_type; const mp_obj_type_t network_bluetooth_gattc_descr_type; STATIC SemaphoreHandle_t item_mut; -STATIC bool network_bluetooth_bt_controller_enabled = false; - - -#define MP_OBJ_IS_BT_DATATYPE(O) (MP_OBJ_IS_STR_OR_BYTES(O) || MP_OBJ_IS_TYPE(O, &mp_type_bytearray) || (O == mp_const_none)) +#define MP_OBJ_IS_BYTEARRAY_OR_BYTES(O) (MP_OBJ_IS_TYPE(O, &mp_type_bytes) || MP_OBJ_IS_TYPE(O, &mp_type_bytearray)) #define ITEM_BEGIN() assert(xSemaphoreTake(item_mut, portMAX_DELAY) == pdTRUE) #define ITEM_END() xSemaphoreGive(item_mut) @@ -108,11 +107,11 @@ typedef enum { NETWORK_BLUETOOTH_GATTC_SEARCH_RES, // Found GATTS services - NETWORK_BLUETOOTH_GATTC_GET_CHAR, - NETWORK_BLUETOOTH_GATTC_GET_DESCR, + NETWORK_BLUETOOTH_GATTC_GET_CHAR, + NETWORK_BLUETOOTH_GATTC_GET_DESCR, - NETWORK_BLUETOOTH_GATTC_OPEN, - NETWORK_BLUETOOTH_GATTC_CLOSE, + NETWORK_BLUETOOTH_GATTC_OPEN, + NETWORK_BLUETOOTH_GATTC_CLOSE, // characteristic events NETWORK_BLUETOOTH_READ, @@ -151,19 +150,19 @@ typedef struct { uint8_t adv_data_len; } gattc_scan_res; - struct { + struct { uint16_t conn_id; esp_gatt_srvc_id_t service_id; } gattc_search_res; - struct { + struct { uint16_t conn_id; esp_gatt_srvc_id_t service_id; esp_gatt_id_t char_id; esp_gatt_char_prop_t props; } gattc_get_char; - struct { + struct { uint16_t conn_id; esp_gatt_srvc_id_t service_id; esp_gatt_id_t char_id; @@ -194,19 +193,19 @@ typedef struct { // come after the first four above, // which _must_ match the read struct - uint8_t* value; // Need to free this! + uint8_t* value; // Need to free this! size_t value_len; } write; struct { uint16_t conn_id; - + esp_gatt_srvc_id_t service_id; esp_gatt_id_t char_id; esp_gatt_id_t descr_id; bool need_rsp; - uint8_t* value; // Need to free this! + uint8_t* value; // Need to free this! size_t value_len; } notify; }; @@ -214,7 +213,7 @@ typedef struct { } callback_data_t; typedef struct { - uint8_t* value; // Need to free this! + uint8_t* value; // Need to free this! size_t value_len; } read_write_data_t; @@ -231,7 +230,7 @@ typedef struct { bool started; bool valid; -} network_bluetooth_service_obj_t; +} network_bluetooth_service_obj_t; // "Connection" @@ -327,7 +326,7 @@ STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { network_bluetooth_singleton->adv_params.adv_type = ADV_TYPE_IND; network_bluetooth_singleton->adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC; network_bluetooth_singleton->adv_params.peer_addr_type = BLE_ADDR_TYPE_PUBLIC; - network_bluetooth_singleton->adv_params.channel_map = ADV_CHNL_ALL; + network_bluetooth_singleton->adv_params.channel_map = ADV_CHNL_ALL; network_bluetooth_singleton->adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY; network_bluetooth_singleton->adv_data.set_scan_rsp = false; network_bluetooth_singleton->adv_data.include_name = false; @@ -357,37 +356,41 @@ STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { STATIC QueueHandle_t callback_q = NULL; STATIC QueueHandle_t read_write_q = NULL; -STATIC size_t cbq_count() { - return uxQueueMessagesWaiting(callback_q); -} - - -STATIC bool cbq_push (const callback_data_t* data) { - //NETWORK_BLUETOOTH_DEBUG_PRINTF("push: Qsize: %u\n", cbq_count()); +STATIC bool cbq_push(const callback_data_t* data) { return xQueueSend(callback_q, data, portMAX_DELAY) == pdPASS; } -STATIC bool cbq_pop (callback_data_t* data) { +STATIC bool cbq_pop(callback_data_t* data) { return xQueueReceive(callback_q, data, 0) == pdPASS; } STATIC void dumpBuf(const uint8_t *buf, size_t len) { - while(len--) + while (len--) { printf("%02X ", *buf++); + } } -STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { +STATIC bool mp_obj_is_bt_datatype(mp_obj_t o) { + return MP_OBJ_IS_STR(o) || MP_OBJ_IS_BYTEARRAY_OR_BYTES(o) || o == mp_const_none; +} + +STATIC void mp_obj_is_bt_datatype_raise(mp_obj_t o) { + if (!mp_obj_is_bt_datatype(o)) { + mp_raise_ValueError("must be str, bytes, bytearray, or None"); + } +} +STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { if (MP_OBJ_IS_INT(src)) { uint32_t arg_uuid = mp_obj_get_int(src); target->len = arg_uuid == (arg_uuid & 0xFFFF) ? sizeof(uint16_t) : sizeof(uint32_t); uint8_t * uuid_ptr = (uint8_t*)&target->uuid.uuid128; - for(int i = 0; i < target->len; i++) { + for (int i = 0; i < target->len; i++) { // LSB first - *uuid_ptr++ = arg_uuid & 0xff; + *uuid_ptr++ = arg_uuid & 0xff; arg_uuid >>= 8; } - } else if (mp_obj_get_type(src) != &mp_type_bytearray) { + } else if (!MP_OBJ_IS_BYTEARRAY_OR_BYTES(src)) { goto PARSE_UUID_BAD; } else { mp_buffer_info_t buf; @@ -401,19 +404,20 @@ STATIC void parse_uuid(mp_obj_t src, esp_bt_uuid_t* target) { return; PARSE_UUID_BAD: - mp_raise_ValueError("uuid must be integer or bytearray(16)"); + mp_raise_ValueError("uuid must be integer, bytearray(16), or bytes(16)"); } static void uuid_to_uuid128(const esp_bt_uuid_t* in, esp_bt_uuid_t* out) { - static const uint8_t base_uuid[] = - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }; + static const uint8_t base_uuid[] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB + }; if (in->len == 16) { *out = *in; return; - } + } out->len = 16; memcpy(out->uuid.uuid128, base_uuid, MP_ARRAY_SIZE(base_uuid)); @@ -425,7 +429,6 @@ static void uuid_to_uuid128(const esp_bt_uuid_t* in, esp_bt_uuid_t* out) { uint32_t t = htonl(in->uuid.uuid32); memcpy(out->uuid.uuid128, &t, sizeof(t)); } - } STATIC bool uuid_eq(const esp_bt_uuid_t* a, const esp_bt_uuid_t* b) { @@ -438,7 +441,7 @@ STATIC bool uuid_eq(const esp_bt_uuid_t* a, const esp_bt_uuid_t* b) { STATIC void network_bluetooth_gatt_id_print(const mp_print_t *print, const esp_gatt_id_t* gatt_id) { esp_bt_uuid_t uuid128; uuid_to_uuid128(&gatt_id->uuid, &uuid128); - for(int i = 0; i < uuid128.len; i++) { + for (int i = 0; i < uuid128.len; i++) { if (print != NULL) { mp_printf(print, "%02X", uuid128.uuid.uuid128[i]); } else { @@ -457,7 +460,6 @@ STATIC void network_bluetooth_gatt_id_print(const mp_print_t *print, const esp_g } else { NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X ", gatt_id->inst_id); } - } typedef enum { @@ -469,19 +471,17 @@ typedef enum { } item_op_t; -STATIC mp_obj_t network_bluetooth_item_opx(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle_or_conn_id, esp_bd_addr_t bda, item_op_t kind) { - //NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_item_op, list is %p\n", list); - +STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle_or_conn_id, esp_bd_addr_t bda, item_op_t kind) { ITEM_BEGIN(); mp_obj_t ret = MP_OBJ_NULL; size_t len; mp_obj_t *items; mp_obj_get_array(list, &len, &items); - for(int i = 0; i < len; i++) { - switch(kind) { + for (int i = 0; i < len; i++) { + switch (kind) { // These all search a services list - case NETWORK_BLUETOOTH_FIND_SERVICE: + case NETWORK_BLUETOOTH_FIND_SERVICE: case NETWORK_BLUETOOTH_FIND_CHAR: case NETWORK_BLUETOOTH_DEL_SERVICE: { @@ -491,12 +491,12 @@ STATIC mp_obj_t network_bluetooth_item_opx(mp_obj_t list, esp_bt_uuid_t* uuid, u size_t char_len; mp_obj_t *char_items; mp_obj_get_array(service->chars, &char_len, &char_items); - for(int j = 0; j < char_len; j++) { + for (int j = 0; j < char_len; j++) { network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) char_items[j]; if ((uuid != NULL && uuid_eq(&chr->char_id.uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { ret = chr; goto NETWORK_BLUETOOTH_ITEM_END; - } + } } } else if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || (uuid == NULL && service->handle == handle_or_conn_id)) { @@ -518,23 +518,13 @@ STATIC mp_obj_t network_bluetooth_item_opx(mp_obj_t list, esp_bt_uuid_t* uuid, u if ((uuid != NULL && uuid_eq(&chr->char_id.uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { ret = chr; goto NETWORK_BLUETOOTH_ITEM_END; - } + } } break; case NETWORK_BLUETOOTH_FIND_CONNECTION: { network_bluetooth_connection_obj_t* conn = (network_bluetooth_connection_obj_t*) items[i]; -#if 0 - { - int res = memcmp(conn->bda, bda, ESP_BD_ADDR_LEN); - NETWORK_BLUETOOTH_DEBUG_PRINTF("compare "); - network_bluetooth_print_bda(NULL, con->bda); - NETWORK_BLUETOOTH_DEBUG_PRINTF(" to "); - network_bluetooth_print_bda(NULL, bda); - NETWORK_BLUETOOTH_DEBUG_PRINTF(" got %d\n", result); - } -#endif if ((bda != NULL && memcmp(conn->bda, bda, ESP_BD_ADDR_LEN) == 0) || (bda == NULL && conn->conn_id == handle_or_conn_id)) { ret = conn; goto NETWORK_BLUETOOTH_ITEM_END; @@ -543,6 +533,7 @@ STATIC mp_obj_t network_bluetooth_item_opx(mp_obj_t list, esp_bt_uuid_t* uuid, u break; } } + NETWORK_BLUETOOTH_ITEM_END: ITEM_END(); return ret; @@ -550,45 +541,48 @@ STATIC mp_obj_t network_bluetooth_item_opx(mp_obj_t list, esp_bt_uuid_t* uuid, u STATIC mp_obj_t network_bluetooth_find_service_by_handle(uint16_t handle) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_opx(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); + return network_bluetooth_item_op(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); } STATIC mp_obj_t network_bluetooth_find_connection_by_bda(esp_bd_addr_t bda) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_opx(bluetooth->connections, NULL, 0, bda, NETWORK_BLUETOOTH_FIND_CONNECTION); + return network_bluetooth_item_op(bluetooth->connections, NULL, 0, bda, NETWORK_BLUETOOTH_FIND_CONNECTION); } STATIC mp_obj_t network_bluetooth_find_connection_by_conn_id(uint16_t conn_id) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_opx(bluetooth->connections, NULL, conn_id, NULL, NETWORK_BLUETOOTH_FIND_CONNECTION); + return network_bluetooth_item_op(bluetooth->connections, NULL, conn_id, NULL, NETWORK_BLUETOOTH_FIND_CONNECTION); } STATIC mp_obj_t network_bluetooth_find_service_by_uuid(esp_bt_uuid_t* uuid) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_opx(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); + return network_bluetooth_item_op(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); } STATIC mp_obj_t network_bluetooth_find_service_in_connection_by_uuid(network_bluetooth_connection_obj_t* connection, esp_bt_uuid_t* uuid) { - return network_bluetooth_item_opx(connection->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); + return network_bluetooth_item_op(connection->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); } +// FIXME: Not used? +#if 0 STATIC mp_obj_t network_bluetooth_find_char_by_uuid(esp_bt_uuid_t* uuid) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_opx(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR); + return network_bluetooth_item_op(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR); } +#endif STATIC mp_obj_t network_bluetooth_find_char_by_handle(uint16_t handle) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_opx(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_CHAR); + return network_bluetooth_item_op(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_CHAR); } STATIC mp_obj_t network_bluetooth_find_char_in_service_by_uuid(network_bluetooth_service_obj_t* service, esp_bt_uuid_t* uuid) { - return network_bluetooth_item_opx(service->chars, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE); + return network_bluetooth_item_op(service->chars, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE); } STATIC mp_obj_t network_bluetooth_del_service_by_uuid(esp_bt_uuid_t* uuid) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_opx(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_DEL_SERVICE); + return network_bluetooth_item_op(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_DEL_SERVICE); } STATIC void network_bluetooth_print_bda(const mp_print_t *print, esp_bd_addr_t bda) { @@ -608,15 +602,15 @@ STATIC bool check_locals_dict(mp_obj_t self, qstr attr, mp_obj_t *dest) { if (elem != NULL && elem->value != NULL) { mp_convert_member_lookup(self, type, elem->value, dest); return true; - } + } } return false; } -#ifdef EVENT_DEBUG +#ifdef EVENT_DEBUG typedef struct { - uint8_t id; + uint8_t id; const char * name; } gatt_status_name_t; @@ -681,9 +675,9 @@ STATIC const gatt_status_name_t gatt_status_names[] = { STATIC void gattc_event_dump( - esp_gattc_cb_event_t event, - esp_gatt_if_t gattc_if, - esp_ble_gattc_cb_param_t *param) { + esp_gattc_cb_event_t event, + esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) { const char * event_names[] = { "REG", // 0x00 "UNREG", @@ -728,22 +722,22 @@ STATIC void gattc_event_dump( }; NETWORK_BLUETOOTH_DEBUG_PRINTF( - "network_bluetooth_gattc_event_handler(" - "event = %02X / %s" - ", if = %02X", - event, event_names[event], gattc_if - ); + "network_bluetooth_gattc_event_handler(" + "event = %02X / %s" + ", if = %02X", + event, event_names[event], gattc_if + ); - NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", param = ("); - switch(event) { + switch (event) { case ESP_GATTC_REG_EVT: { PRINT_STATUS(param->reg.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", app_id = %04X", - param->reg.app_id - ); + ", app_id = %04X", + param->reg.app_id + ); } break; @@ -751,17 +745,17 @@ STATIC void gattc_event_dump( { PRINT_STATUS(param->open.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", conn_id = %04X" - ", addr = %02X:%02X:%02X:%02X:%02X:%02X" - ", mtu = %04X", - param->open.conn_id, - param->open.remote_bda[0], - param->open.remote_bda[1], - param->open.remote_bda[2], - param->open.remote_bda[3], - param->open.remote_bda[4], - param->open.remote_bda[5], - param->open.mtu); + ", conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X" + ", mtu = %04X", + param->open.conn_id, + param->open.remote_bda[0], + param->open.remote_bda[1], + param->open.remote_bda[2], + param->open.remote_bda[3], + param->open.remote_bda[4], + param->open.remote_bda[5], + param->open.mtu); } break; @@ -769,17 +763,17 @@ STATIC void gattc_event_dump( { PRINT_STATUS(param->close.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", addr = %02X:%02X:%02X:%02X:%02X:%02X" - ", reason = ", - param->close.conn_id, - param->close.remote_bda[0], - param->close.remote_bda[1], - param->close.remote_bda[2], - param->close.remote_bda[3], - param->close.remote_bda[4], - param->close.remote_bda[5]); - switch(param->close.reason) { + "conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X" + ", reason = ", + param->close.conn_id, + param->close.remote_bda[0], + param->close.remote_bda[1], + param->close.remote_bda[2], + param->close.remote_bda[3], + param->close.remote_bda[4], + param->close.remote_bda[5]); + switch (param->close.reason) { case ESP_GATT_CONN_UNKNOWN: NETWORK_BLUETOOTH_DEBUG_PRINTF("UNKNOWN"); break; @@ -816,10 +810,10 @@ STATIC void gattc_event_dump( { PRINT_STATUS(param->open.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", conn_id = %04X" - ", mtu = %04X", - param->cfg_mtu.conn_id, - param->cfg_mtu.mtu); + ", conn_id = %04X" + ", mtu = %04X", + param->cfg_mtu.conn_id, + param->cfg_mtu.mtu); } break; @@ -827,22 +821,22 @@ STATIC void gattc_event_dump( { PRINT_STATUS(param->search_cmpl.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", conn_id = %04X", - param->search_cmpl.conn_id); + ", conn_id = %04X", + param->search_cmpl.conn_id); } break; case ESP_GATTC_SEARCH_RES_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X", - param->search_res.conn_id); + "conn_id = %04X", + param->search_res.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->search_res.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->search_res.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->search_res.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->search_res.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } break; @@ -855,29 +849,29 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->read.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->read.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->read.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->read.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->read.char_id); + network_bluetooth_gatt_id_print(NULL, ¶m->read.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); dumpBuf((uint8_t*)¶m->read.descr_id.uuid.uuid, param->read.descr_id.uuid.len); - network_bluetooth_gatt_id_print(NULL,¶m->read.descr_id); + network_bluetooth_gatt_id_print(NULL, ¶m->read.descr_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", value = ("); dumpBuf(param->read.value, param->read.value_len); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", value_len = %d " - ", value_type = %X", - param->read.value_len, - param->read.value_type); + ", value_len = %d " + ", value_type = %X", + param->read.value_len, + param->read.value_type); } break; @@ -890,17 +884,17 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->write.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->write.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->write.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->write.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->write.char_id); + network_bluetooth_gatt_id_print(NULL, ¶m->write.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->write.descr_id); + network_bluetooth_gatt_id_print(NULL, ¶m->write.descr_id); } break; @@ -914,40 +908,40 @@ STATIC void gattc_event_dump( case ESP_GATTC_NOTIFY_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", addr = %02X:%02X:%02X:%02X:%02X:%02X", - param->notify.conn_id, - param->notify.remote_bda[0], - param->notify.remote_bda[1], - param->notify.remote_bda[2], - param->notify.remote_bda[3], - param->notify.remote_bda[4], - param->notify.remote_bda[5]); + "conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->notify.conn_id, + param->notify.remote_bda[0], + param->notify.remote_bda[1], + param->notify.remote_bda[2], + param->notify.remote_bda[3], + param->notify.remote_bda[4], + param->notify.remote_bda[5]); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->notify.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->notify.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->notify.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->notify.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->notify.char_id); + network_bluetooth_gatt_id_print(NULL, ¶m->notify.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->notify.descr_id); + network_bluetooth_gatt_id_print(NULL, ¶m->notify.descr_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", value = ("); dumpBuf(param->notify.value, param->notify.value_len); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", value_len = %d " - ", %s", - param->notify.value_len, - param->notify.is_notify ? "NOTIFY" : "INDICATE"); + ", value_len = %d " + ", %s", + param->notify.value_len, + param->notify.is_notify ? "NOTIFY" : "INDICATE"); } break; @@ -956,13 +950,13 @@ STATIC void gattc_event_dump( case ESP_GATTC_SRVC_CHG_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( - "addr = %02X:%02X:%02X:%02X:%02X:%02X", - param->srvc_chg.remote_bda[0], - param->srvc_chg.remote_bda[1], - param->srvc_chg.remote_bda[2], - param->srvc_chg.remote_bda[3], - param->srvc_chg.remote_bda[4], - param->srvc_chg.remote_bda[5]); + "addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->srvc_chg.remote_bda[0], + param->srvc_chg.remote_bda[1], + param->srvc_chg.remote_bda[2], + param->srvc_chg.remote_bda[3], + param->srvc_chg.remote_bda[4], + param->srvc_chg.remote_bda[5]); } break; @@ -970,33 +964,33 @@ STATIC void gattc_event_dump( case ESP_GATTC_CONGEST_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X, %s CONGESTED", - param->congest.conn_id, - param->congest.congested ? "" : "NOT"); + "conn_id = %04X, %s CONGESTED", + param->congest.conn_id, + param->congest.congested ? "" : "NOT"); } break; - case ESP_GATTC_GET_CHAR_EVT: + case ESP_GATTC_GET_CHAR_EVT: { PRINT_STATUS(param->get_char.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_char.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_char.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->get_char.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_char.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->get_char.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_char.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->get_char.char_id); + network_bluetooth_gatt_id_print(NULL, ¶m->get_char.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_props = "); const char * char_props[] = { "BROADCAST", "READ", "WRITE_NR", "WRITE", "NOTIFY", "INDICATE", "AUTH", "EXT_PROP" }; bool printed = false; - for(int i = 0; i < 7; i ++) { - if (param->get_char.char_prop & (1<get_char.char_prop & (1 << i)) { NETWORK_BLUETOOTH_DEBUG_PRINTF("%s%s", printed ? " | " : "", char_props[i]); printed = true; } @@ -1007,42 +1001,42 @@ STATIC void gattc_event_dump( case ESP_GATTC_GET_DESCR_EVT: { PRINT_STATUS(param->get_descr.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_descr.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_descr.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->get_descr.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_descr.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->get_descr.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_descr.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->get_descr.char_id); + network_bluetooth_gatt_id_print(NULL, ¶m->get_descr.char_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", descr_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->get_descr.descr_id); + network_bluetooth_gatt_id_print(NULL, ¶m->get_descr.descr_id); } break; case ESP_GATTC_GET_INCL_SRVC_EVT: { PRINT_STATUS(param->get_incl_srvc.status); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_incl_srvc.conn_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", conn_id = %04X", param->get_incl_srvc.conn_id); NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->get_incl_srvc.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->get_incl_srvc.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", incl_srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->get_incl_srvc.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->get_incl_srvc.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } @@ -1054,13 +1048,13 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->reg_for_notify.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->reg_for_notify.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->reg_for_notify.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->reg_for_notify.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->reg_for_notify.char_id); + network_bluetooth_gatt_id_print(NULL, ¶m->reg_for_notify.char_id); } break; @@ -1070,13 +1064,13 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->unreg_for_notify.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->unreg_for_notify.srvc_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->unreg_for_notify.srvc_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->unreg_for_notify.srvc_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->unreg_for_notify.char_id); + network_bluetooth_gatt_id_print(NULL, ¶m->unreg_for_notify.char_id); } default: // Rest of events have no printable data @@ -1087,9 +1081,9 @@ STATIC void gattc_event_dump( } STATIC void gatts_event_dump( - esp_gatts_cb_event_t event, - esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t *param) { + esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) { const char * event_names[] = { "REG", @@ -1120,79 +1114,79 @@ STATIC void gatts_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF( - "network_bluetooth_gatts_event_handler(" - "event = %02X / %s" - ", if = %02X", - event, event_names[event], gatts_if - ); + "network_bluetooth_gatts_event_handler(" + "event = %02X / %s" + ", if = %02X", + event, event_names[event], gatts_if + ); - NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", param = ("); - switch(event) { + switch (event) { case ESP_GATTS_REG_EVT: { PRINT_STATUS(param->reg.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", app_id = %04X", - param->reg.app_id - ); + ", app_id = %04X", + param->reg.app_id + ); } break; case ESP_GATTS_READ_EVT: NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", trans_id = %08X" - ", addr = %02X:%02X:%02X:%02X:%02X:%02X", - param->read.conn_id, - param->read.trans_id, - param->read.bda[0], - param->read.bda[1], - param->read.bda[2], - param->read.bda[3], - param->read.bda[4], - param->read.bda[5] - ); + "conn_id = %04X" + ", trans_id = %08X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->read.conn_id, + param->read.trans_id, + param->read.bda[0], + param->read.bda[1], + param->read.bda[2], + param->read.bda[3], + param->read.bda[4], + param->read.bda[5] + ); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", handle = %04X" - ", offset = %04X" - ", is_long = %s" - ", need_resp = %s", - param->read.handle, - param->read.offset, - param->read.is_long ? "true" : "false", - param->read.need_rsp ? "true" : "false"); + ", handle = %04X" + ", offset = %04X" + ", is_long = %s" + ", need_resp = %s", + param->read.handle, + param->read.offset, + param->read.is_long ? "true" : "false", + param->read.need_rsp ? "true" : "false"); break; case ESP_GATTS_WRITE_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", trans_id = %08X" - ", addr = %02X:%02X:%02X:%02X:%02X:%02X", - param->write.conn_id, - param->write.trans_id, - param->write.bda[0], - param->write.bda[1], - param->write.bda[2], - param->write.bda[3], - param->write.bda[4], - param->write.bda[5] - ); + "conn_id = %04X" + ", trans_id = %08X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->write.conn_id, + param->write.trans_id, + param->write.bda[0], + param->write.bda[1], + param->write.bda[2], + param->write.bda[3], + param->write.bda[4], + param->write.bda[5] + ); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", handle = %04X" - ", offset = %04X" - ", need_resp = %s" - ", is_prep = %s" - ", len = %04X", - param->write.handle, - param->write.offset, - param->write.need_rsp ? "true" : "false", - param->write.is_prep ? "true" : "false", - param->write.len); + ", handle = %04X" + ", offset = %04X" + ", need_resp = %s" + ", is_prep = %s" + ", len = %04X", + param->write.handle, + param->write.offset, + param->write.need_rsp ? "true" : "false", + param->write.is_prep ? "true" : "false", + param->write.len); NETWORK_BLUETOOTH_DEBUG_PRINTF(", data = "); dumpBuf(param->write.value, param->write.len); @@ -1202,29 +1196,29 @@ STATIC void gatts_event_dump( case ESP_GATTS_EXEC_WRITE_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", trans_id = %08X" - ", addr = %02X:%02X:%02X:%02X:%02X:%02X" - ", exec_write_flag = %02X", - param->exec_write.conn_id, - param->exec_write.trans_id, - param->exec_write.bda[0], - param->exec_write.bda[1], - param->exec_write.bda[2], - param->exec_write.bda[3], - param->exec_write.bda[4], - param->exec_write.bda[5], - param->exec_write.exec_write_flag); + "conn_id = %04X" + ", trans_id = %08X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X" + ", exec_write_flag = %02X", + param->exec_write.conn_id, + param->exec_write.trans_id, + param->exec_write.bda[0], + param->exec_write.bda[1], + param->exec_write.bda[2], + param->exec_write.bda[3], + param->exec_write.bda[4], + param->exec_write.bda[5], + param->exec_write.exec_write_flag); } break; case ESP_GATTS_MTU_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", mtu = %04X", - param->mtu.conn_id, - param->mtu.mtu); + "conn_id = %04X" + ", mtu = %04X", + param->mtu.conn_id, + param->mtu.mtu); } break; @@ -1232,9 +1226,9 @@ STATIC void gatts_event_dump( { PRINT_STATUS(param->conf.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", conn_id = %04X", - param->conf.conn_id - ); + ", conn_id = %04X", + param->conf.conn_id + ); } break; @@ -1250,8 +1244,8 @@ STATIC void gatts_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", service_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); - network_bluetooth_gatt_id_print(NULL,¶m->create.service_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->create.service_id.is_primary ? "true" : "false"); + network_bluetooth_gatt_id_print(NULL, ¶m->create.service_id.id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->create.service_id.is_primary ? "true" : "false"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } @@ -1261,10 +1255,10 @@ STATIC void gatts_event_dump( { PRINT_STATUS(param->add_incl_srvc.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", attr_handle = %04X" - ", service_handle = %04X", - param->add_incl_srvc.attr_handle, - param->add_incl_srvc.service_handle); + ", attr_handle = %04X" + ", service_handle = %04X", + param->add_incl_srvc.attr_handle, + param->add_incl_srvc.service_handle); } break; @@ -1272,12 +1266,12 @@ STATIC void gatts_event_dump( { PRINT_STATUS(param->add_char.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", attr_handle = %04X" - ", service_handle = %04X", - param->add_char.attr_handle, - param->add_char.service_handle); + ", attr_handle = %04X" + ", service_handle = %04X", + param->add_char.attr_handle, + param->add_char.service_handle); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", uuid = "); + ", uuid = "); dumpBuf((uint8_t*)¶m->add_char.char_uuid.uuid, param->add_char.char_uuid.len); } break; @@ -1286,12 +1280,12 @@ STATIC void gatts_event_dump( { PRINT_STATUS(param->add_char_descr.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", attr_handle = %04X" - ", service_handle = %04X", - param->add_char_descr.attr_handle, - param->add_char_descr.service_handle); + ", attr_handle = %04X" + ", service_handle = %04X", + param->add_char_descr.attr_handle, + param->add_char_descr.service_handle); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", uuid = "); + ", uuid = "); dumpBuf((uint8_t*)¶m->add_char_descr.char_uuid.uuid, param->add_char_descr.char_uuid.len); } break; @@ -1300,8 +1294,8 @@ STATIC void gatts_event_dump( { PRINT_STATUS(param->del.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", service_handle = %04X", - param->del.service_handle); + ", service_handle = %04X", + param->del.service_handle); } break; @@ -1309,8 +1303,8 @@ STATIC void gatts_event_dump( { PRINT_STATUS(param->start.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", service_handle = %04X", - param->start.service_handle); + ", service_handle = %04X", + param->start.service_handle); } break; @@ -1318,39 +1312,39 @@ STATIC void gatts_event_dump( { PRINT_STATUS(param->stop.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", service_handle = %04X", - param->stop.service_handle); + ", service_handle = %04X", + param->stop.service_handle); } break; case ESP_GATTS_CONNECT_EVT: NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", remote_bda = %02X:%02X:%02X:%02X:%02X:%02X" - ", is_connected = %s", - param->connect.conn_id, - param->connect.remote_bda[0], - param->connect.remote_bda[1], - param->connect.remote_bda[2], - param->connect.remote_bda[3], - param->connect.remote_bda[4], - param->connect.remote_bda[5], - param->connect.is_connected ? "true" : "false"); + "conn_id = %04X" + ", remote_bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", is_connected = %s", + param->connect.conn_id, + param->connect.remote_bda[0], + param->connect.remote_bda[1], + param->connect.remote_bda[2], + param->connect.remote_bda[3], + param->connect.remote_bda[4], + param->connect.remote_bda[5], + param->connect.is_connected ? "true" : "false"); break; case ESP_GATTS_DISCONNECT_EVT: NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", remote_bda = %02X:%02X:%02X:%02X:%02X:%02X" - ", is_connected = %s", - param->disconnect.conn_id, - param->disconnect.remote_bda[0], - param->disconnect.remote_bda[1], - param->disconnect.remote_bda[2], - param->disconnect.remote_bda[3], - param->disconnect.remote_bda[4], - param->disconnect.remote_bda[5], - param->disconnect.is_connected ? "true" : "false"); + "conn_id = %04X" + ", remote_bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", is_connected = %s", + param->disconnect.conn_id, + param->disconnect.remote_bda[0], + param->disconnect.remote_bda[1], + param->disconnect.remote_bda[2], + param->disconnect.remote_bda[3], + param->disconnect.remote_bda[4], + param->disconnect.remote_bda[5], + param->disconnect.is_connected ? "true" : "false"); break; case ESP_GATTS_OPEN_EVT: @@ -1371,18 +1365,18 @@ STATIC void gatts_event_dump( case ESP_GATTS_CONGEST_EVT: NETWORK_BLUETOOTH_DEBUG_PRINTF( - "conn_id = %04X" - ", congested = %s", - param->congest.conn_id, - param->congest.congested ? "true" : "false"); + "conn_id = %04X" + ", congested = %s", + param->congest.conn_id, + param->congest.congested ? "true" : "false"); break; case ESP_GATTS_RESPONSE_EVT: { PRINT_STATUS(param->rsp.status); NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", handle = %04X", - param->rsp.handle); + ", handle = %04X", + param->rsp.handle); } break; @@ -1392,7 +1386,7 @@ STATIC void gatts_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF(", srvc_uuid = "); dumpBuf((uint8_t*)¶m->add_attr_tab.svc_uuid.uuid, param->add_attr_tab.svc_uuid.len); NETWORK_BLUETOOTH_DEBUG_PRINTF(", num_handle = %04X", param->add_attr_tab.num_handle); - for(int i = 0; i < param->add_attr_tab.num_handle; i++) { + for (int i = 0; i < param->add_attr_tab.num_handle; i++) { NETWORK_BLUETOOTH_DEBUG_PRINTF("%04X ", param->add_attr_tab.handles[i]); } } @@ -1400,10 +1394,10 @@ STATIC void gatts_event_dump( case ESP_GATTS_SET_ATTR_VAL_EVT: NETWORK_BLUETOOTH_DEBUG_PRINTF( - "srvc_handle = %04X" - ", attr_handle = %04X", - param->set_attr_val.srvc_handle, - param->set_attr_val.attr_handle); + "srvc_handle = %04X" + ", attr_handle = %04X", + param->set_attr_val.srvc_handle, + param->set_attr_val.attr_handle); PRINT_STATUS(param->set_attr_val.status); break; @@ -1432,11 +1426,12 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t "LOCAL_ER", "NC_REQ", "ADV_STOP_COMPLETE", - "SCAN_STOP_COMPLETE"}; + "SCAN_STOP_COMPLETE" + }; NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_gap_event_handler(event = %02X / %s", event, event_names[event]); - NETWORK_BLUETOOTH_DEBUG_PRINTF( ", param = ("); - switch(event) { + NETWORK_BLUETOOTH_DEBUG_PRINTF(", param = ("); + switch (event) { case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: @@ -1452,7 +1447,7 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t } break; - case ESP_GAP_BLE_SCAN_RESULT_EVT: + case ESP_GAP_BLE_SCAN_RESULT_EVT: { const char * search_events[7] = { "INQ_RES", @@ -1469,42 +1464,42 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t NETWORK_BLUETOOTH_DEBUG_PRINTF( - "search_evt = %s", - search_events[param->scan_rst.search_evt]); + "search_evt = %s", + search_events[param->scan_rst.search_evt]); - if ( param->scan_rst.dev_type <= 3 && param->scan_rst.ble_addr_type <=3 ) { + if (param->scan_rst.dev_type <= 3 && param->scan_rst.ble_addr_type <= 3) { NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", dev_type = %s" - ", ble_addr_type = %s" - ", rssi = %d" , - dev_types[param->scan_rst.dev_type], - addr_types[param->scan_rst.ble_addr_type], - param->scan_rst.rssi - - ); + ", dev_type = %s" + ", ble_addr_type = %s" + ", rssi = %d" , + dev_types[param->scan_rst.dev_type], + addr_types[param->scan_rst.ble_addr_type], + param->scan_rst.rssi + + ); } if (param->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) { NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", bda = %02X:%02X:%02X:%02X:%02X:%02X" - ", adv_data_len = %u" - ", scan_rsp_len = %u" , - param->scan_rst.bda[0], - param->scan_rst.bda[1], - param->scan_rst.bda[2], - param->scan_rst.bda[3], - param->scan_rst.bda[4], - param->scan_rst.bda[5], - param->scan_rst.adv_data_len, - param->scan_rst.scan_rsp_len); + ", bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", adv_data_len = %u" + ", scan_rsp_len = %u" , + param->scan_rst.bda[0], + param->scan_rst.bda[1], + param->scan_rst.bda[2], + param->scan_rst.bda[3], + param->scan_rst.bda[4], + param->scan_rst.bda[5], + param->scan_rst.adv_data_len, + param->scan_rst.scan_rsp_len); uint8_t * adv_name; uint8_t adv_name_len = 0; adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, - ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); + ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); NETWORK_BLUETOOTH_DEBUG_PRINTF(", adv_name = "); for (int j = 0; j < adv_name_len; j++) { @@ -1515,36 +1510,43 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t } break; - case ESP_GAP_BLE_AUTH_CMPL_EVT: break; - case ESP_GAP_BLE_KEY_EVT: break; - case ESP_GAP_BLE_SEC_REQ_EVT: break; - case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: break; - case ESP_GAP_BLE_PASSKEY_REQ_EVT: break; - case ESP_GAP_BLE_OOB_REQ_EVT: break; - case ESP_GAP_BLE_LOCAL_IR_EVT: break; - case ESP_GAP_BLE_LOCAL_ER_EVT: break; - case ESP_GAP_BLE_NC_REQ_EVT: break; + case ESP_GAP_BLE_AUTH_CMPL_EVT: + break; + case ESP_GAP_BLE_KEY_EVT: + break; + case ESP_GAP_BLE_SEC_REQ_EVT: + break; + case ESP_GAP_BLE_PASSKEY_NOTIF_EVT: + break; + case ESP_GAP_BLE_PASSKEY_REQ_EVT: + break; + case ESP_GAP_BLE_OOB_REQ_EVT: + break; + case ESP_GAP_BLE_LOCAL_IR_EVT: + break; + case ESP_GAP_BLE_LOCAL_ER_EVT: + break; + case ESP_GAP_BLE_NC_REQ_EVT: + break; } NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); } - - #endif // EVENT_DEBUG -STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { +STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - //NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_callback_queue_handler \n"); + if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { + xQueueReset(callback_q); return mp_const_none; } callback_data_t cbdata; - while(true) { + while (true) { bool got_data = cbq_pop(&cbdata); - //NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_callback_queue_handler pop: %s \n", got_data ? "HIT" : "MISS"); if (!got_data) { return mp_const_none; } @@ -1571,7 +1573,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { break; } - switch(cbdata.event) { + switch (cbdata.event) { case NETWORK_BLUETOOTH_GATTS_START: service->started = true; @@ -1608,14 +1610,10 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { if (chr != MP_OBJ_NULL) { chr->handle = cbdata.gatts_add_char.char_handle; } - } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Service handle %d NOT FOUND\n", cbdata.gatts_add_char.service_handle); } } break; - - case NETWORK_BLUETOOTH_READ: case NETWORK_BLUETOOTH_WRITE: case NETWORK_BLUETOOTH_NOTIFY: @@ -1625,16 +1623,16 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { mp_obj_t value = mp_const_none; bool need_rsp = false; - switch(cbdata.event) { + switch (cbdata.event) { case NETWORK_BLUETOOTH_NOTIFY: - value = mp_obj_new_bytearray(cbdata.notify.value_len, cbdata.notify.value); + value = MP_OBJ_NEW_BYTES(cbdata.notify.value_len, cbdata.notify.value); FREE(cbdata.notify.value); network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.notify.conn_id); if (conn != MP_OBJ_NULL) { network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.notify.service_id.id.uuid); if (service != MP_OBJ_NULL) { self = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.notify.char_id.uuid); - } + } } need_rsp = cbdata.notify.need_rsp; break; @@ -1649,7 +1647,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { case NETWORK_BLUETOOTH_WRITE: self = network_bluetooth_find_char_by_handle(cbdata.write.handle); - value = mp_obj_new_bytearray(cbdata.write.value_len, cbdata.write.value); + value = MP_OBJ_NEW_BYTES(cbdata.write.value_len, cbdata.write.value); need_rsp = cbdata.write.need_rsp; FREE(cbdata.write.value); break; @@ -1663,7 +1661,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { if (self->callback != mp_const_none) { mp_obj_t args[] = {self, MP_OBJ_NEW_SMALL_INT(cbdata.event), value, self->callback_userdata }; - value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); + value = mp_call_function_n_kw(self->callback, MP_ARRAY_SIZE(args), 0, args); } else if (cbdata.event == NETWORK_BLUETOOTH_WRITE) { self->value = value; } @@ -1675,13 +1673,15 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { mp_buffer_info_t buf; memset(&buf, 0, sizeof(mp_buffer_info_t)); - if(MP_OBJ_IS_BT_DATATYPE(value)) { + // If not correct return data type, + // silently send an empty response + if (mp_obj_is_bt_datatype(value)) { mp_get_buffer(value, &buf, MP_BUFFER_READ); - } + } size_t len = MIN(ESP_GATT_MAX_ATTR_LEN, buf.len); - switch(cbdata.event) { + switch (cbdata.event) { case NETWORK_BLUETOOTH_WRITE: case NETWORK_BLUETOOTH_READ: @@ -1699,11 +1699,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { break; } } - } - else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Could not find characteristic\n"); } - } break; @@ -1712,8 +1708,8 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { if (bluetooth->callback != mp_const_none) { // items[0] is event // items[1] is remote address - mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.gatts_connect_disconnect.bda), bluetooth->callback_userdata }; - mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); + mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), MP_OBJ_NEW_BYTES(ESP_BD_ADDR_LEN, cbdata.gatts_connect_disconnect.bda), bluetooth->callback_userdata }; + mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); } break; @@ -1722,13 +1718,13 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { if (bluetooth->callback != mp_const_none) { mp_obj_t data = mp_const_none; if (cbdata.event == NETWORK_BLUETOOTH_GATTC_SCAN_RES) { - mp_obj_t scan_res_args[] = { mp_obj_new_bytearray(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), mp_obj_new_bytearray(cbdata.gattc_scan_res.adv_data_len, cbdata.gattc_scan_res.adv_data) } ; + mp_obj_t scan_res_args[] = { MP_OBJ_NEW_BYTES(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), MP_OBJ_NEW_BYTES(cbdata.gattc_scan_res.adv_data_len, cbdata.gattc_scan_res.adv_data) } ; data = mp_obj_new_tuple(2, scan_res_args); FREE(cbdata.gattc_scan_res.adv_data); - } + } mp_obj_t args[] = {bluetooth, MP_OBJ_NEW_SMALL_INT(cbdata.event), data, bluetooth->callback_userdata }; - mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); + mp_call_function_n_kw(bluetooth->callback, MP_ARRAY_SIZE(args), 0, args); } break; @@ -1740,6 +1736,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { } } break; + case NETWORK_BLUETOOTH_GATTC_OPEN: { network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_bda(cbdata.gattc_open_close.bda); @@ -1755,11 +1752,6 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { case NETWORK_BLUETOOTH_GATTC_SEARCH_RES: { network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_search_res.conn_id); -#if 0 - NETWORK_BLUETOOTH_DEBUG_PRINTF("search res for connid: %u, conn obj = %p, uuid =", cbdata.gattc_search_res.conn_id, conn); - network_bluetooth_gatt_id_print(NULL, &cbdata.gattc_search_res.service_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); -#endif if (conn != MP_OBJ_NULL) { network_bluetooth_service_obj_t *service = m_new_obj(network_bluetooth_service_obj_t); service->base.type = &network_bluetooth_gattc_service_type; @@ -1773,42 +1765,41 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { } break; - case NETWORK_BLUETOOTH_GATTC_GET_CHAR: + case NETWORK_BLUETOOTH_GATTC_GET_CHAR: { - network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_get_char.conn_id); - if (conn != MP_OBJ_NULL) { - network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_char.service_id.id.uuid); - if (service != MP_OBJ_NULL) { - network_bluetooth_char_obj_t *chr = m_new_obj(network_bluetooth_char_obj_t); - chr->base.type = &network_bluetooth_gattc_char_type; - chr->char_id = cbdata.gattc_get_char.char_id; - chr->prop = cbdata.gattc_get_char.props; - chr->service = service; - chr->descriptors = mp_obj_new_list(0, NULL); - - mp_obj_list_append(service->chars, chr); - esp_ble_gattc_get_descriptor(bluetooth->gattc_interface, conn->conn_id, &service->service_id, &chr->char_id, NULL); - } + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_get_char.conn_id); + if (conn != MP_OBJ_NULL) { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_char.service_id.id.uuid); + if (service != MP_OBJ_NULL) { + network_bluetooth_char_obj_t *chr = m_new_obj(network_bluetooth_char_obj_t); + chr->base.type = &network_bluetooth_gattc_char_type; + chr->char_id = cbdata.gattc_get_char.char_id; + chr->prop = cbdata.gattc_get_char.props; + chr->service = service; + chr->descriptors = mp_obj_new_list(0, NULL); + + mp_obj_list_append(service->chars, chr); + esp_ble_gattc_get_descriptor(bluetooth->gattc_interface, conn->conn_id, &service->service_id, &chr->char_id, NULL); + } } } break; - case NETWORK_BLUETOOTH_GATTC_GET_DESCR: + case NETWORK_BLUETOOTH_GATTC_GET_DESCR: { - network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_get_descr.conn_id); - if (conn != MP_OBJ_NULL) { - network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_descr.service_id.id.uuid); - if (service != MP_OBJ_NULL) { - - network_bluetooth_char_obj_t *chr = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.gattc_get_descr.char_id.uuid); - if (chr != NULL) { - network_bluetooth_descr_obj_t* descr = m_new_obj(network_bluetooth_descr_obj_t); - descr->base.type = &network_bluetooth_gattc_descr_type; - descr->chr = chr; - descr->descr_id = cbdata.gattc_get_descr.descr_id; - mp_obj_list_append(chr->descriptors, descr); - } + network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_get_descr.conn_id); + if (conn != MP_OBJ_NULL) { + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_descr.service_id.id.uuid); + if (service != MP_OBJ_NULL) { + network_bluetooth_char_obj_t *chr = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.gattc_get_descr.char_id.uuid); + if (chr != NULL) { + network_bluetooth_descr_obj_t* descr = m_new_obj(network_bluetooth_descr_obj_t); + descr->base.type = &network_bluetooth_gattc_descr_type; + descr->chr = chr; + descr->descr_id = cbdata.gattc_get_descr.descr_id; + mp_obj_list_append(chr->descriptors, descr); } + } } } break; @@ -1823,9 +1814,9 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler (mp_obj_t arg) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_callback_queue_handler_obj, network_bluetooth_callback_queue_handler); STATIC void network_bluetooth_gattc_event_handler( - esp_gattc_cb_event_t event, - esp_gatt_if_t gattc_if, - esp_ble_gattc_cb_param_t *param) { + esp_gattc_cb_event_t event, + esp_gatt_if_t gattc_if, + esp_ble_gattc_cb_param_t *param) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { @@ -1835,13 +1826,13 @@ STATIC void network_bluetooth_gattc_event_handler( gattc_event_dump(event, gattc_if, param); #endif - read_write_data_t read_data; + read_write_data_t read_data = { 0 }; callback_data_t cbdata; - bool nq = true; - switch(event) { + bool enqueue = true; + switch (event) { case ESP_GATTC_REG_EVT: bluetooth->gattc_interface = gattc_if; - nq = false; + enqueue = false; break; case ESP_GATTC_OPEN_EVT: @@ -1852,6 +1843,7 @@ STATIC void network_bluetooth_gattc_event_handler( memcpy(cbdata.gattc_open_close.bda, param->open.remote_bda, ESP_BD_ADDR_LEN); } break; + case ESP_GATTC_CLOSE_EVT: { cbdata.event = NETWORK_BLUETOOTH_GATTC_CLOSE; @@ -1868,9 +1860,9 @@ STATIC void network_bluetooth_gattc_event_handler( } break; - case ESP_GATTC_GET_CHAR_EVT: + case ESP_GATTC_GET_CHAR_EVT: { - cbdata.event = NETWORK_BLUETOOTH_GATTC_GET_CHAR; + cbdata.event = NETWORK_BLUETOOTH_GATTC_GET_CHAR; cbdata.gattc_get_char.conn_id = param->get_char.conn_id; cbdata.gattc_get_char.service_id = param->get_char.srvc_id; cbdata.gattc_get_char.char_id = param->get_char.char_id; @@ -1878,11 +1870,10 @@ STATIC void network_bluetooth_gattc_event_handler( } break; - case ESP_GATTC_GET_DESCR_EVT: { if (param->get_descr.status == ESP_GATT_OK) { - cbdata.event = NETWORK_BLUETOOTH_GATTC_GET_DESCR; + cbdata.event = NETWORK_BLUETOOTH_GATTC_GET_DESCR; cbdata.gattc_get_descr.conn_id = param->get_descr.conn_id; cbdata.gattc_get_descr.service_id = param->get_descr.srvc_id; cbdata.gattc_get_descr.char_id = param->get_descr.char_id; @@ -1899,16 +1890,15 @@ STATIC void network_bluetooth_gattc_event_handler( memcpy(read_data.value, param->read.value, param->read.value_len); } - // fallthrough intentional + // fallthrough intentional case ESP_GATTC_WRITE_CHAR_EVT: xQueueSend(read_write_q, &read_data, portMAX_DELAY); break; case ESP_GATTC_NOTIFY_EVT: { - cbdata.notify.value = MALLOC(param->notify.value_len); // Returns NULL when len == 0 - cbdata.notify.value_len = param->notify.value_len; + cbdata.notify.value_len = param->notify.value_len; if (cbdata.notify.value != NULL) { memcpy(cbdata.notify.value, param->notify.value, param->notify.value_len); @@ -1925,20 +1915,20 @@ STATIC void network_bluetooth_gattc_event_handler( default: - nq = false; + enqueue = false; break; } - if (nq) { + if (enqueue) { cbq_push(&cbdata); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } } STATIC void network_bluetooth_gatts_event_handler( - esp_gatts_cb_event_t event, - esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t *param) { + esp_gatts_cb_event_t event, + esp_gatt_if_t gatts_if, + esp_ble_gatts_cb_param_t *param) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { @@ -1950,12 +1940,12 @@ STATIC void network_bluetooth_gatts_event_handler( #endif callback_data_t cbdata; - bool nq = true; + bool enqueue = true; switch (event) { case ESP_GATTS_REG_EVT: bluetooth->gatts_interface = gatts_if; - nq = false; + enqueue = false; break; case ESP_GATTS_CREATE_EVT: @@ -1969,7 +1959,7 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_START_EVT: case ESP_GATTS_STOP_EVT: { - cbdata.event = event == ESP_GATTS_STOP_EVT ? NETWORK_BLUETOOTH_GATTS_STOP : NETWORK_BLUETOOTH_GATTS_START; + cbdata.event = event == ESP_GATTS_STOP_EVT ? NETWORK_BLUETOOTH_GATTS_STOP : NETWORK_BLUETOOTH_GATTS_START; cbdata.gatts_start_stop.service_handle = param->start.service_handle; } break; @@ -1978,7 +1968,7 @@ STATIC void network_bluetooth_gatts_event_handler( { cbdata.event = NETWORK_BLUETOOTH_GATTS_ADD_CHAR; cbdata.gatts_add_char.service_handle = param->add_char.service_handle; - cbdata.gatts_add_char.char_handle = param->add_char.attr_handle; + cbdata.gatts_add_char.char_handle = param->add_char.attr_handle; cbdata.gatts_add_char.char_uuid = param->add_char.char_uuid; } break; @@ -1987,23 +1977,21 @@ STATIC void network_bluetooth_gatts_event_handler( cbdata.write.value = MALLOC(param->write.len); // Returns NULL when len == 0 if (cbdata.write.value != NULL) { - cbdata.write.value_len = param->write.len; + cbdata.write.value_len = param->write.len; memcpy(cbdata.write.value, param->write.value, param->write.len); } else { - cbdata.write.value_len = 0; + cbdata.write.value_len = 0; } - // fallthrough intentional + // fallthrough intentional case ESP_GATTS_READ_EVT: - { - cbdata.event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; + cbdata.event = event == ESP_GATTS_READ_EVT ? NETWORK_BLUETOOTH_READ : NETWORK_BLUETOOTH_WRITE; - cbdata.read.handle = param->read.handle; - cbdata.read.conn_id = param->read.conn_id; - cbdata.read.trans_id = param->read.trans_id; - cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); - } + cbdata.read.handle = param->read.handle; + cbdata.read.conn_id = param->read.conn_id; + cbdata.read.trans_id = param->read.trans_id; + cbdata.read.need_rsp = event == ESP_GATTS_READ_EVT || (event == ESP_GATTS_WRITE_EVT && param->write.need_rsp); break; case ESP_GATTS_CONNECT_EVT: @@ -2017,24 +2005,20 @@ STATIC void network_bluetooth_gatts_event_handler( } break; - default: - nq = false; + enqueue = false; break; } - if (nq) { + if (enqueue) { cbq_push(&cbdata); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } - } - - STATIC void network_bluetooth_gap_event_handler( - esp_gap_ble_cb_event_t event, - esp_ble_gap_cb_param_t *param) { + esp_gap_ble_cb_event_t event, + esp_ble_gap_cb_param_t *param) { #ifdef EVENT_DEBUG_GAP gap_event_dump(event, param); @@ -2053,7 +2037,9 @@ STATIC void network_bluetooth_gap_event_handler( break; case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT: - // FIXME -- send event? + // No event sent here, since + // the stop action is initiated by + // user code, just like start. if (param->adv_stop_cmpl.status == ESP_BT_STATUS_SUCCESS) { bluetooth->scanning = false; } @@ -2061,10 +2047,9 @@ STATIC void network_bluetooth_gap_event_handler( case ESP_GAP_BLE_SCAN_RESULT_EVT: { - callback_data_t cbdata; - bool nq = true; - switch(param->scan_rst.search_evt) { + bool enqueue = true; + switch (param->scan_rst.search_evt) { case ESP_GAP_SEARCH_INQ_RES_EVT: { uint8_t* adv_name; @@ -2082,7 +2067,6 @@ STATIC void network_bluetooth_gap_event_handler( } else { cbdata.gattc_scan_res.adv_data_len = 0; } - break; } @@ -2094,11 +2078,11 @@ STATIC void network_bluetooth_gap_event_handler( break; default: - nq = false; + enqueue = false; break; } - if (nq) { + if (enqueue) { cbq_push(&cbdata); mp_sched_schedule(MP_OBJ_FROM_PTR(&network_bluetooth_callback_queue_handler_obj), MP_OBJ_NULL); } @@ -2110,11 +2094,13 @@ STATIC void network_bluetooth_gap_event_handler( esp_ble_gap_start_advertising(&bluetooth->adv_params); } break; - default: break; + + default: + // do nothing, intentionally + break; } } - STATIC void network_bluetooth_adv_updated() { network_bluetooth_obj_t* self = network_bluetooth_get_singleton(); esp_ble_gap_stop_advertising(); @@ -2145,12 +2131,11 @@ STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_o mp_printf(print, "GATTCChar(uuid = "); } network_bluetooth_gatt_id_print(print, &self->char_id); - mp_printf(print, ", prop = %02X",self->prop); + mp_printf(print, ", prop = %02X", self->prop); } mp_printf(print, ")"); } - STATIC void network_bluetooth_connection_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_connection_obj_t *connection = MP_OBJ_TO_PTR(self_in); @@ -2160,7 +2145,6 @@ STATIC void network_bluetooth_connection_print(const mp_print_t *print, mp_obj_t mp_printf(print, ")"); } - STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); bool gatts = MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_service_type); @@ -2178,80 +2162,72 @@ STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t se mp_printf(print, ")"); } - STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "Bluetooth(params=())", self); -#define NETWORK_BLUETOOTH_LF "\n" - NETWORK_BLUETOOTH_DEBUG_PRINTF( - "Bluetooth(conn_id = %04X" NETWORK_BLUETOOTH_LF - ", gatts_connected = %s" NETWORK_BLUETOOTH_LF - ", gatts_if = %u" NETWORK_BLUETOOTH_LF - ", gattc_if = %u" NETWORK_BLUETOOTH_LF - ", adv_params = (" - "adv_int_min = %u, " NETWORK_BLUETOOTH_LF - "adv_int_max = %u, " NETWORK_BLUETOOTH_LF - "adv_type = %u, " NETWORK_BLUETOOTH_LF - "own_addr_type = %u, " NETWORK_BLUETOOTH_LF - "peer_addr = %02X:%02X:%02X:%02X:%02X:%02X, " NETWORK_BLUETOOTH_LF - "peer_addr_type = %u, " NETWORK_BLUETOOTH_LF - "channel_map = %u, " NETWORK_BLUETOOTH_LF - "adv_filter_policy = %u" NETWORK_BLUETOOTH_LF - ")" - , - self->conn_id, - self->gatts_connected ? "True" : "False", - self->gatts_interface, - self->gattc_interface, - (unsigned int)(self->adv_params.adv_int_min / 1.6), - (unsigned int)(self->adv_params.adv_int_max / 1.6), - self->adv_params.adv_type, - self->adv_params.own_addr_type, - self->adv_params.peer_addr[0], - self->adv_params.peer_addr[1], - self->adv_params.peer_addr[2], - self->adv_params.peer_addr[3], - self->adv_params.peer_addr[4], - self->adv_params.peer_addr[5], - self->adv_params.peer_addr_type, - self->adv_params.channel_map, - self->adv_params.adv_filter_policy - ); - NETWORK_BLUETOOTH_DEBUG_PRINTF( - ", data = (" - "set_scan_rsp = %s, " NETWORK_BLUETOOTH_LF - "include_name = %s, " NETWORK_BLUETOOTH_LF - "include_txpower = %s, " NETWORK_BLUETOOTH_LF - "min_interval = %d, " NETWORK_BLUETOOTH_LF - "max_interval = %d, " NETWORK_BLUETOOTH_LF - "appearance = %d, " NETWORK_BLUETOOTH_LF - "manufacturer_len = %d, " NETWORK_BLUETOOTH_LF - "p_manufacturer_data = %s, " NETWORK_BLUETOOTH_LF - "service_data_len = %d, " NETWORK_BLUETOOTH_LF - "p_service_data = ", - self->adv_data.set_scan_rsp ? "true" : "false", - self->adv_data.include_name ? "true" : "false", - self->adv_data.include_txpower ? "true" : "false", - self->adv_data.min_interval, - self->adv_data.max_interval, - self->adv_data.appearance, - self->adv_data.manufacturer_len, - self->adv_data.p_manufacturer_data ? (const char *)self->adv_data.p_manufacturer_data : "nil", - self->adv_data.service_data_len); - if (self->adv_data.p_service_data != NULL) { - dumpBuf(self->adv_data.p_service_data, self->adv_data.service_data_len); - } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("nil"); - } - - NETWORK_BLUETOOTH_DEBUG_PRINTF(", " NETWORK_BLUETOOTH_LF "flag = %d" NETWORK_BLUETOOTH_LF , self->adv_data.flag); - - - NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); - +//#define NETWORK_BLUETOOTH_LF "\n" +#define NETWORK_BLUETOOTH_LF + mp_printf(print, + "Bluetooth(params = (conn_id = %04X" NETWORK_BLUETOOTH_LF + ", gatts_connected = %s" NETWORK_BLUETOOTH_LF + ", gatts_if = %u" NETWORK_BLUETOOTH_LF + ", gattc_if = %u" NETWORK_BLUETOOTH_LF + ", adv_params = (" + "adv_int_min = %u, " NETWORK_BLUETOOTH_LF + "adv_int_max = %u, " NETWORK_BLUETOOTH_LF + "adv_type = %u, " NETWORK_BLUETOOTH_LF + "own_addr_type = %u, " NETWORK_BLUETOOTH_LF + "peer_addr = %02X:%02X:%02X:%02X:%02X:%02X, " NETWORK_BLUETOOTH_LF + "peer_addr_type = %u, " NETWORK_BLUETOOTH_LF + "channel_map = %u, " NETWORK_BLUETOOTH_LF + "adv_filter_policy = %u" NETWORK_BLUETOOTH_LF + ")" + , + self->conn_id, + self->gatts_connected ? "True" : "False", + self->gatts_interface, + self->gattc_interface, + (unsigned int)(self->adv_params.adv_int_min / 1.6), + (unsigned int)(self->adv_params.adv_int_max / 1.6), + self->adv_params.adv_type, + self->adv_params.own_addr_type, + self->adv_params.peer_addr[0], + self->adv_params.peer_addr[1], + self->adv_params.peer_addr[2], + self->adv_params.peer_addr[3], + self->adv_params.peer_addr[4], + self->adv_params.peer_addr[5], + self->adv_params.peer_addr_type, + self->adv_params.channel_map, + self->adv_params.adv_filter_policy + ); + mp_printf(print, + ", data = (" + "set_scan_rsp = %s, " NETWORK_BLUETOOTH_LF + "include_name = %s, " NETWORK_BLUETOOTH_LF + "include_txpower = %s, " NETWORK_BLUETOOTH_LF + "min_interval = %d, " NETWORK_BLUETOOTH_LF + "max_interval = %d, " NETWORK_BLUETOOTH_LF + "appearance = %d, " NETWORK_BLUETOOTH_LF + "manufacturer_len = %d, " NETWORK_BLUETOOTH_LF + "p_manufacturer_data = %s, " NETWORK_BLUETOOTH_LF + "service_data_len = %d, " NETWORK_BLUETOOTH_LF + "p_service_data = ", + self->adv_data.set_scan_rsp ? "true" : "false", + self->adv_data.include_name ? "true" : "false", + self->adv_data.include_txpower ? "true" : "false", + self->adv_data.min_interval, + self->adv_data.max_interval, + self->adv_data.appearance, + self->adv_data.manufacturer_len, + self->adv_data.p_manufacturer_data ? (const char *)self->adv_data.p_manufacturer_data : "nil", + self->adv_data.service_data_len); + if (self->adv_data.p_service_data != NULL) { + dumpBuf(self->adv_data.p_service_data, self->adv_data.service_data_len); + } + mp_printf(print, ", " NETWORK_BLUETOOTH_LF "flag = %d" NETWORK_BLUETOOTH_LF , self->adv_data.flag); + mp_printf(print, ")\n"); } - STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { network_bluetooth_obj_t * self = (network_bluetooth_obj_t*)self_in; @@ -2264,7 +2240,7 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { callback_q = xQueueCreate(CALLBACK_QUEUE_SIZE, sizeof(callback_data_t)); if (callback_q == NULL) { mp_raise_msg(&mp_type_OSError, "unable to create callback queue"); - } + } } else { xQueueReset(callback_q); } @@ -2273,38 +2249,25 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { read_write_q = xQueueCreate(1, sizeof(read_write_data_t)); if (read_write_q == NULL) { mp_raise_msg(&mp_type_OSError, "unable to create read queue"); - } + } } else { xQueueReset(read_write_q); } if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT is deinit, initializing\n"); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - esp_bt_controller_init(&bt_cfg); - - // FIXME - // - // Looks like this needs to be globally idempotent - // because: - // 1) You can't disable BT once enabled - // 2) You can't call this twice for enabling - // - // https://github.com/espressif/esp-idf/issues/405#issuecomment-299045124 - - if (!network_bluetooth_bt_controller_enabled) { - network_bluetooth_bt_controller_enabled = true; - switch(esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { - case ESP_OK: - break; - default: - mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); - break; - } + esp_bt_controller_init(&bt_cfg); + + switch (esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { + case ESP_OK: + break; + default: + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); + break; } - switch(esp_bluedroid_init()) { + switch (esp_bluedroid_init()) { case ESP_OK: break; default: @@ -2312,7 +2275,7 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { break; } - switch(esp_bluedroid_enable()) { + switch (esp_bluedroid_enable()) { case ESP_OK: break; default: @@ -2325,7 +2288,7 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { esp_ble_gap_register_callback(network_bluetooth_gap_event_handler); // FIXME, this is hardcoded - switch(esp_ble_gatts_app_register(0)) { + switch (esp_ble_gatts_app_register(0)) { case ESP_OK: break; @@ -2334,7 +2297,7 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { break; } // FIXME, this is hardcoded - switch(esp_ble_gattc_app_register(1)) { + switch (esp_ble_gattc_app_register(1)) { case ESP_OK: break; @@ -2344,8 +2307,6 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { } self->state = NETWORK_BLUETOOTH_STATE_INIT; - } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF("BT already initialized\n"); } return mp_const_none; } @@ -2364,7 +2325,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po bool unset_adv_dev_name = false; bool unset_adv_uuid = false; - enum { + enum { // params ARG_int_min, ARG_int_max, @@ -2423,7 +2384,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po // peer_addr if (args[ARG_peer_addr].u_obj != NULL) { - if(!MP_OBJ_IS_TYPE(args[ARG_peer_addr].u_obj, &mp_type_bytearray)) { + if (!MP_OBJ_IS_TYPE(args[ARG_peer_addr].u_obj, &mp_type_bytearray)) { goto NETWORK_BLUETOOTH_BAD_PEER; } @@ -2439,7 +2400,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po unset_adv_man_name = true; } else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_adv_man_name].u_obj)) { mp_raise_ValueError("adv_man_name must be type str or bytes"); - } + } mp_obj_str_get_buffer(args[ARG_adv_man_name].u_obj, &adv_man_name_buf, MP_BUFFER_READ); } @@ -2469,7 +2430,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po } - // update esp_ble_adv_params_t + // update esp_ble_adv_params_t if (args[ARG_int_min].u_int != -1) { bluetooth->adv_params.adv_int_min = args[ARG_int_min].u_int * 1.6; // 0.625 msec per count @@ -2511,7 +2472,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po changed = true; } - // update esp_ble_adv_data_t + // update esp_ble_adv_data_t // if (args[ARG_adv_is_scan_rsp].u_obj != NULL) { @@ -2565,7 +2526,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po if (unset_adv_uuid || adv_uuid_buf.buf != NULL) { if (bluetooth->adv_data.p_service_uuid != NULL) { - FREE(bluetooth->adv_data.p_service_uuid ); + FREE(bluetooth->adv_data.p_service_uuid); bluetooth->adv_data.p_service_uuid = NULL; } @@ -2591,7 +2552,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po NETWORK_BLUETOOTH_BAD_PEER: mp_raise_ValueError("peer_addr must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")"); NETWORK_BLUETOOTH_BAD_UUID: - mp_raise_ValueError("adv_uuid must be bytearray(" TOSTRING(UUID_LEN ) ")"); + mp_raise_ValueError("adv_uuid must be bytearray(" TOSTRING(UUID_LEN) ")"); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_ble_settings_obj, 1, network_bluetooth_ble_settings); @@ -2677,9 +2638,7 @@ STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { mp_obj_list_append(bluetooth->connections, connection); - NETWORK_BLUETOOTH_DEBUG_PRINTF("Calling open with IF=%u\n", bluetooth->gattc_interface); esp_ble_gattc_open(bluetooth->gattc_interface, connection->bda, true); - NETWORK_BLUETOOTH_DEBUG_PRINTF("AFTER Calling open with IF=%u\n", bluetooth->gattc_interface); return connection; @@ -2692,7 +2651,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_connect_obj, network_bluetoot STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; if (!check_locals_dict(connection, attr, dest)) { - switch(attr) { + switch (attr) { case MP_QSTR_services: dest[0] = connection->services; break; @@ -2723,24 +2682,12 @@ STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *a ret = network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); if (n_args > 1 && MP_OBJ_IS_TYPE(self, &network_bluetooth_gattc_char_type)) { assert(connection != MP_OBJ_NULL); -#if 0 - NETWORK_BLUETOOTH_DEBUG_PRINTF("(un)registering for notify\n"); - NETWORK_BLUETOOTH_DEBUG_PRINTF("interface: %02X\n", bluetooth->gattc_interface); - NETWORK_BLUETOOTH_DEBUG_PRINTF("bda: "); - network_bluetooth_print_bda(NULL, connection->bda); - NETWORK_BLUETOOTH_DEBUG_PRINTF("\nservice: "); - network_bluetooth_gatt_id_print(NULL, &service->service_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); - NETWORK_BLUETOOTH_DEBUG_PRINTF("char: "); - network_bluetooth_gatt_id_print(NULL, &self->char_id); - NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); -#endif if (self->callback != mp_const_none) { if (esp_ble_gattc_register_for_notify(bluetooth->gattc_interface, connection->bda, &service->service_id, &self->char_id) != ESP_OK) { goto NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR; } } else { - if (esp_ble_gattc_unregister_for_notify( bluetooth->gattc_interface, connection->bda, &service->service_id, &self->char_id) != ESP_OK) { + if (esp_ble_gattc_unregister_for_notify(bluetooth->gattc_interface, connection->bda, &service->service_id, &self->char_id) != ESP_OK) { goto NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR; } } @@ -2782,7 +2729,7 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) read_write_data_t read_data; // clear out any stale data - if(xQueueReceive(read_write_q, &read_data, 0) == pdTRUE) { + if (xQueueReceive(read_write_q, &read_data, 0) == pdTRUE) { FREE(read_data.value); } xQueueReset(read_write_q); @@ -2794,7 +2741,7 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) } if (result != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "read call failed"); + mp_raise_msg(&mp_type_OSError, "read call failed"); } TickType_t ticks = portMAX_DELAY; @@ -2807,15 +2754,15 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) if (xQueueReceive(read_write_q, &read_data, ticks) == pdTRUE) { - - mp_obj_t res = mp_obj_new_bytearray(read_data.value_len, read_data.value); + + mp_obj_t res = MP_OBJ_NEW_BYTES(read_data.value_len, read_data.value); FREE(read_data.value); return res; } mp_raise_msg(&mp_type_OSError, "timed out"); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_read_obj,1,2, network_bluetooth_char_read); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_read_obj, 1, 2, network_bluetooth_char_read); STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { bool is_chr; @@ -2845,7 +2792,7 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { read_write_data_t read_data; // clear out any stale data - if(xQueueReceive(read_write_q, &read_data, 0) == pdTRUE) { + if (xQueueReceive(read_write_q, &read_data, 0) == pdTRUE) { FREE(read_data.value); } xQueueReset(read_write_q); @@ -2855,28 +2802,28 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { mp_get_buffer_raise(value, &buf, MP_BUFFER_READ); if (is_chr) { - result = + result = esp_ble_gattc_write_char( - bluetooth->gattc_interface, - connection->conn_id, - &service->service_id, - &chr->char_id, - buf.len, - buf.buf, - ESP_GATT_WRITE_TYPE_NO_RSP, - ESP_GATT_AUTH_REQ_NONE); + bluetooth->gattc_interface, + connection->conn_id, + &service->service_id, + &chr->char_id, + buf.len, + buf.buf, + ESP_GATT_WRITE_TYPE_NO_RSP, + ESP_GATT_AUTH_REQ_NONE); } else { - result = + result = esp_ble_gattc_write_char_descr( - bluetooth->gattc_interface, - connection->conn_id, - &service->service_id, - &chr->char_id, - &descr->descr_id, - buf.len, - buf.buf, - ESP_GATT_WRITE_TYPE_NO_RSP, - ESP_GATT_AUTH_REQ_NONE); + bluetooth->gattc_interface, + connection->conn_id, + &service->service_id, + &chr->char_id, + &descr->descr_id, + buf.len, + buf.buf, + ESP_GATT_WRITE_TYPE_NO_RSP, + ESP_GATT_AUTH_REQ_NONE); } if (result != ESP_OK) { @@ -2905,11 +2852,7 @@ STATIC mp_obj_t network_bluetooth_char_notify_helper(size_t n_args, const mp_obj mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); if (args[ARG_value].u_obj != MP_OBJ_NULL) { - if ( !MP_OBJ_IS_STR_OR_BYTES(args[ARG_value].u_obj) && - !MP_OBJ_IS_TYPE(args[ARG_value].u_obj, &mp_type_bytearray) - ) { - mp_raise_ValueError("value must be string, bytes, bytearray"); - } + mp_obj_is_bt_datatype_raise(args[ARG_value].u_obj); } else { args[ARG_value].u_obj = self->value; } @@ -2921,16 +2864,16 @@ STATIC mp_obj_t network_bluetooth_char_notify_helper(size_t n_args, const mp_obj } STATIC mp_obj_t network_bluetooth_char_notify(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { - return network_bluetooth_char_notify_helper(n_args, pos_args, kw_args, false); + return network_bluetooth_char_notify_helper(n_args, pos_args, kw_args, false); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_notify_obj, 1, network_bluetooth_char_notify); STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { - return network_bluetooth_char_notify_helper(n_args, pos_args, kw_args, true); + return network_bluetooth_char_notify_helper(n_args, pos_args, kw_args, true); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_indicate_obj, 1, network_bluetooth_char_indicate); -STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { +STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); if (n_args != 0 || n_kw != 0) { mp_raise_TypeError("Constructor takes no arguments"); @@ -2993,9 +2936,7 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - if (!MP_OBJ_IS_BT_DATATYPE(args[ARG_value].u_obj)) { - mp_raise_ValueError("value must be str, bytes, bytearray, or None"); - } + mp_obj_is_bt_datatype_raise(args[ARG_value].u_obj); esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); @@ -3045,8 +2986,7 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { uint32_t then = mp_hal_ticks_ms(); // Wait for registration - while(bluetooth->gatts_interface == ESP_GATT_IF_NONE && mp_hal_ticks_ms() - then < 1000) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Waiting for BT interface registration ...\n"); + while (bluetooth->gatts_interface == ESP_GATT_IF_NONE && mp_hal_ticks_ms() - then < 1000) { mp_hal_delay_ms(100); } @@ -3058,8 +2998,8 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { // Handle calculation: // // 1 for 2800/2801 Service declaration - // 1x for each 2803 Char declaration - // 1x for each Char desc declaration --- not used + // 1x for each 2803 Char declaration + // 1x for each Char desc declaration --- not used esp_ble_gatts_create_service(bluetooth->gatts_interface, &self->service_id, 1 + numChars * 2); return mp_const_none; } @@ -3112,7 +3052,7 @@ STATIC void network_bluetooth_descr_attr(mp_obj_t self_in, qstr attr, mp_obj_t * { esp_bt_uuid_t uuid128; uuid_to_uuid128(&self->descr_id.uuid, &uuid128); - dest[0] = mp_obj_new_bytearray(uuid128.len, uuid128.uuid.uuid128); + dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); } break; } @@ -3125,7 +3065,7 @@ STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *d if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type)) { - switch(attr) { + switch (attr) { case MP_QSTR_service: dest[0] = self->service; break; @@ -3133,22 +3073,21 @@ STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *d { esp_bt_uuid_t uuid128; uuid_to_uuid128(&self->char_id.uuid, &uuid128); - dest[0] = mp_obj_new_bytearray(uuid128.len, uuid128.uuid.uuid128); + dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); } break; + case MP_QSTR_value: if (dest[0] == MP_OBJ_NULL) { // load dest[0] = self->value; } else if (dest[1] != MP_OBJ_NULL) { // store - if (!MP_OBJ_IS_BT_DATATYPE(dest[1])) { - mp_raise_ValueError("value must be string, bytes, bytearray, or None"); - } + mp_obj_is_bt_datatype_raise(dest[1]); self->value = dest[1]; dest[0] = MP_OBJ_NULL; } } } else { - switch(attr) { + switch (attr) { case MP_QSTR_service: dest[0] = self->service; break; @@ -3161,7 +3100,7 @@ STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *d { esp_bt_uuid_t uuid128; uuid_to_uuid128(&self->char_id.uuid, &uuid128); - dest[0] = mp_obj_new_bytearray(uuid128.len, uuid128.uuid.uuid128); + dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); } break; @@ -3187,7 +3126,7 @@ STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t // Attributes of GATTS objects only if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_service_type)) { - switch(attr) { + switch (attr) { case MP_QSTR_Char: dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_characteristic_make_new_obj); dest[1] = self; @@ -3196,7 +3135,7 @@ STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t } // Attributes common to GATTS and GATTC - switch(attr) { + switch (attr) { case MP_QSTR_chars: dest[0] = self->chars; @@ -3206,7 +3145,7 @@ STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t { esp_bt_uuid_t uuid128; uuid_to_uuid128(&self->service_id.id.uuid, &uuid128); - dest[0] = mp_obj_new_bytearray(uuid128.len, uuid128.uuid.uuid128); + dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); } break; @@ -3223,7 +3162,7 @@ STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) network_bluetooth_obj_t* self = (network_bluetooth_obj_t*) self_in; if (!check_locals_dict(self, attr, dest)) { - switch(attr) { + switch (attr) { case MP_QSTR_is_scanning: dest[0] = self->scanning ? mp_const_true : mp_const_false; break; @@ -3234,10 +3173,7 @@ STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) } } - - STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { - NETWORK_BLUETOOTH_DEBUG_PRINTF("Entering network_bluetooth_deinit\n"); network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); if (bluetooth->state == NETWORK_BLUETOOTH_STATE_INIT) { @@ -3247,31 +3183,35 @@ STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { size_t len; mp_obj_t *items; mp_obj_get_array(bluetooth->services, &len, &items); - for(int i = 0; i < len; i++) { + for (int i = 0; i < len; i++) { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; if (service->handle != 0) { esp_ble_gatts_delete_service(service->handle); } service->valid = false; } - bluetooth->services = mp_obj_new_list(0, NULL); if (bluetooth->gattc_interface != ESP_GATT_IF_NONE) { - esp_ble_gattc_app_unregister(bluetooth->gattc_interface); + if (esp_ble_gattc_app_unregister(bluetooth->gattc_interface) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_unregister() failed"); + } } if (bluetooth->gatts_interface != ESP_GATT_IF_NONE) { - esp_ble_gatts_app_unregister(bluetooth->gatts_interface); + if (esp_ble_gatts_app_unregister(bluetooth->gatts_interface) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_unregister() failed"); + } } - switch(esp_bluedroid_disable()) { + + switch (esp_bluedroid_disable()) { case ESP_OK: break; default: mp_raise_msg(&mp_type_OSError, "esp_bluedroid_disable() failed"); break; } - switch(esp_bluedroid_deinit()) { + switch (esp_bluedroid_deinit()) { case ESP_OK: break; default: @@ -3279,18 +3219,14 @@ STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { break; } - // FIXME: This fails, with the present IDF -#if 0 - mp_hal_delay_ms(300); - switch(esp_bt_controller_enable(ESP_BT_MODE_IDLE)) { + switch (esp_bt_controller_disable(ESP_BT_MODE_BTDM)) { case ESP_OK: break; default: - mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable(idle) failed"); + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_disable(ESP_BT_MODE_BTDM) failed"); break; } -#endif } return mp_const_none; @@ -3309,10 +3245,10 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_bluetooth_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_gatts_service_type) }, - { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr - { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, - { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, - { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&network_bluetooth_scan_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&network_bluetooth_scan_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_is_scanning), NULL }, // handle by attr // class constants @@ -3321,7 +3257,7 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_GATTS_CONNECT) }, { MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(NETWORK_BLUETOOTH_GATTS_DISCONNECT) }, { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(NETWORK_BLUETOOTH_READ) }, - { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(NETWORK_BLUETOOTH_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(NETWORK_BLUETOOTH_WRITE) }, { MP_ROM_QSTR(MP_QSTR_NOTIFY), MP_ROM_INT(NETWORK_BLUETOOTH_NOTIFY) }, { MP_ROM_QSTR(MP_QSTR_SCAN_RES), MP_ROM_INT(NETWORK_BLUETOOTH_GATTC_SCAN_RES) }, { MP_ROM_QSTR(MP_QSTR_SCAN_CMPL), MP_ROM_INT(NETWORK_BLUETOOTH_GATTC_SCAN_CMPL) }, @@ -3343,8 +3279,8 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_38), MP_ROM_INT(ADV_CHNL_38) }, { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, - - // BLE_ADV_DATA_FLAG + +// BLE_ADV_DATA_FLAG { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_LIMIT_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_LIMIT_DISC) }, { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_GEN_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_GEN_DISC) }, @@ -3375,14 +3311,18 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_PROP_EXT_PROP), MP_ROM_INT(ESP_GATT_CHAR_PROP_BIT_EXT_PROP) }, // esp_ble_adv_filter_t - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) }, - { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), - MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) + }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY) + }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST) + }, + { MP_ROM_QSTR(MP_QSTR_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST), + MP_ROM_INT(ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) + }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_locals_dict, network_bluetooth_locals_dict_table); @@ -3397,7 +3337,7 @@ const mp_obj_type_t network_bluetooth_type = { }; -// +// // CONNECTION OBJECTS // @@ -3418,7 +3358,7 @@ const mp_obj_type_t network_bluetooth_connection_type = { .attr = network_bluetooth_connection_attr, }; -// +// // GATTS SERVICE OBJECTS // @@ -3443,13 +3383,14 @@ const mp_obj_type_t network_bluetooth_gatts_service_type = { }; -// +// // GATTC SERVICE OBJECTS // STATIC const mp_rom_map_elem_t network_bluetooth_gattc_service_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method { MP_ROM_QSTR(MP_QSTR_is_primary), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // Handled by attr method }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_service_locals_dict, network_bluetooth_gattc_service_locals_dict_table); @@ -3465,7 +3406,7 @@ const mp_obj_type_t network_bluetooth_gattc_service_type = { }; -// +// // GATTS CHAR OBJECTS // @@ -3489,7 +3430,7 @@ const mp_obj_type_t network_bluetooth_gatts_char_type = { .attr = network_bluetooth_char_attr, }; -// +// // GATTC CHAR OBJECTS // @@ -3512,7 +3453,7 @@ const mp_obj_type_t network_bluetooth_gattc_char_type = { .attr = network_bluetooth_char_attr, }; -// +// // GATTC DESCR OBJECTS // From 4c4491aff9a66c516e0597255bcedd2d0afad443 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 10 May 2017 14:37:19 -0700 Subject: [PATCH 58/98] esp32/network_bluetooth.c: Removed many unneccessary switch statements, connect now accepts bytes --- esp32/network_bluetooth.c | 65 +++++++++------------------------------ 1 file changed, 15 insertions(+), 50 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 660a65692..8e3c8ebe2 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2259,54 +2259,31 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); esp_bt_controller_init(&bt_cfg); - switch (esp_bt_controller_enable(ESP_BT_MODE_BTDM)) { - case ESP_OK: - break; - default: + if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) { mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); - break; } - switch (esp_bluedroid_init()) { - case ESP_OK: - break; - default: + if (esp_bluedroid_init() != ESP_OK) { mp_raise_msg(&mp_type_OSError, "esp_bluedroid_init() failed"); - break; - } - switch (esp_bluedroid_enable()) { - case ESP_OK: - break; - default: + + if (esp_bluedroid_enable() != ESP_OK) { mp_raise_msg(&mp_type_OSError, "esp_bluedroid_enable() failed"); - break; } esp_ble_gatts_register_callback(network_bluetooth_gatts_event_handler); esp_ble_gattc_register_callback(network_bluetooth_gattc_event_handler); esp_ble_gap_register_callback(network_bluetooth_gap_event_handler); - // FIXME, this is hardcoded - switch (esp_ble_gatts_app_register(0)) { - case ESP_OK: - break; - - default: + if (esp_ble_gatts_app_register(0) != ESP_OK) { mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() failed"); - break; } - // FIXME, this is hardcoded - switch (esp_ble_gattc_app_register(1)) { - case ESP_OK: - break; - - default: + + if (esp_ble_gattc_app_register(1) != ESP_OK) { mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_register() failed"); - break; } - self->state = NETWORK_BLUETOOTH_STATE_INIT; + self->state = NETWORK_BLUETOOTH_STATE_INIT; } return mp_const_none; } @@ -2621,7 +2598,7 @@ STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { network_bluetooth_obj_t * bluetooth = (network_bluetooth_obj_t *)self_in; mp_buffer_info_t bda_buf = { 0 }; - if (!MP_OBJ_IS_TYPE(bda, &mp_type_bytearray)) { + if (!MP_OBJ_IS_BYTEARRAY_OR_BYTES(bda)) { goto NETWORK_BLUETOOTH_connect_BAD_ADX; } mp_get_buffer(bda, &bda_buf, MP_BUFFER_READ); @@ -3204,28 +3181,16 @@ STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { } - switch (esp_bluedroid_disable()) { - case ESP_OK: - break; - default: - mp_raise_msg(&mp_type_OSError, "esp_bluedroid_disable() failed"); - break; + if (esp_bluedroid_disable() != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_disable() failed"); } - switch (esp_bluedroid_deinit()) { - case ESP_OK: - break; - default: - mp_raise_msg(&mp_type_OSError, "esp_bluedroid_deinit() failed"); - break; + if (esp_bluedroid_deinit() != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_deinit() failed"); } - switch (esp_bt_controller_disable(ESP_BT_MODE_BTDM)) { - case ESP_OK: - break; - default: - mp_raise_msg(&mp_type_OSError, "esp_bt_controller_disable(ESP_BT_MODE_BTDM) failed"); - break; + if (esp_bt_controller_disable(ESP_BT_MODE_BTDM) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_disable(ESP_BT_MODE_BTDM) failed"); } } From 2121a5d5f80d7fd11163ad1e56956521daeb49fb Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 10 May 2017 14:38:12 -0700 Subject: [PATCH 59/98] Updated docs to reflect use of bytes, added an example section --- esp32/bluetooth_docs.md | 269 ++++++++++++++++------------------------ 1 file changed, 110 insertions(+), 159 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index ed17059c5..1699a4e26 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -31,7 +31,7 @@ Note that these defaults are set when you create the Bluetooth object. You need bluetooth.ble_settings(int_min = 1280, int_max = 1280, adv_type = bluetooth.ADV_TYPE_IND, own_addr_type = bluetooth.BLE_ADDR_TYPE_PUBLIC, - peer_addr = bytearray([0] * 6)), a + peer_addr = bytes([0] * 6), peer_addr_type = bluetooth.BLE_ADDR_TYPE_PUBLIC, channel_map = bluetooth.ADV_CHNL_ALL, filter_policy = blueooth.ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, @@ -60,7 +60,7 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, * `bluetooth.BLE_ADDR_TYPE_RPA_PUBLIC` * `bluetooth.BLE_ADDR_TYPE_RPA_RANDOM` -`peer_addr` is a `bytearray(6)` or `bytes` representing the peer address. +`peer_addr` is a `bytes(6)` or `bytearray(6)` representing the peer address. `channel_map` is a binary OR of: @@ -103,9 +103,9 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, `bluetooth.deinit()` shutdown Bluetooth. Due to present limitations in the IDF, this does _not_ return the BT stack to a lower powered state. -`bluetooth.connect(bda)` GATTC - connect to a remote GATTS server. BDA is the remote address, as a `bytearray(6)`. See [GATTC](#gattc) for more information +`bluetooth.connect(bda)` GATTC - connect to a remote GATTS server. BDA is the remote address, as a `bytes(6)`. See [GATTC](#gattc) for more information -`bluetooth.Service(uuid, is_primary = True)` GATTS - create a new GATTSService object. `uuid` is either an integer or a bytearray(16). UUIDs are globally unique with in GATTS. If you attempt to create a service with a UUID that is the same as an existing (but not closed) service, you will receive the same service object, and no new service will be created. +`bluetooth.Service(uuid, is_primary = True)` GATTS - create a new GATTSService object. `uuid` is either an integer or a `bytes(16)`. UUIDs are globally unique with in GATTS. If you attempt to create a service with a UUID that is the same as an existing (but not closed) service, you will receive the same service object, and no new service will be created. `bluetooth.services` GATTS - returns the existing GATTS services. @@ -118,7 +118,7 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, * `bluetooth.SCAN_RES` for GATTC scan results * `bluetooth.SCAN_CMPL` when GATTC scan is complete 3. Event data: - * For `bluetooth.CONNECT`, `bluetooth.DISCONNECT` events, this will be a bytearray represeting the remote address. + * For `bluetooth.CONNECT`, `bluetooth.DISCONNECT` events, this will be a `bytes(6)` represeting the remote address. * For `bluetooth.SCAN_RES` this will be a 2-tuple of `(, )` * For `bluetooth.SCAN_CMPL` this will be `None`. 4. The `)` function will connect to a heart rate monitor at address ``, and configure it to send heartrate notifications; the callback function will then print the heart rate. -###### Get a list of current services ```python -currentServices = b.services -``` -###### Get a list of service characteristics -```python -chars = service.chars +import gc +import sys +import network as n +import gc +import time + +b = n.Bluetooth() + +found = {} +complete = True + +def bcb(b,e,d,u): + global complete + global found + if e == b.CONNECT: + print("CONNECT") + elif e == b.DISCONNECT: + print("DISCONNECT") + elif e == b.SCAN_RES: + if complete: + complete = False + found = {} + + adx, name = d + if adx not in found: + found[adx] = name + + elif e == b.SCAN_CMPL: + print("Scan Complete") + complete = True + print ('\nFinal List:') + for adx, name in found.items(): + print ('Found:' + ':'.join(['%02X' % i for i in adx]), name) + onScanComplete() + else: + print ('Unknown event', e,d) + +def cb (cb, event, value, userdata): + print('charcb ', cb, userdata, ' ', end='') + if event == b.READ: + print('Read') + return 'ABCDEFG' + elif event == b.WRITE: + print ('Write', value) + elif event == b.NOTIFY: + print ('Notify', value) + period = None + flags = value[0] + hr = value[1] + if flags & 0x10: + period = (value[3] << 8) + value[2] + print ('HR:', hr, 'Period:', period, 'ms') + +def hr(bda): + ''' Will connect to a BLE heartrate monitor, and enable HR notifications ''' + + conn = b.connect(bda) + while not conn.is_connected: + time.sleep(.1) + + time.sleep(2) # Wait for services + + service = ([s for s in conn.services if s.uuid[0:4] == b'\x00\x00\x18\x0d'] + [None])[0] + if service: + char = ([c for c in service.chars if c.uuid[0:4] == b'\x00\x00\x2a\x37'] + [None])[0] + if char: + descr = ([d for d in char.descriptors if d.uuid[0:4] == b'\x00\x00\x29\x02'] + [None])[0] + if descr: + char.callback(cb) + descr.write(b'\x01\x00') # Turn on notify + + +def gatts(): + s1 = b.Service(0xaabb) + s2 = b.Service(0xDEAD) + + c1 = s1.Char(0xccdd) + c2 = s2.Char(0xccdd) + + c1.callback(cb, 'c1 data') + c2.callback(cb, 'c2 data') + + s1.start() + s2.start() + + b.ble_settings(adv_man_name = "mangocorp", adv_dev_name="mangoprod") + b.ble_adv_enable(True) + + +b.callback(bcb) ``` - - -### Callbacks - -##### Bluetooth Callback - -```python -def bt_callback(btObj, event, data, userdata): - print ("Bluetooth object", btObj) - if event == btObj.CONNECT: - print ("connected") - if event == btObj.DISCONNECT: - print ("disconnected") - - -Bluetooth.callback(bt_callback, "hello") -``` - -`Bluetooth.callback` takes two parameters: The callback function itself, and an optional userdata value to be passed in on callbacks. It returns the current callback function and usedata as tuple. - -`cb_function` can be None, which disables callbacks. `cb_function` is called with four parameters; the bluetooth object, event, event data, and the userdata. - -Event values: -* `Bluetooth.CONNECT` Data param is remote addr -* `Bluetooth.DISCONNECT` -* `Bluetooth.SCAN_DATA` Scan data -* `Bluetooth.SCAN_CMPL` Scan complete - -##### Characteristic Callbacks - -```python -def char_callback(charObj, event, value, userdata): - print('charcb ', cb, userdata,' ', end='') - if event == b.READ: - print('Read') - return 'ABCDEFG' - elif event == b.WRITE: - print ('Write', value) - -Char.callback(cb_function, userdata) -``` - -`Char.callback` takes two parameters: The callback function itself, and an optional userdata value to be passed in on callbacks. It returns the current callback function and userdata as tuple. - -`cb_function` can be None, which disables callbacks. `cb_function` is called with four parameters; the characteristic object, the event type, the event value (the sent value for `WRITE` or the current characteristic value for `READ`), and userdata. - -The event type will be one of `Bluetooth.READ` or `Bluetooth.WRITE`. - -Characteristics have an internal value, which is _not_ used and _not_ updated when there is a callback, though the callback is free to update or use the value as it sees fit. For `READ` operations (or `WRITE` operations that require a return value) the return value of the callback is sent, which must be a `bytearray`, `str`, `bytes`, or `None`. - -###### Value behavior without a callback - -If there is no callback defined for a characteristic, it's internal value will be used for `READ` or `WRITE` events, and `WRITE` events that expect a response will simply return the just-written value. - - - - -### Advertising -##### BLE settings - -```python -b.ble_settings( - int_min = 1280, - int_max = 1280, - type b.ADV_TYPE_IND, - own_addr_type = b.BLE_ADDR_TYPE_PUBLIC, - peer_addr = bytearray([0 for x in range(6)]), - peer_addr_type = b.BLE_ADDR_TYPE_PUBLIC, - channel_map = b.ADV_CHNL_ALL, - filter_policy = b.ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, - adv_is_scan_rsp = False, - adv_dev_name = None, - adv_man_name = None, - adv_inc_tx_power = False, - adv_int_min = 1280, - adv_int_max = 1280, - adv_appearance = 0, - adv_uuid = None, - adv_flags = 0) - -b.adv_enable(True) -``` - -### Scanning - -###### Scan start: - -Advertising and scanning cannot be run at the same time - -`Bluetooth.scan_start(timeout)` - -###### Scan stop: -`Bluetooth.scan_stop()` - - -###### Scan callback data - -The Bluetooth callback will receive: - -* `Bluetooth.SCAN_DATA` Data will be a 2-tuple of `(remote_address, adv_name)` -* `Bluetooth.SCAN_CMPL` Scan has completed; data will be None From 636522e662999ddf0d8f4a6bc344b23e8a3657c7 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 12 May 2017 10:53:52 -0700 Subject: [PATCH 60/98] esp32/network_bluetooth.c: Checked FIXMEs, removed whitespace, fixed adv_uuid_len --- esp32/network_bluetooth.c | 55 ++++----------------------------------- 1 file changed, 5 insertions(+), 50 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 8e3c8ebe2..be9529b8a 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -29,7 +29,6 @@ #include #include - #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" @@ -47,13 +46,11 @@ #include "esp_gatts_api.h" #include "esp_gattc_api.h" - #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) //#define EVENT_DEBUG - #ifdef EVENT_DEBUG # define EVENT_DEBUG_GATTC # define EVENT_DEBUG_GATTS @@ -106,7 +103,6 @@ typedef enum { NETWORK_BLUETOOTH_GATTC_SCAN_CMPL, // Found GATT servers NETWORK_BLUETOOTH_GATTC_SEARCH_RES, // Found GATTS services - NETWORK_BLUETOOTH_GATTC_GET_CHAR, NETWORK_BLUETOOTH_GATTC_GET_DESCR, @@ -232,7 +228,6 @@ typedef struct { } network_bluetooth_service_obj_t; - // "Connection" typedef struct { @@ -289,7 +284,6 @@ typedef struct { esp_gatt_if_t gatts_interface; esp_gatt_if_t gattc_interface; - esp_ble_adv_params_t adv_params; esp_ble_adv_data_t adv_data; @@ -299,14 +293,11 @@ typedef struct { mp_obj_t callback; mp_obj_t callback_userdata; - - } network_bluetooth_obj_t; // Singleton STATIC network_bluetooth_obj_t* network_bluetooth_singleton = NULL; - STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { if (network_bluetooth_singleton == NULL) { @@ -339,6 +330,7 @@ STATIC network_bluetooth_obj_t* network_bluetooth_get_singleton() { network_bluetooth_singleton->adv_data.p_service_data = NULL; network_bluetooth_singleton->adv_data.service_data_len = 0; network_bluetooth_singleton->adv_data.p_service_uuid = 0; + network_bluetooth_singleton->adv_data.service_uuid_len = 0; network_bluetooth_singleton->adv_data.flag = 0; network_bluetooth_singleton->callback = mp_const_none; @@ -470,7 +462,6 @@ typedef enum { NETWORK_BLUETOOTH_DEL_SERVICE, } item_op_t; - STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle_or_conn_id, esp_bd_addr_t bda, item_op_t kind) { ITEM_BEGIN(); mp_obj_t ret = MP_OBJ_NULL; @@ -563,14 +554,6 @@ STATIC mp_obj_t network_bluetooth_find_service_in_connection_by_uuid(network_blu return network_bluetooth_item_op(connection->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); } -// FIXME: Not used? -#if 0 -STATIC mp_obj_t network_bluetooth_find_char_by_uuid(esp_bt_uuid_t* uuid) { - network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_op(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR); -} -#endif - STATIC mp_obj_t network_bluetooth_find_char_by_handle(uint16_t handle) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); return network_bluetooth_item_op(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_CHAR); @@ -673,7 +656,6 @@ STATIC const gatt_status_name_t gatt_status_names[] = { } \ } - STATIC void gattc_event_dump( esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, @@ -946,7 +928,6 @@ STATIC void gattc_event_dump( } break; - case ESP_GATTC_SRVC_CHG_EVT: { NETWORK_BLUETOOTH_DEBUG_PRINTF( @@ -1112,7 +1093,6 @@ STATIC void gatts_event_dump( "SET_ATTR_VAL", }; - NETWORK_BLUETOOTH_DEBUG_PRINTF( "network_bluetooth_gatts_event_handler(" "event = %02X / %s" @@ -1462,7 +1442,6 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t const char * dev_types[] = { "", "BREDR", "BLE", "DUMO" }; const char * addr_types[] = { "PUBLIC", "RANDOM", "RPA_PUBLIC", "RPA_RANDOM" }; - NETWORK_BLUETOOTH_DEBUG_PRINTF( "search_evt = %s", search_events[param->scan_rst.search_evt]); @@ -1495,7 +1474,6 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t param->scan_rst.adv_data_len, param->scan_rst.scan_rsp_len); - uint8_t * adv_name; uint8_t adv_name_len = 0; adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, @@ -1601,7 +1579,6 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { } break; - case NETWORK_BLUETOOTH_GATTS_ADD_CHAR: { network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_add_char.service_handle); @@ -1692,6 +1669,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { break; case NETWORK_BLUETOOTH_NOTIFY: // FIXME, How do you respond to a notify?? + // Do you even need to? break; default: @@ -1913,7 +1891,6 @@ STATIC void network_bluetooth_gattc_event_handler( } break; - default: enqueue = false; break; @@ -2114,7 +2091,6 @@ STATIC void network_bluetooth_adv_updated() { // MicroPython bindings for network_bluetooth // - STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gattc_descr_type)) { network_bluetooth_descr_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -2296,7 +2272,6 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); } - bool changed = false; bool unset_adv_man_name = false; bool unset_adv_dev_name = false; @@ -2354,11 +2329,8 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po mp_buffer_info_t adv_dev_name_buf = { 0 }; mp_buffer_info_t adv_uuid_buf = { 0 }; - - // pre-check complex types - // peer_addr if (args[ARG_peer_addr].u_obj != NULL) { if (!MP_OBJ_IS_TYPE(args[ARG_peer_addr].u_obj, &mp_type_bytearray)) { @@ -2406,7 +2378,6 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po } } - // update esp_ble_adv_params_t if (args[ARG_int_min].u_int != -1) { @@ -2510,6 +2481,7 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po bluetooth->adv_data.service_uuid_len = adv_uuid_buf.len; if (adv_uuid_buf.len > 0) { bluetooth->adv_data.p_service_uuid = MALLOC(adv_uuid_buf.len); + bluetooth->adv_data.service_uuid_len = adv_uuid_buf.len; memcpy(bluetooth->adv_data.p_service_uuid, adv_uuid_buf.buf, adv_uuid_buf.len); } changed = true; @@ -2559,7 +2531,6 @@ STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* return tuple; } - STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_arg) { network_bluetooth_obj_t *bluetooth = MP_OBJ_TO_PTR(self_in); @@ -2586,7 +2557,6 @@ STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_ } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_scan_start_obj, network_bluetooth_scan_start); - STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { (void)self_in; assert(esp_ble_gap_stop_scanning() == ESP_OK); @@ -2624,7 +2594,6 @@ STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_connect_obj, network_bluetooth_connect); - STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; if (!check_locals_dict(connection, attr, dest)) { @@ -2639,7 +2608,6 @@ STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_ob } } - STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); @@ -2684,7 +2652,6 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) network_bluetooth_descr_obj_t *descr; esp_err_t result; - if (MP_OBJ_IS_TYPE(args[0], &network_bluetooth_gattc_char_type)) { is_chr = true; chr = MP_OBJ_TO_PTR(args[0]); @@ -2728,8 +2695,7 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) ticks = (TickType_t)timeout * 1000.0 / portTICK_PERIOD_MS; } } - - + if (xQueueReceive(read_write_q, &read_data, ticks) == pdTRUE) { mp_obj_t res = MP_OBJ_NEW_BYTES(read_data.value_len, read_data.value); @@ -2737,7 +2703,6 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) return res; } mp_raise_msg(&mp_type_OSError, "timed out"); - } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_read_obj, 1, 2, network_bluetooth_char_read); @@ -2747,7 +2712,6 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { network_bluetooth_descr_obj_t *descr; esp_err_t result; - if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gattc_char_type)) { is_chr = true; chr = MP_OBJ_TO_PTR(self_in); @@ -2772,8 +2736,8 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { if (xQueueReceive(read_write_q, &read_data, 0) == pdTRUE) { FREE(read_data.value); } - xQueueReset(read_write_q); + xQueueReset(read_write_q); mp_buffer_info_t buf; mp_get_buffer_raise(value, &buf, MP_BUFFER_READ); @@ -2943,7 +2907,6 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_characteristic_make_new_obj, 1, network_bluetooth_characteristic_make_new); - STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { @@ -2971,7 +2934,6 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() has failed"); } - // Handle calculation: // // 1 for 2800/2801 Service declaration @@ -3180,7 +3142,6 @@ STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { } } - if (esp_bluedroid_disable() != ESP_OK) { mp_raise_msg(&mp_type_OSError, "esp_bluedroid_disable() failed"); } @@ -3301,7 +3262,6 @@ const mp_obj_type_t network_bluetooth_type = { .attr = network_bluetooth_attr, }; - // // CONNECTION OBJECTS // @@ -3313,7 +3273,6 @@ STATIC const mp_rom_map_elem_t network_bluetooth_connection_locals_dict_table[] STATIC MP_DEFINE_CONST_DICT(network_bluetooth_connection_locals_dict, network_bluetooth_connection_locals_dict_table); - const mp_obj_type_t network_bluetooth_connection_type = { { &mp_type_type }, .name = MP_QSTR_GATTCConn, @@ -3347,7 +3306,6 @@ const mp_obj_type_t network_bluetooth_gatts_service_type = { .attr = network_bluetooth_service_attr, }; - // // GATTC SERVICE OBJECTS // @@ -3360,7 +3318,6 @@ STATIC const mp_rom_map_elem_t network_bluetooth_gattc_service_locals_dict_table STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_service_locals_dict, network_bluetooth_gattc_service_locals_dict_table); - const mp_obj_type_t network_bluetooth_gattc_service_type = { { &mp_type_type }, .name = MP_QSTR_GATTCService, @@ -3370,12 +3327,10 @@ const mp_obj_type_t network_bluetooth_gattc_service_type = { .attr = network_bluetooth_service_attr, }; - // // GATTS CHAR OBJECTS // - STATIC const mp_rom_map_elem_t network_bluetooth_gatts_char_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&network_bluetooth_char_indicate_obj) }, From c6307a335bec869fe4217e417be48ad2b7ade404 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 15 May 2017 09:19:25 -0700 Subject: [PATCH 61/98] esp32/Makefile: Updated to latest IDF esp32/sdkconfig.h: Updated to latest IDF --- esp32/Makefile | 7 +++++-- esp32/sdkconfig.h | 9 ++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index 0a99f0e54..110612d9d 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -29,7 +29,7 @@ ESPCOMP = $(ESPIDF)/components ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py # verify the ESP IDF version -ESPIDF_SUPHASH := f73c6f875cc564fa6c9962be71eac4dbdc56aa63 +ESPIDF_SUPHASH := 1e0710f1b24429a316c9c34732aa17bd3f189421 ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') ifneq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH)) $(info ** WARNING **) @@ -204,6 +204,7 @@ ESPIDF_DRIVER_O = $(addprefix $(ESPCOMP)/driver/,\ gpio.o \ timer.o \ spi_master.o \ + spi_common.o \ rtc_module.o \ ) @@ -213,6 +214,7 @@ ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ event_default_handlers.o \ task_wdt.o \ cache_err_int.o \ + clk.o \ core_dump.o \ cpu_start.o \ gdbstub.o \ @@ -222,7 +224,6 @@ ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ ipc.o \ int_wdt.o \ event_loop.o \ - cpu_freq.o \ hwcrypto/sha.o \ hwcrypto/aes.o \ lib_printf.o \ @@ -231,6 +232,7 @@ ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ hw_random.o \ phy_init.o \ intr_alloc.o \ + dport_access.o \ ) ESPIDF_SOC_O = $(addprefix $(ESPCOMP)/soc/,\ @@ -633,6 +635,7 @@ BOOTLOADER_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\ log/log.o \ spi_flash/spi_flash_rom_patch.o \ soc/esp32/rtc_clk.o \ + soc/esp32/rtc_time.o \ micro-ecc/micro-ecc/uECC.o \ bootloader/src/main/bootloader_start.o \ ) diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index 886c31d28..0cc48af75 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -5,6 +5,10 @@ #define CONFIG_APP_OFFSET 0x10000 #define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS y +#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4 + +#define CONFIG_TCPIP_TASK_STACK_SIZE 2560 #define CONFIG_ESP32_APPTRACE_DEST_NONE 1 #define CONFIG_ESP32_PHY_AUTO_INIT 1 @@ -25,6 +29,10 @@ #define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 #define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 #define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP32_XTAL_FREQ_AUTO y +#define CONFIG_ESP32_XTAL_FREQ 0 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 + #define CONFIG_FOUR_MAC_ADDRESS_FROM_EFUSE 1 #define CONFIG_NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE 4 @@ -36,7 +44,6 @@ #define CONFIG_TASK_WDT_CHECK_IDLE_TASK 0 #define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 0 -#define CONFIG_FREERTOS_UNICORE 1 #define CONFIG_FREERTOS_CORETIMER_0 1 #define CONFIG_FREERTOS_HZ 100 #define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 From 705eb88152c85e75668f568cf2a78a48b08e77bd Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 15 May 2017 10:53:49 -0700 Subject: [PATCH 62/98] esp32/network_bluetooth.c: Updated to latest IDF esp32/sdkconfig.h: Updated to latest IDF --- esp32/network_bluetooth.c | 8 +++++--- esp32/sdkconfig.h | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index be9529b8a..5135a236b 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -49,7 +49,7 @@ #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -//#define EVENT_DEBUG +#define EVENT_DEBUG #ifdef EVENT_DEBUG # define EVENT_DEBUG_GATTC @@ -2156,6 +2156,7 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m "peer_addr_type = %u, " NETWORK_BLUETOOTH_LF "channel_map = %u, " NETWORK_BLUETOOTH_LF "adv_filter_policy = %u" NETWORK_BLUETOOTH_LF + "state = %d" NETWORK_BLUETOOTH_LF ")" , self->conn_id, @@ -2174,7 +2175,8 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m self->adv_params.peer_addr[5], self->adv_params.peer_addr_type, self->adv_params.channel_map, - self->adv_params.adv_filter_policy + self->adv_params.adv_filter_policy, + self->state ); mp_printf(print, ", data = (" @@ -2545,7 +2547,7 @@ STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_ static esp_ble_scan_params_t params = { .scan_type = BLE_SCAN_TYPE_ACTIVE, - .own_addr_type = ESP_PUBLIC_ADDR, + .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_interval = 0x50, .scan_window = 0x30 diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index 5a9b9ae42..065e4ba76 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -70,6 +70,9 @@ #define CONFIG_WIFI_ENABLED 1 #define CONFIG_BT_ENABLED 1 #define CONFIG_BLUEDROID_ENABLED 1 +#define CONFIG_GATTS_ENABLE 1 +#define CONFIG_GATTC_ENABLE 1 +#define CONFIG_SMP_ENABLE 1 #define CONFIG_BT_RESERVE_DRAM 0x10000 #define CONFIG_BTDM_CONTROLLER_RUN_CPU 0 #define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 From 7cfc572c290ef21c3750da0d0fcabffb26ba3cea Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 15 May 2017 12:53:55 -0700 Subject: [PATCH 63/98] exp32/sdkconfig.h: changed defines from "y" to "1" --- esp32/sdkconfig.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index 0cc48af75..45e581a45 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -5,7 +5,7 @@ #define CONFIG_APP_OFFSET 0x10000 #define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 -#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS y +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1 #define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4 #define CONFIG_TCPIP_TASK_STACK_SIZE 2560 @@ -29,7 +29,7 @@ #define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 #define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 #define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 -#define CONFIG_ESP32_XTAL_FREQ_AUTO y +#define CONFIG_ESP32_XTAL_FREQ_AUTO 1 #define CONFIG_ESP32_XTAL_FREQ 0 #define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 From 7060dd21b60a6ad345b70a1a4895aae74d444614 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 16 May 2017 10:19:28 -0700 Subject: [PATCH 64/98] esp32/Makefile: -Wno-error=array-bounds for dport_access.o esp32/sdkconfig.h: restored CONFIG_FREERTOS_UNICORE --- esp32/Makefile | 1 + esp32/sdkconfig.h | 1 + 2 files changed, 2 insertions(+) diff --git a/esp32/Makefile b/esp32/Makefile index 110612d9d..5d07a0d1f 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -208,6 +208,7 @@ ESPIDF_DRIVER_O = $(addprefix $(ESPCOMP)/driver/,\ rtc_module.o \ ) +$(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-error=array-bounds ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ app_trace.o \ panic.o \ diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index 45e581a45..1ffd10b6b 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -44,6 +44,7 @@ #define CONFIG_TASK_WDT_CHECK_IDLE_TASK 0 #define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 0 +#define CONFIG_FREERTOS_UNICORE 1 #define CONFIG_FREERTOS_CORETIMER_0 1 #define CONFIG_FREERTOS_HZ 100 #define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 From d3ce5d6b3d98a0787dfaae63650581dbd979db4e Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 17 May 2017 07:58:45 -0700 Subject: [PATCH 65/98] esp32/network_bluetooth.c: Fixed formatting for char print --- esp32/network_bluetooth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 5135a236b..0846cd9b2 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2105,8 +2105,8 @@ STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_o mp_obj_print_helper(print, self->value, PRINT_REPR); } else { mp_printf(print, "GATTCChar(uuid = "); + network_bluetooth_gatt_id_print(print, &self->char_id); } - network_bluetooth_gatt_id_print(print, &self->char_id); mp_printf(print, ", prop = %02X", self->prop); } mp_printf(print, ")"); From 9246c324ffcd0151a07a366df84f0265483f7897 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 17 May 2017 08:11:57 -0700 Subject: [PATCH 66/98] esp32/modnetwork.c: Added #if around bluetooth class esp32/mpconfigport.h Added config option for bluetooth enable --- esp32/modnetwork.c | 2 ++ esp32/mpconfigport.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/esp32/modnetwork.c b/esp32/modnetwork.c index b29de2fe2..e8f65dc04 100644 --- a/esp32/modnetwork.c +++ b/esp32/modnetwork.c @@ -526,7 +526,9 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj }, +#if (MICROPY_BLUETOOTH) { MP_ROM_QSTR(MP_QSTR_Bluetooth), MP_ROM_PTR(&network_bluetooth_type) }, +#endif #if MODNETWORK_INCLUDE_CONSTANTS { MP_OBJ_NEW_QSTR(MP_QSTR_STA_IF), diff --git a/esp32/mpconfigport.h b/esp32/mpconfigport.h index 741a81617..998811e12 100644 --- a/esp32/mpconfigport.h +++ b/esp32/mpconfigport.h @@ -147,6 +147,9 @@ #define mp_type_fileio fatfs_type_fileio #define mp_type_textio fatfs_type_textio +// bluetooth configuration +#define MICROPY_BLUETOOTH (1) + // use vfs's functions for import stat and builtin open #define mp_import_stat mp_vfs_import_stat #define mp_builtin_open mp_vfs_open From 124ef41d411aff20a5910eed89aaa53764ed0d87 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 17 May 2017 11:35:07 -0700 Subject: [PATCH 67/98] esp32/network_bluetooth.c: disabled event debugging --- esp32/network_bluetooth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 0846cd9b2..4fa2b72b5 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -49,7 +49,7 @@ #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -#define EVENT_DEBUG +//#define EVENT_DEBUG #ifdef EVENT_DEBUG # define EVENT_DEBUG_GATTC From 291438c69e43a5ddaebd2418001f412a75c8395b Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 19 May 2017 10:15:35 -0700 Subject: [PATCH 68/98] esp32/network_bluetooth.c: Added GATTS descriptors --- esp32/network_bluetooth.c | 451 ++++++++++++++++++++++++-------------- 1 file changed, 289 insertions(+), 162 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 4fa2b72b5..3a3362269 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -77,6 +77,7 @@ const mp_obj_type_t network_bluetooth_gattc_service_type; const mp_obj_type_t network_bluetooth_gatts_char_type; const mp_obj_type_t network_bluetooth_gattc_char_type; const mp_obj_type_t network_bluetooth_gattc_descr_type; +const mp_obj_type_t network_bluetooth_gatts_descr_type; STATIC SemaphoreHandle_t item_mut; @@ -96,7 +97,7 @@ typedef enum { NETWORK_BLUETOOTH_GATTS_CREATE, NETWORK_BLUETOOTH_GATTS_START, NETWORK_BLUETOOTH_GATTS_STOP, - NETWORK_BLUETOOTH_GATTS_ADD_CHAR, + NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR, // Add char or descriptor // GAP / GATTC events NETWORK_BLUETOOTH_GATTC_SCAN_RES, @@ -131,9 +132,9 @@ typedef struct { struct { uint16_t service_handle; - uint16_t char_handle; - esp_bt_uuid_t char_uuid; - } gatts_add_char; + uint16_t handle; + esp_bt_uuid_t uuid; + } gatts_add_char_descr; struct { uint16_t conn_id; @@ -239,13 +240,13 @@ typedef struct { } network_bluetooth_connection_obj_t; -// "Char" +// "Char" and "Descriptor" common structure typedef struct { mp_obj_base_t base; - mp_obj_t service; + mp_obj_t parent; - esp_gatt_id_t char_id; // common + esp_gatt_id_t id; // common esp_gatt_char_prop_t prop; // common mp_obj_t descriptors; // GATTC @@ -258,16 +259,7 @@ typedef struct { mp_obj_t callback; // common mp_obj_t callback_userdata; // common -} network_bluetooth_char_obj_t; - -// "Descriptor" - -typedef struct { - mp_obj_base_t base; - mp_obj_t chr; - - esp_gatt_id_t descr_id; // common -} network_bluetooth_descr_obj_t; +} network_bluetooth_char_descr_obj_t; // "Bluetooth" Declaration typedef struct { @@ -448,20 +440,22 @@ STATIC void network_bluetooth_gatt_id_print(const mp_print_t *print, const esp_g } } if (print != NULL) { - mp_printf(print, ", inst_id = %02X ", gatt_id->inst_id); + mp_printf(print, ", inst_id = %02X", gatt_id->inst_id); } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X ", gatt_id->inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X", gatt_id->inst_id); } } typedef enum { NETWORK_BLUETOOTH_FIND_SERVICE, NETWORK_BLUETOOTH_FIND_CONNECTION, - NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE, - NETWORK_BLUETOOTH_FIND_CHAR, + NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN, + NETWORK_BLUETOOTH_FIND_CHAR_DESCR, NETWORK_BLUETOOTH_DEL_SERVICE, } item_op_t; + +// FIXME -- this could be more efficient. STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, uint16_t handle_or_conn_id, esp_bd_addr_t bda, item_op_t kind) { ITEM_BEGIN(); mp_obj_t ret = MP_OBJ_NULL; @@ -473,21 +467,31 @@ STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, ui switch (kind) { // These all search a services list case NETWORK_BLUETOOTH_FIND_SERVICE: - case NETWORK_BLUETOOTH_FIND_CHAR: + case NETWORK_BLUETOOTH_FIND_CHAR_DESCR: case NETWORK_BLUETOOTH_DEL_SERVICE: { network_bluetooth_service_obj_t* service = (network_bluetooth_service_obj_t*) items[i]; - if (kind == NETWORK_BLUETOOTH_FIND_CHAR) { + if (kind == NETWORK_BLUETOOTH_FIND_CHAR_DESCR) { size_t char_len; mp_obj_t *char_items; mp_obj_get_array(service->chars, &char_len, &char_items); for (int j = 0; j < char_len; j++) { - network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) char_items[j]; - if ((uuid != NULL && uuid_eq(&chr->char_id.uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { + network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*) char_items[j]; + if ((uuid != NULL && uuid_eq(&chr->id.uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { ret = chr; goto NETWORK_BLUETOOTH_ITEM_END; } + size_t descr_len; + mp_obj_t *descr_items; + mp_obj_get_array(chr->descriptors, &descr_len, &descr_items); + for (int k = 0; k < descr_len; k++) { + network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) descr_items[k]; + if ((uuid != NULL && uuid_eq(&descr->id.uuid, uuid)) || (uuid == NULL && descr->handle == handle_or_conn_id)) { + ret = descr; + goto NETWORK_BLUETOOTH_ITEM_END; + } + } } } else if ((uuid != NULL && uuid_eq(&service->service_id.id.uuid, uuid)) || (uuid == NULL && service->handle == handle_or_conn_id)) { @@ -503,13 +507,23 @@ STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, ui } break; - case NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE: + case NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN: { - network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; - if ((uuid != NULL && uuid_eq(&chr->char_id.uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { + network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*) items[i]; + if ((uuid != NULL && uuid_eq(&chr->id.uuid, uuid)) || (uuid == NULL && chr->handle == handle_or_conn_id)) { ret = chr; goto NETWORK_BLUETOOTH_ITEM_END; } + size_t descr_len; + mp_obj_t *descr_items; + mp_obj_get_array(chr->descriptors, &descr_len, &descr_items); + for (int k = 0; k < descr_len; k++) { + network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) descr_items[k]; + if ((uuid != NULL && uuid_eq(&descr->id.uuid, uuid)) || (uuid == NULL && descr->handle == handle_or_conn_id)) { + ret = descr; + goto NETWORK_BLUETOOTH_ITEM_END; + } + } } break; @@ -554,13 +568,16 @@ STATIC mp_obj_t network_bluetooth_find_service_in_connection_by_uuid(network_blu return network_bluetooth_item_op(connection->services, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_SERVICE); } -STATIC mp_obj_t network_bluetooth_find_char_by_handle(uint16_t handle) { +STATIC mp_obj_t network_bluetooth_find_char_descr_by_handle(uint16_t handle) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); - return network_bluetooth_item_op(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_CHAR); + return network_bluetooth_item_op(bluetooth->services, NULL, handle, NULL, NETWORK_BLUETOOTH_FIND_CHAR_DESCR); } -STATIC mp_obj_t network_bluetooth_find_char_in_service_by_uuid(network_bluetooth_service_obj_t* service, esp_bt_uuid_t* uuid) { - return network_bluetooth_item_op(service->chars, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_IN_SERVICE); +STATIC mp_obj_t network_bluetooth_find_char_descr_in_char_descr_by_uuid(network_bluetooth_char_descr_obj_t* chr, esp_bt_uuid_t* uuid) { + return network_bluetooth_item_op(chr->descriptors, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN); +} +STATIC mp_obj_t network_bluetooth_find_char_descr_in_service_by_uuid(network_bluetooth_service_obj_t* service, esp_bt_uuid_t* uuid) { + return network_bluetooth_item_op(service->chars, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN); } STATIC mp_obj_t network_bluetooth_del_service_by_uuid(esp_bt_uuid_t* uuid) { @@ -1553,18 +1570,21 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { switch (cbdata.event) { case NETWORK_BLUETOOTH_GATTS_START: - service->started = true; + { + service->started = true; - ITEM_BEGIN(); - size_t len; - mp_obj_t *items; - mp_obj_get_array(service->chars, &len, &items); + ITEM_BEGIN(); + size_t len; + mp_obj_t *items; - for (int i = 0; i < len; i++) { - network_bluetooth_char_obj_t* chr = (network_bluetooth_char_obj_t*) items[i]; - esp_ble_gatts_add_char(service->handle, &chr->char_id.uuid, chr->perm, chr->prop, NULL, NULL); + mp_obj_get_array(service->chars, &len, &items); + + for (int i = 0; i < len; i++) { + network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*) items[i]; + esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + } + ITEM_END(); } - ITEM_END(); break; case NETWORK_BLUETOOTH_GATTS_STOP: @@ -1579,13 +1599,25 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { } break; - case NETWORK_BLUETOOTH_GATTS_ADD_CHAR: + case NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR: { - network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_add_char.service_handle); + network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_add_char_descr.service_handle); if (service != MP_OBJ_NULL) { - network_bluetooth_char_obj_t* chr = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.gatts_add_char.char_uuid); + network_bluetooth_char_descr_obj_t* chr = network_bluetooth_find_char_descr_in_service_by_uuid(service, &cbdata.gatts_add_char_descr.uuid); if (chr != MP_OBJ_NULL) { - chr->handle = cbdata.gatts_add_char.char_handle; + chr->handle = cbdata.gatts_add_char_descr.handle; + ITEM_BEGIN(); + size_t len; + mp_obj_t *items; + mp_obj_get_array(chr->descriptors, &len, &items); + for (int j = 0; j < len; j++) { + network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) items[j]; + NETWORK_BLUETOOTH_DEBUG_PRINTF("Adding descr, service hndl = %04X, perm = %02X\n", service->handle, descr->perm); + network_bluetooth_gatt_id_print(NULL, &descr->id); + NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); + esp_ble_gatts_add_char_descr(service->handle, &descr->id.uuid, descr->perm, NULL, NULL); + } + ITEM_END(); } } } @@ -1595,7 +1627,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { case NETWORK_BLUETOOTH_WRITE: case NETWORK_BLUETOOTH_NOTIFY: { - network_bluetooth_char_obj_t* self = MP_OBJ_NULL; + network_bluetooth_char_descr_obj_t* self = MP_OBJ_NULL; mp_obj_t value = mp_const_none; bool need_rsp = false; @@ -1608,14 +1640,14 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { if (conn != MP_OBJ_NULL) { network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.notify.service_id.id.uuid); if (service != MP_OBJ_NULL) { - self = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.notify.char_id.uuid); + self = network_bluetooth_find_char_descr_in_service_by_uuid(service, &cbdata.notify.char_id.uuid); } } need_rsp = cbdata.notify.need_rsp; break; case NETWORK_BLUETOOTH_READ: - self = network_bluetooth_find_char_by_handle(cbdata.read.handle); + self = network_bluetooth_find_char_descr_by_handle(cbdata.read.handle); if (self != MP_OBJ_NULL) { value = self->value; } @@ -1623,7 +1655,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { break; case NETWORK_BLUETOOTH_WRITE: - self = network_bluetooth_find_char_by_handle(cbdata.write.handle); + self = network_bluetooth_find_char_descr_by_handle(cbdata.write.handle); value = MP_OBJ_NEW_BYTES(cbdata.write.value_len, cbdata.write.value); need_rsp = cbdata.write.need_rsp; FREE(cbdata.write.value); @@ -1749,15 +1781,15 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { if (conn != MP_OBJ_NULL) { network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_char.service_id.id.uuid); if (service != MP_OBJ_NULL) { - network_bluetooth_char_obj_t *chr = m_new_obj(network_bluetooth_char_obj_t); + network_bluetooth_char_descr_obj_t *chr = m_new_obj(network_bluetooth_char_descr_obj_t); chr->base.type = &network_bluetooth_gattc_char_type; - chr->char_id = cbdata.gattc_get_char.char_id; + chr->id = cbdata.gattc_get_char.char_id; chr->prop = cbdata.gattc_get_char.props; - chr->service = service; + chr->parent = service; chr->descriptors = mp_obj_new_list(0, NULL); mp_obj_list_append(service->chars, chr); - esp_ble_gattc_get_descriptor(bluetooth->gattc_interface, conn->conn_id, &service->service_id, &chr->char_id, NULL); + esp_ble_gattc_get_descriptor(bluetooth->gattc_interface, conn->conn_id, &service->service_id, &chr->id, NULL); } } } @@ -1769,12 +1801,12 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { if (conn != MP_OBJ_NULL) { network_bluetooth_service_obj_t* service = network_bluetooth_find_service_in_connection_by_uuid(conn, &cbdata.gattc_get_descr.service_id.id.uuid); if (service != MP_OBJ_NULL) { - network_bluetooth_char_obj_t *chr = network_bluetooth_find_char_in_service_by_uuid(service, &cbdata.gattc_get_descr.char_id.uuid); + network_bluetooth_char_descr_obj_t *chr = network_bluetooth_find_char_descr_in_service_by_uuid(service, &cbdata.gattc_get_descr.char_id.uuid); if (chr != NULL) { - network_bluetooth_descr_obj_t* descr = m_new_obj(network_bluetooth_descr_obj_t); + network_bluetooth_char_descr_obj_t* descr = m_new_obj(network_bluetooth_char_descr_obj_t); descr->base.type = &network_bluetooth_gattc_descr_type; - descr->chr = chr; - descr->descr_id = cbdata.gattc_get_descr.descr_id; + descr->parent = chr; + descr->id = cbdata.gattc_get_descr.descr_id; mp_obj_list_append(chr->descriptors, descr); } } @@ -1860,6 +1892,7 @@ STATIC void network_bluetooth_gattc_event_handler( } break; + case ESP_GATTC_READ_DESCR_EVT: case ESP_GATTC_READ_CHAR_EVT: read_data.value = MALLOC(param->read.value_len); read_data.value_len = param->read.value_len; @@ -1869,6 +1902,7 @@ STATIC void network_bluetooth_gattc_event_handler( } // fallthrough intentional + case ESP_GATTC_WRITE_DESCR_EVT: case ESP_GATTC_WRITE_CHAR_EVT: xQueueSend(read_write_q, &read_data, portMAX_DELAY); break; @@ -1941,12 +1975,13 @@ STATIC void network_bluetooth_gatts_event_handler( } break; + case ESP_GATTS_ADD_CHAR_DESCR_EVT: case ESP_GATTS_ADD_CHAR_EVT: { - cbdata.event = NETWORK_BLUETOOTH_GATTS_ADD_CHAR; - cbdata.gatts_add_char.service_handle = param->add_char.service_handle; - cbdata.gatts_add_char.char_handle = param->add_char.attr_handle; - cbdata.gatts_add_char.char_uuid = param->add_char.char_uuid; + cbdata.event = NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR; + cbdata.gatts_add_char_descr.service_handle = param->add_char.service_handle; + cbdata.gatts_add_char_descr.handle = param->add_char.attr_handle; + cbdata.gatts_add_char_descr.uuid = param->add_char.char_uuid; } break; @@ -2091,23 +2126,51 @@ STATIC void network_bluetooth_adv_updated() { // MicroPython bindings for network_bluetooth // -STATIC void network_bluetooth_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +STATIC void network_bluetooth_char_descr_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + + network_bluetooth_char_descr_obj_t * self = MP_OBJ_TO_PTR(self_in); + + enum { + GATTC_CHAR, + GATTS_CHAR, + GATTC_DESCR, + GATTS_DESCR + } type; + if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gattc_descr_type)) { - network_bluetooth_descr_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "GATTCDescr(uuid = "); - network_bluetooth_gatt_id_print(print, &self->descr_id); + type = GATTC_DESCR; + mp_printf(print, "GATTCDescr"); + } else if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gatts_char_type)) { + type = GATTS_CHAR; + mp_printf(print, "GATTCChar"); + } else if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gattc_char_type)) { + type = GATTC_CHAR; + mp_printf(print, "GATTSChar"); } else { - network_bluetooth_char_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type)) { - mp_printf(print, "GATTSChar(uuid = "); - network_bluetooth_gatt_id_print(print, &self->char_id); + type = GATTS_DESCR; + mp_printf(print, "GATTSDescr"); + } + + mp_printf(print, "(uuid = "); + network_bluetooth_gatt_id_print(print, &self->id); + + switch (type) { + case GATTS_CHAR: mp_printf(print, ", handle = %04X, perm = %02X, value = ", self->handle, self->perm); mp_obj_print_helper(print, self->value, PRINT_REPR); - } else { - mp_printf(print, "GATTCChar(uuid = "); - network_bluetooth_gatt_id_print(print, &self->char_id); - } - mp_printf(print, ", prop = %02X", self->prop); + // intentional fallthrough + + case GATTC_CHAR: + mp_printf(print, ", prop = %02X", self->prop); + break; + + case GATTC_DESCR: + // do nothing + break; + + case GATTS_DESCR: + mp_printf(print, ", handle = %04X", self->handle); + break; } mp_printf(print, ")"); } @@ -2238,15 +2301,15 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { esp_bt_controller_init(&bt_cfg); if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); } if (esp_bluedroid_init() != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "esp_bluedroid_init() failed"); + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_init() failed"); } if (esp_bluedroid_enable() != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "esp_bluedroid_enable() failed"); + mp_raise_msg(&mp_type_OSError, "esp_bluedroid_enable() failed"); } esp_ble_gatts_register_callback(network_bluetooth_gatts_event_handler); @@ -2254,11 +2317,11 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { esp_ble_gap_register_callback(network_bluetooth_gap_event_handler); if (esp_ble_gatts_app_register(0) != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() failed"); + mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() failed"); } - + if (esp_ble_gattc_app_register(1) != ESP_OK) { - mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_register() failed"); + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_register() failed"); } self->state = NETWORK_BLUETOOTH_STATE_INIT; @@ -2616,10 +2679,10 @@ STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_callback_obj, 1, 3, network_bluetooth_callback); -STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t network_bluetooth_char_descr_callback(size_t n_args, const mp_obj_t *args) { mp_obj_t ret; - network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) args[0]; - network_bluetooth_service_obj_t *service = self->service; + network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) args[0]; + network_bluetooth_service_obj_t *service = self->parent; network_bluetooth_connection_obj_t *connection = service->connection; network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); @@ -2630,11 +2693,11 @@ STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *a if (n_args > 1 && MP_OBJ_IS_TYPE(self, &network_bluetooth_gattc_char_type)) { assert(connection != MP_OBJ_NULL); if (self->callback != mp_const_none) { - if (esp_ble_gattc_register_for_notify(bluetooth->gattc_interface, connection->bda, &service->service_id, &self->char_id) != ESP_OK) { + if (esp_ble_gattc_register_for_notify(bluetooth->gattc_interface, connection->bda, &service->service_id, &self->id) != ESP_OK) { goto NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR; } } else { - if (esp_ble_gattc_unregister_for_notify(bluetooth->gattc_interface, connection->bda, &service->service_id, &self->char_id) != ESP_OK) { + if (esp_ble_gattc_unregister_for_notify(bluetooth->gattc_interface, connection->bda, &service->service_id, &self->id) != ESP_OK) { goto NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR; } } @@ -2646,12 +2709,12 @@ STATIC mp_obj_t network_bluetooth_char_callback(size_t n_args, const mp_obj_t *a mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_(un)register_for_notify() call failed"); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_callback_obj, 1, 3, network_bluetooth_char_callback); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_descr_callback_obj, 1, 3, network_bluetooth_char_descr_callback); STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) { bool is_chr; - network_bluetooth_char_obj_t *chr; - network_bluetooth_descr_obj_t *descr; + network_bluetooth_char_descr_obj_t *chr; + network_bluetooth_char_descr_obj_t *descr; esp_err_t result; if (MP_OBJ_IS_TYPE(args[0], &network_bluetooth_gattc_char_type)) { @@ -2661,10 +2724,10 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) } else { is_chr = false; descr = MP_OBJ_TO_PTR(args[0]); - chr = descr->chr; + chr = descr->parent; } - network_bluetooth_service_obj_t *service = chr->service; + network_bluetooth_service_obj_t *service = chr->parent; network_bluetooth_connection_obj_t *connection = service->connection; network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); @@ -2681,9 +2744,9 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) xQueueReset(read_write_q); if (is_chr) { - result = esp_ble_gattc_read_char(bluetooth->gattc_interface, connection->conn_id, &service->service_id, &chr->char_id, ESP_GATT_AUTH_REQ_NONE); + result = esp_ble_gattc_read_char(bluetooth->gattc_interface, connection->conn_id, &service->service_id, &chr->id, ESP_GATT_AUTH_REQ_NONE); } else { - result = esp_ble_gattc_read_char_descr(bluetooth->gattc_interface, connection->conn_id, &service->service_id, &chr->char_id, &descr->descr_id, ESP_GATT_AUTH_REQ_NONE); + result = esp_ble_gattc_read_char_descr(bluetooth->gattc_interface, connection->conn_id, &service->service_id, &chr->id, &descr->id, ESP_GATT_AUTH_REQ_NONE); } if (result != ESP_OK) { @@ -2697,7 +2760,7 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) ticks = (TickType_t)timeout * 1000.0 / portTICK_PERIOD_MS; } } - + if (xQueueReceive(read_write_q, &read_data, ticks) == pdTRUE) { mp_obj_t res = MP_OBJ_NEW_BYTES(read_data.value_len, read_data.value); @@ -2708,10 +2771,10 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_read_obj, 1, 2, network_bluetooth_char_read); -STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { +STATIC mp_obj_t network_bluetooth_char_descr_write(mp_obj_t self_in, mp_obj_t value) { bool is_chr; - network_bluetooth_char_obj_t *chr; - network_bluetooth_descr_obj_t *descr; + network_bluetooth_char_descr_obj_t *chr; + network_bluetooth_char_descr_obj_t *descr; esp_err_t result; if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gattc_char_type)) { @@ -2721,10 +2784,10 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { } else { is_chr = false; descr = MP_OBJ_TO_PTR(self_in); - chr = descr->chr; + chr = descr->parent; } - network_bluetooth_service_obj_t *service = chr->service; + network_bluetooth_service_obj_t *service = chr->parent; network_bluetooth_connection_obj_t *connection = service->connection; network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); @@ -2750,7 +2813,7 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { bluetooth->gattc_interface, connection->conn_id, &service->service_id, - &chr->char_id, + &chr->id, buf.len, buf.buf, ESP_GATT_WRITE_TYPE_NO_RSP, @@ -2761,8 +2824,8 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { bluetooth->gattc_interface, connection->conn_id, &service->service_id, - &chr->char_id, - &descr->descr_id, + &chr->id, + &descr->id, buf.len, buf.buf, ESP_GATT_WRITE_TYPE_NO_RSP, @@ -2776,7 +2839,7 @@ STATIC mp_obj_t network_bluetooth_char_write(mp_obj_t self_in, mp_obj_t value) { return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_char_write_obj, network_bluetooth_char_write); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_char_descr_write_obj, network_bluetooth_char_descr_write); STATIC mp_obj_t network_bluetooth_char_notify_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args, bool need_confirm) { @@ -2784,7 +2847,7 @@ STATIC mp_obj_t network_bluetooth_char_notify_helper(size_t n_args, const mp_obj if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); } - network_bluetooth_char_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); + network_bluetooth_char_descr_obj_t* self = MP_OBJ_TO_PTR(pos_args[0]); enum {ARG_value}; static const mp_arg_t allowed_args[] = { @@ -2865,7 +2928,7 @@ STATIC mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, si return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { +STATIC mp_obj_t network_bluetooth_char_descr_make_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { enum {ARG_uuid, ARG_value, ARG_perm, ARG_prop}; static const mp_arg_t allowed_args[] = { @@ -2875,7 +2938,15 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m { MP_QSTR_prop, MP_ARG_INT, {.u_int = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - network_bluetooth_service_obj_t* service = MP_OBJ_TO_PTR(pos_args[0]); + + network_bluetooth_service_obj_t* service = MP_OBJ_NULL; + network_bluetooth_char_descr_obj_t* chr = MP_OBJ_NULL; + + if (MP_OBJ_IS_TYPE(pos_args[0], &network_bluetooth_gatts_service_type)) { // Make new descriptor + service = MP_OBJ_TO_PTR(pos_args[0]); + } else { // Make new char + chr = MP_OBJ_TO_PTR(pos_args[0]); + } mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -2883,31 +2954,44 @@ STATIC mp_obj_t network_bluetooth_characteristic_make_new(size_t n_args, const m esp_bt_uuid_t uuid; parse_uuid(args[ARG_uuid].u_obj, &uuid); - network_bluetooth_char_obj_t *self = network_bluetooth_find_char_in_service_by_uuid(service, &uuid); + + network_bluetooth_char_descr_obj_t *self = MP_OBJ_NULL; + if (service != MP_OBJ_NULL) { + self = network_bluetooth_find_char_descr_in_service_by_uuid(service, &uuid); + } else { + self = network_bluetooth_find_char_descr_in_char_descr_by_uuid(chr, &uuid); + } if (self != MP_OBJ_NULL) { return MP_OBJ_FROM_PTR(self); } - self = m_new_obj(network_bluetooth_char_obj_t); - self->base.type = &network_bluetooth_gatts_char_type; - self->service = service; + self = m_new_obj(network_bluetooth_char_descr_obj_t); self->callback = mp_const_none; - self->char_id.uuid = uuid; + self->id.uuid = uuid; self->value = args[ARG_value].u_obj; self->perm = args[ARG_perm].u_int; self->prop = args[ARG_prop].u_int; + self->descriptors = mp_obj_new_list(0, NULL); ITEM_BEGIN(); - mp_obj_list_append(service->chars, self); + if (service != MP_OBJ_NULL) { + self->base.type = &network_bluetooth_gatts_char_type; + self->parent = service; + mp_obj_list_append(service->chars, self); + } else { + self->base.type = &network_bluetooth_gatts_descr_type; + self->parent = chr; + mp_obj_list_append(chr->descriptors, self); + } ITEM_END(); return MP_OBJ_FROM_PTR(self); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_characteristic_make_new_obj, 1, network_bluetooth_characteristic_make_new); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_descr_make_new_obj, 1, network_bluetooth_char_descr_make_new); STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); @@ -2924,7 +3008,18 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { return mp_const_none; } - mp_int_t numChars = mp_obj_get_int(mp_obj_len(self->chars)); + int numChars = mp_obj_get_int(mp_obj_len(self->chars)); + int numDescrs = 0; + + size_t index; + mp_obj_t *items; + mp_obj_get_array(bluetooth->services, &index, &items); + while (index--) { + network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*)items[index]; + numDescrs += mp_obj_get_int(mp_obj_len(chr->descriptors)); + } + + uint32_t then = mp_hal_ticks_ms(); // Wait for registration @@ -2941,7 +3036,8 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { // 1 for 2800/2801 Service declaration // 1x for each 2803 Char declaration // 1x for each Char desc declaration --- not used - esp_ble_gatts_create_service(bluetooth->gatts_interface, &self->service_id, 1 + numChars * 2); + // 1x for each descriptor? Not sure + esp_ble_gatts_create_service(bluetooth->gatts_interface, &self->service_id, 1 + numChars * 2 + numDescrs); return mp_const_none; } @@ -2982,43 +3078,60 @@ STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); STATIC void network_bluetooth_descr_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - network_bluetooth_descr_obj_t* self = (network_bluetooth_descr_obj_t*) self_in; + network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) self_in; + bool is_gatts = MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gatts_descr_type); + if (!check_locals_dict(self, attr, dest)) { switch (attr) { case MP_QSTR_char: - dest[0] = self->chr; + dest[0] = self->parent; break; case MP_QSTR_uuid: { esp_bt_uuid_t uuid128; - uuid_to_uuid128(&self->descr_id.uuid, &uuid128); + uuid_to_uuid128(&self->id.uuid, &uuid128); dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); } break; + + case MP_QSTR_value: + if (is_gatts) { + dest[0] = self->value; + } + break; } } } STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - network_bluetooth_char_obj_t* self = (network_bluetooth_char_obj_t*) self_in; + network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) self_in; if (!check_locals_dict(self, attr, dest)) { - if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type)) { + bool is_gatts = MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type); - switch (attr) { - case MP_QSTR_service: - dest[0] = self->service; - break; - case MP_QSTR_uuid: - { - esp_bt_uuid_t uuid128; - uuid_to_uuid128(&self->char_id.uuid, &uuid128); - dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); - } - break; + switch (attr) { + case MP_QSTR_Descr: + if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type)) { + dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_char_descr_make_new_obj); + dest[1] = self; + } + break; - case MP_QSTR_value: + case MP_QSTR_service: + dest[0] = self->parent; + break; + + case MP_QSTR_uuid: + { + esp_bt_uuid_t uuid128; + uuid_to_uuid128(&self->id.uuid, &uuid128); + dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); + } + break; + + case MP_QSTR_value: + if (is_gatts) { if (dest[0] == MP_OBJ_NULL) { // load dest[0] = self->value; } else if (dest[1] != MP_OBJ_NULL) { // store @@ -3026,33 +3139,25 @@ STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *d self->value = dest[1]; dest[0] = MP_OBJ_NULL; } - } - } else { - switch (attr) { - case MP_QSTR_service: - dest[0] = self->service; - break; + } + break; - case MP_QSTR_descriptors: - dest[0] = self->descriptors; - break; + case MP_QSTR_descriptors: + dest[0] = self->descriptors; + break; - case MP_QSTR_uuid: - { - esp_bt_uuid_t uuid128; - uuid_to_uuid128(&self->char_id.uuid, &uuid128); - dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); - } - break; - case MP_QSTR_instance: - dest[0] = MP_OBJ_NEW_SMALL_INT(self->char_id.inst_id); - break; + case MP_QSTR_instance: + if (!is_gatts) { + dest[0] = MP_OBJ_NEW_SMALL_INT(self->id.inst_id); + } + break; - case MP_QSTR_prop: + case MP_QSTR_prop: + if (!is_gatts) { dest[0] = MP_OBJ_NEW_SMALL_INT(self->prop); - break; - } + } + break; } } } @@ -3069,7 +3174,7 @@ STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_service_type)) { switch (attr) { case MP_QSTR_Char: - dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_characteristic_make_new_obj); + dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_char_descr_make_new_obj); dest[1] = self; break; } @@ -3334,7 +3439,8 @@ const mp_obj_type_t network_bluetooth_gattc_service_type = { // STATIC const mp_rom_map_elem_t network_bluetooth_gatts_char_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_Descr), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_descr_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&network_bluetooth_char_indicate_obj) }, { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&network_bluetooth_char_notify_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler @@ -3347,7 +3453,7 @@ STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gatts_char_locals_dict, network_bl const mp_obj_type_t network_bluetooth_gatts_char_type = { { &mp_type_type }, .name = MP_QSTR_Char, - .print = network_bluetooth_characteristic_print, + .print = network_bluetooth_char_descr_print, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gatts_char_locals_dict, .attr = network_bluetooth_char_attr, }; @@ -3357,9 +3463,9 @@ const mp_obj_type_t network_bluetooth_gatts_char_type = { // STATIC const mp_rom_map_elem_t network_bluetooth_gattc_char_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_descr_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&network_bluetooth_char_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_descr_write_obj) }, { MP_ROM_QSTR(MP_QSTR_service), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_descriptors), NULL }, // handled by attr handler @@ -3370,7 +3476,7 @@ STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_char_locals_dict, network_bl const mp_obj_type_t network_bluetooth_gattc_char_type = { { &mp_type_type }, .name = MP_QSTR_Char, - .print = network_bluetooth_characteristic_print, + .print = network_bluetooth_char_descr_print, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gattc_char_locals_dict, .attr = network_bluetooth_char_attr, }; @@ -3381,7 +3487,7 @@ const mp_obj_type_t network_bluetooth_gattc_char_type = { STATIC const mp_rom_map_elem_t network_bluetooth_gattc_descr_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&network_bluetooth_char_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_descr_write_obj) }, { MP_ROM_QSTR(MP_QSTR_char), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler }; @@ -3390,8 +3496,29 @@ STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_descr_locals_dict, network_b const mp_obj_type_t network_bluetooth_gattc_descr_type = { { &mp_type_type }, - .name = MP_QSTR_Descr, - .print = network_bluetooth_characteristic_print, + .name = MP_QSTR_GATTCDescr, + .print = network_bluetooth_char_descr_print, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gattc_descr_locals_dict, .attr = network_bluetooth_descr_attr, }; + +// +// GATTS DESCR OBJECTS +// + +STATIC const mp_rom_map_elem_t network_bluetooth_gatts_descr_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_descr_callback_obj) }, + { MP_ROM_QSTR(MP_QSTR_char), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_value), NULL }, // handled by attr handler +}; +STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gatts_descr_locals_dict, network_bluetooth_gatts_descr_locals_dict_table); + +const mp_obj_type_t network_bluetooth_gatts_descr_type = { + { &mp_type_type }, + .name = MP_QSTR_GATTSDescr, + .print = network_bluetooth_char_descr_print, + .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gatts_descr_locals_dict, + .attr = network_bluetooth_descr_attr, +}; + From e4817d019ca56250e3556823eab4dec2f94f6b2f Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 19 May 2017 10:26:50 -0700 Subject: [PATCH 69/98] esp32/network_bluetooth.c: descriptors --> descrs, removed debugging prints --- esp32/network_bluetooth.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 3a3362269..da37937ad 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -249,7 +249,7 @@ typedef struct { esp_gatt_id_t id; // common esp_gatt_char_prop_t prop; // common - mp_obj_t descriptors; // GATTC + mp_obj_t descrs; // GATTC esp_gatt_perm_t perm; // GATTS @@ -484,7 +484,7 @@ STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, ui } size_t descr_len; mp_obj_t *descr_items; - mp_obj_get_array(chr->descriptors, &descr_len, &descr_items); + mp_obj_get_array(chr->descrs, &descr_len, &descr_items); for (int k = 0; k < descr_len; k++) { network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) descr_items[k]; if ((uuid != NULL && uuid_eq(&descr->id.uuid, uuid)) || (uuid == NULL && descr->handle == handle_or_conn_id)) { @@ -516,7 +516,7 @@ STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, ui } size_t descr_len; mp_obj_t *descr_items; - mp_obj_get_array(chr->descriptors, &descr_len, &descr_items); + mp_obj_get_array(chr->descrs, &descr_len, &descr_items); for (int k = 0; k < descr_len; k++) { network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) descr_items[k]; if ((uuid != NULL && uuid_eq(&descr->id.uuid, uuid)) || (uuid == NULL && descr->handle == handle_or_conn_id)) { @@ -574,7 +574,7 @@ STATIC mp_obj_t network_bluetooth_find_char_descr_by_handle(uint16_t handle) { } STATIC mp_obj_t network_bluetooth_find_char_descr_in_char_descr_by_uuid(network_bluetooth_char_descr_obj_t* chr, esp_bt_uuid_t* uuid) { - return network_bluetooth_item_op(chr->descriptors, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN); + return network_bluetooth_item_op(chr->descrs, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN); } STATIC mp_obj_t network_bluetooth_find_char_descr_in_service_by_uuid(network_bluetooth_service_obj_t* service, esp_bt_uuid_t* uuid) { return network_bluetooth_item_op(service->chars, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN); @@ -1609,12 +1609,9 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { ITEM_BEGIN(); size_t len; mp_obj_t *items; - mp_obj_get_array(chr->descriptors, &len, &items); + mp_obj_get_array(chr->descrs, &len, &items); for (int j = 0; j < len; j++) { network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) items[j]; - NETWORK_BLUETOOTH_DEBUG_PRINTF("Adding descr, service hndl = %04X, perm = %02X\n", service->handle, descr->perm); - network_bluetooth_gatt_id_print(NULL, &descr->id); - NETWORK_BLUETOOTH_DEBUG_PRINTF("\n"); esp_ble_gatts_add_char_descr(service->handle, &descr->id.uuid, descr->perm, NULL, NULL); } ITEM_END(); @@ -1786,7 +1783,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { chr->id = cbdata.gattc_get_char.char_id; chr->prop = cbdata.gattc_get_char.props; chr->parent = service; - chr->descriptors = mp_obj_new_list(0, NULL); + chr->descrs = mp_obj_new_list(0, NULL); mp_obj_list_append(service->chars, chr); esp_ble_gattc_get_descriptor(bluetooth->gattc_interface, conn->conn_id, &service->service_id, &chr->id, NULL); @@ -1807,7 +1804,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { descr->base.type = &network_bluetooth_gattc_descr_type; descr->parent = chr; descr->id = cbdata.gattc_get_descr.descr_id; - mp_obj_list_append(chr->descriptors, descr); + mp_obj_list_append(chr->descrs, descr); } } } @@ -2974,7 +2971,7 @@ STATIC mp_obj_t network_bluetooth_char_descr_make_new(size_t n_args, const mp_ob self->value = args[ARG_value].u_obj; self->perm = args[ARG_perm].u_int; self->prop = args[ARG_prop].u_int; - self->descriptors = mp_obj_new_list(0, NULL); + self->descrs = mp_obj_new_list(0, NULL); ITEM_BEGIN(); if (service != MP_OBJ_NULL) { @@ -2984,7 +2981,7 @@ STATIC mp_obj_t network_bluetooth_char_descr_make_new(size_t n_args, const mp_ob } else { self->base.type = &network_bluetooth_gatts_descr_type; self->parent = chr; - mp_obj_list_append(chr->descriptors, self); + mp_obj_list_append(chr->descrs, self); } ITEM_END(); @@ -3016,7 +3013,7 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { mp_obj_get_array(bluetooth->services, &index, &items); while (index--) { network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*)items[index]; - numDescrs += mp_obj_get_int(mp_obj_len(chr->descriptors)); + numDescrs += mp_obj_get_int(mp_obj_len(chr->descrs)); } @@ -3142,8 +3139,8 @@ STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *d } break; - case MP_QSTR_descriptors: - dest[0] = self->descriptors; + case MP_QSTR_descrs: + dest[0] = self->descrs; break; @@ -3468,7 +3465,7 @@ STATIC const mp_rom_map_elem_t network_bluetooth_gattc_char_locals_dict_table[] { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_descr_write_obj) }, { MP_ROM_QSTR(MP_QSTR_service), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_descriptors), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_descrs), NULL }, // handled by attr handler }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_char_locals_dict, network_bluetooth_gattc_char_locals_dict_table); From e51467b2d46203f274a8cd186447e1c2389a90d4 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 19 May 2017 10:52:59 -0700 Subject: [PATCH 70/98] esp32/network_bluetooth.c: Fixed print output for descriptors, removed "prop" from ctor --- esp32/network_bluetooth.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index da37937ad..3dd2387f7 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2139,10 +2139,10 @@ STATIC void network_bluetooth_char_descr_print(const mp_print_t *print, mp_obj_t mp_printf(print, "GATTCDescr"); } else if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gatts_char_type)) { type = GATTS_CHAR; - mp_printf(print, "GATTCChar"); + mp_printf(print, "GATTSChar"); } else if (MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gattc_char_type)) { type = GATTC_CHAR; - mp_printf(print, "GATTSChar"); + mp_printf(print, "GATTCChar"); } else { type = GATTS_DESCR; mp_printf(print, "GATTSDescr"); @@ -2151,24 +2151,14 @@ STATIC void network_bluetooth_char_descr_print(const mp_print_t *print, mp_obj_t mp_printf(print, "(uuid = "); network_bluetooth_gatt_id_print(print, &self->id); - switch (type) { - case GATTS_CHAR: - mp_printf(print, ", handle = %04X, perm = %02X, value = ", self->handle, self->perm); - mp_obj_print_helper(print, self->value, PRINT_REPR); - // intentional fallthrough - - case GATTC_CHAR: + if (type != GATTC_DESCR) { + mp_printf(print, ", handle = %04X, perm = %02X, value = ", self->handle, self->perm); + mp_obj_print_helper(print, self->value, PRINT_REPR); + if (type == GATTC_CHAR) { mp_printf(print, ", prop = %02X", self->prop); - break; - - case GATTC_DESCR: - // do nothing - break; - - case GATTS_DESCR: - mp_printf(print, ", handle = %04X", self->handle); - break; + } } + mp_printf(print, ")"); } @@ -2928,10 +2918,12 @@ STATIC mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, si STATIC mp_obj_t network_bluetooth_char_descr_make_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { enum {ARG_uuid, ARG_value, ARG_perm, ARG_prop}; - static const mp_arg_t allowed_args[] = { + mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_value, MP_ARG_OBJ, {.u_obj = mp_const_none }}, { MP_QSTR_perm, MP_ARG_INT, {.u_int = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE } }, + // "prop" is disabled for descriptors, below + // Ensure the index of "prop" is updated if this list changes { MP_QSTR_prop, MP_ARG_INT, {.u_int = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -2939,10 +2931,12 @@ STATIC mp_obj_t network_bluetooth_char_descr_make_new(size_t n_args, const mp_ob network_bluetooth_service_obj_t* service = MP_OBJ_NULL; network_bluetooth_char_descr_obj_t* chr = MP_OBJ_NULL; - if (MP_OBJ_IS_TYPE(pos_args[0], &network_bluetooth_gatts_service_type)) { // Make new descriptor + if (MP_OBJ_IS_TYPE(pos_args[0], &network_bluetooth_gatts_service_type)) { // Make new char service = MP_OBJ_TO_PTR(pos_args[0]); - } else { // Make new char + } else { // Make new descriptor chr = MP_OBJ_TO_PTR(pos_args[0]); + // Disable the "prop" argument + allowed_args[3].qst = MP_QSTR_; } mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); From 910a2d8c647a34dcc59b3006a607fd1583f13f97 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 19 May 2017 11:02:36 -0700 Subject: [PATCH 71/98] updated docs for GATTS Descr --- esp32/bluetooth_docs.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index 1699a4e26..402f0c8e0 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -199,7 +199,6 @@ For `bluetooth.READ` events, the return value of the callback is what is returne In the absence of a callback, then the characteristic value is return for a read, and it is updated for a write. - `char.indicate()` Send an indicate value. `` is `string`, `bytearray`, `bytes` or `None`. `char.notify()` Send a notify value. `` is `string`, `bytearray`, `bytes` or `None`. @@ -208,8 +207,19 @@ In the absence of a callback, then the characteristic value is return for a read `char.value` Get or set the characteristic value. -`char.service` Get the service this characteristic is attached to. +`char.service` Get the parent service. + +`char.Descr(uuid, value = None, perm = bluetooth.PERM_READ | bluetooth.PERM_WRITE)` Create a new descriptor for a characteristic. + +### GATTSDescr objects + +`descr.uuid` Get the descriptor UUID. + +`descr.value` Get or set the value. + +`descr.char` Get the parent characteristic. +`descr.callback(, )` See `char.callback()`, above. ## GATTC From c7f7574106671991800b60d4b8a91fc03a0f8729 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 24 May 2017 08:55:51 -0700 Subject: [PATCH 72/98] esp32/network_bluetooth.c: Added more parameters to scan_start New parameters are defaulted, and shouldn't affect existing code --- esp32/network_bluetooth.c | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 3dd2387f7..e612828e8 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2583,31 +2583,52 @@ STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* return tuple; } -STATIC mp_obj_t network_bluetooth_scan_start(mp_obj_t self_in, mp_obj_t timeout_arg) { - network_bluetooth_obj_t *bluetooth = MP_OBJ_TO_PTR(self_in); +STATIC mp_obj_t network_bluetooth_scan_start(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { + network_bluetooth_obj_t *bluetooth = MP_OBJ_TO_PTR(pos_args[0]); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { mp_raise_msg(&mp_type_OSError, "bluetooth is deinit"); } + enum { + // params + ARG_timeout, + ARG_scan_type, + ARG_own_addr_type, + ARG_scan_filter_policy, + ARG_scan_interval, + ARG_scan_window + }; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_scan_type, MP_ARG_INT, {.u_int = BLE_SCAN_TYPE_ACTIVE} }, + { MP_QSTR_own_addr_type, MP_ARG_INT, {.u_int = BLE_ADDR_TYPE_PUBLIC} }, + { MP_QSTR_scan_filter_policy, MP_ARG_INT, {.u_int = BLE_SCAN_FILTER_ALLOW_ALL }}, + { MP_QSTR_scan_interval, MP_ARG_INT, {.u_int = 0x50 }}, + { MP_QSTR_scan_window, MP_ARG_INT, {.u_int = 0x30 }}, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + if (bluetooth->scanning) { mp_raise_msg(&mp_type_OSError, "already scanning"); } - mp_int_t timeout = mp_obj_get_int(timeout_arg); - static esp_ble_scan_params_t params = { - .scan_type = BLE_SCAN_TYPE_ACTIVE, - .own_addr_type = BLE_ADDR_TYPE_PUBLIC, - .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, - .scan_interval = 0x50, - .scan_window = 0x30 + esp_ble_scan_params_t params = { + .scan_type = args[ARG_scan_type].u_int, + .own_addr_type = args[ARG_own_addr_type].u_int, + .scan_filter_policy = args[ARG_scan_filter_policy].u_int, + .scan_interval = args[ARG_scan_interval].u_int, + .scan_window = args[ARG_scan_window].u_int }; assert(esp_ble_gap_set_scan_params(¶ms) == ESP_OK); - assert(esp_ble_gap_start_scanning(timeout) == ESP_OK); + assert(esp_ble_gap_start_scanning((uint32_t)args[ARG_timeout].u_int) == ESP_OK); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_scan_start_obj, network_bluetooth_scan_start); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_scan_start_obj, 1, network_bluetooth_scan_start); STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { (void)self_in; @@ -3296,7 +3317,8 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { // esp_ble_addr_type_t { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_PUBLIC) }, { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RANDOM) }, - { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_PUBLIC), MP_ROM_INT(BLE_ADDR_TYPE_RPA_PUBLIC) }, + { MP_ROM_QSTR(MP_QSTR_BLE_ADDR_TYPE_RPA_RANDOM), MP_ROM_INT(BLE_ADDR_TYPE_RPA_RANDOM) }, // esp_ble_adv_channel_t { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_37), MP_ROM_INT(ADV_CHNL_37) }, @@ -3313,6 +3335,16 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_DMT_HOST_SPT), MP_ROM_INT(ESP_BLE_ADV_FLAG_DMT_HOST_SPT) }, { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_NON_LIMIT_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_NON_LIMIT_DISC) }, + // Scan param constants + { MP_ROM_QSTR(MP_QSTR_SCAN_TYPE_PASSIVE), MP_ROM_INT(BLE_SCAN_TYPE_PASSIVE) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_TYPE_ACTIVE), MP_ROM_INT(BLE_SCAN_TYPE_ACTIVE) }, + + { MP_ROM_QSTR(MP_QSTR_SCAN_FILTER_ALLOW_ALL), MP_ROM_INT(BLE_SCAN_FILTER_ALLOW_ALL) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_FILTER_ALLOW_ONLY_WLST), MP_ROM_INT(BLE_SCAN_FILTER_ALLOW_ONLY_WLST) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_FILTER_ALLOW_UND_RPA_DIR), MP_ROM_INT(BLE_SCAN_FILTER_ALLOW_UND_RPA_DIR) }, + { MP_ROM_QSTR(MP_QSTR_SCAN_FILTER_ALLOW_WLIST_PRA_DIR), MP_ROM_INT(BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR) }, + + // exp_gatt_perm_t { MP_ROM_QSTR(MP_QSTR_PERM_READ), MP_ROM_INT(ESP_GATT_PERM_READ) }, { MP_ROM_QSTR(MP_QSTR_PERM_READ_ENCRYPTED), MP_ROM_INT(ESP_GATT_PERM_READ_ENCRYPTED) }, From 12c22d15b5650b27c7df56324c3ba11d0fa7aee1 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 24 May 2017 08:58:25 -0700 Subject: [PATCH 73/98] esp32/bluetoot_docs.md: Updated for scan_start --- esp32/bluetooth_docs.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index 402f0c8e0..6683f8f94 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -123,7 +123,26 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, * For `bluetooth.SCAN_CMPL` this will be `None`. 4. The `)` GATTC - begin scanning for hosts. +`bluetooth.scan_start(timeout, scan_type = bluetooth.SCAN_TYPE_ACTIVE, own_addr_type = bluetooth.BLE_ADDR_TYPE_PUBLIC, scan_filter_policy = SCAN_FILTER_ALLOW_ALL, scan_interval = 0x50, scan_window = 0x30)` GATTC - begin scanning for hosts. + + +`scan_type` is one of: +* `network.SCAN_TYPE_ACTIVE` +* `network.SCAN_TYPE_PASSIVE` + +`own_addr_type` is one of: +* `network.BLE_ADDR_TYPE_PUBLIC` +* `network.BLE_ADDR_TYPE_RANDOM` +* `network.BLE_ADDR_TYPE_RPA_PUBLIC` +* `network.BLE_ADDR_TYPE_RPA_RANDOM` + +`scan_filter_policy` is one of: +* `network.SCAN_FILTER_ALLOW_ALL` +* `network.SCAN_FILTER_ALLOW_ONLY_WLST` +* `network.SCAN_FILTER_ALLOW_UND_RPA_DIR` +* `network.SCAN_FILTER_ALLOW_WLIST_PRA_DIR` + + `bluetooth.scan_stop()` GATTC - terminate scanning early. If called before the scan timeout, you will _not_ receive a `bluetooth.SCAN_CMPL` event. From 1d2a575264a202394e61d80e5d0d795733d8171b Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 30 May 2017 11:04:44 -0700 Subject: [PATCH 74/98] esp32/network_bluetooth.c: Fix, GATTS Descr w/ multiple chars The IDF API for adding descriptors only allows for specifying a _service_ handle. Because of this, you must do this: 1) Add service 2) Add charactteristic 3) Add char descriptor(s) 4) Add _next_ characteristic 5) goto 3 --- esp32/network_bluetooth.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index e612828e8..173e24238 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -259,6 +259,8 @@ typedef struct { mp_obj_t callback; // common mp_obj_t callback_userdata; // common + mp_obj_t next; // next charactersitic to add when service is started + } network_bluetooth_char_descr_obj_t; // "Bluetooth" Declaration @@ -1576,12 +1578,28 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { ITEM_BEGIN(); size_t len; mp_obj_t *items; + network_bluetooth_char_descr_obj_t* prev = MP_OBJ_NULL; mp_obj_get_array(service->chars, &len, &items); + // Only start first + // characteristic, and link chars together + // for easier chaining of starts. + // + // This is because the IDF only allows adding + // descriptors to the last-added charactersitic, + // so we have to add new chars after adding chars + // for (int i = 0; i < len; i++) { network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*) items[i]; - esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + if (i == 0) { + esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + } + chr->next = MP_OBJ_NULL; + if (prev != MP_OBJ_NULL) { + prev->next = chr; + } + prev = chr; } ITEM_END(); } @@ -1614,6 +1632,10 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) items[j]; esp_ble_gatts_add_char_descr(service->handle, &descr->id.uuid, descr->perm, NULL, NULL); } + chr = chr->next; // Now add the next characteristic + if (chr != MP_OBJ_NULL) { + esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + } ITEM_END(); } } From 1702ced7325401204fa230942fb74c513358023b Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 31 May 2017 08:51:00 -0700 Subject: [PATCH 75/98] esp32/bluetooth_docs.md: Fixed some incorrect information WRT scan --- esp32/bluetooth_docs.md | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index 6683f8f94..fbba5e481 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -31,7 +31,7 @@ Note that these defaults are set when you create the Bluetooth object. You need bluetooth.ble_settings(int_min = 1280, int_max = 1280, adv_type = bluetooth.ADV_TYPE_IND, own_addr_type = bluetooth.BLE_ADDR_TYPE_PUBLIC, - peer_addr = bytes([0] * 6), + peer_addr = bytes([0] * 6), peer_addr_type = bluetooth.BLE_ADDR_TYPE_PUBLIC, channel_map = bluetooth.ADV_CHNL_ALL, filter_policy = blueooth.ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, @@ -125,22 +125,23 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, `bluetooth.scan_start(timeout, scan_type = bluetooth.SCAN_TYPE_ACTIVE, own_addr_type = bluetooth.BLE_ADDR_TYPE_PUBLIC, scan_filter_policy = SCAN_FILTER_ALLOW_ALL, scan_interval = 0x50, scan_window = 0x30)` GATTC - begin scanning for hosts. +`timeout` is in seconds. `scan_type` is one of: -* `network.SCAN_TYPE_ACTIVE` -* `network.SCAN_TYPE_PASSIVE` +* `bluetooth.SCAN_TYPE_ACTIVE` +* `bluetooth.SCAN_TYPE_PASSIVE` `own_addr_type` is one of: -* `network.BLE_ADDR_TYPE_PUBLIC` -* `network.BLE_ADDR_TYPE_RANDOM` -* `network.BLE_ADDR_TYPE_RPA_PUBLIC` -* `network.BLE_ADDR_TYPE_RPA_RANDOM` +* `bluetooth.BLE_ADDR_TYPE_PUBLIC` +* `bluetooth.BLE_ADDR_TYPE_RANDOM` +* `bluetooth.BLE_ADDR_TYPE_RPA_PUBLIC` +* `bluetooth.BLE_ADDR_TYPE_RPA_RANDOM` `scan_filter_policy` is one of: -* `network.SCAN_FILTER_ALLOW_ALL` -* `network.SCAN_FILTER_ALLOW_ONLY_WLST` -* `network.SCAN_FILTER_ALLOW_UND_RPA_DIR` -* `network.SCAN_FILTER_ALLOW_WLIST_PRA_DIR` +* `bluetooth.SCAN_FILTER_ALLOW_ALL` +* `bluetooth.SCAN_FILTER_ALLOW_ONLY_WLST` +* `bluetooth.SCAN_FILTER_ALLOW_UND_RPA_DIR` +* `bluetooth.SCAN_FILTER_ALLOW_WLIST_PRA_DIR` @@ -212,7 +213,7 @@ GATTSChar objects are created by calling the `service.Char()` constructor, and t * `bluetooth.READ` when a GATTC issues a read command for that characteristic. * `bluetooth.WRITE` when a GATTC issues a write command for that characteristic. 3. The value. For `bluetooth.READ`, this is the current stored value of the characteristic. For `bluetooth.WRITE` this is the value written by the GATTC. -4. the `` +4. the `` For `bluetooth.READ` events, the return value of the callback is what is returned to the GATTC. When there is a callback for a characteristic, the characteristic value is not modified or otherwise used. It's up to the callback to do whatever is necessary with the write data, or to return the proper data for a read. @@ -270,7 +271,7 @@ When the callback is called, it will be called with 4 parameters: 2. The event that occured, which is: * `bluetooth.NOTIFY` when a GATTS issues a notification for the characteristic 3. The value of the notify/indicate -4. the `` +4. the `` `char.descriptors` Returns a list of [`GATTCDescr`](#gattcdescr-objects) associated with this characteristic. @@ -324,7 +325,7 @@ def bcb(b,e,d,u): if complete: complete = False found = {} - + adx, name = d if adx not in found: found[adx] = name @@ -367,7 +368,7 @@ def hr(bda): service = ([s for s in conn.services if s.uuid[0:4] == b'\x00\x00\x18\x0d'] + [None])[0] if service: char = ([c for c in service.chars if c.uuid[0:4] == b'\x00\x00\x2a\x37'] + [None])[0] - if char: + if char: descr = ([d for d in char.descriptors if d.uuid[0:4] == b'\x00\x00\x29\x02'] + [None])[0] if descr: char.callback(cb) @@ -384,12 +385,12 @@ def gatts(): c1.callback(cb, 'c1 data') c2.callback(cb, 'c2 data') - s1.start() - s2.start() + s1.start() + s2.start() b.ble_settings(adv_man_name = "mangocorp", adv_dev_name="mangoprod") b.ble_adv_enable(True) b.callback(bcb) -``` +:``` From 009a1d6325441e66adcd5ea737b2363c7362d2a6 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 31 May 2017 11:48:15 -0700 Subject: [PATCH 76/98] Merged in some parts from esp32 --- esp32/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esp32/Makefile b/esp32/Makefile index 386d8c3a5..12d35d4da 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -167,10 +167,13 @@ SRC_C = \ machine_touchpad.c \ machine_adc.c \ machine_dac.c \ + machine_pwm.c \ + machine_uart.c \ modmachine.c \ modnetwork.c \ modsocket.c \ modesp.c \ + moduhashlib.c \ espneopixel.c \ network_bluetooth.c \ machine_hw_spi.c \ From 987525d77f46427defb22af7594eed003d1934f8 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 1 Jun 2017 11:13:32 -0700 Subject: [PATCH 77/98] esp32/network_bluetooth.c: Fixed descriptor handle enumeration --- esp32/network_bluetooth.c | 164 +++++++++++++++++++++++++------------- 1 file changed, 107 insertions(+), 57 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 173e24238..56a0d6f2a 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -97,7 +97,8 @@ typedef enum { NETWORK_BLUETOOTH_GATTS_CREATE, NETWORK_BLUETOOTH_GATTS_START, NETWORK_BLUETOOTH_GATTS_STOP, - NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR, // Add char or descriptor + NETWORK_BLUETOOTH_GATTS_ADD_CHAR, // Add char + NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR, // Add descriptor // GAP / GATTC events NETWORK_BLUETOOTH_GATTC_SCAN_RES, @@ -214,32 +215,6 @@ typedef struct { size_t value_len; } read_write_data_t; -// "Service" -// Structure used for both GATTS and GATTC -typedef struct { - mp_obj_base_t base; - - mp_obj_t connection; - esp_gatt_srvc_id_t service_id; - uint16_t handle; - - mp_obj_t chars; // list - bool started; - bool valid; - -} network_bluetooth_service_obj_t; - -// "Connection" - -typedef struct { - mp_obj_base_t base; - esp_bd_addr_t bda; - int32_t conn_id; // int32_t, so we can store -1 for disconnected. - uint16_t mtu; - mp_obj_t services; - -} network_bluetooth_connection_obj_t; - // "Char" and "Descriptor" common structure typedef struct { @@ -259,10 +234,36 @@ typedef struct { mp_obj_t callback; // common mp_obj_t callback_userdata; // common - mp_obj_t next; // next charactersitic to add when service is started - } network_bluetooth_char_descr_obj_t; +// "Service" +// Structure used for both GATTS and GATTC +typedef struct { + mp_obj_base_t base; + + mp_obj_t connection; + esp_gatt_srvc_id_t service_id; + uint16_t handle; + + mp_obj_t chars; // list + bool started; + bool valid; + network_bluetooth_char_descr_obj_t* last_added_chr; + +} network_bluetooth_service_obj_t; + +// "Connection" + +typedef struct { + mp_obj_base_t base; + esp_bd_addr_t bda; + int32_t conn_id; // int32_t, so we can store -1 for disconnected. + uint16_t mtu; + mp_obj_t services; + +} network_bluetooth_connection_obj_t; + + // "Bluetooth" Declaration typedef struct { mp_obj_base_t base; @@ -578,10 +579,30 @@ STATIC mp_obj_t network_bluetooth_find_char_descr_by_handle(uint16_t handle) { STATIC mp_obj_t network_bluetooth_find_char_descr_in_char_descr_by_uuid(network_bluetooth_char_descr_obj_t* chr, esp_bt_uuid_t* uuid) { return network_bluetooth_item_op(chr->descrs, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN); } + STATIC mp_obj_t network_bluetooth_find_char_descr_in_service_by_uuid(network_bluetooth_service_obj_t* service, esp_bt_uuid_t* uuid) { return network_bluetooth_item_op(service->chars, uuid, 0, NULL, NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN); } +STATIC mp_obj_t network_bluetooth_find_next_char_in_service(network_bluetooth_service_obj_t* service, network_bluetooth_char_descr_obj_t* chr) { + + network_bluetooth_char_descr_obj_t* ret = MP_OBJ_NULL; + bool returnNext = false; + size_t len; + mp_obj_t *items; + ITEM_BEGIN(); + mp_obj_get_array(service->chars, &len, &items); + for (int i = 0; i < len; i++) { + if (returnNext) { + ret = items[i]; + break; + } + returnNext = items[i] == chr; + } + ITEM_END(); + return ret; +} + STATIC mp_obj_t network_bluetooth_del_service_by_uuid(esp_bt_uuid_t* uuid) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); return network_bluetooth_item_op(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_DEL_SERVICE); @@ -1578,28 +1599,22 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { ITEM_BEGIN(); size_t len; mp_obj_t *items; - network_bluetooth_char_descr_obj_t* prev = MP_OBJ_NULL; mp_obj_get_array(service->chars, &len, &items); - // Only start first - // characteristic, and link chars together - // for easier chaining of starts. + // Only start first characteristic // // This is because the IDF only allows adding // descriptors to the last-added charactersitic, - // so we have to add new chars after adding chars - // - for (int i = 0; i < len; i++) { - network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*) items[i]; - if (i == 0) { - esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); - } - chr->next = MP_OBJ_NULL; - if (prev != MP_OBJ_NULL) { - prev->next = chr; - } - prev = chr; + // so we have to add new chars after adding descriptros + + + if (len > 0) { + network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*) items[0]; + esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + service->last_added_chr = chr; + } else { + service->last_added_chr = MP_OBJ_NULL; } ITEM_END(); } @@ -1617,26 +1632,59 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { } break; + case NETWORK_BLUETOOTH_GATTS_ADD_CHAR: case NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR: { network_bluetooth_service_obj_t* service = network_bluetooth_find_service_by_handle(cbdata.gatts_add_char_descr.service_handle); if (service != MP_OBJ_NULL) { - network_bluetooth_char_descr_obj_t* chr = network_bluetooth_find_char_descr_in_service_by_uuid(service, &cbdata.gatts_add_char_descr.uuid); + network_bluetooth_char_descr_obj_t* chr = MP_OBJ_NULL; + if (cbdata.event == NETWORK_BLUETOOTH_GATTS_ADD_CHAR) { + // this works because UUIDs for chars must be unique within services. + // chr = network_bluetooth_find_char_descr_in_service_by_uuid(service, &cbdata.gatts_add_char_descr.uuid); + chr = service->last_added_chr; + } else { // It's a descriptor + chr = network_bluetooth_find_char_descr_in_char_descr_by_uuid(service->last_added_chr, &cbdata.gatts_add_char_descr.uuid); + } + + if (chr != MP_OBJ_NULL) { chr->handle = cbdata.gatts_add_char_descr.handle; - ITEM_BEGIN(); + size_t len; mp_obj_t *items; - mp_obj_get_array(chr->descrs, &len, &items); - for (int j = 0; j < len; j++) { - network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) items[j]; - esp_ble_gatts_add_char_descr(service->handle, &descr->id.uuid, descr->perm, NULL, NULL); - } - chr = chr->next; // Now add the next characteristic - if (chr != MP_OBJ_NULL) { - esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + + if (cbdata.event == NETWORK_BLUETOOTH_GATTS_ADD_CHAR) { + // Now add all descriptors + // `chr` is a char in this block + ITEM_BEGIN(); + mp_obj_get_array(chr->descrs, &len, &items); + for (int j = 0; j < len; j++) { + network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) items[j]; + esp_ble_gatts_add_char_descr(service->handle, &descr->id.uuid, descr->perm, NULL, NULL); + } + ITEM_END(); + + } else { + // check to see if all descriptors are registered before adding next char + ITEM_BEGIN(); + bool addNextChar = true; + mp_obj_get_array(service->last_added_chr->descrs, &len, &items); + for (int j = 0; j < len; j++) { + network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) items[j]; + if (descr->handle == 0) { + addNextChar = false; + break; + } + } + ITEM_END(); + if (addNextChar) { + chr = network_bluetooth_find_next_char_in_service(service, chr->parent); + if (chr != MP_OBJ_NULL) { + esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + service->last_added_chr = chr; + } + } } - ITEM_END(); } } } @@ -1997,7 +2045,7 @@ STATIC void network_bluetooth_gatts_event_handler( case ESP_GATTS_ADD_CHAR_DESCR_EVT: case ESP_GATTS_ADD_CHAR_EVT: { - cbdata.event = NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR; + cbdata.event = event == ESP_GATTS_ADD_CHAR_DESCR_EVT ? NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR : NETWORK_BLUETOOTH_GATTS_ADD_CHAR; cbdata.gatts_add_char_descr.service_handle = param->add_char.service_handle; cbdata.gatts_add_char_descr.handle = param->add_char.attr_handle; cbdata.gatts_add_char_descr.uuid = param->add_char.char_uuid; @@ -2950,6 +2998,7 @@ STATIC mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, si self->service_id.is_primary = mp_obj_is_true(args[ARG_primary].u_obj); self->chars = mp_obj_new_list(0, NULL); self->connection = MP_OBJ_NULL; + self->last_added_chr = MP_OBJ_NULL; ITEM_BEGIN(); mp_obj_list_append(bluetooth->services, MP_OBJ_FROM_PTR(self)); @@ -3491,6 +3540,7 @@ STATIC const mp_rom_map_elem_t network_bluetooth_gatts_char_locals_dict_table[] { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_value), NULL }, // handled by attr handler { MP_ROM_QSTR(MP_QSTR_service), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_descrs), NULL }, // handled by attr handler }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gatts_char_locals_dict, network_bluetooth_gatts_char_locals_dict_table); From 40f45007a840e26f29c45b39521d6b2b6986847f Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 6 Jun 2017 10:13:54 -0700 Subject: [PATCH 78/98] esp32/bluetooth_docs.md: Added RSSI to scan results esp32/network_bluetooth.c: Added RSSI to scan results --- esp32/bluetooth_docs.md | 2 +- esp32/network_bluetooth.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index fbba5e481..b35167c5d 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -119,7 +119,7 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, * `bluetooth.SCAN_CMPL` when GATTC scan is complete 3. Event data: * For `bluetooth.CONNECT`, `bluetooth.DISCONNECT` events, this will be a `bytes(6)` represeting the remote address. - * For `bluetooth.SCAN_RES` this will be a 2-tuple of `(, )` + * For `bluetooth.SCAN_RES` this will be a 3-tuple of `(, , )` * For `bluetooth.SCAN_CMPL` this will be `None`. 4. The `callback != mp_const_none) { mp_obj_t data = mp_const_none; if (cbdata.event == NETWORK_BLUETOOTH_GATTC_SCAN_RES) { - mp_obj_t scan_res_args[] = { MP_OBJ_NEW_BYTES(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), MP_OBJ_NEW_BYTES(cbdata.gattc_scan_res.adv_data_len, cbdata.gattc_scan_res.adv_data) } ; - data = mp_obj_new_tuple(2, scan_res_args); + mp_obj_t scan_res_args[] = { + MP_OBJ_NEW_BYTES(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), + MP_OBJ_NEW_BYTES(cbdata.gattc_scan_res.adv_data_len, cbdata.gattc_scan_res.adv_data), + mp_obj_new_int(cbdata.gattc_scan_res.rssi) + } ; + data = mp_obj_new_tuple(3, scan_res_args); FREE(cbdata.gattc_scan_res.adv_data); } @@ -2138,6 +2143,7 @@ STATIC void network_bluetooth_gap_event_handler( adv_name = esp_ble_resolve_adv_data(param->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len); memcpy(cbdata.gattc_scan_res.bda, param->scan_rst.bda, ESP_BD_ADDR_LEN); + cbdata.gattc_scan_res.rssi = param->scan_rst.rssi; cbdata.gattc_scan_res.adv_data = MALLOC(adv_name_len); if (cbdata.gattc_scan_res.adv_data != NULL) { From e908002f6b0e733ab475c925deb0f8fc624ee8f2 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 3 Jul 2017 11:53:38 -0700 Subject: [PATCH 79/98] esp32/network_bluetooth.c: Fixed issue with multiple chars --- esp32/network_bluetooth.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 77c479692..260d7f20a 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -1650,6 +1650,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { if (chr != MP_OBJ_NULL) { chr->handle = cbdata.gatts_add_char_descr.handle; + bool addNextChar = true; size_t len; mp_obj_t *items; @@ -1668,7 +1669,6 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { } else { // check to see if all descriptors are registered before adding next char ITEM_BEGIN(); - bool addNextChar = true; mp_obj_get_array(service->last_added_chr->descrs, &len, &items); for (int j = 0; j < len; j++) { network_bluetooth_char_descr_obj_t* descr = (network_bluetooth_char_descr_obj_t*) items[j]; @@ -1678,12 +1678,14 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { } } ITEM_END(); - if (addNextChar) { - chr = network_bluetooth_find_next_char_in_service(service, chr->parent); - if (chr != MP_OBJ_NULL) { - esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); - service->last_added_chr = chr; - } + } + + if (addNextChar) { + chr = network_bluetooth_find_next_char_in_service(service, chr); + + if (chr != MP_OBJ_NULL) { + esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + service->last_added_chr = chr; } } } From 8feee1d60661f469f79f76ef1d802839d1b9e658 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 5 Jul 2017 15:02:38 -0700 Subject: [PATCH 80/98] esp32/Makefile: non-working attempt to match Makefile to esp32 branch --- esp32/Makefile | 62 ++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index 12d35d4da..fcaaebd18 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -30,7 +30,7 @@ ESPCOMP = $(ESPIDF)/components ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py # verify the ESP IDF version -ESPIDF_SUPHASH := 1e0710f1b24429a316c9c34732aa17bd3f189421 +ESPIDF_SUPHASH := 9b955f4c9f1b32652ea165d3e4cdaad01bba170e ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') ifneq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH)) $(info ** WARNING **) @@ -123,7 +123,6 @@ CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bi CFLAGS += -DIDF_VER=\"$(IDF_VER)\" CFLAGS += $(CFLAGS_MOD) -#CFLAGS += -H # this is what ESPIDF uses for c++ compilation CXXFLAGS = -std=gnu++11 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DESP_PLATFORM $(INC_COMMON) $(INC_MAIN) @@ -163,6 +162,7 @@ SRC_C = \ esponewire.c \ modutime.c \ moduos.c \ + machine_timer.c \ machine_pin.c \ machine_touchpad.c \ machine_adc.c \ @@ -180,11 +180,6 @@ SRC_C = \ mpthreadport.c \ $(SRC_MOD) -STM_SRC_C = $(addprefix stmhal/,\ - pybstdio.c \ - input.c \ - ) - ESP8266_SRC_C = $(addprefix esp8266/,\ modonewire.c \ ) @@ -216,6 +211,7 @@ LIB_SRC_C = $(addprefix lib/,\ timeutils/timeutils.c \ utils/pyexec.c \ utils/interrupt_char.c \ + utils/sys_stdio_mphal.c \ ) ifeq ($(MICROPY_FATFS), 1) @@ -231,14 +227,13 @@ DRIVERS_SRC_C = $(addprefix drivers/,\ OBJ_MP = OBJ_MP += $(PY_O) OBJ_MP += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -OBJ_MP += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o)) OBJ_MP += $(addprefix $(BUILD)/, $(ESP8266_SRC_C:.c=.o)) OBJ_MP += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ_MP += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) OBJ_MP += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(ESP8266_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C) +SRC_QSTR += $(SRC_C) $(ESP8266_SRC_C) $(EXTMOD_SRC_C) $(LIB_SRC_C) $(DRIVERS_SRC_C) # Append any auto-generated sources that are needed by sources listed in SRC_QSTR SRC_QSTR_AUTO_DEPS += @@ -258,7 +253,6 @@ ESPIDF_DRIVER_O = $(addprefix $(ESPCOMP)/driver/,\ $(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-array-bounds ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\ - app_trace.o \ panic.o \ event_default_handlers.o \ task_wdt.o \ @@ -496,6 +490,10 @@ ESPIDF_TCPIP_ADAPTER_O = $(addprefix $(ESPCOMP)/tcpip_adapter/,\ tcpip_adapter_lwip.o \ ) +ESPIDF_APP_TRACE_O = $(addprefix $(ESPCOMP)/app_trace/,\ + app_trace.o \ + ) + ESPIDF_NEWLIB_O = $(addprefix $(ESPCOMP)/newlib/,\ time.o \ syscalls.o \ @@ -505,27 +503,27 @@ ESPIDF_NEWLIB_O = $(addprefix $(ESPCOMP)/newlib/,\ ) ESPIDF_NGHTTP_O = $(addprefix $(ESPCOMP)/nghttp/,\ - library/nghttp2_http.o \ - library/nghttp2_version.o \ - library/nghttp2_mem.o \ - library/nghttp2_hd_huffman.o \ - library/nghttp2_rcbuf.o \ - library/nghttp2_callbacks.o \ - library/nghttp2_session.o \ - library/nghttp2_stream.o \ - library/nghttp2_hd.o \ - library/nghttp2_priority_spec.o \ - library/nghttp2_buf.o \ - library/nghttp2_option.o \ - library/nghttp2_npn.o \ - library/nghttp2_helper.o \ - library/nghttp2_frame.o \ - library/nghttp2_outbound_item.o \ - library/nghttp2_hd_huffman_data.o \ - library/nghttp2_pq.o \ - library/nghttp2_queue.o \ - library/nghttp2_submit.o \ - library/nghttp2_map.o \ + nghttp2/lib/nghttp2_http.o \ + nghttp2/lib/nghttp2_version.o \ + nghttp2/lib/nghttp2_mem.o \ + nghttp2/lib/nghttp2_hd_huffman.o \ + nghttp2/lib/nghttp2_rcbuf.o \ + nghttp2/lib/nghttp2_callbacks.o \ + nghttp2/lib/nghttp2_session.o \ + nghttp2/lib/nghttp2_stream.o \ + nghttp2/lib/nghttp2_hd.o \ + nghttp2/lib/nghttp2_priority_spec.o \ + nghttp2/lib/nghttp2_buf.o \ + nghttp2/lib/nghttp2_option.o \ + nghttp2/lib/nghttp2_npn.o \ + nghttp2/lib/nghttp2_helper.o \ + nghttp2/lib/nghttp2_frame.o \ + nghttp2/lib/nghttp2_outbound_item.o \ + nghttp2/lib/nghttp2_hd_huffman_data.o \ + nghttp2/lib/nghttp2_pq.o \ + nghttp2/lib/nghttp2_queue.o \ + nghttp2/lib/nghttp2_submit.o \ + nghttp2/lib/nghttp2_map.o \ port/http_parser.o \ ) @@ -728,6 +726,7 @@ OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_LWIP_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_MBEDTLS_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_XTENSA_DEBUG_MODULE_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_TCPIP_ADAPTER_O)) +OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_APP_TRACE_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NGHTTP_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NVS_FLASH_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_OPENSSL_O)) @@ -781,7 +780,6 @@ $(BUILD)/application.bin: $(BUILD)/application.elf $(ECHO) "Create $@" $(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $< - $(BUILD)/application.elf: $(OBJ) $(BUILD)/esp32_out.ld $(ECHO) "LINK $@" $(Q)$(LD) $(LDFLAGS) -o $@ $(APP_LD_ARGS) From 58618f5de40db5368cea731a04bcd3a8975d1d7f Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 5 Jul 2017 16:17:45 -0700 Subject: [PATCH 81/98] esp32/Makefile: merged esp32 branch esp32/sdkconfig.h: merged esp32 branch --- esp32/Makefile | 3 +++ esp32/sdkconfig.h | 1 + 2 files changed, 4 insertions(+) diff --git a/esp32/Makefile b/esp32/Makefile index fcaaebd18..c41596468 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -85,6 +85,9 @@ INC_MAIN += -I$(ESPCOMP)/wpa_supplicant/include INC_MAIN += -I$(ESPCOMP)/wpa_supplicant/port/include INC_MAIN += -I$(ESPCOMP)/ethernet/include INC_MAIN += -I$(ESPCOMP)/tcpip_adapter/include +INC_MAIN += -I$(ESPCOMP)/app_trace/include +INC_MAIN += -I$(ESPCOMP)/nghttp/port/include +INC_MAIN += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes # Bluetooth includes have to be separate because diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index 9e382f069..002f8628d 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -78,6 +78,7 @@ #define CONFIG_BTDM_CONTROLLER_RUN_CPU 0 #define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 #define CONFIG_MEMMAP_SMP 1 +#define CONFIG_BT_ACL_CONNECTIONS 4 #define CONFIG_PARTITION_TABLE_SINGLE_APP 1 #define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" From f90d5ba1e1fe4616ded5c7a31744628d6a950516 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 6 Jul 2017 10:31:01 -0700 Subject: [PATCH 82/98] esp32/sdkconfig.h: Added new flags for BT for updated IDF --- esp32/sdkconfig.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index 002f8628d..bb55071dd 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -74,6 +74,7 @@ #define CONFIG_GATTS_ENABLE 1 #define CONFIG_GATTC_ENABLE 1 #define CONFIG_SMP_ENABLE 1 +#define CONFIG_BLE_SMP_ENABLE 1 #define CONFIG_BT_RESERVE_DRAM 0x10000 #define CONFIG_BTDM_CONTROLLER_RUN_CPU 0 #define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 From 83d5cbb9b8406bb6a5bf1db61f4b597fbbc1c64a Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 6 Jul 2017 10:31:25 -0700 Subject: [PATCH 83/98] esp32/network_bluetooth.c: Updated for IDF, fixed descr bug --- esp32/network_bluetooth.c | 165 ++++++++++++++++++++++++++++++++------ 1 file changed, 141 insertions(+), 24 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 260d7f20a..178527d4d 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -97,7 +97,7 @@ typedef enum { NETWORK_BLUETOOTH_GATTS_CREATE, NETWORK_BLUETOOTH_GATTS_START, NETWORK_BLUETOOTH_GATTS_STOP, - NETWORK_BLUETOOTH_GATTS_ADD_CHAR, // Add char + NETWORK_BLUETOOTH_GATTS_ADD_CHAR, // Add char NETWORK_BLUETOOTH_GATTS_ADD_CHAR_DESCR, // Add descriptor // GAP / GATTC events @@ -741,7 +741,9 @@ STATIC void gattc_event_dump( "GET_DESCR", "GET_INCL_SRVC", "REG_FOR_NOTIFY", - "UNREG_FOR_NOTIFY" + "UNREG_FOR_NOTIFY", // 0x27 + "CONNECT", + "DISCONNECT" }; NETWORK_BLUETOOTH_DEBUG_PRINTF( @@ -1094,9 +1096,60 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->unreg_for_notify.char_id); } - default: - // Rest of events have no printable data - // do nothing, intentionally + + case ESP_GATTC_CONNECT_EVT: + { + PRINT_STATUS(param->connect.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->connect.conn_id, + param->connect.remote_bda[0], + param->connect.remote_bda[1], + param->connect.remote_bda[2], + param->connect.remote_bda[3], + param->connect.remote_bda[4], + param->connect.remote_bda[5]); + } + break; + + case ESP_GATTC_DISCONNECT_EVT: + { + PRINT_STATUS(param->disconnect.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", conn_id = %04X" + ", addr = %02X:%02X:%02X:%02X:%02X:%02X", + param->disconnect.conn_id, + param->disconnect.remote_bda[0], + param->disconnect.remote_bda[1], + param->disconnect.remote_bda[2], + param->disconnect.remote_bda[3], + param->disconnect.remote_bda[4], + param->disconnect.remote_bda[5]); + } + break; + + + // Not printed + case ESP_GATTC_UNREG_EVT: + case ESP_GATTC_ACL_EVT: + case ESP_GATTC_CANCEL_OPEN_EVT: + case ESP_GATTC_ENC_CMPL_CB_EVT: + case ESP_GATTC_ADV_DATA_EVT: + case ESP_GATTC_MULT_ADV_ENB_EVT: + case ESP_GATTC_MULT_ADV_UPD_EVT: + case ESP_GATTC_MULT_ADV_DATA_EVT: + case ESP_GATTC_MULT_ADV_DIS_EVT: + case ESP_GATTC_BTH_SCAN_ENB_EVT: + case ESP_GATTC_BTH_SCAN_CFG_EVT: + case ESP_GATTC_BTH_SCAN_RD_EVT: + case ESP_GATTC_BTH_SCAN_THR_EVT: + case ESP_GATTC_BTH_SCAN_PARAM_EVT: + case ESP_GATTC_BTH_SCAN_DIS_EVT: + case ESP_GATTC_SCAN_FLT_CFG_EVT: + case ESP_GATTC_SCAN_FLT_PARAM_EVT: + case ESP_GATTC_SCAN_FLT_STATUS_EVT: + case ESP_GATTC_ADV_VSC_EVT: break; } NETWORK_BLUETOOTH_DEBUG_PRINTF(")\n"); @@ -1447,7 +1500,10 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t "LOCAL_ER", "NC_REQ", "ADV_STOP_COMPLETE", - "SCAN_STOP_COMPLETE" + "SCAN_STOP_COMPLETE", + "SET_STATIC_RAND_ADDR_EVT", + "UPDATE_CONN_PARAMS_EVT", + "SET_PKT_LENGTH_COMPLETE_EVT" }; NETWORK_BLUETOOTH_DEBUG_PRINTF("network_bluetooth_gap_event_handler(event = %02X / %s", event, event_names[event]); @@ -1455,6 +1511,7 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t switch (event) { case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: + case ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT: case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: @@ -1468,6 +1525,45 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t } break; + + case ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT: + { + PRINT_STATUS(param->pkt_data_lenth_cmpl.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", rx_len = %04X" + ", tx_len = %04X", + param->pkt_data_lenth_cmpl.params.rx_len, + param->pkt_data_lenth_cmpl.params.tx_len + ); + + } + break; + + case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: + { + PRINT_STATUS(param->update_conn_params.status); + NETWORK_BLUETOOTH_DEBUG_PRINTF( + ", bda = %02X:%02X:%02X:%02X:%02X:%02X" + ", min_int = %04X" + ", max_int = %04X" + ", latency = %04X" + ", conn_int = %04X" + ", timeout = %04X", + param->update_conn_params.bda[0], + param->update_conn_params.bda[1], + param->update_conn_params.bda[2], + param->update_conn_params.bda[3], + param->update_conn_params.bda[4], + param->update_conn_params.bda[5], + param->update_conn_params.min_int, + param->update_conn_params.max_int, + param->update_conn_params.latency, + param->update_conn_params.conn_int, + param->update_conn_params.timeout + ); + } + break; + case ESP_GAP_BLE_SCAN_RESULT_EVT: { const char * search_events[7] = { @@ -1606,13 +1702,13 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { // Only start first characteristic // // This is because the IDF only allows adding - // descriptors to the last-added charactersitic, + // descriptors to the last-added charactersitic, // so we have to add new chars after adding descriptros - - + + if (len > 0) { network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*) items[0]; - esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); service->last_added_chr = chr; } else { service->last_added_chr = MP_OBJ_NULL; @@ -1684,7 +1780,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { chr = network_bluetooth_find_next_char_in_service(service, chr); if (chr != MP_OBJ_NULL) { - esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); + esp_ble_gatts_add_char(service->handle, &chr->id.uuid, chr->perm, chr->prop, NULL, NULL); service->last_added_chr = chr; } } @@ -1798,8 +1894,8 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { if (bluetooth->callback != mp_const_none) { mp_obj_t data = mp_const_none; if (cbdata.event == NETWORK_BLUETOOTH_GATTC_SCAN_RES) { - mp_obj_t scan_res_args[] = { - MP_OBJ_NEW_BYTES(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), + mp_obj_t scan_res_args[] = { + MP_OBJ_NEW_BYTES(ESP_BD_ADDR_LEN, cbdata.gattc_scan_res.bda), MP_OBJ_NEW_BYTES(cbdata.gattc_scan_res.adv_data_len, cbdata.gattc_scan_res.adv_data), mp_obj_new_int(cbdata.gattc_scan_res.rssi) } ; @@ -1919,6 +2015,10 @@ STATIC void network_bluetooth_gattc_event_handler( enqueue = false; break; + case ESP_GATTC_UNREG_EVT: + bluetooth->gattc_interface = ESP_GATT_IF_NONE; + break; + case ESP_GATTC_OPEN_EVT: { cbdata.event = NETWORK_BLUETOOTH_GATTC_OPEN; @@ -2033,6 +2133,10 @@ STATIC void network_bluetooth_gatts_event_handler( enqueue = false; break; + case ESP_GATTS_UNREG_EVT: + bluetooth->gatts_interface = ESP_GATT_IF_NONE; + break; + case ESP_GATTS_CREATE_EVT: { cbdata.event = NETWORK_BLUETOOTH_GATTS_CREATE; @@ -2268,7 +2372,7 @@ STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t se STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_obj_t *self = MP_OBJ_TO_PTR(self_in); -//#define NETWORK_BLUETOOTH_LF "\n" + //#define NETWORK_BLUETOOTH_LF "\n" #define NETWORK_BLUETOOTH_LF mp_printf(print, "Bluetooth(params = (conn_id = %04X" NETWORK_BLUETOOTH_LF @@ -2362,8 +2466,12 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { if (self->state == NETWORK_BLUETOOTH_STATE_DEINIT) { + self->state = NETWORK_BLUETOOTH_STATE_INIT; + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - esp_bt_controller_init(&bt_cfg); + if (esp_bt_controller_init(&bt_cfg) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_bt_controller_init() failed"); + } if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) { mp_raise_msg(&mp_type_OSError, "esp_bt_controller_enable() failed"); @@ -2377,9 +2485,17 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { mp_raise_msg(&mp_type_OSError, "esp_bluedroid_enable() failed"); } - esp_ble_gatts_register_callback(network_bluetooth_gatts_event_handler); - esp_ble_gattc_register_callback(network_bluetooth_gattc_event_handler); - esp_ble_gap_register_callback(network_bluetooth_gap_event_handler); + if (esp_ble_gatts_register_callback(network_bluetooth_gatts_event_handler) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_register_callback() failed"); + } + + if (esp_ble_gattc_register_callback(network_bluetooth_gattc_event_handler) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_register_callback() failed"); + } + + if (esp_ble_gap_register_callback(network_bluetooth_gap_event_handler) != ESP_OK) { + mp_raise_msg(&mp_type_OSError, "esp_ble_gap_register_callback() failed"); + } if (esp_ble_gatts_app_register(0) != ESP_OK) { mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() failed"); @@ -2389,7 +2505,6 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_register() failed"); } - self->state = NETWORK_BLUETOOTH_STATE_INIT; } return mp_const_none; } @@ -3099,12 +3214,14 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { return mp_const_none; } - int numChars = mp_obj_get_int(mp_obj_len(self->chars)); - int numDescrs = 0; + size_t numDescrs = 0; size_t index; mp_obj_t *items; - mp_obj_get_array(bluetooth->services, &index, &items); + mp_obj_get_array(self->chars, &index, &items); + + size_t numChars = index; + while (index--) { network_bluetooth_char_descr_obj_t* chr = (network_bluetooth_char_descr_obj_t*)items[index]; numDescrs += mp_obj_get_int(mp_obj_len(chr->descrs)); @@ -3119,7 +3236,7 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { } if (bluetooth->gatts_interface == ESP_GATT_IF_NONE) { - mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() has failed"); + mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() has timed out"); } // Handle calculation: @@ -3405,7 +3522,7 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_39), MP_ROM_INT(ADV_CHNL_39) }, { MP_ROM_QSTR(MP_QSTR_ADV_CHNL_ALL), MP_ROM_INT(ADV_CHNL_ALL) }, -// BLE_ADV_DATA_FLAG + // BLE_ADV_DATA_FLAG { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_LIMIT_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_LIMIT_DISC) }, { MP_ROM_QSTR(MP_QSTR_BLE_ADV_FLAG_GEN_DISC), MP_ROM_INT(ESP_BLE_ADV_FLAG_GEN_DISC) }, From f0b7ba4989b748ccbf065bded483e344d6354a65 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 6 Jul 2017 14:28:44 -0700 Subject: [PATCH 84/98] esp32/Makefile: Bluetooth now build configurable esp32/main.c: Bluetooth now build configurable esp32/modnetwork.c: Bluetooth now build configurable esp32/sdkconfig.h: Bluetooth now build configurable --- esp32/Makefile | 25 ++++++++++++++++++++----- esp32/main.c | 6 +++++- esp32/modnetwork.c | 4 +++- esp32/sdkconfig.h | 21 +++++++++++++-------- 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index c41596468..ad1724f87 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -1,13 +1,17 @@ include ../py/mkenv.mk -# qstr definitions (must come before including py.mk) -QSTR_DEFS = qstrdefsport.h -QSTR_GEN_EXTRA_CFLAGS += $(INC_BT) MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 MICROPY_FATFS = 1 MICROPY_PY_BTREE = 0 +MICROPY_ESP32_BLUETOOTH ?= 1 + +# qstr definitions (must come before including py.mk) +QSTR_DEFS = qstrdefsport.h +ifeq ($(MICROPY_ESP32_BLUETOOTH),1) +QSTR_GEN_EXTRA_CFLAGS += $(INC_BT) +endif #FROZEN_DIR = scripts FROZEN_MPY_DIR = modules @@ -124,6 +128,10 @@ INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/sdp/include/ CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM +ifeq ($(MICROPY_ESP32_BLUETOOTH),1) +CFLAGS += -DMICROPY_ESP32_BLUETOOTH=1 +endif + CFLAGS += -DIDF_VER=\"$(IDF_VER)\" CFLAGS += $(CFLAGS_MOD) @@ -178,11 +186,14 @@ SRC_C = \ modesp.c \ moduhashlib.c \ espneopixel.c \ - network_bluetooth.c \ machine_hw_spi.c \ mpthreadport.c \ $(SRC_MOD) +ifeq ($(MICROPY_ESP32_BLUETOOTH),1) +SRC_C += network_bluetooth.c +endif + ESP8266_SRC_C = $(addprefix esp8266/,\ modonewire.c \ ) @@ -713,7 +724,6 @@ ESPIDF_WPA_SUPPLICANT_O = $(addprefix $(ESPCOMP)/wpa_supplicant/,\ OBJ_ESPIDF = -OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_BLUETOOTH_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NEWLIB_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_DRIVER_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ESP32_O)) @@ -735,6 +745,11 @@ OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NVS_FLASH_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_OPENSSL_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SPI_FLASH_O)) OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_WPA_SUPPLICANT_O)) + +ifeq ($(MICROPY_ESP32_BLUETOOTH),1) +OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_BLUETOOTH_O)) +endif + ################################################################################ # Main targets diff --git a/esp32/main.c b/esp32/main.c index 53db45297..5e6c7bc39 100644 --- a/esp32/main.c +++ b/esp32/main.c @@ -53,7 +53,11 @@ #define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) #define MP_TASK_STACK_SIZE (16 * 1024) #define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t)) -#define MP_TASK_HEAP_SIZE (48 * 1024) +#if (MICROPY_ESP32_BLUETOOTH) +# define MP_TASK_HEAP_SIZE (48 * 1024) +#else +# define MP_TASK_HEAP_SIZE (96 * 1024) +#endif STATIC StaticTask_t mp_task_tcb; STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8))); diff --git a/esp32/modnetwork.c b/esp32/modnetwork.c index e8f65dc04..953927d34 100644 --- a/esp32/modnetwork.c +++ b/esp32/modnetwork.c @@ -48,7 +48,9 @@ #include "lwip/dns.h" #include "tcpip_adapter.h" +#if (MICROPY_ESP32_BLUETOOTH) extern const mp_obj_type_t network_bluetooth_type; +#endif #define MODNETWORK_INCLUDE_CONSTANTS (1) @@ -526,7 +528,7 @@ STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj }, -#if (MICROPY_BLUETOOTH) +#if (MICROPY_ESP32_BLUETOOTH) { MP_ROM_QSTR(MP_QSTR_Bluetooth), MP_ROM_PTR(&network_bluetooth_type) }, #endif diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index bb55071dd..a6bd2490c 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -69,17 +69,22 @@ #define CONFIG_NEWLIB_STDOUT_ADDCR 1 #define CONFIG_PHY_ENABLED 1 #define CONFIG_WIFI_ENABLED 1 -#define CONFIG_BT_ENABLED 1 -#define CONFIG_BLUEDROID_ENABLED 1 -#define CONFIG_GATTS_ENABLE 1 -#define CONFIG_GATTC_ENABLE 1 #define CONFIG_SMP_ENABLE 1 -#define CONFIG_BLE_SMP_ENABLE 1 -#define CONFIG_BT_RESERVE_DRAM 0x10000 -#define CONFIG_BTDM_CONTROLLER_RUN_CPU 0 #define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 #define CONFIG_MEMMAP_SMP 1 -#define CONFIG_BT_ACL_CONNECTIONS 4 + +#if (MICROPY_ESP32_BLUETOOTH) +# define CONFIG_BT_ENABLED 1 +# define CONFIG_BLUEDROID_ENABLED 1 +# define CONFIG_GATTS_ENABLE 1 +# define CONFIG_GATTC_ENABLE 1 +# define CONFIG_BT_RESERVE_DRAM 0x10000 +# define CONFIG_BTDM_CONTROLLER_RUN_CPU 0 +# define CONFIG_BT_ACL_CONNECTIONS 4 +# define CONFIG_BLE_SMP_ENABLE 1 +#else +# define CONFIG_BT_RESERVE_DRAM 0 +#endif #define CONFIG_PARTITION_TABLE_SINGLE_APP 1 #define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" From 073b97ca5cbaf3b9a3735fa40cfd6b0b88a1b064 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Fri, 7 Jul 2017 09:30:25 -0700 Subject: [PATCH 85/98] esp32/Makefile: Fixed WDT crash on BT start esp32/sdkconfig.h: Moved BT options into BT block --- esp32/Makefile | 2 +- esp32/sdkconfig.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index ad1724f87..3a900d77a 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -791,7 +791,7 @@ APP_LD_ARGS += $(OBJ) APP_LD_ARGS += --end-group $(BUILD)/esp32_out.ld: sdkconfig.h - $(Q)$(CC) -I. -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@ + $(Q)$(CC) -I. -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@ -DMICROPY_ESP32_BLUETOOTH=$(MICROPY_ESP32_BLUETOOTH) $(BUILD)/network_bluetooth.o: CFLAGS = $(CFLAGS_BT) $(BUILD)/application.bin: $(BUILD)/application.elf diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h index a6bd2490c..81587e072 100644 --- a/esp32/sdkconfig.h +++ b/esp32/sdkconfig.h @@ -3,7 +3,6 @@ #define CONFIG_PHY_DATA_OFFSET 0xf000 #define CONFIG_APP_OFFSET 0x10000 -#define CONFIG_BT_DRAM_RELEASE 1 #define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 #define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1 @@ -77,6 +76,7 @@ # define CONFIG_BT_ENABLED 1 # define CONFIG_BLUEDROID_ENABLED 1 # define CONFIG_GATTS_ENABLE 1 +# define CONFIG_BT_DRAM_RELEASE 1 # define CONFIG_GATTC_ENABLE 1 # define CONFIG_BT_RESERVE_DRAM 0x10000 # define CONFIG_BTDM_CONTROLLER_RUN_CPU 0 From 9097c099b20268c5c658da65cd3fc74235b4ee5e Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Sun, 9 Jul 2017 20:39:53 -0700 Subject: [PATCH 86/98] Minor formatting --- esp32/bluetooth_docs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index b35167c5d..d70d4fc2d 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -393,4 +393,4 @@ def gatts(): b.callback(bcb) -:``` +``` From d182a687764ffa47b3da888a33599de38804a533 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 10 Jul 2017 11:26:53 -0700 Subject: [PATCH 87/98] esp32/bluetooth_docs.md: Updated docs to reflect current API --- esp32/bluetooth_docs.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index b35167c5d..81d6991f3 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -231,6 +231,8 @@ In the absence of a callback, then the characteristic value is return for a read `char.Descr(uuid, value = None, perm = bluetooth.PERM_READ | bluetooth.PERM_WRITE)` Create a new descriptor for a characteristic. +`char.descrs` Get the descriptors associated with the characteristic + ### GATTSDescr objects `descr.uuid` Get the descriptor UUID. @@ -273,7 +275,7 @@ When the callback is called, it will be called with 4 parameters: 3. The value of the notify/indicate 4. the `` -`char.descriptors` Returns a list of [`GATTCDescr`](#gattcdescr-objects) associated with this characteristic. +`char.descrs` Returns a list of [`GATTCDescr`](#gattcdescr-objects) associated with this characteristic. `char.read()` Read the characteristic value @@ -281,7 +283,7 @@ When the callback is called, it will be called with 4 parameters: ### GATTCDescr objects -`GATTCChar` objects often have associated BLE desriptor objects. These can be obtained by accessing the `char.descriptors` property of [`GATTCChar`](#gattcchar-objects) objects. +`GATTCChar` objects often have associated BLE desriptor objects. These can be obtained by accessing the `char.descrs` property of [`GATTCChar`](#gattcchar-objects) objects. `descr.read()` Read from the descriptor. @@ -369,7 +371,7 @@ def hr(bda): if service: char = ([c for c in service.chars if c.uuid[0:4] == b'\x00\x00\x2a\x37'] + [None])[0] if char: - descr = ([d for d in char.descriptors if d.uuid[0:4] == b'\x00\x00\x29\x02'] + [None])[0] + descr = ([d for d in char.descrs if d.uuid[0:4] == b'\x00\x00\x29\x02'] + [None])[0] if descr: char.callback(cb) descr.write(b'\x01\x00') # Turn on notify From 8ed22d16bbc68c0df725e4db2e33e7544bcbebfc Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 10 Jul 2017 11:48:52 -0700 Subject: [PATCH 88/98] esp32/bluetooth_docs.md: Fixed formatting, added .disconnect --- esp32/bluetooth_docs.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index 437a8136c..39bef4a90 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -15,7 +15,7 @@ ## General -### Bluetooth Objects +### Bluetooth objects The Bluetooth object is a global singleton. @@ -103,7 +103,7 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, `bluetooth.deinit()` shutdown Bluetooth. Due to present limitations in the IDF, this does _not_ return the BT stack to a lower powered state. -`bluetooth.connect(bda)` GATTC - connect to a remote GATTS server. BDA is the remote address, as a `bytes(6)`. See [GATTC](#gattc) for more information +`bluetooth.connect(bda)` GATTC - connect to a remote GATTS server. BDA is the remote address, as a `bytes(6)`. Returns a [GATTCConn](#gattcconn-objects) object. `bluetooth.Service(uuid, is_primary = True)` GATTS - create a new GATTSService object. `uuid` is either an integer or a `bytes(16)`. UUIDs are globally unique with in GATTS. If you attempt to create a service with a UUID that is the same as an existing (but not closed) service, you will receive the same service object, and no new service will be created. @@ -161,7 +161,7 @@ When a GATTC connects, advertising ends. After disconnect, then advertising mus ## GATTS -### GATTSService Objects +### GATTSService objects GATTSService objects are created by calling the `bluetooth.Service()` constructor. @@ -245,7 +245,7 @@ In the absence of a callback, then the characteristic value is return for a read ## GATTC -Use `bluetooth.scan_start()`, to find GATTS devices. You'll need to set up a Bluetooth object callback to get scan results. You can then use `bluetooth.connect()` to connec to a GATTS device: +Use `bluetooth.scan_start()`, to find GATTS devices. You'll need to set up a Bluetooth object callback to get scan results. You can then use `bluetooth.connect()` to connect to a GATTS device: `bluetooth.connect()` Returns a `GATTCConn` object. @@ -255,6 +255,8 @@ Use `bluetooth.scan_start()`, to find GATTS devices. You'll need to set up a Bl `conn.is_connected` Returns whether the connection is active or not. +`conn.disconnect()` Disconnect + ### GATTCService objects `service.is_primary` Returns a boolean indicating if the service is a primary service or not. From fc166f7ea17e3ab7e0eccf036784b06f502d9e4c Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Mon, 10 Jul 2017 11:49:39 -0700 Subject: [PATCH 89/98] esp32/network_bluetooth.c: Added disconnect() to GATTCConn --- esp32/network_bluetooth.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 178527d4d..892fef003 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2874,6 +2874,17 @@ STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_ob } } +STATIC mp_obj_t network_bluetooth_connection_disconnect(mp_obj_t self_in) { + network_bluetooth_obj_t * bluetooth = network_bluetooth_get_singleton(); + network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; + if (connection->conn_id != -1) { + esp_ble_gattc_close(bluetooth->gattc_interface, connection->conn_id); + connection->conn_id = -1; + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_connection_disconnect_obj, network_bluetooth_connection_disconnect); + STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); @@ -3595,6 +3606,7 @@ const mp_obj_type_t network_bluetooth_type = { STATIC const mp_rom_map_elem_t network_bluetooth_connection_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Handled by attr method { MP_ROM_QSTR(MP_QSTR_is_connected), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_bluetooth_connection_disconnect_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_connection_locals_dict, network_bluetooth_connection_locals_dict_table); From 2b4dc1c4921c02d30eeb22136e6127fbe4bffd11 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Thu, 13 Jul 2017 11:11:53 -0700 Subject: [PATCH 90/98] esp32/network_bluetooth.c: All properties now functions esp32/bluetooth_docs.md: All properties now functions --- esp32/bluetooth_docs.md | 54 ++--- esp32/network_bluetooth.c | 448 +++++++++++++++++--------------------- 2 files changed, 233 insertions(+), 269 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index 39bef4a90..0dbaaf402 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -107,7 +107,7 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, `bluetooth.Service(uuid, is_primary = True)` GATTS - create a new GATTSService object. `uuid` is either an integer or a `bytes(16)`. UUIDs are globally unique with in GATTS. If you attempt to create a service with a UUID that is the same as an existing (but not closed) service, you will receive the same service object, and no new service will be created. -`bluetooth.services` GATTS - returns the existing GATTS services. +`bluetooth.services()` GATTS - returns the existing GATTS services. `bluetooth.callback(, )` used to set the callback function for bluetooth-object-level callbacks. `` can be set to None. If `` is not specified, it will be set to None. Always returns a 2-tuple of the present `` and ``. If called with no parameters, the values remain unchanged. `` will be called with 4 parameters: @@ -147,7 +147,7 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, `bluetooth.scan_stop()` GATTC - terminate scanning early. If called before the scan timeout, you will _not_ receive a `bluetooth.SCAN_CMPL` event. -`bluetooth.is_scanning` GATTC - returns `True` if the scan is still active +`bluetooth.is_scanning()` GATTC - returns `True` if the scan is still active ## GAP @@ -190,11 +190,11 @@ GATTSService objects are created by calling the `bluetooth.Service()` constructo * `bluetooth.PROP_AUTH` * `bluetooth.PROP_EXT_PROP` -`service.chars` Get the characteristics attached to this service. +`service.chars()` Get the characteristics attached to this service. -`service.is_primary` Get the value of the srvice `primary` flag. +`service.is_primary()` Get the value of the srvice `primary` flag. -`char.uuid` Get the service UUID. +`char.uuid()` Get the service UUID. `service.start()` Start the service; it will be visible to any connecting GATTC. @@ -223,11 +223,11 @@ In the absence of a callback, then the characteristic value is return for a read `char.notify()` Send a notify value. `` is `string`, `bytearray`, `bytes` or `None`. -`char.uuid` Get the characteristic UUID. +`char.uuid()` Get the characteristic UUID. -`char.value` Get or set the characteristic value. +`char.value([value])` Get or set the characteristic value. -`char.service` Get the parent service. +`char.service()` Get the parent service. `char.Descr(uuid, value = None, perm = bluetooth.PERM_READ | bluetooth.PERM_WRITE)` Create a new descriptor for a characteristic. @@ -235,11 +235,11 @@ In the absence of a callback, then the characteristic value is return for a read ### GATTSDescr objects -`descr.uuid` Get the descriptor UUID. +`descr.uuid()` Get the descriptor UUID. -`descr.value` Get or set the value. +`descr.value([value])` Get or set the value. -`descr.char` Get the parent characteristic. +`descr.char()` Get the parent characteristic. `descr.callback(, )` See `char.callback()`, above. @@ -251,19 +251,19 @@ Use `bluetooth.scan_start()`, to find GATTS devices. You'll need to set up a Bl ### GATTCConn objects -`conn.services` Returns the services associated with the connection. This is a list of [`GATTCService`](#gattcservice-objects) objects. +`conn.services()` Returns the services associated with the connection. This is a list of [`GATTCService`](#gattcservice-objects) objects. -`conn.is_connected` Returns whether the connection is active or not. +`conn.is_connected()` Returns whether the connection is active or not. -`conn.disconnect()` Disconnect +`conn.disconnect()` Disconnect ### GATTCService objects -`service.is_primary` Returns a boolean indicating if the service is a primary service or not. +`service.is_primary()` Returns a boolean indicating if the service is a primary service or not. -`service.uuid` Returns the service UUID +`service.uuid()` Returns the service UUID -`service.chars` Returns a list of [`GATTCChar`](#gattcchar-objects) objects associated with this service +`service.chars()` Returns a list of [`GATTCChar`](#gattcchar-objects) objects associated with this service ### GATTCChar objects @@ -277,7 +277,7 @@ When the callback is called, it will be called with 4 parameters: 3. The value of the notify/indicate 4. the `` -`char.descrs` Returns a list of [`GATTCDescr`](#gattcdescr-objects) associated with this characteristic. +`char.descrs()` Returns a list of [`GATTCDescr`](#gattcdescr-objects) associated with this characteristic. `char.read()` Read the characteristic value @@ -285,15 +285,15 @@ When the callback is called, it will be called with 4 parameters: ### GATTCDescr objects -`GATTCChar` objects often have associated BLE desriptor objects. These can be obtained by accessing the `char.descrs` property of [`GATTCChar`](#gattcchar-objects) objects. +`GATTCChar` objects often have associated BLE desriptor objects. These can be obtained by calling `char.descrs()` function of [`GATTCChar`](#gattcchar-objects) objects. `descr.read()` Read from the descriptor. `descr.write()` Write a value to the characteristic. `` can be `str`, `bytearray`, `bytes`, or `None` -`descr.uuid` Get the descriptor UUID. +`descr.uuid()` Get the descriptor UUID. -`descr.char` Get the [`GATTCChar`](#gattcchar-objects) the descriptor is attached to +`descr.char()` Get the [`GATTCChar`](#gattcchar-objects) the descriptor is attached to ## Examples @@ -364,20 +364,24 @@ def hr(bda): ''' Will connect to a BLE heartrate monitor, and enable HR notifications ''' conn = b.connect(bda) - while not conn.is_connected: + while not conn.is_connected(): time.sleep(.1) + print ('Connected') + time.sleep(2) # Wait for services - service = ([s for s in conn.services if s.uuid[0:4] == b'\x00\x00\x18\x0d'] + [None])[0] + service = ([s for s in conn.services() if s.uuid()[0:4] == b'\x00\x00\x18\x0d'] + [None])[0] if service: - char = ([c for c in service.chars if c.uuid[0:4] == b'\x00\x00\x2a\x37'] + [None])[0] + char = ([c for c in service.chars() if c.uuid()[0:4] == b'\x00\x00\x2a\x37'] + [None])[0] if char: - descr = ([d for d in char.descrs if d.uuid[0:4] == b'\x00\x00\x29\x02'] + [None])[0] + descr = ([d for d in char.descrs() if d.uuid()[0:4] == b'\x00\x00\x29\x02'] + [None])[0] if descr: char.callback(cb) descr.write(b'\x01\x00') # Turn on notify + return conn + def gatts(): s1 = b.Service(0xaabb) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 892fef003..12ce433f7 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -444,9 +444,9 @@ STATIC void network_bluetooth_gatt_id_print(const mp_print_t *print, const esp_g } } if (print != NULL) { - mp_printf(print, ", inst_id = %02X", gatt_id->inst_id); + mp_printf(print, ", inst_id=%02X", gatt_id->inst_id); } else { - NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id = %02X", gatt_id->inst_id); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", inst_id=%02X", gatt_id->inst_id); } } @@ -617,22 +617,7 @@ STATIC void network_bluetooth_print_bda(const mp_print_t *print, esp_bd_addr_t b } } -STATIC bool check_locals_dict(mp_obj_t self, qstr attr, mp_obj_t *dest) { - mp_obj_type_t *type = mp_obj_get_type(self); - - if (type->locals_dict != NULL) { - mp_map_t *locals_map = &type->locals_dict->map; - mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); - if (elem != NULL && elem->value != NULL) { - mp_convert_member_lookup(self, type, elem->value, dest); - return true; - } - } - return false; -} - #ifdef EVENT_DEBUG - typedef struct { uint8_t id; const char * name; @@ -861,7 +846,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->search_res.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->search_res.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->search_res.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } break; @@ -875,7 +860,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->read.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->read.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->read.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); @@ -910,7 +895,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->write.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->write.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->write.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); @@ -947,7 +932,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->notify.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->notify.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->notify.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); @@ -1003,7 +988,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->get_char.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_char.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_char.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); @@ -1031,7 +1016,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->get_descr.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_descr.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_descr.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); @@ -1053,14 +1038,14 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->get_incl_srvc.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", incl_srvc_id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->get_incl_srvc.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->get_incl_srvc.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } @@ -1073,7 +1058,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->reg_for_notify.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->reg_for_notify.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->reg_for_notify.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); @@ -1089,7 +1074,7 @@ STATIC void gattc_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->unreg_for_notify.srvc_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->unreg_for_notify.srvc_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->unreg_for_notify.srvc_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); NETWORK_BLUETOOTH_DEBUG_PRINTF(", char_id = ("); @@ -1229,8 +1214,8 @@ STATIC void gatts_event_dump( ", need_resp = %s", param->read.handle, param->read.offset, - param->read.is_long ? "true" : "false", - param->read.need_rsp ? "true" : "false"); + param->read.is_long ? "True" : "False", + param->read.need_rsp ? "True" : "False"); break; @@ -1258,8 +1243,8 @@ STATIC void gatts_event_dump( ", len = %04X", param->write.handle, param->write.offset, - param->write.need_rsp ? "true" : "false", - param->write.is_prep ? "true" : "false", + param->write.need_rsp ? "True" : "False", + param->write.is_prep ? "True" : "False", param->write.len); NETWORK_BLUETOOTH_DEBUG_PRINTF(", data = "); @@ -1319,7 +1304,7 @@ STATIC void gatts_event_dump( NETWORK_BLUETOOTH_DEBUG_PRINTF("id = ("); NETWORK_BLUETOOTH_DEBUG_PRINTF("uuid = "); network_bluetooth_gatt_id_print(NULL, ¶m->create.service_id.id); - NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->create.service_id.is_primary ? "true" : "false"); + NETWORK_BLUETOOTH_DEBUG_PRINTF(", is_primary = %s", param->create.service_id.is_primary ? "True" : "False"); NETWORK_BLUETOOTH_DEBUG_PRINTF(")"); } @@ -1403,7 +1388,7 @@ STATIC void gatts_event_dump( param->connect.remote_bda[3], param->connect.remote_bda[4], param->connect.remote_bda[5], - param->connect.is_connected ? "true" : "false"); + param->connect.is_connected ? "True" : "False"); break; case ESP_GATTS_DISCONNECT_EVT: @@ -1418,7 +1403,7 @@ STATIC void gatts_event_dump( param->disconnect.remote_bda[3], param->disconnect.remote_bda[4], param->disconnect.remote_bda[5], - param->disconnect.is_connected ? "true" : "false"); + param->disconnect.is_connected ? "True" : "False"); break; case ESP_GATTS_OPEN_EVT: @@ -1442,7 +1427,7 @@ STATIC void gatts_event_dump( "conn_id = %04X" ", congested = %s", param->congest.conn_id, - param->congest.congested ? "true" : "false"); + param->congest.congested ? "True" : "False"); break; case ESP_GATTS_RESPONSE_EVT: @@ -2330,14 +2315,14 @@ STATIC void network_bluetooth_char_descr_print(const mp_print_t *print, mp_obj_t mp_printf(print, "GATTSDescr"); } - mp_printf(print, "(uuid = "); + mp_printf(print, "(uuid="); network_bluetooth_gatt_id_print(print, &self->id); if (type != GATTC_DESCR) { - mp_printf(print, ", handle = %04X, perm = %02X, value = ", self->handle, self->perm); + mp_printf(print, ", handle=%04X, perm=%02X, value=", self->handle, self->perm); mp_obj_print_helper(print, self->value, PRINT_REPR); if (type == GATTC_CHAR) { - mp_printf(print, ", prop = %02X", self->prop); + mp_printf(print, ", prop=%02X", self->prop); } } @@ -2347,9 +2332,9 @@ STATIC void network_bluetooth_char_descr_print(const mp_print_t *print, mp_obj_t STATIC void network_bluetooth_connection_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { network_bluetooth_connection_obj_t *connection = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "GATTCConn(bda = "); + mp_printf(print, "GATTCConn(bda="); network_bluetooth_print_bda(print, connection->bda); - mp_printf(print, ", connected = %s", connection->conn_id == -1 ? "False" : "True"); + mp_printf(print, ", connected=%s", connection->conn_id == -1 ? "False" : "True"); mp_printf(print, ")"); } @@ -2357,15 +2342,15 @@ STATIC void network_bluetooth_service_print(const mp_print_t *print, mp_obj_t se network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); bool gatts = MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_service_type); if (gatts) { - mp_printf(print, "GATTSService(uuid = "); + mp_printf(print, "GATTSService(uuid="); } else { - mp_printf(print, "GATTCService(uuid = "); + mp_printf(print, "GATTCService(uuid="); } network_bluetooth_gatt_id_print(print, &self->service_id.id); - mp_printf(print, ", primary = %s", self->service_id.is_primary ? "True" : "False"); + mp_printf(print, ", primary=%s", self->service_id.is_primary ? "True" : "False"); if (gatts) { - mp_printf(print, ", handle = %04X", self->handle); + mp_printf(print, ", handle=%04X", self->handle); } mp_printf(print, ")"); } @@ -2375,20 +2360,20 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m //#define NETWORK_BLUETOOTH_LF "\n" #define NETWORK_BLUETOOTH_LF mp_printf(print, - "Bluetooth(params = (conn_id = %04X" NETWORK_BLUETOOTH_LF - ", gatts_connected = %s" NETWORK_BLUETOOTH_LF - ", gatts_if = %u" NETWORK_BLUETOOTH_LF - ", gattc_if = %u" NETWORK_BLUETOOTH_LF - ", adv_params = (" - "adv_int_min = %u, " NETWORK_BLUETOOTH_LF - "adv_int_max = %u, " NETWORK_BLUETOOTH_LF - "adv_type = %u, " NETWORK_BLUETOOTH_LF - "own_addr_type = %u, " NETWORK_BLUETOOTH_LF - "peer_addr = %02X:%02X:%02X:%02X:%02X:%02X, " NETWORK_BLUETOOTH_LF - "peer_addr_type = %u, " NETWORK_BLUETOOTH_LF - "channel_map = %u, " NETWORK_BLUETOOTH_LF - "adv_filter_policy = %u" NETWORK_BLUETOOTH_LF - "state = %d" NETWORK_BLUETOOTH_LF + "Bluetooth(params=(conn_id=%04X" NETWORK_BLUETOOTH_LF + ", gatts_connected=%s" NETWORK_BLUETOOTH_LF + ", gatts_if=%u" NETWORK_BLUETOOTH_LF + ", gattc_if=%u" NETWORK_BLUETOOTH_LF + ", adv_params=(" + "adv_int_min=%u, " NETWORK_BLUETOOTH_LF + "adv_int_max=%u, " NETWORK_BLUETOOTH_LF + "adv_type=%u, " NETWORK_BLUETOOTH_LF + "own_addr_type=%u, " NETWORK_BLUETOOTH_LF + "peer_addr=%02X:%02X:%02X:%02X:%02X:%02X, " NETWORK_BLUETOOTH_LF + "peer_addr_type=%u, " NETWORK_BLUETOOTH_LF + "channel_map=%u, " NETWORK_BLUETOOTH_LF + "adv_filter_policy=%u" NETWORK_BLUETOOTH_LF + "state=%d" NETWORK_BLUETOOTH_LF ")" , self->conn_id, @@ -2411,20 +2396,20 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m self->state ); mp_printf(print, - ", data = (" - "set_scan_rsp = %s, " NETWORK_BLUETOOTH_LF - "include_name = %s, " NETWORK_BLUETOOTH_LF - "include_txpower = %s, " NETWORK_BLUETOOTH_LF - "min_interval = %d, " NETWORK_BLUETOOTH_LF - "max_interval = %d, " NETWORK_BLUETOOTH_LF - "appearance = %d, " NETWORK_BLUETOOTH_LF - "manufacturer_len = %d, " NETWORK_BLUETOOTH_LF - "p_manufacturer_data = %s, " NETWORK_BLUETOOTH_LF - "service_data_len = %d, " NETWORK_BLUETOOTH_LF - "p_service_data = ", - self->adv_data.set_scan_rsp ? "true" : "false", - self->adv_data.include_name ? "true" : "false", - self->adv_data.include_txpower ? "true" : "false", + ", data=(" + "set_scan_rsp=%s, " NETWORK_BLUETOOTH_LF + "include_name=%s, " NETWORK_BLUETOOTH_LF + "include_txpower=%s, " NETWORK_BLUETOOTH_LF + "min_interval=%d, " NETWORK_BLUETOOTH_LF + "max_interval=%d, " NETWORK_BLUETOOTH_LF + "appearance=%d, " NETWORK_BLUETOOTH_LF + "manufacturer_len=%d, " NETWORK_BLUETOOTH_LF + "p_manufacturer_data=%s, " NETWORK_BLUETOOTH_LF + "service_data_len=%d, " NETWORK_BLUETOOTH_LF + "p_service_data=", + self->adv_data.set_scan_rsp ? "True" : "False", + self->adv_data.include_name ? "True" : "False", + self->adv_data.include_txpower ? "True" : "False", self->adv_data.min_interval, self->adv_data.max_interval, self->adv_data.appearance, @@ -2434,10 +2419,12 @@ STATIC void network_bluetooth_print(const mp_print_t *print, mp_obj_t self_in, m if (self->adv_data.p_service_data != NULL) { dumpBuf(self->adv_data.p_service_data, self->adv_data.service_data_len); } - mp_printf(print, ", " NETWORK_BLUETOOTH_LF "flag = %d" NETWORK_BLUETOOTH_LF , self->adv_data.flag); - mp_printf(print, ")\n"); + mp_printf(print, ", " NETWORK_BLUETOOTH_LF "flag=%d" NETWORK_BLUETOOTH_LF , self->adv_data.flag); + mp_printf(print, ")"); } +// bluetooth.init(...) + STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { network_bluetooth_obj_t * self = (network_bluetooth_obj_t*)self_in; @@ -2510,6 +2497,8 @@ STATIC mp_obj_t network_bluetooth_init(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_init_obj, network_bluetooth_init); +// bluetooth.ble_settings(...) + STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { network_bluetooth_obj_t *bluetooth = network_bluetooth_get_singleton(); @@ -2751,6 +2740,8 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_ble_settings_obj, 1, network_bluetooth_ble_settings); +// bluetooth.ble_adv_enable(...) + STATIC mp_obj_t network_bluetooth_ble_adv_enable(mp_obj_t self_in, mp_obj_t enable) { network_bluetooth_obj_t * self = MP_OBJ_TO_PTR(self_in); self->advertising = mp_obj_is_true(enable); @@ -2776,6 +2767,8 @@ STATIC mp_obj_t network_bluetooth_callback_helper(mp_obj_t* callback, mp_obj_t* return tuple; } +// bluetooth.scan_start(...) + STATIC mp_obj_t network_bluetooth_scan_start(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { network_bluetooth_obj_t *bluetooth = MP_OBJ_TO_PTR(pos_args[0]); @@ -2823,6 +2816,8 @@ STATIC mp_obj_t network_bluetooth_scan_start(size_t n_args, const mp_obj_t *pos_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_scan_start_obj, 1, network_bluetooth_scan_start); +// bluetooth.scan_stop() + STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { (void)self_in; assert(esp_ble_gap_stop_scanning() == ESP_OK); @@ -2830,6 +2825,8 @@ STATIC mp_obj_t network_bluetooth_scan_stop(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_scan_stop_obj, network_bluetooth_scan_stop); +// conn.connect(...) + STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { network_bluetooth_obj_t * bluetooth = (network_bluetooth_obj_t *)self_in; mp_buffer_info_t bda_buf = { 0 }; @@ -2860,19 +2857,23 @@ STATIC mp_obj_t network_bluetooth_connect(mp_obj_t self_in, mp_obj_t bda) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_connect_obj, network_bluetooth_connect); -STATIC void network_bluetooth_connection_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +// conn.services() + +STATIC mp_obj_t network_bluetooth_connection_services(mp_obj_t self_in) { network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; - if (!check_locals_dict(connection, attr, dest)) { - switch (attr) { - case MP_QSTR_services: - dest[0] = connection->services; - break; - case MP_QSTR_is_connected: - dest[0] = connection->conn_id == -1 ? mp_const_false : mp_const_true; - break; - } - } + return connection->services; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_connection_services_obj, network_bluetooth_connection_services); + +// conn.is_connected() + +STATIC mp_obj_t network_bluetooth_connection_is_connected(mp_obj_t self_in) { + network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; + return connection->conn_id == -1 ? mp_const_false : mp_const_true; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_connection_is_connected_obj, network_bluetooth_connection_is_connected); + +// conn.disconnect() STATIC mp_obj_t network_bluetooth_connection_disconnect(mp_obj_t self_in) { network_bluetooth_obj_t * bluetooth = network_bluetooth_get_singleton(); @@ -2885,12 +2886,17 @@ STATIC mp_obj_t network_bluetooth_connection_disconnect(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_connection_disconnect_obj, network_bluetooth_connection_disconnect); +// bluetooth.callback(...) + STATIC mp_obj_t network_bluetooth_callback(size_t n_args, const mp_obj_t *args) { network_bluetooth_obj_t * self = network_bluetooth_get_singleton(); return network_bluetooth_callback_helper(&self->callback, &self->callback_userdata, n_args, args); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_callback_obj, 1, 3, network_bluetooth_callback); +// char.callback(...) +// descr.callback(...) + STATIC mp_obj_t network_bluetooth_char_descr_callback(size_t n_args, const mp_obj_t *args) { mp_obj_t ret; network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) args[0]; @@ -2920,10 +2926,12 @@ STATIC mp_obj_t network_bluetooth_char_descr_callback(size_t n_args, const mp_ob NETWORK_BLUETOOTH_CHAR_CALLBACK_ERROR: mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_(un)register_for_notify() call failed"); } - STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_descr_callback_obj, 1, 3, network_bluetooth_char_descr_callback); -STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) { +// char.read() +// descr.read() + +STATIC mp_obj_t network_bluetooth_char_descr_read(size_t n_args, const mp_obj_t *args) { bool is_chr; network_bluetooth_char_descr_obj_t *chr; network_bluetooth_char_descr_obj_t *descr; @@ -2981,7 +2989,10 @@ STATIC mp_obj_t network_bluetooth_char_read(size_t n_args, const mp_obj_t *args) } mp_raise_msg(&mp_type_OSError, "timed out"); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_read_obj, 1, 2, network_bluetooth_char_read); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_descr_read_obj, 1, 2, network_bluetooth_char_descr_read); + +// char.write(...) +// descr.write(...) STATIC mp_obj_t network_bluetooth_char_descr_write(mp_obj_t self_in, mp_obj_t value) { bool is_chr; @@ -3050,7 +3061,6 @@ STATIC mp_obj_t network_bluetooth_char_descr_write(mp_obj_t self_in, mp_obj_t va return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_bluetooth_char_descr_write_obj, network_bluetooth_char_descr_write); STATIC mp_obj_t network_bluetooth_char_notify_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args, bool need_confirm) { @@ -3081,16 +3091,22 @@ STATIC mp_obj_t network_bluetooth_char_notify_helper(size_t n_args, const mp_obj return mp_const_none; } +// char.notify(...) + STATIC mp_obj_t network_bluetooth_char_notify(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { return network_bluetooth_char_notify_helper(n_args, pos_args, kw_args, false); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_notify_obj, 1, network_bluetooth_char_notify); +// char.indicate(...) + STATIC mp_obj_t network_bluetooth_char_indicate(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { return network_bluetooth_char_notify_helper(n_args, pos_args, kw_args, true); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_indicate_obj, 1, network_bluetooth_char_indicate); +// network.bluetooth(...) + STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t *self = network_bluetooth_get_singleton(); if (n_args != 0 || n_kw != 0) { @@ -3101,6 +3117,8 @@ STATIC mp_obj_t network_bluetooth_make_new(const mp_obj_type_t *type_in, size_t return MP_OBJ_FROM_PTR(self); } +// bluetooth.Service(...) + STATIC mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); @@ -3141,6 +3159,8 @@ STATIC mp_obj_t network_bluetooth_service_make_new(const mp_obj_type_t *type, si return MP_OBJ_FROM_PTR(self); } +// char.Descr(...) + STATIC mp_obj_t network_bluetooth_char_descr_make_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) { enum {ARG_uuid, ARG_value, ARG_perm, ARG_prop}; @@ -3207,9 +3227,10 @@ STATIC mp_obj_t network_bluetooth_char_descr_make_new(size_t n_args, const mp_ob return MP_OBJ_FROM_PTR(self); } - STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_bluetooth_char_descr_make_new_obj, 1, network_bluetooth_char_descr_make_new); +// service.start() + STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { @@ -3259,9 +3280,10 @@ STATIC mp_obj_t network_bluetooth_service_start(mp_obj_t self_in) { esp_ble_gatts_create_service(bluetooth->gatts_interface, &self->service_id, 1 + numChars * 2 + numDescrs); return mp_const_none; } - STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_start_obj, network_bluetooth_service_start); +// service.stop() + STATIC mp_obj_t network_bluetooth_service_stop(mp_obj_t self_in) { network_bluetooth_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -3276,6 +3298,8 @@ STATIC mp_obj_t network_bluetooth_service_stop(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_stop_obj, network_bluetooth_service_stop); +// service.close() + STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); if (bluetooth->state != NETWORK_BLUETOOTH_STATE_INIT) { @@ -3296,147 +3320,90 @@ STATIC mp_obj_t network_bluetooth_service_close(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_close_obj, network_bluetooth_service_close); -STATIC void network_bluetooth_descr_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) self_in; - bool is_gatts = MP_OBJ_IS_TYPE(self_in, &network_bluetooth_gatts_descr_type); +// char.service() +// descr.char() - if (!check_locals_dict(self, attr, dest)) { - switch (attr) { - case MP_QSTR_char: - dest[0] = self->parent; - break; +STATIC mp_obj_t network_bluetooth_char_desc_parent(mp_obj_t self_in) { + network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) self_in; + return self->parent; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_char_desc_parent_obj, network_bluetooth_char_desc_parent); - case MP_QSTR_uuid: - { - esp_bt_uuid_t uuid128; - uuid_to_uuid128(&self->id.uuid, &uuid128); - dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); - } - break; +// char.value([value]) +// descr.value([value]) - case MP_QSTR_value: - if (is_gatts) { - dest[0] = self->value; - } - break; - } +STATIC mp_obj_t network_bluetooth_char_descr_value(size_t n_args, const mp_obj_t *args) { + network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) args[0]; + mp_obj_t value = self->value; + if (n_args > 1) { + self->value = args[1]; } + return value; } +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_bluetooth_char_descr_value_obj, 1, 2, network_bluetooth_char_descr_value); -STATIC void network_bluetooth_char_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) self_in; - if (!check_locals_dict(self, attr, dest)) { - - bool is_gatts = MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type); - - switch (attr) { - case MP_QSTR_Descr: - if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_char_type)) { - dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_char_descr_make_new_obj); - dest[1] = self; - } - break; - - case MP_QSTR_service: - dest[0] = self->parent; - break; - - case MP_QSTR_uuid: - { - esp_bt_uuid_t uuid128; - uuid_to_uuid128(&self->id.uuid, &uuid128); - dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); - } - break; - - case MP_QSTR_value: - if (is_gatts) { - if (dest[0] == MP_OBJ_NULL) { // load - dest[0] = self->value; - } else if (dest[1] != MP_OBJ_NULL) { // store - mp_obj_is_bt_datatype_raise(dest[1]); - self->value = dest[1]; - dest[0] = MP_OBJ_NULL; - } - } - break; - - case MP_QSTR_descrs: - dest[0] = self->descrs; - break; +// char.uuid() +// descr.uuid() +STATIC mp_obj_t network_bluetooth_char_descr_uuid(mp_obj_t self_in) { + network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) self_in; + esp_bt_uuid_t uuid128; + uuid_to_uuid128(&self->id.uuid, &uuid128); + return MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_char_descr_uuid_obj, network_bluetooth_char_descr_uuid); - case MP_QSTR_instance: - if (!is_gatts) { - dest[0] = MP_OBJ_NEW_SMALL_INT(self->id.inst_id); - } - break; +// char.descrs() - case MP_QSTR_prop: - if (!is_gatts) { - dest[0] = MP_OBJ_NEW_SMALL_INT(self->prop); - } - break; - } - } +STATIC mp_obj_t network_bluetooth_char_descrs(mp_obj_t self_in) { + network_bluetooth_char_descr_obj_t* self = (network_bluetooth_char_descr_obj_t*) self_in; + return self->descrs; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_char_descrs_obj, network_bluetooth_char_descrs); -// service attribute handler -STATIC void network_bluetooth_service_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +// service.chars() + +STATIC mp_obj_t network_bluetooth_service_chars(mp_obj_t self_in) { network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; - if (!check_locals_dict(self, attr, dest)) { + return self->chars; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_chars_obj, network_bluetooth_service_chars); - // ATTENTION: All the switches below are for read-only attribs! - if (dest[0] == MP_OBJ_NULL) { +// service.uuid() - // Attributes of GATTS objects only - if (MP_OBJ_IS_TYPE(self, &network_bluetooth_gatts_service_type)) { - switch (attr) { - case MP_QSTR_Char: - dest[0] = MP_OBJ_FROM_PTR(&network_bluetooth_char_descr_make_new_obj); - dest[1] = self; - break; - } - } +STATIC mp_obj_t network_bluetooth_service_uuid(mp_obj_t self_in) { + network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; + esp_bt_uuid_t uuid128; + uuid_to_uuid128(&self->service_id.id.uuid, &uuid128); + return MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_uuid_obj, network_bluetooth_service_uuid); - // Attributes common to GATTS and GATTC - switch (attr) { +// service.is_primary() - case MP_QSTR_chars: - dest[0] = self->chars; - break; +STATIC mp_obj_t network_bluetooth_service_is_primary(mp_obj_t self_in) { + network_bluetooth_service_obj_t* self = (network_bluetooth_service_obj_t*) self_in; + return self->service_id.is_primary ? mp_const_true : mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_service_is_primary_obj, network_bluetooth_service_is_primary); - case MP_QSTR_uuid: - { - esp_bt_uuid_t uuid128; - uuid_to_uuid128(&self->service_id.id.uuid, &uuid128); - dest[0] = MP_OBJ_NEW_BYTES(uuid128.len, uuid128.uuid.uuid128); - } - break; +// bluetooth.services() - case MP_QSTR_is_primary: - dest[0] = self->service_id.is_primary ? mp_const_true : mp_const_false ; - break; - } - } - } +STATIC mp_obj_t network_bluetooth_services(mp_obj_t self_in) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return bluetooth ->services; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_services_obj, network_bluetooth_services); -// bluetooth attribute handler -STATIC void network_bluetooth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - network_bluetooth_obj_t* self = (network_bluetooth_obj_t*) self_in; +// bluetooth.is_scanning() - if (!check_locals_dict(self, attr, dest)) { - switch (attr) { - case MP_QSTR_is_scanning: - dest[0] = self->scanning ? mp_const_true : mp_const_false; - break; - case MP_QSTR_services: - dest[0] = self->services; - break; - } - } +STATIC mp_obj_t network_bluetooth_is_scanning(mp_obj_t self_in) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return bluetooth ->scanning ? mp_const_true : mp_const_false; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_is_scanning_obj, network_bluetooth_is_scanning); + +// bluetooth.deinit() STATIC mp_obj_t network_bluetooth_deinit(mp_obj_t self_in) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); @@ -3497,11 +3464,11 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&network_bluetooth_init_obj) }, { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_bluetooth_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_gatts_service_type) }, - { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Dummy, handled by .attr + { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&network_bluetooth_services_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&network_bluetooth_scan_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_is_scanning), NULL }, // handle by attr + { MP_ROM_QSTR(MP_QSTR_is_scanning), MP_ROM_PTR(&network_bluetooth_is_scanning_obj) }, // class constants @@ -3596,7 +3563,6 @@ const mp_obj_type_t network_bluetooth_type = { .print = network_bluetooth_print, .make_new = network_bluetooth_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_locals_dict, - .attr = network_bluetooth_attr, }; // @@ -3604,9 +3570,9 @@ const mp_obj_type_t network_bluetooth_type = { // STATIC const mp_rom_map_elem_t network_bluetooth_connection_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_services), NULL }, // Handled by attr method - { MP_ROM_QSTR(MP_QSTR_is_connected), NULL }, // Handled by attr method - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_bluetooth_connection_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&network_bluetooth_connection_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_connected), MP_ROM_PTR(&network_bluetooth_connection_is_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_bluetooth_connection_disconnect_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_connection_locals_dict, network_bluetooth_connection_locals_dict_table); @@ -3617,7 +3583,6 @@ const mp_obj_type_t network_bluetooth_connection_type = { .print = network_bluetooth_connection_print, //.make_new = network_bluetooth_service_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_connection_locals_dict, - .attr = network_bluetooth_connection_attr, }; // @@ -3625,9 +3590,10 @@ const mp_obj_type_t network_bluetooth_connection_type = { // STATIC const mp_rom_map_elem_t network_bluetooth_gatts_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_Char), NULL }, // Handled by attr method - { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method - { MP_ROM_QSTR(MP_QSTR_is_primary), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_Char), MP_ROM_PTR(&network_bluetooth_char_descr_make_new_obj) }, + { MP_ROM_QSTR(MP_QSTR_chars), MP_ROM_PTR(&network_bluetooth_service_chars_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_primary), MP_ROM_PTR(&network_bluetooth_service_is_primary_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&network_bluetooth_service_uuid_obj) }, { MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&network_bluetooth_service_start_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&network_bluetooth_service_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&network_bluetooth_service_close_obj) }, @@ -3641,7 +3607,6 @@ const mp_obj_type_t network_bluetooth_gatts_service_type = { .print = network_bluetooth_service_print, .make_new = network_bluetooth_service_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gatts_service_locals_dict, - .attr = network_bluetooth_service_attr, }; // @@ -3649,9 +3614,9 @@ const mp_obj_type_t network_bluetooth_gatts_service_type = { // STATIC const mp_rom_map_elem_t network_bluetooth_gattc_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_chars), NULL }, // Handled by attr method - { MP_ROM_QSTR(MP_QSTR_is_primary), NULL }, // Handled by attr method - { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_chars), MP_ROM_PTR(&network_bluetooth_service_chars_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_primary), MP_ROM_PTR(&network_bluetooth_service_is_primary_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&network_bluetooth_service_uuid_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_service_locals_dict, network_bluetooth_gattc_service_locals_dict_table); @@ -3662,7 +3627,6 @@ const mp_obj_type_t network_bluetooth_gattc_service_type = { .print = network_bluetooth_service_print, .make_new = network_bluetooth_service_make_new, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gattc_service_locals_dict, - .attr = network_bluetooth_service_attr, }; // @@ -3670,14 +3634,14 @@ const mp_obj_type_t network_bluetooth_gattc_service_type = { // STATIC const mp_rom_map_elem_t network_bluetooth_gatts_char_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_Descr), NULL }, // Handled by attr method + { MP_ROM_QSTR(MP_QSTR_Descr), MP_ROM_PTR(&network_bluetooth_char_descr_make_new_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_descr_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&network_bluetooth_char_indicate_obj) }, { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&network_bluetooth_char_notify_obj) }, - { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_value), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_service), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_descrs), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&network_bluetooth_char_descr_uuid_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&network_bluetooth_char_descr_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_service), MP_ROM_PTR(&network_bluetooth_char_desc_parent_obj) }, + { MP_ROM_QSTR(MP_QSTR_descrs), MP_ROM_PTR(&network_bluetooth_char_descrs_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gatts_char_locals_dict, network_bluetooth_gatts_char_locals_dict_table); @@ -3687,7 +3651,6 @@ const mp_obj_type_t network_bluetooth_gatts_char_type = { .name = MP_QSTR_Char, .print = network_bluetooth_char_descr_print, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gatts_char_locals_dict, - .attr = network_bluetooth_char_attr, }; // @@ -3696,11 +3659,11 @@ const mp_obj_type_t network_bluetooth_gatts_char_type = { STATIC const mp_rom_map_elem_t network_bluetooth_gattc_char_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_descr_callback_obj) }, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&network_bluetooth_char_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&network_bluetooth_char_descr_read_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_descr_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_service), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_descrs), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_service), MP_ROM_PTR(&network_bluetooth_char_desc_parent_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&network_bluetooth_char_descr_uuid_obj) }, + { MP_ROM_QSTR(MP_QSTR_descrs), MP_ROM_PTR(&network_bluetooth_char_descrs_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_char_locals_dict, network_bluetooth_gattc_char_locals_dict_table); @@ -3710,7 +3673,6 @@ const mp_obj_type_t network_bluetooth_gattc_char_type = { .name = MP_QSTR_Char, .print = network_bluetooth_char_descr_print, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gattc_char_locals_dict, - .attr = network_bluetooth_char_attr, }; // @@ -3718,10 +3680,10 @@ const mp_obj_type_t network_bluetooth_gattc_char_type = { // STATIC const mp_rom_map_elem_t network_bluetooth_gattc_descr_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&network_bluetooth_char_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&network_bluetooth_char_descr_read_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&network_bluetooth_char_descr_write_obj) }, - { MP_ROM_QSTR(MP_QSTR_char), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_char), MP_ROM_PTR(&network_bluetooth_char_desc_parent_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&network_bluetooth_char_descr_uuid_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gattc_descr_locals_dict, network_bluetooth_gattc_descr_locals_dict_table); @@ -3731,7 +3693,6 @@ const mp_obj_type_t network_bluetooth_gattc_descr_type = { .name = MP_QSTR_GATTCDescr, .print = network_bluetooth_char_descr_print, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gattc_descr_locals_dict, - .attr = network_bluetooth_descr_attr, }; // @@ -3740,9 +3701,9 @@ const mp_obj_type_t network_bluetooth_gattc_descr_type = { STATIC const mp_rom_map_elem_t network_bluetooth_gatts_descr_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_char_descr_callback_obj) }, - { MP_ROM_QSTR(MP_QSTR_char), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_uuid), NULL }, // handled by attr handler - { MP_ROM_QSTR(MP_QSTR_value), NULL }, // handled by attr handler + { MP_ROM_QSTR(MP_QSTR_char), MP_ROM_PTR(&network_bluetooth_char_desc_parent_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&network_bluetooth_char_descr_uuid_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&network_bluetooth_char_descr_value_obj) }, }; STATIC MP_DEFINE_CONST_DICT(network_bluetooth_gatts_descr_locals_dict, network_bluetooth_gatts_descr_locals_dict_table); @@ -3751,6 +3712,5 @@ const mp_obj_type_t network_bluetooth_gatts_descr_type = { .name = MP_QSTR_GATTSDescr, .print = network_bluetooth_char_descr_print, .locals_dict = (mp_obj_dict_t*)&network_bluetooth_gatts_descr_locals_dict, - .attr = network_bluetooth_descr_attr, }; From e00c2a3a1bcb5b081497111e8de1f51926fe72cd Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 18 Jul 2017 11:06:11 -0700 Subject: [PATCH 91/98] esp32/network_bluetooth.c: Fix for bad char write https://github.com/MrSurly/micropython-esp32/issues/2 --- esp32/network_bluetooth.c | 1 + 1 file changed, 1 insertion(+) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 12ce433f7..d198fd735 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2064,6 +2064,7 @@ STATIC void network_bluetooth_gattc_event_handler( case ESP_GATTC_WRITE_DESCR_EVT: case ESP_GATTC_WRITE_CHAR_EVT: xQueueSend(read_write_q, &read_data, portMAX_DELAY); + enqueue = false; break; case ESP_GATTC_NOTIFY_EVT: From 919c79ffa18bd31b3a95670c6349ba1f7ea81864 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 18 Jul 2017 12:08:09 -0700 Subject: [PATCH 92/98] esp32/network_bluetooth.c: Fix for disconnect/reconnect https://github.com/MrSurly/micropython-esp32/issues/1 --- esp32/network_bluetooth.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index d198fd735..2dee5c882 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -453,6 +453,7 @@ STATIC void network_bluetooth_gatt_id_print(const mp_print_t *print, const esp_g typedef enum { NETWORK_BLUETOOTH_FIND_SERVICE, NETWORK_BLUETOOTH_FIND_CONNECTION, + NETWORK_BLUETOOTH_DEL_CONNECTION, NETWORK_BLUETOOTH_FIND_CHAR_DESCR_IN, NETWORK_BLUETOOTH_FIND_CHAR_DESCR, NETWORK_BLUETOOTH_DEL_SERVICE, @@ -532,12 +533,19 @@ STATIC mp_obj_t network_bluetooth_item_op(mp_obj_t list, esp_bt_uuid_t* uuid, ui break; case NETWORK_BLUETOOTH_FIND_CONNECTION: + case NETWORK_BLUETOOTH_DEL_CONNECTION: { network_bluetooth_connection_obj_t* conn = (network_bluetooth_connection_obj_t*) items[i]; if ((bda != NULL && memcmp(conn->bda, bda, ESP_BD_ADDR_LEN) == 0) || (bda == NULL && conn->conn_id == handle_or_conn_id)) { ret = conn; - goto NETWORK_BLUETOOTH_ITEM_END; } + + if (kind == NETWORK_BLUETOOTH_DEL_CONNECTION) { + // a bit ineffecient, but + // list_pop() is static + mp_obj_list_remove(list, conn); + } + goto NETWORK_BLUETOOTH_ITEM_END; } break; } @@ -609,6 +617,11 @@ STATIC mp_obj_t network_bluetooth_del_service_by_uuid(esp_bt_uuid_t* uuid) { return network_bluetooth_item_op(bluetooth->services, uuid, 0, NULL, NETWORK_BLUETOOTH_DEL_SERVICE); } +STATIC mp_obj_t network_bluetooth_del_connection_by_bda(esp_bd_addr_t bda) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return network_bluetooth_item_op(bluetooth->connections, NULL, 0, bda, NETWORK_BLUETOOTH_DEL_CONNECTION); +} + STATIC void network_bluetooth_print_bda(const mp_print_t *print, esp_bd_addr_t bda) { if (print != NULL) { mp_printf(print, "%02X:%02X:%02X:%02X:%02X:%02X", bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); @@ -2881,7 +2894,9 @@ STATIC mp_obj_t network_bluetooth_connection_disconnect(mp_obj_t self_in) { network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; if (connection->conn_id != -1) { esp_ble_gattc_close(bluetooth->gattc_interface, connection->conn_id); + network_bluetooth_del_connection_by_bda(connection->bda); connection->conn_id = -1; + connection->services = mp_obj_new_list(0, NULL); } return mp_const_none; } @@ -3396,6 +3411,14 @@ STATIC mp_obj_t network_bluetooth_services(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_services_obj, network_bluetooth_services); +// bluetooth.conns() + +STATIC mp_obj_t network_bluetooth_conns(mp_obj_t self_in) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + return bluetooth->connections; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_conns_obj, network_bluetooth_conns); + // bluetooth.is_scanning() STATIC mp_obj_t network_bluetooth_is_scanning(mp_obj_t self_in) { @@ -3466,6 +3489,7 @@ STATIC const mp_rom_map_elem_t network_bluetooth_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_bluetooth_connect_obj) }, { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&network_bluetooth_gatts_service_type) }, { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&network_bluetooth_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_conns), MP_ROM_PTR(&network_bluetooth_conns_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&network_bluetooth_callback_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&network_bluetooth_scan_start_obj) }, { MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&network_bluetooth_scan_stop_obj) }, From f782f8a8c60e58032f4192bd332e6907173618cb Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 18 Jul 2017 12:08:35 -0700 Subject: [PATCH 93/98] esp32/bluetooth_docs.md: Updated doc for bluetooth.conns() --- esp32/bluetooth_docs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index 0dbaaf402..f507b204c 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -109,6 +109,8 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, `bluetooth.services()` GATTS - returns the existing GATTS services. +`bluetooth.conns()` GATTC - Returns all the current client connections. + `bluetooth.callback(, )` used to set the callback function for bluetooth-object-level callbacks. `` can be set to None. If `` is not specified, it will be set to None. Always returns a 2-tuple of the present `` and ``. If called with no parameters, the values remain unchanged. `` will be called with 4 parameters: 1. The `bluetooth` object From 88645eba10cc3407a2c77e02c31c929daf42b90d Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 22 Aug 2017 08:40:24 -0700 Subject: [PATCH 94/98] esp32/network_bluetooth.c: Fixed duplicate conn obj on device disconnect --- esp32/network_bluetooth.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index 2dee5c882..b7bb38601 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -1648,6 +1648,16 @@ STATIC void gap_event_dump(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t } #endif // EVENT_DEBUG +STATIC void network_bluetooth_disconnect_helper(network_bluetooth_connection_obj_t* connection) { + network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); + if (connection != MP_OBJ_NULL && connection->conn_id != -1) { + esp_ble_gattc_close(bluetooth->gattc_interface, connection->conn_id); + network_bluetooth_del_connection_by_bda(connection->bda); + connection->conn_id = -1; + connection->services = mp_obj_new_list(0, NULL); + } +} + STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { network_bluetooth_obj_t* bluetooth = network_bluetooth_get_singleton(); @@ -1908,10 +1918,7 @@ STATIC mp_obj_t network_bluetooth_callback_queue_handler(mp_obj_t arg) { case NETWORK_BLUETOOTH_GATTC_CLOSE: { - network_bluetooth_connection_obj_t* conn = network_bluetooth_find_connection_by_conn_id(cbdata.gattc_open_close.conn_id); - if (conn != MP_OBJ_NULL) { - conn->conn_id = -1; - } + network_bluetooth_disconnect_helper(network_bluetooth_find_connection_by_conn_id(cbdata.gattc_open_close.conn_id)); } break; @@ -2297,9 +2304,9 @@ STATIC void network_bluetooth_adv_updated() { esp_ble_gap_config_adv_data(&self->adv_data); // Restart will be handled in network_bluetooth_gap_event_handler - } + /******************************************************************************/ // MicroPython bindings for network_bluetooth // @@ -2890,14 +2897,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_connection_is_connected_obj, // conn.disconnect() STATIC mp_obj_t network_bluetooth_connection_disconnect(mp_obj_t self_in) { - network_bluetooth_obj_t * bluetooth = network_bluetooth_get_singleton(); - network_bluetooth_connection_obj_t* connection = (network_bluetooth_connection_obj_t*) self_in; - if (connection->conn_id != -1) { - esp_ble_gattc_close(bluetooth->gattc_interface, connection->conn_id); - network_bluetooth_del_connection_by_bda(connection->bda); - connection->conn_id = -1; - connection->services = mp_obj_new_list(0, NULL); - } + network_bluetooth_disconnect_helper(self_in); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_bluetooth_connection_disconnect_obj, network_bluetooth_connection_disconnect); From 6add00f479ef4f4c99f48144d36c183bdb0b5f29 Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Wed, 23 Aug 2017 09:46:37 -0700 Subject: [PATCH 95/98] esp32/Makefile: Modified to be more inline with esp32 branch --- esp32/Makefile | 95 ++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 50 deletions(-) diff --git a/esp32/Makefile b/esp32/Makefile index 30c568b0c..2a57edb57 100644 --- a/esp32/Makefile +++ b/esp32/Makefile @@ -4,7 +4,7 @@ include ../py/mkenv.mk MICROPY_PY_USSL = 0 MICROPY_SSL_AXTLS = 0 MICROPY_FATFS = 1 -MICROPY_PY_BTREE = 0 +MICROPY_PY_BTREE = 1 MICROPY_ESP32_BLUETOOTH ?= 1 # qstr definitions (must come before including py.mk) @@ -12,7 +12,7 @@ QSTR_DEFS = qstrdefsport.h ifeq ($(MICROPY_ESP32_BLUETOOTH),1) QSTR_GEN_EXTRA_CFLAGS += $(INC_BT) endif -MICROPY_PY_BTREE = 1 + #FROZEN_DIR = scripts FROZEN_MPY_DIR = modules @@ -49,50 +49,47 @@ endif # pretty format of ESP IDF version, used internally by the IDF IDF_VER := $(shell git -C $(ESPIDF) describe) -# Include dirs for both BT and MAIN -INC_COMMON = -I. -INC_COMMON += -I.. -INC_COMMON += -I$(BUILD) -INC_COMMON += -I$(ESPCOMP)/log/include -INC_COMMON += -I$(ESPCOMP)/esp32/include -INC_COMMON += -I$(ESPCOMP)/soc/esp32/include -INC_COMMON += -I$(ESPCOMP)/freertos/include -INC_COMMON += -I$(ESPCOMP)/tcpip_adapter/include -INC_COMMON += -I$(ESPCOMP)/lwip/include/lwip -INC_COMMON += -I$(ESPCOMP)/lwip/include/lwip/port -INC_COMMON += -I$(ESPCOMP)/driver/include/driver -INC_COMMON += -I$(ESPCOMP)/driver/include -INC_COMMON += -I$(ESPCOMP)/nvs_flash/include +INC += -I. +INC += -I.. +INC += -I$(BUILD) # Include dirs for main code base, excluding BT INC_MAIN += -I../lib/mp-readline INC_MAIN += -I../lib/netutils INC_MAIN += -I../lib/timeutils -INC_MAIN += -I$(ESPCOMP)/spi_flash/include -INC_MAIN += -I$(ESPCOMP)/bootloader_support/include -INC_MAIN += -I$(ESPCOMP)/nghttp/port/include -INC_MAIN += -I$(ESPCOMP)/nghttp/include -INC_MAIN += -I$(ESPCOMP)/ethernet/include -INC_MAIN += -I$(ESPCOMP)/expat/include/expat -INC_MAIN += -I$(ESPCOMP)/expat/port/include -INC_MAIN += -I$(ESPCOMP)/json/include -INC_MAIN += -I$(ESPCOMP)/json/port/include -INC_MAIN += -I$(ESPCOMP)/newlib/include -INC_MAIN += -I$(ESPCOMP)/lwip/include/lwip/port -INC_MAIN += -I$(ESPCOMP)/lwip/include/lwip/posix -INC_MAIN += -I$(ESPCOMP)/mbedtls/include -INC_MAIN += -I$(ESPCOMP)/mbedtls/port/include -INC_MAIN += -I$(ESPCOMP)/vfs/include -INC_MAIN += -I$(ESPCOMP)/newlib/platform_include -INC_MAIN += -I$(ESPCOMP)/xtensa-debug-module/include -INC_MAIN += -I$(ESPCOMP)/wpa_supplicant/include -INC_MAIN += -I$(ESPCOMP)/wpa_supplicant/port/include -INC_MAIN += -I$(ESPCOMP)/ethernet/include -INC_MAIN += -I$(ESPCOMP)/tcpip_adapter/include -INC_MAIN += -I$(ESPCOMP)/app_trace/include -INC_MAIN += -I$(ESPCOMP)/nghttp/port/include -INC_MAIN += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes +INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include +INC_ESPCOMP += -I$(ESPCOMP)/driver/include +INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver +INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include +INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes +INC_ESPCOMP += -I$(ESPCOMP)/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/soc/include +INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include +INC_ESPCOMP += -I$(ESPCOMP)/expat/include/expat +INC_ESPCOMP += -I$(ESPCOMP)/expat/port/include +INC_ESPCOMP += -I$(ESPCOMP)/heap/include +INC_ESPCOMP += -I$(ESPCOMP)/json/include +INC_ESPCOMP += -I$(ESPCOMP)/json/port/include +INC_ESPCOMP += -I$(ESPCOMP)/log/include +INC_ESPCOMP += -I$(ESPCOMP)/newlib/include +INC_ESPCOMP += -I$(ESPCOMP)/nvs_flash/include +INC_ESPCOMP += -I$(ESPCOMP)/freertos/include +INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include +INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/lwip +INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/lwip/port +INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/lwip/posix +INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/include +INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include +INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include +INC_ESPCOMP += -I$(ESPCOMP)/vfs/include +INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include +INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include +INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include +INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include +INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include +INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include # Bluetooth includes have to be separate because # esp-idf/components/bt/bluedroid/osi/include/list.h @@ -126,17 +123,22 @@ INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/smp/include/ INC_BT += -I$(ESPCOMP)/bt/include INC_BT += -I$(ESPCOMP)/bt/bluedroid/stack/sdp/include/ -CFLAGS = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM +CFLAGS_BASE = -std=gnu99 -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM ifeq ($(MICROPY_ESP32_BLUETOOTH),1) -CFLAGS += -DMICROPY_ESP32_BLUETOOTH=1 +CFLAGS_BASE += -DMICROPY_ESP32_BLUETOOTH=1 endif +CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_MAIN) $(INC_ESPCOMP) +CFLAGS_BT := $(CFLAGS_BASE) $(INC) $(INC_BT) $(INC_ESPCOMP) + + + CFLAGS += -DIDF_VER=\"$(IDF_VER)\" CFLAGS += $(CFLAGS_MOD) # this is what ESPIDF uses for c++ compilation -CXXFLAGS = -std=gnu++11 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DESP_PLATFORM $(INC_COMMON) $(INC_MAIN) +CXXFLAGS = -std=gnu++11 -fno-exceptions -fno-rtti -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -DESP_PLATFORM $(INC) $(INC_MAIN) $(INC_ESPCOMP) LDFLAGS = -nostdlib -Map=$(@:.elf=.map) --cref LDFLAGS += --gc-sections -static -EL @@ -157,9 +159,6 @@ COPT += -Os -DNDEBUG #LDFLAGS += --gc-sections endif -CFLAGS_BT := $(CFLAGS) $(INC_COMMON) $(INC_BT) -CFLAGS += $(INC_COMMON) $(INC_MAIN) - ################################################################################ # List of MicroPython source and object files @@ -193,10 +192,6 @@ ifeq ($(MICROPY_ESP32_BLUETOOTH),1) SRC_C += network_bluetooth.c endif -ESP8266_SRC_C = $(addprefix esp8266/,\ - modonewire.c \ - ) - EXTMOD_SRC_C = $(addprefix extmod/,\ modonewire.c \ ) From 54f354737e48a99862c6e85b1f6ac4f41a98e81a Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 5 Sep 2017 10:48:11 -0700 Subject: [PATCH 96/98] updated code example to match current API --- esp32/bluetooth_docs.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index f507b204c..f8ba77a03 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -332,7 +332,7 @@ def bcb(b,e,d,u): complete = False found = {} - adx, name = d + adx, name, rssi = d if adx not in found: found[adx] = name @@ -342,7 +342,6 @@ def bcb(b,e,d,u): print ('\nFinal List:') for adx, name in found.items(): print ('Found:' + ':'.join(['%02X' % i for i in adx]), name) - onScanComplete() else: print ('Unknown event', e,d) From f494f596dec4672df3a752be717ac3d972e31a9a Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Tue, 19 Sep 2017 20:33:05 +0200 Subject: [PATCH 97/98] Fix docs > `adv_enable` needs `ble_` prefix --- esp32/bluetooth_docs.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp32/bluetooth_docs.md b/esp32/bluetooth_docs.md index f8ba77a03..0f6b65504 100644 --- a/esp32/bluetooth_docs.md +++ b/esp32/bluetooth_docs.md @@ -155,9 +155,9 @@ bluetooth.ble_settings(int_min = 1280, int_max = 1280, ### Start and stop advertising -`bluetooth.adv_enable(True)` +`bluetooth.ble_adv_enable(True)` -`bluetooth.adv_enable(False)` +`bluetooth.ble_adv_enable(False)` When a GATTC connects, advertising ends. After disconnect, then advertising must be restarted. From 6d6438718b6a9a4dfc13ffe91948ce8b06cbfa8b Mon Sep 17 00:00:00 2001 From: Eric Poulsen Date: Tue, 5 Dec 2017 09:35:20 -0800 Subject: [PATCH 98/98] esp32/network_bluetooth.c: Fix for issue #15 https://github.com/MrSurly/micropython-esp32/issues/15 --- esp32/network_bluetooth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esp32/network_bluetooth.c b/esp32/network_bluetooth.c index b7bb38601..9a57f5a57 100644 --- a/esp32/network_bluetooth.c +++ b/esp32/network_bluetooth.c @@ -2622,12 +2622,14 @@ STATIC mp_obj_t network_bluetooth_ble_settings(size_t n_args, const mp_obj_t *po if (args[ARG_adv_uuid].u_obj != NULL) { if (mp_obj_get_type(args[ARG_adv_uuid].u_obj) == mp_const_none) { unset_adv_uuid = true; - } else if (!MP_OBJ_IS_TYPE(mp_obj_get_type(args[ARG_adv_uuid].u_obj), &mp_type_bytearray)) { + } else if (!MP_OBJ_IS_BYTEARRAY_OR_BYTES(args[ARG_adv_uuid].u_obj)) { + printf("there\n"); goto NETWORK_BLUETOOTH_BAD_UUID; } mp_get_buffer(args[ARG_adv_uuid].u_obj, &adv_uuid_buf, MP_BUFFER_READ); if (adv_uuid_buf.len != UUID_LEN) { + printf("here\n"); // FIXME: Is length really a fixed amount? goto NETWORK_BLUETOOTH_BAD_UUID; }