Skip to content

Commit 1dc3957

Browse files
committed
LocalPeripheral is now Peripheral; more work on basic GATTS support; UART not working yet
1 parent ef39e72 commit 1dc3957

14 files changed

Lines changed: 192 additions & 95 deletions

File tree

ports/nrf/common-hal/bleio/Characteristic.c

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,63 @@
3535
#include "common-hal/bleio/__init__.h"
3636
#include "shared-module/bleio/Characteristic.h"
3737

38-
38+
// TODO - should these be per object?? *****
3939
STATIC volatile bleio_characteristic_obj_t *m_read_characteristic;
4040
STATIC volatile uint8_t m_tx_in_progress;
4141
STATIC nrf_mutex_t *m_write_mutex;
4242

43+
STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) {
44+
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
45+
uint16_t cccd;
46+
ble_gatts_value_t value = {
47+
.p_value = (uint8_t*) &cccd,
48+
.len = 2,
49+
};
50+
51+
const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->cccd_handle, &value);
52+
53+
54+
if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) {
55+
// CCCD is not set, so say that neither Notify nor Indicate is enabled.
56+
cccd = 0;
57+
} else if (err_code != NRF_SUCCESS) {
58+
mp_raise_OSError_msg_varg(translate("Failed to read CCD value, err 0x%04x"), err_code);
59+
}
60+
61+
return cccd;
62+
}
63+
64+
STATIC void gatts_read(bleio_characteristic_obj_t *characteristic) {
65+
// This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
66+
// we can still read and write the local value.
67+
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
68+
69+
mp_buffer_info_t bufinfo;
70+
ble_gatts_value_t gatts_value = {
71+
.p_value = NULL,
72+
.len = 0,
73+
};
74+
75+
// Read once to find out what size buffer we need, then read again to fill buffer.
76+
77+
uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value);
78+
if (err_code == NRF_SUCCESS) {
79+
characteristic->value_data = mp_obj_new_bytearray_of_zeros(gatts_value.len);
80+
mp_get_buffer_raise(characteristic->value_data, &bufinfo, MP_BUFFER_WRITE);
81+
82+
// Read again, with the correct size of buffer.
83+
err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value);
84+
}
85+
86+
if (err_code != NRF_SUCCESS) {
87+
mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code);
88+
}
89+
}
90+
4391

4492
STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
93+
// This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
94+
// we can still read and write the local value.
4595
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
4696

4797
ble_gatts_value_t gatts_value = {
@@ -55,12 +105,12 @@ STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_in
55105
}
56106
}
57107

58-
STATIC void gatts_notify(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
108+
STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo, uint16_t hvx_type) {
59109
uint16_t hvx_len = bufinfo->len;
60110

61111
ble_gatts_hvx_params_t hvx_params = {
62112
.handle = characteristic->handle,
63-
.type = BLE_GATT_HVX_NOTIFICATION,
113+
.type = hvx_type,
64114
.offset = 0,
65115
.p_len = &hvx_len,
66116
.p_data = bufinfo->buf,
@@ -163,30 +213,46 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self)
163213
ble_drv_add_event_handler(on_ble_evt, NULL);
164214
}
165215

166-
void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self) {
216+
void common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) {
167217
switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
168218
case GATT_ROLE_CLIENT:
169219
gattc_read(self);
170220
break;
171221

222+
case GATT_ROLE_SERVER:
223+
gatts_read(self);
224+
break;
225+
172226
default:
173227
mp_raise_RuntimeError(translate("bad GATT role"));
174228
break;
175229
}
176230
}
177231

178-
void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
232+
void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
233+
bool sent = false;
234+
uint16_t cccd = 0;
235+
179236
switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
180237
case GATT_ROLE_SERVER:
181-
if (self->props.notify) {
182-
gatts_notify(self, bufinfo);
183-
} else {
238+
if (self->props.notify || self->props.indicate) {
239+
cccd = get_cccd(self);
240+
}
241+
// It's possible that both notify and indicate are set.
242+
if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
243+
gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION);
244+
sent = true;
245+
}
246+
if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
247+
gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION);
248+
sent = true;
249+
}
250+
if (!sent) {
184251
gatts_write(self, bufinfo);
185252
}
186253
break;
187254

188255
case GATT_ROLE_CLIENT:
189-
// TODO: Add indications
190256
gattc_write(self, bufinfo);
191257
break;
192258

