diff options
| author | Shaun Jackman <sjackman@gmail.com> | 2006-08-05 00:29:49 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dtor@insightbb.com> | 2006-08-05 00:29:49 -0400 |
| commit | fae3006e4b42eafbed4af714e93cf6c2b92ff793 (patch) | |
| tree | 5b7ece07ff46be2f315de4ce6b15c6b0a2f823c8 /drivers/input/touchscreen | |
| parent | 1ce316efb55a1497d07d518853e60a4356abceb6 (diff) | |
Input: elo - add support for non-pressure-sensitive touchscreens
- Use the touch status bit rather than the pressure bits to
distinguish a BTN_TOUCH event. Non-pressure-sensitive touchscreens
always report full pressure
- Report ABS_PRESSURE information only if the touchscreen supports it
Signed-off-by: Shaun Jackman <sjackman@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen')
| -rw-r--r-- | drivers/input/touchscreen/elo.c | 124 |
1 files changed, 107 insertions, 17 deletions
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index fe6e1a4286..ab565335ee 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
| 24 | #include <linux/serio.h> | 24 | #include <linux/serio.h> |
| 25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 26 | #include <linux/ctype.h> | ||
| 26 | 27 | ||
| 27 | #define DRIVER_DESC "Elo serial touchscreen driver" | 28 | #define DRIVER_DESC "Elo serial touchscreen driver" |
| 28 | 29 | ||
| @@ -36,9 +37,17 @@ MODULE_LICENSE("GPL"); | |||
| 36 | 37 | ||
| 37 | #define ELO_MAX_LENGTH 10 | 38 | #define ELO_MAX_LENGTH 10 |
| 38 | 39 | ||
| 40 | #define ELO10_PACKET_LEN 8 | ||
| 41 | #define ELO10_TOUCH 0x03 | ||
| 42 | #define ELO10_PRESSURE 0x80 | ||
| 43 | |||
| 39 | #define ELO10_LEAD_BYTE 'U' | 44 | #define ELO10_LEAD_BYTE 'U' |
| 40 | 45 | ||
| 46 | #define ELO10_ID_CMD 'i' | ||
| 47 | |||
| 41 | #define ELO10_TOUCH_PACKET 'T' | 48 | #define ELO10_TOUCH_PACKET 'T' |
| 49 | #define ELO10_ACK_PACKET 'A' | ||
| 50 | #define ELI10_ID_PACKET 'I' | ||
| 42 | 51 | ||
| 43 | /* | 52 | /* |
| 44 | * Per-touchscreen data. | 53 | * Per-touchscreen data. |
| @@ -47,10 +56,14 @@ MODULE_LICENSE("GPL"); | |||
| 47 | struct elo { | 56 | struct elo { |
| 48 | struct input_dev *dev; | 57 | struct input_dev *dev; |
| 49 | struct serio *serio; | 58 | struct serio *serio; |
| 59 | struct mutex cmd_mutex; | ||
| 60 | struct completion cmd_done; | ||
| 50 | int id; | 61 | int id; |
| 51 | int idx; | 62 | int idx; |
| 63 | unsigned char expected_packet; | ||
| 52 | unsigned char csum; | 64 | unsigned char csum; |
| 53 | unsigned char data[ELO_MAX_LENGTH]; | 65 | unsigned char data[ELO_MAX_LENGTH]; |
| 66 | unsigned char response[ELO10_PACKET_LEN]; | ||
| 54 | char phys[32]; | 67 | char phys[32]; |
| 55 | }; | 68 | }; |
| 56 | 69 | ||
| @@ -75,16 +88,29 @@ static void elo_process_data_10(struct elo *elo, unsigned char data, struct pt_r | |||
| 75 | data, elo->csum); | 88 | data, elo->csum); |
| 76 | break; | 89 | break; |
| 77 | } | 90 | } |
| 78 | if (elo->data[1] != ELO10_TOUCH_PACKET) { | 91 | if (elo->data[1] != elo->expected_packet) { |
| 79 | pr_debug(elo: "unexpected packet: 0x%02x\n", elo->data[1]); | 92 | if (elo->data[1] != ELO10_TOUCH_PACKET) |
| 93 | pr_debug("elo: unexpected packet: 0x%02x\n", | ||
| 94 | elo->data[1]); | ||
| 80 | break; | 95 | break; |
| 81 | } | 96 | } |
| 82 | input_regs(dev, regs); | 97 | if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { |
| 83 | input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); | 98 | input_regs(dev, regs); |
| 84 | input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); | 99 | input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); |
| 85 | input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]); | 100 | input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); |
| 86 | input_report_key(dev, BTN_TOUCH, elo->data[8] || elo->data[7]); | 101 | if (elo->data[2] & ELO10_PRESSURE) |
| 87 | input_sync(dev); | 102 | input_report_abs(dev, ABS_PRESSURE, |
| 103 | (elo->data[8] << 8) | elo->data[7]); | ||
| 104 | input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); | ||
| 105 | input_sync(dev); | ||
| 106 | } else if (elo->data[1] == ELO10_ACK_PACKET) { | ||
| 107 | if (elo->data[2] == '0') | ||
| 108 | elo->expected_packet = ELO10_TOUCH_PACKET; | ||
| 109 | complete(&elo->cmd_done); | ||
| 110 | } else { | ||
| 111 | memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); | ||
| 112 | elo->expected_packet = ELO10_ACK_PACKET; | ||
| 113 | } | ||
| 88 | break; | 114 | break; |
| 89 | } | 115 | } |
| 90 | elo->csum += data; | 116 | elo->csum += data; |
| @@ -184,6 +210,68 @@ static irqreturn_t elo_interrupt(struct serio *serio, | |||
| 184 | return IRQ_HANDLED; | 210 | return IRQ_HANDLED; |
| 185 | } | 211 | } |
| 186 | 212 | ||
| 213 | static int elo_command_10(struct elo *elo, unsigned char *packet) | ||
| 214 | { | ||
| 215 | int rc = -1; | ||
| 216 | int i; | ||
| 217 | unsigned char csum = 0xaa + ELO10_LEAD_BYTE; | ||
| 218 | |||
| 219 | mutex_lock(&elo->cmd_mutex); | ||
| 220 | |||
| 221 | serio_pause_rx(elo->serio); | ||
| 222 | elo->expected_packet = toupper(packet[0]); | ||
| 223 | init_completion(&elo->cmd_done); | ||
| 224 | serio_continue_rx(elo->serio); | ||
| 225 | |||
| 226 | if (serio_write(elo->serio, ELO10_LEAD_BYTE)) | ||
| 227 | goto out; | ||
| 228 | |||
| 229 | for (i = 0; i < ELO10_PACKET_LEN; i++) { | ||
| 230 | csum += packet[i]; | ||
| 231 | if (serio_write(elo->serio, packet[i])) | ||
| 232 | goto out; | ||
| 233 | } | ||
| 234 | |||
| 235 | if (serio_write(elo->serio, csum)) | ||
| 236 | goto out; | ||
| 237 | |||
| 238 | wait_for_completion_timeout(&elo->cmd_done, HZ); | ||
| 239 | |||
| 240 | if (elo->expected_packet == ELO10_TOUCH_PACKET) { | ||
| 241 | /* We are back in reporting mode, the command was ACKed */ | ||
| 242 | memcpy(packet, elo->response, ELO10_PACKET_LEN); | ||
| 243 | rc = 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | out: | ||
| 247 | mutex_unlock(&elo->cmd_mutex); | ||
| 248 | return rc; | ||
| 249 | } | ||
| 250 | |||
| 251 | static int elo_setup_10(struct elo *elo) | ||
| 252 | { | ||
| 253 | static const char *elo_types[] = { "Accu", "Dura", "Intelli", "Carroll" }; | ||
| 254 | struct input_dev *dev = elo->dev; | ||
| 255 | unsigned char packet[ELO10_PACKET_LEN] = { ELO10_ID_CMD }; | ||
| 256 | |||
| 257 | if (elo_command_10(elo, packet)) | ||
| 258 | return -1; | ||
| 259 | |||
| 260 | dev->id.version = (packet[5] << 8) | packet[4]; | ||
| 261 | |||
| 262 | input_set_abs_params(dev, ABS_X, 96, 4000, 0, 0); | ||
| 263 | input_set_abs_params(dev, ABS_Y, 96, 4000, 0, 0); | ||
| 264 | if (packet[3] & ELO10_PRESSURE) | ||
| 265 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | ||
| 266 | |||
| 267 | printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, " | ||
| 268 | "features: %x02x, controller: 0x%02x\n", | ||
| 269 | elo_types[(packet[1] -'0') & 0x03], | ||
| 270 | packet[5], packet[4], packet[3], packet[7]); | ||
| 271 | |||
| 272 | return 0; | ||
| 273 | } | ||
| 274 | |||
| 187 | /* | 275 | /* |
| 188 | * elo_disconnect() is the opposite of elo_connect() | 276 | * elo_disconnect() is the opposite of elo_connect() |
| 189 | */ | 277 | */ |
| @@ -222,6 +310,9 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
| 222 | elo->serio = serio; | 310 | elo->serio = serio; |
| 223 | elo->id = serio->id.id; | 311 | elo->id = serio->id.id; |
| 224 | elo->dev = input_dev; | 312 | elo->dev = input_dev; |
| 313 | elo->expected_packet = ELO10_TOUCH_PACKET; | ||
| 314 | mutex_init(&elo->cmd_mutex); | ||
| 315 | init_completion(&elo->cmd_done); | ||
| 225 | snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); | 316 | snprintf(elo->phys, sizeof(elo->phys), "%s/input0", serio->phys); |
| 226 | 317 | ||
| 227 | input_dev->private = elo; | 318 | input_dev->private = elo; |
| @@ -236,12 +327,17 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
| 236 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 327 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
| 237 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | 328 | input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); |
| 238 | 329 | ||
| 330 | serio_set_drvdata(serio, elo); | ||
| 331 | err = serio_open(serio, drv); | ||
| 332 | if (err) | ||
| 333 | goto fail2; | ||
| 334 | |||
| 239 | switch (elo->id) { | 335 | switch (elo->id) { |
| 240 | 336 | ||
| 241 | case 0: /* 10-byte protocol */ | 337 | case 0: /* 10-byte protocol */ |
| 242 | input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); | 338 | if (elo_setup_10(elo)) |
| 243 | input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); | 339 | goto fail3; |
| 244 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); | 340 | |
| 245 | break; | 341 | break; |
| 246 | 342 | ||
| 247 | case 1: /* 6-byte protocol */ | 343 | case 1: /* 6-byte protocol */ |
| @@ -258,12 +354,6 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
| 258 | break; | 354 | break; |
| 259 | } | 355 | } |
| 260 | 356 | ||
| 261 | serio_set_drvdata(serio, elo); | ||
| 262 | |||
| 263 | err = serio_open(serio, drv); | ||
| 264 | if (err) | ||
| 265 | goto fail2; | ||
| 266 | |||
| 267 | err = input_register_device(elo->dev); | 357 | err = input_register_device(elo->dev); |
| 268 | if (err) | 358 | if (err) |
| 269 | goto fail3; | 359 | goto fail3; |
