summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShecky Lin <sheckylin@chromium.org>2020-03-11 15:15:46 +0800
committerCommit Bot <commit-bot@chromium.org>2020-03-17 12:11:46 +0000
commitc6f631c3e461cdafe5b643fa5d12415d67097ac6 (patch)
tree2df6ee9ff6f3da0353449dcfea21d3d3c38cdcfc
parente5e676f641dec32ddf4b32d1b8f4f9636e31ff2a (diff)
downloadchrome-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.mk1
-rw-r--r--common/i2c_hid_touchpad.c420
-rw-r--r--include/config.h3
-rw-r--r--include/i2c_hid.h67
-rw-r--r--include/i2c_hid_touchpad.h55
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 */