GCC Code Coverage Report


Directory: main/
File: adapter/wired/dc.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 0 184 0.0%
Functions: 0 9 0.0%
Branches: 0 113 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 <string.h>
7 #include "zephyr/types.h"
8 #include "tools/util.h"
9 #include "adapter/config.h"
10 #include "adapter/wired/wired.h"
11 #include "system/manager.h"
12 #include "tests/cmds.h"
13 #include "bluetooth/mon.h"
14 #include "dc.h"
15
16 #define DC_TIMEOUT_TO_US 250000
17 #define DC_FREQ_TO_US 2000000
18
19 enum {
20 DC_Z = 0,
21 DC_Y,
22 DC_X,
23 DC_D,
24 DC_RD_UP,
25 DC_RD_DOWN,
26 DC_RD_LEFT,
27 DC_RD_RIGHT,
28 DC_C,
29 DC_B,
30 DC_A,
31 DC_START,
32 DC_LD_UP,
33 DC_LD_DOWN,
34 DC_LD_LEFT,
35 DC_LD_RIGHT,
36 };
37
38 enum {
39 DC_KB_LCTRL = 0,
40 DC_KB_LSHIFT,
41 DC_KB_LALT,
42 DC_KB_LWIN,
43 DC_KB_RCTRL,
44 DC_KB_RSHIFT,
45 DC_KB_RALT,
46 DC_KB_RWIN,
47 };
48
49 static DRAM_ATTR const uint8_t dc_axes_idx[ADAPTER_MAX_AXES] =
50 {
51 /* AXIS_LX, AXIS_LY, AXIS_RX, AXIS_RY, TRIG_L, TRIG_R */
52 7, 6, 5, 4, 0, 1
53 };
54
55 static const uint8_t dc_kb_keycode_idx[] =
56 {
57 1, 0, 7, 6, 5, 4
58 };
59
60 static DRAM_ATTR const struct ctrl_meta dc_axes_meta[ADAPTER_MAX_AXES] =
61 {
62 {.size_min = -128, .size_max = 127, .neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80},
63 {.size_min = -128, .size_max = 127, .neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80, .polarity = 1},
64 {.size_min = -128, .size_max = 127, .neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80},
65 {.size_min = -128, .size_max = 127, .neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80, .polarity = 1},
66 {.size_min = 0, .size_max = 255, .neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
67 {.size_min = 0, .size_max = 255, .neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
68 };
69
70 static DRAM_ATTR const struct ctrl_meta dc_mouse_axes_meta[ADAPTER_MAX_AXES] =
71 {
72 {.size_min = -512, .size_max = 511, .neutral = 0x200, .abs_max = 0x1FF, .abs_min = 0x200},
73 {.size_min = -512, .size_max = 511, .neutral = 0x200, .abs_max = 0x1FF, .abs_min = 0x200},
74 {.size_min = -512, .size_max = 511, .neutral = 0x200, .abs_max = 0x1FF, .abs_min = 0x200},
75 {.size_min = -512, .size_max = 511, .neutral = 0x200, .abs_max = 0x1FF, .abs_min = 0x200, .polarity = 1},
76 {.size_min = -512, .size_max = 511, .neutral = 0x200, .abs_max = 0x1FF, .abs_min = 0x200},
77 {.size_min = -512, .size_max = 511, .neutral = 0x200, .abs_max = 0x1FF, .abs_min = 0x200},
78 };
79
80 struct dc_map {
81 union {
82 struct {
83 uint16_t triggers;
84 uint16_t buttons;
85 uint32_t sticks;
86 };
87 uint8_t axes[8];
88 };
89 } __packed;
90
91 struct dc_mouse_map {
92 uint8_t reserved[3];
93 uint8_t buttons;
94 uint8_t relative[4];
95 int32_t raw_axes[4];
96 } __packed;
97
98 struct dc_kb_map {
99 union {
100 struct {
101 uint8_t reserved[3];
102 uint8_t bitfield;
103 };
104 uint8_t key_codes[8];
105 };
106 int8_t br_key_codes[6];
107 } __packed;
108
109 struct dc_vibration {
110 uint8_t incline;
111 uint8_t freq; /* 0.5 Hz step, 0 = 0.5 Hz */
112 uint8_t pwr_n: 3;
113 uint8_t exhalation: 1;
114 uint8_t pwr_p: 3;
115 uint8_t convergence: 1;
116 uint8_t continuous: 1;
117 uint8_t tbd: 3;
118 uint8_t unit: 4;
119 } __packed;
120
121 struct dc_timeout {
122 uint8_t unit2_timeout;
123 uint8_t unit1_timeout; /* 0.25 sec step, 0 = 0.25 sec */
124 uint8_t unit_mask; /* unit1 mask is 0x02 */
125 uint8_t tbd;
126 } __packed;
127
128 static const uint32_t dc_mask[4] = {0x337FFFFF, 0x00000000, 0x00000000, BR_COMBO_MASK};
129 static const uint32_t dc_desc[4] = {0x110000FF, 0x00000000, 0x00000000, 0x00000000};
130 static DRAM_ATTR const uint32_t dc_btns_mask[32] = {
131 0, 0, 0, 0,
132 0, 0, 0, 0,
133 BIT(DC_LD_LEFT), BIT(DC_LD_RIGHT), BIT(DC_LD_DOWN), BIT(DC_LD_UP),
134 BIT(DC_RD_LEFT), BIT(DC_RD_RIGHT), BIT(DC_RD_DOWN), BIT(DC_RD_UP),
135 BIT(DC_X), BIT(DC_B), BIT(DC_A), BIT(DC_Y),
136 BIT(DC_START), BIT(DC_D), 0, 0,
137 0, BIT(DC_Z), 0, 0,
138 0, BIT(DC_C), 0, 0,
139 };
140
141 static const uint32_t dc_mouse_mask[4] = {0x1901C0F0, 0x00000000, 0x00000000, BR_COMBO_MASK};
142 static const uint32_t dc_mouse_desc[4] = {0x0000C0F0, 0x00000000, 0x00000000, 0x00000000};
143 static const uint32_t dc_mouse_btns_mask[32] = {
144 0, 0, 0, 0,
145 0, 0, 0, 0,
146 0, 0, 0, 0,
147 0, 0, 0, 0,
148 0, 0, 0, 0,
149 0, 0, 0, 0,
150 BIT(DC_D), 0, 0, BIT(DC_Y),
151 BIT(DC_X), 0, 0, 0,
152 };
153
154 static const uint32_t dc_kb_mask[4] = {0xE6FF0F0F, 0xFFFFFFFF, 0xFFFFFFFF, 0x0007FFFF | BR_COMBO_MASK};
155 static const uint32_t dc_kb_desc[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
156 static const uint8_t dc_kb_scancode[KBM_MAX] = {
157 /* KB_A, KB_D, KB_S, KB_W, MOUSE_X_LEFT, MOUSE_X_RIGHT, MOUSE_Y_DOWN MOUSE_Y_UP */
158 0x04, 0x07, 0x16, 0x1A, 0x00, 0x00, 0x00, 0x00,
159 /* KB_LEFT, KB_RIGHT, KB_DOWN, KB_UP, MOUSE_WX_LEFT, MOUSE_WX_RIGHT, MOUSE_WY_DOWN, MOUSE_WY_UP */
160 0x50, 0x4F, 0x51, 0x52, 0x00, 0x00, 0x00, 0x00,
161 /* KB_Q, KB_R, KB_E, KB_F, KB_ESC, KB_ENTER, KB_LWIN, KB_HASH */
162 0x14, 0x15, 0x08, 0x09, 0x29, 0x28, 0x00, 0x35,
163 /* MOUSE_RIGHT, KB_Z, KB_LCTRL, MOUSE_MIDDLE, MOUSE_LEFT, KB_X, KB_LSHIFT, KB_SPACE */
164 0x00, 0x1D, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x2C,
165
166 /* KB_B, KB_C, KB_G, KB_H, KB_I, KB_J, KB_K, KB_L */
167 0x05, 0x06, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
168 /* KB_M, KB_N, KB_O, KB_P, KB_T, KB_U, KB_V, KB_Y */
169 0x10, 0x11, 0x12, 0x13, 0x17, 0x18, 0x19, 0x1C,
170 /* KB_1, KB_2, KB_3, KB_4, KB_5, KB_6, KB_7, KB_8 */
171 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
172 /* KB_9, KB_0, KB_BACKSPACE, KB_TAB, KB_MINUS, KB_EQUAL, KB_LEFTBRACE, KB_RIGHTBRACE */
173 0x26, 0x27, 0x2A, 0x2B, 0x2D, 0x2E, 0x30, 0x32,
174
175 /* KB_BACKSLASH, KB_SEMICOLON, KB_APOSTROPHE, KB_GRAVE, KB_COMMA, KB_DOT, KB_SLASH, KB_CAPSLOCK */
176 0x87, 0x33, 0x34, 0x89, 0x36, 0x37, 0x38, 0x39,
177 /* KB_F1, KB_F2, KB_F3, KB_F4, KB_F5, KB_F6, KB_F7, KB_F8 */
178 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
179 /* KB_F9, KB_F10, KB_F11, KB_F12, KB_PSCREEN, KB_SCROLL, KB_PAUSE, KB_INSERT */
180 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
181 /* KB_HOME, KB_PAGEUP, KB_DEL, KB_END, KB_PAGEDOWN, KB_NUMLOCK, KB_KP_DIV, KB_KP_MULTI */
182 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x53, 0x54, 0x55,
183
184 /* KB_KP_MINUS, KB_KP_PLUS, KB_KP_ENTER, KB_KP_1, KB_KP_2, KB_KP_3, KB_KP_4, KB_KP_5 */
185 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D,
186 /* KB_KP_6, KB_KP_7, KB_KP_8, KB_KP_9, KB_KP_0, KB_KP_DOT, KB_LALT, KB_RCTRL */
187 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x00, 0x00,
188 /* KB_RSHIFT, KB_RALT, KB_RWIN */
189 0x00, 0x00, 0x00,
190 };
191
192 static void dc_ctrl_special_action(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
193 /* Output config mode toggle GamePad/GamePadAlt */
194 if (ctrl_data->map_mask[0] & generic_btns_mask[PAD_MT]) {
195 if (ctrl_data->btns[0].value & generic_btns_mask[PAD_MT]) {
196 if (!atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
197 atomic_set_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
198 }
199 }
200 else {
201 if (atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
202 atomic_clear_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
203
204 config.out_cfg[ctrl_data->index].dev_mode &= 0x01;
205 config.out_cfg[ctrl_data->index].dev_mode ^= 0x01;
206 sys_mgr_cmd(SYS_MGR_CMD_WIRED_RST);
207 }
208 }
209 }
210 }
211
212 void IRAM_ATTR dc_init_buffer(int32_t dev_mode, struct wired_data *wired_data) {
213 switch (dev_mode) {
214 case DEV_KB:
215 {
216 struct dc_kb_map *map = (struct dc_kb_map *)wired_data->output;
217 memset(map, 0x00, sizeof(struct dc_kb_map));
218 memset(map->br_key_codes, KBM_NONE, sizeof(map->br_key_codes));
219 break;
220 }
221 case DEV_MOUSE:
222 {
223 struct dc_mouse_map *map = (struct dc_mouse_map *)wired_data->output;
224
225 for (uint32_t i = 0; i < ARRAY_SIZE(map->raw_axes); i++) {
226 map->raw_axes[i] = 0;
227 map->relative[i] = 1;
228 }
229 map->reserved[0] = 0x00;
230 map->reserved[1] = 0x00;
231 map->reserved[2] = 0x00;
232 map->buttons = 0xFF;
233 break;
234 }
235 default:
236 {
237 struct dc_map *map = (struct dc_map *)wired_data->output;
238 struct dc_map *map_mask = (struct dc_map *)wired_data->output_mask;
239
240 for (uint32_t i = 0; i < ADAPTER_MAX_AXES; i++) {
241 map->axes[dc_axes_idx[i]] = dc_axes_meta[i].neutral;
242 }
243 map->buttons = 0xFFFF;
244
245 map_mask->triggers = 0xFFFF;
246 map_mask->buttons = 0x0000;
247 map_mask->sticks = 0x00000000;
248 break;
249 }
250 }
251 }
252
253 void dc_meta_init(struct wired_ctrl *ctrl_data) {
254 memset((void *)ctrl_data, 0, sizeof(*ctrl_data)*4);
255
256 for (uint32_t i = 0; i < WIRED_MAX_DEV; i++) {
257 for (uint32_t j = 0; j < ADAPTER_MAX_AXES; j++) {
258 switch (config.out_cfg[i].dev_mode) {
259 case DEV_KB:
260 ctrl_data[i].mask = dc_kb_mask;
261 ctrl_data[i].desc = dc_kb_desc;
262 goto exit_axes_loop;
263 case DEV_MOUSE:
264 ctrl_data[i].mask = dc_mouse_mask;
265 ctrl_data[i].desc = dc_mouse_desc;
266 ctrl_data[i].axes[j].meta = &dc_mouse_axes_meta[j];
267 break;
268 default:
269 ctrl_data[i].mask = dc_mask;
270 ctrl_data[i].desc = dc_desc;
271 ctrl_data[i].axes[j].meta = &dc_axes_meta[j];
272 break;
273 }
274 }
275 exit_axes_loop:
276 ;
277 }
278 }
279
280 static void dc_ctrl_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
281 struct dc_map map_tmp;
282
283 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
284
285 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
286 if (ctrl_data->map_mask[0] & BIT(i)) {
287 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
288 map_tmp.buttons &= ~dc_btns_mask[i];
289 wired_data->cnt_mask[i] = ctrl_data->btns[0].cnt_mask[i];
290 }
291 else {
292 map_tmp.buttons |= dc_btns_mask[i];
293 wired_data->cnt_mask[i] = 0;
294 }
295 }
296 }
297
298 dc_ctrl_special_action(ctrl_data, wired_data);
299
300 for (uint32_t i = 0; i < ADAPTER_MAX_AXES; i++) {
301 if (ctrl_data->map_mask[0] & (axis_to_btn_mask(i) & dc_desc[0])) {
302 if (ctrl_data->axes[i].value > ctrl_data->axes[i].meta->size_max) {
303 map_tmp.axes[dc_axes_idx[i]] = 255;
304 }
305 else if (ctrl_data->axes[i].value < ctrl_data->axes[i].meta->size_min) {
306 map_tmp.axes[dc_axes_idx[i]] = 0;
307 }
308 else {
309 map_tmp.axes[dc_axes_idx[i]] = (uint8_t)(ctrl_data->axes[i].value + ctrl_data->axes[i].meta->neutral);
310 }
311 }
312 wired_data->cnt_mask[axis_to_btn_id(i)] = ctrl_data->axes[i].cnt_mask;
313 }
314
315 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp));
316
317 TESTS_CMDS_LOG("\"wired_output\": {\"axes\": [%d, %d, %d, %d, %d, %d], \"btns\": %d},\n",
318 map_tmp.axes[dc_axes_idx[0]], map_tmp.axes[dc_axes_idx[1]], map_tmp.axes[dc_axes_idx[2]],
319 map_tmp.axes[dc_axes_idx[3]], map_tmp.axes[dc_axes_idx[4]], map_tmp.axes[dc_axes_idx[5]], map_tmp.buttons);
320 BT_MON_LOG("\"wired_output\": {\"axes\": [%02X, %02X, %02X, %02X, %02X, %02X], \"btns\": %04X},\n",
321 map_tmp.axes[dc_axes_idx[0]], map_tmp.axes[dc_axes_idx[1]], map_tmp.axes[dc_axes_idx[2]],
322 map_tmp.axes[dc_axes_idx[3]], map_tmp.axes[dc_axes_idx[4]], map_tmp.axes[dc_axes_idx[5]], map_tmp.buttons);
323 }
324
325 static void dc_mouse_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
326 struct dc_mouse_map map_tmp;
327 int32_t *raw_axes = (int32_t *)(wired_data->output + 8);
328
329 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
330
331 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
332 if (ctrl_data->map_mask[0] & BIT(i)) {
333 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
334 map_tmp.buttons &= ~dc_mouse_btns_mask[i];
335 }
336 else {
337 map_tmp.buttons |= dc_mouse_btns_mask[i];
338 }
339 }
340 }
341
342 for (uint32_t i = 0; i < 4; i++) {
343 if (ctrl_data->map_mask[0] & (axis_to_btn_mask(i) & dc_mouse_desc[0])) {
344 if (ctrl_data->axes[i].relative) {
345 map_tmp.relative[i] = 1;
346 atomic_add(&raw_axes[i], ctrl_data->axes[i].value);
347 }
348 else {
349 map_tmp.relative[i] = 0;
350 raw_axes[i] = ctrl_data->axes[i].value;
351 }
352 }
353 }
354
355 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp) - 16);
356 }
357
358 static void dc_kb_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
359 struct dc_kb_map map_tmp = {0};
360 uint32_t code_idx = 0;
361
362 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
363
364 /* Clear released keys since previous report and shift remaining one left in array */
365 for (uint32_t i = 0; i < ARRAY_SIZE(dc_kb_keycode_idx);) {
366 int8_t br_key_code = map_tmp.br_key_codes[i];
367
368 if (map_tmp.br_key_codes[i] > KBM_NONE && !(ctrl_data->btns[br_key_code / 32].value & BIT(br_key_code & 0x1F))) {
369 uint32_t j = i;
370 for (; j < (ARRAY_SIZE(dc_kb_keycode_idx) - 1); j++) {
371 map_tmp.br_key_codes[j] = map_tmp.br_key_codes[j + 1];
372 }
373 map_tmp.br_key_codes[j] = KBM_NONE;
374 }
375 else {
376 i++;
377 }
378 }
379
380 /* Update DC keycodes */
381 for (uint32_t i = 0; i < ARRAY_SIZE(dc_kb_keycode_idx); i++) {
382 int8_t br_key_code = map_tmp.br_key_codes[i];
383 if (br_key_code == KBM_NONE) {
384 map_tmp.key_codes[dc_kb_keycode_idx[i]] = 0;
385 }
386 else {
387 map_tmp.key_codes[dc_kb_keycode_idx[i]] = dc_kb_scancode[map_tmp.br_key_codes[i]];
388 code_idx++;
389 }
390 }
391
392 /* Add new key press */
393 for (uint32_t i = 0; i < KBM_MAX && code_idx < ARRAY_SIZE(dc_kb_keycode_idx); i++) {
394 if (ctrl_data->map_mask[i / 32] & BIT(i & 0x1F)) {
395 if (ctrl_data->btns[i / 32].value & BIT(i & 0x1F)) {
396 if (dc_kb_scancode[i]) {
397 for (uint32_t j = 0; j < ARRAY_SIZE(dc_kb_keycode_idx); j++) {
398 if (map_tmp.br_key_codes[j] == i) {
399 goto next_loop;
400 }
401 }
402 map_tmp.br_key_codes[code_idx] = i;
403 map_tmp.key_codes[dc_kb_keycode_idx[code_idx++]] = dc_kb_scancode[i];
404 }
405 }
406 }
407 next_loop:
408 ;
409 }
410
411 map_tmp.bitfield = 0;
412 if (ctrl_data->map_mask[0] & BIT(KB_LCTRL & 0x1F) && ctrl_data->btns[0].value & BIT(KB_LCTRL & 0x1F)) {
413 map_tmp.bitfield |= BIT(DC_KB_LCTRL);
414 }
415 if (ctrl_data->map_mask[0] & BIT(KB_LSHIFT & 0x1F) && ctrl_data->btns[0].value & BIT(KB_LSHIFT & 0x1F)) {
416 map_tmp.bitfield |= BIT(DC_KB_LSHIFT);
417 }
418 if (ctrl_data->map_mask[3] & BIT(KB_LALT & 0x1F) && ctrl_data->btns[3].value & BIT(KB_LALT & 0x1F)) {
419 map_tmp.bitfield |= BIT(DC_KB_LALT);
420 }
421 if (ctrl_data->map_mask[0] & BIT(KB_LWIN & 0x1F) && ctrl_data->btns[0].value & BIT(KB_LWIN & 0x1F)) {
422 map_tmp.bitfield |= BIT(DC_KB_LWIN);
423 }
424 if (ctrl_data->map_mask[3] & BIT(KB_RCTRL & 0x1F) && ctrl_data->btns[3].value & BIT(KB_RCTRL & 0x1F)) {
425 map_tmp.bitfield |= BIT(DC_KB_RCTRL);
426 }
427 if (ctrl_data->map_mask[3] & BIT(KB_RSHIFT & 0x1F) && ctrl_data->btns[3].value & BIT(KB_RSHIFT & 0x1F)) {
428 map_tmp.bitfield |= BIT(DC_KB_RSHIFT);
429 }
430 if (ctrl_data->map_mask[3] & BIT(KB_RALT & 0x1F) && ctrl_data->btns[3].value & BIT(KB_RALT & 0x1F)) {
431 map_tmp.bitfield |= BIT(DC_KB_RALT);
432 }
433 if (ctrl_data->map_mask[3] & BIT(KB_RWIN & 0x1F) && ctrl_data->btns[3].value & BIT(KB_RWIN & 0x1F)) {
434 map_tmp.bitfield |= BIT(DC_KB_RWIN);
435 }
436
437 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp));
438 }
439
440 void dc_from_generic(int32_t dev_mode, struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
441 switch (dev_mode) {
442 case DEV_KB:
443 dc_kb_from_generic(ctrl_data, wired_data);
444 break;
445 case DEV_MOUSE:
446 dc_mouse_from_generic(ctrl_data, wired_data);
447 break;
448 case DEV_PAD:
449 default:
450 dc_ctrl_from_generic(ctrl_data, wired_data);
451 break;
452 }
453 }
454
455 void dc_fb_to_generic(int32_t dev_mode, struct raw_fb *raw_fb_data, struct generic_fb *fb_data) {
456 struct dc_timeout *dc_to = (struct dc_timeout *)&raw_fb_data->data[0];
457 struct dc_vibration *dc_fb = (struct dc_vibration *)&raw_fb_data->data[4];
458
459 // printf("%s unit: %d, cont: %d, conv: %d, exha: %d, pwr_p: %d, pwr_n: %d, freq: %d, inc: %d\n",
460 // __FUNCTION__, dc_fb->unit, dc_fb->continuous, dc_fb->convergence, dc_fb->exhalation,
461 // dc_fb->pwr_p, dc_fb->pwr_n, dc_fb->freq, dc_fb->incline);
462 // printf("timeout: %d mask: %d\n", dc_to->unit1_timeout, dc_to->unit_mask);
463
464 fb_data->wired_id = raw_fb_data->header.wired_id;
465 fb_data->type = raw_fb_data->header.type;
466
467 /* Always stop current timer when we get new fb data */
468 adapter_fb_stop_timer_stop(raw_fb_data->header.wired_id);
469
470 /* This stop rumble when BR timeout trigger */
471 if (raw_fb_data->header.data_len == 0) {
472 fb_data->state = 0;
473 fb_data->lf_pwr = fb_data->hf_pwr = 0;
474 }
475 else {
476 uint32_t timeout_us = (dc_to->unit1_timeout + 1) * DC_TIMEOUT_TO_US;
477 /* pwr is either positive or negative, never both */
478 uint8_t pwr = dc_fb->pwr_p | dc_fb->pwr_n;
479
480 if (pwr) {
481 if (!dc_fb->continuous) {
482 timeout_us = DC_FREQ_TO_US / (dc_fb->freq + 1);
483 }
484 fb_data->state = 1;
485 fb_data->lf_pwr = fb_data->hf_pwr = pwr * (255.0 / 7.0);
486
487 adapter_fb_stop_timer_start(raw_fb_data->header.wired_id, timeout_us);
488 }
489 else {
490 fb_data->state = 0;
491 fb_data->lf_pwr = fb_data->hf_pwr = 0;
492 }
493 }
494 }
495
496 void IRAM_ATTR dc_gen_turbo_mask(struct wired_data *wired_data) {
497 struct dc_map *map_mask = (struct dc_map *)wired_data->output_mask;
498
499 map_mask->triggers = 0xFFFF;
500 map_mask->buttons = 0x0000;
501 map_mask->sticks = 0x00000000;
502
503 wired_gen_turbo_mask_btns16_neg(wired_data, &map_mask->buttons, dc_btns_mask);
504 wired_gen_turbo_mask_axes8(wired_data, map_mask->axes, ADAPTER_MAX_AXES, dc_axes_idx, dc_axes_meta);
505 }
506