1a5f523bcSTias Guns /* 2a5f523bcSTias Guns * Dynapro serial touchscreen driver 3a5f523bcSTias Guns * 4a5f523bcSTias Guns * Copyright (c) 2009 Tias Guns 5a5f523bcSTias Guns * Based on the inexio driver (c) Vojtech Pavlik and Dan Streetman and 6a5f523bcSTias Guns * Richard Lemon 7a5f523bcSTias Guns * 8a5f523bcSTias Guns */ 9a5f523bcSTias Guns 10a5f523bcSTias Guns /* 11a5f523bcSTias Guns * This program is free software; you can redistribute it and/or modify it 12a5f523bcSTias Guns * under the terms of the GNU General Public License version 2 as published by 13a5f523bcSTias Guns * the Free Software Foundation. 14a5f523bcSTias Guns */ 15a5f523bcSTias Guns 16a5f523bcSTias Guns /* 17a5f523bcSTias Guns * 2009/09/19 Tias Guns <tias@ulyssis.org> 18a5f523bcSTias Guns * Copied inexio.c and edited for Dynapro protocol (from retired Xorg module) 19a5f523bcSTias Guns */ 20a5f523bcSTias Guns 21a5f523bcSTias Guns #include <linux/errno.h> 22a5f523bcSTias Guns #include <linux/kernel.h> 23a5f523bcSTias Guns #include <linux/module.h> 24a5f523bcSTias Guns #include <linux/slab.h> 25a5f523bcSTias Guns #include <linux/input.h> 26a5f523bcSTias Guns #include <linux/serio.h> 27a5f523bcSTias Guns #include <linux/init.h> 28a5f523bcSTias Guns 29a5f523bcSTias Guns #define DRIVER_DESC "Dynapro serial touchscreen driver" 30a5f523bcSTias Guns 31a5f523bcSTias Guns MODULE_AUTHOR("Tias Guns <tias@ulyssis.org>"); 32a5f523bcSTias Guns MODULE_DESCRIPTION(DRIVER_DESC); 33a5f523bcSTias Guns MODULE_LICENSE("GPL"); 34a5f523bcSTias Guns 35a5f523bcSTias Guns /* 36a5f523bcSTias Guns * Definitions & global arrays. 37a5f523bcSTias Guns */ 38a5f523bcSTias Guns 39a5f523bcSTias Guns #define DYNAPRO_FORMAT_TOUCH_BIT 0x40 40a5f523bcSTias Guns #define DYNAPRO_FORMAT_LENGTH 3 41a5f523bcSTias Guns #define DYNAPRO_RESPONSE_BEGIN_BYTE 0x80 42a5f523bcSTias Guns 43a5f523bcSTias Guns #define DYNAPRO_MIN_XC 0 44a5f523bcSTias Guns #define DYNAPRO_MAX_XC 0x3ff 45a5f523bcSTias Guns #define DYNAPRO_MIN_YC 0 46a5f523bcSTias Guns #define DYNAPRO_MAX_YC 0x3ff 47a5f523bcSTias Guns 48a5f523bcSTias Guns #define DYNAPRO_GET_XC(data) (data[1] | ((data[0] & 0x38) << 4)) 49a5f523bcSTias Guns #define DYNAPRO_GET_YC(data) (data[2] | ((data[0] & 0x07) << 7)) 50a5f523bcSTias Guns #define DYNAPRO_GET_TOUCHED(data) (DYNAPRO_FORMAT_TOUCH_BIT & data[0]) 51a5f523bcSTias Guns 52a5f523bcSTias Guns /* 53a5f523bcSTias Guns * Per-touchscreen data. 54a5f523bcSTias Guns */ 55a5f523bcSTias Guns 56a5f523bcSTias Guns struct dynapro { 57a5f523bcSTias Guns struct input_dev *dev; 58a5f523bcSTias Guns struct serio *serio; 59a5f523bcSTias Guns int idx; 60a5f523bcSTias Guns unsigned char data[DYNAPRO_FORMAT_LENGTH]; 61a5f523bcSTias Guns char phys[32]; 62a5f523bcSTias Guns }; 63a5f523bcSTias Guns 64a5f523bcSTias Guns static void dynapro_process_data(struct dynapro *pdynapro) 65a5f523bcSTias Guns { 66a5f523bcSTias Guns struct input_dev *dev = pdynapro->dev; 67a5f523bcSTias Guns 68a5f523bcSTias Guns if (DYNAPRO_FORMAT_LENGTH == ++pdynapro->idx) { 69a5f523bcSTias Guns input_report_abs(dev, ABS_X, DYNAPRO_GET_XC(pdynapro->data)); 70a5f523bcSTias Guns input_report_abs(dev, ABS_Y, DYNAPRO_GET_YC(pdynapro->data)); 71a5f523bcSTias Guns input_report_key(dev, BTN_TOUCH, 72a5f523bcSTias Guns DYNAPRO_GET_TOUCHED(pdynapro->data)); 73a5f523bcSTias Guns input_sync(dev); 74a5f523bcSTias Guns 75a5f523bcSTias Guns pdynapro->idx = 0; 76a5f523bcSTias Guns } 77a5f523bcSTias Guns } 78a5f523bcSTias Guns 79a5f523bcSTias Guns static irqreturn_t dynapro_interrupt(struct serio *serio, 80a5f523bcSTias Guns unsigned char data, unsigned int flags) 81a5f523bcSTias Guns { 82a5f523bcSTias Guns struct dynapro *pdynapro = serio_get_drvdata(serio); 83a5f523bcSTias Guns 84a5f523bcSTias Guns pdynapro->data[pdynapro->idx] = data; 85a5f523bcSTias Guns 86a5f523bcSTias Guns if (DYNAPRO_RESPONSE_BEGIN_BYTE & pdynapro->data[0]) 87a5f523bcSTias Guns dynapro_process_data(pdynapro); 88a5f523bcSTias Guns else 89a5f523bcSTias Guns dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n", 90a5f523bcSTias Guns pdynapro->data[0]); 91a5f523bcSTias Guns 92a5f523bcSTias Guns return IRQ_HANDLED; 93a5f523bcSTias Guns } 94a5f523bcSTias Guns 95a5f523bcSTias Guns static void dynapro_disconnect(struct serio *serio) 96a5f523bcSTias Guns { 97a5f523bcSTias Guns struct dynapro *pdynapro = serio_get_drvdata(serio); 98a5f523bcSTias Guns 99a5f523bcSTias Guns input_get_device(pdynapro->dev); 100a5f523bcSTias Guns input_unregister_device(pdynapro->dev); 101a5f523bcSTias Guns serio_close(serio); 102a5f523bcSTias Guns serio_set_drvdata(serio, NULL); 103a5f523bcSTias Guns input_put_device(pdynapro->dev); 104a5f523bcSTias Guns kfree(pdynapro); 105a5f523bcSTias Guns } 106a5f523bcSTias Guns 107a5f523bcSTias Guns /* 108a5f523bcSTias Guns * dynapro_connect() is the routine that is called when someone adds a 109a5f523bcSTias Guns * new serio device that supports dynapro protocol and registers it as 110a5f523bcSTias Guns * an input device. This is usually accomplished using inputattach. 111a5f523bcSTias Guns */ 112a5f523bcSTias Guns 113a5f523bcSTias Guns static int dynapro_connect(struct serio *serio, struct serio_driver *drv) 114a5f523bcSTias Guns { 115a5f523bcSTias Guns struct dynapro *pdynapro; 116a5f523bcSTias Guns struct input_dev *input_dev; 117a5f523bcSTias Guns int err; 118a5f523bcSTias Guns 119a5f523bcSTias Guns pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL); 120a5f523bcSTias Guns input_dev = input_allocate_device(); 121a5f523bcSTias Guns if (!pdynapro || !input_dev) { 122a5f523bcSTias Guns err = -ENOMEM; 123a5f523bcSTias Guns goto fail1; 124a5f523bcSTias Guns } 125a5f523bcSTias Guns 126a5f523bcSTias Guns pdynapro->serio = serio; 127a5f523bcSTias Guns pdynapro->dev = input_dev; 128a5f523bcSTias Guns snprintf(pdynapro->phys, sizeof(pdynapro->phys), 129a5f523bcSTias Guns "%s/input0", serio->phys); 130a5f523bcSTias Guns 131a5f523bcSTias Guns input_dev->name = "Dynapro Serial TouchScreen"; 132a5f523bcSTias Guns input_dev->phys = pdynapro->phys; 133a5f523bcSTias Guns input_dev->id.bustype = BUS_RS232; 134a5f523bcSTias Guns input_dev->id.vendor = SERIO_DYNAPRO; 135a5f523bcSTias Guns input_dev->id.product = 0; 136a5f523bcSTias Guns input_dev->id.version = 0x0001; 137a5f523bcSTias Guns input_dev->dev.parent = &serio->dev; 138a5f523bcSTias Guns input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 139a5f523bcSTias Guns input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 140a5f523bcSTias Guns input_set_abs_params(pdynapro->dev, ABS_X, 141a5f523bcSTias Guns DYNAPRO_MIN_XC, DYNAPRO_MAX_XC, 0, 0); 142a5f523bcSTias Guns input_set_abs_params(pdynapro->dev, ABS_Y, 143a5f523bcSTias Guns DYNAPRO_MIN_YC, DYNAPRO_MAX_YC, 0, 0); 144a5f523bcSTias Guns 145a5f523bcSTias Guns serio_set_drvdata(serio, pdynapro); 146a5f523bcSTias Guns 147a5f523bcSTias Guns err = serio_open(serio, drv); 148a5f523bcSTias Guns if (err) 149a5f523bcSTias Guns goto fail2; 150a5f523bcSTias Guns 151a5f523bcSTias Guns err = input_register_device(pdynapro->dev); 152a5f523bcSTias Guns if (err) 153a5f523bcSTias Guns goto fail3; 154a5f523bcSTias Guns 155a5f523bcSTias Guns return 0; 156a5f523bcSTias Guns 157a5f523bcSTias Guns fail3: serio_close(serio); 158a5f523bcSTias Guns fail2: serio_set_drvdata(serio, NULL); 159a5f523bcSTias Guns fail1: input_free_device(input_dev); 160a5f523bcSTias Guns kfree(pdynapro); 161a5f523bcSTias Guns return err; 162a5f523bcSTias Guns } 163a5f523bcSTias Guns 164a5f523bcSTias Guns /* 165a5f523bcSTias Guns * The serio driver structure. 166a5f523bcSTias Guns */ 167a5f523bcSTias Guns 168a5f523bcSTias Guns static struct serio_device_id dynapro_serio_ids[] = { 169a5f523bcSTias Guns { 170a5f523bcSTias Guns .type = SERIO_RS232, 171a5f523bcSTias Guns .proto = SERIO_DYNAPRO, 172a5f523bcSTias Guns .id = SERIO_ANY, 173a5f523bcSTias Guns .extra = SERIO_ANY, 174a5f523bcSTias Guns }, 175a5f523bcSTias Guns { 0 } 176a5f523bcSTias Guns }; 177a5f523bcSTias Guns 178a5f523bcSTias Guns MODULE_DEVICE_TABLE(serio, dynapro_serio_ids); 179a5f523bcSTias Guns 180a5f523bcSTias Guns static struct serio_driver dynapro_drv = { 181a5f523bcSTias Guns .driver = { 182a5f523bcSTias Guns .name = "dynapro", 183a5f523bcSTias Guns }, 184a5f523bcSTias Guns .description = DRIVER_DESC, 185a5f523bcSTias Guns .id_table = dynapro_serio_ids, 186a5f523bcSTias Guns .interrupt = dynapro_interrupt, 187a5f523bcSTias Guns .connect = dynapro_connect, 188a5f523bcSTias Guns .disconnect = dynapro_disconnect, 189a5f523bcSTias Guns }; 190a5f523bcSTias Guns 19165ac9f7aSAxel Lin module_serio_driver(dynapro_drv); 192