Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for trackpads in the digitizer feature #24964

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from

Conversation

george-norton
Copy link

Updates the digitizer feature to support reporting as a trackpad.

Description

This PR contains the first part of my trackpad changes. It includes the core digitizer feature changes with the USB feature reports and device drivers stripped out. Without the feature reports the trackpad is not compliant with Microsofts Precision Trackpad protocol so it will not work on Windows. Apple also do not support 3rd party trackpads, so it will only work on Linux hosts.

The following functionality is included:

  • The digitizer feature is now processed in a similar way to the pointing device feature.
  • We can fallback to reporting as a mouse. Once feature reports are implemented, this happens automatically.
  • When we fallback to reporting as a mouse, we perform gesture detection in firmware.
  • Support for split transport (but not combining multiple digitizers).
  • Keyboard and user hooks which allow for custom gesture handling.
  • Updated HID descriptors

The mouse fallback is implemented by presenting the digitizer feature as a pointing device driver. This allows us to do stuff like combine the digitizer report with a mouse report when we fallback. The following gestures are detected in firmware:

  • One/Two/Three finger Tap.
  • Tap and hold to drag and drop.
  • Two finger scrolling.
  • Three finger swipes.
    The three finger swipe gestures currently generate key taps, maybe this could be improved.

The updated HID descriptors include reporting physical dimensions of the digitizer. Some hosts will ignore digitizers if they do not know their physical size (either from the descriptor, or from some host configuration file). The digitizer units have also been adjusted from inches to centimeters as this is more common in digitizer devices. There is a useful repository of digitizer hid descriptors here.

The onekey digitizer keymap has been updated and is verified as working (tested with onekey/rp2040) on Windows and Linux. On both systems the stylus draws circles.

The digitizer functionality is currently used out of tree to support several devices:

Subsequent PRs will include:

  • USB feature report handling - although I am not clear how best to implement this in a generic way.
  • Maxtouch digitizer driver.
  • Azoteq IQS digitizer driver.
  • Peacock keyboard support.
  • And probably Ploopy Trackpad and Dilemma v3 support from their respective maintainers.

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Keyboard (addition or update)
  • Keymap/layout (addition or update)
  • Documentation

Checklist

  • My code follows the code style of this project: C, Python
  • I have read the PR Checklist document and have made the appropriate changes.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

Comment on lines 173 to 179
# Digitizers can fallback to reporting as a mouse if the host does not support a digitizer.
# If the mouse collection is in the same endpoint as the digitizer collection both Windows and
# Linux will assume it is a fallback collection and will ignore any events it produces. Having
# them on separate endpoints ensures any mouse events we generate while the host is expecting
# a digitizer, are processed.
DIGITIZER_SHARED_EP = no
MOUSE_SHARED_EP = no
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would making just one of these endpoints separate be enough?

Some MCUs, like STM32F4x1, can support only 3 input endpoints, and forcing both of these endpoints to be separate may be problematic. Maybe you should not override the configuration here, and throw a warning (or even non-fatal #pragma message) on a configuration where both of these endpoints end up being shared?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we just need one moved off the shared endpoint. I had some CI failures when the onekey built some targets which moved the keyboard onto the shared endpoint. I guess these are the targets with only 3 input endpoints?

The macros in usb_descriptors.c dont allow us to use a dedicated endpoint once the shared endpoint is started, so perhaps we need a better way of handling this particular case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently KEYBOARD_SHARED_EP (or its JSON equivalent usb.shared_endpoint.keyboard) is enabled by the following handwired/onekey/* boards:

  • blackpill_{f401,f411}{,_tinyuf2} — STM32F4x1 chips support only 3 input endpoints;
  • at_start_f415 — AT32F415 apparently has the same restriction (“4 bi-directional endpoints support number 0 through 3”, which leaves 3 input endpoints after excluding the mandatory control endpoint 0);
  • evb_wb32f3g71, evb_wb32fq95 — looking at the ChibiOS USB driver, these WB32 chips also support only 3 input endpoints;
  • sipeed_longan_nano — GD32VF103, apparently also just 3 endpoints.

STM32F4x1 chips are somewhat common in custom designs (especially the ones with analog switches, where RP2040 has a disadvantage because of limited ADC capabilities), and those WB32 chips are often found in keyboards from various Chinese manufacturers.

As for the issue of interdependencies between various *_SHARED_EP options, this might need fixing, but the main restriction here is that the whole report descriptor for each endpoint must be contiguous in memory. Maybe some parts of these report descriptors would need to be converted to macros (similar to your DIGITIZER_FINGER_REPORT), so that the final descriptors could be defined without code duplication. This may also allow having a dedicated mouse endpoint together with a shared keyboard endpoint, so that a QMK-based mouse may have its USB descriptors more like a typical USB mouse.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are use cases like the Ploopy trackpad which has no buttons or encoders, where having both mouse and digitizer in the shared endpoint is reasonable (you could write custom gesture detection code that generates mouse keys which would be ignored by the host, but it's a niche case). So perhaps a better approach would be to just add a compile time warning if both are on the shared endpoint and let individual keyboards allocate endpoints as they see fit.

@george-norton george-norton mentioned this pull request Mar 2, 2025
14 tasks
@drashna drashna requested review from drashna, daskygit and a team March 3, 2025 03:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants