Commit 422dee56b8155e4627f657ee67e962066ca7aff3

Authored by Adam Bennett
Committed by Dmitry Torokhov
1 parent 6c04d7b3cf

Input: add driver for hampshire serial touchscreens

Adds support for Hampshire TSHARC serial touchscreens.  Implements
Hampshire's 4-byte communication protocol.

Signed-off-by: Adam Bennett <abennett72@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

Showing 4 changed files with 219 additions and 0 deletions Side-by-side Diff

drivers/input/touchscreen/Kconfig
... ... @@ -119,6 +119,18 @@
119 119 To compile this driver as a module, choose M here: the
120 120 module will be called dynapro.
121 121  
  122 +config TOUCHSCREEN_HAMPSHIRE
  123 + tristate "Hampshire serial touchscreen"
  124 + select SERIO
  125 + help
  126 + Say Y here if you have a Hampshire serial touchscreen connected to
  127 + your system.
  128 +
  129 + If unsure, say N.
  130 +
  131 + To compile this driver as a module, choose M here: the
  132 + module will be called hampshire.
  133 +
122 134 config TOUCHSCREEN_EETI
123 135 tristate "EETI touchscreen panel support"
124 136 depends on I2C
drivers/input/touchscreen/Makefile
... ... @@ -13,6 +13,7 @@
13 13 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
14 14 obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
15 15 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
  16 +obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
