Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * iNexio serial touchscreen driver
0004  *
0005  * Copyright (c) 2008 Richard Lemon
0006  * Based on the mtouch driver (c) Vojtech Pavlik and Dan Streetman
0007  */
0008 
0009 
0010 /*
0011  * 2008/06/19 Richard Lemon <richard@codelemon.com>
0012  *   Copied mtouch.c and edited for iNexio protocol
0013  */
0014 
0015 #include <linux/errno.h>
0016 #include <linux/kernel.h>
0017 #include <linux/module.h>
0018 #include <linux/slab.h>
0019 #include <linux/input.h>
0020 #include <linux/serio.h>
0021 
0022 #define DRIVER_DESC "iNexio serial touchscreen driver"
0023 
0024 MODULE_AUTHOR("Richard Lemon <richard@codelemon.com>");
0025 MODULE_DESCRIPTION(DRIVER_DESC);
0026 MODULE_LICENSE("GPL");
0027 
0028 /*
0029  * Definitions & global arrays.
0030  */
0031 
0032 #define INEXIO_FORMAT_TOUCH_BIT 0x01
0033 #define INEXIO_FORMAT_LENGTH 5
0034 #define INEXIO_RESPONSE_BEGIN_BYTE 0x80
0035 
0036 /* todo: check specs for max length of all responses */
0037 #define INEXIO_MAX_LENGTH 16
0038 
0039 #define INEXIO_MIN_XC 0
0040 #define INEXIO_MAX_XC 0x3fff
0041 #define INEXIO_MIN_YC 0
0042 #define INEXIO_MAX_YC 0x3fff
0043 
0044 #define INEXIO_GET_XC(data) (((data[1])<<7) | data[2])
0045 #define INEXIO_GET_YC(data) (((data[3])<<7) | data[4])
0046 #define INEXIO_GET_TOUCHED(data) (INEXIO_FORMAT_TOUCH_BIT & data[0])
0047 
0048 /*
0049  * Per-touchscreen data.
0050  */
0051 
0052 struct inexio {
0053     struct input_dev *dev;
0054     struct serio *serio;
0055     int idx;
0056     unsigned char data[INEXIO_MAX_LENGTH];
0057     char phys[32];
0058 };
0059 
0060 static void inexio_process_data(struct inexio *pinexio)
0061 {
0062     struct input_dev *dev = pinexio->dev;
0063 
0064     if (INEXIO_FORMAT_LENGTH == ++pinexio->idx) {
0065         input_report_abs(dev, ABS_X, INEXIO_GET_XC(pinexio->data));
0066         input_report_abs(dev, ABS_Y, INEXIO_GET_YC(pinexio->data));
0067         input_report_key(dev, BTN_TOUCH, INEXIO_GET_TOUCHED(pinexio->data));
0068         input_sync(dev);
0069 
0070         pinexio->idx = 0;
0071     }
0072 }
0073 
0074 static irqreturn_t inexio_interrupt(struct serio *serio,
0075         unsigned char data, unsigned int flags)
0076 {
0077     struct inexio *pinexio = serio_get_drvdata(serio);
0078 
0079     pinexio->data[pinexio->idx] = data;
0080 
0081     if (INEXIO_RESPONSE_BEGIN_BYTE&pinexio->data[0])
0082         inexio_process_data(pinexio);
0083     else
0084         printk(KERN_DEBUG "inexio.c: unknown/unsynchronized data from device, byte %x\n",pinexio->data[0]);
0085 
0086     return IRQ_HANDLED;
0087 }
0088 
0089 /*
0090  * inexio_disconnect() is the opposite of inexio_connect()
0091  */
0092 
0093 static void inexio_disconnect(struct serio *serio)
0094 {
0095     struct inexio *pinexio = serio_get_drvdata(serio);
0096 
0097     input_get_device(pinexio->dev);
0098     input_unregister_device(pinexio->dev);
0099     serio_close(serio);
0100     serio_set_drvdata(serio, NULL);
0101     input_put_device(pinexio->dev);
0102     kfree(pinexio);
0103 }
0104 
0105 /*
0106  * inexio_connect() is the routine that is called when someone adds a
0107  * new serio device that supports iNexio protocol and registers it as
0108  * an input device. This is usually accomplished using inputattach.
0109  */
0110 
0111 static int inexio_connect(struct serio *serio, struct serio_driver *drv)
0112 {
0113     struct inexio *pinexio;
0114     struct input_dev *input_dev;
0115     int err;
0116 
0117     pinexio = kzalloc(sizeof(struct inexio), GFP_KERNEL);
0118     input_dev = input_allocate_device();
0119     if (!pinexio || !input_dev) {
0120         err = -ENOMEM;
0121         goto fail1;
0122     }
0123 
0124     pinexio->serio = serio;
0125     pinexio->dev = input_dev;
0126     snprintf(pinexio->phys, sizeof(pinexio->phys), "%s/input0", serio->phys);
0127 
0128     input_dev->name = "iNexio Serial TouchScreen";
0129     input_dev->phys = pinexio->phys;
0130     input_dev->id.bustype = BUS_RS232;
0131     input_dev->id.vendor = SERIO_INEXIO;
0132     input_dev->id.product = 0;
0133     input_dev->id.version = 0x0001;
0134     input_dev->dev.parent = &serio->dev;
0135     input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
0136     input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
0137     input_set_abs_params(pinexio->dev, ABS_X, INEXIO_MIN_XC, INEXIO_MAX_XC, 0, 0);
0138     input_set_abs_params(pinexio->dev, ABS_Y, INEXIO_MIN_YC, INEXIO_MAX_YC, 0, 0);
0139 
0140     serio_set_drvdata(serio, pinexio);
0141 
0142     err = serio_open(serio, drv);
0143     if (err)
0144         goto fail2;
0145 
0146     err = input_register_device(pinexio->dev);
0147     if (err)
0148         goto fail3;
0149 
0150     return 0;
0151 
0152  fail3: serio_close(serio);
0153  fail2: serio_set_drvdata(serio, NULL);
0154  fail1: input_free_device(input_dev);
0155     kfree(pinexio);
0156     return err;
0157 }
0158 
0159 /*
0160  * The serio driver structure.
0161  */
0162 
0163 static const struct serio_device_id inexio_serio_ids[] = {
0164     {
0165         .type   = SERIO_RS232,
0166         .proto  = SERIO_INEXIO,
0167         .id = SERIO_ANY,
0168         .extra  = SERIO_ANY,
0169     },
0170     { 0 }
0171 };
0172 
0173 MODULE_DEVICE_TABLE(serio, inexio_serio_ids);
0174 
0175 static struct serio_driver inexio_drv = {
0176     .driver     = {
0177         .name   = "inexio",
0178     },
0179     .description    = DRIVER_DESC,
0180     .id_table   = inexio_serio_ids,
0181     .interrupt  = inexio_interrupt,
0182     .connect    = inexio_connect,
0183     .disconnect = inexio_disconnect,
0184 };
0185 
0186 module_serio_driver(inexio_drv);