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