Version:  2.6.34 2.6.35 2.6.36 2.6.37 2.6.38 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14

Linux/drivers/input/touchscreen/tsc40.c

  1 /*
  2  * TSC-40 serial touchscreen driver. It should be compatible with
  3  * TSC-10 and 25.
  4  *
  5  * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  6  * License: GPLv2 as published by the FSF.
  7  */
  8 
  9 #include <linux/kernel.h>
 10 #include <linux/module.h>
 11 #include <linux/slab.h>
 12 #include <linux/input.h>
 13 #include <linux/serio.h>
 14 
 15 #define PACKET_LENGTH  5
 16 struct tsc_ser {
 17         struct input_dev *dev;
 18         struct serio *serio;
 19         u32 idx;
 20         unsigned char data[PACKET_LENGTH];
 21         char phys[32];
 22 };
 23 
 24 static void tsc_process_data(struct tsc_ser *ptsc)
 25 {
 26         struct input_dev *dev = ptsc->dev;
 27         u8 *data = ptsc->data;
 28         u32 x;
 29         u32 y;
 30 
 31         x = ((data[1] & 0x03) << 8) | data[2];
 32         y = ((data[3] & 0x03) << 8) | data[4];
 33 
 34         input_report_abs(dev, ABS_X, x);
 35         input_report_abs(dev, ABS_Y, y);
 36         input_report_key(dev, BTN_TOUCH, 1);
 37 
 38         input_sync(dev);
 39 }
 40 
 41 static irqreturn_t tsc_interrupt(struct serio *serio,
 42                 unsigned char data, unsigned int flags)
 43 {
 44         struct tsc_ser *ptsc = serio_get_drvdata(serio);
 45         struct input_dev *dev = ptsc->dev;
 46 
 47         ptsc->data[ptsc->idx] = data;
 48         switch (ptsc->idx++) {
 49         case 0:
 50                 if (unlikely((data & 0x3e) != 0x10)) {
 51                         dev_dbg(&serio->dev,
 52                                 "unsynchronized packet start (0x%02x)\n", data);
 53                         ptsc->idx = 0;
 54                 } else if (!(data & 0x01)) {
 55                         input_report_key(dev, BTN_TOUCH, 0);
 56                         input_sync(dev);
 57                         ptsc->idx = 0;
 58                 }
 59                 break;
 60 
 61         case 1:
 62         case 3:
 63                 if (unlikely(data & 0xfc)) {
 64                         dev_dbg(&serio->dev,
 65                                 "unsynchronized data 0x%02x at offset %d\n",
 66                                 data, ptsc->idx - 1);
 67                         ptsc->idx = 0;
 68                 }
 69                 break;
 70 
 71         case 4:
 72                 tsc_process_data(ptsc);
 73                 ptsc->idx = 0;
 74                 break;
 75         }
 76 
 77         return IRQ_HANDLED;
 78 }
 79 
 80 static int tsc_connect(struct serio *serio, struct serio_driver *drv)
 81 {
 82         struct tsc_ser *ptsc;
 83         struct input_dev *input_dev;
 84         int error;
 85 
 86         ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL);
 87         input_dev = input_allocate_device();
 88         if (!ptsc || !input_dev) {
 89                 error = -ENOMEM;
 90                 goto fail1;
 91         }
 92 
 93         ptsc->serio = serio;
 94         ptsc->dev = input_dev;
 95         snprintf(ptsc->phys, sizeof(ptsc->phys), "%s/input0", serio->phys);
 96 
 97         input_dev->name = "TSC-10/25/40 Serial TouchScreen";
 98         input_dev->phys = ptsc->phys;
 99         input_dev->id.bustype = BUS_RS232;
100         input_dev->id.vendor = SERIO_TSC40;
101         input_dev->id.product = 40;
102         input_dev->id.version = 0x0001;
103         input_dev->dev.parent = &serio->dev;
104 
105         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
106         __set_bit(BTN_TOUCH, input_dev->keybit);
107         input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
108         input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
109 
110         serio_set_drvdata(serio, ptsc);
111 
112         error = serio_open(serio, drv);
113         if (error)
114                 goto fail2;
115 
116         error = input_register_device(ptsc->dev);
117         if (error)
118                 goto fail3;
119 
120         return 0;
121 
122 fail3:
123         serio_close(serio);
124 fail2:
125         serio_set_drvdata(serio, NULL);
126 fail1:
127         input_free_device(input_dev);
128         kfree(ptsc);
129         return error;
130 }
131 
132 static void tsc_disconnect(struct serio *serio)
133 {
134         struct tsc_ser *ptsc = serio_get_drvdata(serio);
135 
136         serio_close(serio);
137 
138         input_unregister_device(ptsc->dev);
139         kfree(ptsc);
140 
141         serio_set_drvdata(serio, NULL);
142 }
143 
144 static struct serio_device_id tsc_serio_ids[] = {
145         {
146                 .type   = SERIO_RS232,
147                 .proto  = SERIO_TSC40,
148                 .id     = SERIO_ANY,
149                 .extra  = SERIO_ANY,
150         },
151         { 0 }
152 };
153 MODULE_DEVICE_TABLE(serio, tsc_serio_ids);
154 
155 #define DRIVER_DESC    "TSC-10/25/40 serial touchscreen driver"
156 
157 static struct serio_driver tsc_drv = {
158         .driver = {
159                 .name   = "tsc40",
160         },
161         .description    = DRIVER_DESC,
162         .id_table       = tsc_serio_ids,
163         .interrupt      = tsc_interrupt,
164         .connect        = tsc_connect,
165         .disconnect     = tsc_disconnect,
166 };
167 
168 module_serio_driver(tsc_drv);
169 
170 MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
171 MODULE_DESCRIPTION(DRIVER_DESC);
172 MODULE_LICENSE("GPL v2");
173 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us