ports/nrf/common-hal/bleio/LocalPeripheral.c renamed to ports/nrf/common-hal/bleio/Peripheral.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* The MIT License (MIT)
55
*
66
* Copyright (c) 2018 Artur Pacholec
7+
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
78
*
89
* Permission is hereby granted, free of charge, to any person obtaining a copy
910
* of this software and associated documentation files (the "Software"), to deal
@@ -35,7 +36,7 @@
3536
#include "py/runtime.h"
3637
#include "shared-bindings/bleio/Adapter.h"
3738
#include "shared-bindings/bleio/Characteristic.h"
38-
#include "shared-bindings/bleio/LocalPeripheral.h"
39+
#include "shared-bindings/bleio/Peripheral.h"
3940
#include "shared-bindings/bleio/Service.h"
4041
#include "shared-bindings/bleio/UUID.h"
4142

@@ -56,7 +57,7 @@ STATIC void check_data_fit(size_t pos, size_t data_len) {
5657
}
5758
}
5859

59-
STATIC uint32_t add_services_to_advertisement(bleio_local_peripheral_obj_t *self, size_t* adv_data_pos_p, size_t uuid_len) {
60+
STATIC uint32_t add_services_to_advertisement(bleio_peripheral_obj_t *self, size_t* adv_data_pos_p, size_t uuid_len) {
6061
uint32_t uuids_total_size = 0;
6162
const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list);
6263
uint32_t err_code = NRF_SUCCESS;
@@ -99,7 +100,7 @@ STATIC uint32_t add_services_to_advertisement(bleio_local_peripheral_obj_t *self
99100

100101

101102

102-
STATIC uint32_t set_advertisement_data(bleio_local_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
103+
STATIC uint32_t set_advertisement_data(bleio_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
103104
common_hal_bleio_adapter_set_enabled(true);
104105

105106
size_t adv_data_pos = 0;
@@ -203,7 +204,7 @@ STATIC uint32_t set_advertisement_data(bleio_local_peripheral_obj_t *self, bool
203204
m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
204205
}
205206

206-
common_hal_bleio_local_peripheral_stop_advertising(self);
207+
common_hal_bleio_peripheral_stop_advertising(self);
207208

208209
const ble_gap_adv_data_t ble_gap_adv_data = {
209210
.adv_data.p_data = self->adv_data,
@@ -221,7 +222,7 @@ STATIC uint32_t set_advertisement_data(bleio_local_peripheral_obj_t *self, bool
221222
}
222223

223224
STATIC void on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
224-
bleio_local_peripheral_obj_t *self = (bleio_local_peripheral_obj_t*)self_in;
225+
bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in;
225226

226227
switch (ble_evt->header.evt_id) {
227228
case BLE_GAP_EVT_CONNECTED: {
@@ -266,14 +267,17 @@ STATIC void on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
266267
break;
267268
}
268269

270+
default:
271+
mp_printf(&mp_plat_print, "Unhandled event: 0x%04x\n", ble_evt->header.evt_id);
272+
break;
269273
}
270274
}
271275

272276

273-
void common_hal_bleio_local_peripheral_construct(bleio_local_peripheral_obj_t *self) {
277+
void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self) {
274278
common_hal_bleio_adapter_set_enabled(true); // TODO -- Do this somewhere else maybe bleio __init__
275279

276-
self->gatt_role = GATT_ROLE_NONE;
280+
self->gatt_role = GATT_ROLE_SERVER;
277281
self->conn_handle = BLE_CONN_HANDLE_INVALID;
278282

279283
// Add all the services.
@@ -301,11 +305,11 @@ void common_hal_bleio_local_peripheral_construct(bleio_local_peripheral_obj_t *s
301305
}
302306

303307

304-
bool common_hal_bleio_local_peripheral_get_connected(bleio_local_peripheral_obj_t *self) {
308+
bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self) {
305309
return self->conn_handle != BLE_CONN_HANDLE_INVALID;
306310
}
307311

308-
void common_hal_bleio_local_peripheral_start_advertising(bleio_local_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
312+
void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
309313
if (connectable) {
310314
ble_drv_add_event_handler(on_ble_evt, self);
311315
}
@@ -316,7 +320,7 @@ void common_hal_bleio_local_peripheral_start_advertising(bleio_local_peripheral_
316320
}
317321
}
318322

319-
void common_hal_bleio_local_peripheral_stop_advertising(bleio_local_peripheral_obj_t *self) {
323+
void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self) {
320324

321325
if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET)
322326
return;

ports/nrf/common-hal/bleio/LocalPeripheral.h renamed to ports/nrf/common-hal/bleio/Peripheral.h

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
* THE SOFTWARE.
2626
*/
2727

28-
#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_LOCALPERIPHERAL_H
29-
#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_LOCALPERIPHERAL_H
28+
#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H
29+
#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H
3030

3131
#include <stdbool.h>
3232

@@ -35,17 +35,6 @@
3535
#include "shared-module/bleio/__init__.h"
3636
#include "shared-module/bleio/Address.h"
3737

38-
// typedef struct {
39-
// mp_obj_base_t base;
40-
// bool is_peripheral;
41-
// mp_obj_t name;
42-
// bleio_address_obj_t address;
43-
// volatile uint16_t conn_handle;
44-
// mp_obj_t service_list;
45-
// mp_obj_t notif_handler;
46-
// mp_obj_t conn_handler;
47-
// } bleio_device_obj_t;
48-
4938
typedef struct {
5039
mp_obj_base_t base;
5140
mp_obj_t name;
@@ -59,6 +48,6 @@ typedef struct {
5948
// there are tricks to get the SD to notice (see DevZone - TBS).
6049
uint8_t adv_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];
6150

62-
} bleio_local_peripheral_obj_t;
51+
} bleio_peripheral_obj_t;
6352

64-
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_LOCALPERIPHERAL_H
53+
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H

ports/nrf/common-hal/bleio/__init__.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "shared-bindings/bleio/__init__.h"
2929
#include "shared-bindings/bleio/Adapter.h"
30+
#include "shared-bindings/bleio/Peripheral.h"
3031
#include "common-hal/bleio/__init__.h"
3132

3233
// Turn off BLE on a reset or reload.
@@ -43,3 +44,25 @@ const super_adapter_obj_t common_hal_bleio_adapter_obj = {
4344
.type = &bleio_adapter_type,
4445
},
4546
};
47+
48+
gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device) {
49+
if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
50+
return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
51+
// Does not exist yet.
52+
// } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
53+
// return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
54+
} else {
55+
return GATT_ROLE_NONE;
56+
}
57+
}
58+
59+
uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) {
60+
if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
61+
return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
62+
// Does not exist yet.
63+
// } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
64+
// return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
65+
} else {
66+
return 0;
67+
}
68+
}

