Path: blob/master/drivers/input/touchscreen/touchwin.c
15109 views
/*1* Touchwindow serial touchscreen driver2*3* Copyright (c) 2006 Rick Koch <[email protected]>4*5* Based on MicroTouch driver (drivers/input/touchscreen/mtouch.c)6* Copyright (c) 2004 Vojtech Pavlik7* and Dan Streetman <[email protected]>8*/910/*11* This program is free software; you can redistribute it and/or modify it12* under the terms of the GNU General Public License version 2 as published13* by the Free Software Foundation.14*/1516/*17* 2005/02/19 Rick Koch:18* The Touchwindow I used is made by Edmark Corp. and19* constantly outputs a stream of 0's unless it is touched.20* It then outputs 3 bytes: X, Y, and a copy of Y.21*/2223#include <linux/errno.h>24#include <linux/kernel.h>25#include <linux/module.h>26#include <linux/slab.h>27#include <linux/input.h>28#include <linux/serio.h>29#include <linux/init.h>3031#define DRIVER_DESC "Touchwindow serial touchscreen driver"3233MODULE_AUTHOR("Rick Koch <[email protected]>");34MODULE_DESCRIPTION(DRIVER_DESC);35MODULE_LICENSE("GPL");3637/*38* Definitions & global arrays.39*/4041#define TW_LENGTH 34243#define TW_MIN_XC 044#define TW_MAX_XC 0xff45#define TW_MIN_YC 046#define TW_MAX_YC 0xff4748/*49* Per-touchscreen data.50*/5152struct tw {53struct input_dev *dev;54struct serio *serio;55int idx;56int touched;57unsigned char data[TW_LENGTH];58char phys[32];59};6061static irqreturn_t tw_interrupt(struct serio *serio,62unsigned char data, unsigned int flags)63{64struct tw *tw = serio_get_drvdata(serio);65struct input_dev *dev = tw->dev;6667if (data) { /* touch */68tw->touched = 1;69tw->data[tw->idx++] = data;70/* verify length and that the two Y's are the same */71if (tw->idx == TW_LENGTH && tw->data[1] == tw->data[2]) {72input_report_abs(dev, ABS_X, tw->data[0]);73input_report_abs(dev, ABS_Y, tw->data[1]);74input_report_key(dev, BTN_TOUCH, 1);75input_sync(dev);76tw->idx = 0;77}78} else if (tw->touched) { /* untouch */79input_report_key(dev, BTN_TOUCH, 0);80input_sync(dev);81tw->idx = 0;82tw->touched = 0;83}8485return IRQ_HANDLED;86}8788/*89* tw_disconnect() is the opposite of tw_connect()90*/9192static void tw_disconnect(struct serio *serio)93{94struct tw *tw = serio_get_drvdata(serio);9596input_get_device(tw->dev);97input_unregister_device(tw->dev);98serio_close(serio);99serio_set_drvdata(serio, NULL);100input_put_device(tw->dev);101kfree(tw);102}103104/*105* tw_connect() is the routine that is called when someone adds a106* new serio device that supports the Touchwin protocol and registers it as107* an input device.108*/109110static int tw_connect(struct serio *serio, struct serio_driver *drv)111{112struct tw *tw;113struct input_dev *input_dev;114int err;115116tw = kzalloc(sizeof(struct tw), GFP_KERNEL);117input_dev = input_allocate_device();118if (!tw || !input_dev) {119err = -ENOMEM;120goto fail1;121}122123tw->serio = serio;124tw->dev = input_dev;125snprintf(tw->phys, sizeof(tw->phys), "%s/input0", serio->phys);126127input_dev->name = "Touchwindow Serial TouchScreen";128input_dev->phys = tw->phys;129input_dev->id.bustype = BUS_RS232;130input_dev->id.vendor = SERIO_TOUCHWIN;131input_dev->id.product = 0;132input_dev->id.version = 0x0100;133input_dev->dev.parent = &serio->dev;134input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);135input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);136input_set_abs_params(tw->dev, ABS_X, TW_MIN_XC, TW_MAX_XC, 0, 0);137input_set_abs_params(tw->dev, ABS_Y, TW_MIN_YC, TW_MAX_YC, 0, 0);138139serio_set_drvdata(serio, tw);140141err = serio_open(serio, drv);142if (err)143goto fail2;144145err = input_register_device(tw->dev);146if (err)147goto fail3;148149return 0;150151fail3: serio_close(serio);152fail2: serio_set_drvdata(serio, NULL);153fail1: input_free_device(input_dev);154kfree(tw);155return err;156}157158/*159* The serio driver structure.160*/161162static struct serio_device_id tw_serio_ids[] = {163{164.type = SERIO_RS232,165.proto = SERIO_TOUCHWIN,166.id = SERIO_ANY,167.extra = SERIO_ANY,168},169{ 0 }170};171172MODULE_DEVICE_TABLE(serio, tw_serio_ids);173174static struct serio_driver tw_drv = {175.driver = {176.name = "touchwin",177},178.description = DRIVER_DESC,179.id_table = tw_serio_ids,180.interrupt = tw_interrupt,181.connect = tw_connect,182.disconnect = tw_disconnect,183};184185/*186* The functions for inserting/removing us as a module.187*/188189static int __init tw_init(void)190{191return serio_register_driver(&tw_drv);192}193194static void __exit tw_exit(void)195{196serio_unregister_driver(&tw_drv);197}198199module_init(tw_init);200module_exit(tw_exit);201202203