Skip to content

Commit 44c9c43

Browse files
committed
ble_uart_echo_test works
1 parent 06f3b40 commit 44c9c43

24 files changed

+352
-589
lines changed

devices/ble_hci/common-hal/_bleio/Adapter.c

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
#define UNIT_1_25_MS (1250)
6161
#define UNIT_10_MS (10000)
6262

63+
#define MAX_ADVERTISEMENT_SIZE (31)
64+
6365
// TODO make this settable from Python.
6466
#define DEFAULT_TX_POWER 0 // 0 dBm
6567
#define MAX_ANONYMOUS_ADV_TIMEOUT_SECS (60*15)
@@ -179,13 +181,31 @@ STATIC void bleio_adapter_reset_name(bleio_adapter_obj_t *self) {
179181
}
180182

181183
// Get various values and limits set by the adapter.
182-
STATIC void bleio_adapter_get_info(bleio_adapter_obj_t *self) {
184+
// Set event mask.
185+
STATIC void bleio_adapter_setup(bleio_adapter_obj_t *self) {
183186

187+
// Get version information.
188+
if (hci_read_local_version(&self->hci_version, &self->hci_revision, &self->lmp_version,
189+
&self->manufacturer, &self->lmp_subversion) != HCI_OK) {
190+
mp_raise_bleio_BluetoothError(translate("Could not read HCI version"));
191+
}
184192
// Get supported features.
185193
if (hci_le_read_local_supported_features(self->features) != HCI_OK) {
186194
mp_raise_bleio_BluetoothError(translate("Could not read BLE features"));
187195
}
188196

197+
// Enabled desired events.
198+
// Most importantly, includes:
199+
// BT_EVT_MASK_LE_META_EVENT BT_EVT_BIT(61)
200+
if (hci_set_event_mask(0x3FFFFFFFFFFFFFFF) != HCI_OK) {
201+
mp_raise_bleio_BluetoothError(translate("Could not set event mask"));
202+
}
203+
// The default events for LE are:
204+
// BT_EVT_MASK_LE_CONN_COMPLETE, BT_EVT_MASK_LE_ADVERTISING_REPORT,
205+
// BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE, BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE
206+
// BT_EVT_MASK_LE_LTK_REQUEST.
207+
// That's all we need right now, so we don't bother to set the LE event mask.
208+
189209
// Get ACL buffer info.
190210
uint16_t le_max_len;
191211
uint8_t le_max_num;
@@ -213,7 +233,7 @@ STATIC void bleio_adapter_get_info(bleio_adapter_obj_t *self) {
213233
}
214234
self->max_adv_data_len = max_adv_data_len;
215235
} else {
216-
self->max_adv_data_len = 31;
236+
self->max_adv_data_len = MAX_ADVERTISEMENT_SIZE;
217237
}
218238
}
219239

@@ -226,7 +246,7 @@ void common_hal_bleio_adapter_hci_uart_init(bleio_adapter_obj_t *self, busio_uar
226246
self->enabled = false;
227247

228248
common_hal_bleio_adapter_set_enabled(self, true);
229-
bleio_adapter_get_info(self);
249+
bleio_adapter_setup(self);
230250
bleio_adapter_reset_name(self);
231251
}
232252

@@ -477,14 +497,10 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
477497
return mp_const_none;
478498
}
479499

480-
// The nRF SD 6.1.0 can only do one concurrent advertisement so share the advertising handle.
481-
//FIX uint8_t adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
482-
483500
STATIC void check_data_fit(size_t data_len, bool connectable) {
484-
//FIX if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED ||
485-
// (connectable && data_len > BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_CONNECTABLE_MAX_SUPPORTED)) {
486-
// mp_raise_ValueError(translate("Data too large for advertisement packet"));
487-
// }
501+
if (data_len > MAX_ADVERTISEMENT_SIZE) {
502+
mp_raise_ValueError(translate("Data too large for advertisement packet"));
503+
}
488504
}
489505

490506
// 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,
604620
0x00 // filter policy: no filter
605621
));
606622

