cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hid-elo.c (7791B)


      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
    232	if (!hid_is_usb(hdev))
    233		return -EINVAL;
    234
    235	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    236	if (!priv)
    237		return -ENOMEM;
    238
    239	INIT_DELAYED_WORK(&priv->work, elo_work);
    240	priv->usbdev = interface_to_usbdev(to_usb_interface(hdev->dev.parent));
    241
    242	hid_set_drvdata(hdev, priv);
    243
    244	ret = hid_parse(hdev);
    245	if (ret) {
    246		hid_err(hdev, "parse failed\n");
    247		goto err_free;
    248	}
    249
    250	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
    251	if (ret) {
    252		hid_err(hdev, "hw start failed\n");
    253		goto err_free;
    254	}
    255
    256	if (elo_broken_firmware(priv->usbdev)) {
    257		hid_info(hdev, "broken firmware found, installing workaround\n");
    258		queue_delayed_work(wq, &priv->work, ELO_PERIODIC_READ_INTERVAL);
    259	}
    260
    261	return 0;
    262err_free:
    263	kfree(priv);
    264	return ret;
    265}
    266
    267static void elo_remove(struct hid_device *hdev)
    268{
    269	struct elo_priv *priv = hid_get_drvdata(hdev);
    270
    271	hid_hw_stop(hdev);
    272	cancel_delayed_work_sync(&priv->work);
    273	kfree(priv);
    274}
    275
    276static const struct hid_device_id elo_devices[] = {
    277	{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009), },
    278	{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0030), },
    279	{ }
    280};
    281MODULE_DEVICE_TABLE(hid, elo_devices);
    282
    283static struct hid_driver elo_driver = {
    284	.name = "elo",
    285	.id_table = elo_devices,
    286	.probe = elo_probe,
    287	.remove = elo_remove,
    288	.raw_event = elo_raw_event,
    289	.input_configured = elo_input_configured,
    290};
    291
    292static int __init elo_driver_init(void)
    293{
    294	int ret;
    295
    296	wq = create_singlethread_workqueue("elousb");
    297	if (!wq)
    298		return -ENOMEM;
    299
    300	ret = hid_register_driver(&elo_driver);
    301	if (ret)
    302		destroy_workqueue(wq);
    303
    304	return ret;
    305}
    306module_init(elo_driver_init);
    307
    308static void __exit elo_driver_exit(void)
    309{
    310	hid_unregister_driver(&elo_driver);
    311	destroy_workqueue(wq);
    312}
    313module_exit(elo_driver_exit);
    314
    315MODULE_AUTHOR("Jiri Slaby <jslaby@suse.cz>");
    316MODULE_LICENSE("GPL");