Merge pull request #638 from hathach/add-gamepad

Enhance HID Gamepad with DPad/Hat
This commit is contained in:
Ha Thach 2021-02-08 19:40:18 +07:00 committed by GitHub
commit ac4555b361
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 185 additions and 32 deletions

View File

@ -183,6 +183,35 @@ void hid_task(void)
if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2);
has_consumer_key = false;
}
// delay a bit before sending next report
board_delay(10);
}
/*------------- Gamepad -------------*/
if ( tud_hid_ready() )
{
// use to avoid send multiple consecutive zero report for keyboard
static bool has_gamepad_key = false;
hid_gamepad_report_t report =
{
.x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0,
.hat = 0, .buttons = 0
};
if ( btn )
{
report.hat = GAMEPAD_HAT_UP;
tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
has_gamepad_key = true;
}else
{
report.hat = GAMEPAD_HAT_CENTERED;
if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
has_gamepad_key = false;
}
}
}

View File

@ -75,7 +75,8 @@ uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD )),
TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE )),
TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL ))
TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )),
TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD ))
};
// Invoked when received GET HID REPORT DESCRIPTOR
@ -105,7 +106,7 @@ uint8_t const desc_configuration[] =
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
};

View File

@ -30,6 +30,7 @@ enum
REPORT_ID_KEYBOARD = 1,
REPORT_ID_MOUSE,
REPORT_ID_CONSUMER_CONTROL,
REPORT_ID_GAMEPAD
};
#endif /* USB_DESCRIPTORS_H_ */

View File

@ -105,7 +105,7 @@ uint8_t const desc_configuration[] =
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
};

View File

@ -118,7 +118,7 @@ uint8_t const desc_configuration[] =
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
TUD_HID_DESCRIPTOR(ITF_NUM_HID1, 4, HID_PROTOCOL_NONE, sizeof(desc_hid_report1), EPNUM_HID1, CFG_TUD_HID_EP_BUFSIZE, 10),
TUD_HID_DESCRIPTOR(ITF_NUM_HID2, 5, HID_PROTOCOL_NONE, sizeof(desc_hid_report2), EPNUM_HID2, CFG_TUD_HID_EP_BUFSIZE, 10)
};
@ -140,11 +140,11 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
char const* string_desc_arr [] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
"123456", // 3: Serials, should use chip ID
"Keyboard Interface", // 4: Interface 1 String
"Mouse Interface", // 5: Interface 2 String
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
"123456", // 3: Serials, should use chip ID
"Keyboard Interface", // 4: Interface 1 String
"Mouse Interface", // 5: Interface 2 String
};
static uint16_t _desc_str[32];

View File