ports/nrf/common-hal/bleio/__init__.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
// 20 bytes max (23 - 3).
3737
#define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3)
3838

39+
gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device);
3940
uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
4041

4142
#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_INIT_H

py/obj.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ mp_obj_t mp_obj_new_str_via_qstr(const char* data, size_t len);
640640
mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr);
641641
mp_obj_t mp_obj_new_bytes(const byte* data, size_t len);
642642
mp_obj_t mp_obj_new_bytearray(size_t n, void *items);
643+
mp_obj_t mp_obj_new_bytearray_of_zeros(size_t n);
643644
mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items);
644645
#if MICROPY_PY_BUILTINS_FLOAT
645646
mp_obj_t mp_obj_new_int_from_float(mp_float_t val);

py/objarray.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,12 @@ mp_obj_t mp_obj_new_bytearray(size_t n, void *items) {
611611
return MP_OBJ_FROM_PTR(o);
612612
}
613613

614+
mp_obj_t mp_obj_new_bytearray_of_zeros(size_t n) {
615+
mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n);
616+
memset(o->items, 0, n);
617+
return MP_OBJ_FROM_PTR(o);
618+
}
619+
614620
// Create bytearray which references specified memory area
615621
mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items) {
616622
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);

shared-bindings/bleio/Characteristic.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ const mp_obj_property_t bleio_characteristic_uuid_obj = {
233233
STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) {
234234
bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in);
235235

236-
common_hal_bleio_characteristic_read_value(self);
236+
common_hal_bleio_characteristic_get_value(self);
237237

238238
return self->value_data;
239239
}
@@ -245,7 +245,7 @@ STATIC mp_obj_t bleio_characteristic_set_value(mp_obj_t self_in, mp_obj_t value_
245245
mp_buffer_info_t bufinfo;
246246
mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ);
247247

248-
common_hal_bleio_characteristic_write_value(self, &bufinfo);
248+
common_hal_bleio_characteristic_set_value(self, &bufinfo);
249249

250250
return mp_const_none;
251251
}

shared-bindings/bleio/Characteristic.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
extern const mp_obj_type_t bleio_characteristic_type;
3333

3434
extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self);
35-
extern void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self);
36-
extern void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
35+
extern void common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self);
36+
extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo);
3737

3838
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H

0 commit comments

Comments
 (0)