linux/drivers/input/touchscreen/fujitsu_ts.c
<<
>>
Prefs
   1/*
   2 * Fujitsu serial touchscreen driver
   3 *
   4 * Copyright (c) Dmitry Torokhov <dtor@mail.ru>
   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
  10 * by the Free Software Foundation.
  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
  20#define DRIVER_DESC     "Fujitsu serial touchscreen driver"
  21
  22MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
  23MODULE_DESCRIPTION(DRIVER_DESC);
  24MODULE_LICENSE("GPL");
  25
  26#define FUJITSU_LENGTH 5
  27
  28/*
  29 * Per-touchscreen data.
  30 */
  31struct fujitsu {
  32        struct input_dev *dev;
  33        struct serio *serio;
  34        int idx;
  35        unsigned char data[FUJITSU_LENGTH];
  36        char phys[32];
  37};
  38
  39/*
  40 * Decode serial data (5 bytes per packet)
  41 * First byte
  42 * 1 C 0 0 R S S S
  43 * Where C is 1 while in calibration mode (which we don't use)
  44 * R is 1 when no coordinate corection was done.
  45 * S are button state
  46 */
  47static irqreturn_t fujitsu_interrupt(struct serio *serio,
  48                                     unsigned char data, unsigned int flags)
  49{
  50        struct fujitsu *fujitsu = serio_get_drvdata(serio);
  51        struct input_dev *dev = fujitsu->dev;
  52
  53        if (fujitsu->idx == 0) {
  54                /* resync skip until start of frame */
  55                if ((data & 0xf0) != 0x80)
  56                        return IRQ_HANDLED;
  57        } else {
  58                /* resync skip garbage */
  59                if (data & 0x80) {
  60                        fujitsu->idx = 0;
  61                        return IRQ_HANDLED;
  62                }
  63        }
  64
  65        fujitsu->data[fujitsu->idx++] = data;
  66        if (fujitsu->idx == FUJITSU_LENGTH) {
  67                input_report_abs(dev, ABS_X,
  68                                 (fujitsu->data[2] << 7) | fujitsu->data[1]);
  69                input_report_abs(dev, ABS_Y,
  70                                 (fujitsu->data[4] << 7) | fujitsu->data[3]);
  71                input_report_key(dev, BTN_TOUCH,
  72                                 (fujitsu->data[0] & 0x03) != 2);
  73                input_sync(dev);
  74                fujitsu->idx = 0;
  75        }
  76
  77        return IRQ_HANDLED;
  78}
  79
  80/*
  81 * fujitsu_disconnect() is the opposite of fujitsu_connect()
  82 */
  83static void fujitsu_disconnect(struct serio *serio)
  84{
  85        struct fujitsu *fujitsu = serio_get_drvdata(serio);
  86
  87        input_get_device(fujitsu->dev);
  88        input_unregister_device(fujitsu->dev);
  89        serio_close(serio);
  90        serio_set_drvdata(serio, NULL);
  91        input_put_device(fujitsu->dev);
  92        kfree(fujitsu);
  93}
  94
  95/*
  96 * fujitsu_connect() is the routine that is called when someone adds a
  97 * new serio device that supports the Fujitsu protocol and registers it
  98 * as input device.
  99 */
 100static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)
 101{
 102        struct fujitsu *fujitsu;
 103        struct input_dev *input_dev;
 104        int err;
 105
 106        fujitsu = kzalloc(sizeof(struct fujitsu), GFP_KERNEL);
 107        input_dev = input_allocate_device();
 108        if (!fujitsu || !input_dev) {
 109                err = -ENOMEM;
 110                goto fail1;
 111        }
 112
 113        fujitsu->serio = serio;
 114        fujitsu->dev = input_dev;
 115        snprintf(fujitsu->phys, sizeof(fujitsu->phys),
 116                 "%s/input0", serio->phys);
 117
 118        input_dev->name = "Fujitsu Serial Touchscreen";
 119        input_dev->phys = fujitsu->phys;
 120        input_dev->id.bustype = BUS_RS232;
 121        input_dev->id.vendor = SERIO_FUJITSU;
 122        input_dev->id.product = 0;
 123        input_dev->id.version = 0x0100;
 124        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 125        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 126
 127        input_set_abs_params(input_dev, ABS_X, 0, 4096, 0, 0);
 128        input_set_abs_params(input_dev, ABS_Y, 0, 4096, 0, 0);
 129        serio_set_drvdata(serio, fujitsu);
 130
 131        err = serio_open(serio, drv);
 132        if (err)
 133                goto fail2;
 134
 135        err = input_register_device(fujitsu->dev);
 136        if (err)
 137                goto fail3;
 138
 139        return 0;
 140
 141 fail3:
 142        serio_close(serio);
 143 fail2:
 144        serio_set_drvdata(serio, NULL);
 145 fail1:
 146        input_free_device(input_dev);
 147        kfree(fujitsu);
 148        return err;
 149}
 150
 151/*
 152 * The serio driver structure.
 153 */
 154static struct serio_device_id fujitsu_serio_ids[] = {
 155        {
 156                .type   = SERIO_RS232,
 157                .proto  = SERIO_FUJITSU,
 158                .id     = SERIO_ANY,
 159                .extra  = SERIO_ANY,
 160        },
 161        { 0 }
 162};
 163
 164MODULE_DEVICE_TABLE(serio, fujitsu_serio_ids);
 165
 166static struct serio_driver fujitsu_drv = {
 167        .driver         = {
 168                .name   = "fujitsu_ts",
 169        },
 170        .description    = DRIVER_DESC,
 171        .id_table       = fujitsu_serio_ids,
 172        .interrupt      = fujitsu_interrupt,
 173        .connect        = fujitsu_connect,
 174        .disconnect     = fujitsu_disconnect,
 175};
 176
 177module_serio_driver(fujitsu_drv);
 178