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 28MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 29MODULE_DESCRIPTION(DRIVER_DESC); 30MODULE_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 58struct 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 66static 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 80static void mtouch_process_response(struct mtouch *mtouch) 81{ 82 if (MTOUCH_RESPONSE_END_BYTE == mtouch->data[mtouch->idx++]) { 83 mtouch->idx = 0; 84 } else if (MTOUCH_MAX_LENGTH == mtouch->idx) { 85 printk(KERN_ERR "mtouch.c: too many response bytes\n"); 86 mtouch->idx = 0; 87 } 88} 89 90static irqreturn_t mtouch_interrupt(struct serio *serio, 91 unsigned char data, unsigned int flags) 92{ 93 struct mtouch* mtouch = serio_get_drvdata(serio); 94 95 mtouch->data[mtouch->idx] = data; 96 97 if (MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch->data[0]) 98 mtouch_process_format_tablet(mtouch); 99 else if (MTOUCH_RESPONSE_BEGIN_BYTE == mtouch->data[0]) 100 mtouch_process_response(mtouch); 101 else 102 printk(KERN_DEBUG "mtouch.c: unknown/unsynchronized data from device, byte %x\n",mtouch->data[0]); 103 104 return IRQ_HANDLED; 105} 106 107/* 108 * mtouch_disconnect() is the opposite of mtouch_connect() 109 */ 110 111static void mtouch_disconnect(struct serio *serio) 112{ 113 struct mtouch* mtouch = serio_get_drvdata(serio); 114 115 input_get_device(mtouch->dev); 116 input_unregister_device(mtouch->dev); 117 serio_close(serio); 118 serio_set_drvdata(serio, NULL); 119 input_put_device(mtouch->dev); 120 kfree(mtouch); 121} 122 123/* 124 * mtouch_connect() is the routine that is called when someone adds a 125 * new serio device that supports MicroTouch (Format Tablet) protocol and registers it as 126 * an input device. 127 */ 128 129static int mtouch_connect(struct serio *serio, struct serio_driver *drv) 130{ 131 struct mtouch *mtouch; 132 struct input_dev *input_dev; 133 int err; 134 135 mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL); 136 input_dev = input_allocate_device(); 137 if (!mtouch || !input_dev) { 138 err = -ENOMEM; 139 goto fail1; 140 } 141 142 mtouch->serio = serio; 143 mtouch->dev = input_dev; 144 snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys); 145 146 input_dev->name = "MicroTouch Serial TouchScreen"; 147 input_dev->phys = mtouch->phys; 148 input_dev->id.bustype = BUS_RS232; 149 input_dev->id.vendor = SERIO_MICROTOUCH; 150 input_dev->id.product = 0; 151 input_dev->id.version = 0x0100; 152 input_dev->dev.parent = &serio->dev; 153 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 154 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 155 input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0); 156 input_set_abs_params(mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0); 157 158 serio_set_drvdata(serio, mtouch); 159 160 err = serio_open(serio, drv); 161 if (err) 162 goto fail2; 163 164 err = input_register_device(mtouch->dev); 165 if (err) 166 goto fail3; 167 168 return 0; 169 170 fail3: serio_close(serio); 171 fail2: serio_set_drvdata(serio, NULL); 172 fail1: input_free_device(input_dev); 173 kfree(mtouch); 174 return err; 175} 176 177/* 178 * The serio driver structure. 179 */ 180 181static struct serio_device_id mtouch_serio_ids[] = { 182 { 183 .type = SERIO_RS232, 184 .proto = SERIO_MICROTOUCH, 185 .id = SERIO_ANY, 186 .extra = SERIO_ANY, 187 }, 188 { 0 } 189}; 190 191MODULE_DEVICE_TABLE(serio, mtouch_serio_ids); 192 193static struct serio_driver mtouch_drv = { 194 .driver = { 195 .name = "mtouch", 196 }, 197 .description = DRIVER_DESC, 198 .id_table = mtouch_serio_ids, 199 .interrupt = mtouch_interrupt, 200 .connect = mtouch_connect, 201 .disconnect = mtouch_disconnect, 202}; 203 204/* 205 * The functions for inserting/removing us as a module. 206 */ 207 208static int __init mtouch_init(void) 209{ 210 return serio_register_driver(&mtouch_drv); 211} 212 213static void __exit mtouch_exit(void) 214{ 215 serio_unregister_driver(&mtouch_drv); 216} 217 218module_init(mtouch_init); 219module_exit(mtouch_exit); 220