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