Blame view

drivers/hid/hid-a4tech.c 4.02 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
14a21cd45   Jiri Slaby   HID: move a4tech ...
2
3
4
5
6
7
8
  /*
   *  HID driver for some a4tech "special" devices
   *
   *  Copyright (c) 1999 Andreas Gal
   *  Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
   *  Copyright (c) 2005 Michael Haboustak <mike-@cinci.rr.com> for Concept2, Inc
   *  Copyright (c) 2006-2007 Jiri Kosina
14a21cd45   Jiri Slaby   HID: move a4tech ...
9
10
11
12
   *  Copyright (c) 2008 Jiri Slaby
   */
  
  /*
14a21cd45   Jiri Slaby   HID: move a4tech ...
13
14
15
16
17
18
   */
  
  #include <linux/device.h>
  #include <linux/input.h>
  #include <linux/hid.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
14a21cd45   Jiri Slaby   HID: move a4tech ...
20
21
22
23
24
  
  #include "hid-ids.h"
  
  #define A4_2WHEEL_MOUSE_HACK_7	0x01
  #define A4_2WHEEL_MOUSE_HACK_B8	0x02
1c703b53e   Nicolas Saenz Julienne   HID: input: fix a...
25
  #define A4_WHEEL_ORIENTATION	(HID_UP_GENDESK | 0x000000b8)
14a21cd45   Jiri Slaby   HID: move a4tech ...
26
27
28
29
30
  struct a4tech_sc {
  	unsigned long quirks;
  	unsigned int hw_wheel;
  	__s32 delayed_value;
  };
1c703b53e   Nicolas Saenz Julienne   HID: input: fix a...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  static int a4_input_mapping(struct hid_device *hdev, struct hid_input *hi,
  			    struct hid_field *field, struct hid_usage *usage,
  			    unsigned long **bit, int *max)
  {
  	struct a4tech_sc *a4 = hid_get_drvdata(hdev);
  
  	if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8 &&
  	    usage->hid == A4_WHEEL_ORIENTATION) {
  		/*
  		 * We do not want to have this usage mapped to anything as it's
  		 * nonstandard and doesn't really behave like an HID report.
  		 * It's only selecting the orientation (vertical/horizontal) of
  		 * the previous mouse wheel report. The input_events will be
  		 * generated once both reports are recorded in a4_event().
  		 */
  		return -1;
  	}
  
  	return 0;
  
  }
14a21cd45   Jiri Slaby   HID: move a4tech ...
52
53
54
55
56
  static int a4_input_mapped(struct hid_device *hdev, struct hid_input *hi,
  		struct hid_field *field, struct hid_usage *usage,
  		unsigned long **bit, int *max)
  {
  	struct a4tech_sc *a4 = hid_get_drvdata(hdev);
abf82e8f7   Błażej Szczygieł   HID: a4tech: fix ...
57
  	if (usage->type == EV_REL && usage->code == REL_WHEEL_HI_RES) {
14a21cd45   Jiri Slaby   HID: move a4tech ...
58
  		set_bit(REL_HWHEEL, *bit);
abf82e8f7   Błażej Szczygieł   HID: a4tech: fix ...
59
60
  		set_bit(REL_HWHEEL_HI_RES, *bit);
  	}
14a21cd45   Jiri Slaby   HID: move a4tech ...
61
62
63
64
65
66
67
68
69
70
71
72
  
  	if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007)
  		return -1;
  
  	return 0;
  }
  
  static int a4_event(struct hid_device *hdev, struct hid_field *field,
  		struct hid_usage *usage, __s32 value)
  {
  	struct a4tech_sc *a4 = hid_get_drvdata(hdev);
  	struct input_dev *input;
1c703b53e   Nicolas Saenz Julienne   HID: input: fix a...
73
  	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput)
14a21cd45   Jiri Slaby   HID: move a4tech ...
74
75
76
77
78
  		return 0;
  
  	input = field->hidinput->input;
  
  	if (a4->quirks & A4_2WHEEL_MOUSE_HACK_B8) {
abf82e8f7   Błażej Szczygieł   HID: a4tech: fix ...
79
  		if (usage->type == EV_REL && usage->code == REL_WHEEL_HI_RES) {
14a21cd45   Jiri Slaby   HID: move a4tech ...
80
81
82
  			a4->delayed_value = value;
  			return 1;
  		}
1c703b53e   Nicolas Saenz Julienne   HID: input: fix a...
83
  		if (usage->hid == A4_WHEEL_ORIENTATION) {
14a21cd45   Jiri Slaby   HID: move a4tech ...
84
85
  			input_event(input, EV_REL, value ? REL_HWHEEL :
  					REL_WHEEL, a4->delayed_value);
abf82e8f7   Błażej Szczygieł   HID: a4tech: fix ...
86
87
  			input_event(input, EV_REL, value ? REL_HWHEEL_HI_RES :
  					REL_WHEEL_HI_RES, a4->delayed_value * 120);
14a21cd45   Jiri Slaby   HID: move a4tech ...
88
89
90
91
92
93
94
95
  			return 1;
  		}
  	}
  
  	if ((a4->quirks & A4_2WHEEL_MOUSE_HACK_7) && usage->hid == 0x00090007) {
  		a4->hw_wheel = !!value;
  		return 1;
  	}
