Skip to content

Commit 25b265e

Browse files
committed
extmod/zephyr_ble: Use received_opcode for notification type detection.
Zephyr's subscribe callback now provides the actual ATT opcode via the received_opcode field on bt_gatt_subscribe_params, added by a local Zephyr patch. Use this to distinguish notifications from indications instead of inferring from the CCCD subscription value. Guarded by BT_GATT_SUBSCRIBE_HAS_RECEIVED_OPCODE so the code builds against both patched and unpatched Zephyr. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
1 parent 9a65d9e commit 25b265e

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

extmod/zephyr_ble/modbluetooth_zephyr.c

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,23 @@ static int call_depth = 0;
8989
#define BLE_HCI_SCAN_WINDOW_MIN 0x10
9090
#define BLE_HCI_SCAN_WINDOW_MAX 0xffff
9191

92+
// Map subscribe params to MicroPython notification/indication IRQ event.
93+
// With BT_GATT_SUBSCRIBE_HAS_RECEIVED_OPCODE, uses the actual ATT opcode.
94+
// Without it, infers from the CCCD subscription value.
95+
// BT_GATT_NOTIFY_TYPE_NOTIFY_MULT (multi-handle notification) maps to NOTIFY
96+
// since MicroPython has no separate IRQ for it.
97+
#if defined(BT_GATT_SUBSCRIBE_HAS_RECEIVED_OPCODE)
98+
#define GATTC_NOTIFY_EVENT_TYPE(params) \
99+
(((params)->received_opcode == BT_GATT_NOTIFY_TYPE_INDICATE) \
100+
? MP_BLUETOOTH_IRQ_GATTC_INDICATE \
101+
: MP_BLUETOOTH_IRQ_GATTC_NOTIFY)
102+
#else
103+
#define GATTC_NOTIFY_EVENT_TYPE(params) \
104+
(((params)->value & BT_GATT_CCC_INDICATE) \
105+
? MP_BLUETOOTH_IRQ_GATTC_INDICATE \
106+
: MP_BLUETOOTH_IRQ_GATTC_NOTIFY)
107+
#endif
108+
92109
#define ERRNO_BLUETOOTH_NOT_ACTIVE MP_ENODEV
93110

94111
#define MP_BLUETOOTH_ZEPHYR_MAX_SERVICES (8)
@@ -2321,10 +2338,7 @@ static uint8_t gattc_notify_cb(struct bt_conn *conn,
23212338
return BT_GATT_ITER_STOP;
23222339
}
23232340

2324-
// Determine if this is a notification or indication based on subscription type
2325-
uint8_t event = (params->value & BT_GATT_CCC_INDICATE)
2326-
? MP_BLUETOOTH_IRQ_GATTC_INDICATE
2327-
: MP_BLUETOOTH_IRQ_GATTC_NOTIFY;
2341+
uint8_t event = GATTC_NOTIFY_EVENT_TYPE(params);
23282342

23292343
DEBUG_printf("gattc_notify_cb: %s received conn_handle=%d value_handle=0x%04x length=%d\n",
23302344
(event == MP_BLUETOOTH_IRQ_GATTC_INDICATE) ? "indication" : "notification",
@@ -2360,12 +2374,7 @@ static uint8_t gattc_auto_notify_cb(struct bt_conn *conn,
23602374
return BT_GATT_ITER_STOP;
23612375
}
23622376

2363-
// Determine event type based on what we subscribed to.
2364-
// Since we subscribe to only one type (prefer INDICATE if supported),
2365-
// params->value correctly indicates the subscription type.
2366-
uint8_t event = (params->value & BT_GATT_CCC_INDICATE)
2367-
? MP_BLUETOOTH_IRQ_GATTC_INDICATE
2368-
: MP_BLUETOOTH_IRQ_GATTC_NOTIFY;
2377+
uint8_t event = GATTC_NOTIFY_EVENT_TYPE(params);
23692378

23702379
DEBUG_printf("gattc_auto_notify_cb: notification received conn_handle=%d value_handle=0x%04x length=%d\n",
23712380
conn_handle, params->value_handle, length);
@@ -2440,10 +2449,10 @@ static bool gattc_register_auto_subscription_type(struct bt_conn *conn, uint16_t
24402449
// matching NimBLE's behavior. Called during characteristic discovery for
24412450
// characteristics with NOTIFY or INDICATE properties.
24422451
//
2443-
// NOTE: Zephyr's bt_gatt_notification() doesn't pass the ATT opcode type
2444-
// (notify vs indicate) to the callback - both go through the same path.
2445-
// We can only infer the type from params->value (what we subscribed to).
2446-
// Therefore we subscribe to only ONE type (prefer INDICATE if supported)
2452+
// When BT_GATT_SUBSCRIBE_HAS_RECEIVED_OPCODE is defined, the stack sets
2453+
// params->received_opcode before invoking the callback, so notification
2454+
// type is detected from the actual ATT opcode regardless of subscription.
2455+
// Without it, we subscribe to only ONE type (prefer NOTIFY if supported)
24472456
// so params->value unambiguously indicates the event type.
24482457
static void gattc_register_auto_subscription(struct bt_conn *conn, uint16_t conn_handle, uint16_t value_handle, uint8_t properties) {
24492458
mp_bluetooth_zephyr_root_pointers_t *rp = MP_STATE_PORT(bluetooth_zephyr_root_pointers);
@@ -2463,8 +2472,9 @@ static void gattc_register_auto_subscription(struct bt_conn *conn, uint16_t conn
24632472
return;
24642473
}
24652474

2466-
// Subscribe to only ONE type so params->value correctly identifies the event.
2467-
// Prefer NOTIFY if supported (more common, lighter weight), else INDICATE.
2475+
// Subscribe to one type. With BT_GATT_SUBSCRIBE_HAS_RECEIVED_OPCODE the
2476+
// stack provides the actual opcode, but subscribing to one type is still
2477+
// correct behavior. Prefer NOTIFY if supported (more common, lighter weight).
24682478
uint16_t sub_value;
24692479
if (properties & BT_GATT_CHRC_NOTIFY) {
24702480
sub_value = BT_GATT_CCC_NOTIFY;

lib/zephyr

0 commit comments

Comments
 (0)