cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gunze.c (3814B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (c) 2000-2001 Vojtech Pavlik
      4 */
      5
      6/*
      7 * Gunze AHL-51S touchscreen driver for Linux
      8 */
      9
     10/*
     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
     20#define DRIVER_DESC	"Gunze AHL-51S touchscreen driver"
     21
     22MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
     23MODULE_DESCRIPTION(DRIVER_DESC);
     24MODULE_LICENSE("GPL");
     25
     26/*
     27 * Definitions & global arrays.
     28 */
     29
     30#define	GUNZE_MAX_LENGTH	10
     31
     32/*
     33 * Per-touchscreen data.
     34 */
     35
     36struct gunze {
     37	struct input_dev *dev;
     38	struct serio *serio;
     39	int idx;
     40	unsigned char data[GUNZE_MAX_LENGTH];
     41	char phys[32];
     42};
     43
     44static void gunze_process_packet(struct gunze *gunze)
     45{
     46	struct input_dev *dev = gunze->dev;
     47
     48	if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
     49		(gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
     50		printk(KERN_WARNING "gunze.c: bad packet: >%.*s<\n", GUNZE_MAX_LENGTH, gunze->data);
     51		return;
     52	}
     53
     54	input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10));
     55	input_report_abs(dev, ABS_Y, 1024 - simple_strtoul(gunze->data + 6, NULL, 10));
     56	input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T');
     57	input_sync(dev);
     58}
     59
     60static irqreturn_t gunze_interrupt(struct serio *serio,
     61		unsigned char data, unsigned int flags)
     62{
     63	struct gunze *gunze = serio_get_drvdata(serio);
     64
     65	if (data == '\r') {
     66		gunze_process_packet(gunze);
     67		gunze->idx = 0;
     68	} else {
     69		if (gunze->idx < GUNZE_MAX_LENGTH)
     70			gunze->data[gunze->idx++] = data;
     71	}
     72	return IRQ_HANDLED;
     73}
     74
     75/*
     76 * gunze_disconnect() is the opposite of gunze_connect()
     77 */
     78
     79static void gunze_disconnect(struct serio *serio)
     80{
     81	struct gunze *gunze = serio_get_drvdata(serio);
     82
     83	input_get_device(gunze->dev);
     84	input_unregister_device(gunze->dev);
     85	serio_close(serio);
     86	serio_set_drvdata(serio, NULL);
     87	input_put_device(gunze->dev);
     88	kfree(gunze);
     89}
     90
     91/*
     92 * gunze_connect() is the routine that is called when someone adds a
     93 * new serio device that supports Gunze protocol and registers it as
     94 * an input device.
     95 */
     96
     97static int gunze_connect(struct serio *serio, struct serio_driver *drv)
     98{
     99	struct gunze *gunze;
    100	struct input_dev *input_dev;
    101	int err;
    102
    103	gunze = kzalloc(sizeof(struct gunze), GFP_KERNEL);
    104	input_dev = input_allocate_device();
    105	if (!gunze || !input_dev) {
    106		err = -ENOMEM;
    107		goto fail1;
    108	}
    109
    110	gunze->serio = serio;
    111	gunze->dev = input_dev;
    112	snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys);
    113
    114	input_dev->name = "Gunze AHL-51S TouchScreen";
    115	input_dev->phys = gunze->phys;
    116	input_dev->id.bustype = BUS_RS232;
    117	input_dev->id.vendor = SERIO_GUNZE;
    118	input_dev->id.product = 0x0051;
    119	input_dev->id.version = 0x0100;
    120	input_dev->dev.parent = &serio->dev;
    121	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    122	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
    123	input_set_abs_params(input_dev, ABS_X, 24, 1000, 0, 0);
    124	input_set_abs_params(input_dev, ABS_Y, 24, 1000, 0, 0);
    125
    126	serio_set_drvdata(serio, gunze);
    127
    128	err = serio_open(serio, drv);
    129	if (err)
    130		goto fail2;
    131
    132	err = input_register_device(gunze->dev);
    133	if (err)
    134		goto fail3;
    135
    136	return 0;
    137
    138 fail3:	serio_close(serio);
    139 fail2:	serio_set_drvdata(serio, NULL);
    140 fail1:	input_free_device(input_dev);
    141	kfree(gunze);
    142	return err;
    143}
    144
    145/*
    146 * The serio driver structure.
    147 */
    148
    149static const struct serio_device_id gunze_serio_ids[] = {
    150	{
    151		.type	= SERIO_RS232,
    152		.proto	= SERIO_GUNZE,
    153		.id	= SERIO_ANY,
    154		.extra	= SERIO_ANY,
    155	},
    156	{ 0 }
    157};
    158
    159MODULE_DEVICE_TABLE(serio, gunze_serio_ids);
    160
    161static struct serio_driver gunze_drv = {
    162	.driver		= {
    163		.name	= "gunze",
    164	},
    165	.description	= DRIVER_DESC,
    166	.id_table	= gunze_serio_ids,
    167	.interrupt	= gunze_interrupt,
    168	.connect	= gunze_connect,
    169	.disconnect	= gunze_disconnect,
    170};
    171
    172module_serio_driver(gunze_drv);