root/drivers/input/touchscreen/touchwin.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tw_interrupt
  2. tw_disconnect
  3. tw_connect

   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 
  29 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
  30 MODULE_DESCRIPTION(DRIVER_DESC);
  31 MODULE_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 
  48 struct 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 
  57 static 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 
  88 static 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 
 106 static 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 
 158 static 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 
 168 MODULE_DEVICE_TABLE(serio, tw_serio_ids);
 169 
 170 static 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 
 181 module_serio_driver(tw_drv);

/* [<][>][^][v][top][bottom][index][help] */