diff options
author | Shecky Lin <sheckylin@chromium.org> | 2020-03-11 15:15:46 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-17 12:11:46 +0000 |
commit | c6f631c3e461cdafe5b643fa5d12415d67097ac6 (patch) | |
tree | 2df6ee9ff6f3da0353449dcfea21d3d3c38cdcfc | |
parent | e5e676f641dec32ddf4b32d1b8f4f9636e31ff2a (diff) | |
download | chrome-ec-c6f631c3e461cdafe5b643fa5d12415d67097ac6.tar.gz |
i2c_hid_touchpad: Add basic structs and descriptors
This is part of a chain to add a common I2C HID interface for
touchpads.
The CL layouts basic struct, defines and HID descriptors that
would be used by an I2C HID touchpad implementation.
BUG=chromium:1008568
BRANCH=none
TEST=Build and run on MCU to forward touchpad events to host
through I2C HID.
Change-Id: I89108f0cdce1a9a11bf1e26e43c6662959c7184e
Signed-off-by: Shecky Lin <sheckylin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2094927
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/i2c_hid_touchpad.c | 420 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/i2c_hid.h | 67 | ||||
-rw-r--r-- | include/i2c_hid_touchpad.h | 55 |
5 files changed, 546 insertions, 0 deletions
diff --git a/common/build.mk b/common/build.mk index 1bf54a3dfe..35004d87db 100644 --- a/common/build.mk +++ b/common/build.mk @@ -77,6 +77,7 @@ common-$(CONFIG_HOSTCMD_GET_UPTIME_INFO)+=uptime.o common-$(CONFIG_HOSTCMD_PD)+=host_command_master.o common-$(CONFIG_HOSTCMD_RTC)+=rtc.o common-$(CONFIG_I2C_DEBUG)+=i2c_trace.o +common-$(CONFIG_I2C_HID_TOUCHPAD)+=i2c_hid_touchpad.o common-$(CONFIG_I2C_MASTER)+=i2c_master.o common-$(CONFIG_I2C_SLAVE)+=i2c_slave.o common-$(CONFIG_I2C_BITBANG)+=i2c_bitbang.o diff --git a/common/i2c_hid_touchpad.c b/common/i2c_hid_touchpad.c new file mode 100644 index 0000000000..cda5800a11 --- /dev/null +++ b/common/i2c_hid_touchpad.c @@ -0,0 +1,420 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "i2c_hid_touchpad.h" + +#include "console.h" +#include "util.h" + +/* 2 bytes for length + 1 byte for report ID */ +#define I2C_HID_HEADER_SIZE 3 + +/* Report ID */ +#define REPORT_ID_TOUCH 0x01 +#define REPORT_ID_MOUSE 0x02 +#define REPORT_ID_DEVICE_CAPS 0x0A +#define REPORT_ID_DEVICE_CERT 0x0B +#define REPORT_ID_INPUT_MODE 0x0C +#define REPORT_ID_REPORTING 0x0D + +#define INPUT_MODE_MOUSE 0x00 +#define INPUT_MODE_TOUCH 0x03 + +/* VID/PID/FW version */ +#if !defined(I2C_HID_TOUCHPAD_VENDOR_ID) || \ + !defined(I2C_HID_TOUCHPAD_PRODUCT_ID) || \ + !defined(I2C_HID_TOUCHPAD_FW_VERSION) +#error "Must define touchpad VID/PID/FW version" +#endif +/* + * Touchpad properties + * + * Physical dimensions are in the unit of mms. + */ +#if !defined(I2C_HID_TOUCHPAD_MAX_X) || \ + !defined(I2C_HID_TOUCHPAD_MAX_Y) || \ + !defined(I2C_HID_TOUCHPAD_MAX_PHYSICAL_X) || \ + !defined(I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y) +#error "Must define finger maximum X/Y and physical dimensions" +#endif +/* + * Maximum width/height of the contact (i.e., touch major/minor in Linux MT-B) + * + * According to the Linux's MT protocol, the max value of touch major/minor + * should be sqrt(X^2+Y^2). However, this is rarely implemented by touchpads + * in practice. Touchpads often output major/minor in custom units with very + * different data ranges. It is therefore recommended for the user to check the + * device's spec and set these values manually. + */ +#if !defined(I2C_HID_TOUCHPAD_MAX_WIDTH) || \ + !defined(I2C_HID_TOUCHPAD_MAX_HEIGHT) || \ + !defined(I2C_HID_TOUCHPAD_MAX_PRESSURE) +#error "Must define finger maximum width/height/pressure" +#endif +/* + * The touchpad is expected to provide at least the horizontal/vertical status + * for each contact (if one is wider than its height). This can be computed + * simply as bool(WIDTH>HEIGHT). + */ +#ifndef I2C_HID_TOUCHPAD_MAX_ORIENTATION +#error "Must define finger maximum orientation value" +#endif +/* + * Conversion factor between the finger movement and the mouse cursor movement. + * This is a bit similar to the mouse CPI and is used by mouse reports only. + */ +#if !defined(I2C_HID_TOUCHPAD_MOUSE_SCALE_X) || \ + !defined(I2C_HID_TOUCHPAD_MOUSE_SCALE_Y) +#error "Must define mouse horizontal/vertical scaling factors" +#endif + +/* Helper bit-op macros */ +#define N_BITS(n) \ +( \ + (n) < (1 << 1) ? 1 : \ + (n) < (1 << 2) ? 2 : \ + (n) < (1 << 3) ? 3 : \ + (n) < (1 << 4) ? 4 : \ + (n) < (1 << 5) ? 5 : \ + (n) < (1 << 6) ? 6 : \ + (n) < (1 << 7) ? 7 : \ + (n) < (1 << 8) ? 8 : \ + (n) < (1 << 9) ? 9 : \ + (n) < (1 << 10) ? 10 : \ + (n) < (1 << 11) ? 11 : \ + (n) < (1 << 12) ? 12 : \ + (n) < (1 << 13) ? 13 : \ + (n) < (1 << 14) ? 14 : \ + (n) < (1 << 15) ? 15 : \ + 16 \ +) +/* We would need to pad some bits at the end of each finger struct to match + * the allocation unit's boundary so the array indexing may work correctly. + */ +#define N_VAR_BITS \ +( \ + N_BITS(I2C_HID_TOUCHPAD_MAX_X) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_Y) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE) + \ + N_BITS(I2C_HID_TOUCHPAD_MAX_ORIENTATION) \ +) +#define N_PADDING_BITS ((DIV_ROUND_UP(N_VAR_BITS, 8) * 8) - N_VAR_BITS) +#define N_BITS_ORIENTATION \ + (N_BITS(I2C_HID_TOUCHPAD_MAX_ORIENTATION) + N_PADDING_BITS) +/* Structs for holding input report data + * + * These need to be modified in correspondence with the HID input report + * descriptor below. + * + * The HID usage names differ from the Evdev event names in some cases. For + * example, touch major/minor are put under width/height and orientation is + * called azimuth. + */ +struct finger { + /* + * Whether a finger is intentional or not. This could be used to + * identify unintended contacts or palms but is up to the OS + * explanation. + */ + uint8_t confidence:1; + /* + * Whether a finger is touching the surface (leaving/left finger gets + * 0). + */ + uint8_t tip:1; + /* + * Whether a finger is within the sensor range. For example, hovering + * fingers would have tip=0 and inrange=1. + */ + uint8_t inrange:1; + /* + * Contact id. This is like slot numbers in Linux MT-B. + */ + uint8_t id:5; + uint16_t x:N_BITS(I2C_HID_TOUCHPAD_MAX_X); + uint16_t y:N_BITS(I2C_HID_TOUCHPAD_MAX_Y); + uint16_t width:N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH); + uint16_t height:N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT); + uint16_t pressure:N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE); + uint16_t orientation:N_BITS_ORIENTATION; +} __packed; + +struct touch_report { + uint8_t button:1; + uint8_t count:7; + uint16_t timestamp; + struct finger finger[I2C_HID_TOUCHPAD_MAX_FINGERS]; +} __packed; + +struct mouse_report { + uint8_t button1:1; + /* Windows expects at least two button usages in a mouse report. Many + * touchpads on the Chromebook are a single clickable surface, so + * button2 isn't used. That said, we may later report a button2 event if + * necessary. + */ + uint8_t button2:1; + uint8_t unused:6; + int8_t x; + int8_t y; +} __packed; + +/* HID input report descriptor + * + * For a complete reference, please see the following docs on usb.org + * + * 1. Device Class Definition for HID + * 2. HID Usage Tables + */ +static const uint8_t report_desc[] = { + /* Mouse Collection */ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ + 0x09, 0x02, /* Usage (Mouse) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x85, REPORT_ID_MOUSE, /* Report ID (Mouse) */ + 0x09, 0x01, /* Usage (Pointer) */ + 0xA1, 0x00, /* Collection (Physical) */ + 0x05, 0x09, /* Usage Page (Button) */ + 0x19, 0x01, /* Usage Minimum (Button 1) */ + 0x29, 0x02, /* Usage Maximum (Button 2) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, 0x02, /* Report Count (2) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ + 0x95, 0x06, /* Report Count (6) */ + 0x81, 0x03, /* Input (Cnst,Var,Abs) */ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ + 0x09, 0x30, /* Usage (X) */ + 0x09, 0x31, /* Usage (Y) */ + 0x15, 0x81, /* Logical Minimum (-127) */ + 0x25, 0x7F, /* Logical Maximum (127) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x02, /* Report Count (2) */ + 0x81, 0x06, /* Input (Data,Var,Rel) */ + 0xC0, /* End Collection */ + 0xC0, /* End Collection */ + + /* Touchpad Collection */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x09, 0x05, /* Usage (Touch Pad) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x85, REPORT_ID_TOUCH, /* Report ID (Touch) */ + + /* Button */ + 0x05, 0x09, /* Usage Page (Button) */ + 0x19, 0x01, /* Usage Minimum (0x01) */ + 0x29, 0x01, /* Usage Maximum (0x01) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0x75, 0x01, /* Report Size (1) */ + 0x95, 0x01, /* Report Count (1) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ + + /* Contact count */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x09, 0x54, /* Usage (Contact count) */ + 0x25, I2C_HID_TOUCHPAD_MAX_FINGERS, /* Logical Max. (MAX_FINGERS) */ + 0x75, 0x07, /* Report Size (7) */ + 0x95, 0x01, /* Report Count (1) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ + + /* Scan time */ + 0x55, 0x0C, /* Unit Exponent (-4) */ + 0x66, 0x01, 0x10, /* Unit (Seconds) */ + 0x47, 0xFF, 0xFF, 0x00, 0x00, /* Physical Maximum (65535) */ + 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535) */ + 0x75, 0x10, /* Report Size (16) */ + 0x95, 0x01, /* Report Count (1) */ + 0x05, 0x0D, /* Usage Page (Digitizers) */ + 0x09, 0x56, /* Usage (Scan Time) */ + 0x81, 0x02, /* Input (Data,Var,Abs) */ + +#define FINGER(FINGER_NUMBER) \ + /* Finger FINGER_NUMBER */ \ + 0x05, 0x0D, /* Usage Page (Digitizer) */ \ + 0x09, 0x22, /* Usage (Finger) */ \ + 0xA1, 0x02, /* Collection (Logical) */ \ + 0x09, 0x47, /* Usage (Confidence) */ \ + 0x09, 0x42, /* Usage (Tip Switch) */ \ + 0x09, 0x32, /* Usage (In Range) */ \ + 0x15, 0x00, /* Logical Minimum (0) */ \ + 0x25, 0x01, /* Logical Maximum (1) */ \ + 0x75, 0x01, /* Report Size (1) */ \ + 0x95, 0x03, /* Report Count (3) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x51, /* Usage (Contact identifier) */ \ + 0x25, 0x1F, /* Logical Maximum (31) */ \ + 0x75, 0x05, /* Report Size (5) */ \ + 0x95, 0x01, /* Report Count (1) */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x05, 0x01, /* Usage Page (Generic Desktop) */ \ + 0x09, 0x30, /* Usage (X) */ \ + 0x55, 0x0E, /* Unit Exponent (-2) */ \ + 0x65, 0x11, /* Unit (SI Linear, Length: cm) */ \ + 0x35, 0x00, /* Physical Minimum (0) */ \ + 0x46, I2C_HID_TOUCHPAD_MAX_PHYSICAL_X&0xff, \ + I2C_HID_TOUCHPAD_MAX_PHYSICAL_X>>8, \ + /* Physical Maximum */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_X&0xff, I2C_HID_TOUCHPAD_MAX_X>>8, \ + /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_X), \ + /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x31, /* Usage (Y) */ \ + 0x46, I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y&0xff, \ + I2C_HID_TOUCHPAD_MAX_PHYSICAL_Y>>8, \ + /* Physical Maximum */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_Y&0xff, I2C_HID_TOUCHPAD_MAX_Y>>8, \ + /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_Y), \ + /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x05, 0x0D, /* Usage Page (Digitizer) */ \ + 0x09, 0x48, /* Usage (Width) */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_WIDTH&0xff, I2C_HID_TOUCHPAD_MAX_WIDTH>>8, \ + /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_WIDTH), \ + /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x49, /* Usage (Height) */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_HEIGHT&0xff, I2C_HID_TOUCHPAD_MAX_HEIGHT>>8,\ + /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_HEIGHT), \ + /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x30, /* Usage (Tip pressure) */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_PRESSURE&0xff, \ + I2C_HID_TOUCHPAD_MAX_PRESSURE>>8, \ + /* Logical Maximum */ \ + 0x75, N_BITS(I2C_HID_TOUCHPAD_MAX_PRESSURE), \ + /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0x09, 0x3f, /* Usage (Azimuth Orientation) */ \ + 0x16, 0x00, 0x00, /* Logical Minimum (0) */ \ + 0x26, I2C_HID_TOUCHPAD_MAX_ORIENTATION&0xff, \ + I2C_HID_TOUCHPAD_MAX_ORIENTATION>>8, \ + /* Logical Maximum */ \ + 0x75, N_BITS_ORIENTATION, /* Report Size */ \ + 0x81, 0x02, /* Input (Data,Var,Abs) */ \ + 0xC0, /* End Collection */ + + FINGER(1) + FINGER(2) + FINGER(3) + FINGER(4) + FINGER(5) + +#undef FINGER + + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x85, REPORT_ID_DEVICE_CAPS, /* Report ID (Device Capabilities) */ + 0x09, 0x55, /* Usage (Contact Count Maximum) */ + 0x09, 0x59, /* Usage (Pad Type) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x02, /* Report Count (2) */ + 0x25, 0x0F, /* Logical Maximum (15) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ + 0x85, REPORT_ID_DEVICE_CERT, /* Report ID (Device Certification) */ + 0x09, 0xC5, /* Usage (Vendor Usage 0xC5) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ + 0x75, 0x08, /* Report Size (8) */ + 0x96, 0x00, 0x01, /* Report Count (256) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0xC0, /* End Collection */ + + /* Configuration Collection */ + 0x05, 0x0D, /* Usage Page (Digitizer) */ + 0x09, 0x0E, /* Usage (Configuration) */ + 0xA1, 0x01, /* Collection (Application) */ + 0x85, REPORT_ID_INPUT_MODE, /* Report ID (Input Mode) */ + 0x09, 0x22, /* Usage (Finger) */ + 0xA1, 0x02, /* Collection (Logical) */ + 0x09, 0x52, /* Usage (Input Mode) */ + 0x15, 0x00, /* Logical Minimum (0) */ + 0x25, 0x0F, /* Logical Maximum (15) */ + 0x75, 0x08, /* Report Size (8) */ + 0x95, 0x01, /* Report Count (1) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0xC0, /* End Collection */ + 0x09, 0x22, /* Usage (Finger) */ + 0xA1, 0x00, /* Collection (Physical) */ + 0x85, REPORT_ID_REPORTING, /* Report ID (Selective Reporting)*/ + 0x09, 0x57, /* Usage (Surface Switch) */ + 0x09, 0x58, /* Usage (Button Switch) */ + 0x75, 0x04, /* Report Size (4) */ + 0x95, 0x02, /* Report Count (2) */ + 0x25, 0x01, /* Logical Maximum (1) */ + 0xB1, 0x02, /* Feature (Data,Var,Abs) */ + 0xC0, /* End Collection */ + 0xC0, /* End Collection */ +}; + +static const uint8_t device_caps[] = { + I2C_HID_TOUCHPAD_MAX_FINGERS, /* Contact Count Maximum */ + 0x00, /* Pad Type: Depressible click-pad */ +}; + +/* A 256-byte default blob for the 'device certification status' feature report + * expected by Windows. + */ +static const uint8_t device_cert[] = { + 0xFC, 0x28, 0xFE, 0x84, 0x40, 0xCB, 0x9A, 0x87, + 0x0D, 0xBE, 0x57, 0x3C, 0xB6, 0x70, 0x09, 0x88, + 0x07, 0x97, 0x2D, 0x2B, 0xE3, 0x38, 0x34, 0xB6, + 0x6C, 0xED, 0xB0, 0xF7, 0xE5, 0x9C, 0xF6, 0xC2, + 0x2E, 0x84, 0x1B, 0xE8, 0xB4, 0x51, 0x78, 0x43, + 0x1F, 0x28, 0x4B, 0x7C, 0x2D, 0x53, 0xAF, 0xFC, + 0x47, 0x70, 0x1B, 0x59, 0x6F, 0x74, 0x43, 0xC4, + 0xF3, 0x47, 0x18, 0x53, 0x1A, 0xA2, 0xA1, 0x71, + 0xC7, 0x95, 0x0E, 0x31, 0x55, 0x21, 0xD3, 0xB5, + 0x1E, 0xE9, 0x0C, 0xBA, 0xEC, 0xB8, 0x89, 0x19, + 0x3E, 0xB3, 0xAF, 0x75, 0x81, 0x9D, 0x53, 0xB9, + 0x41, 0x57, 0xF4, 0x6D, 0x39, 0x25, 0x29, 0x7C, + 0x87, 0xD9, 0xB4, 0x98, 0x45, 0x7D, 0xA7, 0x26, + 0x9C, 0x65, 0x3B, 0x85, 0x68, 0x89, 0xD7, 0x3B, + 0xBD, 0xFF, 0x14, 0x67, 0xF2, 0x2B, 0xF0, 0x2A, + 0x41, 0x54, 0xF0, 0xFD, 0x2C, 0x66, 0x7C, 0xF8, + 0xC0, 0x8F, 0x33, 0x13, 0x03, 0xF1, 0xD3, 0xC1, + 0x0B, 0x89, 0xD9, 0x1B, 0x62, 0xCD, 0x51, 0xB7, + 0x80, 0xB8, 0xAF, 0x3A, 0x10, 0xC1, 0x8A, 0x5B, + 0xE8, 0x8A, 0x56, 0xF0, 0x8C, 0xAA, 0xFA, 0x35, + 0xE9, 0x42, 0xC4, 0xD8, 0x55, 0xC3, 0x38, 0xCC, + 0x2B, 0x53, 0x5C, 0x69, 0x52, 0xD5, 0xC8, 0x73, + 0x02, 0x38, 0x7C, 0x73, 0xB6, 0x41, 0xE7, 0xFF, + 0x05, 0xD8, 0x2B, 0x79, 0x9A, 0xE2, 0x34, 0x60, + 0x8F, 0xA3, 0x32, 0x1F, 0x09, 0x78, 0x62, 0xBC, + 0x80, 0xE3, 0x0F, 0xBD, 0x65, 0x20, 0x08, 0x13, + 0xC1, 0xE2, 0xEE, 0x53, 0x2D, 0x86, 0x7E, 0xA7, + 0x5A, 0xC5, 0xD3, 0x7D, 0x98, 0xBE, 0x31, 0x48, + 0x1F, 0xFB, 0xDA, 0xAF, 0xA2, 0xA8, 0x6A, 0x89, + 0xD6, 0xBF, 0xF2, 0xD3, 0x32, 0x2A, 0x9A, 0xE4, + 0xCF, 0x17, 0xB7, 0xB8, 0xF4, 0xE1, 0x33, 0x08, + 0x24, 0x8B, 0xC4, 0x43, 0xA5, 0xE5, 0x24, 0xC2, +}; + +#define MAX_SIZEOF(a, b) (sizeof(a) > sizeof(b) ? sizeof(a) : sizeof(b)) + +static struct i2c_hid_descriptor hid_desc = { + .wHIDDescLength = I2C_HID_DESC_LENGTH, + .bcdVersion = I2C_HID_BCD_VERSION, + .wReportDescLength = sizeof(report_desc), + .wReportDescRegister = I2C_HID_REPORT_DESC_REGISTER, + .wInputRegister = I2C_HID_INPUT_REPORT_REGISTER, + .wMaxInputLength = I2C_HID_HEADER_SIZE + + MAX_SIZEOF(struct touch_report, struct mouse_report), + .wOutputRegister = 0, + .wMaxOutputLength = 0, + .wCommandRegister = I2C_HID_COMMAND_REGISTER, + .wDataRegister = I2C_HID_DATA_REGISTER, + .wVendorID = I2C_HID_TOUCHPAD_VENDOR_ID, + .wProductID = I2C_HID_TOUCHPAD_PRODUCT_ID, + .wVersionID = I2C_HID_TOUCHPAD_FW_VERSION, +}; + diff --git a/include/config.h b/include/config.h index 45ca08e6da..22204bf717 100644 --- a/include/config.h +++ b/include/config.h @@ -2244,6 +2244,9 @@ */ #undef CONFIG_SMBUS_PEC +/* Support I2C HID touchpad interface. */ +#undef CONFIG_I2C_HID_TOUCHPAD + /* * Add hosts-side support for entering programming mode for I2C ITE ECs. * Must define ite_dfu_config_t for configuration in board file. diff --git a/include/i2c_hid.h b/include/i2c_hid.h new file mode 100644 index 0000000000..8568b42837 --- /dev/null +++ b/include/i2c_hid.h @@ -0,0 +1,67 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * General definitions for I2C-HID + * + * For a complete reference, please see the following docs on + * https://docs.microsoft.com/ + * + * 1. hid-over-i2c-protocol-spec-v1-0.docx + */ +#ifndef __CROS_EC_I2C_HID_H +#define __CROS_EC_I2C_HID_H + +#include "common.h" +#include "stdint.h" + +/* + * I2C-HID registers + * + * Except for I2C_HID_HID_DESC_REGISTER, fields in this section can be chosen + * freely so we just picked something that we are happy with. + * + * I2C_HID_HID_DESC_REGISTER is defined in the ACPI table so please make sure + * you have put in the same value there. + */ +#define I2C_HID_HID_DESC_REGISTER 0x0001 +#define I2C_HID_REPORT_DESC_REGISTER 0x1000 +#define I2C_HID_INPUT_REPORT_REGISTER 0x2000 +#define I2C_HID_COMMAND_REGISTER 0x3000 +#define I2C_HID_DATA_REGISTER 0x3000 + +/* I2C-HID commands */ +#define I2C_HID_CMD_RESET 0x01 +#define I2C_HID_CMD_GET_REPORT 0x02 +#define I2C_HID_CMD_SET_REPORT 0x03 +#define I2C_HID_CMD_GET_IDLE 0x04 +#define I2C_HID_CMD_SET_IDLE 0x05 +#define I2C_HID_CMD_GET_PROTOCOL 0x06 +#define I2C_HID_CMD_SET_PROTOCOL 0x07 +#define I2C_HID_CMD_SET_POWER 0x08 + +/* Common HID fields */ +#define I2C_HID_DESC_LENGTH sizeof(struct i2c_hid_descriptor) +#define I2C_HID_BCD_VERSION 0x0100 + +/* I2C-HID HID descriptor */ +struct __packed i2c_hid_descriptor { + uint16_t wHIDDescLength; + uint16_t bcdVersion; + uint16_t wReportDescLength; + uint16_t wReportDescRegister; + uint16_t wInputRegister; + uint16_t wMaxInputLength; + uint16_t wOutputRegister; + uint16_t wMaxOutputLength; + uint16_t wCommandRegister; + uint16_t wDataRegister; + uint16_t wVendorID; + uint16_t wProductID; + uint16_t wVersionID; + uint32_t reserved; +}; + +#endif /* __CROS_EC_I2C_HID_H */ diff --git a/include/i2c_hid_touchpad.h b/include/i2c_hid_touchpad.h new file mode 100644 index 0000000000..e24c0f0ab8 --- /dev/null +++ b/include/i2c_hid_touchpad.h @@ -0,0 +1,55 @@ +/* Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Implementation of I2C HID for touchpads */ +#ifndef __CROS_EC_I2C_HID_TOUCHPAD_H +#define __CROS_EC_I2C_HID_TOUCHPAD_H + +#include "common.h" +#include "i2c_hid.h" +#include "stdbool.h" +#include "stdint.h" + +/* Max fingers to support */ +#define I2C_HID_TOUCHPAD_MAX_FINGERS 5 + +/* + * Struct holding a touchpad event + * + * The user should parse the original touchpad report, apply necessary + * transformations and fill the result in this common struct. The touchpad is + * assumed to implement the Linux HID MT-B protocol. + */ +struct touchpad_event { + /* If hover is detected */ + bool hover; + /* If button is clicked */ + bool button; + /* Struct for contacts */ + struct { + /* X & Y of the contact */ + uint16_t x; + uint16_t y; + /* Pressure/contact area */ + uint16_t pressure; + /* W & H of the contact */ + uint16_t width; + uint16_t height; + /* + * Orientation of the contact ellipse. Can be plain 0 if + * unavailable. + */ + uint16_t orientation; + /* + * If the touchpad believes it is a palm. Some touchpads report + * it through the confidence field. + */ + bool is_palm; + /* If this slot contains valid contact (touching the surface) */ + bool valid; + } __packed finger[I2C_HID_TOUCHPAD_MAX_FINGERS]; +} __packed; + +#endif /* __CROS_EC_I2C_HID_TOUCHPAD_H */ |