| 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 |