abf82e8f7   Błażej Szczygieł   HID: a4tech: fix ...
96
  	if (usage->code == REL_WHEEL_HI_RES && a4->hw_wheel) {
14a21cd45   Jiri Slaby   HID: move a4tech ...
97
  		input_event(input, usage->type, REL_HWHEEL, value);
abf82e8f7   Błażej Szczygieł   HID: a4tech: fix ...
98
  		input_event(input, usage->type, REL_HWHEEL_HI_RES, value * 120);
14a21cd45   Jiri Slaby   HID: move a4tech ...
99
100
101
102
103
104
105
106
107
108
  		return 1;
  	}
  
  	return 0;
  }
  
  static int a4_probe(struct hid_device *hdev, const struct hid_device_id *id)
  {
  	struct a4tech_sc *a4;
  	int ret;
abf832bfc   Benjamin Tissoires   HID: trivial devm...
109
  	a4 = devm_kzalloc(&hdev->dev, sizeof(*a4), GFP_KERNEL);
14a21cd45   Jiri Slaby   HID: move a4tech ...
110
  	if (a4 == NULL) {
4291ee305   Joe Perches   HID: Add and use ...
111
112
  		hid_err(hdev, "can't alloc device descriptor
  ");
abf832bfc   Benjamin Tissoires   HID: trivial devm...
113
  		return -ENOMEM;
14a21cd45   Jiri Slaby   HID: move a4tech ...
114
115
116
117
118
119
120
121
  	}
  
  	a4->quirks = id->driver_data;
  
  	hid_set_drvdata(hdev, a4);
  
  	ret = hid_parse(hdev);
  	if (ret) {
4291ee305   Joe Perches   HID: Add and use ...
122
123
  		hid_err(hdev, "parse failed
  ");
abf832bfc   Benjamin Tissoires   HID: trivial devm...
124
  		return ret;
14a21cd45   Jiri Slaby   HID: move a4tech ...
125
  	}
93c10132a   Jiri Slaby   HID: move connect...
126
  	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
14a21cd45   Jiri Slaby   HID: move a4tech ...
127
  	if (ret) {
4291ee305   Joe Perches   HID: Add and use ...
128
129
  		hid_err(hdev, "hw start failed
  ");
abf832bfc   Benjamin Tissoires   HID: trivial devm...
130
  		return ret;
14a21cd45   Jiri Slaby   HID: move a4tech ...
131
132
133
  	}
  
  	return 0;
14a21cd45   Jiri Slaby   HID: move a4tech ...
134
135
136
137
138
139
140
  }
  
  static const struct hid_device_id a4_devices[] = {
  	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU),
  		.driver_data = A4_2WHEEL_MOUSE_HACK_7 },
  	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D),
  		.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
b7e1b2039   Lech Perczak   HID: fix A4Tech R...
141
142
  	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649),
  		.driver_data = A4_2WHEEL_MOUSE_HACK_B8 },
14a21cd45   Jiri Slaby   HID: move a4tech ...
143
144
145
146
147
148
149
  	{ }
  };
  MODULE_DEVICE_TABLE(hid, a4_devices);
  
  static struct hid_driver a4_driver = {
  	.name = "a4tech",
  	.id_table = a4_devices,
1c703b53e   Nicolas Saenz Julienne   HID: input: fix a...
150
  	.input_mapping = a4_input_mapping,
14a21cd45   Jiri Slaby   HID: move a4tech ...
151
152
153
  	.input_mapped = a4_input_mapped,
  	.event = a4_event,
  	.probe = a4_probe,
14a21cd45   Jiri Slaby   HID: move a4tech ...
154
  };
f425458ea   H Hartley Sweeten   HID: Use module_h...
155
  module_hid_driver(a4_driver);
14a21cd45   Jiri Slaby   HID: move a4tech ...
156

14a21cd45   Jiri Slaby   HID: move a4tech ...
157
  MODULE_LICENSE("GPL");