Skip to content

Commit 68ea026

Browse files
committed
refactor(split): Clean up split GATT discovery.
* Use Zephyr auto CCC discovery instead of doing it ourselves. * Split service versus characteristic discovery into dedicated steps in the flow. * Fix for not searching properly when connecting to a peripheral a second time.
1 parent 28cc5ce commit 68ea026

File tree

2 files changed

+58
-48
lines changed

2 files changed

+58
-48
lines changed

app/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ config ZMK_SPLIT_BLE_ROLE_CENTRAL
9898
bool "Central"
9999
select BT_CENTRAL
100100
select BT_GATT_CLIENT
101+
select BT_GATT_AUTO_DISCOVER_CCC
101102

102103
if !ZMK_SPLIT_BLE_ROLE_CENTRAL
103104

app/src/split/bluetooth/central.c

+57-48
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ static int start_scan(void);
3131

3232
static struct bt_conn *default_conn;
3333

34-
static struct bt_uuid_128 uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
34+
static struct bt_uuid_128 split_service_uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
3535
static struct bt_gatt_discover_params discover_params;
3636
static struct bt_gatt_subscribe_params subscribe_params;
37+
static struct bt_gatt_discover_params sub_discover_params;
3738
static uint16_t run_behavior_handle;
3839

3940
static uint8_t split_central_notify_func(struct bt_conn *conn,
@@ -76,81 +77,85 @@ static uint8_t split_central_notify_func(struct bt_conn *conn,
7677
return BT_GATT_ITER_CONTINUE;
7778
}
7879

79-
static int split_central_subscribe(struct bt_conn *conn) {
80+
static void split_central_subscribe(struct bt_conn *conn) {
8081
int err = bt_gatt_subscribe(conn, &subscribe_params);
8182
switch (err) {
8283
case -EALREADY:
8384
LOG_DBG("[ALREADY SUBSCRIBED]");
8485
break;
85-
// break;
86-
// bt_gatt_unsubscribe(conn, &subscribe_params);
87-
// return split_central_subscribe(conn);
8886
case 0:
8987
LOG_DBG("[SUBSCRIBED]");
9088
break;
9189
default:
9290
LOG_ERR("Subscribe failed (err %d)", err);
9391
break;
9492
}
95-
96-
return 0;
9793
}
9894

99-
static uint8_t split_central_discovery_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
100-
struct bt_gatt_discover_params *params) {
101-
int err;
102-
95+
static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
96+
const struct bt_gatt_attr *attr,
97+
struct bt_gatt_discover_params *params) {
10398
if (!attr) {
10499
LOG_DBG("Discover complete");
105-
(void)memset(params, 0, sizeof(*params));
106100
return BT_GATT_ITER_STOP;
107101
}
108102

109103
LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
110104

111-
if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
112-
memcpy(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID), sizeof(uuid));
113-
discover_params.uuid = &uuid.uuid;
114-
discover_params.start_handle = attr->handle + 1;
105+
if (attr->user_data &&
106+
!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
107+
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) {
108+
LOG_DBG("Found position state characteristic");
109+
discover_params.uuid = NULL;
110+
discover_params.start_handle = attr->handle + 2;
115111
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
116112

117-
err = bt_gatt_discover(conn, &discover_params);
118-
if (err) {
119-
LOG_ERR("Discover failed (err %d)", err);
120-
}
121-
} else if (!bt_uuid_cmp(discover_params.uuid,
122-
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) {
123-
memcpy(&uuid, BT_UUID_GATT_CCC, sizeof(uuid));
124-
discover_params.uuid = &uuid.uuid;
125-
discover_params.start_handle = attr->handle + 2;
126-
discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
113+
subscribe_params.disc_params = &sub_discover_params;
114+
subscribe_params.end_handle = discover_params.end_handle;
127115
subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
128-
129-
err = bt_gatt_discover(conn, &discover_params);
130-
if (err) {
131-
LOG_ERR("Discover failed (err %d)", err);
132-
}
133-
} else if (!bt_uuid_cmp(discover_params.uuid,
134-
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID))) {
135-
run_behavior_handle = bt_gatt_attr_value_handle(attr);
136-
} else {
137116
subscribe_params.notify = split_central_notify_func;
138117
subscribe_params.value = BT_GATT_CCC_NOTIFY;
139-
subscribe_params.ccc_handle = attr->handle;
140-
141118
split_central_subscribe(conn);
119+
} else if (attr->user_data &&
120+
!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
121+
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID))) {
122+
LOG_DBG("Found run behavior handle");
123+
run_behavior_handle = bt_gatt_attr_value_handle(attr);
124+
}
142125

143-
memcpy(&uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID), sizeof(uuid));
144-
discover_params.uuid = &uuid.uuid;
145-
discover_params.start_handle = attr->handle + 1;
146-
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
126+
bool subscribed = (run_behavior_handle && subscribe_params.value_handle);
147127

148-
err = bt_gatt_discover(conn, &discover_params);
149-
if (err) {
150-
LOG_ERR("Discover failed (err %d)", err);
151-
}
128+
return subscribed ? BT_GATT_ITER_STOP : BT_GATT_ITER_CONTINUE;
129+
}
130+
131+
static uint8_t split_central_service_discovery_func(struct bt_conn *conn,
132+
const struct bt_gatt_attr *attr,
133+
struct bt_gatt_discover_params *params) {
134+
int err;
135+
136+
if (!attr) {
137+
LOG_DBG("Discover complete");
138+
(void)memset(params, 0, sizeof(*params));
139+
return BT_GATT_ITER_STOP;
140+
}
141+
142+
LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
143+
144+
if (bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
145+
LOG_DBG("Found other service");
146+
return BT_GATT_ITER_CONTINUE;
152147
}
153148

149+
LOG_DBG("Found split service");
150+
discover_params.uuid = NULL;
151+
discover_params.func = split_central_chrc_discovery_func;
152+
discover_params.start_handle = attr->handle + 1;
153+
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
154+
155+
err = bt_gatt_discover(conn, &discover_params);
156+
if (err) {
157+
LOG_ERR("Failed to start discovering split service characteristics (err %d)", err);
158+
}
154159
return BT_GATT_ITER_STOP;
155160
}
156161

@@ -165,9 +170,9 @@ static void split_central_process_connection(struct bt_conn *conn) {
165170
return;
166171
}
167172

168-
if (conn == default_conn && !subscribe_params.value) {
169-
discover_params.uuid = &uuid.uuid;
170-
discover_params.func = split_central_discovery_func;
173+
if (conn == default_conn && !subscribe_params.value_handle) {
174+
discover_params.uuid = &split_service_uuid.uuid;
175+
discover_params.func = split_central_service_discovery_func;
171176
discover_params.start_handle = 0x0001;
172177
discover_params.end_handle = 0xffff;
173178
discover_params.type = BT_GATT_DISCOVER_PRIMARY;
@@ -322,6 +327,10 @@ static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) {
322327
bt_conn_unref(default_conn);
323328
default_conn = NULL;
324329

330+
// Clean up previously discovered handles;
331+
subscribe_params.value_handle = 0;
332+
run_behavior_handle = 0;
333+
325334
start_scan();
326335
}
327336

0 commit comments

Comments
 (0)