diff --git a/site/_wiki/Development/Configurations.md b/site/_wiki/Development/Configurations.md index dc185d5..efb78d8 100644 --- a/site/_wiki/Development/Configurations.md +++ b/site/_wiki/Development/Configurations.md @@ -1,5 +1,5 @@ --- -title: Writing OpenTabletDriver Configurations +title: Tablet configuration reference --- ## Device Information diff --git a/site/_wiki/Documentation/ConfigurationGuide.md b/site/_wiki/Documentation/ConfigurationGuide.md new file mode 100644 index 0000000..1082bda --- /dev/null +++ b/site/_wiki/Documentation/ConfigurationGuide.md @@ -0,0 +1,482 @@ +--- +title: "Guide: Adding support for a new tablet" +--- + +## Prelude + +This guide will step you through how to make a configuration for a tablet. Some +tablets can take a few minutes to set up, while others can require analyzing +the USB packets sent by the manufacturers tablet driver among other things. + +It is probably worthwhile to keep the [Tablet configuration reference] open in +another tab. This guide will assume that you are aware of the details provided +on that page. + +[Tablet configuration reference]: {% link _wiki/Development/Configurations.md %} + +## Preparing your system for adding support + +It is highly recommended to remove (or unload) your existing tablet drivers +before proceeding. + +### Uninstalling drivers on Windows {#preparing-windows} + +Tablet drivers are often automatically installed by Windows. + +Running [TabletDriverCleanup] is the easiest way to ensure that +OpenTabletDriver has access to the tablet. + +[TabletDriverCleanup]: {{ site.data.links.external.TabletDriverCleanup.latest }} + +### Unloading drivers on Linux {#preparing-linux} + +If you've installed OpenTabletDriver from an official package, the stock tablet +drivers are already blacklisted. + +Still, run the following command to ensure that the upstream drivers are unloaded: + +```sh +sudo rmmod hid_uclogic wacom 2>/dev/null +``` + +You likely need to set up udev rules so that your user can access the raw +device directly. + +Normally, this is autogenerated by the build process and uses the officially +supported configs. + +You can define these manually for now, and put them in a local udev rule file, +e.g. `/etc/udev/rules.d/91-opentabletdriver-adds.rules`: + +```conf +KERNEL=="hidraw*", ATTRS{idVendor}=="b33f", ATTRS{idProduct}=="c4k3", TAG+="uaccess", TAG+="udev-acl" +SUBSYSTEM=="usb", ATTRS{idVendor}=="b33f", ATTRS{idProduct}=="c4k3", TAG+="uaccess", TAG+="udev-acl" +``` + +Make sure to change the values of `idVendor` and `idProduct` as appropriate. +You can get them with `lsusb`. + +> Note: `idVendor` and `idProduct` must be in base-16 (hexadecimal) as opposed + to the base-10 format used in OpenTabletDriver configurations. + +See `man 7 udev` for systemd udev syntax. If you're not using systemd udev, see +your distro documentation, or change the appropriate usb and hidraw permissions +manually. + +### MacOS {#preparing-macos} + +All you should need for OpenTabletDriver to initialize and access your tablet, +is uninstalling the OEM drivers. + +## Configuration Template {#config-template-intro} + +Getting a configuration template is usually simple if OpenTabletDriver supports +other tablets from your manufacturer, especially if it's in the same line of +models. + +- Copy a "neighbouring" configuration from the + `OpenTabletDriver.Configurations/Configurations/` folder +- Rename the file to be `.json`, e.g. `H420.json` + +If your manufacturer does not have an existing template, please use the +[Configuration skeleton] or copy any other tablet configuration and follow the +guide carefully. + +> Note that the configuration format between OpenTabletDriver 0.6 (`0.6.x`) and + 0.7 (`master`) differs slightly. Make sure that you pick a configuration of + the same format as the version of OpenTabletDriver you're using. + +[Configuration skeleton]: https://github.com/OpenTabletDriver/OpenTabletDriver/issues/3249 + +## Setting specifications according to official manufacturer specifications {#oem-values} + +Setting up some of the specifications now can simplify touching up later values +if you know what they are. You can also add them as you discover the feature; +we will ensure the specifications are set correctly at the end of the guide. + +Some (almost) always correct values include: + +- Pen and tablet (aux) button counts +- Tool support (such as tablet mouse) +- Touch support +- Pen pressure range + +Digitizer dimensions (for both pen and touch digitizer) will be determined as a +later part of the guide, and are not always correct. + +Note that wheels (rings) are not yet supported, and should not be directly defined. +See [OpenTabletDriver#1367] for more information + +If the parser you use picks up wheel buttons as an aux button, make sure to +take this into consideration when specifying aux button count. + +[OpenTabletDriver#1367]: https://github.com/OpenTabletDriver/OpenTabletDriver/issues/1367 + +## Configuring the digitizer identifier {#digitizer-identifier} + +Configuring a correct digitizer identifier is the bread and butter of tablet +detection. This section covers how to set all the identifier fields +appropriately. + +A single tablet model generally only needs a single identifier. Still, firmware +variants for an otherwise identical tablet can cause tablets to need more than +1 identifier to correctly identify variants. + +Therefore, it is important to make your identifier as relaxed as possible while +still being strict enough to not cause identifier conflicts with other +configurations. + +Detection, in broad terms, checks in the following order: + +1. Match VendorID and ProductID +2. If not null, match InputReportLength and OutputReportLength + - This helps select a specific interface of the tablet +3. If not null, match DeviceStrings + - This helps differentiate between firmwares + +There is more to detection than this (such as attributes), but 99.9% of use +cases can be covered with the above. + +### ID's and report lengths {#identifiers-and-report-lengths} + +At the very minimum, your configuration should have a non-null `VendorID` and `ProductID`. + +If your tablet has multiple interfaces, it is very likely only 1 of them +contains the tablet data stream. This is where `InputReportLength` and +`OutputReportLength` comes in. + +Even if your tablet only has a single interface, it is often a good idea to +specify at least one of the lengths as non-zero, and only define them as `null` +if you know what you're doing + +> If you specify report lengths as null, it can be hard to fix any future + conflicts that may arise without knowing what values your specific tablet + has. If you do decide to specify them as null, please make sure to include a + OpenTabletDriver diagnostics with the pull request, and optionally include + the lengths in the commit description. + +### Picking the Parser {#parser} + +Picking the parser is the most important part of ensuring your tablet functions +correctly. Picking the wrong parser can result in missing or (sometimes subtly) +broken features. + +You must use a class which implements the `Parse(byte[])` function. + +How to write a parser from scratch is out of scope of this guide, but if you +find that a parser you're using needs a code change to work, it is usually a +better idea to make a new parser that builds off it instead. + +To see which functionality is supported by a parser, please see the code for +the parsers return paths in its `Parse(byte[])` function. An example is +provided below. + +If you don't know anything about your tablet, or if you're writing your own +parser, it is recommended to start out with the `PassthroughReportParser` +parser, as it does not directly parse data but instead just allows the Tablet +Debugger to display the raw data. + +It is important to not get overzealous and pick a too specific parser before +you've ensured that the tablet is initialized correctly. + +#### `XP_PenReportParser` example + +At the time of this writing, [`XP_PenReportParser`] can return 5 different +types of reports (not in order) + +[`XP_PenReportParser`]: https://github.com/OpenTabletDriver/OpenTabletDriver/blob/f14a184fef67a52637ab494497a151044bafd553/OpenTabletDriver.Configurations/Parsers/XP_Pen/XP_PenReportParser.cs#L7-L21 + +##### `OutOfRangeReport` + +Fairly selfdescript, it doesn't actually report any specific values to the +OS but rather 'resets' the pen out. + +##### `XP_PenAuxReport` + +Reports `IAuxReport`, an aux-buttons-only report, ie. no position coordinates. + +##### `XP_PenTabletReport` + +Reports the following reports: + +- `ITabletReport` + - The pen's pressure + - Pen buttons + - It is an `IAbsolutePositionReport` that also reports the following: + - The 2-point vector of the pen +- `ITiltReport` + - The 2-point vector of the pen's tilt +- `IEraserReport` + - Whether the eraser is active or not + +##### `XP_PenTabletOverflowReport` + +An almost identical version of the above `XP_PenTabletReport` except with +larger ranges for the position coordinate and the data structure adjusted +accordingly. + +##### `TabletReport` + +A barebones tablet report that only reports an `ITabletReport` + +### Init strings (Feature/OutputInitReport, InitializationStrings) {#init-strings} + +These are almost always necessary to use to bring the tablet out of HID mode +and into a more preferred mode, e.g. vendor mode. + +Vendor mode is the mode used by the official drivers, and allows +OpenTabletDriver to support all of the tablets features, assuming the parser +supports it. + +Getting these can be achieved in 2 ways: + +#### Guessing + +Copying the appropriate init strings from a sibling configuration is usually +adequate. + +##### Common initialization strings {#common-init-strings} + +For many UC-Logic based tablets, like Huion and Gaomon, they seem to all share +almost the same indices to probe across many generations. + +Here are some recommended starting points for initialization strings, in order +of most common to least common + +- `200` +- `100` + +If `100` works but you have missing auxiliary buttons, you may need to follow +it up with an string initialization on `123` + +The following 2 initialization strings have only been seen once: + +- `109` +- `100` followed by `110` + +#### USB Packet capture {#pcap} + +This is usually done with Wireshark (and winpcap). A guide on this is planned +but not in progress. See [opentabletdriver.github.io#171] for more information. + +[opentabletdriver.github.io#171]: https://github.com/OpenTabletDriver/opentabletdriver.github.io/issues/171 + +### Device strings {#device-strings} + +In some cases, vendors (especially Huion) might release a tablet with different +specifications that otherwise has the same ID's as another released tablet. + +While this complicates things, we have another tool in our arsenal called +device strings descriptors. + +The configuration format is a dictionary where the key matches the descriptor +ID (up to 255) and the value is a regex that the string descriptor's value must +match with. + +While they are similar to [initialization strings](#init-strings), the +difference here is that we read the returned output when initializing the +string, and as such can match tablets based on its contents. + +#### Common device strings {#common-device-strings} + +Below are some usually common device strings for various vendors. + +These are not guaranteed to be correct across all models for the vendor, but +may help some people decode their meaning. + +| Index | Value | +| ----: | :---- | +| 2 | **XP-Pen**: Model Name +| 4 | **XP-Pen**: Firmware Build ID +| 5 | **XP-Pen**: Firmware Build String +| 23 | **VEIKK**: Firmware Build Date +| 201 | **Gaomon**, **Huion**, and some other **UC-Logic** based: Firmware Build ID + +Be wary that probing strings can also change behavior in the device, which can +usually be rectified by replugging the tablet. + +## Validating values {#validation} + +Assuming you now have a configuration that correctly identifies your tablet, +you now have to validate that you're using the correct parser and then the +correct configuration values. + +### Validating the parser {#validation-parser} + +This section is **not** for making sure the specifications in the configuration +is configured correctly, only the parser. + +The values below can be validated from entirely within the tablet debugger. + +The tablet debugger will show the values as parsed directly from the tablet, +before any configuration adjustments (such as button count) take place. + +If any of the values seems absent or malfunctioning (overflowing, abrupt jumps), +you are probably using the wrong parser. + +#### Digitizer {#validation-parser-digitizer} + +Verify that the top left of the tablet equals to `[0, 0]` or `[1, 1]`. + +Verify that the X and Y values increment monotonically. Critically, the value +must never wrap around. + +#### Pen maximum pressure {#validation-parser-pen-pressure} + +Value must transition somewhat smoothly from around 0 to its maximum value. + +#### All pen and auxiliary buttons {#validation-parser-buttons} + +Every button click must cause a distinct state change. + +Some tablets may support a separate 'unclick' report. + +#### Tool identification {#validation-tool-identification} + +This is mostly a Wacom feature, and can be difficult to read manually from the +tablet debugger. Use the recording feature of the tablet debugger and read the +annotated file for tool idenfication. + +Unless you have many tools at your disposal, testing the actual functionality +can be difficult. `ToolID` is the "model number" of the tool, whereas +`ToolSerial` is the, well, the serial ID of the tool. + +The tool ID is used for art programs (and the operating system) to assume some +defaults. The extent of exposing tool ID correctly is not completely finished, +and is only partially supported on Linux for now. + +The serial ID is very useful for artists that have multiple of the same tool so +that their art program can track per-tool settings. + +#### Touch {#validation-touch} + +Touch is currently not exposed to the operating system, but some parsers do +parse touch. If your tablet does parse touch, make sure that it behaves +similarly to the [pen digitizer](#validation-parser-digitizer). + +See [OpenTabletDriver#1664] for more information on exposing this to the OS. + +[OpenTabletDriver#1664]: https://github.com/OpenTabletDriver/OpenTabletDriver/issues/1664 + +### Correctly determining digitizer dimensions {#digitizer-correct-dimensions} + +The ideal way to calculate the these values, is to first figure out the `MaxX` and +`MaxY` values of the digitizer. + +You will need the following values: + +- The LPMM (lines per millimeter) of the tablet for both axises (horizontal and vertical). +- The maximum reported **X** (horizontal) value of the tablet +- The maximum reported **Y** (vertical) value of the tablet + +> The manufacturers digitizer dimensions can often times be slightly wrong + (usually rounded up), so getting this right ensures that users can keep using + the exact same tablet area between different tablets in OpenTabletDriver + +#### Getting maximum X and Y values {#digitizer-max-positional-values} + +You can get the X and Y values from OpenTabletDriver's tablet debugger. +Move your tool (e.g. pen) to the outer edges (usually right side and bottom +side) of the digitizer area while keeping an eye on the reported X and Y values +in the tablet debugger. + +If your tablet is reporting very quickly, it might be worth using the tablet data recording feature. +> A way to easily display the maximum value returned is planned but not + implemented yet. See [OpenTabletDriver#2433] for more information. + +The `MaxX` and `MaxY` values should be equal to the highest observed value +reported by the tablet on each axis. + +To ensure getting the highest possible X and Y values, make sure that you're +moving your tool to the edge at multiple angles. + +If your achieved `MaxX` and `MaxY` values seem incorrect (such as 4096 x 4096), +you might be initializing the tablet incorrectly, or you're not using the +correct parser. See the [Parser](#parser) section for more information. + +[OpenTabletDriver#2433]: https://github.com/OpenTabletDriver/OpenTabletDriver/issues/2433 + +#### Getting the LPMM {#digitizer-lpmm} + +This is almost always exactly 100 LPMM or exactly 200 LPMM for both axises, or another +round value, like LPI rounded to nearest thousands, like 4000 LPI. + +> If your tablet only offers an line per inch (LPI) value, you can divide the + LPI by `25.4` to get the LPMM. + +#### Calculating the width and height {#digitizer-dimensions-calculation} + +With the LPMM and maximum values reported by the tablet in hand, calculate the +width and the height using the following formulas: + +```py +Width = MaxX / Horizontal_LPMM +Height = MaxY / Vertical_LPMM +``` + +Double check that the resulting width and height is close to the manufacturer's +specified digitizer working area. + +A deviation of up to 10% is normal, but if it is obviously wrong (more than 50% +out), confirm that both your LPMM and width/height values are correct. + +> If the guessed LPMM seems incorrect, it is better to manually measure the + width and the height of the digitizers active area. + +### Verify functionality {#verify-functionality} + +Now that you've checked the values for correctness, you now have to validate +the exposed functionality as much as possible. + +You don't need to validate every single feature set in the OS. For example, +pressure is assumed working if the tablet debugger reports it correctly. + +You now need to double check that the following functionality completely works: + +- The entirety of the tablets area is usable +- All pen buttons works and can be assigned +- All auxiliary (tablet) buttons works and can be assigned +- Extra tool functionality, if able: + - Tablet mouse + - Any other tools your tablet might support + +If anything is not working to your expectations, you might be using the wrong +parser, or you specified some values incorrectly. + +If you're stuck, you can visit our [Discord]({{ site.data.links.project.DiscordInvite }}) and +ask for help in one of the following channels: `#configs` or `#support-misc` + +## Fin + +That's it, you've now successfully made a tablet configuration! + +Now, optionally commit it with `git` and push it to your chosen branch and an open a [pull request]. + +[pull request]: {{ site.data.links.project.UpstreamRepo }}/pulls + +## FAQ {#faq} + +You should also read the [General FAQ]({% link _wiki/FAQ/General.md %}) and +your OS-appropriate FAQ ([Windows]({% link _wiki/FAQ/Windows.md %}), +[Linux]({% link _wiki/FAQ/Linux.md %}), +[MacOS]({% link _wiki/FAQ/MacOS.md %})) +too for other issues that might not be covered below. + +### My cursor is going everywhere {#faq-cursor-skipping} + +Make sure you've uninstalled other drivers. + +If you did, and you're on Linux, your tablet might need the `libinputoverride` attribute. + +### My tablet can't be that difficult to add, TL;DR? + +- Copy existing config from a sibling tablet +- Adjust identifiers and confirm that the tablet debugger is doing things now +- Confirm that the parser is functioning correctly (pressure etc) +- Figure out `MaxX` and `MaxY` and `LPMM` of your tablet's digitizer. +- Adjust height and widths based off of `MaxX`, `MaxY` and their `LPMM`. +- Double check that it still works from a replug +- Double check that all the specifications are correct + - Buttons, digitizer area, pressure, touch, etc. +- Submit pull request to the appropriate branch and pray that your configuration passes tests + - If submitting a PR, don't forget to update `TABLETS.md` to document the support.