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

572 lines
13 KiB
C
Raw Normal View History

2024-05-07 10:09:20 +00:00
#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