mirror of
https://github.com/m5stack/M5Stack_MicroPython.git
synced 2026-05-20 10:14:44 -07:00
Updated MicroPython scheduler functions Updated all affected modules esp-idf sdspi_host driver refactored Using SDCard in SPI mode and display at the same time now works Tested on M5Stack & Adafruit 2.4" TFT Featherwing Display module refactored uses (modified) esp-idf spi-master driver 16-bit color mode added low level display functions added get TP calibration constants function added Backlight on/off function added M5Stack & GENERIC display types added display initialization sequence for unknown display types can now be handled from MicroPython tpcalib frozen module updated I2C module refactored SLAVE mode added Low level I2C functions added esp-idf i2c driver modified SPI module updated UART module updated network module updated machine module: added method for reading internal ESP32 temperature sensor _thread module: status of the system tasks is now available in _thread.list() os module: SDCard mode can now be configured from MicroPython time.ticks_xx() functions now returns correct tick count after time update rtc module updated Added MPU9250 frozen module (available on M5Stack) Experimental Bluetooth support, not yet finished Experimental support for eve display modules, not yet finished License file added License information in many source files updated/added
1205 lines
42 KiB
C
1205 lines
42 KiB
C
/*
|
|
* This file is part of the MicroPython project, http://micropython.org/
|
|
*
|
|
* The MIT License (MIT)
|
|
*
|
|
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
|
|
// Free RTOS
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/semphr.h"
|
|
|
|
// Generic
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
// MicroPython
|
|
#include "py/runtime.h"
|
|
#include "py/obj.h"
|
|
#include "py/objstr.h"
|
|
#include "py/runtime0.h"
|
|
|
|
// IDF
|
|
#include "bt.h"
|
|
#include "esp_bt_main.h"
|
|
#include "esp_gap_ble_api.h"
|
|
#include "esp_gatts_api.h"
|
|
#include "esp_gattc_api.h"
|
|
|
|
//extern bool bluetooth_enabled;
|
|
|
|
static bool bluetooth_enabled = false;
|
|
|
|
#define EVENT_DEBUG
|
|
|
|
#ifdef EVENT_DEBUG
|
|
# define EVENT_DEBUG_GATTC
|
|
# define EVENT_DEBUG_GATTS
|
|
# define EVENT_DEBUG_GAP
|
|
#endif
|
|
#define MSEC_0_625_TO_UNIT(time) ((time) * 1000 / (625))
|
|
|
|
#define MALLOC(x) pvPortMalloc(x)
|
|
#define FREE(x) vPortFree(x)
|
|
#define UUID_LEN 16
|
|
#define STRINGIFY(x) #x
|
|
#define TOSTRING(x) STRINGIFY(x)
|
|
#define BAD_UUID(name) mp_raise_ValueError(name "must be bytearray(" TOSTRING(UUID_LEN) ")");
|
|
#define BAD_PEER(name) mp_raise_ValueError(name "must be bytearray(" TOSTRING(ESP_BD_ADDR_LEN) ")");
|
|
#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 NETWORK_BLUETOOTH_DEBUG_PRINTF(args...) printf(args)
|
|
|
|
#define CALLBACK_QUEUE_SIZE 10
|
|
|
|
typedef enum {
|
|
|
|
// GATTS
|
|
BTLE_GATTS_CONNECT,
|
|
BTLE_GATTS_DISCONNECT,
|
|
|
|
BTLE_GATTS_CREATE,
|
|
BTLE_GATTS_START,
|
|
BTLE_GATTS_STOP,
|
|
BTLE_GATTS_ADD_CHAR, // Add char
|
|
BTLE_GATTS_ADD_CHAR_DESCR, // Add descriptor
|
|
|
|
// GAP / GATTC events
|
|
BTLE_GATTC_SCAN_RES,
|
|
BTLE_GATTC_SCAN_CMPL, // Found GATT servers
|
|
BTLE_GATTC_SEARCH_RES, // Found GATTS services
|
|
|
|
BTLE_GATTC_GET_CHAR,
|
|
BTLE_GATTC_GET_DESCR,
|
|
|
|
BTLE_GATTC_OPEN,
|
|
BTLE_GATTC_CLOSE,
|
|
|
|
// characteristic events
|
|
BTLE_READ,
|
|
BTLE_WRITE,
|
|
BTLE_NOTIFY,
|
|
|
|
} btle_event_t;
|
|
|
|
typedef struct {
|
|
btle_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 handle;
|
|
esp_bt_uuid_t uuid;
|
|
} gatts_add_char_descr;
|
|
|
|
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;
|
|
int rssi;
|
|
} gattc_scan_res;
|
|
|
|
struct {
|
|
uint16_t conn_id;
|
|
esp_gatt_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;
|
|
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;
|
|
esp_bd_addr_t bda;
|
|
|
|
} gattc_open_close;
|
|
|
|
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;
|
|
|
|
struct {
|
|
uint16_t conn_id;
|
|
esp_bd_addr_t remote_bda;
|
|
uint16_t handle;
|
|
|
|
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;
|
|
|
|
const mp_obj_type_t btle_type;
|
|
|
|
STATIC SemaphoreHandle_t item_mut;
|
|
STATIC QueueHandle_t callback_q = NULL;
|
|
STATIC QueueHandle_t read_write_q = NULL;
|
|
|
|
STATIC void dumpBuf(const uint8_t *buf, size_t len) {
|
|
while (len--) {
|
|
printf("%02X ", *buf++);
|
|
}
|
|
}
|
|
|
|
typedef struct {
|
|
mp_obj_base_t base;
|
|
enum {
|
|
BTLE_STATE_DEINIT,
|
|
BTLE_STATE_INIT
|
|
} state;
|
|
bool advertising;
|
|
bool scanning;
|
|
bool gatts_connected;
|
|
|
|
uint16_t conn_id;
|
|
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;
|
|
|
|
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;
|
|
} btle_obj_t;
|
|
|
|
// Singleton
|
|
STATIC btle_obj_t* btle_singleton = NULL;
|
|
|
|
STATIC btle_obj_t* btle_get_singleton() {
|
|
|
|
if (btle_singleton == NULL) {
|
|
btle_singleton = m_new_obj(btle_obj_t);
|
|
|
|
btle_singleton->base.type = &btle_type;
|
|
|
|
btle_singleton->state = BTLE_STATE_DEINIT;
|
|
btle_singleton->advertising = false;
|
|
btle_singleton->scanning = false;
|
|
btle_singleton->gatts_connected = false;
|
|
btle_singleton->conn_id = 0;
|
|
btle_singleton->gatts_interface = ESP_GATT_IF_NONE;
|
|
btle_singleton->gattc_interface = ESP_GATT_IF_NONE;
|
|
btle_singleton->adv_params.adv_int_min = 1280 * 1.6;
|
|
btle_singleton->adv_params.adv_int_max = 1280 * 1.6;
|
|
btle_singleton->adv_params.adv_type = ADV_TYPE_IND;
|
|
btle_singleton->adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
|
|
btle_singleton->adv_params.peer_addr_type = BLE_ADDR_TYPE_PUBLIC;
|
|
btle_singleton->adv_params.channel_map = ADV_CHNL_ALL;
|
|
btle_singleton->adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY;
|
|
btle_singleton->adv_data.set_scan_rsp = false;
|
|
btle_singleton->adv_data.include_name = false;
|
|
btle_singleton->adv_data.include_txpower = false;
|
|
btle_singleton->adv_data.min_interval = 1280 * 1.6;
|
|
btle_singleton->adv_data.max_interval = 1280 * 1.6;
|
|
btle_singleton->adv_data.appearance = 0;
|
|
btle_singleton->adv_data.p_manufacturer_data = NULL;
|
|
btle_singleton->adv_data.manufacturer_len = 0;
|
|
btle_singleton->adv_data.p_service_data = NULL;
|
|
btle_singleton->adv_data.service_data_len = 0;
|
|
btle_singleton->adv_data.p_service_uuid = 0;
|
|
btle_singleton->adv_data.service_uuid_len = 0;
|
|
btle_singleton->adv_data.flag = 0;
|
|
|
|
btle_singleton->callback = mp_const_none;
|
|
btle_singleton->callback_userdata = mp_const_none;
|
|
|
|
btle_singleton->services = mp_obj_new_list(0, NULL);
|
|
btle_singleton->connections = mp_obj_new_list(0, NULL);
|
|
memset(btle_singleton->adv_params.peer_addr, 0, sizeof(btle_singleton->adv_params.peer_addr));
|
|
}
|
|
return btle_singleton;
|
|
}
|
|
|
|
#if CONFIG_GATTS_ENABLE
|
|
STATIC void btle_gatts_event_handler(
|
|
esp_gatts_cb_event_t event,
|
|
esp_gatt_if_t gatts_if,
|
|
esp_ble_gatts_cb_param_t *param) {
|
|
|
|
btle_obj_t* bluetooth = btle_get_singleton();
|
|
if (bluetooth->state != BTLE_STATE_INIT) {
|
|
return;
|
|
}
|
|
|
|
#ifdef EVENT_DEBUG_GATTS
|
|
//gatts_event_dump(event, gatts_if, param);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_GATTC_ENABLE
|
|
STATIC void btle_gattc_event_handler(
|
|
esp_gattc_cb_event_t event,
|
|
esp_gatt_if_t gattc_if,
|
|
esp_ble_gattc_cb_param_t *param) {
|
|
|
|
btle_obj_t* bluetooth = btle_get_singleton();
|
|
if (bluetooth->state != BTLE_STATE_INIT) {
|
|
return;
|
|
}
|
|
#ifdef EVENT_DEBUG_GATTC
|
|
//gattc_event_dump(event, gattc_if, param);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef EVENT_DEBUG_GAP
|
|
|
|
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},
|
|
};
|
|
|
|
#define PRINT_STATUS(STATUS) { \
|
|
bool found = false; \
|
|
NETWORK_BLUETOOTH_DEBUG_PRINTF("status = %02X / ", (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", gatt_status_names[i].name); \
|
|
break; \
|
|
} \
|
|
} \
|
|
if (!found) { \
|
|
NETWORK_BLUETOOTH_DEBUG_PRINTF("???"); \
|
|
} \
|
|
}
|
|
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",
|
|
"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]);
|
|
NETWORK_BLUETOOTH_DEBUG_PRINTF(", param = (");
|
|
switch (event) {
|
|
case ESP_GAP_BLE_EVT_MAX:
|
|
break;
|
|
|
|
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:
|
|
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:
|
|
case ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT:
|
|
case ESP_GAP_BLE_SET_LOCAL_PRIVACY_COMPLETE_EVT:
|
|
{
|
|
PRINT_STATUS(param->adv_data_cmpl.status);
|
|
}
|
|
break;
|
|
|
|
|
|
case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
|
|
{
|
|
PRINT_STATUS(param->adv_data_cmpl.status);
|
|
NETWORK_BLUETOOTH_DEBUG_PRINTF(
|
|
", rssi = %d, bda = %02X:%02X:%02X:%02X:%02X:%02X",
|
|
param->read_rssi_cmpl.rssi,
|
|
param->read_rssi_cmpl.remote_addr[0],
|
|
param->read_rssi_cmpl.remote_addr[1],
|
|
param->read_rssi_cmpl.remote_addr[2],
|
|
param->read_rssi_cmpl.remote_addr[3],
|
|
param->read_rssi_cmpl.remote_addr[4],
|
|
param->read_rssi_cmpl.remote_addr[5]);
|
|
}
|
|
break;
|
|
|
|
case ESP_GAP_BLE_ADD_WHITELIST_COMPLETE_EVT:
|
|
{
|
|
PRINT_STATUS(param->adv_data_cmpl.status);
|
|
NETWORK_BLUETOOTH_DEBUG_PRINTF(
|
|
", wl_opration = %s",
|
|
param->update_whitelist_cmpl.wl_opration == ESP_BLE_WHITELIST_ADD
|
|
? "ADD" : "REMOVE");
|
|
}
|
|
break;
|
|
|
|
case ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT:
|
|
{
|
|
PRINT_STATUS(param->adv_data_cmpl.status);
|
|
NETWORK_BLUETOOTH_DEBUG_PRINTF(
|
|
", dev_num = %d, bond_dev = <print not impl>",
|
|
param->get_bond_dev_cmpl.dev_num);
|
|
}
|
|
break;
|
|
case ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT:
|
|
{
|
|
PRINT_STATUS(param->adv_data_cmpl.status);
|
|
NETWORK_BLUETOOTH_DEBUG_PRINTF(
|
|
", bda = %02X:%02X:%02X:%02X:%02X:%02X",
|
|
param->remove_bond_dev_cmpl.bd_addr[0],
|
|
param->remove_bond_dev_cmpl.bd_addr[1],
|
|
param->remove_bond_dev_cmpl.bd_addr[2],
|
|
param->remove_bond_dev_cmpl.bd_addr[3],
|
|
param->remove_bond_dev_cmpl.bd_addr[4],
|
|
param->remove_bond_dev_cmpl.bd_addr[5]);
|
|
}
|
|
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] = {
|
|
"INQ_RES",
|
|
"INQ_CMPL",
|
|
"DISC_RES",
|
|
"DISC_BLE_RES",
|
|
"DISC_CMPL",
|
|
"DI_DISC_CMPL",
|
|
"SEARCH_CANCEL_CMPL"
|
|
};
|
|
|
|
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]);
|
|
|
|
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
|
|
|
|
);
|
|
}
|
|
|
|
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);
|
|
|
|
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(", 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 void btle_gap_event_handler
|
|
(
|
|
esp_gap_ble_cb_event_t event,
|
|
esp_ble_gap_cb_param_t *param) {
|
|
|
|
#ifdef EVENT_DEBUG_GAP
|
|
gap_event_dump(event, param);
|
|
#endif
|
|
|
|
btle_obj_t* bluetooth = btle_get_singleton();
|
|
if (bluetooth->state != BTLE_STATE_INIT) {
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------------
|
|
STATIC void btle_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
|
btle_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
|
//#define BTLE_LF "\n"
|
|
#define BTLE_LF
|
|
mp_printf(print,
|
|
"Bluetooth(params=(conn_id=%04X" BTLE_LF
|
|
", gatts_connected=%s" BTLE_LF
|
|
", gatts_if=%u" BTLE_LF
|
|
", gattc_if=%u" BTLE_LF
|
|
", adv_params=("
|
|
"adv_int_min=%u, " BTLE_LF
|
|
"adv_int_max=%u, " BTLE_LF
|
|
"adv_type=%u, " BTLE_LF
|
|
"own_addr_type=%u, " BTLE_LF
|
|
"peer_addr=%02X:%02X:%02X:%02X:%02X:%02X, " BTLE_LF
|
|
"peer_addr_type=%u, " BTLE_LF
|
|
"channel_map=%u, " BTLE_LF
|
|
"adv_filter_policy=%u" BTLE_LF
|
|
"state=%d" BTLE_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,
|
|
self->state
|
|
);
|
|
mp_printf(print,
|
|
", data=("
|
|
"set_scan_rsp=%s, " BTLE_LF
|
|
"include_name=%s, " BTLE_LF
|
|
"include_txpower=%s, " BTLE_LF
|
|
"min_interval=%d, " BTLE_LF
|
|
"max_interval=%d, " BTLE_LF
|
|
"appearance=%d, " BTLE_LF
|
|
"manufacturer_len=%d, " BTLE_LF
|
|
"p_manufacturer_data=%s, " BTLE_LF
|
|
"service_data_len=%d, " BTLE_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, ", " BTLE_LF "flag=%d" BTLE_LF , self->adv_data.flag);
|
|
mp_printf(print, ")");
|
|
}
|
|
|
|
// bluetooth.init(...)
|
|
|
|
//-----------------------------------------
|
|
STATIC mp_obj_t btle_init(mp_obj_t self_in)
|
|
{
|
|
btle_obj_t * self = (btle_obj_t*)self_in;
|
|
|
|
if (bluetooth_enabled) return mp_const_none;
|
|
|
|
if (item_mut == NULL) {
|
|
item_mut = xSemaphoreCreateMutex();
|
|
xSemaphoreGive(item_mut);
|
|
}
|
|
|
|
if (callback_q == NULL) {
|
|
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);
|
|
}
|
|
|
|
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 == BTLE_STATE_DEINIT) {
|
|
|
|
self->state = BTLE_STATE_INIT;
|
|
|
|
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
|
if (esp_bt_controller_init(&bt_cfg) != ESP_OK) {
|
|
mp_raise_msg(&mp_type_OSError, "esp_bt_controller_init() failed");
|
|
}
|
|
|
|
// Enable Bluetooth dual mode
|
|
if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) {
|
|
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");
|
|
}
|
|
|
|
if (esp_bluedroid_enable() != ESP_OK) {
|
|
mp_raise_msg(&mp_type_OSError, "esp_bluedroid_enable() failed");
|
|
}
|
|
|
|
|
|
#if CONFIG_GATTS_ENABLE
|
|
if (esp_ble_gatts_register_callback(btle_gatts_event_handler) != ESP_OK) {
|
|
mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_register_callback() failed");
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_GATTC_ENABLE
|
|
if (esp_ble_gattc_register_callback(btle_gattc_event_handler) != ESP_OK) {
|
|
mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_register_callback() failed");
|
|
}
|
|
#endif
|
|
|
|
if (esp_ble_gap_register_callback(btle_gap_event_handler) != ESP_OK) {
|
|
mp_raise_msg(&mp_type_OSError, "esp_ble_gap_register_callback() failed");
|
|
}
|
|
|
|
#if CONFIG_GATTS_ENABLE
|
|
if (esp_ble_gatts_app_register(0) != ESP_OK) {
|
|
mp_raise_msg(&mp_type_OSError, "esp_ble_gatts_app_register() failed");
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_GATTC_ENABLE
|
|
if (esp_ble_gattc_app_register(1) != ESP_OK) {
|
|
mp_raise_msg(&mp_type_OSError, "esp_ble_gattc_app_register() failed");
|
|
}
|
|
#endif
|
|
|
|
}
|
|
return mp_const_none;
|
|
}
|
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(btle_init_obj, btle_init);
|
|
|
|
STATIC mp_obj_t btle_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
|
printf("enter btle_make_new\n");
|
|
btle_obj_t *self = btle_get_singleton();
|
|
if (n_args != 0 || n_kw != 0) {
|
|
mp_raise_TypeError("Constructor takes no arguments");
|
|
}
|
|
|
|
btle_init(self);
|
|
return MP_OBJ_FROM_PTR(self);
|
|
}
|
|
|
|
STATIC void btle_adv_updated() {
|
|
btle_obj_t* self = btle_get_singleton();
|
|
esp_ble_gap_stop_advertising();
|
|
esp_ble_gap_config_adv_data(&self->adv_data);
|
|
|
|
// Restart will be handled in btle_gap_event_handler
|
|
}
|
|
|
|
STATIC mp_obj_t btle_adv_params(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) {
|
|
btle_obj_t *bluetooth = btle_get_singleton();
|
|
|
|
if (bluetooth->state != BTLE_STATE_INIT) {
|
|
mp_raise_msg(&mp_type_OSError, "bluetooth is deinit");
|
|
}
|
|
|
|
bool changed = false;
|
|
|
|
enum {
|
|
// params
|
|
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 = -1} },
|
|
{ MP_QSTR_int_max, 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 }},
|
|
{ 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_arg_val_t args[MP_ARRAY_SIZE(allowed_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 };
|
|
|
|
// 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)) {
|
|
BAD_PEER("peer addr ");
|
|
}
|
|
|
|
mp_get_buffer(args[ARG_peer_addr].u_obj, &peer_addr_buf, MP_BUFFER_READ);
|
|
if (peer_addr_buf.len != ESP_BD_ADDR_LEN) {
|
|
BAD_PEER("peer addr ");
|
|
}
|
|
}
|
|
|
|
|
|
// 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
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_int_max].u_int != -1) {
|
|
bluetooth->adv_params.adv_int_max = args[ARG_int_max].u_int * 1.6;
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_type].u_int != -1) {
|
|
bluetooth->adv_params.adv_type = args[ARG_type].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_own_addr_type].u_int != -1) {
|
|
bluetooth->adv_params.own_addr_type = args[ARG_own_addr_type].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (peer_addr_buf.buf != NULL) {
|
|
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) {
|
|
bluetooth->adv_params.peer_addr_type = args[ARG_peer_addr_type].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_channel_map].u_int != -1) {
|
|
bluetooth->adv_params.channel_map = args[ARG_channel_map].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_filter_policy].u_int != -1) {
|
|
bluetooth->adv_params.adv_filter_policy = args[ARG_filter_policy].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (changed) {
|
|
btle_adv_updated();
|
|
}
|
|
|
|
return mp_const_none;
|
|
|
|
|
|
}
|
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(btle_adv_params_obj, 1, btle_adv_params);
|
|
|
|
STATIC mp_obj_t btle_adv_data(size_t n_args, const mp_obj_t *pos_args, mp_map_t * kw_args) {
|
|
btle_obj_t *bluetooth = btle_get_singleton();
|
|
|
|
if (bluetooth->state != BTLE_STATE_INIT) {
|
|
mp_raise_msg(&mp_type_OSError, "bluetooth is deinit");
|
|
}
|
|
|
|
bool changed = false;
|
|
bool unset_man_name = false;
|
|
bool unset_dev_name = false;
|
|
bool unset_uuid = false;
|
|
|
|
enum {
|
|
// data
|
|
ARG_is_scan_rsp,
|
|
ARG_dev_name,
|
|
ARG_man_name,
|
|
ARG_inc_txpower,
|
|
ARG_int_min,
|
|
ARG_int_max,
|
|
ARG_appearance,
|
|
ARG_uuid,
|
|
ARG_flags
|
|
};
|
|
|
|
static const mp_arg_t allowed_args[] = {
|
|
{ MP_QSTR_is_scan_rsp, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = NULL}},
|
|
{ MP_QSTR_dev_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }},
|
|
{ MP_QSTR_man_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }},
|
|
{ MP_QSTR_inc_tx_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = NULL }},
|
|
{ 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_appearance, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1 }},
|
|
{ MP_QSTR_uuid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = NULL }},
|
|
{ MP_QSTR_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(0, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
|
|
|
mp_buffer_info_t man_name_buf = { 0 };
|
|
mp_buffer_info_t dev_name_buf = { 0 };
|
|
mp_buffer_info_t uuid_buf = { 0 };
|
|
|
|
// pre-check complex types
|
|
|
|
// man_name
|
|
if (args[ARG_man_name].u_obj != NULL) {
|
|
if (mp_obj_get_type(args[ARG_man_name].u_obj) == mp_const_none) {
|
|
unset_man_name = true;
|
|
} else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_man_name].u_obj)) {
|
|
mp_raise_ValueError("man_name must be type str or bytes");
|
|
}
|
|
mp_obj_str_get_buffer(args[ARG_man_name].u_obj, &man_name_buf, MP_BUFFER_READ);
|
|
}
|
|
|
|
// dev_name
|
|
if (args[ARG_dev_name].u_obj != NULL) {
|
|
if (mp_obj_get_type(args[ARG_dev_name].u_obj) == mp_const_none) {
|
|
unset_dev_name = true;
|
|
} else if (!MP_OBJ_IS_STR_OR_BYTES(args[ARG_dev_name].u_obj)) {
|
|
mp_raise_ValueError("dev_name must be type str or bytes");
|
|
}
|
|
mp_obj_str_get_buffer(args[ARG_dev_name].u_obj, &dev_name_buf, MP_BUFFER_READ);
|
|
}
|
|
|
|
// uuid
|
|
if (args[ARG_uuid].u_obj != NULL) {
|
|
if (mp_obj_get_type(args[ARG_uuid].u_obj) == mp_const_none) {
|
|
unset_uuid = true;
|
|
} else if (!MP_OBJ_IS_TYPE(mp_obj_get_type(args[ARG_uuid].u_obj), &mp_type_bytearray)) {
|
|
BAD_UUID("uuid ");
|
|
}
|
|
|
|
mp_get_buffer(args[ARG_uuid].u_obj, &uuid_buf, MP_BUFFER_READ);
|
|
if (uuid_buf.len != UUID_LEN) {
|
|
// FIXME: Is length really a fixed amount?
|
|
BAD_UUID("uuid ");
|
|
}
|
|
}
|
|
|
|
// update esp_ble_data_t
|
|
|
|
if (args[ARG_is_scan_rsp].u_obj != NULL) {
|
|
bluetooth->adv_data.set_scan_rsp = mp_obj_is_true(args[ARG_is_scan_rsp].u_obj);
|
|
changed = true;
|
|
}
|
|
|
|
if (unset_dev_name) {
|
|
esp_ble_gap_set_device_name("");
|
|
bluetooth->adv_data.include_name = false;
|
|
} else if (dev_name_buf.buf != NULL) {
|
|
esp_ble_gap_set_device_name(dev_name_buf.buf);
|
|
bluetooth->adv_data.include_name = dev_name_buf.len > 0;
|
|
changed = true;
|
|
}
|
|
|
|
if (unset_man_name || man_name_buf.buf != NULL) {
|
|
if (bluetooth->adv_data.p_manufacturer_data != NULL) {
|
|
FREE(bluetooth->adv_data.p_manufacturer_data);
|
|
bluetooth->adv_data.p_manufacturer_data = NULL;
|
|
}
|
|
|
|
bluetooth->adv_data.manufacturer_len = man_name_buf.len;
|
|
if (man_name_buf.len > 0) {
|
|
bluetooth->adv_data.p_manufacturer_data = MALLOC(man_name_buf.len);
|
|
memcpy(bluetooth->adv_data.p_manufacturer_data, man_name_buf.buf, man_name_buf.len);
|
|
}
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_inc_txpower].u_obj != NULL) {
|
|
bluetooth->adv_data.include_txpower = mp_obj_is_true(args[ARG_inc_txpower].u_obj);
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_int_min].u_int != -1) {
|
|
bluetooth->adv_data.min_interval = args[ARG_int_min].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_int_max].u_int != -1) {
|
|
bluetooth->adv_data.max_interval = args[ARG_int_max].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_appearance].u_int != -1) {
|
|
bluetooth->adv_data.appearance = args[ARG_appearance].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (unset_uuid || uuid_buf.buf != NULL) {
|
|
|
|
if (bluetooth->adv_data.p_service_uuid != NULL) {
|
|
FREE(bluetooth->adv_data.p_service_uuid);
|
|
bluetooth->adv_data.p_service_uuid = NULL;
|
|
}
|
|
|
|
bluetooth->adv_data.service_uuid_len = uuid_buf.len;
|
|
if (uuid_buf.len > 0) {
|
|
bluetooth->adv_data.p_service_uuid = MALLOC(uuid_buf.len);
|
|
bluetooth->adv_data.service_uuid_len = uuid_buf.len;
|
|
memcpy(bluetooth->adv_data.p_service_uuid, uuid_buf.buf, uuid_buf.len);
|
|
}
|
|
changed = true;
|
|
}
|
|
|
|
if (args[ARG_flags].u_int != -1) {
|
|
bluetooth->adv_data.flag = args[ARG_flags].u_int;
|
|
changed = true;
|
|
}
|
|
|
|
if (changed) {
|
|
btle_adv_updated();
|
|
}
|
|
|
|
return mp_const_none;
|
|
}
|
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(btle_adv_data_obj, 1, btle_adv_data);
|
|
|
|
STATIC mp_obj_t btle_ble_adv_enable(mp_obj_t self_in, mp_obj_t enable_in) {
|
|
btle_obj_t * self = MP_OBJ_TO_PTR(self_in);
|
|
bool enable = mp_obj_is_true(enable_in);
|
|
if (enable) {
|
|
esp_ble_adv_params_t params = {
|
|
.adv_int_min = MSEC_0_625_TO_UNIT(100), // 100ms
|
|
.adv_int_max = MSEC_0_625_TO_UNIT(100), // 100ms
|
|
.adv_type = ADV_TYPE_IND,
|
|
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
|
|
.channel_map = ADV_CHNL_ALL,
|
|
.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
|
};
|
|
esp_ble_gap_start_advertising(¶ms);
|
|
} else {
|
|
esp_ble_gap_stop_advertising();
|
|
}
|
|
self->advertising = enable;
|
|
return mp_const_none;
|
|
}
|
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(btle_ble_adv_enable_obj, btle_ble_adv_enable);
|
|
|
|
|
|
STATIC const mp_rom_map_elem_t btle_locals_dict_table[] = {
|
|
// instance methods
|
|
|
|
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&btle_init_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_adv_params), MP_ROM_PTR(&btle_adv_params_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_adv_data), MP_ROM_PTR(&btle_adv_data_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&btle_ble_adv_enable_obj) },
|
|
/*
|
|
{ MP_ROM_QSTR(MP_QSTR_ble_settings), MP_ROM_PTR(&btle_ble_settings_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_ble_adv_enable), MP_ROM_PTR(&btle_ble_adv_enable_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&btle_deinit_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&btle_connect_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&btle_gatts_service_type) },
|
|
{ MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&btle_services_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_conns), MP_ROM_PTR(&btle_conns_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&btle_callback_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_scan_start), MP_ROM_PTR(&btle_scan_start_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_scan_stop), MP_ROM_PTR(&btle_scan_stop_obj) },
|
|
{ MP_ROM_QSTR(MP_QSTR_is_scanning), MP_ROM_PTR(&btle_is_scanning_obj) },
|
|
|
|
// class constants
|
|
|
|
// Callback types
|
|
{ MP_ROM_QSTR(MP_QSTR_CONNECT), MP_ROM_INT(BTLE_GATTS_CONNECT) },
|
|
{ MP_ROM_QSTR(MP_QSTR_DISCONNECT), MP_ROM_INT(BTLE_GATTS_DISCONNECT) },
|
|
{ MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(BTLE_READ) },
|
|
{ MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(BTLE_WRITE) },
|
|
{ MP_ROM_QSTR(MP_QSTR_NOTIFY), MP_ROM_INT(BTLE_NOTIFY) },
|
|
{ MP_ROM_QSTR(MP_QSTR_SCAN_RES), MP_ROM_INT(BTLE_GATTC_SCAN_RES) },
|
|
{ MP_ROM_QSTR(MP_QSTR_SCAN_CMPL), MP_ROM_INT(BTLE_GATTC_SCAN_CMPL) },
|
|
|
|
// 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) },
|
|
|
|
// 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) },
|
|
|
|
// 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) },
|
|
{ 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(btle_locals_dict, btle_locals_dict_table);
|
|
|
|
const mp_obj_type_t btle_type = {
|
|
{ &mp_type_type },
|
|
.name = MP_QSTR_Bluetooth,
|
|
.print = btle_print,
|
|
.make_new = btle_make_new,
|
|
.locals_dict = (mp_obj_dict_t*)&btle_locals_dict,
|
|
};
|
|
|
|
|