root/drivers/input/touchscreen/penmount.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pm_mtevent
  2. pm_checkpacket
  3. pm_parse_9000
  4. pm_parse_6000
  5. pm_parse_3000
  6. pm_parse_6250
  7. pm_interrupt
  8. pm_disconnect
  9. pm_connect

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Penmount serial touchscreen driver
   4  *
   5  * Copyright (c) 2006 Rick Koch <n1gp@hotmail.com>
   6  * Copyright (c) 2011 John Sung <penmount.touch@gmail.com>
   7  *
   8  * Based on ELO driver (drivers/input/touchscreen/elo.c)
   9  * Copyright (c) 2004 Vojtech Pavlik
  10  */
  11 
  12 
  13 #include <linux/errno.h>
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/slab.h>
  17 #include <linux/input.h>
  18 #include <linux/input/mt.h>
  19 #include <linux/serio.h>
  20 
  21 #define DRIVER_DESC     "PenMount serial touchscreen driver"
  22 
  23 MODULE_AUTHOR("Rick Koch <n1gp@hotmail.com>");
  24 MODULE_AUTHOR("John Sung <penmount.touch@gmail.com>");
  25 MODULE_DESCRIPTION(DRIVER_DESC);
  26 MODULE_LICENSE("GPL");
  27 
  28 /*
  29  * Definitions & global arrays.
  30  */
  31 
  32 #define PM_MAX_LENGTH   6
  33 #define PM_MAX_MTSLOT   16
  34 #define PM_3000_MTSLOT  2
  35 #define PM_6250_MTSLOT  12
  36 
  37 /*
  38  * Multi-touch slot
  39  */
  40 
  41 struct mt_slot {
  42         unsigned short x, y;
  43         bool active; /* is the touch valid? */
  44 };
  45 
  46 /*
  47  * Per-touchscreen data.
  48  */
  49 
  50 struct pm {
  51         struct input_dev *dev;
  52         struct serio *serio;
  53         int idx;
  54         unsigned char data[PM_MAX_LENGTH];
  55         char phys[32];
  56         unsigned char packetsize;
  57         unsigned char maxcontacts;
  58         struct mt_slot slots[PM_MAX_MTSLOT];
  59         void (*parse_packet)(struct pm *);
  60 };
  61 
  62 /*
  63  * pm_mtevent() sends mt events and also emulates pointer movement
  64  */
  65 
  66 static void pm_mtevent(struct pm *pm, struct input_dev *input)
  67 {
  68         int i;
  69 
  70         for (i = 0; i < pm->maxcontacts; ++i) {
  71                 input_mt_slot(input, i);
  72                 input_mt_report_slot_state(input, MT_TOOL_FINGER,
  73                                 pm->slots[i].active);
  74                 if (pm->slots[i].active) {
  75                         input_event(input, EV_ABS, ABS_MT_POSITION_X, pm->slots[i].x);
  76                         input_event(input, EV_ABS, ABS_MT_POSITION_Y, pm->slots[i].y);
  77                 }
  78         }
  79 
  80         input_mt_report_pointer_emulation(input, true);
  81         input_sync(input);
  82 }
  83 
  84 /*
  85  * pm_checkpacket() checks if data packet is valid
  86  */
  87 
  88 static bool pm_checkpacket(unsigned char *packet)
  89 {
  90         int total = 0;
  91         int i;
  92 
  93         for (i = 0; i < 5; i++)
  94                 total += packet[i];
  95 
  96         return packet[5] == (unsigned char)~(total & 0xff);
  97 }
  98 
  99 static void pm_parse_9000(struct pm *pm)
 100 {
 101         struct input_dev *dev = pm->dev;
 102 
 103         if ((pm->data[0] & 0x80) && pm->packetsize == ++pm->idx) {
 104                 input_report_abs(dev, ABS_X, pm->data[1] * 128 + pm->data[2]);
 105                 input_report_abs(dev, ABS_Y, pm->data[3] * 128 + pm->data[4]);
 106                 input_report_key(dev, BTN_TOUCH, !!(pm->data[0] & 0x40));
 107                 input_sync(dev);
 108                 pm->idx = 0;
 109         }
 110 }
 111 
 112 static void pm_parse_6000(struct pm *pm)
 113 {
 114         struct input_dev *dev = pm->dev;
 115 
 116         if ((pm->data[0] & 0xbf) == 0x30 && pm->packetsize == ++pm->idx) {
 117                 if (pm_checkpacket(pm->data)) {
 118                         input_report_abs(dev, ABS_X,
 119                                         pm->data[2] * 256 + pm->data[1]);
 120                         input_report_abs(dev, ABS_Y,
 121                                         pm->data[4] * 256 + pm->data[3]);
 122                         input_report_key(dev, BTN_TOUCH, pm->data[0] & 0x40);
 123                         input_sync(dev);
 124                 }
 125                 pm->idx = 0;
 126         }
 127 }
 128 
 129 static void pm_parse_3000(struct pm *pm)
 130 {
 131         struct input_dev *dev = pm->dev;
 132 
 133         if ((pm->data[0] & 0xce) == 0x40 && pm->packetsize == ++pm->idx) {
 134                 if (pm_checkpacket(pm->data)) {
 135                         int slotnum = pm->data[0] & 0x0f;
 136                         pm->slots[slotnum].active = pm->data[0] & 0x30;
 137                         pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
 138                         pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
 139                         pm_mtevent(pm, dev);
 140                 }
 141                 pm->idx = 0;
 142         }
 143 }
 144 
 145 static void pm_parse_6250(struct pm *pm)
 146 {
 147         struct input_dev *dev = pm->dev;
 148 
 149         if ((pm->data[0] & 0xb0) == 0x30 && pm->packetsize == ++pm->idx) {
 150                 if (pm_checkpacket(pm->data)) {
 151                         int slotnum = pm->data[0] & 0x0f;
 152                         pm->slots[slotnum].active = pm->data[0] & 0x40;
 153                         pm->slots[slotnum].x = pm->data[2] * 256 + pm->data[1];
 154                         pm->slots[slotnum].y = pm->data[4] * 256 + pm->data[3];
 155                         pm_mtevent(pm, dev);
 156                 }
 157                 pm->idx = 0;
 158         }
 159 }
 160 
 161 static irqreturn_t pm_interrupt(struct serio *serio,
 162                 unsigned char data, unsigned int flags)
 163 {
 164         struct pm *pm = serio_get_drvdata(serio);
 165 
 166         pm->data[pm->idx] = data;
 167 
 168         pm->parse_packet(pm);
 169 
 170         return IRQ_HANDLED;
 171 }
 172 
 173 /*
 174  * pm_disconnect() is the opposite of pm_connect()
 175  */
 176 
 177 static void pm_disconnect(struct serio *serio)
 178 {
 179         struct pm *pm = serio_get_drvdata(serio);
 180 
 181         serio_close(serio);
 182 
 183         input_unregister_device(pm->dev);
 184         kfree(pm);
 185 
 186         serio_set_drvdata(serio, NULL);
 187 }
 188 
 189 /*
 190  * pm_connect() is the routine that is called when someone adds a
 191  * new serio device that supports PenMount protocol and registers it as
 192  * an input device.
 193  */
 194 
 195 static int pm_connect(struct serio *serio, struct serio_driver *drv)
 196 {
 197         struct pm *pm;
 198         struct input_dev *input_dev;
 199         int max_x, max_y;
 200         int err;
 201 
 202         pm = kzalloc(sizeof(struct pm), GFP_KERNEL);
 203         input_dev = input_allocate_device();
 204         if (!pm || !input_dev) {
 205                 err = -ENOMEM;
 206                 goto fail1;
 207         }
 208 
 209         pm->serio = serio;
 210         pm->dev = input_dev;
 211         snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
 212         pm->maxcontacts = 1;
 213 
 214         input_dev->name = "PenMount Serial TouchScreen";
 215         input_dev->phys = pm->phys;
 216         input_dev->id.bustype = BUS_RS232;
 217         input_dev->id.vendor = SERIO_PENMOUNT;
 218         input_dev->id.product = 0;
 219         input_dev->id.version = 0x0100;
 220         input_dev->dev.parent = &serio->dev;
 221 
 222         input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 223         input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 224 
 225         switch (serio->id.id) {
 226         default:
 227         case 0:
 228                 pm->packetsize = 5;
 229                 pm->parse_packet = pm_parse_9000;
 230                 input_dev->id.product = 0x9000;
 231                 max_x = max_y = 0x3ff;
 232                 break;
 233 
 234         case 1:
 235                 pm->packetsize = 6;
 236                 pm->parse_packet = pm_parse_6000;
 237                 input_dev->id.product = 0x6000;
 238                 max_x = max_y = 0x3ff;
 239                 break;
 240 
 241         case 2:
 242                 pm->packetsize = 6;
 243                 pm->parse_packet = pm_parse_3000;
 244                 input_dev->id.product = 0x3000;
 245                 max_x = max_y = 0x7ff;
 246                 pm->maxcontacts = PM_3000_MTSLOT;
 247                 break;
 248 
 249         case 3:
 250                 pm->packetsize = 6;
 251                 pm->parse_packet = pm_parse_6250;
 252                 input_dev->id.product = 0x6250;
 253                 max_x = max_y = 0x3ff;
 254                 pm->maxcontacts = PM_6250_MTSLOT;
 255                 break;
 256         }
 257 
 258         input_set_abs_params(pm->dev, ABS_X, 0, max_x, 0, 0);
 259         input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0);
 260 
 261         if (pm->maxcontacts > 1) {
 262                 input_mt_init_slots(pm->dev, pm->maxcontacts, 0);
 263                 input_set_abs_params(pm->dev,
 264                                      ABS_MT_POSITION_X, 0, max_x, 0, 0);
 265                 input_set_abs_params(pm->dev,
 266                                      ABS_MT_POSITION_Y, 0, max_y, 0, 0);
 267         }
 268 
 269         serio_set_drvdata(serio, pm);
 270 
 271         err = serio_open(serio, drv);
 272         if (err)
 273                 goto fail2;
 274 
 275         err = input_register_device(pm->dev);
 276         if (err)
 277                 goto fail3;
 278 
 279         return 0;
 280 
 281  fail3: serio_close(serio);
 282  fail2: serio_set_drvdata(serio, NULL);
 283  fail1: input_free_device(input_dev);
 284         kfree(pm);
 285         return err;
 286 }
 287 
 288 /*
 289  * The serio driver structure.
 290  */
 291 
 292 static const struct serio_device_id pm_serio_ids[] = {
 293         {
 294                 .type   = SERIO_RS232,
 295                 .proto  = SERIO_PENMOUNT,
 296                 .id     = SERIO_ANY,
 297                 .extra  = SERIO_ANY,
 298         },
 299         { 0 }
 300 };
 301 
 302 MODULE_DEVICE_TABLE(serio, pm_serio_ids);
 303 
 304 static struct serio_driver pm_drv = {
 305         .driver         = {
 306                 .name   = "serio-penmount",
 307         },
 308         .description    = DRIVER_DESC,
 309         .id_table       = pm_serio_ids,
 310         .interrupt      = pm_interrupt,
 311         .connect        = pm_connect,
 312         .disconnect     = pm_disconnect,
 313 };
 314 
 315 module_serio_driver(pm_drv);

/* [<][>][^][v][top][bottom][index][help] */