Skip to content

Commit bc9ec1c

Browse files
committed
extmod/modbluetooth: Merge gatts_notify/indicate implementation.
Makes gatts_notify and gatts_indicate work in the same way: by default they send the DB value, but you can manually override the payload. In other words, makes gatts_indicate work the same as gatts_notify. Note: This removes support for queuing notifications and indications on btstack when the ACL buffer is full. This functionality will be reimplemented in a future commit. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent 9e6885a commit bc9ec1c

File tree

6 files changed

+88
-173
lines changed

6 files changed

+88
-173
lines changed

docs/library/bluetooth.rst

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -514,19 +514,24 @@ writes from a client to a given characteristic, use
514514

515515
Sends a notification request to a connected client.
516516

517-
If *data* is not ``None``, then that value is sent to the client as part of
518-
the notification. The local value will not be modified.
517+
If *data* is ``None`` (the default), then the current local value (as set
518+
with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
519519

520-
Otherwise, if *data* is ``None``, then the current local value (as
521-
set with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
520+
Otherwise, if *data* is not ``None``, then that value is sent to the client
521+
as part of the notification. The local value will not be modified.
522522

523523
**Note:** The notification will be sent regardless of the subscription
524524
status of the client to this characteristic.
525525

526-
.. method:: BLE.gatts_indicate(conn_handle, value_handle, /)
526+
.. method:: BLE.gatts_indicate(conn_handle, value_handle, data=None, /)
527527

528-
Sends an indication request containing the characteristic's current value to
529-
a connected client.
528+
Sends a indication request to a connected client.
529+
530+
If *data* is ``None`` (the default), then the current local value (as set
531+
with :meth:`gatts_write <BLE.gatts_write>`) will be sent.
532+
533+
Otherwise, if *data* is not ``None``, then that value is sent to the client
534+
as part of the indication. The local value will not be modified.
530535

531536
On acknowledgment (or failure, e.g. timeout), the
532537
``_IRQ_GATTS_INDICATE_DONE`` event will be raised.

extmod/btstack/modbluetooth_btstack.c

Lines changed: 23 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,6 @@ STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(uint16_t uuid16, const uint8_t *uu
130130
// Pending operation types.
131131
enum {
132132
// Queued for sending when possible.
133-
MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY, // Waiting for context callback
134-
MP_BLUETOOTH_BTSTACK_PENDING_INDICATE, // Waiting for context callback
135133
MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE, // Waiting for conn handle
136134
// Hold buffer pointer until complete.
137135
MP_BLUETOOTH_BTSTACK_PENDING_WRITE, // Waiting for write done event
@@ -150,11 +148,7 @@ struct _mp_btstack_pending_op_t {
150148
uint16_t conn_handle;
151149
uint16_t value_handle;
152150

153-
// For notify/indicate only.
154-
// context_registration.context will point back to this struct.
155-
btstack_context_callback_registration_t context_registration;
156-
157-
// For notify/indicate/write-without-response, this is the actual buffer to send.
151+
// For write-without-response, this is the actual buffer to send.
158152
// For write-with-response, just holding onto the buffer for GC ref.
159153
size_t len;
160154
uint8_t buf[];
@@ -170,30 +164,6 @@ STATIC void btstack_remove_pending_operation(mp_btstack_pending_op_t *pending_op
170164
}
171165
}
172166

173-
// Called in response to a gatts_notify/indicate being unable to complete, which then calls
174-
// att_server_request_to_send_notification.
175-
// We now have an opportunity to re-try the operation with an empty ACL buffer.
176-
STATIC void btstack_notify_indicate_ready_handler(void *context) {
177-
MICROPY_PY_BLUETOOTH_ENTER
178-
mp_btstack_pending_op_t *pending_op = (mp_btstack_pending_op_t *)context;
179-
DEBUG_printf("btstack_notify_indicate_ready_handler op_type=%d conn_handle=%d value_handle=%d len=%zu\n", pending_op->op_type, pending_op->conn_handle, pending_op->value_handle, pending_op->len);
180-
if (pending_op->op_type == MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY) {
181-
int err = att_server_notify(pending_op->conn_handle, pending_op->value_handle, pending_op->buf, pending_op->len);
182-
DEBUG_printf("btstack_notify_indicate_ready_handler: sending notification err=%d\n", err);
183-
assert(err == ERROR_CODE_SUCCESS);
184-
(void)err;
185-
} else {
186-
assert(pending_op->op_type == MP_BLUETOOTH_BTSTACK_PENDING_INDICATE);
187-
int err = att_server_indicate(pending_op->conn_handle, pending_op->value_handle, NULL, 0);
188-
DEBUG_printf("btstack_notify_indicate_ready_handler: sending indication err=%d\n", err);
189-
assert(err == ERROR_CODE_SUCCESS);
190-
(void)err;
191-
}
192-
// Can't free the pending op as we're in IRQ context. Leave it for the GC.
193-
btstack_remove_pending_operation(pending_op, false /* del */);
194-
MICROPY_PY_BLUETOOTH_EXIT
195-
}
196-
197167
// Register a pending background operation -- copies the buffer, and makes it known to the GC.
198168
STATIC mp_btstack_pending_op_t *btstack_enqueue_pending_operation(uint16_t op_type, uint16_t conn_handle, uint16_t value_handle, const uint8_t *buf, size_t len) {
199169
DEBUG_printf("btstack_enqueue_pending_operation op_type=%d conn_handle=%d value_handle=%d len=%zu\n", op_type, conn_handle, value_handle, len);
@@ -204,11 +174,6 @@ STATIC mp_btstack_pending_op_t *btstack_enqueue_pending_operation(uint16_t op_ty
204174
pending_op->len = len;
205175
memcpy(pending_op->buf, buf, len);
206176

207-
if (op_type == MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY || op_type == MP_BLUETOOTH_BTSTACK_PENDING_INDICATE) {
208-
pending_op->context_registration.callback = &btstack_notify_indicate_ready_handler;
209-
pending_op->context_registration.context = pending_op;
210-
}
211-
212177
MICROPY_PY_BLUETOOTH_ENTER
213178
bool added = btstack_linked_list_add(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->pending_ops, (btstack_linked_item_t *)pending_op);
214179
assert(added);
@@ -854,7 +819,7 @@ void mp_bluetooth_set_io_capability(uint8_t capability) {
854819
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
855820

856821
size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf) {
857-
uint8_t *value = NULL;
822+
const uint8_t *value = NULL;
858823
size_t value_len = 0;
859824
mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, BTSTACK_GAP_DEVICE_NAME_HANDLE, &value, &value_len);
860825
*buf = value;
@@ -1095,7 +1060,7 @@ int mp_bluetooth_gatts_register_service_end(void) {
10951060
return 0;
10961061
}
10971062

1098-
int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) {
1063+
int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len) {
10991064
DEBUG_printf("mp_bluetooth_gatts_read\n");
11001065
if (!mp_bluetooth_is_active()) {
11011066
return ERRNO_BLUETOOTH_NOT_ACTIVE;
@@ -1114,85 +1079,41 @@ int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t
11141079
return mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, value, value_len);
11151080
}
11161081

1117-
int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) {
1118-
DEBUG_printf("mp_bluetooth_gatts_notify\n");
1082+
int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len) {
1083+
DEBUG_printf("mp_bluetooth_gatts_notify_indicate\n");
11191084

11201085
if (!mp_bluetooth_is_active()) {
11211086
return ERRNO_BLUETOOTH_NOT_ACTIVE;
11221087
}
11231088

1124-
// Note: btstack doesn't appear to support sending a notification without a value, so include the stored value.
1125-
uint8_t *data = NULL;
1126-
size_t len = 0;
1127-
mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &data, &len);
1128-
return mp_bluetooth_gatts_notify_send(conn_handle, value_handle, data, len);
1129-
}
1130-
1131-
int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len) {
1132-
DEBUG_printf("mp_bluetooth_gatts_notify_send\n");
1133-
1134-
if (!mp_bluetooth_is_active()) {
1135-
return ERRNO_BLUETOOTH_NOT_ACTIVE;
1089+
if (!value) {
1090+
// NULL value means "use DB value".
1091+
mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &value, &value_len);
11361092
}
11371093

1094+
int err = ERROR_CODE_UNKNOWN_HCI_COMMAND;
1095+
11381096
// Attempt to send immediately. If it succeeds, btstack will copy the buffer.
11391097
MICROPY_PY_BLUETOOTH_ENTER
1140-
int err = att_server_notify(conn_handle, value_handle, value, value_len);
1141-
MICROPY_PY_BLUETOOTH_EXIT
1142-
1143-
if (err == BTSTACK_ACL_BUFFERS_FULL) {
1144-
DEBUG_printf("mp_bluetooth_gatts_notify_send: ACL buffer full, scheduling callback\n");
1145-
// Schedule callback, making a copy of the buffer.
1146-
mp_btstack_pending_op_t *pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY, conn_handle, value_handle, value, value_len);
1147-
1148-
err = att_server_request_to_send_notification(&pending_op->context_registration, conn_handle);
1149-
1150-
if (err != ERROR_CODE_SUCCESS) {
1151-
// Failure. Unref and free the pending operation.
1152-
btstack_remove_pending_operation(pending_op, true /* del */);
1153-
}
1154-
1155-
return 0;
1156-
} else {
1157-
return btstack_error_to_errno(err);
1158-
}
1159-
}
1160-
1161-
int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
1162-
DEBUG_printf("mp_bluetooth_gatts_indicate\n");
1163-
1164-
if (!mp_bluetooth_is_active()) {
1165-
return ERRNO_BLUETOOTH_NOT_ACTIVE;
1098+
switch (gatts_op) {
1099+
case MP_BLUETOOTH_GATTS_OP_NOTIFY:
1100+
err = att_server_notify(conn_handle, value_handle, value, value_len);
1101+
break;
1102+
case MP_BLUETOOTH_GATTS_OP_INDICATE:
1103+
// Indicate will raise ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE when
1104+
// acknowledged (or timeout/error).
1105+
err = att_server_indicate(conn_handle, value_handle, value, value_len);
1106+
break;
11661107
}
1167-
1168-
uint8_t *data = NULL;
1169-
size_t len = 0;
1170-
mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &data, &len);
1171-
1172-
// Indicate will raise ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE when
1173-
// acknowledged (or timeout/error).
1174-
1175-
// Attempt to send immediately, will copy buffer.
1176-
MICROPY_PY_BLUETOOTH_ENTER
1177-
int err = att_server_indicate(conn_handle, value_handle, data, len);
11781108
MICROPY_PY_BLUETOOTH_EXIT
11791109

11801110
if (err == BTSTACK_ACL_BUFFERS_FULL) {
1181-
DEBUG_printf("mp_bluetooth_gatts_indicate: ACL buffer full, scheduling callback\n");
1182-
// Schedule callback, making a copy of the buffer.
1183-
mp_btstack_pending_op_t *pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_INDICATE, conn_handle, value_handle, data, len);
1184-
1185-
err = att_server_request_to_send_indication(&pending_op->context_registration, conn_handle);
1186-
1187-
if (err != ERROR_CODE_SUCCESS) {
1188-
// Failure. Unref and free the pending operation.
1189-
btstack_remove_pending_operation(pending_op, true /* del */);
1190-
}
1111+
DEBUG_printf("mp_bluetooth_gatts_notify_indicate: ACL buffer full, scheduling callback\n");
11911112

1192-
return 0;
1193-
} else {
1194-
return btstack_error_to_errno(err);
1113+
// TODO: re-implement the handling for this.
11951114
}
1115+
1116+
return btstack_error_to_errno(err);
11961117
}
11971118

