745 lines
20 KiB
C
745 lines
20 KiB
C
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||
|
|
/*
|
||
|
|
* Copyright (c) 2019 MediaTek Inc.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/*****************************************************************
|
||
|
|
*
|
||
|
|
* File Name: Focaltech_ex_fun.c
|
||
|
|
*
|
||
|
|
* Author: Xu YongFeng
|
||
|
|
*
|
||
|
|
* Created: 2015-01-29
|
||
|
|
*
|
||
|
|
* Modify by mshl on 2015-03-20
|
||
|
|
*
|
||
|
|
* Abstract:
|
||
|
|
*
|
||
|
|
* Reference:
|
||
|
|
*
|
||
|
|
*****************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************
|
||
|
|
* 1.Included header files
|
||
|
|
*****************************************************************/
|
||
|
|
#include "focaltech_core.h"
|
||
|
|
|
||
|
|
/*****************************************************************
|
||
|
|
* Private constant and macro definitions using #define
|
||
|
|
*****************************************************************/
|
||
|
|
/*create apk debug channel*/
|
||
|
|
#define PROC_UPGRADE 0
|
||
|
|
#define PROC_READ_REGISTER 1
|
||
|
|
#define PROC_WRITE_REGISTER 2
|
||
|
|
#define PROC_AUTOCLB 4
|
||
|
|
#define PROC_UPGRADE_INFO 5
|
||
|
|
#define PROC_WRITE_DATA 6
|
||
|
|
#define PROC_READ_DATA 7
|
||
|
|
#define PROC_SET_TEST_FLAG 8
|
||
|
|
#define FTS_DEBUG_DIR_NAME "fts_debug"
|
||
|
|
#define PROC_NAME "ftxxxx-debug"
|
||
|
|
#define WRITE_BUF_SIZE 1016
|
||
|
|
#define READ_BUF_SIZE 1016
|
||
|
|
|
||
|
|
/*****************************************************************
|
||
|
|
* Private enumerations, structures and unions using typedef
|
||
|
|
*****************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************
|
||
|
|
* Static variables
|
||
|
|
*****************************************************************/
|
||
|
|
static unsigned char proc_operate_mode = PROC_UPGRADE;
|
||
|
|
static struct proc_dir_entry *fts_proc_entry;
|
||
|
|
/*****************************************************************
|
||
|
|
* Global variable or extern global variabls/functions
|
||
|
|
*****************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************
|
||
|
|
* Static function prototypes
|
||
|
|
*****************************************************************/
|
||
|
|
|
||
|
|
/*interface of write proc*/
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_debug_write
|
||
|
|
* Brief:interface of write proc
|
||
|
|
* Input: file point, data buf, data len, no use
|
||
|
|
* Output: no
|
||
|
|
* Return: data len
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_debug_write(struct file *filp, const char __user *buff,
|
||
|
|
size_t count, loff_t *ppos)
|
||
|
|
{
|
||
|
|
unsigned char writebuf[WRITE_BUF_SIZE];
|
||
|
|
int buflen = count;
|
||
|
|
int writelen = 0;
|
||
|
|
int ret = 0;
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
/* FTS_DBG("\n zax proc w 0\n"); */
|
||
|
|
esd_switch(0);
|
||
|
|
apk_debug_flag = 1;
|
||
|
|
/* FTS_DBG("\n zax v= %d\n",apk_debug_flag); */
|
||
|
|
|
||
|
|
#endif
|
||
|
|
if (copy_from_user(&writebuf, buff, buflen)) {
|
||
|
|
dev_notice(&fts_i2c_client->dev, "%s:copy from user error\n",
|
||
|
|
__func__);
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
return -EFAULT;
|
||
|
|
}
|
||
|
|
proc_operate_mode = writebuf[0];
|
||
|
|
|
||
|
|
switch (proc_operate_mode) {
|
||
|
|
case PROC_UPGRADE: {
|
||
|
|
char upgrade_file_path[128];
|
||
|
|
|
||
|
|
memset(upgrade_file_path, 0, sizeof(upgrade_file_path));
|
||
|
|
sprintf(upgrade_file_path, "%s", writebuf + 1);
|
||
|
|
upgrade_file_path[buflen - 1] = '\0';
|
||
|
|
TPD_DEBUG("%s\n", upgrade_file_path);
|
||
|
|
|
||
|
|
/* #if FT_ESD_PROTECT */
|
||
|
|
/* esd_switch(0);apk_debug_flag = 1; */
|
||
|
|
/* #endif */
|
||
|
|
disable_irq(fts_i2c_client->irq);
|
||
|
|
ret = fts_ctpm_fw_upgrade_with_app_file(fts_i2c_client,
|
||
|
|
upgrade_file_path);
|
||
|
|
enable_irq(fts_i2c_client->irq);
|
||
|
|
if (ret < 0) {
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
dev_notice(&fts_i2c_client->dev, "%s:upgrade failed.\n",
|
||
|
|
__func__);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
/* #if FT_ESD_PROTECT */
|
||
|
|
/* esd_switch(1);apk_debug_flag = 0; */
|
||
|
|
/* #endif */
|
||
|
|
} break;
|
||
|
|
/* case PROC_SET_TEST_FLAG: */
|
||
|
|
|
||
|
|
/* break; */
|
||
|
|
case PROC_SET_TEST_FLAG:
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
apk_debug_flag = writebuf[1];
|
||
|
|
if (apk_debug_flag == 1)
|
||
|
|
esd_switch(0);
|
||
|
|
else if (apk_debug_flag == 0)
|
||
|
|
esd_switch(1);
|
||
|
|
FTS_DBG("\n zax flag=%d\n", apk_debug_flag);
|
||
|
|
#endif
|
||
|
|
break;
|
||
|
|
case PROC_READ_REGISTER:
|
||
|
|
writelen = 1;
|
||
|
|
ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen);
|
||
|
|
if (ret < 0) {
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
dev_notice(&fts_i2c_client->dev, "%s:write iic error\n",
|
||
|
|
__func__);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case PROC_WRITE_REGISTER:
|
||
|
|
writelen = 2;
|
||
|
|
ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen);
|
||
|
|
if (ret < 0) {
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
dev_notice(&fts_i2c_client->dev, "%s:write iic error\n",
|
||
|
|
__func__);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case PROC_AUTOCLB:
|
||
|
|
TPD_DEBUG("%s: autoclb\n", __func__);
|
||
|
|
fts_ctpm_auto_clb(fts_i2c_client);
|
||
|
|
break;
|
||
|
|
case PROC_READ_DATA:
|
||
|
|
case PROC_WRITE_DATA:
|
||
|
|
writelen = count - 1;
|
||
|
|
if (writelen > 0) {
|
||
|
|
ret = fts_i2c_write(fts_i2c_client, writebuf + 1,
|
||
|
|
writelen);
|
||
|
|
if (ret < 0) {
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
dev_notice(&fts_i2c_client->dev,
|
||
|
|
"%s:write iic error\n", __func__);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
/* FTS_DBG("\n zax proc w 1\n"); */
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
/* FTS_DBG("\n zax v= %d\n",apk_debug_flag); */
|
||
|
|
#endif
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* interface of read proc */
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_debug_read
|
||
|
|
* Brief:interface of read proc
|
||
|
|
* Input: point to the data, no use, no use, read len, no use, no use
|
||
|
|
* Output: page point to data
|
||
|
|
* Return: read char number
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_debug_read(struct file *filp, char __user *buff,
|
||
|
|
size_t count, loff_t *ppos)
|
||
|
|
{
|
||
|
|
int ret = 0;
|
||
|
|
int num_read_chars = 0;
|
||
|
|
int readlen = 0;
|
||
|
|
u8 regvalue = 0x00, regaddr = 0x00;
|
||
|
|
unsigned char buf[READ_BUF_SIZE];
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
/* FTS_DBG("\n zax proc r 0\n"); */
|
||
|
|
esd_switch(0);
|
||
|
|
apk_debug_flag = 1;
|
||
|
|
/* FTS_DBG("\n zax v= %d\n",apk_debug_flag); */
|
||
|
|
#endif
|
||
|
|
switch (proc_operate_mode) {
|
||
|
|
case PROC_UPGRADE:
|
||
|
|
/* after calling fts_debug_write to upgrade */
|
||
|
|
regaddr = 0xA6;
|
||
|
|
ret = fts_read_reg(fts_i2c_client, regaddr, ®value);
|
||
|
|
if (ret < 0)
|
||
|
|
num_read_chars =
|
||
|
|
sprintf(buf, "%s", "get fw version failed.\n");
|
||
|
|
else
|
||
|
|
num_read_chars = sprintf(
|
||
|
|
buf, "current fw version:0x%02x\n", regvalue);
|
||
|
|
break;
|
||
|
|
case PROC_READ_REGISTER:
|
||
|
|
readlen = 1;
|
||
|
|
ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen);
|
||
|
|
if (ret < 0) {
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
dev_notice(&fts_i2c_client->dev, "%s:read iic error\n",
|
||
|
|
__func__);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
num_read_chars = 1;
|
||
|
|
break;
|
||
|
|
case PROC_READ_DATA:
|
||
|
|
if (count > READ_BUF_SIZE) {
|
||
|
|
dev_notice(&fts_i2c_client->dev,
|
||
|
|
"%s:read proc data count > READ_BUF_SIZE\n",
|
||
|
|
__func__);
|
||
|
|
return -EFAULT;
|
||
|
|
}
|
||
|
|
readlen = count;
|
||
|
|
ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen);
|
||
|
|
if (ret < 0) {
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
dev_notice(&fts_i2c_client->dev, "%s:read iic error\n",
|
||
|
|
__func__);
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
num_read_chars = readlen;
|
||
|
|
break;
|
||
|
|
case PROC_WRITE_DATA:
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (copy_to_user(buff, buf, num_read_chars)) {
|
||
|
|
dev_notice(&fts_i2c_client->dev, "%s:copy to user error\n",
|
||
|
|
__func__);
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
return -EFAULT;
|
||
|
|
}
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
/* FTS_DBG("\n zax proc r 1\n"); */
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
/* FTS_DBG("\n zax v= %d\n",apk_debug_flag); */
|
||
|
|
#endif
|
||
|
|
/* memcpy(buff, buf, num_read_chars); */
|
||
|
|
return num_read_chars;
|
||
|
|
}
|
||
|
|
static const struct file_operations fts_proc_fops = {
|
||
|
|
.owner = THIS_MODULE, .read = fts_debug_read, .write = fts_debug_write,
|
||
|
|
};
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_create_apk_debug_channel
|
||
|
|
* Brief: create apk debug channel
|
||
|
|
* Input: i2c info
|
||
|
|
* Output: no
|
||
|
|
* Return: success =0
|
||
|
|
***********************************************************************/
|
||
|
|
int fts_create_apk_debug_channel(struct i2c_client *client)
|
||
|
|
{
|
||
|
|
fts_proc_entry = proc_create(PROC_NAME, 0664, NULL, &fts_proc_fops);
|
||
|
|
if (fts_proc_entry == NULL) {
|
||
|
|
dev_notice(&client->dev, "Couldn't create proc entry!\n");
|
||
|
|
return -ENOMEM;
|
||
|
|
}
|
||
|
|
dev_info(&client->dev, "Create proc entry success!\n");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_release_apk_debug_channel
|
||
|
|
* Brief: release apk debug channel
|
||
|
|
* Input: no
|
||
|
|
* Output: no
|
||
|
|
* Return: no
|
||
|
|
***********************************************************************/
|
||
|
|
void fts_release_apk_debug_channel(void)
|
||
|
|
{
|
||
|
|
|
||
|
|
if (fts_proc_entry)
|
||
|
|
proc_remove(fts_proc_entry);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_tpfwver_show
|
||
|
|
* Brief: show tp fw vwersion
|
||
|
|
* Input: device, device attribute, char buf
|
||
|
|
* Output: no
|
||
|
|
* Return: char number
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_tpfwver_show(struct device *dev,
|
||
|
|
struct device_attribute *attr, char *buf)
|
||
|
|
{
|
||
|
|
ssize_t num_read_chars = 0;
|
||
|
|
u8 fwver = 0;
|
||
|
|
|
||
|
|
|
||
|
|
mutex_lock(&fts_input_dev->mutex);
|
||
|
|
if (fts_read_reg(fts_i2c_client, FTS_REG_FW_VER, &fwver) < 0)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
if (fwver == 255)
|
||
|
|
num_read_chars =
|
||
|
|
snprintf(buf, PAGE_SIZE, "get tp fw version fail!\n");
|
||
|
|
else
|
||
|
|
num_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver);
|
||
|
|
|
||
|
|
mutex_unlock(&fts_input_dev->mutex);
|
||
|
|
|
||
|
|
return num_read_chars;
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_tpfwver_store
|
||
|
|
* Brief: no
|
||
|
|
* Input: device, device attribute, char buf, char count
|
||
|
|
* Output: no
|
||
|
|
* Return: EPERM
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_tpfwver_store(struct device *dev,
|
||
|
|
struct device_attribute *attr, const char *buf,
|
||
|
|
size_t count)
|
||
|
|
{
|
||
|
|
/* place holder for future use */
|
||
|
|
return -EPERM;
|
||
|
|
}
|
||
|
|
|
||
|
|
int isNumCh(const char ch)
|
||
|
|
{
|
||
|
|
int result = 0;
|
||
|
|
/* 获取16进制的高字节位数据 */
|
||
|
|
if (ch >= '0' && ch <= '9')
|
||
|
|
result = 1; /* (int)(ch - '0'); */
|
||
|
|
else if (ch >= 'a' && ch <= 'f')
|
||
|
|
result = 1; /* (int)(ch - 'a') + 10; */
|
||
|
|
else if (ch >= 'A' && ch <= 'F')
|
||
|
|
result = 1; /* (int)(ch - 'A') + 10; */
|
||
|
|
else
|
||
|
|
result = 0;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
int hexCharToValue(const char ch)
|
||
|
|
{
|
||
|
|
int result = 0;
|
||
|
|
/* 获取16进制的高字节位数据 */
|
||
|
|
if (ch >= '0' && ch <= '9')
|
||
|
|
result = (int)(ch - '0');
|
||
|
|
else if (ch >= 'a' && ch <= 'f')
|
||
|
|
result = (int)(ch - 'a') + 10;
|
||
|
|
else if (ch >= 'A' && ch <= 'F')
|
||
|
|
result = (int)(ch - 'A') + 10;
|
||
|
|
else
|
||
|
|
result = -1;
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
int hexToStr(char *hex, int iHexLen, char *ch, int *iChLen)
|
||
|
|
{
|
||
|
|
int high = 0;
|
||
|
|
int low = 0;
|
||
|
|
int tmp = 0;
|
||
|
|
int i = 0;
|
||
|
|
int iCharLen = 0;
|
||
|
|
|
||
|
|
if (hex == NULL || ch == NULL)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
FTS_DBG("iHexLen: %d in function:%s\n\n", iHexLen, __func__);
|
||
|
|
|
||
|
|
if (iHexLen % 2 == 1)
|
||
|
|
return -2;
|
||
|
|
|
||
|
|
for (i = 0; i < iHexLen; i += 2) {
|
||
|
|
high = hexCharToValue(hex[i]);
|
||
|
|
if (high < 0) {
|
||
|
|
ch[iCharLen] = '\0';
|
||
|
|
return -3;
|
||
|
|
}
|
||
|
|
|
||
|
|
low = hexCharToValue(hex[i + 1]);
|
||
|
|
if (low < 0) {
|
||
|
|
ch[iCharLen] = '\0';
|
||
|
|
return -3;
|
||
|
|
}
|
||
|
|
tmp = (high << 4) + low;
|
||
|
|
ch[iCharLen++] = (char)tmp;
|
||
|
|
}
|
||
|
|
ch[iCharLen] = '\0';
|
||
|
|
*iChLen = iCharLen;
|
||
|
|
FTS_DBG("iCharLen: %d, iChLen: %d in function:%s\n\n", iCharLen,
|
||
|
|
*iChLen, __func__);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void strToBytes(char *bufStr, int iLen, char *uBytes, int *iBytesLen)
|
||
|
|
{
|
||
|
|
int i = 0;
|
||
|
|
int iNumChLen = 0;
|
||
|
|
|
||
|
|
*iBytesLen = 0;
|
||
|
|
|
||
|
|
for (i = 0; i < iLen; i++) {
|
||
|
|
if (isNumCh(bufStr[i])) /* filter illegal chars */
|
||
|
|
bufStr[iNumChLen++] = bufStr[i];
|
||
|
|
}
|
||
|
|
|
||
|
|
bufStr[iNumChLen] = '\0';
|
||
|
|
|
||
|
|
hexToStr(bufStr, iNumChLen, uBytes, iBytesLen);
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_tprwreg_show
|
||
|
|
* Brief: no
|
||
|
|
* Input: device, device attribute, char buf
|
||
|
|
* Output: no
|
||
|
|
* Return: EPERM
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_tprwreg_show(struct device *dev,
|
||
|
|
struct device_attribute *attr, char *buf)
|
||
|
|
{
|
||
|
|
/* place holder for future use */
|
||
|
|
return -EPERM;
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_tprwreg_store
|
||
|
|
* Brief: read/write register
|
||
|
|
* Input: device, device attribute, char buf, char count
|
||
|
|
* Output: print register value
|
||
|
|
* Return: char count
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_tprwreg_store(struct device *dev,
|
||
|
|
struct device_attribute *attr, const char *buf,
|
||
|
|
size_t count)
|
||
|
|
{
|
||
|
|
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
||
|
|
ssize_t num_read_chars = 0;
|
||
|
|
int retval;
|
||
|
|
/*u32 wmreg=0;*/
|
||
|
|
unsigned int long wmreg = 0;
|
||
|
|
u8 regaddr = 0xff, regvalue = 0xff;
|
||
|
|
u8 valbuf[5] = {0};
|
||
|
|
|
||
|
|
memset(valbuf, 0, sizeof(valbuf));
|
||
|
|
mutex_lock(&fts_input_dev->mutex);
|
||
|
|
num_read_chars = count - 1;
|
||
|
|
if (num_read_chars != 2) {
|
||
|
|
if (num_read_chars != 4) {
|
||
|
|
dev_notice(dev, "please input 2 or 4 character\n");
|
||
|
|
goto error_return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
memcpy(valbuf, buf, num_read_chars);
|
||
|
|
/* retval = strict_strtoul(valbuf, 16, &wmreg); */
|
||
|
|
strToBytes((char *)buf, num_read_chars, valbuf, &retval);
|
||
|
|
|
||
|
|
if (retval == 1)
|
||
|
|
regaddr = valbuf[0];
|
||
|
|
else if (retval == 2) {
|
||
|
|
regaddr = valbuf[0];
|
||
|
|
regvalue = valbuf[1];
|
||
|
|
} else
|
||
|
|
retval = 0;
|
||
|
|
|
||
|
|
if (retval != 0) {
|
||
|
|
dev_notice(
|
||
|
|
dev,
|
||
|
|
"%s() - ERROR: Could not convert the given input to a number. The given input was: \"%s\"\n",
|
||
|
|
__func__, buf);
|
||
|
|
goto error_return;
|
||
|
|
}
|
||
|
|
if (num_read_chars == 2) {
|
||
|
|
/*read register*/
|
||
|
|
regaddr = wmreg;
|
||
|
|
FTS_DBG("[focal](0x%02x)\n", regaddr);
|
||
|
|
if (fts_read_reg(client, regaddr, ®value) < 0)
|
||
|
|
FTS_DBG("[Focal] %s : fail read the register(0x%02x)\n",
|
||
|
|
__func__, regaddr);
|
||
|
|
else
|
||
|
|
FTS_DBG("[Focal] %s : the register(0x%02x) is 0x%02x\n",
|
||
|
|
__func__, regaddr, regvalue);
|
||
|
|
} else {
|
||
|
|
regaddr = wmreg >> 8;
|
||
|
|
regvalue = wmreg;
|
||
|
|
if (fts_write_reg(client, regaddr, regvalue) < 0)
|
||
|
|
dev_notice(
|
||
|
|
dev,
|
||
|
|
"[Focal] %s : Could not write the register(0x%02x)\n",
|
||
|
|
__func__, regaddr);
|
||
|
|
else
|
||
|
|
dev_dbg(dev,
|
||
|
|
"[Focal] %s : Write 0x%02x into register(0x%02x) successful\n",
|
||
|
|
__func__, regvalue, regaddr);
|
||
|
|
}
|
||
|
|
error_return:
|
||
|
|
mutex_unlock(&fts_input_dev->mutex);
|
||
|
|
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_fwupdate_show
|
||
|
|
* Brief: no
|
||
|
|
* Input: device, device attribute, char buf
|
||
|
|
* Output: no
|
||
|
|
* Return: EPERM
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_fwupdate_show(struct device *dev,
|
||
|
|
struct device_attribute *attr, char *buf)
|
||
|
|
{
|
||
|
|
/* place holder for future use */
|
||
|
|
return -EPERM;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_fwupdate_store
|
||
|
|
* Brief: upgrade from *.i
|
||
|
|
* Input: device, device attribute, char buf, char count
|
||
|
|
* Output: no
|
||
|
|
* Return: char count
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_fwupdate_store(struct device *dev,
|
||
|
|
struct device_attribute *attr,
|
||
|
|
const char *buf, size_t count)
|
||
|
|
{
|
||
|
|
/* struct fts_ts_data *data = NULL; */
|
||
|
|
u8 uc_host_fm_ver;
|
||
|
|
int i_ret;
|
||
|
|
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
||
|
|
/* data = (struct fts_ts_data *) i2c_get_clientdata(client); */
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(0);
|
||
|
|
apk_debug_flag = 1;
|
||
|
|
#endif
|
||
|
|
mutex_lock(&fts_input_dev->mutex);
|
||
|
|
|
||
|
|
disable_irq(client->irq);
|
||
|
|
|
||
|
|
i_ret = fts_ctpm_fw_upgrade_with_i_file(client);
|
||
|
|
if (i_ret == 0) {
|
||
|
|
msleep(300);
|
||
|
|
uc_host_fm_ver = fts_ctpm_get_i_file_ver();
|
||
|
|
dev_dbg(dev, "%s [FTS] upgrade to new version 0x%x\n", __func__,
|
||
|
|
uc_host_fm_ver);
|
||
|
|
} else
|
||
|
|
dev_notice(dev, "%s ERROR:[FTS] upgrade failed ret=%d.\n",
|
||
|
|
__func__, i_ret);
|
||
|
|
|
||
|
|
/* fts_ctpm_auto_upgrade(client); */
|
||
|
|
enable_irq(client->irq);
|
||
|
|
mutex_unlock(&fts_input_dev->mutex);
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_fwupgradeapp_show
|
||
|
|
* Brief: no
|
||
|
|
* Input: device, device attribute, char buf
|
||
|
|
* Output: no
|
||
|
|
* Return: EPERM
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_fwupgradeapp_show(struct device *dev,
|
||
|
|
struct device_attribute *attr, char *buf)
|
||
|
|
{
|
||
|
|
/* place holder for future use */
|
||
|
|
return -EPERM;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_fwupgradeapp_store
|
||
|
|
* Brief: upgrade from app.bin
|
||
|
|
* Input: device, device attribute, char buf, char count
|
||
|
|
* Output: no
|
||
|
|
* Return: char count
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_fwupgradeapp_store(struct device *dev,
|
||
|
|
struct device_attribute *attr,
|
||
|
|
const char *buf, size_t count)
|
||
|
|
{
|
||
|
|
char fwname[128];
|
||
|
|
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
||
|
|
|
||
|
|
memset(fwname, 0, sizeof(fwname));
|
||
|
|
sprintf(fwname, "%s", buf);
|
||
|
|
fwname[count - 1] = '\0';
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(0);
|
||
|
|
apk_debug_flag = 1;
|
||
|
|
#endif
|
||
|
|
mutex_lock(&fts_input_dev->mutex);
|
||
|
|
|
||
|
|
disable_irq(client->irq);
|
||
|
|
fts_ctpm_fw_upgrade_with_app_file(client, fwname);
|
||
|
|
enable_irq(client->irq);
|
||
|
|
|
||
|
|
mutex_unlock(&fts_input_dev->mutex);
|
||
|
|
#if FT_ESD_PROTECT
|
||
|
|
esd_switch(1);
|
||
|
|
apk_debug_flag = 0;
|
||
|
|
#endif
|
||
|
|
return count;
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_ftsgetprojectcode_show
|
||
|
|
* Brief: no
|
||
|
|
* Input: device, device attribute, char buf
|
||
|
|
* Output: no
|
||
|
|
* Return: EPERM
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_getprojectcode_show(struct device *dev,
|
||
|
|
struct device_attribute *attr, char *buf)
|
||
|
|
{
|
||
|
|
|
||
|
|
return -EPERM;
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_ftsgetprojectcode_store
|
||
|
|
* Brief: no
|
||
|
|
* Input: device, device attribute, char buf, char count
|
||
|
|
* Output: no
|
||
|
|
* Return: EPERM
|
||
|
|
***********************************************************************/
|
||
|
|
static ssize_t fts_getprojectcode_store(struct device *dev,
|
||
|
|
struct device_attribute *attr,
|
||
|
|
const char *buf, size_t count)
|
||
|
|
{
|
||
|
|
/* place holder for future use */
|
||
|
|
return -EPERM;
|
||
|
|
}
|
||
|
|
|
||
|
|
/****************************************/
|
||
|
|
/* sysfs */
|
||
|
|
/* get the fw version
|
||
|
|
* example:cat ftstpfwver
|
||
|
|
*/
|
||
|
|
static DEVICE_ATTR(ftstpfwver, 0644, fts_tpfwver_show,
|
||
|
|
fts_tpfwver_store);
|
||
|
|
/* upgrade from *.i
|
||
|
|
* example: echo 1 > ftsfwupdate
|
||
|
|
*/
|
||
|
|
static DEVICE_ATTR(ftsfwupdate, 0644, fts_fwupdate_show,
|
||
|
|
fts_fwupdate_store);
|
||
|
|
/* read and write register
|
||
|
|
* read example: echo 88 > ftstprwreg ---read register 0x88
|
||
|
|
* write example:echo 8807 > ftstprwreg ---write 0x07 into register 0x88
|
||
|
|
*
|
||
|
|
* note:the number of input must be 2 or 4.if it not enough,please fill in the
|
||
|
|
* 0.
|
||
|
|
*/
|
||
|
|
static DEVICE_ATTR(ftstprwreg, 0644, fts_tprwreg_show,
|
||
|
|
fts_tprwreg_store);
|
||
|
|
/* upgrade from app.bin
|
||
|
|
* example:echo "*_app.bin" > ftsfwupgradeapp
|
||
|
|
*/
|
||
|
|
static DEVICE_ATTR(ftsfwupgradeapp, 0644, fts_fwupgradeapp_show,
|
||
|
|
fts_fwupgradeapp_store);
|
||
|
|
static DEVICE_ATTR(ftsgetprojectcode, 0644,
|
||
|
|
fts_getprojectcode_show, fts_getprojectcode_store);
|
||
|
|
|
||
|
|
/* add your attr in here*/
|
||
|
|
static struct attribute *fts_attributes[] = {
|
||
|
|
&dev_attr_ftstpfwver.attr, &dev_attr_ftsfwupdate.attr,
|
||
|
|
&dev_attr_ftstprwreg.attr, &dev_attr_ftsfwupgradeapp.attr,
|
||
|
|
&dev_attr_ftsgetprojectcode.attr, NULL};
|
||
|
|
|
||
|
|
static struct attribute_group fts_attribute_group = {.attrs = fts_attributes};
|
||
|
|
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_create_sysfs
|
||
|
|
* Brief: create sysfs for debug
|
||
|
|
* Input: i2c info
|
||
|
|
* Output: no
|
||
|
|
* Return: success =0
|
||
|
|
***********************************************************************/
|
||
|
|
int fts_create_sysfs(struct i2c_client *client)
|
||
|
|
{
|
||
|
|
int err;
|
||
|
|
|
||
|
|
err = sysfs_create_group(&client->dev.kobj, &fts_attribute_group);
|
||
|
|
if (err != 0) {
|
||
|
|
dev_notice(&client->dev,
|
||
|
|
"%s() - ERROR: sysfs_create_group() failed.\n",
|
||
|
|
__func__);
|
||
|
|
sysfs_remove_group(&client->dev.kobj, &fts_attribute_group);
|
||
|
|
return -EIO;
|
||
|
|
}
|
||
|
|
pr_info("fts:%s() - sysfs_create_group() succeeded.\n", __func__);
|
||
|
|
/* HidI2c_To_StdI2c(client); */
|
||
|
|
return err;
|
||
|
|
}
|
||
|
|
/*******************************************************************************
|
||
|
|
* Name: fts_remove_sysfs
|
||
|
|
* Brief: remove sys
|
||
|
|
* Input: i2c info
|
||
|
|
* Output: no
|
||
|
|
* Return: no
|
||
|
|
***********************************************************************/
|
||
|
|
int fts_remove_sysfs(struct i2c_client *client)
|
||
|
|
{
|
||
|
|
sysfs_remove_group(&client->dev.kobj, &fts_attribute_group);
|
||
|
|
return 0;
|
||
|
|
}
|