@ -143,6 +143,97 @@ typedef enum
/** @} */
//--------------------------------------------------------------------+
// GAMEPAD
//--------------------------------------------------------------------+
/** \addtogroup ClassDriver_HID_Gamepad Gamepad
* @{ */
/* From https://www.kernel.org/doc/html/latest/input/gamepad.html
____________________________ __
/ [__ZL__] [__ZR__] \ |
/ [__ TL __] [__ TR __] \ | Front Triggers
__/________________________________\__ __|
/ _ \ |
/ /\ __ (N) \ |
/ || __ |MO| __ _ _ \ | Main Pad
| <===DP===> |SE| |ST| (W) -|- (E) | |
\ || ___ ___ _ / |
/\ \/ / \ / \ (S) /\ __|
/ \________ | LS | ____ | RS | ________/ \ |
| / \ \___/ / \ \___/ / \ | | Control Sticks
| / \_____/ \_____/ \ | __|
| / \ |
\_____/ \_____/
|________|______| |______|___________|
D-Pad Left Right Action Pad
Stick Stick
|_____________|
Menu Pad
Most gamepads have the following features:
- Action-Pad 4 buttons in diamonds-shape (on the right side) NORTH, SOUTH, WEST and EAST.
- D-Pad (Direction-pad) 4 buttons (on the left side) that point up, down, left and right.
- Menu-Pad Different constellations, but most-times 2 buttons: SELECT - START.
- Analog-Sticks provide freely moveable sticks to control directions, Analog-sticks may also
provide a digital button if you press them.
- Triggers are located on the upper-side of the pad in vertical direction. The upper buttons
are normally named Left- and Right-Triggers, the lower buttons Z-Left and Z-Right.
- Rumble Many devices provide force-feedback features. But are mostly just simple rumble motors.
*/
/// HID Gamepad Protocol Report.
typedef struct TU_ATTR_PACKED
{
int8_t x; ///< Delta x movement of left analog-stick
int8_t y; ///< Delta y movement of left analog-stick
int8_t z; ///< Delta z movement of right analog-joystick
int8_t rz; ///< Delta Rz movement of right analog-joystick
int8_t rx; ///< Delta Rx movement of analog left trigger
int8_t ry; ///< Delta Ry movement of analog right trigger
uint8_t hat; ///< Buttons mask for currently pressed buttons in the DPad/hat
uint16_t buttons; ///< Buttons mask for currently pressed buttons
}hid_gamepad_report_t;
/// Standard Gamepad Buttons Bitmap (from Linux input event codes)
typedef enum
{
GAMEPAD_BUTTON_A = TU_BIT(0), ///< A/South button
GAMEPAD_BUTTON_B = TU_BIT(1), ///< B/East button
GAMEPAD_BUTTON_C = TU_BIT(2), ///< C button
GAMEPAD_BUTTON_X = TU_BIT(3), ///< X/North button
GAMEPAD_BUTTON_Y = TU_BIT(4), ///< Y/West button
GAMEPAD_BUTTON_Z = TU_BIT(5), ///< Z button
GAMEPAD_BUTTON_TL = TU_BIT(6), ///< L1 button
GAMEPAD_BUTTON_TR = TU_BIT(7), ///< R1 button
GAMEPAD_BUTTON_TL2 = TU_BIT(8), ///< L2 button
GAMEPAD_BUTTON_TR2 = TU_BIT(9), ///< R2 button
GAMEPAD_BUTTON_SELECT = TU_BIT(10), ///< Select button
GAMEPAD_BUTTON_START = TU_BIT(11), ///< Start button
GAMEPAD_BUTTON_MODE = TU_BIT(12), ///< Mode button
GAMEPAD_BUTTON_THUMBL = TU_BIT(13), ///< L3 button
GAMEPAD_BUTTON_THUMBR = TU_BIT(14), ///< R3 button
//GAMEPAD_BUTTON_ = TU_BIT(15), ///< Undefined button
}hid_gamepad_button_bm_t;
/// Standard Gamepad HAT/DPAD Buttons (from Linux input event codes)
typedef enum
{
GAMEPAD_HAT_CENTERED = 0, ///< DPAD_CENTERED
GAMEPAD_HAT_UP = 1, ///< DPAD_UP
GAMEPAD_HAT_UP_RIGHT = 2, ///< DPAD_UP_RIGHT
GAMEPAD_HAT_RIGHT = 3, ///< DPAD_RIGHT
GAMEPAD_HAT_DOWN_RIGHT = 4, ///< DPAD_DOWN_RIGHT
GAMEPAD_HAT_DOWN = 5, ///< DPAD_DOWN
GAMEPAD_HAT_DOWN_LEFT = 6, ///< DPAD_DOWN_LEFT
GAMEPAD_HAT_LEFT = 7, ///< DPAD_LEFT
GAMEPAD_HAT_UP_LEFT = 8, ///< DPAD_UP_LEFT
}hid_gamepad_hat_t;
/// @}
//--------------------------------------------------------------------+
// MOUSE
//--------------------------------------------------------------------+

View File

