summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Pfetsch <spfetsch@google.com>2023-04-24 16:31:48 -0700
committerSteve Pfetsch <spfetsch@google.com>2023-09-20 01:40:38 -0700
commit31a52ccf8ddf9dd852f1a6c5f8dd37e26b71e6f9 (patch)
tree32e5296bd36ea4fe49aad4fc2d13c974ff4a00d8
parentf64ddf4ab6423810776918c6c40e6cda8c3c06ad (diff)
downloadcommon-31a52ccf8ddf9dd852f1a6c5f8dd37e26b71e6f9.tar.gz
touch/common: gti: interactive calibrate/self-test interface
Introduce an interface that exposes the driver's calibration and self-test functionality with extra care placed on ensuring the client is knowledgable about conditions required to safely calibrate the touch screen. The interface provides foolproofing to prevent casual read/writes to the driver node from triggering calibration, as the client must be aware of the interface's timing constraints and perform actions within predetermined time intervals. A well-behaved client is expected to fulfill UI obligations on behalf of the driver, such as displaying appropriate instructional messages regarding how the touchscreen must be situated before calibration begins, alerting the user not to touch the screen as calibration begins, and providing a message indicating when calibration has completed. The interface also provides a means for users to run a touchscreen's self-test, but the consequences of doing so incorrectly are not detrimental to the touchscreen's performance. Bug: 230050981 Change-Id: I9649ccca804ad22f24ee81cc9d17a1ccb1e45b6e Signed-off-by: Steve Pfetsch <spfetsch@google.com>
-rw-r--r--goog_touch_interface.c328
-rw-r--r--goog_touch_interface.h86
2 files changed, 414 insertions, 0 deletions
diff --git a/goog_touch_interface.c b/goog_touch_interface.c
index 5fcb677..884da8c 100644
--- a/goog_touch_interface.c
+++ b/goog_touch_interface.c
@@ -478,6 +478,10 @@ static ssize_t vrr_enabled_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t vrr_enabled_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size);
+static ssize_t interactive_calibrate_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+static ssize_t interactive_calibrate_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size);
static DEVICE_ATTR_RO(config_name);
static DEVICE_ATTR_RW(force_active);
@@ -500,6 +504,7 @@ static DEVICE_ATTR_RW(sensing_enabled);
static DEVICE_ATTR_RO(test_limits_name);
static DEVICE_ATTR_RW(v4l2_enabled);
static DEVICE_ATTR_RW(vrr_enabled);
+static DEVICE_ATTR_RW(interactive_calibrate);
static struct attribute *goog_attributes[] = {
&dev_attr_config_name.attr,
@@ -523,6 +528,7 @@ static struct attribute *goog_attributes[] = {
&dev_attr_test_limits_name.attr,
&dev_attr_v4l2_enabled.attr,
&dev_attr_vrr_enabled.attr,
+ &dev_attr_interactive_calibrate.attr,
NULL,
};
@@ -1313,6 +1319,316 @@ static ssize_t vrr_enabled_store(struct device *dev,
return size;
}
+/* -----------------------------------------------------------------------
+ * Interactive calibration states
+ *
+ * State "IDLE"/ 0 - idle, no calibration underway => return to this state after
+ * an error and after certain timeouts have elapsed
+ *
+ * State "INIT_X" / 101 / 201 - calibration or test is beginning. The client
+ * has displayed warnings and will begin transitioning itself to the
+ * "screen off" / "do not touch" state
+ *
+ * State "RUN_X" / 102 / 202 - screen is off and nothing is touching the
+ * screen. Calibration can begin immediately when this state is entered
+ *
+ * State "END_X" / 103 / 203 - the client has waited the designated time and
+ * will assume calibration/test is complete, will read the status of this state
+ * as the final calibration status. Transition back to the IDLE state will
+ * occur automatically.
+ */
+bool ical_state_idle(struct goog_touch_interface *gti, u32 next_state,
+ u64 elapsed)
+{
+ /* Valid next-states are 'INIT_CAL', 'INIT_TEST', or 'IDLE' */
+ if (next_state == ICAL_STATE_IDLE) {
+ gti->ical_result = ICAL_RES_SUCCESS;
+ gti->ical_func_result = 0;
+ /* Do not update the ical timestamp */
+ return false;
+ } else if ((next_state == ICAL_STATE_INIT_CAL ||
+ next_state == ICAL_STATE_INIT_TEST) &&
+ elapsed > MIN_DELAY_IDLE) {
+ gti->ical_state = next_state;
+ gti->ical_result = ICAL_RES_SUCCESS;
+ } else {
+ GOOG_ERR(gti,
+ "ical - error: invalid transition or time! %u => %u, min=%lluns, t=%lluns\n",
+ gti->ical_state, next_state, MIN_DELAY_IDLE,
+ elapsed);
+ gti->ical_state = ICAL_STATE_IDLE;
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+ return true;
+}
+
+void ical_state_init_cal(struct goog_touch_interface *gti, u32 next_state,
+ u64 elapsed)
+{
+ u32 ret;
+
+ /* only valid next-state is 'RUN_CAL', as long as time elapsed
+ * is within range. When 'RUN_CAL' is received calibration begins.
+ */
+ if (next_state == ICAL_STATE_RUN_CAL &&
+ elapsed > MIN_DELAY_INIT_CAL && elapsed < MAX_DELAY_INIT_CAL) {
+ /* Begin calibration */
+
+ gti->cmd.calibrate_cmd.result = GTI_CALIBRATE_RESULT_NA;
+ memset(gti->cmd.calibrate_cmd.buffer, 0,
+ sizeof(gti->cmd.calibrate_cmd.buffer));
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_CALIBRATE);
+ if (ret == 0) {
+ if (gti->cmd.calibrate_cmd.result == GTI_CALIBRATE_RESULT_DONE) {
+ gti->ical_func_result = gti->cmd.calibrate_cmd.result;
+ GOOG_INFO(gti,
+ "ical - CALIBRATE_RESULT_DONE - [%s]\n",
+ gti->cmd.calibrate_cmd.buffer);
+ } else {
+ gti->ical_func_result = ICAL_RES_FAIL;
+ GOOG_ERR(gti,
+ "ical - calibrate result other/fail - N/A or [%s]\n",
+ gti->cmd.calibrate_cmd.buffer);
+ }
+
+ gti->ical_state = ICAL_STATE_RUN_CAL;
+ gti->ical_result = ICAL_RES_SUCCESS;
+ } else {
+ gti->ical_state = ICAL_STATE_IDLE;
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+ } else {
+ GOOG_ERR(gti,
+ "ical - error: invalid transition or time! %u => %u, min=%lluns, t=%lluns, max=%lluns\n",
+ gti->ical_state, next_state,
+ MIN_DELAY_INIT_CAL, elapsed,
+ MAX_DELAY_INIT_CAL);
+ gti->ical_state = ICAL_STATE_IDLE;
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+}
+
+void ical_state_run_cal(struct goog_touch_interface *gti, u32 next_state,
+ u64 elapsed)
+{
+ /* only valid next-state is 'END_CAL', as long as time elapsed
+ * is within ranged.
+ */
+ if (next_state == ICAL_STATE_END_CAL &&
+ elapsed > MIN_DELAY_RUN_CAL && elapsed < MAX_DELAY_RUN_CAL) {
+ GOOG_INFO(gti,
+ "ical - Calibration complete after %lluns\n",
+ elapsed);
+
+ gti->ical_state = ICAL_STATE_END_CAL;
+ gti->ical_result = ICAL_RES_SUCCESS;
+
+ } else {
+ GOOG_ERR(gti,
+ "ical - error: invalid transition or time! %u => %u, min=%lluns, t=%lluns, max=%lluns\n",
+ gti->ical_state, next_state,
+ MIN_DELAY_RUN_CAL, elapsed,
+ MAX_DELAY_RUN_CAL);
+ gti->ical_state = ICAL_STATE_IDLE;
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+}
+
+void ical_state_end_cal(struct goog_touch_interface *gti, u32 next_state,
+ u64 elapsed)
+{
+ /* Nothing to do but accept a transition back to IDLE.
+ * Necessary because the interface only executes when called
+ */
+ if (next_state == ICAL_STATE_IDLE &&
+ elapsed > MIN_DELAY_END_CAL && elapsed < MAX_DELAY_END_CAL) {
+ gti->ical_result = ICAL_RES_SUCCESS;
+ } else {
+ GOOG_ERR(gti,
+ "ical - error: invalid transition or time! %u => %u, min=%lluns, t=%lluns, max=%lluns\n",
+ gti->ical_state, next_state,
+ MIN_DELAY_END_CAL, elapsed,
+ MAX_DELAY_END_CAL);
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+ gti->ical_state = ICAL_STATE_IDLE;
+}
+
+void ical_state_init_test(struct goog_touch_interface *gti, u32 next_state,
+ u64 elapsed)
+{
+ u32 ret;
+
+ /* only valid next-state is 'RUN_TEST', as long as time elapsed
+ * is within range. When '202' is received calibration begins.
+ */
+ if (next_state == ICAL_STATE_RUN_TEST &&
+ elapsed > MIN_DELAY_INIT_TEST && elapsed < MAX_DELAY_INIT_TEST) {
+ /* Begin selftest */
+
+ gti->cmd.selftest_cmd.result = GTI_SELFTEST_RESULT_NA;
+ memset(gti->cmd.selftest_cmd.buffer, 0,
+ sizeof(gti->cmd.selftest_cmd.buffer));
+ ret = goog_process_vendor_cmd(gti, GTI_CMD_SELFTEST);
+ if (ret == 0) {
+ if (gti->cmd.selftest_cmd.result ==
+ GTI_SELFTEST_RESULT_DONE) {
+ gti->ical_func_result = gti->cmd.selftest_cmd.result;
+
+ GOOG_INFO(gti,
+ "ical - SELFTEST_RESULT_DONE - [%s]\n",
+ gti->cmd.selftest_cmd.buffer);
+ } else if (gti->cmd.selftest_cmd.result ==
+ GTI_SELFTEST_RESULT_SHELL_CMDS_REDIRECT) {
+ gti->ical_func_result = ICAL_RES_SUCCESS;
+
+ GOOG_ERR(gti,
+ "ical - SELFTEST_RESULT_SHELL_CMDS_REDIRECT - [%s]\n",
+ gti->cmd.selftest_cmd.buffer);
+ } else {
+ gti->ical_func_result = ICAL_RES_FAIL;
+
+ GOOG_ERR(gti,
+ "ical - selftest result other/fail - N/A or [%s]\n",
+ gti->cmd.selftest_cmd.buffer);
+ }
+
+ gti->ical_state = ICAL_STATE_RUN_TEST;
+ gti->ical_result = ICAL_RES_SUCCESS;
+ } else {
+ gti->ical_state = ICAL_STATE_IDLE;
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+ } else {
+ GOOG_ERR(gti,
+ "ical - error: invalid transition or time! %u => %u, min=%lluns, t=%lluns, max=%lluns\n",
+ gti->ical_state, next_state,
+ MIN_DELAY_INIT_TEST, elapsed,
+ MAX_DELAY_INIT_TEST);
+ gti->ical_state = ICAL_STATE_IDLE;
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+}
+
+void ical_state_run_test(struct goog_touch_interface *gti, u32 next_state,
+ u64 elapsed)
+{
+ /* only valid next-state is 'END_TEST', as long as time elapsed
+ * is within ranged.
+ */
+ if (next_state == ICAL_STATE_END_TEST &&
+ elapsed > MIN_DELAY_RUN_TEST && elapsed < MAX_DELAY_RUN_TEST) {
+ /* Check and evaluate self-test here */
+ gti->ical_state = ICAL_STATE_END_TEST;
+ gti->ical_result = ICAL_RES_SUCCESS;
+
+ } else {
+ GOOG_ERR(gti,
+ "ical - error: invalid transition or time! %u => %u, min=%lluns, t=%lluns, max=%lluns\n",
+ gti->ical_state, next_state,
+ MIN_DELAY_RUN_TEST, elapsed,
+ MAX_DELAY_RUN_TEST);
+ gti->ical_state = ICAL_STATE_IDLE;
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+}
+
+void ical_state_end_test(struct goog_touch_interface *gti, u32 next_state,
+ u64 elapsed)
+{
+ /* Nothing to do but accept a transition back to IDLE.
+ * Necessary because the interface only executes when called
+ */
+ if (next_state == ICAL_STATE_IDLE &&
+ elapsed > MIN_DELAY_END_TEST && elapsed < MAX_DELAY_END_TEST) {
+ gti->ical_result = ICAL_RES_SUCCESS;
+ } else {
+ GOOG_ERR(gti,
+ "ical - error: invalid transition or time! %u => %u, min=%lluns, t=%lluns, max=%lluns\n",
+ gti->ical_state, next_state,
+ MIN_DELAY_END_TEST, elapsed,
+ MAX_DELAY_END_TEST);
+ gti->ical_result = ICAL_RES_FAIL;
+ }
+ gti->ical_state = ICAL_STATE_IDLE;
+}
+
+/* Advance the interactive calibration state machine */
+static ssize_t interactive_calibrate_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct goog_touch_interface *gti = dev_get_drvdata(dev);
+
+ u32 next_state = 0;
+ u64 entry_time = ktime_get_ns();
+ u64 elapsed = entry_time - gti->ical_timestamp_ns;
+
+ if (kstrtou32(buf, 10, &next_state)) {
+ GOOG_ERR(gti, "error: invalid input!\n");
+ return size;
+ }
+
+ switch (gti->ical_state) {
+ case ICAL_STATE_IDLE:
+ if (ical_state_idle(gti, next_state, elapsed))
+ gti->ical_timestamp_ns = entry_time;
+ break;
+
+ case ICAL_STATE_INIT_CAL:
+ ical_state_init_cal(gti, next_state, elapsed);
+ gti->ical_timestamp_ns = entry_time;
+ break;
+
+ case ICAL_STATE_RUN_CAL:
+ ical_state_run_cal(gti, next_state, elapsed);
+ gti->ical_timestamp_ns = entry_time;
+ break;
+
+ case ICAL_STATE_END_CAL:
+ ical_state_end_cal(gti, next_state, elapsed);
+ gti->ical_timestamp_ns = entry_time;
+ break;
+
+ case ICAL_STATE_INIT_TEST:
+ ical_state_init_test(gti, next_state, elapsed);
+ gti->ical_timestamp_ns = entry_time;
+ break;
+
+ case ICAL_STATE_RUN_TEST:
+ ical_state_run_test(gti, next_state, elapsed);
+ gti->ical_timestamp_ns = entry_time;
+ break;
+
+ case ICAL_STATE_END_TEST:
+ ical_state_end_test(gti, next_state, elapsed);
+ gti->ical_timestamp_ns = entry_time;
+ break;
+
+ default:
+ GOOG_ERR(gti, "ical - unknown/invalid current state = %u, but will go back to 0.\n",
+ gti->ical_state);
+ gti->ical_state = ICAL_STATE_IDLE;
+ gti->ical_result = ICAL_RES_SUCCESS;
+ break;
+ }
+
+ return size;
+}
+
+/* Show result/status of the calibrate state machine */
+static ssize_t interactive_calibrate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t buf_idx = 0;
+ struct goog_touch_interface *gti = dev_get_drvdata(dev);
+
+ buf_idx += scnprintf(buf + buf_idx, PAGE_SIZE,
+ "%d - %d\n", gti->ical_result, gti->ical_func_result);
+ GOOG_INFO(gti, "%s", buf);
+
+ return buf_idx;
+}
+
/*-----------------------------------------------------------------------------
* Debug: functions.
*/
@@ -1815,6 +2131,9 @@ int goog_process_vendor_cmd(struct goog_touch_interface *gti, enum gti_cmd_type
/* Use optional vendor operation if available. */
switch (cmd_type) {
+ case GTI_CMD_CALIBRATE:
+ ret = gti->options.calibrate(private_data, &gti->cmd.calibrate_cmd);
+ break;
case GTI_CMD_PING:
ret = gti->options.ping(private_data, &gti->cmd.ping_cmd);
break;
@@ -3052,6 +3371,12 @@ void goog_register_tbn(struct goog_touch_interface *gti)
}
}
+static int goog_calibrate_nop(
+ void *private_data, struct gti_calibrate_cmd *cmd)
+{
+ return -ESRCH;
+}
+
static int goog_get_context_driver_nop(
void *private_data, struct gti_context_driver_cmd *cmd)
{
@@ -3300,6 +3625,7 @@ void goog_init_options(struct goog_touch_interface *gti,
}
/* Initialize default functions. */
+ gti->options.calibrate = goog_calibrate_nop;
gti->options.get_context_driver = goog_get_context_driver_nop;
gti->options.get_context_stylus = goog_get_context_stylus_nop;
gti->options.get_coord_filter_enabled = goog_get_coord_filter_enabled_nop;
@@ -3330,6 +3656,8 @@ void goog_init_options(struct goog_touch_interface *gti,
/* Set optional operation if available. */
if (options) {
+ if (options->calibrate)
+ gti->options.calibrate = options->calibrate;
if (options->get_context_driver)
gti->options.get_context_driver = options->get_context_driver;
if (options->get_context_stylus)
diff --git a/goog_touch_interface.h b/goog_touch_interface.h
index 6409cd0..1976920 100644
--- a/goog_touch_interface.h
+++ b/goog_touch_interface.h
@@ -47,12 +47,56 @@
#define GTI_DEBUG_INPUT_LOGS_LEN 4
/*-----------------------------------------------------------------------------
+ * Interactive calibration minimum and maximum state times.
+ */
+
+/* Must wait at least 5s before beginning any operation */
+#define MIN_DELAY_IDLE (5 * 1e9)
+
+/* Must wait at least 1s between screen-turning-off and calibration start, and
+ * cannot stay in this state longer than 15s.
+ */
+#define MIN_DELAY_INIT_CAL (1 * 1e9)
+#define MAX_DELAY_INIT_CAL (15 * 1e9)
+
+/* Must wait at least 3s for calibration to complete and cannot stay in this
+ * state longer than 15s.
+ */
+#define MIN_DELAY_RUN_CAL (3 * 1e9)
+#define MAX_DELAY_RUN_CAL (15 * 1e9)
+
+/* Must wait at least 1s before final return to idle and cannot stay in this
+ * state longer than 15s.
+ */
+#define MIN_DELAY_END_CAL (1 * 1e9)
+#define MAX_DELAY_END_CAL (15 * 1e9)
+
+/* Must wait at least 1s between screen-turning-off and self-test start, and
+ * cannot state in this state longer than 15s.
+ */
+#define MIN_DELAY_INIT_TEST (1 * 1e9)
+#define MAX_DELAY_INIT_TEST (15 * 1e9)
+
+/* Must wait at least 3s for self-test to complete and cannot stay in this state
+ * longer than 15s.
+ */
+#define MIN_DELAY_RUN_TEST (3 * 1e9)
+#define MAX_DELAY_RUN_TEST (15 * 1e9)
+
+/* Must wait at least 1s before final return to idle and cannot stay in this
+ * state longer than 15s.
+ */
+#define MIN_DELAY_END_TEST (1 * 1e9)
+#define MAX_DELAY_END_TEST (15 * 1e9)
+
+/*-----------------------------------------------------------------------------
* enums.
*/
enum gti_cmd_type : u32 {
/* GTI_CMD operations. */
GTI_CMD_OPS_START = 0x100,
+ GTI_CMD_CALIBRATE,
GTI_CMD_PING,
GTI_CMD_RESET,
GTI_CMD_SELFTEST,
@@ -91,6 +135,13 @@ enum gti_cmd_type : u32 {
GTI_CMD_SET_SENSING_MODE,
};
+enum gti_calibrate_result : u32 {
+ GTI_CALIBRATE_RESULT_DONE = 0,
+ GTI_CALIBRATE_RESULT_SHELL_CMDS_REDIRECT,
+ GTI_CALIBRATE_RESULT_FAIL,
+ GTI_CALIBRATE_RESULT_NA = 0xFFFFFFFF,
+};
+
enum gti_continuous_report_setting : u32 {
GTI_CONTINUOUS_REPORT_DISABLE = 0,
GTI_CONTINUOUS_REPORT_ENABLE,
@@ -272,10 +323,32 @@ enum gti_noise_mode_level : u8 {
GTI_NOISE_MODE_LEVEL3,
};
+enum gti_ical_res : u32 {
+ ICAL_RES_SUCCESS = 0,
+ ICAL_RES_FAIL = 0x80000000,
+ ICAL_RES_NA = 0xFFFFFFFF,
+};
+
+enum gti_ical_state : u32 {
+ ICAL_STATE_IDLE = 0,
+ ICAL_STATE_INIT_CAL = 101,
+ ICAL_STATE_RUN_CAL = 102,
+ ICAL_STATE_END_CAL = 103,
+ ICAL_STATE_INIT_TEST = 201,
+ ICAL_STATE_RUN_TEST = 202,
+ ICAL_STATE_END_TEST = 203,
+ ICAL_STATE_NA = 0xFFFFFFFF,
+};
+
/*-----------------------------------------------------------------------------
* Structures.
*/
+struct gti_calibrate_cmd {
+ enum gti_calibrate_result result;
+ char buffer[PAGE_SIZE];
+};
+
struct gti_context_changed {
union {
struct {
@@ -411,6 +484,7 @@ struct gti_sensor_data_cmd {
/**
* struct gti_union_cmd_data - GTI commands to vendor driver.
+ * @calibrate_cmd: command to calibrate the touchscreen
* @context_driver_cmd: command to update touch offload driver context.
* @context_stylus_cmd: command to update touch offload stylus context.
* @continuous_report_cmd: command to set continuous reporting.
@@ -433,6 +507,7 @@ struct gti_sensor_data_cmd {
* @manual_sensor_data_cmd: command to get sensor data manually.
*/
struct gti_union_cmd_data {
+ struct gti_calibrate_cmd calibrate_cmd;
struct gti_context_driver_cmd context_driver_cmd;
struct gti_context_stylus_cmd context_stylus_cmd;
struct gti_continuous_report_cmd continuous_report_cmd;
@@ -466,6 +541,7 @@ struct gti_fw_status_data {
/**
* struct gti_optional_configuration - optional configuration by vendor driver.
+ * @calibrate: vendor driver operation to exec calibration
* @get_context_driver: vendor driver operation to update touch offload driver context.
* @get_context_stylus: vendor driver operation to update touch offload stylus context.
* @get_coord_filter_enabled: vendor driver operation to get the coordinate filter enabled.
@@ -500,6 +576,7 @@ struct gti_optional_configuration {
* Vendor command with GTI default NOP handler.
* No need to check before use.
*/
+ int (*calibrate)(void *private_data, struct gti_calibrate_cmd *cmd);
int (*get_context_driver)(void *private_data, struct gti_context_driver_cmd *cmd);
int (*get_context_stylus)(void *private_data, struct gti_context_stylus_cmd *cmd);
int (*get_coord_filter_enabled)(void *private_data, struct gti_coord_filter_cmd *cmd);
@@ -631,6 +708,10 @@ struct gti_pm {
* @panel_id: id of the display panel.
* @charger_state: indicates a USB charger is connected.
* @charger_notifier: notifier for power_supply updates.
+ * @ical_state: state of interactive calibration finite state machine.
+ * @ical_timestamp_ns: time of last interactive calibration state transition.
+ * @ical_result: interactive calibration FSM result.
+ * @ical_func_result: result returned from the requested interactive function.
* @irq_index: irq count that handle by GTI.
* @input_index: the count of slot bit changed during goog_input_process().
* @vendor_irq_handler: irq handler that register by vendor driver.
@@ -727,6 +808,11 @@ struct goog_touch_interface {
u8 charger_state;
struct notifier_block charger_notifier;
+ u32 ical_state;
+ u64 ical_timestamp_ns;
+ s32 ical_result;
+ s32 ical_func_result;
+
u64 irq_index;
u64 input_index;
irq_handler_t vendor_irq_handler;