607-
// The HCI commands expect 31 octets, even though the actual data length may be shorter.
608-
uint8_t full_data[31] = { 0 };
623+
// The HCI commands expect MAX_ADVERTISEMENT_SIZE (31)octets,
624+
// even though the actual data length may be shorter.
625+
uint8_t full_data[MAX_ADVERTISEMENT_SIZE] = { 0 };
609626
memcpy(full_data, advertising_data, MIN(sizeof(full_data), advertising_data_len));
610627
check_hci_error(hci_le_set_advertising_data(advertising_data_len, full_data));
611628
memset(full_data, 0, sizeof(full_data));
@@ -636,7 +653,7 @@ void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, bool
636653
check_data_fit(advertising_data_bufinfo->len, connectable);
637654
check_data_fit(scan_response_data_bufinfo->len, connectable);
638655

639-
if (advertising_data_bufinfo->len > 31 && scan_response_data_bufinfo->len > 0) {
656+
if (advertising_data_bufinfo->len > MAX_ADVERTISEMENT_SIZE && scan_response_data_bufinfo->len > 0) {
640657
mp_raise_bleio_BluetoothError(translate("Extended advertisements with scan response not supported."));
641658
}
642659

devices/ble_hci/common-hal/_bleio/Adapter.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ typedef struct _bleio_adapter_obj_t {
5656
bool circuitpython_advertising;
5757
bool enabled;
5858

59+
// HCI adapter version info.
60+
uint8_t hci_version;
61+
uint8_t lmp_version;
62+
uint16_t hci_revision;
63+
uint16_t manufacturer;
64+
uint16_t lmp_subversion;
65+
5966
// Used to monitor advertising timeout for legacy avertising.
6067
uint64_t advertising_start_ticks;
6168
uint64_t advertising_timeout_msecs; // If zero, do not check.

devices/ble_hci/common-hal/_bleio/Characteristic.c

Lines changed: 65 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929

3030
#include "shared-bindings/_bleio/__init__.h"
3131
#include "shared-bindings/_bleio/Characteristic.h"
32+
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
3233
#include "shared-bindings/_bleio/Descriptor.h"
34+
#include "shared-bindings/_bleio/PacketBuffer.h"
3335
#include "shared-bindings/_bleio/Service.h"
3436

3537
#include "common-hal/_bleio/Adapter.h"
@@ -47,8 +49,12 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
4749
self->props = props;
4850
self->read_perm = read_perm;
4951
self->write_perm = write_perm;
50-
self->descriptor_linked_list = mp_obj_new_list(0, NULL);
51-
self->watchers_list = mp_obj_new_list(0, NULL);
52+
self->descriptor_list = mp_obj_new_list(0, NULL);
53+
self->observer = mp_const_none;
54+
self->user_desc = NULL;
55+
self->cccd = NULL;
56+
self->sccd = NULL;
57+
self->value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len);
5258

5359
const mp_int_t max_length_max = 512;
5460
if (max_length < 0 || max_length > max_length_max) {
@@ -62,14 +68,10 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
6268
} else {
6369
common_hal_bleio_service_add_characteristic(self->service, self, initial_value_bufinfo);
6470
}
65-
66-
if (initial_value_bufinfo != NULL) {
67-
common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo);
68-
}
6971
}
7072

71-
bleio_descriptor_obj_t *common_hal_bleio_characteristic_get_descriptor_linked_list(bleio_characteristic_obj_t *self) {
72-
return self->descriptor_linked_list;
73+
mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) {
74+
return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items);
7375
}
7476

7577
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
7981
size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t* buf, size_t len) {
8082
// Do GATT operations only if this characteristic has been added to a registered service.
8183
if (self->handle != BLE_GATT_HANDLE_INVALID) {
82-
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
84+
//FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
8385
if (common_hal_bleio_service_get_is_remote(self->service)) {
84-
// self->value is set by evt handler.
85-
return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len);
86+
//FIX read remote chars
87+
//uint8_t rsp[MAX(len, 512)];
88+
//FIX improve att_read_req to write into our requested buffer.
89+
// return att_read_req(conn_handle, self->handle, rsp);
90+
return 0; //FIX
8691
} else {
87-
// conn_handle is ignored for non-system attributes.
88-
return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len);
92+
mp_buffer_info_t bufinfo;
93+
if (!mp_get_buffer(self->value, &bufinfo, MP_BUFFER_READ)) {
94+
return 0;
95+
}
96+
memcpy(buf, bufinfo.buf, MIN(len, bufinfo.len));
8997
}
9098
}
9199

