GCC Code Coverage Report


Directory: main/
File: adapter/adapter.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 203 290 70.0%
Functions: 16 20 80.0%
Branches: 91 151 60.3%

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 <string.h>
8 #include <stdlib.h>
9 #include <freertos/FreeRTOS.h>
10 #include <xtensa/hal.h>
11 #include <esp_heap_caps.h>
12 #include <esp_timer.h>
13 #include <esp32/rom/ets_sys.h>
14 #include "sdkconfig.h"
15 #include "queue_bss.h"
16 #include "zephyr/types.h"
17 #include "tools/util.h"
18 #include "config.h"
19 #include "adapter.h"
20 #include "adapter_debug.h"
21 #include "wired/wired.h"
22 #include "wireless/wireless.h"
23 #include "macro.h"
24 #include "bluetooth/host.h"
25 #include "tests/cmds.h"
26
27 const uint32_t hat_to_ld_btns[16] = {
28 BIT(PAD_LD_UP), BIT(PAD_LD_UP) | BIT(PAD_LD_RIGHT), BIT(PAD_LD_RIGHT), BIT(PAD_LD_DOWN) | BIT(PAD_LD_RIGHT),
29 BIT(PAD_LD_DOWN), BIT(PAD_LD_DOWN) | BIT(PAD_LD_LEFT), BIT(PAD_LD_LEFT), BIT(PAD_LD_UP) | BIT(PAD_LD_LEFT),
30 };
31
32 const uint32_t generic_btns_mask[32] = {
33 BIT(PAD_LX_LEFT), BIT(PAD_LX_RIGHT), BIT(PAD_LY_DOWN), BIT(PAD_LY_UP),
34 BIT(PAD_RX_LEFT), BIT(PAD_RX_RIGHT), BIT(PAD_RY_DOWN), BIT(PAD_RY_UP),
35 BIT(PAD_LD_LEFT), BIT(PAD_LD_RIGHT), BIT(PAD_LD_DOWN), BIT(PAD_LD_UP),
36 BIT(PAD_RD_LEFT), BIT(PAD_RD_RIGHT), BIT(PAD_RD_DOWN), BIT(PAD_RD_UP),
37 BIT(PAD_RB_LEFT), BIT(PAD_RB_RIGHT), BIT(PAD_RB_DOWN), BIT(PAD_RB_UP),
38 BIT(PAD_MM), BIT(PAD_MS), BIT(PAD_MT), BIT(PAD_MQ),
39 BIT(PAD_LM), BIT(PAD_LS), BIT(PAD_LT), BIT(PAD_LJ),
40 BIT(PAD_RM), BIT(PAD_RS), BIT(PAD_RT), BIT(PAD_RJ),
41 };
42
43 struct wireless_ctrl *ctrl_input;
44 struct wired_ctrl *ctrl_output;
45 struct generic_fb fb_input;
46 struct bt_adapter bt_adapter = {0};
47 struct wired_adapter wired_adapter = {0};
48 static uint32_t adapter_out_mask[WIRED_MAX_DEV] = {0};
49 static bool rumble_mute = false;
50
51 209746 static uint32_t btn_id_to_btn_idx(uint8_t btn_id) {
52
2/2
✓ Branch 0 (2→3) taken 122686 times.
✓ Branch 1 (2→6) taken 87060 times.
209746 if (btn_id < 32) {
53 return 0;
54 }
55
2/2
✓ Branch 0 (3→4) taken 80126 times.
✓ Branch 1 (3→6) taken 42560 times.
122686 else if (btn_id >= 32 && btn_id < 64) {
56 return 1;
57 }
58
2/2
✓ Branch 0 (4→5) taken 37566 times.
✓ Branch 1 (4→6) taken 42560 times.
80126 else if (btn_id >= 64 && btn_id < 96) {
59 return 2;
60 }
61 else {
62 37566 return 3;
63 }
64 }
65
66 8832 static uint32_t adapter_map_from_axis(struct map_cfg * map_cfg) {
67 8832 uint32_t out_mask = BIT(map_cfg->dst_id);
68 8832 struct wired_ctrl *out = &ctrl_output[map_cfg->dst_id];
69 8832 uint8_t src = map_cfg->src_btn;
70 8832 uint8_t dst = map_cfg->dst_btn;
71 8832 uint32_t dst_mask = BIT(dst & 0x1F);
72 8832 uint32_t dst_btn_idx = btn_id_to_btn_idx(dst);
73 8832 uint32_t src_axis_idx = btn_id_to_axis(src);
74 8832 uint32_t dst_axis_idx = btn_id_to_axis(dst);
75
76
1/2
✓ Branch 0 (2→3) taken 8832 times.
✗ Branch 1 (2→26) not taken.
8832 if (src_axis_idx == AXIS_NONE) {
77 return 0;
78 }
79
80 /* Check if mapping dst exist in output */
81
2/2
✓ Branch 0 (3→4) taken 8776 times.
✓ Branch 1 (3→25) taken 56 times.
8832 if (dst_mask & out->mask[dst_btn_idx]) {
82 8776 int32_t abs_src_value = abs(ctrl_input->axes[src_axis_idx].value);
83 8776 int32_t src_sign = btn_sign(ctrl_input->axes[src_axis_idx].meta->polarity, src);
84 8776 int32_t sign_check = src_sign * ctrl_input->axes[src_axis_idx].value;
85
86 /* Check if the srv value sign match the src mapping sign */
87
2/2
✓ Branch 0 (4→5) taken 7948 times.
✓ Branch 1 (4→24) taken 828 times.
8776 if (sign_check >= 0) {
88 /* Get proper abs_max base on sign and update max if current value is over */
89 7948 int32_t src_abs_max;
90
2/2
✓ Branch 0 (5→6) taken 4882 times.
✓ Branch 1 (5→9) taken 3066 times.
7948 if (src_sign > 0) {
91
2/2
✓ Branch 0 (6→7) taken 148 times.
✓ Branch 1 (6→8) taken 4734 times.
4882 if (abs_src_value > ctrl_input->axes[src_axis_idx].meta->abs_max) {
92 148 ctrl_input->axes[src_axis_idx].meta->abs_max = abs_src_value;
93 }
94 4882 src_abs_max = ctrl_input->axes[src_axis_idx].meta->abs_max;
95 }
96 else {
97
2/2
✓ Branch 0 (9→10) taken 120 times.
✓ Branch 1 (9→11) taken 2946 times.
3066 if (abs_src_value > ctrl_input->axes[src_axis_idx].meta->abs_min) {
98 120 ctrl_input->axes[src_axis_idx].meta->abs_min = abs_src_value;
99 }
100 3066 src_abs_max = ctrl_input->axes[src_axis_idx].meta->abs_min;
101 }
102
103 /* Check if dst is an axis */
104
2/2
✓ Branch 0 (12→13) taken 6996 times.
✓ Branch 1 (12→22) taken 952 times.
7948 if (dst_mask & out->desc[dst_btn_idx]) {
105 /* Keep track of source axis type */
106 6996 out->axes[dst_axis_idx].relative = ctrl_input->axes[src_axis_idx].meta->relative;
107 /* Dst is an axis */
108 6996 int32_t deadzone = (int32_t)(((float)map_cfg->perc_deadzone / 10000) * src_abs_max) + ctrl_input->axes[src_axis_idx].meta->deadzone;
109 /* Check if axis over deadzone */
110
2/2
✓ Branch 0 (13→14) taken 831 times.
✓ Branch 1 (13→24) taken 6165 times.
6996 if (abs_src_value > deadzone) {
111 831 int32_t value = abs_src_value - deadzone;
112 831 int32_t dst_sign = btn_sign(out->axes[dst_axis_idx].meta->polarity, dst);
113
2/2
✓ Branch 0 (14→15) taken 404 times.
✓ Branch 1 (14→16) taken 427 times.
831 int32_t dst_abs_max = (dst_sign > 0) ? out->axes[dst_axis_idx].meta->abs_max : out->axes[dst_axis_idx].meta->abs_min;
114 831 float scale, fvalue;
115
1/2
✓ Branch 0 (17→18) taken 831 times.
✗ Branch 1 (17→19) not taken.
831 switch (map_cfg->algo & 0xF) {
116 831 case LINEAR:
117 831 scale = ((float)dst_abs_max / (src_abs_max - deadzone)) * (((float)map_cfg->perc_max) / 100);
118 831 break;
119 default:
120 scale = ((float)map_cfg->perc_max) / 100;
121 break;
122
123 }
124 831 fvalue = dst_sign * value * scale;
125 831 value = (int32_t)fvalue;
126
127
2/2
✓ Branch 0 (20→21) taken 661 times.
✓ Branch 1 (20→24) taken 170 times.
831 if (abs(value) > abs(out->axes[dst_axis_idx].value)) {
128 661 out->axes[dst_axis_idx].value = value;
129 661 out->axes[dst_axis_idx].cnt_mask = map_cfg->turbo;
130 }
131 }
132 }
133 else {
134 /* Dst is a button */
135 952 int32_t threshold = (int32_t)(((float)map_cfg->perc_threshold / 100) * src_abs_max);
136 /* Check if axis over threshold */
137
2/2
✓ Branch 0 (22→23) taken 56 times.
✓ Branch 1 (22→24) taken 896 times.
952 if (abs_src_value >= threshold) {
138 56 out->btns[dst_btn_idx].value |= dst_mask;
139 56 out->btns[dst_btn_idx].cnt_mask[dst & 0x1F] = map_cfg->turbo;
140 }
141 }
142 }
143 /* Flag this dst for update */
144 8776 out->map_mask[dst_btn_idx] |= dst_mask;
145 }
146
147 return out_mask;
148 }
149
150 34664 static uint32_t adapter_map_from_btn(struct map_cfg * map_cfg, uint32_t src_mask, uint32_t src_btn_idx) {
151 34664 uint32_t out_mask = BIT(map_cfg->dst_id);
152 34664 struct wired_ctrl *out = &ctrl_output[map_cfg->dst_id];
153 34664 uint8_t dst = map_cfg->dst_btn;
154 34664 uint32_t dst_mask = BIT(dst & 0x1F);
155 34664 uint32_t dst_btn_idx = btn_id_to_btn_idx(dst);
156
157 /* Check if mapping dst exist in output */
158
2/2
✓ Branch 0 (2→3) taken 29532 times.
✓ Branch 1 (2→13) taken 5132 times.
34664 if (dst_mask & out->mask[dst_btn_idx]) {
159 /* Check if button pressed */
160
2/2
✓ Branch 0 (3→4) taken 2024 times.
✓ Branch 1 (3→12) taken 27508 times.
29532 if (ctrl_input->btns[src_btn_idx].value & src_mask) {
161 /* Check if dst is an axis */
162
2/2
✓ Branch 0 (4→5) taken 162 times.
✓ Branch 1 (4→11) taken 1862 times.
2024 if (dst_mask & out->desc[dst_btn_idx]) {
163 /* Dst is an axis */
164 162 uint32_t axis_id = btn_id_to_axis(dst);
165
166
1/2
✓ Branch 0 (5→6) taken 162 times.
✗ Branch 1 (5→14) not taken.
162 if (axis_id == AXIS_NONE) {
167 return 0;
168 }
169 else {
170 162 int32_t dst_sign = btn_sign(out->axes[axis_id].meta->polarity, dst);
171
2/2
✓ Branch 0 (6→7) taken 134 times.
✓ Branch 1 (6→8) taken 28 times.
162 int32_t dst_abs_max = (dst_sign > 0) ? out->axes[axis_id].meta->abs_max : out->axes[axis_id].meta->abs_min;
172 162 float fvalue = dst_sign * dst_abs_max * (((float)map_cfg->perc_max) / 100);
173 162 int32_t value = (int32_t)fvalue;
174
175
2/2
✓ Branch 0 (9→10) taken 154 times.
✓ Branch 1 (9→12) taken 8 times.
162 if (abs(value) > abs(out->axes[axis_id].value)) {
176 154 out->axes[axis_id].value = value;
177 154 out->axes[axis_id].cnt_mask = map_cfg->turbo;
178 }
179 }
180 }
181 else {
182 /* Dst is a button */
183 1862 out->btns[dst_btn_idx].value |= dst_mask;
184 1862 out->btns[dst_btn_idx].cnt_mask[dst & 0x1F] = map_cfg->turbo;
185 }
186 }
187 /* Flag this dst for update */
188 29532 out->map_mask[dst_btn_idx] |= dst_mask;
189 }
190
191 return out_mask;
192 }
193
194 1330 static uint32_t adapter_mapping(struct in_cfg * in_cfg) {
195 1330 uint32_t out_mask = 0;
196
197
2/2
✓ Branch 0 (10→3) taken 166250 times.
✓ Branch 1 (10→11) taken 1330 times.
167580 for (uint32_t i = 0; i < in_cfg->map_size; i++) {
198 166250 uint8_t src = in_cfg->map_cfg[i].src_btn;
199 166250 uint32_t src_mask = BIT(src & 0x1F);
200 166250 uint32_t src_btn_idx = btn_id_to_btn_idx(src);
201
202 /* Check if mapping src exist in input */
203
2/2
✓ Branch 0 (3→4) taken 43496 times.
✓ Branch 1 (3→9) taken 122754 times.
166250 if (src_mask & ctrl_input->mask[src_btn_idx]) {
204 /* Check if src is an axis */
205
2/2
✓ Branch 0 (4→5) taken 8832 times.
✓ Branch 1 (4→7) taken 34664 times.
43496 if (src_mask & ctrl_input->desc[src_btn_idx]) {
206 /* Src is an axis */
207 8832 out_mask |= adapter_map_from_axis(&in_cfg->map_cfg[i]);
208 }
209 else {
210 /* Src is a button */
211 34664 out_mask |= adapter_map_from_btn(&in_cfg->map_cfg[i], src_mask, src_btn_idx);
212 }
213 }
214 }
215 1330 return out_mask;
216 }
217
218 27 static void adapter_fb_stop_cb(void* arg) {
219 27 struct raw_fb fb_data = {0};
220
221 27 fb_data.header.wired_id = (uint8_t)(uintptr_t)arg;
222 27 fb_data.header.type = FB_TYPE_RUMBLE;
223 27 fb_data.header.data_len = 0;
224
225 27 adapter_fb_stop_timer_stop((uint8_t)(uintptr_t)arg);
226
227 /* Unmute system rumble */
228 27 rumble_mute = false;
229
230 /* Send 0 byte data, system that require callback stop shall look for that */
231 27 adapter_q_fb(&fb_data);
232 27 }
233
234 uint32_t adapter_get_out_mask(uint8_t dev_id) {
235 return adapter_out_mask[dev_id];
236 }
237
238 17826 int32_t btn_id_to_axis(uint8_t btn_id) {
239
7/17
✓ Branch 0 (2→3) taken 4020 times.
✓ Branch 1 (2→4) taken 2936 times.
✓ Branch 2 (2→5) taken 2936 times.
✓ Branch 3 (2→6) taken 1482 times.
✓ Branch 4 (2→7) taken 1480 times.
✗ Branch 5 (2→8) not taken.
✗ Branch 6 (2→9) not taken.
✗ Branch 7 (2→10) not taken.
✗ Branch 8 (2→11) not taken.
✗ Branch 9 (2→12) not taken.
✗ Branch 10 (2→13) not taken.
✗ Branch 11 (2→14) not taken.
✗ Branch 12 (2→15) not taken.
✗ Branch 13 (2→16) not taken.
✗ Branch 14 (2→17) not taken.
✓ Branch 15 (2→18) taken 952 times.
✓ Branch 16 (2→19) taken 4020 times.
17826 switch (btn_id) {
240 case PAD_LX_LEFT:
241 case PAD_LX_RIGHT:
242 case MOUSE_WX_LEFT:
243 case MOUSE_WX_RIGHT:
244 return AXIS_LX;
245 4020 case PAD_LY_DOWN:
246 case PAD_LY_UP:
247 case MOUSE_WY_DOWN:
248 case MOUSE_WY_UP:
249 4020 return AXIS_LY;
250 2936 case PAD_RX_LEFT:
251 case PAD_RX_RIGHT:
252 //case MOUSE_X_LEFT:
253 //case MOUSE_X_RIGHT:
254 2936 return AXIS_RX;
255 2936 case PAD_RY_DOWN:
256 case PAD_RY_UP:
257 //case MOUSE_Y_DOWN:
258 //case MOUSE_Y_UP:
259 2936 return AXIS_RY;
260 1482 case PAD_LM:
261 1482 return TRIG_L;
262 1480 case PAD_RM:
263 1480 return TRIG_R;
264 case PAD_LS:
265 return TRIG_LS;
266 case PAD_RS:
267 return TRIG_RS;
268 case PAD_LD_LEFT:
269 return DPAD_LEFT;
270 case PAD_LD_RIGHT:
271 return DPAD_RIGHT;
272 case PAD_LD_DOWN:
273 return DPAD_DOWN;
274 case PAD_LD_UP:
275 return DPAD_UP;
276 case PAD_RB_LEFT:
277 return BTN_LEFT;
278 case PAD_RB_RIGHT:
279 return BTN_RIGHT;
280 case PAD_RB_DOWN:
281 return BTN_DOWN;
282 case PAD_RB_UP:
283 return BTN_UP;
284 }
285 952 return AXIS_NONE;
286 }
287
288 uint8_t btn_is_axis(uint8_t dst_id, uint8_t dst_btn) {
289 struct wired_ctrl *out = &ctrl_output[dst_id];
290 uint32_t dst_mask = BIT(dst_btn & 0x1F);
291 uint32_t dst_btn_idx = btn_id_to_btn_idx(dst_btn);
292 if (dst_mask & out->desc[dst_btn_idx]) {
293 return 1;
294 }
295 return 0;
296 }
297
298 7864 uint32_t axis_to_btn_mask(uint8_t axis) {
299
6/17
✓ Branch 0 (2→3) taken 1330 times.
✓ Branch 1 (2→4) taken 1294 times.
✓ Branch 2 (2→5) taken 1294 times.
✓ Branch 3 (2→6) taken 1308 times.
✓ Branch 4 (2→7) taken 1308 times.
✗ Branch 5 (2→8) not taken.
✗ Branch 6 (2→9) not taken.
✗ Branch 7 (2→10) not taken.
✗ Branch 8 (2→11) not taken.
✗ Branch 9 (2→12) not taken.
✗ Branch 10 (2→13) not taken.
✗ Branch 11 (2→14) not taken.
✗ Branch 12 (2→15) not taken.
✗ Branch 13 (2→16) not taken.
✗ Branch 14 (2→17) not taken.
✗ Branch 15 (2→18) not taken.
✓ Branch 16 (2→19) taken 1330 times.
7864 switch (axis) {
300 case AXIS_LX:
301 return BIT(PAD_LX_LEFT) | BIT(PAD_LX_RIGHT) | BIT(MOUSE_WX_LEFT) | BIT(MOUSE_WX_RIGHT);
302 1330 case AXIS_LY:
303 1330 return BIT(PAD_LY_DOWN) | BIT(PAD_LY_UP) | BIT(MOUSE_WY_DOWN) | BIT(MOUSE_WY_UP);
304 1294 case AXIS_RX:
305 1294 return BIT(PAD_RX_LEFT) | BIT(PAD_RX_RIGHT); /* BIT(MOUSE_X_LEFT) | BIT(MOUSE_X_RIGHT) */
306 1294 case AXIS_RY:
307 1294 return BIT(PAD_RY_DOWN) | BIT(PAD_RY_UP); /* BIT(MOUSE_Y_DOWN) | BIT(MOUSE_Y_UP) */
308 1308 case TRIG_L:
309 1308 return BIT(PAD_LM);
310 1308 case TRIG_R:
311 1308 return BIT(PAD_RM);
312 case TRIG_LS:
313 return BIT(PAD_LS);
314 case TRIG_RS:
315 return BIT(PAD_RS);
316 case DPAD_LEFT:
317 return BIT(PAD_LD_LEFT);
318 case DPAD_RIGHT:
319 return BIT(PAD_LD_RIGHT);
320 case DPAD_DOWN:
321 return BIT(PAD_LD_DOWN);
322 case DPAD_UP:
323 return BIT(PAD_LD_UP);
324 case BTN_LEFT:
325 return BIT(PAD_RB_LEFT);
326 case BTN_RIGHT:
327 return BIT(PAD_RB_RIGHT);
328 case BTN_DOWN:
329 return BIT(PAD_RB_DOWN);
330 case BTN_UP:
331 return BIT(PAD_RB_UP);
332 }
333 return 0x00000000;
334 }
335
336 7864 uint32_t IRAM_ATTR axis_to_btn_id(uint8_t axis) {
337
6/16
✓ Branch 0 (2→3) taken 1330 times.
✓ Branch 1 (2→4) taken 1294 times.
✓ Branch 2 (2→5) taken 1294 times.
✓ Branch 3 (2→6) taken 1308 times.
✓ Branch 4 (2→7) taken 1308 times.
✗ Branch 5 (2→8) not taken.
✗ Branch 6 (2→9) not taken.
✗ Branch 7 (2→10) not taken.
✗ Branch 8 (2→11) not taken.
✗ Branch 9 (2→12) not taken.
✗ Branch 10 (2→13) not taken.
✗ Branch 11 (2→14) not taken.
✗ Branch 12 (2→15) not taken.
✗ Branch 13 (2→16) not taken.
✗ Branch 14 (2→17) not taken.
✓ Branch 15 (2→18) taken 1330 times.
7864 switch (axis) {
338 case AXIS_LX:
339 return PAD_LX_LEFT;
340 1330 case AXIS_LY:
341 1330 return PAD_LY_DOWN;
342 1294 case AXIS_RX:
343 1294 return PAD_RX_LEFT;
344 1294 case AXIS_RY:
345 1294 return PAD_RY_DOWN;
346 1308 case TRIG_L:
347 1308 return PAD_LM;
348 1308 case TRIG_R:
349 1308 return PAD_RM;
350 case TRIG_LS:
351 return PAD_LS;
352 case TRIG_RS:
353 return PAD_RS;
354 case DPAD_LEFT:
355 return PAD_LD_LEFT;
356 case DPAD_RIGHT:
357 return PAD_LD_RIGHT;
358 case DPAD_DOWN:
359 return PAD_LD_DOWN;
360 case DPAD_UP:
361 return PAD_LD_UP;
362 case BTN_LEFT:
363 return PAD_RB_LEFT;
364 case BTN_RIGHT:
365 return PAD_RB_RIGHT;
366 case BTN_DOWN:
367 return PAD_RB_DOWN;
368 case BTN_UP:
369 return PAD_RB_UP;
370 }
371 return 0;
372 }
373
374 9769 int8_t btn_sign(uint32_t polarity, uint8_t btn_id) {
375
2/3
✓ Branch 0 (2→3) taken 5878 times.
✗ Branch 1 (2→4) not taken.
✓ Branch 2 (2→5) taken 3891 times.
9769 switch (btn_id) {
376 5878 case PAD_LX_RIGHT:
377 case PAD_LY_UP:
378 case PAD_RX_RIGHT:
379 case PAD_RY_UP:
380 case PAD_LM:
381 case PAD_RM:
382 case MOUSE_WX_RIGHT:
383 case MOUSE_WY_UP:
384 //case MOUSE_X_RIGHT:
385 //case MOUSE_Y_UP:
386 case PAD_LS:
387 case PAD_RS:
388 case PAD_LD_LEFT:
389 case PAD_LD_RIGHT:
390 case PAD_LD_DOWN:
391 case PAD_LD_UP:
392 case PAD_RB_LEFT:
393 case PAD_RB_RIGHT:
394 case PAD_RB_DOWN:
395 case PAD_RB_UP:
396
2/2
✓ Branch 0 (3→4) taken 4970 times.
✓ Branch 1 (3→6) taken 908 times.
5878 return polarity ? -1 : 1;
397 3891 case PAD_LX_LEFT:
398 case PAD_LY_DOWN:
399 case PAD_RY_DOWN:
400 case PAD_RX_LEFT:
401 case MOUSE_WX_LEFT:
402 case MOUSE_WY_DOWN:
403 //case MOUSE_X_LEFT:
404 //case MOUSE_Y_DOWN:
405
2/2
✓ Branch 0 (5→4) taken 908 times.
✓ Branch 1 (5→6) taken 2983 times.
3891 return polarity ? 1 : -1;
406 }
407 return 1;
408 }
409
410 192 void IRAM_ATTR adapter_init_buffer(uint8_t wired_id) {
411
1/2
✓ Branch 0 (2→3) taken 192 times.
✗ Branch 1 (2→4) not taken.
192 if (wired_adapter.system_id != WIRED_AUTO) {
412 192 wired_adapter.data[wired_id].index = wired_id;
413 192 wired_init_buffer(config.out_cfg[wired_id].dev_mode, &wired_adapter.data[wired_id]);
414 }
415 192 }
416
417 1330 void adapter_bridge(struct bt_data *bt_data) {
418 1330 uint32_t out_mask = 0;
419
420
1/2
✓ Branch 0 (2→3) taken 1330 times.
✗ Branch 1 (2→19) not taken.
1330 if (bt_data->base.pids->type != BT_NONE) {
421
1/2
✓ Branch 0 (4→5) taken 1330 times.
✗ Branch 1 (4→19) not taken.
1330 if (wireless_to_generic(bt_data, ctrl_input)) {
422 /* Unsupported report */
423 return;
424 }
425
426 #ifdef CONFIG_BLUERETRO_ADAPTER_INPUT_DBG
427 1330 TESTS_CMDS_LOG("\"generic_input\": {");
428 1330 adapter_debug_wireless_print(ctrl_input);
429 #endif
430
1/2
✓ Branch 0 (7→8) taken 1330 times.
✗ Branch 1 (7→19) not taken.
1330 if (wired_adapter.system_id != WIRED_AUTO) {
431
1/2
✓ Branch 0 (9→10) taken 1330 times.
✗ Branch 1 (9→19) not taken.
1330 if (wired_meta_init(ctrl_output)) {
432 /* Unsupported system */
433 return;
434 }
435
436 2660 adapter_out_mask[bt_data->base.pids->out_idx] =
437 1330 out_mask = adapter_mapping(&config.in_cfg[bt_data->base.pids->out_idx]);
438
439 #ifdef CONFIG_BLUERETRO_ADAPTER_INPUT_MAP_DBG
440 1330 TESTS_CMDS_LOG("\"mapped_input\": {");
441 1330 adapter_debug_wired_print(&ctrl_output[bt_data->base.pids->out_idx]);
442 #endif
443 1330 ctrl_output[bt_data->base.pids->out_idx].index = bt_data->base.pids->out_idx;
444 1330 sys_macro_hdl(&ctrl_output[bt_data->base.pids->out_idx], &bt_data->base.flags[PAD]);
445
2/2
✓ Branch 0 (18→15) taken 1330 times.
✓ Branch 1 (18→19) taken 1330 times.
2660 for (uint32_t i = 0; out_mask; i++, out_mask >>= 1) {
446
1/2
✓ Branch 0 (15→16) taken 1330 times.
✗ Branch 1 (15→17) not taken.
1330 if (out_mask & 0x1) {
447 1330 ctrl_output[i].index = i;
448 1330 wired_from_generic(config.out_cfg[i].dev_mode, &ctrl_output[i], &wired_adapter.data[i]);
449 }
450 }
451 }
452 }
453 }
454
455 27 void adapter_fb_stop_timer_start(uint8_t dev_id, uint64_t dur_us) {
456
1/2
✓ Branch 0 (2→3) taken 27 times.
✗ Branch 1 (2→6) not taken.
27 if (wired_adapter.data[dev_id].fb_timer_hdl == NULL) {
457 27 const esp_timer_create_args_t fb_timer_args = {
458 .callback = &adapter_fb_stop_cb,
459 27 .arg = (void*)(uintptr_t)dev_id,
460 .name = "fb_timer"
461 };
462 27 esp_timer_create(&fb_timer_args, (esp_timer_handle_t *)&wired_adapter.data[dev_id].fb_timer_hdl);
463 27 esp_timer_start_once(wired_adapter.data[dev_id].fb_timer_hdl, dur_us);
464 }
465 27 }
466
467 27 void adapter_fb_stop_timer_stop(uint8_t dev_id) {
468
1/2
✓ Branch 0 (2→3) taken 27 times.
✗ Branch 1 (2→5) not taken.
27 if (wired_adapter.data[dev_id].fb_timer_hdl) {
469 27 esp_timer_delete(wired_adapter.data[dev_id].fb_timer_hdl);
470 27 wired_adapter.data[dev_id].fb_timer_hdl = NULL;
471 }
472 27 }
473
474 bool adapter_bridge_fb(struct raw_fb *fb_data, struct bt_data *bt_data) {
475 bool ret = false;
476
477 if (wired_adapter.system_id != WIRED_AUTO && bt_data && bt_data->base.pids) {
478 wired_fb_to_generic(config.out_cfg[bt_data->base.pids->id].dev_mode, fb_data, &fb_input);
479
480 if (bt_data->base.pids->type != BT_NONE) {
481 ret = wireless_fb_from_generic(&fb_input, bt_data);
482 }
483 }
484 return ret;
485 }
486
487 28 void IRAM_ATTR adapter_q_fb(struct raw_fb *fb_data) {
488 /* Best efford only on fb */
489
1/2
✓ Branch 0 (2→3) taken 28 times.
✗ Branch 1 (2→4) not taken.
28 if (!rumble_mute) {
490 28 queue_bss_enqueue(wired_adapter.input_q_hdl, (uint8_t *)fb_data, sizeof(*fb_data));
491 }
492 28 }
493
494 82 void adapter_toggle_fb(uint32_t wired_id, uint32_t duration_us, uint8_t lf_pwr, uint8_t hf_pwr) {
495 82 struct bt_dev *device = NULL;
496 82 struct bt_data *bt_data = NULL;
497
498 82 bt_host_get_active_dev_from_out_idx(wired_id, &device);
499
4/4
✓ Branch 0 (3→4) taken 50 times.
✓ Branch 1 (3→9) taken 32 times.
✓ Branch 2 (4→5) taken 27 times.
✓ Branch 3 (4→9) taken 23 times.
82 if (!rumble_mute && device) {
500 27 bt_data = &bt_adapter.data[device->ids.id];
501 27 if (bt_data) {
502 27 struct generic_fb fb_data = {0};
503
504 27 fb_data.wired_id = wired_id;
505 27 fb_data.type = FB_TYPE_RUMBLE;
506 27 fb_data.state = 1;
507 27 fb_data.hf_pwr = hf_pwr;
508 27 fb_data.lf_pwr = lf_pwr;
509 27 rumble_mute = true;
510 27 adapter_fb_stop_timer_start(wired_id, duration_us);
511 27 wireless_fb_from_generic(&fb_data, bt_data);
512 27 bt_hid_feedback(device, bt_data->base.output);
513 }
514 }
515 82 }
516
517 1 void adapter_init(void) {
518 1 wired_adapter.system_id = WIRED_AUTO;
519
520 /* Save regular DRAM by allocating big sruct w/ only 32bits access in IRAM */
521 1 ctrl_input = heap_caps_aligned_alloc(32, sizeof(struct wireless_ctrl), MALLOC_CAP_32BIT);
522
1/2
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 1 times.
1 if (ctrl_input == NULL) {
523 printf("# %s ctrl_input alloc fail\n", __FUNCTION__);
524 }
525 1 ctrl_output = heap_caps_aligned_alloc(32, sizeof(struct wired_ctrl) * WIRED_MAX_DEV, MALLOC_CAP_32BIT);
526
1/2
✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 1 times.
1 if (ctrl_output == NULL) {
527 printf("# %s ctrl_output alloc fail\n", __FUNCTION__);
528 }
529
2/2
✓ Branch 0 (13→9) taken 7 times.
✓ Branch 1 (13→14) taken 1 times.
8 for (uint32_t i = 0; i < BT_MAX_DEV; i++) {
530 7 bt_adapter.data[i].raw_src_mappings = heap_caps_aligned_alloc(32, sizeof(struct raw_src_mapping) * REPORT_MAX, MALLOC_CAP_32BIT);
531
1/2
✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→12) taken 7 times.
7 if (bt_adapter.data[i].raw_src_mappings == NULL) {
532 printf("# %s bt_adapter.data[%ld].raw_src_mappings alloc fail\n", __FUNCTION__, i);
533 }
534 }
535
536 1 wired_adapter.input_q_hdl = queue_bss_init(16, sizeof(struct raw_fb));
537
1/2
✗ Branch 0 (15→16) not taken.
✓ Branch 1 (15→17) taken 1 times.
1 if (wired_adapter.input_q_hdl == NULL) {
538 ets_printf("# %s: Failed to create fb queue\n", __FUNCTION__);
539 }
540 1 }
541
542 void adapter_meta_init(void) {
543 if (wired_adapter.system_id != WIRED_AUTO) {
544 wired_meta_init(ctrl_output);
545 }
546 }
547