summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei-Han Chen <stimim@google.com>2018-03-12 20:15:34 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-03-27 18:22:58 +0000
commit40eed04c2bc7536ead3ca8f1861d3796827c7e38 (patch)
tree8602a1e86d336ea8d2a927fe1dee11410f32b003
parente1f2136d8af819af173fc1288877f938ca7f13c2 (diff)
downloadchrome-ec-40eed04c2bc7536ead3ca8f1861d3796827c7e38.tar.gz
ec: add driver/touchpad_st.c
Initial commit for ST touchpad. This CL will support X/Y mode function. BRANCH=none BUG=none TEST=make BOARD=whiskers TEST=manually test touchpad function on whiskers Signed-off-by: Wei-Han Chen <stimim@chromium.org> Change-Id: I1669286ca764fbbd4a691171193415dd4999673f Reviewed-on: https://chromium-review.googlesource.com/958894 Commit-Ready: Wei-Han Chen <stimim@chromium.org> Tested-by: Wei-Han Chen <stimim@chromium.org> Reviewed-by: Wei-Han Chen <stimim@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/982348 Reviewed-by: Furquan Shaikh <furquan@chromium.org> Commit-Queue: Furquan Shaikh <furquan@chromium.org> Tested-by: Furquan Shaikh <furquan@chromium.org> Trybot-Ready: Furquan Shaikh <furquan@chromium.org>
-rw-r--r--driver/build.mk1
-rw-r--r--driver/touchpad_st.c474
-rw-r--r--driver/touchpad_st.h245
-rw-r--r--include/update_fw.h17
4 files changed, 732 insertions, 5 deletions
diff --git a/driver/build.mk b/driver/build.mk
index cc0a119640..541b8df235 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -90,6 +90,7 @@ driver-$(CONFIG_TEMP_SENSOR_F75303)+=temp_sensor/f75303.o
# Touchpads
driver-$(CONFIG_TOUCHPAD_ELAN)+=touchpad_elan.o
+driver-$(CONFIG_TOUCHPAD_ST)+=touchpad_st.o
# Thermistors
driver-$(CONFIG_THERMISTOR_NCP15WB)+=temp_sensor/thermistor_ncp15wb.o
diff --git a/driver/touchpad_st.c b/driver/touchpad_st.c
new file mode 100644
index 0000000000..0806f93a6a
--- /dev/null
+++ b/driver/touchpad_st.c
@@ -0,0 +1,474 @@
+/* Copyright 2018 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 "atomic.h"
+#include "board.h"
+#include "common.h"
+#include "console.h"
+#include "gpio.h"
+#include "hwtimer.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "registers.h"
+#include "spi.h"
+#include "task.h"
+#include "timer.h"
+#include "touchpad.h"
+#include "touchpad_st.h"
+#include "update_fw.h"
+#include "usb_hid_touchpad.h"
+#include "util.h"
+
+/* Console output macros */
+#define CC_TOUCHPAD CC_USB
+#define CPUTS(outstr) cputs(CC_TOUCHPAD, outstr)
+#define CPRINTF(format, args...) cprintf(CC_TOUCHPAD, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_TOUCHPAD, format, ## args)
+
+#define SPI (&(spi_devices[SPI_ST_TP_DEVICE_ID]))
+
+BUILD_ASSERT(sizeof(struct st_tp_event_t) == 8);
+
+static struct st_tp_system_info_t system_info;
+
+static int st_tp_read_all_events(void);
+static int st_tp_send_ack(void);
+static int st_tp_start_scan(void);
+static int st_tp_read_host_buffer_header(void);
+
+/*
+ * Current system state, meaning of each bit is defined below.
+ */
+static int system_state;
+
+#define SYSTEM_STATE_DEBUG_MODE (1 << 0)
+#define SYSTEM_STATE_ENABLE_HEAT_MAP (1 << 1)
+#define SYSTEM_STATE_ENABLE_DOME_SWITCH (1 << 2)
+#define SYSTEM_STATE_ACTIVE_MODE (1 << 3)
+#define SYSTEM_STATE_DOME_SWITCH_LEVEL (1 << 4)
+
+/*
+ * Timestamp of last interrupt (32 bits are enough as we divide the value by 100
+ * and then put it in a 16-bit field).
+ */
+static uint32_t irq_ts;
+
+static struct {
+#if ST_TP_DUMMY_BYTE == 1
+ uint8_t dummy;
+#endif
+ union {
+ uint8_t bytes[512];
+ struct st_tp_host_buffer_header_t buffer_header;
+ struct st_tp_host_buffer_heat_map_t heat_map;
+ struct st_tp_host_data_header_t data_header;
+ struct st_tp_event_t events[32];
+ } /* anonymous */;
+} __packed rx_buf;
+
+static void set_bits(int *lvalue, int rvalue, int mask)
+{
+ *lvalue &= ~mask;
+ *lvalue |= rvalue & mask;
+}
+
+/*
+ * Parse a finger report from ST event and save it to (report)->finger.
+ *
+ * @param report: pointer to a USB HID touchpad report.
+ * @param event: a pointer event from ST.
+ * @param i: array index for next finger.
+ *
+ * @return array index of next finger (i.e. (i + 1) if a finger is added).
+ */
+static int st_tp_parse_finger(struct usb_hid_touchpad_report *report,
+ struct st_tp_event_t *event,
+ int i)
+{
+ /* We cannot report more fingers */
+ if (i >= ARRAY_SIZE(report->finger))
+ return i;
+
+ /* This is not a finger */
+ if (event->finger.touch_type == ST_TP_TOUCH_TYPE_INVALID)
+ return i;
+
+ switch (event->evt_id) {
+ case ST_TP_EVENT_ID_ENTER_POINTER:
+ case ST_TP_EVENT_ID_MOTION_POINTER:
+ report->finger[i].tip = 1;
+ report->finger[i].inrange = 1;
+ report->finger[i].id = event->finger.touch_id;
+ report->finger[i].pressure = event->finger.z;
+ report->finger[i].width = (event->finger.minor |
+ (event->minor_high << 4));
+ report->finger[i].height = (event->finger.major |
+ (event->major_high << 4));
+ report->finger[i].x = (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_X -
+ event->finger.x);
+ report->finger[i].y = (CONFIG_USB_HID_TOUCHPAD_LOGICAL_MAX_Y -
+ event->finger.y);
+ break;
+ case ST_TP_EVENT_ID_LEAVE_POINTER:
+ report->finger[i].id = event->finger.touch_id;
+ break;
+ }
+ return i + 1;
+}
+
+static int st_tp_write_hid_report(void)
+{
+ int ret, i, num_finger;
+ struct usb_hid_touchpad_report report;
+ struct st_tp_event_t *event;
+
+ ret = st_tp_read_host_buffer_header();
+ if (ret)
+ return ret;
+
+ if (rx_buf.buffer_header.flags & ST_TP_BUFFER_HEADER_DOMESWITCH_CHG) {
+ /*
+ * dome_switch_level from device is inverted.
+ * That is, 0 => pressed, 1 => released.
+ */
+ set_bits(&system_state,
+ (rx_buf.buffer_header.dome_switch_level ?
+ 0 : SYSTEM_STATE_DOME_SWITCH_LEVEL),
+ SYSTEM_STATE_DOME_SWITCH_LEVEL);
+ }
+
+ ret = st_tp_read_all_events();
+ if (ret)
+ return ret;
+
+ memset(&report, 0, sizeof(report));
+ report.id = 0x1;
+ num_finger = 0;
+
+ for (i = 0; i < ARRAY_SIZE(rx_buf.events); i++) {
+ event = &rx_buf.events[i];
+
+ /*
+ * this is not a valid event, and assume all following
+ * events are invalid too
+ */
+ if (event->magic != 0x3)
+ break;
+
+ switch (event->evt_id) {
+ case ST_TP_EVENT_ID_ENTER_POINTER:
+ case ST_TP_EVENT_ID_MOTION_POINTER:
+ case ST_TP_EVENT_ID_LEAVE_POINTER:
+ num_finger = st_tp_parse_finger(&report,
+ event,
+ num_finger);
+ break;
+ default:
+ break;
+ }
+ }
+
+ report.button = !!(system_state & SYSTEM_STATE_DOME_SWITCH_LEVEL);
+ report.count = num_finger;
+ report.timestamp = irq_ts / USB_HID_TOUCHPAD_TIMESTAMP_UNIT;
+
+ set_touchpad_report(&report);
+ return ret;
+}
+
+static int st_tp_read_report(void)
+{
+ if (system_state & SYSTEM_STATE_ENABLE_HEAT_MAP) {
+ /* TODO(stimim): implement this */
+ } else {
+ st_tp_write_hid_report();
+ }
+ return st_tp_send_ack();
+}
+
+static int st_tp_read_host_buffer_header(void)
+{
+ const uint8_t tx_buf[] = { ST_TP_CMD_READ_SPI_HOST_BUFFER, 0x00, 0x00 };
+ int rx_len = ST_TP_DUMMY_BYTE + sizeof(rx_buf.buffer_header);
+
+ return spi_transaction(SPI, tx_buf, sizeof(tx_buf),
+ (uint8_t *)&rx_buf, rx_len);
+}
+
+static int st_tp_send_ack(void)
+{
+ uint8_t tx_buf[] = { ST_TP_CMD_SPI_HOST_BUFFER_ACK };
+
+ return spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0);
+}
+
+static int st_tp_update_system_state(int new_state, int mask)
+{
+ int ret = EC_SUCCESS;
+
+ /* copy reserved bits */
+ set_bits(&new_state, system_state, ~mask);
+
+ mask = SYSTEM_STATE_DEBUG_MODE;
+ if ((new_state & mask) != (system_state & mask))
+ set_bits(&system_state, new_state, mask);
+
+ mask = SYSTEM_STATE_ENABLE_HEAT_MAP | SYSTEM_STATE_ENABLE_DOME_SWITCH;
+ if ((new_state & mask) != (system_state & mask)) {
+ uint8_t tx_buf[] = {
+ ST_TP_CMD_WRITE_FEATURE_SELECT,
+ 0x05,
+ 0
+ };
+ if (new_state & SYSTEM_STATE_ENABLE_HEAT_MAP)
+ tx_buf[2] |= 1 << 0;
+ if (new_state & SYSTEM_STATE_ENABLE_DOME_SWITCH)
+ tx_buf[2] |= 1 << 1;
+ ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0);
+ if (ret)
+ return ret;
+ set_bits(&system_state, new_state, mask);
+ }
+
+ mask = SYSTEM_STATE_ACTIVE_MODE;
+ if ((new_state & mask) != (system_state & mask)) {
+ uint8_t tx_buf[] = {
+ ST_TP_CMD_WRITE_SCAN_MODE_SELECT,
+ ST_TP_SCAN_MODE_ACTIVE,
+ !!(new_state & SYSTEM_STATE_ACTIVE_MODE),
+ };
+ CPRINTS("Enable Multi-Touch: %d", tx_buf[2]);
+ ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0);
+ if (ret)
+ return ret;
+ set_bits(&system_state, new_state, mask);
+ }
+ return ret;
+}
+
+static void st_tp_enable_interrupt(int enable)
+{
+ uint8_t tx_buf[] = {
+ ST_TP_CMD_WRITE_SYSTEM_COMMAND, 0x01, enable ? 1 : 0};
+ if (enable)
+ gpio_enable_interrupt(GPIO_TOUCHPAD_INT);
+ spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0);
+ if (!enable)
+ gpio_disable_interrupt(GPIO_TOUCHPAD_INT);
+}
+
+static int st_tp_start_scan(void)
+{
+ int new_state = (SYSTEM_STATE_ACTIVE_MODE |
+ SYSTEM_STATE_ENABLE_DOME_SWITCH);
+ int mask = new_state;
+ int ret;
+
+ ret = st_tp_update_system_state(new_state, mask);
+ if (ret)
+ return ret;
+ st_tp_send_ack();
+ st_tp_enable_interrupt(1);
+ return ret;
+}
+
+static int st_tp_read_host_data_memory(uint16_t addr, void *rx_buf, int len) {
+ uint8_t tx_buf[] = {
+ ST_TP_CMD_READ_HOST_DATA_MEMORY, addr >> 8, addr & 0xFF
+ };
+
+ return spi_transaction(SPI, tx_buf, sizeof(tx_buf), rx_buf, len);
+}
+
+static int st_tp_load_host_data(uint8_t mem_id)
+{
+ uint8_t tx_buf[] = {
+ ST_TP_CMD_WRITE_SYSTEM_COMMAND, 0x06, mem_id
+ };
+ int retry, ret;
+ uint16_t count;
+ struct st_tp_host_data_header_t *header = &rx_buf.data_header;
+ int rx_len = sizeof(*header) + ST_TP_DUMMY_BYTE;
+
+ st_tp_read_host_data_memory(0x0000, &rx_buf, rx_len);
+ if (header->host_data_mem_id == mem_id)
+ return EC_SUCCESS; /* already loaded no need to reload */
+
+ count = header->count;
+
+ ret = spi_transaction(SPI, tx_buf, sizeof(tx_buf), NULL, 0);
+ if (ret)
+ return ret;
+
+ ret = EC_ERROR_TIMEOUT;
+ retry = 5;
+ while (retry--) {
+ st_tp_read_host_data_memory(0x0000, &rx_buf, rx_len);
+ if (header->magic == ST_TP_HEADER_MAGIC &&
+ header->host_data_mem_id == mem_id &&
+ header->count != count) {
+ ret = EC_SUCCESS;
+ break;
+ }
+ usleep(10 * MSEC);
+ }
+ return ret;
+}
+
+/*
+ * Read System Info from Host Data Memory.
+ *
+ * @param reload: true to force reloading system info into host data memory
+ * before reading.
+ */
+static int st_tp_read_system_info(int reload)
+{
+ int ret = EC_SUCCESS;
+ int rx_len = ST_TP_DUMMY_BYTE + ST_TP_SYSTEM_INFO_LEN;
+ uint8_t *ptr = rx_buf.bytes;
+
+ if (reload)
+ ret = st_tp_load_host_data(ST_TP_MEM_ID_SYSTEM_INFO);
+ if (ret)
+ return ret;
+ ret = st_tp_read_host_data_memory(0x0000, &rx_buf, rx_len);
+ if (ret)
+ return ret;
+
+ /* Parse the content */
+ memcpy(&system_info, ptr, ST_TP_SYSTEM_INFO_PART_1_SIZE);
+
+ /* Check header */
+ if (system_info.header.magic != ST_TP_HEADER_MAGIC ||
+ system_info.header.host_data_mem_id != ST_TP_MEM_ID_SYSTEM_INFO)
+ return EC_ERROR_UNKNOWN;
+
+ ptr += ST_TP_SYSTEM_INFO_PART_1_SIZE;
+ ptr += ST_TP_SYSTEM_INFO_PART_1_RESERVED;
+ memcpy(&system_info.scr_res_x, ptr, ST_TP_SYSTEM_INFO_PART_2_SIZE);
+
+#define ST_TP_SHOW(attr) CPRINTS(#attr ": %04x", system_info.attr)
+ ST_TP_SHOW(chip0_id[0]);
+ ST_TP_SHOW(chip0_id[1]);
+ ST_TP_SHOW(chip0_ver);
+ ST_TP_SHOW(scr_tx_len);
+ ST_TP_SHOW(scr_rx_len);
+ ST_TP_SHOW(release_info);
+#undef ST_TP_SHOW
+ return ret;
+}
+
+static int st_tp_read_all_events(void)
+{
+ uint8_t cmd = ST_TP_CMD_READ_ALL_EVENTS;
+ int rx_len = sizeof(rx_buf.events) + ST_TP_DUMMY_BYTE;
+
+ return spi_transaction(SPI, &cmd, 1, (uint8_t *)&rx_buf, rx_len);
+}
+
+static int st_tp_reset(void)
+{
+ board_touchpad_reset();
+ return st_tp_read_all_events();
+}
+
+/* Initialize the controller ICs after reset */
+static void st_tp_init(void)
+{
+ st_tp_reset();
+ /*
+ * On boot, ST firmware will load system info to host data memory,
+ * So we don't need to reload it.
+ */
+ st_tp_read_system_info(0);
+
+ system_state = 0;
+
+ st_tp_start_scan();
+}
+
+#ifdef CONFIG_USB_UPDATE
+int touchpad_get_info(struct touchpad_info *tp)
+{
+ if (st_tp_read_system_info(1)) {
+ tp->status = EC_RES_SUCCESS;
+ tp->vendor = ST_VENDOR_ID;
+ /*
+ * failed to get system info, FW corrupted, return some default
+ * values.
+ */
+ tp->st.id = 0x3936;
+ tp->st.fw_version = 0;
+ tp->st.fw_checksum = 0;
+ return sizeof(*tp);
+ }
+
+ tp->status = EC_RES_SUCCESS;
+ tp->vendor = ST_VENDOR_ID;
+ tp->st.id = (system_info.chip0_id[0] << 8) | system_info.chip0_id[1];
+ tp->st.fw_version = system_info.release_info;
+ tp->st.fw_checksum = system_info.fw_crc;
+
+ return sizeof(*tp);
+}
+
+/*
+ * @param offset: should be address between 0 to 1M, aligned with
+ * ST_TP_DMA_CHUNK_SIZE.
+ * @param size: length of `data` array.
+ * @param data: content of new touchpad firmware.
+ */
+int touchpad_update_write(int offset, int size, const uint8_t *data)
+{
+ CPRINTS("%s %08x %d", __func__, offset, size);
+
+ return EC_RES_INVALID_COMMAND;
+}
+
+int touchpad_debug(const uint8_t *param, unsigned int param_size,
+ uint8_t **data, unsigned int *data_size)
+{
+ return EC_RES_INVALID_COMMAND;
+}
+#endif
+
+void touchpad_interrupt(enum gpio_signal signal)
+{
+ irq_ts = __hw_clock_source_read();
+
+ task_wake(TASK_ID_TOUCHPAD);
+}
+
+void touchpad_task(void *u)
+{
+ st_tp_init();
+
+ while (1) {
+ task_wait_event(-1);
+
+ while (!gpio_get_level(GPIO_TOUCHPAD_INT))
+ st_tp_read_report();
+ }
+}
+
+/* Debugging commands */
+static int command_touchpad_st(int argc, char **argv)
+{
+ if (argc != 2)
+ return EC_ERROR_PARAM_COUNT;
+ if (strcasecmp(argv[1], "enable") == 0) {
+ return EC_ERROR_NOT_HANDLED;
+ } else if (strcasecmp(argv[1], "disable") == 0) {
+ return EC_ERROR_NOT_HANDLED;
+ } else if (strcasecmp(argv[1], "version") == 0) {
+ st_tp_read_system_info(1);
+ return 0;
+ } else {
+ return EC_ERROR_PARAM1;
+ }
+}
+DECLARE_CONSOLE_COMMAND(touchpad_st, command_touchpad_st,
+ "<enable|disable|version>",
+ "Read write spi. id is spi_devices array index");
diff --git a/driver/touchpad_st.h b/driver/touchpad_st.h
new file mode 100644
index 0000000000..23bb404d36
--- /dev/null
+++ b/driver/touchpad_st.h
@@ -0,0 +1,245 @@
+/* Copyright 2018 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.
+ */
+
+#ifndef __CROS_EC_TOUCHPAD_ST_H
+#define __CROS_EC_TOUCHPAD_ST_H
+
+#include <stdint.h>
+
+#include "common.h"
+
+#define ST_VENDOR_ID 0x0483
+
+#define ST_TP_DUMMY_BYTE 1
+
+#define ST_TP_CMD_READ_ALL_EVENTS 0x87
+#define ST_TP_CMD_WRITE_SCAN_MODE_SELECT 0xA0
+#define ST_TP_CMD_WRITE_FEATURE_SELECT 0xA2
+#define ST_TP_CMD_WRITE_SYSTEM_COMMAND 0xA4
+#define ST_TP_CMD_WRITE_HOST_DATA_MEMORY 0xA6
+#define ST_TP_CMD_READ_HOST_DATA_MEMORY 0xA7
+#define ST_TP_CMD_WRITE_FW_CONFIG 0xA8
+#define ST_TP_CMD_READ_FW_CONFIG 0xA9
+#define ST_TP_CMD_SPI_HOST_BUFFER_ACK 0xC0
+#define ST_TP_CMD_READ_SPI_HOST_BUFFER 0xC1
+
+#define ST_TP_CMD_WRITE_HW_REG 0xFA
+#define ST_TP_CMD_READ_HW_REG 0xFB
+
+/* Max number of bytes that the DMA can burn on the flash in one shot in FTI */
+#define ST_TP_FLASH_BUFFER_SIZE (64 * 1024)
+/* Max number of bytes that can be written in I2C to the DMA */
+#define ST_TP_DMA_CHUNK_SIZE 32
+
+#define ST_HOST_BUFFER_DATA_VALID (1 << 0)
+#define ST_HOST_BUFFER_MT_READY (1 << 3)
+#define ST_HOST_BUFFER_SF_READY (1 << 4)
+#define ST_HOST_BUFFER_SS_READY (1 << 5)
+
+#define ST_TP_SCAN_MODE_ACTIVE 0x00
+#define ST_TP_SCAN_MODE_LOW_POWER 0x01
+#define ST_TP_SCAN_MODE_TUNING_WIZARD 0x02
+#define ST_TP_SCAN_MODE_LOCKED 0x03
+
+#define ST_TOUCH_ROWS (18) /* force len */
+#define ST_TOUCH_COLS (25) /* sense len */
+
+#define ST_TOUCH_HEADER_SIZE 32
+
+#define BYTES_PER_PIXEL 2
+/* Number of bits per pixel, this value is decided by experiments. */
+#define BITS_PER_PIXEL (11)
+
+#define ST_TOUCH_FRAME_SIZE (ST_TOUCH_ROWS * ST_TOUCH_COLS * \
+ BYTES_PER_PIXEL)
+#define ST_TOUCH_FORCE_SIZE (ST_TOUCH_ROWS * BYTES_PER_PIXEL)
+#define ST_TOUCH_SENSE_SIZE (ST_TOUCH_COLS * BYTES_PER_PIXEL)
+
+#define ST_TP_MEM_ID_SYSTEM_INFO 0x01
+
+#define ST_TP_FLASH_OFFSET_CODE (0x0000 << 2)
+#define ST_TP_FLASH_OFFSET_CONFIG (0x7C00 << 2)
+#define ST_TP_FLASH_OFFSET_CX (0x7000 << 2)
+
+
+struct st_tp_host_data_header_t {
+#define ST_TP_HEADER_MAGIC 0xA5
+ uint8_t magic; /* this should always be ST_TP_HEADER_MAGIC */
+ uint8_t host_data_mem_id;
+ uint16_t count;
+} __packed;
+
+/* Compute offset of end of a member in given type */
+#define endof(type, member) (offsetof(type, member) + \
+ sizeof(((type *)NULL)->member))
+
+struct st_tp_system_info_t {
+ /* Part 1, basic info */
+ struct st_tp_host_data_header_t header;
+ uint16_t api_ver_rev;
+ uint8_t api_ver_minor;
+ uint8_t api_ver_major;
+ uint16_t chip0_ver;
+ uint8_t chip0_id[2]; /* should be 0x3936 */
+ uint16_t chip1_ver;
+ uint16_t chip1_id;
+ uint16_t fw_ver;
+ uint16_t svn_rev;
+ uint16_t cfg_ver;
+ uint16_t cfg_project_id;
+ uint16_t cx_ver;
+ uint16_t cx_project_id;
+ uint8_t cfg_afe_ver;
+ uint8_t cx_afe_ver;
+ uint8_t panel_cfg_afe_ver;
+ uint8_t protocol;
+ uint8_t die_id[16];
+ uint64_t release_info; /* unsigned little endian 64 bit integer */
+ uint32_t fw_crc;
+ uint32_t cfg_crc;
+#define ST_TP_SYSTEM_INFO_PART_1_SIZE endof(struct st_tp_system_info_t, cfg_crc)
+#define ST_TP_SYSTEM_INFO_PART_1_RESERVED 16
+
+ uint16_t scr_res_x;
+ uint16_t scr_res_y;
+ uint8_t scr_tx_len;
+ uint8_t scr_rx_len;
+ uint8_t key_len;
+ uint8_t frc_len;
+#define ST_TP_SYSTEM_INFO_PART_2_SIZE (endof(struct st_tp_system_info_t, \
+ frc_len) - \
+ offsetof(struct st_tp_system_info_t, \
+ scr_res_x))
+#define ST_TP_SYSTEM_INFO_PART_2_RESERVED 40
+
+#if 0 /* the following parts are defined in spec, but not currently used. */
+
+ uint16_t dbg_frame_addr;
+#define ST_TP_SYSTEM_INFO_PART_3_SIZE (endof(struct st_tp_system_info_t, \
+ dbg_frame_addr) - \
+ offsetof(struct st_tp_system_info_t, \
+ dbg_frame_addr))
+#define ST_TP_SYSTEM_INFO_PART_3_RESERVED 6
+
+ uint16_t ms_scr_raw_addr;
+ uint16_t ms_scr_filter_addr;
+ uint16_t ms_scr_str_addr;
+ uint16_t ms_scr_bl_addr;
+ uint16_t ss_tch_tx_raw_addr;
+ uint16_t ss_tch_tx_filter_addr;
+ uint16_t ss_tch_tx_str_addr;
+ uint16_t ss_tch_tx_bl_addr;
+ uint16_t ss_tch_rx_raw_addr;
+ uint16_t ss_tch_rx_filter_addr;
+ uint16_t ss_tch_rx_str_addr;
+ uint16_t ss_tch_rx_bl_addr;
+ uint16_t key_raw_addr;
+ uint16_t key_filter_addr;
+ uint16_t key_str_addr;
+ uint16_t key_bl_addr;
+ uint16_t frc_raw_addr;
+ uint16_t frc_filter_addr;
+ uint16_t frc_str_addr;
+ uint16_t frc_bl_addr;
+ uint16_t ss_hvr_tx_raw_addr;
+ uint16_t ss_hvr_tx_filter_addr;
+ uint16_t ss_hvr_tx_str_addr;
+ uint16_t ss_hvr_tx_bl_addr;
+ uint16_t ss_hvr_rx_raw_addr;
+ uint16_t ss_hvr_rx_filter_addr;
+ uint16_t ss_hvr_rx_str_addr;
+ uint16_t ss_hvr_rx_bl_addr;
+ uint16_t ss_prx_tx_raw_addr;
+ uint16_t ss_prx_tx_filter_addr;
+ uint16_t ss_prx_tx_str_addr;
+ uint16_t ss_prx_tx_bl_addr;
+ uint16_t ss_prx_rx_raw_addr;
+ uint16_t ss_prx_rx_filter_addr;
+ uint16_t ss_prx_rx_str_addr;
+ uint16_t ss_prx_rx_bl_addr;
+#define ST_TP_SYSTEM_INFO_PART_4_SIZE (endof(struct st_tp_system_info_t, \
+ ss_prx_rx_bl_addr) - \
+ offsetof(struct st_tp_system_info_t, \
+ ms_scr_raw_addr))
+#endif /* if 0 */
+} __packed;
+
+#define ST_TP_SYSTEM_INFO_LEN (sizeof(struct st_tp_system_info_t) + \
+ ST_TP_SYSTEM_INFO_PART_1_RESERVED)
+
+struct st_tp_host_buffer_header_t {
+#define ST_TP_BUFFER_HEADER_DATA_VALID (1 << 0)
+#define ST_TP_BUFFER_HEADER_EVT_FIFO_NOT_EMPTY (1 << 1)
+#define ST_TP_BUFFER_HEADER_SYS_FAULT (1 << 2)
+#define ST_TP_BUFFER_HEADER_HEAT_MAP_MT_RDY (1 << 3)
+#define ST_TP_BUFFER_HEADER_HEAT_MAP_SF_RDY (1 << 4)
+#define ST_TP_BUFFER_HEADER_HEAT_MAP_SS_RDY (1 << 5)
+#define ST_TP_BUFFER_HEADER_DOMESWITCH_CHG (1 << 6)
+ uint8_t flags;
+ uint8_t reserved[3];
+ uint8_t heatmap_miss_count;
+ uint8_t event_count;
+ uint8_t event_miss_count;
+ uint8_t dome_switch_down_count:3;
+ uint8_t dome_switch_up_count:3;
+ uint8_t dome_switch_level:1;
+ uint8_t dome_switch_overflow:1;
+} __packed;
+
+struct st_tp_host_buffer_heat_map_t {
+ uint8_t frame[ST_TOUCH_FRAME_SIZE];
+#if 0 /* we are not using these now */
+ uint8_t force[ST_TOUCH_FORCE_SIZE];
+ uint8_t sense[ST_TOUCH_SENSE_SIZE];
+#endif
+} __packed;
+
+struct st_tp_event_t {
+ unsigned magic:2; /* should always be 0x3 */
+ unsigned major_high:2;
+#define ST_TP_EVENT_ID_ENTER_POINTER 0x1
+#define ST_TP_EVENT_ID_MOTION_POINTER 0x2
+#define ST_TP_EVENT_ID_LEAVE_POINTER 0x3
+#define ST_TP_EVENT_ID_STATUS_REPORT 0x4
+#define ST_TP_EVENT_ID_USER_REPORT 0x5
+#define ST_TP_EVENT_ID_DEBUG_REPORT 0xe
+#define ST_TP_EVENT_ID_ERROR_REPORT 0xf
+ unsigned evt_id:4;
+
+ union {
+ struct {
+#define ST_TP_TOUCH_TYPE_INVALID 0x0
+#define ST_TP_TOUCH_TYPE_FINGER 0x1
+#define ST_TP_TOUCH_TYPE_GLOVE 0x2
+#define ST_TP_TOUCH_TYPE_STYLUS 0x3
+#define ST_TP_TOUCH_TYPE_PALM 0x4
+ unsigned touch_type:4;
+ unsigned touch_id:4;
+ unsigned y:12;
+ unsigned x:12;
+ uint8_t z;
+ uint8_t minor:4; // need to be concat with minor_high
+ uint8_t major:4; // need to be concat with major_high
+ } __packed finger;
+
+ struct {
+ uint8_t report_type;
+ uint32_t info;
+ uint8_t reserved;
+ } __packed report;
+ } __packed ; /* anonymous */
+
+ unsigned minor_high:2;
+ unsigned reserved:1;
+ unsigned evt_left:5;
+} __packed;
+
+enum ST_TP_MODE {
+ X_Y_MODE = 0,
+ HEAT_MAP_MODE,
+};
+
+#endif /* __CROS_EC_TOUCHPAD_ST_H */
+
diff --git a/include/update_fw.h b/include/update_fw.h
index e454f129bd..b013b77a75 100644
--- a/include/update_fw.h
+++ b/include/update_fw.h
@@ -211,11 +211,18 @@ struct touchpad_info {
uint8_t allowed_fw_hash[32];
/* Vendor specific data. */
- struct {
- uint16_t id;
- uint16_t fw_version;
- uint16_t fw_checksum;
- } elan;
+ union {
+ struct {
+ uint16_t id;
+ uint16_t fw_version;
+ uint16_t fw_checksum;
+ } elan __packed;
+ struct {
+ uint16_t id;
+ uint16_t fw_version;
+ uint16_t fw_checksum;
+ } st __packed;
+ } __packed;
} __packed;
/*