blob: c814628cb3d54fae98d914351f19fcba235fb011 [file] [log] [blame]
/*
* Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/mutex.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/err.h>
#include "ist30xx.h"
#include "ist30xx_update.h"
#include "ist30xx_misc.h"
static char IsfwUpdate[20] = { 0 };
#define FW_DOWNLOADING "Downloading"
#define FW_DOWNLOAD_COMPLETE "Complete"
#define FW_DOWNLOAD_FAIL "FAIL"
#define FACTORY_BUF_SIZE (1024)
#define BUILT_IN (0)
#define CMD_STATE_WAITING (0)
#define CMD_STATE_RUNNING (1)
#define CMD_STATE_OK (2)
#define CMD_STATE_FAIL (3)
#define CMD_STATE_NA (4)
#define TSP_NODE_DEBUG (1)
#define NODE_X_NUM 12
#define NODE_Y_NUM 18
static u16 node_value[TSP_TOTAL_NUM];
extern struct ist30xx_data *ts_data;
extern TSP_INFO ist30xx_tsp_info;
extern TKEY_INFO ist30xx_tkey_info;
#define TSP_CMD(name, func) .cmd_name = name, .cmd_func = func
struct tsp_cmd {
struct list_head list;
const char * cmd_name;
void (*cmd_func)(void *dev_data);
};
u32 ist30xxb_get_fw_ver(struct ist30xx_data *data)
{
u32 addr = data->tags.cfg_addr + 4;
u32 len = 1;
u32 ver = 0;
int ret = -EPERM;
ist30xx_disable_irq(data);
ret = ist30xx_cmd_reg(data->client, CMD_ENTER_REG_ACCESS);
if (ret) goto get_fw_ver_fail;
ret = ist30xx_write_cmd(data->client, IST30XX_RX_CNT_ADDR, len);
if (ret) goto get_fw_ver_fail;
ret = ist30xx_read_cmd(data->client, addr, &ver);
if (ret) goto get_fw_ver_fail;
tsp_debug("Reg addr: %x, ver: %x\n", addr, ver);
ret = ist30xx_cmd_reg(data->client, CMD_EXIT_REG_ACCESS);
if (ret == 0)
goto get_fw_ver_end;
get_fw_ver_fail:
ist30xx_cmd_run_device(data->client);
get_fw_ver_end:
ist30xx_cmd_start_scan(data->client);
ist30xx_enable_irq(data);
return ver;
}
int ist30xxb_get_key_sensitivity(struct ist30xx_data *data, int id)
{
u32 addr = IST30XXB_MEM_COUNT + 4 * sizeof(u32);
u32 val = 0;
if (id >= ist30xx_tkey_info.key_num)
return 0;
ist30xx_disable_irq(data);
ist30xx_read_cmd(ts_data->client, addr, &val);
ist30xx_enable_irq(data);
tsp_debug("Reg addr: %x, val: %8x\n", addr, val);
val >>= (16 * id);
return (int)(val & 0xFFFF);
}
/* Factory CMD function */
static void set_default_result(struct sec_factory *sec)
{
char delim = ':';
memset(sec->cmd_result, 0, ARRAY_SIZE(sec->cmd_result));
memcpy(sec->cmd_result, sec->cmd, strlen(sec->cmd));
strncat(sec->cmd_result, &delim, CMD_STATE_RUNNING);
}
static void set_cmd_result(struct sec_factory *sec, char *buf, int len)
{
strncat(sec->cmd_result, buf, len);
}
static void not_support_cmd(void *dev_data)
{
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
snprintf(buf, sizeof(buf), "%s", "NA");
tsp_info("%s(), %s\n", __func__, buf);
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
sec->cmd_state = CMD_STATE_NA;
dev_info(&data->client->dev, "%s: \"%s(%d)\"\n", __func__,
buf, strnlen(buf, sizeof(buf)));
return;
}
static void get_chip_vendor(void *dev_data)
{
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
snprintf(buf, sizeof(buf), "%s", TSP_CHIP_VENDOR);
tsp_info("%s(), %s\n", __func__, buf);
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__,
buf, strnlen(buf, sizeof(buf)));
}
static void get_chip_name(void *dev_data)
{
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
snprintf(buf, sizeof(buf), "%s", TSP_CHIP_NAME);
tsp_info("%s(), %s\n", __func__, buf);
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__,
buf, strnlen(buf, sizeof(buf)));
}
static void get_chip_id(void *dev_data)
{
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
snprintf(buf, sizeof(buf), "%#02x", data->chip_id);
tsp_info("%s(), %s\n", __func__, buf);
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__,
buf, strnlen(buf, sizeof(buf)));
}
static void fw_update(void *dev_data)
{
int ret;
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
tsp_info("%s(), %d\n", __func__, sec->cmd_param[0]);
switch (sec->cmd_param[0]) {
case BUILT_IN:
sec->cmd_state = CMD_STATE_OK;
ret = ist30xx_fw_recovery(data);
if (ret < 0) {
sec->cmd_state = CMD_STATE_FAIL;
return;
}
break;
default:
tsp_warn("%s(), Invalid fw file type!\n", __func__);
break;
}
if (sec->cmd_state == CMD_STATE_OK)
snprintf(buf, sizeof(buf), "%s", "OK");
else
snprintf(buf, sizeof(buf), "%s", "NG");
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
}
static void get_fw_ver_bin(void *dev_data)
{
u32 ver = 0;
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
ver = ist30xx_parse_ver(FLAG_PARAM, data->fw.buf);
snprintf(buf, sizeof(buf), "IM00%04x", ver);
tsp_info("%s(), %s\n", __func__, buf);
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__,
buf, strnlen(buf, sizeof(buf)));
}
static void get_fw_ver_ic(void *dev_data)
{
u32 ver = 0;
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
if (data->status.power == 1)
ver = ist30xxb_get_fw_ver(ts_data);
snprintf(buf, sizeof(buf), "IM00%04x", ver & 0xFFFF);
tsp_info("%s(), %s\n", __func__, buf);
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__,
buf, strnlen(buf, sizeof(buf)));
}
static void get_threshold(void *dev_data)
{
char buf[16] = { 0 };
int val = TSP_THRESHOLD;
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
snprintf(buf, sizeof(buf), "%d", val);
tsp_info("%s(), %s\n", __func__, buf);
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__,
buf, strnlen(buf, sizeof(buf)));
}
static void get_x_num(void *dev_data)
{
int val = ist30xx_tsp_info.width;
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
if (val >= 0) {
snprintf(buf, sizeof(buf), "%u", val);
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__, buf,
strnlen(buf, sizeof(buf)));
} else {
snprintf(buf, sizeof(buf), "%s", "NG");
sec->cmd_state = CMD_STATE_FAIL;
dev_info(&data->client->dev,
"%s: fail to read num of x (%d).\n", __func__, val);
}
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
tsp_info("%s(), %s\n", __func__, buf);
}
static void get_y_num(void *dev_data)
{
int val = ist30xx_tsp_info.height;
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
if (val >= 0) {
snprintf(buf, sizeof(buf), "%u", val);
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__, buf,
strnlen(buf, sizeof(buf)));
} else {
snprintf(buf, sizeof(buf), "%s", "NG");
sec->cmd_state = CMD_STATE_FAIL;
dev_info(&data->client->dev,
"%s: fail to read num of x (%d).\n", __func__, val);
}
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
tsp_info("%s(), %s\n", __func__, buf);
}
static int check_rx_tx_num(void *dev_data)
{
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
char buff[SEC_CMD_STR_LEN] = {0};
int node;
if (sec->cmd_param[0] < 0 ||
sec->cmd_param[0] >= NODE_X_NUM ||
sec->cmd_param[1] < 0 ||
sec->cmd_param[1] >= NODE_Y_NUM) {
snprintf(buff, sizeof(buff) , "%s", "NG");
set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = 3;
dev_info(&data->client->dev, "%s: parameter error: %u,%u\n",
__func__, sec->cmd_param[0],
sec->cmd_param[1]);
node = -1;
return node;
}
//node = info->cmd_param[1] * NODE_Y_NUM + info->cmd_param[0];
node = sec->cmd_param[0] * NODE_Y_NUM + sec->cmd_param[1];
dev_info(&data->client->dev, "%s: node = %d\n", __func__,
node);
return node;
}
void get_cm_abs(void *dev_data)
{
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
char buff[16] = {0};
unsigned int val;
int node;
printk("[TSP] %s, %d\n", __func__, __LINE__ );
set_default_result(sec);
node = check_rx_tx_num(data);
if (node < 0)
return;
val = node_value[node];
snprintf(buff, sizeof(buff), "%u", val);
set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = 2;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__, buff,
strnlen(buff, sizeof(buff)));
}
void get_reference(void *dev_data)
{
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
char buff[16] = {0};
unsigned int val;
int node;
printk("[TSP] %s, %d\n", __func__, __LINE__ );
set_default_result(sec);
node = check_rx_tx_num(data);
if (node < 0)
return;
val = node_value[node];
snprintf(buff, sizeof(buff), "%u", val);
set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = 2;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__, buff,
strnlen(buff, sizeof(buff)));
}
int check_tsp_channel(void *dev_data)
{
int node = -EPERM;
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
TSP_INFO *tsp = &ist30xx_tsp_info;
if ((sec->cmd_param[0] < 0) || (sec->cmd_param[0] >= tsp->width) ||
(sec->cmd_param[1] < 0) || (sec->cmd_param[1] >= tsp->height)) {
dev_info(&data->client->dev, "%s: parameter error: %u,%u\n",
__func__, sec->cmd_param[0], sec->cmd_param[1]);
} else {
node = sec->cmd_param[0] + sec->cmd_param[1] * tsp->width;
dev_info(&data->client->dev, "%s: node = %d\n", __func__, node);
}
return node;
}
extern int parse_tsp_node(u8 flag, struct TSP_NODE_BUF *node, s16 *buf16);
void run_raw_read(void *dev_data)
{
int i, ret;
int min_val, max_val;
char buf[16] = { 0 };
u8 flag = NODE_FLAG_RAW;
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
TSP_INFO *tsp = &ist30xx_tsp_info;
set_default_result(sec);
ret = ist30xx_read_touch_node(flag, &tsp->node);
if (ret) {
sec->cmd_state = CMD_STATE_FAIL;
tsp_warn("%s(), tsp node read fail!\n", __func__);
return;
}
ist30xx_parse_touch_node(flag, &tsp->node);
ret = parse_tsp_node(flag, &tsp->node, node_value);
if (ret) {
sec->cmd_state = CMD_STATE_FAIL;
tsp_warn("%s(), tsp node parse fail - flag: %d\n", __func__, flag);
return;
}
sec->cmd_state = CMD_STATE_OK;
}
void run_reference_read(void *dev_data)
{
int i, ret;
int min_val, max_val;
char buf[16] = { 0 };
u8 flag = NODE_FLAG_RAW;
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
TSP_INFO *tsp = &ist30xx_tsp_info;
set_default_result(sec);
ret = ist30xx_read_touch_node(flag, &tsp->node);
if (ret) {
sec->cmd_state = CMD_STATE_FAIL;
tsp_warn("%s(), tsp node read fail!\n", __func__);
return;
}
ist30xx_parse_touch_node(flag, &tsp->node);
ret = parse_tsp_node(flag, &tsp->node, node_value);
if (ret) {
sec->cmd_state = CMD_STATE_FAIL;
tsp_warn("%s(), tsp node parse fail - flag: %d\n", __func__, flag);
return;
}
min_val = max_val = node_value[0];
for (i = 0; i < tsp->width * tsp->height; i++) {
#if TSP_NODE_DEBUG
if ((i % tsp->width) == 0)
printk("\n%s %4d: ", IST30XX_DEBUG_TAG, i);
printk("%4d ", node_value[i]);
#endif
max_val = max(max_val, (int)node_value[i]);
min_val = min(min_val, (int)node_value[i]);
}
snprintf(buf, sizeof(buf), "%d,%d", min_val, max_val);
tsp_info("%s(), %s\n", __func__, buf);
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
sec->cmd_state = CMD_STATE_OK;
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__, buf,
strnlen(buf, sizeof(buf)));
}
void get_raw_value(void *dev_data)
{
int idx = 0;
char buf[16] = { 0 };
struct ist30xx_data *data = (struct ist30xx_data *)dev_data;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
set_default_result(sec);
idx = check_tsp_channel(data);
if (idx < 0) { // Parameter parsing fail
snprintf(buf, sizeof(buf), "%s", "NG");
sec->cmd_state = CMD_STATE_FAIL;
} else {
snprintf(buf, sizeof(buf), "%d", node_value[idx]);
sec->cmd_state = CMD_STATE_OK;
}
set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
tsp_info("%s(), [%d][%d]: %s\n", __func__,
sec->cmd_param[0], sec->cmd_param[1], buf);
dev_info(&data->client->dev, "%s: %s(%d)\n", __func__, buf,
strnlen(buf, sizeof(buf)));
}
/* sysfs: /sys/class/sec/tsp/close_tsp_test */
static ssize_t show_close_tsp_test(struct device *dev,
struct device_attribute *attr, char *buf)
{
return snprintf(buf, FACTORY_BUF_SIZE, "%u\n", 0);
}
/* sysfs: /sys/class/sec/tsp/cmd */
static ssize_t store_cmd(struct device *dev, struct device_attribute
*devattr, const char *buf, size_t count)
{
struct ist30xx_data *data = dev_get_drvdata(dev);
struct sec_factory *sec = (struct sec_factory *)&data->sec;
struct i2c_client *client = data->client;
char *cur, *start, *end;
char msg[SEC_CMD_STR_LEN] = { 0 };
int len, i;
struct tsp_cmd *tsp_cmd_ptr = NULL;
char delim = ',';
bool cmd_found = false;
int param_cnt = 0;
int ret;
if (sec->cmd_is_running == true) {
dev_err(&client->dev, "tsp_cmd: other cmd is running.\n");
tsp_err("tsp_cmd: other cmd is running.\n");
goto err_out;
}
/* check lock */
mutex_lock(&sec->cmd_lock);
sec->cmd_is_running = true;
mutex_unlock(&sec->cmd_lock);
sec->cmd_state = CMD_STATE_RUNNING;
for (i = 0; i < ARRAY_SIZE(sec->cmd_param); i++)
sec->cmd_param[i] = 0;
len = (int)count;
if (*(buf + len - 1) == '\n')
len--;
memset(sec->cmd, 0, ARRAY_SIZE(sec->cmd));
memcpy(sec->cmd, buf, len);
cur = strchr(buf, (int)delim);
if (cur)
memcpy(msg, buf, cur - buf);
else
memcpy(msg, buf, len);
/* find command */
list_for_each_entry(tsp_cmd_ptr, &sec->cmd_list_head, list) {
if (!strcmp(msg, tsp_cmd_ptr->cmd_name)) {
cmd_found = true;
break;
}
}
/* set not_support_cmd */
if (!cmd_found) {
list_for_each_entry(tsp_cmd_ptr, &sec->cmd_list_head, list) {
if (!strcmp("not_support_cmd", tsp_cmd_ptr->cmd_name))
break;
}
}
/* parsing parameters */
if (cur && cmd_found) {
cur++;
start = cur;
memset(msg, 0, ARRAY_SIZE(msg));
do {
if (*cur == delim || cur - buf == len) {
end = cur;
memcpy(msg, start, end - start);
*(msg + strlen(msg)) = '\0';
ret = kstrtoint(msg, 10, \
sec->cmd_param + param_cnt);
start = cur + 1;
memset(msg, 0, ARRAY_SIZE(msg));
param_cnt++;
}
cur++;
} while (cur - buf <= len);
}
dev_info(&client->dev, "cmd = %s\n", tsp_cmd_ptr->cmd_name);
tsp_info("SEC CMD = %s\n", tsp_cmd_ptr->cmd_name);
for (i = 0; i < param_cnt; i++)
dev_info(&client->dev, "cmd param %d= %d\n", i, sec->cmd_param[i]);
tsp_cmd_ptr->cmd_func(data);
err_out:
return count;
}
/* sysfs: /sys/class/sec/tsp/cmd_status */
static ssize_t show_cmd_status(struct device *dev,
struct device_attribute *devattr, char *buf)
{
struct ist30xx_data *data = dev_get_drvdata(dev);
struct sec_factory *sec = (struct sec_factory *)&data->sec;
char msg[16] = { 0 };
dev_info(&data->client->dev, "tsp cmd: status:%d\n", sec->cmd_state);
if (sec->cmd_state == CMD_STATE_WAITING)
snprintf(msg, sizeof(msg), "WAITING");
else if (sec->cmd_state == CMD_STATE_RUNNING)
snprintf(msg, sizeof(msg), "RUNNING");
else if (sec->cmd_state == CMD_STATE_OK)
snprintf(msg, sizeof(msg), "OK");
else if (sec->cmd_state == CMD_STATE_FAIL)
snprintf(msg, sizeof(msg), "FAIL");
else if (sec->cmd_state == CMD_STATE_NA)
snprintf(msg, sizeof(msg), "NOT_APPLICABLE");
return snprintf(buf, FACTORY_BUF_SIZE, "%s\n", msg);
}
/* sysfs: /sys/class/sec/tsp/result */
static ssize_t show_cmd_result(struct device *dev, struct device_attribute
*devattr, char *buf)
{
struct ist30xx_data *data = dev_get_drvdata(dev);
struct sec_factory *sec = (struct sec_factory *)&data->sec;
dev_info(&data->client->dev, "tsp cmd: result: %s\n", sec->cmd_result);
mutex_lock(&sec->cmd_lock);
sec->cmd_is_running = false;
mutex_unlock(&sec->cmd_lock);
sec->cmd_state = CMD_STATE_WAITING;
return snprintf(buf, FACTORY_BUF_SIZE, "%s\n", sec->cmd_result);
}
/* sysfs: /sys/class/sec/tsp/sec_touchscreen/tsp_firm_version_phone */
static ssize_t phone_firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
{
u32 ver = ist30xx_parse_ver(FLAG_PARAM, ts_data->fw.buf);
tsp_info("%s(), IM00%04x\n", __func__, ver);
return sprintf(buf, "IM00%04x", ver);
}
/* sysfs: /sys/class/sec/tsp/sec_touchscreen/tsp_firm_version_panel */
static ssize_t part_firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
{
u32 ver = 0;
if (ts_data->status.power == 1)
ver = ist30xxb_get_fw_ver(ts_data);
tsp_info("%s(), IM00%04x\n", __func__, ver);
return sprintf(buf, "IM00%04x", ver);
}
/* sysfs: /sys/class/sec/tsp/sec_touchscreen/tsp_threshold */
static ssize_t threshold_firmware_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int val = TSP_THRESHOLD;
tsp_info("%s(), %d\n", __func__, val);
return sprintf(buf, "%d", val);
}
/* sysfs: /sys/class/sec/tsp/sec_touchscreen/tsp_firm_update */
static ssize_t firmware_update(struct device *dev, struct device_attribute *attr, char *buf)
{
bool ret;
sprintf(IsfwUpdate, "%s\n", FW_DOWNLOADING);
tsp_info("%s(), %s\n", __func__, IsfwUpdate);
ret = ist30xx_fw_recovery(ts_data);
ret = (ret == 0 ? 1 : -1);
sprintf(IsfwUpdate, "%s\n",
(ret > 0 ? FW_DOWNLOAD_COMPLETE : FW_DOWNLOAD_FAIL));
tsp_info("%s(), %s\n", __func__, IsfwUpdate);
return sprintf(buf, "%d", ret);
}
/* sysfs: /sys/class/sec/tsp/sec_touchscreen/tsp_firm_update_status */
static ssize_t firmware_update_status(struct device *dev, struct device_attribute *attr, char *buf)
{
tsp_info("%s(), %s\n", __func__, IsfwUpdate);
return sprintf(buf, "%s\n", IsfwUpdate);
}
/* sysfs: /sys/class/sec/tsp/sec_touchkey/touchkey_menu */
static ssize_t menu_sensitivity_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int sensitivity = ist30xxb_get_key_sensitivity(ts_data, 0);
tsp_info("%s(), %d\n", __func__, sensitivity);
return sprintf(buf, "%d\n", sensitivity);
}
/* sysfs: /sys/class/sec/tsp/sec_touchkey/touchkey_back */
static ssize_t back_sensitivity_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int sensitivity = ist30xxb_get_key_sensitivity(ts_data, 1);
tsp_info("%s(), %d\n", __func__, sensitivity);
return sprintf(buf, "%d\n", sensitivity);
}
/* sysfs: /sys/class/sec/tsp/sec_touchkey/touchkey_threshold */
static ssize_t touchkey_threshold_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int val = TKEY_THRESHOLD;
tsp_info("%s(), %d\n", __func__, val);
return snprintf(buf, sizeof(int), "%d\n", val);
}
struct tsp_cmd tsp_cmds[] = {
{ TSP_CMD("fw_update", not_support_cmd), },
{ TSP_CMD("get_fw_ver_bin", get_fw_ver_bin), },
{ TSP_CMD("get_fw_ver_ic", get_fw_ver_ic), },
{ TSP_CMD("get_config_ver", not_support_cmd), },
{ TSP_CMD("get_threshold", not_support_cmd), },
{ TSP_CMD("module_off_master", not_support_cmd), },
{ TSP_CMD("module_on_master", not_support_cmd), },
{ TSP_CMD("module_off_slave", not_support_cmd), },
{ TSP_CMD("module_on_slave", not_support_cmd), },
{ TSP_CMD("get_chip_vendor", get_chip_vendor), },
{ TSP_CMD("get_chip_name", get_chip_name), },
{ TSP_CMD("run_rawcap_read", run_raw_read), },
{ TSP_CMD("get_x_num", get_x_num), },
{ TSP_CMD("get_y_num", get_y_num), },
{TSP_CMD("get_reference", get_reference),},
{ TSP_CMD("get_cm_abs", get_cm_abs), },
{ TSP_CMD("get_rawcap", not_support_cmd), },
{ TSP_CMD("get_cm_delta", not_support_cmd), },
{ TSP_CMD("get_intensity", not_support_cmd), },
{TSP_CMD("run_reference_read", run_reference_read),},
{ TSP_CMD("run_cm_abs_read", run_raw_read), },
{ TSP_CMD("run_cm_delta_read", not_support_cmd), },
{ TSP_CMD("run_intensity_read", not_support_cmd), },
{ TSP_CMD("not_support_cmd", not_support_cmd), },
};
#define SEC_DEFAULT_ATTR (S_IRUGO | S_IWUSR | S_IWOTH | S_IXOTH)
/* sysfs - touchscreen */
static DEVICE_ATTR(tsp_firm_version_phone, SEC_DEFAULT_ATTR,
phone_firmware_show, NULL);
static DEVICE_ATTR(tsp_firm_version_panel, SEC_DEFAULT_ATTR,
part_firmware_show, NULL);
static DEVICE_ATTR(tsp_threshold, SEC_DEFAULT_ATTR,
threshold_firmware_show, NULL);
static DEVICE_ATTR(tsp_firm_update, SEC_DEFAULT_ATTR,
firmware_update, NULL);
static DEVICE_ATTR(tsp_firm_update_status, SEC_DEFAULT_ATTR,
firmware_update_status, NULL);
/* sysfs - touchkey */
static DEVICE_ATTR(touchkey_menu, SEC_DEFAULT_ATTR,
menu_sensitivity_show, NULL);
static DEVICE_ATTR(touchkey_back, SEC_DEFAULT_ATTR,
back_sensitivity_show, NULL);
static DEVICE_ATTR(touchkey_threshold, SEC_DEFAULT_ATTR,
touchkey_threshold_show, NULL);
/* sysfs - tsp */
static DEVICE_ATTR(close_tsp_test, S_IRUGO, show_close_tsp_test, NULL);
static DEVICE_ATTR(cmd, S_IWUSR | S_IWGRP, NULL, store_cmd);
static DEVICE_ATTR(cmd_status, S_IRUGO, show_cmd_status, NULL);
static DEVICE_ATTR(cmd_result, S_IRUGO, show_cmd_result, NULL);
static struct attribute *sec_tsp_attributes[] = {
&dev_attr_tsp_firm_version_phone.attr,
&dev_attr_tsp_firm_version_panel.attr,
&dev_attr_tsp_threshold.attr,
&dev_attr_tsp_firm_update.attr,
&dev_attr_tsp_firm_update_status.attr,
NULL,
};
static struct attribute *sec_tkey_attributes[] = {
&dev_attr_touchkey_menu.attr,
&dev_attr_touchkey_back.attr,
&dev_attr_touchkey_threshold.attr,
NULL,
};
static struct attribute *sec_touch_facotry_attributes[] = {
&dev_attr_close_tsp_test.attr,
&dev_attr_cmd.attr,
&dev_attr_cmd_status.attr,
&dev_attr_cmd_result.attr,
NULL,
};
static struct attribute_group sec_tsp_attr_group = {
.attrs = sec_tsp_attributes,
};
static struct attribute_group sec_tkey_attr_group = {
.attrs = sec_tkey_attributes,
};
static struct attribute_group sec_touch_factory_attr_group = {
.attrs = sec_touch_facotry_attributes,
};
extern struct class *sec_class;
struct device *sec_touchscreen;
EXPORT_SYMBOL(sec_touchscreen);
struct device *sec_touchkey;
EXPORT_SYMBOL(sec_touchkey);
struct device *sec_fac_dev;
int sec_touch_sysfs(struct ist30xx_data *data)
{
printk("[TSP] %s\n", __func__);
/* /sys/class/sec/sec_touchscreen */
sec_touchscreen = device_create(sec_class, NULL, 0, NULL, "sec_touchscreen");
if (IS_ERR(sec_touchscreen)) {
tsp_err("Failed to create device (%s)!\n", "sec_touchscreen");
return -ENODEV;
}
/* /sys/class/sec/sec_touchscreen/... */
if (sysfs_create_group(&sec_touchscreen->kobj, &sec_tsp_attr_group))
tsp_err("Failed to create sysfs group(%s)!\n", "sec_touchscreen");
/* /sys/class/sec/sec_touchkey */
sec_touchkey = device_create(sec_class, NULL, 0, NULL, "sec_touchkey");
if (IS_ERR(sec_touchkey)) {
tsp_err("Failed to create device (%s)!\n", "sec_touchkey");
return -ENODEV;
}
/* /sys/class/sec/sec_touchkey/... */
if (sysfs_create_group(&sec_touchkey->kobj, &sec_tkey_attr_group))
tsp_err("Failed to create sysfs group(%s)!\n", "sec_touchkey");
/* /sys/class/sec/tsp */
sec_fac_dev = device_create(sec_class, NULL, 0, data, "tsp");
if (IS_ERR(sec_fac_dev)) {
tsp_err("Failed to create device (%s)!\n", "tsp");
return -ENODEV;
}
/* /sys/class/sec/tsp/... */
if (sysfs_create_group(&sec_fac_dev->kobj, &sec_touch_factory_attr_group))
tsp_err("Failed to create sysfs group(%s)!\n", "tsp");
return 0;
}
EXPORT_SYMBOL(sec_touch_sysfs);
int sec_fac_cmd_init(struct ist30xx_data *data)
{
int i;
struct sec_factory *sec = (struct sec_factory *)&data->sec;
INIT_LIST_HEAD(&sec->cmd_list_head);
for (i = 0; i < ARRAY_SIZE(tsp_cmds); i++)
list_add_tail(&tsp_cmds[i].list, &sec->cmd_list_head);
mutex_init(&sec->cmd_lock);
sec->cmd_is_running = false;
return 0;
}
EXPORT_SYMBOL(sec_fac_cmd_init);