Path: blob/master/drivers/input/touchscreen/mtouch.c
15109 views
/*1* MicroTouch (3M) serial touchscreen driver2*3* Copyright (c) 2004 Vojtech Pavlik4*/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 published by9* the Free Software Foundation.10*/1112/*13* 2005/02/19 Dan Streetman <[email protected]>14* Copied elo.c and edited for MicroTouch protocol15*/1617#include <linux/errno.h>18#include <linux/kernel.h>19#include <linux/module.h>20#include <linux/slab.h>21#include <linux/input.h>22#include <linux/serio.h>23#include <linux/init.h>2425#define DRIVER_DESC "MicroTouch serial touchscreen driver"2627MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");28MODULE_DESCRIPTION(DRIVER_DESC);29MODULE_LICENSE("GPL");3031/*32* Definitions & global arrays.33*/3435#define MTOUCH_FORMAT_TABLET_STATUS_BIT 0x8036#define MTOUCH_FORMAT_TABLET_TOUCH_BIT 0x4037#define MTOUCH_FORMAT_TABLET_LENGTH 538#define MTOUCH_RESPONSE_BEGIN_BYTE 0x0139#define MTOUCH_RESPONSE_END_BYTE 0x0d4041/* todo: check specs for max length of all responses */42#define MTOUCH_MAX_LENGTH 164344#define MTOUCH_MIN_XC 045#define MTOUCH_MAX_XC 0x3fff46#define MTOUCH_MIN_YC 047#define MTOUCH_MAX_YC 0x3fff4849#define MTOUCH_GET_XC(data) (((data[2])<<7) | data[1])50#define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3])51#define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0])5253/*54* Per-touchscreen data.55*/5657struct mtouch {58struct input_dev *dev;59struct serio *serio;60int idx;61unsigned char data[MTOUCH_MAX_LENGTH];62char phys[32];63};6465static void mtouch_process_format_tablet(struct mtouch *mtouch)66{67struct input_dev *dev = mtouch->dev;6869if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) {70input_report_abs(dev, ABS_X, MTOUCH_GET_XC(mtouch->data));71input_report_abs(dev, ABS_Y, MTOUCH_MAX_YC - MTOUCH_GET_YC(mtouch->data));72input_report_key(dev, BTN_TOUCH, MTOUCH_GET_TOUCHED(mtouch->data));73input_sync(dev);7475mtouch->idx = 0;76}77}7879static void mtouch_process_response(struct mtouch *mtouch)80{81if (MTOUCH_RESPONSE_END_BYTE == mtouch->data[mtouch->idx++]) {82/* FIXME - process response */83mtouch->idx = 0;84} else if (MTOUCH_MAX_LENGTH == mtouch->idx) {85printk(KERN_ERR "mtouch.c: too many response bytes\n");86mtouch->idx = 0;87}88}8990static irqreturn_t mtouch_interrupt(struct serio *serio,91unsigned char data, unsigned int flags)92{93struct mtouch* mtouch = serio_get_drvdata(serio);9495mtouch->data[mtouch->idx] = data;9697if (MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch->data[0])98mtouch_process_format_tablet(mtouch);99else if (MTOUCH_RESPONSE_BEGIN_BYTE == mtouch->data[0])100mtouch_process_response(mtouch);101else102printk(KERN_DEBUG "mtouch.c: unknown/unsynchronized data from device, byte %x\n",mtouch->data[0]);103104return IRQ_HANDLED;105}106107/*108* mtouch_disconnect() is the opposite of mtouch_connect()109*/110111static void mtouch_disconnect(struct serio *serio)112{113struct mtouch* mtouch = serio_get_drvdata(serio);114115input_get_device(mtouch->dev);116input_unregister_device(mtouch->dev);117serio_close(serio);118serio_set_drvdata(serio, NULL);119input_put_device(mtouch->dev);120kfree(mtouch);121}122123/*124* mtouch_connect() is the routine that is called when someone adds a125* new serio device that supports MicroTouch (Format Tablet) protocol and registers it as126* an input device.127*/128129static int mtouch_connect(struct serio *serio, struct serio_driver *drv)130{131struct mtouch *mtouch;132struct input_dev *input_dev;133int err;134135mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL);136input_dev = input_allocate_device();137if (!mtouch || !input_dev) {138err = -ENOMEM;139goto fail1;140}141142mtouch->serio = serio;143mtouch->dev = input_dev;144snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys);145146input_dev->name = "MicroTouch Serial TouchScreen";147input_dev->phys = mtouch->phys;148input_dev->id.bustype = BUS_RS232;149input_dev->id.vendor = SERIO_MICROTOUCH;150input_dev->id.product = 0;151input_dev->id.version = 0x0100;152input_dev->dev.parent = &serio->dev;153input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);154input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);155input_set_abs_params(mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);156input_set_abs_params(mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);157158serio_set_drvdata(serio, mtouch);159160err = serio_open(serio, drv);161if (err)162goto fail2;163164err = input_register_device(mtouch->dev);165if (err)166goto fail3;167168return 0;169170fail3: serio_close(serio);171fail2: serio_set_drvdata(serio, NULL);172fail1: input_free_device(input_dev);173kfree(mtouch);174return err;175}176177/*178* The serio driver structure.179*/180181static struct serio_device_id mtouch_serio_ids[] = {182{183.type = SERIO_RS232,184.proto = SERIO_MICROTOUCH,185.id = SERIO_ANY,186.extra = SERIO_ANY,187},188{ 0 }189};190191MODULE_DEVICE_TABLE(serio, mtouch_serio_ids);192193static struct serio_driver mtouch_drv = {194.driver = {195.name = "mtouch",196},197.description = DRIVER_DESC,198.id_table = mtouch_serio_ids,199.interrupt = mtouch_interrupt,200.connect = mtouch_connect,201.disconnect = mtouch_disconnect,202};203204/*205* The functions for inserting/removing us as a module.206*/207208static int __init mtouch_init(void)209{210return serio_register_driver(&mtouch_drv);211}212213static void __exit mtouch_exit(void)214{215serio_unregister_driver(&mtouch_drv);216}217218module_init(mtouch_init);219module_exit(mtouch_exit);220221222