aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/penmount.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2011-09-13 01:12:58 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-09-21 01:46:30 -0400
commit98b013eb7a94cfd29fcc782f3b7d9f9fe06ac50d (patch)
treecb2f76a8e6bdfdf24055e1564ec2085a72b99f6d /drivers/input/touchscreen/penmount.c
parentbd8f6d2ed416d6c70fc3d4f98b165a56e025331c (diff)
Input: penmount - rework handling of different protocols
Instead of having one large switch based on product ID use pointer to function actually doing protocol decoding. Tested-by: John Sung <penmount.touch@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen/penmount.c')
-rw-r--r--drivers/input/touchscreen/penmount.c120
1 files changed, 64 insertions, 56 deletions
diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c
index a047850e38b1..7fc556295c0e 100644
--- a/drivers/input/touchscreen/penmount.c
+++ b/drivers/input/touchscreen/penmount.c
@@ -61,6 +61,7 @@ struct pm {
61 unsigned char packetsize; 61 unsigned char packetsize;
62 unsigned char maxcontacts; 62 unsigned char maxcontacts;
63 struct mt_slot slots[PM_MAX_MTSLOT]; 63 struct mt_slot slots[PM_MAX_MTSLOT];
64 void (*parse_packet)(struct pm *);
64}; 65};
65 66
66/* 67/*
@@ -100,73 +101,76 @@ static bool pm_checkpacket(unsigned char *packet)
100 return packet[5] == (unsigned char)~(total & 0xff); 101 return packet[5] == (unsigned char)~(total & 0xff);
101} 102}
102 103
103static irqreturn_t pm_interrupt(struct serio *serio, 104static void pm_parse_9000(struct pm *pm)
104 unsigned char data, unsigned int flags)
105{ 105{
106 struct pm *pm = serio_get_drvdata(serio);
107 struct input_dev *dev = pm->dev; 106 struct input_dev *dev = pm->dev;
108 107
109 pm->data[pm->idx] = data; 108 if ((pm->data[0] & 0x80) && pm->packetsize == ++pm->idx) {
109 input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]);
110 input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]);
111 input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
112 input_sync(dev);
113 pm->idx = 0;
114 }
115}
110 116
111 switch (pm->dev->id.product) { 117static void pm_parse_6000(struct pm *pm)
112 case 0x9000: 118{
113 if (pm->data[0] & 0x80) { 119 struct input_dev *dev = pm->dev;
114 if (pm->packetsize == ++pm->idx) {
115 input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]);
116 input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]);
117 input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
118 input_sync(dev);
119 pm->idx = 0;
120 }
121 }
122 break;
123 120
124 case 0x6000: 121 if ((pm->data[0] & 0xbf) == 0x30 && pm->packetsize == ++pm->idx) {
125 if ((pm->data[0] & 0xbf) == 0x30) { 122 if (pm_checkpacket(pm->data)) {
126 if (pm->packetsize == ++pm->idx) { 123 input_report_abs(dev, ABS_X,
127 if (pm_checkpacket(pm->data)) { 124 pm->data[2] * 256 + pm->data[1]);
128 input_report_abs(dev, ABS_X, 125 input_report_abs(dev, ABS_Y,
129 pm->data[2] * 256 + pm->data[1]); 126 pm->data[4] * 256 + pm->data[3]);
130 input_report_abs(dev, ABS_Y, 127 input_report_key(dev, BTN_TOUCH, pm->data[0] & 0x40);
131 pm->data[4] * 256 + pm->data[3]); 128 input_sync(dev);
132 input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
133 input_sync(dev);
134 }
135 pm->idx = 0;
136 }
137 } 129 }
138 break; 130 pm->idx = 0;
131 }
132}
133
134static void pm_parse_3000(struct pm *pm)
135{
136 struct input_dev *dev = pm->dev;
139 137
140 case 0x3000: 138 if ((pm->data[0] & 0xce) == 0x40 && pm->packetsize == ++pm->idx) {
141 if ((pm->data[0] & 0xce) == 0x40) { 139 if (pm_checkpacket(pm->data)) {
142 if (pm->packetsize == ++pm->idx) { 140 int slotnum = pm->data[0] & 0x0f;
143 if (pm_checkpacket(pm->data)) { 141 pm->slots[slotnum].active = pm->data[0] & 0x30;
144 int slotnum = pm->data[0] & 0x0f; 142 pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
145 pm->slots[slotnum].active = pm->data[0] & 0x30; 143 pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
146 pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1]; 144 pm_mtevent(pm, dev);
147 pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
148 pm_mtevent(pm, dev);
149 }
150 pm->idx = 0;
151 }
152 } 145 }
153 break; 146 pm->idx = 0;
147 }
148}
149
150static void pm_parse_6250(struct pm *pm)
151{
152 struct input_dev *dev = pm->dev;
154 153
155 case 0x6250: 154 if ((pm->data[0] & 0xb0) == 0x30 && pm->packetsize == ++pm->idx) {
156 if ((pm->data[0] & 0xb0) == 0x30) { 155 if (pm_checkpacket(pm->data)) {
157 if (pm->packetsize == ++pm->idx) { 156 int slotnum = pm->data[0] & 0x0f;
158 if (pm_checkpacket(pm->data)) { 157 pm->slots[slotnum].active = pm->data[0] & 0x40;
159 int slotnum = pm->data[0] & 0x0f; 158 pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
160 pm->slots[slotnum].active = pm->data[0] & 0x40; 159 pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
161 pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1]; 160 pm_mtevent(pm, dev);
162 pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
163 pm_mtevent(pm, dev);
164 }
165 pm->idx = 0;
166 }
167 } 161 }
168 break; 162 pm->idx = 0;
169 } 163 }
164}
165
166static irqreturn_t pm_interrupt(struct serio *serio,
167 unsigned char data, unsigned int flags)
168{
169 struct pm *pm = serio_get_drvdata(serio);
170
171 pm->data[pm->idx] = data;
172
173 pm->parse_packet(pm);
170 174
171 return IRQ_HANDLED; 175 return IRQ_HANDLED;
172} 176}
@@ -227,18 +231,21 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
227 default: 231 default:
228 case 0: 232 case 0:
229 pm->packetsize = 5; 233 pm->packetsize = 5;
234 pm->parse_packet = pm_parse_9000;
230 input_dev->id.product = 0x9000; 235 input_dev->id.product = 0x9000;
231 max_x = max_y = 0x3ff; 236 max_x = max_y = 0x3ff;
232 break; 237 break;
233 238
234 case 1: 239 case 1:
235 pm->packetsize = 6; 240 pm->packetsize = 6;
241 pm->parse_packet = pm_parse_6000;
236 input_dev->id.product = 0x6000; 242 input_dev->id.product = 0x6000;
237 max_x = max_y = 0x3ff; 243 max_x = max_y = 0x3ff;
238 break; 244 break;
239 245
240 case 2: 246 case 2:
241 pm->packetsize = 6; 247 pm->packetsize = 6;
248 pm->parse_packet = pm_parse_3000;
242 input_dev->id.product = 0x3000; 249 input_dev->id.product = 0x3000;
243 max_x = max_y = 0x7ff; 250 max_x = max_y = 0x7ff;
244 pm->maxcontacts = PM_3000_MTSLOT; 251 pm->maxcontacts = PM_3000_MTSLOT;
@@ -246,6 +253,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv)
246 253
247 case 3: 254 case 3:
248 pm->packetsize = 6; 255 pm->packetsize = 6;
256 pm->parse_packet = pm_parse_6250;
249 input_dev->id.product = 0x6250; 257 input_dev->id.product = 0x6250;
250 max_x = max_y = 0x3ff; 258 max_x = max_y = 0x3ff;
251 pm->maxcontacts = PM_6250_MTSLOT; 259 pm->maxcontacts = PM_6250_MTSLOT;