Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | // 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); |