Skip to content
This repository was archived by the owner on Dec 14, 2025. It is now read-only.

Commit f9461fa

Browse files
committed
[BT] Support Switch 2 ctrls reconnection & cleanup
1 parent b00bd1e commit f9461fa

7 files changed

Lines changed: 450 additions & 66 deletions

File tree

main/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ set(cov_srcs
4848
"bluetooth/hidp/wii.c"
4949
"bluetooth/hidp/ps.c"
5050
"bluetooth/hidp/sw.c"
51+
"bluetooth/hidp/sw2.c"
5152
"system/manager.c"
5253
"tools/devcrypto.c"
5354
"tools/ps1_gameid.c"

main/bluetooth/att_hid.c

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "zephyr/gatt.h"
1616
#include "adapter/hid_parser.h"
1717
#include "adapter/mapping_quirks.h"
18+
#include "hidp/sw2.h"
1819

1920
enum {
2021
BT_ATT_HID_DEVICE_NAME = 0,
@@ -471,9 +472,14 @@ static void bt_att_hid_process_current_state(struct bt_dev *device,
471472

472473
static void bt_att_hid_start_next_state(struct bt_dev *device,
473474
struct bt_att_hid *hid_data) {
474-
device->hid_state++;
475-
if (device->hid_state < BT_ATT_HID_STATE_MAX && start_state_func[device->hid_state]) {
476-
start_state_func[device->hid_state](device, hid_data);
475+
if (device->ids.type == BT_SW2 && !atomic_test_bit(&device->flags, BT_DEV_HID_INIT_DONE)) {
476+
bt_hid_sw2_init(device);
477+
}
478+
else {
479+
device->hid_state++;
480+
if (device->hid_state < BT_ATT_HID_STATE_MAX && start_state_func[device->hid_state]) {
481+
start_state_func[device->hid_state](device, hid_data);
482+
}
477483
}
478484
}
479485

@@ -487,9 +493,14 @@ static int32_t bt_att_get_report_index(struct bt_att_hid *hid_data, uint8_t repo
487493
}
488494

489495
void bt_att_hid_init(struct bt_dev *device) {
490-
struct bt_att_hid *hid_data = &att_hid[device->ids.id];
491-
memset((uint8_t *)hid_data, 0, sizeof(*hid_data));
492-
bt_att_cmd_mtu_req(device->acl_handle, bt_att_get_le_max_mtu());
496+
if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_PENDING)) {
497+
struct bt_att_hid *hid_data = &att_hid[device->ids.id];
498+
499+
atomic_set_bit(&device->flags, BT_DEV_HID_INTR_PENDING);
500+
501+
memset((uint8_t *)hid_data, 0, sizeof(*hid_data));
502+
bt_att_cmd_mtu_req(device->acl_handle, bt_att_get_le_max_mtu());
503+
}
493504
}
494505

495506
void bt_att_write_hid_report(struct bt_dev *device, uint8_t report_id, uint8_t *data, uint32_t len) {
@@ -530,19 +541,7 @@ void bt_att_hid_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, u
530541
if (!atomic_test_bit(&device->flags, BT_DEV_HID_INTR_READY)) {
531542
bt_hci_stop_inquiry();
532543

533-
if (device->ids.type == BT_SW2) {
534-
uint16_t data = BT_GATT_CCC_NOTIFY;
535-
uint8_t led[16] = {
536-
0x09, 0x91, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00,
537-
bt_hid_led_dev_id_map[device->ids.out_idx],
538-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
539-
bt_att_cmd_write_req(device->acl_handle, 0x001b, (uint8_t *)&data, sizeof(data));
540-
bt_att_cmd_write_cmd(device->acl_handle, 0x0014, (uint8_t *)&led, sizeof(led));
541-
bt_att_cmd_write_req(device->acl_handle, 0x000b, (uint8_t *)&data, sizeof(data));
542-
}
543-
else {
544-
bt_att_hid_start_first_state(device, hid_data);
545-
}
544+
bt_att_hid_start_first_state(device, hid_data);
546545
}
547546
break;
548547
}
@@ -675,27 +674,18 @@ void bt_att_hid_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, u
675674
{
676675
struct bt_att_notify *notify = (struct bt_att_notify *)bt_hci_acl_pkt->att_data;
677676

678-
if (device->ids.type == BT_SW2) {
679-
bt_host_bridge(device, 1, notify->value, att_len - sizeof(notify->handle));
680-
}
681-
else {
682-
for (uint32_t i = 0; i < HID_MAX_REPORT; i++) {
683-
if (notify->handle == hid_data->reports[i].report_hdl) {
684-
#ifdef CONFIG_BLUERETRO_ADAPTER_RUMBLE_TEST
685-
struct bt_hidp_xb1_rumble rumble = {
686-
.enable = 0x03,
687-
.duration = 0xFF,
688-
.cnt = 0x00,
689-
};
690-
rumble.mag_r = bt_hci_acl_pkt->hidp_data[11];
691-
rumble.mag_l = bt_hci_acl_pkt->hidp_data[9];
692-
bt_hid_cmd_xbox_rumble(device, &rumble);
693-
#else
694-
bt_host_bridge(device, hid_data->reports[i].id, notify->value, att_len - sizeof(notify->handle));
695-
#endif
696-
break;
677+
switch (device->ids.type) {
678+
case BT_SW2:
679+
bt_hid_sw2_hdlr(device, notify->handle, notify->value, att_len - sizeof(notify->handle));
680+
break;
681+
default:
682+
for (uint32_t i = 0; i < HID_MAX_REPORT; i++) {
683+
if (notify->handle == hid_data->reports[i].report_hdl) {
684+
bt_host_bridge(device, hid_data->reports[i].id, notify->value, att_len - sizeof(notify->handle));
685+
break;
686+
}
697687
}
698-
}
688+
break;
699689
}
700690
break;
701691
}

main/bluetooth/hci.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,6 @@ static void bt_hci_le_meta_evt_hdlr(struct bt_hci_pkt *bt_hci_evt_pkt) {
10921092
uint8_t *end = data + le_adv_report->adv_info[0].length;
10931093
uint8_t len, type;
10941094
uint16_t value;
1095-
bool sw2 = false;
10961095

10971096
printf("# BT_HCI_EVT_LE_ADVERTISING_REPORT\n");
10981097

@@ -1124,7 +1123,6 @@ static void bt_hci_le_meta_evt_hdlr(struct bt_hci_pkt *bt_hci_evt_pkt) {
11241123
/* Manufacturer Specific Data */
11251124
value = *(uint16_t *)&data[1];
11261125
if (value == 0x0553) {
1127-
sw2 = true;
11281126
goto connect;
11291127
}
11301128
break;
@@ -1140,15 +1138,6 @@ static void bt_hci_le_meta_evt_hdlr(struct bt_hci_pkt *bt_hci_evt_pkt) {
11401138
bt_host_reset_dev(device);
11411139
memcpy((uint8_t *)&device->le_remote_bdaddr, (uint8_t *)&le_adv_report->adv_info[0].addr, sizeof(device->le_remote_bdaddr));
11421140
device->ids.type = BT_HID_GENERIC;
1143-
if (sw2) {
1144-
device->ids.type = BT_SW2;
1145-
struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
1146-
if (data) {
1147-
bt_data->base.vid = *(uint16_t *)&data[6];
1148-
bt_data->base.pid = *(uint16_t *)&data[8];
1149-
printf("%s: VID: 0x%04X PID: 0x%04X\n", __FUNCTION__, bt_data->base.vid, bt_data->base.pid);
1150-
}
1151-
}
11521141
bt_l2cap_init_dev_scid(device);
11531142
atomic_set_bit(&device->flags, BT_DEV_DEVICE_FOUND);
11541143
bt_hci_cmd_le_set_scan_enable(0);

main/bluetooth/hidp/hidp.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019-2023, Jacques Gagnon
2+
* Copyright (c) 2019-2025, Jacques Gagnon
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

@@ -11,6 +11,7 @@
1111
#include "wii.h"
1212
#include "ps.h"
1313
#include "sw.h"
14+
#include "sw2.h"
1415

1516
typedef void (*bt_hid_init_t)(struct bt_dev *device);
1617
typedef void (*bt_hid_hdlr_t)(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint32_t len);
@@ -52,6 +53,7 @@ static const struct bt_name_type bt_name_type[] = {
5253
{"BlueN64 Gamepad", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_BLUEN64_N64)},
5354
{"Hyperkin Pad", BT_SW, BT_SW_HYPERKIN_ADMIRAL, 0},
5455
{"OUYA Game Controller", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_OUYA)},
56+
{"DeviceName", BT_SW2, BT_SUBTYPE_DEFAULT, 0},
5557
#endif
5658
};
5759

@@ -61,6 +63,7 @@ static const bt_hid_init_t bt_hid_init_list[BT_TYPE_MAX] = {
6163
bt_hid_wii_init, /* BT_WII */
6264
bt_hid_ps_init, /* BT_PS */
6365
bt_hid_sw_init, /* BT_SW */
66+
bt_hid_sw2_init, /* BT_SW2 */
6467
};
6568

6669
static const bt_hid_hdlr_t bt_hid_hdlr_list[BT_TYPE_MAX] = {
@@ -69,6 +72,7 @@ static const bt_hid_hdlr_t bt_hid_hdlr_list[BT_TYPE_MAX] = {
6972
bt_hid_wii_hdlr, /* BT_WII */
7073
bt_hid_ps_hdlr, /* BT_PS */
7174
bt_hid_sw_hdlr, /* BT_SW */
75+
NULL, /* BT_SW2 */
7276
};
7377

7478
static const bt_hid_cmd_t bt_hid_feedback_list[BT_TYPE_MAX] = {
@@ -77,6 +81,7 @@ static const bt_hid_cmd_t bt_hid_feedback_list[BT_TYPE_MAX] = {
7781
bt_hid_cmd_wii_set_feedback, /* BT_WII */
7882
bt_hid_cmd_ps_set_conf, /* BT_PS */
7983
bt_hid_cmd_sw_set_conf, /* BT_SW */
84+
bt_hid_cmd_sw2_out, /* BT_SW2 */
8085
};
8186

8287
void bt_hid_set_type_flags_from_name(struct bt_dev *device, const char* name) {

0 commit comments

Comments
 (0)