Path: blob/master/drivers/input/touchscreen/penmount.c
15111 views
/*1* Penmount serial touchscreen driver2*3* Copyright (c) 2006 Rick Koch <[email protected]>4*5* Based on ELO driver (drivers/input/touchscreen/elo.c)6* Copyright (c) 2004 Vojtech Pavlik7*/89/*10* This program is free software; you can redistribute it and/or modify it11* under the terms of the GNU General Public License version 2 as published12* by the Free Software Foundation.13*/1415#include <linux/errno.h>16#include <linux/kernel.h>17#include <linux/module.h>18#include <linux/slab.h>19#include <linux/input.h>20#include <linux/serio.h>21#include <linux/init.h>2223#define DRIVER_DESC "Penmount serial touchscreen driver"2425MODULE_AUTHOR("Rick Koch <[email protected]>");26MODULE_DESCRIPTION(DRIVER_DESC);27MODULE_LICENSE("GPL");2829/*30* Definitions & global arrays.31*/3233#define PM_MAX_LENGTH 53435/*36* Per-touchscreen data.37*/3839struct pm {40struct input_dev *dev;41struct serio *serio;42int idx;43unsigned char data[PM_MAX_LENGTH];44char phys[32];45};4647static irqreturn_t pm_interrupt(struct serio *serio,48unsigned char data, unsigned int flags)49{50struct pm *pm = serio_get_drvdata(serio);51struct input_dev *dev = pm->dev;5253pm->data[pm->idx] = data;5455if (pm->data[0] & 0x80) {56if (PM_MAX_LENGTH == ++pm->idx) {57input_report_abs(dev, ABS_X, pm->data[2] * 128 + pm->data[1]);58input_report_abs(dev, ABS_Y, pm->data[4] * 128 + pm->data[3]);59input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));60input_sync(dev);61pm->idx = 0;62}63}6465return IRQ_HANDLED;66}6768/*69* pm_disconnect() is the opposite of pm_connect()70*/7172static void pm_disconnect(struct serio *serio)73{74struct pm *pm = serio_get_drvdata(serio);7576input_get_device(pm->dev);77input_unregister_device(pm->dev);78serio_close(serio);79serio_set_drvdata(serio, NULL);80input_put_device(pm->dev);81kfree(pm);82}8384/*85* pm_connect() is the routine that is called when someone adds a86* new serio device that supports Gunze protocol and registers it as87* an input device.88*/8990static int pm_connect(struct serio *serio, struct serio_driver *drv)91{92struct pm *pm;93struct input_dev *input_dev;94int err;9596pm = kzalloc(sizeof(struct pm), GFP_KERNEL);97input_dev = input_allocate_device();98if (!pm || !input_dev) {99err = -ENOMEM;100goto fail1;101}102103pm->serio = serio;104pm->dev = input_dev;105snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);106107input_dev->name = "Penmount Serial TouchScreen";108input_dev->phys = pm->phys;109input_dev->id.bustype = BUS_RS232;110input_dev->id.vendor = SERIO_PENMOUNT;111input_dev->id.product = 0;112input_dev->id.version = 0x0100;113input_dev->dev.parent = &serio->dev;114115input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);116input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);117input_set_abs_params(pm->dev, ABS_X, 0, 0x3ff, 0, 0);118input_set_abs_params(pm->dev, ABS_Y, 0, 0x3ff, 0, 0);119120serio_set_drvdata(serio, pm);121122err = serio_open(serio, drv);123if (err)124goto fail2;125126err = input_register_device(pm->dev);127if (err)128goto fail3;129130return 0;131132fail3: serio_close(serio);133fail2: serio_set_drvdata(serio, NULL);134fail1: input_free_device(input_dev);135kfree(pm);136return err;137}138139/*140* The serio driver structure.141*/142143static struct serio_device_id pm_serio_ids[] = {144{145.type = SERIO_RS232,146.proto = SERIO_PENMOUNT,147.id = SERIO_ANY,148.extra = SERIO_ANY,149},150{ 0 }151};152153MODULE_DEVICE_TABLE(serio, pm_serio_ids);154155static struct serio_driver pm_drv = {156.driver = {157.name = "penmountlpc",158},159.description = DRIVER_DESC,160.id_table = pm_serio_ids,161.interrupt = pm_interrupt,162.connect = pm_connect,163.disconnect = pm_disconnect,164};165166/*167* The functions for inserting/removing us as a module.168*/169170static int __init pm_init(void)171{172return serio_register_driver(&pm_drv);173}174175static void __exit pm_exit(void)176{177serio_unregister_driver(&pm_drv);178}179180module_init(pm_init);181module_exit(pm_exit);182183184