GCC Code Coverage Report


Directory: main/
File: bluetooth/hidp/sw2.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 0 228 0.0%
Functions: 0 9 0.0%
Branches: 0 58 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2025, Jacques Gagnon
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <stdio.h>
7 #include <esp_timer.h>
8 #include "bluetooth/host.h"
9 #include "bluetooth/hci.h"
10 #include "bluetooth/mon.h"
11 #include "bluetooth/att.h"
12 #include "zephyr/att.h"
13 #include "zephyr/gatt.h"
14 #include "tools/util.h"
15 #include "tests/cmds.h"
16 #include "adapter/config.h"
17 #include "sw2.h"
18
19 #define SW2_INIT_STATE_RETRY_MAX 10
20
21 enum {
22 SW2_INIT_STATE_READ_INFO = 0,
23 SW2_INIT_STATE_READ_LTK,
24 SW2_INIT_STATE_SET_BDADDR,
25 SW2_INIT_STATE_READ_NEW_LTK,
26 SW2_INIT_STATE_READ_LEFT_FACTORY_CALIB,
27 SW2_INIT_STATE_READ_RIGHT_FACTORY_CALIB,
28 SW2_INIT_STATE_READ_USER_CALIB,
29 SW2_INIT_STATE_SET_LED,
30 SW2_INIT_STATE_EN_REPORT,
31 };
32
33 static struct bt_hid_sw2_ctrl_calib calib[BT_MAX_DEV] = {0};
34
35 static void bt_hid_sw2_set_calib(struct bt_hid_sw2_ctrl_calib *calib, uint8_t *data, uint8_t stick) {
36 calib->sticks[stick].axes[0].neutral = ((data[1] << 8) & 0xF00) | data[0];
37 calib->sticks[stick].axes[1].neutral = (data[2] << 4) | (data[1] >> 4);
38 calib->sticks[stick].axes[0].rel_max = ((data[4] << 8) & 0xF00) | data[3];
39 calib->sticks[stick].axes[1].rel_max = (data[5] << 4) | (data[4] >> 4);
40 calib->sticks[stick].axes[0].rel_min = ((data[7] << 8) & 0xF00) | data[6];
41 calib->sticks[stick].axes[1].rel_min = (data[8] << 4) | (data[7] >> 4);
42 }
43
44 static void bt_hid_sw2_print_calib(struct bt_hid_sw2_ctrl_calib *calib) {
45 TESTS_CMDS_LOG("\"calib_data\": {");
46 TESTS_CMDS_LOG("\"rel_min\": [%u, %u, %u, %u], ", calib->sticks[0].axes[0].rel_min, calib->sticks[0].axes[1].rel_min,
47 calib->sticks[1].axes[0].rel_min, calib->sticks[1].axes[1].rel_min);
48 TESTS_CMDS_LOG("\"rel_max\": [%u, %u, %u, %u], ", calib->sticks[0].axes[0].rel_max, calib->sticks[0].axes[1].rel_max,
49 calib->sticks[1].axes[0].rel_max, calib->sticks[1].axes[1].rel_max);
50 TESTS_CMDS_LOG("\"neutral\": [%u, %u, %u, %u], ", calib->sticks[0].axes[0].neutral, calib->sticks[0].axes[1].neutral,
51 calib->sticks[1].axes[0].neutral, calib->sticks[1].axes[1].neutral);
52 TESTS_CMDS_LOG("\"deadzone\": [%u, %u, %u, %u]},\n", calib->sticks[0].deadzone, calib->sticks[0].deadzone,
53 calib->sticks[1].deadzone, calib->sticks[1].deadzone);
54 printf("rel_min LX %04d RX %04d\n", calib->sticks[0].axes[0].rel_min, calib->sticks[1].axes[0].rel_min);
55 printf("neutral LX %04d RX %04d\n", calib->sticks[0].axes[0].neutral, calib->sticks[1].axes[0].neutral);
56 printf("rel_max LX %04d RX %04d\n", calib->sticks[0].axes[0].rel_max, calib->sticks[1].axes[0].rel_max);
57 printf("rel_min LY %04d RY %04d\n", calib->sticks[0].axes[1].rel_min, calib->sticks[1].axes[1].rel_min);
58 printf("neutral LY %04d RY %04d\n", calib->sticks[0].axes[1].neutral, calib->sticks[1].axes[1].neutral);
59 printf("rel_max LY %04d RY %04d\n", calib->sticks[0].axes[1].rel_max, calib->sticks[1].axes[1].rel_max);
60 printf(" LD %04d RD %04d\n", calib->sticks[0].deadzone, calib->sticks[1].deadzone);
61 bt_mon_log(true, "rel_min LX %04d RX %04d\n", calib->sticks[0].axes[0].rel_min, calib->sticks[1].axes[0].rel_min);
62 bt_mon_log(true, "neutral LX %04d RX %04d\n", calib->sticks[0].axes[0].neutral, calib->sticks[1].axes[0].neutral);
63 bt_mon_log(true, "rel_max LX %04d RX %04d\n", calib->sticks[0].axes[0].rel_max, calib->sticks[1].axes[0].rel_max);
64 bt_mon_log(true, "rel_min LY %04d RY %04d\n", calib->sticks[0].axes[1].rel_min, calib->sticks[1].axes[1].rel_min);
65 bt_mon_log(true, "neutral LY %04d RY %04d\n", calib->sticks[0].axes[1].neutral, calib->sticks[1].axes[1].neutral);
66 bt_mon_log(true, "rel_max LY %04d RY %04d\n", calib->sticks[0].axes[1].rel_max, calib->sticks[1].axes[1].rel_max);
67 bt_mon_log(true, " LD %04d RD %04d\n", calib->sticks[0].deadzone, calib->sticks[1].deadzone);
68 }
69
70 void bt_hid_sw2_init_rumble_gc(struct bt_data *bt_data) {
71 bt_data->base.output[1] = 0x50;
72
73 bt_data->base.output[5] = BT_HIDP_SW2_CMD_SET_LED;
74 bt_data->base.output[6] = BT_HIDP_SW2_REQ_TYPE_REQ;
75 bt_data->base.output[7] = BT_HIDP_SW2_REQ_INT_BLE;
76 bt_data->base.output[8] = BT_HIDP_SW2_SUBCMD_SET_LED;
77 bt_data->base.output[10] = 0x08;
78 bt_data->base.output[13] = bt_hid_led_dev_id_map[bt_data->base.pids->out_idx];
79 }
80
81 void bt_hid_sw2_init_rumble_pro2(struct bt_data *bt_data) {
82 bt_data->base.output[1] = 0x50;
83 bt_data->base.output[2] = 0xe1;
84 bt_data->base.output[4] = 0x10;
85 bt_data->base.output[5] = 0x1e;
86
87 bt_data->base.output[17] = 0x50;
88 bt_data->base.output[18] = 0xe1;
89 bt_data->base.output[20] = 0x10;
90 bt_data->base.output[21] = 0x1e;
91
92 bt_data->base.output[33] = BT_HIDP_SW2_CMD_SET_LED;
93 bt_data->base.output[34] = BT_HIDP_SW2_REQ_TYPE_REQ;
94 bt_data->base.output[35] = BT_HIDP_SW2_REQ_INT_BLE;
95 bt_data->base.output[36] = BT_HIDP_SW2_SUBCMD_SET_LED;
96 bt_data->base.output[38] = 0x08;
97 bt_data->base.output[41] = bt_hid_led_dev_id_map[bt_data->base.pids->out_idx];
98 }
99
100 void bt_hid_cmd_sw2_out(struct bt_dev *device, void *report) {
101 struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
102 if (bt_data) {
103 switch (bt_data->base.pid) {
104 case SW2_PRO2_PID:
105 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_OUT_CMD_ATT_HDL, (uint8_t *)report, 41);
106 bt_data->base.output[17] &= 0xF0;
107 bt_data->base.output[17] |= device->tid & 0xF;
108 break;
109 case SW2_GC_PID:
110 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_OUT_CMD_ATT_HDL, (uint8_t *)report, 21);
111 break;
112 }
113
114 bt_data->base.output[1] &= 0xF0;
115 bt_data->base.output[1] |= device->tid++ & 0xF;
116 }
117 }
118
119 void bt_hid_sw2_get_calib(int32_t dev_id, struct bt_hid_sw2_ctrl_calib **cal) {
120 struct bt_dev *device = NULL;
121 bt_host_get_dev_from_id(dev_id, &device);
122
123 if (device && atomic_test_bit(&device->flags, BT_DEV_CALIB_SET)) {
124 *cal = &calib[dev_id];
125 }
126 }
127
128 static void bt_hid_sw2_exec_next_state(struct bt_dev *device) {
129 switch(device->hid_state) {
130 case SW2_INIT_STATE_READ_INFO:
131 {
132 uint8_t read_info[] = {
133 BT_HIDP_SW2_CMD_READ_SPI,
134 BT_HIDP_SW2_REQ_TYPE_REQ,
135 BT_HIDP_SW2_REQ_INT_BLE,
136 BT_HIDP_SW2_SUBCMD_READ_SPI,
137 0x00, 0x08, 0x00, 0x00, 0x40, 0x7e, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00
138 };
139 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, read_info, sizeof(read_info));
140 break;
141 }
142 case SW2_INIT_STATE_SET_BDADDR:
143 {
144 uint8_t set_bdaddr[] = {
145 BT_HIDP_SW2_CMD_PAIRING,
146 BT_HIDP_SW2_REQ_TYPE_REQ,
147 BT_HIDP_SW2_REQ_INT_BLE,
148 BT_HIDP_SW2_SUBCMD_PAIRING_STEP1,
149 0x00, 0x0e, 0x00, 0x00, 0x00, 0x02,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 };
153 bt_addr_le_t bdaddr;
154 bt_hci_get_le_local_addr(&bdaddr);
155 memcpy(&set_bdaddr[10], bdaddr.a.val, sizeof(bdaddr.a.val));
156 memcpy(&set_bdaddr[16], bdaddr.a.val, sizeof(bdaddr.a.val));
157 set_bdaddr[16]--;
158 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, set_bdaddr, sizeof(set_bdaddr));
159 break;
160 }
161 case SW2_INIT_STATE_READ_LTK:
162 case SW2_INIT_STATE_READ_NEW_LTK:
163 {
164 uint8_t read_ltk[] = {
165 BT_HIDP_SW2_CMD_READ_SPI,
166 BT_HIDP_SW2_REQ_TYPE_REQ,
167 BT_HIDP_SW2_REQ_INT_BLE,
168 BT_HIDP_SW2_SUBCMD_READ_SPI,
169 0x00, 0x08, 0x00, 0x00,
170 0x10, /* Read len */
171 0x7e, 0x00, 0x00,
172 0x1a, 0xa0, 0x1f, 0x00, /* LTK offset in SPI flash */
173 };
174 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, read_ltk, sizeof(read_ltk));
175 break;
176 }
177 case SW2_INIT_STATE_READ_LEFT_FACTORY_CALIB:
178 {
179 uint8_t read_calib[] = {
180 BT_HIDP_SW2_CMD_READ_SPI,
181 BT_HIDP_SW2_REQ_TYPE_REQ,
182 BT_HIDP_SW2_REQ_INT_BLE,
183 BT_HIDP_SW2_SUBCMD_READ_SPI,
184 0x00, 0x08, 0x00, 0x00,
185 0x40, /* Read len */
186 0x7e, 0x00, 0x00,
187 0x80, 0x30, 0x01, 0x00, /* Left Factory Calib addr */
188 };
189 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, read_calib, sizeof(read_calib));
190 break;
191 }
192 case SW2_INIT_STATE_READ_RIGHT_FACTORY_CALIB:
193 {
194 uint8_t read_calib[] = {
195 BT_HIDP_SW2_CMD_READ_SPI,
196 BT_HIDP_SW2_REQ_TYPE_REQ,
197 BT_HIDP_SW2_REQ_INT_BLE,
198 BT_HIDP_SW2_SUBCMD_READ_SPI,
199 0x00, 0x08, 0x00, 0x00,
200 0x40, /* Read len */
201 0x7e, 0x00, 0x00,
202 0xc0, 0x30, 0x01, 0x00, /* Right Factory Calib addr */
203 };
204 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, read_calib, sizeof(read_calib));
205 break;
206 }
207 case SW2_INIT_STATE_READ_USER_CALIB:
208 {
209 uint8_t read_calib[] = {
210 BT_HIDP_SW2_CMD_READ_SPI,
211 BT_HIDP_SW2_REQ_TYPE_REQ,
212 BT_HIDP_SW2_REQ_INT_BLE,
213 BT_HIDP_SW2_SUBCMD_READ_SPI,
214 0x00, 0x08, 0x00, 0x00,
215 0x40, /* Read len */
216 0x7e, 0x00, 0x00,
217 0x40, 0xc0, 0x1f, 0x00, /* User Calib addr */
218 };
219 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, read_calib, sizeof(read_calib));
220 break;
221 }
222 case SW2_INIT_STATE_SET_LED:
223 {
224 uint8_t led[] = {
225 BT_HIDP_SW2_CMD_SET_LED,
226 BT_HIDP_SW2_REQ_TYPE_REQ,
227 BT_HIDP_SW2_REQ_INT_BLE,
228 BT_HIDP_SW2_SUBCMD_SET_LED,
229 0x00, 0x08, 0x00, 0x00,
230 bt_hid_led_dev_id_map[device->ids.out_idx],
231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 };
233 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, led, sizeof(led));
234 break;
235 }
236 case SW2_INIT_STATE_EN_REPORT:
237 default:
238 {
239 uint16_t data = BT_GATT_CCC_NOTIFY;
240 bt_att_cmd_write_req(device->acl_handle, 0x000b, (uint8_t *)&data, sizeof(data));
241 data = 0;
242 bt_att_cmd_write_req(device->acl_handle, 0x001b, (uint8_t *)&data, sizeof(data));
243 break;
244 }
245 }
246 }
247
248 void bt_hid_sw2_init(struct bt_dev *device) {
249 /* enable cmds rsp */
250 uint16_t data = BT_GATT_CCC_NOTIFY;
251 bt_att_cmd_write_req(device->acl_handle, 0x001b, (uint8_t *)&data, sizeof(data));
252
253 bt_hid_sw2_exec_next_state(device);
254
255 atomic_set_bit(&device->flags, BT_DEV_HID_INIT_DONE);
256 }
257
258 void bt_hid_sw2_hdlr(struct bt_dev *device, uint16_t att_handle, uint8_t *data, uint32_t len) {
259 switch (att_handle) {
260 case BT_HIDP_SW2_REPORT_TYPE1_ATT_HDL:
261 bt_host_bridge(device, 1, data, len);
262 struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
263 if (bt_data && bt_data->base.pid != SW2_GC_PID
264 && config.out_cfg[device->ids.out_idx].acc_mode & ACC_RUMBLE) {
265 bt_hid_cmd_sw2_out(device, bt_data->base.output);
266 }
267 break;
268 case BT_HIDP_SW2_REPORT_TYPE2_ATT_HDL:
269 bt_host_bridge(device, 2, data, len);
270 break;
271 case BT_HIDP_SW2_ACK_ATT_HDL:
272 {
273 struct bt_hidp_sw2_ack *ack = (struct bt_hidp_sw2_ack *)data;
274 switch (ack->cmd) {
275 case BT_HIDP_SW2_CMD_READ_SPI:
276 switch (device->hid_state) {
277 case SW2_INIT_STATE_READ_INFO:
278 {
279 struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
280 if (bt_data) {
281 bt_data->base.vid = *(uint16_t *)&ack->value[30];
282 bt_data->base.pid = *(uint16_t *)&ack->value[32];
283
284 printf("%s: VID: 0x%04X PID: 0x%04X\n", __FUNCTION__, bt_data->base.vid, bt_data->base.pid);
285 bt_mon_log(true, "%s: VID: 0x%04X PID: 0x%04X\n", __FUNCTION__, bt_data->base.vid, bt_data->base.pid);
286
287 /* Init output data for Rumble/LED feedback */
288 switch (bt_data->base.pid) {
289 case SW2_LJC_PID:
290 case SW2_RJC_PID:
291 case SW2_PRO2_PID:
292 bt_hid_sw2_init_rumble_pro2(bt_data);
293 break;
294 case SW2_GC_PID:
295 bt_hid_sw2_init_rumble_gc(bt_data);
296 break;
297 default:
298 printf("# Unknown pid : %04X\n", bt_data->base.pid);
299 break;
300 }
301 }
302 break;
303 }
304 case SW2_INIT_STATE_READ_LTK:
305 {
306 struct bt_smp_encrypt_info encrypt_info = {0};
307
308 printf("%s: LTK: ", __FUNCTION__);
309 for (uint32_t i = 0; i < 16; i++) {
310 printf("%02X ", ack->value[12 + i]);
311 }
312 printf("\n");
313 if (bt_host_load_le_ltk(&device->le_remote_bdaddr, &encrypt_info, NULL) == 0) {
314 if (memcmp(encrypt_info.ltk, &ack->value[12], sizeof(encrypt_info.ltk)) == 0) {
315 /* LTK match, skip pairing */
316 device->hid_state += 2;
317 }
318 }
319 break;
320 }
321 case SW2_INIT_STATE_READ_NEW_LTK:
322 printf("%s: NEW LTK: ", __FUNCTION__);
323 for (uint32_t i = 0; i < 16; i++) {
324 printf("%02X ", ack->value[12 + i]);
325 }
326 printf("\n");
327 bt_host_store_le_ltk(&device->le_remote_bdaddr, (struct bt_smp_encrypt_info *)&ack->value[12]);
328 break;
329 case SW2_INIT_STATE_READ_LEFT_FACTORY_CALIB:
330 {
331 struct bt_hid_sw2_ctrl_calib *dev_calib = &calib[device->ids.id];
332 uint8_t *data = &ack->value[52];
333 if (data[0] != 0xFF) {
334 bt_hid_sw2_set_calib(dev_calib, data, 0);
335 }
336 break;
337 }
338 case SW2_INIT_STATE_READ_RIGHT_FACTORY_CALIB:
339 {
340 struct bt_hid_sw2_ctrl_calib *dev_calib = &calib[device->ids.id];
341 uint8_t *data = &ack->value[52];
342 if (data[0] != 0xFF) {
343 bt_hid_sw2_set_calib(dev_calib, data, 1);
344 }
345 bt_hid_sw2_print_calib(dev_calib);
346 break;
347 }
348 case SW2_INIT_STATE_READ_USER_CALIB:
349 {
350 struct bt_hid_sw2_ctrl_calib *dev_calib = &calib[device->ids.id];
351 uint8_t *data = &ack->value[14];
352 if (data[0] != 0xFF) {
353 bt_hid_sw2_set_calib(dev_calib, data, 0);
354 }
355 data = &ack->value[46];
356 if (data[0] != 0xFF) {
357 bt_hid_sw2_set_calib(dev_calib, data, 1);
358 }
359 bt_hid_sw2_print_calib(dev_calib);
360 atomic_set_bit(&device->flags, BT_DEV_CALIB_SET);
361 /* Force reinit once calib available */
362 bt_type_update(device->ids.id, BT_SW2, device->ids.subtype);
363 break;
364 }
365 }
366 device->hid_state++;
367 bt_hid_sw2_exec_next_state(device);
368 break;
369 case BT_HIDP_SW2_CMD_SET_LED:
370 printf("# BT_HIDP_SW2_CMD_SET_LED\n");
371 device->hid_state++;
372 bt_hid_sw2_exec_next_state(device);
373 break;
374 case BT_HIDP_SW2_CMD_PAIRING:
375 switch(ack->subcmd) {
376 case BT_HIDP_SW2_SUBCMD_PAIRING_STEP1:
377 {
378 uint8_t pair2[] = {
379 BT_HIDP_SW2_CMD_PAIRING,
380 BT_HIDP_SW2_REQ_TYPE_REQ,
381 BT_HIDP_SW2_REQ_INT_BLE,
382 BT_HIDP_SW2_SUBCMD_PAIRING_STEP2,
383 0x00, 0x11, 0x00, 0x00, 0x00, 0xea, 0xbd, 0x47, 0x13, 0x89, 0x35, 0x42, 0xc6, 0x79, 0xee, 0x07, 0xf2, 0x53, 0x2c, 0x6c, 0x31
384 };
385 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, pair2, sizeof(pair2));
386 break;
387 }
388 case BT_HIDP_SW2_SUBCMD_PAIRING_STEP2:
389 {
390 uint8_t pair3[] = {
391 BT_HIDP_SW2_CMD_PAIRING,
392 BT_HIDP_SW2_REQ_TYPE_REQ,
393 BT_HIDP_SW2_REQ_INT_BLE,
394 BT_HIDP_SW2_SUBCMD_PAIRING_STEP3,
395 0x00, 0x11, 0x00, 0x00, 0x00, 0x40, 0xb0, 0x8a, 0x5f, 0xcd, 0x1f, 0x9b, 0x41, 0x12, 0x5c, 0xac, 0xc6, 0x3f, 0x38, 0xa0, 0x73
396 };
397 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, pair3, sizeof(pair3));
398 break;
399 }
400 case BT_HIDP_SW2_SUBCMD_PAIRING_STEP3:
401 {
402 uint8_t pair4[] = {
403 BT_HIDP_SW2_CMD_PAIRING,
404 BT_HIDP_SW2_REQ_TYPE_REQ,
405 BT_HIDP_SW2_REQ_INT_BLE,
406 BT_HIDP_SW2_SUBCMD_PAIRING_STEP4,
407 0x00, 0x01, 0x00, 0x00, 0x00
408 };
409 bt_att_cmd_write_cmd(device->acl_handle, BT_HIDP_SW2_CMD_ATT_HDL, pair4, sizeof(pair4));
410 break;
411 }
412 case BT_HIDP_SW2_SUBCMD_PAIRING_STEP4:
413 {
414 device->hid_state++;
415 bt_hid_sw2_exec_next_state(device);
416 break;
417 }
418 }
419 break;
420 }
421 break;
422 }
423 default:
424 printf("%s: unknown handle %04X\n", __FUNCTION__, att_handle);
425 break;
426 }
427 }
428