Files
zsa_qmk_firmware/drivers/sensors/navigator_trackpad.h
Florian 29ee055e25
Some checks failed
Build firmware / build-firmware (default) (push) Failing after 2s
Build firmware / build-firmware (oryx) (push) Failing after 2s
feat(trackpad): macos scroll resolution hid descriptor
2025-12-05 16:37:56 +07:00

203 lines
6.6 KiB
C

// Copyright 2025 ZSA Technology Labs, Inc <contact@zsa.io>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "report.h"
#include "pointing_device.h"
#define NAVIGATOR_TRACKPAD_READ 7
#define NAVIGATOR_TRACKPAD_PROBE 1000
#ifndef NAVIGATOR_TRACKPAD_TAP_MOVE_THRESHOLD
# define NAVIGATOR_TRACKPAD_TAP_MOVE_THRESHOLD 100 // Max movement (squared) before tap becomes a drag
#endif
#ifndef NAVIGATOR_TRACKPAD_TAP_TIMEOUT
# define NAVIGATOR_TRACKPAD_TAP_TIMEOUT 200 // Max duration (ms) for a tap
#endif
#ifndef NAVIGATOR_TRACKPAD_TAP_SETTLE_TIME
# define NAVIGATOR_TRACKPAD_TAP_SETTLE_TIME 30 // Ignore movement during initial contact (ms)
#endif
#ifndef NAVIGATOR_TRACKPAD_MAX_DELTA
# define NAVIGATOR_TRACKPAD_MAX_DELTA 250 // Max allowed delta per frame to prevent jumps
#endif
#ifndef NAVIGATOR_TRACKPAD_ADDRESS
# define NAVIGATOR_TRACKPAD_ADDRESS 0x58
#endif
#ifndef NAVIGATOR_TRACKPAD_TIMEOUT
# define NAVIGATOR_TRACKPAD_TIMEOUT 100
#endif
#define NAVIGATOR_TRACKPAD_PTP_MODE
#if !defined(NAVIGATOR_TRACKPAD_RELATIVE_MODE) && !defined(NAVIGATOR_TRACKPAD_PTP_MODE)
# define NAVIGATOR_TRACKPAD_PTP_MODE
#endif
#define CGEN6_MAX_PACKET_SIZE 17
#define CGEN6_PTP_REPORT_ID 0x01
#define CGEN6_MOUSE_REPORT_ID 0x06
#define CGEN6_ABSOLUTE_REPORT_ID 0x09
// C3 error codes when reading memory
#define CGEN6_SUCCESS 0x00
#define CGEN6_CKSUM_FAILED 0x01
#define CGEN6_LEN_MISMATCH 0x02
#define CGEN6_I2C_FAILED 0x03
// C3 register addresses
#define CGEN6_REG_BASE 0x20000800
#define CGEN6_HARDWARE_ID CGEN6_REG_BASE + 0x08
#define CGEN6_FIRMWARE_ID CGEN6_REG_BASE + 0x09
#define CGEN6_FIRMWARE_REV CGEN6_REG_BASE + 0x10
#define CGEN6_VENDOR_ID CGEN6_REG_BASE + 0x0A
#define CGEN6_PRODUCT_ID CGEN6_REG_BASE + 0x0C
#define CGEN6_VERSION_ID CGEN6_REG_BASE + 0x0E
#define CGEN6_FEED_CONFIG4 0x200E000B
#define CGEN6_FEED_CONFIG3 0x200E000A
#define CGEN6_SYS_CONFIG1 0x20000008
#define CGEN6_XY_CONFIG 0x20080018
#define CGEN6_SFR_BASE 0x40000008
#define CGEN6_GPIO_BASE 0x00052000
#define CGEN6_I2C_DR 0x61010000
#define CPI_TICKS 7
#define DEFAULT_CPI_TICK 4
#define CPI_1 200
#define CPI_2 400
#define CPI_3 800
#define CPI_4 1024
#define CPI_5 1400
#define CPI_6 1800
#define CPI_7 2048
#ifndef NAVIGATOR_TRACKPAD_SCROLL_DIVIDER
# define NAVIGATOR_TRACKPAD_SCROLL_DIVIDER 10
#endif
#ifndef NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER
# define NAVIGATOR_TRACKPAD_SCROLL_MULTIPLIER 3
#endif
// Two-finger scrolling (define to enable)
// #define NAVIGATOR_TRACKPAD_SCROLL_WITH_TWO_FINGERS
// macOS scrolling mode (define to enable)
// macOS doesn't respect the HID Resolution Multiplier descriptor.
// When enabled, sends raw scroll deltas without the multiplier (like Apple trackpads).
// macOS applies its own HIDScrollResolution (400 DPI) and acceleration curves.
// When disabled (default), applies multiplier for Windows/Linux hi-res scrolling.
// #define NAVIGATOR_TRACKPAD_MACOS_SCROLLING
// Scroll inversion configuration
// Define these to invert scroll direction on respective axes
// #define NAVIGATOR_SCROLL_INVERT_X
// #define NAVIGATOR_SCROLL_INVERT_Y
// Scroll inertia configuration
/*
To enable, add to your config.h:
#define NAVIGATOR_TRACKPAD_SCROLL_INERTIA_ENABLE
Configurable values (all optional):
- NAVIGATOR_TRACKPAD_SCROLL_INERTIA_FRICTION - Higher = stops faster (default: 50, range 1-255)
- NAVIGATOR_TRACKPAD_SCROLL_INERTIA_INTERVAL - Time between glide reports in ms (default: 15)
- NAVIGATOR_TRACKPAD_SCROLL_INERTIA_TRIGGER - Minimum velocity to trigger glide (default: 3)
*/
#ifdef NAVIGATOR_TRACKPAD_SCROLL_INERTIA_ENABLE
#ifndef NAVIGATOR_TRACKPAD_SCROLL_INERTIA_FRICTION
#define NAVIGATOR_TRACKPAD_SCROLL_INERTIA_FRICTION 5 // Higher = stops faster (1-255)
#endif
#ifndef NAVIGATOR_TRACKPAD_SCROLL_INERTIA_INTERVAL
#define NAVIGATOR_TRACKPAD_SCROLL_INERTIA_INTERVAL 7 // Glide report interval in ms
#endif
#ifndef NAVIGATOR_TRACKPAD_SCROLL_INERTIA_TRIGGER
#define NAVIGATOR_TRACKPAD_SCROLL_INERTIA_TRIGGER 1 // Min velocity to trigger glide
#endif
typedef struct {
int16_t vx; // Current X velocity (Q8 fixed point)
int16_t vy; // Current Y velocity (Q8 fixed point)
int16_t smooth_vx; // Smoothed X velocity (Q8 fixed point)
int16_t smooth_vy; // Smoothed Y velocity (Q8 fixed point)
uint16_t timer; // Timer for interval tracking
bool active; // Is glide currently active
#ifdef NAVIGATOR_TRACKPAD_MACOS_SCROLLING
uint8_t no_output_count; // Counter for consecutive frames with no output
#endif
} scroll_inertia_t;
#endif
#if defined(NAVIGATOR_TRACKPAD_PTP_MODE)
# ifndef MOUSE_EXTENDED_REPORT
# define MOUSE_EXTENDED_REPORT
# endif
typedef struct {
uint8_t tip;
uint16_t x;
uint16_t y;
} cgen6_finger_t;
typedef struct {
cgen6_finger_t fingers[2];
uint8_t buttons;
} cgen6_report_t;
// Trackpad gesture state machine
typedef enum {
TP_IDLE, // No fingers touching
TP_MOVING, // One finger movement = mouse cursor
TP_SCROLLING, // Two finger movement = scroll
} trackpad_state_t;
typedef struct {
trackpad_state_t state;
uint16_t touch_start_time; // When finger first touched
uint16_t settled_x; // Position after settle time (for tap threshold)
uint16_t settled_y;
uint16_t prev_x; // Previous position (for delta calculation)
uint16_t prev_y;
uint8_t max_finger_count; // Max fingers seen during this gesture
bool settled; // Has the settle time elapsed?
bool pending_click; // Need to send a click release next cycle
uint16_t last_scroll_end; // Time when last scroll gesture ended
} trackpad_gesture_t;
#endif
#if defined(NAVIGATOR_TRACKPAD_ABSOLUTE_MODE)
typedef struct {
uint16_t x;
uint16_t y;
uint8_t palm;
uint8_t z;
} finger_data_t;
typedef struct {
finger_data_t fingers[3]; // Cirque support 5 fingers, we only need 3 for our application
uint8_t contact_flags;
uint8_t buttons;
} cgen6_report_t;
#endif
#if defined(NAVIGATOR_TRACKPAD_RELATIVE_MODE)
typedef struct {
uint8_t buttons;
int8_t xDelta;
int8_t yDelta;
int8_t scrollDelta;
int8_t panDelta;
} cgen6_report_t;
#endif
const pointing_device_driver_t navigator_trackpad_pointing_device_driver;
void navigator_trackpad_device_init(void);
report_mouse_t navigator_trackpad_get_report(report_mouse_t mouse_report);
uint16_t navigator_trackpad_get_cpi(void);
void navigator_trackpad_set_cpi(uint16_t cpi);
void restore_cpi(uint8_t cpi);