linux/drivers/hid/hid-elo.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * HID driver for ELO usb touchscreen 4000/4500
   4 *
   5 * Copyright (c) 2013 Jiri Slaby
   6 *
   7 * Data parsing taken from elousb driver by Vojtech Pavlik.
   8 */
   9
  10#include <linux/hid.h>
  11#include <linux/input.h>
  12#include <linux/module.h>
  13#include <linux/usb.h>
  14#include <linux/workqueue.h>
  15
  16#include "hid-ids.h"
  17
  18#define ELO_PERIODIC_READ_INTERVAL      HZ
  19#define ELO_SMARTSET_CMD_TIMEOUT        2000 /* msec */
  20
  21/* Elo SmartSet commands */
  22#define ELO_FLUSH_SMARTSET_RESPONSES    0x02 /* Flush all pending smartset responses */
  23#define ELO_SEND_SMARTSET_COMMAND       0x05 /* Send a smartset command */
  24#define ELO_GET_SMARTSET_RESPONSE       0x06 /* Get a smartset response */
  25#define ELO_DIAG                        0x64 /* Diagnostics command */
  26#define ELO_SMARTSET_PACKET_SIZE        8
  27
  28struct elo_priv {
  29        struct usb_device *usbdev;
  30        struct delayed_work work;
  31        unsigned char buffer[ELO_SMARTSET_PACKET_SIZE];
  32};
  33
  34static struct workqueue_struct *wq;
  35static bool use_fw_quirk = true;
  36module_param(use_fw_quirk, bool, S_IRUGO);
  37MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)");
  38
  39static int elo_input_configured(struct hid_device *hdev,
  40                struct hid_input *hidinput)
  41{
  42        struct input_dev *input = hidinput->input;
  43
  44        /*
  45         * ELO devices have one Button usage in GenDesk field, which makes
  46         * hid-input map it to BTN_LEFT; that confuses userspace, which then
  47         * considers the device to be a mouse/touchpad instead of touchscreen.
  48         */
  49        clear_bit(BTN_LEFT, input->keybit);
  50        set_bit(BTN_TOUCH, input->keybit);
  51        set_bit(ABS_PRESSURE, input->absbit);
  52        input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0);
  53
  54        return 0;
  55}
  56
  57static void elo_process_data(struct input_dev *input, const u8 *data, int size)
  58{
  59        int press;
  60
  61        input_report_abs(input, ABS_X, (data[3] << 8) | data[2]);
  62        input_report_abs(input, ABS_Y, (data[5] << 8) | data[4]);
  63
  64        press = 0;
  65        if (data[1] & 0x80)
  66                press = (data[7] << 8) | data[6];
  67        input_report_abs(input, ABS_PRESSURE, press);
  68
  69        if (data[1] & 0x03) {
  70                input_report_key(input, BTN_TOUCH, 1);
  71                input_sync(input);
  72        }
  73
  74        if (data[1] & 0x04)
  75                input_report_key(input, BTN_TOUCH, 0);
  76
  77        input_sync(input);
  78}
  79
  80static int elo_raw_event(struct hid_device *hdev, struct hid_report *report,
  81         u8 *data, int size)
  82{
  83        struct hid_input *hidinput;
  84
  85        if (!(hdev->claimed & HID_CLAIMED_INPUT) || list_empty(&hdev->inputs))
  86                return 0;
  87
  88        hidinput = list_first_entry(&hdev->inputs, struct hid_input, list);
  89
  90        switch (report->id) {
  91        case 0:
  92                if (data[0] == 'T') {   /* Mandatory ELO packet marker */
  93                        elo_process_data(hidinput->input, data, size);
  94                        return 1;
  95                }
  96                break;
  97        default:        /* unknown report */
  98                /* Unknown report type; pass upstream */
  99                hid_info(hdev, "unknown report type %d\n", report->id);
 100                break;
 101        }
 102
 103        return 0;
 104}
 105
 106static int elo_smartset_send_get(struct usb_device *dev, u8 command,
 107                void *data)
 108{
 109        unsigned int pipe;
 110        u8 dir;
 111
 112        if (command == ELO_SEND_SMARTSET_COMMAND) {
 113                pipe = usb_sndctrlpipe(dev, 0);
 114                dir = USB_DIR_OUT;
 115        } else if (command == ELO_GET_SMARTSET_RESPONSE) {
 116                pipe = usb_rcvctrlpipe(dev, 0);
 117                dir = USB_DIR_IN;
 118        } else
 119                return -EINVAL;
 120
 121        return usb_control_msg(dev, pipe, command,
 122                        dir | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 123                        0, 0, data, ELO_SMARTSET_PACKET_SIZE,
 124                        ELO_SMARTSET_CMD_TIMEOUT);
 125}
 126
 127static int elo_flush_smartset_responses(struct usb_device *dev)
 128{
 129        return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 130                        ELO_FLUSH_SMARTSET_RESPONSES,
 131                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 132                        0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 133}
 134
 135static void elo_work(struct work_struct *work)
 136{
 137        struct elo_priv *priv = container_of(work, struct elo_priv, work.work);
 138        struct usb_device *dev = priv->usbdev;
 139        unsigned char *buffer = priv->buffer;
 140        int ret;
 141
 142        ret = elo_flush_smartset_responses(dev);
 143        if (ret < 0) {
 144                dev_err(&dev->dev, "initial FLUSH_SMARTSET_RESPONSES failed, error %d\n",
 145                                ret);
 146                goto fail;
 147        }
 148
 149        /* send Diagnostics command */
 150        *buffer = ELO_DIAG;
 151        ret = elo_smartset_send_get(dev, ELO_SEND_SMARTSET_COMMAND, buffer);
 152        if (ret < 0) {
 153                dev_err(&dev->dev, "send Diagnostics Command failed, error %d\n",
 154                                ret);
 155                goto fail;
 156        }
 157
 158        /* get the result */
 159        ret = elo_smartset_send_get(dev, ELO_GET_SMARTSET_RESPONSE, buffer);
 160        if (ret < 0) {
 161                dev_err(&dev->dev, "get Diagnostics Command response failed, error %d\n",
 162                                ret);
 163                goto fail;
 164        }
 165
 166        /* read the ack */
 167        if (*buffer != 'A') {
 168                ret = elo_smartset_send_get(dev, ELO_GET_SMARTSET_RESPONSE,
 169                                buffer);
 170                if (ret < 0) {
 171                        dev_err(&dev->dev, "get acknowledge response failed, error %d\n",
 172                                        ret);
 173                        goto fail;
 174                }
 175        }
 176
 177fail:
 178        ret = elo_flush_smartset_responses(dev);
 179        if (ret < 0)
 180                dev_err(&dev->dev, "final FLUSH_SMARTSET_RESPONSES failed, error %d\n",
 181                                ret);
 182        queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL);
 183}
 184
 185/*
 186 * Not all Elo devices need the periodic HID descriptor reads.
 187 * Only firmware version M needs this.
 188 */
 189static bool elo_broken_firmware(struct usb_device *dev)
 190{
 191        struct usb_device *hub = dev->parent;
 192        struct usb_device *child = NULL;
 193        u16 fw_lvl = le16_to_cpu(dev->descriptor.bcdDevice);
 194        u16 child_vid, child_pid;
 195        int i;
 196    
 197        if (!use_fw_quirk)
 198                return false;
 199        if (fw_lvl != 0x10d)
 200                return false;
 201
 202        /* iterate sibling devices of the touch controller */
 203        usb_hub_for_each_child(hub, i, child) {
 204                child_vid = le16_to_cpu(child->descriptor.idVendor);
 205                child_pid = le16_to_cpu(child->descriptor.idProduct);
 206
 207                /*
 208                 * If one of the devices below is present attached as a sibling of 
 209                 * the touch controller then  this is a newer IBM 4820 monitor that 
 210                 * does not need the IBM-requested workaround if fw level is
 211                 * 0x010d - aka 'M'.
 212                 * No other HW can have this combination.
 213                 */
 214                if (child_vid==0x04b3) {
 215                        switch (child_pid) {
 216                        case 0x4676: /* 4820 21x Video */
 217                        case 0x4677: /* 4820 51x Video */
 218                        case 0x4678: /* 4820 2Lx Video */
 219                        case 0x4679: /* 4820 5Lx Video */
 220                                return false;
 221                        }
 222                }
 223        }
 224        return true;
 225}
 226
 227static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
 228{
 229        struct elo_priv *priv;
 230        int ret;
 231        struct usb_device *udev;
 232
 233        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 234        if (!priv)
 235                return -ENOMEM;
 236
 237        INIT_DELAYED_WORK(&priv->work, elo_work);
 238        udev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
 239        priv->usbdev = usb_get_dev(udev);
 240
 241        hid_set_drvdata(hdev, priv);
 242
 243        ret = hid_parse(hdev);
 244        if (ret) {
 245                hid_err(hdev, "parse failed\n");
 246                goto err_free;
 247        }
 248
 249        ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 250        if (ret) {
 251                hid_err(hdev, "hw start failed\n");
 252                goto err_free;
 253        }
 254
 255        if (elo_broken_firmware(priv->usbdev)) {
 256                hid_info(hdev, "broken firmware found, installing workaround\n");
 257                queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL);
 258        }
 259
 260        return 0;
 261err_free:
 262        kfree(priv);
 263        return ret;
 264}
 265
 266static void elo_remove(struct hid_device *hdev)
 267{
 268        struct elo_priv *priv = hid_get_drvdata(hdev);
 269
 270        usb_put_dev(priv->usbdev);
 271
 272        hid_hw_stop(hdev);
 273        cancel_delayed_work_sync(&priv->work);
 274        kfree(priv);
 275}
 276
 277static const struct hid_device_id elo_devices[] = {
 278        { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009), },
 279        { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030), },
 280        { }
 281};
 282MODULE_DEVICE_TABLE(hid, elo_devices);
 283
 284static struct hid_driver elo_driver = {
 285        .name = "elo",
 286        .id_table = elo_devices,
 287        .probe = elo_probe,
 288        .remove = elo_remove,
 289        .raw_event = elo_raw_event,
 290        .input_configured = elo_input_configured,
 291};
 292
 293static int __init elo_driver_init(void)
 294{
 295        int ret;
 296
 297        wq = create_singlethread_workqueue("elousb");
 298        if (!wq)
 299                return -ENOMEM;
 300
 301        ret = hid_register_driver(&elo_driver);
 302        if (ret)
 303                destroy_workqueue(wq);
 304
 305        return ret;
 306}
 307module_init(elo_driver_init);
 308
 309static void __exit elo_driver_exit(void)
 310{
 311        hid_unregister_driver(&elo_driver);
 312        destroy_workqueue(wq);
 313}
 314module_exit(elo_driver_exit);
 315
 316MODULE_AUTHOR("Jiri Slaby <jslaby@suse.cz>");
 317MODULE_LICENSE("GPL");
 318