^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Touchwindow serial touchscreen driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2004 Vojtech Pavlik
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * and Dan Streetman <ddstreet@ieee.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * 2005/02/19 Rick Koch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * The Touchwindow I used is made by Edmark Corp. and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * constantly outputs a stream of 0's unless it is touched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * It then outputs 3 bytes: X, Y, and a copy of Y.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define DRIVER_DESC "Touchwindow serial touchscreen driver"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) MODULE_DESCRIPTION(DRIVER_DESC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * Definitions & global arrays.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define TW_LENGTH 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define TW_MIN_XC 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define TW_MAX_XC 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define TW_MIN_YC 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define TW_MAX_YC 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Per-touchscreen data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct tw {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct input_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct serio *serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int touched;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned char data[TW_LENGTH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) char phys[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static irqreturn_t tw_interrupt(struct serio *serio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned char data, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct tw *tw = serio_get_drvdata(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct input_dev *dev = tw->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (data) { /* touch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) tw->touched = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) tw->data[tw->idx++] = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* verify length and that the two Y's are the same */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) input_report_abs(dev, ABS_X, tw->data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) input_report_abs(dev, ABS_Y, tw->data[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) input_report_key(dev, BTN_TOUCH, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) tw->idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) } else if (tw->touched) { /* untouch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) input_report_key(dev, BTN_TOUCH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) tw->idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) tw->touched = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * tw_disconnect() is the opposite of tw_connect()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static void tw_disconnect(struct serio *serio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct tw *tw = serio_get_drvdata(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) input_get_device(tw->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) input_unregister_device(tw->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) serio_close(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) serio_set_drvdata(serio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) input_put_device(tw->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) kfree(tw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * tw_connect() is the routine that is called when someone adds a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * new serio device that supports the Touchwin protocol and registers it as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * an input device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int tw_connect(struct serio *serio, struct serio_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct tw *tw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct input_dev *input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) tw = kzalloc(sizeof(struct tw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) input_dev = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!tw || !input_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) tw->serio = serio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) tw->dev = input_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) input_dev->name = "Touchwindow Serial TouchScreen";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) input_dev->phys = tw->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) input_dev->id.bustype = BUS_RS232;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) input_dev->id.vendor = SERIO_TOUCHWIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) input_dev->id.product = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) input_dev->id.version = 0x0100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) input_dev->dev.parent = &serio->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) serio_set_drvdata(serio, tw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) err = serio_open(serio, drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) goto fail2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) err = input_register_device(tw->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) goto fail3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) fail3: serio_close(serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) fail2: serio_set_drvdata(serio, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) fail1: input_free_device(input_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) kfree(tw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * The serio driver structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static const struct serio_device_id tw_serio_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .type = SERIO_RS232,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .proto = SERIO_TOUCHWIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .id = SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .extra = SERIO_ANY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) { 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) MODULE_DEVICE_TABLE(serio, tw_serio_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static struct serio_driver tw_drv = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .name = "touchwin",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .description = DRIVER_DESC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .id_table = tw_serio_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) .interrupt = tw_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .connect = tw_connect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .disconnect = tw_disconnect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) module_serio_driver(tw_drv);