| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2019-2025, Jacques Gagnon | ||
| 3 | * SPDX-License-Identifier: Apache-2.0 | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include "bluetooth/host.h" | ||
| 7 | #include "bluetooth/hci.h" | ||
| 8 | #include "tools/util.h" | ||
| 9 | #include "generic.h" | ||
| 10 | #include "ps3.h" | ||
| 11 | #include "wii.h" | ||
| 12 | #include "ps.h" | ||
| 13 | #include "sw.h" | ||
| 14 | #include "sw2.h" | ||
| 15 | |||
| 16 | typedef void (*bt_hid_init_t)(struct bt_dev *device); | ||
| 17 | typedef void (*bt_hid_hdlr_t)(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint32_t len); | ||
| 18 | typedef void (*bt_hid_cmd_t)(struct bt_dev *device, void *report); | ||
| 19 | |||
| 20 | const uint8_t bt_hid_led_dev_id_map[] = { | ||
| 21 | 0x1, 0x2, 0x4, 0x8, 0x3, 0x6, 0xC | ||
| 22 | }; | ||
| 23 | |||
| 24 | static const struct bt_name_type bt_name_type[] = { | ||
| 25 | #ifndef CONFIG_BLUERETRO_GENERIC_HID_DEBUG | ||
| 26 | {"PLAYSTATION(R)3", BT_PS3, BT_SUBTYPE_DEFAULT, 0}, | ||
| 27 | {"Xbox Wireless Controller", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, 0}, | ||
| 28 | {"DualSense Wireless Controller", BT_PS, BT_PS5_DS, 0}, | ||
| 29 | {"Wireless Controller", BT_PS, BT_SUBTYPE_DEFAULT, 0}, | ||
| 30 | {"Nintendo RVL-CNT-01-UC", BT_WII, BT_WIIU_PRO, 0}, /* Must be before WII */ | ||
| 31 | {"Nintendo RVL-CNT-01", BT_WII, BT_SUBTYPE_DEFAULT, 0}, | ||
| 32 | {"Pro Controller", BT_SW, BT_SUBTYPE_DEFAULT, 0}, | ||
| 33 | {"Joy-Con (L)", BT_SW, BT_SW_LEFT_JOYCON, 0}, | ||
| 34 | {"Joy-Con (R)", BT_SW, BT_SW_RIGHT_JOYCON, 0}, | ||
| 35 | {"SNES Controller", BT_SW, BT_SW_SNES, BIT(BT_QUIRK_TRIGGER_PRI_SEC_INVERT)}, | ||
| 36 | {"HVC Controller", BT_SW, BT_SW_NES, BIT(BT_QUIRK_FACE_BTNS_ROTATE_RIGHT) | BIT(BT_QUIRK_TRIGGER_PRI_SEC_INVERT)}, | ||
| 37 | {"NES Controller", BT_SW, BT_SW_NES, BIT(BT_QUIRK_FACE_BTNS_ROTATE_RIGHT) | BIT(BT_QUIRK_TRIGGER_PRI_SEC_INVERT)}, | ||
| 38 | {"N64 Controller", BT_SW, BT_SW_N64, 0}, | ||
| 39 | {"MD/Gen Control Pad", BT_SW, BT_SW_MD_GEN, 0}, | ||
| 40 | {"8Bitdo NES30 Arcade", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_FACE_BTNS_TRIGGER_TO_8BUTTONS)}, | ||
| 41 | {"8BitDo Arcade Stick", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_FACE_BTNS_TRIGGER_TO_8BUTTONS)}, | ||
| 42 | {"8BitDo NGC Modkit", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_8BITDO_GC)}, | ||
| 43 | {"8BitDo N30 Modkit", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_FACE_BTNS_ROTATE_RIGHT)}, | ||
| 44 | {"8BitDo GBros Adapter", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_8BITDO_GBROS)}, | ||
| 45 | {"8Bitdo N64 GamePad", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_8BITDO_N64)}, | ||
| 46 | {"8BitDo N64 Modkit", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_8BITDO_N64_MK)}, | ||
| 47 | {"8BitDo NEOGEO GP", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_TRIGGER_PRI_SEC_INVERT)}, | ||
| 48 | {"8BitDo M30 gamepad", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_8BITDO_M30)}, | ||
| 49 | {"8BitDo M30 Modkit", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_8BITDO_M30_MODKIT)}, | ||
| 50 | {"8BitDo S30 Modkit", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_8BITDO_SATURN)}, | ||
| 51 | {"Retro Bit Bluetooth Controller", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_FACE_BTNS_TRIGGER_TO_6BUTTONS) | BIT(BT_QUIRK_TRIGGER_PRI_SEC_INVERT)}, | ||
| 52 | {"Joy Controller", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_RF_WARRIOR)}, | ||
| 53 | {"BlueN64 Gamepad", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_BLUEN64_N64)}, | ||
| 54 | {"Hyperkin Pad", BT_SW, BT_SW_HYPERKIN_ADMIRAL, 0}, | ||
| 55 | {"OUYA Game Controller", BT_HID_GENERIC, BT_SUBTYPE_DEFAULT, BIT(BT_QUIRK_OUYA)}, | ||
| 56 | {"DeviceName", BT_SW2, BT_SUBTYPE_DEFAULT, 0}, | ||
| 57 | #endif | ||
| 58 | }; | ||
| 59 | |||
| 60 | static const bt_hid_init_t bt_hid_init_list[BT_TYPE_MAX] = { | ||
| 61 | bt_hid_generic_init, /* BT_HID_GENERIC */ | ||
| 62 | bt_hid_ps3_init, /* BT_PS3 */ | ||
| 63 | bt_hid_wii_init, /* BT_WII */ | ||
| 64 | bt_hid_ps_init, /* BT_PS */ | ||
| 65 | bt_hid_sw_init, /* BT_SW */ | ||
| 66 | bt_hid_sw2_init, /* BT_SW2 */ | ||
| 67 | }; | ||
| 68 | |||
| 69 | static const bt_hid_hdlr_t bt_hid_hdlr_list[BT_TYPE_MAX] = { | ||
| 70 | bt_hid_generic_hdlr, /* BT_HID_GENERIC */ | ||
| 71 | bt_hid_ps3_hdlr, /* BT_PS3 */ | ||
| 72 | bt_hid_wii_hdlr, /* BT_WII */ | ||
| 73 | bt_hid_ps_hdlr, /* BT_PS */ | ||
| 74 | bt_hid_sw_hdlr, /* BT_SW */ | ||
| 75 | NULL, /* BT_SW2 */ | ||
| 76 | }; | ||
| 77 | |||
| 78 | static const bt_hid_cmd_t bt_hid_feedback_list[BT_TYPE_MAX] = { | ||
| 79 | bt_hid_cmd_generic_rumble, /* BT_HID_GENERIC */ | ||
| 80 | bt_hid_cmd_ps3_set_conf, /* BT_PS3 */ | ||
| 81 | bt_hid_cmd_wii_set_feedback, /* BT_WII */ | ||
| 82 | bt_hid_cmd_ps_set_conf, /* BT_PS */ | ||
| 83 | bt_hid_cmd_sw_set_conf, /* BT_SW */ | ||
| 84 | bt_hid_cmd_sw2_out, /* BT_SW2 */ | ||
| 85 | }; | ||
| 86 | |||
| 87 | 92 | void bt_hid_set_type_flags_from_name(struct bt_dev *device, const char* name) { | |
| 88 |
2/2✓ Branch 0 (8→3) taken 1231 times.
✓ Branch 1 (8→9) taken 21 times.
|
1252 | for (uint32_t i = 0; i < sizeof(bt_name_type)/sizeof(*bt_name_type); i++) { |
| 89 |
2/2✓ Branch 0 (4→5) taken 71 times.
✓ Branch 1 (4→7) taken 1160 times.
|
1231 | if (strcasestr(name, bt_name_type[i].name) != NULL) { |
| 90 | 71 | struct bt_data *bt_data = &bt_adapter.data[device->ids.id]; | |
| 91 | |||
| 92 | 71 | bt_type_update(device->ids.id, bt_name_type[i].type, bt_name_type[i].subtype); | |
| 93 | 71 | bt_data->base.flags[PAD] = bt_name_type[i].hid_flags; | |
| 94 | 71 | device->name = &bt_name_type[i]; | |
| 95 | 71 | break; | |
| 96 | } | ||
| 97 | } | ||
| 98 | 92 | } | |
| 99 | |||
| 100 | 92 | void bt_hid_init(struct bt_dev *device) { | |
| 101 |
2/4✓ Branch 0 (2→3) taken 92 times.
✗ Branch 1 (2→5) not taken.
✓ Branch 2 (3→4) taken 92 times.
✗ Branch 3 (3→5) not taken.
|
92 | if (device->ids.type > BT_NONE && bt_hid_init_list[device->ids.type]) { |
| 102 | 92 | bt_hid_init_list[device->ids.type](device); | |
| 103 | } | ||
| 104 | 92 | } | |
| 105 | |||
| 106 | 1469 | void bt_hid_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint32_t len) { | |
| 107 |
2/4✓ Branch 0 (2→3) taken 1469 times.
✗ Branch 1 (2→5) not taken.
✓ Branch 2 (3→4) taken 1469 times.
✗ Branch 3 (3→5) not taken.
|
1469 | if (device->ids.type > BT_NONE && bt_hid_hdlr_list[device->ids.type]) { |
| 108 | 1469 | bt_hid_hdlr_list[device->ids.type](device, bt_hci_acl_pkt, len); | |
| 109 | } | ||
| 110 | 1469 | } | |
| 111 | |||
| 112 | 27 | void bt_hid_feedback(struct bt_dev *device, void *report) { | |
| 113 |
2/4✓ Branch 0 (2→3) taken 27 times.
✗ Branch 1 (2→5) not taken.
✓ Branch 2 (3→4) taken 27 times.
✗ Branch 3 (3→5) not taken.
|
27 | if (device->ids.type > BT_NONE && bt_hid_feedback_list[device->ids.type]) { |
| 114 | 27 | bt_hid_feedback_list[device->ids.type](device, report); | |
| 115 | } | ||
| 116 | 27 | } | |
| 117 | |||
| 118 | 196 | void bt_hid_cmd(uint16_t handle, uint16_t cid, uint8_t hidp_hdr, uint8_t protocol, uint16_t len) { | |
| 119 | 196 | uint16_t packet_len = (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE | |
| 120 | + sizeof(struct bt_l2cap_hdr) + sizeof(struct bt_hidp_hdr) + len); | ||
| 121 | |||
| 122 | 196 | bt_hci_pkt_tmp.h4_hdr.type = BT_HCI_H4_TYPE_ACL; | |
| 123 | |||
| 124 | 196 | bt_hci_pkt_tmp.acl_hdr.handle = bt_acl_handle_pack(handle, 0x2); | |
| 125 | 196 | bt_hci_pkt_tmp.acl_hdr.len = packet_len - BT_HCI_H4_HDR_SIZE - BT_HCI_ACL_HDR_SIZE; | |
| 126 | |||
| 127 | 196 | bt_hci_pkt_tmp.l2cap_hdr.len = bt_hci_pkt_tmp.acl_hdr.len - sizeof(bt_hci_pkt_tmp.l2cap_hdr); | |
| 128 | 196 | bt_hci_pkt_tmp.l2cap_hdr.cid = cid; | |
| 129 | |||
| 130 | 196 | bt_hci_pkt_tmp.hidp_hdr.hdr = hidp_hdr; | |
| 131 | 196 | bt_hci_pkt_tmp.hidp_hdr.protocol = protocol; | |
| 132 | |||
| 133 | 196 | bt_host_txq_add((uint8_t *)&bt_hci_pkt_tmp, packet_len); | |
| 134 | 196 | } | |
| 135 |