Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * Fujitsu serial touchscreen driver
  3  *
  4  * Copyright (c) Dmitry Torokhov <dtor@mail.ru>
  5  */
  6 
  7 /*
  8  * This program is free software; you can redistribute it and/or modify it
  9  * under the terms of the GNU General Public License version 2 as published
 10  * by the Free Software Foundation.
 11  */
 12 
 13 #include <linux/errno.h>
 14 #include <linux/kernel.h>
 15 #include <linux/module.h>
 16 #include <linux/slab.h>
 17 #include <linux/input.h>
 18 #include <linux/serio.h>
 19 #include <linux/init.h>
 20 
 21 #define DRIVER_DESC     "Fujitsu serial touchscreen driver"
 22 
 23 MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
 24 MODULE_DESCRIPTION(DRIVER_DESC);
 25 MODULE_LICENSE("GPL");
 26 
 27 #define FUJITSU_LENGTH 5
 28 
 29 /*
 30  * Per-touchscreen data.
 31  */
 32 struct fujitsu {
 33         struct input_dev *dev;
 34         struct serio *serio;
 35         int idx;
 36         unsigned char data[FUJITSU_LENGTH];
 37         char phys[32];
 38 };
 39 
 40 /*
 41  * Decode serial data (5 bytes per packet)
 42  * First byte
 43  * 1 C 0 0 R S S S
 44  * Where C is 1 while in calibration mode (which we don't use)
 45  * R is 1 when no coordinate corection was done.
 46  * S are button state
 47  */
 48 static irqreturn_t fujitsu_interrupt(struct serio *serio,
 49                                      unsigned char data, unsigned int flags)
 50 {
 51         struct fujitsu *fujitsu = serio_get_drvdata(serio);
 52         struct input_dev *dev = fujitsu->dev;
 53 
 54         if (fujitsu->idx == 0) {
 55                 /* resync skip until start of frame */
 56                 if ((data & 0xf0) != 0x80)
 57                         return IRQ_HANDLED;
 58         } else {
 59                 /* resync skip garbage */
 60                 if (data & 0x80) {
 61                         fujitsu->idx = 0;
 62                         return IRQ_HANDLED;
 63                 }
 64         }
 65 
 66         fujitsu->data[fujitsu->idx++] = data;
 67         if (fujitsu->idx == FUJITSU_LENGTH) {
 68                 input_report_abs(dev, ABS_X,
 69                                  (fujitsu->data[2] << 7) | fujitsu->data[1]);
 70                 input_report_abs(dev, ABS_Y,
 71                                  (fujitsu->data[4] << 7) | fujitsu->data[3]);
 72                 input_report_key(dev, BTN_TOUCH,
 73                                  (fujitsu->data[0] & 0x03) != 2);
 74                 input_sync(dev);
 75                 fujitsu->idx = 0;
 76         }
 77 
 78         return IRQ_HANDLED;
 79 }
 80 
 81 /*
 82  * fujitsu_disconnect() is the opposite of fujitsu_connect()
 83  */
 84 static void fujitsu_disconnect(struct serio *serio)
 85 {
 86         struct fujitsu *fujitsu = serio_get_drvdata(serio);
 87 
 88         input_get_device(fujitsu->dev);
 89         input_unregister_device(fujitsu->dev);
 90         serio_close(serio);
 91         serio_set_drvdata(serio, NULL);
 92         input_put_device(fujitsu->dev);
 93         kfree(fujitsu);
 94 }
 95 
 96 /*
 97  * fujitsu_connect() is the routine that is called when someone adds a
 98  * new serio device that supports the Fujitsu protocol and registers it
 99  * as input device.
100  */
101 static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)
102 {
103         struct fujitsu *fujitsu;
104         struct input_dev *input_dev;
105         int err;
106 
107         fujitsu = kzalloc(sizeof(struct fujitsu), GFP_KERNEL);
108         input_dev = input_allocate_device();
109         if (!fujitsu || !input_dev) {
110                 err = -ENOMEM;
111                 goto fail1;
112         }
113 
114         fujitsu->serio = serio;
115         fujitsu->dev = input_dev;
116         snprintf(fujitsu->phys, sizeof(fujitsu->phys),
117                  "%s/input0", serio->phys);
118 
119         input_dev->name = "Fujitsu Serial Touchscreen";
120         input_dev->phys = fujitsu->phys;
121         input_dev->id.bustype = BUS_RS232;
122         input_dev->id.vendor = SERIO_FUJITSU;
123         input_dev->id.product = 0;
124         input_dev->id.version = 0x0100;
125         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
126         input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
127 
128         input_set_abs_params(input_dev, ABS_X, 0, 4096, 0, 0);
129         input_set_abs_params(input_dev, ABS_Y, 0, 4096, 0, 0);
130         serio_set_drvdata(serio, fujitsu);
131 
132         err = serio_open(serio, drv);
133         if (err)
134                 goto fail2;
135 
136         err = input_register_device(fujitsu->dev);
137         if (err)
138                 goto fail3;
139 
140         return 0;
141 
142  fail3:
143         serio_close(serio);
144  fail2:
145         serio_set_drvdata(serio, NULL);
146  fail1:
147         input_free_device(input_dev);
148         kfree(fujitsu);
149         return err;
150 }
151 
152 /*
153  * The serio driver structure.
154  */
155 static struct serio_device_id fujitsu_serio_ids[] = {
156         {
157                 .type   = SERIO_RS232,
158                 .proto  = SERIO_FUJITSU,
159                 .id     = SERIO_ANY,
160                 .extra  = SERIO_ANY,
161         },
162         { 0 }
163 };
164 
165 MODULE_DEVICE_TABLE(serio, fujitsu_serio_ids);
166 
167 static struct serio_driver fujitsu_drv = {
168         .driver         = {
169                 .name   = "fujitsu_ts",
170         },
171         .description    = DRIVER_DESC,
172         .id_table       = fujitsu_serio_ids,
173         .interrupt      = fujitsu_interrupt,
174         .connect        = fujitsu_connect,
175         .disconnect     = fujitsu_disconnect,
176 };
177 
178 static int __init fujitsu_init(void)
179 {
180         return serio_register_driver(&fujitsu_drv);
181 }
182 
183 static void __exit fujitsu_exit(void)
184 {
185         serio_unregister_driver(&fujitsu_drv);
186 }
187 
188 module_init(fujitsu_init);
189 module_exit(fujitsu_exit);
190 
  This page was automatically generated by the LXR engine.