模拟游戏设备 - Raspberry PI Zero [英] Emulate a Gaming Device - Raspberry PI Zero
问题描述
我想将我的 Raspberry PI Zero 用作 HID 设备(操纵杆).
Hi I want to use my Raspberry PI Zero as a HID Device (Joystick).
当我将 Raspberry PI Zero USB 端口连接到我的 PC 时,我希望它显示为操纵杆并添加 X &Y 轴,我目前设法将树莓派零显示为键盘并向其发送击键.通过使用 this 页面作为参考,有人知道我的想法是否真的可行吗?
When I connect my Raspberry PI Zero USB port to my PC I want it to show up as a joystick and add X & Y Axis to it, I currently managed to show the raspberry pi zero as a keyboard and send keystrokes to it. By using this page as reference, Anyone knows if my idea is actually possible?
推荐答案
应该是可以的(但我没有 PI 硬件来测试它).
It should be possible (but I don't have the PI hardware to test it on).
链接中的报告描述符指定了仅限键盘的 HID 报告描述符 - 即使标题是键盘/鼠标/操纵杆 (HID)":
The report descriptor in your link specifies a keyboard-only HID report descriptor - even though the heading is "Keyboard / Mouse / Joystick (HID)":
echo -ne \x05\x01\x09\x06\xa1\x01\x05\x07\x19\xe0\x29\xe7\x15\x00
\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x03
\x95\x05\x75\x01\x05\x08\x19\x01\x29\x05\x91\x02\x95\x01
\x75\x03\x91\x03\x95\x06\x75\x08\x15\x00\x25\x65\x05\x07
\x19\x00\x29\x65\x81\x00\xc0 > functions/hid.usb0/report_desc
...解码为:
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
09 06 (LOCAL) USAGE 0x00010006 Keyboard (CA=Application Collection)
A1 01 (MAIN) COLLECTION 0x00000001 Application (Usage=0x00010006: Page=Generic Desktop Page, Usage=Keyboard, Type=CA)
05 07 (GLOBAL) USAGE_PAGE 0x0007 Keyboard/Keypad Page
19 E0 (LOCAL) USAGE_MINIMUM 0x000700E0 Keyboard Left Control (DV=Dynamic Value)
29 E7 (LOCAL) USAGE_MAXIMUM 0x000700E7 Keyboard Right GUI (DV=Dynamic Value)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
95 08 (GLOBAL) REPORT_COUNT 0x08 (8) Number of fields
81 02 (MAIN) INPUT 0x00000002 (8 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
81 03 (MAIN) INPUT 0x00000003 (1 field x 8 bits) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
95 05 (GLOBAL) REPORT_COUNT 0x05 (5) Number of fields
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
05 08 (GLOBAL) USAGE_PAGE 0x0008 LED Indicator Page
19 01 (LOCAL) USAGE_MINIMUM 0x00080001 Num Lock (OOC=On/Off Control)
29 05 (LOCAL) USAGE_MAXIMUM 0x00080005 Kana (OOC=On/Off Control)
91 02 (MAIN) OUTPUT 0x00000002 (5 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
95 01 (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields
75 03 (GLOBAL) REPORT_SIZE 0x03 (3) Number of bits per field
91 03 (MAIN) OUTPUT 0x00000003 (1 field x 3 bits) 1=Constant 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
95 06 (GLOBAL) REPORT_COUNT 0x06 (6) Number of fields
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14
25 65 (GLOBAL) LOGICAL_MAXIMUM 0x65 (101)
05 07 (GLOBAL) USAGE_PAGE 0x0007 Keyboard/Keypad Page
19 00 (LOCAL) USAGE_MINIMUM 0x00070000 Keyboard No event indicated (Sel=Selector)
29 65 (LOCAL) USAGE_MAXIMUM 0x00070065 Keyboard Application (Sel=Selector)
81 00 (MAIN) INPUT 0x00000000 (6 fields x 8 bits) 0=Data 0=Array 0=Absolute
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Keyboard/Keypad Page inputReport (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
// No REPORT ID byte
// Collection: Keyboard
uint8_t KB_KeyboardKeyboardLeftControl : 1; // Usage 0x000700E0: Keyboard Left Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftShift : 1; // Usage 0x000700E1: Keyboard Left Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftAlt : 1; // Usage 0x000700E2: Keyboard Left Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftGui : 1; // Usage 0x000700E3: Keyboard Left GUI, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightControl : 1; // Usage 0x000700E4: Keyboard Right Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightShift : 1; // Usage 0x000700E5: Keyboard Right Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightAlt : 1; // Usage 0x000700E6: Keyboard Right Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightGui : 1; // Usage 0x000700E7: Keyboard Right GUI, Value = 0 to 1
uint8_t pad_2; // Pad
uint8_t KB_Keyboard[6]; // Value = 0 to 101
} inputReport_t;
//--------------------------------------------------------------------------------
// LED Indicator Page outputReport (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
// No REPORT ID byte
// Collection: Keyboard
uint8_t LED_KeyboardNumLock : 1; // Usage 0x00080001: Num Lock, Value = 0 to 1
uint8_t LED_KeyboardCapsLock : 1; // Usage 0x00080002: Caps Lock, Value = 0 to 1
uint8_t LED_KeyboardScrollLock : 1; // Usage 0x00080003: Scroll Lock, Value = 0 to 1
uint8_t LED_KeyboardCompose : 1; // Usage 0x00080004: Compose, Value = 0 to 1
uint8_t LED_KeyboardKana : 1; // Usage 0x00080005: Kana, Value = 0 to 1
uint8_t : 3; // Pad
} outputReport_t;
我认为至少需要更改 HID 报告描述符字节以指定操纵杆报告而不是键盘报告.有很多替代方案,但类似于以下定义了 8 位 x 轴和 y 轴以及 8 个按钮的内容可能是一个不错的起点:
I think at least the HID report descriptor bytes would need to be changed to specify a joystick report rather than a keyboard report. There are many alternatives, but something like the following, which defines an 8-bit x- and y-axis and 8 buttons, could be a good place to start:
//--------------------------------------------------------------------------------
// Decoded Application Collection
//--------------------------------------------------------------------------------
/*
05 01 (GLOBAL) USAGE_PAGE 0x0001 Generic Desktop Page
09 04 (LOCAL) USAGE 0x00010004 Joystick (CA=Application Collection)
A1 01 (MAIN) COLLECTION 0x00000001 Application (Usage=0x00010004: Page=Generic Desktop Page, Usage=Joystick, Type=CA)
15 81 (GLOBAL) LOGICAL_MINIMUM 0x81 (-127)
25 7F (GLOBAL) LOGICAL_MAXIMUM 0x7F (127)
09 01 (LOCAL) USAGE 0x00010001 Pointer (CP=Physical Collection)
A1 00 (MAIN) COLLECTION 0x00000000 Physical (Usage=0x00010001: Page=Generic Desktop Page, Usage=Pointer, Type=CP)
09 30 (LOCAL) USAGE 0x00010030 X (DV=Dynamic Value)
09 31 (LOCAL) USAGE 0x00010031 Y (DV=Dynamic Value)
75 08 (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field
95 02 (GLOBAL) REPORT_COUNT 0x02 (2) Number of fields
81 02 (MAIN) INPUT 0x00000002 (2 fields x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Physical
05 09 (GLOBAL) USAGE_PAGE 0x0009 Button Page
19 01 (LOCAL) USAGE_MINIMUM 0x00090001 Button 1 Primary/trigger (MULTI=Selector, On/Off, Momentary, or One Shot)
29 08 (LOCAL) USAGE_MAXIMUM 0x00090008 Button 8 (MULTI=Selector, On/Off, Momentary, or One Shot)
15 00 (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Info: Consider replacing 15 00 with 14
25 01 (GLOBAL) LOGICAL_MAXIMUM 0x01 (1)
75 01 (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field
95 08 (GLOBAL) REPORT_COUNT 0x08 (8) Number of fields
81 02 (MAIN) INPUT 0x00000002 (8 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap
C0 (MAIN) END_COLLECTION Application
*/
//--------------------------------------------------------------------------------
// Generic Desktop Page inputReport (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
// No REPORT ID byte
// Collection: Joystick Pointer
int8_t GD_JoystickPointerX; // Usage 0x00010030: X, Value = -127 to 127
int8_t GD_JoystickPointerY; // Usage 0x00010031: Y, Value = -127 to 127
// Collection: Joystick
uint8_t BTN_JoystickButton1 : 1; // Usage 0x00090001: Button 1 Primary/trigger, Value = 0 to 1
uint8_t BTN_JoystickButton2 : 1; // Usage 0x00090002: Button 2 Secondary, Value = 0 to 1
uint8_t BTN_JoystickButton3 : 1; // Usage 0x00090003: Button 3 Tertiary, Value = 0 to 1
uint8_t BTN_JoystickButton4 : 1; // Usage 0x00090004: Button 4, Value = 0 to 1
uint8_t BTN_JoystickButton5 : 1; // Usage 0x00090005: Button 5, Value = 0 to 1
uint8_t BTN_JoystickButton6 : 1; // Usage 0x00090006: Button 6, Value = 0 to 1
uint8_t BTN_JoystickButton7 : 1; // Usage 0x00090007: Button 7, Value = 0 to 1
uint8_t BTN_JoystickButton8 : 1; // Usage 0x00090008: Button 8, Value = 0 to 1
} inputReport_t;
您可能还需要更改:
echo 1 > functions/hid.usb0/protocol
echo 1 > functions/hid.usb0/subclass
...它定义了一个 BOOT 键盘,以:
...which defines a BOOT keyboard, to:
echo 0 > functions/hid.usb0/protocol
echo 0 > functions/hid.usb0/subclass
...表示设备没有特定的子类(例如 BOOT 设备)或协议(例如键盘或鼠标).
...which says that the device has no specific subclass (e.g. BOOT device) or protocol (e.g. keyboard or mouse).
可能还需要进行其他更改,但正如我所说,我没有可以试验的硬件.
There may be other changes necessary but, as I said, I don't have the hardware to experiment with.
我希望这会有所帮助.
这篇关于模拟游戏设备 - Raspberry PI Zero的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!