12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229 |
- /*
- *
- * FocalTech TouchScreen driver.
- *
- * Copyright (c) 2012-2019, Focaltech Ltd. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
- /*****************************************************************************
- *
- * File Name: Focaltech_ex_fun.c
- *
- * Author: Focaltech Driver Team
- *
- * Created: 2016-08-08
- *
- * Abstract:
- *
- * Reference:
- *
- *****************************************************************************/
- /*****************************************************************************
- * 1.Included header files
- *****************************************************************************/
- #include <linux/uaccess.h>
- #include "focaltech_core.h"
- /*****************************************************************************
- * Private constant and macro definitions using #define
- *****************************************************************************/
- #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 PROC_SET_SLAVE_ADDR 10
- #define PROC_HW_RESET 11
- #define PROC_READ_STATUS 12
- #define PROC_SET_BOOT_MODE 13
- #define PROC_ENTER_TEST_ENVIRONMENT 14
- #define PROC_NAME "ftxxxx-debug"
- #define PROC_BUF_SIZE 256
- /*****************************************************************************
- * Private enumerations, structures and unions using typedef
- *****************************************************************************/
- enum {
- RWREG_OP_READ = 0,
- RWREG_OP_WRITE = 1,
- };
- /*****************************************************************************
- * Static variables
- *****************************************************************************/
- static struct rwreg_operation_t {
- int type; /* 0: read, 1: write */
- int reg; /* register */
- int len; /* read/write length */
- int val; /* length = 1; read: return value, write: op return */
- int res; /* 0: success, otherwise: fail */
- char *opbuf; /* length >= 1, read return value, write: op return */
- } rw_op;
- /*****************************************************************************
- * Global variable or extern global variabls/functions
- *****************************************************************************/
- /*****************************************************************************
- * Static function prototypes
- *****************************************************************************/
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- static ssize_t fts_debug_write(
- struct file *filp, const char __user *buff, size_t count, loff_t *ppos)
- {
- u8 *writebuf = NULL;
- u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
- int buflen = count;
- int writelen = 0;
- int ret = 0;
- char tmp[PROC_BUF_SIZE];
- struct fts_ts_data *ts_data = fts_data;
- struct ftxxxx_proc *proc = &ts_data->proc;
- if ((buflen <= 1) || (buflen > PAGE_SIZE)) {
- FTS_ERROR("apk proc wirte count(%d>%d) fail", buflen, (int)PAGE_SIZE);
- return -EINVAL;
- }
- if (buflen > PROC_BUF_SIZE) {
- writebuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
- if (NULL == writebuf) {
- FTS_ERROR("apk proc wirte buf zalloc fail");
- return -ENOMEM;
- }
- } else {
- writebuf = tmpbuf;
- }
- if (copy_from_user(writebuf, buff, buflen)) {
- FTS_ERROR("[APK]: copy from user error!!");
- ret = -EFAULT;
- goto proc_write_err;
- }
- proc->opmode = writebuf[0];
- switch (proc->opmode) {
- case PROC_SET_TEST_FLAG:
- FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x", writebuf[1]);
- if (writebuf[1] == 0) {
- #if FTS_ESDCHECK_EN
- fts_esdcheck_switch(ENABLE);
- #endif
- } else {
- #if FTS_ESDCHECK_EN
- fts_esdcheck_switch(DISABLE);
- #endif
- }
- break;
- case PROC_READ_REGISTER:
- proc->cmd[0] = writebuf[1];
- break;
- case PROC_WRITE_REGISTER:
- ret = fts_write_reg(writebuf[1], writebuf[2]);
- if (ret < 0) {
- FTS_ERROR("PROC_WRITE_REGISTER write error");
- goto proc_write_err;
- }
- break;
- case PROC_READ_DATA:
- writelen = buflen - 1;
- if (writelen >= FTX_MAX_COMMMAND_LENGTH) {
- FTS_ERROR("cmd(PROC_READ_DATA) len(%d) fail", writelen);
- goto proc_write_err;
- }
- memcpy(proc->cmd, writebuf + 1, writelen);
- proc->cmd_len = writelen;
- ret = fts_write(writebuf + 1, writelen);
- if (ret < 0) {
- FTS_ERROR("PROC_READ_DATA write error");
- goto proc_write_err;
- }
- break;
- case PROC_WRITE_DATA:
- writelen = buflen - 1;
- ret = fts_write(writebuf + 1, writelen);
- if (ret < 0) {
- FTS_ERROR("PROC_WRITE_DATA write error");
- goto proc_write_err;
- }
- break;
- case PROC_SET_SLAVE_ADDR:
- break;
- case PROC_HW_RESET:
- snprintf(tmp, PROC_BUF_SIZE, "%s", writebuf + 1);
- tmp[buflen - 1] = '\0';
- if (strncmp(tmp, "focal_driver", 12) == 0) {
- FTS_INFO("APK execute HW Reset");
- fts_reset_proc(0);
- }
- break;
- case PROC_SET_BOOT_MODE:
- FTS_DEBUG("[APK]: PROC_SET_BOOT_MODE = %x", writebuf[1]);
- if (0 == writebuf[1]) {
- ts_data->fw_is_running = true;
- } else {
- ts_data->fw_is_running = false;
- }
- break;
- case PROC_ENTER_TEST_ENVIRONMENT:
- FTS_DEBUG("[APK]: PROC_ENTER_TEST_ENVIRONMENT = %x", writebuf[1]);
- if (0 == writebuf[1]) {
- fts_enter_test_environment(0);
- } else {
- fts_enter_test_environment(1);
- }
- break;
- default:
- break;
- }
- ret = buflen;
- proc_write_err:
- if ((buflen > PROC_BUF_SIZE) && writebuf) {
- kfree(writebuf);
- writebuf = NULL;
- }
- return ret;
- }
- 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 buflen = count;
- u8 *readbuf = NULL;
- u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
- struct fts_ts_data *ts_data = fts_data;
- struct ftxxxx_proc *proc = &ts_data->proc;
- if ((buflen <= 0) || (buflen > PAGE_SIZE)) {
- FTS_ERROR("apk proc read count(%d>%d) fail", buflen, (int)PAGE_SIZE);
- return -EINVAL;
- }
- if (buflen > PROC_BUF_SIZE) {
- readbuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
- if (NULL == readbuf) {
- FTS_ERROR("apk proc wirte buf zalloc fail");
- return -ENOMEM;
- }
- } else {
- readbuf = tmpbuf;
- }
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(1);
- #endif
- switch (proc->opmode) {
- case PROC_READ_REGISTER:
- num_read_chars = 1;
- ret = fts_read_reg(proc->cmd[0], &readbuf[0]);
- if (ret < 0) {
- FTS_ERROR("PROC_READ_REGISTER read error");
- goto proc_read_err;
- }
- break;
- case PROC_WRITE_REGISTER:
- break;
- case PROC_READ_DATA:
- num_read_chars = buflen;
- ret = fts_read(NULL, 0, readbuf, num_read_chars);
- if (ret < 0) {
- FTS_ERROR("PROC_READ_DATA read error");
- goto proc_read_err;
- }
- break;
- case PROC_WRITE_DATA:
- break;
- default:
- break;
- }
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(0);
- #endif
- if (copy_to_user(buff, readbuf, num_read_chars)) {
- FTS_ERROR("copy to user error");
- ret = -EFAULT;
- goto proc_read_err;
- }
- ret = num_read_chars;
- proc_read_err:
- if ((buflen > PROC_BUF_SIZE) && readbuf) {
- kfree(readbuf);
- readbuf = NULL;
- }
- return ret;
- }
- static const struct proc_ops fts_proc_fops = {
- .proc_read = fts_debug_read,
- .proc_write = fts_debug_write,
- };
- #else
- static int fts_debug_write(struct file *filp,
- const char __user *buff, unsigned long len, void *data)
- {
- u8 *writebuf = NULL;
- u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
- int buflen = count;
- int writelen = 0;
- int ret = 0;
- char tmp[PROC_BUF_SIZE];
- struct fts_ts_data *ts_data = fts_data;
- struct ftxxxx_proc *proc = &ts_data->proc;
- if ((buflen <= 1) || (buflen > PAGE_SIZE)) {
- FTS_ERROR("apk proc wirte count(%d>%d) fail", buflen, (int)PAGE_SIZE);
- return -EINVAL;
- }
- if (buflen > PROC_BUF_SIZE) {
- writebuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
- if (NULL == writebuf) {
- FTS_ERROR("apk proc wirte buf zalloc fail");
- return -ENOMEM;
- }
- } else {
- writebuf = tmpbuf;
- }
- if (copy_from_user(writebuf, buff, buflen)) {
- FTS_ERROR("[APK]: copy from user error!!");
- ret = -EFAULT;
- goto proc_write_err;
- }
- proc->opmode = writebuf[0];
- switch (proc->opmode) {
- case PROC_SET_TEST_FLAG:
- FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x", writebuf[1]);
- if (writebuf[1] == 0) {
- #if FTS_ESDCHECK_EN
- fts_esdcheck_switch(ENABLE);
- #endif
- } else {
- #if FTS_ESDCHECK_EN
- fts_esdcheck_switch(DISABLE);
- #endif
- }
- break;
- case PROC_READ_REGISTER:
- proc->cmd[0] = writebuf[1];
- break;
- case PROC_WRITE_REGISTER:
- ret = fts_write_reg(writebuf[1], writebuf[2]);
- if (ret < 0) {
- FTS_ERROR("PROC_WRITE_REGISTER write error");
- goto proc_write_err;
- }
- break;
- case PROC_READ_DATA:
- writelen = buflen - 1;
- if (writelen >= FTX_MAX_COMMMAND_LENGTH) {
- FTS_ERROR("cmd(PROC_READ_DATA) length(%d) fail", writelen);
- goto proc_write_err;
- }
- memcpy(proc->cmd, writebuf + 1, writelen);
- proc->cmd_len = writelen;
- ret = fts_write(writebuf + 1, writelen);
- if (ret < 0) {
- FTS_ERROR("PROC_READ_DATA write error");
- goto proc_write_err;
- }
- break;
- case PROC_WRITE_DATA:
- writelen = buflen - 1;
- ret = fts_write(writebuf + 1, writelen);
- if (ret < 0) {
- FTS_ERROR("PROC_WRITE_DATA write error");
- goto proc_write_err;
- }
- break;
- case PROC_SET_SLAVE_ADDR:
- break;
- case PROC_HW_RESET:
- snprintf(tmp, PROC_BUF_SIZE, "%s", writebuf + 1);
- tmp[buflen - 1] = '\0';
- if (strncmp(tmp, "focal_driver", 12) == 0) {
- FTS_INFO("APK execute HW Reset");
- fts_reset_proc(0);
- }
- break;
- case PROC_SET_BOOT_MODE:
- FTS_DEBUG("[APK]: PROC_SET_BOOT_MODE = %x", writebuf[1]);
- if (0 == writebuf[1]) {
- ts_data->fw_is_running = true;
- } else {
- ts_data->fw_is_running = false;
- }
- break;
- case PROC_ENTER_TEST_ENVIRONMENT:
- FTS_DEBUG("[APK]: PROC_ENTER_TEST_ENVIRONMENT = %x", writebuf[1]);
- if (0 == writebuf[1]) {
- fts_enter_test_environment(0);
- } else {
- fts_enter_test_environment(1);
- }
- break;
- default:
- break;
- }
- ret = buflen;
- proc_write_err:
- if ((buflen > PROC_BUF_SIZE) && writebuf) {
- kfree(writebuf);
- writebuf = NULL;
- }
- return ret;
- }
- static int fts_debug_read(
- char *page, char **start, off_t off, int count, int *eof, void *data )
- {
- int ret = 0;
- int num_read_chars = 0;
- int buflen = count;
- u8 *readbuf = NULL;
- u8 tmpbuf[PROC_BUF_SIZE] = { 0 };
- struct fts_ts_data *ts_data = fts_data;
- struct ftxxxx_proc *proc = &ts_data->proc;
- if ((buflen <= 0) || (buflen > PAGE_SIZE)) {
- FTS_ERROR("apk proc read count(%d>%d) fail", buflen, (int)PAGE_SIZE);
- return -EINVAL;
- }
- if (buflen > PROC_BUF_SIZE) {
- readbuf = (u8 *)kzalloc(buflen * sizeof(u8), GFP_KERNEL);
- if (NULL == readbuf) {
- FTS_ERROR("apk proc wirte buf zalloc fail");
- return -ENOMEM;
- }
- } else {
- readbuf = tmpbuf;
- }
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(1);
- #endif
- switch (proc->opmode) {
- case PROC_READ_REGISTER:
- num_read_chars = 1;
- ret = fts_read_reg(proc->cmd[0], &readbuf[0]);
- if (ret < 0) {
- FTS_ERROR("PROC_READ_REGISTER read error");
- goto proc_read_err;
- }
- break;
- case PROC_WRITE_REGISTER:
- break;
- case PROC_READ_DATA:
- num_read_chars = buflen;
- ret = fts_read(NULL, 0, readbuf, num_read_chars);
- if (ret < 0) {
- FTS_ERROR("PROC_READ_DATA read error");
- goto proc_read_err;
- }
- break;
- case PROC_WRITE_DATA:
- break;
- default:
- break;
- }
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(0);
- #endif
- if (copy_to_user(buff, readbuf, num_read_chars)) {
- FTS_ERROR("copy to user error");
- ret = -EFAULT;
- goto proc_read_err;
- }
- ret = num_read_chars;
- proc_read_err:
- if ((buflen > PROC_BUF_SIZE) && readbuf) {
- kfree(readbuf);
- readbuf = NULL;
- }
- return ret;
- }
- #endif
- int fts_create_apk_debug_channel(struct fts_ts_data *ts_data)
- {
- struct ftxxxx_proc *proc = &ts_data->proc;
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- proc->proc_entry = proc_create(PROC_NAME, 0777, NULL, &fts_proc_fops);
- if (NULL == proc->proc_entry) {
- FTS_ERROR("create proc entry fail");
- return -ENOMEM;
- }
- #else
- proc->proc_entry = create_proc_entry(PROC_NAME, 0777, NULL);
- if (NULL == proc->proc_entry) {
- FTS_ERROR("create proc entry fail");
- return -ENOMEM;
- }
- proc->proc_entry->write_proc = fts_debug_write;
- proc->proc_entry->read_proc = fts_debug_read;
- #endif
- FTS_INFO("Create proc entry success!");
- return 0;
- }
- void fts_release_apk_debug_channel(struct fts_ts_data *ts_data)
- {
- struct ftxxxx_proc *proc = &ts_data->proc;
- if (proc->proc_entry) {
- #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
- proc_remove(proc->proc_entry);
- #else
- remove_proc_entry(PROC_NAME, NULL);
- #endif
- }
- }
- /************************************************************************
- * sysfs interface
- ***********************************************************************/
- /* fts_hw_reset interface */
- static ssize_t fts_hw_reset_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct input_dev *input_dev = fts_data->input_dev;
- ssize_t count = 0;
- mutex_lock(&input_dev->mutex);
- fts_reset_proc(0);
- count = snprintf(buf, PAGE_SIZE, "hw reset executed\n");
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- static ssize_t fts_hw_reset_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- return -EPERM;
- }
- /* fts_irq interface */
- static ssize_t fts_irq_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- ssize_t count = 0;
- struct irq_desc *desc = irq_to_desc(fts_data->irq);
- count = snprintf(buf, PAGE_SIZE, "irq_depth:%d\n", desc->depth);
- return count;
- }
- static ssize_t fts_irq_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct input_dev *input_dev = fts_data->input_dev;
- mutex_lock(&input_dev->mutex);
- if (FTS_SYSFS_ECHO_ON(buf)) {
- FTS_INFO("enable irq");
- fts_irq_enable();
- } else if (FTS_SYSFS_ECHO_OFF(buf)) {
- FTS_INFO("disable irq");
- fts_irq_disable();
- }
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- /* fts_boot_mode interface */
- static ssize_t fts_bootmode_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct input_dev *input_dev = fts_data->input_dev;
- FTS_FUNC_ENTER();
- mutex_lock(&input_dev->mutex);
- if (FTS_SYSFS_ECHO_ON(buf)) {
- FTS_INFO("[EX-FUN]set to boot mode");
- fts_data->fw_is_running = false;
- } else if (FTS_SYSFS_ECHO_OFF(buf)) {
- FTS_INFO("[EX-FUN]set to fw mode");
- fts_data->fw_is_running = true;
- }
- mutex_unlock(&input_dev->mutex);
- FTS_FUNC_EXIT();
- return count;
- }
- static ssize_t fts_bootmode_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- ssize_t count = 0;
- struct input_dev *input_dev = fts_data->input_dev;
- FTS_FUNC_ENTER();
- mutex_lock(&input_dev->mutex);
- if (true == fts_data->fw_is_running) {
- count = snprintf(buf, PAGE_SIZE, "tp is in fw mode\n");
- } else {
- count = snprintf(buf, PAGE_SIZE, "tp is in boot mode\n");
- }
- mutex_unlock(&input_dev->mutex);
- FTS_FUNC_EXIT();
- return count;
- }
- /* fts_tpfwver interface */
- static ssize_t fts_fw_version_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- struct fts_ts_data *ts_data = fts_data;
- struct input_dev *input_dev = ts_data->input_dev;
- ssize_t num_read_chars = 0;
- u8 fwver = 0;
- mutex_lock(&input_dev->mutex);
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(1);
- #endif
- fts_read_reg(FTS_REG_FW_VER, &fwver);
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(0);
- #endif
- if ((fwver == 0xFF) || (fwver == 0x00))
- 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(&input_dev->mutex);
- return num_read_chars;
- }
- static ssize_t fts_fw_version_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- return -EPERM;
- }
- /* fts_rw_reg */
- static ssize_t fts_tprwreg_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- int count;
- int i;
- struct input_dev *input_dev = fts_data->input_dev;
- mutex_lock(&input_dev->mutex);
- if (rw_op.len < 0) {
- count = snprintf(buf, PAGE_SIZE, "Invalid cmd line\n");
- } else if (rw_op.len == 1) {
- if (RWREG_OP_READ == rw_op.type) {
- if (rw_op.res == 0) {
- count = snprintf(buf, PAGE_SIZE, "Read %02X: %02X\n", rw_op.reg, rw_op.val);
- } else {
- count = snprintf(buf, PAGE_SIZE, "Read %02X failed, ret: %d\n", rw_op.reg, rw_op.res);
- }
- } else {
- if (rw_op.res == 0) {
- count = snprintf(buf, PAGE_SIZE, "Write %02X, %02X success\n", rw_op.reg, rw_op.val);
- } else {
- count = snprintf(buf, PAGE_SIZE, "Write %02X failed, ret: %d\n", rw_op.reg, rw_op.res);
- }
- }
- } else {
- if (RWREG_OP_READ == rw_op.type) {
- count = snprintf(buf, PAGE_SIZE, "Read Reg: [%02X]-[%02X]\n", rw_op.reg, rw_op.reg + rw_op.len);
- count += snprintf(buf + count, PAGE_SIZE, "Result: ");
- if (rw_op.res) {
- count += snprintf(buf + count, PAGE_SIZE, "failed, ret: %d\n", rw_op.res);
- } else {
- if (rw_op.opbuf) {
- for (i = 0; i < rw_op.len; i++) {
- count += snprintf(buf + count, PAGE_SIZE, "%02X ", rw_op.opbuf[i]);
- }
- count += snprintf(buf + count, PAGE_SIZE, "\n");
- }
- }
- } else {
- count = snprintf(buf, PAGE_SIZE, "Write Reg: [%02X]-[%02X]\n", rw_op.reg, rw_op.reg + rw_op.len - 1);
- count += snprintf(buf + count, PAGE_SIZE, "Write Data: ");
- if (rw_op.opbuf) {
- for (i = 1; i < rw_op.len; i++) {
- count += snprintf(buf + count, PAGE_SIZE, "%02X ", rw_op.opbuf[i]);
- }
- count += snprintf(buf + count, PAGE_SIZE, "\n");
- }
- if (rw_op.res) {
- count += snprintf(buf + count, PAGE_SIZE, "Result: failed, ret: %d\n", rw_op.res);
- } else {
- count += snprintf(buf + count, PAGE_SIZE, "Result: success\n");
- }
- }
- /*if (rw_op.opbuf) {
- * kfree(rw_op.opbuf);
- * rw_op.opbuf = NULL;
- *}
- */
- }
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- static int shex_to_int(const char *hex_buf, int size)
- {
- int i;
- int base = 1;
- int value = 0;
- char single;
- for (i = size - 1; i >= 0; i--) {
- single = hex_buf[i];
- if ((single >= '0') && (single <= '9')) {
- value += (single - '0') * base;
- } else if ((single >= 'a') && (single <= 'z')) {
- value += (single - 'a' + 10) * base;
- } else if ((single >= 'A') && (single <= 'Z')) {
- value += (single - 'A' + 10) * base;
- } else {
- return -EINVAL;
- }
- base *= 16;
- }
- return value;
- }
- static u8 shex_to_u8(const char *hex_buf, int size)
- {
- return (u8)shex_to_int(hex_buf, size);
- }
- /*
- * Format buf:
- * [0]: '0' write, '1' read(reserved)
- * [1-2]: addr, hex
- * [3-4]: length, hex
- * [5-6]...[n-(n+1)]: data, hex
- */
- static int fts_parse_buf(const char *buf, size_t cmd_len)
- {
- int length;
- int i;
- char *tmpbuf;
- rw_op.reg = shex_to_u8(buf + 1, 2);
- length = shex_to_int(buf + 3, 2);
- if (buf[0] == '1') {
- rw_op.len = length;
- rw_op.type = RWREG_OP_READ;
- FTS_DEBUG("read %02X, %d bytes", rw_op.reg, rw_op.len);
- } else {
- if (cmd_len < (length * 2 + 5)) {
- pr_err("data invalided!\n");
- return -EINVAL;
- }
- FTS_DEBUG("write %02X, %d bytes", rw_op.reg, length);
- /* first byte is the register addr */
- rw_op.type = RWREG_OP_WRITE;
- rw_op.len = length + 1;
- }
- if (rw_op.len > 0) {
- tmpbuf = (char *)kzalloc(rw_op.len, GFP_KERNEL);
- if (!tmpbuf) {
- FTS_ERROR("allocate memory failed!\n");
- return -ENOMEM;
- }
- if (RWREG_OP_WRITE == rw_op.type) {
- tmpbuf[0] = rw_op.reg & 0xFF;
- FTS_DEBUG("write buffer: ");
- for (i = 1; i < rw_op.len; i++) {
- tmpbuf[i] = shex_to_u8(buf + 5 + i * 2 - 2, 2);
- FTS_DEBUG("buf[%d]: %02X", i, tmpbuf[i] & 0xFF);
- }
- }
- rw_op.opbuf = tmpbuf;
- }
- return rw_op.len;
- }
- static ssize_t fts_tprwreg_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct input_dev *input_dev = fts_data->input_dev;
- ssize_t cmd_length = 0;
- mutex_lock(&input_dev->mutex);
- cmd_length = count - 1;
- if (rw_op.opbuf) {
- kfree(rw_op.opbuf);
- rw_op.opbuf = NULL;
- }
- FTS_DEBUG("cmd len: %d, buf: %s", (int)cmd_length, buf);
- /* compatible old ops */
- if (2 == cmd_length) {
- rw_op.type = RWREG_OP_READ;
- rw_op.len = 1;
- rw_op.reg = shex_to_int(buf, 2);
- } else if (4 == cmd_length) {
- rw_op.type = RWREG_OP_WRITE;
- rw_op.len = 1;
- rw_op.reg = shex_to_int(buf, 2);
- rw_op.val = shex_to_int(buf + 2, 2);
- } else if (cmd_length < 5) {
- FTS_ERROR("Invalid cmd buffer");
- mutex_unlock(&input_dev->mutex);
- return -EINVAL;
- } else {
- rw_op.len = fts_parse_buf(buf, cmd_length);
- }
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(1);
- #endif
- if (rw_op.len < 0) {
- FTS_ERROR("cmd buffer error!");
- goto exit;
- }
- if (RWREG_OP_READ == rw_op.type) {
- if (rw_op.len == 1) {
- u8 reg, val;
- reg = rw_op.reg & 0xFF;
- rw_op.res = fts_read_reg(reg, &val);
- rw_op.val = val;
- } else {
- char reg;
- reg = rw_op.reg & 0xFF;
- rw_op.res = fts_read(®, 1, rw_op.opbuf, rw_op.len);
- }
- if (rw_op.res < 0) {
- FTS_ERROR("Could not read 0x%02x", rw_op.reg);
- } else {
- FTS_INFO("read 0x%02x, %d bytes successful", rw_op.reg, rw_op.len);
- rw_op.res = 0;
- }
- } else {
- if (rw_op.len == 1) {
- u8 reg, val;
- reg = rw_op.reg & 0xFF;
- val = rw_op.val & 0xFF;
- rw_op.res = fts_write_reg(reg, val);
- } else {
- rw_op.res = fts_write(rw_op.opbuf, rw_op.len);
- }
- if (rw_op.res < 0) {
- FTS_ERROR("Could not write 0x%02x", rw_op.reg);
- } else {
- FTS_INFO("Write 0x%02x, %d bytes successful", rw_op.val, rw_op.len);
- rw_op.res = 0;
- }
- }
- exit:
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(0);
- #endif
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- /* fts_driver_info interface */
- static ssize_t fts_driverinfo_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- int count = 0;
- struct fts_ts_data *ts_data = fts_data;
- struct fts_ts_platform_data *pdata = ts_data->pdata;
- struct input_dev *input_dev = ts_data->input_dev;
- mutex_lock(&input_dev->mutex);
- count += scnprintf(buf + count, PAGE_SIZE, "Driver Ver:%s\n", FTS_DRIVER_VERSION);
- count += snprintf(buf + count, PAGE_SIZE, "Resolution:(%d,%d)~(%d,%d)\n",
- pdata->x_min, pdata->y_min, pdata->x_max, pdata->y_max);
- count += snprintf(buf + count, PAGE_SIZE, "Max Touchs:%d\n", pdata->max_touch_number);
- count += scnprintf(buf + count, PAGE_SIZE, "reset gpio:%d,int gpio:%d,irq:%d\n",
- pdata->reset_gpio, pdata->irq_gpio, ts_data->irq);
- count += scnprintf(buf + count, PAGE_SIZE, "IC ID:0x%02x%02x\n",
- ts_data->ic_info.ids.chip_idh, ts_data->ic_info.ids.chip_idl);
- if (ts_data->bus_type == BUS_TYPE_I2C)
- count += scnprintf(buf + count, PAGE_SIZE, "BUS:%s,addr:0x%x\n",
- "I2C", ts_data->client->addr);
- else
- count += scnprintf(buf + count, PAGE_SIZE,
- "BUS:%s,mode:%d,max_freq:%d\n", "SPI",
- ts_data->spi->mode, ts_data->spi->max_speed_hz);
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- static ssize_t fts_driverinfo_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- return -EPERM;
- }
- /* fts_dump_reg interface */
- static ssize_t fts_dumpreg_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- int count = 0;
- u8 val = 0;
- struct input_dev *input_dev = fts_data->input_dev;
- mutex_lock(&input_dev->mutex);
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(1);
- #endif
- fts_read_reg(FTS_REG_POWER_MODE, &val);
- count += snprintf(buf + count, PAGE_SIZE, "Power Mode:0x%02x\n", val);
- fts_read_reg(FTS_REG_FW_VER, &val);
- count += snprintf(buf + count, PAGE_SIZE, "FW Ver:0x%02x\n", val);
- fts_read_reg(FTS_REG_LIC_VER, &val);
- count += snprintf(buf + count, PAGE_SIZE, "LCD Initcode Ver:0x%02x\n", val);
- fts_read_reg(FTS_REG_IDE_PARA_VER_ID, &val);
- count += snprintf(buf + count, PAGE_SIZE, "Param Ver:0x%02x\n", val);
- fts_read_reg(FTS_REG_IDE_PARA_STATUS, &val);
- count += snprintf(buf + count, PAGE_SIZE, "Param status:0x%02x\n", val);
- fts_read_reg(FTS_REG_VENDOR_ID, &val);
- count += snprintf(buf + count, PAGE_SIZE, "Vendor ID:0x%02x\n", val);
- fts_read_reg(FTS_REG_LCD_BUSY_NUM, &val);
- count += snprintf(buf + count, PAGE_SIZE, "LCD Busy Number:0x%02x\n", val);
- fts_read_reg(FTS_REG_GESTURE_EN, &val);
- count += snprintf(buf + count, PAGE_SIZE, "Gesture Mode:0x%02x\n", val);
- fts_read_reg(FTS_REG_CHARGER_MODE_EN, &val);
- count += snprintf(buf + count, PAGE_SIZE, "charge stat:0x%02x\n", val);
- fts_read_reg(FTS_REG_INT_CNT, &val);
- count += snprintf(buf + count, PAGE_SIZE, "INT count:0x%02x\n", val);
- fts_read_reg(FTS_REG_FLOW_WORK_CNT, &val);
- count += snprintf(buf + count, PAGE_SIZE, "ESD count:0x%02x\n", val);
- #if FTS_ESDCHECK_EN
- fts_esdcheck_proc_busy(0);
- #endif
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- static ssize_t fts_dumpreg_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- return -EPERM;
- }
- /* fts_dump_reg interface */
- static ssize_t fts_tpbuf_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- int count = 0;
- int i = 0;
- struct input_dev *input_dev = fts_data->input_dev;
- mutex_lock(&input_dev->mutex);
- count += snprintf(buf + count, PAGE_SIZE, "touch point buffer:\n");
- for (i = 0; i < fts_data->pnt_buf_size; i++) {
- count += snprintf(buf + count, PAGE_SIZE, "%02x ",
- fts_data->point_buf[i]);
- }
- count += snprintf(buf + count, PAGE_SIZE, "\n");
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- static ssize_t fts_tpbuf_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- return -EPERM;
- }
- /* fts_log_level interface */
- static ssize_t fts_log_level_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- int count = 0;
- struct input_dev *input_dev = fts_data->input_dev;
- mutex_lock(&input_dev->mutex);
- count += snprintf(buf + count, PAGE_SIZE, "log level:%d\n",
- fts_data->log_level);
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- static ssize_t fts_log_level_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- int value = 0;
- struct input_dev *input_dev = fts_data->input_dev;
- FTS_FUNC_ENTER();
- mutex_lock(&input_dev->mutex);
- sscanf(buf, "%d", &value);
- FTS_DEBUG("log level:%d->%d", fts_data->log_level, value);
- fts_data->log_level = value;
- mutex_unlock(&input_dev->mutex);
- FTS_FUNC_EXIT();
- return count;
- }
- #ifdef CONFIG_FTS_TRUSTED_TOUCH
- static ssize_t trusted_touch_enable_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct fts_ts_data *info = fts_data;
- return scnprintf(buf, PAGE_SIZE, "%d",
- atomic_read(&info->trusted_touch_enabled));
- }
- static ssize_t trusted_touch_enable_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct fts_ts_data *info = fts_data;
- unsigned long value;
- int err = 0;
- if (count > 2)
- return -EINVAL;
- err = kstrtoul(buf, 10, &value);
- if (err != 0)
- return err;
- if (!atomic_read(&info->trusted_touch_initialized))
- return -EIO;
- #ifdef CONFIG_ARCH_QTI_VM
- err = fts_ts_handle_trusted_touch_tvm(info, value);
- if (err) {
- pr_err("Failed to handle trusted touch in tvm\n");
- return -EINVAL;
- }
- #else
- err = fts_ts_handle_trusted_touch_pvm(info, value);
- if (err) {
- pr_err("Failed to handle trusted touch in pvm\n");
- return -EINVAL;
- }
- #endif
- err = count;
- return err;
- }
- static ssize_t trusted_touch_event_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct fts_ts_data *info = fts_data;
- 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 fts_ts_data *info = fts_data;
- unsigned long value;
- int err = 0;
- 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;
- }
- static ssize_t trusted_touch_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct fts_ts_data *info = fts_data;
- return scnprintf(buf, PAGE_SIZE, "%s", info->vm_info->trusted_touch_type);
- }
- #endif
- /* get the fw version example:cat fw_version */
- static DEVICE_ATTR_RW(fts_fw_version);
- /* read and write register(s)
- * All data type is **HEX**
- * Single Byte:
- * read: echo 88 > rw_reg ---read register 0x88
- * write: echo 8807 > rw_reg ---write 0x07 into register 0x88
- * Multi-bytes:
- * [0:rw-flag][1-2: reg addr, hex][3-4: length, hex][5-6...n-n+1: write data, hex]
- * rw-flag: 0, write; 1, read
- * read: echo 10005 > rw_reg ---read reg 0x00-0x05
- * write: echo 000050102030405 > rw_reg ---write reg 0x00-0x05 as 01,02,03,04,05
- * Get result:
- * cat rw_reg
- */
- static DEVICE_ATTR(fts_rw_reg, S_IRUGO | S_IWUSR, fts_tprwreg_show, fts_tprwreg_store);
- static DEVICE_ATTR(fts_driver_info, S_IRUGO | S_IWUSR, fts_driverinfo_show, fts_driverinfo_store);
- static DEVICE_ATTR(fts_dump_reg, S_IRUGO | S_IWUSR, fts_dumpreg_show, fts_dumpreg_store);
- static DEVICE_ATTR(fts_hw_reset, S_IRUGO | S_IWUSR, fts_hw_reset_show, fts_hw_reset_store);
- static DEVICE_ATTR(fts_irq, S_IRUGO | S_IWUSR, fts_irq_show, fts_irq_store);
- static DEVICE_ATTR(fts_boot_mode, S_IRUGO | S_IWUSR, fts_bootmode_show, fts_bootmode_store);
- static DEVICE_ATTR(fts_touch_point, S_IRUGO | S_IWUSR, fts_tpbuf_show, fts_tpbuf_store);
- 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);
- static DEVICE_ATTR_RO(trusted_touch_type);
- #endif
- /* add your attr in here*/
- static struct attribute *fts_attributes[] = {
- &dev_attr_fts_fw_version.attr,
- &dev_attr_fts_rw_reg.attr,
- &dev_attr_fts_dump_reg.attr,
- &dev_attr_fts_driver_info.attr,
- &dev_attr_fts_hw_reset.attr,
- &dev_attr_fts_irq.attr,
- &dev_attr_fts_boot_mode.attr,
- &dev_attr_fts_touch_point.attr,
- &dev_attr_fts_log_level.attr,
- #ifdef CONFIG_FTS_TRUSTED_TOUCH
- &dev_attr_trusted_touch_enable.attr,
- &dev_attr_trusted_touch_event.attr,
- &dev_attr_trusted_touch_type.attr,
- #endif
- NULL
- };
- static struct attribute_group fts_attribute_group = {
- .attrs = fts_attributes
- };
- int fts_create_sysfs(struct fts_ts_data *ts_data)
- {
- int ret = 0;
- ret = sysfs_create_group(&ts_data->dev->kobj, &fts_attribute_group);
- if (ret) {
- FTS_ERROR("[EX]: sysfs_create_group() failed!!");
- sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group);
- return -ENOMEM;
- } else {
- FTS_INFO("[EX]: sysfs_create_group() succeeded!!");
- }
- return ret;
- }
- int fts_remove_sysfs(struct fts_ts_data *ts_data)
- {
- sysfs_remove_group(&ts_data->dev->kobj, &fts_attribute_group);
- return 0;
- }
|