@ -107,9 +107,6 @@ bool tud_hid_n_boot_mode(uint8_t itf)
return _hidd_itf[itf].boot_mode;
}
//--------------------------------------------------------------------+
// KEYBOARD API
//--------------------------------------------------------------------+
bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier, uint8_t keycode[6])
{
hid_keyboard_report_t report;
@ -127,10 +124,8 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier,
return tud_hid_n_report(itf, report_id, &report, sizeof(report));
}
//--------------------------------------------------------------------+
// MOUSE APPLICATION API
//--------------------------------------------------------------------+
bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id,
uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal)
{
hid_mouse_report_t report =
{
@ -144,6 +139,24 @@ bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int
return tud_hid_n_report(itf, report_id, &report, sizeof(report));
}
bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id,
int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons)
{
hid_gamepad_report_t report =
{
.x = x,
.y = y,
.z = z,
.rz = rz,
.rx = rx,
.ry = ry,
.hat = hat,
.buttons = buttons,
};
return tud_hid_n_report(itf, report_id, &report, sizeof(report));
}
//--------------------------------------------------------------------+
// USBD-CLASS API
//--------------------------------------------------------------------+

View File

@ -71,6 +71,10 @@ bool tud_hid_n_keyboard_report(uint8_t itf, uint8_t report_id, uint8_t modifier,
// use template layout report as defined by hid_mouse_report_t
bool tud_hid_n_mouse_report(uint8_t itf, uint8_t report_id, uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal);
// Gamepad: convenient helper to send mouse report if application
// use template layout report TUD_HID_REPORT_DESC_GAMEPAD
bool tud_hid_n_gamepad_report(uint8_t itf, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint16_t buttons);
//--------------------------------------------------------------------+
// Application API (Single Port)
//--------------------------------------------------------------------+
@ -119,6 +123,8 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate);
#endif
// TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, );
//--------------------------------------------------------------------+
// Inline Functions
@ -301,14 +307,37 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8
HID_COLLECTION_END \
// Gamepad Report Descriptor Template
// with 16 buttons and 2 joysticks with following layout
// | Button Map (2 bytes) | X | Y | Z | Rz
// with 16 buttons, 2 joysticks and 1 hat/dpad with following layout
// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (2 bytes) |
#define TUD_HID_REPORT_DESC_GAMEPAD(...) \
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ) ,\
HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\
/* Report ID if any */\
__VA_ARGS__ \
/* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_RX ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_RY ) ,\
HID_LOGICAL_MIN ( 0x81 ) ,\
HID_LOGICAL_MAX ( 0x7f ) ,\
HID_REPORT_COUNT ( 6 ) ,\
HID_REPORT_SIZE ( 8 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
/* 8 bit DPad/Hat Button Map */ \
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_HAT_SWITCH ) ,\
HID_LOGICAL_MIN ( 1 ) ,\
HID_LOGICAL_MAX ( 8 ) ,\
HID_PHYSICAL_MIN ( 0 ) ,\
HID_PHYSICAL_MAX_N ( 315, 2 ) ,\
HID_REPORT_COUNT ( 1 ) ,\
HID_REPORT_SIZE ( 8 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
/* 16 bit Button Map */ \
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
HID_USAGE_MIN ( 1 ) ,\
@ -318,17 +347,6 @@ static inline bool tud_hid_mouse_report(uint8_t report_id, uint8_t buttons, int8
HID_REPORT_COUNT ( 16 ) ,\
HID_REPORT_SIZE ( 1 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
/* X, Y, Z, Rz (min -127, max 127 ) */ \
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
HID_LOGICAL_MIN ( 0x81 ) ,\
HID_LOGICAL_MAX ( 0x7f ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_Z ) ,\
HID_USAGE ( HID_USAGE_DESKTOP_RZ ) ,\
HID_REPORT_COUNT ( 4 ) ,\
HID_REPORT_SIZE ( 8 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
HID_COLLECTION_END \
// HID Generic Input & Output