Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hid-lg.c
Go to the documentation of this file.
1 /*
2  * HID driver for some logitech "special" devices
3  *
4  * Copyright (c) 1999 Andreas Gal
5  * Copyright (c) 2000-2005 Vojtech Pavlik <[email protected]>
6  * Copyright (c) 2005 Michael Haboustak <[email protected]> for Concept2, Inc
7  * Copyright (c) 2006-2007 Jiri Kosina
8  * Copyright (c) 2008 Jiri Slaby
9  * Copyright (c) 2010 Hendrik Iben
10  */
11 
12 /*
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the Free
15  * Software Foundation; either version 2 of the License, or (at your option)
16  * any later version.
17  */
18 
19 #include <linux/device.h>
20 #include <linux/hid.h>
21 #include <linux/module.h>
22 #include <linux/random.h>
23 #include <linux/sched.h>
24 #include <linux/wait.h>
25 
26 #include "hid-ids.h"
27 #include "hid-lg.h"
28 
29 #define LG_RDESC 0x001
30 #define LG_BAD_RELATIVE_KEYS 0x002
31 #define LG_DUPLICATE_USAGES 0x004
32 #define LG_EXPANDED_KEYMAP 0x010
33 #define LG_IGNORE_DOUBLED_WHEEL 0x020
34 #define LG_WIRELESS 0x040
35 #define LG_INVERT_HWHEEL 0x080
36 #define LG_NOGET 0x100
37 #define LG_FF 0x200
38 #define LG_FF2 0x400
39 #define LG_RDESC_REL_ABS 0x800
40 #define LG_FF3 0x1000
41 #define LG_FF4 0x2000
42 
43 /* Size of the original descriptor of the Driving Force Pro wheel */
44 #define DFP_RDESC_ORIG_SIZE 97
45 
46 /* Fixed report descriptor for Logitech Driving Force Pro wheel controller
47  *
48  * The original descriptor hides the separate throttle and brake axes in
49  * a custom vendor usage page, providing only a combined value as
50  * GenericDesktop.Y.
51  * This descriptor removes the combined Y axis and instead reports
52  * separate throttle (Y) and brake (RZ).
53  */
54 static __u8 dfp_rdesc_fixed[] = {
55 0x05, 0x01, /* Usage Page (Desktop), */
56 0x09, 0x04, /* Usage (Joystik), */
57 0xA1, 0x01, /* Collection (Application), */
58 0xA1, 0x02, /* Collection (Logical), */
59 0x95, 0x01, /* Report Count (1), */
60 0x75, 0x0E, /* Report Size (14), */
61 0x14, /* Logical Minimum (0), */
62 0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */
63 0x34, /* Physical Minimum (0), */
64 0x46, 0xFF, 0x3F, /* Physical Maximum (16383), */
65 0x09, 0x30, /* Usage (X), */
66 0x81, 0x02, /* Input (Variable), */
67 0x95, 0x0E, /* Report Count (14), */
68 0x75, 0x01, /* Report Size (1), */
69 0x25, 0x01, /* Logical Maximum (1), */
70 0x45, 0x01, /* Physical Maximum (1), */
71 0x05, 0x09, /* Usage Page (Button), */
72 0x19, 0x01, /* Usage Minimum (01h), */
73 0x29, 0x0E, /* Usage Maximum (0Eh), */
74 0x81, 0x02, /* Input (Variable), */
75 0x05, 0x01, /* Usage Page (Desktop), */
76 0x95, 0x01, /* Report Count (1), */
77 0x75, 0x04, /* Report Size (4), */
78 0x25, 0x07, /* Logical Maximum (7), */
79 0x46, 0x3B, 0x01, /* Physical Maximum (315), */
80 0x65, 0x14, /* Unit (Degrees), */
81 0x09, 0x39, /* Usage (Hat Switch), */
82 0x81, 0x42, /* Input (Variable, Nullstate), */
83 0x65, 0x00, /* Unit, */
84 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
85 0x46, 0xFF, 0x00, /* Physical Maximum (255), */
86 0x75, 0x08, /* Report Size (8), */
87 0x81, 0x01, /* Input (Constant), */
88 0x09, 0x31, /* Usage (Y), */
89 0x81, 0x02, /* Input (Variable), */
90 0x09, 0x35, /* Usage (Rz), */
91 0x81, 0x02, /* Input (Variable), */
92 0x81, 0x01, /* Input (Constant), */
93 0xC0, /* End Collection, */
94 0xA1, 0x02, /* Collection (Logical), */
95 0x09, 0x02, /* Usage (02h), */
96 0x95, 0x07, /* Report Count (7), */
97 0x91, 0x02, /* Output (Variable), */
98 0xC0, /* End Collection, */
99 0xC0 /* End Collection */
100 };
101 
102 
103 /*
104  * Certain Logitech keyboards send in report #3 keys which are far
105  * above the logical maximum described in descriptor. This extends
106  * the original value of 0x28c of logical maximum to 0x104d
107  */
108 static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
109  unsigned int *rsize)
110 {
111  struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
112 
113  if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
114  rdesc[84] == 0x8c && rdesc[85] == 0x02) {
115  hid_info(hdev,
116  "fixing up Logitech keyboard report descriptor\n");
117  rdesc[84] = rdesc[89] = 0x4d;
118  rdesc[85] = rdesc[90] = 0x10;
119  }
120  if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
121  rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
122  rdesc[49] == 0x81 && rdesc[50] == 0x06) {
123  hid_info(hdev,
124  "fixing up rel/abs in Logitech report descriptor\n");
125  rdesc[33] = rdesc[50] = 0x02;
126  }
127  if ((drv_data->quirks & LG_FF4) && *rsize >= 101 &&
128  rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
129  rdesc[47] == 0x05 && rdesc[48] == 0x09) {
130  hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n");
131  rdesc[41] = 0x05;
132  rdesc[42] = 0x09;
133  rdesc[47] = 0x95;
134  rdesc[48] = 0x0B;
135  }
136 
137  switch (hdev->product) {
139  if (*rsize == DFP_RDESC_ORIG_SIZE) {
140  hid_info(hdev,
141  "fixing up Logitech Driving Force Pro report descriptor\n");
142  rdesc = dfp_rdesc_fixed;
143  *rsize = sizeof(dfp_rdesc_fixed);
144  }
145  break;
146  }
147 
148  return rdesc;
149 }
150 
151 #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \
152  EV_KEY, (c))
153 
154 static int lg_ultrax_remote_mapping(struct hid_input *hi,
155  struct hid_usage *usage, unsigned long **bit, int *max)
156 {
157  if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
158  return 0;
159 
160  set_bit(EV_REP, hi->input->evbit);
161  switch (usage->hid & HID_USAGE) {
162  /* Reported on Logitech Ultra X Media Remote */
163  case 0x004: lg_map_key_clear(KEY_AGAIN); break;
164  case 0x00d: lg_map_key_clear(KEY_HOME); break;
165  case 0x024: lg_map_key_clear(KEY_SHUFFLE); break;
166  case 0x025: lg_map_key_clear(KEY_TV); break;
167  case 0x026: lg_map_key_clear(KEY_MENU); break;
168  case 0x031: lg_map_key_clear(KEY_AUDIO); break;
169  case 0x032: lg_map_key_clear(KEY_TEXT); break;
170  case 0x033: lg_map_key_clear(KEY_LAST); break;
171  case 0x047: lg_map_key_clear(KEY_MP3); break;
172  case 0x048: lg_map_key_clear(KEY_DVD); break;
173  case 0x049: lg_map_key_clear(KEY_MEDIA); break;
174  case 0x04a: lg_map_key_clear(KEY_VIDEO); break;
175  case 0x04b: lg_map_key_clear(KEY_ANGLE); break;
176  case 0x04c: lg_map_key_clear(KEY_LANGUAGE); break;
177  case 0x04d: lg_map_key_clear(KEY_SUBTITLE); break;
178  case 0x051: lg_map_key_clear(KEY_RED); break;
179  case 0x052: lg_map_key_clear(KEY_CLOSE); break;
180 
181  default:
182  return 0;
183  }
184  return 1;
185 }
186 
187 static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage,
188  unsigned long **bit, int *max)
189 {
190  if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
191  return 0;
192 
193  switch (usage->hid & HID_USAGE) {
194 
195  case 0x00d: lg_map_key_clear(KEY_MEDIA); break;
196  default:
197  return 0;
198 
199  }
200  return 1;
201 }
202 
203 static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage,
204  unsigned long **bit, int *max)
205 {
206  if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
207  return 0;
208 
209  switch (usage->hid & HID_USAGE) {
210  case 0x1001: lg_map_key_clear(KEY_MESSENGER); break;
211  case 0x1003: lg_map_key_clear(KEY_SOUND); break;
212  case 0x1004: lg_map_key_clear(KEY_VIDEO); break;
213  case 0x1005: lg_map_key_clear(KEY_AUDIO); break;
214  case 0x100a: lg_map_key_clear(KEY_DOCUMENTS); break;
215  /* The following two entries are Playlist 1 and 2 on the MX3200 */
216  case 0x100f: lg_map_key_clear(KEY_FN_1); break;
217  case 0x1010: lg_map_key_clear(KEY_FN_2); break;
218  case 0x1011: lg_map_key_clear(KEY_PREVIOUSSONG); break;
219  case 0x1012: lg_map_key_clear(KEY_NEXTSONG); break;
220  case 0x1013: lg_map_key_clear(KEY_CAMERA); break;
221  case 0x1014: lg_map_key_clear(KEY_MESSENGER); break;
222  case 0x1015: lg_map_key_clear(KEY_RECORD); break;
223  case 0x1016: lg_map_key_clear(KEY_PLAYER); break;
224  case 0x1017: lg_map_key_clear(KEY_EJECTCD); break;
225  case 0x1018: lg_map_key_clear(KEY_MEDIA); break;
226  case 0x1019: lg_map_key_clear(KEY_PROG1); break;
227  case 0x101a: lg_map_key_clear(KEY_PROG2); break;
228  case 0x101b: lg_map_key_clear(KEY_PROG3); break;
229  case 0x101c: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
230  case 0x101f: lg_map_key_clear(KEY_ZOOMIN); break;
231  case 0x1020: lg_map_key_clear(KEY_ZOOMOUT); break;
232  case 0x1021: lg_map_key_clear(KEY_ZOOMRESET); break;
233  case 0x1023: lg_map_key_clear(KEY_CLOSE); break;
234  case 0x1027: lg_map_key_clear(KEY_MENU); break;
235  /* this one is marked as 'Rotate' */
236  case 0x1028: lg_map_key_clear(KEY_ANGLE); break;
237  case 0x1029: lg_map_key_clear(KEY_SHUFFLE); break;
238  case 0x102a: lg_map_key_clear(KEY_BACK); break;
239  case 0x102b: lg_map_key_clear(KEY_CYCLEWINDOWS); break;
240  case 0x102d: lg_map_key_clear(KEY_WWW); break;
241  /* The following two are 'Start/answer call' and 'End/reject call'
242  on the MX3200 */
243  case 0x1031: lg_map_key_clear(KEY_OK); break;
244  case 0x1032: lg_map_key_clear(KEY_CANCEL); break;
245  case 0x1041: lg_map_key_clear(KEY_BATTERY); break;
246  case 0x1042: lg_map_key_clear(KEY_WORDPROCESSOR); break;
247  case 0x1043: lg_map_key_clear(KEY_SPREADSHEET); break;
248  case 0x1044: lg_map_key_clear(KEY_PRESENTATION); break;
249  case 0x1045: lg_map_key_clear(KEY_UNDO); break;
250  case 0x1046: lg_map_key_clear(KEY_REDO); break;
251  case 0x1047: lg_map_key_clear(KEY_PRINT); break;
252  case 0x1048: lg_map_key_clear(KEY_SAVE); break;
253  case 0x1049: lg_map_key_clear(KEY_PROG1); break;
254  case 0x104a: lg_map_key_clear(KEY_PROG2); break;
255  case 0x104b: lg_map_key_clear(KEY_PROG3); break;
256  case 0x104c: lg_map_key_clear(KEY_PROG4); break;
257 
258  default:
259  return 0;
260  }
261  return 1;
262 }
263 
264 static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi,
265  struct hid_field *field, struct hid_usage *usage,
266  unsigned long **bit, int *max)
267 {
268  /* extended mapping for certain Logitech hardware (Logitech cordless
269  desktop LX500) */
270  static const u8 e_keymap[] = {
271  0,216, 0,213,175,156, 0, 0, 0, 0,
272  144, 0, 0, 0, 0, 0, 0, 0, 0,212,
273  174,167,152,161,112, 0, 0, 0,154, 0,
274  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
275  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
276  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277  0, 0, 0, 0, 0,183,184,185,186,187,
278  188,189,190,191,192,193,194, 0, 0, 0
279  };
280  struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
281  unsigned int hid = usage->hid;
282 
284  lg_ultrax_remote_mapping(hi, usage, bit, max))
285  return 1;
286 
287  if (hdev->product == USB_DEVICE_ID_DINOVO_MINI &&
288  lg_dinovo_mapping(hi, usage, bit, max))
289  return 1;
290 
291  if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max))
292  return 1;
293 
294  if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
295  return 0;
296 
297  hid &= HID_USAGE;
298 
299  /* Special handling for Logitech Cordless Desktop */
300  if (field->application == HID_GD_MOUSE) {
301  if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) &&
302  (hid == 7 || hid == 8))
303  return -1;
304  } else {
305  if ((drv_data->quirks & LG_EXPANDED_KEYMAP) &&
306  hid < ARRAY_SIZE(e_keymap) &&
307  e_keymap[hid] != 0) {
308  hid_map_usage(hi, usage, bit, max, EV_KEY,
309  e_keymap[hid]);
310  return 1;
311  }
312  }
313 
314  return 0;
315 }
316 
317 static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
318  struct hid_field *field, struct hid_usage *usage,
319  unsigned long **bit, int *max)
320 {
321  struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
322 
323  if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY &&
324  (field->flags & HID_MAIN_ITEM_RELATIVE))
325  field->flags &= ~HID_MAIN_ITEM_RELATIVE;
326 
327  if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY ||
328  usage->type == EV_REL || usage->type == EV_ABS))
329  clear_bit(usage->code, *bit);
330 
331  return 0;
332 }
333 
334 static int lg_event(struct hid_device *hdev, struct hid_field *field,
335  struct hid_usage *usage, __s32 value)
336 {
337  struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
338 
339  if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) {
340  input_event(field->hidinput->input, usage->type, usage->code,
341  -value);
342  return 1;
343  }
344  if (drv_data->quirks & LG_FF4) {
345  return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data);
346  }
347 
348  return 0;
349 }
350 
351 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
352 {
353  unsigned int connect_mask = HID_CONNECT_DEFAULT;
354  struct lg_drv_data *drv_data;
355  int ret;
356 
357  drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
358  if (!drv_data) {
359  hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
360  return -ENOMEM;
361  }
362  drv_data->quirks = id->driver_data;
363 
364  hid_set_drvdata(hdev, (void *)drv_data);
365 
366  if (drv_data->quirks & LG_NOGET)
367  hdev->quirks |= HID_QUIRK_NOGET;
368 
369  ret = hid_parse(hdev);
370  if (ret) {
371  hid_err(hdev, "parse failed\n");
372  goto err_free;
373  }
374 
375  if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
376  connect_mask &= ~HID_CONNECT_FF;
377 
378  ret = hid_hw_start(hdev, connect_mask);
379  if (ret) {
380  hid_err(hdev, "hw start failed\n");
381  goto err_free;
382  }
383 
384  /* Setup wireless link with Logitech Wii wheel */
386  unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
387 
388  ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
389 
390  if (ret >= 0) {
391  /* insert a little delay of 10 jiffies ~ 40ms */
393  init_waitqueue_head (&wait);
395 
396  /* Select random Address */
397  buf[1] = 0xB2;
398  get_random_bytes(&buf[2], 2);
399 
400  ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
401  }
402  }
403 
404  if (drv_data->quirks & LG_FF)
405  lgff_init(hdev);
406  if (drv_data->quirks & LG_FF2)
407  lg2ff_init(hdev);
408  if (drv_data->quirks & LG_FF3)
409  lg3ff_init(hdev);
410  if (drv_data->quirks & LG_FF4)
411  lg4ff_init(hdev);
412 
413  return 0;
414 err_free:
415  kfree(drv_data);
416  return ret;
417 }
418 
419 static void lg_remove(struct hid_device *hdev)
420 {
421  struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
422  if (drv_data->quirks & LG_FF4)
423  lg4ff_deinit(hdev);
424 
425  hid_hw_stop(hdev);
426  kfree(drv_data);
427 }
428 
429 static const struct hid_device_id lg_devices[] = {
431  .driver_data = LG_RDESC | LG_WIRELESS },
433  .driver_data = LG_RDESC | LG_WIRELESS },
435  .driver_data = LG_RDESC | LG_WIRELESS },
436 
438  .driver_data = LG_BAD_RELATIVE_KEYS },
439 
441  .driver_data = LG_DUPLICATE_USAGES },
443  .driver_data = LG_DUPLICATE_USAGES },
445  .driver_data = LG_DUPLICATE_USAGES },
446 
448  .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
450  .driver_data = LG_IGNORE_DOUBLED_WHEEL | LG_EXPANDED_KEYMAP },
451 
453  .driver_data = LG_NOGET },
455  .driver_data = LG_NOGET | LG_FF4 },
456 
458  .driver_data = LG_FF2 },
460  .driver_data = LG_FF },
462  .driver_data = LG_FF },
464  .driver_data = LG_FF },
466  .driver_data = LG_FF },
468  .driver_data = LG_FF4 },
470  .driver_data = LG_FF4 },
472  .driver_data = LG_FF4 },
474  .driver_data = LG_FF4 },
476  .driver_data = LG_FF4 },
478  .driver_data = LG_NOGET | LG_FF4 },
480  .driver_data = LG_FF4 },
482  .driver_data = LG_FF },
484  .driver_data = LG_FF2 },
486  .driver_data = LG_FF3 },
488  .driver_data = LG_RDESC_REL_ABS },
490  .driver_data = LG_RDESC_REL_ABS },
491  { }
492 };
493 
494 MODULE_DEVICE_TABLE(hid, lg_devices);
495 
496 static struct hid_driver lg_driver = {
497  .name = "logitech",
498  .id_table = lg_devices,
499  .report_fixup = lg_report_fixup,
500  .input_mapping = lg_input_mapping,
501  .input_mapped = lg_input_mapped,
502  .event = lg_event,
503  .probe = lg_probe,
504  .remove = lg_remove,
505 };
506 
507 static int __init lg_init(void)
508 {
509  return hid_register_driver(&lg_driver);
510 }
511 
512 static void __exit lg_exit(void)
513 {
514  hid_unregister_driver(&lg_driver);
515 }
516 
517 module_init(lg_init);
518 module_exit(lg_exit);
519 MODULE_LICENSE("GPL");