1 /* 2 * Dynapro serial touchscreen driver 3 * 4 * Copyright (c) 2009 Tias Guns 5 * Based on the inexio driver (c) Vojtech Pavlik and Dan Streetman and 6 * Richard Lemon 7 * 8 */ 9 10 /* 11 * This program is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License version 2 as published by 13 * the Free Software Foundation. 14 */ 15 16 /* 17 * 2009/09/19 Tias Guns <tias@ulyssis.org> 18 * Copied inexio.c and edited for Dynapro protocol (from retired Xorg module) 19 */ 20 21 #include <linux/errno.h> 22 #include <linux/kernel.h> 23 #include <linux/module.h> 24 #include <linux/slab.h> 25 #include <linux/input.h> 26 #include <linux/serio.h> 27 #include <linux/init.h> 28 29 #define DRIVER_DESC "Dynapro serial touchscreen driver" 30 31 MODULE_AUTHOR("Tias Guns <tias@ulyssis.org>"); 32 MODULE_DESCRIPTION(DRIVER_DESC); 33 MODULE_LICENSE("GPL"); 34 35 /* 36 * Definitions & global arrays. 37 */ 38 39 #define DYNAPRO_FORMAT_TOUCH_BIT 0x40 40 #define DYNAPRO_FORMAT_LENGTH 3 41 #define DYNAPRO_RESPONSE_BEGIN_BYTE 0x80 42 43 #define DYNAPRO_MIN_XC 0 44 #define DYNAPRO_MAX_XC 0x3ff 45 #define DYNAPRO_MIN_YC 0 46 #define DYNAPRO_MAX_YC 0x3ff 47 48 #define DYNAPRO_GET_XC(data) (data[1] | ((data[0] & 0x38) << 4)) 49 #define DYNAPRO_GET_YC(data) (data[2] | ((data[0] & 0x07) << 7)) 50 #define DYNAPRO_GET_TOUCHED(data) (DYNAPRO_FORMAT_TOUCH_BIT & data[0]) 51 52 /* 53 * Per-touchscreen data. 54 */ 55 56 struct dynapro { 57 struct input_dev *dev; 58 struct serio *serio; 59 int idx; 60 unsigned char data[DYNAPRO_FORMAT_LENGTH]; 61 char phys[32]; 62 }; 63 64 static void dynapro_process_data(struct dynapro *pdynapro) 65 { 66 struct input_dev *dev = pdynapro->dev; 67 68 if (DYNAPRO_FORMAT_LENGTH == ++pdynapro->idx) { 69 input_report_abs(dev, ABS_X, DYNAPRO_GET_XC(pdynapro->data)); 70 input_report_abs(dev, ABS_Y, DYNAPRO_GET_YC(pdynapro->data)); 71 input_report_key(dev, BTN_TOUCH, 72 DYNAPRO_GET_TOUCHED(pdynapro->data)); 73 input_sync(dev); 74 75 pdynapro->idx = 0; 76 } 77 } 78 79 static irqreturn_t dynapro_interrupt(struct serio *serio, 80 unsigned char data, unsigned int flags) 81 { 82 struct dynapro *pdynapro = serio_get_drvdata(serio); 83 84 pdynapro->data[pdynapro->idx] = data; 85 86 if (DYNAPRO_RESPONSE_BEGIN_BYTE & pdynapro->data[0]) 87 dynapro_process_data(pdynapro); 88 else 89 dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n", 90 pdynapro->data[0]); 91 92 return IRQ_HANDLED; 93 } 94 95 static void dynapro_disconnect(struct serio *serio) 96 { 97 struct dynapro *pdynapro = serio_get_drvdata(serio); 98 99 input_get_device(pdynapro->dev); 100 input_unregister_device(pdynapro->dev); 101 serio_close(serio); 102 serio_set_drvdata(serio, NULL); 103 input_put_device(pdynapro->dev); 104 kfree(pdynapro); 105 } 106 107 /* 108 * dynapro_connect() is the routine that is called when someone adds a 109 * new serio device that supports dynapro protocol and registers it as 110 * an input device. This is usually accomplished using inputattach. 111 */ 112 113 static int dynapro_connect(struct serio *serio, struct serio_driver *drv) 114 { 115 struct dynapro *pdynapro; 116 struct input_dev *input_dev; 117 int err; 118 119 pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL); 120 input_dev = input_allocate_device(); 121 if (!pdynapro || !input_dev) { 122 err = -ENOMEM; 123 goto fail1; 124 } 125 126 pdynapro->serio = serio; 127 pdynapro->dev = input_dev; 128 snprintf(pdynapro->phys, sizeof(pdynapro->phys), 129 "%s/input0", serio->phys); 130 131 input_dev->name = "Dynapro Serial TouchScreen"; 132 input_dev->phys = pdynapro->phys; 133 input_dev->id.bustype = BUS_RS232; 134 input_dev->id.vendor = SERIO_DYNAPRO; 135 input_dev->id.product = 0; 136 input_dev->id.version = 0x0001; 137 input_dev->dev.parent = &serio->dev; 138 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 139 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 140 input_set_abs_params(pdynapro->dev, ABS_X, 141 DYNAPRO_MIN_XC, DYNAPRO_MAX_XC, 0, 0); 142 input_set_abs_params(pdynapro->dev, ABS_Y, 143 DYNAPRO_MIN_YC, DYNAPRO_MAX_YC, 0, 0); 144 145 serio_set_drvdata(serio, pdynapro); 146 147 err = serio_open(serio, drv); 148 if (err) 149 goto fail2; 150 151 err = input_register_device(pdynapro->dev); 152 if (err) 153 goto fail3; 154 155 return 0; 156 157 fail3: serio_close(serio); 158 fail2: serio_set_drvdata(serio, NULL); 159 fail1: input_free_device(input_dev); 160 kfree(pdynapro); 161 return err; 162 } 163 164 /* 165 * The serio driver structure. 166 */ 167 168 static struct serio_device_id dynapro_serio_ids[] = { 169 { 170 .type = SERIO_RS232, 171 .proto = SERIO_DYNAPRO, 172 .id = SERIO_ANY, 173 .extra = SERIO_ANY, 174 }, 175 { 0 } 176 }; 177 178 MODULE_DEVICE_TABLE(serio, dynapro_serio_ids); 179 180 static struct serio_driver dynapro_drv = { 181 .driver = { 182 .name = "dynapro", 183 }, 184 .description = DRIVER_DESC, 185 .id_table = dynapro_serio_ids, 186 .interrupt = dynapro_interrupt, 187 .connect = dynapro_connect, 188 .disconnect = dynapro_disconnect, 189 }; 190 191 module_serio_driver(dynapro_drv); 192