@@ -102,32 +110,40 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self,
102110

103111
// Do GATT operations only if this characteristic has been added to a registered service.
104112
if (self->handle != BLE_GATT_HANDLE_INVALID) {
105-
106113
if (common_hal_bleio_service_get_is_remote(self->service)) {
107-
uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
108-
// Last argument is true if write-no-reponse desired.
109-
common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo,
110-
(self->props & CHAR_PROP_WRITE_NO_RESPONSE));
114+
//FIX uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection);
115+
if (self->props & CHAR_PROP_WRITE) {
116+
//FIX writing remote chars
117+
//uint8_t rsp[sizeof(bt_att_error_rsp)];
118+
//att_write_req(conn_handle, self->handle, bufinfo->buf, bufinfo->len, rsp);
119+
} else if (self->props & CHAR_PROP_WRITE_NO_RESPONSE) {
120+
//att_write_cmd(conn_handle, self->handle, bufinfo->buff, bufinfo->len);
121+
} else {
122+
mp_raise_bleio_BluetoothError(translate("Characteristic not writable"));
123+
}
111124
} else {
112125
// Always write the value locally even if no connections are active.
113-
// conn_handle is ignored for non-system attributes, so we use BLE_CONN_HANDLE_INVALID.
114-
common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo);
126+
bleio_characteristic_set_local_value(self, bufinfo);
115127
// Notify or indicate all active connections.
116-
uint16_t cccd = 0;
128+
129+
uint16_t cccd_value = 0;
130+
mp_buffer_info_t cccd_bufinfo = {
131+
.buf = &cccd_value,
132+
.len = sizeof(cccd_value),
133+
};
117134

