Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * $$ | |
3 | * | |
4 | * Force feedback support for hid-compliant for some of the devices from | |
5 | * Logitech, namely: | |
6 | * - WingMan Cordless RumblePad | |
7 | * - WingMan Force 3D | |
8 | * | |
9 | * Copyright (c) 2002-2004 Johann Deneux | |
10 | */ | |
11 | ||
12 | /* | |
13 | * This program is free software; you can redistribute it and/or modify | |
14 | * it under the terms of the GNU General Public License as published by | |
15 | * the Free Software Foundation; either version 2 of the License, or | |
16 | * (at your option) any later version. | |
17 | * | |
18 | * This program is distributed in the hope that it will be useful, | |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | * GNU General Public License for more details. | |
22 | * | |
23 | * You should have received a copy of the GNU General Public License | |
24 | * along with this program; if not, write to the Free Software | |
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
26 | * | |
27 | * Should you need to contact me, the author, you can do so by | |
28 | * e-mail - mail your message to <johann.deneux@it.uu.se> | |
29 | */ | |
30 | ||
31 | #include <linux/input.h> | |
32 | #include <linux/sched.h> | |
33 | ||
34 | //#define DEBUG | |
35 | #include <linux/usb.h> | |
36 | ||
37 | #include <linux/circ_buf.h> | |
38 | ||
39 | #include "hid.h" | |
40 | #include "fixp-arith.h" | |
41 | ||
42 | ||
43 | /* Periodicity of the update */ | |
44 | #define PERIOD (HZ/10) | |
45 | ||
46 | #define RUN_AT(t) (jiffies + (t)) | |
47 | ||
48 | /* Effect status */ | |
49 | #define EFFECT_STARTED 0 /* Effect is going to play after some time | |
50 | (ff_replay.delay) */ | |
51 | #define EFFECT_PLAYING 1 /* Effect is being played */ | |
52 | #define EFFECT_USED 2 | |
53 | ||
54 | // For lgff_device::flags | |
55 | #define DEVICE_CLOSING 0 /* The driver is being unitialised */ | |
56 | ||
57 | /* Check that the current process can access an effect */ | |
58 | #define CHECK_OWNERSHIP(effect) (current->pid == 0 \ | |
59 | || effect.owner == current->pid) | |
60 | ||
61 | #define LGFF_CHECK_OWNERSHIP(i, l) \ | |
62 | (i>=0 && i<LGFF_EFFECTS \ | |
63 | && test_bit(EFFECT_USED, l->effects[i].flags) \ | |
64 | && CHECK_OWNERSHIP(l->effects[i])) | |
65 | ||
66 | #define LGFF_EFFECTS 8 | |
67 | ||
68 | struct device_type { | |
69 | u16 idVendor; | |
70 | u16 idProduct; | |
71 | signed short *ff; | |
72 | }; | |
73 | ||
74 | struct lgff_effect { | |
75 | pid_t owner; | |
76 | ||
77 | struct ff_effect effect; | |
78 | ||
79 | unsigned long flags[1]; | |
80 | unsigned int count; /* Number of times left to play */ | |
81 | unsigned long started_at; /* When the effect started to play */ | |
82 | }; | |
83 | ||
84 | struct lgff_device { | |
85 | struct hid_device* hid; | |
86 | ||
87 | struct hid_report* constant; | |
88 | struct hid_report* rumble; | |
89 | struct hid_report* condition; | |
90 | ||
91 | struct lgff_effect effects[LGFF_EFFECTS]; | |
92 | spinlock_t lock; /* device-level lock. Having locks on | |
93 | a per-effect basis could be nice, but | |
94 | isn't really necessary */ | |
95 | ||
96 | unsigned long flags[1]; /* Contains various information about the | |
97 | state of the driver for this device */ | |
98 | ||
99 | struct timer_list timer; | |
100 | }; | |
101 | ||
102 | /* Callbacks */ | |
103 | static void hid_lgff_exit(struct hid_device* hid); | |
104 | static int hid_lgff_event(struct hid_device *hid, struct input_dev *input, | |
105 | unsigned int type, unsigned int code, int value); | |
106 | static int hid_lgff_flush(struct input_dev *input, struct file *file); | |
107 | static int hid_lgff_upload_effect(struct input_dev *input, | |
108 | struct ff_effect *effect); | |
109 | static int hid_lgff_erase(struct input_dev *input, int id); | |
110 | ||
111 | /* Local functions */ | |
112 | static void hid_lgff_input_init(struct hid_device* hid); | |
113 | static void hid_lgff_timer(unsigned long timer_data); | |
114 | static struct hid_report* hid_lgff_duplicate_report(struct hid_report*); | |
115 | static void hid_lgff_delete_report(struct hid_report*); | |
116 | ||
117 | static signed short ff_rumble[] = { | |
118 | FF_RUMBLE, | |
119 | -1 | |
120 | }; | |
121 | ||
122 | static signed short ff_joystick[] = { | |
123 | FF_CONSTANT, | |
124 | -1 | |
125 | }; | |
126 | ||
127 | static struct device_type devices[] = { | |
128 | {0x046d, 0xc211, ff_rumble}, | |
129 | {0x046d, 0xc219, ff_rumble}, | |
130 | {0x046d, 0xc283, ff_joystick}, | |
131 | {0x0000, 0x0000, ff_joystick} | |
132 | }; | |
133 | ||
134 | int hid_lgff_init(struct hid_device* hid) | |
135 | { | |
136 | struct lgff_device *private; | |
137 | struct hid_report* report; | |
138 | struct hid_field* field; | |
139 | ||
140 | /* Find the report to use */ | |
141 | if (list_empty(&hid->report_enum[HID_OUTPUT_REPORT].report_list)) { | |
142 | err("No output report found"); | |
143 | return -1; | |
144 | } | |
145 | /* Check that the report looks ok */ | |
146 | report = (struct hid_report*)hid->report_enum[HID_OUTPUT_REPORT].report_list.next; | |
147 | if (!report) { | |
148 | err("NULL output report"); | |
149 | return -1; | |
150 | } | |
151 | field = report->field[0]; | |
152 | if (!field) { | |
153 | err("NULL field"); | |
154 | return -1; | |
155 | } | |
156 | ||
157 | private = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); | |
158 | if (!private) | |
159 | return -1; | |
160 | memset(private, 0, sizeof(struct lgff_device)); | |
161 | hid->ff_private = private; | |
162 | ||
163 | /* Input init */ | |
164 | hid_lgff_input_init(hid); | |
165 | ||
166 | ||
167 | private->constant = hid_lgff_duplicate_report(report); | |
168 | if (!private->constant) { | |
169 | kfree(private); | |
170 | return -1; | |
171 | } | |
172 | private->constant->field[0]->value[0] = 0x51; | |
173 | private->constant->field[0]->value[1] = 0x08; | |
174 | private->constant->field[0]->value[2] = 0x7f; | |
175 | private->constant->field[0]->value[3] = 0x7f; | |
176 | ||
177 | private->rumble = hid_lgff_duplicate_report(report); | |
178 | if (!private->rumble) { | |
179 | hid_lgff_delete_report(private->constant); | |
180 | kfree(private); | |
181 | return -1; | |
182 | } | |
183 | private->rumble->field[0]->value[0] = 0x42; | |
184 | ||
185 | ||
186 | private->condition = hid_lgff_duplicate_report(report); | |
187 | if (!private->condition) { | |
188 | hid_lgff_delete_report(private->rumble); | |
189 | hid_lgff_delete_report(private->constant); | |
190 | kfree(private); | |
191 | return -1; | |
192 | } | |
193 | ||
194 | private->hid = hid; | |
195 | ||
196 | spin_lock_init(&private->lock); | |
197 | init_timer(&private->timer); | |
198 | private->timer.data = (unsigned long)private; | |
199 | private->timer.function = hid_lgff_timer; | |
200 | ||
201 | /* Event and exit callbacks */ | |
202 | hid->ff_exit = hid_lgff_exit; | |
203 | hid->ff_event = hid_lgff_event; | |
204 | ||
205 | /* Start the update task */ | |
206 | private->timer.expires = RUN_AT(PERIOD); | |
207 | add_timer(&private->timer); /*TODO: only run the timer when at least | |
208 | one effect is playing */ | |
209 | ||
210 | printk(KERN_INFO "Force feedback for Logitech force feedback devices by Johann Deneux <johann.deneux@it.uu.se>\n"); | |
211 | ||
212 | return 0; | |
213 | } | |
214 | ||
215 | static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) | |
216 | { | |
217 | struct hid_report* ret; | |
218 | ||
219 | ret = kmalloc(sizeof(struct lgff_device), GFP_KERNEL); | |
220 | if (!ret) | |
221 | return NULL; | |
222 | *ret = *report; | |
223 | ||
224 | ret->field[0] = kmalloc(sizeof(struct hid_field), GFP_KERNEL); | |
225 | if (!ret->field[0]) { | |
226 | kfree(ret); | |
227 | return NULL; | |
228 | } | |
229 | *ret->field[0] = *report->field[0]; | |
230 | ||
231 | ret->field[0]->value = kmalloc(sizeof(s32[8]), GFP_KERNEL); | |
232 | if (!ret->field[0]->value) { | |
233 | kfree(ret->field[0]); | |
234 | kfree(ret); | |
235 | return NULL; | |
236 | } | |
237 | memset(ret->field[0]->value, 0, sizeof(s32[8])); | |
238 | ||
239 | return ret; | |
240 | } | |
241 | ||
242 | static void hid_lgff_delete_report(struct hid_report* report) | |
243 | { | |
244 | if (report) { | |
245 | kfree(report->field[0]->value); | |
246 | kfree(report->field[0]); | |
247 | kfree(report); | |
248 | } | |
249 | } | |
250 | ||
251 | static void hid_lgff_input_init(struct hid_device* hid) | |
252 | { | |
253 | struct device_type* dev = devices; | |
254 | signed short* ff; | |
255 | u16 idVendor = le16_to_cpu(hid->dev->descriptor.idVendor); | |
256 | u16 idProduct = le16_to_cpu(hid->dev->descriptor.idProduct); | |
257 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); | |
258 | ||
259 | while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct)) | |
260 | dev++; | |
261 | ||
262 | ff = dev->ff; | |
263 | ||
264 | while (*ff >= 0) { | |
265 | set_bit(*ff, hidinput->input.ffbit); | |
266 | ++ff; | |
267 | } | |
268 | ||
269 | hidinput->input.upload_effect = hid_lgff_upload_effect; | |
270 | hidinput->input.flush = hid_lgff_flush; | |
271 | ||
272 | set_bit(EV_FF, hidinput->input.evbit); | |
273 | hidinput->input.ff_effects_max = LGFF_EFFECTS; | |
274 | } | |
275 | ||
276 | static void hid_lgff_exit(struct hid_device* hid) | |
277 | { | |
278 | struct lgff_device *lgff = hid->ff_private; | |
279 | ||
280 | set_bit(DEVICE_CLOSING, lgff->flags); | |
281 | del_timer_sync(&lgff->timer); | |
282 | ||
283 | hid_lgff_delete_report(lgff->condition); | |
284 | hid_lgff_delete_report(lgff->rumble); | |
285 | hid_lgff_delete_report(lgff->constant); | |
286 | ||
287 | kfree(lgff); | |
288 | } | |
289 | ||
290 | static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, | |
291 | unsigned int type, unsigned int code, int value) | |
292 | { | |
293 | struct lgff_device *lgff = hid->ff_private; | |
294 | struct lgff_effect *effect = lgff->effects + code; | |
295 | unsigned long flags; | |
296 | ||
297 | if (type != EV_FF) return -EINVAL; | |
298 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; | |
299 | if (value < 0) return -EINVAL; | |
300 | ||
301 | spin_lock_irqsave(&lgff->lock, flags); | |
302 | ||
303 | if (value > 0) { | |
304 | if (test_bit(EFFECT_STARTED, effect->flags)) { | |
305 | spin_unlock_irqrestore(&lgff->lock, flags); | |
306 | return -EBUSY; | |
307 | } | |
308 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | |
309 | spin_unlock_irqrestore(&lgff->lock, flags); | |
310 | return -EBUSY; | |
311 | } | |
312 | ||
313 | effect->count = value; | |
314 | ||
315 | if (effect->effect.replay.delay) { | |
316 | set_bit(EFFECT_STARTED, effect->flags); | |
317 | } else { | |
318 | set_bit(EFFECT_PLAYING, effect->flags); | |
319 | } | |
320 | effect->started_at = jiffies; | |
321 | } | |
322 | else { /* value == 0 */ | |
323 | clear_bit(EFFECT_STARTED, effect->flags); | |
324 | clear_bit(EFFECT_PLAYING, effect->flags); | |
325 | } | |
326 | ||
327 | spin_unlock_irqrestore(&lgff->lock, flags); | |
328 | ||
329 | return 0; | |
330 | ||
331 | } | |
332 | ||
333 | /* Erase all effects this process owns */ | |
334 | static int hid_lgff_flush(struct input_dev *dev, struct file *file) | |
335 | { | |
336 | struct hid_device *hid = dev->private; | |
337 | struct lgff_device *lgff = hid->ff_private; | |
338 | int i; | |
339 | ||
340 | for (i=0; i<dev->ff_effects_max; ++i) { | |
341 | ||
342 | /*NOTE: no need to lock here. The only times EFFECT_USED is | |
343 | modified is when effects are uploaded or when an effect is | |
344 | erased. But a process cannot close its dev/input/eventX fd | |
345 | and perform ioctls on the same fd all at the same time */ | |
346 | if ( current->pid == lgff->effects[i].owner | |
347 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { | |
348 | ||
349 | if (hid_lgff_erase(dev, i)) | |
350 | warn("erase effect %d failed", i); | |
351 | } | |
352 | ||
353 | } | |
354 | ||
355 | return 0; | |
356 | } | |
357 | ||
358 | static int hid_lgff_erase(struct input_dev *dev, int id) | |
359 | { | |
360 | struct hid_device *hid = dev->private; | |
361 | struct lgff_device *lgff = hid->ff_private; | |
362 | unsigned long flags; | |
363 | ||
364 | if (!LGFF_CHECK_OWNERSHIP(id, lgff)) return -EACCES; | |
365 | ||
366 | spin_lock_irqsave(&lgff->lock, flags); | |
367 | lgff->effects[id].flags[0] = 0; | |
368 | spin_unlock_irqrestore(&lgff->lock, flags); | |
369 | ||
370 | return 0; | |
371 | } | |
372 | ||
373 | static int hid_lgff_upload_effect(struct input_dev* input, | |
374 | struct ff_effect* effect) | |
375 | { | |
376 | struct hid_device *hid = input->private; | |
377 | struct lgff_device *lgff = hid->ff_private; | |
378 | struct lgff_effect new; | |
379 | int id; | |
380 | unsigned long flags; | |
381 | ||
382 | dbg("ioctl rumble"); | |
383 | ||
384 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; | |
385 | ||
386 | spin_lock_irqsave(&lgff->lock, flags); | |
387 | ||
388 | if (effect->id == -1) { | |
389 | int i; | |
390 | ||
391 | for (i=0; i<LGFF_EFFECTS && test_bit(EFFECT_USED, lgff->effects[i].flags); ++i); | |
392 | if (i >= LGFF_EFFECTS) { | |
393 | spin_unlock_irqrestore(&lgff->lock, flags); | |
394 | return -ENOSPC; | |
395 | } | |
396 | ||
397 | effect->id = i; | |
398 | lgff->effects[i].owner = current->pid; | |
399 | lgff->effects[i].flags[0] = 0; | |
400 | set_bit(EFFECT_USED, lgff->effects[i].flags); | |
401 | } | |
402 | else if (!LGFF_CHECK_OWNERSHIP(effect->id, lgff)) { | |
403 | spin_unlock_irqrestore(&lgff->lock, flags); | |
404 | return -EACCES; | |
405 | } | |
406 | ||
407 | id = effect->id; | |
408 | new = lgff->effects[id]; | |
409 | ||
410 | new.effect = *effect; | |
411 | ||
412 | if (test_bit(EFFECT_STARTED, lgff->effects[id].flags) | |
413 | || test_bit(EFFECT_STARTED, lgff->effects[id].flags)) { | |
414 | ||
415 | /* Changing replay parameters is not allowed (for the time | |
416 | being) */ | |
417 | if (new.effect.replay.delay != lgff->effects[id].effect.replay.delay | |
418 | || new.effect.replay.length != lgff->effects[id].effect.replay.length) { | |
419 | spin_unlock_irqrestore(&lgff->lock, flags); | |
420 | return -ENOSYS; | |
421 | } | |
422 | ||
423 | lgff->effects[id] = new; | |
424 | ||
425 | } else { | |
426 | lgff->effects[id] = new; | |
427 | } | |
428 | ||
429 | spin_unlock_irqrestore(&lgff->lock, flags); | |
430 | return 0; | |
431 | } | |
432 | ||
433 | static void hid_lgff_timer(unsigned long timer_data) | |
434 | { | |
435 | struct lgff_device *lgff = (struct lgff_device*)timer_data; | |
436 | struct hid_device *hid = lgff->hid; | |
437 | unsigned long flags; | |
438 | int x = 0x7f, y = 0x7f; // Coordinates of constant effects | |
439 | unsigned int left = 0, right = 0; // Rumbling | |
440 | int i; | |
441 | ||
442 | spin_lock_irqsave(&lgff->lock, flags); | |
443 | ||
444 | for (i=0; i<LGFF_EFFECTS; ++i) { | |
445 | struct lgff_effect* effect = lgff->effects +i; | |
446 | ||
447 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | |
448 | ||
449 | switch (effect->effect.type) { | |
450 | case FF_CONSTANT: { | |
451 | //TODO: handle envelopes | |
452 | int degrees = effect->effect.direction * 360 >> 16; | |
453 | x += fixp_mult(fixp_sin(degrees), | |
454 | fixp_new16(effect->effect.u.constant.level)); | |
455 | y += fixp_mult(-fixp_cos(degrees), | |
456 | fixp_new16(effect->effect.u.constant.level)); | |
457 | } break; | |
458 | case FF_RUMBLE: | |
459 | right += effect->effect.u.rumble.strong_magnitude; | |
460 | left += effect->effect.u.rumble.weak_magnitude; | |
461 | break; | |
462 | }; | |
463 | ||
464 | /* One run of the effect is finished playing */ | |
465 | if (time_after(jiffies, | |
466 | effect->started_at | |
467 | + effect->effect.replay.delay*HZ/1000 | |
468 | + effect->effect.replay.length*HZ/1000)) { | |
469 | dbg("Finished playing once %d", i); | |
470 | if (--effect->count <= 0) { | |
471 | dbg("Stopped %d", i); | |
472 | clear_bit(EFFECT_PLAYING, effect->flags); | |
473 | } | |
474 | else { | |
475 | dbg("Start again %d", i); | |
476 | if (effect->effect.replay.length != 0) { | |
477 | clear_bit(EFFECT_PLAYING, effect->flags); | |
478 | set_bit(EFFECT_STARTED, effect->flags); | |
479 | } | |
480 | effect->started_at = jiffies; | |
481 | } | |
482 | } | |
483 | ||
484 | } else if (test_bit(EFFECT_STARTED, lgff->effects[i].flags)) { | |
485 | /* Check if we should start playing the effect */ | |
486 | if (time_after(jiffies, | |
487 | lgff->effects[i].started_at | |
488 | + lgff->effects[i].effect.replay.delay*HZ/1000)) { | |
489 | dbg("Now playing %d", i); | |
490 | clear_bit(EFFECT_STARTED, lgff->effects[i].flags); | |
491 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); | |
492 | } | |
493 | } | |
494 | } | |
495 | ||
496 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | |
497 | ||
498 | // Clamp values | |
499 | CLAMP(x); | |
500 | CLAMP(y); | |
501 | CLAMP(left); | |
502 | CLAMP(right); | |
503 | ||
504 | #undef CLAMP | |
505 | ||
506 | if (x != lgff->constant->field[0]->value[2] | |
507 | || y != lgff->constant->field[0]->value[3]) { | |
508 | lgff->constant->field[0]->value[2] = x; | |
509 | lgff->constant->field[0]->value[3] = y; | |
510 | dbg("(x,y)=(%04x, %04x)", x, y); | |
511 | hid_submit_report(hid, lgff->constant, USB_DIR_OUT); | |
512 | } | |
513 | ||
514 | if (left != lgff->rumble->field[0]->value[2] | |
515 | || right != lgff->rumble->field[0]->value[3]) { | |
516 | lgff->rumble->field[0]->value[2] = left; | |
517 | lgff->rumble->field[0]->value[3] = right; | |
518 | dbg("(left,right)=(%04x, %04x)", left, right); | |
519 | hid_submit_report(hid, lgff->rumble, USB_DIR_OUT); | |
520 | } | |
521 | ||
522 | if (!test_bit(DEVICE_CLOSING, lgff->flags)) { | |
523 | lgff->timer.expires = RUN_AT(PERIOD); | |
524 | add_timer(&lgff->timer); | |
525 | } | |
526 | ||
527 | spin_unlock_irqrestore(&lgff->lock, flags); | |
528 | } |