// 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(sizeof(struct touchit213), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!touchit213 || !input_dev) {
		err = -ENOMEM;
		goto fail1;
	}

	touchit213->serio = serio;
	touchit213->dev = input_dev;
	snprintf(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);
