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