GCC Code Coverage Report


Directory: main/
File: bluetooth/hidp/ps.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 92 131 70.2%
Functions: 6 7 85.7%
Branches: 16 42 38.1%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2019-2024, Jacques Gagnon
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <stdio.h>
7 #include <esp32/rom/crc.h>
8 #include <esp_timer.h>
9 #include "adapter/adapter.h"
10 #include "adapter/config.h"
11 #include "bluetooth/host.h"
12 #include "ps.h"
13
14 static void bt_hid_cmd_ps5_set_conf(struct bt_dev *device, void *report);
15
16 10 static void bt_hid_cmd_ps4_set_conf(struct bt_dev *device, void *report) {
17 10 struct bt_hidp_ps4_set_conf *set_conf = (struct bt_hidp_ps4_set_conf *)bt_hci_pkt_tmp.hidp_data;
18
19 10 bt_hci_pkt_tmp.hidp_hdr.hdr = BT_HIDP_DATA_OUT;
20 10 bt_hci_pkt_tmp.hidp_hdr.protocol = BT_HIDP_PS4_SET_CONF;
21
22 10 memcpy((void *)set_conf, report, sizeof(*set_conf));
23
24 10 set_conf->crc = crc32_le((uint32_t)~0xFFFFFFFF, (void *)&bt_hci_pkt_tmp.hidp_hdr,
25 sizeof(bt_hci_pkt_tmp.hidp_hdr) + sizeof(*set_conf) - sizeof(set_conf->crc));
26
27 10 bt_hid_cmd(device->acl_handle, device->intr_chan.dcid, BT_HIDP_DATA_OUT, BT_HIDP_PS4_SET_CONF, sizeof(*set_conf));
28 10 }
29
30 static void bt_hid_cmd_ps5_trigger_init(struct bt_dev *device) {
31 int32_t perc_threshold_l = -1;
32 int32_t perc_threshold_r = -1;
33 int32_t dev = device->ids.id;
34 uint32_t map_cnt_l = 0;
35 uint32_t map_cnt_r = 0;
36
37 if (wired_adapter.system_id == WIRED_AUTO) {
38 /* Can't configure feature if target system is unknown */
39 return;
40 }
41
42 printf("# %s\n", __FUNCTION__);
43
44 /* Make sure meta desc is init */
45 adapter_meta_init();
46
47 /* Go through the list of mappings, looking for PAD_RM and PAD_LM */
48 for (uint32_t i = 0; i < config.in_cfg[dev].map_size; i++) {
49 if (config.in_cfg[dev].map_cfg[i].dst_btn < BR_COMBO_BASE_1) {
50 uint8_t is_axis = btn_is_axis(config.in_cfg[dev].map_cfg[i].dst_id, config.in_cfg[dev].map_cfg[i].dst_btn);
51 if (config.in_cfg[dev].map_cfg[i].src_btn == PAD_RM) {
52 map_cnt_r++;
53 if (is_axis) {
54 continue;
55 }
56 if (config.in_cfg[dev].map_cfg[i].perc_threshold > perc_threshold_r) {
57 perc_threshold_r = config.in_cfg[dev].map_cfg[i].perc_threshold;
58 }
59 }
60 else if (config.in_cfg[dev].map_cfg[i].src_btn == PAD_LM) {
61 map_cnt_l++;
62 if (is_axis) {
63 continue;
64 }
65 if (config.in_cfg[dev].map_cfg[i].perc_threshold > perc_threshold_l) {
66 perc_threshold_l = config.in_cfg[dev].map_cfg[i].perc_threshold;
67 }
68 }
69 }
70 }
71 /* If only one mapping exist do not set resistance */
72 if (map_cnt_r < 2) {
73 perc_threshold_r = -1;
74 }
75 if (map_cnt_l < 2) {
76 perc_threshold_l = -1;
77 }
78
79 uint8_t r2_start_resistance_value = (perc_threshold_r * 255) / 100;
80 uint8_t l2_start_resistance_value = (perc_threshold_l * 255) / 100;
81
82 uint8_t r2_trigger_start_resistance = (uint8_t)(0x94 * (r2_start_resistance_value / 255.0));
83 uint8_t r2_trigger_effect_force =
84 (uint8_t)((0xb4 - r2_trigger_start_resistance) * (r2_start_resistance_value / 255.0) + r2_trigger_start_resistance);
85
86 uint8_t l2_trigger_start_resistance = (uint8_t)(0x94 * (l2_start_resistance_value / 255.0));
87 uint8_t l2_trigger_effect_force =
88 (uint8_t)((0xb4 - l2_trigger_start_resistance) * (l2_start_resistance_value / 255.0) + l2_trigger_start_resistance);
89
90 struct bt_hidp_ps5_set_conf ps5_set_conf = {
91 .conf0 = 0x02,
92 .cmd = 0x0c,
93 .r2_trigger_motor_mode = perc_threshold_r > -1 ? 0x02 : 0x00,
94 .r2_trigger_start_resistance = r2_trigger_start_resistance,
95 .r2_trigger_effect_force = r2_trigger_effect_force,
96 .r2_trigger_range_force = 0xff,
97 .r2_trigger_near_release_str = 0x00,
98 .r2_trigger_near_middle_str = 0x00,
99 .r2_trigger_pressed_str = 0x00,
100 .r2_trigger_actuation_freq = 0x00,
101 .l2_trigger_motor_mode = perc_threshold_l > -1 ? 0x02 : 0x00,
102 .l2_trigger_start_resistance = l2_trigger_start_resistance,
103 .l2_trigger_effect_force = l2_trigger_effect_force,
104 .l2_trigger_range_force = 0xff,
105 .l2_trigger_near_release_str = 0x00,
106 .l2_trigger_near_middle_str = 0x00,
107 .l2_trigger_pressed_str = 0x00,
108 .l2_trigger_actuation_freq = 0x00,
109 };
110
111 bt_hid_cmd_ps5_set_conf(device, (void *)&ps5_set_conf);
112 }
113
114 12 static void bt_hid_ps5_init_callback(void *arg) {
115 12 struct bt_dev *device = (struct bt_dev *)arg;
116
117
1/2
✓ Branch 0 (2→3) taken 12 times.
✗ Branch 1 (2→10) not taken.
12 if (device->ids.report_type != BT_HIDP_PS4_STATUS) {
118 12 struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
119 12 struct bt_hidp_ps5_set_conf *set_conf = (struct bt_hidp_ps5_set_conf *)bt_data->base.output;
120
121 /* Init output data for Rumble/LED feedback */
122 12 memset(set_conf, 0x00, sizeof(*set_conf));
123 12 set_conf->conf0 = 0x02;
124 12 set_conf->cmd = 0x03;
125 12 set_conf->conf1 = 0x04;
126 12 set_conf->leds = hw_config.ps_ctrl_colors[device->ids.out_idx];
127
128 12 struct bt_hidp_ps5_set_conf ps5_clear_led = {
129 .conf0 = 0x02,
130 .conf1 = 0x08,
131 };
132 12 struct bt_hidp_ps5_set_conf ps5_set_led = {
133 .conf0 = 0x02,
134 .conf1 = 0x04,
135 };
136 12 ps5_set_led.leds = hw_config.ps_ctrl_colors[device->ids.out_idx];
137 12 printf("# %s\n", __FUNCTION__);
138
139 12 bt_hid_cmd_ps5_set_conf(device, (void *)&ps5_clear_led);
140 12 bt_hid_cmd_ps5_set_conf(device, (void *)&ps5_set_led);
141
142 /* Set trigger "click" haptic effect when rumble is on */
143 12 if (config.out_cfg[device->ids.out_idx].acc_mode == ACC_RUMBLE
144
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→9) taken 12 times.
12 || config.out_cfg[device->ids.out_idx].acc_mode == ACC_BOTH) {
145 bt_hid_cmd_ps5_trigger_init(device);
146 }
147 }
148
149 12 esp_timer_delete(device->timer_hdl);
150 12 device->timer_hdl = NULL;
151
152 12 atomic_set_bit(&device->flags, BT_DEV_HID_INIT_DONE);
153 12 printf("# PS init done\n");
154 12 }
155
156 25 static void bt_hid_cmd_ps5_set_conf(struct bt_dev *device, void *report) {
157 25 struct bt_hidp_ps5_set_conf *set_conf = (struct bt_hidp_ps5_set_conf *)bt_hci_pkt_tmp.hidp_data;
158
159 25 bt_hci_pkt_tmp.hidp_hdr.hdr = BT_HIDP_DATA_OUT;
160 25 bt_hci_pkt_tmp.hidp_hdr.protocol = BT_HIDP_PS5_SET_CONF;
161
162 25 memcpy((void *)set_conf, report, sizeof(*set_conf));
163
164 25 set_conf->crc = crc32_le((uint32_t)~0xFFFFFFFF, (void *)&bt_hci_pkt_tmp.hidp_hdr,
165 sizeof(bt_hci_pkt_tmp.hidp_hdr) + sizeof(*set_conf) - sizeof(set_conf->crc));
166
167 25 bt_hid_cmd(device->acl_handle, device->intr_chan.dcid, BT_HIDP_DATA_OUT, BT_HIDP_PS5_SET_CONF, sizeof(*set_conf));
168 25 }
169
170 3 void bt_hid_cmd_ps_set_conf(struct bt_dev *device, void *report) {
171
2/2
✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→5) taken 2 times.
3 switch (device->ids.subtype) {
172 1 case BT_PS5_DS:
173 1 bt_hid_cmd_ps5_set_conf(device, report);
174 1 break;
175 2 default:
176 2 bt_hid_cmd_ps4_set_conf(device, report);
177 2 break;
178 }
179 3 }
180
181 12 void bt_hid_ps_init(struct bt_dev *device) {
182 #ifndef CONFIG_BLUERETRO_TEST_FALLBACK_REPORT
183 12 struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
184 12 struct bt_hidp_ps4_set_conf *set_conf = (struct bt_hidp_ps4_set_conf *)bt_data->base.output;
185
186 /* Init output data for Rumble/LED feedback */
187 12 set_conf->conf0 = 0xc4;
188 12 set_conf->conf1 = 0x03;
189 12 set_conf->leds = hw_config.ps_ctrl_colors[bt_data->base.pids->out_idx];
190
191
2/2
✓ Branch 0 (2→3) taken 4 times.
✓ Branch 1 (2→5) taken 8 times.
12 switch (device->ids.subtype) {
192 4 case BT_PS5_DS:
193 4 bt_hid_ps5_init_callback((void *)device);
194 4 break;
195 8 default:
196 {
197 8 const esp_timer_create_args_t ps5_timer_args = {
198 .callback = &bt_hid_ps5_init_callback,
199 .arg = (void *)device,
200 .name = "ps5_init_timer"
201 };
202 8 struct bt_hidp_ps4_set_conf ps4_set_conf = {
203 .conf0 = 0xc0,
204 .conf1 = 0x07,
205 };
206 8 ps4_set_conf.leds = hw_config.ps_ctrl_colors[device->ids.out_idx];
207
208 8 printf("# %s\n", __FUNCTION__);
209
210 8 esp_timer_create(&ps5_timer_args, (esp_timer_handle_t *)&device->timer_hdl);
211 8 esp_timer_start_once(device->timer_hdl, 1000000);
212 8 bt_hid_cmd_ps4_set_conf(device, (void *)&ps4_set_conf);
213 8 break;
214 }
215 }
216 #endif
217 12 }
218
219 254 void bt_hid_ps_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint32_t len) {
220 254 uint32_t hidp_data_len = len - (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE
221 + sizeof(struct bt_l2cap_hdr) + sizeof(struct bt_hidp_hdr));
222
223
1/2
✓ Branch 0 (2→3) taken 254 times.
✗ Branch 1 (2→19) not taken.
254 switch (bt_hci_acl_pkt->sig_hdr.code) {
224 254 case BT_HIDP_DATA_IN:
225
3/4
✓ Branch 0 (3→4) taken 123 times.
✓ Branch 1 (3→9) taken 41 times.
✓ Branch 2 (3→14) taken 90 times.
✗ Branch 3 (3→19) not taken.
254 switch (bt_hci_acl_pkt->hidp_hdr.protocol) {
226 123 case BT_HIDP_HID_STATUS:
227
2/2
✓ Branch 0 (4→5) taken 6 times.
✓ Branch 1 (4→7) taken 117 times.
123 if (device->ids.report_type != BT_HIDP_HID_STATUS) {
228 6 bt_type_update(device->ids.id, BT_PS, BT_SUBTYPE_DEFAULT);
229 6 device->ids.report_type = BT_HIDP_HID_STATUS;
230 }
231 123 bt_host_bridge(device, bt_hci_acl_pkt->hidp_hdr.protocol, bt_hci_acl_pkt->hidp_data, hidp_data_len);
232 123 break;
233 41 case BT_HIDP_PS4_STATUS:
234
2/2
✓ Branch 0 (9→10) taken 2 times.
✓ Branch 1 (9→12) taken 39 times.
41 if (device->ids.report_type != BT_HIDP_PS4_STATUS) {
235 2 bt_type_update(device->ids.id, BT_PS, BT_SUBTYPE_DEFAULT);
236 2 device->ids.report_type = BT_HIDP_PS4_STATUS;
237 }
238 #ifdef CONFIG_BLUERETRO_ADAPTER_RUMBLE_TEST
239 struct bt_hidp_ps4_set_conf rumble4 = {
240 .conf0 = 0xc4,
241 .conf1 = 0x03,
242 };
243 rumble4.r_rumble = bt_hci_acl_pkt->hidp_data[10];
244 rumble4.l_rumble = bt_hci_acl_pkt->hidp_data[9];
245 bt_hid_cmd_ps4_set_conf(device, &rumble4);
246 #else
247 41 bt_host_bridge(device, bt_hci_acl_pkt->hidp_hdr.protocol, bt_hci_acl_pkt->hidp_data, hidp_data_len);
248 #endif
249 41 break;
250 90 case BT_HIDP_PS5_STATUS:
251
2/2
✓ Branch 0 (14→15) taken 8 times.
✓ Branch 1 (14→17) taken 82 times.
90 if (device->ids.report_type != BT_HIDP_PS5_STATUS) {
252 8 bt_type_update(device->ids.id, BT_PS, BT_PS5_DS);
253 8 device->ids.report_type = BT_HIDP_PS5_STATUS;
254 }
255 #ifdef CONFIG_BLUERETRO_ADAPTER_RUMBLE_TEST
256 struct bt_hidp_ps5_set_conf rumble = {
257 .conf0 = 0x02,
258 .cmd = 0x03,
259 };
260 rumble.r_rumble = bt_hci_acl_pkt->hidp_data[6];
261 rumble.l_rumble = bt_hci_acl_pkt->hidp_data[5];
262 bt_hid_cmd_ps5_set_conf(device, &rumble);
263 #else
264 90 bt_host_bridge(device, bt_hci_acl_pkt->hidp_hdr.protocol, bt_hci_acl_pkt->hidp_data, hidp_data_len);
265 #endif
266 90 break;
267 }
268 break;
269 }
270 254 }
271