Path: blob/master/drivers/input/touchscreen/fujitsu_ts.c
15111 views
/*1* Fujitsu serial touchscreen driver2*3* Copyright (c) Dmitry Torokhov <[email protected]>4*/56/*7* This program is free software; you can redistribute it and/or modify it8* under the terms of the GNU General Public License version 2 as published9* by the Free Software Foundation.10*/1112#include <linux/errno.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/slab.h>16#include <linux/input.h>17#include <linux/serio.h>18#include <linux/init.h>1920#define DRIVER_DESC "Fujitsu serial touchscreen driver"2122MODULE_AUTHOR("Dmitry Torokhov <[email protected]>");23MODULE_DESCRIPTION(DRIVER_DESC);24MODULE_LICENSE("GPL");2526#define FUJITSU_LENGTH 52728/*29* Per-touchscreen data.30*/31struct fujitsu {32struct input_dev *dev;33struct serio *serio;34int idx;35unsigned char data[FUJITSU_LENGTH];36char phys[32];37};3839/*40* Decode serial data (5 bytes per packet)41* First byte42* 1 C 0 0 R S S S43* 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 state46*/47static irqreturn_t fujitsu_interrupt(struct serio *serio,48unsigned char data, unsigned int flags)49{50struct fujitsu *fujitsu = serio_get_drvdata(serio);51struct input_dev *dev = fujitsu->dev;5253if (fujitsu->idx == 0) {54/* resync skip until start of frame */55if ((data & 0xf0) != 0x80)56return IRQ_HANDLED;57} else {58/* resync skip garbage */59if (data & 0x80) {60fujitsu->idx = 0;61return IRQ_HANDLED;62}63}6465fujitsu->data[fujitsu->idx++] = data;66if (fujitsu->idx == FUJITSU_LENGTH) {67input_report_abs(dev, ABS_X,68(fujitsu->data[2] << 7) | fujitsu->data[1]);69input_report_abs(dev, ABS_Y,70(fujitsu->data[4] << 7) | fujitsu->data[3]);71input_report_key(dev, BTN_TOUCH,72(fujitsu->data[0] & 0x03) != 2);73input_sync(dev);74fujitsu->idx = 0;75}7677return IRQ_HANDLED;78}7980/*81* fujitsu_disconnect() is the opposite of fujitsu_connect()82*/83static void fujitsu_disconnect(struct serio *serio)84{85struct fujitsu *fujitsu = serio_get_drvdata(serio);8687input_get_device(fujitsu->dev);88input_unregister_device(fujitsu->dev);89serio_close(serio);90serio_set_drvdata(serio, NULL);91input_put_device(fujitsu->dev);92kfree(fujitsu);93}9495/*96* fujitsu_connect() is the routine that is called when someone adds a97* new serio device that supports the Fujitsu protocol and registers it98* as input device.99*/100static int fujitsu_connect(struct serio *serio, struct serio_driver *drv)101{102struct fujitsu *fujitsu;103struct input_dev *input_dev;104int err;105106fujitsu = kzalloc(sizeof(struct fujitsu), GFP_KERNEL);107input_dev = input_allocate_device();108if (!fujitsu || !input_dev) {109err = -ENOMEM;110goto fail1;111}112113fujitsu->serio = serio;114fujitsu->dev = input_dev;115snprintf(fujitsu->phys, sizeof(fujitsu->phys),116"%s/input0", serio->phys);117118input_dev->name = "Fujitsu Serial Touchscreen";119input_dev->phys = fujitsu->phys;120input_dev->id.bustype = BUS_RS232;121input_dev->id.vendor = SERIO_FUJITSU;122input_dev->id.product = 0;123input_dev->id.version = 0x0100;124input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);125input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);126127input_set_abs_params(input_dev, ABS_X, 0, 4096, 0, 0);128input_set_abs_params(input_dev, ABS_Y, 0, 4096, 0, 0);129serio_set_drvdata(serio, fujitsu);130131err = serio_open(serio, drv);132if (err)133goto fail2;134135err = input_register_device(fujitsu->dev);136if (err)137goto fail3;138139return 0;140141fail3:142serio_close(serio);143fail2:144serio_set_drvdata(serio, NULL);145fail1:146input_free_device(input_dev);147kfree(fujitsu);148return err;149}150151/*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};163164MODULE_DEVICE_TABLE(serio, fujitsu_serio_ids);165166static 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};176177static int __init fujitsu_init(void)178{179return serio_register_driver(&fujitsu_drv);180}181182static void __exit fujitsu_exit(void)183{184serio_unregister_driver(&fujitsu_drv);185}186187module_init(fujitsu_init);188module_exit(fujitsu_exit);189190191