summaryrefslogtreecommitdiff
path: root/src/class
diff options
context:
space:
mode:
authorReinhard Panhuber <[email protected]>2021-02-12 18:05:20 +0100
committerReinhard Panhuber <[email protected]>2021-02-12 18:05:20 +0100
commitcdf600048f717f187243b8118eac43b793c3feec (patch)
tree00d88a8e39560c2e1a35f6c9feb97062733d9d8b /src/class
parent185414721ff549058a199ade40966015e6260996 (diff)
parent09868434cd9f53394350cce682333ada97f796c3 (diff)
Merge remote-tracking branch 'upstream/master' into edpt_ISO_xfer
Diffstat (limited to 'src/class')
-rw-r--r--src/class/dfu/dfu_rt_device.c4
-rw-r--r--src/class/dfu/dfu_rt_device.h2
-rw-r--r--src/class/hid/hid.h91
-rw-r--r--src/class/hid/hid_device.c47
-rw-r--r--src/class/hid/hid_device.h53
-rw-r--r--src/class/hid/hid_host.c6
-rw-r--r--src/class/midi/midi_device.c49
7 files changed, 209 insertions, 43 deletions
diff --git a/src/class/dfu/dfu_rt_device.c b/src/class/dfu/dfu_rt_device.c
index 38644615a..5700615be 100644
--- a/src/class/dfu/dfu_rt_device.c
+++ b/src/class/dfu/dfu_rt_device.c
@@ -26,7 +26,7 @@
#include "tusb_option.h"
-#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RT)
+#if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RUNTIME)
#include "dfu_rt_device.h"
#include "device/usbd_pvt.h"
@@ -110,7 +110,7 @@ bool dfu_rtd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
{
case DFU_REQUEST_DETACH:
tud_control_status(rhport, request);
- tud_dfu_rt_reboot_to_dfu();
+ tud_dfu_runtime_reboot_to_dfu_cb();
break;
case DFU_REQUEST_GETSTATUS:
diff --git a/src/class/dfu/dfu_rt_device.h b/src/class/dfu/dfu_rt_device.h
index 643e25d8f..cff43d035 100644
--- a/src/class/dfu/dfu_rt_device.h
+++ b/src/class/dfu/dfu_rt_device.h
@@ -58,7 +58,7 @@ typedef enum
//--------------------------------------------------------------------+
// Invoked when received new data
-TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); // TODO rename to _cb convention
+TU_ATTR_WEAK void tud_dfu_runtime_reboot_to_dfu_cb(void);
//--------------------------------------------------------------------+
// Internal Class Driver API
diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h
index 8803e4b66..a7db087a7 100644
--- a/src/class/hid/hid.h
+++ b/src/class/hid/hid.h
@@ -144,6 +144,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
//--------------------------------------------------------------------+
/** \addtogroup ClassDriver_HID_Mouse Mouse
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index 1f03f8862..4cdcecc9e 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -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
//--------------------------------------------------------------------+
@@ -368,14 +381,24 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
uint8_t itf = 0;
hidd_interface_t * p_hid = _hidd_itf;
- for ( ; ; itf++, p_hid++)
+ // Identify which interface to use
+ for (itf = 0; itf < CFG_TUD_HID; itf++)
{
- if (itf >= TU_ARRAY_SIZE(_hidd_itf)) return false;
-
- if ( ep_addr == p_hid->ep_out ) break;
+ p_hid = &_hidd_itf[itf];
+ if ( (ep_addr == p_hid->ep_out) || (ep_addr == p_hid->ep_in) ) break;
}
+ TU_ASSERT(itf < CFG_TUD_HID);
- if (ep_addr == p_hid->ep_out)
+ // Sent report successfully
+ if (ep_addr == p_hid->ep_in)
+ {
+ if (tud_hid_report_complete_cb)
+ {
+ tud_hid_report_complete_cb(itf, p_hid->epin_buf, (uint8_t) xferred_bytes);
+ }
+ }
+ // Received report
+ else if (ep_addr == p_hid->ep_out)
{
tud_hid_set_report_cb(
#if CFG_TUD_HID > 1
diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h
index 456b011ba..d5de53221 100644
--- a/src/class/hid/hid_device.h
+++ b/src/class/hid/hid_device.h
@@ -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,11 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t idle_rate);
#endif
+// Invoked when sent REPORT successfully to host
+// Application can use this to send the next report
+// Note: For composite reports, report[0] is report ID
+TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t itf, uint8_t const* report, uint8_t len);
+
//--------------------------------------------------------------------+
// Inline Functions
@@ -301,14 +310,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 +350,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
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index a96eb6276..64d1b8e5d 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -39,6 +39,7 @@ typedef struct {
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out;
+ bool valid;
uint16_t report_size;
}hidh_interface_t;
@@ -53,6 +54,7 @@ static inline bool hidh_interface_open(uint8_t rhport, uint8_t dev_addr, uint8_t
p_hid->ep_in = p_endpoint_desc->bEndpointAddress;
p_hid->report_size = p_endpoint_desc->wMaxPacketSize.size; // TODO get size from report descriptor
p_hid->itf_num = interface_number;
+ p_hid->valid = true;
return true;
}
@@ -246,14 +248,14 @@ bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num)
usbh_driver_set_config_complete(dev_addr, itf_num);
#if CFG_TUH_HID_KEYBOARD
- if ( keyboardh_data[dev_addr-1].itf_num == itf_num)
+ if (( keyboardh_data[dev_addr-1].itf_num == itf_num) && keyboardh_data[dev_addr-1].valid)
{
tuh_hid_keyboard_mounted_cb(dev_addr);
}
#endif
#if CFG_TUH_HID_MOUSE
- if ( mouseh_data[dev_addr-1].ep_in == itf_num )
+ if (( mouseh_data[dev_addr-1].ep_in == itf_num ) && mouseh_data[dev_addr-1].valid)
{
tuh_hid_mouse_mounted_cb(dev_addr);
}
diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c
index ce4c9cafe..b9d6b2efc 100644
--- a/src/class/midi/midi_device.c
+++ b/src/class/midi/midi_device.c
@@ -85,6 +85,32 @@ bool tud_midi_n_mounted (uint8_t itf)
return midi->ep_in && midi->ep_out;
}
+static void _prep_out_transaction (midid_interface_t* p_midi)
+{
+ uint8_t const rhport = TUD_OPT_RHPORT;
+ uint16_t available = tu_fifo_remaining(&p_midi->rx_ff);
+
+ // Prepare for incoming data but only allow what we can store in the ring buffer.
+ // TODO Actually we can still carry out the transfer, keeping count of received bytes
+ // and slowly move it to the FIFO when read().
+ // This pre-check reduces endpoint claiming
+ TU_VERIFY(available >= sizeof(p_midi->epout_buf), );
+
+ // claim endpoint
+ TU_VERIFY(usbd_edpt_claim(rhport, p_midi->ep_out), );
+
+ // fifo can be changed before endpoint is claimed
+ available = tu_fifo_remaining(&p_midi->rx_ff);
+
+ if ( available >= sizeof(p_midi->epout_buf) ) {
+ usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, sizeof(p_midi->epout_buf));
+ }else
+ {
+ // Release endpoint since we don't make any transfer
+ usbd_edpt_release(rhport, p_midi->ep_out);
+ }
+}
+
//--------------------------------------------------------------------+
// READ API
//--------------------------------------------------------------------+
@@ -135,12 +161,17 @@ uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bu
void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id)
{
(void) jack_id;
- tu_fifo_clear(&_midid_itf[itf].rx_ff);
+ midid_interface_t* p_midi = &_midid_itf[itf];
+ tu_fifo_clear(&p_midi->rx_ff);
+ _prep_out_transaction(p_midi);
}
bool tud_midi_n_receive (uint8_t itf, uint8_t packet[4])
{
- return tu_fifo_read_n(&_midid_itf[itf].rx_ff, packet, 4);
+ midid_interface_t* p_midi = &_midid_itf[itf];
+ uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4);
+ _prep_out_transaction(p_midi);
+ return (num_read == 4);
}
void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) {
@@ -192,6 +223,7 @@ uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, u
if (midi->write_buffer[0] == 0x4) {
if (data == 0xf7) {
midi->write_buffer[0] = 0x5;
+ midi->write_target_length = 2;
} else {
midi->write_target_length = 4;
}
@@ -274,8 +306,8 @@ void midid_init(void)
midid_interface_t* midi = &_midid_itf[i];
// config fifo
- tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, true);
- tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, true);
+ tu_fifo_config(&midi->rx_ff, midi->rx_ff_buf, CFG_TUD_MIDI_RX_BUFSIZE, 1, false); // true, true
+ tu_fifo_config(&midi->tx_ff, midi->tx_ff_buf, CFG_TUD_MIDI_TX_BUFSIZE, 1, false); // OBVS.
#if CFG_FIFO_MUTEX
tu_fifo_config_mutex(&midi->rx_ff, osal_mutex_create(&midi->rx_ff_mutex));
@@ -366,11 +398,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
}
// Prepare for incoming data
- if ( !usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE) )
- {
- TU_LOG1_FAILED();
- TU_BREAKPOINT();
- }
+ _prep_out_transaction(p_midi);
return drv_len;
}
@@ -391,6 +419,7 @@ bool midid_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t
bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
{
(void) result;
+ (void) rhport;
uint8_t itf;
midid_interface_t* p_midi;
@@ -414,7 +443,7 @@ bool midid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32
// prepare for next
// TODO for now ep_out is not used by public API therefore there is no race condition,
// and does not need to claim like ep_in
- TU_ASSERT(usbd_edpt_xfer(rhport, p_midi->ep_out, p_midi->epout_buf, CFG_TUD_MIDI_EP_BUFSIZE), false);
+ _prep_out_transaction(p_midi);
}
else if ( ep_addr == p_midi->ep_in )
{