@@ -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.
24482457static 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 ;
0 commit comments