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 60e417536bca8988d22ea1cc20a634ffa67bb2a8 491 lines 13 kB view raw
1/* 2 * $Id: h3600_ts_input.c,v 1.4 2002/01/23 06:39:37 jsimmons Exp $ 3 * 4 * Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com 5 * 6 * Sponsored by Transvirtual Technology. 7 * 8 * Derived from the code in h3600_ts.[ch] by Charles Flynn 9 */ 10 11/* 12 * Driver for the h3600 Touch Screen and other Atmel controlled devices. 13 */ 14 15/* 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation; either version 2 of the License, or 19 * (at your option) any later version. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29 * 30 * Should you need to contact me, the author, you can do so by 31 * e-mail - mail your message to <jsimmons@transvirtual.com>. 32 */ 33 34#include <linux/errno.h> 35#include <linux/kernel.h> 36#include <linux/module.h> 37#include <linux/slab.h> 38#include <linux/input.h> 39#include <linux/serio.h> 40#include <linux/init.h> 41#include <linux/delay.h> 42 43/* SA1100 serial defines */ 44#include <asm/arch/hardware.h> 45#include <asm/arch/irqs.h> 46 47#define DRIVER_DESC "H3600 touchscreen driver" 48 49MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>"); 50MODULE_DESCRIPTION(DRIVER_DESC); 51MODULE_LICENSE("GPL"); 52 53/* 54 * Definitions & global arrays. 55 */ 56 57/* The start and end of frame characters SOF and EOF */ 58#define CHAR_SOF 0x02 59#define CHAR_EOF 0x03 60#define FRAME_OVERHEAD 3 /* CHAR_SOF,CHAR_EOF,LENGTH = 3 */ 61 62/* 63 Atmel events and response IDs contained in frame. 64 Programmer has no control over these numbers. 65 TODO there are holes - specifically 1,7,0x0a 66*/ 67#define VERSION_ID 0 /* Get Version (request/respose) */ 68#define KEYBD_ID 2 /* Keyboard (event) */ 69#define TOUCHS_ID 3 /* Touch Screen (event)*/ 70#define EEPROM_READ_ID 4 /* (request/response) */ 71#define EEPROM_WRITE_ID 5 /* (request/response) */ 72#define THERMAL_ID 6 /* (request/response) */ 73#define NOTIFY_LED_ID 8 /* (request/response) */ 74#define BATTERY_ID 9 /* (request/response) */ 75#define SPI_READ_ID 0x0b /* ( request/response) */ 76#define SPI_WRITE_ID 0x0c /* ( request/response) */ 77#define FLITE_ID 0x0d /* backlight ( request/response) */ 78#define STX_ID 0xa1 /* extension pack status (req/resp) */ 79 80#define MAX_ID 14 81 82#define H3600_MAX_LENGTH 16 83#define H3600_KEY 0xf 84 85#define H3600_SCANCODE_RECORD 1 /* 1 -> record button */ 86#define H3600_SCANCODE_CALENDAR 2 /* 2 -> calendar */ 87#define H3600_SCANCODE_CONTACTS 3 /* 3 -> contact */ 88#define H3600_SCANCODE_Q 4 /* 4 -> Q button */ 89#define H3600_SCANCODE_START 5 /* 5 -> start menu */ 90#define H3600_SCANCODE_UP 6 /* 6 -> up */ 91#define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ 92#define H3600_SCANCODE_LEFT 8 /* 8 -> left */ 93#define H3600_SCANCODE_DOWN 9 /* 9 -> down */ 94 95/* 96 * Per-touchscreen data. 97 */ 98struct h3600_dev { 99 struct input_dev *dev; 100 struct serio *serio; 101 unsigned char event; /* event ID from packet */ 102 unsigned char chksum; 103 unsigned char len; 104 unsigned char idx; 105 unsigned char buf[H3600_MAX_LENGTH]; 106 char phys[32]; 107}; 108 109static irqreturn_t action_button_handler(int irq, void *dev_id) 110{ 111 int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; 112 struct input_dev *dev = (struct input_dev *) dev_id; 113 114 input_report_key(dev, KEY_ENTER, down); 115 input_sync(dev); 116 117 return IRQ_HANDLED; 118} 119 120static irqreturn_t npower_button_handler(int irq, void *dev_id) 121{ 122 int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; 123 struct input_dev *dev = (struct input_dev *) dev_id; 124 125 /* 126 * This interrupt is only called when we release the key. So we have 127 * to fake a key press. 128 */ 129 input_report_key(dev, KEY_SUSPEND, 1); 130 input_report_key(dev, KEY_SUSPEND, down); 131 input_sync(dev); 132 133 return IRQ_HANDLED; 134} 135 136#ifdef CONFIG_PM 137 138static int flite_brightness = 25; 139 140enum flite_pwr { 141 FLITE_PWR_OFF = 0, 142 FLITE_PWR_ON = 1 143}; 144 145/* 146 * h3600_flite_power: enables or disables power to frontlight, using last bright */ 147unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) 148{ 149 unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness; 150 struct h3600_dev *ts = input_get_drvdata(dev); 151 152 /* Must be in this order */ 153 ts->serio->write(ts->serio, 1); 154 ts->serio->write(ts->serio, pwr); 155 ts->serio->write(ts->serio, brightness); 156 return 0; 157} 158 159#endif 160 161/* 162 * This function translates the native event packets to linux input event 163 * packets. Some packets coming from serial are not touchscreen related. In 164 * this case we send them off to be processed elsewhere. 165 */ 166static void h3600ts_process_packet(struct h3600_dev *ts) 167{ 168 struct input_dev *dev = ts->dev; 169 static int touched = 0; 170 int key, down = 0; 171 172 switch (ts->event) { 173 /* 174 Buttons - returned as a single byte 175 7 6 5 4 3 2 1 0 176 S x x x N N N N 177 178 S switch state ( 0=pressed 1=released) 179 x Unused. 180 NNNN switch number 0-15 181 182 Note: This is true for non interrupt generated key events. 183 */ 184 case KEYBD_ID: 185 down = (ts->buf[0] & 0x80) ? 0 : 1; 186 187 switch (ts->buf[0] & 0x7f) { 188 case H3600_SCANCODE_RECORD: 189 key = KEY_RECORD; 190 break; 191 case H3600_SCANCODE_CALENDAR: 192 key = KEY_PROG1; 193 break; 194 case H3600_SCANCODE_CONTACTS: 195 key = KEY_PROG2; 196 break; 197 case H3600_SCANCODE_Q: 198 key = KEY_Q; 199 break; 200 case H3600_SCANCODE_START: 201 key = KEY_PROG3; 202 break; 203 case H3600_SCANCODE_UP: 204 key = KEY_UP; 205 break; 206 case H3600_SCANCODE_RIGHT: 207 key = KEY_RIGHT; 208 break; 209 case H3600_SCANCODE_LEFT: 210 key = KEY_LEFT; 211 break; 212 case H3600_SCANCODE_DOWN: 213 key = KEY_DOWN; 214 break; 215 default: 216 key = 0; 217 } 218 if (key) 219 input_report_key(dev, key, down); 220 break; 221 /* 222 * Native touchscreen event data is formatted as shown below:- 223 * 224 * +-------+-------+-------+-------+ 225 * | Xmsb | Xlsb | Ymsb | Ylsb | 226 * +-------+-------+-------+-------+ 227 * byte 0 1 2 3 228 */ 229 case TOUCHS_ID: 230 if (!touched) { 231 input_report_key(dev, BTN_TOUCH, 1); 232 touched = 1; 233 } 234 235 if (ts->len) { 236 unsigned short x, y; 237 238 x = ts->buf[0]; x <<= 8; x += ts->buf[1]; 239 y = ts->buf[2]; y <<= 8; y += ts->buf[3]; 240 241 input_report_abs(dev, ABS_X, x); 242 input_report_abs(dev, ABS_Y, y); 243 } else { 244 input_report_key(dev, BTN_TOUCH, 0); 245 touched = 0; 246 } 247 break; 248 default: 249 /* Send a non input event elsewhere */ 250 break; 251 } 252 253 input_sync(dev); 254} 255 256/* 257 * h3600ts_event() handles events from the input module. 258 */ 259static int h3600ts_event(struct input_dev *dev, unsigned int type, 260 unsigned int code, int value) 261{ 262#if 0 263 struct h3600_dev *ts = input_get_drvdata(dev); 264 265 switch (type) { 266 case EV_LED: { 267 // ts->serio->write(ts->serio, SOME_CMD); 268 return 0; 269 } 270 } 271 return -1; 272#endif 273 return 0; 274} 275 276/* 277 Frame format 278 byte 1 2 3 len + 4 279 +-------+---------------+---------------+--=------------+ 280 |SOF |id |len | len bytes | Chksum | 281 +-------+---------------+---------------+--=------------+ 282 bit 0 7 8 11 12 15 16 283 284 +-------+---------------+-------+ 285 |SOF |id |0 |Chksum | - Note Chksum does not include SOF 286 +-------+---------------+-------+ 287 bit 0 7 8 11 12 15 16 288 289*/ 290 291static int state; 292 293/* decode States */ 294#define STATE_SOF 0 /* start of FRAME */ 295#define STATE_ID 1 /* state where we decode the ID & len */ 296#define STATE_DATA 2 /* state where we decode data */ 297#define STATE_EOF 3 /* state where we decode checksum or EOF */ 298 299static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, 300 unsigned int flags) 301{ 302 struct h3600_dev *ts = serio_get_drvdata(serio); 303 304 /* 305 * We have a new frame coming in. 306 */ 307 switch (state) { 308 case STATE_SOF: 309 if (data == CHAR_SOF) 310 state = STATE_ID; 311 break; 312 case STATE_ID: 313 ts->event = (data & 0xf0) >> 4; 314 ts->len = (data & 0xf); 315 ts->idx = 0; 316 if (ts->event >= MAX_ID) { 317 state = STATE_SOF; 318 break; 319 } 320 ts->chksum = data; 321 state = (ts->len > 0) ? STATE_DATA : STATE_EOF; 322 break; 323 case STATE_DATA: 324 ts->chksum += data; 325 ts->buf[ts->idx]= data; 326 if (++ts->idx == ts->len) 327 state = STATE_EOF; 328 break; 329 case STATE_EOF: 330 state = STATE_SOF; 331 if (data == CHAR_EOF || data == ts->chksum) 332 h3600ts_process_packet(ts); 333 break; 334 default: 335 printk("Error3\n"); 336 break; 337 } 338 339 return IRQ_HANDLED; 340} 341 342/* 343 * h3600ts_connect() is the routine that is called when someone adds a 344 * new serio device that supports H3600 protocol and registers it as 345 * an input device. 346 */ 347static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) 348{ 349 struct h3600_dev *ts; 350 struct input_dev *input_dev; 351 int err; 352 353 ts = kzalloc(sizeof(struct h3600_dev), GFP_KERNEL); 354 input_dev = input_allocate_device(); 355 if (!ts || !input_dev) { 356 err = -ENOMEM; 357 goto fail1; 358 } 359 360 ts->serio = serio; 361 ts->dev = input_dev; 362 snprintf(ts->phys, sizeof(ts->phys), "%s/input0", serio->phys); 363 364 input_dev->name = "H3600 TouchScreen"; 365 input_dev->phys = ts->phys; 366 input_dev->id.bustype = BUS_RS232; 367 input_dev->id.vendor = SERIO_H3600; 368 input_dev->id.product = 0x0666; /* FIXME !!! We can ask the hardware */ 369 input_dev->id.version = 0x0100; 370 input_dev->dev.parent = &serio->dev; 371 372 input_set_drvdata(input_dev, ts); 373 374 input_dev->event = h3600ts_event; 375 376 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_LED) | BIT(EV_PWR); 377 input_dev->ledbit[0] = BIT(LED_SLEEP); 378 input_set_abs_params(input_dev, ABS_X, 60, 985, 0, 0); 379 input_set_abs_params(input_dev, ABS_Y, 35, 1024, 0, 0); 380 381 set_bit(KEY_RECORD, input_dev->keybit); 382 set_bit(KEY_Q, input_dev->keybit); 383 set_bit(KEY_PROG1, input_dev->keybit); 384 set_bit(KEY_PROG2, input_dev->keybit); 385 set_bit(KEY_PROG3, input_dev->keybit); 386 set_bit(KEY_UP, input_dev->keybit); 387 set_bit(KEY_RIGHT, input_dev->keybit); 388 set_bit(KEY_LEFT, input_dev->keybit); 389 set_bit(KEY_DOWN, input_dev->keybit); 390 set_bit(KEY_ENTER, input_dev->keybit); 391 set_bit(KEY_SUSPEND, input_dev->keybit); 392 set_bit(BTN_TOUCH, input_dev->keybit); 393 394 /* Device specific stuff */ 395 set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); 396 set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); 397 398 if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, 399 IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) { 400 printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); 401 err = -EBUSY; 402 goto fail2; 403 } 404 405 if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, 406 IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) { 407 printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); 408 err = -EBUSY; 409 goto fail3; 410 } 411 412 serio_set_drvdata(serio, ts); 413 414 err = serio_open(serio, drv); 415 if (err) 416 return err; 417 418 //h3600_flite_control(1, 25); /* default brightness */ 419 input_register_device(ts->dev); 420 421 return 0; 422 423fail3: free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev); 424fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev); 425fail1: serio_set_drvdata(serio, NULL); 426 input_free_device(input_dev); 427 kfree(ts); 428 return err; 429} 430 431/* 432 * h3600ts_disconnect() is the opposite of h3600ts_connect() 433 */ 434 435static void h3600ts_disconnect(struct serio *serio) 436{ 437 struct h3600_dev *ts = serio_get_drvdata(serio); 438 439 free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); 440 free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev); 441 input_get_device(ts->dev); 442 input_unregister_device(ts->dev); 443 serio_close(serio); 444 serio_set_drvdata(serio, NULL); 445 input_put_device(ts->dev); 446 kfree(ts); 447} 448 449/* 450 * The serio driver structure. 451 */ 452 453static struct serio_device_id h3600ts_serio_ids[] = { 454 { 455 .type = SERIO_RS232, 456 .proto = SERIO_H3600, 457 .id = SERIO_ANY, 458 .extra = SERIO_ANY, 459 }, 460 { 0 } 461}; 462 463MODULE_DEVICE_TABLE(serio, h3600ts_serio_ids); 464 465static struct serio_driver h3600ts_drv = { 466 .driver = { 467 .name = "h3600ts", 468 }, 469 .description = DRIVER_DESC, 470 .id_table = h3600ts_serio_ids, 471 .interrupt = h3600ts_interrupt, 472 .connect = h3600ts_connect, 473 .disconnect = h3600ts_disconnect, 474}; 475 476/* 477 * The functions for inserting/removing us as a module. 478 */ 479 480static int __init h3600ts_init(void) 481{ 482 return serio_register_driver(&h3600ts_drv); 483} 484 485static void __exit h3600ts_exit(void) 486{ 487 serio_unregister_driver(&h3600ts_drv); 488} 489 490module_init(h3600ts_init); 491module_exit(h3600ts_exit);