diff options
| -rw-r--r-- | drivers/input/touchscreen/elo.c | 225 |
1 files changed, 120 insertions, 105 deletions
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 8f38c5e55ce6..486d31ba9c09 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
| @@ -72,45 +72,49 @@ static void elo_process_data_10(struct elo *elo, unsigned char data) | |||
| 72 | struct input_dev *dev = elo->dev; | 72 | struct input_dev *dev = elo->dev; |
| 73 | 73 | ||
| 74 | elo->data[elo->idx] = data; | 74 | elo->data[elo->idx] = data; |
| 75 | switch (elo->idx++) { | ||
| 76 | case 0: | ||
| 77 | elo->csum = 0xaa; | ||
| 78 | if (data != ELO10_LEAD_BYTE) { | ||
| 79 | pr_debug("elo: unsynchronized data: 0x%02x\n", data); | ||
| 80 | elo->idx = 0; | ||
| 81 | } | ||
| 82 | break; | ||
| 83 | 75 | ||
| 84 | case 9: | 76 | switch (elo->idx++) { |
| 77 | case 0: | ||
| 78 | elo->csum = 0xaa; | ||
| 79 | if (data != ELO10_LEAD_BYTE) { | ||
| 80 | dev_dbg(&elo->serio->dev, | ||
| 81 | "unsynchronized data: 0x%02x\n", data); | ||
| 85 | elo->idx = 0; | 82 | elo->idx = 0; |
| 86 | if (data != elo->csum) { | 83 | } |
| 87 | pr_debug("elo: bad checksum: 0x%02x, expected 0x%02x\n", | 84 | break; |
| 88 | data, elo->csum); | 85 | |
| 89 | break; | 86 | case 9: |
| 90 | } | 87 | elo->idx = 0; |
| 91 | if (elo->data[1] != elo->expected_packet) { | 88 | if (data != elo->csum) { |
| 92 | if (elo->data[1] != ELO10_TOUCH_PACKET) | 89 | dev_dbg(&elo->serio->dev, |
| 93 | pr_debug("elo: unexpected packet: 0x%02x\n", | 90 | "bad checksum: 0x%02x, expected 0x%02x\n", |
| 94 | elo->data[1]); | 91 | data, elo->csum); |
| 95 | break; | 92 | break; |
| 96 | } | 93 | } |
| 97 | if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { | 94 | if (elo->data[1] != elo->expected_packet) { |
| 98 | input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); | 95 | if (elo->data[1] != ELO10_TOUCH_PACKET) |
| 99 | input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); | 96 | dev_dbg(&elo->serio->dev, |
| 100 | if (elo->data[2] & ELO10_PRESSURE) | 97 | "unexpected packet: 0x%02x\n", |
| 101 | input_report_abs(dev, ABS_PRESSURE, | 98 | elo->data[1]); |
| 102 | (elo->data[8] << 8) | elo->data[7]); | ||
| 103 | input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); | ||
| 104 | input_sync(dev); | ||
| 105 | } else if (elo->data[1] == ELO10_ACK_PACKET) { | ||
| 106 | if (elo->data[2] == '0') | ||
| 107 | elo->expected_packet = ELO10_TOUCH_PACKET; | ||
| 108 | complete(&elo->cmd_done); | ||
| 109 | } else { | ||
| 110 | memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); | ||
| 111 | elo->expected_packet = ELO10_ACK_PACKET; | ||
| 112 | } | ||
| 113 | break; | 99 | break; |
| 100 | } | ||
| 101 | if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { | ||
| 102 | input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); | ||
| 103 | input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); | ||
| 104 | if (elo->data[2] & ELO10_PRESSURE) | ||
| 105 | input_report_abs(dev, ABS_PRESSURE, | ||
| 106 | (elo->data[8] << 8) | elo->data[7]); | ||
| 107 | input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); | ||
| 108 | input_sync(dev); | ||
| 109 | } else if (elo->data[1] == ELO10_ACK_PACKET) { | ||
| 110 | if (elo->data[2] == '0') | ||
| 111 | elo->expected_packet = ELO10_TOUCH_PACKET; | ||
| 112 | complete(&elo->cmd_done); | ||
| 113 | } else { | ||
| 114 | memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); | ||
| 115 | elo->expected_packet = ELO10_ACK_PACKET; | ||
| 116 | } | ||
| 117 | break; | ||
| 114 | } | 118 | } |
| 115 | elo->csum += data; | 119 | elo->csum += data; |
| 116 | } | 120 | } |
| @@ -123,42 +127,53 @@ static void elo_process_data_6(struct elo *elo, unsigned char data) | |||
| 123 | 127 | ||
| 124 | switch (elo->idx++) { | 128 | switch (elo->idx++) { |
| 125 | 129 | ||
| 126 | case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break; | 130 | case 0: |
| 127 | case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break; | 131 | if ((data & 0xc0) != 0xc0) |
| 128 | case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break; | 132 | elo->idx = 0; |
| 129 | 133 | break; | |
| 130 | case 3: | ||
| 131 | if (data & 0xc0) { | ||
| 132 | elo->idx = 0; | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | 134 | ||
| 136 | input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); | 135 | case 1: |
| 137 | input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); | 136 | if ((data & 0xc0) != 0x80) |
| 137 | elo->idx = 0; | ||
| 138 | break; | ||
| 138 | 139 | ||
| 139 | if (elo->id == 2) { | 140 | case 2: |
| 140 | input_report_key(dev, BTN_TOUCH, 1); | 141 | if ((data & 0xc0) != 0x40) |
| 141 | input_sync(dev); | 142 | elo->idx = 0; |
| 142 | elo->idx = 0; | 143 | break; |
| 143 | } | ||
| 144 | 144 | ||
| 145 | case 3: | ||
| 146 | if (data & 0xc0) { | ||
| 147 | elo->idx = 0; | ||
| 145 | break; | 148 | break; |
| 149 | } | ||
| 146 | 150 | ||
| 147 | case 4: | 151 | input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); |
| 148 | if (data) { | 152 | input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); |
| 149 | input_sync(dev); | ||
| 150 | elo->idx = 0; | ||
| 151 | } | ||
| 152 | break; | ||
| 153 | 153 | ||
| 154 | case 5: | 154 | if (elo->id == 2) { |
| 155 | if ((data & 0xf0) == 0) { | 155 | input_report_key(dev, BTN_TOUCH, 1); |
| 156 | input_report_abs(dev, ABS_PRESSURE, elo->data[5]); | ||
| 157 | input_report_key(dev, BTN_TOUCH, !!elo->data[5]); | ||
| 158 | } | ||
| 159 | input_sync(dev); | 156 | input_sync(dev); |
| 160 | elo->idx = 0; | 157 | elo->idx = 0; |
| 161 | break; | 158 | } |
| 159 | |||
| 160 | break; | ||
| 161 | |||
| 162 | case 4: | ||
| 163 | if (data) { | ||
| 164 | input_sync(dev); | ||
| 165 | elo->idx = 0; | ||
| 166 | } | ||
| 167 | break; | ||
| 168 | |||
| 169 | case 5: | ||
| 170 | if ((data & 0xf0) == 0) { | ||
| 171 | input_report_abs(dev, ABS_PRESSURE, elo->data[5]); | ||
| 172 | input_report_key(dev, BTN_TOUCH, !!elo->data[5]); | ||
| 173 | } | ||
| 174 | input_sync(dev); | ||
| 175 | elo->idx = 0; | ||
| 176 | break; | ||
| 162 | } | 177 | } |
| 163 | } | 178 | } |
| 164 | 179 | ||
| @@ -170,17 +185,17 @@ static void elo_process_data_3(struct elo *elo, unsigned char data) | |||
| 170 | 185 | ||
| 171 | switch (elo->idx++) { | 186 | switch (elo->idx++) { |
| 172 | 187 | ||
| 173 | case 0: | 188 | case 0: |
| 174 | if ((data & 0x7f) != 0x01) | 189 | if ((data & 0x7f) != 0x01) |
| 175 | elo->idx = 0; | ||
| 176 | break; | ||
| 177 | case 2: | ||
| 178 | input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); | ||
| 179 | input_report_abs(dev, ABS_X, elo->data[1]); | ||
| 180 | input_report_abs(dev, ABS_Y, elo->data[2]); | ||
| 181 | input_sync(dev); | ||
| 182 | elo->idx = 0; | 190 | elo->idx = 0; |
| 183 | break; | 191 | break; |
| 192 | case 2: | ||
| 193 | input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); | ||
| 194 | input_report_abs(dev, ABS_X, elo->data[1]); | ||
| 195 | input_report_abs(dev, ABS_Y, elo->data[2]); | ||
| 196 | input_sync(dev); | ||
| 197 | elo->idx = 0; | ||
| 198 | break; | ||
| 184 | } | 199 | } |
| 185 | } | 200 | } |
| 186 | 201 | ||
| @@ -189,19 +204,19 @@ static irqreturn_t elo_interrupt(struct serio *serio, | |||
| 189 | { | 204 | { |
| 190 | struct elo *elo = serio_get_drvdata(serio); | 205 | struct elo *elo = serio_get_drvdata(serio); |
| 191 | 206 | ||
| 192 | switch(elo->id) { | 207 | switch (elo->id) { |
| 193 | case 0: | 208 | case 0: |
| 194 | elo_process_data_10(elo, data); | 209 | elo_process_data_10(elo, data); |
| 195 | break; | 210 | break; |
| 196 | 211 | ||
| 197 | case 1: | 212 | case 1: |
| 198 | case 2: | 213 | case 2: |
| 199 | elo_process_data_6(elo, data); | 214 | elo_process_data_6(elo, data); |
| 200 | break; | 215 | break; |
| 201 | 216 | ||
| 202 | case 3: | 217 | case 3: |
| 203 | elo_process_data_3(elo, data); | 218 | elo_process_data_3(elo, data); |
| 204 | break; | 219 | break; |
| 205 | } | 220 | } |
| 206 | 221 | ||
| 207 | return IRQ_HANDLED; | 222 | return IRQ_HANDLED; |
| @@ -261,10 +276,10 @@ static int elo_setup_10(struct elo *elo) | |||
| 261 | if (packet[3] & ELO10_PRESSURE) | 276 | if (packet[3] & ELO10_PRESSURE) |
| 262 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 277 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
| 263 | 278 | ||
| 264 | printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, " | 279 | dev_info(&elo->serio->dev, |
| 265 | "features: 0x%02x, controller: 0x%02x\n", | 280 | "%sTouch touchscreen, fw: %02x.%02x, features: 0x%02x, controller: 0x%02x\n", |
| 266 | elo_types[(packet[1] -'0') & 0x03], | 281 | elo_types[(packet[1] -'0') & 0x03], |
| 267 | packet[5], packet[4], packet[3], packet[7]); | 282 | packet[5], packet[4], packet[3], packet[7]); |
| 268 | 283 | ||
| 269 | return 0; | 284 | return 0; |
| 270 | } | 285 | } |
| @@ -330,24 +345,24 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
| 330 | 345 | ||
| 331 | switch (elo->id) { | 346 | switch (elo->id) { |
| 332 | 347 | ||
| 333 | case 0: /* 10-byte protocol */ | 348 | case 0: /* 10-byte protocol */ |
| 334 | if (elo_setup_10(elo)) | 349 | if (elo_setup_10(elo)) |
| 335 | goto fail3; | 350 | goto fail3; |
| 336 | 351 | ||
| 337 | break; | 352 | break; |
| 338 | 353 | ||
| 339 | case 1: /* 6-byte protocol */ | 354 | case 1: /* 6-byte protocol */ |
| 340 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); | 355 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); |
| 341 | 356 | ||
| 342 | case 2: /* 4-byte protocol */ | 357 | case 2: /* 4-byte protocol */ |
| 343 | input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); | 358 | input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); |
| 344 | input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); | 359 | input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); |
| 345 | break; | 360 | break; |
| 346 | 361 | ||
| 347 | case 3: /* 3-byte protocol */ | 362 | case 3: /* 3-byte protocol */ |
| 348 | input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0); | 363 | input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0); |
| 349 | input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0); | 364 | input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0); |
| 350 | break; | 365 | break; |
| 351 | } | 366 | } |
| 352 | 367 | ||
| 353 | err = input_register_device(elo->dev); | 368 | err = input_register_device(elo->dev); |
