mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 15:11:48 -04:00
input: touchscreen: focaltech: TUI error handling state machine
Introduce state machine for various checkpoints in trusted touch usecase. In error scenarios, this state machine helps driver to rollback to previous state. Change-Id: Ia9f9e01905b5d1561dd21ea782cf9f09001d35a7 Signed-off-by: Ritesh Kumar <riteshk@codeaurora.org>
This commit is contained in:
parent
c19cc3d79e
commit
6aca8a8c07
3 changed files with 486 additions and 158 deletions
|
|
@ -100,6 +100,8 @@ static int fts_ts_probe_delayed(struct fts_ts_data *fts_data);
|
|||
|
||||
#ifdef CONFIG_FTS_TRUSTED_TOUCH
|
||||
|
||||
static void fts_ts_trusted_touch_abort_handler(struct fts_ts_data *fts_data,
|
||||
int error);
|
||||
static struct hh_acl_desc *fts_ts_vm_get_acl(enum hh_vm_names vm_name)
|
||||
{
|
||||
struct hh_acl_desc *acl_desc;
|
||||
|
|
@ -241,7 +243,28 @@ static void fts_ts_vm_deinit(struct fts_ts_data *fts_data)
|
|||
|
||||
#ifdef CONFIG_ARCH_QTI_VM
|
||||
static int fts_ts_vm_mem_release(struct fts_ts_data *fts_data);
|
||||
static void fts_ts_trusted_touch_vm_mode_disable(struct fts_ts_data *fts_data);
|
||||
static void fts_ts_trusted_touch_tvm_vm_mode_disable(struct fts_ts_data *fts_data);
|
||||
static void fts_ts_trusted_touch_abort_tvm(struct fts_ts_data *fts_data);
|
||||
static void fts_ts_trusted_touch_event_notify(struct fts_ts_data *fts_data, int event);
|
||||
|
||||
static int fts_ts_trusted_touch_get_tvm_driver_state(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int state;
|
||||
|
||||
mutex_lock(&fts_data->vm_info->tvm_state_mutex);
|
||||
state = atomic_read(&fts_data->vm_info->tvm_state);
|
||||
mutex_unlock(&fts_data->vm_info->tvm_state_mutex);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static void fts_ts_trusted_touch_set_tvm_driver_state(struct fts_ts_data *fts_data,
|
||||
int state)
|
||||
{
|
||||
mutex_lock(&fts_data->vm_info->tvm_state_mutex);
|
||||
atomic_set(&fts_data->vm_info->tvm_state, state);
|
||||
mutex_unlock(&fts_data->vm_info->tvm_state_mutex);
|
||||
}
|
||||
|
||||
static int fts_ts_sgl_cmp(const void *a, const void *b)
|
||||
{
|
||||
|
|
@ -293,69 +316,130 @@ static int fts_ts_vm_handle_vm_hardware(struct fts_ts_data *fts_data)
|
|||
}
|
||||
|
||||
fts_irq_enable();
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data, TVM_INTERRUPT_ENABLED);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void fts_ts_trusted_touch_tvm_vm_mode_enable(struct fts_ts_data *fts_data)
|
||||
{
|
||||
|
||||
struct hh_sgl_desc *sgl_desc, *expected_sgl_desc;
|
||||
struct hh_acl_desc *acl_desc;
|
||||
struct irq_data *irq_data;
|
||||
int rc = 0;
|
||||
int irq = 0;
|
||||
|
||||
if (fts_ts_trusted_touch_get_tvm_driver_state(fts_data) !=
|
||||
TVM_ALL_RESOURCES_LENT_NOTIFIED) {
|
||||
pr_err("All lend notifications not received\n");
|
||||
fts_ts_trusted_touch_event_notify(fts_data,
|
||||
TRUSTED_TOUCH_EVENT_NOTIFICATIONS_PENDING);
|
||||
return;
|
||||
}
|
||||
|
||||
acl_desc = fts_ts_vm_get_acl(HH_TRUSTED_VM);
|
||||
if (IS_ERR(acl_desc)) {
|
||||
pr_err("failed to populated acl data:rc=%d\n",
|
||||
PTR_ERR(acl_desc));
|
||||
goto accept_fail;
|
||||
}
|
||||
|
||||
sgl_desc = hh_rm_mem_accept(fts_data->vm_info->vm_mem_handle,
|
||||
HH_RM_MEM_TYPE_IO,
|
||||
HH_RM_TRANS_TYPE_LEND,
|
||||
HH_RM_MEM_ACCEPT_VALIDATE_ACL_ATTRS |
|
||||
HH_RM_MEM_ACCEPT_VALIDATE_LABEL |
|
||||
HH_RM_MEM_ACCEPT_DONE, TRUSTED_TOUCH_MEM_LABEL,
|
||||
acl_desc, NULL, NULL, 0);
|
||||
if (IS_ERR_OR_NULL(sgl_desc)) {
|
||||
pr_err("failed to do mem accept :rc=%d\n",
|
||||
PTR_ERR(sgl_desc));
|
||||
goto acl_fail;
|
||||
}
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data, TVM_IOMEM_ACCEPTED);
|
||||
|
||||
/* Initiate i2c session on tvm */
|
||||
rc = pm_runtime_get_sync(fts_data->client->adapter->dev.parent);
|
||||
if (rc < 0) {
|
||||
pr_err("failed to get sync rc:%d\n", rc);
|
||||
goto acl_fail;
|
||||
}
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data, TVM_I2C_SESSION_ACQUIRED);
|
||||
|
||||
expected_sgl_desc = fts_ts_vm_get_sgl(fts_data->vm_info);
|
||||
if (fts_ts_vm_compare_sgl_desc(expected_sgl_desc, sgl_desc)) {
|
||||
pr_err("IO sg list does not match\n");
|
||||
goto sgl_cmp_fail;
|
||||
}
|
||||
|
||||
kfree(expected_sgl_desc);
|
||||
kfree(acl_desc);
|
||||
|
||||
irq = hh_irq_accept(fts_data->vm_info->irq_label, -1, IRQ_TYPE_EDGE_RISING);
|
||||
if (irq < 0) {
|
||||
pr_err("failed to accept irq\n");
|
||||
goto accept_fail;
|
||||
}
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data, TVM_IRQ_ACCEPTED);
|
||||
|
||||
|
||||
irq_data = irq_get_irq_data(irq);
|
||||
if (!irq_data) {
|
||||
pr_err("Invalid irq data for trusted touch\n");
|
||||
goto accept_fail;
|
||||
}
|
||||
if (!irq_data->hwirq) {
|
||||
pr_err("Invalid irq in irq data\n");
|
||||
goto accept_fail;
|
||||
}
|
||||
if (irq_data->hwirq != fts_data->vm_info->hw_irq) {
|
||||
pr_err("Invalid irq lent\n");
|
||||
goto accept_fail;
|
||||
}
|
||||
|
||||
pr_debug("irq:returned from accept:%d\n", irq);
|
||||
fts_data->irq = irq;
|
||||
|
||||
rc = fts_ts_vm_handle_vm_hardware(fts_data);
|
||||
if (rc) {
|
||||
pr_err(" Delayed probe failure on VM!\n");
|
||||
goto accept_fail;
|
||||
}
|
||||
atomic_set(&fts_data->trusted_touch_enabled, 1);
|
||||
pr_info("trusted touch enabled\n");
|
||||
|
||||
return;
|
||||
sgl_cmp_fail:
|
||||
kfree(expected_sgl_desc);
|
||||
acl_fail:
|
||||
kfree(acl_desc);
|
||||
accept_fail:
|
||||
fts_ts_trusted_touch_abort_handler(fts_data,
|
||||
TRUSTED_TOUCH_EVENT_ACCEPT_FAILURE);
|
||||
}
|
||||
static void fts_ts_vm_irq_on_lend_callback(void *data,
|
||||
unsigned long notif_type,
|
||||
enum hh_irq_label label)
|
||||
{
|
||||
struct fts_ts_data *fts_data = data;
|
||||
struct irq_data *irq_data;
|
||||
int irq = 0;
|
||||
int const resource_timeout = msecs_to_jiffies(2000);
|
||||
int rc = 0;
|
||||
|
||||
irq = hh_irq_accept(fts_data->vm_info->irq_label, -1,
|
||||
IRQ_TYPE_EDGE_RISING);
|
||||
if (irq < 0) {
|
||||
pr_err("failed to accept irq\n");
|
||||
goto irq_fail;
|
||||
pr_debug("received irq lend request for label:%d\n", label);
|
||||
if (fts_ts_trusted_touch_get_tvm_driver_state(fts_data) ==
|
||||
TVM_IOMEM_LENT_NOTIFIED) {
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data,
|
||||
TVM_ALL_RESOURCES_LENT_NOTIFIED);
|
||||
} else {
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data,
|
||||
TVM_IRQ_LENT_NOTIFIED);
|
||||
}
|
||||
atomic_set(&fts_data->vm_info->tvm_owns_irq, 1);
|
||||
irq_data = irq_get_irq_data(irq);
|
||||
if (!irq_data) {
|
||||
pr_err("Invalid irq data for trusted touch\n");
|
||||
goto irq_fail;
|
||||
}
|
||||
if (!irq_data->hwirq) {
|
||||
pr_err("Invalid irq in irq data\n");
|
||||
goto irq_fail;
|
||||
}
|
||||
if (irq_data->hwirq != fts_data->vm_info->hw_irq) {
|
||||
pr_err("Invalid irq lent\n");
|
||||
goto irq_fail;
|
||||
}
|
||||
|
||||
pr_debug("irq:returned from accept:%d\n", irq);
|
||||
fts_data->irq = irq;
|
||||
if (!wait_for_completion_timeout(&fts_data->resource_checkpoint,
|
||||
resource_timeout)) {
|
||||
pr_err("Resources not acquired in TVM\n");
|
||||
goto irq_fail;
|
||||
}
|
||||
|
||||
rc = fts_ts_vm_handle_vm_hardware(fts_data);
|
||||
if (rc) {
|
||||
pr_err(" Delayed probe failure on VM!\n");
|
||||
goto irq_fail;
|
||||
}
|
||||
|
||||
atomic_set(&fts_data->trusted_touch_enabled, 1);
|
||||
return;
|
||||
irq_fail:
|
||||
fts_ts_trusted_touch_vm_mode_disable(fts_data);
|
||||
}
|
||||
|
||||
static void fts_ts_vm_mem_on_lend_handler(enum hh_mem_notifier_tag tag,
|
||||
unsigned long notif_type, void *entry_data, void *notif_msg)
|
||||
{
|
||||
struct hh_rm_notif_mem_shared_payload *payload;
|
||||
struct hh_sgl_desc *sgl_desc, *expected_sgl_desc;
|
||||
struct hh_acl_desc *acl_desc;
|
||||
struct trusted_touch_vm_info *vm_info;
|
||||
struct fts_ts_data *fts_data;
|
||||
int rc = 0;
|
||||
|
||||
if (notif_type != HH_RM_NOTIF_MEM_SHARED ||
|
||||
tag != HH_MEM_NOTIFIER_TAG_TOUCH) {
|
||||
|
|
@ -379,62 +463,31 @@ static void fts_ts_vm_mem_on_lend_handler(enum hh_mem_notifier_tag tag,
|
|||
if (payload->trans_type != HH_RM_TRANS_TYPE_LEND ||
|
||||
payload->label != TRUSTED_TOUCH_MEM_LABEL) {
|
||||
pr_err("Invalid label or transaction type\n");
|
||||
goto onlend_fail;
|
||||
}
|
||||
|
||||
acl_desc = fts_ts_vm_get_acl(HH_TRUSTED_VM);
|
||||
if (IS_ERR(acl_desc)) {
|
||||
pr_err("failed to populated acl data:rc=%d\n",
|
||||
PTR_ERR(acl_desc));
|
||||
goto onlend_fail;
|
||||
}
|
||||
|
||||
sgl_desc = hh_rm_mem_accept(payload->mem_handle, HH_RM_MEM_TYPE_IO,
|
||||
HH_RM_TRANS_TYPE_LEND,
|
||||
HH_RM_MEM_ACCEPT_VALIDATE_ACL_ATTRS |
|
||||
HH_RM_MEM_ACCEPT_VALIDATE_LABEL |
|
||||
HH_RM_MEM_ACCEPT_DONE, payload->label, acl_desc,
|
||||
NULL, NULL, 0);
|
||||
if (IS_ERR_OR_NULL(sgl_desc)) {
|
||||
pr_err("failed to do mem accept :rc=%d\n",
|
||||
PTR_ERR(sgl_desc));
|
||||
goto acl_fail;
|
||||
}
|
||||
atomic_set(&vm_info->tvm_owns_iomem, 1);
|
||||
|
||||
/* Initiate i2c session on tvm */
|
||||
rc = pm_runtime_get_sync(fts_data->client->adapter->dev.parent);
|
||||
if (rc < 0) {
|
||||
pr_err("failed to get sync rc:%d\n", rc);
|
||||
(void)fts_ts_vm_mem_release(fts_data);
|
||||
atomic_set(&fts_data->vm_info->tvm_owns_iomem, 0);
|
||||
goto acl_fail;
|
||||
}
|
||||
complete(&fts_data->resource_checkpoint);
|
||||
|
||||
expected_sgl_desc = fts_ts_vm_get_sgl(vm_info);
|
||||
if (fts_ts_vm_compare_sgl_desc(expected_sgl_desc, sgl_desc)) {
|
||||
pr_err("IO sg list does not match\n");
|
||||
goto sgl_cmp_fail;
|
||||
return;
|
||||
}
|
||||
|
||||
vm_info->vm_mem_handle = payload->mem_handle;
|
||||
kfree(expected_sgl_desc);
|
||||
kfree(acl_desc);
|
||||
return;
|
||||
|
||||
sgl_cmp_fail:
|
||||
kfree(expected_sgl_desc);
|
||||
acl_fail:
|
||||
kfree(acl_desc);
|
||||
onlend_fail:
|
||||
fts_ts_trusted_touch_vm_mode_disable(fts_data);
|
||||
pr_debug("received mem lend request with handle:%d\n",
|
||||
vm_info->vm_mem_handle);
|
||||
if (fts_ts_trusted_touch_get_tvm_driver_state(fts_data) ==
|
||||
TVM_IRQ_LENT_NOTIFIED) {
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data,
|
||||
TVM_ALL_RESOURCES_LENT_NOTIFIED);
|
||||
} else {
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data,
|
||||
TVM_IOMEM_LENT_NOTIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
static int fts_ts_vm_mem_release(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!fts_data->vm_info->vm_mem_handle) {
|
||||
pr_err("Invalid memory handle\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = hh_rm_mem_release(fts_data->vm_info->vm_mem_handle, 0);
|
||||
if (rc)
|
||||
pr_err("VM mem release failed: rc=%d\n", rc);
|
||||
|
|
@ -444,44 +497,58 @@ static int fts_ts_vm_mem_release(struct fts_ts_data *fts_data)
|
|||
HH_MEM_NOTIFIER_TAG_TOUCH, 0);
|
||||
if (rc)
|
||||
pr_err("Failed to notify mem release to PVM: rc=%d\n");
|
||||
pr_debug("vm mem release succeded\n");
|
||||
|
||||
fts_data->vm_info->vm_mem_handle = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void fts_ts_trusted_touch_vm_mode_disable(struct fts_ts_data *fts_data)
|
||||
static void fts_ts_trusted_touch_tvm_vm_mode_disable(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
|
||||
if (atomic_read(&fts_data->vm_info->tvm_owns_iomem) &&
|
||||
atomic_read(&fts_data->vm_info->tvm_owns_irq))
|
||||
fts_irq_disable();
|
||||
|
||||
if (atomic_read(&fts_data->vm_info->tvm_owns_iomem)) {
|
||||
fts_release_all_finger();
|
||||
rc = fts_ts_vm_mem_release(fts_data);
|
||||
if (rc)
|
||||
pr_err("Failed to release mem rc:%d\n", rc);
|
||||
else
|
||||
atomic_set(&fts_data->vm_info->tvm_owns_iomem, 0);
|
||||
pm_runtime_put_sync(fts_data->client->adapter->dev.parent);
|
||||
if (atomic_read(&fts_data->trusted_touch_abort_status)) {
|
||||
fts_ts_trusted_touch_abort_tvm(fts_data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (atomic_read(&fts_data->vm_info->tvm_owns_irq)) {
|
||||
rc = hh_irq_release(fts_data->vm_info->irq_label);
|
||||
if (rc)
|
||||
pr_err("Failed to release irq rc:%d\n", rc);
|
||||
else
|
||||
atomic_set(&fts_data->vm_info->tvm_owns_irq, 0);
|
||||
fts_irq_disable();
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data,
|
||||
TVM_INTERRUPT_DISABLED);
|
||||
|
||||
rc = hh_irq_release_notify(fts_data->vm_info->irq_label);
|
||||
if (rc)
|
||||
pr_err("Failed to notify release irq rc:%d\n", rc);
|
||||
rc = hh_irq_release(fts_data->vm_info->irq_label);
|
||||
if (rc) {
|
||||
pr_err("Failed to release irq rc:%d\n", rc);
|
||||
goto error;
|
||||
} else {
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data,
|
||||
TVM_IRQ_RELEASED);
|
||||
}
|
||||
rc = hh_irq_release_notify(fts_data->vm_info->irq_label);
|
||||
if (rc)
|
||||
pr_err("Failed to notify release irq rc:%d\n", rc);
|
||||
|
||||
pr_debug("vm irq release succeded\n");
|
||||
|
||||
fts_release_all_finger();
|
||||
rc = fts_ts_vm_mem_release(fts_data);
|
||||
if (rc) {
|
||||
pr_err("Failed to release mem rc:%d\n", rc);
|
||||
goto error;
|
||||
} else {
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data,
|
||||
TVM_IOMEM_RELEASED);
|
||||
}
|
||||
pm_runtime_put_sync(fts_data->client->adapter->dev.parent);
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data,
|
||||
TVM_I2C_SESSION_RELEASED);
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data, TRUSTED_TOUCH_TVM_INIT);
|
||||
atomic_set(&fts_data->trusted_touch_enabled, 0);
|
||||
reinit_completion(&fts_data->resource_checkpoint);
|
||||
pr_debug("trusted touch disabled\n");
|
||||
pr_info("trusted touch disabled\n");
|
||||
return;
|
||||
error:
|
||||
fts_ts_trusted_touch_abort_handler(fts_data,
|
||||
TRUSTED_TOUCH_EVENT_RELEASE_FAILURE);
|
||||
}
|
||||
|
||||
int fts_ts_handle_trusted_touch_tvm(struct fts_ts_data *fts_data, int value)
|
||||
|
|
@ -490,13 +557,14 @@ int fts_ts_handle_trusted_touch_tvm(struct fts_ts_data *fts_data, int value)
|
|||
|
||||
switch (value) {
|
||||
case 0:
|
||||
if (atomic_read(&fts_data->trusted_touch_enabled) == 0) {
|
||||
if ((atomic_read(&fts_data->trusted_touch_enabled) == 0) &&
|
||||
(atomic_read(&fts_data->trusted_touch_abort_status) == 0)) {
|
||||
pr_err("Trusted touch is already disabled\n");
|
||||
break;
|
||||
}
|
||||
if (atomic_read(&fts_data->trusted_touch_mode) ==
|
||||
TRUSTED_TOUCH_VM_MODE) {
|
||||
fts_ts_trusted_touch_vm_mode_disable(fts_data);
|
||||
fts_ts_trusted_touch_tvm_vm_mode_disable(fts_data);
|
||||
} else {
|
||||
pr_err("Unsupported trusted touch mode\n");
|
||||
}
|
||||
|
|
@ -510,7 +578,7 @@ int fts_ts_handle_trusted_touch_tvm(struct fts_ts_data *fts_data, int value)
|
|||
}
|
||||
if (atomic_read(&fts_data->trusted_touch_mode) ==
|
||||
TRUSTED_TOUCH_VM_MODE) {
|
||||
pr_err("Cannot turnon trusted touch(vm mode) in VM\n");
|
||||
fts_ts_trusted_touch_tvm_vm_mode_enable(fts_data);
|
||||
} else {
|
||||
pr_err("Unsupported trusted touch mode\n");
|
||||
}
|
||||
|
|
@ -525,8 +593,115 @@ int fts_ts_handle_trusted_touch_tvm(struct fts_ts_data *fts_data, int value)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void fts_ts_trusted_touch_abort_tvm(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int rc = 0;
|
||||
int tvm_state = fts_ts_trusted_touch_get_tvm_driver_state(fts_data);
|
||||
|
||||
if (tvm_state >= TRUSTED_TOUCH_TVM_STATE_MAX) {
|
||||
pr_err("invalid tvm driver state: %d\n", tvm_state);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (tvm_state) {
|
||||
case TVM_INTERRUPT_ENABLED:
|
||||
fts_irq_disable();
|
||||
case TVM_IRQ_ACCEPTED:
|
||||
case TVM_INTERRUPT_DISABLED:
|
||||
rc = hh_irq_release(fts_data->vm_info->irq_label);
|
||||
if (rc)
|
||||
pr_err("Failed to release irq rc:%d\n", rc);
|
||||
rc = hh_irq_release_notify(fts_data->vm_info->irq_label);
|
||||
if (rc)
|
||||
pr_err("Failed to notify irq release rc:%d\n", rc);
|
||||
case TVM_I2C_SESSION_ACQUIRED:
|
||||
case TVM_IOMEM_ACCEPTED:
|
||||
case TVM_IRQ_RELEASED:
|
||||
fts_release_all_finger();
|
||||
rc = fts_ts_vm_mem_release(fts_data);
|
||||
if (rc)
|
||||
pr_err("Failed to release mem rc:%d\n", rc);
|
||||
case TVM_IOMEM_RELEASED:
|
||||
pm_runtime_put_sync(fts_data->client->adapter->dev.parent);
|
||||
case TVM_I2C_SESSION_RELEASED:
|
||||
case TVM_IOMEM_LENT_NOTIFIED:
|
||||
case TVM_IRQ_LENT_NOTIFIED:
|
||||
case TVM_ALL_RESOURCES_LENT_NOTIFIED:
|
||||
case TRUSTED_TOUCH_TVM_INIT:
|
||||
atomic_set(&fts_data->trusted_touch_enabled, 0);
|
||||
}
|
||||
|
||||
atomic_set(&fts_data->trusted_touch_abort_status, 0);
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data, TRUSTED_TOUCH_TVM_INIT);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void fts_ts_bus_put(struct fts_ts_data *fts_data);
|
||||
|
||||
static int fts_ts_trusted_touch_get_pvm_driver_state(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int state;
|
||||
|
||||
mutex_lock(&fts_data->vm_info->pvm_state_mutex);
|
||||
state = atomic_read(&fts_data->vm_info->pvm_state);
|
||||
mutex_unlock(&fts_data->vm_info->pvm_state_mutex);
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
static void fts_ts_trusted_touch_set_pvm_driver_state(struct fts_ts_data *fts_data,
|
||||
int state)
|
||||
{
|
||||
mutex_lock(&fts_data->vm_info->pvm_state_mutex);
|
||||
atomic_set(&fts_data->vm_info->pvm_state, state);
|
||||
mutex_unlock(&fts_data->vm_info->pvm_state_mutex);
|
||||
}
|
||||
|
||||
static void fts_ts_trusted_touch_abort_pvm(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int rc = 0;
|
||||
int pvm_state = fts_ts_trusted_touch_get_pvm_driver_state(fts_data);
|
||||
|
||||
if (pvm_state >= TRUSTED_TOUCH_PVM_STATE_MAX) {
|
||||
pr_err("Invalid driver state: %d\n", pvm_state);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pvm_state) {
|
||||
case PVM_IRQ_RELEASE_NOTIFIED:
|
||||
case PVM_ALL_RESOURCES_RELEASE_NOTIFIED:
|
||||
case PVM_IRQ_LENT:
|
||||
case PVM_IRQ_LENT_NOTIFIED:
|
||||
rc = hh_irq_reclaim(fts_data->vm_info->irq_label);
|
||||
if (rc)
|
||||
pr_err("failed to reclaim irq on pvm rc:%d\n", rc);
|
||||
case PVM_IRQ_RECLAIMED:
|
||||
case PVM_IOMEM_LENT:
|
||||
case PVM_IOMEM_LENT_NOTIFIED:
|
||||
case PVM_IOMEM_RELEASE_NOTIFIED:
|
||||
rc = hh_rm_mem_reclaim(fts_data->vm_info->vm_mem_handle, 0);
|
||||
if (rc)
|
||||
pr_err("failed to reclaim iomem on pvm rc:%d\n", rc);
|
||||
fts_data->vm_info->vm_mem_handle = 0;
|
||||
case PVM_IOMEM_RECLAIMED:
|
||||
case PVM_INTERRUPT_DISABLED:
|
||||
fts_irq_enable();
|
||||
case PVM_I2C_RESOURCE_ACQUIRED:
|
||||
case PVM_INTERRUPT_ENABLED:
|
||||
fts_ts_bus_put(fts_data);
|
||||
complete(&fts_data->trusted_touch_powerdown);
|
||||
case TRUSTED_TOUCH_PVM_INIT:
|
||||
case PVM_I2C_RESOURCE_RELEASED:
|
||||
atomic_set(&fts_data->trusted_touch_enabled, 0);
|
||||
}
|
||||
|
||||
atomic_set(&fts_data->trusted_touch_abort_status, 0);
|
||||
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, TRUSTED_TOUCH_PVM_INIT);
|
||||
}
|
||||
|
||||
static int fts_ts_clk_prepare_enable(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -591,18 +766,48 @@ static struct hh_notify_vmid_desc *fts_ts_vm_get_vmid(hh_vmid_t vmid)
|
|||
return vmid_desc;
|
||||
}
|
||||
|
||||
static void fts_ts_trusted_touch_complete(struct fts_ts_data *fts_data)
|
||||
static void fts_trusted_touch_pvm_vm_mode_disable(struct fts_ts_data *fts_data)
|
||||
{
|
||||
if (atomic_read(&fts_data->vm_info->pvm_owns_iomem) &&
|
||||
atomic_read(&fts_data->vm_info->pvm_owns_irq)) {
|
||||
fts_irq_enable();
|
||||
fts_ts_bus_put(fts_data);
|
||||
complete(&fts_data->trusted_touch_powerdown);
|
||||
atomic_set(&fts_data->trusted_touch_enabled, 0);
|
||||
pr_debug("reenabled interrupts on PVM\n");
|
||||
} else {
|
||||
pr_err("PVM does not own irq and IOMEM\n");
|
||||
int rc = 0;
|
||||
|
||||
if (atomic_read(&fts_data->trusted_touch_abort_status)) {
|
||||
fts_ts_trusted_touch_abort_pvm(fts_data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fts_ts_trusted_touch_get_pvm_driver_state(fts_data) !=
|
||||
PVM_ALL_RESOURCES_RELEASE_NOTIFIED)
|
||||
pr_err("all release notifications are not received yet\n");
|
||||
|
||||
rc = hh_irq_reclaim(fts_data->vm_info->irq_label);
|
||||
if (rc) {
|
||||
pr_err("failed to reclaim irq on pvm rc:%d\n", rc);
|
||||
goto error;
|
||||
}
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data,
|
||||
PVM_IRQ_RECLAIMED);
|
||||
|
||||
rc = hh_rm_mem_reclaim(fts_data->vm_info->vm_mem_handle, 0);
|
||||
if (rc) {
|
||||
pr_err("Trusted touch VM mem reclaim failed rc:%d\n", rc);
|
||||
goto error;
|
||||
}
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, PVM_IOMEM_RECLAIMED);
|
||||
fts_data->vm_info->vm_mem_handle = 0;
|
||||
|
||||
fts_irq_enable();
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, PVM_INTERRUPT_ENABLED);
|
||||
fts_ts_bus_put(fts_data);
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data,
|
||||
PVM_I2C_RESOURCE_RELEASED);
|
||||
complete(&fts_data->trusted_touch_powerdown);
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data,
|
||||
TRUSTED_TOUCH_PVM_INIT);
|
||||
atomic_set(&fts_data->trusted_touch_enabled, 0);
|
||||
return;
|
||||
error:
|
||||
fts_ts_trusted_touch_abort_handler(fts_data,
|
||||
TRUSTED_TOUCH_EVENT_RECLAIM_FAILURE);
|
||||
}
|
||||
|
||||
static void fts_ts_vm_irq_on_release_callback(void *data,
|
||||
|
|
@ -610,26 +815,36 @@ static void fts_ts_vm_irq_on_release_callback(void *data,
|
|||
enum hh_irq_label label)
|
||||
{
|
||||
struct fts_ts_data *fts_data = data;
|
||||
int rc = 0;
|
||||
|
||||
rc = hh_irq_reclaim(fts_data->vm_info->irq_label);
|
||||
if (rc)
|
||||
pr_err("failed to reclaim irq on pvm rc:%d\n", rc);
|
||||
else
|
||||
atomic_set(&fts_data->vm_info->pvm_owns_irq, 1);
|
||||
if (notif_type != HH_RM_NOTIF_VM_IRQ_RELEASED) {
|
||||
pr_err("invalid notification type\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fts_ts_trusted_touch_get_pvm_driver_state(fts_data) ==
|
||||
PVM_IOMEM_RELEASE_NOTIFIED) {
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data,
|
||||
PVM_ALL_RESOURCES_RELEASE_NOTIFIED);
|
||||
} else {
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data,
|
||||
PVM_IRQ_RELEASE_NOTIFIED);
|
||||
}
|
||||
}
|
||||
|
||||
static void fts_ts_vm_mem_on_release_handler(enum hh_mem_notifier_tag tag,
|
||||
unsigned long notif_type, void *entry_data, void *notif_msg)
|
||||
{
|
||||
struct hh_rm_notif_mem_released_payload *payload;
|
||||
struct hh_rm_notif_mem_released_payload *release_payload;
|
||||
struct trusted_touch_vm_info *vm_info;
|
||||
struct fts_ts_data *fts_data;
|
||||
int rc = 0;
|
||||
|
||||
if (notif_type != HH_RM_NOTIF_MEM_RELEASED ||
|
||||
tag != HH_MEM_NOTIFIER_TAG_TOUCH) {
|
||||
pr_err(" Invalid tag or command passed\n");
|
||||
if (notif_type != HH_RM_NOTIF_MEM_RELEASED) {
|
||||
pr_err(" Invalid notification type\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tag != HH_MEM_NOTIFIER_TAG_TOUCH) {
|
||||
pr_err(" Invalid tag\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -638,7 +853,6 @@ static void fts_ts_vm_mem_on_release_handler(enum hh_mem_notifier_tag tag,
|
|||
return;
|
||||
}
|
||||
|
||||
payload = (struct hh_rm_notif_mem_released_payload *)notif_msg;
|
||||
fts_data = (struct fts_ts_data *)entry_data;
|
||||
vm_info = fts_data->vm_info;
|
||||
if (!vm_info) {
|
||||
|
|
@ -646,18 +860,20 @@ static void fts_ts_vm_mem_on_release_handler(enum hh_mem_notifier_tag tag,
|
|||
return;
|
||||
}
|
||||
|
||||
if (payload->mem_handle != vm_info->vm_mem_handle) {
|
||||
release_payload = (struct hh_rm_notif_mem_released_payload *)notif_msg;
|
||||
if (release_payload->mem_handle != vm_info->vm_mem_handle) {
|
||||
pr_err("Invalid mem handle detected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rc = hh_rm_mem_reclaim(payload->mem_handle, 0);
|
||||
if (rc) {
|
||||
pr_err("Trusted touch VM mem release failed rc:%d\n", rc);
|
||||
return;
|
||||
if (fts_ts_trusted_touch_get_pvm_driver_state(fts_data) ==
|
||||
PVM_IRQ_RELEASE_NOTIFIED) {
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data,
|
||||
PVM_ALL_RESOURCES_RELEASE_NOTIFIED);
|
||||
} else {
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data,
|
||||
PVM_IOMEM_RELEASE_NOTIFIED);
|
||||
}
|
||||
atomic_set(&vm_info->pvm_owns_iomem, 1);
|
||||
vm_info->vm_mem_handle = 0;
|
||||
}
|
||||
|
||||
static int fts_ts_vm_mem_lend(struct fts_ts_data *fts_data)
|
||||
|
|
@ -692,6 +908,10 @@ static int fts_ts_vm_mem_lend(struct fts_ts_data *fts_data)
|
|||
goto error;
|
||||
}
|
||||
|
||||
pr_info("vm mem lend succeded\n");
|
||||
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, PVM_IOMEM_LENT);
|
||||
|
||||
hh_rm_get_vmid(HH_TRUSTED_VM, &trusted_vmid);
|
||||
|
||||
vmid_desc = fts_ts_vm_get_vmid(trusted_vmid);
|
||||
|
|
@ -703,6 +923,8 @@ static int fts_ts_vm_mem_lend(struct fts_ts_data *fts_data)
|
|||
goto vmid_error;
|
||||
}
|
||||
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, PVM_IOMEM_LENT_NOTIFIED);
|
||||
|
||||
fts_data->vm_info->vm_mem_handle = mem_handle;
|
||||
vmid_error:
|
||||
kfree(vmid_desc);
|
||||
|
|
@ -714,7 +936,7 @@ sgl_error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int fts_ts_trusted_touch_vm_mode_enable(struct fts_ts_data *fts_data)
|
||||
static int fts_ts_trusted_touch_pvm_vm_mode_enable(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int rc = 0;
|
||||
struct trusted_touch_vm_info *vm_info = fts_data->vm_info;
|
||||
|
|
@ -726,35 +948,42 @@ static int fts_ts_trusted_touch_vm_mode_enable(struct fts_ts_data *fts_data)
|
|||
return rc;
|
||||
}
|
||||
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, PVM_I2C_RESOURCE_ACQUIRED);
|
||||
/* flush pending interurpts from FIFO */
|
||||
fts_irq_disable();
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, PVM_INTERRUPT_DISABLED);
|
||||
fts_release_all_finger();
|
||||
|
||||
rc = fts_ts_vm_mem_lend(fts_data);
|
||||
if (rc) {
|
||||
pr_err("Failed to lend memory\n");
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
atomic_set(&vm_info->pvm_owns_iomem, 0);
|
||||
|
||||
rc = hh_irq_lend_v2(vm_info->irq_label, vm_info->vm_name,
|
||||
fts_data->irq, &fts_ts_vm_irq_on_release_callback, fts_data);
|
||||
if (rc) {
|
||||
pr_err("Failed to lend irq\n");
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
atomic_set(&vm_info->pvm_owns_irq, 0);
|
||||
|
||||
pr_info("vm irq lend succeded for irq:%d\n", fts_data->irq);
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, PVM_IRQ_LENT);
|
||||
|
||||
rc = hh_irq_lend_notify(vm_info->irq_label);
|
||||
if (rc) {
|
||||
pr_err("Failed to notify irq\n");
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, PVM_IRQ_LENT_NOTIFIED);
|
||||
|
||||
reinit_completion(&fts_data->trusted_touch_powerdown);
|
||||
atomic_set(&fts_data->trusted_touch_enabled, 1);
|
||||
pr_debug("trusted touch enabled\n");
|
||||
return rc;
|
||||
error:
|
||||
fts_ts_trusted_touch_abort_handler(fts_data, TRUSTED_TOUCH_EVENT_LEND_FAILURE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int fts_ts_handle_trusted_touch_pvm(struct fts_ts_data *fts_data, int value)
|
||||
|
|
@ -763,13 +992,14 @@ int fts_ts_handle_trusted_touch_pvm(struct fts_ts_data *fts_data, int value)
|
|||
|
||||
switch (value) {
|
||||
case 0:
|
||||
if (atomic_read(&fts_data->trusted_touch_enabled) == 0) {
|
||||
if (atomic_read(&fts_data->trusted_touch_enabled) == 0 &&
|
||||
(atomic_read(&fts_data->trusted_touch_abort_status) == 0)) {
|
||||
pr_err("Trusted touch is already disabled\n");
|
||||
break;
|
||||
}
|
||||
if (atomic_read(&fts_data->trusted_touch_mode) ==
|
||||
TRUSTED_TOUCH_VM_MODE) {
|
||||
fts_ts_trusted_touch_complete(fts_data);
|
||||
fts_trusted_touch_pvm_vm_mode_disable(fts_data);
|
||||
} else {
|
||||
pr_err("Unsupported trusted touch mode\n");
|
||||
}
|
||||
|
|
@ -783,7 +1013,7 @@ int fts_ts_handle_trusted_touch_pvm(struct fts_ts_data *fts_data, int value)
|
|||
}
|
||||
if (atomic_read(&fts_data->trusted_touch_mode) ==
|
||||
TRUSTED_TOUCH_VM_MODE) {
|
||||
err = fts_ts_trusted_touch_vm_mode_enable(fts_data);
|
||||
err = fts_ts_trusted_touch_pvm_vm_mode_enable(fts_data);
|
||||
} else {
|
||||
pr_err("Unsupported trusted touch mode\n");
|
||||
}
|
||||
|
|
@ -799,6 +1029,19 @@ int fts_ts_handle_trusted_touch_pvm(struct fts_ts_data *fts_data, int value)
|
|||
|
||||
#endif
|
||||
|
||||
static void fts_ts_trusted_touch_event_notify(struct fts_ts_data *fts_data, int event)
|
||||
{
|
||||
atomic_set(&fts_data->trusted_touch_event, event);
|
||||
sysfs_notify(&fts_data->client->dev.kobj, NULL, "trusted_touch_event");
|
||||
}
|
||||
|
||||
static void fts_ts_trusted_touch_abort_handler(struct fts_ts_data *fts_data, int error)
|
||||
{
|
||||
atomic_set(&fts_data->trusted_touch_abort_status, error);
|
||||
pr_err("TUI session aborted with failure:%d\n", error);
|
||||
fts_ts_trusted_touch_event_notify(fts_data, error);
|
||||
}
|
||||
|
||||
static int fts_ts_vm_init(struct fts_ts_data *fts_data)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -824,9 +1067,8 @@ static int fts_ts_vm_init(struct fts_ts_data *fts_data)
|
|||
vm_info->mem_cookie = mem_cookie;
|
||||
rc = hh_irq_wait_for_lend_v2(vm_info->irq_label, HH_PRIMARY_VM,
|
||||
&fts_ts_vm_irq_on_lend_callback, fts_data);
|
||||
atomic_set(&vm_info->tvm_owns_irq, 0);
|
||||
atomic_set(&vm_info->tvm_owns_iomem, 0);
|
||||
init_completion(&fts_data->resource_checkpoint);
|
||||
mutex_init(&fts_data->vm_info->tvm_state_mutex);
|
||||
fts_ts_trusted_touch_set_tvm_driver_state(fts_data, TRUSTED_TOUCH_TVM_INIT);
|
||||
#else
|
||||
mem_cookie = hh_mem_notifier_register(HH_MEM_NOTIFIER_TAG_TOUCH,
|
||||
fts_ts_vm_mem_on_release_handler, fts_data);
|
||||
|
|
@ -836,8 +1078,8 @@ static int fts_ts_vm_init(struct fts_ts_data *fts_data)
|
|||
goto init_fail;
|
||||
}
|
||||
vm_info->mem_cookie = mem_cookie;
|
||||
atomic_set(&vm_info->pvm_owns_irq, 1);
|
||||
atomic_set(&vm_info->pvm_owns_iomem, 1);
|
||||
mutex_init(&fts_data->vm_info->pvm_state_mutex);
|
||||
fts_ts_trusted_touch_set_pvm_driver_state(fts_data, TRUSTED_TOUCH_PVM_INIT);
|
||||
#endif
|
||||
return rc;
|
||||
init_fail:
|
||||
|
|
@ -1557,17 +1799,6 @@ static irqreturn_t fts_irq_handler(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FTS_TRUSTED_TOUCH
|
||||
#ifndef CONFIG_ARCH_QTI_VM
|
||||
if (atomic_read(&fts_data->trusted_touch_enabled)) {
|
||||
if (atomic_read(&fts_data->vm_info->pvm_owns_iomem) &&
|
||||
atomic_read(&fts_data->vm_info->pvm_owns_irq)) {
|
||||
pr_err("Trusted Touch Enabled: Cannot service irq\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
fts_irq_read_report();
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,6 +144,48 @@ enum trusted_touch_mode_config {
|
|||
TRUSTED_TOUCH_MODE_NONE
|
||||
};
|
||||
|
||||
enum trusted_touch_pvm_states {
|
||||
TRUSTED_TOUCH_PVM_INIT,
|
||||
PVM_I2C_RESOURCE_ACQUIRED,
|
||||
PVM_INTERRUPT_DISABLED,
|
||||
PVM_IOMEM_LENT,
|
||||
PVM_IOMEM_LENT_NOTIFIED,
|
||||
PVM_IRQ_LENT,
|
||||
PVM_IRQ_LENT_NOTIFIED,
|
||||
PVM_IOMEM_RELEASE_NOTIFIED,
|
||||
PVM_IRQ_RELEASE_NOTIFIED,
|
||||
PVM_ALL_RESOURCES_RELEASE_NOTIFIED,
|
||||
PVM_IRQ_RECLAIMED,
|
||||
PVM_IOMEM_RECLAIMED,
|
||||
PVM_INTERRUPT_ENABLED,
|
||||
PVM_I2C_RESOURCE_RELEASED,
|
||||
TRUSTED_TOUCH_PVM_STATE_MAX
|
||||
};
|
||||
|
||||
enum trusted_touch_tvm_states {
|
||||
TRUSTED_TOUCH_TVM_INIT,
|
||||
TVM_IOMEM_LENT_NOTIFIED,
|
||||
TVM_IRQ_LENT_NOTIFIED,
|
||||
TVM_ALL_RESOURCES_LENT_NOTIFIED,
|
||||
TVM_IOMEM_ACCEPTED,
|
||||
TVM_I2C_SESSION_ACQUIRED,
|
||||
TVM_IRQ_ACCEPTED,
|
||||
TVM_INTERRUPT_ENABLED,
|
||||
TVM_INTERRUPT_DISABLED,
|
||||
TVM_IRQ_RELEASED,
|
||||
TVM_IOMEM_RELEASED,
|
||||
TVM_I2C_SESSION_RELEASED,
|
||||
TRUSTED_TOUCH_TVM_STATE_MAX
|
||||
};
|
||||
|
||||
#define TRUSTED_TOUCH_EVENT_LEND_FAILURE -1
|
||||
#define TRUSTED_TOUCH_EVENT_LEND_NOTIFICATION_FAILURE -2
|
||||
#define TRUSTED_TOUCH_EVENT_ACCEPT_FAILURE -3
|
||||
#define TRUSTED_TOUCH_EVENT_FUNCTIONAL_FAILURE -4
|
||||
#define TRUSTED_TOUCH_EVENT_RELEASE_FAILURE -5
|
||||
#define TRUSTED_TOUCH_EVENT_RECLAIM_FAILURE -6
|
||||
#define TRUSTED_TOUCH_EVENT_NOTIFICATIONS_PENDING 5
|
||||
|
||||
#ifdef CONFIG_FTS_TRUSTED_TOUCH
|
||||
#define TRUSTED_TOUCH_MEM_LABEL 0x7
|
||||
|
||||
|
|
@ -157,11 +199,11 @@ struct trusted_touch_vm_info {
|
|||
u32 iomem_list_size;
|
||||
void *mem_cookie;
|
||||
#ifdef CONFIG_ARCH_QTI_VM
|
||||
atomic_t tvm_owns_iomem;
|
||||
atomic_t tvm_owns_irq;
|
||||
struct mutex tvm_state_mutex;
|
||||
atomic_t tvm_state;
|
||||
#else
|
||||
atomic_t pvm_owns_iomem;
|
||||
atomic_t pvm_owns_irq;
|
||||
struct mutex pvm_state_mutex;
|
||||
atomic_t pvm_state;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
|
@ -225,11 +267,12 @@ struct fts_ts_data {
|
|||
struct mutex fts_clk_io_ctrl_mutex;
|
||||
const char *touch_environment;
|
||||
struct completion trusted_touch_powerdown;
|
||||
struct completion resource_checkpoint;
|
||||
struct clk *core_clk;
|
||||
struct clk *iface_clk;
|
||||
atomic_t trusted_touch_initialized;
|
||||
atomic_t trusted_touch_enabled;
|
||||
atomic_t trusted_touch_event;
|
||||
atomic_t trusted_touch_abort_status;
|
||||
atomic_t delayed_vm_probe_pending;
|
||||
atomic_t trusted_touch_mode;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1120,6 +1120,58 @@ static ssize_t trusted_touch_enable_store(struct device *dev,
|
|||
return err;
|
||||
}
|
||||
|
||||
static ssize_t trusted_touch_event_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct fts_ts_data *info;
|
||||
|
||||
if (!client)
|
||||
return scnprintf(buf, PAGE_SIZE, "client is null\n");
|
||||
|
||||
info = i2c_get_clientdata(client);
|
||||
if (!info) {
|
||||
FTS_ERROR("info is null\n");
|
||||
return scnprintf(buf, PAGE_SIZE, "info is null\n");
|
||||
}
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d",
|
||||
atomic_read(&info->trusted_touch_event));
|
||||
}
|
||||
|
||||
static ssize_t trusted_touch_event_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct fts_ts_data *info;
|
||||
unsigned long value;
|
||||
int err = 0;
|
||||
|
||||
if (!client)
|
||||
return -EIO;
|
||||
info = i2c_get_clientdata(client);
|
||||
if (!info) {
|
||||
FTS_ERROR("info is null\n");
|
||||
return -EIO;
|
||||
}
|
||||
if (count > 2)
|
||||
return -EINVAL;
|
||||
|
||||
err = kstrtoul(buf, 10, &value);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
if (!atomic_read(&info->trusted_touch_initialized))
|
||||
return -EIO;
|
||||
|
||||
if (value)
|
||||
return -EIO;
|
||||
|
||||
atomic_set(&info->trusted_touch_event, value);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* get the fw version example:cat fw_version */
|
||||
|
|
@ -1148,6 +1200,7 @@ static DEVICE_ATTR(fts_touch_point, S_IRUGO | S_IWUSR, fts_tpbuf_show, fts_tpbuf
|
|||
static DEVICE_ATTR(fts_log_level, S_IRUGO | S_IWUSR, fts_log_level_show, fts_log_level_store);
|
||||
#ifdef CONFIG_FTS_TRUSTED_TOUCH
|
||||
static DEVICE_ATTR_RW(trusted_touch_enable);
|
||||
static DEVICE_ATTR_RW(trusted_touch_event);
|
||||
#endif
|
||||
|
||||
/* add your attr in here*/
|
||||
|
|
@ -1163,6 +1216,7 @@ static struct attribute *fts_attributes[] = {
|
|||
&dev_attr_fts_log_level.attr,
|
||||
#ifdef CONFIG_FTS_TRUSTED_TOUCH
|
||||
&dev_attr_trusted_touch_enable.attr,
|
||||
&dev_attr_trusted_touch_event.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue