From d3073ef4943c70a3942ac91bb46fdc1a90f9e566 Mon Sep 17 00:00:00 2001
From: Drashna Jaelre <drashna@live.com>
Date: Sun, 13 Nov 2022 08:05:46 -0800
Subject: [PATCH] Add pointing device support to data driven config (#18215)

Co-authored-by: Joel Challis <git@zvecr.com>
---
 data/mappings/info_config.hjson         | 18 +++++++
 data/mappings/info_rules.hjson          |  2 +
 data/schemas/keyboard.jsonschema        | 63 +++++++++++++++++++++++++
 lib/python/qmk/cli/generate/config_h.py | 13 +++++
 4 files changed, 96 insertions(+)

diff --git a/data/mappings/info_config.hjson b/data/mappings/info_config.hjson
index a013e98b34..a80d5cff6f 100644
--- a/data/mappings/info_config.hjson
+++ b/data/mappings/info_config.hjson
@@ -11,6 +11,10 @@
     // invalid: Default `false`. Set to `true` to generate errors when a value exists
     // replace_with: use with a key marked deprecated or invalid to designate a replacement
     "AUDIO_VOICES": {"info_key": "audio.voices", "value_type": "bool"},
+    "AUTO_MOUSE_DEFAULT_LAYER": {"info_key": "pointing_device.auto_mouse.default_layer"},
+    "AUTO_MOUSE_TIME": {"info_key": "pointing_device.auto_mouse.time"},
+    "AUTO_MOUSE_DELAY": {"info_key": "pointing_device.auto_mouse.delay"},
+    "AUTO_MOUSE_DEBOUNCE": {"info_key": "pointing_device.auto_mouse.debounce"},
     "BACKLIGHT_BREATHING": {"info_key": "backlight.breathing", "value_type": "bool"},
     "BREATHING_PERIOD": {"info_key": "backlight.breathing_period", "value_type": "int"},
     "BACKLIGHT_LEVELS": {"info_key": "backlight.levels", "value_type": "int"},
@@ -87,6 +91,19 @@
     "RGB_MATRIX_VAL_STEP": {"info_key": "rgb_matrix.val_steps", "value_type": "int"},
     "RGB_MATRIX_SPD_STEP": {"info_key": "rgb_matrix.speed_steps", "value_type": "int"},
     "RGBW": {"info_key": "rgblight.rgbw", "value_type": "bool"},
+    "POINTING_DEVICE_AUTO_MOUSE_ENABLE": {"info_key": "pointing_device.auto_mouse.enabled"},
+    "POINTING_DEVICE_CS_PIN": {"info_key": "pointing_device.pins.cs"},
+    "POINTING_DEVICE_INVERT_X": {"info_key": "pointing_device.invert_x", "value_type": "bool"},
+    "POINTING_DEVICE_INVERT_X_RIGHT": {"info_key": "split.pointing_device.right.invert_x", "value_type": "bool"},
+    "POINTING_DEVICE_INVERT_Y": {"info_key": "pointing_device.invert_y", "value_type": "bool"},
+    "POINTING_DEVICE_INVERT_Y_RIGHT": {"info_key": "split.pointing_device.right.invert_y", "value_type": "bool"},
+    "POINTING_DEVICE_MOTION_PIN": {"info_key": "pointing_device.pins.motion"},
+    "POINTING_DEVICE_SDIO_PIN": {"info_key": "pointing_device.pins.sdio"},
+    "POINTING_DEVICE_SCLK_PIN": {"info_key": "pointing_device.pins.sclk"},
+    "POINTING_DEVICE_TASK_THROTTLE_MS": {"info_key": "pointing_device.throttle", "value_type": "int"},
+    "POINTING_DEVICE_GESTURES_CURSOR_GLIDE_ENABLE": {"info_key": "pointing_device.gestures.cursor_glide", "value_type": "bool"},
+    "POINTING_DEVICE_GESTURES_SCROLL_ENABLE": {"info_key": "pointing_device.gestures.scroll", "value_type": "bool"},
+
     "PRODUCT": {"info_key": "keyboard_name", "warn_duplicate": false, "value_type": "str"},
     "PRODUCT_ID": {"info_key": "usb.pid", "value_type": "hex"},
     "VENDOR_ID": {"info_key": "usb.vid", "value_type": "hex"},
@@ -99,6 +116,7 @@
     "SECURE_IDLE_TIMEOUT": {"info_key": "secure.idle_timeout", "value_type": "int"},
     "SENDSTRING_BELL": {"info_key": "audio.macro_beep", "value_type": "bool"},
     "SPLIT_MODS_ENABLE": {"info_key": "split.transport.sync_modifiers", "value_type": "bool"},
+    "SPLIT_POINTING_ENABLE": {"info_key": "split.transport.sync_pointing", "value_type": "bool"},
     "SPLIT_TRANSPORT_MIRROR": {"info_key": "split.transport.sync_matrix_state", "value_type": "bool"},
     "SPLIT_USB_DETECT": {"info_key": "split.usb_detect.enabled", "value_type": "bool"},
     "SPLIT_USB_TIMEOUT": {"info_key": "split.usb_detect.timeout", "value_type": "int"},
diff --git a/data/mappings/info_rules.hjson b/data/mappings/info_rules.hjson
index 2f8656c4bf..2cc465f30d 100644
--- a/data/mappings/info_rules.hjson
+++ b/data/mappings/info_rules.hjson
@@ -36,6 +36,8 @@
     "PS2_ENABLE": {"info_key": "ps2.enabled", "value_type": "bool"},
     "PS2_MOUSE_ENABLE": {"info_key": "ps2.mouse_enabled", "value_type": "bool"},
     "PS2_DRIVER": {"info_key": "ps2.driver"},
+    "POINTING_DEVICE_ENABLE": {"info_key": "pointing_device.enabled", "value_type": "bool"},
+    "POINTING_DEVICE_DRIVER": {"info_key": "pointing_device.driver"},
 
     // Items we want flagged in lint
     "CTPC": {"info_key": "_deprecated.ctpc", "deprecated": true, "replace_with": "CONVERT_TO=proton_c"},
diff --git a/data/schemas/keyboard.jsonschema b/data/schemas/keyboard.jsonschema
index daf54141a8..d5f4f392d7 100644
--- a/data/schemas/keyboard.jsonschema
+++ b/data/schemas/keyboard.jsonschema
@@ -363,6 +363,48 @@
                 }
             }
         },
