GCC Code Coverage Report


Directory: main/
File: adapter/wired/real.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 0 152 0.0%
Functions: 0 8 0.0%
Branches: 0 65 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 "real.h"
15
16 enum {
17 REAL_A = 0,
18 REAL_LD_LEFT,
19 REAL_LD_RIGHT,
20 REAL_LD_UP,
21 REAL_LD_DOWN,
22 REAL_M_RIGHT,
23 REAL_M_MIDDLE,
24 REAL_M_LEFT,
25 REAL_L = 10,
26 REAL_R,
27 REAL_X,
28 REAL_P,
29 REAL_C,
30 REAL_B,
31 };
32
33 enum {
34 REAL_FS_LD_LEFT = 0,
35 REAL_FS_LD_RIGHT,
36 REAL_FS_LD_DOWN,
37 REAL_FS_LD_UP,
38 REAL_FS_C,
39 REAL_FS_B,
40 REAL_FS_A,
41 REAL_FS_T,
42 REAL_FS_R = 12,
43 REAL_FS_L,
44 REAL_FS_X,
45 REAL_FS_P,
46 };
47
48 static DRAM_ATTR const uint8_t real_mouse_axes_idx[ADAPTER_MAX_AXES] =
49 {
50 /* AXIS_LX, AXIS_LY, AXIS_RX, AXIS_RY, TRIG_L, TRIG_R */
51 1, 0, 1, 0, 1, 0
52 };
53
54 static DRAM_ATTR const struct ctrl_meta real_fs_axes_meta[ADAPTER_MAX_AXES] =
55 {
56 {.size_min = -512, .size_max = 511, .neutral = 512, .abs_max = 511, .abs_min = 512},
57 {.size_min = -512, .size_max = 511, .neutral = 512, .abs_max = 511, .abs_min = 512, .polarity = 1},
58 {.size_min = -512, .size_max = 511, .neutral = 512, .abs_max = 511, .abs_min = 512}, //NA
59 {.size_min = -512, .size_max = 511, .neutral = 512, .abs_max = 511, .abs_min = 512, .polarity = 1},
60 {.size_min = 0, .size_max = 255, .neutral = 0x00, .abs_max = 0xFF, .abs_min = 0}, //NA
61 {.size_min = 0, .size_max = 255, .neutral = 0x00, .abs_max = 0xFF, .abs_min = 0}, //NA
62 };
63
64 static DRAM_ATTR const struct ctrl_meta real_mouse_axes_meta[ADAPTER_MAX_AXES] =
65 {
66 {.size_min = -512, .size_max = 511, .neutral = 0x00, .abs_max = 511, .abs_min = 512},
67 {.size_min = -512, .size_max = 511, .neutral = 0x00, .abs_max = 511, .abs_min = 512, .polarity = 1},
68 {.size_min = -512, .size_max = 511, .neutral = 0x00, .abs_max = 511, .abs_min = 512},
69 {.size_min = -512, .size_max = 511, .neutral = 0x00, .abs_max = 511, .abs_min = 512, .polarity = 1},
70 {.size_min = -512, .size_max = 511, .neutral = 0x00, .abs_max = 511, .abs_min = 512},
71 {.size_min = -512, .size_max = 511, .neutral = 0x00, .abs_max = 511, .abs_min = 512},
72 };
73
74 struct real_map {
75 uint16_t buttons;
76 } __packed;
77
78 struct real_fs_map {
79 uint8_t ids[3];
80 uint8_t axes[4];
81 uint16_t buttons;
82 } __packed;
83
84 struct real_mouse_map {
85 uint8_t id;
86 uint8_t buttons;
87 uint8_t relative[2];
88 int32_t raw_axes[2];
89 } __packed;
90
91 static const uint32_t real_mask[4] = {0x33770F00, 0x00000000, 0x00000000, BR_COMBO_MASK};
92 static const uint32_t real_desc[4] = {0x00000000, 0x00000000, 0x00000000, 0x00000000};
93 static DRAM_ATTR const uint32_t real_btns_mask[32] = {
94 0, 0, 0, 0,
95 0, 0, 0, 0,
96 BIT(REAL_LD_LEFT), BIT(REAL_LD_RIGHT), BIT(REAL_LD_DOWN), BIT(REAL_LD_UP),
97 0, 0, 0, 0,
98 BIT(REAL_A), BIT(REAL_C), BIT(REAL_B), 0,
99 BIT(REAL_P), BIT(REAL_X), 0, 0,
100 BIT(REAL_L), BIT(REAL_L), 0, 0,
101 BIT(REAL_R), BIT(REAL_R), 0, 0,
102 };
103
104 static const uint32_t real_fs_mask[4] = {0x337F0FCF, 0x00000000, 0x00000000, BR_COMBO_MASK};
105 static const uint32_t real_fs_desc[4] = {0x000000CF, 0x00000000, 0x00000000, 0x00000000};
106 static DRAM_ATTR const uint32_t real_fs_btns_mask[32] = {
107 0, 0, 0, 0,
108 0, 0, 0, 0,
109 BIT(REAL_FS_LD_LEFT), BIT(REAL_FS_LD_RIGHT), BIT(REAL_FS_LD_DOWN), BIT(REAL_FS_LD_UP),
110 0, 0, 0, 0,
111 BIT(REAL_FS_A), BIT(REAL_FS_C), BIT(REAL_FS_B), BIT(REAL_FS_T),
112 BIT(REAL_FS_P), BIT(REAL_FS_X), 0, 0,
113 BIT(REAL_FS_L), BIT(REAL_FS_L), 0, 0,
114 BIT(REAL_FS_R), BIT(REAL_FS_R), 0, 0,
115 };
116
117 static const uint32_t real_mouse_mask[4] = {0x190000F0, 0x00000000, 0x00000000, BR_COMBO_MASK};
118 static const uint32_t real_mouse_desc[4] = {0x000000F0, 0x00000000, 0x00000000, 0x00000000};
119 static const uint32_t real_mouse_btns_mask[32] = {
120 0, 0, 0, 0,
121 0, 0, 0, 0,
122 0, 0, 0, 0,
123 0, 0, 0, 0,
124 0, 0, 0, 0,
125 0, 0, 0, 0,
126 BIT(REAL_M_RIGHT), 0, 0, BIT(REAL_M_MIDDLE),
127 BIT(REAL_M_LEFT), 0, 0, 0,
128 };
129
130 static void real_ctrl_special_action(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
131 /* Output config mode toggle GamePad/GamePadAlt */
132 if (ctrl_data->map_mask[0] & generic_btns_mask[PAD_MT]) {
133 if (ctrl_data->btns[0].value & generic_btns_mask[PAD_MT]) {
134 if (!atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
135 atomic_set_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
136 }
137 }
138 else {
139 if (atomic_test_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE)) {
140 atomic_clear_bit(&wired_data->flags, WIRED_WAITING_FOR_RELEASE);
141
142 config.out_cfg[ctrl_data->index].dev_mode &= 0x01;
143 config.out_cfg[ctrl_data->index].dev_mode ^= 0x01;
144 sys_mgr_cmd(SYS_MGR_CMD_WIRED_RST);
145 }
146 }
147 }
148 }
149
150 void IRAM_ATTR real_init_buffer(int32_t dev_mode, struct wired_data *wired_data) {
151 switch (dev_mode) {
152 case DEV_MOUSE:
153 {
154 struct real_mouse_map *map = (struct real_mouse_map *)wired_data->output;
155
156 map->id = 0x49;
157 map->buttons = 0x00;
158 for (uint32_t i = 0; i < 2; i++) {
159 map->raw_axes[i] = 0;
160 map->relative[i] = 1;
161 }
162 break;
163 }
164 case DEV_PAD_ALT:
165 {
166 struct real_fs_map *map = (struct real_fs_map *)wired_data->output;
167
168 map->ids[0] = 0x01;
169 map->ids[1] = 0x7B;
170 map->ids[2] = 0x08;
171 map->axes[0] = 0x80;
172 map->axes[1] = 0x20;
173 map->axes[2] = 0x08;
174 map->axes[3] = 0x02;
175 map->buttons = 0x0000;
176 memset(wired_data->output_mask, 0xFF, sizeof(struct real_fs_map));
177 break;
178 }
179 default:
180 {
181 struct real_map *map = (struct real_map *)wired_data->output;
182
183 map->buttons = 0x0080;
184 memset(wired_data->output_mask, 0xFF, sizeof(struct real_map));
185 break;
186 }
187 }
188 }
189
190 void real_meta_init(struct wired_ctrl *ctrl_data) {
191 memset((void *)ctrl_data, 0, sizeof(*ctrl_data)*WIRED_MAX_DEV);
192
193 for (uint32_t i = 0; i < WIRED_MAX_DEV; i++) {
194 for (uint32_t j = 0; j < ADAPTER_MAX_AXES; j++) {
195 switch (config.out_cfg[i].dev_mode) {
196 case DEV_MOUSE:
197 ctrl_data[i].mask = real_mouse_mask;
198 ctrl_data[i].desc = real_mouse_desc;
199 ctrl_data[i].axes[j].meta = &real_mouse_axes_meta[j];
200 break;
201 case DEV_PAD_ALT:
202 ctrl_data[i].mask = real_fs_mask;
203 ctrl_data[i].desc = real_fs_desc;
204 ctrl_data[i].axes[j].meta = &real_fs_axes_meta[j];
205 break;
206 default:
207 ctrl_data[i].mask = real_mask;
208 ctrl_data[i].desc = real_desc;
209 break;
210 }
211 }
212 }
213 }
214
215 void real_ctrl_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
216 struct real_map map_tmp;
217 uint32_t map_mask = 0xFFFF;
218
219 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
220
221 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
222 if (ctrl_data->map_mask[0] & BIT(i)) {
223 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
224 map_tmp.buttons |= real_btns_mask[i];
225 map_mask &= ~real_btns_mask[i];
226 wired_data->cnt_mask[i] = ctrl_data->btns[0].cnt_mask[i];
227 }
228 else if (map_mask & real_btns_mask[i]) {
229 map_tmp.buttons &= ~real_btns_mask[i];
230 wired_data->cnt_mask[i] = 0;
231 }
232 }
233 }
234
235 real_ctrl_special_action(ctrl_data, wired_data);
236
237 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp));
238
239 TESTS_CMDS_LOG("\"wired_output\": {\"btns\": %d},\n", map_tmp.buttons);
240 BT_MON_LOG("\"wired_output\": {\"btns\": %04X},\n", map_tmp.buttons);
241 }
242
243 /* I didn't RE this one my self, base on : */
244 /* https://github.com/libretro/opera-libretro/blob/068c69ff784f2abaea69cdf1b8d3d9d39ac4826e/libopera/opera_pbus.c#L89 */
245 void real_fs_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
246 struct real_fs_map map_tmp;
247 uint32_t map_mask = 0xFFFF;
248
249 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
250
251 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
252 if (ctrl_data->map_mask[0] & BIT(i)) {
253 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
254 map_tmp.buttons |= real_fs_btns_mask[i];
255 map_mask &= ~real_fs_btns_mask[i];
256 wired_data->cnt_mask[i] = ctrl_data->btns[0].cnt_mask[i];
257 }
258 else if (map_mask & real_fs_btns_mask[i]) {
259 map_tmp.buttons &= ~real_fs_btns_mask[i];
260 wired_data->cnt_mask[i] = 0;
261 }
262 }
263 }
264
265 real_ctrl_special_action(ctrl_data, wired_data);
266
267 for (uint32_t i = 0; i < 4; i++) {
268 if (ctrl_data->map_mask[0] & (axis_to_btn_mask(i) & real_fs_desc[0])) {
269 uint16_t tmp = ctrl_data->axes[i].meta->neutral;
270
271 if (ctrl_data->axes[i].value > ctrl_data->axes[i].meta->size_max) {
272 tmp = 1023;
273 }
274 else if (ctrl_data->axes[i].value < ctrl_data->axes[i].meta->size_min) {
275 tmp = 0;
276 }
277 else {
278 tmp = (uint16_t)(ctrl_data->axes[i].value + ctrl_data->axes[i].meta->neutral);
279 }
280
281 switch (i) {
282 case 0:
283 map_tmp.axes[0] = ((tmp & 0x3FC) >> 2);
284 map_tmp.axes[1] &= ~0xC0;
285 map_tmp.axes[1] |= ((tmp & 0x003) << 6);
286 break;
287 case 1:
288 map_tmp.axes[1] &= ~0x3F;
289 map_tmp.axes[1] |= ((tmp & 0x3F0) >> 4);
290 map_tmp.axes[2] &= ~0xF0;
291 map_tmp.axes[2] |= ((tmp & 0x00F) << 4);
292 break;
293 case 3:
294 map_tmp.axes[2] &= ~0x0F;
295 map_tmp.axes[2] |= ((tmp & 0x3C0) >> 6);
296 map_tmp.axes[3] &= ~0xFC;
297 map_tmp.axes[3] |= ((tmp & 0x03F) << 2);
298 break;
299 }
300 }
301 }
302
303 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp));
304
305 #ifdef CONFIG_BLUERETRO_RAW_OUTPUT
306 printf("{\"log_type\": \"wired_output\", \"axes\": [%d, %d, %d, %d], \"btns\": %d}\n",
307 map_tmp.axes[0], map_tmp.axes[1], map_tmp.axes[2], map_tmp.axes[3],
308 map_tmp.buttons);
309 #endif
310 }
311
312 static void real_mouse_from_generic(struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
313 struct real_mouse_map map_tmp;
314 int32_t *raw_axes = (int32_t *)(wired_data->output + 4);
315
316 memcpy((void *)&map_tmp, wired_data->output, sizeof(map_tmp));
317
318 for (uint32_t i = 0; i < ARRAY_SIZE(generic_btns_mask); i++) {
319 if (ctrl_data->map_mask[0] & BIT(i)) {
320 if (ctrl_data->btns[0].value & generic_btns_mask[i]) {
321 map_tmp.buttons |= real_mouse_btns_mask[i];
322 }
323 else {
324 map_tmp.buttons &= ~real_mouse_btns_mask[i];
325 }
326 }
327 }
328
329 for (uint32_t i = 2; i < 4; i++) {
330 if (ctrl_data->map_mask[0] & (axis_to_btn_mask(i) & real_mouse_desc[0])) {
331 if (ctrl_data->axes[i].relative) {
332 map_tmp.relative[real_mouse_axes_idx[i]] = 1;
333 atomic_add(&raw_axes[real_mouse_axes_idx[i]], ctrl_data->axes[i].value);
334 }
335 else {
336 map_tmp.relative[real_mouse_axes_idx[i]] = 0;
337 raw_axes[real_mouse_axes_idx[i]] = ctrl_data->axes[i].value;
338 }
339 }
340 }
341
342 memcpy(wired_data->output, (void *)&map_tmp, sizeof(map_tmp) - 8);
343 }
344
345 void real_from_generic(int32_t dev_mode, struct wired_ctrl *ctrl_data, struct wired_data *wired_data) {
346 switch (dev_mode) {
347 case DEV_MOUSE:
348 real_mouse_from_generic(ctrl_data, wired_data);
349 break;
350 case DEV_PAD_ALT:
351 real_fs_from_generic(ctrl_data, wired_data);
352 break;
353 default:
354 real_ctrl_from_generic(ctrl_data, wired_data);
355 break;
356 }
357 }
358
359 void IRAM_ATTR real_gen_turbo_mask(int32_t dev_mode, struct wired_data *wired_data) {
360 const uint32_t *btns_mask = (dev_mode == DEV_PAD) ? real_btns_mask : real_fs_btns_mask;
361 uint16_t *buttons = (dev_mode == DEV_PAD) ? wired_data->output_mask16 : (uint16_t *)&wired_data->output_mask[7];
362
363 *buttons = 0xFFFF;
364
365 wired_gen_turbo_mask_btns16_pos(wired_data, buttons, btns_mask);
366 }
367