input: touchpanel: Add ST Touchscreen version 4.1.0 driver

This is the reference driver source code for ST
Touchscreen of version 4.1.0. It is used for QVR8998
touchscreen.

Signed-off-by: chenx <chenxiang0527@thundersoft.com>
Git-commit: 2cd09314337d614e69d0ebd99afb71d99d31b69a
Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-3.10
CRs-Fixed: 1106217
Change-Id: I6674245402c0a5d6cca6bf82a9f8b1bf4f4f4ef3
Signed-off-by: Jin Fu <jinf@codeaurora.org>
This commit is contained in:
chenx 2017-01-11 23:31:30 +08:00 committed by Mohan Pallaka
parent 1252d8e66a
commit e8a48fda8f
34 changed files with 11279 additions and 0 deletions

View File

@ -0,0 +1,54 @@
STMicroelectronics touch controller
The STMicroelectronics controller is connected to host processor
via i2c. The controller generates interrupts when the
user touches the panel. The host controller is expected
to read the touch coordinates over i2c and pass the coordinates
to the rest of the system.
Required properties:
- compatible : should be "st,fts".
- reg : i2c slave address of the device.
- interrupt-parent : parent of interrupt.
- interrupts : touch sample interrupt to indicate presense or release
of fingers on the panel.
- vdd-supply : Power supply needed to power up the device.
- vcc-supply : Power source required to power up i2c bus.
- st,irq-gpio : irq gpio which is to provide interrupts to host,
same as "interrupts" node. It will also
contain active low or active high information.
- st,reset-gpio : reset gpio to control the reset of chip.
- pinctrl-names : This should be defined if a target uses pinctrl framework.
See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
Specify the names of the configs that pinctrl can install in driver.
Following are the pinctrl configs that can be installed:
"pmx_ts_active" : Active configuration of pins, this should specify active
config defined in pin groups of interrupt and reset gpio.
"pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep
config defined in pin groups of interrupt and reset gpio.
"pmx_ts_release" : Release configuration of pins, this should specify
release config defined in pin groups of interrupt and reset gpio.
- st,regulator_avdd : name of Power supply needed to power up the device.
- st,regulator_dvdd : name of Power source required to power up i2c bus.
Optional properties:
Example:
i2c@78b9000 { /* BLSP1 QUP5 */
st_fts@49 {
compatible = "st,fts";
reg = <0x49>;
interrupt-parent = <&msm_gpio>;
interrupts = <13 0x2008>;
vdd-supply = <&pm8916_l17>;
vcc-supply = <&pm8916_l6>;
pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
pinctrl-0 = <&ts_int_active &ts_reset_active>;
pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
st,irq-gpio = <&msm_gpio 13 0x00000001>;
st,reset-gpio = <&msm_gpio 12 0x0>;
st,regulator_dvdd = "vdd";
st,regulator_avdd = "avdd";
};
};

View File

@ -1246,4 +1246,14 @@ config TOUCHSCREEN_ROHM_BU21023
To compile this driver as a module, choose M here: the
module will be called bu21023_ts.
config TOUCHSCREEN_ST
bool "STMicroelectronics Touchscreen Driver"
depends on I2C
help
Say Y here if you have a STMicroelectronics Touchscreen.
If unsure, say N.
source "drivers/input/touchscreen/st/Kconfig"
endif

View File

@ -104,3 +104,4 @@ obj-$(CONFIG_TOUCHSCREEN_ZET6223) += zet6223.o
obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o
obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
obj-$(CONFIG_TOUCHSCREEN_ST) += st/

View File

@ -0,0 +1,9 @@
#
# STMicroelectronics touchscreen driver configuration
#
config TOUCHSCREEN_ST_I2C
tristate "STMicroelectronics i2c touchscreen"
depends on TOUCHSCREEN_ST
help
This enables support for ST touch panel over I2C based touchscreens.

View File

@ -0,0 +1,5 @@
#
## Makefile for the STMicroelectronics touchscreen driver.
#
obj-$(CONFIG_TOUCHSCREEN_ST_I2C) += fts.o fts_gui.o fts_driver_test.o fts_lib/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,249 @@
/*
* fts.c
*
* FTS Capacitive touch screen controller (FingerTipS)
*
* Copyright (C) 2016, STMicroelectronics Limited.
* Authors: AMG(Analog Mems Group)
*
* marco.cali@st.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#ifndef _LINUX_FTS_I2C_H_
#define _LINUX_FTS_I2C_H_
#include "fts_lib/ftsSoftware.h"
#include "fts_lib/ftsHardware.h"
#define FTS_POWER_ON 1
#define FTS_POWER_OFF 0
/****************** CONFIGURATION SECTION ******************/
/* #define PHONE_KEY */
/* #define PHONE_GESTURE */
#define SCRIPTLESS
#ifdef SCRIPTLESS
#define SCRIPTLESS_DEBUG
/* uncomment this macro definition to print debug
* message for script less support
*/
#endif
#define DRIVER_TEST
#define FW_H_FILE
#ifdef FW_H_FILE
#define FW_SIZE_NAME myArray_size
#define FW_ARRAY_NAME myArray
#endif
#define LIMITS_H_FILE
#ifdef LIMITS_H_FILE
#define LIMITS_SIZE_NAME myArray2_size
#define LIMITS_ARRAY_NAME myArray2
#endif
#define FTS_TS_DRV_NAME "fts"
#define FTS_TS_DRV_VERSION "4.1.0"
#define X_AXIS_MAX 1440
#define X_AXIS_MIN 0
#define Y_AXIS_MAX 2560
#define Y_AXIS_MIN 0
#define PRESSURE_MIN 0
#define PRESSURE_MAX 127
#define FINGER_MAX 10
#define STYLUS_MAX 1
#define TOUCH_ID_MAX (FINGER_MAX + STYLUS_MAX)
#define AREA_MIN PRESSURE_MIN
#define AREA_MAX PRESSURE_MAX
/*********************************************************/
/* Flash programming */
#define INIT_FLAG_CNT 3
/* KEYS */
#define KEY1 0x02
#define KEY2 0x01
#define KEY3 0x04
/*
* Configuration mode
*/
#define MODE_NORMAL 0
#define MODE_GESTURE 1
#define MODE_GLOVE 2
#define MODE_SENSEOFF 3
/*
* Status Event Field:
* id of command that triggered the event
*/
#define FTS_FLASH_WRITE_CONFIG 0x03
#define FTS_FLASH_WRITE_COMP_MEMORY 0x04
#define FTS_FORCE_CAL_SELF_MUTUAL 0x05
#define FTS_FORCE_CAL_SELF 0x06
#define FTS_WATER_MODE_ON 0x07
#define FTS_WATER_MODE_OFF 0x08
#define EXP_FN_WORK_DELAY_MS 1000
#define CMD_STR_LEN 32
#ifdef SCRIPTLESS
/*
* I2C Command Read/Write Function
*/
#define CMD_RESULT_STR_LEN 2048
#endif
#define TSP_BUF_SIZE 4096
struct fts_i2c_platform_data {
int (*power)(bool on);
int irq_gpio;
int reset_gpio;
const char *pwr_reg_name;
const char *bus_reg_name;
};
/*
* Forward declaration
*/
struct fts_ts_info;
extern char tag[8];
/*
* Dispatch event handler
*/
typedef unsigned char * (*event_dispatch_handler_t)
(struct fts_ts_info *info, unsigned char *data);
/*
* struct fts_ts_info - FTS capacitive touch screen device information
* @dev: Pointer to the structure device
* @client: I2C client structure
* @input_dev Input device structure
* @work Work thread
* @event_wq Event queue for work thread
* @cmd_done Asyncronous command notification
* @event_dispatch_table Event dispatch table handlers
* @fw_version Firmware version
* @attrs SysFS attributes
* @mode Device operating mode
* @touch_id Bitmask for touch id (mapped to input slots)
* @buttons Bitmask for buttons status
* @timer Timer when operating in polling mode
* @early_suspend Structure for early suspend functions
* @power Power on/off routine
*/
struct fts_ts_info {
struct device *dev;
struct i2c_client *client;
struct input_dev *input_dev;
struct work_struct work;
struct workqueue_struct *event_wq;
struct delayed_work fwu_work;
struct workqueue_struct *fwu_workqueue;
struct completion cmd_done;
event_dispatch_handler_t *event_dispatch_table;
unsigned int fw_version;
unsigned int config_id;
struct attribute_group attrs;
unsigned int mode;
unsigned long touch_id;
unsigned int buttons;
#ifdef FTS_USE_POLLING_MODE
struct hrtimer timer;
#endif
#ifdef SCRIPTLESS
/*I2C cmd*/
struct device *i2c_cmd_dev;
char cmd_read_result[CMD_RESULT_STR_LEN];
char cmd_wr_result[CMD_RESULT_STR_LEN];
char cmd_write_result[20];
#endif
#ifdef DRIVER_TEST
struct device *test_cmd_dev;
#endif
int (*power)(bool on);
struct fts_i2c_platform_data *bdata;
struct regulator *pwr_reg;
struct regulator *bus_reg;
bool fw_force;
int debug_enable;
int resume_bit;
int fwupdate_stat;
int touch_debug;
struct notifier_block notifier;
bool sensor_sleep;
bool stay_awake;
/* input lock */
struct mutex input_report_mutex;
/* switches */
int gesture_enabled;
int glove_enabled;
};
typedef enum {
ERR_ITO_NO_ERR, /* < 0 No ITO Error */
ERR_ITO_PANEL_OPEN_FORCE, /* < 1 Panel Open Force */
ERR_ITO_PANEL_OPEN_SENSE, /* < 2 Panel Open Sense */
ERR_ITO_F2G, /* < 3 Force short to ground */
ERR_ITO_S2G, /* < 4 Sense short to ground */
ERR_ITO_F2VDD, /* < 5 Force short to VDD */
ERR_ITO_S2VDD, /* < 6 Sense short to VDD */
ERR_ITO_P2P_FORCE, /* < 7 Pin to Pin short (Force) */
ERR_ITO_P2P_SENSE, /* < 8 Pin to Pin short (Sense) */
} errItoSubTypes_t;
int fts_chip_powercycle(struct fts_ts_info *info);
int fts_chip_powercycle2(struct fts_ts_info *info, unsigned long sleep);
int fts_get_fw_version(struct fts_ts_info *info);
extern unsigned int le_to_uint(const unsigned char *ptr);
extern unsigned int be_to_uint(const unsigned char *ptr);
extern int input_register_notifier_client(struct notifier_block *nb);
extern int input_unregister_notifier_client(struct notifier_block *nb);
#ifdef SCRIPTLESS
extern struct attribute_group i2c_cmd_attr_group;
#endif
#ifdef DRIVER_TEST
extern struct attribute_group test_cmd_attr_group;
#endif
#endif

View File