16 17 obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
17 18 obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
18 19 obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
drivers/input/touchscreen/hampshire.c
  1 +/*
  2 + * Hampshire serial touchscreen driver
  3 + *
  4 + * Copyright (c) 2010 Adam Bennett
  5 + * Based on the dynapro driver (c) Tias Guns
  6 + *
  7 + */
  8 +
  9 +/*
  10 + * This program is free software; you can redistribute it and/or modify it
  11 + * under the terms of the GNU General Public License version 2 as published by
  12 + * the Free Software Foundation.
  13 + */
  14 +
  15 +/*
  16 + * 2010/04/08 Adam Bennett <abennett72@gmail.com>
  17 + * Copied dynapro.c and edited for Hampshire 4-byte protocol
  18 + */
  19 +
  20 +#include <linux/errno.h>
  21 +#include <linux/kernel.h>
  22 +#include <linux/module.h>
  23 +#include <linux/slab.h>
  24 +#include <linux/input.h>
  25 +#include <linux/serio.h>
  26 +#include <linux/init.h>
  27 +
  28 +#define DRIVER_DESC "Hampshire serial touchscreen driver"
  29 +
  30 +MODULE_AUTHOR("Adam Bennett <abennett72@gmail.com>");
  31 +MODULE_DESCRIPTION(DRIVER_DESC);
  32 +MODULE_LICENSE("GPL");
  33 +
  34 +/*
  35 + * Definitions & global arrays.
  36 + */
  37 +
  38 +#define HAMPSHIRE_FORMAT_TOUCH_BIT 0x40
  39 +#define HAMPSHIRE_FORMAT_LENGTH 4
  40 +#define HAMPSHIRE_RESPONSE_BEGIN_BYTE 0x80
  41 +
  42 +#define HAMPSHIRE_MIN_XC 0
  43 +#define HAMPSHIRE_MAX_XC 0x1000
  44 +#define HAMPSHIRE_MIN_YC 0
  45 +#define HAMPSHIRE_MAX_YC 0x1000
  46 +
  47 +#define HAMPSHIRE_GET_XC(data) (((data[3] & 0x0c) >> 2) | (data[1] << 2) | ((data[0] & 0x38) << 6))
  48 +#define HAMPSHIRE_GET_YC(data) ((data[3] & 0x03) | (data[2] << 2) | ((data[0] & 0x07) << 9))
  49 +#define HAMPSHIRE_GET_TOUCHED(data) (HAMPSHIRE_FORMAT_TOUCH_BIT & data[0])
  50 +
  51 +/*
  52 + * Per-touchscreen data.
  53 + */
  54 +
  55 +struct hampshire {
  56 + struct input_dev *dev;
  57 + struct serio *serio;
  58 + int idx;
  59 + unsigned char data[HAMPSHIRE_FORMAT_LENGTH];
  60 + char phys[32];
  61 +};
  62 +
  63 +static void hampshire_process_data(struct hampshire *phampshire)
  64 +{
  65 + struct input_dev *dev = phampshire->dev;
  66 +
  67 + if (HAMPSHIRE_FORMAT_LENGTH == ++phampshire->idx) {
  68 + input_report_abs(dev, ABS_X, HAMPSHIRE_GET_XC(phampshire->data));
  69 + input_report_abs(dev, ABS_Y, HAMPSHIRE_GET_YC(phampshire->data));
  70 + input_report_key(dev, BTN_TOUCH,
  71 + HAMPSHIRE_GET_TOUCHED(phampshire->data));
  72 + input_sync(dev);
  73 +
  74 + phampshire->idx = 0;
  75 + }
  76 +}
  77 +
  78 +static irqreturn_t hampshire_interrupt(struct serio *serio,
  79 + unsigned char data, unsigned int flags)
  80 +{
  81 + struct hampshire *phampshire = serio_get_drvdata(serio);
  82 +
  83 + phampshire->data[phampshire->idx] = data;
  84 +
  85 + if (HAMPSHIRE_RESPONSE_BEGIN_BYTE & phampshire->data[0])
  86 + hampshire_process_data(phampshire);
  87 + else
  88 + dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n",
  89 + phampshire->data[0]);
  90 +
  91 + return IRQ_HANDLED;
  92 +}
  93 +
  94 +static void hampshire_disconnect(struct serio *serio)
  95 +{
  96 + struct hampshire *phampshire = serio_get_drvdata(serio);
  97 +
  98 + input_get_device(phampshire->dev);
  99 + input_unregister_device(phampshire->dev);
  100 + serio_close(serio);
  101 + serio_set_drvdata(serio, NULL);
  102 + input_put_device(phampshire->dev);
  103 + kfree(phampshire);
  104 +}
  105 +
  106 +/*
  107 + * hampshire_connect() is the routine that is called when someone adds a
  108 + * new serio device that supports hampshire protocol and registers it as
  109 + * an input device. This is usually accomplished using inputattach.
  110 + */
  111 +
  112 +static int hampshire_connect(struct serio *serio, struct serio_driver *drv)
  113 +{
  114 + struct hampshire *phampshire;
  115 + struct input_dev *input_dev;
  116 + int err;
  117 +
  118 + phampshire = kzalloc(sizeof(struct hampshire), GFP_KERNEL);
  119 + input_dev = input_allocate_device();
  120 + if (!phampshire || !input_dev) {
  121 + err = -ENOMEM;
  122 + goto fail1;
  123 + }
  124 +
  125 + phampshire->serio = serio;
  126 + phampshire->dev = input_dev;
  127 + snprintf(phampshire->phys, sizeof(phampshire->phys),
  128 + "%s/input0", serio->phys);
  129 +
  130 + input_dev->name = "Hampshire Serial TouchScreen";
  131 + input_dev->phys = phampshire->phys;
  132 + input_dev->id.bustype = BUS_RS232;
  133 + input_dev->id.vendor = SERIO_HAMPSHIRE;
  134 + input_dev->id.product = 0;
  135 + input_dev->id.version = 0x0001;
  136 + input_dev->dev.parent = &serio->dev;
  137 + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
  138 + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
  139 + input_set_abs_params(phampshire->dev, ABS_X,
  140 + HAMPSHIRE_MIN_XC, HAMPSHIRE_MAX_XC, 0, 0);
  141 + input_set_abs_params(phampshire->dev, ABS_Y,
  142 + HAMPSHIRE_MIN_YC, HAMPSHIRE_MAX_YC, 0, 0);
  143 +
  144 + serio_set_drvdata(serio, phampshire);
  145 +
  146 + err = serio_open(serio, drv);
  147 + if (err)
  148 + goto fail2;
  149 +
  150 + err = input_register_device(phampshire->dev);
  151 + if (err)
  152 + goto fail3;
  153 +
  154 + return 0;
  155 +
  156 + fail3: serio_close(serio);
  157 + fail2: serio_set_drvdata(serio, NULL);
  158 + fail1: input_free_device(input_dev);
  159 + kfree(phampshire);
  160 + return err;
  161 +}
  162 +
  163 +/*
  164 + * The serio driver structure.
  165 + */
  166 +
  167 +static struct serio_device_id hampshire_serio_ids[] = {
  168 + {
  169 + .type = SERIO_RS232,
  170 + .proto = SERIO_HAMPSHIRE,
  171 + .id = SERIO_ANY,
  172 + .extra = SERIO_ANY,
  173 + },
  174 + { 0 }
  175 +};
  176 +
  177 +MODULE_DEVICE_TABLE(serio, hampshire_serio_ids);
  178 +
  179 +static struct serio_driver hampshire_drv = {
  180 + .driver = {
  181 + .name = "hampshire",
  182 + },
  183 + .description = DRIVER_DESC,
  184 + .id_table = hampshire_serio_ids,
  185 + .interrupt = hampshire_interrupt,
  186 + .connect = hampshire_connect,
  187 + .disconnect = hampshire_disconnect,
  188 +};
  189 +
  190 +/*
  191 + * The functions for inserting/removing us as a module.
  192 + */
  193 +
  194 +static int __init hampshire_init(void)
  195 +{
  196 + return serio_register_driver(&hampshire_drv);
  197 +}
  198 +
  199 +static void __exit hampshire_exit(void)
  200 +{
  201 + serio_unregister_driver(&hampshire_drv);
  202 +}
  203 +
  204 +module_init(hampshire_init);
  205 +module_exit(hampshire_exit);
include/linux/serio.h
... ... @@ -196,6 +196,7 @@
196 196 #define SERIO_TOUCHIT213 0x38
197 197 #define SERIO_W8001 0x39
198 198 #define SERIO_DYNAPRO 0x3a
  199 +#define SERIO_HAMPSHIRE 0x3b
199 200  
200 201 #endif