summaryrefslogtreecommitdiff
path: root/nt36xxx/nt36xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'nt36xxx/nt36xxx.c')
-rw-r--r--nt36xxx/nt36xxx.c115
1 files changed, 108 insertions, 7 deletions
diff --git a/nt36xxx/nt36xxx.c b/nt36xxx/nt36xxx.c
index a93ea5c..8547ad3 100644
--- a/nt36xxx/nt36xxx.c
+++ b/nt36xxx/nt36xxx.c
@@ -31,6 +31,8 @@
#define NVT_PRODUCT_ID 0x7806
#define NVT_VERSION 0x0100
+#define INFO_BUF_SIZE (64 + 1)
+
#if defined(CONFIG_DRM_PANEL)
#include <drm/drm_panel.h>
#elif defined(CONFIG_DRM_MSM)
@@ -1453,6 +1455,9 @@ static enum power_supply_property pen_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+#if NVT_TOUCH_EXT_USI
+ POWER_SUPPLY_PROP_SERIAL_NUMBER,
+#endif
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_SCOPE,
};
@@ -1498,6 +1503,15 @@ static int pen_get_battery_property(struct power_supply *psy,
break;
+#if NVT_TOUCH_EXT_USI
+ case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+ /* the latest serial number */
+ mutex_lock(&ts->lock);
+ val->strval = ts->battery_serial_number_str;
+ mutex_unlock(&ts->lock);
+
+ break;
+#endif
case POWER_SUPPLY_PROP_STATUS:
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
break;
@@ -1550,6 +1564,50 @@ static void pen_clean_battery(struct power_supply *battery)
kfree(psy_desc);
}
+#if NVT_TOUCH_EXT_USI
+static void process_usi_responses(uint16_t info_buf_flags, const uint8_t *info_buf)
+{
+ uint32_t pen_serial_high;
+ uint32_t pen_serial_low;
+ uint8_t pen_bat_capa;
+
+ if (info_buf_flags & USI_GID_FLAG) {
+ nvt_usi_store_gid(info_buf + USI_GID_OFFSET);
+ nvt_usi_get_serial_number(&pen_serial_high, &pen_serial_low);
+ if (ts->pen_serial_high != pen_serial_high ||
+ ts->pen_serial_low != pen_serial_low) {
+ int idx = 0;
+ int sz = sizeof(ts->battery_serial_number_str);
+
+ idx += scnprintf(ts->battery_serial_number_str + idx, sz - idx,
+ "%08X", pen_serial_high);
+ idx += scnprintf(ts->battery_serial_number_str + idx, sz - idx,
+ "%08X", pen_serial_low);
+
+ ts->pen_serial_high = pen_serial_high;
+ ts->pen_serial_low = pen_serial_low;
+
+ power_supply_changed(ts->pen_bat_psy);
+ }
+ }
+
+ if (info_buf_flags & USI_BATTERY_FLAG) {
+ nvt_usi_store_battery(info_buf + USI_BATTERY_OFFSET);
+ nvt_usi_get_battery(&pen_bat_capa);
+ if (ts->pen_bat_capa != pen_bat_capa) {
+ ts->pen_bat_capa = pen_bat_capa;
+ power_supply_changed(ts->pen_bat_psy);
+ }
+ }
+
+ if (info_buf_flags & USI_FW_VERSION_FLAG)
+ nvt_usi_store_fw_version(info_buf + USI_FW_VERSION_OFFSET);
+
+ if (info_buf_flags & USI_CAPABILITY_FLAG)
+ nvt_usi_store_capability(info_buf + USI_CAPABILITY_OFFSET);
+}
+#endif
+
static irqreturn_t nvt_ts_isr(int irq, void *handle)
{
struct nvt_ts_data *ts = (struct nvt_ts_data *)handle;
@@ -1592,6 +1650,11 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data)
uint32_t pen_btn2 = 0;
uint8_t touch_freq_index;
uint8_t pen_freq_index;
+#if NVT_TOUCH_EXT_USI
+ uint8_t info_buf[INFO_BUF_SIZE] = {0};
+ uint16_t info_buf_flags;
+ uint32_t pen_serial_low;
+#endif
if (!ts->probe_done)
return IRQ_HANDLED;
@@ -1871,10 +1934,6 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data)
#endif
pen_btn1 = (uint32_t)(point_data[77] & 0x01);
pen_btn2 = (uint32_t)((point_data[77] >> 1) & 0x01);
- if (point_data[78] && ts->pen_bat_capa != (uint32_t)point_data[78]) {
- ts->pen_bat_capa = (uint32_t)point_data[78];
- power_supply_changed(ts->pen_bat_psy);
- }
// printk("x=%d,y=%d,p=%d,tx=%d,ty=%d,d=%d,b1=%d,b2=%d,bat=%d\n", pen_x, pen_y, pen_pressure,
// pen_tilt_x, pen_tilt_y, pen_distance, pen_btn1, pen_btn2, pen_battery);
@@ -1902,13 +1961,35 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data)
input_report_key(ts->pen_input_dev, BTN_TOOL_PEN, 1);
input_report_key(ts->pen_input_dev, BTN_STYLUS, pen_btn1);
input_report_key(ts->pen_input_dev, BTN_STYLUS2, pen_btn2);
+#if NVT_TOUCH_EXT_USI
+ /*
+ * Input Subsystem doesn't support 64bits serial number.
+ * So we only reports the lower 32bit.
+ */
+ if (!nvt_usi_get_serial_number(NULL, &pen_serial_low))
+ input_event(ts->pen_input_dev, EV_MSC,
+ MSC_SERIAL, pen_serial_low);
+#endif
+ input_sync(ts->pen_input_dev);
+#if NVT_TOUCH_EXT_USI
+ info_buf_flags = point_data[63] + (point_data[64] << 8);
+
+ if (info_buf_flags) {
+ nvt_set_page(ts->mmap->EB_INFO_ADDR);
+ info_buf[0] = ts->mmap->EB_INFO_ADDR & 0x7F;
+ CTP_SPI_READ(ts->client, info_buf, INFO_BUF_SIZE);
+ nvt_set_page(ts->mmap->EVENT_BUF_ADDR);
+
+ process_usi_responses(info_buf_flags, info_buf);
+ }
+#endif
} else if (ts->pen_format_id == 0xF0) {
// report Pen ID
} else {
NVT_ERR("Unknown pen format id!\n");
goto XFER_ERROR;
}
- } else { // pen_format_id = 0xFF, i.e. no pen present
+ } else if (ts->pen_active) { // pen_format_id = 0xFF and a pen was reporting
input_set_timestamp(ts->pen_input_dev, ts->timestamp);
/* Snapshot some stylus context information for offload */
@@ -1929,9 +2010,15 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data)
input_report_key(ts->pen_input_dev, BTN_TOOL_PEN, 0);
input_report_key(ts->pen_input_dev, BTN_STYLUS, 0);
input_report_key(ts->pen_input_dev, BTN_STYLUS2, 0);
+#if NVT_TOUCH_EXT_USI
+ if (!nvt_usi_get_serial_number(NULL, &pen_serial_low))
+ input_event(ts->pen_input_dev, EV_MSC, MSC_SERIAL, pen_serial_low);
+#endif
+ input_sync(ts->pen_input_dev);
+#if NVT_TOUCH_EXT_USI
+ nvt_usi_clear_stylus_read_map();
+#endif
}
-
- input_sync(ts->pen_input_dev);
} /* if (ts->pen_support) */
/* Check any sensing freq hopping for touch or stylus. */
@@ -2399,6 +2486,10 @@ static int32_t nvt_ts_probe(struct spi_device *client)
input_set_abs_params(ts->pen_input_dev, ABS_TILT_Y, PEN_TILT_MIN,
PEN_TILT_MAX, 0, 0);
+#if NVT_TOUCH_EXT_USI
+ __set_bit(EV_MSC, ts->pen_input_dev->evbit);
+ __set_bit(MSC_SERIAL, ts->pen_input_dev->mscbit);
+#endif
snprintf(ts->pen_phys, sizeof(ts->pen_phys), "input/pen");
ts->pen_input_dev->name = NVT_PEN_NAME;
ts->pen_input_dev->uniq = ts->pen_input_dev->name;
@@ -2882,6 +2973,9 @@ int nvt_ts_suspend(struct device *dev)
{
uint8_t buf[4] = {0};
uint32_t i = 0;
+#if NVT_TOUCH_EXT_USI
+ uint32_t pen_serial_low;
+#endif
if (!ts->bTouchIsAwake) {
NVT_LOG("Touch is already suspend\n");
@@ -2955,12 +3049,19 @@ int nvt_ts_suspend(struct device *dev)
input_report_key(ts->pen_input_dev, BTN_TOOL_PEN, 0);
input_report_key(ts->pen_input_dev, BTN_STYLUS, 0);
input_report_key(ts->pen_input_dev, BTN_STYLUS2, 0);
+#if NVT_TOUCH_EXT_USI
+ if (!nvt_usi_get_serial_number(NULL, &pen_serial_low))
+ input_event(ts->pen_input_dev, EV_MSC, MSC_SERIAL, pen_serial_low);
+#endif
input_sync(ts->pen_input_dev);
ts->pen_active = 0;
ts->pen_offload_coord_timestamp = ts->timestamp;
memset(&ts->pen_offload_coord, 0,
sizeof(ts->pen_offload_coord));
+#if NVT_TOUCH_EXT_USI
+ nvt_usi_clear_stylus_read_map();
+#endif
}
#if (WAKEUP_GESTURE) && (NVT_TOUCH_EXT_API)