sdk-hwV1.3/lichee/linux-4.9/drivers/input/touchscreen/cf11xx/sitronix_ts_sysfs.c

572 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <linux/ctype.h>
#include "sitronix_ts_custom_func.h"
#include "sitronix_ts.h"
char stinfbuf[16];
static ssize_t st_inform_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ssize_t sret;
mutex_lock(&stx_gpts.dev_mutex);
st_get_touch_info(&stx_gpts);
mutex_unlock(&stx_gpts.dev_mutex);
sret = snprintf(buf, 1000,
"Sitronix touch\n"
"FW Version = %d\n"
"FW Revision = %s\n"
"Channels = %d x %d\n"
"Max touches = %d\n"
"res = %d x %d\n"
"chip = 0x%x\n",
stx_gpts.ts_dev_info.fw_version[0],
stx_gpts.ts_dev_info.fw_revision,
stx_gpts.ts_dev_info.rx_chs,
stx_gpts.ts_dev_info.tx_chs,
stx_gpts.ts_dev_info.max_touches,
stx_gpts.ts_dev_info.x_res, stx_gpts.ts_dev_info.y_res,
stx_gpts.ts_dev_info.chip_id);
return sret;
}
static ssize_t st_inform_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
memset(stinfbuf, 0, 16);
memcpy(stinfbuf, buf, count);
STX_INFO("%s inbuffer:%s buf:%s ", __func__, stinfbuf, buf);
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static ssize_t st_glove_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ssize_t sret;
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
/*add function*/
#ifdef ST_GLOVE_SWITCH_MODE
sret = snprintf(buf, 100, "Sitronix glove_mode = %s\n",
stx_gpts.glove_mode ? "on" : "off");
#else
sret = snprintf(buf, 100, "Don't support ST_GLOVE_SWITCH_MODE mode\n");
#endif
mutex_unlock(&stx_gpts.dev_mutex);
return sret;
}
static ssize_t st_glove_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
#ifdef ST_GLOVE_SWITCH_MODE
if (buf[0] == '1')
st_enter_glove_mode(&stx_gpts);
if (buf[0] == '0')
st_leave_glove_mode(&stx_gpts);
#endif
/*add function*/
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static ssize_t st_cases_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ssize_t sret;
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
/*add function*/
#ifdef ST_CASES_SWITCH_MODE
sret = snprintf(buf, 100, "Sitronix cases_mode = %s\n",
stx_gpts.cases_mode ? "on" : "off");
#else
sret = snprintf(buf, 100, "Don't support ST_CASES_SWITCH_MODE mode\n");
#endif
mutex_unlock(&stx_gpts.dev_mutex);
return sret;
}
static ssize_t st_cases_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
#ifdef ST_CASES_SWITCH_MODE
if (buf[0] == '1')
stx_gpts.cases_mode = true;
if (buf[0] == '0')
stx_gpts.cases_mode = false;
#endif
/*add function*/
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static ssize_t st_rawtest_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t sret;
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
/*add function*/
#ifdef ST_TEST_RAW
sret = snprintf(
buf, 200,
"Sitronix Raw Test Result = %d ( 0 == success, >0 failed sensor number, < 0 err) \n",
stx_gpts.rawTestResult);
#else
sret = snprintf(buf, 100, "Don't support ST_TEST_RAW mode\n");
#endif
mutex_unlock(&stx_gpts.dev_mutex);
return sret;
}
static ssize_t st_rawtest_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
#ifdef ST_TEST_RAW
int status = 0;
#endif
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
#ifdef ST_TEST_RAW
status = st_testraw_invoke();
stx_gpts.rawTestResult = status;
#endif
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static int st_char2hex(char data)
{
int num = 0;
if ((data >= '0') && (data <= '9')) {
num = data - '0';
}
if ((data >= 'a') && (data <= 'f')) {
num = data - 'a' + 10;
}
if ((data >= 'A') && (data <= 'F')) {
num = data - 'A' + 10;
}
return num;
}
u8 st_reg_data = 0;
static ssize_t st_rwreg_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ssize_t num_read_chars;
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
num_read_chars = snprintf(buf, 128, "0x%x\n", st_reg_data);
mutex_unlock(&stx_gpts.dev_mutex);
STX_INFO("%s num_read_chars:%zu buf:%s", __func__, num_read_chars, buf);
return num_read_chars;
}
static ssize_t st_rwreg_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
ssize_t num_chars = 0;
int reg_addr;
int reg_data;
char buffer[2] = { 0 };
STX_INFO("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
STX_INFO("%s count:%zu buf:%s ", __func__, count, buf);
num_chars = count - 1;
if (num_chars == 2) {
reg_addr = st_char2hex(buf[0]) * 0x10 + st_char2hex(buf[1]);
STX_INFO("%s reg_addr:0x%x", __func__, reg_addr);
/*read register and save data to reg_data*/
stx_i2c_read(stx_gpts.client, &st_reg_data, 1, reg_addr);
}
if (num_chars == 4) {
reg_addr = st_char2hex(buf[0]) * 0x10 + st_char2hex(buf[1]);
reg_data = st_char2hex(buf[2]) * 0x10 + st_char2hex(buf[3]);
STX_INFO("%s reg_addr:0x%x reg_data:0x%x", __func__, reg_addr,
reg_data);
/*write register*/
buffer[0] = reg_addr;
buffer[1] = reg_data;
stx_i2c_write(stx_gpts.client, buffer, 2);
}
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static ssize_t st_mt_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
ssize_t sret = 0;
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
/*add function*/
mutex_unlock(&stx_gpts.dev_mutex);
return sret;
}
static ssize_t st_mt_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
/*add function*/
#ifdef ST_MONITOR_THREAD
if (buf[0] == '1')
sitronix_monitor_start();
if (buf[0] == '0')
sitronix_monitor_stop();
#endif
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static ssize_t st_forceUpg_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
char spath[40] = { 0 };
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
sprintf(spath, "%s", buf);
stx_force_upgrade_fw(spath);
st_print_version(&stx_gpts);
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static ssize_t st_manual_rst_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
if (buf[0] == '1') {
st_reset_ic();
STX_INFO("TP has manual reset");
}
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static ssize_t st_smart_wakeup_switch_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
if (buf[0] == '1')
stx_gpts.fsmart_wakeup = 1;
else if (buf[0] == '0')
stx_gpts.fsmart_wakeup = 0;
STX_INFO("fsmart_wakeup = %d", stx_gpts.fsmart_wakeup);
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
static void StrToHex(char *pbDest, const char *pbSrc, int nLen)
{
char h1, h2;
char s1, s2;
int i;
for (i = 0; i < nLen / 2; i++) {
h1 = pbSrc[2 * i];
h2 = pbSrc[2 * i + 1];
s1 = toupper(h1) - 0x30;
if (s1 > 9)
s1 -= 7;
s2 = toupper(h2) - 0x30;
if (s2 > 9)
s2 -= 7;
pbDest[i] = s1 * 16 + s2;
}
}
static ssize_t st_temporary_set_i2caddr_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
char addr;
STX_DEBUG("%s", __func__);
mutex_lock(&stx_gpts.dev_mutex);
StrToHex(&addr, buf, 2);
stx_gpts.client->addr = addr;
STX_INFO("i2caddr = 0x%x ", addr);
mutex_unlock(&stx_gpts.dev_mutex);
return count;
}
/****************************************/
/* sysfs */
/**获取tp信息**/
static DEVICE_ATTR(stinform, S_IRUGO | S_IWUSR, st_inform_show,
st_inform_store);
/**手套模式1 正常模式0**/
static DEVICE_ATTR(stglove, S_IRUGO | S_IWUSR, st_glove_show, st_glove_store);
static DEVICE_ATTR(stcases, S_IRUGO | S_IWUSR, st_cases_show, st_cases_store);
/**皮套模式1 正常模式0**/
static DEVICE_ATTR(strawtest, S_IRUGO | S_IWUSR, st_rawtest_show,
st_rawtest_store);
/*read and write register
*read example: echo 88 > strwreg ---read register 0x88
*write example:echo 8807 > strwreg ---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(strwreg, S_IRUGO | S_IWUSR, st_rwreg_show, st_rwreg_store);
static DEVICE_ATTR(stmt, S_IRUGO | S_IWUSR, st_mt_show, st_mt_store);
/**升级touchscreen 固件程序 固件默认存放在request_fw 空间**/
static DEVICE_ATTR(stupgrade, S_IRUGO | S_IWUSR, NULL, st_forceUpg_store);
/**手动拉节点RST,尝试TP 恢复 **/
static DEVICE_ATTR(streset, S_IRUGO | S_IWUSR, NULL, st_manual_rst_store);
/*开关智能唤醒设备节点,上层可通过此节点控制
*echo 1 > st_smtwakeup 打开
*echo 0 > st_smtwakeup 关闭*/
static DEVICE_ATTR(st_smtwakeup, S_IRUGO | S_IWUSR, NULL,
st_smart_wakeup_switch_store);
static DEVICE_ATTR(st_i2caddr_set, S_IRUGO | S_IWUSR, NULL,
st_temporary_set_i2caddr_store);
static struct attribute *st_attributes[] = { &dev_attr_stinform.attr,
&dev_attr_stglove.attr,
&dev_attr_stcases.attr,
&dev_attr_strawtest.attr,
&dev_attr_strwreg.attr,
&dev_attr_stmt.attr,
&dev_attr_stupgrade.attr,
&dev_attr_streset.attr,
&dev_attr_st_smtwakeup.attr,
&dev_attr_st_i2caddr_set.attr,
NULL };
static struct attribute_group st_attribute_group = { .attrs = st_attributes
};
int st_create_sysfs(struct i2c_client *client)
{
int err;
//kobject_creat_and_add
err = sysfs_create_group(&client->dev.kobj, &st_attribute_group);
if (0 != err) {
STX_ERROR("%s() - ERROR: sysfs_create_group() failed.",
__func__);
sysfs_remove_group(&client->dev.kobj, &st_attribute_group);
return -EIO;
} else {
STX_INFO("sysfs_create_group() ok.");
}
return err;
}
int st_remove_sysfs(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &st_attribute_group);
return 0;
}
#ifdef ST_DEVICE_NODE
#define SITRONIX_I2C_TOUCH_DEV_NAME "sitronixDev"
static struct cdev sitronix_cdev;
static struct class *sitronix_class;
static int sitronix_major = 0;
int sitronix_open(struct inode *inode, struct file *filp)
{
STX_INFO("Enter stx OPEN");
stx_gpts.fapp_in = 1;
#ifdef ST_MONITOR_THREAD
sitronix_monitor_stop();
#endif
return 0;
}
EXPORT_SYMBOL(sitronix_open);
int sitronix_release(struct inode *inode, struct file *filp)
{
STX_INFO("Enter stx RELEASE");
stx_gpts.fapp_in = 0;
#ifdef ST_MONITOR_THREAD
sitronix_monitor_start();
#endif
return 0;
}
EXPORT_SYMBOL(sitronix_release);
ssize_t sitronix_write(struct file *file, const char *buf, size_t count,
loff_t *ppos)
{
int ret;
char *tmp;
if (!(stx_gpts.client))
return -EIO;
if (count > 8192)
count = 8192;
tmp = (char *)kmalloc(count, GFP_KERNEL);
if (tmp == NULL)
return -ENOMEM;
if (copy_from_user(tmp, buf, count)) {
kfree(tmp);
return -EFAULT;
}
STX_INFO("writing %zu bytes.", count);
ret = i2c_master_send(stx_gpts.client, tmp, count);
kfree(tmp);
return ret;
}
EXPORT_SYMBOL(sitronix_write);
ssize_t sitronix_read(struct file *file, char *buf, size_t count, loff_t *ppos)
{
char *tmp;
int ret;
if (!(stx_gpts.client))
return -EIO;
if (count > 8192)
count = 8192;
tmp = (char *)kmalloc(count, GFP_KERNEL);
if (tmp == NULL)
return -ENOMEM;
STX_INFO("reading %zu bytes.", count);
ret = i2c_master_recv(stx_gpts.client, tmp, count);
if (ret >= 0)
ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
kfree(tmp);
return ret;
}
EXPORT_SYMBOL(sitronix_read);
long sitronix_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
//int err = 0;
int retval = 0;
//uint8_t temp[4];
if (!(stx_gpts.client))
return -EIO;
return retval;
}
EXPORT_SYMBOL(sitronix_ioctl);
static struct file_operations nc_fops = {
.owner = THIS_MODULE,
.write = sitronix_write,
.read = sitronix_read,
.open = sitronix_open,
.unlocked_ioctl = sitronix_ioctl,
.release = sitronix_release,
};
int st_dev_node_init(void)
{
int result;
int err = 0;
dev_t devno = MKDEV(sitronix_major, 0);
result = alloc_chrdev_region(&devno, 0, 1, SITRONIX_I2C_TOUCH_DEV_NAME);
if (result < 0) {
STX_ERROR("fail to allocate chrdev (%d) ", result);
return result;
}
sitronix_major = MAJOR(devno);
cdev_init(&sitronix_cdev, &nc_fops);
sitronix_cdev.owner = THIS_MODULE;
sitronix_cdev.ops = &nc_fops;
err = cdev_add(&sitronix_cdev, devno, 1);
if (err) {
STX_ERROR("fail to add cdev (%d)", err);
return err;
}
STX_INFO("%s,%d", __FUNCTION__, __LINE__);
sitronix_class = class_create(THIS_MODULE, SITRONIX_I2C_TOUCH_DEV_NAME);
if (IS_ERR(sitronix_class)) {
result = PTR_ERR(sitronix_class);
unregister_chrdev(sitronix_major, SITRONIX_I2C_TOUCH_DEV_NAME);
STX_ERROR("fail to create class (%d)", result);
return result;
}
STX_DEBUG("%s,%d", __FUNCTION__, __LINE__);
device_create(sitronix_class, NULL, MKDEV(sitronix_major, 0), NULL,
SITRONIX_I2C_TOUCH_DEV_NAME);
return 0;
}
void st_dev_node_exit(void)
{
dev_t dev_id = MKDEV(sitronix_major, 0);
cdev_del(&sitronix_cdev);
device_destroy(sitronix_class, dev_id); //delete device node under /dev
class_destroy(sitronix_class); //delete class created by us
unregister_chrdev_region(dev_id, 1);
}
#endif