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_10_MS (10000)
|
||||
|
||||
#define MAX_ADVERTISEMENT_SIZE (31)
|
||||
|
||||
// TODO make this settable from Python.
|
||||
#define DEFAULT_TX_POWER 0 // 0 dBm
|
||||
#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.
|
||||
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.
|
||||
if (hci_le_read_local_supported_features(self->features) != HCI_OK) {
|
||||
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.
|
||||
uint16_t le_max_len;
|
||||
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;
|
||||
} 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;
|
||||
|
||||
common_hal_bleio_adapter_set_enabled(self, true);
|
||||
bleio_adapter_get_info(self);
|
||||
bleio_adapter_setup(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;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
//FIX if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED ||
|
||||
// (connectable && data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED)) {
|
||||
// mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||
// }
|
||||
if (data_len > MAX_ADVERTISEMENT_SIZE) {
|
||||
mp_raise_ValueError(translate("Data too large for advertisement packet"));
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
));
|
||||
|
||||
// The HCI commands expect 31 octets, even though the actual data length may be shorter.
|
||||
uint8_t full_data[31] = { 0 };
|
||||
// The HCI commands expect MAX_ADVERTISEMENT_SIZE (31)octets,
|
||||
// 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));
|
||||
check_hci_error(hci_le_set_advertising_data(advertising_data_len, 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(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."));
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,13 @@ typedef struct _bleio_adapter_obj_t {
|
||||
bool circuitpython_advertising;
|
||||
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.
|
||||
uint64_t advertising_start_ticks;
|
||||
uint64_t advertising_timeout_msecs; // If zero, do not check.
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
#include "shared-bindings/_bleio/__init__.h"
|
||||
#include "shared-bindings/_bleio/Characteristic.h"
|
||||
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
|
||||
#include "shared-bindings/_bleio/Descriptor.h"
|
||||
#include "shared-bindings/_bleio/PacketBuffer.h"
|
||||
#include "shared-bindings/_bleio/Service.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->read_perm = read_perm;
|
||||
self->write_perm = write_perm;
|
||||
self->descriptor_linked_list = mp_obj_new_list(0, NULL);
|
||||
self->watchers_list = mp_obj_new_list(0, NULL);
|
||||
self->descriptor_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;
|
||||
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 {
|
||||
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) {
|
||||
return self->descriptor_linked_list;
|
||||
mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) {
|
||||
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) {
|
||||
@ -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) {
|
||||
// Do GATT operations only if this characteristic has been added to a registered service.
|
||||
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)) {
|
||||
// self->value is set by evt handler.
|
||||
return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len);
|
||||
//FIX read remote chars
|
||||
//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 {
|
||||
// conn_handle is ignored for non-system attributes.
|
||||
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;
|
||||
}
|
||||
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.
|
||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||
|
||||
if (common_hal_bleio_service_get_is_remote(self->service)) {
|
||||
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||
// Last argument is true if write-no-reponse desired.
|
||||
common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo,
|
||||
(self->props & CHAR_PROP_WRITE_NO_RESPONSE));
|
||||
//FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||
if (self->props & CHAR_PROP_WRITE) {
|
||||
//FIX writing remote chars
|
||||
//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 {
|
||||
// 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.
|
||||
common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo);
|
||||
bleio_characteristic_set_local_value(self, bufinfo);
|
||||
// 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 indicate = self->props & CHAR_PROP_INDICATE;
|
||||
// Read the CCCD value, if there is one.
|
||||
if ((notify | indicate) && self->cccd_handle != BLE_GATT_HANDLE_INVALID) {
|
||||
common_hal_bleio_gatts_read(self->cccd_handle, BLE_CONN_HANDLE_INVALID,
|
||||
(uint8_t *) &cccd, sizeof(cccd));
|
||||
if ((notify | indicate) && self->cccd != NULL) {
|
||||
common_hal_bleio_descriptor_get_value(self->cccd, cccd_bufinfo.buf, cccd_bufinfo.len);
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
if (indicate && (cccd & CCCD_INDICATE)) {
|
||||
if (indicate && (cccd_value & CCCD_INDICATE)) {
|
||||
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.
|
||||
self->service->end_handle = descriptor->handle;
|
||||
|
||||
// Link together all the descriptors for this characteristic.
|
||||
descriptor->next = self->descriptor_linked_list;
|
||||
self->descriptor_linked_list = descriptor;
|
||||
mp_obj_list_append(MP_OBJ_FROM_PTR(self->descriptor_list),
|
||||
MP_OBJ_FROM_PTR(descriptor));
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
@ -174,33 +189,12 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
|
||||
(notify ? CCCD_NOTIFY : 0) |
|
||||
(indicate ? CCCD_INDICATE : 0);
|
||||
|
||||
//FIX do remote
|
||||
(void) cccd_value;
|
||||
//FIX call att_something to set remote CCCD
|
||||
// ble_gattc_write_params_t write_params = {
|
||||
// .write_op = BLE_GATT_OP_WRITE_REQ,
|
||||
// .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);
|
||||
// uint8_t rsp[sizeof(bt_att_error_rsp)];
|
||||
// if (att_write_req(conn_handle, self->cccd->handle, &cccd_value, sizeof(cccd_value)) == 0) {
|
||||
// mp_raise_bleio_BluetoothError(translate("Could not write CCCD"));
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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_uuid_obj_t *uuid;
|
||||
mp_obj_t value;
|
||||
mp_obj_list_t watcher_list;
|
||||
mp_obj_list_t descriptor_linked_list;
|
||||
mp_obj_t observer;
|
||||
mp_obj_list_t *descriptor_list;
|
||||
uint16_t max_length;
|
||||
bool fixed_length;
|
||||
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 write_perm;
|
||||
bleio_descriptor_obj_t *descriptor_linked_list;
|
||||
uint16_t user_desc_handle;
|
||||
uint16_t cccd_handle;
|
||||
uint16_t sccd_handle;
|
||||
bleio_descriptor_obj_t *user_desc;
|
||||
bleio_descriptor_obj_t *cccd;
|
||||
bleio_descriptor_obj_t *sccd;
|
||||
} 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
|
||||
|
@ -37,44 +37,13 @@
|
||||
#include "common-hal/_bleio/CharacteristicBuffer.h"
|
||||
|
||||
// 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) {
|
||||
// uint8_t is_nested_critical_region;
|
||||
// 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 void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
|
||||
ringbuf_put_n(&self->ringbuf, data, len);
|
||||
}
|
||||
|
||||
// STATIC bool characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) {
|
||||
// bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param;
|
||||
// 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;
|
||||
// }
|
||||
void bleio_characteristic_buffer_update(bleio_characteristic_buffer_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||
write_to_ringbuf(self, bufinfo->buf, bufinfo->len);
|
||||
}
|
||||
|
||||
// Assumes that timeout and buffer_size have been validated before call.
|
||||
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.
|
||||
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) {
|
||||
@ -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);
|
||||
|
||||
// Writes now OK.
|
||||
// FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
|
||||
return num_bytes_read;
|
||||
}
|
||||
|
||||
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);
|
||||
//FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
return count;
|
||||
}
|
||||
|
||||
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);
|
||||
//FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
} 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
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include "shared-bindings/_bleio/Connection.h"
|
||||
|
||||
#include "att.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -319,10 +321,11 @@ static volatile bool m_discovery_successful;
|
||||
// }
|
||||
|
||||
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->is_central = false;
|
||||
//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) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
//FIX return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID;
|
||||
return self->connection->conn_handle != BLE_CONN_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -369,8 +371,7 @@ mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_
|
||||
|
||||
// Return the current negotiated MTU length, minus overhead.
|
||||
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 0;
|
||||
return (self->mtu == 0 ? BT_ATT_DEFAULT_LE_MTU : self->mtu) - 3;
|
||||
}
|
||||
|
||||
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) {
|
||||
// bleio_service_obj_t* tail = connection->remote_service_linked_list;
|
||||
|
||||
// for (size_t i = 0; i < response->count; ++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.
|
||||
// service->uuid = NULL;
|
||||
// }
|
||||
|
||||
// service->next = tail;
|
||||
// tail = service;
|
||||
//
|
||||
// mp_obj_list_append(MP_OBJ_FROM_PTR(connection->remote_service_list),
|
||||
// MP_OBJ_FROM_PTR(service));
|
||||
// }
|
||||
|
||||
// connection->remote_service_linked_list = tail;
|
||||
|
||||
//
|
||||
// if (response->count > 0) {
|
||||
// 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
|
||||
// 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) {
|
||||
@ -581,7 +579,8 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
||||
// GATT_MAX_DATA_LENGTH, false, mp_const_empty_bytes);
|
||||
// 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) {
|
||||
@ -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);
|
||||
|
||||
// // 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) {
|
||||
// // 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
|
||||
// // 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;
|
||||
// }
|
||||
// } 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;
|
||||
// while (service != NULL) {
|
||||
// for (size_t i = 0; i < self->remote_service_list->len; i++) {
|
||||
// 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.
|
||||
// if (service->uuid == NULL) {
|
||||
// service = service->next;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
@ -714,11 +715,12 @@ void common_hal_bleio_connection_set_connection_interval(bleio_connection_intern
|
||||
// next_desc_start_handle, next_desc_end_handle)) {
|
||||
// // Get the most recently discovered descriptor, and then ask for descriptors
|
||||
// // 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;
|
||||
// }
|
||||
// }
|
||||
// service = service->next;
|
||||
// }
|
||||
|
||||
// // 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);
|
||||
bleio_connection_ensure_connected(self);
|
||||
// Convert to a tuple and then clear the list so the callee will take ownership.
|
||||
mp_obj_tuple_t *services_tuple = service_linked_list_to_tuple(self->connection->remote_service_linked_list);
|
||||
self->connection->remote_service_linked_list = NULL;
|
||||
|
||||
return services_tuple;
|
||||
mp_obj_tuple_t *services_tuple =
|
||||
mp_obj_new_tuple(self->connection->remote_service_list->len,
|
||||
self->connection->remote_service_list->items);
|
||||
mp_obj_list_clear(MP_OBJ_FROM_PTR(self->connection->remote_service_list));
|
||||
return services_tuple;
|
||||
}
|
||||
|
||||
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.
|
||||
bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle) {
|
||||
//FIX bleio_connection_internal_t *connection;
|
||||
// for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
// connection = &bleio_connections[i];
|
||||
// if (connection->conn_handle == conn_handle) {
|
||||
// return connection;
|
||||
// }
|
||||
// }
|
||||
bleio_connection_internal_t *connection;
|
||||
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
|
||||
connection = &bleio_connections[i];
|
||||
if (connection->conn_handle == conn_handle) {
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ typedef struct {
|
||||
uint16_t conn_handle;
|
||||
bool is_central;
|
||||
// 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
|
||||
// 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).
|
||||
@ -60,7 +60,6 @@ typedef struct {
|
||||
volatile pair_status_t pair_status;
|
||||
uint8_t sec_status; // Internal security status.
|
||||
mp_obj_t connection_obj;
|
||||
//REMOVE ble_drv_evt_handler_entry_t handler_entry;
|
||||
//REMOVE ble_gap_conn_params_t conn_params;
|
||||
volatile bool conn_params_updating;
|
||||
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->read_perm = read_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;
|
||||
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) {
|
||||
// Do GATT operations only if this descriptor has been registered
|
||||
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)) {
|
||||
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 {
|
||||
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.
|
||||
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)) {
|
||||
// false means WRITE_REQ, not write-no-response
|
||||
common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false);
|
||||
//FIX
|
||||
// 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 {
|
||||
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 "supervisor/shared/tick.h"
|
||||
|
||||
// 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)) {
|
||||
// // This shouldn't happen.
|
||||
// return;
|
||||
// }
|
||||
// // Push all the data onto the ring buffer.
|
||||
// //FIX uint8_t is_nested_critical_region;
|
||||
// //FIX sd_nvic_critical_region_enter(&is_nested_critical_region);
|
||||
// // Make room for the new value by dropping the oldest packets first.
|
||||
// while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
|
||||
// uint16_t packet_length;
|
||||
// ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
||||
// for (uint16_t i = 0; i < packet_length; i++) {
|
||||
// ringbuf_get(&self->ringbuf);
|
||||
// }
|
||||
// // set an overflow flag?
|
||||
// }
|
||||
// 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);
|
||||
// }
|
||||
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)) {
|
||||
// This shouldn't happen.
|
||||
return;
|
||||
}
|
||||
// Push all the data onto the ring buffer.
|
||||
// Make room for the new value by dropping the oldest packets first.
|
||||
while (ringbuf_capacity(&self->ringbuf) - ringbuf_num_filled(&self->ringbuf) < len + sizeof(uint16_t)) {
|
||||
uint16_t packet_length;
|
||||
ringbuf_get_n(&self->ringbuf, (uint8_t*) &packet_length, sizeof(uint16_t));
|
||||
for (uint16_t i = 0; i < packet_length; i++) {
|
||||
ringbuf_get(&self->ringbuf);
|
||||
}
|
||||
// set an overflow flag?
|
||||
}
|
||||
ringbuf_put_n(&self->ringbuf, (uint8_t*) &len, sizeof(uint16_t));
|
||||
ringbuf_put_n(&self->ringbuf, data, len);
|
||||
}
|
||||
|
||||
//FIX
|
||||
// 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
|
||||
// // 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
|
||||
// // of the lower level link and ATT layers.
|
||||
// self->packet_queued = false;
|
||||
// if (self->pending_size > 0) {
|
||||
// uint16_t conn_handle = self->conn_handle;
|
||||
// uint32_t err_code;
|
||||
// if (self->client) {
|
||||
// ble_gattc_write_params_t write_params = {
|
||||
// .write_op = self->write_type,
|
||||
// .handle = self->characteristic->handle,
|
||||
// .p_value = self->outgoing[self->pending_index],
|
||||
// .len = self->pending_size,
|
||||
// };
|
||||
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
|
||||
// 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
|
||||
// of the lower level link and ATT layers.
|
||||
self->packet_queued = false;
|
||||
if (self->pending_size > 0) {
|
||||
mp_buffer_info_t bufinfo = {
|
||||
.buf = self->outgoing[self->pending_index],
|
||||
.len = self->pending_size,
|
||||
};
|
||||
common_hal_bleio_characteristic_set_value(self->characteristic, &bufinfo);
|
||||
|
||||
// err_code = sd_ble_gattc_write(conn_handle, &write_params);
|
||||
// } else {
|
||||
// uint16_t hvx_len = self->pending_size;
|
||||
self->pending_size = 0;
|
||||
self->pending_index = (self->pending_index + 1) % 2;
|
||||
self->packet_queued = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ble_gatts_hvx_params_t hvx_params = {
|
||||
// .handle = self->characteristic->handle,
|
||||
// .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 bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_t *bufinfo) {
|
||||
write_to_ringbuf(self, bufinfo->buf, bufinfo->len);
|
||||
}
|
||||
|
||||
void common_hal_bleio_packet_buffer_construct(
|
||||
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->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 outgoing = self->characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE);
|
||||
bleio_characteristic_properties_t incoming =
|
||||
self->characteristic->props & (CHAR_PROP_WRITE_NO_RESPONSE | CHAR_PROP_WRITE);
|
||||
bleio_characteristic_properties_t outgoing =
|
||||
self->characteristic->props & (CHAR_PROP_NOTIFY | CHAR_PROP_INDICATE);
|
||||
|
||||
if (self->client) {
|
||||
// Swap if we're the client.
|
||||
@ -219,32 +117,7 @@ void common_hal_bleio_packet_buffer_construct(
|
||||
self->outgoing[1] = NULL;
|
||||
}
|
||||
|
||||
//FIX if (self->client) {
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
bleio_characteristic_set_observer(self->characteristic, self);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// Copy received data.
|
||||
// Get packet length, which is in first two bytes of packet.
|
||||
uint16_t packet_length;
|
||||
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;
|
||||
}
|
||||
|
||||
// Writes now OK.
|
||||
//FIX sd_nvic_critical_region_exit(is_nested_critical_region);
|
||||
|
||||
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;
|
||||
|
||||
//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];
|
||||
|
||||
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;
|
||||
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 (!self->packet_queued) {
|
||||
//FIX queue_next_write(self);
|
||||
queue_next_write(self);
|
||||
}
|
||||
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) {
|
||||
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;
|
||||
} 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
|
||||
|
@ -70,8 +70,8 @@ bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
|
||||
return self->uuid;
|
||||
}
|
||||
|
||||
mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self) {
|
||||
return self->characteristic_list;
|
||||
mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self) {
|
||||
return mp_obj_new_tuple(self->characteristic_list->len, self->characteristic_list->items);
|
||||
}
|
||||
|
||||
bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) {
|
||||
@ -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.
|
||||
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));
|
||||
}
|
||||
|
@ -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) {
|
||||
// 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) {
|
||||
bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "shared-bindings/_bleio/UUID.h"
|
||||
|
||||
#include "att.h"
|
||||
#include "hci.h"
|
||||
|
||||
void bleio_background(void);
|
||||
@ -44,7 +45,7 @@ typedef struct {
|
||||
|
||||
// We assume variable length data.
|
||||
// 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
|
||||
#define BLE_GATT_HANDLE_INVALID 0x0000
|
||||
|
@ -64,8 +64,6 @@ typedef struct __packed {
|
||||
uint8_t uuid[0]; // 2 or 16 bytes
|
||||
} characteristic_declaration_t;
|
||||
|
||||
//FIX BLEDeviceEventHandler event_handlers[2];
|
||||
|
||||
STATIC uint8_t bleio_properties_to_ble_spec_properties(uint8_t bleio_properties) {
|
||||
uint8_t ble_spec_properties = 0;
|
||||
if (bleio_properties & CHAR_PROP_BROADCAST) {
|
||||
@ -220,21 +218,16 @@ bool att_connect_to_address(bt_addr_le_t *addr) {
|
||||
return is_connected;
|
||||
}
|
||||
|
||||
bool att_disconnect_from_address(bt_addr_le_t *addr) {
|
||||
uint16_t conn_handle = att_conn_handle(addr);
|
||||
if (conn_handle == 0xffff) {
|
||||
bool att_disconnect(uint16_t conn_handle) {
|
||||
if (conn_handle == BLE_CONN_HANDLE_INVALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hci_disconnect(conn_handle);
|
||||
|
||||
hci_poll_for_incoming_pkt_timeout(timeout);
|
||||
|
||||
if (!att_handle_is_connected(conn_handle)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
// Confirm we're now disconnected.
|
||||
return !att_handle_is_connected(conn_handle);
|
||||
}
|
||||
|
||||
//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].mtu = BT_ATT_DEFAULT_LE_MTU;
|
||||
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;
|
||||
}
|
||||
|
||||
//FIX
|
||||
// if (event_handlers[BLEDisconnected]) {
|
||||
// event_handlers[BLEDisconnected](bleDevice);
|
||||
// }
|
||||
|
||||
bleio_connections[peer_index].conn_handle = 0xffff;
|
||||
bleio_connections[peer_index].role = 0x00;
|
||||
memset(&bleio_connections[peer_index].addr, 0x00, sizeof(bleio_connections[peer_index].addr));
|
||||
@ -630,7 +614,7 @@ bool att_disconnect_all(void) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hci_disconnect(bleio_connections[i].conn_handle) != 0) {
|
||||
if (att_disconnect(bleio_connections[i].conn_handle) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1391,7 +1375,8 @@ STATIC void process_write_req_or_cmd(uint16_t conn_handle, uint16_t mtu, uint8_t
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
//FIX need to set up event handlers, etc.?
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//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[]) {
|
||||
struct __packed {
|
||||
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;
|
||||
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[]) {
|
||||
@ -1738,3 +1714,76 @@ void att_process_data(uint16_t conn_handle, uint8_t dlen, uint8_t data[]) {
|
||||
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);
|
||||
bool att_address_is_connected(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_from_address(bt_addr_le_t *addr);
|
||||
bool att_discover_attributes(bt_addr_le_t *addr, const char* service_uuid_filter);
|
||||
bool att_exchange_mtu(uint16_t conn_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*) pkt->params;
|
||||
(void) disconn_complete;
|
||||
//FIX
|
||||
// ATT.removeConnection(disconn_complete->handle, disconn_complete->reason);
|
||||
// L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason);
|
||||
|
||||
att_remove_connection(disconn_complete->handle, disconn_complete->reason);
|
||||
//FIX L2CAPSignaling.removeConnection(disconn_complete->handle, disconn_complete->reason);
|
||||
hci_le_set_advertising_enable(0x01);
|
||||
break;
|
||||
}
|
||||
|
||||
case BT_HCI_EVT_CMD_COMPLETE: {
|
||||
|
||||
struct cmd_complete_with_status {
|
||||
struct bt_hci_evt_cmd_complete cmd_complete;
|
||||
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;
|
||||
|
||||
if (le_conn_complete->status == BT_HCI_ERR_SUCCESS) {
|
||||
// ATT.addConnection(le_conn_complete->handle,
|
||||
// le_conn_complete->role,
|
||||
// le_conn_complete->peer_addr //FIX struct
|
||||
// le_conn_complete->interval,
|
||||
// le_conn_complete->latency,
|
||||
// le_conn_complete->supv_timeout
|
||||
// le_conn_complete->clock_accuracy);
|
||||
att_add_connection(
|
||||
le_conn_complete->handle,
|
||||
le_conn_complete->role,
|
||||
&le_conn_complete->peer_addr,
|
||||
le_conn_complete->interval,
|
||||
le_conn_complete->latency,
|
||||
le_conn_complete->supv_timeout,
|
||||
le_conn_complete->clock_accuracy);
|
||||
|
||||
}
|
||||
} 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_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
|
||||
// GAP.handleLeAdvertisingReport(leAdvertisingReport->type,
|
||||
// leAdvertisingReport->peerBdaddrType,
|
||||
@ -538,7 +539,7 @@ hci_result_t hci_read_rssi(uint16_t handle, int *rssi) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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_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
|
||||
|
@ -90,6 +90,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
|
||||
self->props = props;
|
||||
self->read_perm = read_perm;
|
||||
self->write_perm = write_perm;
|
||||
self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||
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;
|
||||
@ -105,10 +106,6 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
|
||||
} else {
|
||||
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) {
|
||||
@ -124,7 +121,6 @@ size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *sel
|
||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
|
||||
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);
|
||||
} else {
|
||||
// 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);
|
||||
|
||||
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 = {
|
||||
.p_uuid = &desc_uuid,
|
||||
|
@ -39,7 +39,7 @@ typedef struct _bleio_characteristic_obj {
|
||||
// Will be MP_OBJ_NULL before being assigned to a Service.
|
||||
bleio_service_obj_t *service;
|
||||
bleio_uuid_obj_t *uuid;
|
||||
mp_obj_t value;
|
||||
mp_obj_t initial_value;
|
||||
uint16_t max_length;
|
||||
bool fixed_length;
|
||||
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,
|
||||
props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN,
|
||||
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_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->read_perm = read_perm;
|
||||
self->write_perm = write_perm;
|
||||
self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
|
||||
|
||||
const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_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->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) {
|
||||
@ -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"));
|
||||
}
|
||||
|
||||
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
|
||||
|
||||
// Do GATT operations only if this descriptor has been registered.
|
||||
if (self->handle != BLE_GATT_HANDLE_INVALID) {
|
||||
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.
|
||||
struct _bleio_characteristic_obj *characteristic;
|
||||
bleio_uuid_obj_t *uuid;
|
||||
mp_obj_t value;
|
||||
mp_obj_t initial_value;
|
||||
uint16_t max_length;
|
||||
bool fixed_length;
|
||||
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;
|
||||
#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 = {
|
||||
.p_uuid = &char_uuid,
|
||||
.p_attr_md = &char_attr_md,
|
||||
.init_len = 0,
|
||||
.p_value = NULL,
|
||||
.init_len = char_value_bufinfo.len,
|
||||
.p_value = char_value_bufinfo.buf,
|
||||
.init_offs = 0,
|
||||
.max_len = characteristic->max_length,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user