diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-09-13 01:12:58 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-09-21 01:46:30 -0400 |
commit | 98b013eb7a94cfd29fcc782f3b7d9f9fe06ac50d (patch) | |
tree | cb2f76a8e6bdfdf24055e1564ec2085a72b99f6d /drivers/input/touchscreen/penmount.c | |
parent | bd8f6d2ed416d6c70fc3d4f98b165a56e025331c (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.c | 120 |
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 | ||
103 | static irqreturn_t pm_interrupt(struct serio *serio, | 104 | static 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) { | 117 | static 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 | |||
134 | static 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 | |||
150 | static 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 | |||
166 | static 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; |