Skip to content

Commit e0bec77

Browse files
MarekPietapdunaj
authored andcommitted
applications: nrf_desktop: Add device description discovery
Change adds discovering custom device description service on central. Jira:DESK-748 Signed-off-by: Marek Pieta <[email protected]>
1 parent 110f657 commit e0bec77

File tree

2 files changed

+139
-72
lines changed

2 files changed

+139
-72
lines changed

applications/nrf_desktop/src/events/ble_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct ble_discovery_complete_event {
107107

108108
struct bt_gatt_dm *dm;
109109
u16_t pid;
110+
bool peer_llpm_support;
110111
enum peer_type peer_type;
111112
};
112113
EVENT_TYPE_DECLARE(ble_discovery_complete_event);

applications/nrf_desktop/src/modules/ble_discovery.c

Lines changed: 138 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,28 @@
1515

1616
#include "ble_event.h"
1717
#include "ble_discovery_def.h"
18+
#include "dev_descr.h"
1819

1920
#include <logging/log.h>
2021
LOG_MODULE_REGISTER(MODULE, CONFIG_DESKTOP_BLE_DISCOVERY_LOG_LEVEL);
2122

23+
enum discovery_state {
24+
DISCOVERY_STATE_START,
25+
DISCOVERY_STATE_DEV_DESCR,
26+
DISCOVERY_STATE_DIS,
27+
DISCOVERY_STATE_HIDS,
28+
29+
DISCOVERY_STATE_COUNT,
30+
};
31+
32+
static enum discovery_state state;
33+
2234
static u16_t peer_vid;
2335
static u16_t peer_pid;
36+
static bool peer_llpm_support;
2437
static struct bt_conn *discovering_peer_conn;
2538

26-
static struct k_work hids_discovery_start;
39+
static struct k_work next_discovery_step;
2740

2841
#define VID_POS_IN_PNP_ID sizeof(u8_t)
2942
#define PID_POS_IN_PNP_ID (VID_POS_IN_PNP_ID + sizeof(u16_t))
@@ -41,10 +54,12 @@ static void peer_unpair(void)
4154
}
4255
bt_conn_unref(discovering_peer_conn);
4356
discovering_peer_conn = NULL;
57+
state = DISCOVERY_STATE_START;
4458
}
4559

