2005-04-17 02:20:36 +04:00
/*
* MicroTouch ( 3 M ) serial touchscreen driver
*
* Copyright ( c ) 2004 Vojtech Pavlik
*/
/*
* 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 .
*/
/*
* 2005 / 02 / 19 Dan Streetman < ddstreet @ ieee . org >
* Copied elo . c and edited for MicroTouch protocol
*/
# 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 "MicroTouch serial touchscreen driver"
MODULE_AUTHOR ( " Vojtech Pavlik <vojtech@ucw.cz> " ) ;
MODULE_DESCRIPTION ( DRIVER_DESC ) ;
MODULE_LICENSE ( " GPL " ) ;
/*
* Definitions & global arrays .
*/
# define MTOUCH_FORMAT_TABLET_STATUS_BIT 0x80
# define MTOUCH_FORMAT_TABLET_TOUCH_BIT 0x40
# define MTOUCH_FORMAT_TABLET_LENGTH 5
# define MTOUCH_RESPONSE_BEGIN_BYTE 0x01
# define MTOUCH_RESPONSE_END_BYTE 0x0d
/* todo: check specs for max length of all responses */
# define MTOUCH_MAX_LENGTH 16
# define MTOUCH_MIN_XC 0
# define MTOUCH_MAX_XC 0x3fff
# define MTOUCH_MIN_YC 0
# define MTOUCH_MAX_YC 0x3fff
# define MTOUCH_GET_XC(data) (((data[2])<<7) | data[1])
# define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3])
# define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0])
/*
* Per - touchscreen data .
*/
struct mtouch {
2005-09-15 11:01:46 +04:00
struct input_dev * dev ;
2005-04-17 02:20:36 +04:00
struct serio * serio ;
int idx ;
unsigned char data [ MTOUCH_MAX_LENGTH ] ;
char phys [ 32 ] ;
} ;
static void mtouch_process_format_tablet ( struct mtouch * mtouch , struct pt_regs * regs )
{
2005-09-15 11:01:46 +04:00
struct input_dev * dev = mtouch - > dev ;
2005-04-17 02:20:36 +04:00
if ( MTOUCH_FORMAT_TABLET_LENGTH = = + + mtouch - > idx ) {
input_regs ( dev , regs ) ;
input_report_abs ( dev , ABS_X , MTOUCH_GET_XC ( mtouch - > data ) ) ;
input_report_abs ( dev , ABS_Y , MTOUCH_MAX_YC - MTOUCH_GET_YC ( mtouch - > data ) ) ;
input_report_key ( dev , BTN_TOUCH , MTOUCH_GET_TOUCHED ( mtouch - > data ) ) ;
input_sync ( dev ) ;
mtouch - > idx = 0 ;
}
}
static void mtouch_process_response ( struct mtouch * mtouch , struct pt_regs * regs )
{
if ( MTOUCH_RESPONSE_END_BYTE = = mtouch - > data [ mtouch - > idx + + ] ) {
/* FIXME - process response */
mtouch - > idx = 0 ;
} else if ( MTOUCH_MAX_LENGTH = = mtouch - > idx ) {
printk ( KERN_ERR " mtouch.c: too many response bytes \n " ) ;
mtouch - > idx = 0 ;
}
}
static irqreturn_t mtouch_interrupt ( struct serio * serio ,
unsigned char data , unsigned int flags , struct pt_regs * regs )
{
struct mtouch * mtouch = serio_get_drvdata ( serio ) ;
mtouch - > data [ mtouch - > idx ] = data ;
if ( MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch - > data [ 0 ] )
mtouch_process_format_tablet ( mtouch , regs ) ;
else if ( MTOUCH_RESPONSE_BEGIN_BYTE = = mtouch - > data [ 0 ] )
mtouch_process_response ( mtouch , regs ) ;
else
printk ( KERN_DEBUG " mtouch.c: unknown/unsynchronized data from device, byte %x \n " , mtouch - > data [ 0 ] ) ;
return IRQ_HANDLED ;
}
/*
* mtouch_disconnect ( ) is the opposite of mtouch_connect ( )
*/
static void mtouch_disconnect ( struct serio * serio )
{
struct mtouch * mtouch = serio_get_drvdata ( serio ) ;
2005-09-15 11:01:46 +04:00
input_get_device ( mtouch - > dev ) ;
input_unregister_device ( mtouch - > dev ) ;
2005-04-17 02:20:36 +04:00
serio_close ( serio ) ;
serio_set_drvdata ( serio , NULL ) ;
2005-09-15 11:01:46 +04:00
input_put_device ( mtouch - > dev ) ;
2005-04-17 02:20:36 +04:00
kfree ( mtouch ) ;
}
/*
* mtouch_connect ( ) is the routine that is called when someone adds a
* new serio device that supports MicroTouch ( Format Tablet ) protocol and registers it as
* an input device .
*/
static int mtouch_connect ( struct serio * serio , struct serio_driver * drv )
{
struct mtouch * mtouch ;
2005-09-15 11:01:46 +04:00
struct input_dev * input_dev ;
2005-04-17 02:20:36 +04:00
int err ;
2005-09-15 11:01:46 +04:00
mtouch = kzalloc ( sizeof ( struct mtouch ) , GFP_KERNEL ) ;
input_dev = input_allocate_device ( ) ;
if ( ! mtouch | | ! input_dev ) {
err = - ENOMEM ;
goto fail ;
}
2005-04-17 02:20:36 +04:00
mtouch - > serio = serio ;
2005-09-15 11:01:46 +04:00
mtouch - > dev = input_dev ;
2006-06-26 09:46:04 +04:00
snprintf ( mtouch - > phys , sizeof ( mtouch - > phys ) , " %s/input0 " , serio - > phys ) ;
2005-04-17 02:20:36 +04:00
2005-09-15 11:01:46 +04:00
input_dev - > private = mtouch ;
input_dev - > name = " MicroTouch Serial TouchScreen " ;
input_dev - > phys = mtouch - > phys ;
input_dev - > id . bustype = BUS_RS232 ;
input_dev - > id . vendor = SERIO_MICROTOUCH ;
input_dev - > id . product = 0 ;
input_dev - > id . version = 0x0100 ;
input_dev - > evbit [ 0 ] = BIT ( EV_KEY ) | BIT ( EV_ABS ) ;
input_dev - > keybit [ LONG ( BTN_TOUCH ) ] = BIT ( BTN_TOUCH ) ;
input_set_abs_params ( mtouch - > dev , ABS_X , MTOUCH_MIN_XC , MTOUCH_MAX_XC , 0 , 0 ) ;
input_set_abs_params ( mtouch - > dev , ABS_Y , MTOUCH_MIN_YC , MTOUCH_MAX_YC , 0 , 0 ) ;
2005-04-17 02:20:36 +04:00
serio_set_drvdata ( serio , mtouch ) ;
err = serio_open ( serio , drv ) ;
2005-09-15 11:01:46 +04:00
if ( err )
goto fail ;
2005-04-17 02:20:36 +04:00
2005-09-15 11:01:46 +04:00
input_register_device ( mtouch - > dev ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
2005-09-15 11:01:46 +04:00
fail : serio_set_drvdata ( serio , NULL ) ;
input_free_device ( input_dev ) ;
kfree ( mtouch ) ;
return err ;
2005-04-17 02:20:36 +04:00
}
/*
* The serio driver structure .
*/
static struct serio_device_id mtouch_serio_ids [ ] = {
{
. type = SERIO_RS232 ,
. proto = SERIO_MICROTOUCH ,
. id = SERIO_ANY ,
. extra = SERIO_ANY ,
} ,
{ 0 }
} ;
MODULE_DEVICE_TABLE ( serio , mtouch_serio_ids ) ;
static struct serio_driver mtouch_drv = {
. driver = {
. name = " mtouch " ,
} ,
. description = DRIVER_DESC ,
. id_table = mtouch_serio_ids ,
. interrupt = mtouch_interrupt ,
. connect = mtouch_connect ,
. disconnect = mtouch_disconnect ,
} ;
/*
* The functions for inserting / removing us as a module .
*/
static int __init mtouch_init ( void )
{
serio_register_driver ( & mtouch_drv ) ;
return 0 ;
}
static void __exit mtouch_exit ( void )
{
serio_unregister_driver ( & mtouch_drv ) ;
}
module_init ( mtouch_init ) ;
module_exit ( mtouch_exit ) ;