mtouch.c (4920B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * MicroTouch (3M) serial touchscreen driver 4 * 5 * Copyright (c) 2004 Vojtech Pavlik 6 */ 7 8 9/* 10 * 2005/02/19 Dan Streetman <ddstreet@ieee.org> 11 * Copied elo.c and edited for MicroTouch protocol 12 */ 13 14#include <linux/errno.h> 15#include <linux/kernel.h> 16#include <linux/module.h> 17#include <linux/slab.h> 18#include <linux/input.h> 19#include <linux/serio.h> 20 21#define DRIVER_DESC "MicroTouch serial touchscreen driver" 22 23MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 24MODULE_DESCRIPTION(DRIVER_DESC); 25MODULE_LICENSE("GPL"); 26 27/* 28 * Definitions & global arrays. 29 */ 30 31#define MTOUCH_FORMAT_TABLET_STATUS_BIT 0x80 32#define MTOUCH_FORMAT_TABLET_TOUCH_BIT 0x40 33#define MTOUCH_FORMAT_TABLET_LENGTH 5 34#define MTOUCH_RESPONSE_BEGIN_BYTE 0x01 35#define MTOUCH_RESPONSE_END_BYTE 0x0d 36 37/* todo: check specs for max length of all responses */ 38#define MTOUCH_MAX_LENGTH 16 39 40#define MTOUCH_MIN_XC 0 41#define MTOUCH_MAX_XC 0x3fff 42#define MTOUCH_MIN_YC 0 43#define MTOUCH_MAX_YC 0x3fff 44 45#define MTOUCH_GET_XC(data) (((data[2])<<7) | data[1]) 46#define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3]) 47#define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0]) 48 49/* 50 * Per-touchscreen data. 51 */ 52 53struct mtouch { 54 struct input_dev *dev; 55 struct serio *serio; 56 int idx; 57 unsigned char data[MTOUCH_MAX_LENGTH]; 58 char phys[32]; 59}; 60 61static void mtouch_process_format_tablet(struct mtouch *mtouch) 62{ 63 struct input_dev *dev = mtouch->dev; 64 65 if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) { 66 input_report_abs(dev, ABS_X, MTOUCH_GET_XC(mtouch->data)); 67 input_report_abs(dev, ABS_Y, MTOUCH_MAX_YC - MTOUCH_GET_YC(mtouch->data)); 68 input_report_key(dev, BTN_TOUCH, MTOUCH_GET_TOUCHED(mtouch->data)); 69 input_sync(dev); 70 71 mtouch->idx = 0; 72 } 73} 74 75static void mtouch_process_response(struct mtouch *mtouch) 76{ 77 if (MTOUCH_RESPONSE_END_BYTE == mtouch->data[mtouch->idx++]) { 78 /* FIXME - process response */ 79 mtouch->idx = 0; 80 } else if (MTOUCH_MAX_LENGTH == mtouch->idx) { 81 printk(KERN_ERR "mtouch.c: too many response bytes\n"); 82 mtouch->idx = 0; 83 } 84} 85 86static irqreturn_t mtouch_interrupt(struct serio *serio, 87 unsigned char data, unsigned int flags) 88{ 89 struct mtouch *mtouch = serio_get_drvdata(serio); 90 91 mtouch->data[mtouch->idx] = data; 92 93 if (MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch->data[0]) 94 mtouch_process_format_tablet(mtouch); 95 else if (MTOUCH_RESPONSE_BEGIN_BYTE == mtouch->data[0]) 96 mtouch_process_response(mtouch); 97 else 98 printk(KERN_DEBUG "mtouch.c: unknown/unsynchronized data from device, byte %x\n",mtouch->data[0]); 99 100 return IRQ_HANDLED; 101} 102 103/* 104 * mtouch_disconnect() is the opposite of mtouch_connect() 105 */ 106 107static void mtouch_disconnect(struct serio *serio) 108{ 109 struct mtouch *mtouch = serio_get_drvdata(serio); 110 111 input_get_device(mtouch->dev); 112 input_unregister_device(mtouch->dev); 113 serio_close(serio); 114 serio_set_drvdata(serio, NULL); 115 input_put_device(mtouch->dev); 116 kfree(mtouch); 117} 118 119/* 120 * mtouch_connect() is the routine that is called when someone adds a 121 * new serio device that supports MicroTouch (Format Tablet) protocol and registers it as 122 * an input device. 123 */ 124 125static int mtouch_connect(struct serio *serio, struct serio_driver *drv) 126{ 127 struct mtouch *mtouch; 128 struct input_dev *input_dev; 129 int err; 130 131 mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL); 132 input_dev = input_allocate_device(); 133 if (!mtouch || !input_dev) { 134 err = -ENOMEM; 135 goto fail1; 136 } 137 138 mtouch->serio = serio; 139 mtouch->dev = input_dev; 140 snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys); 141 142 input_dev->name = "MicroTouch Serial TouchScreen"; 143 input_dev->phys = mtouch->phys; 144 input_dev->id.bustype = BUS_RS232; 145 input_dev->id.vendor = SERIO_MICROTOUCH; 146 input_dev->id.product = 0; 147 input_dev->id.version = 0x0100; 148 input_dev->dev.parent = &serio->dev; 149 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 150 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 151 input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0); 152 input_set_abs_params(mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0); 153 154 serio_set_drvdata(serio, mtouch); 155 156 err = serio_open(serio, drv); 157 if (err) 158 goto fail2; 159 160 err = input_register_device(mtouch->dev); 161 if (err) 162 goto fail3; 163 164 return 0; 165 166 fail3: serio_close(serio); 167 fail2: serio_set_drvdata(serio, NULL); 168 fail1: input_free_device(input_dev); 169 kfree(mtouch); 170 return err; 171} 172 173/* 174 * The serio driver structure. 175 */ 176 177static const struct serio_device_id mtouch_serio_ids[] = { 178 { 179 .type = SERIO_RS232, 180 .proto = SERIO_MICROTOUCH, 181 .id = SERIO_ANY, 182 .extra = SERIO_ANY, 183 }, 184 { 0 } 185}; 186 187MODULE_DEVICE_TABLE(serio, mtouch_serio_ids); 188 189static struct serio_driver mtouch_drv = { 190 .driver = { 191 .name = "mtouch", 192 }, 193 .description = DRIVER_DESC, 194 .id_table = mtouch_serio_ids, 195 .interrupt = mtouch_interrupt, 196 .connect = mtouch_connect, 197 .disconnect = mtouch_disconnect, 198}; 199 200module_serio_driver(mtouch_drv);