GCC Code Coverage Report


Directory: main/
File: adapter/wireless/ps3.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 29 50 58.0%
Functions: 1 2 50.0%
Branches: 13 23 56.5%

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 "tests/cmds.h"
10 #include "bluetooth/mon.h"
11 #include "ps3.h"
12 #include "bluetooth/hidp/ps3.h"
13
14 enum {
15 PS3_SELECT = 8,
16 PS3_L3,
17 PS3_R3,
18 PS3_START,
19 PS3_D_UP,
20 PS3_D_RIGHT,
21 PS3_D_DOWN,
22 PS3_D_LEFT,
23 PS3_L2,
24 PS3_R2,
25 PS3_L1,
26 PS3_R1,
27 PS3_T,
28 PS3_C,
29 PS3_X,
30 PS3_S,
31 PS3_PS,
32 };
33
34 static const uint8_t led_dev_id_map[] = {
35 0x1, 0x2, 0x4, 0x8, 0x3, 0x6, 0xC
36 };
37
38 static const uint8_t ps3_axes_idx[ADAPTER_PS2_MAX_AXES] =
39 {
40 /* AXIS_LX, AXIS_LY, AXIS_RX, AXIS_RY, TRIG_L, TRIG_R */
41 0, 1, 2, 3, 12, 13,
42 /* TRIG_LS, TRIG_RS, DPAD_L, DPAD_R, DPAD_D, DPAD_U */
43 14, 15, 11, 9, 10, 8,
44 /* BTN_L, BTN_R, BTN_D, BTN_U */
45 19, 17, 18, 16
46 };
47
48 static const struct ctrl_meta ps3_axes_meta[ADAPTER_PS2_MAX_AXES] =
49 {
50 {.neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80},
51 {.neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80, .polarity = 1},
52 {.neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80},
53 {.neutral = 0x80, .abs_max = 0x7F, .abs_min = 0x80, .polarity = 1},
54 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
55 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
56 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
57 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
58 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
59 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
60 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
61 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
62 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
63 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
64 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
65 {.neutral = 0x00, .abs_max = 0xFF, .abs_min = 0x00},
66 };
67
68 struct ps3_map {
69 uint32_t buttons;
70 uint8_t reserved;
71 uint8_t axes[20];
72 } __packed;
73
74 static const uint32_t ps3_mask[4] = {0xBB7F0FFF, 0x00000000, 0x00000000, 0x00000000};
75 static const uint32_t ps3_desc[4] = {0x110000FF, 0x00000000, 0x00000000, 0x00000000};
76 static const uint32_t ps3_pressure_desc[4] = {0x330F0FFF, 0x00000000, 0x00000000, 0x00000000};
77 static const uint32_t ps3_btns_mask[32] = {
78 0, 0, 0, 0,
79 0, 0, 0, 0,
80 BIT(PS3_D_LEFT), BIT(PS3_D_RIGHT), BIT(PS3_D_DOWN), BIT(PS3_D_UP),
81 0, 0, 0, 0,
82 BIT(PS3_S), BIT(PS3_C), BIT(PS3_X), BIT(PS3_T),
83 BIT(PS3_START), BIT(PS3_SELECT), BIT(PS3_PS), 0,
84 0, BIT(PS3_L1), 0, BIT(PS3_L3),
85 0, BIT(PS3_R1), 0, BIT(PS3_R3),
86 };
87
88 24 int32_t ps3_to_generic(struct bt_data *bt_data, struct wireless_ctrl *ctrl_data) {
89 24 uint32_t i = 8;
90 24 uint32_t axes_cnt = ADAPTER_MAX_AXES;
91 24 struct ps3_map *map = (struct ps3_map *)bt_data->base.input;
92 24 struct ctrl_meta *meta = bt_data->raw_src_mappings[PAD].meta;
93
94 24 TESTS_CMDS_LOG("\"wireless_input\": {\"report_id\": %ld, \"axes\": [%u, %u, %u, %u, %u, %u], \"btns\": %lu},\n",
95 bt_data->base.report_id, map->axes[ps3_axes_idx[0]], map->axes[ps3_axes_idx[1]], map->axes[ps3_axes_idx[2]],
96 map->axes[ps3_axes_idx[3]], map->axes[ps3_axes_idx[4]], map->axes[ps3_axes_idx[5]], map->buttons);
97
98 24 memset((void *)ctrl_data, 0, sizeof(*ctrl_data));
99
100 24 ctrl_data->mask = (uint32_t *)ps3_mask;
101 24 ctrl_data->desc = (uint32_t *)ps3_desc;
102
103
1/2
✗ Branch 0 (4→5) not taken.
✓ Branch 1 (4→9) taken 24 times.
24 if (wired_adapter.system_id == PSX || wired_adapter.system_id == PS2) {
104 ctrl_data->desc = (uint32_t *)ps3_pressure_desc;
105 axes_cnt = ADAPTER_PS2_MAX_AXES;
106 i = 20;
107 }
108
109
2/2
✓ Branch 0 (10→6) taken 576 times.
✓ Branch 1 (10→11) taken 24 times.
600 for (; i < ARRAY_SIZE(generic_btns_mask); i++) {
110
2/2
✓ Branch 0 (6→7) taken 30 times.
✓ Branch 1 (6→8) taken 546 times.
576 if (map->buttons & ps3_btns_mask[i]) {
111 30 ctrl_data->btns[0].value |= generic_btns_mask[i];
112 }
113 }
114
115
2/2
✓ Branch 0 (12→13) taken 2 times.
✓ Branch 1 (12→23) taken 22 times.
24 if (!atomic_test_bit(&bt_data->base.flags[PAD], BT_INIT)) {
116 2 memcpy(meta, ps3_axes_meta, sizeof(ps3_axes_meta));
117 2 bt_mon_log(false, "%s: axes_cal: [", __FUNCTION__);
118
2/2
✓ Branch 0 (20→16) taken 32 times.
✓ Branch 1 (20→21) taken 2 times.
34 for (uint32_t i = 0; i < ADAPTER_PS2_MAX_AXES; i++) {
119 32 meta[i].abs_max *= MAX_PULL_BACK;
120 32 meta[i].abs_min *= MAX_PULL_BACK;
121 32 bt_data->base.axes_cal[i] = -(map->axes[ps3_axes_idx[i]] - ps3_axes_meta[i].neutral);
122
2/2
✓ Branch 0 (16→17) taken 30 times.
✓ Branch 1 (16→18) taken 2 times.
32 if (i) {
123 30 bt_mon_log(false, ", ");
124 }
125 32 bt_mon_log(false, "%d", bt_data->base.axes_cal[i]);
126 }
127 2 atomic_set_bit(&bt_data->base.flags[PAD], BT_INIT);
128 2 bt_mon_log(true, "]");
129 }
130
131
2/2
✓ Branch 0 (25→24) taken 144 times.
✓ Branch 1 (25→26) taken 24 times.
168 for (i = 0; i < axes_cnt; i++) {
132 144 ctrl_data->axes[i].meta = &meta[i];
133 144 ctrl_data->axes[i].value = map->axes[ps3_axes_idx[i]] - ps3_axes_meta[i].neutral + bt_data->base.axes_cal[i];
134 }
135
136 24 return 0;
137 }
138
139 bool ps3_fb_from_generic(struct generic_fb *fb_data, struct bt_data *bt_data) {
140 struct bt_hidp_ps3_set_conf *set_conf = (struct bt_hidp_ps3_set_conf *)bt_data->base.output;
141 bool ret = true;
142
143 switch (fb_data->type) {
144 case FB_TYPE_RUMBLE:
145 if (fb_data->state) {
146 set_conf->hf_lf_motors_enable = 0x01;
147
148 set_conf->lf_motor_pwr = fb_data->lf_pwr;
149 set_conf->lf_motor_len = (fb_data->lf_pwr) ? 0xFF : 0x00;
150
151 set_conf->hf_motor_len = (fb_data->hf_pwr > 128) ? 0xFF : 0x00;
152 }
153 else {
154 set_conf->hf_lf_motors_enable = 0x00;
155
156 set_conf->lf_motor_pwr = 0x00;
157 set_conf->lf_motor_len = 0x00;
158
159 set_conf->hf_motor_len = 0x00;
160 }
161 break;
162 case FB_TYPE_PLAYER_LED:
163 set_conf->leds = (led_dev_id_map[bt_data->base.pids->out_idx] << 1);
164 break;
165 }
166 return ret;
167 }
168