Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) 2000-2001 Vojtech Pavlik
0004  */
0005 
0006 /*
0007  * Gunze AHL-51S touchscreen driver for Linux
0008  */
0009 
0010 /*
0011  */
0012 
0013 #include <linux/errno.h>
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/slab.h>
0017 #include <linux/input.h>
0018 #include <linux/serio.h>
0019 
0020 #define DRIVER_DESC "Gunze AHL-51S touchscreen driver"
0021 
0022 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
0023 MODULE_DESCRIPTION(DRIVER_DESC);
0024 MODULE_LICENSE("GPL");
0025 
0026 /*
0027  * Definitions & global arrays.
0028  */
0029 
0030 #define GUNZE_MAX_LENGTH    10
0031 
0032 /*
0033  * Per-touchscreen data.
0034  */
0035 
0036 struct gunze {
0037     struct input_dev *dev;
0038     struct serio *serio;
0039     int idx;
0040     unsigned char data[GUNZE_MAX_LENGTH];
0041     char phys[32];
0042 };
0043 
0044 static void gunze_process_packet(struct gunze *gunze)
0045 {
0046     struct input_dev *dev = gunze->dev;
0047 
0048     if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
0049         (gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
0050         printk(KERN_WARNING "gunze.c: bad packet: >%.*s<\n", GUNZE_MAX_LENGTH, gunze->data);
0051         return;
0052     }
0053 
0054     input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10));
0055     input_report_abs(dev, ABS_Y, 1024 - simple_strtoul(gunze->data + 6, NULL, 10));
0056     input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T');
0057     input_sync(dev);
0058 }
0059 
0060 static irqreturn_t gunze_interrupt(struct serio *serio,
0061         unsigned char data, unsigned int flags)
0062 {
0063     struct gunze *gunze = serio_get_drvdata(serio);
0064 
0065     if (data == '\r') {
0066         gunze_process_packet(gunze);
0067         gunze->idx = 0;
0068     } else {
0069         if (gunze->idx < GUNZE_MAX_LENGTH)
0070             gunze->data[gunze->idx++] = data;
0071     }
0072     return IRQ_HANDLED;
0073 }
0074 
0075 /*
0076  * gunze_disconnect() is the opposite of gunze_connect()
0077  */
0078 
0079 static void gunze_disconnect(struct serio *serio)
0080 {
0081     struct gunze *gunze = serio_get_drvdata(serio);
0082 
0083     input_get_device(gunze->dev);
0084     input_unregister_device(gunze->dev);
0085     serio_close(serio);
0086     serio_set_drvdata(serio, NULL);
0087     input_put_device(gunze->dev);
0088     kfree(gunze);
0089 }
0090 
0091 /*
0092  * gunze_connect() is the routine that is called when someone adds a
0093  * new serio device that supports Gunze protocol and registers it as
0094  * an input device.
0095  */
0096 
0097 static int gunze_connect(struct serio *serio, struct serio_driver *drv)
0098 {
0099     struct gunze *gunze;
0100     struct input_dev *input_dev;
0101     int err;
0102 
0103     gunze = kzalloc(sizeof(struct gunze), GFP_KERNEL);
0104     input_dev = input_allocate_device();
0105     if (!gunze || !input_dev) {
0106         err = -ENOMEM;
0107         goto fail1;
0108     }
0109 
0110     gunze->serio = serio;
0111     gunze->dev = input_dev;
0112     snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys);
0113 
0114     input_dev->name = "Gunze AHL-51S TouchScreen";
0115     input_dev->phys = gunze->phys;
0116     input_dev->id.bustype = BUS_RS232;
0117     input_dev->id.vendor = SERIO_GUNZE;
0118     input_dev->id.product = 0x0051;
0119     input_dev->id.version = 0x0100;
0120     input_dev->dev.parent = &serio->dev;
0121     input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
0122     input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
0123     input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
0124     input_set_abs_params(input_dev, ABS_Y, 24, 1000, 0, 0);
0125 
0126     serio_set_drvdata(serio, gunze);
0127 
0128     err = serio_open(serio, drv);
0129     if (err)
0130         goto fail2;
0131 
0132     err = input_register_device(gunze->dev);
0133     if (err)
0134         goto fail3;
0135 
0136     return 0;
0137 
0138  fail3: serio_close(serio);
0139  fail2: serio_set_drvdata(serio, NULL);
0140  fail1: input_free_device(input_dev);
0141     kfree(gunze);
0142     return err;
0143 }
0144 
0145 /*
0146  * The serio driver structure.
0147  */
0148 
0149 static const struct serio_device_id gunze_serio_ids[] = {
0150     {
0151         .type   = SERIO_RS232,
0152         .proto  = SERIO_GUNZE,
0153         .id = SERIO_ANY,
0154         .extra  = SERIO_ANY,
0155     },
0156     { 0 }
0157 };
0158 
0159 MODULE_DEVICE_TABLE(serio, gunze_serio_ids);
0160 
0161 static struct serio_driver gunze_drv = {
0162     .driver     = {
0163         .name   = "gunze",
0164     },
0165     .description    = DRIVER_DESC,
0166     .id_table   = gunze_serio_ids,
0167     .interrupt  = gunze_interrupt,
0168     .connect    = gunze_connect,
0169     .disconnect = gunze_disconnect,
0170 };
0171 
0172 module_serio_driver(gunze_drv);