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