+        "pointing_device": {
+            "type": "object",
+            "properties": {
+                "enabled": {"type": "boolean"},
+                "driver": {"type": "string"},
+                "auto_mouse":  {
+                    "type": "object",
+                    "properties": {
+                        "enabled": {"type": "boolean"},
+                        "default_layer": {"type":  "qmk.definitions.v1#/unsigned_int_8"},
+                        "time": {"type":  "qmk.definitions.v1#/unsigned_int"},
+                        "delay": {"type":  "qmk.definitions.v1#/unsigned_int"},
+                        "debounce": {"type":  "qmk.definitions.v1#/unsigned_int"}
+                    }
+                }
+                "pins": {
+                    "type": "object",
+                    "additionalProperties": false,
+                    "properties": {
+                        "motion": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+                        "cs": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+                        "sdio": {"$ref": "qmk.definitions.v1#/mcu_pin"},
+                        "sclk": {"$ref": "qmk.definitions.v1#/mcu_pin"}
+                    }
+                },
+                "throttle": {"$ref": "qmk.definitions.v1#/unsigned_int_8"},
+                "invert_x": {"type": "boolean"},
+                "invert_y": {"type": "boolean"},
+                "gestures": {
+                    "type": "object",
+                    "properties": {
+                        "cursor_glide": {"type": "boolean"},
+                        "scroll": {"type": "boolean"}
+                    }
+                },
+                "rotation": {
+                    "type": "integer",
+                    "minimum": 0,
+                    "enum": [0, 90, 180, 270]
+                }
+            }
+        },
         "rgb_matrix": {
             "type": "object",
             "properties": {
@@ -544,6 +586,26 @@
                     "type": "string",
                     "enum": ["eeprom", "left", "matrix_grid", "pin", "right"]
                 },
+                "pointing_device": {
+                    "right": {
+                        "type": "object",
+                        "additionalProperties": false,
+                        "type": "object",
+                        "properties": {
+                            "side": {
+                                "type": "string",
+                                "enum": ["left", "right", "combined"]
+                            },
+                            "invert_x": {"type": "boolean"},
+                            "invert_y": {"type": "boolean"},
+                            "rotation": {
+                                "type": "integer",
+                                "minimum": 0,
+                                "enum": [0, 90, 180, 270]
+                            }
+                        }
+                    }
+                },
                 "soft_serial_pin": {"$ref": "qmk.definitions.v1#/mcu_pin"},
                 "soft_serial_speed": {
                     "type": "integer",
@@ -560,6 +622,7 @@
                         },
                         "sync_matrix_state": {"type": "boolean"},
                         "sync_modifiers": {"type": "boolean"},
+                        "sync_pointing": {"type": "boolean"},
                         "watchdog": {"type": "boolean"},
                         "watchdog_timeout": {"$ref": "qmk.definitions.v1#/unsigned_int"}
                     }
diff --git a/lib/python/qmk/cli/generate/config_h.py b/lib/python/qmk/cli/generate/config_h.py
index 31b8d70635..51051ef610 100755
--- a/lib/python/qmk/cli/generate/config_h.py
+++ b/lib/python/qmk/cli/generate/config_h.py
@@ -126,6 +126,13 @@ def generate_encoder_config(encoder_json, config_h_lines, postfix=''):
         config_h_lines.append(generate_define(f'ENCODER_RESOLUTIONS{postfix}', f'{{ {", ".join(map(str,resolutions))} }}'))
 
 
+def generate_pointing_device_config(pointing_device_json, config_h_lines, postfix=''):
+
+    rotation = pointing_device_json.get('rotation', 0)
+
+    generate_define(f'POINTING_DEVICE_ROTATION_{rotation}{postfix}')
+
+
 def generate_split_config(kb_info_json, config_h_lines):
     """Generate the config.h lines for split boards."""
     if 'primary' in kb_info_json['split']:
@@ -156,6 +163,9 @@ def generate_split_config(kb_info_json, config_h_lines):
     if 'right' in kb_info_json['split'].get('encoder', {}):
         generate_encoder_config(kb_info_json['split']['encoder']['right'], config_h_lines, '_RIGHT')
 
+    if 'right' in kb_info_json['split'].get('pointing_device', {}):
+        generate_pointing_device_config(kb_info_json['split']['pointing_device']['right'], config_h_lines, '_RIGHT')
+
 
 def generate_led_animations_config(led_feature_json, config_h_lines, prefix):
     for animation in led_feature_json.get('animations', {}):
@@ -207,5 +217,8 @@ def generate_config_h(cli):
     if 'rgblight' in kb_info_json:
         generate_led_animations_config(kb_info_json['rgblight'], config_h_lines, 'RGBLIGHT_EFFECT_')
 
+    if 'pointing_device' in kb_info_json:
+        generate_pointing_device_config(kb_info_json['pointing_device'], config_h_lines)
+
     # Show the results
     dump_lines(cli.args.output, config_h_lines, cli.args.quiet)