diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 5302af3b8..958d8f4af 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -197,11 +197,43 @@ static void send_hid_report(uint8_t report_id, uint32_t btn) } } break; - default: break; } } +/* use this to send stylus touch signal through USB. */ +static void send_stylus_touch(uint16_t x, uint16_t y, bool state) +{ + // skip if hid is not ready yet + if ( !tud_hid_ready() ) return; + + static bool has_stylus_pen = false; + + hid_stylus_report_t report = + { + .attr = 0, + .x = 0, + .y = 0 + }; + + report.x = x; + report.y = y; + + if (state) + { + report.attr = STYLUS_ATTR_TIP_SWITCH | STYLUS_ATTR_IN_RANGE; + tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + + has_stylus_pen = true; + }else + { + report.attr = 0; + if (has_stylus_pen) tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + has_stylus_pen = false; + } + +} + // Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) // tud_hid_report_complete_cb() is used to send the next report after previous one is complete void hid_task(void) diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index e174db46d..15c6e1f73 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -79,6 +79,7 @@ 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_STYLUS_PEN( HID_REPORT_ID(REPORT_ID_STYLUS_PEN )), TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )), TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD )) }; diff --git a/examples/device/hid_composite/src/usb_descriptors.h b/examples/device/hid_composite/src/usb_descriptors.h index e733d31dd..18d31172b 100644 --- a/examples/device/hid_composite/src/usb_descriptors.h +++ b/examples/device/hid_composite/src/usb_descriptors.h @@ -29,6 +29,7 @@ enum { REPORT_ID_KEYBOARD = 1, REPORT_ID_MOUSE, + REPORT_ID_STYLUS_PEN, REPORT_ID_CONSUMER_CONTROL, REPORT_ID_GAMEPAD, REPORT_ID_COUNT diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index db9a500ee..fb27c0d0e 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -325,6 +325,29 @@ typedef enum /// @} +//--------------------------------------------------------------------+ +// Digitizer Stylus Pen +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Stylus Stylus + * @{ */ + +// Standard Stylus Pen Report. +typedef struct TU_ATTR_PACKED +{ + uint8_t attr; /**< Attribute mask for describing current status of the stylus pen. */ + uint16_t x; /**< Current x position of the mouse. */ + uint16_t y; /**< Current y position of the mouse. */ +} hid_stylus_report_t; + +// Standard Stylus Pen Attributes Bitmap. +typedef enum +{ + STYLUS_ATTR_TIP_SWITCH = TU_BIT(0), ///< Tip switch + STYLUS_ATTR_IN_RANGE = TU_BIT(1), ///< In-range bit. +} hid_stylus_attr_bm_t; + +/// @} + //--------------------------------------------------------------------+ // Keyboard //--------------------------------------------------------------------+ @@ -760,7 +783,9 @@ enum { HID_USAGE_PAGE_PID = 0x0f, HID_USAGE_PAGE_UNICODE = 0x10, HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, + HID_USAGE_PAGE_IN_RANGE = 0x32, HID_USAGE_PAGE_MEDICAL = 0x40, + HID_USAGE_PAGE_TIP_SWITCH = 0x42, HID_USAGE_PAGE_LIGHTING_AND_ILLUMINATION = 0x59, HID_USAGE_PAGE_MONITOR = 0x80, // 0x80 - 0x83 HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 @@ -846,6 +871,15 @@ enum { HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 }; +/// HID Usage Table: Digitizer Page (0x0D) +enum { + // Touch Screen. + HID_USAGE_DIGITIZER_TOUCH_SCREEN = 0x04, + + // Stylus Pen. + HID_USAGE_DIGITIZER_STYLUS = 0x20, +}; + /// HID Usage Table: Consumer Page (0x0C) /// Only contains controls that supported by Windows (whole list is too long) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index eedcba984..b4f24902b 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,6 +194,16 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } +bool tud_hid_n_stylus_report(uint8_t instance, uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y) { + hid_stylus_report_t report = { + .attr = attrs, + .x = x, + .y = y, + }; + + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); +} + //--------------------------------------------------------------------+ // USBD-CLASS API //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index ab2e27373..513d6e996 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -79,6 +79,9 @@ bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t but // use template layout report TUD_HID_REPORT_DESC_GAMEPAD bool tud_hid_n_gamepad_report(uint8_t instance, 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, uint32_t buttons); +// STYLUS PEN: convenient helper to send absolute stylus pen report if application +bool tud_hid_n_stylus_report(uint8_t instance, uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y); + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -114,6 +117,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_gamepad_report(uint8_t report_i return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); } +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_stylus_report(uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y) { + return tud_hid_n_stylus_report(0, report_id, attrs, x, y); +} + //--------------------------------------------------------------------+ // Application Callbacks //--------------------------------------------------------------------+ @@ -257,6 +264,41 @@ void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, u HID_COLLECTION_END , \ HID_COLLECTION_END \ +// Stylus Pen Report Descriptor Template +#define TUD_HID_REPORT_DESC_STYLUS_PEN(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DIGITIZER ) , \ + HID_USAGE ( HID_USAGE_DIGITIZER_TOUCH_SCREEN ) , \ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) , \ + /* Report ID if any */\ + __VA_ARGS__ \ + HID_USAGE ( HID_USAGE_DIGITIZER_STYLUS ) , \ + HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) , \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_TIP_SWITCH ) , \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_IN_RANGE ) , \ + HID_LOGICAL_MIN ( 0 ), \ + HID_LOGICAL_MAX ( 1 ), \ + HID_REPORT_SIZE ( 1 ), \ + HID_REPORT_COUNT( 2 ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \ + HID_REPORT_SIZE ( 1 ), \ + HID_REPORT_COUNT( 6 ), \ + HID_INPUT ( HID_CONSTANT | HID_ARRAY | HID_ABSOLUTE), \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ), \ + HID_PHYSICAL_MAX( 0x7fff ), \ + HID_LOGICAL_MAX ( 0x7fff ), \ + HID_REPORT_SIZE ( 16 ), \ + HID_REPORT_COUNT( 1 ), \ + HID_UNIT_EXPONENT( -1 ), \ + HID_UNIT ( HID_VARIABLE | HID_NONLINEAR ), \ + HID_PHYSICAL_MIN( 0 ), \ + HID_PHYSICAL_MAX( 0 ), \ + HID_USAGE ( HID_USAGE_DESKTOP_X ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \ + HID_USAGE ( HID_USAGE_DESKTOP_Y ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \ + HID_COLLECTION_END , \ + HID_COLLECTION_END \ + // Absolute Mouse Report Descriptor Template #define TUD_HID_REPORT_DESC_ABSMOUSE(...) \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\