ble_uart_echo_test works
This commit is contained in:
parent
06f3b4048a
commit
44c9c43cd1
@ -60,6 +60,8 @@
|
|||||||
#define UNIT_1_25_MS (1250)
|
#define UNIT_1_25_MS (1250)
|
||||||
#define UNIT_10_MS (10000)
|
#define UNIT_10_MS (10000)
|
||||||
|
|
||||||
|
#define MAX_ADVERTISEMENT_SIZE (31)
|
||||||
|
|
||||||
// TODO make this settable from Python.
|
// TODO make this settable from Python.
|
||||||
#define DEFAULT_TX_POWER 0 // 0 dBm
|
#define DEFAULT_TX_POWER 0 // 0 dBm
|
||||||
#define MAX_ANONYMOUS_ADV_TIMEOUT_SECS (60*15)
|
#define MAX_ANONYMOUS_ADV_TIMEOUT_SECS (60*15)
|
||||||
@ -179,13 +181,31 @@ STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get various values and limits set by the adapter.
|
// Get various values and limits set by the adapter.
|
||||||
STATIC void bleio_adapter_get_info(bleio_adapter_obj_t *self) {
|
// Set event mask.
|
||||||
|
STATIC void bleio_adapter_setup(bleio_adapter_obj_t *self) {
|
||||||
|
|
||||||
|
// Get version information.
|
||||||
|
if (hci_read_local_version(&self->hci_version, &self->hci_revision, &self->lmp_version,
|
||||||
|
&self->manufacturer, &self->lmp_subversion) != HCI_OK) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Could not read HCI version"));
|
||||||
|
}
|
||||||
// Get supported features.
|
// Get supported features.
|
||||||
if (hci_le_read_local_supported_features(self->features) != HCI_OK) {
|
if (hci_le_read_local_supported_features(self->features) != HCI_OK) {
|
||||||
mp_raise_bleio_BluetoothError(translate("Could not read BLE features"));
|
mp_raise_bleio_BluetoothError(translate("Could not read BLE features"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enabled desired events.
|
||||||
|
// Most importantly, includes:
|
||||||
|
// BT_EVT_MASK_LE_META_EVENT BT_EVT_BIT(61)
|
||||||
|
if (hci_set_event_mask(0x3FFFFFFFFFFFFFFF) != HCI_OK) {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Could not set event mask"));
|
||||||
|
}
|
||||||
|
// The default events for LE are:
|
||||||
|
// BT_EVT_MASK_LE_CONN_COMPLETE, BT_EVT_MASK_LE_ADVERTISING_REPORT,
|
||||||
|
// BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE, BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE
|
||||||
|
// BT_EVT_MASK_LE_LTK_REQUEST.
|
||||||
|
// That's all we need right now, so we don't bother to set the LE event mask.
|
||||||
|
|
||||||
// Get ACL buffer info.
|
// Get ACL buffer info.
|
||||||
uint16_t le_max_len;
|
uint16_t le_max_len;
|
||||||
uint8_t le_max_num;
|
uint8_t le_max_num;
|
||||||
@ -213,7 +233,7 @@ STATIC void bleio_adapter_get_info(bleio_adapter_obj_t *self) {
|
|||||||
}
|
}
|
||||||
self->max_adv_data_len = max_adv_data_len;
|
self->max_adv_data_len = max_adv_data_len;
|
||||||
} else {
|
} else {
|
||||||
self->max_adv_data_len = 31;
|
self->max_adv_data_len = MAX_ADVERTISEMENT_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,7 +246,7 @@ void common_hal_bleio_adapter_hci_uart_init(bleio_adapter_obj_t *self, busio_uar
|
|||||||
self->enabled = false;
|
self->enabled = false;
|
||||||
|
|
||||||
common_hal_bleio_adapter_set_enabled(self, true);
|
common_hal_bleio_adapter_set_enabled(self, true);
|
||||||
bleio_adapter_get_info(self);
|
bleio_adapter_setup(self);
|
||||||
bleio_adapter_reset_name(self);
|
bleio_adapter_reset_name(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,14 +497,10 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
|
|||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The nRF SD 6.1.0 can only do one concurrent advertisement so share the advertising handle.
|
|
||||||
//FIX uint8_t adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
|
|
||||||
|
|
||||||
STATIC void check_data_fit(size_t data_len, bool connectable) {
|
STATIC void check_data_fit(size_t data_len, bool connectable) {
|
||||||
//FIX if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED ||
|
if (data_len > MAX_ADVERTISEMENT_SIZE) {
|
||||||
// (connectable && data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED)) {
|
mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||||
// mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// STATIC bool advertising_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
|
// STATIC bool advertising_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
|
||||||
@ -604,8 +620,9 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self,
|
|||||||
0x00 // filter policy: no filter
|
0x00 // filter policy: no filter
|
||||||
));
|
));
|
||||||
|
|
||||||
// The HCI commands expect 31 octets, even though the actual data length may be shorter.
|
// The HCI commands expect MAX_ADVERTISEMENT_SIZE (31)octets,
|
||||||
uint8_t full_data[31] = { 0 };
|
// even though the actual data length may be shorter.
|
||||||
|
uint8_t full_data[MAX_ADVERTISEMENT_SIZE] = { 0 };
|
||||||
memcpy(full_data, advertising_data, MIN(sizeof(full_data), advertising_data_len));
|
memcpy(full_data, advertising_data, MIN(sizeof(full_data), advertising_data_len));
|
||||||
check_hci_error(hci_le_set_advertising_data(advertising_data_len, full_data));
|
check_hci_error(hci_le_set_advertising_data(advertising_data_len, full_data));
|
||||||
memset(full_data, 0, sizeof(full_data));
|
memset(full_data, 0, sizeof(full_data));
|
||||||
@ -636,7 +653,7 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
|
|||||||
check_data_fit(advertising_data_bufinfo->len, connectable);
|
check_data_fit(advertising_data_bufinfo->len, connectable);
|
||||||
check_data_fit(scan_response_data_bufinfo->len, connectable);
|
check_data_fit(scan_response_data_bufinfo->len, connectable);
|
||||||
|
|
||||||
if (advertising_data_bufinfo->len > 31 && scan_response_data_bufinfo->len > 0) {
|
if (advertising_data_bufinfo->len > MAX_ADVERTISEMENT_SIZE && scan_response_data_bufinfo->len > 0) {
|
||||||
mp_raise_bleio_BluetoothError(translate("Extended advertisements with scan response not supported."));
|
mp_raise_bleio_BluetoothError(translate("Extended advertisements with scan response not supported."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,13 @@ typedef struct _bleio_adapter_obj_t {
|
|||||||
bool circuitpython_advertising;
|
bool circuitpython_advertising;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
|
// HCI adapter version info.
|
||||||
|
uint8_t hci_version;
|
||||||
|
uint8_t lmp_version;
|
||||||
|
uint16_t hci_revision;
|
||||||
|
uint16_t manufacturer;
|
||||||
|
uint16_t lmp_subversion;
|
||||||
|
|
||||||
// Used to monitor advertising timeout for legacy avertising.
|
// Used to monitor advertising timeout for legacy avertising.
|
||||||
uint64_t advertising_start_ticks;
|
uint64_t advertising_start_ticks;
|
||||||
uint64_t advertising_timeout_msecs; // If zero, do not check.
|
uint64_t advertising_timeout_msecs; // If zero, do not check.
|
||||||
|
@ -29,7 +29,9 @@
|
|||||||
|
|
||||||
#include "shared-bindings/_bleio/__init__.h"
|
#include "shared-bindings/_bleio/__init__.h"
|
||||||
#include "shared-bindings/_bleio/Characteristic.h"
|
#include "shared-bindings/_bleio/Characteristic.h"
|
||||||
|
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
|
||||||
#include "shared-bindings/_bleio/Descriptor.h"
|
#include "shared-bindings/_bleio/Descriptor.h"
|
||||||
|
#include "shared-bindings/_bleio/PacketBuffer.h"
|
||||||
#include "shared-bindings/_bleio/Service.h"
|
#include "shared-bindings/_bleio/Service.h"
|
||||||
|
|
||||||
#include "common-hal/_bleio/Adapter.h"
|
#include "common-hal/_bleio/Adapter.h"
|
||||||
@ -47,8 +49,12 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
|
|||||||
self->props = props;
|
self->props = props;
|
||||||
self->read_perm = read_perm;
|
self->read_perm = read_perm;
|
||||||
self->write_perm = write_perm;
|
self->write_perm = write_perm;
|
||||||
self->descriptor_linked_list = mp_obj_new_list(0, NULL);
|
self->descriptor_list = mp_obj_new_list(0, NULL);
|
||||||
self->watchers_list = mp_obj_new_list(0, NULL);
|
self->observer = mp_const_none;
|
||||||
|
self->user_desc = NULL;
|
||||||
|
self->cccd = NULL;
|
||||||
|
self->sccd = NULL;
|
||||||
|
self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||||
|
|
||||||
const mp_int_t max_length_max = 512;
|
const mp_int_t max_length_max = 512;
|
||||||
if (max_length < 0 || max_length > max_length_max) {
|
if (max_length < 0 || max_length > max_length_max) {
|
||||||
@ -62,14 +68,10 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
|
|||||||
} else {
|
} else {
|
||||||
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo);
|
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initial_value_bufinfo != NULL) {
|
|
||||||
common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_linked_list(bleio_characteristic_obj_t *self) {
|
mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) {
|
||||||
return self->descriptor_linked_list;
|
return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items);
|
||||||
}
|
}
|
||||||
|
|
||||||
bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) {
|
bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) {
|
||||||
@ -79,13 +81,19 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character
|
|||||||
size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len) {
|
size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len) {
|
||||||
// Do GATT operations only if this characteristic has been added to a registered service.
|
// Do GATT operations only if this characteristic has been added to a registered service.
|
||||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
//FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
||||||
// self->value is set by evt handler.
|
//FIX read remote chars
|
||||||
return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len);
|
//uint8_t rsp[MAX(len, 512)];
|
||||||
|
//FIX improve att_read_req to write into our requested buffer.
|
||||||
|
// return att_read_req(conn_handle, self->handle, rsp);
|
||||||
|
return 0; //FIX
|
||||||
} else {
|
} else {
|
||||||
// conn_handle is ignored for non-system attributes.
|
mp_buffer_info_t bufinfo;
|
||||||
return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len);
|
if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(buf, bufinfo.buf, MIN(len, bufinfo.len));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,32 +110,40 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self,
|
|||||||
|
|
||||||
// Do GATT operations only if this characteristic has been added to a registered service.
|
// Do GATT operations only if this characteristic has been added to a registered service.
|
||||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
|
|
||||||
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
||||||
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
//FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
// Last argument is true if write-no-reponse desired.
|
if (self->props & CHAR_PROP_WRITE) {
|
||||||
common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo,
|
//FIX writing remote chars
|
||||||
(self->props & CHAR_PROP_WRITE_NO_RESPONSE));
|
//uint8_t rsp[sizeof(bt_att_error_rsp)];
|
||||||
|
//att_write_req(conn_handle, self->handle, bufinfo->buf, bufinfo->len, rsp);
|
||||||
|
} else if (self->props & CHAR_PROP_WRITE_NO_RESPONSE) {
|
||||||
|
//att_write_cmd(conn_handle, self->handle, bufinfo->buff, bufinfo->len);
|
||||||
|
} else {
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Characteristic not writable"));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Always write the value locally even if no connections are active.
|
// Always write the value locally even if no connections are active.
|
||||||
// conn_handle is ignored for non-system attributes, so we use BLE_CONN_HANDLE_INVALID.
|
bleio_characteristic_set_local_value(self, bufinfo);
|
||||||
common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo);
|
|
||||||
// Notify or indicate all active connections.
|
// Notify or indicate all active connections.
|
||||||
uint16_t cccd = 0;
|
|
||||||
|
uint16_t cccd_value = 0;
|
||||||
|
mp_buffer_info_t cccd_bufinfo = {
|
||||||
|
.buf = &cccd_value,
|
||||||
|
.len = sizeof(cccd_value),
|
||||||
|
};
|
||||||
|
|
||||||
const bool notify = self->props & CHAR_PROP_NOTIFY;
|
const bool notify = self->props & CHAR_PROP_NOTIFY;
|
||||||
const bool indicate = self->props & CHAR_PROP_INDICATE;
|
const bool indicate = self->props & CHAR_PROP_INDICATE;
|
||||||
// Read the CCCD value, if there is one.
|
// Read the CCCD value, if there is one.
|
||||||
if ((notify | indicate) && self->cccd_handle != BLE_GATT_HANDLE_INVALID) {
|
if ((notify | indicate) && self->cccd != NULL) {
|
||||||
common_hal_bleio_gatts_read(self->cccd_handle, BLE_CONN_HANDLE_INVALID,
|
common_hal_bleio_descriptor_get_value(self->cccd, cccd_bufinfo.buf, cccd_bufinfo.len);
|
||||||
(uint8_t *) &cccd, sizeof(cccd));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's possible that both notify and indicate are set.
|
// It's possible that both notify and indicate are set.
|
||||||
if (notify && (cccd & CCCD_NOTIFY)) {
|
if (notify && (cccd_value & CCCD_NOTIFY)) {
|
||||||
att_notify(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
|
att_notify(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
|
||||||
}
|
}
|
||||||
if (indicate && (cccd & CCCD_INDICATE)) {
|
if (indicate && (cccd_value & CCCD_INDICATE)) {
|
||||||
att_indicate(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
|
att_indicate(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -153,13 +169,12 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *
|
|||||||
// Include this descriptor in the service handle's range.
|
// Include this descriptor in the service handle's range.
|
||||||
self->service->end_handle = descriptor->handle;
|
self->service->end_handle = descriptor->handle;
|
||||||
|
|
||||||
// Link together all the descriptors for this characteristic.
|
mp_obj_list_append(MP_OBJ_FROM_PTR(self->descriptor_list),
|
||||||
descriptor->next = self->descriptor_linked_list;
|
MP_OBJ_FROM_PTR(descriptor));
|
||||||
self->descriptor_linked_list = descriptor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
|
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
|
||||||
if (self->cccd_handle == BLE_GATT_HANDLE_INVALID) {
|
if (self->cccd == NULL) {
|
||||||
mp_raise_bleio_BluetoothError(translate("No CCCD for this Characteristic"));
|
mp_raise_bleio_BluetoothError(translate("No CCCD for this Characteristic"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,33 +189,12 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
|
|||||||
(notify ? CCCD_NOTIFY : 0) |
|
(notify ? CCCD_NOTIFY : 0) |
|
||||||
(indicate ? CCCD_INDICATE : 0);
|
(indicate ? CCCD_INDICATE : 0);
|
||||||
|
|
||||||
|
//FIX do remote
|
||||||
(void) cccd_value;
|
(void) cccd_value;
|
||||||
//FIX call att_something to set remote CCCD
|
// uint8_t rsp[sizeof(bt_att_error_rsp)];
|
||||||
// ble_gattc_write_params_t write_params = {
|
// if (att_write_req(conn_handle, self->cccd->handle, &cccd_value, sizeof(cccd_value)) == 0) {
|
||||||
// .write_op = BLE_GATT_OP_WRITE_REQ,
|
// mp_raise_bleio_BluetoothError(translate("Could not write CCCD"));
|
||||||
// .handle = self->cccd_handle,
|
|
||||||
// .p_value = (uint8_t *) &cccd_value,
|
|
||||||
// .len = 2,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// while (1) {
|
|
||||||
// uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
|
||||||
// if (err_code == NRF_SUCCESS) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Write with response will return NRF_ERROR_BUSY if the response has not been received.
|
|
||||||
// // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
|
|
||||||
// if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
|
|
||||||
// // We could wait for an event indicating the write is complete, but just retrying is easier.
|
|
||||||
// RUN_BACKGROUND_TASKS;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Some real error occurred.
|
|
||||||
// check_nrf_error(err_code);
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
|
bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||||
@ -208,14 +202,25 @@ bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_b
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (bufinfo->len > self->max_length) {
|
if (bufinfo->len > self->max_length) {
|
||||||
bool
|
|
||||||
}
|
|
||||||
|
|
||||||
mp_buffer_info_t char_bufinfo;
|
|
||||||
if (!mp_get_buffer(characteristic->value, &bufinfo, MP_BUFFER_WRITE)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy(&char_bufinfo->buf, bufinfo->buf, bufinfo->len);
|
|
||||||
|
|
||||||
for (size_t i; i < characteristic->set_callbacks.
|
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
||||||
|
|
||||||
|
if (MP_OBJ_IS_TYPE(self->observer, &bleio_characteristic_buffer_type)) {
|
||||||
|
bleio_characteristic_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
|
||||||
|
} else if (MP_OBJ_IS_TYPE(self->observer, &bleio_packet_buffer_type)) {
|
||||||
|
bleio_packet_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer) {
|
||||||
|
self->observer = observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self) {
|
||||||
|
self->observer = mp_const_none;
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ typedef struct _bleio_characteristic_obj {
|
|||||||
bleio_service_obj_t *service;
|
bleio_service_obj_t *service;
|
||||||
bleio_uuid_obj_t *uuid;
|
bleio_uuid_obj_t *uuid;
|
||||||
mp_obj_t value;
|
mp_obj_t value;
|
||||||
mp_obj_list_t watcher_list;
|
mp_obj_t observer;
|
||||||
mp_obj_list_t descriptor_linked_list;
|
mp_obj_list_t *descriptor_list;
|
||||||
uint16_t max_length;
|
uint16_t max_length;
|
||||||
bool fixed_length;
|
bool fixed_length;
|
||||||
uint16_t decl_handle;
|
uint16_t decl_handle;
|
||||||
@ -50,9 +50,14 @@ typedef struct _bleio_characteristic_obj {
|
|||||||
bleio_attribute_security_mode_t read_perm;
|
bleio_attribute_security_mode_t read_perm;
|
||||||
bleio_attribute_security_mode_t write_perm;
|
bleio_attribute_security_mode_t write_perm;
|
||||||
bleio_descriptor_obj_t *descriptor_linked_list;
|
bleio_descriptor_obj_t *descriptor_linked_list;
|
||||||
uint16_t user_desc_handle;
|
bleio_descriptor_obj_t *user_desc;
|
||||||
uint16_t cccd_handle;
|
bleio_descriptor_obj_t *cccd;
|
||||||
uint16_t sccd_handle;
|
bleio_descriptor_obj_t *sccd;
|
||||||
} bleio_characteristic_obj_t;
|
} bleio_characteristic_obj_t;
|
||||||
|
|
||||||
|
bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
|
||||||
|
|
||||||
|
void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer);
|
||||||
|
void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H
|
||||||
|
@ -37,44 +37,13 @@
|
|||||||
#include "common-hal/_bleio/CharacteristicBuffer.h"
|
#include "common-hal/_bleio/CharacteristicBuffer.h"
|
||||||
|
|
||||||
// Push all the data onto the ring buffer. When the buffer is full, new bytes will be dropped.
|
// Push all the data onto the ring buffer. When the buffer is full, new bytes will be dropped.
|
||||||
// STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
||||||
// uint8_t is_nested_critical_region;
|
ringbuf_put_n(&self->ringbuf, data, len);
|
||||||
// sd_nvic_critical_region_enter(&is_nested_critical_region);
|
}
|
||||||
// ringbuf_put_n(&self->ringbuf, data, len);
|
|
||||||
// sd_nvic_critical_region_exit(is_nested_critical_region);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// STATIC bool characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) {
|
void bleio_characteristic_buffer_update(bleio_characteristic_buffer_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||||
// bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param;
|
write_to_ringbuf(self, bufinfo->buf, bufinfo->len);
|
||||||
// switch (ble_evt->header.evt_id) {
|
}
|
||||||
// case BLE_GATTS_EVT_WRITE: {
|
|
||||||
// // A client wrote to this server characteristic.
|
|
||||||
|
|
||||||
// ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
|
|
||||||
// // Event handle must match the handle for my characteristic.
|
|
||||||
// if (evt_write->handle == self->characteristic->handle) {
|
|
||||||
// write_to_ringbuf(self, evt_write->data, evt_write->len);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// case BLE_GATTC_EVT_HVX: {
|
|
||||||
// // A remote service wrote to this characteristic.
|
|
||||||
|
|
||||||
// ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx;
|
|
||||||
// // Must be a notification, and event handle must match the handle for my characteristic.
|
|
||||||
// if (evt_hvx->type == BLE_GATT_HVX_NOTIFICATION &&
|
|
||||||
// evt_hvx->handle == self->characteristic->handle) {
|
|
||||||
// write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// return false;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Assumes that timeout and buffer_size have been validated before call.
|
// Assumes that timeout and buffer_size have been validated before call.
|
||||||
void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self,
|
void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self,
|
||||||
@ -88,8 +57,7 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe
|
|||||||
// true means long-lived, so it won't be moved.
|
// true means long-lived, so it won't be moved.
|
||||||
ringbuf_alloc(&self->ringbuf, buffer_size, true);
|
ringbuf_alloc(&self->ringbuf, buffer_size, true);
|
||||||
|
|
||||||
// FIX ble_drv_add_event_handler(characteristic_buffer_on_ble_evt, self);
|
bleio_characteristic_set_observer(characteristic, self);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
|
uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
|
||||||
@ -104,32 +72,17 @@ uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy received data. Lock out write interrupt handler while copying.
|
|
||||||
// FIX uint8_t is_nested_critical_region;
|
|
||||||
// FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
|
||||||
|
|
||||||
uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len);
|
uint32_t num_bytes_read = ringbuf_get_n(&self->ringbuf, data, len);
|
||||||
|
|
||||||
// Writes now OK.
|
|
||||||
// FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
|
||||||
|
|
||||||
return num_bytes_read;
|
return num_bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
|
uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) {
|
||||||
//FIX uint8_t is_nested_critical_region;
|
|
||||||
//FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
|
||||||
uint16_t count = ringbuf_num_filled(&self->ringbuf);
|
uint16_t count = ringbuf_num_filled(&self->ringbuf);
|
||||||
//FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) {
|
void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) {
|
||||||
// prevent conflict with uart irq
|
|
||||||
//FIX uint8_t is_nested_critical_region;
|
|
||||||
//FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
|
||||||
ringbuf_clear(&self->ringbuf);
|
ringbuf_clear(&self->ringbuf);
|
||||||
//FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) {
|
bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) {
|
||||||
@ -138,7 +91,7 @@ bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer
|
|||||||
|
|
||||||
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
|
void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) {
|
||||||
if (!common_hal_bleio_characteristic_buffer_deinited(self)) {
|
if (!common_hal_bleio_characteristic_buffer_deinited(self)) {
|
||||||
//FIX ble_drv_remove_event_handler(characteristic_buffer_on_ble_evt, self);
|
bleio_characteristic_clear_observer(self->characteristic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,4 +38,6 @@ typedef struct {
|
|||||||
ringbuf_t ringbuf;
|
ringbuf_t ringbuf;
|
||||||
} bleio_characteristic_buffer_obj_t;
|
} bleio_characteristic_buffer_obj_t;
|
||||||
|
|
||||||
|
void bleio_characteristic_buffer_update(bleio_characteristic_buffer_obj_t *self, mp_buffer_info_t *bufinfo);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTICBUFFER_H
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTICBUFFER_H
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "shared-bindings/_bleio/Connection.h"
|
#include "shared-bindings/_bleio/Connection.h"
|
||||||
|
|
||||||
|
#include "att.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@ -319,10 +321,11 @@ static volatile bool m_discovery_successful;
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
void bleio_connection_clear(bleio_connection_internal_t *self) {
|
void bleio_connection_clear(bleio_connection_internal_t *self) {
|
||||||
self->remote_service_linked_list = NULL;
|
mp_obj_list_clear(MP_OBJ_FROM_PTR(self->remote_service_list));
|
||||||
|
|
||||||
//FIX self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||||
self->pair_status = PAIR_NOT_PAIRED;
|
self->pair_status = PAIR_NOT_PAIRED;
|
||||||
|
self->is_central = false;
|
||||||
//FIX bonding_clear_keys(&self->bonding_keys);
|
//FIX bonding_clear_keys(&self->bonding_keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,12 +340,11 @@ bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) {
|
|||||||
if (self->connection == NULL) {
|
if (self->connection == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID;
|
||||||
//FIX return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) {
|
void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) {
|
||||||
//FIX sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
hci_disconnect(self->conn_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond) {
|
void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond) {
|
||||||
@ -369,8 +371,7 @@ mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_
|
|||||||
|
|
||||||
// Return the current negotiated MTU length, minus overhead.
|
// Return the current negotiated MTU length, minus overhead.
|
||||||
mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self) {
|
mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self) {
|
||||||
/// FIX return (self->mtu == 0 ? BLE_GATT_ATT_MTU_DEFAULT : self->mtu) - 3;
|
return (self->mtu == 0 ? BT_ATT_DEFAULT_LE_MTU : self->mtu) - 3;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval) {
|
void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval) {
|
||||||
@ -449,8 +450,6 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_connection_internal_t* connection) {
|
// STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_connection_internal_t* connection) {
|
||||||
// bleio_service_obj_t* tail = connection->remote_service_linked_list;
|
|
||||||
|
|
||||||
// for (size_t i = 0; i < response->count; ++i) {
|
// for (size_t i = 0; i < response->count; ++i) {
|
||||||
// ble_gattc_service_t *gattc_service = &response->services[i];
|
// ble_gattc_service_t *gattc_service = &response->services[i];
|
||||||
|
|
||||||
@ -477,13 +476,11 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
|||||||
// // For now, just set the UUID to NULL.
|
// // For now, just set the UUID to NULL.
|
||||||
// service->uuid = NULL;
|
// service->uuid = NULL;
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
// service->next = tail;
|
// mp_obj_list_append(MP_OBJ_FROM_PTR(connection->remote_service_list),
|
||||||
// tail = service;
|
// MP_OBJ_FROM_PTR(service));
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
// connection->remote_service_linked_list = tail;
|
|
||||||
|
|
||||||
// if (response->count > 0) {
|
// if (response->count > 0) {
|
||||||
// m_discovery_successful = true;
|
// m_discovery_successful = true;
|
||||||
// }
|
// }
|
||||||
@ -525,7 +522,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
|||||||
// GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
|
// GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
|
||||||
// NULL);
|
// NULL);
|
||||||
|
|
||||||
// mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
|
// mp_obj_list_append(MP_OBJ_FROM_PTR(m_char_discovery_service->characteristic_list),
|
||||||
|
// MP_OBJ_FROM_PTR(characteristic));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// if (response->count > 0) {
|
// if (response->count > 0) {
|
||||||
@ -581,7 +579,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
|||||||
// GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes);
|
// GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes);
|
||||||
// descriptor->handle = gattc_desc->handle;
|
// descriptor->handle = gattc_desc->handle;
|
||||||
|
|
||||||
// mp_obj_list_append(m_desc_discovery_characteristic->descriptor_linked_list, MP_OBJ_FROM_PTR(descriptor));
|
// mp_obj_list_append(MP_OBJ_FROM_PTR(m_desc_discovery_characteristic->descriptor_list),
|
||||||
|
// MP_OBJ_FROM_PTR(descriptor));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// if (response->count > 0) {
|
// if (response->count > 0) {
|
||||||
@ -622,7 +621,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
|||||||
// ble_drv_add_event_handler(discovery_on_ble_evt, self);
|
// ble_drv_add_event_handler(discovery_on_ble_evt, self);
|
||||||
|
|
||||||
// // Start over with an empty list.
|
// // Start over with an empty list.
|
||||||
// self->remote_service_linked_list = NULL;
|
// self->remote_service_list = mp_obj_new_list(0, NULL);
|
||||||
|
|
||||||
|
|
||||||
// if (service_uuids_whitelist == mp_const_none) {
|
// if (service_uuids_whitelist == mp_const_none) {
|
||||||
// // List of service UUID's not given, so discover all available services.
|
// // List of service UUID's not given, so discover all available services.
|
||||||
@ -634,7 +634,9 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
|||||||
|
|
||||||
// // Get the most recently discovered service, and then ask for services
|
// // Get the most recently discovered service, and then ask for services
|
||||||
// // whose handles start after the last attribute handle inside that service.
|
// // whose handles start after the last attribute handle inside that service.
|
||||||
// const bleio_service_obj_t *service = self->remote_service_linked_list;
|
// // There must be at least one if discover_next_services() returned true.
|
||||||
|
// const bleio_service_obj_t *service =
|
||||||
|
// self->remote_service_list->items[self->remote_service_list->len - 1];
|
||||||
// next_service_start_handle = service->end_handle + 1;
|
// next_service_start_handle = service->end_handle + 1;
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
@ -658,11 +660,10 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
// bleio_service_obj_t *service = self->remote_service_linked_list;
|
// for (size_t i = 0; i < self->remote_service_list->len; i++) {
|
||||||
// while (service != NULL) {
|
// bleio_service_obj_t *service = MP_OBJ_TO_PTR(self->remote_service_list->items[i]);
|
||||||
// // Skip the service if it had an unknown (unregistered) UUID.
|
// // Skip the service if it had an unknown (unregistered) UUID.
|
||||||
// if (service->uuid == NULL) {
|
// if (service->uuid == NULL) {
|
||||||
// service = service->next;
|
|
||||||
// continue;
|
// continue;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -714,11 +715,12 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
|||||||
// next_desc_start_handle, next_desc_end_handle)) {
|
// next_desc_start_handle, next_desc_end_handle)) {
|
||||||
// // Get the most recently discovered descriptor, and then ask for descriptors
|
// // Get the most recently discovered descriptor, and then ask for descriptors
|
||||||
// // whose handles start after that descriptor's handle.
|
// // whose handles start after that descriptor's handle.
|
||||||
// const bleio_descriptor_obj_t *descriptor = characteristic->descriptor_linked_list;
|
// // There must be at least one if discover_next_descriptors() returned true.
|
||||||
|
// const bleio_descriptor_obj_t *descriptor =
|
||||||
|
// characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1];
|
||||||
// next_desc_start_handle = descriptor->handle + 1;
|
// next_desc_start_handle = descriptor->handle + 1;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// service = service->next;
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// // This event handler is no longer needed.
|
// // This event handler is no longer needed.
|
||||||
@ -730,10 +732,11 @@ mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_conne
|
|||||||
//FIX discover_remote_services(self->connection, service_uuids_whitelist);
|
//FIX discover_remote_services(self->connection, service_uuids_whitelist);
|
||||||
bleio_connection_ensure_connected(self);
|
bleio_connection_ensure_connected(self);
|
||||||
// Convert to a tuple and then clear the list so the callee will take ownership.
|
// Convert to a tuple and then clear the list so the callee will take ownership.
|
||||||
mp_obj_tuple_t *services_tuple = service_linked_list_to_tuple(self->connection->remote_service_linked_list);
|
mp_obj_tuple_t *services_tuple =
|
||||||
self->connection->remote_service_linked_list = NULL;
|
mp_obj_new_tuple(self->connection->remote_service_list->len,
|
||||||
|
self->connection->remote_service_list->items);
|
||||||
return services_tuple;
|
mp_obj_list_clear(MP_OBJ_FROM_PTR(self->connection->remote_service_list));
|
||||||
|
return services_tuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) {
|
uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self) {
|
||||||
@ -757,13 +760,13 @@ mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t* interna
|
|||||||
|
|
||||||
// Find the connection that uses the given conn_handle. Return NULL if not found.
|
// Find the connection that uses the given conn_handle. Return NULL if not found.
|
||||||
bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle) {
|
bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle) {
|
||||||
//FIX bleio_connection_internal_t *connection;
|
bleio_connection_internal_t *connection;
|
||||||
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||||
// connection = &bleio_connections[i];
|
connection = &bleio_connections[i];
|
||||||
// if (connection->conn_handle == conn_handle) {
|
if (connection->conn_handle == conn_handle) {
|
||||||
// return connection;
|
return connection;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ typedef struct {
|
|||||||
uint16_t conn_handle;
|
uint16_t conn_handle;
|
||||||
bool is_central;
|
bool is_central;
|
||||||
// Remote services discovered when this peripheral is acting as a client.
|
// Remote services discovered when this peripheral is acting as a client.
|
||||||
bleio_service_obj_t *remote_service_linked_list;
|
mp_obj_list_t *remote_service_list;
|
||||||
// The advertising data and scan response buffers are held by us, not by the SD, so we must
|
// The advertising data and scan response buffers are held by us, not by the SD, so we must
|
||||||
// maintain them and not change it. If we need to change the contents during advertising,
|
// maintain them and not change it. If we need to change the contents during advertising,
|
||||||
// there are tricks to get the SD to notice (see DevZone - TBS).
|
// there are tricks to get the SD to notice (see DevZone - TBS).
|
||||||
@ -60,7 +60,6 @@ typedef struct {
|
|||||||
volatile pair_status_t pair_status;
|
volatile pair_status_t pair_status;
|
||||||
uint8_t sec_status; // Internal security status.
|
uint8_t sec_status; // Internal security status.
|
||||||
mp_obj_t connection_obj;
|
mp_obj_t connection_obj;
|
||||||
//REMOVE ble_drv_evt_handler_entry_t handler_entry;
|
|
||||||
//REMOVE ble_gap_conn_params_t conn_params;
|
//REMOVE ble_gap_conn_params_t conn_params;
|
||||||
volatile bool conn_params_updating;
|
volatile bool conn_params_updating;
|
||||||
uint16_t mtu;
|
uint16_t mtu;
|
||||||
|
@ -39,6 +39,7 @@ void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_c
|
|||||||
self->handle = BLE_GATT_HANDLE_INVALID;
|
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||||
self->read_perm = read_perm;
|
self->read_perm = read_perm;
|
||||||
self->write_perm = write_perm;
|
self->write_perm = write_perm;
|
||||||
|
self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||||
|
|
||||||
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
||||||
if (max_length < 0 || max_length > max_length_max) {
|
if (max_length < 0 || max_length > max_length_max) {
|
||||||
@ -62,11 +63,20 @@ bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio
|
|||||||
size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len) {
|
size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t* buf, size_t len) {
|
||||||
// Do GATT operations only if this descriptor has been registered
|
// Do GATT operations only if this descriptor has been registered
|
||||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection);
|
|
||||||
if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
|
if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
|
||||||
return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len);
|
//uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection);
|
||||||
|
//FIX have att_read_req fill in a buffer
|
||||||
|
//uint8_t rsp[MAX(len, 512)];
|
||||||
|
//return att_read_req(conn_handle, self->handle, rsp, len);
|
||||||
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len);
|
mp_buffer_info_t bufinfo;
|
||||||
|
if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t actual_length = MIN(len, bufinfo.len);
|
||||||
|
memcpy(buf, bufinfo.buf, actual_length);
|
||||||
|
return actual_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,13 +95,20 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff
|
|||||||
|
|
||||||
// Do GATT operations only if this descriptor has been registered.
|
// Do GATT operations only if this descriptor has been registered.
|
||||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection);
|
|
||||||
if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
|
if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) {
|
||||||
// false means WRITE_REQ, not write-no-response
|
//FIX
|
||||||
common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false);
|
// uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
|
// att_write_req(conn_handle, self->handle, bufinfo->buf, bufinfo->len, rsp);
|
||||||
} else {
|
} else {
|
||||||
common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo);
|
// Always write the value locally even if no connections are active.
|
||||||
|
if (self->fixed_length && bufinfo->len != self->max_length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (bufinfo->len > self->max_length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,152 +36,48 @@
|
|||||||
#include "shared-bindings/_bleio/PacketBuffer.h"
|
#include "shared-bindings/_bleio/PacketBuffer.h"
|
||||||
#include "supervisor/shared/tick.h"
|
#include "supervisor/shared/tick.h"
|
||||||
|
|
||||||
// STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
||||||
// if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) {
|
if (len + sizeof(uint16_t) > ringbuf_capacity(&self->ringbuf)) {
|
||||||
// // This shouldn't happen.
|
// This shouldn't happen.
|
||||||
// return;
|
return;
|
||||||
// }
|
}
|
||||||
// // Push all the data onto the ring buffer.
|
// Push all the data onto the ring buffer.
|
||||||
// //FIX uint8_t is_nested_critical_region;
|
// Make room for the new value by dropping the oldest packets first.
|
||||||
// //FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
|
||||||
// // Make room for the new value by dropping the oldest packets first.
|
uint16_t packet_length;
|
||||||
// while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
|
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
||||||
// uint16_t packet_length;
|
for (uint16_t i = 0; i < packet_length; i++) {
|
||||||
// ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
ringbuf_get(&self->ringbuf);
|
||||||
// for (uint16_t i = 0; i < packet_length; i++) {
|
}
|
||||||
// ringbuf_get(&self->ringbuf);
|
// set an overflow flag?
|
||||||
// }
|
}
|
||||||
// // set an overflow flag?
|
ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t));
|
||||||
// }
|
ringbuf_put_n(&self->ringbuf, data, len);
|
||||||
// ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t));
|
}
|
||||||
// ringbuf_put_n(&self->ringbuf, data, len);
|
|
||||||
// //FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
|
||||||
// }
|
|
||||||
|
|
||||||
//FIX
|
STATIC uint32_t queue_next_write(bleio_packet_buffer_obj_t *self) {
|
||||||
// STATIC uint32_t queue_next_write(bleio_packet_buffer_obj_t *self) {
|
// Queue up the next outgoing buffer. We use two, one that has been passed to the SD for
|
||||||
// // Queue up the next outgoing buffer. We use two, one that has been passed to the SD for
|
// transmission (when packet_queued is true) and the other is `pending` and can still be
|
||||||
// // transmission (when packet_queued is true) and the other is `pending` and can still be
|
// modified. By primarily appending to the `pending` buffer we can reduce the protocol overhead
|
||||||
// // modified. By primarily appending to the `pending` buffer we can reduce the protocol overhead
|
// of the lower level link and ATT layers.
|
||||||
// // of the lower level link and ATT layers.
|
self->packet_queued = false;
|
||||||
// self->packet_queued = false;
|
if (self->pending_size > 0) {
|
||||||
// if (self->pending_size > 0) {
|
mp_buffer_info_t bufinfo = {
|
||||||
// uint16_t conn_handle = self->conn_handle;
|
.buf = self->outgoing[self->pending_index],
|
||||||
// uint32_t err_code;
|
.len = self->pending_size,
|
||||||
// if (self->client) {
|
};
|
||||||
// ble_gattc_write_params_t write_params = {
|
common_hal_bleio_characteristic_set_value(self->characteristic, &bufinfo);
|
||||||
// .write_op = self->write_type,
|
|
||||||
// .handle = self->characteristic->handle,
|
|
||||||
// .p_value = self->outgoing[self->pending_index],
|
|
||||||
// .len = self->pending_size,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
self->pending_size = 0;
|
||||||
// } else {
|
self->pending_index = (self->pending_index + 1) % 2;
|
||||||
// uint16_t hvx_len = self->pending_size;
|
self->packet_queued = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// ble_gatts_hvx_params_t hvx_params = {
|
void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||||
// .handle = self->characteristic->handle,
|
write_to_ringbuf(self, bufinfo->buf, bufinfo->len);
|
||||||
// .type = self->write_type,
|
}
|
||||||
// .offset = 0,
|
|
||||||
// .p_len = &hvx_len,
|
|
||||||
// .p_data = self->outgoing[self->pending_index],
|
|
||||||
// };
|
|
||||||
// err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
|
|
||||||
// }
|
|
||||||
// if (err_code != NRF_SUCCESS) {
|
|
||||||
// // On error, simply skip updating the pending buffers so that the next HVC or WRITE
|
|
||||||
// // complete event triggers another attempt.
|
|
||||||
// return err_code;
|
|
||||||
// }
|
|
||||||
// self->pending_size = 0;
|
|
||||||
// self->pending_index = (self->pending_index + 1) % 2;
|
|
||||||
// self->packet_queued = true;
|
|
||||||
// }
|
|
||||||
// return NRF_SUCCESS;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// STATIC bool packet_buffer_on_ble_client_evt(ble_evt_t *ble_evt, void *param) {
|
|
||||||
// const uint16_t evt_id = ble_evt->header.evt_id;
|
|
||||||
// // Check if this is a GATTC event so we can make sure the conn_handle is valid.
|
|
||||||
// if (evt_id < BLE_GATTC_EVT_BASE || evt_id > BLE_GATTC_EVT_LAST) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// uint16_t conn_handle = ble_evt->evt.gattc_evt.conn_handle;
|
|
||||||
// bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param;
|
|
||||||
// if (conn_handle != self->conn_handle) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// switch (evt_id) {
|
|
||||||
// case BLE_GATTC_EVT_HVX: {
|
|
||||||
// // A remote service wrote to this characteristic.
|
|
||||||
// ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx;
|
|
||||||
// // Must be a notification, and event handle must match the handle for my characteristic.
|
|
||||||
// if (evt_hvx->handle == self->characteristic->handle) {
|
|
||||||
// write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
|
|
||||||
// if (evt_hvx->type == BLE_GATT_HVX_INDICATION) {
|
|
||||||
// sd_ble_gattc_hv_confirm(conn_handle, evt_hvx->handle);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: {
|
|
||||||
// queue_next_write(self);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case BLE_GATTC_EVT_WRITE_RSP: {
|
|
||||||
// queue_next_write(self);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// return false;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// STATIC bool packet_buffer_on_ble_server_evt(ble_evt_t *ble_evt, void *param) {
|
|
||||||
// bleio_packet_buffer_obj_t *self = (bleio_packet_buffer_obj_t *) param;
|
|
||||||
// switch (ble_evt->header.evt_id) {
|
|
||||||
// case BLE_GATTS_EVT_WRITE: {
|
|
||||||
// uint16_t conn_handle = ble_evt->evt.gatts_evt.conn_handle;
|
|
||||||
// // A client wrote to this server characteristic.
|
|
||||||
|
|
||||||
// ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
|
|
||||||
|
|
||||||
// // Event handle must match the handle for my characteristic.
|
|
||||||
// if (evt_write->handle == self->characteristic->handle) {
|
|
||||||
// if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
|
|
||||||
// self->conn_handle = conn_handle;
|
|
||||||
// } else if (self->conn_handle != conn_handle) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// write_to_ringbuf(self, evt_write->data, evt_write->len);
|
|
||||||
// } else if (evt_write->handle == self->characteristic->cccd_handle) {
|
|
||||||
// uint16_t cccd = *((uint16_t*) evt_write->data);
|
|
||||||
// if (cccd & BLE_GATT_HVX_NOTIFICATION) {
|
|
||||||
// self->conn_handle = conn_handle;
|
|
||||||
// } else {
|
|
||||||
// self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// case BLE_GAP_EVT_DISCONNECTED: {
|
|
||||||
// if (self->conn_handle == ble_evt->evt.gap_evt.conn_handle) {
|
|
||||||
// self->conn_handle = BLE_CONN_HANDLE_INVALID;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// case BLE_GATTS_EVT_HVN_TX_COMPLETE: {
|
|
||||||
// queue_next_write(self);
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// return false;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
void common_hal_bleio_packet_buffer_construct(
|
void common_hal_bleio_packet_buffer_construct(
|
||||||
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
|
bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic,
|
||||||
@ -189,8 +85,10 @@ void common_hal_bleio_packet_buffer_construct(
|
|||||||
|
|
||||||
self->characteristic = characteristic;
|
self->characteristic = characteristic;
|
||||||
self->client = self->characteristic->service->is_remote;
|
self->client = self->characteristic->service->is_remote;
|
||||||
bleio_characteristic_properties_t incoming = self->characteristic->props & (CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE);
|
bleio_characteristic_properties_t incoming =
|
||||||
bleio_characteristic_properties_t outgoing = self->characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE);
|
self->characteristic->props & (CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE);
|
||||||
|
bleio_characteristic_properties_t outgoing =
|
||||||
|
self->characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE);
|
||||||
|
|
||||||
if (self->client) {
|
if (self->client) {
|
||||||
// Swap if we're the client.
|
// Swap if we're the client.
|
||||||
@ -219,32 +117,7 @@ void common_hal_bleio_packet_buffer_construct(
|
|||||||
self->outgoing[1] = NULL;
|
self->outgoing[1] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIX if (self->client) {
|
bleio_characteristic_set_observer(self->characteristic, self);
|
||||||
// ble_drv_add_event_handler(packet_buffer_on_ble_client_evt, self);
|
|
||||||
// if (incoming) {
|
|
||||||
// // Prefer notify if both are available.
|
|
||||||
// if (incoming & CHAR_PROP_NOTIFY) {
|
|
||||||
// self->write_type = BLE_GATT_HVX_NOTIFICATION;
|
|
||||||
// common_hal_bleio_characteristic_set_cccd(self->characteristic, true, false);
|
|
||||||
// } else {
|
|
||||||
// common_hal_bleio_characteristic_set_cccd(self->characteristic, false, true);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (outgoing) {
|
|
||||||
// self->write_type = BLE_GATT_OP_WRITE_REQ;
|
|
||||||
// if (outgoing & CHAR_PROP_WRITE_NO_RESPONSE) {
|
|
||||||
// self->write_type = BLE_GATT_OP_WRITE_CMD;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// ble_drv_add_event_handler(packet_buffer_on_ble_server_evt, self);
|
|
||||||
// if (outgoing) {
|
|
||||||
// self->write_type = BLE_GATT_HVX_INDICATION;
|
|
||||||
// if (outgoing & CHAR_PROP_NOTIFY) {
|
|
||||||
// self->write_type = BLE_GATT_HVX_NOTIFICATION;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) {
|
mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) {
|
||||||
@ -252,10 +125,7 @@ mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy received data. Lock out write interrupt handler while copying.
|
// Copy received data.
|
||||||
//FIX uint8_t is_nested_critical_region;
|
|
||||||
//FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
|
||||||
|
|
||||||
// Get packet length, which is in first two bytes of packet.
|
// Get packet length, which is in first two bytes of packet.
|
||||||
uint16_t packet_length;
|
uint16_t packet_length;
|
||||||
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
||||||
@ -274,9 +144,6 @@ mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self
|
|||||||
ret = packet_length;
|
ret = packet_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes now OK.
|
|
||||||
//FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,9 +174,6 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, u
|
|||||||
|
|
||||||
size_t num_bytes_written = 0;
|
size_t num_bytes_written = 0;
|
||||||
|
|
||||||
//FIX uint8_t is_nested_critical_region;
|
|
||||||
//FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
|
||||||
|
|
||||||
uint8_t* pending = self->outgoing[self->pending_index];
|
uint8_t* pending = self->outgoing[self->pending_index];
|
||||||
|
|
||||||
if (self->pending_size == 0) {
|
if (self->pending_size == 0) {
|
||||||
@ -321,11 +185,9 @@ mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, u
|
|||||||
self->pending_size += len;
|
self->pending_size += len;
|
||||||
num_bytes_written += len;
|
num_bytes_written += len;
|
||||||
|
|
||||||
//FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
|
||||||
|
|
||||||
// If no writes are queued then sneak in this data.
|
// If no writes are queued then sneak in this data.
|
||||||
if (!self->packet_queued) {
|
if (!self->packet_queued) {
|
||||||
//FIX queue_next_write(self);
|
queue_next_write(self);
|
||||||
}
|
}
|
||||||
return num_bytes_written;
|
return num_bytes_written;
|
||||||
}
|
}
|
||||||
@ -398,6 +260,6 @@ bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) {
|
|||||||
|
|
||||||
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) {
|
void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) {
|
||||||
if (!common_hal_bleio_packet_buffer_deinited(self)) {
|
if (!common_hal_bleio_packet_buffer_deinited(self)) {
|
||||||
//FIX ble_drv_remove_event_handler(packet_buffer_on_ble_client_evt, self);
|
bleio_characteristic_clear_observer(self->characteristic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,4 +48,6 @@ typedef struct {
|
|||||||
bool packet_queued;
|
bool packet_queued;
|
||||||
} bleio_packet_buffer_obj_t;
|
} bleio_packet_buffer_obj_t;
|
||||||
|
|
||||||
|
void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_t *bufinfo);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_PACKETBUFFER_H
|
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_PACKETBUFFER_H
|
||||||
|
@ -70,8 +70,8 @@ bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
|
|||||||
return self->uuid;
|
return self->uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self) {
|
mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self) {
|
||||||
return self->characteristic_list;
|
return mp_obj_new_tuple(self->characteristic_list->len, self->characteristic_list->items);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) {
|
bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) {
|
||||||
@ -122,21 +122,8 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
|
|||||||
|
|
||||||
// Adds CCCD to attribute table, and also extends self->end_handle to include the CCCD.
|
// Adds CCCD to attribute table, and also extends self->end_handle to include the CCCD.
|
||||||
common_hal_bleio_characteristic_add_descriptor(characteristic, cccd);
|
common_hal_bleio_characteristic_add_descriptor(characteristic, cccd);
|
||||||
characteristic->cccd_handle = cccd->handle;
|
characteristic->cccd = cccd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #if CIRCUITPY_VERBOSE_BLE
|
|
||||||
// // Turn on read authorization so that we receive an event to print on every read.
|
|
||||||
// char_attr_md.rd_auth = true;
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// These are not supplied or available.
|
|
||||||
characteristic->user_desc_handle = BLE_GATT_HANDLE_INVALID;
|
|
||||||
characteristic->sccd_handle = BLE_GATT_HANDLE_INVALID;
|
|
||||||
|
|
||||||
// #if CIRCUITPY_VERBOSE_BLE
|
|
||||||
// mp_printf(&mp_plat_print, "Char handle %x user %x cccd %x sccd %x\n", characteristic->handle, characteristic->user_desc_handle, characteristic->cccd_handle, characteristic->sccd_handle);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
|
mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
|
||||||
}
|
}
|
||||||
|
@ -83,21 +83,6 @@ void check_hci_error(hci_result_t result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// void check_gatt_status(uint16_t gatt_status) {
|
|
||||||
// if (gatt_status == BLE_GATT_STATUS_SUCCESS) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// switch (gatt_status) {
|
|
||||||
// case BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION:
|
|
||||||
// mp_raise_bleio_SecurityError(translate("Insufficient authentication"));
|
|
||||||
// return;
|
|
||||||
// case BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION:
|
|
||||||
// mp_raise_bleio_SecurityError(translate("Insufficient encryption"));
|
|
||||||
// return;
|
|
||||||
// default:
|
|
||||||
// mp_raise_bleio_BluetoothError(translate("Unknown gatt error: 0x%04x"), gatt_status);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// void check_sec_status(uint8_t sec_status) {
|
// void check_sec_status(uint8_t sec_status) {
|
||||||
// if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) {
|
// if (sec_status == BLE_GAP_SEC_STATUS_SUCCESS) {
|
||||||
@ -148,134 +133,6 @@ void common_hal_bleio_check_connected(uint16_t conn_handle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GATTS read of a Characteristic or Descriptor.
|
|
||||||
size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) {
|
|
||||||
// conn_handle is ignored unless this is a system attribute.
|
|
||||||
// If we're not connected, that's OK, because we can still read and write the local value.
|
|
||||||
|
|
||||||
//FIX ble_gatts_value_t gatts_value = {
|
|
||||||
// .p_value = buf,
|
|
||||||
// .len = len,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// check_nrf_error(sd_ble_gatts_value_get(conn_handle, handle, &gatts_value));
|
|
||||||
|
|
||||||
// return gatts_value.len;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) {
|
|
||||||
// conn_handle is ignored unless this is a system attribute.
|
|
||||||
// If we're not connected, that's OK, because we can still read and write the local value.
|
|
||||||
|
|
||||||
//FIX ble_gatts_value_t gatts_value = {
|
|
||||||
// .p_value = bufinfo->buf,
|
|
||||||
// .len = bufinfo->len,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// check_nrf_error(sd_ble_gatts_value_set(conn_handle, handle, &gatts_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
//FIX
|
|
||||||
// typedef struct {
|
|
||||||
// uint8_t* buf;
|
|
||||||
// size_t len;
|
|
||||||
// size_t final_len;
|
|
||||||
// uint16_t conn_handle;
|
|
||||||
// volatile uint16_t status;
|
|
||||||
// volatile bool done;
|
|
||||||
// } read_info_t;
|
|
||||||
|
|
||||||
// STATIC bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) {
|
|
||||||
// read_info_t* read = param;
|
|
||||||
// switch (ble_evt->header.evt_id) {
|
|
||||||
|
|
||||||
// // More events may be handled later, so keep this as a switch.
|
|
||||||
|
|
||||||
// case BLE_GATTC_EVT_READ_RSP: {
|
|
||||||
// ble_gattc_evt_t* evt = &ble_evt->evt.gattc_evt;
|
|
||||||
// ble_gattc_evt_read_rsp_t *response = &evt->params.read_rsp;
|
|
||||||
// if (read && evt->conn_handle == read->conn_handle) {
|
|
||||||
// read->status = evt->gatt_status;
|
|
||||||
// size_t len = MIN(read->len, response->len);
|
|
||||||
// memcpy(read->buf, response->data, len);
|
|
||||||
// read->final_len = len;
|
|
||||||
// // Indicate to busy-wait loop that we've read the attribute value.
|
|
||||||
// read->done = true;
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// default:
|
|
||||||
// // For debugging.
|
|
||||||
// // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
|
|
||||||
// return false;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t* buf, size_t len) {
|
|
||||||
common_hal_bleio_check_connected(conn_handle);
|
|
||||||
|
|
||||||
//FIX read_info_t read_info;
|
|
||||||
// read_info.buf = buf;
|
|
||||||
// read_info.len = len;
|
|
||||||
// read_info.final_len = 0;
|
|
||||||
// read_info.conn_handle = conn_handle;
|
|
||||||
// // Set to true by the event handler.
|
|
||||||
// read_info.done = false;
|
|
||||||
// ble_drv_add_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
|
||||||
|
|
||||||
// uint32_t nrf_error = NRF_ERROR_BUSY;
|
|
||||||
// while (nrf_error == NRF_ERROR_BUSY) {
|
|
||||||
// nrf_error = sd_ble_gattc_read(conn_handle, handle, 0);
|
|
||||||
// }
|
|
||||||
// if (nrf_error != NRF_SUCCESS) {
|
|
||||||
// ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
|
||||||
// check_nrf_error(nrf_error);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// while (!read_info.done) {
|
|
||||||
// RUN_BACKGROUND_TASKS;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info);
|
|
||||||
// check_gatt_status(read_info.status);
|
|
||||||
// return read_info.final_len;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) {
|
|
||||||
common_hal_bleio_check_connected(conn_handle);
|
|
||||||
|
|
||||||
//FIX
|
|
||||||
// ble_gattc_write_params_t write_params = {
|
|
||||||
// .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ,
|
|
||||||
// .handle = handle,
|
|
||||||
// .p_value = bufinfo->buf,
|
|
||||||
// .len = bufinfo->len,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// while (1) {
|
|
||||||
// uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
|
||||||
// if (err_code == NRF_SUCCESS) {
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Write with response will return NRF_ERROR_BUSY if the response has not been received.
|
|
||||||
// // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
|
|
||||||
// if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
|
|
||||||
// // We could wait for an event indicating the write is complete, but just retrying is easier.
|
|
||||||
// MICROPY_VM_HOOK_LOOP;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Some real error occurred.
|
|
||||||
// check_nrf_error(err_code);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void common_hal_bleio_gc_collect(void) {
|
void common_hal_bleio_gc_collect(void) {
|
||||||
bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
|
bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "shared-bindings/_bleio/UUID.h"
|
#include "shared-bindings/_bleio/UUID.h"
|
||||||
|
|
||||||
|
#include "att.h"
|
||||||
#include "hci.h"
|
#include "hci.h"
|
||||||
|
|
||||||
void bleio_background(void);
|
void bleio_background(void);
|
||||||
@ -44,7 +45,7 @@ typedef struct {
|
|||||||
|
|
||||||
// We assume variable length data.
|
// We assume variable length data.
|
||||||
// 20 bytes max (23 - 3).
|
// 20 bytes max (23 - 3).
|
||||||
#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3)
|
#define GATT_MAX_DATA_LENGTH (BT_ATT_DEFAULT_LE_MTU - 3)
|
||||||
|
|
||||||
//FIX
|
//FIX
|
||||||
#define BLE_GATT_HANDLE_INVALID 0x0000
|
#define BLE_GATT_HANDLE_INVALID 0x0000
|
||||||
|
@ -64,8 +64,6 @@ typedef struct __packed {
|
|||||||
uint8_t uuid[0]; // 2 or 16 bytes
|
uint8_t uuid[0]; // 2 or 16 bytes
|
||||||
} characteristic_declaration_t;
|
} characteristic_declaration_t;
|
||||||
|
|
||||||
//FIX BLEDeviceEventHandler event_handlers[2];
|
|
||||||
|
|
||||||
STATIC uint8_t bleio_properties_to_ble_spec_properties(uint8_t bleio_properties) {
|
STATIC uint8_t bleio_properties_to_ble_spec_properties(uint8_t bleio_properties) {
|
||||||
uint8_t ble_spec_properties = 0;
|
uint8_t ble_spec_properties = 0;
|
||||||
if (bleio_properties & CHAR_PROP_BROADCAST) {
|
if (bleio_properties & CHAR_PROP_BROADCAST) {
|
||||||
@ -220,21 +218,16 @@ bool att_connect_to_address(bt_addr_le_t *addr) {
|
|||||||
return is_connected;
|
return is_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool att_disconnect_from_address(bt_addr_le_t *addr) {
|
bool att_disconnect(uint16_t conn_handle) {
|
||||||
uint16_t conn_handle = att_conn_handle(addr);
|
if (conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||||
if (conn_handle == 0xffff) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hci_disconnect(conn_handle);
|
hci_disconnect(conn_handle);
|
||||||
|
|
||||||
hci_poll_for_incoming_pkt_timeout(timeout);
|
hci_poll_for_incoming_pkt_timeout(timeout);
|
||||||
|
|
||||||
if (!att_handle_is_connected(conn_handle)) {
|
// Confirm we're now disconnected.
|
||||||
return true;
|
return !att_handle_is_connected(conn_handle);
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIX
|
//FIX
|
||||||
@ -512,10 +505,6 @@ void att_add_connection(uint16_t handle, uint8_t role, bt_addr_le_t *peer_addr,
|
|||||||
bleio_connections[peer_index].role = role;
|
bleio_connections[peer_index].role = role;
|
||||||
bleio_connections[peer_index].mtu = BT_ATT_DEFAULT_LE_MTU;
|
bleio_connections[peer_index].mtu = BT_ATT_DEFAULT_LE_MTU;
|
||||||
memcpy(&bleio_connections[peer_index].addr, peer_addr, sizeof(bleio_connections[peer_index].addr));
|
memcpy(&bleio_connections[peer_index].addr, peer_addr, sizeof(bleio_connections[peer_index].addr));
|
||||||
|
|
||||||
//FIX if (event_handlers[BLEConnected]) {
|
|
||||||
// event_handlers[BLEConnected](BLEDevice(peer_bdaddr_type, peer_bdaddr));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -564,11 +553,6 @@ void att_remove_connection(uint16_t handle, uint8_t reason) {
|
|||||||
long_write_value_length = 0;
|
long_write_value_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIX
|
|
||||||
// if (event_handlers[BLEDisconnected]) {
|
|
||||||
// event_handlers[BLEDisconnected](bleDevice);
|
|
||||||
// }
|
|
||||||
|
|
||||||
bleio_connections[peer_index].conn_handle = 0xffff;
|
bleio_connections[peer_index].conn_handle = 0xffff;
|
||||||
bleio_connections[peer_index].role = 0x00;
|
bleio_connections[peer_index].role = 0x00;
|
||||||
memset(&bleio_connections[peer_index].addr, 0x00, sizeof(bleio_connections[peer_index].addr));
|
memset(&bleio_connections[peer_index].addr, 0x00, sizeof(bleio_connections[peer_index].addr));
|
||||||
@ -630,7 +614,7 @@ bool att_disconnect_all(void) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hci_disconnect(bleio_connections[i].conn_handle) != 0) {
|
if (att_disconnect(bleio_connections[i].conn_handle) != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1391,7 +1375,8 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
common_hal_bleio_characteristic_set_value(characteristic, &bufinfo);
|
// Just change the local value. Don't fire off notifications, etc.
|
||||||
|
bleio_characteristic_set_local_value(characteristic, &bufinfo);
|
||||||
|
|
||||||
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
|
} else if (MP_OBJ_IS_TYPE(attribute_obj, &bleio_descriptor_type)) {
|
||||||
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
|
bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(attribute_obj);
|
||||||
@ -1403,7 +1388,6 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIX need to set up event handlers, etc.?
|
|
||||||
common_hal_bleio_descriptor_set_value(descriptor, &bufinfo);
|
common_hal_bleio_descriptor_set_value(descriptor, &bufinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1593,14 +1577,6 @@ bool att_exchange_mtu(uint16_t conn_handle) {
|
|||||||
return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer);
|
return send_req_wait_for_rsp(conn_handle, sizeof(req), (uint8_t *) &req, response_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler event_handler) {
|
|
||||||
// if (event < (sizeof(event_handlers) / (sizeof(event_handlers[0])))) {
|
|
||||||
// event_handlers[event] = event_handler;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[]) {
|
int att_read_req(uint16_t conn_handle, uint16_t handle, uint8_t response_buffer[]) {
|
||||||
struct __packed {
|
struct __packed {
|
||||||
struct bt_att_hdr h;
|
struct bt_att_hdr h;
|
||||||
@ -1642,7 +1618,7 @@ void att_write_cmd(uint16_t conn_handle, uint16_t handle, const uint8_t* data, u
|
|||||||
cmd->r.handle = handle;
|
cmd->r.handle = handle;
|
||||||
memcpy(cmd->r.value, data, data_len);
|
memcpy(cmd->r.value, data, data_len);
|
||||||
|
|
||||||
return send_req(conn_handle, sizeof(cmd_bytes), cmd_bytes);
|
send_req(conn_handle, sizeof(cmd_bytes), cmd_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
||||||
@ -1738,3 +1714,76 @@ void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FIX Do we need all of these?
|
||||||
|
void check_att_err(uint8_t err) {
|
||||||
|
const compressed_string_t *msg = NULL;
|
||||||
|
switch (err) {
|
||||||
|
case 0:
|
||||||
|
return;
|
||||||
|
case BT_ATT_ERR_INVALID_HANDLE:
|
||||||
|
msg = translate("Invalid handle");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_READ_NOT_PERMITTED:
|
||||||
|
msg = translate("Read not permitted");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_WRITE_NOT_PERMITTED:
|
||||||
|
msg = translate("Write not permitted");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_INVALID_PDU:
|
||||||
|
msg = translate("Invalid PDU");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_NOT_SUPPORTED:
|
||||||
|
msg = translate("Not supported");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_INVALID_OFFSET:
|
||||||
|
msg = translate("Invalid offset");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_PREPARE_QUEUE_FULL:
|
||||||
|
msg = translate("Prepare queue full");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_ATTRIBUTE_NOT_FOUND:
|
||||||
|
msg = translate("Attribute not found");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_ATTRIBUTE_NOT_LONG:
|
||||||
|
msg = translate("Attribute not long");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_ENCRYPTION_KEY_SIZE:
|
||||||
|
msg = translate("Encryption key size");
|
||||||
|
case BT_ATT_ERR_INVALID_ATTRIBUTE_LEN:
|
||||||
|
msg = translate("Invalid attribute length");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_UNLIKELY:
|
||||||
|
msg = translate("Unlikely");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_UNSUPPORTED_GROUP_TYPE:
|
||||||
|
msg = translate("Unsupported group type");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_INSUFFICIENT_RESOURCES:
|
||||||
|
msg = translate("Insufficient resources");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_DB_OUT_OF_SYNC:
|
||||||
|
msg = translate("DB out of sync");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_VALUE_NOT_ALLOWED:
|
||||||
|
msg = translate("Value not allowed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (msg) {
|
||||||
|
mp_raise_bleio_BluetoothError(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (err) {
|
||||||
|
case BT_ATT_ERR_AUTHENTICATION:
|
||||||
|
msg = translate("Insufficient authentication");
|
||||||
|
break;
|
||||||
|
case BT_ATT_ERR_INSUFFICIENT_ENCRYPTION:
|
||||||
|
msg = translate("Insufficient encryption");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (msg) {
|
||||||
|
mp_raise_bleio_SecurityError(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_raise_bleio_BluetoothError(translate("Unknown ATT error: 0x%02x"), err);
|
||||||
|
}
|
||||||
|
@ -35,8 +35,8 @@ void bleio_att_reset(void);
|
|||||||
//FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);
|
//FIX void att_set_event_handler(BLEDeviceEvent event, BLEDeviceEventHandler eventHandler);
|
||||||
bool att_address_is_connected(bt_addr_le_t *addr);
|
bool att_address_is_connected(bt_addr_le_t *addr);
|
||||||
bool att_connect_to_address(bt_addr_le_t *addr);
|
bool att_connect_to_address(bt_addr_le_t *addr);
|
||||||
|
bool att_disconnect(uint16_t conn_handle);
|
||||||
bool att_disconnect_all(void);
|
bool att_disconnect_all(void);
|
||||||
bool att_disconnect_from_address(bt_addr_le_t *addr);
|
|
||||||
bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter);
|
bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter);
|
||||||
bool att_exchange_mtu(uint16_t conn_handle);
|
bool att_exchange_mtu(uint16_t conn_handle);
|
||||||
bool att_handle_is_connected(uint16_t handle);
|
bool att_handle_is_connected(uint16_t handle);
|
||||||
|
@ -172,15 +172,14 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[])
|
|||||||
struct bt_hci_evt_disconn_complete *disconn_complete =
|
struct bt_hci_evt_disconn_complete *disconn_complete =
|
||||||
(struct bt_hci_evt_disconn_complete*) pkt->params;
|
(struct bt_hci_evt_disconn_complete*) pkt->params;
|
||||||
(void) disconn_complete;
|
(void) disconn_complete;
|
||||||
//FIX
|
|
||||||
// ATT.removeConnection(disconn_complete->handle, disconn_complete->reason);
|
att_remove_connection(disconn_complete->handle, disconn_complete->reason);
|
||||||
// L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason);
|
//FIX L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason);
|
||||||
hci_le_set_advertising_enable(0x01);
|
hci_le_set_advertising_enable(0x01);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BT_HCI_EVT_CMD_COMPLETE: {
|
case BT_HCI_EVT_CMD_COMPLETE: {
|
||||||
|
|
||||||
struct cmd_complete_with_status {
|
struct cmd_complete_with_status {
|
||||||
struct bt_hci_evt_cmd_complete cmd_complete;
|
struct bt_hci_evt_cmd_complete cmd_complete;
|
||||||
struct bt_hci_evt_cc_status cc_status;
|
struct bt_hci_evt_cc_status cc_status;
|
||||||
@ -238,19 +237,21 @@ STATIC void process_evt_pkt(size_t pkt_len, uint8_t pkt_data[])
|
|||||||
(struct bt_hci_evt_le_conn_complete *) le_evt;
|
(struct bt_hci_evt_le_conn_complete *) le_evt;
|
||||||
|
|
||||||
if (le_conn_complete->status == BT_HCI_ERR_SUCCESS) {
|
if (le_conn_complete->status == BT_HCI_ERR_SUCCESS) {
|
||||||
// ATT.addConnection(le_conn_complete->handle,
|
att_add_connection(
|
||||||
// le_conn_complete->role,
|
le_conn_complete->handle,
|
||||||
// le_conn_complete->peer_addr //FIX struct
|
le_conn_complete->role,
|
||||||
// le_conn_complete->interval,
|
&le_conn_complete->peer_addr,
|
||||||
// le_conn_complete->latency,
|
le_conn_complete->interval,
|
||||||
// le_conn_complete->supv_timeout
|
le_conn_complete->latency,
|
||||||
// le_conn_complete->clock_accuracy);
|
le_conn_complete->supv_timeout,
|
||||||
|
le_conn_complete->clock_accuracy);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (meta_evt->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT) {
|
} else if (meta_evt->subevent == BT_HCI_EVT_LE_ADVERTISING_REPORT) {
|
||||||
struct bt_hci_evt_le_advertising_info *le_advertising_info =
|
struct bt_hci_evt_le_advertising_info *le_advertising_info =
|
||||||
(struct bt_hci_evt_le_advertising_info *) le_evt;
|
(struct bt_hci_evt_le_advertising_info *) le_evt;
|
||||||
if (le_advertising_info->evt_type == BT_HCI_ADV_DIRECT_IND) { //FIX handle kind of advertising
|
if (le_advertising_info->evt_type == BT_HCI_ADV_DIRECT_IND) {
|
||||||
|
//FIX
|
||||||
// last byte is RSSI
|
// last byte is RSSI
|
||||||
// GAP.handleLeAdvertisingReport(leAdvertisingReport->type,
|
// GAP.handleLeAdvertisingReport(leAdvertisingReport->type,
|
||||||
// leAdvertisingReport->peerBdaddrType,
|
// leAdvertisingReport->peerBdaddrType,
|
||||||
@ -538,7 +539,7 @@ hci_result_t hci_read_rssi(uint16_t handle, int *rssi) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
hci_result_t hci_set_evt_mask(uint64_t event_mask) {
|
hci_result_t hci_set_event_mask(uint64_t event_mask) {
|
||||||
return send_command(BT_HCI_OP_SET_EVENT_MASK, sizeof(event_mask), &event_mask);
|
return send_command(BT_HCI_OP_SET_EVENT_MASK, sizeof(event_mask), &event_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,6 @@ hci_result_t hci_read_rssi(uint16_t handle, int *rssi);
|
|||||||
hci_result_t hci_reset(void);
|
hci_result_t hci_reset(void);
|
||||||
|
|
||||||
hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint8_t data_len, uint8_t *data);
|
hci_result_t hci_send_acl_pkt(uint16_t handle, uint8_t cid, uint8_t data_len, uint8_t *data);
|
||||||
hci_result_t hci_set_evt_mask(uint64_t event_mask);
|
hci_result_t hci_set_event_mask(uint64_t event_mask);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H
|
#endif // MICROPY_INCLUDED_DEVICES_BLE_HCI_COMMON_HAL_BLEIO_HCI_H
|
||||||
|
@ -90,6 +90,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
|
|||||||
self->props = props;
|
self->props = props;
|
||||||
self->read_perm = read_perm;
|
self->read_perm = read_perm;
|
||||||
self->write_perm = write_perm;
|
self->write_perm = write_perm;
|
||||||
|
self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||||
self->descriptor_list = mp_obj_new_list(0, NULL);
|
self->descriptor_list = mp_obj_new_list(0, NULL);
|
||||||
|
|
||||||
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
||||||
@ -105,10 +106,6 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
|
|||||||
} else {
|
} else {
|
||||||
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo);
|
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initial_value_bufinfo != NULL) {
|
|
||||||
common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) {
|
mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) {
|
||||||
@ -124,7 +121,6 @@ size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *sel
|
|||||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||||
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
||||||
// self->value is set by evt handler.
|
|
||||||
return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len);
|
return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len);
|
||||||
} else {
|
} else {
|
||||||
// conn_handle is ignored for non-system attributes.
|
// conn_handle is ignored for non-system attributes.
|
||||||
@ -205,7 +201,7 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *
|
|||||||
bleio_attribute_gatts_set_security_mode(&desc_attr_md.write_perm, descriptor->write_perm);
|
bleio_attribute_gatts_set_security_mode(&desc_attr_md.write_perm, descriptor->write_perm);
|
||||||
|
|
||||||
mp_buffer_info_t desc_value_bufinfo;
|
mp_buffer_info_t desc_value_bufinfo;
|
||||||
mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ);
|
mp_get_buffer_raise(descriptor->initial_value, &desc_value_bufinfo, MP_BUFFER_READ);
|
||||||
|
|
||||||
ble_gatts_attr_t desc_attr = {
|
ble_gatts_attr_t desc_attr = {
|
||||||
.p_uuid = &desc_uuid,
|
.p_uuid = &desc_uuid,
|
||||||
|
@ -39,7 +39,7 @@ typedef struct _bleio_characteristic_obj {
|
|||||||
// Will be MP_OBJ_NULL before being assigned to a Service.
|
// Will be MP_OBJ_NULL before being assigned to a Service.
|
||||||
bleio_service_obj_t *service;
|
bleio_service_obj_t *service;
|
||||||
bleio_uuid_obj_t *uuid;
|
bleio_uuid_obj_t *uuid;
|
||||||
mp_obj_t value;
|
mp_obj_t initial_value;
|
||||||
uint16_t max_length;
|
uint16_t max_length;
|
||||||
bool fixed_length;
|
bool fixed_length;
|
||||||
uint16_t handle;
|
uint16_t handle;
|
||||||
|
@ -523,7 +523,7 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio
|
|||||||
characteristic, m_char_discovery_service, gattc_char->handle_value, uuid,
|
characteristic, m_char_discovery_service, gattc_char->handle_value, uuid,
|
||||||
props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
||||||
GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
|
GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc
|
||||||
NULL);
|
mp_const_empty_bytes);
|
||||||
|
|
||||||
mp_obj_list_append(MP_OBJ_FROM_PTR(m_char_discovery_service->characteristic_list),
|
mp_obj_list_append(MP_OBJ_FROM_PTR(m_char_discovery_service->characteristic_list),
|
||||||
MP_OBJ_FROM_PTR(characteristic));
|
MP_OBJ_FROM_PTR(characteristic));
|
||||||
|
@ -39,6 +39,7 @@ void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_c
|
|||||||
self->handle = BLE_GATT_HANDLE_INVALID;
|
self->handle = BLE_GATT_HANDLE_INVALID;
|
||||||
self->read_perm = read_perm;
|
self->read_perm = read_perm;
|
||||||
self->write_perm = write_perm;
|
self->write_perm = write_perm;
|
||||||
|
self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||||
|
|
||||||
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX;
|
||||||
if (max_length < 0 || max_length > max_length_max) {
|
if (max_length < 0 || max_length > max_length_max) {
|
||||||
@ -47,8 +48,6 @@ void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_c
|
|||||||
}
|
}
|
||||||
self->max_length = max_length;
|
self->max_length = max_length;
|
||||||
self->fixed_length = fixed_length;
|
self->fixed_length = fixed_length;
|
||||||
|
|
||||||
common_hal_bleio_descriptor_set_value(self, initial_value_bufinfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
|
bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
|
||||||
@ -81,8 +80,6 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff
|
|||||||
mp_raise_ValueError(translate("Value length > max_length"));
|
mp_raise_ValueError(translate("Value length > max_length"));
|
||||||
}
|
}
|
||||||
|
|
||||||
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
|
||||||
|
|
||||||
// Do GATT operations only if this descriptor has been registered.
|
// Do GATT operations only if this descriptor has been registered.
|
||||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||||
uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection);
|
uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection);
|
||||||
|
@ -41,7 +41,7 @@ typedef struct _bleio_descriptor_obj {
|
|||||||
// Will be MP_OBJ_NULL before being assigned to a Characteristic.
|
// Will be MP_OBJ_NULL before being assigned to a Characteristic.
|
||||||
struct _bleio_characteristic_obj *characteristic;
|
struct _bleio_characteristic_obj *characteristic;
|
||||||
bleio_uuid_obj_t *uuid;
|
bleio_uuid_obj_t *uuid;
|
||||||
mp_obj_t value;
|
mp_obj_t initial_value;
|
||||||
uint16_t max_length;
|
uint16_t max_length;
|
||||||
bool fixed_length;
|
bool fixed_length;
|
||||||
uint16_t handle;
|
uint16_t handle;
|
||||||
|
@ -124,11 +124,14 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self,
|
|||||||
char_attr_md.rd_auth = true;
|
char_attr_md.rd_auth = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
mp_buffer_info_t char_value_bufinfo;
|
||||||
|
mp_get_buffer_raise(characteristic->initial_value, &char_value_bufinfo, MP_BUFFER_READ);
|
||||||
|
|
||||||
ble_gatts_attr_t char_attr = {
|
ble_gatts_attr_t char_attr = {
|
||||||
.p_uuid = &char_uuid,
|
.p_uuid = &char_uuid,
|
||||||
.p_attr_md = &char_attr_md,
|
.p_attr_md = &char_attr_md,
|
||||||
.init_len = 0,
|
.init_len = char_value_bufinfo.len,
|
||||||
.p_value = NULL,
|
.p_value = char_value_bufinfo.buf,
|
||||||
.init_offs = 0,
|
.init_offs = 0,
|
||||||
.max_len = characteristic->max_length,
|
.max_len = characteristic->max_length,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user