118135
const bool notify = self->props & CHAR_PROP_NOTIFY;
119136
const bool indicate = self->props & CHAR_PROP_INDICATE;
120137
// Read the CCCD value, if there is one.
121-
if ((notify | indicate) && self->cccd_handle != BLE_GATT_HANDLE_INVALID) {
122-
common_hal_bleio_gatts_read(self->cccd_handle, BLE_CONN_HANDLE_INVALID,
123-
(uint8_t *) &cccd, sizeof(cccd));
138+
if ((notify | indicate) && self->cccd != NULL) {
139+
common_hal_bleio_descriptor_get_value(self->cccd, cccd_bufinfo.buf, cccd_bufinfo.len);
124140
}
125141

126142
// It's possible that both notify and indicate are set.
127-
if (notify && (cccd & CCCD_NOTIFY)) {
143+
if (notify && (cccd_value & CCCD_NOTIFY)) {
128144
att_notify(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
129145
}
130-
if (indicate && (cccd & CCCD_INDICATE)) {
146+
if (indicate && (cccd_value & CCCD_INDICATE)) {
131147
att_indicate(self->handle, bufinfo->buf, MIN(bufinfo->len, self->max_length));
132148

133149
}
@@ -153,13 +169,12 @@ void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *
153169
// Include this descriptor in the service handle's range.
154170
self->service->end_handle = descriptor->handle;
155171

156-
// Link together all the descriptors for this characteristic.
157-
descriptor->next = self->descriptor_linked_list;
158-
self->descriptor_linked_list = descriptor;
172+
mp_obj_list_append(MP_OBJ_FROM_PTR(self->descriptor_list),
173+
MP_OBJ_FROM_PTR(descriptor));
159174
}
160175

161176
void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
162-
if (self->cccd_handle == BLE_GATT_HANDLE_INVALID) {
177+
if (self->cccd == NULL) {
163178
mp_raise_bleio_BluetoothError(translate("No CCCD for this Characteristic"));
164179
}
165180

@@ -174,48 +189,38 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
174189
(notify ? CCCD_NOTIFY : 0) |
175190
(indicate ? CCCD_INDICATE : 0);
176191

192+
//FIX do remote
177193
(void) cccd_value;
178-
//FIX call att_something to set remote CCCD
179-
// ble_gattc_write_params_t write_params = {
180-
// .write_op = BLE_GATT_OP_WRITE_REQ,
181-
// .handle = self->cccd_handle,
182-
// .p_value = (uint8_t *) &cccd_value,
183-
// .len = 2,
184-
// };
185-
186-
// while (1) {
187-
// uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
188-
// if (err_code == NRF_SUCCESS) {
189-
// break;
190-
// }
191-
192-
// // Write with response will return NRF_ERROR_BUSY if the response has not been received.
193-
// // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
194-
// if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
195-
// // We could wait for an event indicating the write is complete, but just retrying is easier.
196-
// RUN_BACKGROUND_TASKS;
197-
// continue;
198-
// }
199-
200-
// // Some real error occurred.
201-
// check_nrf_error(err_code);
194+
// uint8_t rsp[sizeof(bt_att_error_rsp)];
195+
// if (att_write_req(conn_handle, self->cccd->handle, &cccd_value, sizeof(cccd_value)) == 0) {
196+
// mp_raise_bleio_BluetoothError(translate("Could not write CCCD"));
202197
// }
203-
204198
}
205199

206200
bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
207201
if (self->fixed_length && bufinfo->len != self->max_length) {
208202
return false;
209203
}
210204
if (bufinfo->len > self->max_length) {
211-
bool
205+
return false;
212206
}
213207

214-
mp_buffer_info_t char_bufinfo;
215-
if (!mp_get_buffer(characteristic->value, &bufinfo, MP_BUFFER_WRITE)) {
208+
self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len);
209+
210+
if (MP_OBJ_IS_TYPE(self->observer, &bleio_characteristic_buffer_type)) {
211+
bleio_characteristic_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
212+
} else if (MP_OBJ_IS_TYPE(self->observer, &bleio_packet_buffer_type)) {
213+
bleio_packet_buffer_update(MP_OBJ_FROM_PTR(self->observer), bufinfo);
214+
} else {
216215
return false;
217216
}
218-
memcpy(&char_bufinfo->buf, bufinfo->buf, bufinfo->len);
217+
return true;
218+
}
219+
220+
void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer) {
221+
self->observer = observer;
222+
}
219223

220-
for (size_t i; i < characteristic->set_callbacks.
224+
void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self) {
225+
self->observer = mp_const_none;
221226
}

devices/ble_hci/common-hal/_bleio/Characteristic.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ typedef struct _bleio_characteristic_obj {
4040
bleio_service_obj_t *service;
4141
bleio_uuid_obj_t *uuid;
4242
mp_obj_t value;
43-
mp_obj_list_t watcher_list;
44-
mp_obj_list_t descriptor_linked_list;
43+
mp_obj_t observer;
44+
mp_obj_list_t *descriptor_list;
4545
uint16_t max_length;
4646
bool fixed_length;
4747
uint16_t decl_handle;
@@ -50,9 +50,14 @@ typedef struct _bleio_characteristic_obj {
5050
bleio_attribute_security_mode_t read_perm;
5151
bleio_attribute_security_mode_t write_perm;
5252
bleio_descriptor_obj_t *descriptor_linked_list;
53-
uint16_t user_desc_handle;
54-
uint16_t cccd_handle;
55-
uint16_t sccd_handle;
53+
bleio_descriptor_obj_t *user_desc;
54+
bleio_descriptor_obj_t *cccd;
55+
bleio_descriptor_obj_t *sccd;
5656
} bleio_characteristic_obj_t;
5757

58+
bool bleio_characteristic_set_local_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
59+
60+
void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer);
61+
void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self);
62+
5863
#endif // MICROPY_INCLUDED_BLE_HCI_COMMON_HAL_CHARACTERISTIC_H

0 commit comments

Comments
 (0)