Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.31-rc7 325 lines 7.1 kB view raw
1/* 2 * Wacom W8001 penabled serial touchscreen driver 3 * 4 * Copyright (c) 2008 Jaya Kumar 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive for 8 * more details. 9 * 10 * Layout based on Elo serial touchscreen driver by Vojtech Pavlik 11 */ 12 13#include <linux/errno.h> 14#include <linux/kernel.h> 15#include <linux/module.h> 16#include <linux/slab.h> 17#include <linux/input.h> 18#include <linux/serio.h> 19#include <linux/init.h> 20#include <linux/ctype.h> 21 22#define DRIVER_DESC "Wacom W8001 serial touchscreen driver" 23 24MODULE_AUTHOR("Jaya Kumar <jayakumar.lkml@gmail.com>"); 25MODULE_DESCRIPTION(DRIVER_DESC); 26MODULE_LICENSE("GPL"); 27 28/* 29 * Definitions & global arrays. 30 */ 31 32#define W8001_MAX_LENGTH 11 33#define W8001_PACKET_LEN 11 34#define W8001_LEAD_MASK 0x80 35#define W8001_LEAD_BYTE 0x80 36#define W8001_TAB_MASK 0x40 37#define W8001_TAB_BYTE 0x40 38 39#define W8001_QUERY_PACKET 0x20 40 41struct w8001_coord { 42 u8 rdy; 43 u8 tsw; 44 u8 f1; 45 u8 f2; 46 u16 x; 47 u16 y; 48 u16 pen_pressure; 49 u8 tilt_x; 50 u8 tilt_y; 51}; 52 53/* 54 * Per-touchscreen data. 55 */ 56 57struct w8001 { 58 struct input_dev *dev; 59 struct serio *serio; 60 struct mutex cmd_mutex; 61 struct completion cmd_done; 62 int id; 63 int idx; 64 unsigned char expected_packet; 65 unsigned char data[W8001_MAX_LENGTH]; 66 unsigned char response[W8001_PACKET_LEN]; 67 char phys[32]; 68}; 69 70static int parse_data(u8 *data, struct w8001_coord *coord) 71{ 72 coord->rdy = data[0] & 0x20; 73 coord->tsw = data[0] & 0x01; 74 coord->f1 = data[0] & 0x02; 75 coord->f2 = data[0] & 0x04; 76 77 coord->x = (data[1] & 0x7F) << 9; 78 coord->x |= (data[2] & 0x7F) << 2; 79 coord->x |= (data[6] & 0x60) >> 5; 80 81 coord->y = (data[3] & 0x7F) << 9; 82 coord->y |= (data[4] & 0x7F) << 2; 83 coord->y |= (data[6] & 0x18) >> 3; 84 85 coord->pen_pressure = data[5] & 0x7F; 86 coord->pen_pressure |= (data[6] & 0x07) << 7 ; 87 88 coord->tilt_x = data[7] & 0x7F; 89 coord->tilt_y = data[8] & 0x7F; 90 91 return 0; 92} 93 94static void w8001_process_data(struct w8001 *w8001, unsigned char data) 95{ 96 struct input_dev *dev = w8001->dev; 97 u8 tmp; 98 struct w8001_coord coord; 99 100 w8001->data[w8001->idx] = data; 101 switch (w8001->idx++) { 102 case 0: 103 if ((data & W8001_LEAD_MASK) != W8001_LEAD_BYTE) { 104 pr_debug("w8001: unsynchronized data: 0x%02x\n", data); 105 w8001->idx = 0; 106 } 107 break; 108 case 8: 109 tmp = w8001->data[0] & W8001_TAB_MASK; 110 if (unlikely(tmp == W8001_TAB_BYTE)) 111 break; 112 w8001->idx = 0; 113 memset(&coord, 0, sizeof(coord)); 114 parse_data(w8001->data, &coord); 115 input_report_abs(dev, ABS_X, coord.x); 116 input_report_abs(dev, ABS_Y, coord.y); 117 input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure); 118 input_report_key(dev, BTN_TOUCH, coord.tsw); 119 input_sync(dev); 120 break; 121 case 10: 122 w8001->idx = 0; 123 memcpy(w8001->response, &w8001->data, W8001_PACKET_LEN); 124 w8001->expected_packet = W8001_QUERY_PACKET; 125 complete(&w8001->cmd_done); 126 break; 127 } 128} 129 130 131static irqreturn_t w8001_interrupt(struct serio *serio, 132 unsigned char data, unsigned int flags) 133{ 134 struct w8001 *w8001 = serio_get_drvdata(serio); 135 136 w8001_process_data(w8001, data); 137 138 return IRQ_HANDLED; 139} 140 141static int w8001_async_command(struct w8001 *w8001, unsigned char *packet, 142 int len) 143{ 144 int rc = -1; 145 int i; 146 147 mutex_lock(&w8001->cmd_mutex); 148 149 for (i = 0; i < len; i++) { 150 if (serio_write(w8001->serio, packet[i])) 151 goto out; 152 } 153 rc = 0; 154 155out: 156 mutex_unlock(&w8001->cmd_mutex); 157 return rc; 158} 159 160static int w8001_command(struct w8001 *w8001, unsigned char *packet, int len) 161{ 162 int rc = -1; 163 int i; 164 165 mutex_lock(&w8001->cmd_mutex); 166 167 serio_pause_rx(w8001->serio); 168 init_completion(&w8001->cmd_done); 169 serio_continue_rx(w8001->serio); 170 171 for (i = 0; i < len; i++) { 172 if (serio_write(w8001->serio, packet[i])) 173 goto out; 174 } 175 176 wait_for_completion_timeout(&w8001->cmd_done, HZ); 177 178 if (w8001->expected_packet == W8001_QUERY_PACKET) { 179 /* We are back in reporting mode, the query was ACKed */ 180 memcpy(packet, w8001->response, W8001_PACKET_LEN); 181 rc = 0; 182 } 183 184out: 185 mutex_unlock(&w8001->cmd_mutex); 186 return rc; 187} 188 189static int w8001_setup(struct w8001 *w8001) 190{ 191 struct w8001_coord coord; 192 struct input_dev *dev = w8001->dev; 193 unsigned char start[1] = { '1' }; 194 unsigned char query[11] = { '*' }; 195 196 if (w8001_command(w8001, query, 1)) 197 return -1; 198 199 memset(&coord, 0, sizeof(coord)); 200 parse_data(query, &coord); 201 202 input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); 203 input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); 204 input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); 205 input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); 206 input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0); 207 208 if (w8001_async_command(w8001, start, 1)) 209 return -1; 210 211 return 0; 212} 213 214/* 215 * w8001_disconnect() is the opposite of w8001_connect() 216 */ 217 218static void w8001_disconnect(struct serio *serio) 219{ 220 struct w8001 *w8001 = serio_get_drvdata(serio); 221 222 input_get_device(w8001->dev); 223 input_unregister_device(w8001->dev); 224 serio_close(serio); 225 serio_set_drvdata(serio, NULL); 226 input_put_device(w8001->dev); 227 kfree(w8001); 228} 229 230/* 231 * w8001_connect() is the routine that is called when someone adds a 232 * new serio device that supports the w8001 protocol and registers it as 233 * an input device. 234 */ 235 236static int w8001_connect(struct serio *serio, struct serio_driver *drv) 237{ 238 struct w8001 *w8001; 239 struct input_dev *input_dev; 240 int err; 241 242 w8001 = kzalloc(sizeof(struct w8001), GFP_KERNEL); 243 input_dev = input_allocate_device(); 244 if (!w8001 || !input_dev) { 245 err = -ENOMEM; 246 goto fail1; 247 } 248 249 w8001->serio = serio; 250 w8001->id = serio->id.id; 251 w8001->dev = input_dev; 252 mutex_init(&w8001->cmd_mutex); 253 init_completion(&w8001->cmd_done); 254 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys); 255 256 input_dev->name = "Wacom W8001 Penabled Serial TouchScreen"; 257 input_dev->phys = w8001->phys; 258 input_dev->id.bustype = BUS_RS232; 259 input_dev->id.vendor = SERIO_W8001; 260 input_dev->id.product = w8001->id; 261 input_dev->id.version = 0x0100; 262 input_dev->dev.parent = &serio->dev; 263 264 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 265 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 266 267 serio_set_drvdata(serio, w8001); 268 err = serio_open(serio, drv); 269 if (err) 270 goto fail2; 271 272 if (w8001_setup(w8001)) 273 goto fail3; 274 275 err = input_register_device(w8001->dev); 276 if (err) 277 goto fail3; 278 279 return 0; 280 281fail3: 282 serio_close(serio); 283fail2: 284 serio_set_drvdata(serio, NULL); 285fail1: 286 input_free_device(input_dev); 287 kfree(w8001); 288 return err; 289} 290 291static struct serio_device_id w8001_serio_ids[] = { 292 { 293 .type = SERIO_RS232, 294 .proto = SERIO_W8001, 295 .id = SERIO_ANY, 296 .extra = SERIO_ANY, 297 }, 298 { 0 } 299}; 300 301MODULE_DEVICE_TABLE(serio, w8001_serio_ids); 302 303static struct serio_driver w8001_drv = { 304 .driver = { 305 .name = "w8001", 306 }, 307 .description = DRIVER_DESC, 308 .id_table = w8001_serio_ids, 309 .interrupt = w8001_interrupt, 310 .connect = w8001_connect, 311 .disconnect = w8001_disconnect, 312}; 313 314static int __init w8001_init(void) 315{ 316 return serio_register_driver(&w8001_drv); 317} 318 319static void __exit w8001_exit(void) 320{ 321 serio_unregister_driver(&w8001_drv); 322} 323 324module_init(w8001_init); 325module_exit(w8001_exit);