|
90 | 90 | #define GIP_CMD_GUIDE_COLOR 0x0e
|
91 | 91 | #define GIP_SL_ELITE_CONFIG 0x4d
|
92 | 92 |
|
| 93 | +#define GIP_BTN_OFFSET_XBE1 28 |
| 94 | +#define GIP_BTN_OFFSET_XBE2 14 |
| 95 | + |
93 | 96 | #define GIP_FLAG_FRAGMENT (1u << 7)
|
94 | 97 | #define GIP_FLAG_INIT_FRAG (1u << 6)
|
95 | 98 | #define GIP_FLAG_SYSTEM (1u << 5)
|
@@ -269,11 +272,12 @@ typedef enum
|
269 | 272 |
|
270 | 273 | typedef enum
|
271 | 274 | {
|
272 |
| - GIP_PADDLES_UNKNOWN, |
273 |
| - GIP_PADDLES_XBE1, |
274 |
| - GIP_PADDLES_XBE2_RAW, |
275 |
| - GIP_PADDLES_XBE2, |
276 |
| -} GIP_PaddleFormat; |
| 275 | + GIP_BTN_FMT_UNKNOWN, |
| 276 | + GIP_BTN_FMT_XBE1, |
| 277 | + GIP_BTN_FMT_XBE2_RAW, |
| 278 | + GIP_BTN_FMT_XBE2_4, |
| 279 | + GIP_BTN_FMT_XBE2_5, |
| 280 | +} GIP_EliteButtonFormat; |
277 | 281 |
|
278 | 282 | /* These come across the wire as little-endian, so let's store them in-memory as such so we can memcmp */
|
279 | 283 | #define MAKE_GUID(NAME, A, B, C, D0, D1, D2, D3, D4, D5, D6, D7) \
|
@@ -471,12 +475,11 @@ typedef struct GIP_Attachment
|
471 | 475 | int altcode_digit;
|
472 | 476 |
|
473 | 477 | GIP_AttachmentType attachment_type;
|
474 |
| - GIP_PaddleFormat paddle_format; |
| 478 | + GIP_EliteButtonFormat xbe_format; |
475 | 479 | Uint32 features;
|
476 | 480 | Uint32 quirks;
|
477 | 481 | Uint8 share_button_idx;
|
478 | 482 | Uint8 paddle_idx;
|
479 |
| - int paddle_offset; |
480 | 483 |
|
481 | 484 | Uint8 extra_button_idx;
|
482 | 485 | int extra_buttons;
|
@@ -1114,9 +1117,30 @@ static bool GIP_FragmentFailed(GIP_Attachment *attachment, const GIP_Header *hea
|
1114 | 1117 | }
|
1115 | 1118 |
|
1116 | 1119 | static bool GIP_EnableEliteButtons(GIP_Attachment *attachment) {
|
1117 |
| - if (attachment->paddle_format == GIP_PADDLES_XBE2_RAW || |
1118 |
| - (attachment->firmware_major_version != 4 && attachment->firmware_minor_version < 17)) |
1119 |
| - { |
| 1120 | + if (attachment->device->device->vendor_id == USB_VENDOR_MICROSOFT) { |
| 1121 | + if (attachment->device->device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1) { |
| 1122 | + attachment->xbe_format = GIP_BTN_FMT_XBE1; |
| 1123 | + } else if (attachment->device->device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) { |
| 1124 | + if (attachment->firmware_major_version == 4) { |
| 1125 | + attachment->xbe_format = GIP_BTN_FMT_XBE2_4; |
| 1126 | + } else if (attachment->firmware_major_version == 5) { |
| 1127 | + /* |
| 1128 | + * The exact range for this being necessary is unknown, but it |
| 1129 | + * starts at 5.11 and at either 5.16 or 5.17. This approach |
| 1130 | + * still works on 5.21, even if it's not necessary, so having |
| 1131 | + * a loose upper limit is fine. |
| 1132 | + */ |
| 1133 | + if (attachment->firmware_minor_version >= 11 && |
| 1134 | + attachment->firmware_minor_version < 17) |
| 1135 | + { |
| 1136 | + attachment->xbe_format = GIP_BTN_FMT_XBE2_RAW; |
| 1137 | + } else { |
| 1138 | + attachment->xbe_format = GIP_BTN_FMT_XBE2_5; |
| 1139 | + } |
| 1140 | + } |
| 1141 | + } |
| 1142 | + } |
| 1143 | + if (attachment->xbe_format == GIP_BTN_FMT_XBE2_RAW) { |
1120 | 1144 | /*
|
1121 | 1145 | * The meaning of this packet is unknown and not documented, but it's
|
1122 | 1146 | * needed for the Elite 2 controller to send raw reports
|
@@ -1182,10 +1206,9 @@ static bool GIP_SendInitSequence(GIP_Attachment *attachment)
|
1182 | 1206 | {
|
1183 | 1207 | return false;
|
1184 | 1208 | }
|
1185 |
| - |
1186 |
| - if (!GIP_EnableEliteButtons(attachment)) { |
1187 |
| - return false; |
1188 |
| - } |
| 1209 | + } |
| 1210 | + if (!GIP_EnableEliteButtons(attachment)) { |
| 1211 | + return false; |
1189 | 1212 | }
|
1190 | 1213 | if (!GIP_SendSetDeviceState(attachment, GIP_STATE_START)) {
|
1191 | 1214 | return false;
|
@@ -1661,11 +1684,6 @@ static bool GIP_HandleCommandFirmware(
|
1661 | 1684 | if (attachment->device->device->vendor_id == USB_VENDOR_MICROSOFT &&
|
1662 | 1685 | attachment->device->device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2)
|
1663 | 1686 | {
|
1664 |
| - if (attachment->firmware_major_version == 5 && attachment->firmware_minor_version < 17) { |
1665 |
| - attachment->paddle_format = GIP_PADDLES_XBE2_RAW; |
1666 |
| - } else { |
1667 |
| - attachment->paddle_format = GIP_PADDLES_XBE2; |
1668 |
| - } |
1669 | 1687 | return GIP_EnableEliteButtons(attachment);
|
1670 | 1688 | }
|
1671 | 1689 | return true;
|
@@ -1694,28 +1712,47 @@ static bool GIP_HandleCommandRawReport(
|
1694 | 1712 | return true;
|
1695 | 1713 | }
|
1696 | 1714 |
|
1697 |
| - if (num_bytes < 17 || num_bytes <= attachment->paddle_offset) { |
| 1715 | + if (num_bytes < 17) { |
1698 | 1716 | SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GIP: Discarding too-short raw report");
|
1699 | 1717 | return false;
|
1700 | 1718 | }
|
1701 | 1719 |
|
1702 |
| - if ((attachment->features & GIP_FEATURE_ELITE_BUTTONS) && attachment->paddle_format == GIP_PADDLES_XBE2_RAW) { |
1703 |
| - SDL_SendJoystickButton(timestamp, |
1704 |
| - joystick, |
1705 |
| - attachment->paddle_idx, |
1706 |
| - (bytes[attachment->paddle_offset] & 0x01) != 0); |
1707 |
| - SDL_SendJoystickButton(timestamp, |
1708 |
| - joystick, |
1709 |
| - attachment->paddle_idx + 1, |
1710 |
| - (bytes[attachment->paddle_offset] & 0x02) != 0); |
1711 |
| - SDL_SendJoystickButton(timestamp, |
1712 |
| - joystick, |
1713 |
| - attachment->paddle_idx + 2, |
1714 |
| - (bytes[attachment->paddle_offset] & 0x04) != 0); |
1715 |
| - SDL_SendJoystickButton(timestamp, |
1716 |
| - joystick, |
1717 |
| - attachment->paddle_idx + 3, |
1718 |
| - (bytes[attachment->paddle_offset] & 0x08) != 0); |
| 1720 | + if ((attachment->features & GIP_FEATURE_ELITE_BUTTONS) && attachment->xbe_format == GIP_BTN_FMT_XBE2_RAW) { |
| 1721 | + if (bytes[15] & 3) { |
| 1722 | + SDL_SendJoystickButton(timestamp, |
| 1723 | + joystick, |
| 1724 | + attachment->paddle_idx, |
| 1725 | + 0); |
| 1726 | + SDL_SendJoystickButton(timestamp, |
| 1727 | + joystick, |
| 1728 | + attachment->paddle_idx + 1, |
| 1729 | + 0); |
| 1730 | + SDL_SendJoystickButton(timestamp, |
| 1731 | + joystick, |
| 1732 | + attachment->paddle_idx + 2, |
| 1733 | + 0); |
| 1734 | + SDL_SendJoystickButton(timestamp, |
| 1735 | + joystick, |
| 1736 | + attachment->paddle_idx + 3, |
| 1737 | + 0); |
| 1738 | + } else { |
| 1739 | + SDL_SendJoystickButton(timestamp, |
| 1740 | + joystick, |
| 1741 | + attachment->paddle_idx, |
| 1742 | + (bytes[GIP_BTN_OFFSET_XBE2] & 0x01) != 0); |
| 1743 | + SDL_SendJoystickButton(timestamp, |
| 1744 | + joystick, |
| 1745 | + attachment->paddle_idx + 1, |
| 1746 | + (bytes[GIP_BTN_OFFSET_XBE2] & 0x02) != 0); |
| 1747 | + SDL_SendJoystickButton(timestamp, |
| 1748 | + joystick, |
| 1749 | + attachment->paddle_idx + 2, |
| 1750 | + (bytes[GIP_BTN_OFFSET_XBE2] & 0x04) != 0); |
| 1751 | + SDL_SendJoystickButton(timestamp, |
| 1752 | + joystick, |
| 1753 | + attachment->paddle_idx + 3, |
| 1754 | + (bytes[GIP_BTN_OFFSET_XBE2] & 0x08) != 0); |
| 1755 | + } |
1719 | 1756 | }
|
1720 | 1757 | return true;
|
1721 | 1758 | }
|
@@ -2080,46 +2117,78 @@ static bool GIP_HandleLLInputReport(
|
2080 | 2117 | break;
|
2081 | 2118 | }
|
2082 | 2119 |
|
2083 |
| - if ((attachment->features & GIP_FEATURE_ELITE_BUTTONS) && |
2084 |
| - num_bytes > attachment->paddle_offset && |
2085 |
| - attachment->last_input[attachment->paddle_offset] != bytes[attachment->paddle_offset]) |
2086 |
| - { |
2087 |
| - if (attachment->paddle_format == GIP_PADDLES_XBE1) { |
2088 |
| - if (bytes[attachment->paddle_offset] & 0x10) { |
2089 |
| - SDL_SendJoystickButton(timestamp, |
2090 |
| - joystick, |
2091 |
| - attachment->paddle_idx, |
2092 |
| - (bytes[attachment->paddle_offset] & 0x02) != 0); |
2093 |
| - SDL_SendJoystickButton(timestamp, |
2094 |
| - joystick, |
2095 |
| - attachment->paddle_idx + 1, |
2096 |
| - (bytes[attachment->paddle_offset] & 0x08) != 0); |
2097 |
| - SDL_SendJoystickButton(timestamp, |
2098 |
| - joystick, |
2099 |
| - attachment->paddle_idx + 2, |
2100 |
| - (bytes[attachment->paddle_offset] & 0x01) != 0); |
2101 |
| - SDL_SendJoystickButton(timestamp, |
2102 |
| - joystick, |
2103 |
| - attachment->paddle_idx + 3, |
2104 |
| - (bytes[attachment->paddle_offset] & 0x04) != 0); |
| 2120 | + if (attachment->features & GIP_FEATURE_ELITE_BUTTONS) { |
| 2121 | + bool clear = false; |
| 2122 | + if (attachment->xbe_format == GIP_BTN_FMT_XBE1 && |
| 2123 | + num_bytes > GIP_BTN_OFFSET_XBE1 && |
| 2124 | + attachment->last_input[GIP_BTN_OFFSET_XBE1] != bytes[GIP_BTN_OFFSET_XBE1] && |
| 2125 | + (bytes[GIP_BTN_OFFSET_XBE1] & 0x10)) |
| 2126 | + { |
| 2127 | + SDL_SendJoystickButton(timestamp, |
| 2128 | + joystick, |
| 2129 | + attachment->paddle_idx, |
| 2130 | + (bytes[GIP_BTN_OFFSET_XBE1] & 0x02) != 0); |
| 2131 | + SDL_SendJoystickButton(timestamp, |
| 2132 | + joystick, |
| 2133 | + attachment->paddle_idx + 1, |
| 2134 | + (bytes[GIP_BTN_OFFSET_XBE1] & 0x08) != 0); |
| 2135 | + SDL_SendJoystickButton(timestamp, |
| 2136 | + joystick, |
| 2137 | + attachment->paddle_idx + 2, |
| 2138 | + (bytes[GIP_BTN_OFFSET_XBE1] & 0x01) != 0); |
| 2139 | + SDL_SendJoystickButton(timestamp, |
| 2140 | + joystick, |
| 2141 | + attachment->paddle_idx + 3, |
| 2142 | + (bytes[GIP_BTN_OFFSET_XBE1] & 0x04) != 0); |
| 2143 | + } else if ((attachment->xbe_format == GIP_BTN_FMT_XBE2_4 || |
| 2144 | + attachment->xbe_format == GIP_BTN_FMT_XBE2_5) && |
| 2145 | + num_bytes > GIP_BTN_OFFSET_XBE2) |
| 2146 | + { |
| 2147 | + int profile_offset = attachment->xbe_format == GIP_BTN_FMT_XBE2_4 ? 15 : 20; |
| 2148 | + if (attachment->last_input[GIP_BTN_OFFSET_XBE2] != bytes[GIP_BTN_OFFSET_XBE2] || |
| 2149 | + attachment->last_input[profile_offset] != bytes[profile_offset]) |
| 2150 | + { |
| 2151 | + if (bytes[profile_offset] & 3) { |
| 2152 | + clear = true; |
| 2153 | + } else { |
| 2154 | + SDL_SendJoystickButton(timestamp, |
| 2155 | + joystick, |
| 2156 | + attachment->paddle_idx, |
| 2157 | + (bytes[GIP_BTN_OFFSET_XBE2] & 0x01) != 0); |
| 2158 | + SDL_SendJoystickButton(timestamp, |
| 2159 | + joystick, |
| 2160 | + attachment->paddle_idx + 1, |
| 2161 | + (bytes[GIP_BTN_OFFSET_XBE2] & 0x02) != 0); |
| 2162 | + SDL_SendJoystickButton(timestamp, |
| 2163 | + joystick, |
| 2164 | + attachment->paddle_idx + 2, |
| 2165 | + (bytes[GIP_BTN_OFFSET_XBE2] & 0x04) != 0); |
| 2166 | + SDL_SendJoystickButton(timestamp, |
| 2167 | + joystick, |
| 2168 | + attachment->paddle_idx + 3, |
| 2169 | + (bytes[GIP_BTN_OFFSET_XBE2] & 0x08) != 0); |
| 2170 | + } |
2105 | 2171 | }
|
2106 |
| - } else if (attachment->paddle_format == GIP_PADDLES_XBE2) { |
| 2172 | + } else { |
| 2173 | + clear = true; |
| 2174 | + } |
| 2175 | + if (clear) { |
2107 | 2176 | SDL_SendJoystickButton(timestamp,
|
2108 | 2177 | joystick,
|
2109 | 2178 | attachment->paddle_idx,
|
2110 |
| - (bytes[attachment->paddle_offset] & 0x01) != 0); |
| 2179 | + 0); |
2111 | 2180 | SDL_SendJoystickButton(timestamp,
|
2112 | 2181 | joystick,
|
2113 | 2182 | attachment->paddle_idx + 1,
|
2114 |
| - (bytes[attachment->paddle_offset] & 0x02) != 0); |
| 2183 | + 0); |
2115 | 2184 | SDL_SendJoystickButton(timestamp,
|
2116 | 2185 | joystick,
|
2117 | 2186 | attachment->paddle_idx + 2,
|
2118 |
| - (bytes[attachment->paddle_offset] & 0x04) != 0); |
| 2187 | + 0); |
2119 | 2188 | SDL_SendJoystickButton(timestamp,
|
2120 | 2189 | joystick,
|
2121 | 2190 | attachment->paddle_idx + 3,
|
2122 |
| - (bytes[attachment->paddle_offset] & 0x08) != 0); |
| 2191 | + 0); |
2123 | 2192 | }
|
2124 | 2193 | }
|
2125 | 2194 |
|
@@ -2593,19 +2662,11 @@ static bool HIDAPI_DriverGIP_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystic
|
2593 | 2662 |
|
2594 | 2663 | // Initialize the joystick capabilities
|
2595 | 2664 | joystick->nbuttons = 11;
|
2596 |
| - if (device->vendor_id == USB_VENDOR_MICROSOFT) { |
2597 |
| - if (device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1) { |
2598 |
| - attachment->paddle_offset = 28; |
2599 |
| - attachment->paddle_format = GIP_PADDLES_XBE1; |
2600 |
| - } else if (device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) { |
2601 |
| - attachment->paddle_offset = 14; |
2602 |
| - attachment->paddle_format = GIP_PADDLES_XBE2; |
2603 |
| - if (attachment->firmware_major_version == 5 && attachment->firmware_minor_version < 17) { |
2604 |
| - attachment->paddle_format = GIP_PADDLES_XBE2_RAW; |
2605 |
| - } |
2606 |
| - } |
2607 |
| - } |
2608 |
| - if (attachment->paddle_offset > 0) { |
| 2665 | + GIP_EnableEliteButtons(attachment); |
| 2666 | + if (attachment->xbe_format != GIP_BTN_FMT_UNKNOWN || |
| 2667 | + (device->vendor_id == USB_VENDOR_MICROSOFT && |
| 2668 | + device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2)) |
| 2669 | + { |
2609 | 2670 | attachment->paddle_idx = (Uint8) joystick->nbuttons;
|
2610 | 2671 | joystick->nbuttons += 4;
|
2611 | 2672 | }
|
|
0 commit comments