模拟游戏设备 - Raspberry PI 零

Emulate a Gaming Device - Raspberry PI Zero

嗨,我想将我的 Raspberry PI 零用作 HID 设备(操纵杆)。

当我将 Raspberry PI 零 USB 端口连接到我的电脑时,我希望它显示为操纵杆并向其添加 X 和 Y 轴,我目前设法显示 raspberry pi 零作为键盘并向其发送击键。通过使用 this 页面作为参考,有人知道我的想法是否真的可行吗?

应该可以(但我没有PI硬件来测试)。

您 link 中的报告描述符指定了一个 keyboard-only HID 报告描述符 - 即使标题是 "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-axis 以及 8 个按钮,可能是一个很好的起点:

//--------------------------------------------------------------------------------
// 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键盘,为:

echo 0 > functions/hid.usb0/protocol
echo 0 > functions/hid.usb0/subclass

...表示该设备没有特定的子类(例如 BOOT 设备)或协议(例如键盘或鼠标)。

可能还需要进行其他更改,但正如我所说,我没有可用于试验的硬件。

希望对您有所帮助。