@ -0,0 +1,871 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* API used by Driver Test Apk *
* *
**************************************************************************
**************************************************************************
*/
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/completion.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include "fts.h"
#include "fts_lib/ftsCompensation.h"
#include "fts_lib/ftsIO.h"
#include "fts_lib/ftsError.h"
#include "fts_lib/ftsFrame.h"
#include "fts_lib/ftsFlash.h"
#include "fts_lib/ftsTest.h"
#include "fts_lib/ftsTime.h"
#include "fts_lib/ftsTool.h"
#ifdef DRIVER_TEST
#define MAX_PARAMS 10
/* DEFINE COMMANDS TO TEST */
#define CMD_READ 0x00
#define CMD_WRITE 0x01
#define CMD_READU16 0x02
#define CMD_READB2 0x03
#define CMD_READB2U16 0x04
#define CMD_POLLFOREVENT 0x05
#define CMD_SYSTEMRESET 0x06
#define CMD_CLEANUP 0x07
#define CMD_GETFORCELEN 0x08
#define CMD_GETSENSELEN 0x09
#define CMD_GETMSFRAME 0x0A
/* #define CMD_GETMSKEYFRAME 0x0B */
#define CMD_GETSSFRAME 0x0C
#define CMD_REQCOMPDATA 0x0D
#define CMD_READCOMPDATAHEAD 0x0E
#define CMD_READMSCOMPDATA 0x0F
#define CMD_READSSCOMPDATA 0x10
#define CMD_READGNCOMPDATA 0x11
#define CMD_GETFWVER 0x12
#define CMD_FLASHSTATUS 0x13
#define CMD_FLASHUNLOCK 0x14
#define CMD_READFWFILE 0x15
#define CMD_FLASHPROCEDURE 0x16
#define CMD_ITOTEST 0x17
#define CMD_INITTEST 0x18
#define CMD_MSRAWTEST 0x19
#define CMD_MSINITDATATEST 0x1A
#define CMD_SSRAWTEST 0x1B
#define CMD_SSINITDATATEST 0x1C
#define CMD_MAINTEST 0x1D
#define CMD_POWERCYCLE 0x1E
#define CMD_FWWRITE 0x1F
#define CMD_READCHIPINFO 0x20
#define CMD_REQFRAME 0x21
u32 *functionToTest;
int numberParam;
static ssize_t stm_driver_test_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count) {
int n;
char *p = (char *) buf;
functionToTest = (u32 *) kmalloc(MAX_PARAMS * sizeof (u32), GFP_KERNEL);
if (functionToTest == NULL) {
logError(1, "%s impossible to allocate functionToTest!\n", tag);
return count;
}
memset(functionToTest, 0, MAX_PARAMS * sizeof (u32));
for (n = 0; n < (count + 1) / 3 && n < MAX_PARAMS; n++) {
sscanf(p, "%02X ", &functionToTest[n]);
p += 3;
logError(1, "%s functionToTest[%d] = %02X\n", tag, n, functionToTest[n]);
}
numberParam = n;
logError(1, "%s Number of Parameters = %d\n", tag, numberParam);
return count;
}
static ssize_t stm_driver_test_show(struct device *dev, struct device_attribute *attr,
char *buf) {
char buff[CMD_STR_LEN] = {0};
int res = -1, j, count;
/* int res2; */
int size = 6 * 2;
int temp, i, byteToRead;
u8 *readData = NULL;
u8 *all_strbuff = NULL;
u8 *cmd;
MutualSenseFrame frameMS;
SelfSenseFrame frameSS;
DataHeader dataHead;
MutualSenseData compData;
SelfSenseData comData;
GeneralData gnData;
u16 address;
u16 fw_version;
u16 config_id;
Firmware fw;
/* struct used for defining which test perform during the MP test */
TestToDo todoDefault;
struct i2c_client *client = to_i2c_client(dev);
struct fts_ts_info *info = i2c_get_clientdata(client);
fw.data = NULL;
todoDefault.MutualRaw = 1;
todoDefault.MutualRawGap = 1;
todoDefault.MutualCx1 = 0;
todoDefault.MutualCx2 = 1;
todoDefault.MutualCx2Adj = 1;
todoDefault.MutualCxTotal = 0;
todoDefault.MutualCxTotalAdj = 0;
todoDefault.MutualKeyRaw = 0;
todoDefault.MutualKeyCx1 = 0;
todoDefault.MutualKeyCx2 = 0;
todoDefault.MutualKeyCxTotal = 0;
todoDefault.SelfForceRaw = 1;
todoDefault.SelfForceRawGap = 0;
todoDefault.SelfForceIx1 = 0;
todoDefault.SelfForceIx2 = 0;
todoDefault.SelfForceIx2Adj = 0;
todoDefault.SelfForceIxTotal = 1;
todoDefault.SelfForceIxTotalAdj = 0;
todoDefault.SelfForceCx1 = 0;
todoDefault.SelfForceCx2 = 0;
todoDefault.SelfForceCx2Adj = 0;
todoDefault.SelfForceCxTotal = 0;
todoDefault.SelfForceCxTotalAdj = 0;
todoDefault.SelfSenseRaw = 1;
todoDefault.SelfSenseRawGap = 0;
todoDefault.SelfSenseIx1 = 0;
todoDefault.SelfSenseIx2 = 0;
todoDefault.SelfSenseIx2Adj = 0;
todoDefault.SelfSenseIxTotal = 1;
todoDefault.SelfSenseIxTotalAdj = 0;
todoDefault.SelfSenseCx1 = 0;
todoDefault.SelfSenseCx2 = 0;
todoDefault.SelfSenseCx2Adj = 0;
todoDefault.SelfSenseCxTotal = 0;
todoDefault.SelfSenseCxTotalAdj = 0;
if (numberParam >= 1 && functionToTest != NULL) {
res = fts_disableInterrupt();
if (res < 0) {
logError(0, "%s stm_driver_test_show: ERROR %08X\n", tag, res);
res = (res | ERROR_DISABLE_INTER);
goto END;
}
switch (functionToTest[0]) {
case CMD_READ:
if (numberParam >= 4) {
temp = (int) functionToTest[1];
if (numberParam == 4 + (temp - 1) && temp != 0) {
cmd = (u8 *) kmalloc(temp * sizeof (u8), GFP_KERNEL);
for (i = 0; i < temp; i++) {
cmd[i] = functionToTest[i + 2];
}
byteToRead = functionToTest[i + 2];
readData = (u8 *) kmalloc(byteToRead * sizeof (u8), GFP_KERNEL);
res = fts_readCmd(cmd, temp, readData, byteToRead);
size += (byteToRead * sizeof (u8))*2;
} else {
logError(1, "%s Wrong parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_WRITE:
if (numberParam >= 3) { /* need to pass: cmdLength cmd[0] cmd[1] … cmd[cmdLength-1] */
temp = (int) functionToTest[1];
if (numberParam == 3 + (temp - 1) && temp != 0) {
cmd = (u8 *) kmalloc(temp * sizeof (u8), GFP_KERNEL);
for (i = 0; i < temp; i++) {
cmd[i] = functionToTest[i + 2];
}
res = fts_writeCmd(cmd, temp);
} else {
logError(1, "%s Wrong parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_FWWRITE:
if (numberParam >= 3) { /* need to pass: cmdLength cmd[0] cmd[1] … cmd[cmdLength-1] */
temp = (int) functionToTest[1];
if (numberParam == 3 + (temp - 1) && temp != 0) {
cmd = (u8 *) kmalloc(temp * sizeof (u8), GFP_KERNEL);
for (i = 0; i < temp; i++) {
cmd[i] = functionToTest[i + 2];
}
res = fts_writeFwCmd(cmd, temp);
} else {
logError(1, "%s Wrong parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_READU16:
if (numberParam == 6) { /* need to pass: cmd addr[0] addr[1] byteToRead hasDummyByte */
byteToRead = functionToTest[4];
readData = (u8 *) kmalloc(byteToRead * sizeof (u8), GFP_KERNEL);
res = readCmdU16((u8) functionToTest[1], (u16) ((((u8) functionToTest[2] & 0x00FF) << 8) + ((u8) functionToTest[3] & 0x00FF)), readData, byteToRead, functionToTest[5]);
size += (byteToRead * sizeof (u8))*2;
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_READB2:
if (numberParam == 4) { /* need to pass: addr[0] addr[1] byteToRead */
byteToRead = functionToTest[3];
readData = (u8 *) kmalloc(byteToRead * sizeof (u8), GFP_KERNEL);
res = readB2((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), readData, byteToRead);
size += (byteToRead * sizeof (u8))*2;
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_READB2U16:
if (numberParam == 4) { /* need to pass: addr[0] addr[1] byteToRead */
byteToRead = functionToTest[3];
readData = (u8 *) kmalloc(byteToRead * sizeof (u8), GFP_KERNEL);
res = readB2U16((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), readData, byteToRead);
size += (byteToRead * sizeof (u8))*2;
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_POLLFOREVENT:
if (numberParam >= 5) { /* need to pass: eventLength event[0] event[1] event[eventLength-1] timeTowait */
temp = (int) functionToTest[1];
if (numberParam == 5 + (temp - 1) && temp != 0) {
readData = (u8 *) kmalloc(FIFO_EVENT_SIZE * sizeof (u8), GFP_KERNEL);
res = pollForEvent((int *) &functionToTest[2], temp, readData, ((functionToTest[temp + 2] & 0x00FF) << 8)+(functionToTest[temp + 3] & 0x00FF));
if (res >= OK)
res = OK; /* pollForEvent return the number of error found */
size += (FIFO_EVENT_SIZE * sizeof (u8))*2;
byteToRead = FIFO_EVENT_SIZE;
} else {
logError(1, "%s Wrong parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_SYSTEMRESET:
res = fts_system_reset();
break;
case CMD_READCHIPINFO:
if (numberParam == 2) { /* need to pass: doRequest */
res = readChipInfo(functionToTest[1]);
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_CLEANUP: /* TOUCH ENABLE/DISABLE */
if (numberParam == 2) { /* need to pass: enableTouch */
res = cleanUp(functionToTest[1]);
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_GETFORCELEN: /* read number Tx channels */
temp = getForceLen();
if (temp < OK)
res = temp;
else {
size += (1 * sizeof (u8))*2;
res = OK;
}
break;
case CMD_GETSENSELEN: /* read number Rx channels */
temp = getSenseLen();
if (temp < OK)
res = temp;
else {
size += (1 * sizeof (u8))*2;
res = OK;
}
break;
case CMD_REQFRAME: /* request a frame */
if (numberParam == 3) {
logError(0, "%s Requesting Frame\n", tag);
res = requestFrame((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)));
if (res < OK) {
logError(0, "%s Error requesting frame ERROR %02X\n", tag, res);
} else {
logError(0, "%s Requesting Frame Finished!\n", tag);
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_GETMSFRAME:
if (numberParam == 3) {
logError(0, "%s Get 1 MS Frame\n", tag);
flushFIFO(); /* delete the events related to some touch (allow to call this function while touching the sreen without having a flooding of the FIFO) */
res = getMSFrame2((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &frameMS);
if (res < 0) {
logError(0, "%s Error while taking the MS frame... ERROR %02X\n", tag, res);
} else {
logError(0, "%s The frame size is %d words\n", tag, res);
size = (res * sizeof (short) + 8)*2;
/* set res to OK because if getMSFrame is
successful res = number of words read
*/
res = OK;
print_frame_short("MS frame =", array1dTo2d_short(frameMS.node_data, frameMS.node_data_size, frameMS.header.sense_node), frameMS.header.force_node, frameMS.header.sense_node);
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
/*read self raw*/
case CMD_GETSSFRAME:
if (numberParam == 3) {
logError(0, "%s Get 1 SS Frame\n", tag);
flushFIFO(); /* delete the events related to some touch (allow to call this function while touching the sreen without having a flooding of the FIFO) */
res = getSSFrame2((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &frameSS);
if (res < OK) {
logError(0, "%s Error while taking the SS frame... ERROR %02X\n", tag, res);
} else {
logError(0, "%s The frame size is %d words\n", tag, res);
size = (res * sizeof (short) + 8)*2+1;
/* set res to OK because if getMSFrame is
successful res = number of words read
*/
res = OK;
print_frame_short("SS force frame =", array1dTo2d_short(frameSS.force_data, frameSS.header.force_node, 1), frameSS.header.force_node, 1);
print_frame_short("SS sense frame =", array1dTo2d_short(frameSS.sense_data, frameSS.header.sense_node, frameSS.header.sense_node), 1, frameSS.header.sense_node);
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_REQCOMPDATA: /* request comp data */
if (numberParam == 3) {
logError(0, "%s Requesting Compensation Data\n", tag);
res = requestCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)));
if (res < OK) {
logError(0, "%s Error requesting compensation data ERROR %02X\n", tag, res);
} else {
logError(0, "%s Requesting Compensation Data Finished!\n", tag);
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_READCOMPDATAHEAD: /* read comp data header */
if (numberParam == 3) {
logError(0, "%s Requesting Compensation Data\n", tag);
res = requestCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)));
if (res < OK) {
logError(0, "%s Error requesting compensation data ERROR %02X\n", tag, res);
} else {
logError(0, "%s Requesting Compensation Data Finished!\n", tag);
res = readCompensationDataHeader((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &dataHead, &address);
if (res < OK) {
logError(0, "%s Read Compensation Data Header ERROR %02X\n", tag, res);
} else {
logError(0, "%s Read Compensation Data Header OK!\n", tag);
size += (2 * sizeof (u8))*2;
}
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_READMSCOMPDATA: /* read mutual comp data */
if (numberParam == 3) {
logError(0, "%s Get MS Compensation Data\n", tag);
res = readMutualSenseCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &compData);
if (res < OK) {
logError(0, "%s Error reading MS compensation data ERROR %02X\n", tag, res);
} else {
logError(0, "%s MS Compensation Data Reading Finished!\n", tag);
size = ((compData.node_data_size + 9) * sizeof (u8))*2;
print_frame_u8("MS Data (Cx2) =", array1dTo2d_u8(compData.node_data, compData.node_data_size, compData.header.sense_node), compData.header.force_node, compData.header.sense_node);
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_READSSCOMPDATA:
if (numberParam == 3) { /* read self comp data */
logError(0, "%s Get SS Compensation Data...\n", tag);
res = readSelfSenseCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &comData);
if (res < OK) {
logError(0, "%s Error reading SS compensation data ERROR %02X\n", tag, res);
} else {
logError(0, "%s SS Compensation Data Reading Finished!\n", tag);
size = ((comData.header.force_node + comData.header.sense_node)*2 + 12) * sizeof (u8)*2;
print_frame_u8("SS Data Ix2_fm = ", array1dTo2d_u8(comData.ix2_fm, comData.header.force_node, comData.header.force_node), 1, comData.header.force_node);
print_frame_u8("SS Data Cx2_fm = ", array1dTo2d_u8(comData.cx2_fm, comData.header.force_node, comData.header.force_node), 1, comData.header.force_node);
print_frame_u8("SS Data Ix2_sn = ", array1dTo2d_u8(comData.ix2_sn, comData.header.sense_node, comData.header.sense_node), 1, comData.header.sense_node);
print_frame_u8("SS Data Cx2_sn = ", array1dTo2d_u8(comData.cx2_sn, comData.header.sense_node, comData.header.sense_node), 1, comData.header.sense_node);
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_READGNCOMPDATA:
if (numberParam == 3) { /* read self comp data */
logError(0, "%s Get General Compensation Data...\n", tag);
res = readGeneralCompensationData((u16) ((((u8) functionToTest[1] & 0x00FF) << 8) + ((u8) functionToTest[2] & 0x00FF)), &gnData);
if (res < OK) {
logError(0, "%s Error reading General compensation data ERROR %02X\n", tag, res);
} else {
logError(0, "%s General Compensation Data Reading Finished!\n", tag);
size = (14) * sizeof (u8)*2;
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_GETFWVER:
res = getFirmwareVersion(&fw_version, &config_id);
if (res < OK) {
logError(1, "%s Error reading firmware version and config id ERROR %02X\n", tag, res);
} else {
logError(0, "%s getFirmwareVersion Finished!\n", tag);
size += (4) * sizeof (u8)*2;
}
break;
#ifdef FTM3_CHIP
case CMD_FLASHSTATUS:
res = flash_status(); /* return 0 = flash ready, 1 = flash busy, <0 error */
if (res < OK) {
logError(1, "%s Error reading flash status ERROR %02X\n", tag, res);
} else {
logError(0, "%s Flash Status: %d\n", tag, res);
size += (1 * sizeof (u8))*2;
temp = res; /* need to store the value for further display */
res = OK; /* set res =ok for returning code */
}
break;
#endif
case CMD_FLASHUNLOCK:
res = flash_unlock();
if (res < OK) {
logError(1, "%s Impossible Unlock Flash ERROR %02X\n", tag, res);
} else {
logError(0, "%s Flash Unlock OK!\n", tag);
}
break;
case CMD_READFWFILE:
if (numberParam == 2) { /* read fw file */
logError(0, "%s Reading FW File...\n", tag);
res = readFwFile(PATH_FILE_FW, &fw, functionToTest[1]);
if (res < OK) {
logError(0, "%s Error reading FW File ERROR %02X\n", tag, res);
} else {
logError(0, "%s Read FW File Finished!\n", tag);
}
kfree(fw.data);
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_FLASHPROCEDURE:
if (numberParam == 3) { /* flashing procedure */
logError(0, "%s Starting Flashing Procedure...\n", tag);
res = flashProcedure(PATH_FILE_FW, functionToTest[1], functionToTest[2]);
if (res < OK) {
logError(0, "%s Error during flash procedure ERROR %02X\n", tag, res);
} else {
logError(0, "%s Flash Procedure Finished!\n", tag);
}
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
/*ITO TEST*/
case CMD_ITOTEST:
res = production_test_ito();
break;
/*Initialization*/
case CMD_INITTEST:
if (numberParam == 2) { /* need to specify if if save value on Flash */
if (functionToTest[1] == 0x01)
res = production_test_initialization();
else
res = production_test_splited_initialization(false);
} else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_MSRAWTEST: /* MS Raw DATA TEST */
if (numberParam == 2) /* need to specify if stopOnFail */
res = production_test_ms_raw(LIMITS_FILE, functionToTest[1], &todoDefault);
else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_MSINITDATATEST: /* MS CX DATA TEST */
if (numberParam == 2) /* need to specify if stopOnFail */
res = production_test_ms_cx(LIMITS_FILE, functionToTest[1], &todoDefault);
else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_SSRAWTEST: /* SS RAW DATA TEST */
if (numberParam == 2) /* need to specify if stopOnFail */
res = production_test_ss_raw(LIMITS_FILE, functionToTest[1], &todoDefault);
else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_SSINITDATATEST: /* SS IX CX DATA TEST */
if (numberParam == 2) /* need to specify if stopOnFail */
res = production_test_ss_ix_cx(LIMITS_FILE, functionToTest[1], &todoDefault);
else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
/*PRODUCTION TEST*/
case CMD_MAINTEST:
if (numberParam == 3) /* need to specify if stopOnFail and saveInit */
res = production_test_main(LIMITS_FILE, functionToTest[1], functionToTest[2], &todoDefault, INIT_FIELD);
else {
logError(1, "%s Wrong number of parameters!\n", tag);
res = ERROR_OP_NOT_ALLOW;
}
break;
case CMD_POWERCYCLE:
res = fts_chip_powercycle(info);
break;
default:
logError(1, "%s COMMAND ID NOT VALID!! Inset a value between 00 and 1E..\n", tag);
res = ERROR_OP_NOT_ALLOW;
break;
}
/*res2 = fts_enableInterrupt(); enabling the interrupt was disabled on purpose in this node because it can be used for testing procedure and between one step and another the interrupt wan to be kept disabled
if (res2 < 0) {
logError(0, "%s stm_driver_test_show: ERROR %08X\n", tag, (res2 | ERROR_ENABLE_INTER));
}*/
} else {
logError(1, "%s NO COMMAND SPECIFIED!!! do: 'echo [cmd_code] [args] > stm_fts_cmd' before looking for result!\n", tag);
res = ERROR_OP_NOT_ALLOW;
functionToTest = NULL;
}
END: /* here start the reporting phase, assembling the data to send in the file node */
all_strbuff = (u8 *) kmalloc(size, GFP_KERNEL);
memset(all_strbuff, 0, size);
snprintf(buff, sizeof (buff), "%02X", 0xAA);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%08X", res);
strlcat(all_strbuff, buff, size);
if (res >= OK) {
/*all the other cases are already fine printing only the res.*/
switch (functionToTest[0]) {
case CMD_READ:
case CMD_READU16:
case CMD_READB2:
case CMD_READB2U16:
case CMD_POLLFOREVENT:
for (j = 0; j < byteToRead; j++) {
snprintf(buff, sizeof (buff), "%02X", readData[j]);
strlcat(all_strbuff, buff, size);
}
break;
case CMD_GETFORCELEN:
case CMD_GETSENSELEN:
case CMD_FLASHSTATUS:
snprintf(buff, sizeof (buff), "%02X", (u8) temp);
strlcat(all_strbuff, buff, size);
break;
case CMD_GETMSFRAME:
snprintf(buff, sizeof (buff), "%02X", (u8) frameMS.header.force_node);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", (u8) frameMS.header.sense_node);
strlcat(all_strbuff, buff, size);
for (j = 0; j < frameMS.node_data_size; j++) {
snprintf(buff, sizeof (buff), "%04X", frameMS.node_data[j]);
strlcat(all_strbuff, buff, size);
}
kfree(frameMS.node_data);
break;
case CMD_GETSSFRAME:
snprintf(buff, sizeof (buff), "%02X", (u8) frameSS.header.force_node);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", (u8) frameSS.header.sense_node);
strlcat(all_strbuff, buff, size);
/* Copying self raw data Force */
for (j = 0; j < frameSS.header.force_node; j++) {
snprintf(buff, sizeof (buff), "%04X", frameSS.force_data[j]);
strlcat(all_strbuff, buff, size);
}
/* Copying self raw data Sense */
for (j = 0; j < frameSS.header.sense_node; j++) {
snprintf(buff, sizeof (buff), "%04X", frameSS.sense_data[j]);
strlcat(all_strbuff, buff, size);
}
kfree(frameSS.force_data);
kfree(frameSS.sense_data);
break;
case CMD_READMSCOMPDATA:
snprintf(buff, sizeof (buff), "%02X", (u8) compData.header.force_node);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", (u8) compData.header.sense_node);
strlcat(all_strbuff, buff, size);
/* Cpying CX1 value */
snprintf(buff, sizeof (buff), "%02X", compData.cx1);
strlcat(all_strbuff, buff, size);
/* Copying CX2 values */
for (j = 0; j < compData.node_data_size; j++) {
snprintf(buff, sizeof (buff), "%02X", *(compData.node_data + j));
strlcat(all_strbuff, buff, size);
}
kfree(compData.node_data);
break;
case CMD_READSSCOMPDATA:
snprintf(buff, sizeof (buff), "%02X", comData.header.force_node);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", comData.header.sense_node);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", comData.f_ix1);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", comData.s_ix1);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", comData.f_cx1);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", comData.s_cx1);
strlcat(all_strbuff, buff, size);
/* Copying IX2 Force */
for (j = 0; j < comData.header.force_node; j++) {
snprintf(buff, sizeof (buff), "%02X", comData.ix2_fm[j]);
strlcat(all_strbuff, buff, size);
}
/* Copying IX2 Sense */
for (j = 0; j < comData.header.sense_node; j++) {
snprintf(buff, sizeof (buff), "%02X", comData.ix2_sn[j]);
strlcat(all_strbuff, buff, size);
}
/* Copying CX2 Force */
for (j = 0; j < comData.header.force_node; j++) {
snprintf(buff, sizeof (buff), "%02X", comData.cx2_fm[j]);
strlcat(all_strbuff, buff, size);
}
/* Copying CX2 Sense */
for (j = 0; j < comData.header.sense_node; j++) {
snprintf(buff, sizeof (buff), "%02X", comData.cx2_sn[j]);
strlcat(all_strbuff, buff, size);
}
kfree(comData.ix2_fm);
kfree(comData.ix2_sn);
kfree(comData.cx2_fm);
kfree(comData.cx2_sn);
break;
case CMD_READGNCOMPDATA:
snprintf(buff, sizeof (buff), "%02X", gnData.header.force_node);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", gnData.header.sense_node);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", gnData.ftsd_lp_timer_cal0);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", gnData.ftsd_lp_timer_cal1);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", gnData.ftsd_lp_timer_cal2);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", gnData.ftsd_lp_timer_cal3);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", gnData.ftsa_lp_timer_cal0);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", gnData.ftsa_lp_timer_cal1);
strlcat(all_strbuff, buff, size);
break;
case CMD_GETFWVER:
snprintf(buff, sizeof (buff), "%04X", fw_version);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%04X", config_id);
strlcat(all_strbuff, buff, size);
break;
case CMD_READCOMPDATAHEAD:
snprintf(buff, sizeof (buff), "%02X", dataHead.force_node);
strlcat(all_strbuff, buff, size);
snprintf(buff, sizeof (buff), "%02X", dataHead.sense_node);
strlcat(all_strbuff, buff, size);
break;
default:
break;
}
}
snprintf(buff, sizeof (buff), "%02X", 0xBB);
strlcat(all_strbuff, buff, size);
count = snprintf(buf, TSP_BUF_SIZE, "%s\n", all_strbuff);
numberParam = 0; /* need to reset the number of parameters in order to wait the next comand, comment if you want to repeat the last comand sent just doing a cat */
/* logError(0,"%s numberParameters = %d\n",tag, numberParam); */
kfree(all_strbuff);
kfree(functionToTest);
return count;
}
/*static DEVICE_ATTR(stm_driver_test, (S_IRWXU|S_IRWXG), stm_driver_test_show, stm_driver_test_store);*/
static DEVICE_ATTR(stm_driver_test, (S_IRUGO | S_IWUSR | S_IWGRP), stm_driver_test_show, stm_driver_test_store);
static struct attribute *test_cmd_attributes[] = {
&dev_attr_stm_driver_test.attr,
NULL,
};
struct attribute_group test_cmd_attr_group = {
.attrs = test_cmd_attributes,
};
#endif

View File

@ -0,0 +1,10 @@
#ifndef FTS_FW_H
#define FTS_FW_H
/* This is an auto generated header file
* --->Remember to change the name of the two variables!<--- */
const uint32_t myArray_size;
const uint8_t myArray[] = {
};
#endif

View File

@ -0,0 +1,359 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/completion.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include "fts.h"
#include "fts_lib/ftsCompensation.h"
#include "fts_lib/ftsIO.h"
#include "fts_lib/ftsError.h"
#include "fts_lib/ftsFrame.h"
#include "fts_lib/ftsTest.h"
#include "fts_lib/ftsTime.h"
#include "fts_lib/ftsTool.h"
#ifdef SCRIPTLESS
unsigned int data[CMD_RESULT_STR_LEN] = {0};
unsigned char pAddress_i2c[CMD_RESULT_STR_LEN] = {0};
int byte_count_read;
char Out_buff[TSP_BUF_SIZE];
/*I2C CMd functions: functions to interface with GUI without script */
ssize_t fts_i2c_wr_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct fts_ts_info *info = i2c_get_clientdata(client);
int i;
char buff[16];
memset(Out_buff, 0x00, ARRAY_SIZE(Out_buff));
if (byte_count_read == 0) {
snprintf(Out_buff, sizeof(Out_buff), "{FAILED}");
return snprintf(buf, TSP_BUF_SIZE, "{%s}\n", Out_buff);
}
#ifdef SCRIPTLESS_DEBUG
printk("%s:DATA READ {", __func__);
for (i = 0; i < byte_count_read; i++) {
printk(" %02X", (unsigned int)info->cmd_wr_result[i]);
if (i < (byte_count_read-1)) {
printk(" ");
}
}
printk("}\n");
#endif
snprintf(buff, sizeof(buff), "{");
strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
for (i = 0; i < (byte_count_read+2); i++) {
if ((i == 0)) {
char temp_byte_count_read = (byte_count_read >> 8) & 0xFF;
snprintf(buff, sizeof(buff), "%02X", temp_byte_count_read);
} else if (i == 1) {
char temp_byte_count_read = (byte_count_read) & 0xFF;
snprintf(buff, sizeof(buff), "%02X", temp_byte_count_read);
} else {
snprintf(buff, sizeof(buff), "%02X", info->cmd_wr_result[i-2]);
}
/* snprintf(buff, sizeof(buff), "%02X", info->cmd_wr_result[i]); */
strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
if (i < (byte_count_read+1)) {
snprintf(buff, sizeof(buff), " ");
strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
}
}
snprintf(buff, sizeof(buff), "}");
strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
return snprintf(buf, TSP_BUF_SIZE, "%s\n", Out_buff);
}
ssize_t fts_i2c_wr_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct fts_ts_info *info = i2c_get_clientdata(client);
unsigned char pAddress[8] = {0};
unsigned int byte_count = 0 ;
int i ;
unsigned int data[8] = {0};
memset(data, 0x00, ARRAY_SIZE(data));
memset(info->cmd_wr_result, 0x00, ARRAY_SIZE(info->cmd_wr_result));
sscanf(buf, "%x %x %x %x %x %x %x %x ", (data+7), (data), (data+1),
(data+2), (data+3), (data+4), (data+5), (data+6));
byte_count = data[7];
/*if (sizeof(buf) != byte_count )
{
printk("%s : Byte count is wrong\n",__func__);
return count;
}*/
#ifdef SCRIPTLESS_DEBUG
printk("\n");
printk("%s: Input Data 1:", __func__);
for (i = 0 ; i < 7; i++) {
printk(" %02X", data[i]);
pAddress[i] = (unsigned char)data[i];
}
printk("\n");
#else
for (i = 0 ; i < 7; i++) {
pAddress[i] = (unsigned char)data[i];
}
#endif
byte_count_read = data[byte_count-1];
ret = fts_writeCmd(pAddress, 3);
msleep(20);
ret = fts_readCmd(&pAddress[3], (byte_count-4), info->cmd_wr_result,
byte_count_read);
#ifdef SCRIPTLESS_DEBUG
printk("%s:DATA READ\n{", __func__);
for (i = 0; i < (2+byte_count_read); i++) {
if ((i == 0)) {
char temp_byte_count_read = (byte_count_read >> 8) & 0xFF;
printk("%02X", (unsigned int)temp_byte_count_read);
} else if (i == 1) {
char temp_byte_count_read = (byte_count_read) & 0xFF;
printk("%02X", (unsigned int)temp_byte_count_read);
} else {
printk("%02X", (unsigned int)info->cmd_read_result[i-2]);
}
if (i < (byte_count_read+1)) {
printk(" ");
}
}
printk("}\n");
#endif
if (ret)
dev_err(dev, "Unable to read register\n");
return count;
}
ssize_t fts_i2c_read_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct fts_ts_info *info = i2c_get_clientdata(client);
int i ;
char buff[16];
memset(Out_buff, 0x00, ARRAY_SIZE(Out_buff));
if (byte_count_read == 0) {
snprintf(Out_buff, sizeof(Out_buff), "{FAILED}");
return snprintf(buf, TSP_BUF_SIZE, "{%s}\n", Out_buff);
}
#ifdef SCRIPTLESS_DEBUG
printk("%s:DATA READ {", __func__);
for (i = 0; i < byte_count_read; i++) {
printk("%02X", (unsigned int)info->cmd_read_result[i]);
if (i < (byte_count_read-1)) {
printk(" ");
}
}
printk("}\n");
#endif
snprintf(buff, sizeof(buff), "{");
strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
for (i = 0; i < (byte_count_read+2); i++) {
if ((i == 0)) {
char temp_byte_count_read = (byte_count_read >> 8) & 0xFF;
snprintf(buff, sizeof(buff), "%02X", temp_byte_count_read);
} else if (i == 1) {
char temp_byte_count_read = (byte_count_read) & 0xFF;
snprintf(buff, sizeof(buff), "%02X", temp_byte_count_read);
} else {
snprintf(buff, sizeof(buff), "%02X", info->cmd_read_result[i-2]);
}
strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
if (i < (byte_count_read+1)) {
snprintf(buff, sizeof(buff), " ");
strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
}
}
snprintf(buff, sizeof(buff), "}");
strlcat(Out_buff, buff, ARRAY_SIZE(Out_buff));
return snprintf(buf, TSP_BUF_SIZE, "%s\n", Out_buff);
}
ssize_t fts_i2c_read_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct fts_ts_info *info = i2c_get_clientdata(client);
unsigned char pAddress[8] = {0};
unsigned int byte_count = 0;
int i ;
unsigned int data[8] = {0};
byte_count_read = 0;
memset(data, 0x00, ARRAY_SIZE(data));
memset(info->cmd_read_result, 0x00, ARRAY_SIZE(info->cmd_read_result));
sscanf(buf, "%x %x %x %x %x %x %x %x ", (data+7), (data), (data+1), (data+2), (data+3), (data+4), (data+5), (data+6));
byte_count = data[7];
if (byte_count > 7) {
#ifdef SCRIPTLESS_DEBUG
printk("%s : Byte count is more than 7\n", __func__);
#endif
return count;
}
/*if (sizeof(buf) != byte_count )
{
printk("%s : Byte count is wrong\n",__func__);
return count;
}*/
#ifdef SCRIPTLESS_DEBUG
printk("\n");
printk("%s: Input Data 1:", __func__);
for (i = 0 ; i < byte_count; i++) {
printk(" %02X", data[i]);
pAddress[i] = (unsigned char)data[i];
}
printk("\n");
#else
for (i = 0 ; i < byte_count; i++) {
pAddress[i] = (unsigned char)data[i];
}
#endif
byte_count_read = data[byte_count-1];
ret = fts_readCmd(pAddress, (byte_count-1), info->cmd_read_result, byte_count_read);
#ifdef SCRIPTLESS_DEBUG
printk("%s:DATA READ\n{", __func__);
for (i = 0; i < (byte_count_read+2); i++) {
if ((i == 0)) {
char temp_byte_count_read = (byte_count_read >> 8) & 0xFF;
printk("%02X", (unsigned int)temp_byte_count_read);
} else if (i == 1) {
char temp_byte_count_read = (byte_count_read) & 0xFF;
printk("%02X", (unsigned int)temp_byte_count_read);
} else {
printk("%02X", (unsigned int)info->cmd_read_result[i-2]);
}
if (i < (byte_count_read+1)) {
printk(" ");
}
}
printk("}\n");
#endif
if (ret)
dev_err(dev, "Unable to read register\n");
return count;
}
ssize_t fts_i2c_write_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct fts_ts_info *info = i2c_get_clientdata(client);
return snprintf(buf, TSP_BUF_SIZE, "%s", info->cmd_write_result);
}
ssize_t fts_i2c_write_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct fts_ts_info *info = i2c_get_clientdata(client);
unsigned int byte_count = 0;
int i ;
memset(data, 0x00, ARRAY_SIZE(data));
memset(pAddress_i2c, 0x00, ARRAY_SIZE(pAddress_i2c));
memset(info->cmd_write_result, 0x00, ARRAY_SIZE(info->cmd_write_result));
sscanf(buf, "%x %x", data, (data + 1));
byte_count = data[0] << 8 | data[1];
if (byte_count <= ARRAY_SIZE(pAddress_i2c)) {
for (i = 0; i < (byte_count); i++) {
sscanf(&buf[3*(i+2)], "%x ", (data+i));
} } else {
#ifdef SCRIPTLESS_DEBUG
printk("%s : message size is more than allowed limit of 512 bytes\n", __func__);
#endif
snprintf(info->cmd_write_result, sizeof(info->cmd_write_result), "{Write NOT OK}\n");
}
#ifdef SCRIPTLESS_DEBUG
printk("\n");
printk("%s: Byte_count= %02d | Count = %02d | size of buf:%02d\n", __func__, byte_count, (int)count, (int)sizeof(buf));
printk("%s: Input Data 1:", __func__);
for (i = 0 ; i < byte_count; i++) {
printk("%02X", data[i]);
pAddress_i2c[i] = (unsigned char)data[i];
}
printk("\n");
#else
for (i = 0; i < byte_count; i++) {
pAddress_i2c[i] = (unsigned char)data[i];
}
#endif
if ((pAddress_i2c[0] == 0xb3) && (pAddress_i2c[3] == 0xb1)) {
ret = fts_writeCmd(pAddress_i2c, 3);
msleep(20);
ret = fts_writeCmd(&pAddress_i2c[3], byte_count-3);
} else {
ret = fts_writeCmd(pAddress_i2c, byte_count);
}
#ifdef SCRIPTLESS_DEBUG
printk("%s:DATA :", __func__);
for (i = 0; i < byte_count; i++) {
printk(" %02X", (unsigned int)pAddress_i2c[i]);
}
printk(" byte_count: %02X\n", byte_count);
#endif
if (ret < 0) {
dev_err(dev, "{Write NOT OK}\n");
snprintf(info->cmd_write_result, sizeof(info->cmd_write_result), "{Write NOT OK}\n");
} else {
snprintf(info->cmd_write_result, sizeof(info->cmd_write_result), "{Write OK}\n");
#ifdef SCRIPTLESS_DEBUG
printk("%s : {Write OK}\n", __func__);
#endif
}
return count;
}
static DEVICE_ATTR(iread, (S_IWUSR|S_IWGRP), NULL, fts_i2c_read_store);
static DEVICE_ATTR(iread_result, (S_IRUSR|S_IRGRP), fts_i2c_read_show, NULL);
static DEVICE_ATTR(iwr, (S_IWUSR|S_IWGRP), NULL, fts_i2c_wr_store);
static DEVICE_ATTR(iwr_result, (S_IRUSR|S_IRGRP), fts_i2c_wr_show, NULL);
static DEVICE_ATTR(iwrite, (S_IWUSR|S_IWGRP), NULL, fts_i2c_write_store);
static DEVICE_ATTR(iwrite_result, (S_IRUSR|S_IRGRP), fts_i2c_write_show, NULL);
static struct attribute *i2c_cmd_attributes[] = {
&dev_attr_iread.attr,
&dev_attr_iread_result.attr,
&dev_attr_iwr.attr,
&dev_attr_iwr_result.attr,
&dev_attr_iwrite.attr,
&dev_attr_iwrite_result.attr,
NULL,
};
struct attribute_group i2c_cmd_attr_group = {
.attrs = i2c_cmd_attributes,
};
#endif

View File

@ -0,0 +1,7 @@
#
# Makefile for the FTS touchscreen driver.
#
obj-$(CONFIG_TOUCHSCREEN_ST_I2C) += ftsCompensation.o \
ftsCrossCompile.o ftsError.o ftsFrame.o ftsIO.o ftsTest.o \
ftsTime.o ftsTool.o ftsFlash.o ftsGesture.o

View File

@ -0,0 +1,591 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS functions for getting Initialization Data *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsCrossCompile.h"
#include "ftsCompensation.h"
#include "ftsError.h"
#include "ftsFrame.h"
#include "ftsHardware.h"
#include "ftsIO.h"
#include "ftsSoftware.h"
#include "ftsTool.h"
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <stdarg.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/time.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/regulator/consumer.h>
#include <linux/of_gpio.h>
/* #include <linux/sec_sysfs.h> */
static char tag[8] = "[ FTS ]\0";
chipInfo ftsInfo;
int requestCompensationData(u16 type)
{
int retry = 0;
int ret;
u16 answer;
int event_to_search[3];
u8 readEvent[FIFO_EVENT_SIZE];
u8 cmd[3] = { FTS_CMD_REQU_COMP_DATA, 0x00, 0x00 };
/* B8 is the command for asking compensation data */
u16ToU8(type, &cmd[1]);
event_to_search[0] = (int)EVENTID_COMP_DATA_READ;
event_to_search[1] = cmd[1];
event_to_search[2] = cmd[2];
while (retry < COMP_DATA_READ_RETRY) {
logError(0, "%s %s", tag, printHex("Command = ", cmd, 3));
ret = fts_writeFwCmd(cmd, 3);
/* send the request to the chip to load in memory the Compensation Data */
if (ret < OK) {
logError(1, "%s requestCompensationData: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
ret = pollForEvent(event_to_search, 3, readEvent, TIMEOUT_REQU_COMP_DATA);
if (ret < OK) {
logError(0, "%s Event did not Found at %d attemp! \n", tag, retry+1);
retry += 1;
} else {
retry = 0;
break;
}
}
if (retry == COMP_DATA_READ_RETRY) {
logError(1, "%s requestCompensationData: ERROR %02X\n", tag, ERROR_TIMEOUT);
return ERROR_TIMEOUT;
}
u8ToU16_le(&readEvent[1], &answer);
if (answer == type)
return OK;
logError(1, "%s The event found has a different type of Compensation data ERROR %02X \n", tag, ERROR_DIFF_COMP_TYPE);
return ERROR_DIFF_COMP_TYPE;
}
int readCompensationDataHeader(u16 type, DataHeader *header, u16 *address)
{
u16 offset = ADDR_FRAMEBUFFER_DATA;
u16 answer;
u8 data[COMP_DATA_HEADER];
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, offset, data, COMP_DATA_HEADER, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s readCompensationDataHeader: ERROR %02X \n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
logError(0, "%s Read Data Header done! \n", tag);
if (data[0] != HEADER_SIGNATURE) {
logError(1, "%s readCompensationDataHeader: ERROR %02X The Header Signature was wrong! %02X != %02X \n", tag, ERROR_WRONG_COMP_SIGN, data[0], HEADER_SIGNATURE);
return ERROR_WRONG_COMP_SIGN;
}
u8ToU16_le(&data[1], &answer);
if (answer != type) {
logError(1, "%s readCompensationDataHeader: ERROR %02X\n", tag, ERROR_DIFF_COMP_TYPE);
return ERROR_DIFF_COMP_TYPE;
}
logError(0, "%s Type of Compensation data OK! \n", tag);
header->type = type;
header->force_node = (int)data[4];
header->sense_node = (int)data[5];
*address = offset + COMP_DATA_HEADER;
return OK;
}
int readMutualSenseGlobalData(u16 *address, MutualSenseData *global)
{
u8 data[COMP_DATA_GLOBAL];
logError(0, "%s Address for Global data= %02X \n", tag, *address);
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, *address, data, COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s readMutualSenseGlobalData: ERROR %02X\n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
logError(0, "%s Global data Read !\n", tag);
global->tuning_ver = data[0];
global->cx1 = data[1];
logError(0, "%s tuning_ver = %d CX1 = %d \n", tag, global->tuning_ver, global->cx1);
*address += COMP_DATA_GLOBAL;
return OK;
}
int readMutualSenseNodeData(u16 address, MutualSenseData *node)
{
int size = node->header.force_node*node->header.sense_node;
logError(0, "%s Address for Node data = %02X \n", tag, address);
node->node_data = (u8 *)kmalloc(size*(sizeof(u8)), GFP_KERNEL);
if (node->node_data == NULL) {
logError(1, "%s readMutualSenseNodeData: ERROR %02X", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
logError(0, "%s Node Data to read %d bytes \n", tag, size);
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, node->node_data, size, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s readMutualSenseNodeData: ERROR %02X \n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
node->node_data_size = size;
logError(0, "%s Read node data ok! \n", tag);
return size;
}
int readMutualSenseCompensationData(u16 type, MutualSenseData *data)
{
int ret;
u16 address;
if (!(type == MS_TOUCH_ACTIVE || type == MS_TOUCH_LOW_POWER ||
type == MS_TOUCH_ULTRA_LOW_POWER || type == MS_KEY)) {
logError(1, "%s readMutualSenseCompensationData: Choose a MS type of compensation data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = requestCompensationData(type);
if (ret < 0) {
logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
return (ret|ERROR_REQU_COMP_DATA);
}
ret = readCompensationDataHeader(type, &(data->header), &address);
if (ret < 0) {
logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
return (ret|ERROR_COMP_DATA_HEADER);
}
ret = readMutualSenseGlobalData(&address, data);
if (ret < 0) {
logError(1, "%s readMutualSenseCompensationData: ERROR %02X \n", tag, ERROR_COMP_DATA_GLOBAL);
return (ret|ERROR_COMP_DATA_GLOBAL);
}
ret = readMutualSenseNodeData(address, data);
if (ret < 0) {
logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_NODE);
return (ret|ERROR_COMP_DATA_NODE);
}
return OK;
}
int readSelfSenseGlobalData(u16 *address, SelfSenseData *global)
{
u8 data[COMP_DATA_GLOBAL];
logError(0, "%s Address for Global data= %02X \n", tag, *address);
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, *address, data, COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s readSelfSenseGlobalData: ERROR %02X \n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
logError(0, "%s Global data Read !\n", tag);
global->tuning_ver = data[0];
global->f_ix1 = data[1];
global->s_ix1 = data[2];
global->f_cx1 = data[3];
global->s_cx1 = data[4];
global->f_max_n = data[5];
global->s_max_n = data[6];
logError(0, "%s tuning_ver = %d f_ix1 = %d s_ix1 = %d f_cx1 = %d s_cx1 = %d \n", tag, global->tuning_ver, global->f_ix1, global->s_ix1, global->f_cx1, global->s_cx1);
logError(0, "%s max_n = %d s_max_n = %d \n", tag, global->f_max_n, global->s_max_n);
*address += COMP_DATA_GLOBAL;
return OK;
}
int readSelfSenseNodeData(u16 address, SelfSenseData *node)
{
int size = node->header.force_node*2+node->header.sense_node*2;
u8 data[size];
node->ix2_fm = (u8 *)kmalloc(node->header.force_node*(sizeof(u8)), GFP_KERNEL);
node->cx2_fm = (u8 *)kmalloc(node->header.force_node*(sizeof(u8)), GFP_KERNEL);
node->ix2_sn = (u8 *)kmalloc(node->header.sense_node*(sizeof(u8)), GFP_KERNEL);
node->cx2_sn = (u8 *)kmalloc(node->header.sense_node*(sizeof(u8)), GFP_KERNEL);
if (node->ix2_fm == NULL || node->cx2_fm == NULL || node->ix2_sn == NULL
|| node->cx2_sn == NULL) {
logError(1, "%s readSelfSenseNodeData: ERROR %02X", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
logError(0, "%s Address for Node data = %02X \n", tag, address);
logError(0, "%s Node Data to read %d bytes \n", tag, size);
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, data, size, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s readSelfSenseNodeData: ERROR %02X\n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
logError(0, "%s Read node data ok! \n", tag);
memcpy(node->ix2_fm, data, node->header.force_node);
memcpy(node->ix2_sn, &data[node->header.force_node], node->header.sense_node);
memcpy(node->cx2_fm, &data[node->header.force_node + node->header.sense_node], node->header.force_node);
memcpy(node->cx2_sn, &data[node->header.force_node*2 + node->header.sense_node], node->header.sense_node);
return OK;
}
int readSelfSenseCompensationData(u16 type, SelfSenseData *data)
{
int ret;
u16 address;
if (!(type == SS_TOUCH || type == SS_KEY || type == SS_HOVER || type == SS_PROXIMITY)) {
logError(1, "%s readSelfSenseCompensationData: Choose a SS type of compensation data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = requestCompensationData(type);
if (ret < 0) {
logError(1, "%s readSelfSenseCompensationData: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
return (ret|ERROR_REQU_COMP_DATA);
}
ret = readCompensationDataHeader(type, &(data->header), &address);
if (ret < 0) {
logError(1, "%s readSelfSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
return (ret|ERROR_COMP_DATA_HEADER);
}
ret = readSelfSenseGlobalData(&address, data);
if (ret < 0) {
logError(1, "%s readSelfSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_GLOBAL);
return (ret|ERROR_COMP_DATA_GLOBAL);
}
ret = readSelfSenseNodeData(address, data);
if (ret < 0) {
logError(1, "%s readSelfSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_NODE);
return (ret|ERROR_COMP_DATA_NODE);
}
return OK;
}
int readGeneralGlobalData(u16 address, GeneralData *global)
{
u8 data[COMP_DATA_GLOBAL];
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, data, COMP_DATA_GLOBAL, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s readGeneralGlobalData: ERROR %02X \n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
global->ftsd_lp_timer_cal0 = data[0];
global->ftsd_lp_timer_cal1 = data[1];
global->ftsd_lp_timer_cal2 = data[2];
global->ftsd_lp_timer_cal3 = data[3];
global->ftsa_lp_timer_cal0 = data[4];
global->ftsa_lp_timer_cal1 = data[5];
return OK;
}
int readGeneralCompensationData(u16 type, GeneralData *data)
{
int ret;
u16 address;
if (!(type == GENERAL_TUNING)) {
logError(1, "%s readGeneralCompensationData: Choose a GENERAL type of compensation data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = requestCompensationData(type);
if (ret < 0) {
logError(1, "%s readGeneralCompensationData: ERROR %02X \n", tag, ERROR_REQU_COMP_DATA);
return ERROR_REQU_COMP_DATA;
}
ret = readCompensationDataHeader(type, &(data->header), &address);
if (ret < 0) {
logError(1, "%s readGeneralCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
return ERROR_COMP_DATA_HEADER;
}
ret = readGeneralGlobalData(address, data);
if (ret < 0) {
logError(1, "%s readGeneralCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_GLOBAL);
return ERROR_COMP_DATA_GLOBAL;
}
return OK;
}
int defaultChipInfo(int i2cError)
{
int i;
logError(0, "%s Setting default Chip Info... \n", tag);
ftsInfo.u32_echoEn = 0x00000000;
ftsInfo.u8_msScrConfigTuneVer = 0;
ftsInfo.u8_ssTchConfigTuneVer = 0;
ftsInfo.u8_msScrCxmemTuneVer = 0;
ftsInfo.u8_ssTchCxmemTuneVer = 0;
if (i2cError == 1) {
ftsInfo.u16_fwVer = 0xFFFF;
ftsInfo.u16_cfgId = 0xFFFF;
for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
ftsInfo.u8_extReleaseInfo[i] = 0xFF;
}
} else {
ftsInfo.u16_fwVer = 0x0000;
ftsInfo.u16_cfgId = 0x0000;
for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
ftsInfo.u8_extReleaseInfo[i] = 0x00;
}
}
ftsInfo.u32_mpPassFlag = INIT_FIELD;
logError(0, "%s default Chip Info DONE! \n", tag);
return OK;
}
int readChipInfo(int doRequest)
{
int ret, i;
u16 answer;
u8 data[CHIP_INFO_SIZE+3];
/* +3 because need to read all the field of the struct plus the signature and 2 address bytes */
int index = 0;
logError(0, "%s Starting Read Chip Info... \n", tag);
if (doRequest == 1) {
ret = requestCompensationData(CHIP_INFO);
if (ret < 0) {
logError(1, "%s readChipInfo: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
ret = (ret | ERROR_REQU_COMP_DATA);
goto FAIL;
}
}
logError(0, "%s Byte to read = %d bytes \n", tag, CHIP_INFO_SIZE+3);
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, ADDR_FRAMEBUFFER_DATA, data, CHIP_INFO_SIZE+3, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s readChipInfo: ERROR %02X\n", tag, ERROR_I2C_R);
ret = ERROR_I2C_R;
goto FAIL;
}
logError(0, "%s Read data ok! \n", tag);
logError(0, "%s Starting parsing of data... \n", tag);
if (data[0] != HEADER_SIGNATURE) {
logError(1, "%s readChipInfo: ERROR %02X The Header Signature was wrong! %02X != %02X \n", tag, ERROR_WRONG_COMP_SIGN, data[0], HEADER_SIGNATURE);
ret = ERROR_WRONG_COMP_SIGN;
goto FAIL;
}
u8ToU16_le(&data[1], &answer);
if (answer != CHIP_INFO) {
logError(1, "%s readChipInfo: ERROR %02X\n", tag, ERROR_DIFF_COMP_TYPE);
ret = ERROR_DIFF_COMP_TYPE;
goto FAIL;
}
index += 3;
ftsInfo.u8_loadCnt = data[index++];
ftsInfo.u8_infoVer = data[index++];
u8ToU16(&data[index], &ftsInfo.u16_ftsdId);
index += 2;
ftsInfo.u8_ftsdVer = data[index++];
ftsInfo.u8_ftsaId = data[index++];
ftsInfo.u8_ftsaVer = data[index++];
ftsInfo.u8_tchRptVer = data[index++];
logError(1, "%s External Release = ", tag);
for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
ftsInfo.u8_extReleaseInfo[i] = data[index++];
logError(1, "%02X ", ftsInfo.u8_extReleaseInfo[i]);
}
logError(1, "\n");
for (i = 0; i < sizeof(ftsInfo.u8_custInfo); i++) {
ftsInfo.u8_custInfo[i] = data[index++];
}
u8ToU16(&data[index], &ftsInfo.u16_fwVer);
index += 2;
logError(1, "%s FW VERSION = %04X \n", tag, ftsInfo.u16_fwVer);
u8ToU16(&data[index], &ftsInfo.u16_cfgId);
index += 2;
logError(1, "%s CONFIG ID = %04X \n", tag, ftsInfo.u16_cfgId);
ftsInfo.u32_projId = ((data[index + 3] & 0x000000FF) << 24) + ((data[index + 2] & 0x000000FF) << 16) + ((data[index + 1] & 0x000000FF) << 8) + (data[index] & 0x000000FF);
index += 4;
u8ToU16(&data[index], &ftsInfo.u16_scrXRes);
index += 2;
u8ToU16(&data[index], &ftsInfo.u16_scrYRes);
index += 2;
ftsInfo.u8_scrForceLen = data[index++];
logError(1, "%s Force Len = %d \n", tag, ftsInfo.u8_scrForceLen);
ftsInfo.u8_scrSenseLen = data[index++];
logError(1, "%s Sense Len = %d \n", tag, ftsInfo.u8_scrSenseLen);
for (i = 0; i < 8; i++) {
ftsInfo.u64_scrForceEn[i] = data[index++];
}
for (i = 0; i < 8; i++) {
ftsInfo.u64_scrSenseEn[i] = data[index++];
}
ftsInfo.u8_msKeyLen = data[index++];
logError(1, "%s MS Key Len = %d \n", tag, ftsInfo.u8_msKeyLen);
for (i = 0; i < 8; i++) {
ftsInfo.u64_msKeyForceEn[i] = data[index++];
}
for (i = 0; i < 8; i++) {
ftsInfo.u64_msKeySenseEn[i] = data[index++];
}
ftsInfo.u8_ssKeyLen = data[index++];
logError(1, "%s SS Key Len = %d \n", tag, ftsInfo.u8_ssKeyLen);
for (i = 0; i < 8; i++) {
ftsInfo.u64_ssKeyForceEn[i] = data[index++];
}
for (i = 0; i < 8; i++) {
ftsInfo.u64_ssKeySenseEn[i] = data[index++];
}
ftsInfo.u8_frcTchXLen = data[index++];
ftsInfo.u8_frcTchYLen = data[index++];
for (i = 0; i < 8; i++) {
ftsInfo.u64_frcTchForceEn[i] = data[index++];
}
for (i = 0; i < 8; i++) {
ftsInfo.u64_frcTchSenseEn[i] = data[index++];
}
ftsInfo.u8_msScrConfigTuneVer = data[index++];
logError(1, "%s CFG MS TUNING VERSION = %02X \n", tag, ftsInfo.u8_msScrConfigTuneVer);
ftsInfo.u8_msScrLpConfigTuneVer = data[index++];
ftsInfo.u8_msScrHwulpConfigTuneVer = data[index++];
ftsInfo.u8_msKeyConfigTuneVer = data[index++];
ftsInfo.u8_ssTchConfigTuneVer = data[index++];
logError(1, "%s CFG SS TUNING VERSION = %02X \n", tag, ftsInfo.u8_ssTchConfigTuneVer);
ftsInfo.u8_ssKeyConfigTuneVer = data[index++];
ftsInfo.u8_ssHvrConfigTuneVer = data[index++];
ftsInfo.u8_frcTchConfigTuneVer = data[index++];
ftsInfo.u8_msScrCxmemTuneVer = data[index++];
logError(1, "%s CX MS TUNING VERSION = %02X \n", tag, ftsInfo.u8_msScrCxmemTuneVer);
ftsInfo.u8_msScrLpCxmemTuneVer = data[index++];
ftsInfo.u8_msScrHwulpCxmemTuneVer = data[index++];
ftsInfo.u8_msKeyCxmemTuneVer = data[index++];
ftsInfo.u8_ssTchCxmemTuneVer = data[index++];
logError(1, "%s CX SS TUNING VERSION = %02X \n", tag, ftsInfo.u8_ssTchCxmemTuneVer);
ftsInfo.u8_ssKeyCxmemTuneVer = data[index++];
ftsInfo.u8_ssHvrCxmemTuneVer = data[index++];
ftsInfo.u8_frcTchCxmemTuneVer = data[index++];
ftsInfo.u32_mpPassFlag = ((data[index + 3] & 0x000000FF) << 24) + ((data[index + 2] & 0x000000FF) << 16) + ((data[index + 1] & 0x000000FF) << 8) + (data[index] & 0x000000FF);
index += 4;
logError(1, "%s MP SIGNATURE = %08X \n", tag, ftsInfo.u32_mpPassFlag);
ftsInfo.u32_featEn = ((data[index + 3] & 0x000000FF) << 24) + ((data[index + 2] & 0x000000FF) << 16) + ((data[index + 1] & 0x000000FF) << 8) + (data[index] & 0x000000FF);
index += 4;
ftsInfo.u32_echoEn = ((data[index + 3] & 0x000000FF) << 24) + ((data[index + 2] & 0x000000FF) << 16) + ((data[index + 1] & 0x000000FF) << 8) + (data[index] & 0x000000FF);
index += 4;
logError(1, "%s FEATURES = %08X \n", tag, ftsInfo.u32_echoEn);
logError(1, "%s Parsed %d bytes! \n", tag, index);
if (index != CHIP_INFO_SIZE + 3) {
logError(1, "%s readChipInfo: index = %d different from %d ERROR %02X\n", tag, index, CHIP_INFO_SIZE+3, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
logError(1, "%s Chip Info Read DONE!\n", tag);
return OK;
FAIL:
defaultChipInfo(isI2cError(ret));
return ret;
}

View File

@ -0,0 +1,146 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS functions for getting Initialization Data *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsCrossCompile.h"
#include "ftsSoftware.h"
#define COMP_DATA_READ_RETRY 2
/* Bytes dimension of Compensation Data Format */
#define COMP_DATA_HEADER 8
#define COMP_DATA_GLOBAL 8
#define HEADER_SIGNATURE 0xA5
/* Possible Compensation/Frame Data Type */
#define GENERAL_TUNING 0x0100
#define MS_TOUCH_ACTIVE 0x0200
#define MS_TOUCH_LOW_POWER 0x0400
#define MS_TOUCH_ULTRA_LOW_POWER 0x0800
#define MS_KEY 0x1000
#define SS_TOUCH 0x2000
#define SS_KEY 0x4000
#define SS_HOVER 0x8000
#define SS_PROXIMITY 0x0001
#define CHIP_INFO 0xFFFF
#define TIMEOUT_REQU_COMP_DATA 1000 /* ms */
/* CHIP INFO */
#define CHIP_INFO_SIZE 138/* bytes to read from framebuffer (exclude the signature and the type because already checked during the reading) */
#define EXTERNAL_RELEASE_INFO_SIZE 8/* bytes */
typedef struct {
int force_node, sense_node;
u16 type;
} DataHeader;
typedef struct {
DataHeader header;
u8 tuning_ver;
u8 cx1;
u8 *node_data;
int node_data_size;
} MutualSenseData;
typedef struct {
DataHeader header;
u8 tuning_ver;
u8 f_ix1, s_ix1;
u8 f_cx1, s_cx1;
u8 f_max_n, s_max_n;
u8 *ix2_fm;
u8 *ix2_sn;
u8 *cx2_fm;
u8 *cx2_sn;
} SelfSenseData;
typedef struct {
DataHeader header;
u8 ftsd_lp_timer_cal0;
u8 ftsd_lp_timer_cal1;
u8 ftsd_lp_timer_cal2;
u8 ftsd_lp_timer_cal3;
u8 ftsa_lp_timer_cal0;
u8 ftsa_lp_timer_cal1;
} GeneralData;
typedef struct {
u8 u8_loadCnt; /* 03 - Load Counter */
u8 u8_infoVer; /* 04 - New chip info version */
u16 u16_ftsdId; /* 05 - FTSD ID */
u8 u8_ftsdVer; /* 07 - FTSD version */
u8 u8_ftsaId; /* 08 - FTSA ID */
u8 u8_ftsaVer; /* 09 - FTSA version */
u8 u8_tchRptVer; /* 0A - Touch report version (e.g. ST, Samsung etc) */
u8 u8_extReleaseInfo[EXTERNAL_RELEASE_INFO_SIZE]; /* 0B - External release information */
u8 u8_custInfo[12]; /* 13 - Customer information */
u16 u16_fwVer; /* 1F - Firmware version */
u16 u16_cfgId; /* 21 - Configuration ID */
u32 u32_projId; /* 23 - Project ID */
u16 u16_scrXRes; /* 27 - X resolution on main screen */
u16 u16_scrYRes; /* 29 - Y resolution on main screen */
u8 u8_scrForceLen; /* 2B - Number of force channel on main screen */
u8 u8_scrSenseLen; /* 2C - Number of sense channel on main screen */
u8 u64_scrForceEn[8]; /* 2D - Force channel enabled on main screen */
u8 u64_scrSenseEn[8]; /* 35 - Sense channel enabled on main screen */
u8 u8_msKeyLen; /* 3D - Number of MS Key channel */
u8 u64_msKeyForceEn[8]; /* 3E - MS Key force channel enable */
u8 u64_msKeySenseEn[8]; /* 46 - MS Key sense channel enable */
u8 u8_ssKeyLen; /* 4E - Number of SS Key channel */
u8 u64_ssKeyForceEn[8]; /* 4F - SS Key force channel enable */
u8 u64_ssKeySenseEn[8]; /* 57 - SS Key sense channel enable */
u8 u8_frcTchXLen; /* 5F - Number of force touch force channel */
u8 u8_frcTchYLen; /* 60 - Number of force touch sense channel */
u8 u64_frcTchForceEn[8]; /* 61 - Force touch force channel enable */
u8 u64_frcTchSenseEn[8]; /* 69 - Force touch sense channel enable */
u8 u8_msScrConfigTuneVer; /* 71 - MS screen tuning version in config */
u8 u8_msScrLpConfigTuneVer; /* 72 - MS screen LP mode tuning version in config */
u8 u8_msScrHwulpConfigTuneVer; /* 73 - MS screen ultra low power mode tuning version in config */
u8 u8_msKeyConfigTuneVer; /* 74 - MS Key tuning version in config */
u8 u8_ssTchConfigTuneVer; /* 75 - SS touch tuning version in config */
u8 u8_ssKeyConfigTuneVer; /* 76 - SS Key tuning version in config */
u8 u8_ssHvrConfigTuneVer; /* 77 - SS hover tuning version in config */
u8 u8_frcTchConfigTuneVer; /* 78 - Force touch tuning version in config */
u8 u8_msScrCxmemTuneVer; /* 79 - MS screen tuning version in cxmem */
u8 u8_msScrLpCxmemTuneVer; /* 7A - MS screen LP mode tuning version in cxmem */
u8 u8_msScrHwulpCxmemTuneVer; /* 7B - MS screen ultra low power mode tuning version in cxmem */
u8 u8_msKeyCxmemTuneVer; /* 7C - MS Key tuning version in cxmem */
u8 u8_ssTchCxmemTuneVer; /* 7D - SS touch tuning version in cxmem */
u8 u8_ssKeyCxmemTuneVer; /* 7E - SS Key tuning version in cxmem */
u8 u8_ssHvrCxmemTuneVer; /* 7F - SS hover tuning version in cxmem */
u8 u8_frcTchCxmemTuneVer; /* 80 - Force touch tuning version in cxmem */
u32 u32_mpPassFlag; /* 81 - Mass production pass flag */
u32 u32_featEn; /* 85 - Supported features */
u32 u32_echoEn; /* 89 - enable of particular features: first bit is Echo Enables */
} chipInfo;
int requestCompensationData(u16 type);
int readCompensationDataHeader(u16 type, DataHeader *header, u16 *address);
int readMutualSenseGlobalData(u16 *address, MutualSenseData *global);
int readMutualSenseNodeData(u16 address, MutualSenseData *node);
int readMutualSenseCompensationData(u16 type, MutualSenseData *data);
int readSelfSenseGlobalData(u16 *address, SelfSenseData *global);
int readSelfSenseNodeData(u16 address, SelfSenseData *node);
int readSelfSenseCompensationData(u16 type, SelfSenseData *data);
int readGeneralGlobalData(u16 address, GeneralData *global);
int readGeneralCompensationData(u16 type, GeneralData *data);
int defaultChipInfo(int i2cError);
int readChipInfo(int doRequest);

View File

@ -0,0 +1,43 @@
#include "ftsCrossCompile.h"
#include "ftsError.h"
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/regulator/consumer.h>
#include <linux/of_gpio.h>
/* #include <linux/sec_sysfs.h> */
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/spi/spidev.h>
#include <linux/fcntl.h>
#include <linux/syscalls.h>
/* static char tag[8]="[ FTS ]\0"; */
void *stmalloc(size_t size)
{
return kmalloc(size, GFP_KERNEL);
}
void stfree(void *ptr)
{
kfree(ptr);
}

View File

@ -0,0 +1,34 @@
/* #define NDK */
/* #define DEBUG */
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/regulator/consumer.h>
#include <linux/of_gpio.h>
/* #include <linux/sec_sysfs.h> */
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/spi/spidev.h>
#include <linux/fcntl.h>
#include <linux/syscalls.h>
void *stmalloc(size_t size);
void stfree(void *ptr);

View File

@ -0,0 +1,105 @@
/*
***************************************************************************
* STMicroelectronics
**************************************************************************
* marco.cali@st.com
**************************************************************************
*
* FTS error/info kernel log reporting
*
**************************************************************************
**************************************************************************
*/
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/completion.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include "../fts.h"
#include "ftsCrossCompile.h"
#include "ftsError.h"
#include "ftsIO.h"
#include "ftsTool.h"
void logError(int force, const char *msg, ...)
{
if (force == 1
#ifdef DEBUG
|| 1
#endif
) {
va_list args;
va_start(args, msg);
vprintk(msg, args);
va_end(args);
}
}
int isI2cError(int error)
{
if (((error & 0x000000FF) >= (ERROR_I2C_R & 0x000000FF)) && ((error & 0x000000FF) <= (ERROR_I2C_O & 0x000000FF)))
return 1;
else
return 0;
}
int errorHandler(u8 *event, int size)
{
int res = OK;
struct fts_ts_info *info = NULL;
if (getClient() != NULL)
info = i2c_get_clientdata(getClient());
if (info != NULL && event != NULL && size > 1 && event[0] == EVENTID_ERROR_EVENT) {
logError(1, "%s errorHandler: Starting handling...\n", tag);
switch (event[1])
/* TODO: write an error log for undefinied command subtype 0xBA*/
{
case EVENT_TYPE_ESD_ERROR: /* esd */
res = fts_chip_powercycle(info);
if (res < OK) {
logError(1, "%s errorHandler: Error performing powercycle ERROR %08X\n", tag, res);
}
res = fts_system_reset();
if (res < OK) {
logError(1, "%s errorHandler: Cannot reset the device ERROR %08X\n", tag, res);
}
res = (ERROR_HANDLER_STOP_PROC|res);
break;
case EVENT_TYPE_WATCHDOG_ERROR: /* watchdog */
res = fts_system_reset();
if (res < OK) {
logError(1, "%s errorHandler: Cannot reset the device ERROR %08X\n", tag, res);
}
res = (ERROR_HANDLER_STOP_PROC|res);
break;
default:
logError(1, "%s errorHandler: No Action taken! \n", tag);
break;
}
logError(1, "%s errorHandler: handling Finished! res = %08X\n", tag, res);
return res;
}
logError(1, "%s errorHandler: event Null or not correct size! ERROR %08X \n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}

View File

@ -0,0 +1,75 @@
/*
**************************************************************************
** STMicroelectronics
**************************************************************************
** marco.cali@st.com
**************************************************************************
*
* FTS error/info kernel log reporting
*
**************************************************************************
**************************************************************************
*/
/*FIRST LEVEL ERROR CODE*/
#define OK ((int)0x00000000) /*No ERROR*/
#define ERROR_ALLOC ((int)0x80000001) /*allocation of memory failed*/
#define ERROR_I2C_R ((int)0x80000002) /*i2c read failed*/
#define ERROR_I2C_W ((int)0x80000003) /*i2c write failed*/
#define ERROR_I2C_WR ((int)0x80000004) /*i2c write/read failed*/
#define ERROR_I2C_O ((int)0x80000005) /*error during opening a i2c device*/
#define ERROR_OP_NOT_ALLOW ((int)0x80000006) /*operation not allowed*/
#define ERROR_TIMEOUT ((int)0x80000007) /*timeout expired! exceed the max number of retries or the max waiting time*/
#define ERROR_FILE_NOT_FOUND ((int)0x80000008) /*the file that i want to open is not found*/
#define ERROR_FILE_PARSE ((int)0x80000009) /*error during parsing the file*/
#define ERROR_FILE_READ ((int)0x8000000A) /*error during reading the file*/
#define ERROR_LABEL_NOT_FOUND ((int)0x8000000B) /*label not found*/
#define ERROR_FW_NO_UPDATE ((int)0x8000000C) /*fw in the chip newer than the one in the memmh*/
#define ERROR_FLASH_UNKNOWN ((int)0x8000000D) /*flash status busy or unknown*/
/*SECOND LEVEL ERROR CODE*/
#define ERROR_DISABLE_INTER ((int)0x80000200) /*unable to disable the interrupt*/
#define ERROR_ENABLE_INTER ((int)0x80000300) /*unable to activate the interrup*/
#define ERROR_READ_B2 ((int)0x80000400) /*B2 command failed*/
#define ERROR_GET_OFFSET ((int)0x80000500) /*unable to read an offset from memory*/
#define ERROR_GET_FRAME_DATA ((int)0x80000600) /*unable to retrieve the data of a required frame*/
#define ERROR_DIFF_COMP_TYPE ((int)0x80000700) /*FW answers with an event that has a different address respect the request done*/
#define ERROR_WRONG_COMP_SIGN ((int)0x80000800) /*the signature of the compensation data is not A5*/
#define ERROR_SENSE_ON_FAIL ((int)0x80000900) /*the command Sense On failed*/
#define ERROR_SENSE_OFF_FAIL ((int)0x80000A00) /*the command Sense Off failed*/
#define ERROR_SYSTEM_RESET_FAIL ((int)0x80000B00) /*the command SYSTEM RESET failed*/
#define ERROR_FLASH_NOT_READY ((int)0x80000C00) /*flash status not ready within a timeout*/
#define ERROR_FW_VER_READ ((int)0x80000D00) /*unable to retrieve fw_vers or the config_id*/
#define ERROR_GESTURE_ENABLE_FAIL ((int)0x80000E00) /*unable to enable/disable the gesture*/
#define ERROR_GESTURE_START_ADD ((int)0x80000F00) /*unable to start to add custom gesture*/
#define ERROR_GESTURE_FINISH_ADD ((int)0x80001000) /*unable to finish to add custom gesture*/
#define ERROR_GESTURE_DATA_ADD ((int)0x80001100) /*unable to add custom gesture data*/
#define ERROR_GESTURE_REMOVE ((int)0x80001200) /*unable to remove custom gesture data*/
#define ERROR_FEATURE_ENABLE_DISABLE ((int)0x80001300) /*unable to enable/disable a feature mode in the IC*/
/*THIRD LEVEL ERROR CODE*/
#define ERROR_CH_LEN ((int)0x80010000) /*unable to retrieve the force and/or sense length*/
#define ERROR_REQU_COMP_DATA ((int)0x80020000) /*compensation data request failed*/
#define ERROR_COMP_DATA_HEADER ((int)0x80030000) /*unable to retrieve the compensation data header*/
#define ERROR_COMP_DATA_GLOBAL ((int)0x80040000) /*unable to retrieve the global compensation data*/
#define ERROR_COMP_DATA_NODE ((int)0x80050000) /*unable to retrieve the compensation data for each node*/
#define ERROR_TEST_CHECK_FAIL ((int)0x80060000) /*check of production limits or of fw answers failed*/
#define ERROR_MEMH_READ ((int)0x80070000) /*memh reading failed*/
#define ERROR_FLASH_BURN_FAILED ((int)0x80080000) /*flash burn failed*/
#define ERROR_MS_TUNING ((int)0x80090000) /*ms tuning failed*/
#define ERROR_SS_TUNING ((int)0x800A0000) /*ss tuning failed*/
#define ERROR_LP_TIMER_TUNING ((int)0x800B0000) /*lp timer calibration failed*/
#define ERROR_SAVE_CX_TUNING ((int)0x800C0000) /*save cx data to flash failed*/
#define ERROR_HANDLER_STOP_PROC ((int)0x800D0000) /*stop the poll of the FIFO if particular errors are found*/
#define ERROR_CHECK_ECHO_FAIL ((int)0x800E0000) /*unable to retrieve echo event*/
/*FOURTH LEVEL ERROR CODE*/
#define ERROR_PROD_TEST_DATA ((int)0x81000000) /*production data test failed*/
#define ERROR_FLASH_PROCEDURE ((int)0x82000000) /*complete flash procedure failed*/
#define ERROR_PROD_TEST_ITO ((int)0x83000000) /*production ito test failed*/
#define ERROR_PROD_TEST_INITIALIZATION ((int)0x84000000) /*production initialization test failed*/
#define ERROR_GET_INIT_STATUS ((int)0x85000000) /*mismatch of the MS or SS tuning_version*/
void logError(int force, const char *msg, ...);
int isI2cError(int error);
int errorHandler(u8 *event, int size);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS API for Flashing the IC *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsSoftware.h"
/* Flash possible status */
#define FLASH_READY 0
#define FLASH_BUSY 1
#define FLASH_UNKNOWN -1
#define FLASH_STATUS_BYTES 1
/* Flash timing parameters */
#define FLASH_RETRY_COUNT 1000
#define FLASH_WAIT_BEFORE_RETRY 50 /* ms */
#define FLASH_WAIT_TIME 200 /* ms */
/* PATHS FW FILES */
/* #define PATH_FILE_FW "fw.memh" */
#ifdef FTM3_CHIP
#define PATH_FILE_FW "st_fts.bin"
#else
#define PATH_FILE_FW "st_fts.ftb" /* new bin file structure */
#endif
#ifndef FTM3_CHIP
#define FLASH_CHUNK (64*1024)
#define DMA_CHUNK 32
#endif
typedef struct {
u8 *data;
u16 fw_ver;
u16 config_id;
u8 externalRelease[EXTERNAL_RELEASE_INFO_SIZE];
int data_size;
#ifndef FTM3_CHIP
u32 sec0_size;
u32 sec1_size;
u32 sec2_size;
u32 sec3_size;
#endif
} Firmware;
#ifdef FTM3_CHIP
int flash_status(void);
int flash_status_ready(void);
int wait_for_flash_ready(void);
int parseBinFile(const char *pathToFile, u8 **data, int *length, int dimension);
/* int parseMemhFile(const char* pathToFile, u8** data, int* length, int dimension); */
#else
int wait_for_flash_ready(u8 type);
int fts_warm_boot(void);
int parseBinFile(const char *pathToFile, Firmware *fw, int keep_cx);
int flash_erase_unlock(void);
int flash_full_erase(void);
int start_flash_dma(void);
int fillFlash(u32 address, u8 *data, int size);
#endif
int flash_unlock(void);
int fillMemory(u32 address, u8 *data, int size);
int getFirmwareVersion(u16 *fw_vers, u16 *config_id);
int readFwFile(const char *path, Firmware *fw, int keep_cx);
int flash_burn(Firmware fw, int force_burn);
int flashProcedure(const char *path, int force, int keep_cx);

View File

@ -0,0 +1,569 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS functions for getting frames *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsCrossCompile.h"
#include "ftsCompensation.h"
#include "ftsError.h"
#include "ftsFrame.h"
#include "ftsHardware.h"
#include "ftsIO.h"
#include "ftsSoftware.h"
#include "ftsTool.h"
#include "ftsTime.h"
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <stdarg.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/time.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/regulator/consumer.h>
#include <linux/of_gpio.h>
/* #include <linux/sec_sysfs.h> */
static char tag[8] = "[ FTS ]\0";
static int sense_len, force_len;
/*int getOffsetFrame(u16 address, u16 *offset)
{
u8 data[2];
u8 cmd = { FTS_CMD_FRAMEBUFFER_R };
if (readCmdU16(cmd, address, data, OFFSET_LENGTH, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s getOffsetFrame: ERROR %02X\n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
else {
u8ToU16(data, offset);
logError(0, "%s %s", tag, printHex("Offest = ", data, OFFSET_LENGTH));
return OK;
}
}*/
int getChannelsLength(void)
{
int ret;
u8 *data = (u8 *)kmalloc(2*sizeof(u8), GFP_KERNEL);
if (data == NULL) {
logError(1, "%s getChannelsLength: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = readB2(ADDR_SENSE_LEN, data, 2);
if (ret < OK) {
logError(1, "%s getChannelsLength: ERROR %02X\n", tag, ERROR_READ_B2);
return (ret|ERROR_READ_B2);
}
sense_len = (int)data[0];
force_len = (int)data[1];
logError(0, "%s Force_len = %d Sense_Len = %d\n", tag, force_len, sense_len);
kfree(data);
return OK;
}
int getFrameData(u16 address, int size, short **frame)
{
int i, j, ret;
u8 *data = (u8 *)kmalloc(size*sizeof(u8), GFP_KERNEL);
if (data == NULL) {
logError(1, "%s getFrameData: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = readCmdU16(FTS_CMD_FRAMEBUFFER_R, address, data, size, DUMMY_FRAMEBUFFER);
if (ret < OK) {
logError(1, "%s getFrameData: ERROR %02X\n", tag, ERROR_I2C_R);
kfree(data);
return ERROR_I2C_R;
}
j = 0;
for (i = 0; i < size; i += 2) {
(*frame)[j] = (short)((data[i + 1] << 8) + data[i]);
j++;
}
kfree(data);
return OK;
}
/*int getMSFrame(u16 type, short **frame, int keep_first_row)
{
u16 offset;
int size, ret;
if (getSenseLen() == 0 || getForceLen() == 0) {
ret=getChannelsLength();
if (ret<OK) {
logError(1, "%s getMSFrame: ERROR %02X\n", tag,ERROR_CH_LEN);
return (ret|ERROR_CH_LEN);
}
}
ret = getOffsetFrame(type, &offset);
if (ret<OK) {
logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_GET_OFFSET);
return (ret | ERROR_GET_OFFSET);
}
switch (type) {
case ADDR_RAW_TOUCH:
case ADDR_FILTER_TOUCH:
case ADDR_NORM_TOUCH:
case ADDR_CALIB_TOUCH:
if (keep_first_row ==1)
size = ((force_len+1)*sense_len);
else {
size = ((force_len)*sense_len);
offset+= (sense_len * BYTES_PER_NODE);
}
break;
default:
logError(1, "%s getMSFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
*frame = (short*)kmalloc(size*sizeof(short), GFP_KERNEL);
if (*frame==NULL) {
logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret=getFrameData(offset, size*BYTES_PER_NODE, frame);
if (ret<OK) {
logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
return (ret|ERROR_GET_FRAME_DATA);
}
logError(0, "%s Frame acquired!\n", tag);
return size;
}
int getMSKeyFrame(u16 type, short **frame) {
u16 offset;
int size, ret;
u16 address;
MutualSenseData data;
if (type != ADDR_RAW_MS_KEY) {
logError(1, "%s getMSKeyFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = getOffsetFrame(type, &offset);
if (ret<OK) {
logError(1, "%s getMSKeyFrame: ERROR %02X\n", tag, ERROR_GET_OFFSET);
return (ret | ERROR_GET_OFFSET);
}
ret = requestCompensationData(MS_KEY);
if (ret < OK) {
logError(1, "%s getMSKeyFrame: readMutualSenseCompensationData ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
return (ret | ERROR_REQU_COMP_DATA);
}
ret = readCompensationDataHeader(MS_KEY, &(data.header), &address);
if (ret < OK) {
logError(1, "%s getMSKeyFrame: readMutualSenseCompensationData ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
return (ret | ERROR_COMP_DATA_HEADER);
}
if (data.header.force_node>data.header.sense_node)
size = data.header.force_node;
else
size = data.header.sense_node;
*frame = (short*)kmalloc(size*sizeof(short), GFP_KERNEL);
if (frame == NULL) {
logError(1, "%s getMSKeyFrame: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = getFrameData(offset, size*BYTES_PER_NODE, frame);
if (ret<OK) {
logError(1, "%s getMSKeyFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
return (ret | ERROR_GET_FRAME_DATA);
}
logError(0, "%s Frame acquired!\n", tag);
}
int getSSFrame(u16 type, short **frame) {
u16 offset;
int size, ret;
if (getSenseLen() == 0 || getForceLen() == 0) {
ret = getChannelsLength();
if (ret<0) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_CH_LEN);
return (ret | ERROR_CH_LEN);
}
}
switch (type) {
case ADDR_RAW_HOVER_FORCE:
case ADDR_FILTER_HOVER_FORCE:
case ADDR_NORM_HOVER_FORCE:
case ADDR_CALIB_HOVER_FORCE:
case ADDR_RAW_PRX_FORCE:
case ADDR_FILTER_PRX_FORCE:
case ADDR_NORM_PRX_FORCE:
case ADDR_CALIB_PRX_FORCE:
size = ((force_len)* 1);
break;
case ADDR_RAW_HOVER_SENSE:
case ADDR_FILTER_HOVER_SENSE:
case ADDR_NORM_HOVER_SENSE:
case ADDR_CALIB_HOVER_SENSE:
case ADDR_RAW_PRX_SENSE:
case ADDR_FILTER_PRX_SENSE:
case ADDR_NORM_PRX_SENSE:
case ADDR_CALIB_PRX_SENSE:
size = ((1)*sense_len);
break;
default:
logError(1, "%s getSSFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = getOffsetFrame(type, &offset);
if (ret<OK) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_GET_OFFSET);
return (ret | ERROR_GET_OFFSET);
}
*frame = (short*)kmalloc(size*sizeof(short), GFP_KERNEL);
if (*frame == NULL) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = getFrameData(offset, size*BYTES_PER_NODE, frame);
if (ret<OK) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
return (ret | ERROR_GET_FRAME_DATA);
}
logError(0, "%s Frame acquired!\n", tag);
return size;
}
int getNmsFrame(u16 type, short ***frames, int *size, int keep_first_row, int fs, int n) {
int i;
StopWatch global, local;
int temp;
*frames = (short **)kmalloc(n*sizeof(short *), GFP_KERNEL);
if (*frames == NULL) {
logError(1, "%s getNmsFrame: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
fs = (1*1000 / fs) ;
startStopWatch(&global);
for (i = 0; i < n; i++) {
startStopWatch(&local);
*size = getMSFrame(type, ((*frames)+i), keep_first_row);
if (*size < OK) {
logError(1, "%s getNFrame: getFrame failed\n",tag);
return *size;
}
stopStopWatch(&local);
temp = elapsedMillisecond(&local);
logError(0, "%s Iteration %d performed in %d ms... the process wait for %ld ms\n\n", tag, i, temp, (unsigned long)(fs - temp));
if (temp < fs)
msleep((unsigned long)(fs - temp));
}
stopStopWatch(&global);
temp = elapsedMillisecond(&global);
logError(0, "%s Global Iteration performed in %d ms\n", tag, temp);
temp /= n;
logError(0, "%s Mean Iteration performed in %d ms\n", tag, temp);
return (1000 / (temp));
}*/
int getSenseLen(void)
{
int ret;
if (sense_len != 0)
return sense_len;
ret = getChannelsLength();
if (ret < OK)
return ret;
else
return sense_len;
}
int getForceLen(void)
{
int ret;
if (force_len != 0)
return force_len;
ret = getChannelsLength();
if (ret < OK)
return ret;
else
return force_len;
}
int requestFrame(u16 type)
{
int retry = 0;
int ret;
u16 answer;
int event_to_search[1];
u8 readEvent[FIFO_EVENT_SIZE];
u8 cmd[3] = { FTS_CMD_REQU_FRAME_DATA, 0x00, 0x00 };
/* B7 is the command for asking frame data */
event_to_search[0] = (int)EVENTID_FRAME_DATA_READ;
u16ToU8(type, &cmd[1]);
while (retry < FRAME_DATA_READ_RETRY) {
logError(0, "%s %s", tag, printHex("Command = ", cmd, 3));
ret = fts_writeFwCmd(cmd, 3);
/* send the request to the chip to load in memory the Frame Data */
if (ret < OK) {
logError(1, "%s requestFrame: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
ret = pollForEvent(event_to_search, 1, readEvent, TIMEOUT_REQU_COMP_DATA);
if (ret < OK) {
logError(0, "%s Event did not Found at %d attemp!\n", tag, retry + 1);
retry += 1;
} else {
retry = 0;
break;
}
}
if (retry == FRAME_DATA_READ_RETRY) {
logError(1, "%s requestFrame: ERROR %02X\n", tag, ERROR_TIMEOUT);
return ERROR_TIMEOUT;
}
u8ToU16_le(&readEvent[1], &answer);
if (answer == type)
return OK;
logError(1, "%s The event found has a different type of Frame data ERROR %02X\n", tag, ERROR_DIFF_COMP_TYPE);
return ERROR_DIFF_COMP_TYPE;
}
int readFrameDataHeader(u16 type, DataHeader *header)
{
u16 offset = ADDR_FRAMEBUFFER_DATA;
u16 answer;
u8 data[FRAME_DATA_HEADER];
if (readCmdU16(FTS_CMD_FRAMEBUFFER_R, offset, data, FRAME_DATA_HEADER, DUMMY_FRAMEBUFFER) < 0) {
logError(1, "%s readFrameDataHeader: ERROR %02X\n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
logError(0, "%s Read Data Header done!\n", tag);
if (data[0] != FRAME_HEADER_SIGNATURE) {
logError(1, "%s readFrameDataHeader: ERROR %02X The Header Signature was wrong! %02X != %02X\n", tag, ERROR_WRONG_COMP_SIGN, data[0], HEADER_SIGNATURE);
return ERROR_WRONG_COMP_SIGN;
}
u8ToU16_le(&data[1], &answer);
if (answer != type) {
logError(1, "%s readFrameDataHeader: ERROR %02X\n", tag, ERROR_DIFF_COMP_TYPE);
return ERROR_DIFF_COMP_TYPE;
}
logError(0, "%s Type of Frame data OK!\n", tag);
header->type = type;
header->force_node = (int)data[4];
header->sense_node = (int)data[5];
return OK;
}
int getMSFrame2(u16 type, MutualSenseFrame *frame)
{
u16 offset = ADDR_FRAMEBUFFER_DATA+FRAME_DATA_HEADER;
int size, ret;
if (!(type == MS_TOUCH_ACTIVE || type == MS_TOUCH_LOW_POWER || type == MS_TOUCH_ULTRA_LOW_POWER || type == MS_KEY)) {
logError(1, "%s getMSFrame: Choose a MS type of frame data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = requestFrame(type);
if (ret < 0) {
logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
return (ret | ERROR_REQU_COMP_DATA);
}
ret = readFrameDataHeader(type, &(frame->header));
if (ret < 0) {
logError(1, "%s readMutualSenseCompensationData: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
return (ret | ERROR_COMP_DATA_HEADER);
}
switch (type) {
case MS_TOUCH_ACTIVE:
case MS_TOUCH_LOW_POWER:
case MS_TOUCH_ULTRA_LOW_POWER:
size = frame->header.force_node*frame->header.sense_node;
break;
case MS_KEY:
if (frame->header.force_node > frame->header.sense_node)
/* or use directly the number in the ftsChip */
size = frame->header.force_node;
else
size = frame->header.sense_node;
frame->header.force_node = 1;
frame->header.sense_node = size;
break;
default:
logError(1, "%s getMSFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
frame->node_data = (short *)kmalloc(size*sizeof(short), GFP_KERNEL);
if (frame->node_data == NULL) {
logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = getFrameData(offset, size*BYTES_PER_NODE, &(frame->node_data));
if (ret < OK) {
logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
return (ret | ERROR_GET_FRAME_DATA);
}
/* if you want to access one node i,j, you should compute the offset like: offset = i*columns + j = > frame[i, j] */
logError(0, "%s Frame acquired!\n", tag);
frame->node_data_size = size;
return size; /* return the number of data put inside frame */
}
int getSSFrame2(u16 type, SelfSenseFrame *frame)
{
u16 offset = ADDR_FRAMEBUFFER_DATA + FRAME_DATA_HEADER;
int size, ret;
short *temp = NULL;
if (!(type == SS_TOUCH || type == SS_KEY || type == SS_HOVER || type == SS_PROXIMITY)) {
logError(1, "%s getSSFrame: Choose a SS type of frame data ERROR %02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
ret = requestFrame(type);
if (ret < 0) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_REQU_COMP_DATA);
return (ret | ERROR_REQU_COMP_DATA);
}
ret = readFrameDataHeader(type, &(frame->header));
if (ret < 0) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_COMP_DATA_HEADER);
return (ret | ERROR_COMP_DATA_HEADER);
}
switch (type) {
case SS_TOUCH:
case SS_HOVER:
case SS_PROXIMITY:
size = frame->header.force_node+frame->header.sense_node;
break;
default:
logError(1, "%s getSSFrame: ERROR % 02X\n", tag, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
temp = (short *)kmalloc(size*sizeof(short), GFP_KERNEL);
if (temp == NULL) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
ret = getFrameData(offset, size*BYTES_PER_NODE, &temp);
if (ret < OK) {
logError(1, "%s getMSFrame: ERROR %02X\n", tag, ERROR_GET_FRAME_DATA);
return (ret | ERROR_GET_FRAME_DATA);
}
frame->force_data = (short *)kmalloc(frame->header.force_node*sizeof(short), GFP_KERNEL);
if (frame->force_data == NULL) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
memcpy(frame->force_data, temp, frame->header.force_node*sizeof(short));
frame->sense_data = (short *)kmalloc(frame->header.sense_node*sizeof(short), GFP_KERNEL);
if (frame->sense_data == NULL) {
logError(1, "%s getSSFrame: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
memcpy(frame->sense_data, &temp[frame->header.force_node], frame->header.sense_node*sizeof(short));
logError(0, "%s Frame acquired!\n", tag);
kfree(temp);
return size; /* return the number of data put inside frame */
}

View File

@ -0,0 +1,49 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS functions for getting frames *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsSoftware.h"
/* Number of data bytes for each node */
#define BYTES_PER_NODE 2
#define OFFSET_LENGTH 2
#define FRAME_DATA_HEADER 8
#define FRAME_HEADER_SIGNATURE 0xB5
#define FRAME_DATA_READ_RETRY 2
typedef struct {
DataHeader header;
short *node_data;
int node_data_size;
} MutualSenseFrame;
typedef struct {
DataHeader header;
short *force_data;
short *sense_data;
} SelfSenseFrame;
/* int getOffsetFrame(u16 address, u16 *offset); */
int getChannelsLength(void);
int getFrameData(u16 address, int size, short **frame);
/* int getMSFrame(u16 type, short **frame, int keep_first_row); */
/* int getMSKeyFrame(u16 type, short **frame); */
/* int getSSFrame(u16 type, short **frame); */
/* int getNmsFrame(u16 type, short ***frames, int * sizes, int keep_first_row, int fs, int n); */
int getSenseLen(void);
int getForceLen(void);
int requestFrame(u16 type);
int readFrameDataHeader(u16 type, DataHeader *header);
int getMSFrame2(u16 type, MutualSenseFrame *frame);
int getSSFrame2(u16 type, SelfSenseFrame *frame);

View File

@ -0,0 +1,393 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS Gesture Utilities *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsSoftware.h"
#include "ftsError.h"
#include "ftsGesture.h"
#include "ftsIO.h"
#include "ftsTool.h"
static char tag[8] = "[ FTS ]\0";
static u8 gesture_mask[GESTURE_MASK_SIZE] = { 0 };
static u8 custom_gestures[GESTURE_CUSTOM_NUMBER][GESTURE_CUSTOM_POINTS];
static u8 custom_gesture_index[GESTURE_CUSTOM_NUMBER] = { 0 };
int enableGesture(u8 *mask, int size)
{
u8 cmd[size+2];
u8 readData[FIFO_EVENT_SIZE];
int i, res;
int event_to_search[4] = {EVENTID_GESTURE, EVENT_TYPE_ENB, 0x00, GESTURE_ENABLE};
logError(0, "%s Trying to enable gesture...\n", tag);
cmd[0] = FTS_CMD_GESTURE_CMD;
cmd[1] = GESTURE_ENABLE;
if (size <= GESTURE_MASK_SIZE) {
if (mask != NULL) {
for (i = 0; i < size; i++) {
cmd[i + 2] = mask[i];
gesture_mask[i] = gesture_mask[i]|mask[i];
/* back up of the gesture enabled */
}
while (i < GESTURE_MASK_SIZE) {
cmd[i + 2] = gesture_mask[i];
i++;
}
} else {
for (i = 0; i < GESTURE_MASK_SIZE; i++) {
cmd[i + 2] = gesture_mask[i];
}
}
res = fts_writeFwCmd(cmd, GESTURE_MASK_SIZE + 2);
if (res < OK) {
logError(1, "%s enableGesture: ERROR %08X\n", tag, res);
return res;
}
res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
if (res < OK) {
logError(1, "%s enableGesture: pollForEvent ERROR %08X\n", tag, res);
return res;
}
if (readData[4] != 0x00) {
logError(1, "%s enableGesture: ERROR %08X\n", tag, ERROR_GESTURE_ENABLE_FAIL);
return ERROR_GESTURE_ENABLE_FAIL;
}
logError(0, "%s enableGesture DONE!\n", tag);
return OK;
} else {
logError(1, "%s enableGesture: Size not valid! %d > %d ERROR %08X\n", tag, size, GESTURE_MASK_SIZE);
return ERROR_OP_NOT_ALLOW;
}
}
int disableGesture(u8 *mask, int size)
{
u8 cmd[2+GESTURE_MASK_SIZE];
u8 readData[FIFO_EVENT_SIZE];
u8 temp;
int i, res;
int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, 0x00, GESTURE_DISABLE };
logError(0, "%s Trying to disable gesture...\n", tag);
cmd[0] = FTS_CMD_GESTURE_CMD;
cmd[1] = GESTURE_DISABLE;
if (size <= GESTURE_MASK_SIZE) {
if (mask != NULL) {
for (i = 0; i < size; i++) {
cmd[i + 2] = mask[i];
temp = gesture_mask[i] ^ mask[i];
/* enabled XOR disabled */
gesture_mask[i] = temp & gesture_mask[i];
/* disable the gestures that were enabled */
}
while (i < GESTURE_MASK_SIZE) {
cmd[i + 2] = gesture_mask[i];
/* disable all the other gesture not specified */
gesture_mask[i] = 0x00;
i++;
}
} else {
for (i = 0; i < GESTURE_MASK_SIZE; i++) {
cmd[i + 2] = gesture_mask[i];
}
}
res = fts_writeFwCmd(cmd, 2 + GESTURE_MASK_SIZE);
if (res < OK) {
logError(1, "%s disableGesture: ERROR %08X\n", tag, res);
return res;
}
res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
if (res < OK) {
logError(1, "%s disableGesture: pollForEvent ERROR %08X\n", tag, res);
return res;
}
if (readData[4] != 0x00) {
logError(1, "%s disableGesture: ERROR %08X\n", tag, ERROR_GESTURE_ENABLE_FAIL);
return ERROR_GESTURE_ENABLE_FAIL;
}
logError(0, "%s disableGesture DONE!\n", tag);
return OK;
} else {
logError(1, "%s disableGesture: Size not valid! %d > %d ERROR %08X\n", tag, size, GESTURE_MASK_SIZE);
return ERROR_OP_NOT_ALLOW;
}
}
int startAddCustomGesture(u8 gestureID)
{
u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GESTURE_START_ADD, gestureID };
int res;
u8 readData[FIFO_EVENT_SIZE];
int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_START_ADD };
res = fts_writeFwCmd(cmd, 3);
if (res < OK) {
logError(1, "%s startAddCustomGesture: Impossible to start adding custom gesture ID = %02X! ERROR %08X\n", tag, gestureID, res);
return res;
}
res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
if (res < OK) {
logError(1, "%s startAddCustomGesture: start add event not found! ERROR %08X\n", tag, res);
return res;
}
if (readData[2] != gestureID || readData[4] != 0x00) { /* check of gestureID is redundant */
logError(1, "%s startAddCustomGesture: start add event status not OK! ERROR %08X\n", tag, readData[4]);
return ERROR_GESTURE_START_ADD;
}
return OK;
}
int finishAddCustomGesture(u8 gestureID)
{
u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GESTURE_FINISH_ADD, gestureID };
int res;
u8 readData[FIFO_EVENT_SIZE];
int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_FINISH_ADD };
res = fts_writeFwCmd(cmd, 3);
if (res < OK) {
logError(1, "%s finishAddCustomGesture: Impossible to finish adding custom gesture ID = %02X! ERROR %08X\n", tag, gestureID, res);
return res;
}
res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
if (res < OK) {
logError(1, "%s finishAddCustomGesture: finish add event not found! ERROR %08X\n", tag, res);
return res;
}
if (readData[2] != gestureID || readData[4] != 0x00) { /* check of gestureID is redundant */
logError(1, "%s finishAddCustomGesture: finish add event status not OK! ERROR %08X\n", tag, readData[4]);
return ERROR_GESTURE_FINISH_ADD;
}
return OK;
}
int loadCustomGesture(u8 *template, u8 gestureID)
{
int res, i;
int remaining = GESTURE_CUSTOM_POINTS;
int toWrite, offset = 0;
u8 cmd[TEMPLATE_CHUNK + 5];
int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_DATA_ADD };
u8 readData[FIFO_EVENT_SIZE];
logError(0, "%s Starting adding custom gesture procedure...\n", tag);
res = startAddCustomGesture(gestureID);
if (res < OK) {
logError(1, "%s loadCustomGesture: unable to start adding procedure! ERROR %08X\n", tag, res);
return res;
}
cmd[0] = FTS_CMD_GESTURE_CMD;
cmd[1] = GESTURE_DATA_ADD;
cmd[2] = gestureID;
while (remaining > 0) {
if (remaining > TEMPLATE_CHUNK) {
toWrite = TEMPLATE_CHUNK;
} else {
toWrite = remaining;
}
cmd[3] = toWrite;
cmd[4] = offset;
for (i = 0; i < toWrite; i++) {
cmd[i + 5] = template[i];
}
res = fts_writeFwCmd(cmd, toWrite + 5);
if (res < OK) {
logError(1, "%s loadCustomGesture: unable to start adding procedure! ERROR %08X\n", tag, res);
return res;
}
res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
if (res < OK) {
logError(1, "%s loadCustomGesture: add event not found! ERROR %08X\n", tag, res);
return res;
}
if (readData[2] != gestureID || readData[4] != 0x00) { /* check of gestureID is redundant */
logError(1, "%s loadCustomGesture: add event status not OK! ERROR %08X\n", tag, readData[4]);
return ERROR_GESTURE_DATA_ADD;
}
remaining -= toWrite;
offset += toWrite / 2;
}
res = finishAddCustomGesture(gestureID);
if (res < OK) {
logError(1, "%s loadCustomGesture: unable to finish adding procedure! ERROR %08X\n", tag, res);
return res;
}
logError(0, "%s Adding custom gesture procedure DONE!\n", tag);
return OK;
}
int reloadCustomGesture(void)
{
int res, i;
logError(0, "%s Starting reload Gesture Template...\n", tag);
for (i = 0; i < GESTURE_CUSTOM_NUMBER; i++) {
if (custom_gesture_index[i] == 1) {
res = loadCustomGesture(custom_gestures[i], GESTURE_CUSTOM_OFFSET+i);
if (res < OK) {
logError(1, "%s reloadCustomGesture: Impossible to load custom gesture ID = %02X! ERROR %08X\n", tag, GESTURE_CUSTOM_OFFSET + i, res);
return res;
}
}
}
logError(0, "%s Reload Gesture Template DONE!\n", tag);
return OK;
}
int enterGestureMode(int reload)
{
u8 cmd = FTS_CMD_GESTURE_MODE;
int res, ret;
res = fts_disableInterrupt();
if (res < OK) {
logError(1, "%s enterGestureMode: ERROR %08X\n", tag, res|ERROR_DISABLE_INTER);
return res | ERROR_DISABLE_INTER;
}
if (reload == 1) {
res = reloadCustomGesture();
if (res < OK) {
logError(1, "%s enterGestureMode: impossible reload custom gesture! ERROR %08X\n", tag, res);
goto END;
}
res = disableGesture(NULL, 0);
if (res < OK) {
logError(1, "%s enterGestureMode: disableGesture ERROR %08X\n", tag, res);
goto END;
}
res = enableGesture(NULL, 0);
if (res < OK) {
logError(1, "%s enterGestureMode: enableGesture ERROR %08X\n", tag, res);
goto END;
}
}
res = fts_writeFwCmd(&cmd, 1);
if (res < OK) {
logError(1, "%s enterGestureMode: enter gesture mode ERROR %08X\n", tag, res);
goto END;
}
res = OK;
END:
ret = fts_enableInterrupt();
if (ret < OK) {
logError(1, "%s enterGestureMode: fts_enableInterrupt ERROR %08X\n", tag, res | ERROR_ENABLE_INTER);
res |= ret | ERROR_ENABLE_INTER;
}
return res;
}
int addCustomGesture(u8 *data, int size, u8 gestureID)
{
int index, res, i;
index = gestureID - GESTURE_CUSTOM_OFFSET;
logError(0, "%s Starting Custom Gesture Adding procedure...\n", tag);
if (size != GESTURE_CUSTOM_POINTS && gestureID != GES_ID_CUST1 && gestureID != GES_ID_CUST2 && gestureID != GES_ID_CUST3 && gestureID != GES_ID_CUST4 && gestureID && GES_ID_CUST5) {
logError(1, "%s addCustomGesture: Invalid size (%d) or Custom GestureID (%02X)! ERROR %08X\n", tag, size, gestureID, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
for (i = 0; i < GESTURE_CUSTOM_POINTS; i++) {
custom_gestures[index][i] = data[i];
}
res = loadCustomGesture(custom_gestures[index], gestureID);
if (res < OK) {
logError(1, "%s addCustomGesture: impossible to load the custom gesture! ERROR %08X\n", tag, res);
return res;
}
custom_gesture_index[index] = 1;
logError(0, "%s Custom Gesture Adding procedure DONE!\n", tag);
return OK;
}
int removeCustomGesture(u8 gestureID)
{
int res, index;
u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GETURE_REMOVE_CUSTOM, gestureID };
int event_to_search[4] = {EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GETURE_REMOVE_CUSTOM };
u8 readData[FIFO_EVENT_SIZE];
index = gestureID - GESTURE_CUSTOM_OFFSET;
logError(0, "%s Starting Custom Gesture Removing procedure...\n", tag);
if (gestureID != GES_ID_CUST1 && gestureID != GES_ID_CUST2 && gestureID != GES_ID_CUST3 && gestureID != GES_ID_CUST4 && gestureID && GES_ID_CUST5) {
logError(1, "%s removeCustomGesture: Invalid size (%d) or Custom GestureID (%02X)! ERROR %08X\n", tag, gestureID, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
res = fts_writeFwCmd(cmd, 3);/* when a gesture is removed, it is also disabled automatically */
if (res < OK) {
logError(1, "%s removeCustomGesture: Impossible to remove custom gesture ID = %02X! ERROR %08X\n", tag, gestureID, res);
return res;
}
res = pollForEvent(event_to_search, 4, readData, GENERAL_TIMEOUT);
if (res < OK) {
logError(1, "%s removeCustomGesture: remove event not found! ERROR %08X\n", tag, res);
return res;
}
if (readData[2] != gestureID || readData[4] != 0x00) { /* check of gestureID is redundant */
logError(1, "%s removeCustomGesture: remove event status not OK! ERROR %08X\n", tag, readData[4]);
return ERROR_GESTURE_REMOVE;
}
custom_gesture_index[index] = 0;
logError(0, "%s Custom Gesture Remove procedure DONE!\n", tag);
return OK;
}

View File

@ -0,0 +1,74 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS Gesture Utilities *
* *
**************************************************************************
**************************************************************************
*/
#define GESTURE_MASK_SIZE 8
#define GESTURE_CUSTOM_POINTS (30*2)
/* for each custom gesture should be provided 30 points (each point is a couple of x,y) */
#define GESTURE_CUSTOM_NUMBER 5 /* fw support up to 5 custom gestures */
#define TEMPLATE_CHUNK (10*2)
/* number of points to transfer with each I2C transaction */
/* Gesture IDs */
#define GES_ID_DBLTAP 0x01 /* Double Tap */
#define GES_ID_O 0x02 /* 'O' */
#define GES_ID_C 0x03 /* 'C' */
#define GES_ID_M 0x04 /* 'M' */
#define GES_ID_W 0x05 /* 'W' */
#define GES_ID_E 0x06 /* 'e' */
#define GES_ID_HFLIP_L2R 0x07 /* Left to right line */
#define GES_ID_HFLIP_R2L 0x08 /* Right to left line */
#define GES_ID_VFLIP_T2D 0x09 /* Top to bottom line */
#define GES_ID_VFLIP_D2T 0x0A /* Bottom to Top line */
#define GES_ID_L 0x0B /* 'L' */
#define GES_ID_F 0x0C /* 'F' */
#define GES_ID_V 0x0D /* 'V' */
#define GES_ID_AT 0x0E /* '@' */
#define GES_ID_S 0x0F /* 'S' */
#define GES_ID_Z 0x10 /* 'Z' */
#define GES_ID_CUST1 0x11 /* Custom gesture 1 */
#define GES_ID_CUST2 0x12 /* Custom gesture 2 */
#define GES_ID_CUST3 0x13 /* Custom gesture 3 */
#define GES_ID_CUST4 0x14 /* Custom gesture 4 */
#define GES_ID_CUST5 0x15 /* Custom gesture 5 */
#define GES_ID_LEFTBRACE 0x20 /* '<' */
#define GES_ID_RIGHTBRACE 0x21 /* '>' */
#define GESTURE_CUSTOM_OFFSET GES_ID_CUST1
/* Command sub-type */
#define GESTURE_ENABLE 0x01
#define GESTURE_DISABLE 0x02
#define GESTURE_ENB_CHECK 0x03
#define GESTURE_START_ADD 0x10
#define GESTURE_DATA_ADD 0x11
#define GESTURE_FINISH_ADD 0x12
#define GETURE_REMOVE_CUSTOM 0x13
#define GESTURE_CHECK_CUSTOM 0x14
/* Event sub-type */
#define EVENT_TYPE_ENB 0x04
#define EVENT_TYPE_CHECK_ENB 0x03
#define EVENT_TYPE_GESTURE_DTC1 0x01
#define EVENT_TYPE_GESTURE_DTC2 0x02
int disableGesture(u8 *mask, int size);
int enableGesture(u8 *mask, int size);
int startAddCustomGesture(u8 gestureID);
int finishAddCustomGesture(u8 gestureID);
int loadCustomGesture(u8 *template, u8 gestureID);
int reloadCustomGesture(void);
int enterGestureMode(int reload);

View File

@ -0,0 +1,177 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* HW related data *
* *
**************************************************************************
**************************************************************************
*/
#define FTM3_CHIP
/* DUMMY BYTES DATA */
#define DUMMY_HW_REG 1
#define DUMMY_FRAMEBUFFER 1
#define DUMMY_MEMORY 1
/* DIGITAL CHIP INFO */
#ifdef FTM3_CHIP
#define DCHIP_ID_0 0x39
#define DCHIP_ID_1 0x6C
#else
#define DCHIP_ID_0 0x36
#define DCHIP_ID_1 0x70
#endif
#ifdef FTM3_CHIP
#define DCHIP_ID_ADDR 0x0007
#define DCHIP_FW_VER_ADDR 0x000A
#else
#define DCHIP_ID_ADDR 0x0004
#define DCHIP_FW_VER_ADDR 0x000B
#endif
#define DCHIP_FW_VER_BYTE 2
/* CHUNKS */
#define READ_CHUNK (2*1024)
#define WRITE_CHUNK (2*1024)
#define MEMORY_CHUNK (2*1024)
/* PROTOCOL INFO */
#ifdef FTM3_CHIP
#define I2C_SAD 0x49
#else
#define I2C_SAD 0x48
#endif
#define I2C_INTERFACE /* comment if the chip use SPI */
#define ICR_ADDR 0x0024
#define ICR_SPI_VALUE 0x02
/* SYSTEM RESET INFO */
#ifdef FTM3_CHIP
#define SYSTEM_RESET_ADDRESS 0x0023
#define SYSTEM_RESET_VALUE 0x01
#else
#define SYSTEM_RESET_ADDRESS 0x0028
#define SYSTEM_RESET_VALUE 0x80
#endif
/* INTERRUPT INFO */
#ifdef FTM3_CHIP
#define IER_ADDR 0x001C
#else
#define IER_ADDR 0x002C
#endif
#define IER_ENABLE 0x41
#define IER_DISABLE 0x00
/* FLASH COMMAND */
#define FLASH_CMD_UNLOCK 0xF7
#ifdef FTM3_CHIP
#define FLASH_CMD_WRITE_LOWER_64 0xF0
#define FLASH_CMD_WRITE_UPPER_64 0xF1
#define FLASH_CMD_BURN 0xF2
#define FLASH_CMD_ERASE 0xF3
#define FLASH_CMD_READSTATUS 0xF4
#else
#define FLASH_CMD_WRITE_64K 0xF8
#define FLASH_CMD_READ_REGISTER 0xF9
#define FLASH_CMD_WRITE_REGISTER 0xFA
#endif
/* FLASH UNLOCK PARAMETER */
#define FLASH_UNLOCK_CODE0 0x74
#define FLASH_UNLOCK_CODE1 0x45
#ifndef FTM3_CHIP
/* FLASH ERASE and DMA PARAMETER */
#define FLASH_ERASE_UNLOCK_CODE0 0x72
#define FLASH_ERASE_UNLOCK_CODE1 0x03
#define FLASH_ERASE_UNLOCK_CODE2 0x02
#define FLASH_ERASE_CODE0 0x02
#define FLASH_ERASE_CODE1 0xC0
#define FLASH_DMA_CODE0 0x05
#define FLASH_DMA_CODE1 0xC0
#define FLASH_DMA_CONFIG 0x06
#endif
/* FLASH ADDRESS */
#ifdef FTM3_CHIP
#define FLASH_ADDR_SWITCH_CMD 0x00010000
#define FLASH_ADDR_CODE 0x00000000
#define FLASH_ADDR_CONFIG 0x0001E800
#define FLASH_ADDR_CX 0x0001F000
#else
#define ADDR_WARM_BOOT 0x001E
#define WARM_BOOT_VALUE 0x38
#define FLASH_ADDR_CODE 0x00000000
#define FLASH_ADDR_CONFIG 0x0000FC00
#endif
/* CRC ADDR */
#ifdef FTM3_CHIP
#define ADDR_CRC_BYTE0 0x00
#define ADDR_CRC_BYTE1 0x86
#define CRC_MASK 0x02
#else
#define ADDR_CRC_BYTE0 0x00
#define ADDR_CRC_BYTE1 0x74
#define CRC_MASK 0x03
#endif
/* SIZES FW, CODE, CONFIG, MEMH */
#ifdef FTM3_CHIP
#define FW_HEADER_SIZE 32
#define FW_SIZE (int)(128*1024)
#define FW_CODE_SIZE (int)(122*1024)
#define FW_CONFIG_SIZE (int)(2*1024)
#define FW_CX_SIZE (int)(FW_SIZE-FW_CODE_SIZE-FW_CONFIG_SIZE)
#define FW_VER_MEMH_BYTE1 193
#define FW_VER_MEMH_BYTE0 192
#define FW_OFF_CONFID_MEMH_BYTE1 2
#define FW_OFF_CONFID_MEMH_BYTE0 1
#define FW_BIN_VER_OFFSET 4
#define FW_BIN_CONFIG_VER_OFFSET (FW_HEADER_SIZE+FW_CODE_SIZE+1)
#else
#define FW_HEADER_SIZE 64
#define FW_HEADER_SIGNATURE 0xAA55AA55
#define FW_FTB_VER 0x00000001
#define FW_BYTES_ALIGN 4
#define FW_BIN_VER_OFFSET 16
#define FW_BIN_CONFIG_VER_OFFSET 20
#endif
/* FIFO */
#define FIFO_EVENT_SIZE 8
#ifdef FTM3_CHIP
#define FIFO_DEPTH 32
#else
#define FIFO_DEPTH 64
#endif
#define FIFO_CMD_READONE 0x85
#define FIFO_CMD_READALL 0x86
#define FIFO_CMD_LAST 0x87
#define FIFO_CMD_FLUSH 0xA1
/* CONSTANT TOTAL CX */
#define CX1_WEIGHT 4
#define CX2_WEIGHT 1
/* OP CODES FOR MEMORY (based on protocol) */
#define FTS_CMD_HW_REG_R 0xB6
#define FTS_CMD_HW_REG_W 0xB6
#define FTS_CMD_FRAMEBUFFER_R 0xD0
#define FTS_CMD_FRAMEBUFFER_W 0xD0

View File

@ -0,0 +1,403 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* I2C/SPI Communication *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsSoftware.h"
#include "ftsCrossCompile.h"
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <stdarg.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/regulator/consumer.h>
#include <linux/of_gpio.h>
/* #include <linux/sec_sysfs.h> */
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/spi/spidev.h>
static struct i2c_client *client;
static u16 I2CSAD;
#include "ftsError.h"
#include "ftsHardware.h"
#include "ftsIO.h"
#include "ftsTool.h"
static char tag[8] = "[ FTS ]\0";
int openChannel(struct i2c_client *clt)
{
client = clt;
I2CSAD = clt->addr;
logError(1, "%s openChannel: SAD: %02X\n", tag, I2CSAD);
return OK;
}
struct device *getDev(void)
{
if (client != NULL)
return &(client->dev);
else
return NULL;
}
struct i2c_client *getClient(void)
{
if (client != NULL)
return client;
else
return NULL;
}
int fts_readCmd(u8 *cmd, int cmdLength, u8 *outBuf, int byteToRead)
{
int ret = -1;
int retry = 0;
struct i2c_msg I2CMsg[2];
/* write msg */
I2CMsg[0].addr = (__u16)I2CSAD;
I2CMsg[0].flags = (__u16)0;
I2CMsg[0].len = (__u16)cmdLength;
I2CMsg[0].buf = (__u8 *)cmd;
/* read msg */
I2CMsg[1].addr = (__u16)I2CSAD;
I2CMsg[1].flags = I2C_M_RD;
I2CMsg[1].len = byteToRead;
I2CMsg[1].buf = (__u8 *)outBuf;
if (client == NULL)
return ERROR_I2C_O;
while (retry < I2C_RETRY && ret < OK) {
ret = i2c_transfer(client->adapter, I2CMsg, 2);
if (ret >= OK)
break;
retry++;
msleep(I2C_WAIT_BEFORE_RETRY);
}
if (ret < 0) {
logError(1, "%s fts_readCmd: ERROR %02X\n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
return OK;
}
int fts_writeCmd(u8 *cmd, int cmdLength)
{
int ret = -1;
int retry = 0;
struct i2c_msg I2CMsg[2];
I2CMsg[0].addr = (__u16)I2CSAD;
I2CMsg[0].flags = (__u16)0;
I2CMsg[0].len = (__u16)cmdLength;
I2CMsg[0].buf = (__u8 *)cmd;
if (client == NULL)
return ERROR_I2C_O;
while (retry < I2C_RETRY && ret < OK) {
ret = i2c_transfer(client->adapter, I2CMsg, 1);
if (ret >= OK)
break;
retry++;
msleep(I2C_WAIT_BEFORE_RETRY);
/* logError(1, "%s fts_writeCmd: attempt %d\n", tag, retry); */
}
if (ret < 0) {
logError(1, "%s fts_writeCmd: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
return OK;
}
int fts_writeFwCmd(u8 *cmd, int cmdLength)
{
int ret = -1;
int ret2 = -1;
int retry = 0;
struct i2c_msg I2CMsg[2];
I2CMsg[0].addr = (__u16)I2CSAD;
I2CMsg[0].flags = (__u16)0;
I2CMsg[0].len = (__u16)cmdLength;
I2CMsg[0].buf = (__u8 *)cmd;
if (client == NULL)
return ERROR_I2C_O;
while (retry < I2C_RETRY && (ret < OK || ret2 < OK)) {
ret = i2c_transfer(client->adapter, I2CMsg, 1);
retry++;
if (ret >= 0) {
ret2 = checkEcho(cmd, cmdLength);
break;
}
msleep(I2C_WAIT_BEFORE_RETRY);
/* logError(1, "%s fts_writeCmd: attempt %d\n", tag, retry); */
}
if (ret < 0) {
logError(1, "%s fts_writeFwCmd: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
if (ret2 < OK) {
logError(1, "%s fts_writeFwCmd: check echo ERROR %02X\n", tag, ret2);
return (ret|ERROR_I2C_W);
}
return OK;
}
int writeReadCmd(u8 *writeCmd1, int writeCmdLength, u8 *readCmd1,
int readCmdLength, u8 *outBuf, int byteToRead)
{
int ret = -1;
int retry = 0;
struct i2c_msg I2CMsg[3];
/* write msg */
I2CMsg[0].addr = (__u16)I2CSAD;
I2CMsg[0].flags = (__u16)0;
I2CMsg[0].len = (__u16)writeCmdLength;
I2CMsg[0].buf = (__u8 *)writeCmd1;
/* write msg */
I2CMsg[1].addr = (__u16)I2CSAD;
I2CMsg[1].flags = (__u16)0;
I2CMsg[1].len = (__u16)readCmdLength;
I2CMsg[1].buf = (__u8 *)readCmd1;
/* read msg */
I2CMsg[2].addr = (__u16)I2CSAD;
I2CMsg[2].flags = I2C_M_RD;
I2CMsg[2].len = byteToRead;
I2CMsg[2].buf = (__u8 *)outBuf;
if (client == NULL)
return ERROR_I2C_O;
while (retry < I2C_RETRY && ret < OK) {
ret = i2c_transfer(client->adapter, I2CMsg, 3);
if (ret >= OK)
break;
retry++;
msleep(I2C_WAIT_BEFORE_RETRY);
}
if (ret < 0) {
logError(1, "%s writeReadCmd: ERROR %02X\n", tag, ERROR_I2C_WR);
return ERROR_I2C_WR;
}
return OK;
}
int readCmdU16(u8 cmd, u16 address, u8 *outBuf, int byteToRead, int hasDummyByte)
{
int remaining = byteToRead;
int toRead = 0;
u8 rCmd[3] = { cmd, 0x00, 0x00 };
u8 *buff = (u8 *)kmalloc((READ_CHUNK + 1)*sizeof(u8), GFP_KERNEL);
if (buff == NULL) {
logError(1, "%s readCmdU16: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
while (remaining > 0) {
if (remaining >= READ_CHUNK) {
toRead = READ_CHUNK;
remaining -= READ_CHUNK;
} else {
toRead = remaining;
remaining = 0;
}
rCmd[1] = (u8)((address & 0xFF00) >> 8);
rCmd[2] = (u8)(address & 0xFF);
if (hasDummyByte) {
if (fts_readCmd(rCmd, 3, buff, toRead + 1) < 0) {
logError(1, "%s readCmdU16: ERROR %02X\n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
memcpy(outBuf, buff + 1, toRead);
} else {
if (fts_readCmd(rCmd, 3, buff, toRead) < 0)
return ERROR_I2C_R;
memcpy(outBuf, buff, toRead);
}
address += toRead;
outBuf += toRead;
}
kfree(buff);
return OK;
}
int writeCmdU16(u8 WriteCmd, u16 address, u8 *dataToWrite, int byteToWrite)
{
int remaining = byteToWrite;
int toWrite = 0;
u8 *buff = (u8 *)kmalloc((WRITE_CHUNK + 3)*sizeof(u8), GFP_KERNEL);
if (buff == NULL) {
logError(1, "%s writeCmdU16: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
buff[0] = WriteCmd;
while (remaining > 0) {
if (remaining >= WRITE_CHUNK) {
toWrite = WRITE_CHUNK;
remaining -= WRITE_CHUNK;
} else {
toWrite = remaining;
remaining = 0;
}
buff[1] = (u8)((address & 0xFF00) >> 8);
buff[2] = (u8)(address & 0xFF);
memcpy(buff + 3, dataToWrite, toWrite);
if (fts_writeCmd(buff, 3 + toWrite) < 0) {
logError(1, "%s writeCmdU16: ERROR %02\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
address += toWrite;
dataToWrite += toWrite;
}
return OK;
}
int writeCmdU32(u8 writeCmd1, u8 writeCmd2, u32 address, u8 *dataToWrite, int byteToWrite)
{
int remaining = byteToWrite;
int toWrite = 0;
u8 buff1[3] = { writeCmd1, 0x00, 0x00 };
u8 *buff2 = (u8 *)kmalloc((WRITE_CHUNK + 3)*sizeof(u8), GFP_KERNEL);
if (buff2 == NULL) {
logError(1, "%s writeCmdU32: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
buff2[0] = writeCmd2;
while (remaining > 0) {
if (remaining >= WRITE_CHUNK) {
toWrite = WRITE_CHUNK;
remaining -= WRITE_CHUNK;
} else {
toWrite = remaining;
remaining = 0;
}
buff1[1] = (u8)((address & 0xFF000000) >> 24);
buff1[2] = (u8)((address & 0x00FF0000) >> 16);
buff2[1] = (u8)((address & 0x0000FF00) >> 8);
buff2[2] = (u8)(address & 0xFF);
memcpy(buff2 + 3, dataToWrite, toWrite);
if (fts_writeCmd(buff1, 3) < 0) {
logError(1, "%s writeCmdU32: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
if (fts_writeCmd(buff2, 3 + toWrite) < 0) {
logError(1, "%s writeCmdU32: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
address += toWrite;
dataToWrite += toWrite;
}
return OK;
}
int writeReadCmdU32(u8 wCmd, u8 rCmd, u32 address, u8 *outBuf, int byteToRead, int hasDummyByte)
{
int remaining = byteToRead;
int toRead = 0;
u8 reaCmd[3];
u8 wriCmd[3];
u8 *buff = (u8 *)kmalloc((READ_CHUNK + 1)*sizeof(u8), GFP_KERNEL);
if (buff == NULL) {
logError(1, "%s writereadCmd32: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
reaCmd[0] = rCmd;
wriCmd[0] = wCmd;
while (remaining > 0) {
if (remaining >= READ_CHUNK) {
toRead = READ_CHUNK;
remaining -= READ_CHUNK;
} else {
toRead = remaining;
remaining = 0;
}
wriCmd[1] = (u8)((address & 0xFF000000) >> 24);
wriCmd[2] = (u8)((address & 0x00FF0000) >> 16);
reaCmd[1] = (u8)((address & 0x0000FF00) >> 8);
reaCmd[2] = (u8)(address & 0x000000FF);
if (hasDummyByte) {
if (writeReadCmd(wriCmd, 3, reaCmd, 3, buff, toRead + 1) < 0) {
logError(1, "%s writeCmdU32: ERROR %02X\n", tag, ERROR_I2C_WR);
return ERROR_I2C_WR;
}
memcpy(outBuf, buff + 1, toRead);
} else {
if (writeReadCmd(wriCmd, 3, reaCmd, 3, buff, toRead) < 0)
return ERROR_I2C_WR;
memcpy(outBuf, buff, toRead);
}
address += toRead;
outBuf += toRead;
}
return OK;
}

View File

@ -0,0 +1,35 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* I2C/SPI Communication *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsSoftware.h"
#include "ftsCrossCompile.h"
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#define I2C_RETRY 3 /* number */
#define I2C_WAIT_BEFORE_RETRY 10 /* ms */
int openChannel(struct i2c_client *clt);
struct device *getDev(void);
struct i2c_client *getClient(void);
int fts_readCmd(u8 *cmd, int cmdLenght, u8 *outBuf, int byteToRead);
int fts_writeCmd(u8 *cmd, int cmdLenght);
int fts_writeFwCmd(u8 *cmd, int cmdLenght);
int writeReadCmd(u8 *writeCmd, int writeCmdLenght, u8 *readCmd, int readCmdLenght, u8 *outBuf, int byteToRead);
int readCmdU16(u8 cmd, u16 address, u8 *outBuf, int byteToRead, int hasDummyByte);
int writeCmdU16(u8 WriteCmd, u16 address, u8 *dataToWrite, int byteToWrite);
int writeCmdU32(u8 writeCmd1, u8 writeCmd2, u32 address, u8 *dataToWrite, int byteToWrite);
int writeReadCmdU32(u8 wCmd, u8 rCmd, u32 address, u8 *outBuf, int byteToRead, int hasDummyByte);

View File

@ -0,0 +1,131 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FW related data *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsHardware.h"
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#define ECHO_ENABLED 0x00000001
/* chipInfo ftsInfo; */
/* FTS FW COMAND */
#define FTS_CMD_MS_MT_SENSE_OFF 0x92
#define FTS_CMD_MS_MT_SENSE_ON 0x93
#define FTS_CMD_SS_HOVER_OFF 0x94
#define FTS_CMD_SS_HOVER_ON 0x95
#define FTS_CMD_LP_TIMER_CALIB 0x97
#define FTS_CMD_MS_KEY_OFF 0x9A
#define FTS_CMD_MS_KEY_ON 0x9B
#define FTS_CMD_MS_COMP_TUNING 0xA3
#define FTS_CMD_SS_COMP_TUNING 0xA4
#define FTS_CMD_FULL_INITIALIZATION 0xA5
#define FTS_CMD_ITO_CHECK 0xA7
#define FTS_CMD_RELEASE_INFO 0xAA
#define FTS_CMD_GESTURE_MODE 0xAD
#define FTS_CMD_REQU_FW_CONF 0xB2
#define FTS_CMD_REQU_FRAME_DATA 0xB7
#define FTS_CMD_REQU_COMP_DATA 0xB8
#define FTS_CMD_WRITE_MP_FLAG 0xC0
#define FTS_CMD_FEATURE_ENABLE 0xC1
#define FTS_CMD_FEATURE_DISABLE 0xC2
#define FTS_CMD_GESTURE_CMD 0xC3
#define FTS_CMD_SAVE_CX_TUNING 0xFC
/* Event ID */
#define EVENTID_NO_EVENT 0x00
#define EVENTID_ERROR_EVENT 0x0F
#define EVENTID_CONTROL_READY 0x10
#define EVENTID_FW_CONFIGURATION 0x12
#define EVENTID_COMP_DATA_READ 0x13
#define EVENTID_STATUS_UPDATE 0x16
#define EVENTID_RELEASE_INFO 0x1C
#define EVENTID_ENTER_POINTER 0x03
#define EVENTID_LEAVE_POINTER 0x04
#define EVENTID_MOTION_POINTER 0x05
#define EVENTID_HOVER_ENTER_POINTER 0x07
#define EVENTID_HOVER_LEAVE_POINTER 0x08
#define EVENTID_HOVER_MOTION_POINTER 0x09
#define EVENTID_PROXIMITY_ENTER 0x0B
#define EVENTID_PROXIMITY_LEAVE 0x0C
#define EVENTID_KEY_STATUS 0x0E
#define EVENTID_GESTURE 0x22
#define EVENTID_FRAME_DATA_READ 0x25
#define EVENTID_ECHO 0xEC
#define EVENTID_LAST (EVENTID_FRAME_DATA_READ+1)
/* EVENT TYPE */
#define EVENT_TYPE_MS_TUNING_CMPL 0x01
#define EVENT_TYPE_SS_TUNING_CMPL 0x02
#define EVENT_TYPE_COMP_DATA_SAVED 0x04
#define EVENT_TYPE_ITO 0x05
#define EVENT_TYPE_FULL_INITIALIZATION 0x07
#define EVENT_TYPE_LPTIMER_TUNING_CMPL 0x20
#define EVENT_TYPE_ESD_ERROR 0x0A
#define EVENT_TYPE_WATCHDOG_ERROR 0x01
/* CONFIG ID INFO */
#define CONFIG_ID_ADDR 0x0001
#define CONFIG_ID_BYTE 2
/* ADDRESS OFFSET IN SYSINFO */
#define ADDR_RAW_TOUCH 0x0000
#define ADDR_FILTER_TOUCH 0x0002
#define ADDR_NORM_TOUCH 0x0004
#define ADDR_CALIB_TOUCH 0x0006
#define ADDR_RAW_HOVER_FORCE 0x000A
#define ADDR_RAW_HOVER_SENSE 0x000C
#define ADDR_FILTER_HOVER_FORCE 0x000E
#define ADDR_FILTER_HOVER_SENSE 0x0010
#define ADDR_NORM_HOVER_FORCE 0x0012
#define ADDR_NORM_HOVER_SENSE 0x0014
#define ADDR_CALIB_HOVER_FORCE 0x0016
#define ADDR_CALIB_HOVER_SENSE 0x0018
#define ADDR_RAW_PRX_FORCE 0x001A
#define ADDR_RAW_PRX_SENSE 0x001C
#define ADDR_FILTER_PRX_FORCE 0x001E
#define ADDR_FILTER_PRX_SENSE 0x0020
#define ADDR_NORM_PRX_FORCE 0x0022
#define ADDR_NORM_PRX_SENSE 0x0024
#define ADDR_CALIB_PRX_FORCE 0x0026
#define ADDR_CALIB_PRX_SENSE 0x0028
#define ADDR_RAW_MS_KEY 0x0032
#define ADDR_COMP_DATA 0x0050
#define ADDR_FRAMEBUFFER_DATA 0x8000
/* ADDRESS FW REGISTER */
#define ADDR_SENSE_LEN 0x0014
#define ADDR_FORCE_LEN 0x0015
#define ADDR_MS_TUNING_VER 0x0729
#define ADDR_SS_TUNING_VER 0x074E
/* B2 INFO */
#define B2_DATA_BYTES 4
#define B2_CHUNK ((FIFO_DEPTH/2)*B2_DATA_BYTES) /* number of bytes */
/* FEATURES */
#define FEAT_GESTURE 0x00
#define FEAT_GLOVE 0x01
#define FEAT_STYLUS 0x02
#define FEAT_COVER 0x04
#define FEAT_CHARGER 0x08
#define FEAT_VR 0x10
#define FEAT_EDGE_REJECTION 0x20
/* MP_FLAG_VALUE */
#define INIT_MP 0xA5A5A501
#define INIT_FIELD 0xA5A5A502

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,158 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS API for MP test *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsSoftware.h"
#define LIMITS_FILE "stm_fts_production_limits.csv"
#define WAIT_FOR_FRESH_FRAMES 100 /* ms */
#define WAIT_AFTER_SENSEOFF 50 /* ms */
#define TIMEOUT_ITO_TEST_RESULT 200 /* ms */
#define TIMEOUT_INITIALIZATION_TEST_RESULT 5000 /* ms */
/* LABELS PRODUCTION TEST LIMITS FILE */
#define MS_RAW_MIN_MAX "MS_RAW_DATA_MIN_MAX"
#define MS_RAW_GAP "MS_RAW_DATA_GAP"
#define MS_CX1_MIN_MAX "MS_TOUCH_ACTIVE_CX1_MIN_MAX"
#define MS_CX2_MAP_MIN "MS_TOUCH_ACTIVE_CX2_MIN"
#define MS_CX2_MAP_MAX "MS_TOUCH_ACTIVE_CX2_MAX"
#define MS_CX2_ADJH_MAP_MAX "MS_TOUCH_ACTIVE_CX2_ADJ_HORIZONTAL"
#define MS_CX2_ADJV_MAP_MAX "MS_TOUCH_ACTIVE_CX2_ADJ_VERTICAL"
#define MS_TOTAL_CX_MAP_MIN "MS_TOUCH_ACTIVE_TOTAL_CX_MIN"
#define MS_TOTAL_CX_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_MAX"
#define MS_TOTAL_CX_ADJH_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_ADJ_HORIZONTAL"
#define MS_TOTAL_CX_ADJV_MAP_MAX "MS_TOUCH_ACTIVE_TOTAL_CX_ADJ_VERTICAL"
#define SS_RAW_FORCE_MIN_MAX "SS_RAW_DATA_FORCE_MIN_MAX"
#define SS_RAW_SENSE_MIN_MAX "SS_RAW_DATA_SENSE_MIN_MAX"
#define SS_RAW_FORCE_GAP "SS_RAW_DATA_FORCE_GAP"
#define SS_RAW_SENSE_GAP "SS_RAW_DATA_SENSE_GAP"
#define SS_IX1_FORCE_MIN_MAX "SS_TOUCH_ACTIVE_IX1_FORCE_MIN_MAX"
#define SS_IX1_SENSE_MIN_MAX "SS_TOUCH_ACTIVE_IX1_SENSE_MIN_MAX"
#define SS_CX1_FORCE_MIN_MAX "SS_TOUCH_ACTIVE_CX1_FORCE_MIN_MAX"
#define SS_CX1_SENSE_MIN_MAX "SS_TOUCH_ACTIVE_CX1_SENSE_MIN_MAX"
#define SS_IX2_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_IX2_FORCE_MIN"
#define SS_IX2_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_IX2_FORCE_MAX"
#define SS_IX2_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_IX2_SENSE_MIN"
#define SS_IX2_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_IX2_SENSE_MAX"
#define SS_IX2_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_IX2_ADJ_VERTICAL"
#define SS_IX2_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_IX2_ADJ_HORIZONTAL"
#define SS_CX2_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_CX2_FORCE_MIN"
#define SS_CX2_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_CX2_FORCE_MAX"
#define SS_CX2_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_CX2_SENSE_MIN"
#define SS_CX2_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_CX2_SENSE_MAX"
#define SS_CX2_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_CX2_ADJ_VERTICAL"
#define SS_CX2_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_CX2_ADJ_HORIZONTAL"
/* TOTAL SS */
#define SS_TOTAL_IX_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_IX_FORCE_MIN"
#define SS_TOTAL_IX_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_FORCE_MAX"
#define SS_TOTAL_IX_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_IX_SENSE_MIN"
#define SS_TOTAL_IX_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_SENSE_MAX"
#define SS_TOTAL_IX_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_ADJ_VERTICAL"
#define SS_TOTAL_IX_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_IX_ADJ_HORIZONTAL"
#define SS_TOTAL_CX_FORCE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_CX_FORCE_MIN"
#define SS_TOTAL_CX_FORCE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_FORCE_MAX"
#define SS_TOTAL_CX_SENSE_MAP_MIN "SS_TOUCH_ACTIVE_TOTAL_CX_SENSE_MIN"
#define SS_TOTAL_CX_SENSE_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_SENSE_MAX"
#define SS_TOTAL_CX_FORCE_ADJV_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_ADJ_VERTICAL"
#define SS_TOTAL_CX_SENSE_ADJH_MAP_MAX "SS_TOUCH_ACTIVE_TOTAL_CX_ADJ_HORIZONTAL"
/* KEYS */
#define MS_KEY_RAW_MIN_MAX "MS_KEY_RAW_DATA_MIN_MAX"
#define MS_KEY_CX1_MIN_MAX "MS_KEY_CX1_MIN_MAX"
#define MS_KEY_CX2_MAP_MIN "MS_KEY_CX2_MIN"
#define MS_KEY_CX2_MAP_MAX "MS_KEY_CX2_MAX"
#define MS_KEY_TOTAL_CX_MAP_MIN "MS_KEY_TOTAL_CX_MIN"
#define MS_KEY_TOTAL_CX_MAP_MAX "MS_KEY_TOTAL_CX_MAX"
/* CONSTANT TOTAL IX */
#define SS_IX1_FORCE_W "SS_IX1_FORCE_W"
#define SS_IX2_FORCE_W "SS_IX2_FORCE_W"
#define SS_IX1_SENSE_W "SS_IX1_SENSE_W"
#define SS_IX2_SENSE_W "SS_IX2_SENSE_W"
#define SAVE_FLAG_RETRY 3
typedef struct {
int MutualRaw;
int MutualRawGap;
int MutualCx1;
int MutualCx2;
int MutualCx2Adj;
int MutualCxTotal;
int MutualCxTotalAdj;
int MutualKeyRaw;
int MutualKeyCx1;
int MutualKeyCx2;
int MutualKeyCxTotal;
int SelfForceRaw;
int SelfForceRawGap;
int SelfForceIx1;
int SelfForceIx2;
int SelfForceIx2Adj;
int SelfForceIxTotal;
int SelfForceIxTotalAdj;
int SelfForceCx1;
int SelfForceCx2;
int SelfForceCx2Adj;
int SelfForceCxTotal;
int SelfForceCxTotalAdj;
int SelfSenseRaw;
int SelfSenseRawGap;
int SelfSenseIx1;
int SelfSenseIx2;
int SelfSenseIx2Adj;
int SelfSenseIxTotal;
int SelfSenseIxTotalAdj;
int SelfSenseCx1;
int SelfSenseCx2;
int SelfSenseCx2Adj;
int SelfSenseCxTotal;
int SelfSenseCxTotalAdj;
} TestToDo;
int computeAdjHoriz(u8 *data, int row, int column, u8 **result);
int computeAdjHorizTotal(u16 *data, int row, int column, u16 **result);
int computeAdjVert(u8 *data, int row, int column, u8 **result);
int computeAdjVertTotal(u16 *data, int row, int column, u16 **result);
int computeTotal(u8 *data, u8 main, int row, int column, int m, int n, u16 **result);
int checkLimitsMinMax(short *data, int row, int column, int min, int max);
int checkLimitsMap(u8 *data, int row, int column, int *min, int *max);
int checkLimitsMapTotal(u16 *data, int row, int column, int *min, int *max);
int checkLimitsMapAdj(u8 *data, int row, int column, int *max);
int checkLimitsMapAdjTotal(u16 *data, int row, int column, int *max);
int production_test_ito(void);
int production_test_initialization(void);
int ms_compensation_tuning(void);
int ss_compensation_tuning(void);
int lp_timer_calibration(void);
int save_cx_tuning(void);
int production_test_splited_initialization(int saveToFlash);
int production_test_main(char *pathThresholds, int stop_on_fail,
int saveInit, TestToDo *todo, u32 signature);
int production_test_ms_raw(char *path_limits, int stop_on_fail, TestToDo *todo);
int production_test_ms_cx(char *path_limits, int stop_on_fail, TestToDo *todo);
int production_test_ss_raw(char *path_limits, int stop_on_fail, TestToDo *todo);
int production_test_ss_ix_cx(char *path_limits, int stop_on_fail, TestToDo *todo);
int production_test_data(char *path_limits, int stop_on_fail, TestToDo *todo);
int production_test_ms_key_cx(char *path_limits, int stop_on_fail, TestToDo *todo);
int production_test_ms_key_raw(char *path_limits);
int save_mp_flag(u32 signature);
int parseProductionTestLimits(char *path, char *label, int **data, int *row, int *column);
int readLine(char *data, char **line, int size, int *n);

View File

@ -0,0 +1,84 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS Utility for mesuring/handling the time *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsCrossCompile.h"
#include "ftsTime.h"
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <stdarg.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/time.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/regulator/consumer.h>
#include <linux/of_gpio.h>
/* #include <linux/sec_sysfs.h> */
void startStopWatch(StopWatch *w)
{
w->start = current_kernel_time();
}
void stopStopWatch(StopWatch *w)
{
w->end = current_kernel_time();
}
int elapsedMillisecond(StopWatch *w)
{
int result;
result = ((w->end.tv_sec - w->start.tv_sec)*1000) + (w->end.tv_nsec - w->start.tv_nsec) / 1000000;
return result;
}
int elapsedNanosecond(StopWatch *w)
{
int result;
result = ((w->end.tv_sec - w->start.tv_sec)*1000000000) + (w->end.tv_nsec - w->start.tv_nsec);
return result;
}
char *timestamp(void)
{
char *result = NULL;
result = (char *)kmalloc((1)*sizeof(char), GFP_KERNEL);
if (result == NULL)
return NULL;
result[0] = ' ';
return result;
}
void stdelay(unsigned long ms)
{
msleep(ms);
}

View File

@ -0,0 +1,29 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS Utility for mesuring/handling the time *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsCrossCompile.h"
#include <linux/time.h>
typedef struct {
struct timespec start, end;
} StopWatch;
void startStopWatch(StopWatch *w);
void stopStopWatch(StopWatch *w);
int elapsedMillisecond(StopWatch *w);
int elapsedNanosecond(StopWatch *w);
char *timestamp(void);
void stdelay(unsigned long ms);

View File

@ -0,0 +1,706 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS Utility Functions *
* *
**************************************************************************
**************************************************************************
*/
#include "ftsCompensation.h"
#include "ftsCrossCompile.h"
#include "ftsError.h"
#include "ftsHardware.h"
#include "ftsIO.h"
#include "ftsSoftware.h"
#include "ftsTime.h"
#include "ftsTool.h"
#include "../fts.h" /* needed for the PHONE_KEY define */
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <stdarg.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/serio.h>
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/power_supply.h>
#include <linux/firmware.h>
#include <linux/gpio.h>
/* static char tag[8]="[ FTS ]\0"; */
static int reset_gpio = GPIO_NOT_DEFINED;
static int system_resetted_up;
static int system_resetted_down;
extern chipInfo ftsInfo;
int readB2(u16 address, u8 *outBuf, int len)
{
int remaining = len;
int toRead = 0;
int retry = 0;
int ret;
int event_to_search[3];
u8 *readEvent = (u8 *)kmalloc(FIFO_EVENT_SIZE*sizeof(u8), GFP_KERNEL);
u8 cmd[4] = { FTS_CMD_REQU_FW_CONF, 0x00, 0x00, (u8)len };
if (readEvent == NULL) {
logError(1, "%s readB2: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
u16ToU8_be(address, &cmd[1]);
logError(0, "%s %s", tag, printHex("Command B2 = ", cmd, 4));
do {
remaining = len;
ret = fts_writeFwCmd(cmd, 4);
if (ret < 0) {
logError(1, "%s readB2: ERROR %02X\n", tag, ERROR_I2C_W);
return ret;
} /* ask to the FW the data */
logError(0, "%s Command to FW sent!\n", tag);
event_to_search[0] = (int)EVENTID_FW_CONFIGURATION;
while (remaining > OK) {
event_to_search[1] = (int)((address & 0xFF00)>>8);
event_to_search[2] = (int) (address & 0x00FF);
if (remaining > B2_DATA_BYTES) {
toRead = B2_DATA_BYTES;
remaining -= B2_DATA_BYTES;
} else {
toRead = remaining;
remaining = 0;
}
ret = pollForEvent(event_to_search, 3, readEvent, GENERAL_TIMEOUT);
if (ret >= OK) { /* start the polling for reading the reply */
memcpy(outBuf, &readEvent[3], toRead);
retry = 0;
outBuf += toRead;
} else {
retry += 1;
break;
}
address += B2_DATA_BYTES;
}
} while (retry < B2_RETRY && retry != 0);
kfree(readEvent);
if (retry == B2_RETRY) {
logError(1, "%s readB2: ERROR %02X\n", tag, ERROR_TIMEOUT);
return ERROR_TIMEOUT;
}
logError(0, "%s B2 read %d bytes\n", tag, len);
return OK;
}
int readB2U16(u16 address, u8 *outBuf, int byteToRead)
{
int remaining = byteToRead;
int toRead = 0;
int ret;
u8 *buff = (u8 *)kmalloc((B2_CHUNK + 1)*sizeof(u8), GFP_KERNEL);
if (buff == NULL) {
logError(1, "%s readB2U16: ERROR %02X\n", tag, ERROR_ALLOC);
return ERROR_ALLOC;
}
while (remaining > 0) {
if (remaining >= B2_CHUNK) {
toRead = B2_CHUNK;
remaining -= B2_CHUNK;
} else {
toRead = remaining;
remaining = 0;
}
ret = readB2(address, buff, toRead);
if (ret < 0)
return ret;
memcpy(outBuf, buff, toRead);
address += toRead;
outBuf += toRead;
}
kfree(buff);
return OK;
}
int releaseInformation(void)
{
int ret;
u8 cmd[1] = { FTS_CMD_RELEASE_INFO };
int event_to_search[1];
u8 readEvent[FIFO_EVENT_SIZE];
event_to_search[0] = (int)EVENTID_RELEASE_INFO;
logError(0, "%s releaseInformation started... Chip INFO:\n", tag);
ret = fts_writeFwCmd(cmd, 1);
if (ret < OK) {
logError(1, "%s releaseInformation: ERROR %02X\n", tag, ret);
return ret;
}
ret = pollForEvent(event_to_search, 1, &readEvent[0], RELEASE_INFO_TIMEOUT);
/* start the polling for reading the reply */
if (ret < OK) {
logError(1, "%s releaseInformation: ERROR %02X\n", tag, ret);
return ret;
}
logError(0, "%s releaseInformation: Finished!\n", tag, ret);
return OK;
}
char *printHex(char *label, u8 *buff, int count)
{
int i, offset;
char *result = NULL;
offset = strlen(label);
result = (char *)kmalloc(((offset + 3 * count) + 1)*sizeof(char), GFP_KERNEL);
if (result != NULL) {
strlcpy(result, label, sizeof(result));
for (i = 0; i < count; i++) {
snprintf(&result[offset + i * 3], 4, "%02X ", buff[i]);
}
strlcat(result, "\n", sizeof(result));
}
return result;
}
int pollForEvent(int *event_to_search, int event_bytes, u8 *readData, int time_to_wait)
{
int i, find, retry, count_err;
int time_to_count;
int err_handling = OK;
StopWatch clock;
u8 cmd[1] = { FIFO_CMD_READONE };
char *temp = NULL;
find = 0;
retry = 0;
count_err = 0;
time_to_count = time_to_wait / TIMEOUT_RESOLUTION;
startStopWatch(&clock);
while (find != 1 && retry < time_to_count && fts_readCmd(cmd, 1, readData, FIFO_EVENT_SIZE) >= 0) {
/* Log of errors */
if (readData[0] == EVENTID_ERROR_EVENT) {
logError(1, "%s %s", tag, printHex("ERROR EVENT = ", readData, FIFO_EVENT_SIZE));
count_err++;
err_handling = errorHandler(readData, FIFO_EVENT_SIZE);
if ((err_handling&0xF0FF0000) == ERROR_HANDLER_STOP_PROC) {
logError(1, "%s pollForEvent: forced to be stopped! ERROR %08X\n", tag, err_handling);
return err_handling;
}
} else {
if (readData[0] != EVENTID_NO_EVENT) {
logError(1, "%s %s", tag, printHex("READ EVENT = ", readData, FIFO_EVENT_SIZE));
}
if (readData[0] == EVENTID_CONTROL_READY && event_to_search[0] != EVENTID_CONTROL_READY) {
logError(1, "%s pollForEvent: Unmanned Controller Ready Event! Setting reset flags...\n", tag);
setSystemResettedUp(1);
setSystemResettedDown(1);
}
}
find = 1;
for (i = 0; i < event_bytes; i++) {
if (event_to_search[i] != -1 && (int)readData[i] != event_to_search[i]) {
find = 0;
break;
}
}
retry++;
msleep(TIMEOUT_RESOLUTION);
}
stopStopWatch(&clock);
if ((retry >= time_to_count) && find != 1) {
logError(1, "%s pollForEvent: ERROR %02X\n", tag, ERROR_TIMEOUT);
return ERROR_TIMEOUT;
} else if (find == 1) {
temp = printHex("FOUND EVENT = ", readData, FIFO_EVENT_SIZE);
if (temp != NULL)
logError(0, "%s %s", tag, temp);
kfree(temp);
logError(0, "%s Event found in %d ms (%d iterations)! Number of errors found = %d\n", tag, elapsedMillisecond(&clock), retry, count_err);
return count_err;
}
logError(1, "%s pollForEvent: ERROR %02X\n", tag, ERROR_I2C_R);
return ERROR_I2C_R;
}
int flushFIFO(void)
{
u8 cmd = FIFO_CMD_FLUSH; /* flush the FIFO */
if (fts_writeCmd(&cmd, 1) < 0) {
logError(1, "%s flushFIFO: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
logError(0, "%s FIFO flushed!\n", tag);
return OK;
}
int fts_disableInterrupt(void)
{
u8 cmd[4] = { FTS_CMD_HW_REG_W, 0x00, 0x00, IER_DISABLE }; /* disable interrupt */
u16ToU8_be(IER_ADDR, &cmd[1]);
if (fts_writeCmd(cmd, 4) < OK) {
logError(1, "%s fts_disableInterrupt: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
logError(0, "%s Interrupt Disabled!\n", tag);
return OK;
}
int fts_enableInterrupt(void)
{
u8 cmd[4] = { FTS_CMD_HW_REG_W, 0x00, 0x00, IER_ENABLE }; /* enable interrupt */
u16ToU8_be(IER_ADDR, &cmd[1]);
if (fts_writeCmd(cmd, 4) < 0) {
logError(1, "%s fts_enableInterrupt: ERROR %02X\n", tag, ERROR_I2C_W);
return ERROR_I2C_W;
}
logError(0, "%s Interrupt Enabled!\n", tag);
return OK;
}
int u8ToU16n(u8 *src, int src_length, u16 *dst)
{
int i, j;
if (src_length % 2 != 0) {
return 0;
}
j = 0;
dst = (u16 *)kmalloc((src_length / 2)*sizeof(u16), GFP_KERNEL);
for (i = 0; i < src_length; i += 2) {
dst[j] = ((src[i+1] & 0x00FF) << 8) + (src[i] & 0x00FF);
j++;
}
return (src_length / 2);
}
int u8ToU16(u8 *src, u16 *dst)
{
*dst = (u16)(((src[1] & 0x00FF) << 8) + (src[0] & 0x00FF));
return 0;
}
int u8ToU16_le(u8 *src, u16 *dst)
{
*dst = (u16)(((src[0] & 0x00FF) << 8) + (src[1] & 0x00FF));
return 0;
}
int u16ToU8n(u16 *src, int src_length, u8 *dst)
{
int i, j;
dst = (u8 *)kmalloc((2 * src_length)*sizeof(u8), GFP_KERNEL);
j = 0;
for (i = 0; i < src_length; i++) {
dst[j] = (u8) (src[i] & 0xFF00)>>8;
dst[j+1] = (u8) (src[i] & 0x00FF);
j += 2;
}
return src_length * 2;
}
int u16ToU8(u16 src, u8 *dst)
{
dst[0] = (u8)((src & 0xFF00) >> 8);
dst[1] = (u8)(src & 0x00FF);
return 0;
}
int u16ToU8_be(u16 src, u8 *dst)
{
dst[0] = (u8)((src & 0xFF00) >> 8);
dst[1] = (u8)(src & 0x00FF);
return 0;
}
int u16ToU8_le(u16 src, u8 *dst)
{
dst[1] = (u8)((src & 0xFF00) >> 8);
dst[0] = (u8)(src & 0x00FF);
return 0;
}
int u8ToU32(u8 *src, u32 *dst)
{
*dst = (u32)(((src[3] & 0x000000FF) << 24) + ((src[2] & 0x000000FF) << 16) + ((src[1] & 0x000000FF) << 8) + (src[0] & 0x000000FF));
return 0;
}
int u32ToU8(u32 src, u8 *dst)
{
dst[3] = (u8)((src & 0xFF000000) >> 24);
dst[2] = (u8)((src & 0x00FF0000) >> 16);
dst[1] = (u8)((src & 0x0000FF00) >> 8);
dst[0] = (u8)(src & 0x000000FF);
return 0;
}
int attempt_function(int(*code)(void), unsigned long wait_before_retry, int retry_count)
{
int result;
int count = 0;
do {
result = code();
count++;
msleep(wait_before_retry);
} while (count < retry_count && result < 0);
if (count == retry_count)
return (result | ERROR_TIMEOUT);
else
return result;
}
void setResetGpio(int gpio)
{
reset_gpio = gpio;
logError(1, "%s setResetGpio: reset_gpio = %d\n", tag, reset_gpio);
}
int fts_system_reset(void)
{
u8 readData[FIFO_EVENT_SIZE];
int event_to_search;
int res = -1;
int i;
u8 cmd[4] = { FTS_CMD_HW_REG_W, 0x00, 0x00, SYSTEM_RESET_VALUE };
event_to_search = (int)EVENTID_CONTROL_READY;
u16ToU8_be(SYSTEM_RESET_ADDRESS, &cmd[1]);
logError(0, "%s System resetting...\n", tag);
for (i = 0; i < SYSTEM_RESET_RETRY && res < 0; i++) {
if (reset_gpio == GPIO_NOT_DEFINED) {
res = fts_writeCmd(cmd, 4);
} else {
gpio_set_value(reset_gpio, 0);
msleep(10);
gpio_set_value(reset_gpio, 1);
res = OK;
}
if (res < OK) {
logError(1, "%s fts_system_reset: ERROR %02X\n", tag, ERROR_I2C_W);
} else {
res = pollForEvent(&event_to_search, 1, readData, GENERAL_TIMEOUT);
if (res < OK) {
logError(1, "%s fts_system_reset: ERROR %02X\n", tag, res);
}
}
}
if (res < OK) {
logError(1, "%s fts_system_reset...failed after 3 attempts: ERROR %02X\n", tag, (res | ERROR_SYSTEM_RESET_FAIL));
return (res | ERROR_SYSTEM_RESET_FAIL);
}
logError(0, "%s System reset DONE!\n", tag);
system_resetted_down = 1;
system_resetted_up = 1;
return OK;
}
int isSystemResettedDown(void)
{
return system_resetted_down;
}
int isSystemResettedUp(void)
{
return system_resetted_up;
}
void setSystemResettedDown(int val)
{
system_resetted_down = val;
}
void setSystemResettedUp(int val)
{
system_resetted_up = val;
}
int senseOn(void)
{
int ret;
u8 cmd[1] = { FTS_CMD_MS_MT_SENSE_ON };
ret = fts_writeFwCmd(cmd, 1);
if (ret < OK) {
logError(1, "%s senseOn: ERROR %02X\n", tag, ERROR_SENSE_ON_FAIL);
return (ret|ERROR_SENSE_ON_FAIL);
}
logError(0, "%s senseOn: SENSE ON\n", tag);
return OK;
}
int senseOff(void)
{
int ret;
u8 cmd[1] = { FTS_CMD_MS_MT_SENSE_OFF };
ret = fts_writeFwCmd(cmd, 1);
if (ret < OK) {
logError(1, "%s senseOff: ERROR %02X\n", tag, ERROR_SENSE_OFF_FAIL);
return (ret | ERROR_SENSE_OFF_FAIL);
}
logError(0, "%s senseOff: SENSE OFF\n", tag);
return OK;
}
int keyOn(void)
{
int ret;
u8 cmd[1] = { FTS_CMD_MS_KEY_ON };
ret = fts_writeFwCmd(cmd, 1);
if (ret < OK) {
logError(1, "%s keyOn: ERROR %02X\n", tag, ERROR_SENSE_ON_FAIL);
return (ret | ERROR_SENSE_ON_FAIL);
}
logError(0, "%s keyOn: KEY ON\n", tag);
return OK;
}
int keyOff(void)
{
int ret;
u8 cmd[1] = { FTS_CMD_MS_KEY_OFF };
ret = fts_writeFwCmd(cmd, 1);
if (ret < OK) {
logError(1, "%s keyOff: ERROR %02X\n", tag, ERROR_SENSE_OFF_FAIL);
return (ret | ERROR_SENSE_OFF_FAIL);
}
logError(0, "%s keyOff: KEY OFF\n", tag);
return OK;
}
int cleanUp(int enableTouch)
{
int res;
logError(0, "%s cleanUp: system reset...\n", tag);
res = fts_system_reset();
if (res < OK)
return res;
if (enableTouch) {
logError(0, "%s cleanUp: enabling touches...\n", tag);
res = senseOn();
if (res < OK)
return res;
#ifdef PHONE_KEY
res = keyOn();
if (res < OK)
return res;
#endif
logError(0, "%s cleanUp: enabling interrupts...\n", tag);
res = fts_enableInterrupt();
if (res < OK)
return res;
}
return OK;
}
int checkEcho(u8 *cmd, int size)
{
int ret, i;
int event_to_search[size+1];
u8 readData[FIFO_EVENT_SIZE];
if ((ftsInfo.u32_echoEn & 0x00000001) != ECHO_ENABLED) {
logError(1, "%s ECHO Not Enabled!\n", tag);
return OK;
}
if (size < 1) {
logError(1, "%s checkEcho: Error Size = %d not valid! or ECHO not Enabled! ERROR %08X\n", tag, size, ERROR_OP_NOT_ALLOW);
return ERROR_OP_NOT_ALLOW;
}
if ((size+2) > FIFO_EVENT_SIZE)
size = FIFO_EVENT_SIZE-2;
/* Echo event EC xx xx xx xx xx xx fifo_status therefore for command
*with more than 6 bytes will echo only the first 6
*/
event_to_search[0] = EVENTID_ECHO;
for (i = 1; i <= size; i++) {
event_to_search[i] = cmd[i-1];
}
ret = pollForEvent(event_to_search, size+1, readData, GENERAL_TIMEOUT);
if (ret < OK) {
logError(1, "%s checkEcho: Echo Event not found! ERROR %02X\n", tag, ret);
return (ret | ERROR_CHECK_ECHO_FAIL);
}
logError(0, "%s ECHO OK!\n", tag);
return OK;
}
int featureEnableDisable(int on_off, u8 feature)
{
int ret;
u8 cmd[2] = { 0x00, feature };
if (on_off == FEAT_ENABLE) {
cmd[0] = FTS_CMD_FEATURE_ENABLE;
logError(0, "%s featureEnableDisable: Enabling feature %02X ...\n", tag, feature);
} else {
cmd[0] = FTS_CMD_FEATURE_DISABLE;
logError(0, "%s featureEnableDisable: Disabling feature %02X ...\n", tag, feature);
}
ret = fts_writeCmd(cmd, 2); /* not use writeFwCmd because this function can be called also during interrupt enable and should be fast */
if (ret < OK) {
logError(1, "%s featureEnableDisable: ERROR %02X\n", tag, ret);
return (ret | ERROR_FEATURE_ENABLE_DISABLE);
}
logError(0, "%s featureEnableDisable: DONE!\n", tag);
return OK;
}
short **array1dTo2d_short(short *data, int size, int columns)
{
int i;
short **matrix = (short **)kmalloc(((int)(size / columns))*sizeof(short *), GFP_KERNEL);
if (matrix != NULL) {
for (i = 0; i < (int)(size / columns); i++) {
matrix[i] = (short *)kmalloc(columns*sizeof(short), GFP_KERNEL);
}
for (i = 0; i < size; i++)
matrix[i / columns][i % columns] = data[i];
}
return matrix;
}
u8 **array1dTo2d_u8(u8 *data, int size, int columns)
{
int i;
u8 **matrix = (u8 **)kmalloc(((int)(size / columns))*sizeof(u8 *), GFP_KERNEL);
if (matrix != NULL) {
for (i = 0; i < (int)(size / columns); i++) {
matrix[i] = (u8 *)kmalloc(columns*sizeof(u8), GFP_KERNEL);
}
for (i = 0; i < size; i++)
matrix[i / columns][i % columns] = data[i];
}
return matrix;
}
void print_frame_short(char *label, short **matrix, int row, int column)
{
int i, j;
logError(0, "%s %s\n", tag, label);
for (i = 0; i < row; i++) {
logError(0, "%s ", tag);
for (j = 0; j < column; j++) {
printk("%d ", matrix[i][j]);
}
logError(0, "\n");
kfree(matrix[i]);
}
}
void print_frame_u8(char *label, u8 **matrix, int row, int column)
{
int i, j;
logError(0, "%s %s\n", tag, label);
for (i = 0; i < row; i++) {
logError(0, "%s ", tag);
for (j = 0; j < column; j++) {
printk("%d ", matrix[i][j]);
}
logError(0, "\n");
kfree(matrix[i]);
}
}
void print_frame_u32(char *label, u32 **matrix, int row, int column)
{
int i, j;
logError(0, "%s %s\n", tag, label);
for (i = 0; i < row; i++) {
logError(0, "%s ", tag);
for (j = 0; j < column; j++) {
printk("%d ", matrix[i][j]);
}
logError(0, "\n");
kfree(matrix[i]);
}
}
void print_frame_int(char *label, int **matrix, int row, int column)
{
int i, j;
logError(0, "%s %s\n", tag, label);
for (i = 0; i < row; i++) {
logError(0, "%s ", tag);
for (j = 0; j < column; j++) {
printk("%d ", matrix[i][j]);
}
logError(0, "\n");
kfree(matrix[i]);
}
}

View File

@ -0,0 +1,64 @@
/*
**************************************************************************
** STMicroelectronics **
**************************************************************************
** marco.cali@st.com **
**************************************************************************
* *
* FTS Utility Functions *
* *
**************************************************************************
**************************************************************************
*/
#define GPIO_NOT_DEFINED -1
#define TIMEOUT_RESOLUTION 10 /* ms */
#define GENERAL_TIMEOUT (50*TIMEOUT_RESOLUTION) /* ms */
#define RELEASE_INFO_TIMEOUT (15*TIMEOUT_RESOLUTION) /* ms */
#define FEAT_ENABLE 1
#define FEAT_DISABLE 0
#define SYSTEM_RESET_RETRY 3
#define B2_RETRY 2
int readB2(u16 address, u8 *outBuf, int len);
int readB2U16(u16 address, u8 *outBuf, int byteToRead);
int releaseInformation(void);
char *printHex(char *label, u8 *buff, int count);
int pollForEvent(int *event_to_search, int event_bytes, u8 *readData, int time_to_wait);
int fts_disableInterrupt(void);
int fts_enableInterrupt(void);
int u8ToU16(u8 *src, u16 *dst);
int u8ToU16_le(u8 *src, u16 *dst);
int u8ToU16n(u8 *src, int src_length, u16 *dst);
int u16ToU8(u16 src, u8 *dst);
int u16ToU8_le(u16 src, u8 *dst);
int u16ToU8_be(u16 src, u8 *dst);
int u16ToU8n(u16 *src, int src_length, u8 *dst);
int u8ToU32(u8 *src, u32 *dst);
int u32ToU8(u32 src, u8 *dst);
int attempt_function(int(*code)(void), unsigned long wait_before_retry, int retry_count);
void setResetGpio(int gpio);
int fts_system_reset(void);
int isSystemResettedUp(void);
int isSystemResettedDown(void);
void setSystemResettedUp(int val);
void setSystemResettedDown(int val);
int senseOn(void);
int senseOff(void);
int keyOn(void);
int keyOff(void);
int featureEnableDisable(int on_off, u8 feature);
int checkEcho(u8 *cmd, int size);
void print_frame_short(char *label, short **matrix, int row, int column);
short **array1dTo2d_short(short *data, int size, int columns);
u8 **array1dTo2d_u8(u8 *data, int size, int columns);
void print_frame_u8(char *label, u8 **matrix, int row, int column);
void print_frame_u32(char *label, u32 **matrix, int row, int column);
void print_frame_int(char *label, int **matrix, int row, int column);
int cleanUp(int enableTouch);
int flushFIFO(void);

View File

@ -0,0 +1,10 @@
#ifndef FTS_LIMITS_H
#define FTS_LIMITS_H
/* This is an auto generated header file
* --->Remember to change the name of the two variables!<--- */
const uint32_t myArray2_size;
const uint8_t myArray2[] = {
};
#endif