11981119
int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) {

extmod/modbluetooth.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_passkey_obj, 4, 4,
733733
STATIC mp_obj_t bluetooth_ble_gatts_read(mp_obj_t self_in, mp_obj_t value_handle_in) {
734734
(void)self_in;
735735
size_t len = 0;
736-
uint8_t *buf;
736+
const uint8_t *buf;
737737
mp_bluetooth_gatts_read(mp_obj_get_int(value_handle_in), &buf, &len);
738738
return mp_obj_new_bytes(buf, len);
739739
}
@@ -751,32 +751,30 @@ STATIC mp_obj_t bluetooth_ble_gatts_write(size_t n_args, const mp_obj_t *args) {
751751
}
752752
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_write_obj, 3, 4, bluetooth_ble_gatts_write);
753753

754-
STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) {
754+
STATIC mp_obj_t bluetooth_ble_gatts_notify_indicate(size_t n_args, const mp_obj_t *args, int gatts_op) {
755755
mp_int_t conn_handle = mp_obj_get_int(args[1]);
756756
mp_int_t value_handle = mp_obj_get_int(args[2]);
757757

758+
const uint8_t *value = NULL;
759+
size_t value_len = 0;
758760
if (n_args == 4 && args[3] != mp_const_none) {
759761
mp_buffer_info_t bufinfo = {0};
760762
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
761-
int err = mp_bluetooth_gatts_notify_send(conn_handle, value_handle, bufinfo.buf, bufinfo.len);
762-
bluetooth_handle_errno(err);
763-
return mp_const_none;
764-
} else {
765-
int err = mp_bluetooth_gatts_notify(conn_handle, value_handle);
766-
return bluetooth_handle_errno(err);
763+
value = bufinfo.buf;
764+
value_len = bufinfo.len;
767765
}
766+
return bluetooth_handle_errno(mp_bluetooth_gatts_notify_indicate(conn_handle, value_handle, gatts_op, value, value_len));
768767
}
769-
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify);
770768

