Path: blob/master/drivers/input/touchscreen/dynapro.c
15109 views
/*1* Dynapro serial touchscreen driver2*3* Copyright (c) 2009 Tias Guns4* Based on the inexio driver (c) Vojtech Pavlik and Dan Streetman and5* Richard Lemon6*7*/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 published by12* the Free Software Foundation.13*/1415/*16* 2009/09/19 Tias Guns <[email protected]>17* Copied inexio.c and edited for Dynapro protocol (from retired Xorg module)18*/1920#include <linux/errno.h>21#include <linux/kernel.h>22#include <linux/module.h>23#include <linux/slab.h>24#include <linux/input.h>25#include <linux/serio.h>26#include <linux/init.h>2728#define DRIVER_DESC "Dynapro serial touchscreen driver"2930MODULE_AUTHOR("Tias Guns <[email protected]>");31MODULE_DESCRIPTION(DRIVER_DESC);32MODULE_LICENSE("GPL");3334/*35* Definitions & global arrays.36*/3738#define DYNAPRO_FORMAT_TOUCH_BIT 0x4039#define DYNAPRO_FORMAT_LENGTH 340#define DYNAPRO_RESPONSE_BEGIN_BYTE 0x804142#define DYNAPRO_MIN_XC 043#define DYNAPRO_MAX_XC 0x3ff44#define DYNAPRO_MIN_YC 045#define DYNAPRO_MAX_YC 0x3ff4647#define DYNAPRO_GET_XC(data) (data[1] | ((data[0] & 0x38) << 4))48#define DYNAPRO_GET_YC(data) (data[2] | ((data[0] & 0x07) << 7))49#define DYNAPRO_GET_TOUCHED(data) (DYNAPRO_FORMAT_TOUCH_BIT & data[0])5051/*52* Per-touchscreen data.53*/5455struct dynapro {56struct input_dev *dev;57struct serio *serio;58int idx;59unsigned char data[DYNAPRO_FORMAT_LENGTH];60char phys[32];61};6263static void dynapro_process_data(struct dynapro *pdynapro)64{65struct input_dev *dev = pdynapro->dev;6667if (DYNAPRO_FORMAT_LENGTH == ++pdynapro->idx) {68input_report_abs(dev, ABS_X, DYNAPRO_GET_XC(pdynapro->data));69input_report_abs(dev, ABS_Y, DYNAPRO_GET_YC(pdynapro->data));70input_report_key(dev, BTN_TOUCH,71DYNAPRO_GET_TOUCHED(pdynapro->data));72input_sync(dev);7374pdynapro->idx = 0;75}76}7778static irqreturn_t dynapro_interrupt(struct serio *serio,79unsigned char data, unsigned int flags)80{81struct dynapro *pdynapro = serio_get_drvdata(serio);8283pdynapro->data[pdynapro->idx] = data;8485if (DYNAPRO_RESPONSE_BEGIN_BYTE & pdynapro->data[0])86dynapro_process_data(pdynapro);87else88dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n",89pdynapro->data[0]);9091return IRQ_HANDLED;92}9394static void dynapro_disconnect(struct serio *serio)95{96struct dynapro *pdynapro = serio_get_drvdata(serio);9798input_get_device(pdynapro->dev);99input_unregister_device(pdynapro->dev);100serio_close(serio);101serio_set_drvdata(serio, NULL);102input_put_device(pdynapro->dev);103kfree(pdynapro);104}105106/*107* dynapro_connect() is the routine that is called when someone adds a108* new serio device that supports dynapro protocol and registers it as109* an input device. This is usually accomplished using inputattach.110*/111112static int dynapro_connect(struct serio *serio, struct serio_driver *drv)113{114struct dynapro *pdynapro;115struct input_dev *input_dev;116int err;117118pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL);119input_dev = input_allocate_device();120if (!pdynapro || !input_dev) {121err = -ENOMEM;122goto fail1;123}124125pdynapro->serio = serio;126pdynapro->dev = input_dev;127snprintf(pdynapro->phys, sizeof(pdynapro->phys),128"%s/input0", serio->phys);129130input_dev->name = "Dynapro Serial TouchScreen";131input_dev->phys = pdynapro->phys;132input_dev->id.bustype = BUS_RS232;133input_dev->id.vendor = SERIO_DYNAPRO;134input_dev->id.product = 0;135input_dev->id.version = 0x0001;136input_dev->dev.parent = &serio->dev;137input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);138input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);139input_set_abs_params(pdynapro->dev, ABS_X,140DYNAPRO_MIN_XC, DYNAPRO_MAX_XC, 0, 0);141input_set_abs_params(pdynapro->dev, ABS_Y,142DYNAPRO_MIN_YC, DYNAPRO_MAX_YC, 0, 0);143144serio_set_drvdata(serio, pdynapro);145146err = serio_open(serio, drv);147if (err)148goto fail2;149150err = input_register_device(pdynapro->dev);151if (err)152goto fail3;153154return 0;155156fail3: serio_close(serio);157fail2: serio_set_drvdata(serio, NULL);158fail1: input_free_device(input_dev);159kfree(pdynapro);160return err;161}162163/*164* The serio driver structure.165*/166167static struct serio_device_id dynapro_serio_ids[] = {168{169.type = SERIO_RS232,170.proto = SERIO_DYNAPRO,171.id = SERIO_ANY,172.extra = SERIO_ANY,173},174{ 0 }175};176177MODULE_DEVICE_TABLE(serio, dynapro_serio_ids);178179static struct serio_driver dynapro_drv = {180.driver = {181.name = "dynapro",182},183.description = DRIVER_DESC,184.id_table = dynapro_serio_ids,185.interrupt = dynapro_interrupt,186.connect = dynapro_connect,187.disconnect = dynapro_disconnect,188};189190/*191* The functions for inserting/removing us as a module.192*/193194static int __init dynapro_init(void)195{196return serio_register_driver(&dynapro_drv);197}198199static void __exit dynapro_exit(void)200{201serio_unregister_driver(&dynapro_drv);202}203204module_init(dynapro_init);205module_exit(dynapro_exit);206207208