linux/drivers/input/touchscreen/touchwin.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Touchwindow serial touchscreen driver
   4 *
   5 * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
   6 *
   7 * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c)
   8 * Copyright (c) 2004 Vojtech Pavlik
   9 * and Dan Streetman <ddstreet@ieee.org>
  10 */
  11
  12
  13/*
  14 * 2005/02/19 Rick Koch:
  15 *   The Touchwindow I used is made by Edmark Corp. and
  16 *   constantly outputs a stream of 0's unless it is touched.
  17 *   It then outputs 3 bytes: X, Y, and a copy of Y.
  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
  27#define DRIVER_DESC     "Touchwindow serial touchscreen driver"
  28
  29MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
  30MODULE_DESCRIPTION(DRIVER_DESC);
  31MODULE_LICENSE("GPL");
  32
  33/*
  34 * Definitions & global arrays.
  35 */
  36
  37#define TW_LENGTH 3
  38
  39#define TW_MIN_XC 0
  40#define TW_MAX_XC 0xff
  41#define TW_MIN_YC 0
  42#define TW_MAX_YC 0xff
  43
  44/*
  45 * Per-touchscreen data.
  46 */
  47
  48struct tw {
  49        struct input_dev *dev;
  50        struct serio *serio;
  51        int idx;
  52        int touched;
  53        unsigned char data[TW_LENGTH];
  54        char phys[32];
  55};
  56
  57static irqreturn_t tw_interrupt(struct serio *serio,
  58                unsigned char data, unsigned int flags)
  59{
  60        struct tw *tw = serio_get_drvdata(serio);
  61        struct input_dev *dev = tw->dev;
  62
  63        if (data) {             /* touch */
  64                tw->touched = 1;
  65                tw->data[tw->idx++] = data;
  66                /* verify length and that the two Y's are the same */
  67                if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
  68                        input_report_abs(dev, ABS_X, tw->data[0]);
  69                        input_report_abs(dev, ABS_Y, tw->data[1]);
  70                        input_report_key(dev, BTN_TOUCH, 1);
  71                        input_sync(dev);
  72                        tw->idx = 0;
  73                }
  74        } else if (tw->touched) {       /* untouch */
  75                input_report_key(dev, BTN_TOUCH, 0);
  76                input_sync(dev);
  77                tw->idx = 0;
  78                tw->touched = 0;
  79        }
  80
  81        return IRQ_HANDLED;
  82}
  83
  84/*
  85 * tw_disconnect() is the opposite of tw_connect()
  86 */
  87
  88static void tw_disconnect(struct serio *serio)
  89{
  90        struct tw *tw = serio_get_drvdata(serio);
  91
  92        input_get_device(tw->dev);
  93        input_unregister_device(tw->dev);
  94        serio_close(serio);
  95        serio_set_drvdata(serio, NULL);
  96        input_put_device(tw->dev);
  97        kfree(tw);
  98}
  99
 100/*
 101 * tw_connect() is the routine that is called when someone adds a
 102 * new serio device that supports the Touchwin protocol and registers it as
 103 * an input device.
 104 */
 105
 106static int tw_connect(struct serio *serio, struct serio_driver *drv)
 107{
 108        struct tw *tw;
 109        struct input_dev *input_dev;
 110        int err;
 111
 112        tw = kzalloc(sizeof(struct tw), GFP_KERNEL);
 113        input_dev = input_allocate_device();
 114        if (!tw || !input_dev) {
 115                err = -ENOMEM;
 116                goto fail1;
 117        }
 118
 119        tw->serio = serio;
 120        tw->dev = input_dev;
 121        snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
 122
 123        input_dev->name = "Touchwindow Serial TouchScreen";
 124        input_dev->phys = tw->phys;
 125        input_dev->id.bustype = BUS_RS232;
 126        input_dev->id.vendor = SERIO_TOUCHWIN;
 127        input_dev->id.product = 0;
 128        input_dev->id.version = 0x0100;
 129        input_dev->dev.parent = &serio->dev;
 130        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 131        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 132        input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);
 133        input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0);
 134
 135        serio_set_drvdata(serio, tw);
 136
 137        err = serio_open(serio, drv);
 138        if (err)
 139                goto fail2;
 140
 141        err = input_register_device(tw->dev);
 142        if (err)
 143                goto fail3;
 144
 145        return 0;
 146
 147 fail3: serio_close(serio);
 148 fail2: serio_set_drvdata(serio, NULL);
 149 fail1: input_free_device(input_dev);
 150        kfree(tw);
 151        return err;
 152}
 153
 154/*
 155 * The serio driver structure.
 156 */
 157
 158static const struct serio_device_id tw_serio_ids[] = {
 159        {
 160                .type   = SERIO_RS232,
 161                .proto  = SERIO_TOUCHWIN,
 162                .id     = SERIO_ANY,
 163                .extra  = SERIO_ANY,
 164        },
 165        { 0 }
 166};
 167
 168MODULE_DEVICE_TABLE(serio, tw_serio_ids);
 169
 170static struct serio_driver tw_drv = {
 171        .driver         = {
 172                .name   = "touchwin",
 173        },
 174        .description    = DRIVER_DESC,
 175        .id_table       = tw_serio_ids,
 176        .interrupt      = tw_interrupt,
 177        .connect        = tw_connect,
 178        .disconnect     = tw_disconnect,
 179};
 180
 181module_serio_driver(tw_drv);
 182