771-
STATIC mp_obj_t bluetooth_ble_gatts_indicate(mp_obj_t self_in, mp_obj_t conn_handle_in, mp_obj_t value_handle_in) {
772-
(void)self_in;
773-
mp_int_t conn_handle = mp_obj_get_int(conn_handle_in);
774-
mp_int_t value_handle = mp_obj_get_int(value_handle_in);
769+
STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) {
770+
return bluetooth_ble_gatts_notify_indicate(n_args, args, MP_BLUETOOTH_GATTS_OP_NOTIFY);
771+
}
772+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify);
775773

776-
int err = mp_bluetooth_gatts_indicate(conn_handle, value_handle);
777-
return bluetooth_handle_errno(err);
774+
STATIC mp_obj_t bluetooth_ble_gatts_indicate(size_t n_args, const mp_obj_t *args) {
775+
return bluetooth_ble_gatts_notify_indicate(n_args, args, MP_BLUETOOTH_GATTS_OP_INDICATE);
778776
}
779-
STATIC MP_DEFINE_CONST_FUN_OBJ_3(bluetooth_ble_gatts_indicate_obj, bluetooth_ble_gatts_indicate);
777+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_indicate_obj, 3, 4, bluetooth_ble_gatts_indicate);
780778

781779
STATIC mp_obj_t bluetooth_ble_gatts_set_buffer(size_t n_args, const mp_obj_t *args) {
782780
mp_int_t value_handle = mp_obj_get_int(args[1]);
@@ -1718,7 +1716,7 @@ mp_bluetooth_gatts_db_entry_t *mp_bluetooth_gatts_db_lookup(mp_gatts_db_t db, ui
17181716
return MP_OBJ_TO_PTR(elem->value);
17191717
}
17201718

1721-
int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, uint8_t **value, size_t *value_len) {
1719+
int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, const uint8_t **value, size_t *value_len) {
17221720
MICROPY_PY_BLUETOOTH_ENTER
17231721
mp_bluetooth_gatts_db_entry_t *entry = mp_bluetooth_gatts_db_lookup(db, handle);
17241722
if (entry) {

extmod/modbluetooth.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@
186186
#define MP_BLUETOOTH_PASSKEY_ACTION_DISPLAY (3)
187187
#define MP_BLUETOOTH_PASSKEY_ACTION_NUMERIC_COMPARISON (4)
188188

189+
// These are the ops for mp_bluetooth_gatts_notify_indicate.
190+
#define MP_BLUETOOTH_GATTS_OP_NOTIFY (1)
191+
#define MP_BLUETOOTH_GATTS_OP_INDICATE (2)
192+
189193
/*
190194
These aren't included in the module for space reasons, but can be used
191195
in your Python code if necessary.
@@ -333,15 +337,11 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
333337
int mp_bluetooth_gatts_register_service_end(void);
334338

335339
// Read the value from the local gatts db (likely this has been written by a central).
336-
int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len);
340+
int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len);
337341
// Write a value to the local gatts db (ready to be queried by a central). Optionally send notifications/indications.
338342
int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len, bool send_update);
339-
// Notify the central that it should do a read.
340-
int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle);
341-
// Notify the central, including a data payload. (Note: does not set the gatts db value).
342-
int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len);
343-
// Indicate the central.
344-
int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle);
343+
// Send a notification/indication to the central, optionally with custom payload (otherwise the DB value is used).
344+
int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len);
345345

346346
// Resize and enable/disable append-mode on a value.
347347
// Append-mode means that remote writes will append and local reads will clear after reading.
@@ -508,7 +508,7 @@ STATIC inline void mp_bluetooth_gatts_db_reset(mp_gatts_db_t db) {
508508

509509
void mp_bluetooth_gatts_db_create_entry(mp_gatts_db_t db, uint16_t handle, size_t len);
510510
mp_bluetooth_gatts_db_entry_t *mp_bluetooth_gatts_db_lookup(mp_gatts_db_t db, uint16_t handle);
511-
int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, uint8_t **value, size_t *value_len);
511+
int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, const uint8_t **value, size_t *value_len);
512512
int mp_bluetooth_gatts_db_write(mp_gatts_db_t db, uint16_t handle, const uint8_t *value, size_t value_len);
513513
int mp_bluetooth_gatts_db_resize(mp_gatts_db_t db, uint16_t handle, size_t len, bool append);
514514

extmod/nimble/modbluetooth_nimble.c

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ int mp_bluetooth_gap_disconnect(uint16_t conn_handle) {
10081008
return ble_hs_err_to_errno(ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM));
10091009
}
10101010

1011-
int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) {
1011+
int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len) {
10121012
if (!mp_bluetooth_is_active()) {
10131013
return ERRNO_BLUETOOTH_NOT_ACTIVE;
10141014
}
@@ -1026,35 +1026,40 @@ int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t
10261026
return err;
10271027
}
10281028

1029-
// TODO: Could use ble_gatts_chr_updated to send to all subscribed centrals.
1030-
1031-
int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) {
1029+
int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len) {
10321030
if (!mp_bluetooth_is_active()) {
10331031
return ERRNO_BLUETOOTH_NOT_ACTIVE;
10341032
}
1035-
// Confusingly, notify/notify_custom/indicate are "gattc" function (even though they're used by peripherals (i.e. gatt servers)).
1036-
// See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html
1037-
return ble_hs_err_to_errno(ble_gattc_notify(conn_handle, value_handle));
1038-
}
10391033

1040-
int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len) {
1041-
if (!mp_bluetooth_is_active()) {
1042-
return ERRNO_BLUETOOTH_NOT_ACTIVE;
1043-
}
1044-
struct os_mbuf *om = ble_hs_mbuf_from_flat(value, value_len);
1045-
if (om == NULL) {
1046-
return MP_ENOMEM;
1034+
int err = BLE_HS_EINVAL;
1035+
1036+
// NULL om in the _custom methods means "use DB value" (NimBLE will call
1037+
// back into mp_bluetooth_gatts_read for us).
1038+
struct os_mbuf *om = NULL;
1039+
1040+
if (value) {
1041+
om = ble_hs_mbuf_from_flat(value, value_len);
1042+
if (om == NULL) {
1043+
return MP_ENOMEM;
1044+
}
10471045
}
1048-
return ble_hs_err_to_errno(ble_gattc_notify_custom(conn_handle, value_handle, om));
1049-
}
10501046

1051-
int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
1052-
if (!mp_bluetooth_is_active()) {
1053-
return ERRNO_BLUETOOTH_NOT_ACTIVE;
1047+
// Note: Confusingly, Nimble's notify/notify_custom and indicate/indicate_custom
1048+
// are "gattc" functions (even though they're used by peripherals, i.e. gatt servers).
1049+
// See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html
1050+
1051+
switch (gatts_op) {
1052+
case MP_BLUETOOTH_GATTS_OP_NOTIFY:
1053+
err = ble_gattc_notify_custom(conn_handle, value_handle, om);
1054+
break;
1055+
case MP_BLUETOOTH_GATTS_OP_INDICATE:
1056+
// This will raise BLE_GAP_EVENT_NOTIFY_TX with a status when it is
1057+
// acknowledged (or timeout/error).
1058+
err = ble_gattc_indicate_custom(conn_handle, value_handle, om);
1059+
break;
10541060
}
1055-
// This will raise BLE_GAP_EVENT_NOTIFY_TX with a status when it is
1056-
// acknowledged (or timeout/error).
1057-
return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle));
1061+
1062+
return ble_hs_err_to_errno(err);
10581063
}
10591064

10601065
int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy