// SPDX-License-Identifier: GPL-2.0-only
/*
 * Sahara TouchIT-213 serial touchscreen driver
 *
 * Copyright (c) 2007-2008 Claudio Nieder <private@claudio.ch>
 *
 * Based on Touchright driver (drivers/input/touchscreen/touchright.c)
 * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
 * Copyright (c) 2004 Vojtech Pavlik
 * and Dan Streetman <ddstreet@ieee.org>
 */


#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/serio.h>

#define DRIVER_DESC	"Sahara TouchIT-213 serial touchscreen driver"

MODULE_AUTHOR("Claudio Nieder <private@claudio.ch>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

/*
 * Definitions & global arrays.
 */

/*
 * Data is received through COM1 at 9600bit/s,8bit,no parity in packets
 * of 5 byte each.
 *
 *   +--------+   +--------+   +--------+   +--------+   +--------+
 *   |1000000p|   |0xxxxxxx|   |0xxxxxxx|   |0yyyyyyy|   |0yyyyyyy|
 *   +--------+   +--------+   +--------+   +--------+   +--------+
 *                    MSB          LSB          MSB          LSB
 *
 * The value of p is 1 as long as the screen is touched and 0 when
 * reporting the location where touching stopped, e.g. where the pen was
 * lifted from the screen.
 *
 * When holding the screen in landscape mode as the BIOS text output is
 * presented, x is the horizontal axis with values growing from left to
 * right and y is the vertical axis with values growing from top to
 * bottom.
 *
 * When holding the screen in portrait mode with the Sahara logo in its
 * correct position, x ist the vertical axis with values growing from
 * top to bottom and y is the horizontal axis with values growing from
 * right to left.
 */

#define T213_FORMAT_TOUCH_BIT	0x01
#define T213_FORMAT_STATUS_BYTE	0x80
#define T213_FORMAT_STATUS_MASK	~T213_FORMAT_TOUCH_BIT

/*
 * On my Sahara Touch-IT 213 I have observed x values from 0 to 0x7f0
 * and y values from 0x1d to 0x7e9, so the actual measurement is
 * probably done with an 11 bit precision.
 */
#define T213_MIN_XC 0
#define T213_MAX_XC 0x07ff
#define T213_MIN_YC 0
#define T213_MAX_YC 0x07ff

/*
 * Per-touchscreen data.
 */

struct touchit213 {
	struct input_dev *dev;
	struct serio *serio;
	int idx;
	unsigned char csum;
	unsigned char data[5];
	char phys[32];
};

static irqreturn_t touchit213_interrupt(struct serio *serio,
		unsigned char data, unsigned int flags)
{
	struct touchit213 *touchit213 = serio_get_drvdata(serio);
	struct input_dev *dev = touchit213->dev;

	touchit213->data[touchit213->idx] = data;

	switch (touchit213->idx++) {
	case 0:
		if ((touchit213->data[0] & T213_FORMAT_STATUS_MASK) !=
				T213_FORMAT_STATUS_BYTE) {
			pr_debug("unsynchronized data: 0x%02x\n", data);
			touchit213->idx = 0;
		}
		break;

	case 4:
		touchit213->idx = 0;
		input_report_abs(dev, ABS_X,
			(touchit213->data[1] << 7) | touchit213->data[2]);
		input_report_abs(dev, ABS_Y,
			(touchit213->data[3] << 7) | touchit213->data[4]);
		input_report_key(dev, BTN_TOUCH,
			touchit213->data[0] & T213_FORMAT_TOUCH_BIT);
		input_sync(dev);
		break;
	}

	return IRQ_HANDLED;
}

/*
 * touchit213_disconnect() is the opposite of touchit213_connect()
 */

static void touchit213_disconnect(struct serio *serio)
{
	struct touchit213 *touchit213 = serio_get_drvdata(serio);

	input_get_device(touchit213->dev);
	input_unregister_device(touchit213->dev);
	serio_close(serio);
	serio_set_drvdata(serio, NULL);
	input_put_device(touchit213->dev);
	kfree(touchit213);
}

/*
 * touchit213_connect() is the routine that is called when someone adds a
 * new serio device that supports the Touchright protocol and registers it as
 * an input device.
 */

static int touchit213_connect(struct serio *serio, struct serio_driver *drv)
{
	struct touchit213 *touchit213;
	struct input_dev *input_dev;
	int err;

	touchit213 = kzalloc_obj(*touchit213);
	input_dev = input_allocate_device();
	if (!touchit213 || !input_dev) {
		err = -ENOMEM;
		goto fail1;
	}

	touchit213->serio = serio;
	touchit213->dev = input_dev;
	scnprintf(touchit213->phys, sizeof(touchit213->phys),
		  "%s/input0", serio->phys);

	input_dev->name = "Sahara Touch-iT213 Serial TouchScreen";
	input_dev->phys = touchit213->phys;
	input_dev->id.bustype = BUS_RS232;
	input_dev->id.vendor = SERIO_TOUCHIT213;
	input_dev->id.product = 0;
	input_dev->id.version = 0x0100;
	input_dev->dev.parent = &serio->dev;
	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
	input_set_abs_params(touchit213->dev, ABS_X,
			     T213_MIN_XC, T213_MAX_XC, 0, 0);
	input_set_abs_params(touchit213->dev, ABS_Y,
			     T213_MIN_YC, T213_MAX_YC, 0, 0);

	serio_set_drvdata(serio, touchit213);

	err = serio_open(serio, drv);
	if (err)
		goto fail2;

	err = input_register_device(touchit213->dev);
	if (err)
		goto fail3;

	return 0;

 fail3:	serio_close(serio);
 fail2:	serio_set_drvdata(serio, NULL);
 fail1:	input_free_device(input_dev);
	kfree(touchit213);
	return err;
}

/*
 * The serio driver structure.
 */

static const struct serio_device_id touchit213_serio_ids[] = {
	{
		.type	= SERIO_RS232,
		.proto	= SERIO_TOUCHIT213,
		.id	= SERIO_ANY,
		.extra	= SERIO_ANY,
	},
	{ 0 }
};

MODULE_DEVICE_TABLE(serio, touchit213_serio_ids);

static struct serio_driver touchit213_drv = {
	.driver		= {
		.name	= "touchit213",
	},
	.description	= DRIVER_DESC,
	.id_table	= touchit213_serio_ids,
	.interrupt	= touchit213_interrupt,
	.connect	= touchit213_connect,
	.disconnect	= touchit213_disconnect,
};

module_serio_driver(touchit213_drv);
