mirror of https://github.com/PCSX2/pcsx2.git
USB: Gametrak/RealPlay
This commit is contained in:
parent
97727cae2c
commit
c36666b4d4
|
@ -36,6 +36,10 @@ void RegisterDevice::Register()
|
|||
inst.Add(DEVTYPE_HIDMOUSE, new DeviceProxy<usb_hid::HIDMouseDevice>());
|
||||
inst.Add(DEVTYPE_RBKIT, new DeviceProxy<usb_pad::RBDrumKitDevice>());
|
||||
inst.Add(DEVTYPE_BUZZ, new DeviceProxy<usb_pad::BuzzDevice>());
|
||||
#ifdef _WIN32
|
||||
inst.Add(DEVTYPE_GAMETRAK, new DeviceProxy<usb_pad::GametrakDevice>());
|
||||
inst.Add(DEVTYPE_REALPLAY, new DeviceProxy<usb_pad::RealPlayDevice>());
|
||||
#endif
|
||||
inst.Add(DEVTYPE_EYETOY, new DeviceProxy<usb_eyetoy::EyeToyWebCamDevice>());
|
||||
inst.Add(DEVTYPE_BEATMANIA_DADADA, new DeviceProxy<usb_hid::BeatManiaDevice>());
|
||||
inst.Add(DEVTYPE_SEGA_SEAMIC, new DeviceProxy<usb_pad::SeamicDevice>());
|
||||
|
|
|
@ -44,6 +44,8 @@ enum DeviceType
|
|||
DEVTYPE_HIDMOUSE,
|
||||
DEVTYPE_RBKIT,
|
||||
DEVTYPE_BUZZ,
|
||||
DEVTYPE_GAMETRAK,
|
||||
DEVTYPE_REALPLAY,
|
||||
DEVTYPE_EYETOY,
|
||||
DEVTYPE_BEATMANIA_DADADA,
|
||||
DEVTYPE_SEGA_SEAMIC,
|
||||
|
|
|
@ -1468,6 +1468,14 @@ namespace usb_pad
|
|||
{
|
||||
return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DLG_KEYBOARDMANIA), h.hWnd, DxDialogProc, (LPARAM)&s);
|
||||
}
|
||||
if (strcmp(dev_type, GametrakDevice::TypeName()) == 0)
|
||||
{
|
||||
return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DLG_GAMETRAK), h.hWnd, DxDialogProc, (LPARAM)&s);
|
||||
}
|
||||
if (strcmp(dev_type, RealPlayDevice::TypeName()) == 0)
|
||||
{
|
||||
return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DLG_REALPLAY), h.hWnd, DxDialogProc, (LPARAM)&s);
|
||||
}
|
||||
return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DIALOG1), h.hWnd, DxDialogProc, (LPARAM)&s);
|
||||
}
|
||||
|
||||
|
|
|
@ -1002,6 +1002,24 @@ namespace usb_pad
|
|||
return ReadAxisFiltered(port, id);
|
||||
}
|
||||
|
||||
int32_t GetAxisControlUnfiltered(int port, ControlID id)
|
||||
{
|
||||
InputMapped im;
|
||||
if (!GetInputMap(port, id, im))
|
||||
return 0;
|
||||
|
||||
assert(im.index < g_pJoysticks.size());
|
||||
if (im.index >= g_pJoysticks.size())
|
||||
return 0;
|
||||
|
||||
LONG value = 0;
|
||||
if (im.type == MT_AXIS)
|
||||
{
|
||||
value = g_pJoysticks[im.index]->GetAxis(im.mapped);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
//set left/right ffb torque
|
||||
HRESULT SetConstantForce(int port, LONG magnitude)
|
||||
{
|
||||
|
|
|
@ -218,6 +218,7 @@ namespace usb_pad
|
|||
LONG GetAxisValueFromOffset(int axis, const DIJOYSTATE2& j);
|
||||
bool GetControl(int port, int id);
|
||||
float GetAxisControl(int port, ControlID id);
|
||||
int32_t GetAxisControlUnfiltered(int port, ControlID id);
|
||||
void CreateFFB(int port, LPDIRECTINPUTDEVICE8 device, DWORD axis);
|
||||
bool FindFFDevice(int port);
|
||||
bool UpdateFFBSettings(int port, LPDIRECTINPUTDEVICE8 device);
|
||||
|
|
|
@ -57,8 +57,34 @@ namespace usb_pad
|
|||
pad_copy_data(mType, buf, mWheelData);
|
||||
return 5;
|
||||
}
|
||||
|
||||
if (mType == WT_KEYBOARDMANIA_CONTROLLER)
|
||||
else if (mType == WT_GAMETRAK_CONTROLLER)
|
||||
{
|
||||
mWheelData.buttons |= GetControl(mPort, CID_HATLEFT) << 4;
|
||||
mWheelData.clutch = GetAxisControlUnfiltered(mPort, CID_STEERING) >> 4;
|
||||
mWheelData.throttle = GetAxisControlUnfiltered(mPort, CID_STEERING_R) >> 4;
|
||||
mWheelData.brake = GetAxisControlUnfiltered(mPort, CID_THROTTLE) >> 4;
|
||||
mWheelData.hatswitch = GetAxisControlUnfiltered(mPort, CID_BRAKE) >> 4;
|
||||
mWheelData.hat_horz = GetAxisControlUnfiltered(mPort, CID_HATUP) >> 4;
|
||||
mWheelData.hat_vert = GetAxisControlUnfiltered(mPort, CID_HATDOWN) >> 4;
|
||||
pad_copy_data(mType, buf, mWheelData);
|
||||
return 16;
|
||||
}
|
||||
else if (mType >= WT_REALPLAY_RACING && mType <= WT_REALPLAY_POOL)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (GetControl(mPort, i))
|
||||
{
|
||||
mWheelData.buttons |= 1 << i;
|
||||
}
|
||||
}
|
||||
mWheelData.clutch = GetAxisControlUnfiltered(mPort, CID_SQUARE) >> 4;
|
||||
mWheelData.throttle = GetAxisControlUnfiltered(mPort, CID_TRIANGLE) >> 4;
|
||||
mWheelData.brake = GetAxisControlUnfiltered(mPort, CID_CROSS) >> 4;
|
||||
pad_copy_data(mType, buf, mWheelData);
|
||||
return 19;
|
||||
}
|
||||
else if (mType == WT_KEYBOARDMANIA_CONTROLLER)
|
||||
{
|
||||
for (int i = 0; i < 31; i++)
|
||||
{
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#define IDOK2 2
|
||||
#define IDD_DLG_BUZZ 114
|
||||
#define IDD_DLG_KEYBOARDMANIA 115
|
||||
#define IDD_DLG_GAMETRAK 116
|
||||
#define IDD_DLG_REALPLAY 120
|
||||
#define IDD_DIALOG1 202
|
||||
#define IDC_DEL0 1001
|
||||
#define IDC_ASS0 1002
|
||||
|
@ -194,7 +196,7 @@
|
|||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 117
|
||||
#define _APS_NEXT_RESOURCE_VALUE 121
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1137
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
|
|
|
@ -327,6 +327,60 @@ BEGIN
|
|||
PUSHBUTTON "Cancel",IDCANCEL,525,140,50,15
|
||||
END
|
||||
|
||||
IDD_DLG_GAMETRAK DIALOGEX 0, 0, 260, 115
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Gametrak"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
PUSHBUTTON "Left X",IDC_ASS0,10,40,50,14
|
||||
PUSHBUTTON "Left Y",IDC_ASS1,70,40,50,14
|
||||
PUSHBUTTON "Left Z",IDC_ASS2,40,10,50,14
|
||||
PUSHBUTTON "Right X",IDC_ASS3,140,40,50,14
|
||||
PUSHBUTTON "Right Y",IDC_ASS4,200,40,50,14
|
||||
PUSHBUTTON "Right Z",IDC_ASS5,170,10,50,14
|
||||
PUSHBUTTON "Foot Mat",IDC_ASS6,105,70,50,14
|
||||
LTEXT "1/1/1/1",IDC_LABEL0,10,55,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL1,70,55,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL2,40,25,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL3,140,55,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL4,200,55,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL5,170,25,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL6,105,85,55,8
|
||||
DEFPUSHBUTTON "OK",IDOK,145,95,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,200,95,50,14
|
||||
END
|
||||
|
||||
IDD_DLG_REALPLAY DIALOGEX 0, 0, 260, 151
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "RealPlay"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
PUSHBUTTON "Up",IDC_ASS0,40,10,50,14
|
||||
PUSHBUTTON "Down",IDC_ASS1,40,70,50,14
|
||||
PUSHBUTTON "Left",IDC_ASS2,10,40,50,14
|
||||
PUSHBUTTON "Right",IDC_ASS3,70,40,50,14
|
||||
PUSHBUTTON "Red",IDC_ASS4,170,10,50,14
|
||||
PUSHBUTTON "Green",IDC_ASS5,170,70,50,14
|
||||
PUSHBUTTON "Yellow",IDC_ASS6,140,40,50,14
|
||||
PUSHBUTTON "Blue",IDC_ASS7,200,40,50,14
|
||||
PUSHBUTTON "Accel X",IDC_ASS8,45,100,50,14
|
||||
PUSHBUTTON "Accel Y",IDC_ASS9,105,100,50,14
|
||||
PUSHBUTTON "Accel Z",IDC_ASS10,165,100,50,14
|
||||
LTEXT "1/1/1/1",IDC_LABEL0,40,25,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL1,40,85,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL2,10,55,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL3,70,55,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL4,170,25,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL5,170,85,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL6,140,55,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL7,200,55,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL8,45,115,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL9,105,115,55,8
|
||||
LTEXT "1/1/1/1",IDC_LABEL10,165,115,55,8
|
||||
DEFPUSHBUTTON "OK",IDOK,145,130,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,200,130,50,14
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -351,6 +405,14 @@ BEGIN
|
|||
IDD_DLG_KEYBOARDMANIA, DIALOG
|
||||
BEGIN
|
||||
END
|
||||
|
||||
IDD_DLG_GAMETRAK, DIALOG
|
||||
BEGIN
|
||||
END
|
||||
|
||||
IDD_DLG_REALPLAY, DIALOG
|
||||
BEGIN
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
@ -375,6 +437,16 @@ BEGIN
|
|||
0
|
||||
END
|
||||
|
||||
IDD_DLG_GAMETRAK AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
IDD_DLG_REALPLAY AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -59,6 +59,16 @@ namespace usb_pad
|
|||
"",
|
||||
"KONAMI"};
|
||||
|
||||
static const USBDescStrings gametrak_desc_strings = {
|
||||
"",
|
||||
"In2Games Ltd.",
|
||||
"Game-Trak V1.3"};
|
||||
|
||||
static const USBDescStrings realplay_desc_strings = {
|
||||
"",
|
||||
"In2Games",
|
||||
"Real Play"};
|
||||
|
||||
std::list<std::string> PadDevice::ListAPIs()
|
||||
{
|
||||
return RegisterPad::instance().Names();
|
||||
|
@ -102,6 +112,26 @@ namespace usb_pad
|
|||
return PadDevice::LongAPIName(name);
|
||||
}
|
||||
|
||||
std::list<std::string> GametrakDevice::ListAPIs()
|
||||
{
|
||||
return PadDevice::ListAPIs();
|
||||
}
|
||||
|
||||
const TCHAR* GametrakDevice::LongAPIName(const std::string& name)
|
||||
{
|
||||
return PadDevice::LongAPIName(name);
|
||||
}
|
||||
|
||||
std::list<std::string> RealPlayDevice::ListAPIs()
|
||||
{
|
||||
return PadDevice::ListAPIs();
|
||||
}
|
||||
|
||||
const TCHAR* RealPlayDevice::LongAPIName(const std::string& name)
|
||||
{
|
||||
return PadDevice::LongAPIName(name);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void PrintBits(void* data, int size)
|
||||
{
|
||||
|
@ -123,6 +153,19 @@ namespace usb_pad
|
|||
#define DbgPrint(...)
|
||||
#endif //_DEBUG
|
||||
|
||||
uint32_t gametrak_compute_key(uint32_t* key)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
ret = *key << 2 & 0xFC0000;
|
||||
ret |= *key << 17 & 0x020000;
|
||||
ret ^= *key << 16 & 0xFE0000;
|
||||
ret |= *key & 0x010000;
|
||||
ret |= *key >> 9 & 0x007F7F;
|
||||
ret |= *key << 7 & 0x008080;
|
||||
*key = ret;
|
||||
return ret >> 16;
|
||||
};
|
||||
|
||||
typedef struct PADState
|
||||
{
|
||||
USBDevice dev;
|
||||
|
@ -134,6 +177,9 @@ namespace usb_pad
|
|||
{
|
||||
int dev_subtype;
|
||||
} f;
|
||||
uint8_t gametrak_state;
|
||||
uint32_t gametrak_key;
|
||||
uint8_t realplay_state;
|
||||
} PADState;
|
||||
|
||||
typedef struct u_wheel_data_t
|
||||
|
@ -192,6 +238,38 @@ namespace usb_pad
|
|||
case USB_TOKEN_IN:
|
||||
if (devep == 1 && s->pad)
|
||||
{
|
||||
if (s->pad->Type() == WT_GAMETRAK_CONTROLLER)
|
||||
{
|
||||
if (s->gametrak_state == 0)
|
||||
{
|
||||
s->gametrak_state = 1;
|
||||
const unsigned char secret[] = "Gametrak\0\0\0\0\0\0\0\0";
|
||||
memcpy(data, secret, sizeof(secret));
|
||||
usb_packet_copy(p, data, 16);
|
||||
break;
|
||||
}
|
||||
else if (s->gametrak_state == 1)
|
||||
{
|
||||
s->pad->TokenIn(data, p->iov.size);
|
||||
data[0x00] |= s->gametrak_key >> 16 & 1;
|
||||
data[0x02] |= s->gametrak_key >> 17 & 1;
|
||||
data[0x04] |= s->gametrak_key >> 18 & 1;
|
||||
data[0x06] |= s->gametrak_key >> 19 & 1;
|
||||
data[0x08] |= s->gametrak_key >> 20 & 1;
|
||||
data[0x0A] |= s->gametrak_key >> 21 & 1;
|
||||
usb_packet_copy(p, data, 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (s->pad->Type() >= WT_REALPLAY_RACING && s->pad->Type() <= WT_REALPLAY_POOL)
|
||||
{
|
||||
s->pad->TokenIn(data, p->iov.size);
|
||||
// simulate a slight move to avoid a game "protection" : controller disconnected
|
||||
s->realplay_state = !s->realplay_state;
|
||||
data[0] |= s->realplay_state;
|
||||
usb_packet_copy(p, data, 19);
|
||||
break;
|
||||
}
|
||||
ret = s->pad->TokenIn(data, p->iov.size);
|
||||
if (ret > 0)
|
||||
usb_packet_copy(p, data, MIN(ret, (int)sizeof(data)));
|
||||
|
@ -260,11 +338,26 @@ namespace usb_pad
|
|||
ret = sizeof(kbm_hid_report_descriptor);
|
||||
memcpy(data, kbm_hid_report_descriptor, ret);
|
||||
}
|
||||
else
|
||||
else if (t == WT_GENERIC)
|
||||
{
|
||||
ret = sizeof(pad_driving_force_hid_separate_report_descriptor);
|
||||
memcpy(data, pad_driving_force_hid_separate_report_descriptor, ret);
|
||||
}
|
||||
else if (t == WT_BUZZ_CONTROLLER)
|
||||
{
|
||||
ret = sizeof(buzz_hid_report_descriptor);
|
||||
memcpy(data, buzz_hid_report_descriptor, ret);
|
||||
}
|
||||
else if (t == WT_GAMETRAK_CONTROLLER)
|
||||
{
|
||||
ret = sizeof(gametrak_hid_report_descriptor);
|
||||
memcpy(data, gametrak_hid_report_descriptor, ret);
|
||||
}
|
||||
else if (t >= WT_REALPLAY_RACING && t <= WT_REALPLAY_POOL)
|
||||
{
|
||||
ret = sizeof(realplay_hid_report_descriptor);
|
||||
memcpy(data, realplay_hid_report_descriptor, ret);
|
||||
}
|
||||
p->actual_length = ret;
|
||||
break;
|
||||
default:
|
||||
|
@ -273,6 +366,30 @@ namespace usb_pad
|
|||
break;
|
||||
/* hid specific requests */
|
||||
case SET_REPORT:
|
||||
if (t == WT_GAMETRAK_CONTROLLER)
|
||||
{
|
||||
const char secret[] = "Gametrak";
|
||||
if (length == 8 && memcmp(data, secret, 8) == 0)
|
||||
{
|
||||
s->gametrak_state = 0;
|
||||
s->gametrak_key = 0;
|
||||
}
|
||||
else if (length == 2)
|
||||
{
|
||||
if (data[0] == 0x45)
|
||||
{
|
||||
s->gametrak_key = data[1] << 16;
|
||||
}
|
||||
if ((s->gametrak_key >> 16) == data[1])
|
||||
{
|
||||
gametrak_compute_key(&s->gametrak_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "gametrak error : own key = %02x, recv key = %02x\n", s->gametrak_key >> 16, data[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// no idea, Rock Band 2 keeps spamming this
|
||||
if (length > 0)
|
||||
{
|
||||
|
@ -419,6 +536,38 @@ namespace usb_pad
|
|||
buf[3] = (data.buttons >> 8) & 0xff;
|
||||
buf[4] = 0xf0 | ((data.buttons >> 16) & 0xf);
|
||||
break;
|
||||
|
||||
case WT_GAMETRAK_CONTROLLER:
|
||||
memset(buf, 0, 16);
|
||||
buf[0] = data.clutch & 0xfe;
|
||||
buf[1] = data.clutch >> 8;
|
||||
buf[2] = data.throttle & 0xfe;
|
||||
buf[3] = data.throttle >> 8;
|
||||
buf[4] = data.brake & 0xfe;
|
||||
buf[5] = data.brake >> 8;
|
||||
buf[6] = data.hatswitch & 0xfe;
|
||||
buf[7] = data.hatswitch >> 8;
|
||||
buf[8] = data.hat_horz & 0xfe;
|
||||
buf[9] = data.hat_horz >> 8;
|
||||
buf[10] = data.hat_vert & 0xfe;
|
||||
buf[11] = data.hat_vert >> 8;
|
||||
buf[12] = data.buttons;
|
||||
break;
|
||||
|
||||
case WT_REALPLAY_RACING:
|
||||
case WT_REALPLAY_SPHERE:
|
||||
case WT_REALPLAY_GOLF:
|
||||
case WT_REALPLAY_POOL:
|
||||
memset(buf, 0, 19);
|
||||
buf[0] = data.clutch & 0xfe;
|
||||
buf[1] = data.clutch >> 8;
|
||||
buf[2] = data.throttle & 0xff;
|
||||
buf[3] = data.throttle >> 8;
|
||||
buf[4] = data.brake & 0xff;
|
||||
buf[5] = data.brake >> 8;
|
||||
buf[14] = data.buttons;
|
||||
break;
|
||||
|
||||
case WT_SEGA_SEAMIC:
|
||||
buf[0] = data.steering & 0xFF;
|
||||
buf[1] = data.throttle & 0xFF;
|
||||
|
@ -745,13 +894,13 @@ namespace usb_pad
|
|||
if (!proxy)
|
||||
{
|
||||
Console.WriteLn("Buzz: Invalid input API.\n");
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Pad* pad = proxy->CreateObject(port, TypeName());
|
||||
|
||||
if (!pad)
|
||||
return NULL;
|
||||
return nullptr;
|
||||
|
||||
pad->Type(WT_BUZZ_CONTROLLER);
|
||||
PADState* s = new PADState();
|
||||
|
@ -843,4 +992,156 @@ namespace usb_pad
|
|||
return PadDevice::Freeze(mode, dev, data);
|
||||
}
|
||||
|
||||
// ---- Gametrak ----
|
||||
|
||||
USBDevice* GametrakDevice::CreateDevice(int port)
|
||||
{
|
||||
std::string varApi;
|
||||
#ifdef _WIN32
|
||||
std::wstring tmp;
|
||||
LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, tmp);
|
||||
varApi = wstr_to_str(tmp);
|
||||
#else
|
||||
LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, varApi);
|
||||
#endif
|
||||
PadProxyBase* proxy = RegisterPad::instance().Proxy(varApi);
|
||||
if (!proxy)
|
||||
{
|
||||
Console.WriteLn("Gametrak: Invalid input API.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Pad* pad = proxy->CreateObject(port, TypeName());
|
||||
|
||||
if (!pad)
|
||||
return nullptr;
|
||||
|
||||
pad->Type(WT_GAMETRAK_CONTROLLER);
|
||||
PADState* s = new PADState();
|
||||
|
||||
s->desc.full = &s->desc_dev;
|
||||
s->desc.str = gametrak_desc_strings;
|
||||
|
||||
if (usb_desc_parse_dev(gametrak_dev_descriptor, sizeof(gametrak_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(gametrak_config_descriptor, sizeof(gametrak_config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
|
||||
s->f.dev_subtype = pad->Type();
|
||||
s->pad = pad;
|
||||
s->port = port;
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.klass.handle_attach = usb_desc_attach;
|
||||
s->dev.klass.handle_reset = pad_handle_reset;
|
||||
s->dev.klass.handle_control = pad_handle_control;
|
||||
s->dev.klass.handle_data = pad_handle_data;
|
||||
s->dev.klass.unrealize = pad_handle_destroy;
|
||||
s->dev.klass.open = pad_open;
|
||||
s->dev.klass.close = pad_close;
|
||||
s->dev.klass.usb_desc = &s->desc;
|
||||
s->dev.klass.product_desc = s->desc.str[2];
|
||||
|
||||
usb_desc_init(&s->dev);
|
||||
usb_ep_init(&s->dev);
|
||||
pad_handle_reset((USBDevice*)s);
|
||||
|
||||
return (USBDevice*)s;
|
||||
|
||||
fail:
|
||||
pad_handle_destroy((USBDevice*)s);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int GametrakDevice::Configure(int port, const std::string& api, void* data)
|
||||
{
|
||||
auto proxy = RegisterPad::instance().Proxy(api);
|
||||
if (proxy)
|
||||
return proxy->Configure(port, TypeName(), data);
|
||||
return RESULT_CANCELED;
|
||||
}
|
||||
|
||||
int GametrakDevice::Freeze(FreezeAction mode, USBDevice* dev, void* data)
|
||||
{
|
||||
return PadDevice::Freeze(mode, dev, data);
|
||||
}
|
||||
|
||||
// ---- RealPlay ----
|
||||
|
||||
USBDevice* RealPlayDevice::CreateDevice(int port)
|
||||
{
|
||||
std::string varApi;
|
||||
#ifdef _WIN32
|
||||
std::wstring tmp;
|
||||
LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, tmp);
|
||||
varApi = wstr_to_str(tmp);
|
||||
#else
|
||||
LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, varApi);
|
||||
#endif
|
||||
PadProxyBase* proxy = RegisterPad::instance().Proxy(varApi);
|
||||
if (!proxy)
|
||||
{
|
||||
Console.WriteLn("RealPlay: Invalid input API");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Pad* pad = proxy->CreateObject(port, TypeName());
|
||||
|
||||
if (!pad)
|
||||
return nullptr;
|
||||
|
||||
pad->Type((PS2WheelTypes)(WT_REALPLAY_RACING + GetSelectedSubtype(std::make_pair(port, TypeName()))));
|
||||
PADState* s = new PADState();
|
||||
|
||||
s->desc.full = &s->desc_dev;
|
||||
s->desc.str = realplay_desc_strings;
|
||||
|
||||
if (pad->Type() == WT_REALPLAY_RACING && usb_desc_parse_dev(realplay_racing_dev_descriptor, sizeof(realplay_racing_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (pad->Type() == WT_REALPLAY_SPHERE && usb_desc_parse_dev(realplay_sphere_dev_descriptor, sizeof(realplay_sphere_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (pad->Type() == WT_REALPLAY_GOLF && usb_desc_parse_dev(realplay_golf_dev_descriptor, sizeof(realplay_golf_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (pad->Type() == WT_REALPLAY_POOL && usb_desc_parse_dev(realplay_pool_dev_descriptor, sizeof(realplay_pool_dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(realplay_config_descriptor, sizeof(realplay_config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
|
||||
s->f.dev_subtype = pad->Type();
|
||||
s->pad = pad;
|
||||
s->port = port;
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.klass.handle_attach = usb_desc_attach;
|
||||
s->dev.klass.handle_reset = pad_handle_reset;
|
||||
s->dev.klass.handle_control = pad_handle_control;
|
||||
s->dev.klass.handle_data = pad_handle_data;
|
||||
s->dev.klass.unrealize = pad_handle_destroy;
|
||||
s->dev.klass.open = pad_open;
|
||||
s->dev.klass.close = pad_close;
|
||||
s->dev.klass.usb_desc = &s->desc;
|
||||
s->dev.klass.product_desc = s->desc.str[1];
|
||||
|
||||
usb_desc_init(&s->dev);
|
||||
usb_ep_init(&s->dev);
|
||||
pad_handle_reset((USBDevice*)s);
|
||||
|
||||
return (USBDevice*)s;
|
||||
|
||||
fail:
|
||||
pad_handle_destroy((USBDevice*)s);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int RealPlayDevice::Configure(int port, const std::string& api, void* data)
|
||||
{
|
||||
auto proxy = RegisterPad::instance().Proxy(api);
|
||||
if (proxy)
|
||||
return proxy->Configure(port, TypeName(), data);
|
||||
return RESULT_CANCELED;
|
||||
}
|
||||
|
||||
int RealPlayDevice::Freeze(FreezeAction mode, USBDevice* dev, void* data)
|
||||
{
|
||||
return PadDevice::Freeze(mode, dev, data);
|
||||
}
|
||||
|
||||
} // namespace usb_pad
|
||||
|
|
|
@ -111,6 +111,54 @@ namespace usb_pad
|
|||
}
|
||||
};
|
||||
|
||||
class GametrakDevice
|
||||
{
|
||||
public:
|
||||
virtual ~GametrakDevice() {}
|
||||
static USBDevice* CreateDevice(int port);
|
||||
static const TCHAR* Name()
|
||||
{
|
||||
return TEXT("Gametrak Device");
|
||||
}
|
||||
static const char* TypeName()
|
||||
{
|
||||
return "gametrak_device";
|
||||
}
|
||||
static std::list<std::string> ListAPIs();
|
||||
static const TCHAR* LongAPIName(const std::string& name);
|
||||
static int Configure(int port, const std::string& api, void* data);
|
||||
static int Freeze(FreezeAction mode, USBDevice* dev, void* data);
|
||||
static std::vector<std::string> SubTypes()
|
||||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
static void Initialize();
|
||||
};
|
||||
|
||||
class RealPlayDevice
|
||||
{
|
||||
public:
|
||||
virtual ~RealPlayDevice() {}
|
||||
static USBDevice* CreateDevice(int port);
|
||||
static const TCHAR* Name()
|
||||
{
|
||||
return TEXT("RealPlay Device");
|
||||
}
|
||||
static const char* TypeName()
|
||||
{
|
||||
return "realplay_device";
|
||||
}
|
||||
static std::list<std::string> ListAPIs();
|
||||
static const TCHAR* LongAPIName(const std::string& name);
|
||||
static int Configure(int port, const std::string& api, void* data);
|
||||
static int Freeze(FreezeAction mode, USBDevice* dev, void* data);
|
||||
static std::vector<std::string> SubTypes()
|
||||
{
|
||||
return {"RealPlay Racing", "RealPlay Sphere", "RealPlay Golf", "RealPlay Pool"};
|
||||
}
|
||||
static void Initialize();
|
||||
};
|
||||
|
||||
class SeamicDevice
|
||||
{
|
||||
public:
|
||||
|
@ -205,6 +253,11 @@ namespace usb_pad
|
|||
WT_GT_FORCE, //formula gp
|
||||
WT_ROCKBAND1_DRUMKIT,
|
||||
WT_BUZZ_CONTROLLER,
|
||||
WT_GAMETRAK_CONTROLLER,
|
||||
WT_REALPLAY_RACING,
|
||||
WT_REALPLAY_SPHERE,
|
||||
WT_REALPLAY_GOLF,
|
||||
WT_REALPLAY_POOL,
|
||||
WT_SEGA_SEAMIC,
|
||||
WT_KEYBOARDMANIA_CONTROLLER,
|
||||
};
|
||||
|
@ -1455,6 +1508,318 @@ namespace usb_pad
|
|||
0xc0 // END_COLLECTION
|
||||
};
|
||||
|
||||
//////////////
|
||||
// GameTrak //
|
||||
//////////////
|
||||
|
||||
// Product ID :
|
||||
// 0x0982 - PlayStation 2
|
||||
// 0x0984 - ???
|
||||
|
||||
static uint8_t gametrak_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x10, 0x01, // bcdUSB 1.10
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x08, // bMaxPacketSize0 8
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0x82, 0x09, // idProduct 0x0982
|
||||
0x01, 0x00, // bcdDevice 0.01
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t gametrak_config_descriptor[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x22, 0x00, // wTotalLength 34
|
||||
0x01, // bNumInterfaces 1
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration (String Index)
|
||||
0x80, // bmAttributes
|
||||
0x0A, // bMaxPower 20mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x01, // bNumEndpoints 1
|
||||
0x03, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x09, // bLength
|
||||
0x21, // bDescriptorType (HID)
|
||||
0x01, 0x01, // bcdHID 1.01
|
||||
0x00, // bCountryCode
|
||||
0x01, // bNumDescriptors
|
||||
0x22, // bDescriptorType[0] (HID)
|
||||
0x7A, 0x00, // wDescriptorLength[0] 122
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x10, 0x00, // wMaxPacketSize 16
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
};
|
||||
|
||||
static const uint8_t gametrak_hid_report_descriptor[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x04, // Usage (Joystick)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0xA1, 0x00, // Collection (Physical)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x33, // Usage (Rx)
|
||||
0x09, 0x34, // Usage (Ry)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x16, 0x00, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
|
||||
0x36, 0x00, 0x00, // Physical Minimum (0)
|
||||
0x46, 0xFF, 0x0F, // Physical Maximum (4095)
|
||||
0x66, 0x00, 0x00, // Unit (None)
|
||||
0x75, 0x10, // Report Size (16)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, // End Collection
|
||||
0x09, 0x39, // Usage (Hat switch)
|
||||
0x15, 0x01, // Logical Minimum (1)
|
||||
0x25, 0x08, // Logical Maximum (8)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
|
||||
0x75, 0x04, // Report Size (4)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x0C, // Usage Maximum (0x0C)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x0C, // Report Count (12)
|
||||
0x55, 0x00, // Unit Exponent (0)
|
||||
0x65, 0x00, // Unit (None)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x08, // Usage Page (LEDs)
|
||||
0x09, 0x43, // Usage (Slow Blink On Time)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0x09, 0x44, // Usage (Slow Blink Off Time)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0x09, 0x45, // Usage (Fast Blink On Time)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0x09, 0x46, // Usage (Fast Blink Off Time)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
//////////////
|
||||
// RealPlay //
|
||||
//////////////
|
||||
|
||||
// Product ID :
|
||||
// Racing - 0x09B2
|
||||
// Sphere - 0x09B3
|
||||
// Golf - 0x09B5
|
||||
// Pool - 0x09B6
|
||||
|
||||
// RealPlay Golf is dumped from a real controller.
|
||||
// The others were force-brutted to be accepted by games - they may be inaccurate.
|
||||
|
||||
static const uint8_t realplay_racing_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x02, // bcdUSB 2.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0xB2, 0x09, // idProduct 0x09B2
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t realplay_sphere_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x02, // bcdUSB 2.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0xB3, 0x09, // idProduct 0x09B3
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t realplay_golf_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x02, // bcdUSB 2.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0xB5, 0x09, // idProduct 0x09B5
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t realplay_pool_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x02, // bcdUSB 2.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0xB6, 0x09, // idProduct 0x09B6
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t realplay_config_descriptor[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x29, 0x00, // wTotalLength 41
|
||||
0x01, // bNumInterfaces 1
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration (String Index)
|
||||
0x80, // bmAttributes
|
||||
0x32, // bMaxPower 100mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints 2
|
||||
0x03, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x09, // bLength
|
||||
0x21, // bDescriptorType (HID)
|
||||
0x11, 0x01, // bcdHID 1.11
|
||||
0x00, // bCountryCode
|
||||
0x01, // bNumDescriptors
|
||||
0x22, // bDescriptorType[0] (HID)
|
||||
0x85, 0x00, // wDescriptorLength[0] 133
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x02, // bEndpointAddress (OUT/H2D)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
};
|
||||
|
||||
static const uint8_t realplay_hid_report_descriptor[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x05, // Usage (Game Pad)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0xFF, 0x0F, // Physical Maximum (4095)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x75, 0x0C, // Report Size (12)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x75, 0x0C, // Report Size (12)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x75, 0x0C, // Report Size (12)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x20, // Usage (0x20)
|
||||
0x09, 0x21, // Usage (0x21)
|
||||
0x09, 0x22, // Usage (0x22)
|
||||
0x09, 0x23, // Usage (0x23)
|
||||
0x09, 0x24, // Usage (0x24)
|
||||
0x09, 0x25, // Usage (0x25)
|
||||
0x09, 0x26, // Usage (0x26)
|
||||
0x09, 0x27, // Usage (0x27)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x45, 0x01, // Physical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x08, // Usage Maximum (0x08)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x28, // Usage (0x28)
|
||||
0x09, 0x29, // Usage (0x29)
|
||||
0x09, 0x2A, // Usage (0x2A)
|
||||
0x09, 0x2B, // Usage (0x2B)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
struct dfp_buttons_t
|
||||
{
|
||||
uint16_t cross : 1;
|
||||
|
|
Loading…
Reference in New Issue