service discovery works; need to work on char and descriptor discovery
This commit is contained in:
parent
a995a5c58f
commit
ac95106b88
|
@ -149,6 +149,8 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *
|
||||||
}
|
}
|
||||||
|
|
||||||
descriptor->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(descriptor));
|
descriptor->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(descriptor));
|
||||||
|
// Include this desriptor in the service handles range.
|
||||||
|
self->service->end_handle = descriptor->handle;
|
||||||
|
|
||||||
// Link together all the descriptors for this characteristic.
|
// Link together all the descriptors for this characteristic.
|
||||||
descriptor->next = self->descriptor_list;
|
descriptor->next = self->descriptor_list;
|
||||||
|
|
|
@ -42,6 +42,8 @@ uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uu
|
||||||
vm_used_ble = true;
|
vm_used_ble = true;
|
||||||
|
|
||||||
self->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(self));
|
self->handle = bleio_adapter_add_attribute(&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(self));
|
||||||
|
self->start_handle = self->handle;
|
||||||
|
self->end_handle = self->handle;
|
||||||
if (self->handle == BLE_GATT_HANDLE_INVALID) {
|
if (self->handle == BLE_GATT_HANDLE_INVALID) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -90,10 +92,12 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
|
||||||
}
|
}
|
||||||
characteristic->decl_handle = bleio_adapter_add_attribute(
|
characteristic->decl_handle = bleio_adapter_add_attribute(
|
||||||
&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic));
|
&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic));
|
||||||
// This is the value handle
|
// This is the value handle.
|
||||||
characteristic->handle = bleio_adapter_add_attribute(
|
characteristic->handle = bleio_adapter_add_attribute(
|
||||||
&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic));
|
&common_hal_bleio_adapter_obj, MP_OBJ_TO_PTR(characteristic));
|
||||||
|
|
||||||
|
self->end_handle = characteristic->handle;
|
||||||
|
|
||||||
if (characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) {
|
if (characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE)) {
|
||||||
// We need a CCCD.
|
// We need a CCCD.
|
||||||
bleio_descriptor_obj_t *cccd = m_new_obj(bleio_descriptor_obj_t);
|
bleio_descriptor_obj_t *cccd = m_new_obj(bleio_descriptor_obj_t);
|
||||||
|
@ -107,6 +111,8 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
|
||||||
cccd->handle = cccd_handle;
|
cccd->handle = cccd_handle;
|
||||||
characteristic->cccd_handle = cccd_handle;
|
characteristic->cccd_handle = cccd_handle;
|
||||||
common_hal_bleio_characteristic_add_descriptor(characteristic, cccd);
|
common_hal_bleio_characteristic_add_descriptor(characteristic, cccd);
|
||||||
|
|
||||||
|
self->end_handle = cccd_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #if CIRCUITPY_VERBOSE_BLE
|
// #if CIRCUITPY_VERBOSE_BLE
|
||||||
|
|
|
@ -43,7 +43,7 @@ typedef struct bleio_service_obj {
|
||||||
// A local service doesn't know the connection.
|
// A local service doesn't know the connection.
|
||||||
mp_obj_t connection;
|
mp_obj_t connection;
|
||||||
mp_obj_list_t *characteristic_list;
|
mp_obj_list_t *characteristic_list;
|
||||||
// Range of attribute handles of this remote service.
|
// Range of attribute handles of this service.
|
||||||
uint16_t start_handle;
|
uint16_t start_handle;
|
||||||
uint16_t end_handle;
|
uint16_t end_handle;
|
||||||
struct bleio_service_obj* next;
|
struct bleio_service_obj* next;
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
#include "shared-bindings/_bleio/UUID.h"
|
#include "shared-bindings/_bleio/UUID.h"
|
||||||
#include "supervisor/shared/bluetooth.h"
|
#include "supervisor/shared/bluetooth.h"
|
||||||
|
|
||||||
|
bool vm_used_ble;
|
||||||
|
|
||||||
void check_hci_error(hci_result_t result) {
|
void check_hci_error(hci_result_t result) {
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case HCI_OK:
|
case HCI_OK:
|
||||||
|
@ -110,6 +112,8 @@ void check_hci_error(hci_result_t result) {
|
||||||
|
|
||||||
// Turn off BLE on a reset or reload.
|
// Turn off BLE on a reset or reload.
|
||||||
void bleio_reset() {
|
void bleio_reset() {
|
||||||
|
bleio_hci_reset();
|
||||||
|
|
||||||
if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) {
|
if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,6 @@ void check_gatt_status(uint16_t gatt_status);
|
||||||
void check_sec_status(uint8_t sec_status);
|
void check_sec_status(uint8_t sec_status);
|
||||||
|
|
||||||
// Track if the user code modified the BLE state to know if we need to undo it on reload.
|
// Track if the user code modified the BLE state to know if we need to undo it on reload.
|
||||||
bool vm_used_ble;
|
extern bool vm_used_ble;
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_INIT_H
|
||||||
|
|
|
@ -116,7 +116,7 @@ STATIC void check_and_save_expected_rsp(uint16_t conn_handle, uint8_t opcode, ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void att_init(void) {
|
void bleio_att_reset(void) {
|
||||||
max_mtu = BT_ATT_DEFAULT_LE_MTU;
|
max_mtu = BT_ATT_DEFAULT_LE_MTU;
|
||||||
timeout = 5000;
|
timeout = 5000;
|
||||||
long_write_handle = BLE_GATT_HANDLE_INVALID;
|
long_write_handle = BLE_GATT_HANDLE_INVALID;
|
||||||
|
@ -884,6 +884,8 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen,
|
||||||
struct bt_att_read_group_req *req = (struct bt_att_read_group_req *) data;
|
struct bt_att_read_group_req *req = (struct bt_att_read_group_req *) data;
|
||||||
uint16_t type_uuid = req->uuid[0] | (req->uuid[1] << 8);
|
uint16_t type_uuid = req->uuid[0] | (req->uuid[1] << 8);
|
||||||
|
|
||||||
|
// We only support returning services for BT_ATT_OP_READ_GROUP_REQ, which is typically used
|
||||||
|
// for service discovery.
|
||||||
if (dlen != sizeof(struct bt_att_read_group_req) + sizeof(type_uuid) ||
|
if (dlen != sizeof(struct bt_att_read_group_req) + sizeof(type_uuid) ||
|
||||||
(type_uuid != BLE_TYPE_PRIMARY_SERVICE &&
|
(type_uuid != BLE_TYPE_PRIMARY_SERVICE &&
|
||||||
type_uuid != BLE_TYPE_SECONDARY_SERVICE)) {
|
type_uuid != BLE_TYPE_SECONDARY_SERVICE)) {
|
||||||
|
@ -897,7 +899,7 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen,
|
||||||
} rsp_t;
|
} rsp_t;
|
||||||
|
|
||||||
uint8_t rsp_bytes[mtu];
|
uint8_t rsp_bytes[mtu];
|
||||||
rsp_t *rsp = (rsp_t *) &rsp_bytes;
|
rsp_t *rsp = (rsp_t *) rsp_bytes;
|
||||||
rsp->h.code = BT_ATT_OP_READ_GROUP_RSP;
|
rsp->h.code = BT_ATT_OP_READ_GROUP_RSP;
|
||||||
rsp->r.len = 0;
|
rsp->r.len = 0;
|
||||||
|
|
||||||
|
@ -907,13 +909,22 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen,
|
||||||
bool no_data = true;
|
bool no_data = true;
|
||||||
|
|
||||||
// All the data chunks must have uuid's that are the same size.
|
// All the data chunks must have uuid's that are the same size.
|
||||||
// Keep track fo the first one to make sure.
|
// Keep track of the first one to make sure.
|
||||||
size_t sizeof_first_service_uuid = 0;
|
size_t sizeof_first_service_uuid = 0;
|
||||||
|
|
||||||
|
// Size of a single bt_att_group_data chunk. Start with the intial size, and
|
||||||
|
// add the uuid size in the loop below.
|
||||||
|
size_t data_length = sizeof(struct bt_att_group_data);
|
||||||
|
|
||||||
const uint16_t max_attribute_handle = bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj);
|
const uint16_t max_attribute_handle = bleio_adapter_max_attribute_handle(&common_hal_bleio_adapter_obj);
|
||||||
for (uint16_t handle = req->start_handle;
|
for (uint16_t handle = req->start_handle;
|
||||||
handle <= max_attribute_handle && handle <= req->end_handle;
|
handle <= max_attribute_handle && handle <= req->end_handle;
|
||||||
handle++) {
|
handle++) {
|
||||||
no_data = false;
|
|
||||||
|
if (rsp_length + data_length > mtu) {
|
||||||
|
// The next possible bt_att_group_data chunk won't fit. The response is full.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
|
mp_obj_t *attribute_obj = bleio_adapter_get_attribute(&common_hal_bleio_adapter_obj, handle);
|
||||||
if (type_uuid != bleio_attribute_type_uuid(attribute_obj)) {
|
if (type_uuid != bleio_attribute_type_uuid(attribute_obj)) {
|
||||||
|
@ -925,33 +936,28 @@ void process_read_by_group_req(uint16_t conn_handle, uint16_t mtu, uint8_t dlen,
|
||||||
|
|
||||||
// Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute
|
// Is this a 16-bit or a 128-bit uuid? It must match in size with any previous attribute
|
||||||
// in this transmission.
|
// in this transmission.
|
||||||
const uint8_t sizeof_service_uuid = common_hal_bleio_uuid_get_size(service->uuid) / 8;
|
const uint32_t sizeof_service_uuid = common_hal_bleio_uuid_get_size(service->uuid) / 8;
|
||||||
if (sizeof_first_service_uuid == 0) {
|
if (sizeof_first_service_uuid == 0) {
|
||||||
sizeof_first_service_uuid = sizeof_service_uuid;
|
sizeof_first_service_uuid = sizeof_service_uuid;
|
||||||
|
data_length += sizeof_service_uuid;
|
||||||
} else if (sizeof_first_service_uuid != sizeof_service_uuid) {
|
} else if (sizeof_first_service_uuid != sizeof_service_uuid) {
|
||||||
// Mismatched sizes. Transmit just what we have so far in this batch.
|
// Mismatched sizes, which can't be in the same batch.
|
||||||
|
// Transmit just what we have so far in this batch.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size of bt_att_group_data chunk with uuid.
|
|
||||||
const uint16_t data_length = sizeof(struct bt_att_group_data) + sizeof_service_uuid;
|
|
||||||
|
|
||||||
if (rsp_length + data_length > mtu) {
|
|
||||||
// No room for another bt_att_group_data chunk.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass the length of ONE bt_att_group_data chunk. There may be multiple ones in this transmission.
|
// Pass the length of ONE bt_att_group_data chunk. There may be multiple ones in this transmission.
|
||||||
rsp->r.len = data_length;
|
rsp->r.len = data_length;
|
||||||
|
|
||||||
uint8_t group_data_bytes[data_length];
|
struct bt_att_group_data *group_data = (struct bt_att_group_data *) &rsp_bytes[rsp_length];
|
||||||
struct bt_att_group_data *group_data = (struct bt_att_group_data *) group_data_bytes;
|
|
||||||
|
|
||||||
group_data->start_handle = service->start_handle;
|
group_data->start_handle = service->start_handle;
|
||||||
group_data->end_handle = service->end_handle;
|
group_data->end_handle = service->end_handle;
|
||||||
common_hal_bleio_uuid_pack_into(service->uuid, group_data->value);
|
common_hal_bleio_uuid_pack_into(service->uuid, group_data->value);
|
||||||
|
|
||||||
rsp_length += data_length;
|
rsp_length += data_length;
|
||||||
|
no_data = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (no_data) {
|
if (no_data) {
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include "hci_include/att.h"
|
#include "hci_include/att.h"
|
||||||
#include "hci_include/att_internal.h"
|
#include "hci_include/att_internal.h"
|
||||||
|
|
||||||
|
void bleio_att_reset(void);
|
||||||
|
|
||||||
//FIX BLEDevice att_central(void);
|
//FIX BLEDevice att_central(void);
|
||||||
//FIX BLERemoteDevice* att_device(uint8_t address_type, const uint8_t address[6]);
|
//FIX BLERemoteDevice* att_device(uint8_t address_type, const uint8_t address[6]);
|
||||||
//FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);
|
//FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);
|
||||||
|
|
|
@ -272,16 +272,18 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hci_init(void) {
|
void bleio_hci_reset(void) {
|
||||||
rx_idx = 0;
|
rx_idx = 0;
|
||||||
pending_pkt = 0;
|
pending_pkt = 0;
|
||||||
hci_poll_in_progress = false;
|
hci_poll_in_progress = false;
|
||||||
|
|
||||||
|
bleio_att_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
hci_result_t hci_poll_for_incoming_pkt_timeout(uint32_t timeout_msecs) {
|
hci_result_t hci_poll_for_incoming_pkt_timeout(uint32_t timeout_msecs) {
|
||||||
uint64_t start = supervisor_ticks_ms64();
|
uint64_t start = supervisor_ticks_ms64();
|
||||||
|
|
||||||
hci_result_t result;
|
hci_result_t result = HCI_OK;
|
||||||
|
|
||||||
while (supervisor_ticks_ms64() - start < timeout_msecs) {
|
while (supervisor_ticks_ms64() - start < timeout_msecs) {
|
||||||
result = hci_poll_for_incoming_pkt();
|
result = hci_poll_for_incoming_pkt();
|
||||||
|
|
|
@ -39,7 +39,7 @@ typedef int hci_result_t;
|
||||||
#define HCI_WRITE_ERROR (-5)
|
#define HCI_WRITE_ERROR (-5)
|
||||||
#define HCI_ATT_ERROR (-6)
|
#define HCI_ATT_ERROR (-6)
|
||||||
|
|
||||||
void hci_init(void);
|
void bleio_hci_reset(void);
|
||||||
|
|
||||||
hci_result_t hci_disconnect(uint16_t handle);
|
hci_result_t hci_disconnect(uint16_t handle);
|
||||||
|
|
||||||
|
|
8
main.c
8
main.c
|
@ -105,6 +105,12 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) {
|
||||||
static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]);
|
static size_t PLACE_IN_DTCM_BSS(_pystack[CIRCUITPY_PYSTACK_SIZE / sizeof(size_t)]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void reset_devices(void) {
|
||||||
|
#if CIRCUITPY_BLEIO_HCI
|
||||||
|
bleio_reset();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void start_mp(supervisor_allocation* heap) {
|
void start_mp(supervisor_allocation* heap) {
|
||||||
reset_status_led();
|
reset_status_led();
|
||||||
autoreload_stop();
|
autoreload_stop();
|
||||||
|
@ -459,6 +465,8 @@ int __attribute__((used)) main(void) {
|
||||||
|
|
||||||
// Reset everything and prep MicroPython to run boot.py.
|
// Reset everything and prep MicroPython to run boot.py.
|
||||||
reset_port();
|
reset_port();
|
||||||
|
// Port-independent devices, like CIRCUITPY_BLEIO_HCI.
|
||||||
|
reset_devices();
|
||||||
reset_board();
|
reset_board();
|
||||||
|
|
||||||
// Turn on autoreload by default but before boot.py in case it wants to change it.
|
// Turn on autoreload by default but before boot.py in case it wants to change it.
|
||||||
|
|
|
@ -112,7 +112,7 @@ CFLAGS += $(OPTIMIZATION_FLAGS) -DNDEBUG
|
||||||
$(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY))
|
$(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY))
|
||||||
#Debugging/Optimization
|
#Debugging/Optimization
|
||||||
ifeq ($(DEBUG), 1)
|
ifeq ($(DEBUG), 1)
|
||||||
CFLAGS += -ggdb -Og
|
CFLAGS += -ggdb3 -Og
|
||||||
# You may want to disable -flto if it interferes with debugging.
|
# You may want to disable -flto if it interferes with debugging.
|
||||||
CFLAGS += -flto -flto-partition=none
|
CFLAGS += -flto -flto-partition=none
|
||||||
# You may want to enable these flags to make setting breakpoints easier.
|
# You may want to enable these flags to make setting breakpoints easier.
|
||||||
|
|
Loading…
Reference in New Issue