Haptic Pen Implementation Guide
This document details the protocol implementation for a Haptic Pen device connecting to a compatible Windows 11 host. This does not include guidance on mechanical constraints, electrical constraints or component selection for generating the haptic response within the pen transducer. This implementation guidance is agnostic of the pen protocol used between the pen transducer and pen digitizer, however an implementation may elect to use a pen protocol with an uplink capability which enables the pen digitizer to provide additional parameters to the pen transducer for the purposes of modulating haptic response.
Device Class
Haptic Pen is an extension of the Pen Device class on Windows. This implementation guide adds to the Pen Implementation Guide and focuses on implementing haptics within the pen transducer, so haptic pens must meet the requirements in Pen Implementation Guide in addition to those contained here.
Device Bus Connectivity
The Haptic Pen shall use the Microsoft provided inbox drivers to connect to a Windows host using HID over Bluetooth.
Haptic Pen Protocol Implementation
A good understanding of the HID protocol is needed to be able to understand the information presented here. See the following resources for information about the HID protocol:
Windows includes a HID class driver and corresponding HID Bluetooth-enabled miniport driver, therefore there is no need for any third-party mini-port drivers. Haptic pen device firmware only needs to report the usages described in this topic. Windows will use the firmware and its own HID drivers to enable the device and give Windows applications access to the device.
A sample descriptor is provided in the Sample Report Descriptors section below.
Required Top Level HID Collection
A Haptic Pen device should use the HID protocol on a Windows 10 system in such a way that the device provides a top-level collection that appears as a digitizer/stylus (Page 0x0D, Usage 0x20).
Pen Digitizer Input Report
The pen digitizer collection must report the stylus identifier consisting of the transducer serial number and transducer Vendor ID in the input reports reported to the OS. The same stylus identifier must be reported through the stylus collection. This enables the OS to correlate the pen input generated by the digitizer to the stylus. Details on the pen implementation guide can be found here: Pen Protocol Implementation.
Transducer Serial Number
The Transducer Serial Number is a unique persistent identifier for the transducer used in the pen accessory communicating with the pen digitizer. This is required to be 32-bits and is defined by the vendor or entity identified by the transducer vendor ID. In circumstances where the Transducer Serial Number is unknown to the digitizer either because the pen accessory does not support transmitting this value or that the transmission has not been received in full, the digitizer shall report 0 to the host. Null position is not supported by the host.
Transducer Serial Number – Part 2
Transducer Serial Number – Part 2 allows for an additional 32-bits to be specified as part of the unique persistent identifier for the transducer used in a pen accessory. In circumstances where the Transducer Serial Number – Part 2 is unknown to the digitizer either because the pen accessory does not support transmitting this value or that the transmission has not been received in full, the digitizer shall report 0 to the host. Null position is not supported by the host.
Page | ID | Notes |
---|---|---|
0xD | 0x5B | Mandatory for features dependent on unique pen identification (see below) |
0xD | 0x6E | Optional extension of the serial number by an additional 32 bits |
Transducer Vendor ID
The Transducer Vendor ID is a field for communicating the manufacturer of the transducer used in the pen accessory communicating with the pen digitizer. This is required to be a 2-byte USB-IF assigned vendor ID either of the manufacturer or that of the IHV/OEM authorizing the use of their USB-IF vendor ID for this purpose.
Page | ID | Notes |
---|---|---|
0xD | 0x91 | Mandatory for features dependent on unique pen identification (see below) |
Features Dependent On Unique Pen Identification
Reporting PenID is mandatory to enable scenarios such as pen haptics (required for haptic features in this guide).
It is also mandatory for scenarios which use multiple pens for inking. For example:
- Whiteboard app on windows supports multiple pen usage where each pen can be mapped to a certain inking tool
- In general, apps that want to assign attributes or behaviors to different physical pens, even though the digitizer may only support a single pen on screen at the time
- Apps which want to track multiple simultaneous pens on supported digitizers
Haptic Output Report
If a pen device supports haptic feedback, it can allow the system and applications to take advantage of it by including a haptic feedback collection (Page 0x0E, Usage 0x01) within the stylus TLC. For more information on how the HID specification supports haptic feedback, please consult the Haptics page ratification to the HID specification.
The host uses the following usages in an output report (through the haptic feedback collection) to allow the host to issue haptic feedback events to the haptic pen device. If a device chooses to expose a haptic feedback collection, some usages are mandatory to allow host-initiated haptic feedback to be supported.
Member | Description | Page | ID | Mandatory/Optional |
---|---|---|---|---|
Waveform List | Ordered list of haptic waveforms supported by the device | 0x0E | 0x10 | Mandatory |
Duration List | Ordered list of durations for waveforms in the Waveform List | 0x0E | 0x11 | Mandatory |
Auto Trigger | Waveform to fire automatically at device's discretion | 0x0E | 0x20 | Mandatory |
Auto Trigger Associated Control | HID usage of the control associated with haptic feedback | 0x0E | 0x22 | Mandatory |
Intensity | Output - Intensity of Manual Trigger waveform as a percentage | 0x0E | 0x23 | Optional |
Repeat Count | Output - Number of times to play Manual Trigger waveform after initial play | 0x0E | 0x24 | Optional |
Retrigger Period | Output - Duration of time to wait before re-triggering Manual Trigger when repeating | 0x0E | 0x25 | Optional |
Waveform Cutoff Time | Max time a Manual Trigger waveform can play before being cut off | 0x0E | 0x28 | Optional |
Waveform List
Waveform List usage represents a collection of the HID usages of supported waveforms, ordered using ordinals. The pre-defined haptics waveforms are defined in the HID specification. For pen haptic devices, these waveforms can be classified as two segments that correspond to different scenarios:
- WAVEFORM_*CONTINOUS - Ink based feedback for simulating various textures while the user is actively inking with different tools such as pen, pencil etc.
- WAVEFORM_* - Discrete, non-continuous interaction-based feedback for when a user performs some input driven task such as hovering over a button, clicking a disabled button, and successful ink shape recognition.
The full list of waveforms supported for pen haptic devices is below:
Waveform | Description | Page | ID | Mandatory/Optional |
---|---|---|---|---|
WAVEFORM_NONE | No-op. Should not impact the play state of ongoing waveforms | 0x0E | 0x1001 | Mandatory |
WAVEFORM_STOP | Stops the playback of ongoing waveforms | 0x0E | 0x1002 | Mandatory |
WAVEFORM_CLICK | Creates a short “click” feedback. Default fallback when interaction feedback waveform selected by the app is not supported by haptic pen | 0x0E | 0x1003 | Mandatory |
WAVEFORM_INKCONTINUOUS | Simulates the feel of inking with a physical ball point pen. Default fall back when an inking waveform is not supported by haptic pen | 0x0E | 0x100B | Mandatory |
WAVEFORM_SUCCESS | Strong haptic signal to alert user an action has succeeded | 0x0E | 0x1009 | Optional |
WAVEFORM_ERROR | Strong haptic signal to alert user an action has failed, or an error has occurred | 0x0E | 0x100A | Optional |
WAVEFORM_HOVER | Haptic signal when user hovers over an interactive UI element with a haptic pen | 0x0E | 0x1008 | Optional |
WAVEFORM_PRESS | Haptic signal for when a user presses an interactive UI element in an incremental action (see Release) | 0x0E | 0x1006 | Optional |
WAVEFORM_RELEASE | Haptic signal for when a user releases an interactive UI element in an incremental action (see Press) | 0x0E | 0x1007 | Optional |
WAVEFORM_PENCILCONTINUOUS | Continuous haptic signal when user selects pencil as inking tool | 0x0E | 0x100C | Optional |
WAVEFORM_MARKERCONTINUOUS | Continuous haptic signal when user selects marker as inking tool | 0x0E | 0x100D | Optional |
WAVEFORM_CHISELMARKERCONTINUOUS | Continuous haptic signal when user selects chisel marker/highlighter as inking tool | 0x0E | 0x100E | Optional |
WAVEFORM_BRUSHCONTINUOUS | Continuous haptic signal when user selects brush as inking tool | 0x0E | 0x100F | Optional |
WAVEFORM_ERASERCONTINUOUS | Continuous haptic signal when user selects eraser as inking tool | 0x0E | 0x1010 | Optional |
WAVEFORM_SPARKLECONTINUOUS | Continuous haptic signal for special ink tools, such as a multi-colored brush | 0x0E | 0x1011 | Optional |
Note
While not required, it is encouraged to also implement the other enumerated waveforms in order to provide a more complete user experience. In particular, WAVEFORM_PRESS and WAVEFORM_RELEASE are highly recommended as they provide valuable interaction feedback.
Both WAVEFORM_NONE and WAVEFORM_STOP are required for all HID-compliant haptics devices. Ordinals 1 and 2 are implicitly set to WAVEFORM_NONE and WAVEFORM_STOP. They do not need to be declared in the Waveform List or Duration List. The Waveform List declares supported waveforms by the physical minimum and maximum of each ordinal in the list.
Duration List
Duration List usage represents a collection of the durations for the supported waveforms in the Waveform list, ordered using ordinals. The unit for waveform duration is milliseconds, and duration must be a positive non-zero value for any non-continuous waveform. If a waveform is continuous (will play until stopped by the host or the Waveform Cutoff Time is exceeded), then its duration is defined as zero.
WAVEFORM_NONE and WAVEFORM_STOP are assumed to have a duration of zero. They do not need to be declared in the Duration List.
Intensity
The Intensity usage represents the percentage of maximum intensity to apply to a waveform. This value should vary between 0 and 100 percent. 100 percent indicates waveforms will be triggered by the device at their maximum strength, and 0 percent indicates the haptic transducer is not enabled.
Repeat Count
The Repeat Count usage represents the number of times to repeat a waveform. A Repeat Count of zero indicates the Manual Trigger waveform should only be played a single time (no repeat). If the Waveform Cutoff Time has been exceeded, it is expected that any incomplete repeats will be ignored.
Retrigger Period
The Retrigger Period usage represents the amount of time for the device to wait before repeating a Manual Trigger waveform in an output report, per the value specified by Repeat Count. The units for this value are milliseconds. If the Retrigger Period is smaller than the duration of the waveform being played, the waveform should be stopped and restarted at the time period indicated by the retrigger period.
Waveform Cutoff Time
The Waveform Cutoff Time usage represents the maximum amount of time the device will allow a Manual Trigger waveform to be repeated before ending playback. This is a constant value for the device and includes both continuous waveforms without set durations, and waveforms with discrete durations which are set to repeat many times. The units for this value are milliseconds.
Haptic Output Report
The host uses the following usages in an output report to issue haptic feedback events to the Haptic Pen device. Some usages are Mandatory for compatibility with the Windows host implementation.
Member | Description | Page | ID | Mandatory/Optional |
---|---|---|---|---|
Manual Trigger | Waveform to fire as explicit command from the host | 0x0E | 0x21 | Mandatory |
Intensity | Intensity of Manual Trigger waveform as a percentage | 0x0E | 0x23 | Mandatory |
Repeat Count | Number of times to play Manual Trigger waveform after initial play | 0x0E | 0x24 | Optional |
Retrigger Period | Duration of time to wait before retriggering Manual Trigger when repeating | 0x0E | 0x25 | Optional |
Manual Trigger
The Manual Trigger usage represents a supported waveform usage from the waveform list which has been requested to be played by the host. When an output report containing a Manual Trigger other than WAVEFORM_NONE is sent to the device, it should immediately begin playing the specified waveform with the additional properties included in the output report (Intensity, Repeat Count, Retrigger Period). When an output report contains a Manual Trigger of WAVEFORM_STOP, any ongoing waveform playback should be stopped.
For Intensity, Repeat Count, and Retrigger Period usages, please see the previous section with respect to the output feature report.
Starting and Stopping Haptics
The flowchart below describes when the pen’s haptic signals should be configured, cleared, started, and stopped.
The various haptics states described below are:
- Playing: The pen is actively playing the haptic waveform
- Paused: The pen is configured with a waveform, but is not actively playing it
- Stopped: The pen is not configured with a waveform and is not actively playing anything
For the pen state with respect to the digitzer, please refer to Windows Pen States.
Note
When the pen goes out of range it’s recommended, but not required, to clear the haptic configuration. This is conveyed in the diagram below by the two alternate paths exiting from the "Pen: In range; Haptics: Paused" state when the pen goes out of range.
Note
The host at any time may request for a non-continuous waveform to be played. In that event, the pen should play it and then return to the state it was previously in.
Note
The host shall only configure continuous waveforms. Discrete/non-continuous waveforms shall only be manually triggered.
Keyboard Collection (Optional)
An optional feature to enable reporting of tail-end button clicks to the host via HID keyboard reports.
A compatible device shall report 3 distinct keyboard combinations corresponding to 3 distinct button actions via a HID Bluetooth keyboard device exposed to the host. The actions and corresponding keyboard combinations are outlined below:
Button Action | Key Combination |
---|---|
Single Click | WIN+F20 |
Double Click | WIN+F19 |
Press and Hold | Win+F18 |
Bluetooth Button Implementation
To implement a tail-end Bluetooth button, the device will report 3 distinct keyboard combinations corresponding to 3 distinct button actions via a HID Bluetooth LE keyboard device exposed to the host. The actions and corresponding keyboard combinations are outlined below:
Bluetooth Button Action | Key Combination to Report |
---|---|
Single-click | WIN+F20 |
Double-click | WIN+F19 |
Press and hold | WIN+F18 |
Pen Stowage
Starting with Windows 10, version 1903, Windows supports notifications for devices incorporating compatible pen stowage. The mechanism relies on the hardware detecting the pen being removed or replaced and generating a corresponding HID keyboard report for a pair of shortcut combinations. To signal a dock (pen replaced in stowage), report WIN+CTRL+F20 and to signal an undock (pen removed from stowage), report WIN+CTRL+F19. This can be implemented with firmware or a driver.
These undock/dock events bring-up/dismiss the Shell ink workspace menu. Starting with Windows 10, version 2004 Office also reacts to these events by using a platform API that enables any developer to extend their application for awareness of stowage events. There is no support to query whether the pen is present in the dock, apps are only notified of removal and return events if they are in the foreground.
Sample HID Report Descriptor
05,0D, // Usage Page (Digitizers)
09,20, // Usage (Stylus)
A1,01, // Collection (Application)
85,40, // Report ID (64)
95,01, // Report Count (1)
75,20, // Report Size (32)
17,00,00,00,80, // Logical Minimum (-2147483648)
27,FF,FF,FF,7F, // Logical Maximum (2147483647)
09,5B, // Transducer Serial Number
81,02, // Input (Data,Var,Abs)
75,10, // Report Size (16)
15,01, // Logical Minimum (1)
27,FF,FF,00,00, // Logical Maximum (65535)
09,91, // Transducer Vendor ID
81,02, // Input (Data,Var,Abs)
05,0E, // Usage Page (Haptics)
09,01, // Usage (0x01)
A1,02, // Collection (Logical)
85,41, // Report ID (65)
95,01, // Report Count (1)
75,08, // Report Size (8)
15,01, // Logical Minimum (1)
26,FF,00, // Logical Maximum (255)
09,24, // Usage (0x24)
B1,02, // Feature (Data,Var,Abs)
09,24, // Usage (0x24)
91,02, // Output (Data,Var,Abs)
09,23, // Usage (0x23)
B1,02, // Feature (Data,Var,Abs)
09,23, // Usage (0x23)
91,02, // Output (Data,Var,Abs)
15,01, // Logical Minimum (1)
25,12, // Logical Maximum (18)
09,20, // Usage (0x20)
B1,02, // Feature (Data,Var,Abs)
09,21, // Usage (0x21)
91,02, // Output (Data,Var,Abs)
15,00, // Logical Minimum (0)
26,FE,00, // Logical Maximum (254)
66,01,10, // Unit (SI Linear)
55,FD, // Unit Exponent (253)
35,00, // Physical Minimum (0)
46,EC,09, // Physical Maximum (2540)
09,28, // Usage (0x28)
91,02, // Output (Data,Var,Abs)
75,10, // Report Size (16)
26,D0,07, // Logical Maximum (2000)
46,D0,07, // Physical Maximum (2000)
09,25, // Usage (0x25)
91,02, // Output (Data,Var,Abs)
09,25, // Usage (0x25)
B1,02, // Feature (Data,Var,Abs)
45,00, // Physical Maximum (0)
85,42, // Report ID (66)
75,20, // Report Size (32)
17,42,00,0D,00, // Logical Minimum (852034)
27,42,00,0D,00, // Logical Maximum (852034)
09,22, // Usage (0x22)
B1,02, // Feature (Data,Var,Abs)
09,11, // Usage (0x11)
A1,02, // Collection (Logical)
05,0A, // Usage Page (Ordinal)
75,10, // Report Size (16)
95,10, // Report Count (16)
15,01, // Logical Minimum (1)
27,FF,FF,00,00, // Logical Maximum (65535)
19,03, // Usage Minimum (0x03)
29,12, // Usage Maximum (0x12)
B1,02, // Feature (Data,Var,Abs)
C0, // End Collection ()
05,0E, // Usage Page (Haptics)
09,10, // Usage (0x10)
A1,02, // Collection (Logical)
05,0A, // Usage Page (Ordinal)
16,03,10, // Logical Minimum (4099)
26,FF,2F, // Logical Maximum (12287)
19,03, // Usage Minimum (0x03)
29,12, // Usage Maximum (0x12)
B1,02, // Feature (Data,Var,Abs)
C0, // End Collection ()
C0, // End Collection ()
C0 // End Collection ()