SSL_TSC.C
/* Use our own dbg macro */
#define dbg(format, arg...) printk("----[%s: %d]: " format , __FUNCTION__ , __LINE__, ## arg)
#define mmadbg(format, arg...) printk("----[%s: %d]: " format , __FUNCTION__ , __LINE__, ## arg)
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x60, I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD;
//I2C_CLIENT_INSMOD_1(multi_touch_xx);
static int irq_no=-1;
/* Each client has this additional data */
static int nastech_i2c_continue_read(struct i2c_client *clinet, u8* buffer, u8 len);
typedef struct
{
u32 u32X; /* X coordinate, 0~2047 */
u32 u32Y; /* Y coordinate, 0~2047 */
u8 u8Finger; /* Number of fingers in the touch event */
u32 u32Dis_X; /* X distance between two fingers */
u32 u32Dis_Y; /* Y distance between two fingers. This value could be negative */
} TOUCH_DATA_st;
static struct work_struct nas_works;
static struct i2c_client *myI2C_client=NULL;
struct nas_cdev {
struct cdev *cdev;
};
/* Structure for Input Type*/
struct nas_ts_priv {
uint32_t local_irq;
struct nas_cdev cdev;
TOUCH_DATA_st *touchData;
//struct i2c_client *client;
struct i2c_client *client;
struct input_dev *input;
//int reported_finger_count;
u16 keybuff[20]; // number of key K1 K2 ...K5
#ifdef REPORTALL
u16 prekeybuff[20]; // number of key K1 K2 ...K5
#endif
char phys[32];
};
static struct nas_ts_priv *nas_priv = NULL;
#define ST_PEN_UP 0
#define ST_PEN_DOWN 1
u8 Calculate_8BitsChecksum( u8 *msg, s32 s32Length )
{
s32 s32Checksum = 0;
s32 i;
for ( i = 0 ; i < s32Length; i++ )
{
s32Checksum += msg[i];
}
return (u8)( ( -s32Checksum ) & 0xFF );
}
#define REPORT_PACKET_LENGTH 8
void nas_ts_irq_callback(void)
{
// read coordinate thought I2C
u8 val[REPORT_PACKET_LENGTH] = {0};
u8 Checksum = 0;
nas_priv->touchData->u32X = 0;
nas_priv->touchData->u32Y = 0;
nas_priv->touchData->u32Dis_X = 0;
nas_priv->touchData->u32Dis_Y = 0;
nas_priv->touchData->u8Finger = 0;
printk("**************************/n");
printk("***nas_ts_irq_callback***/n");
printk("**************************/n");
static bool pen_updown = false; //1(true) for down, 0(false) for up
static bool pre_pen_updown = ST_PEN_UP;
myI2C_client = nas_priv->client;
if(nastech_i2c_continue_read(myI2C_client,&val[0], REPORT_PACKET_LENGTH ) >= 0)
{
Checksum = Calculate_8BitsChecksum( val, (REPORT_PACKET_LENGTH-1) );
if ( ( Checksum == val[7] && val[0] == 0x52 ) ) // Check the packet ID(0x52)and checksum
{
/* parsing the coordinate report packet */
/* MSG20XX EVK report format */
/*
* +---------------------------------+
* byte[0] | Packet ID ( 0x52 ) |
* +----------------+----------------+
* byte[1] | u32X[11:8] | u32Y[11:8] |
* +---------------------------------+
* byte[2] | u32X[7:0] |
* +---------------------------------+
* byte[3] | u32Y[7:0] |
* +----------------+----------------+
* byte[4] | u32Dis_X[11:8] | u32Dis_Y[11:8] |
* +----------------+----------------+
* byte[5] | u32Dis_X[7:0] |
* +---------------------------------+
* byte[6] | u32Dis_Y[7:0] |
* +---------------------------------+
* byte[7] | Checksum |
* +---------------------------------+
*/
nas_priv->touchData->u32X = ( val[1] & 0xF0 ) << 4 | val[2];
nas_priv->touchData->u32Y = ( val[1] & 0x0F )<< 8 | val[3];
nas_priv->touchData->u32Dis_X = ( val[4] & 0xF0 ) << 4 | val[5];
nas_priv->touchData->u32Dis_Y = ( val[4] & 0x0F ) << 8 | val[6];
printk("<<<<<<<<<data<<<<<<<<<<<<</n");
printk("<x=%d,y=%d,dx=%d,dy=%d,</n",nas_priv->touchData->u32X,nas_priv->touchData->u32Y,nas_priv->touchData->u32Dis_X,nas_priv->touchData->u32Dis_Y);
printk("<<<<<<<<<data<<<<<<<<<<<<</n");
if ( nas_priv->touchData->u32X == 0xFFF && nas_priv->touchData->u32Y == 0xFFF && nas_priv->touchData->u32X == 0xFFF && nas_priv->touchData->u32Y == 0xFFF )
{
/* The coordinate report stands for a Touch-End event */
/* Inform the OS or system mailbox that the Touch-End event happened */
}
else
{
/* The coordinate report stands for Touch-On-Panel event */
if ( nas_priv->touchData->u32Dis_X == 0 && nas_priv->touchData->u32Dis_Y == 0 )
{
/* If the distance values are zero, the TP detects one-finger-touch event */
nas_priv->touchData->u8Finger = 1;
}
else if ( nas_priv->touchData->u32Dis_X <= 2047 && nas_priv->touchData->u32Dis_Y <= 2047 )
{
/* If the distance values are valid, the TP detects two-finger-touch event */
nas_priv->touchData->u8Finger = 2;
}
else
{
#ifdef DEBUG
printk(" /* Fetal error */n/* Discard the invalid coordinate reports due to fetal error. *//n");
#endif
}
}
}
else
{
/* Packet error happened. */
/* Check I2C signal quality and I2C master codes */
}
input_report_abs(nas_priv->input, ABS_X, nas_priv->touchData->u32X);
input_report_abs(nas_priv->input, ABS_Y, nas_priv->touchData->u32Y);
input_report_abs(nas_priv->input, ABS_HAT0X, nas_priv->touchData->u32Dis_X);
input_report_abs(nas_priv->input, ABS_HAT0Y, nas_priv->touchData->u32Dis_Y);
input_sync(nas_priv->input);
}
}
static void nastech_ts_work(struct work_struct *work)
{
nas_ts_irq_callback();
}
static int multi_touch_xx_probe(struct i2c_client *client,const struct i2c_device_id *id);
static int __devexit multi_touch_xx_remove(struct i2c_client *client);
static const struct i2c_device_id multi_touch_xx_id[]={
{"multi_touch_xx",0},
{}
};
/* This is the driver that will be inserted */
static struct i2c_driver multi_touch_xx_driver = {
.driver = {
.name = "multi_touch_xx",
.owner = THIS_MODULE,
},
//.id = I2C_DRIVERID_multi_touch_xx,
.probe = multi_touch_xx_probe,
.remove = __devexit_p(multi_touch_xx_remove),
.id_table = multi_touch_xx_id,
};
static irqreturn_t nastech_ts_isr(int irq, void *dev_id)
{
//disable_irq(ON_TOUCH_INT);
disable_irq(&nas_priv->local_irq);
schedule_work(&nas_works);
enable_irq( &nas_priv->local_irq);
return IRQ_HANDLED;
}
static int nastech_i2c_continue_read(struct i2c_client *clinet, u8* buffer, u8 len)
{
//unsigned char buffer[8];
int rc;
//buffer[0] = addr;
if (1 != (rc = i2c_master_send(clinet, 0x60, 1)))
{
//printk("i2c i/o error: rc == %d (should be 1)/n", rc);
mmadbg("i2c i/o error: rc == %d (should be 1)/n", rc);
}
//msleep(10);
if (1 != (rc = i2c_master_recv(clinet, &buffer[0], len)))
{
//dbg("i2c i/o error: rc == %d (should be 1)/n", rc);
mmadbg("i2c i/o error: rc == %d (should be 1)/n", rc);
}
printk(">>> nastech_i2c_continue_read>>>>>>>>>>>%x,>>>>>>>>>>>>/n",buffer[0]);
dbg("read : addr:value = 0x%x:0x%x/n", 0x60, buffer[0] );
return (buffer[0]);
}
static int multi_touch_xx_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
u8 value[8];
int err = 0;
uint32_t irq;
struct i2c_client *new_client;
//struct nas_ts_data *nastech_data;
struct input_dev *pInput_dev;
static struct nas_ts_priv *nas_priv = NULL;
INIT_WORK(&nas_works, nastech_ts_work);
/*----------------------i2c init---------------------*/
printk("/***************************/n");
printk("/*******multi_touch_xx_probe********************/n");
printk("/***************************/n");
//================================//
// Register as I2C Client //
//================================//
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
{
goto exit;
}
printk(">>>>>>after check_functionality/n");
if(!(nas_priv=kzalloc(sizeof(struct nas_ts_priv), GFP_KERNEL)))
{
err = -ENOMEM;
goto exit;
}
printk(">>>>>>after zalloc/n");
nas_priv->client=kzalloc(sizeof(struct i2c_client),GFP_KERNEL);
new_client=nas_priv->client;
//=====================================================================================================================//
//nas_priv->nas_ts_datap = nastech_data;
printk(">1oc/n");
//nas_priv->client = &nastech_data->client;
printk("2loc/n");
i2c_set_clientdata(new_client,nas_priv);
//printk(">>>>>>after i2c_set_clientdata/n");
nas_priv->client->addr = 0x60;
printk(">>>3oc/n");
nas_priv->client->adapter = client->adapter;
printk(">>4alloc/n");
nas_priv->client->driver = &multi_touch_xx_driver;
printk(">5c/n");
nas_priv->client->flags = 0;
printk(">>>6alloc/n");
//=====================================================================================================================//
// Touch Panel Setting & Calibrate //
//=====================================================================================================================//
//=====================================================================================================================//
//================================//
// Register as Input Device //
//================================//
printk(">>>>>>before input allocate/n");
pInput_dev = input_allocate_device();
printk(">>>>>>after input allocate/n");
if(!pInput_dev) {
printk(KERN_ERR"[%s - %d] malloc memory for pInput_dev ERR!/n", __FUNCTION__, __LINE__);
goto exit_kfree;
}
printk("input/n");
nas_priv->input=pInput_dev;
nas_priv->input->evbit[0] = BIT_MASK (EV_SYN)| BIT_MASK (EV_ABS) | BIT_MASK (EV_KEY) ;//mult touch
nas_priv->input->keybit [BIT_WORD (BTN_TOUCH)] = BIT_MASK (BTN_TOUCH);
//
printk("input_set_abs_params/n");
input_set_abs_params(nas_priv->input, ABS_X, 0, 1791, 0, 0);//³]©wµŽ¹ï®yŒÐªº³Ì€jÈ»P³Ì€pÈ
input_set_abs_params(nas_priv->input, ABS_Y, 0, 1023, 0, 0);//³]©wµŽ¹ï®yŒÐªº³Ì€jÈ»P³Ì€pÈ
input_set_abs_params(nas_priv->input, ABS_HAT0X, 0, 1791, 0, 0);//³]©wµŽ¹ï®yŒÐªº³Ì€jÈ»P³Ì€pÈ
input_set_abs_params(nas_priv->input, ABS_HAT0Y, 0, 1023, 0, 0);//³]©wµŽ¹ï®yŒÐªº³Ì€jÈ»P³Ì€pÈ
printk(" after input_set_abs_params/n");
//sprintf(nas_priv->phys, "ts0");
//nas_priv->input->private = nas_priv; //????
nas_priv->input->name = "nastech_ts";
nas_priv->input->phys = nas_priv->phys;
nas_priv->input->id.bustype = BUS_I2C;
nas_priv->input->id.vendor = 0x2011;
nas_priv->input->id.product = 0x0800;
//nas_priv->input->id.version = NASTECH_TS_VERSION;
//=====================================================================================================================//
if(input_register_device(nas_priv->input)) {
printk(KERN_ERR"[%s - %d] input_register_device for auo-tp2 err!/n", __FUNCTION__, __LINE__);
goto exit_kfree;
}
printk(" after input_register_device/n");
nastech_i2c_continue_read(nas_priv->client,&value[0],8);
printk(" after icontinue_read_device%x,/n",value[0]);
// register the GPIO inerrupt
gpio_direction_input(TOUCH_INT_PIN);
irq = gpio_to_irq(TOUCH_INT_PIN);
nas_priv->local_irq = irq;
set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
if( request_irq(irq, nastech_ts_isr,IRQF_DISABLED|IRQF_TRIGGER_FALLING, "nastech_ts", (void *)nas_priv->input))
{
input_free_device(pInput_dev);
goto exit_kfree;
}
enable_irq(&nas_priv->local_irq);
return 0;
exit_kfree:
kfree(nas_priv->client);
exit:
destroy_workqueue (&nas_works);
unregister_chrdev_region(MKDEV(NASTECH_TS_MAJOR, 0), 1);
cdev_del(&nas_priv->cdev);
kfree(nas_priv);
return err;
return err;
}
//static int multi_touch_xx_detach_client(struct i2c_client *client)
static int __devexit multi_touch_xx_remove(struct i2c_client *client)
{
struct multi_touch_xx_info *data = i2c_get_clientdata(client);
kfree(data);
dbg("no err, return /n");
return 0;
}
uint32_t ssltsc_vbat(void)
{
return 0;
}
static int __init multi_touch_xx_init(void)
{
dbg("register the driver/n");
dbg("init multi_touch_xx/n");
printk("***********************/n");
printk("**********multi_touch_xx_init*************/n");
printk("***********************/n");
return i2c_add_driver(&multi_touch_xx_driver);
}
static void __exit multi_touch_xx_exit(void)
{
dbg("exit multi_touch_xx/n");
i2c_del_driver(&multi_touch_xx_driver);
}
MODULE_AUTHOR("Maggie Qiu <maggieqiu@solomon-systech.com>");
MODULE_DESCRIPTION("I2C multi_touch_xx driver
i2c_register_board_info(0, _i2c, ARRAY_SIZE(_i2c));