4660
static void hids_discovery_completed(struct bt_gatt_dm *dm, void *context)
4761
{
62+
__ASSERT_NO_MSG(dm != NULL);
4863
__ASSERT_NO_MSG(bt_gatt_dm_conn_get(dm) == discovering_peer_conn);
4964
BUILD_ASSERT_MSG(PEER_TYPE_COUNT <= __CHAR_BIT__, "");
5065
LOG_INF("HIDS discovery procedure succeeded");
@@ -56,6 +71,7 @@ static void hids_discovery_completed(struct bt_gatt_dm *dm, void *context)
5671

5772
event->dm = dm;
5873
event->pid = peer_pid;
74+
event->peer_llpm_support = peer_llpm_support;
5975

6076
for (size_t i = 0; i < ARRAY_SIZE(bt_peripherals); i++) {
6177
if (bt_peripherals[i].pid == peer_pid) {
@@ -81,93 +97,94 @@ static void hids_discovery_completed(struct bt_gatt_dm *dm, void *context)
8197
peer_unpair();
8298
}
8399

84-
static void hids_discovery_service_not_found(struct bt_conn *conn,
85-
void *context)
100+
static void service_not_found(struct bt_conn *conn, void *context)
86101
{
87-
LOG_ERR("Cannot find HIDS during the discovery");
102+
LOG_ERR("Service not found");
88103
__ASSERT_NO_MSG(discovering_peer_conn == conn);
89104
peer_unpair();
90105
}
91106

92-
static void hids_discovery_error_found(struct bt_conn *conn, int err,
93-
void *context)
107+
static void discovery_error(struct bt_conn *conn, int err, void *context)
94108
{
95-
LOG_ERR("HIDS discovery failed (err:%d)", err);
109+
LOG_ERR("Error discovering peer (err:%d)", err);
96110
__ASSERT_NO_MSG(discovering_peer_conn == conn);
97111
peer_unpair();
98112
}
99113

100-
static void start_hids_discovery(struct bt_conn *conn)
114+
static void read_dev_descr(const u8_t *ptr, u16_t len)
101115
{
102-
static const struct bt_gatt_dm_cb discovery_cb = {
103-
.completed = hids_discovery_completed,
104-
.service_not_found = hids_discovery_service_not_found,
105-
.error_found = hids_discovery_error_found,
106-
};
107-
108-
int err = bt_gatt_dm_start(conn, BT_UUID_HIDS, &discovery_cb, NULL);
109-
110-
if (err == -EALREADY) {
111-
LOG_ERR("Discovery already in progress");
112-
module_set_state(MODULE_STATE_ERROR);
113-
} else if (err) {
114-
LOG_ERR("Cannot start the discovery (err:%d)", err);
115-
peer_unpair();
116-
}
116+
__ASSERT_NO_MSG(len >= DEV_DESCR_LEN);
117+
peer_llpm_support = ptr[DEV_DESCR_LLPM_SUPPORT_POS];
118+
LOG_INF("LLPM %ssupported", peer_llpm_support ? ("") : ("not "));
117119
}
118120

119-
static bool verify_peer(void)
121+
static void read_dis(const u8_t *ptr, u16_t len)
120122
{
121-
if (peer_vid != vendor_vid) {
122-
LOG_WRN("Invalid peripheral VID");
123-
return false;
124-
}
123+
__ASSERT_NO_MSG(len >= MIN_LEN_DIS_PNP_ID);
125124

126-
return true;
127-
}
125+
peer_vid = sys_get_le16(&ptr[VID_POS_IN_PNP_ID]);
126+
peer_pid = sys_get_le16(&ptr[PID_POS_IN_PNP_ID]);
128127

129-
static void hids_discovery_start_fn(struct k_work *w)
130-
{
131-
if (!verify_peer()) {
132-
peer_unpair();
133-
} else {
134-
start_hids_discovery(discovering_peer_conn);
135-
}
128+
LOG_INF("VID: %02x PID: %02x", peer_vid, peer_pid);
136129
}
137130

138131
static u8_t read_attr(struct bt_conn *conn, u8_t err,
139-
struct bt_gatt_read_params *params,
140-
const void *data, u16_t length)
132+
struct bt_gatt_read_params *params,
133+
const void *data, u16_t length)
141134
{
142135
if (err) {
143-
LOG_ERR("Problem with reading GATT (err:%u)", err);
136+
LOG_ERR("Problem reading GATT (err:%" PRIu8 ")", err);
144137
peer_unpair();
145138
return BT_GATT_ITER_STOP;
146139
}
147140

148-
__ASSERT_NO_MSG(length >= MIN_LEN_DIS_PNP_ID);
141+
__ASSERT_NO_MSG(data != NULL);
149142
const u8_t *data_ptr = data;
150143

151-
peer_vid = sys_get_le16(&data_ptr[VID_POS_IN_PNP_ID]);
152-
peer_pid = sys_get_le16(&data_ptr[PID_POS_IN_PNP_ID]);
144+
switch (state) {
145+
case DISCOVERY_STATE_DEV_DESCR:
146+
read_dev_descr(data_ptr, length);
147+
break;
153148

154-
LOG_INF("VID: %02x PID: %02x", peer_vid, peer_pid);
149+
case DISCOVERY_STATE_DIS:
150+
read_dis(data_ptr, length);
151+
break;
152+
153+
default:
154+
__ASSERT_NO_MSG(false);
155+
}
155156

156-
k_work_submit(&hids_discovery_start);
157+
k_work_submit(&next_discovery_step);
157158

158159
return BT_GATT_ITER_STOP;
159160
}
160161

161-
static void dis_read_completed(struct bt_gatt_dm *dm, void *context)
162+
static void discovery_completed(struct bt_gatt_dm *dm, void *context)
162163
{
164+
__ASSERT_NO_MSG(dm != NULL);
163165
__ASSERT_NO_MSG(discovering_peer_conn == bt_gatt_dm_conn_get(dm));
166+
const struct bt_uuid *uuid = NULL;
164167
const struct bt_gatt_attr *attr;
165168
int err;
166169

167-
attr = bt_gatt_dm_char_by_uuid(dm, BT_UUID_DIS_PNP_ID);
170+
switch (state) {
171+
case DISCOVERY_STATE_DEV_DESCR:
172+
uuid = &custom_desc_chrc_uuid.uuid;
173+
break;
174+
175+
case DISCOVERY_STATE_DIS:
176+
uuid = BT_UUID_DIS_PNP_ID;
177+
break;
178+
179+
default:
180+
/* Should not happen. */
181+
__ASSERT_NO_MSG(false);
182+
}
183+
184+
attr = bt_gatt_dm_char_by_uuid(dm, uuid);
168185

169186
if (!attr) {
170-
LOG_ERR("PnP ID characteristic not found - disconnecting");
187+
LOG_ERR("Characteristic not found - disconnecting");
171188
err = bt_gatt_dm_data_release(dm);
172189
if (err) {
173190
goto error;
@@ -184,48 +201,99 @@ static void dis_read_completed(struct bt_gatt_dm *dm, void *context)
184201

185202
rp.single.handle = attr->handle + 1;
186203

204+
err = bt_gatt_read(bt_gatt_dm_conn_get(dm), &rp);
205+
if (err) {
206+
LOG_ERR("GATT read problem (err:%d)", err);
207+
peer_unpair();
208+
}
209+
187210
err = bt_gatt_dm_data_release(dm);
188211
if (err) {
189212
goto error;
190213
}
191214

192-
bt_gatt_read(discovering_peer_conn, &rp);
193215
return;
194216
error:
195217
LOG_ERR("Discovery data release failed (err:%d)", err);
196218
module_set_state(MODULE_STATE_ERROR);
197219
}
198220

199-
static void dis_not_found(struct bt_conn *conn, void *context)
221+
static void start_discovery(struct bt_conn *conn,
222+
const struct bt_uuid *svc_uuid,
223+
bool discovery_hids)
200224
{
201-
LOG_ERR("DIS not found");
202-
__ASSERT_NO_MSG(discovering_peer_conn == conn);
203-
peer_unpair();
225+
static const struct bt_gatt_dm_cb discovery_cb = {
226+
.completed = discovery_completed,
227+
.service_not_found = service_not_found,
228+
.error_found = discovery_error,
229+
};
230+
231+
static const struct bt_gatt_dm_cb hids_discovery_cb = {
232+
.completed = hids_discovery_completed,
233+
.service_not_found = service_not_found,
234+
.error_found = discovery_error,
235+
};
236+
237+
int err = bt_gatt_dm_start(conn, svc_uuid,
238+
discovery_hids ? &hids_discovery_cb : &discovery_cb,
239+
NULL);
240+
241+
__ASSERT_NO_MSG(err != -EALREADY);
242+
__ASSERT_NO_MSG(err != -EINVAL);
243+
if (err) {
244+
LOG_ERR("Cannot start discovery (err:%d)", err);
245+
peer_unpair();
246+
}
204247
}
205248

206-
static void dis_read_error(struct bt_conn *conn, int err, void *context)
249+
static bool verify_peer(void)
207250
{
208-
LOG_ERR("Error discovering DIS (err:%d)", err);
209-
__ASSERT_NO_MSG(discovering_peer_conn == conn);
210-
peer_unpair();
251+
if (peer_vid != vendor_vid) {
252+
LOG_WRN("Invalid peripheral VID");
253+
return false;
254+
}
255+
256+
return true;
211257
}
212258

213-
static void start_dis_read(struct bt_conn *conn)
259+
static void next_discovery_step_fn(struct k_work *w)
214260
{
215-
static const struct bt_gatt_dm_cb dis_discovery_cb = {
216-
.completed = dis_read_completed,
217-
.service_not_found = dis_not_found,
218-
.error_found = dis_read_error,
219-
};
261+
BUILD_ASSERT_MSG((DISCOVERY_STATE_HIDS + 1) == DISCOVERY_STATE_COUNT,
262+
"HIDs must be discovered last - after device is verified");
220263

221-
int err = bt_gatt_dm_start(conn, BT_UUID_DIS, &dis_discovery_cb, NULL);
264+
state++;
222265

223-
if (err) {
224-
LOG_ERR("Cannot start DIS discovery (err:%d)", err);
225-
peer_unpair();
266+
switch (state) {
267+
case DISCOVERY_STATE_DEV_DESCR:
268+
start_discovery(discovering_peer_conn, &custom_desc_uuid.uuid, false);
269+
break;
270+
271+
case DISCOVERY_STATE_DIS:
272+
start_discovery(discovering_peer_conn, BT_UUID_DIS, false);
273+
break;
274+
275+
case DISCOVERY_STATE_HIDS:
276+
if (!verify_peer()) {
277+
peer_unpair();
278+
} else {
279+
start_discovery(discovering_peer_conn, BT_UUID_HIDS, true);
280+
}
281+
break;
282+
283+
case DISCOVERY_STATE_START:
284+
case DISCOVERY_STATE_COUNT:
285+
default:
286+
__ASSERT_NO_MSG(false);
226287
}
227288
}
228289

290+
static void init(void)
291+
{
292+
k_work_init(&next_discovery_step, next_discovery_step_fn);
293+
state = DISCOVERY_STATE_START;
294+
module_set_state(MODULE_STATE_READY);
295+
}
296+
229297
static bool event_handler(const struct event_header *eh)
230298
{
231299
if (is_ble_peer_event(eh)) {
@@ -236,8 +304,7 @@ static bool event_handler(const struct event_header *eh)
236304
case PEER_STATE_SECURED:
237305
discovering_peer_conn = event->id;
238306
bt_conn_ref(discovering_peer_conn);
239-
240-
start_dis_read(event->id);
307+
k_work_submit(&next_discovery_step);
241308
break;
242309

243310
default:
@@ -258,6 +325,7 @@ static bool event_handler(const struct event_header *eh)
258325
}
259326
bt_conn_unref(discovering_peer_conn);
260327
discovering_peer_conn = NULL;
328+
state = DISCOVERY_STATE_START;
261329

262330
return false;
263331
}
@@ -267,9 +335,7 @@ static bool event_handler(const struct event_header *eh)
267335
cast_module_state_event(eh);
268336

269337
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
270-
k_work_init(&hids_discovery_start,
271-
hids_discovery_start_fn);
272-
module_set_state(MODULE_STATE_READY);
338+
init();
273339
}
274340

275341
return false;

0 commit comments

Comments
 (0)