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