This source file includes following definitions.
- holtekff_send
- holtekff_play
- holtekff_init
- holtekff_init
- holtek_probe
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <linux/hid.h>
15 #include <linux/input.h>
16 #include <linux/module.h>
17 #include <linux/slab.h>
18
19 #include "hid-ids.h"
20
21 #ifdef CONFIG_HOLTEK_FF
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 #define HOLTEKFF_MSG_LENGTH 7
66
67 static const u8 start_effect_1[] = { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
68 static const u8 stop_all4[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
69 static const u8 stop_all6[] = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
70
71 struct holtekff_device {
72 struct hid_field *field;
73 };
74
75 static void holtekff_send(struct holtekff_device *holtekff,
76 struct hid_device *hid,
77 const u8 data[HOLTEKFF_MSG_LENGTH])
78 {
79 int i;
80
81 for (i = 0; i < HOLTEKFF_MSG_LENGTH; i++) {
82 holtekff->field->value[i] = data[i];
83 }
84
85 dbg_hid("sending %7ph\n", data);
86
87 hid_hw_request(hid, holtekff->field->report, HID_REQ_SET_REPORT);
88 }
89
90 static int holtekff_play(struct input_dev *dev, void *data,
91 struct ff_effect *effect)
92 {
93 struct hid_device *hid = input_get_drvdata(dev);
94 struct holtekff_device *holtekff = data;
95 int left, right;
96
97 u8 buf[HOLTEKFF_MSG_LENGTH] =
98 { 0x01, 0x01, 0xff, 0xff, 0x10, 0xe0, 0x00 };
99
100 left = effect->u.rumble.strong_magnitude;
101 right = effect->u.rumble.weak_magnitude;
102 dbg_hid("called with 0x%04x 0x%04x\n", left, right);
103
104 if (!left && !right) {
105 holtekff_send(holtekff, hid, stop_all6);
106 return 0;
107 }
108
109 if (left)
110 buf[1] |= 0x80;
111 if (right)
112 buf[1] |= 0x40;
113
114
115 buf[6] = min(0xf, (left >> 12) + (right >> 12));
116
117 holtekff_send(holtekff, hid, buf);
118 holtekff_send(holtekff, hid, start_effect_1);
119
120 return 0;
121 }
122
123 static int holtekff_init(struct hid_device *hid)
124 {
125 struct holtekff_device *holtekff;
126 struct hid_report *report;
127 struct hid_input *hidinput;
128 struct list_head *report_list =
129 &hid->report_enum[HID_OUTPUT_REPORT].report_list;
130 struct input_dev *dev;
131 int error;
132
133 if (list_empty(&hid->inputs)) {
134 hid_err(hid, "no inputs found\n");
135 return -ENODEV;
136 }
137 hidinput = list_entry(hid->inputs.next, struct hid_input, list);
138 dev = hidinput->input;
139
140 if (list_empty(report_list)) {
141 hid_err(hid, "no output report found\n");
142 return -ENODEV;
143 }
144
145 report = list_entry(report_list->next, struct hid_report, list);
146
147 if (report->maxfield < 1 || report->field[0]->report_count != 7) {
148 hid_err(hid, "unexpected output report layout\n");
149 return -ENODEV;
150 }
151
152 holtekff = kzalloc(sizeof(*holtekff), GFP_KERNEL);
153 if (!holtekff)
154 return -ENOMEM;
155
156 set_bit(FF_RUMBLE, dev->ffbit);
157
158 holtekff->field = report->field[0];
159
160
161 holtekff_send(holtekff, hid, stop_all4);
162 holtekff_send(holtekff, hid, stop_all6);
163
164 error = input_ff_create_memless(dev, holtekff, holtekff_play);
165 if (error) {
166 kfree(holtekff);
167 return error;
168 }
169
170 hid_info(hid, "Force feedback for Holtek On Line Grip based devices by Anssi Hannula <anssi.hannula@iki.fi>\n");
171
172 return 0;
173 }
174 #else
175 static inline int holtekff_init(struct hid_device *hid)
176 {
177 return 0;
178 }
179 #endif
180
181 static int holtek_probe(struct hid_device *hdev, const struct hid_device_id *id)
182 {
183 int ret;
184
185 ret = hid_parse(hdev);
186 if (ret) {
187 hid_err(hdev, "parse failed\n");
188 goto err;
189 }
190
191 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
192 if (ret) {
193 hid_err(hdev, "hw start failed\n");
194 goto err;
195 }
196
197 holtekff_init(hdev);
198
199 return 0;
200 err:
201 return ret;
202 }
203
204 static const struct hid_device_id holtek_devices[] = {
205 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
206 { }
207 };
208 MODULE_DEVICE_TABLE(hid, holtek_devices);
209
210 static struct hid_driver holtek_driver = {
211 .name = "holtek",
212 .id_table = holtek_devices,
213 .probe = holtek_probe,
214 };
215 module_hid_driver(holtek_driver);
216
217 MODULE_LICENSE("GPL");
218 MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
219 MODULE_DESCRIPTION("Force feedback support for Holtek On Line Grip based devices");