2 * Penmount serial touchscreen driver
4 * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
6 * Based on ELO driver (drivers/input/touchscreen/elo.c)
7 * Copyright (c) 2004 Vojtech Pavlik
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation.
16 #include <linux/errno.h>
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/slab.h>
20 #include <linux/input.h>
21 #include <linux/serio.h>
22 #include <linux/init.h>
24 #define DRIVER_DESC "Penmount serial touchscreen driver"
26 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
27 MODULE_DESCRIPTION(DRIVER_DESC
);
28 MODULE_LICENSE("GPL");
31 * Definitions & global arrays.
34 #define PM_MAX_LENGTH 5
37 * Per-touchscreen data.
41 struct input_dev
*dev
;
44 unsigned char data
[PM_MAX_LENGTH
];
48 static irqreturn_t
pm_interrupt(struct serio
*serio
,
49 unsigned char data
, unsigned int flags
)
51 struct pm
*pm
= serio_get_drvdata(serio
);
52 struct input_dev
*dev
= pm
->dev
;
54 pm
->data
[pm
->idx
] = data
;
56 if (pm
->data
[0] & 0x80) {
57 if (PM_MAX_LENGTH
== ++pm
->idx
) {
58 input_report_abs(dev
, ABS_X
, pm
->data
[2] * 128 + pm
->data
[1]);
59 input_report_abs(dev
, ABS_Y
, pm
->data
[4] * 128 + pm
->data
[3]);
60 input_report_key(dev
, BTN_TOUCH
, !!(pm
->data
[0] & 0x40));
70 * pm_disconnect() is the opposite of pm_connect()
73 static void pm_disconnect(struct serio
*serio
)
75 struct pm
*pm
= serio_get_drvdata(serio
);
77 input_get_device(pm
->dev
);
78 input_unregister_device(pm
->dev
);
80 serio_set_drvdata(serio
, NULL
);
81 input_put_device(pm
->dev
);
86 * pm_connect() is the routine that is called when someone adds a
87 * new serio device that supports Gunze protocol and registers it as
91 static int pm_connect(struct serio
*serio
, struct serio_driver
*drv
)
94 struct input_dev
*input_dev
;
97 pm
= kzalloc(sizeof(struct pm
), GFP_KERNEL
);
98 input_dev
= input_allocate_device();
99 if (!pm
|| !input_dev
) {
106 snprintf(pm
->phys
, sizeof(pm
->phys
), "%s/input0", serio
->phys
);
108 input_dev
->name
= "Penmount Serial TouchScreen";
109 input_dev
->phys
= pm
->phys
;
110 input_dev
->id
.bustype
= BUS_RS232
;
111 input_dev
->id
.vendor
= SERIO_PENMOUNT
;
112 input_dev
->id
.product
= 0;
113 input_dev
->id
.version
= 0x0100;
114 input_dev
->dev
.parent
= &serio
->dev
;
116 input_dev
->evbit
[0] = BIT(EV_KEY
) | BIT(EV_ABS
);
117 input_dev
->keybit
[LONG(BTN_TOUCH
)] = BIT(BTN_TOUCH
);
118 input_set_abs_params(pm
->dev
, ABS_X
, 0, 0x3ff, 0, 0);
119 input_set_abs_params(pm
->dev
, ABS_Y
, 0, 0x3ff, 0, 0);
121 serio_set_drvdata(serio
, pm
);
123 err
= serio_open(serio
, drv
);
127 err
= input_register_device(pm
->dev
);
133 fail3
: serio_close(serio
);
134 fail2
: serio_set_drvdata(serio
, NULL
);
135 fail1
: input_free_device(input_dev
);
141 * The serio driver structure.
144 static struct serio_device_id pm_serio_ids
[] = {
147 .proto
= SERIO_PENMOUNT
,
154 MODULE_DEVICE_TABLE(serio
, pm_serio_ids
);
156 static struct serio_driver pm_drv
= {
158 .name
= "penmountlpc",
160 .description
= DRIVER_DESC
,
161 .id_table
= pm_serio_ids
,
162 .interrupt
= pm_interrupt
,
163 .connect
= pm_connect
,
164 .disconnect
= pm_disconnect
,
168 * The functions for inserting/removing us as a module.
171 static int __init
pm_init(void)
173 return serio_register_driver(&pm_drv
);
176 static void __exit
pm_exit(void)
178 serio_unregister_driver(&pm_drv
);
181 module_init(pm_init
);
182 module_exit(pm_exit
);