2007-07-18 08:37:01 +04:00
/*
* Fujitsu serial touchscreen driver
*
* Copyright ( c ) Dmitry Torokhov < dtor @ mail . ru >
*/
/*
* 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 .
*/
# include <linux/errno.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/input.h>
# include <linux/serio.h>
# include <linux/init.h>
# define DRIVER_DESC "Fujitsu serial touchscreen driver"
MODULE_AUTHOR ( " Dmitry Torokhov <dtor@mail.ru> " ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_LICENSE ( " GPL " ) ;
# define FUJITSU_LENGTH 5
/*
* Per - touchscreen data .
*/
struct fujitsu {
struct input_dev * dev ;
struct serio * serio ;
int idx ;
unsigned char data [ FUJITSU_LENGTH ] ;
char phys [ 32 ] ;
} ;
/*
* Decode serial data ( 5 bytes per packet )
* First byte
* 1 C 0 0 R S S S
* Where C is 1 while in calibration mode ( which we don ' t use )
* R is 1 when no coordinate corection was done .
* S are button state
*/
static irqreturn_t fujitsu_interrupt ( struct serio * serio ,
unsigned char data , unsigned int flags )
{
struct fujitsu * fujitsu = serio_get_drvdata ( serio ) ;
struct input_dev * dev = fujitsu - > dev ;
if ( fujitsu - > idx = = 0 ) {
/* resync skip until start of frame */
if ( ( data & 0xf0 ) ! = 0x80 )
return IRQ_HANDLED ;
} else {
/* resync skip garbage */
if ( data & 0x80 ) {
fujitsu - > idx = 0 ;
return IRQ_HANDLED ;
}
}
fujitsu - > data [ fujitsu - > idx + + ] = data ;
if ( fujitsu - > idx = = FUJITSU_LENGTH ) {
input_report_abs ( dev , ABS_X ,
( fujitsu - > data [ 2 ] < < 7 ) | fujitsu - > data [ 1 ] ) ;
input_report_abs ( dev , ABS_Y ,
( fujitsu - > data [ 4 ] < < 7 ) | fujitsu - > data [ 3 ] ) ;
input_report_key ( dev , BTN_TOUCH ,
( fujitsu - > data [ 0 ] & 0x03 ) ! = 2 ) ;
input_sync ( dev ) ;
fujitsu - > idx = 0 ;
}
return IRQ_HANDLED ;
}
/*
* fujitsu_disconnect ( ) is the opposite of fujitsu_connect ( )
*/
static void fujitsu_disconnect ( struct serio * serio )
{
struct fujitsu * fujitsu = serio_get_drvdata ( serio ) ;
input_get_device ( fujitsu - > dev ) ;
input_unregister_device ( fujitsu - > dev ) ;
serio_close ( serio ) ;
serio_set_drvdata ( serio , NULL ) ;
input_put_device ( fujitsu - > dev ) ;
kfree ( fujitsu ) ;
}
/*
* fujitsu_connect ( ) is the routine that is called when someone adds a
* new serio device that supports the Fujitsu protocol and registers it
* as input device .
*/
static int fujitsu_connect ( struct serio * serio , struct serio_driver * drv )
{
struct fujitsu * fujitsu ;
struct input_dev * input_dev ;
int err ;
fujitsu = kzalloc ( sizeof ( struct fujitsu ) , GFP_KERNEL ) ;
input_dev = input_allocate_device ( ) ;
if ( ! fujitsu | | ! input_dev ) {
err = - ENOMEM ;
goto fail1 ;
}
fujitsu - > serio = serio ;
fujitsu - > dev = input_dev ;
snprintf ( fujitsu - > phys , sizeof ( fujitsu - > phys ) ,
" %s/input0 " , serio - > phys ) ;
input_dev - > name = " Fujitsu Serial Touchscreen " ;
input_dev - > phys = fujitsu - > phys ;
input_dev - > id . bustype = BUS_RS232 ;
input_dev - > id . vendor = SERIO_FUJITSU ;
input_dev - > id . product = 0 ;
input_dev - > id . version = 0x0100 ;
2007-10-19 10:40:32 +04:00
input_dev - > evbit [ 0 ] = BIT_MASK ( EV_KEY ) | BIT_MASK ( EV_ABS ) ;
input_dev - > keybit [ BIT_WORD ( BTN_TOUCH ) ] = BIT_MASK ( BTN_TOUCH ) ;
2007-07-18 08:37:01 +04:00
input_set_abs_params ( input_dev , ABS_X , 0 , 4096 , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_Y , 0 , 4096 , 0 , 0 ) ;
serio_set_drvdata ( serio , fujitsu ) ;
err = serio_open ( serio , drv ) ;
if ( err )
goto fail2 ;
err = input_register_device ( fujitsu - > dev ) ;
if ( err )
goto fail3 ;
return 0 ;
fail3 :
serio_close ( serio ) ;
fail2 :
serio_set_drvdata ( serio , NULL ) ;
fail1 :
input_free_device ( input_dev ) ;
kfree ( fujitsu ) ;
return err ;
}
/*
* The serio driver structure .
*/
static struct serio_device_id fujitsu_serio_ids [ ] = {
{
. type = SERIO_RS232 ,
. proto = SERIO_FUJITSU ,
. id = SERIO_ANY ,
. extra = SERIO_ANY ,
} ,
{ 0 }
} ;
MODULE_DEVICE_TABLE ( serio , fujitsu_serio_ids ) ;
static struct serio_driver fujitsu_drv = {
. driver = {
. name = " fujitsu_ts " ,
} ,
. description = DRIVER_DESC ,
. id_table = fujitsu_serio_ids ,
. interrupt = fujitsu_interrupt ,
. connect = fujitsu_connect ,
. disconnect = fujitsu_disconnect ,
} ;
static int __init fujitsu_init ( void )
{
return serio_register_driver ( & fujitsu_drv ) ;
}
static void __exit fujitsu_exit ( void )
{
serio_unregister_driver ( & fujitsu_drv ) ;
}
module_init ( fujitsu_init ) ;
module_exit ( fujitsu_exit ) ;