switch-pico/xinput_feasibility_descriptors.h

153 lines
5.1 KiB
C++

#pragma once
#include <stddef.h>
#include <stdint.h>
#ifndef SWITCH_PICO_HID_INSTANCE_COUNT
#define SWITCH_PICO_HID_INSTANCE_COUNT 1
#endif
#if SWITCH_PICO_HID_INSTANCE_COUNT < 1 || SWITCH_PICO_HID_INSTANCE_COUNT > 4
#error "SWITCH_PICO_HID_INSTANCE_COUNT must be between 1 and 4"
#endif
namespace XInputFeasibility {
constexpr uint16_t kPrototypeVendorId = 0xcafe;
constexpr uint16_t kPrototypeProductId = 0x4010;
constexpr uint16_t kPrototypeDeviceRevision = 0x0101;
constexpr uint8_t kInterfaceDescriptorSize = 39;
constexpr uint16_t kConfigurationDescriptorSize =
9 + SWITCH_PICO_HID_INSTANCE_COUNT * kInterfaceDescriptorSize;
constexpr uint16_t kMsCompatIdDescriptorSize =
16 + SWITCH_PICO_HID_INSTANCE_COUNT * 24;
constexpr uint8_t kMsVendorRequest = 0x20;
constexpr uint16_t kMsCompatIdIndex = 0x0004;
constexpr uint16_t kSwitchProbeVendorId = 0x057e;
constexpr uint16_t kSwitchProbeProductId = 0x2009;
// Windows caches Microsoft OS descriptor support by VID, PID, and bcdDevice.
// Use a revision distinct from genuine Pro Controllers so their cached
// "unsupported" result cannot suppress this probe's 0xEE request.
constexpr uint16_t kSwitchProbeDeviceRevision = 0x0211;
static const uint8_t kSwitchProbeDeviceDescriptor[] = {
0x12,
0x01, // Device descriptor
0x00,
0x02, // USB 2.0
0x00,
0x00,
0x00, // Class information comes from the interface descriptor
0x40, // Endpoint zero packet size
static_cast<uint8_t>(kSwitchProbeVendorId & 0xff),
static_cast<uint8_t>(kSwitchProbeVendorId >> 8),
static_cast<uint8_t>(kSwitchProbeProductId & 0xff),
static_cast<uint8_t>(kSwitchProbeProductId >> 8),
static_cast<uint8_t>(kSwitchProbeDeviceRevision & 0xff),
static_cast<uint8_t>(kSwitchProbeDeviceRevision >> 8),
0x01,
0x02,
0x03, // Manufacturer, product, serial strings
0x01, // One configuration
};
static const uint8_t kDeviceDescriptor[] = {
0x12,
0x01, // Device descriptor
0x00,
0x02, // USB 2.0
0x00,
0x00,
0x00, // Composite device; each interface binds to the XUSB driver
0x40, // Endpoint zero packet size
static_cast<uint8_t>(kPrototypeVendorId & 0xff),
static_cast<uint8_t>(kPrototypeVendorId >> 8),
static_cast<uint8_t>(kPrototypeProductId & 0xff),
static_cast<uint8_t>(kPrototypeProductId >> 8),
static_cast<uint8_t>(kPrototypeDeviceRevision & 0xff),
static_cast<uint8_t>(kPrototypeDeviceRevision >> 8),
0x01,
0x02,
0x03, // Manufacturer, product, serial strings
0x01, // One configuration
};
#define XINPUT_FEASIBILITY_INTERFACE(number, endpoint) \
0x09, 0x04, number, 0x00, 0x02, 0xff, 0x5d, 0x01, 0x00, 0x10, 0x21, 0x10, \
0x01, 0x01, 0x24, static_cast<uint8_t>(0x80 | endpoint), 0x14, 0x03, \
0x00, 0x03, 0x13, endpoint, 0x00, 0x03, 0x00, 0x07, 0x05, \
static_cast<uint8_t>(0x80 | endpoint), 0x03, 0x20, 0x00, 0x04, 0x07, \
0x05, endpoint, 0x03, 0x20, 0x00, 0x08
static const uint8_t kConfigurationDescriptor[] = {
0x09,
0x02,
static_cast<uint8_t>(kConfigurationDescriptorSize & 0xff),
static_cast<uint8_t>(kConfigurationDescriptorSize >> 8),
SWITCH_PICO_HID_INSTANCE_COUNT,
0x01,
0x00,
0x80,
0xfa,
XINPUT_FEASIBILITY_INTERFACE(0x00, 0x01),
#if SWITCH_PICO_HID_INSTANCE_COUNT >= 2
XINPUT_FEASIBILITY_INTERFACE(0x01, 0x02),
#endif
#if SWITCH_PICO_HID_INSTANCE_COUNT >= 3
XINPUT_FEASIBILITY_INTERFACE(0x02, 0x03),
#endif
#if SWITCH_PICO_HID_INSTANCE_COUNT >= 4
XINPUT_FEASIBILITY_INTERFACE(0x03, 0x04),
#endif
};
#undef XINPUT_FEASIBILITY_INTERFACE
#define XINPUT_FEASIBILITY_COMPAT_FUNCTION(number) \
number, 0x01, 'X', 'U', 'S', 'B', '1', '0', 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
static const uint8_t kMsCompatIdDescriptor[] = {
static_cast<uint8_t>(kMsCompatIdDescriptorSize & 0xff),
static_cast<uint8_t>(kMsCompatIdDescriptorSize >> 8),
0x00,
0x00,
0x00,
0x01, // Microsoft OS descriptor version 1.0
0x04,
0x00, // Extended compatible ID descriptor
SWITCH_PICO_HID_INSTANCE_COUNT,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
XINPUT_FEASIBILITY_COMPAT_FUNCTION(0x00),
#if SWITCH_PICO_HID_INSTANCE_COUNT >= 2
XINPUT_FEASIBILITY_COMPAT_FUNCTION(0x01),
#endif
#if SWITCH_PICO_HID_INSTANCE_COUNT >= 3
XINPUT_FEASIBILITY_COMPAT_FUNCTION(0x02),
#endif
#if SWITCH_PICO_HID_INSTANCE_COUNT >= 4
XINPUT_FEASIBILITY_COMPAT_FUNCTION(0x03),
#endif
};
#undef XINPUT_FEASIBILITY_COMPAT_FUNCTION
static const uint8_t kProbeMsCompatIdDescriptor[] = {
0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static_assert(sizeof(kDeviceDescriptor) == 18);
static_assert(sizeof(kSwitchProbeDeviceDescriptor) == 18);
static_assert(sizeof(kConfigurationDescriptor) == kConfigurationDescriptorSize);
static_assert(sizeof(kMsCompatIdDescriptor) == kMsCompatIdDescriptorSize);
static_assert(sizeof(kProbeMsCompatIdDescriptor) == 16);
} // namespace XInputFeasibility