GCC Code Coverage Report


Directory: main/
File: bluetooth/att_hid.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 0 367 0.0%
Functions: 0 30 0.0%
Branches: 0 159 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2019-2025, Jacques Gagnon
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <stdio.h>
7 #include "host.h"
8 #include "hci.h"
9 #include "att.h"
10 #include "att_cfg.h"
11 #include "att_hid.h"
12 #include "mon.h"
13 #include "zephyr/uuid.h"
14 #include "zephyr/att.h"
15 #include "zephyr/gatt.h"
16 #include "adapter/hid_parser.h"
17 #include "adapter/mapping_quirks.h"
18 #include "hidp/sw2.h"
19
20 enum {
21 BT_ATT_HID_DEVICE_NAME = 0,
22 BT_ATT_HID_APPEARANCE,
23 BT_ATT_HID_PNP,
24 BT_ATT_HID_FIND_HID_HDLS,
25 BT_ATT_HID_IDENT_HID_HLDS,
26 BT_ATT_HID_CHAR_PROP,
27 BT_ATT_HID_REPORT_MAP,
28 BT_ATT_HID_REPORT_REF,
29 BT_ATT_HID_REPORT_CFG,
30 BT_ATT_HID_PPCP_CFG,
31 BT_ATT_HID_BATT_LVL,
32 BT_ATT_HID_INIT,
33 BT_ATT_HID_STATE_MAX,
34 };
35
36 struct bt_att_read_type_data {
37 uint16_t handle;
38 uint8_t char_prop;
39 uint16_t char_value_handle;
40 uint16_t uuid;
41 } __packed;
42
43 struct bt_att_report_ref {
44 uint8_t report_id;
45 uint8_t report_type;
46 } __packed;
47
48 struct bt_att_group_data_uuid16 {
49 uint16_t start_handle;
50 uint16_t end_handle;
51 uint16_t uuid;
52 } __packed;
53
54 struct bt_att_hid_report {
55 uint8_t id;
56 uint8_t type;
57 uint8_t char_prop;
58 uint16_t report_hdl;
59 uint16_t cfg_hdl;
60 uint16_t ref_hdl;
61 };
62
63 struct bt_att_hid {
64 char device_name[32];
65 uint16_t appearance;
66 uint16_t dev_name_hdl;
67 uint16_t start_hdl;
68 uint16_t end_hdl;
69 uint16_t map_hdl;
70 uint8_t report_cnt;
71 uint8_t report_found;
72 uint8_t report_idx;
73 struct bt_att_hid_report reports[HID_MAX_REPORT];
74 };
75
76 typedef void (*bit_att_hid_start_func_t)(struct bt_dev *device,
77 struct bt_att_hid *hid_data);
78 typedef void (*bit_att_hid_process_func_t)(struct bt_dev *device,
79 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len);
80
81 static struct bt_att_hid att_hid[BT_MAX_DEV] = {0};
82
83 static void bt_att_hid_start_next_state(struct bt_dev *device,
84 struct bt_att_hid *hid_data);
85
86 static void bt_att_hid_start_device_name(struct bt_dev *device,
87 struct bt_att_hid *hid_data) {
88 bt_att_cmd_read_type_req_uuid16(device->acl_handle, 0x0001, 0xFFFF, BT_UUID_GAP_DEVICE_NAME);
89 }
90
91 static void bt_att_hid_process_device_name(struct bt_dev *device,
92 struct bt_att_hid *hid_data, uint32_t att_len,
93 uint8_t *data, uint32_t data_len) {
94 char tmp[32] = {0};
95 uint32_t name_len = data_len + strlen(hid_data->device_name);
96
97 if (data) {
98 if (name_len < sizeof(hid_data->device_name)) {
99 memcpy(tmp, data, data_len);
100 strcat(hid_data->device_name, tmp);
101 if (att_len == device->mtu) {
102 bt_att_cmd_read_blob_req(device->acl_handle,
103 hid_data->dev_name_hdl, strlen(hid_data->device_name));
104 return;
105 }
106 }
107 else {
108 memcpy(tmp, data,
109 sizeof(hid_data->device_name) - strlen(hid_data->device_name) - 1);
110 strcat(hid_data->device_name, tmp);
111 }
112 }
113
114 bt_hid_set_type_flags_from_name(device, hid_data->device_name);
115 printf("dev: %ld type: %ld %s\n", device->ids.id, device->ids.type, hid_data->device_name);
116 bt_mon_log(true, "dev: %ld type: %ld %s\n", device->ids.id, device->ids.type, hid_data->device_name);
117
118 bt_att_hid_start_next_state(device, hid_data);
119 }
120
121 static void bt_att_hid_start_appearance(struct bt_dev *device,
122 struct bt_att_hid *hid_data) {
123 bt_att_cmd_read_type_req_uuid16(device->acl_handle, 0x0001, 0xFFFF, BT_UUID_GAP_APPEARANCE);
124 }
125
126 static void bt_att_hid_process_appearance(struct bt_dev *device,
127 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
128 if (data) {
129 hid_data->appearance = *(uint16_t *)data;
130 }
131 printf("dev: %ld appearance: %03X:%02X\n",
132 device->ids.id, hid_data->appearance >> 6, hid_data->appearance & 0x3F);
133 bt_mon_log(true, "dev: %ld appearance: %03X:%02X\n",
134 device->ids.id, hid_data->appearance >> 6, hid_data->appearance & 0x3F);
135 bt_att_hid_start_next_state(device, hid_data);
136 }
137
138 static void bt_att_hid_start_pnp(struct bt_dev *device,
139 struct bt_att_hid *hid_data) {
140 bt_att_cmd_read_type_req_uuid16(device->acl_handle, 0x0001, 0xFFFF, BT_UUID_DIS_PNP_ID);
141 }
142
143 static void bt_att_hid_process_pnp(struct bt_dev *device,
144 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
145 struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
146 if (data) {
147 bt_data->base.vid = *(uint16_t *)&data[1];
148 bt_data->base.pid = *(uint16_t *)&data[3];
149 }
150 printf("%s: VID: 0x%04X PID: 0x%04X\n", __FUNCTION__, bt_data->base.vid, bt_data->base.pid);
151 bt_mon_log(true, "%s: VID: 0x%04X PID: 0x%04X\n", __FUNCTION__, bt_data->base.vid, bt_data->base.pid);
152 bt_att_hid_start_next_state(device, hid_data);
153 }
154
155 static void bt_att_hid_start_find_hid_hdls(struct bt_dev *device,
156 struct bt_att_hid *hid_data) {
157 bt_att_cmd_read_group_req_uuid16(device->acl_handle, 0x0001, BT_UUID_GATT_PRIMARY);
158 }
159
160 static void bt_att_hid_process_find_hid_hdls(struct bt_dev *device,
161 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
162 if (data) {
163 const uint32_t elem_cnt = (att_len - 2) / data_len;
164
165 if (data_len == 6) {
166 struct bt_att_group_data_uuid16 *elem = (struct bt_att_group_data_uuid16 *)data;
167 for (uint32_t i = 0; i < elem_cnt; i++) {
168 if (elem[i].uuid == BT_UUID_HIDS) {
169 hid_data->start_hdl = elem[i].start_handle;
170 hid_data->end_hdl = elem[i].end_handle;
171 }
172 }
173 }
174 struct bt_att_group_data *last_elem = (struct bt_att_group_data *)((uint8_t *)data + data_len * (elem_cnt - 1));
175 bt_att_cmd_read_group_req_uuid16(device->acl_handle, last_elem->end_handle, BT_UUID_GATT_PRIMARY);
176 }
177 else {
178 bt_att_hid_start_next_state(device, hid_data);
179 }
180 }
181
182 static void bt_att_hid_start_ident_hid_hdls(struct bt_dev *device,
183 struct bt_att_hid *hid_data) {
184 bt_att_cmd_find_info_req(device->acl_handle, hid_data->start_hdl, hid_data->end_hdl);
185 }
186
187 static void bt_att_hid_process_ident_hid_hdls(struct bt_dev *device,
188 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *info, uint32_t format) {
189 if (info) {
190 uint16_t last_handle;
191 struct bt_att_info_16 *info16;
192 struct bt_att_info_128 *info128;
193 uint32_t elem_cnt;
194
195 if (format == BT_ATT_INFO_16) {
196 info16 = (struct bt_att_info_16 *)info;
197 elem_cnt = (att_len - 2)/sizeof(*info16);
198
199 last_handle = info16[elem_cnt - 1].handle;
200 }
201 else {
202 info128 = (struct bt_att_info_128 *)info;
203 elem_cnt = (att_len - 2)/sizeof(*info128);
204
205 last_handle = info128[elem_cnt - 1].handle;
206 }
207
208 for (uint32_t i = 0; i < elem_cnt; i++) {
209 uint16_t handle;
210 uint16_t uuid;
211
212 if (format == BT_ATT_INFO_16) {
213 handle = info16[i].handle;
214 uuid = info16[i].uuid;
215 }
216 else {
217 handle = info128[i].handle;
218 uuid = *(uint16_t *)&info128[i].uuid[12];
219 }
220
221 printf("INFO HDL: %04X UUID: %04X REPORT_CNT: %d\n", handle, uuid, hid_data->report_cnt);
222 bt_mon_log(true, "INFO HDL: %04X UUID: %04X REPORT_CNT: %d\n", handle, uuid, hid_data->report_cnt);
223
224 switch (uuid) {
225 case BT_UUID_GATT_PRIMARY:
226 hid_data->report_cnt = 0;
227 break;
228 case BT_UUID_GATT_CHRC:
229 if (hid_data->report_found) {
230 hid_data->report_cnt++;
231 if (hid_data->report_cnt == HID_MAX_REPORT) {
232 goto find_info_rsp_end;
233 }
234 }
235 hid_data->report_found = 0;
236 break;
237 case BT_UUID_HIDS_REPORT:
238 hid_data->reports[hid_data->report_cnt].report_hdl = handle;
239 hid_data->report_found = 1;
240 break;
241 case BT_UUID_GATT_CCC:
242 hid_data->reports[hid_data->report_cnt].cfg_hdl = handle;
243 break;
244 case BT_UUID_HIDS_REPORT_REF:
245 hid_data->reports[hid_data->report_cnt].ref_hdl = handle;
246 break;
247 case BT_UUID_HIDS_REPORT_MAP:
248 hid_data->map_hdl = handle;
249 break;
250 case BT_UUID_HIDS_INFO:
251 case BT_UUID_HIDS_CTRL_POINT:
252 break;
253 }
254 }
255
256 find_info_rsp_end:
257 if (last_handle < hid_data->end_hdl) {
258 bt_att_cmd_find_info_req(device->acl_handle, last_handle + 1, hid_data->end_hdl);
259 }
260 else {
261 device->hid_state = BT_ATT_HID_CHAR_PROP;
262 bt_att_cmd_read_type_req_uuid16(device->acl_handle,
263 hid_data->start_hdl, hid_data->end_hdl, BT_UUID_GATT_CHRC);
264 }
265 }
266 else {
267 bt_att_hid_start_next_state(device, hid_data);
268 }
269 }
270
271 static void bt_att_hid_start_char_prop(struct bt_dev *device,
272 struct bt_att_hid *hid_data) {
273 bt_att_cmd_read_type_req_uuid16(device->acl_handle,
274 hid_data->start_hdl, hid_data->end_hdl, BT_UUID_GATT_CHRC);
275 }
276
277 static void bt_att_hid_process_char_prop(struct bt_dev *device,
278 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
279 if (data) {
280 struct bt_att_read_type_data *read_type_data = (struct bt_att_read_type_data *)data;
281 const uint32_t elem_cnt = (att_len - 2) / data_len;
282 uint16_t last_handle = read_type_data[elem_cnt - 1].handle;
283
284 for (uint32_t i = 0; i < elem_cnt; i++) {
285 for (uint32_t j = 0; j < HID_MAX_REPORT; j++) {
286 if (hid_data->reports[j].report_hdl == read_type_data[i].char_value_handle) {
287 printf("CHAR_PROP Handl: %04X Prop: %02X\n", read_type_data[i].char_value_handle, read_type_data[i].char_prop);
288 bt_mon_log(true, "CHAR_PROP Handl: %04X Prop: %02X\n", read_type_data[i].char_value_handle, read_type_data[i].char_prop);
289 hid_data->reports[j].char_prop = read_type_data[i].char_prop;
290 }
291 }
292 }
293
294 if (last_handle < hid_data->end_hdl) {
295 bt_att_cmd_read_type_req_uuid16(device->acl_handle,
296 last_handle + 1, hid_data->end_hdl, BT_UUID_GATT_CHRC);
297 return;
298 }
299 }
300 bt_att_hid_start_next_state(device, hid_data);
301 }
302
303 static void bt_att_hid_start_report_map(struct bt_dev *device,
304 struct bt_att_hid *hid_data) {
305 bt_att_cmd_read_req(device->acl_handle, hid_data->map_hdl);
306 }
307
308 static void bt_att_hid_process_report_map(struct bt_dev *device,
309 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
310 struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
311
312 if (bt_data->base.sdp_data == NULL) {
313 bt_data->base.sdp_data = malloc(BT_SDP_DATA_SIZE);
314 if (bt_data->base.sdp_data == NULL) {
315 printf("# dev: %ld Failed to alloc report memory\n", device->ids.id);
316 return;
317 }
318 }
319
320 if (data) {
321 memcpy(bt_data->base.sdp_data + bt_data->base.sdp_len, data, data_len);
322 bt_data->base.sdp_len += data_len;
323
324 if (att_len == device->mtu) {
325 bt_att_cmd_read_blob_req(device->acl_handle, hid_data->map_hdl, bt_data->base.sdp_len);
326 return;
327 }
328 }
329
330 if (bt_data->base.sdp_data) {
331 hid_parser(bt_data, bt_data->base.sdp_data, bt_data->base.sdp_len);
332 free(bt_data->base.sdp_data);
333 bt_data->base.sdp_data = NULL;
334 }
335 if (hid_data->reports[hid_data->report_idx].ref_hdl) {
336 bt_att_hid_start_next_state(device, hid_data);
337 }
338 else {
339 printf("# dev: %ld No report found!!\n", device->ids.id);
340 }
341 }
342
343 static void bt_att_hid_start_report_ref(struct bt_dev *device,
344 struct bt_att_hid *hid_data) {
345 hid_data->report_idx = 0;
346 bt_att_cmd_read_req(device->acl_handle, hid_data->reports[hid_data->report_idx].ref_hdl);
347 }
348
349 static void bt_att_hid_process_report_ref(struct bt_dev *device,
350 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
351 if (data) {
352 struct bt_att_report_ref *report_ref = (struct bt_att_report_ref *)data;
353
354 hid_data->reports[hid_data->report_idx].id = report_ref->report_id;
355 hid_data->reports[hid_data->report_idx++].type = report_ref->report_type;
356
357 if (hid_data->report_idx < HID_MAX_REPORT && hid_data->reports[hid_data->report_idx].ref_hdl) {
358 bt_att_cmd_read_req(device->acl_handle, hid_data->reports[hid_data->report_idx].ref_hdl);
359 return;
360 }
361 }
362 bt_att_hid_start_next_state(device, hid_data);
363 }
364
365 static void bt_att_hid_continue_report_cfg(struct bt_dev *device,
366 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
367 uint32_t i = hid_data->report_idx;
368 for (; i < HID_MAX_REPORT; i++) {
369 if (hid_data->reports[i].char_prop & BT_GATT_CHRC_NOTIFY) {
370 uint16_t data = BT_GATT_CCC_NOTIFY;
371 bt_att_cmd_write_req(device->acl_handle, hid_data->reports[i].cfg_hdl, (uint8_t *)&data, sizeof(data));
372 hid_data->report_idx = i + 1;
373 break;
374 }
375 }
376 if (i >= HID_MAX_REPORT) {
377 bt_att_hid_start_next_state(device, hid_data);
378 }
379 }
380
381 static void bt_att_hid_start_report_cfg(struct bt_dev *device,
382 struct bt_att_hid *hid_data) {
383 hid_data->report_idx = 0;
384 bt_att_hid_continue_report_cfg(device, hid_data, 0, NULL, 0);
385 }
386
387 static void bt_att_hid_start_ppcp_cfg(struct bt_dev *device,
388 struct bt_att_hid *hid_data) {
389 bt_att_cmd_read_type_req_uuid16(device->acl_handle, 0x0001, 0xFFFF, BT_UUID_GAP_PPCP);
390 }
391
392 static void bt_att_hid_process_ppcp_cfg(struct bt_dev *device,
393 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
394 if (data) {
395 struct bt_l2cap_conn_param_req *conn_param_req = (struct bt_l2cap_conn_param_req *)data;
396 struct hci_cp_le_conn_update le_conn_update = {0};
397
398 le_conn_update.handle = device->acl_handle;
399 le_conn_update.conn_interval_min = conn_param_req->min_interval;
400 le_conn_update.conn_interval_max = conn_param_req->max_interval;
401 le_conn_update.conn_latency = conn_param_req->latency;
402 le_conn_update.supervision_timeout = conn_param_req->timeout;
403 le_conn_update.min_ce_len = 0;
404 le_conn_update.max_ce_len = 0;
405
406 bt_hci_le_conn_update(&le_conn_update);
407 }
408 bt_att_hid_start_next_state(device, hid_data);
409 }
410
411 static void bt_att_hid_start_batt_lvl(struct bt_dev *device,
412 struct bt_att_hid *hid_data) {
413 bt_att_cmd_read_type_req_uuid16(device->acl_handle, 0x0001, 0xFFFF, BT_UUID_BAS_BATTERY_LEVEL);
414 }
415
416 static void bt_att_hid_process_batt_lvl(struct bt_dev *device,
417 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
418 bt_att_hid_start_next_state(device, hid_data);
419 }
420
421 static void bt_att_hid_start_init(struct bt_dev *device,
422 struct bt_att_hid *hid_data) {
423 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
424 atomic_set_bit(&device->flags, BT_DEV_HID_INTR_READY);
425 bt_hid_init(device);
426 }
427 }
428
429 static bit_att_hid_start_func_t start_state_func[BT_ATT_HID_STATE_MAX] = {
430 bt_att_hid_start_device_name,
431 bt_att_hid_start_appearance,
432 bt_att_hid_start_pnp,
433 bt_att_hid_start_find_hid_hdls,
434 bt_att_hid_start_ident_hid_hdls,
435 bt_att_hid_start_char_prop,
436 bt_att_hid_start_report_map,
437 bt_att_hid_start_report_ref,
438 bt_att_hid_start_report_cfg,
439 bt_att_hid_start_ppcp_cfg,
440 bt_att_hid_start_batt_lvl,
441 bt_att_hid_start_init, /* Need to be last one */
442 };
443 static bit_att_hid_process_func_t process_state_func[BT_ATT_HID_STATE_MAX] = {
444 bt_att_hid_process_device_name,
445 bt_att_hid_process_appearance,
446 bt_att_hid_process_pnp,
447 bt_att_hid_process_find_hid_hdls,
448 bt_att_hid_process_ident_hid_hdls,
449 bt_att_hid_process_char_prop,
450 bt_att_hid_process_report_map,
451 bt_att_hid_process_report_ref,
452 bt_att_hid_continue_report_cfg,
453 bt_att_hid_process_ppcp_cfg,
454 bt_att_hid_process_batt_lvl,
455 NULL, /* Need to be last one */
456 };
457
458 static void bt_att_hid_start_first_state(struct bt_dev *device,
459 struct bt_att_hid *hid_data) {
460 device->hid_state = 0;
461 if (device->hid_state < BT_ATT_HID_STATE_MAX && start_state_func[0]) {
462 start_state_func[0](device, hid_data);
463 }
464 }
465
466 static void bt_att_hid_process_current_state(struct bt_dev *device,
467 struct bt_att_hid *hid_data, uint32_t att_len, uint8_t *data, uint32_t data_len) {
468 if (device->hid_state < BT_ATT_HID_STATE_MAX && process_state_func[device->hid_state]) {
469 process_state_func[device->hid_state](device, hid_data, att_len, data, data_len);
470 }
471 }
472
473 static void bt_att_hid_start_next_state(struct bt_dev *device,
474 struct bt_att_hid *hid_data) {
475 if (device->ids.type == BT_SW2 && !atomic_test_bit(&device->flags, BT_DEV_HID_INIT_DONE)) {
476 bt_hid_sw2_init(device);
477 }
478 else {
479 device->hid_state++;
480 if (device->hid_state < BT_ATT_HID_STATE_MAX && start_state_func[device->hid_state]) {
481 start_state_func[device->hid_state](device, hid_data);
482 }
483 }
484 }
485
486 static int32_t bt_att_get_report_index(struct bt_att_hid *hid_data, uint8_t report_id, uint8_t report_type) {
487 for (uint32_t i = 0; i < HID_MAX_REPORT; i++) {
488 if (hid_data->reports[i].id == report_id && hid_data->reports[i].type == report_type) {
489 return i;
490 }
491 }
492 return -1;
493 }
494
495 void bt_att_hid_init(struct bt_dev *device) {
496 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_PENDING)) {
497 struct bt_att_hid *hid_data = &att_hid[device->ids.id];
498
499 atomic_set_bit(&device->flags, BT_DEV_HID_INTR_PENDING);
500
501 memset((uint8_t *)hid_data, 0, sizeof(*hid_data));
502 bt_att_cmd_mtu_req(device->acl_handle, bt_att_get_le_max_mtu());
503 }
504 }
505
506 void bt_att_write_hid_report(struct bt_dev *device, uint8_t report_id, uint8_t *data, uint32_t len) {
507 struct bt_att_hid *hid_data = &att_hid[device->ids.id];
508
509 int32_t index = bt_att_get_report_index(hid_data, report_id, 0x02);
510 if (index > -1) {
511 uint16_t att_handle = hid_data->reports[index].report_hdl;
512 uint8_t char_prop = hid_data->reports[index].char_prop;
513
514 if (att_handle) {
515 if (char_prop & BT_GATT_CHRC_WRITE) {
516 bt_att_cmd_write_req(device->acl_handle, att_handle, data, len);
517 }
518 else {
519 bt_att_cmd_write_cmd(device->acl_handle, att_handle, data, len);
520 }
521 }
522 }
523 }
524
525 void bt_att_hid_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint32_t len) {
526 struct bt_att_hid *hid_data = &att_hid[device->ids.id];
527 uint32_t att_len = len - (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE + sizeof(struct bt_l2cap_hdr));
528
529 switch (bt_hci_acl_pkt->att_hdr.code) {
530 case BT_ATT_OP_ERROR_RSP:
531 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
532 bt_att_hid_process_current_state(device, hid_data, att_len, NULL, 0);
533 }
534 break;
535 case BT_ATT_OP_MTU_RSP:
536 {
537 struct bt_att_exchange_mtu_rsp *mtu_rsp = (struct bt_att_exchange_mtu_rsp *)bt_hci_acl_pkt->att_data;
538
539 device->mtu = mtu_rsp->mtu;
540
541 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
542 bt_hci_stop_inquiry();
543
544 bt_att_hid_start_first_state(device, hid_data);
545 }
546 break;
547 }
548 case BT_ATT_OP_FIND_INFO_RSP:
549 {
550 struct bt_att_find_info_rsp *find_info_rsp = (struct bt_att_find_info_rsp *)bt_hci_acl_pkt->att_data;
551
552 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
553 switch (device->hid_state) {
554 case BT_ATT_HID_IDENT_HID_HLDS:
555 bt_att_hid_process_ident_hid_hdls(device, hid_data, att_len, find_info_rsp->info, find_info_rsp->format);
556 break;
557 default:
558 printf("# %s: Invalid state: %ld rsp: 0x%02X\n", __FUNCTION__, device->hid_state, bt_hci_acl_pkt->att_hdr.code);
559 break;
560 }
561 }
562 break;
563 }
564 case BT_ATT_OP_READ_TYPE_RSP:
565 {
566 struct bt_att_read_type_rsp *read_type_rsp = (struct bt_att_read_type_rsp *)bt_hci_acl_pkt->att_data;
567 uint8_t rsp_len = read_type_rsp->len - sizeof(read_type_rsp->data[0].handle);
568
569 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
570 switch (device->hid_state) {
571 case BT_ATT_HID_DEVICE_NAME:
572 hid_data->dev_name_hdl = read_type_rsp->data[0].handle;
573 if (rsp_len) {
574 bt_att_hid_process_device_name(device, hid_data, att_len, read_type_rsp->data[0].value, rsp_len);
575 }
576 else {
577 bt_att_cmd_read_req(device->acl_handle, read_type_rsp->data[0].handle);
578 }
579 break;
580 case BT_ATT_HID_APPEARANCE:
581 bt_att_hid_process_appearance(device, hid_data, att_len, read_type_rsp->data[0].value, rsp_len);
582 break;
583 case BT_ATT_HID_PNP:
584 bt_att_hid_process_pnp(device, hid_data, att_len, read_type_rsp->data[0].value, rsp_len);
585 break;
586 case BT_ATT_HID_CHAR_PROP:
587 bt_att_hid_process_char_prop(device, hid_data, att_len, (uint8_t *)read_type_rsp->data, read_type_rsp->len);
588 break;
589 case BT_ATT_HID_PPCP_CFG:
590 bt_att_hid_process_ppcp_cfg(device, hid_data, att_len, read_type_rsp->data[0].value, rsp_len);
591 break;
592 case BT_ATT_HID_BATT_LVL:
593 bt_att_hid_process_batt_lvl(device, hid_data, att_len, read_type_rsp->data[0].value, rsp_len);
594 break;
595 default:
596 printf("# %s: Invalid state: %ld rsp: 0x%02X\n", __FUNCTION__, device->hid_state, bt_hci_acl_pkt->att_hdr.code);
597 break;
598 }
599 }
600 break;
601 }
602 case BT_ATT_OP_READ_RSP:
603 {
604 struct bt_att_read_rsp *read_rsp = (struct bt_att_read_rsp *)bt_hci_acl_pkt->att_data;
605
606 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
607 switch (device->hid_state) {
608 case BT_ATT_HID_DEVICE_NAME:
609 bt_att_hid_process_device_name(device, hid_data, att_len, read_rsp->value, att_len - 1);
610 break;
611 case BT_ATT_HID_REPORT_MAP:
612 bt_att_hid_process_report_map(device, hid_data, att_len, read_rsp->value, att_len - 1);
613 break;
614 case BT_ATT_HID_REPORT_REF:
615 bt_att_hid_process_report_ref(device, hid_data, att_len, read_rsp->value, att_len - 1);
616 break;
617 default:
618 printf("# %s: Invalid state: %ld rsp: 0x%02X\n", __FUNCTION__, device->hid_state, bt_hci_acl_pkt->att_hdr.code);
619 break;
620 }
621 }
622 break;
623 }
624 case BT_ATT_OP_READ_BLOB_RSP:
625 {
626 struct bt_att_read_blob_rsp *read_blob_rsp = (struct bt_att_read_blob_rsp *)bt_hci_acl_pkt->att_data;
627
628 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
629 switch (device->hid_state) {
630 case BT_ATT_HID_DEVICE_NAME:
631 bt_att_hid_process_device_name(device, hid_data, att_len, read_blob_rsp->value, att_len - 1);
632 break;
633 case BT_ATT_HID_REPORT_MAP:
634 bt_att_hid_process_report_map(device, hid_data, att_len, read_blob_rsp->value, att_len - 1);
635 break;
636 default:
637 printf("# %s: Invalid state: %ld rsp: 0x%02X\n", __FUNCTION__, device->hid_state, bt_hci_acl_pkt->att_hdr.code);
638 break;
639 }
640 }
641 break;
642 }
643 case BT_ATT_OP_READ_GROUP_RSP:
644 {
645 struct bt_att_read_group_rsp *read_group_rsp = (struct bt_att_read_group_rsp *)bt_hci_acl_pkt->att_data;
646
647 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
648 switch (device->hid_state) {
649 case BT_ATT_HID_FIND_HID_HDLS:
650 bt_att_hid_process_find_hid_hdls(device, hid_data, att_len, (uint8_t *)read_group_rsp->data, read_group_rsp->len);
651 break;
652 default:
653 printf("# %s: Invalid state: %ld rsp: 0x%02X\n", __FUNCTION__, device->hid_state, bt_hci_acl_pkt->att_hdr.code);
654 break;
655 }
656 }
657 break;
658 }
659 case BT_ATT_OP_WRITE_RSP:
660 {
661 if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
662 switch (device->hid_state) {
663 case BT_ATT_HID_REPORT_CFG:
664 bt_att_hid_continue_report_cfg(device, hid_data, att_len, NULL, 0);
665 break;
666 default:
667 printf("# %s: Invalid state: %ld rsp: 0x%02X\n", __FUNCTION__, device->hid_state, bt_hci_acl_pkt->att_hdr.code);
668 break;
669 }
670 }
671 break;
672 }
673 case BT_ATT_OP_NOTIFY:
674 {
675 struct bt_att_notify *notify = (struct bt_att_notify *)bt_hci_acl_pkt->att_data;
676
677 switch (device->ids.type) {
678 case BT_SW2:
679 bt_hid_sw2_hdlr(device, notify->handle, notify->value, att_len - sizeof(notify->handle));
680 break;
681 default:
682 for (uint32_t i = 0; i < HID_MAX_REPORT; i++) {
683 if (notify->handle == hid_data->reports[i].report_hdl) {
684 bt_host_bridge(device, hid_data->reports[i].id, notify->value, att_len - sizeof(notify->handle));
685 break;
686 }
687 }
688 break;
689 }
690 break;
691 }
692 default:
693 bt_att_cfg_hdlr(device, bt_hci_acl_pkt, len);
694 break;
695 }
696 }
697