aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
authorJohn Sung <penmount.touch@gmail.com>2011-09-09 16:33:12 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-09-21 01:46:29 -0400
commitc42e2e406ad49f320947ba044d3bbf9b05703089 (patch)
tree76044dcd6f5a8d3f5b6f1c3b2c7bc742876f2b86 /drivers/input/touchscreen
parent21ae508bab28c2b0ae8709c95a36739b6f1ae5be (diff)
Input: penmount - add PenMount 6000 support
Add support for PenMount 6000 touch controller. Signed-off-by: John Sung <penmount.touch@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/penmount.c65
1 files changed, 57 insertions, 8 deletions
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index 3342c6d8e57d..e9117adcf6df 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -33,7 +33,7 @@ MODULE_LICENSE("GPL");
33 * Definitions & global arrays. 33 * Definitions & global arrays.
34 */ 34 */
35 35
36#define PM_MAX_LENGTH 5 36#define PM_MAX_LENGTH 6
37 37
38/* 38/*
39 * Per-touchscreen data. 39 * Per-touchscreen data.
@@ -45,8 +45,24 @@ struct pm {
45 int idx; 45 int idx;
46 unsigned char data[PM_MAX_LENGTH]; 46 unsigned char data[PM_MAX_LENGTH];
47 char phys[32]; 47 char phys[32];
48 unsigned char packetsize;
48}; 49};
49 50
51/*
52 * pm_checkpacket() checks if data packet is valid
53 */
54
55static bool pm_checkpacket(unsigned char *packet)
56{
57 int total = 0;
58 int i;
59
60 for (i = 0; i < 5; i++)
61 total += packet[i];
62
63 return packet[5] == (unsigned char)~(total & 0xff);
64}
65
50static irqreturn_t pm_interrupt(struct serio *serio, 66static irqreturn_t pm_interrupt(struct serio *serio,
51 unsigned char data, unsigned int flags) 67 unsigned char data, unsigned int flags)
52{ 68{
@@ -55,14 +71,34 @@ static irqreturn_t pm_interrupt(struct serio *serio,
55 71
56 pm->data[pm->idx] = data; 72 pm->data[pm->idx] = data;
57 73
58 if (pm->data[0] & 0x80) { 74 switch (pm->dev->id.product) {
59 if (PM_MAX_LENGTH == ++pm->idx) { 75 case 0x9000:
60 input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]); 76 if (pm->data[0] & 0x80) {
61 input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]); 77 if (pm->packetsize == ++pm->idx) {
62 input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40)); 78 input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]);
63 input_sync(dev); 79 input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]);
64 pm->idx = 0; 80 input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
81 input_sync(dev);
82 pm->idx = 0;
83 }
84 }
85 break;
86
87 case 0x6000:
88 if ((pm->data[0] & 0xbf) == 0x30) {
89 if (pm->packetsize == ++pm->idx) {
90 if (pm_checkpacket(pm->data)) {
91 input_report_abs(dev, ABS_X,
92 pm->data[2] * 256 + pm->data[1]);
93 input_report_abs(dev, ABS_Y,
94 pm->data[4] * 256 + pm->data[3]);
95 input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
96 input_sync(dev);
97 }
98 pm->idx = 0;
99 }
65 } 100 }
101 break;
66 } 102 }
67 103
68 return IRQ_HANDLED; 104 return IRQ_HANDLED;
@@ -120,6 +156,19 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
120 input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0); 156 input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0);
121 input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0); 157 input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0);
122 158
159 switch (serio->id.id) {
160 default:
161 case 0:
162 pm->packetsize = 5;
163 input_dev->id.product = 0x9000;
164 break;
165
166 case 1:
167 pm->packetsize = 6;
168 input_dev->id.product = 0x6000;
169 break;
170 }
171
123 serio_set_drvdata(serio, pm); 172 serio_set_drvdata(serio, pm);
124 173
125 err = serio_open(serio, drv); 174 err = serio_open(serio, drv);