1 /* 2 * Force feedback support for Logitech Gaming Wheels 3 * 4 * Including G27, G25, DFP, DFGT, FFEX, Momo, Momo2 & 5 * Speed Force Wireless (WiiWheel) 6 * 7 * Copyright (c) 2010 Simon Wood <simon@mungewell.org> 8 */ 9 10 /* 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26 27 #include <linux/input.h> 28 #include <linux/usb.h> 29 #include <linux/hid.h> 30 31 #include "usbhid/usbhid.h" 32 #include "hid-lg.h" 33 #include "hid-ids.h" 34 35 #define DFGT_REV_MAJ 0x13 36 #define DFGT_REV_MIN 0x22 37 #define DFGT2_REV_MIN 0x26 38 #define DFP_REV_MAJ 0x11 39 #define DFP_REV_MIN 0x06 40 #define FFEX_REV_MAJ 0x21 41 #define FFEX_REV_MIN 0x00 42 #define G25_REV_MAJ 0x12 43 #define G25_REV_MIN 0x22 44 #define G27_REV_MAJ 0x12 45 #define G27_REV_MIN 0x38 46 #define G27_2_REV_MIN 0x39 47 48 #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev) 49 50 static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range); 51 static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range); 52 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf); 53 static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count); 54 55 static DEVICE_ATTR(range, S_IRWXU | S_IRWXG | S_IROTH, lg4ff_range_show, lg4ff_range_store); 56 57 struct lg4ff_device_entry { 58 __u32 product_id; 59 __u16 range; 60 __u16 min_range; 61 __u16 max_range; 62 #ifdef CONFIG_LEDS_CLASS 63 __u8 led_state; 64 struct led_classdev *led[5]; 65 #endif 66 struct list_head list; 67 void (*set_range)(struct hid_device *hid, u16 range); 68 }; 69 70 static const signed short lg4ff_wheel_effects[] = { 71 FF_CONSTANT, 72 FF_AUTOCENTER, 73 -1 74 }; 75 76 struct lg4ff_wheel { 77 const __u32 product_id; 78 const signed short *ff_effects; 79 const __u16 min_range; 80 const __u16 max_range; 81 void (*set_range)(struct hid_device *hid, u16 range); 82 }; 83 84 static const struct lg4ff_wheel lg4ff_devices[] = { 85 {USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, 86 {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, 87 {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_dfp}, 88 {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, 89 {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, 90 {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, 91 {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL}, 92 {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL} 93 }; 94 95 struct lg4ff_native_cmd { 96 const __u8 cmd_num; /* Number of commands to send */ 97 const __u8 cmd[]; 98 }; 99 100 struct lg4ff_usb_revision { 101 const __u16 rev_maj; 102 const __u16 rev_min; 103 const struct lg4ff_native_cmd *command; 104 }; 105 106 static const struct lg4ff_native_cmd native_dfp = { 107 1, 108 {0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00} 109 }; 110 111 static const struct lg4ff_native_cmd native_dfgt = { 112 2, 113 {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1st command */ 114 0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00} /* 2nd command */ 115 }; 116 117 static const struct lg4ff_native_cmd native_g25 = { 118 1, 119 {0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00} 120 }; 121 122 static const struct lg4ff_native_cmd native_g27 = { 123 2, 124 {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1st command */ 125 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* 2nd command */ 126 }; 127 128 static const struct lg4ff_usb_revision lg4ff_revs[] = { 129 {DFGT_REV_MAJ, DFGT_REV_MIN, &native_dfgt}, /* Driving Force GT */ 130 {DFGT_REV_MAJ, DFGT2_REV_MIN, &native_dfgt}, /* Driving Force GT v2 */ 131 {DFP_REV_MAJ, DFP_REV_MIN, &native_dfp}, /* Driving Force Pro */ 132 {G25_REV_MAJ, G25_REV_MIN, &native_g25}, /* G25 */ 133 {G27_REV_MAJ, G27_REV_MIN, &native_g27}, /* G27 */ 134 {G27_REV_MAJ, G27_2_REV_MIN, &native_g27}, /* G27 v2 */ 135 }; 136 137 /* Recalculates X axis value accordingly to currently selected range */ 138 static __s32 lg4ff_adjust_dfp_x_axis(__s32 value, __u16 range) 139 { 140 __u16 max_range; 141 __s32 new_value; 142 143 if (range == 900) 144 return value; 145 else if (range == 200) 146 return value; 147 else if (range < 200) 148 max_range = 200; 149 else 150 max_range = 900; 151 152 new_value = 8192 + mult_frac(value - 8192, max_range, range); 153 if (new_value < 0) 154 return 0; 155 else if (new_value > 16383) 156 return 16383; 157 else 158 return new_value; 159 } 160 161 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, 162 struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data) 163 { 164 struct lg4ff_device_entry *entry = drv_data->device_props; 165 __s32 new_value = 0; 166 167 if (!entry) { 168 hid_err(hid, "Device properties not found"); 169 return 0; 170 } 171 172 switch (entry->product_id) { 173 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 174 switch (usage->code) { 175 case ABS_X: 176 new_value = lg4ff_adjust_dfp_x_axis(value, entry->range); 177 input_event(field->hidinput->input, usage->type, usage->code, new_value); 178 return 1; 179 default: 180 return 0; 181 } 182 default: 183 return 0; 184 } 185 } 186 187 static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) 188 { 189 struct hid_device *hid = input_get_drvdata(dev); 190 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 191 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 192 __s32 *value = report->field[0]->value; 193 int x; 194 195 #define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0) 196 197 switch (effect->type) { 198 case FF_CONSTANT: 199 x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ 200 CLAMP(x); 201 202 if (x == 0x80) { 203 /* De-activate force in slot-1*/ 204 value[0] = 0x13; 205 value[1] = 0x00; 206 value[2] = 0x00; 207 value[3] = 0x00; 208 value[4] = 0x00; 209 value[5] = 0x00; 210 value[6] = 0x00; 211 212 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 213 return 0; 214 } 215 216 value[0] = 0x11; /* Slot 1 */ 217 value[1] = 0x08; 218 value[2] = x; 219 value[3] = 0x80; 220 value[4] = 0x00; 221 value[5] = 0x00; 222 value[6] = 0x00; 223 224 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 225 break; 226 } 227 return 0; 228 } 229 230 /* Sends default autocentering command compatible with 231 * all wheels except Formula Force EX */ 232 static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) 233 { 234 struct hid_device *hid = input_get_drvdata(dev); 235 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 236 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 237 __s32 *value = report->field[0]->value; 238 __u32 expand_a, expand_b; 239 struct lg4ff_device_entry *entry; 240 struct lg_drv_data *drv_data; 241 242 drv_data = hid_get_drvdata(hid); 243 if (!drv_data) { 244 hid_err(hid, "Private driver data not found!\n"); 245 return; 246 } 247 248 entry = drv_data->device_props; 249 if (!entry) { 250 hid_err(hid, "Device properties not found!\n"); 251 return; 252 } 253 254 /* De-activate Auto-Center */ 255 if (magnitude == 0) { 256 value[0] = 0xf5; 257 value[1] = 0x00; 258 value[2] = 0x00; 259 value[3] = 0x00; 260 value[4] = 0x00; 261 value[5] = 0x00; 262 value[6] = 0x00; 263 264 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 265 return; 266 } 267 268 if (magnitude <= 0xaaaa) { 269 expand_a = 0x0c * magnitude; 270 expand_b = 0x80 * magnitude; 271 } else { 272 expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa); 273 expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa); 274 } 275 276 /* Adjust for non-MOMO wheels */ 277 switch (entry->product_id) { 278 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: 279 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: 280 break; 281 default: 282 expand_a = expand_a >> 1; 283 break; 284 } 285 286 value[0] = 0xfe; 287 value[1] = 0x0d; 288 value[2] = expand_a / 0xaaaa; 289 value[3] = expand_a / 0xaaaa; 290 value[4] = expand_b / 0xaaaa; 291 value[5] = 0x00; 292 value[6] = 0x00; 293 294 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 295 296 /* Activate Auto-Center */ 297 value[0] = 0x14; 298 value[1] = 0x00; 299 value[2] = 0x00; 300 value[3] = 0x00; 301 value[4] = 0x00; 302 value[5] = 0x00; 303 value[6] = 0x00; 304 305 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 306 } 307 308 /* Sends autocentering command compatible with Formula Force EX */ 309 static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) 310 { 311 struct hid_device *hid = input_get_drvdata(dev); 312 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 313 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 314 __s32 *value = report->field[0]->value; 315 magnitude = magnitude * 90 / 65535; 316 317 value[0] = 0xfe; 318 value[1] = 0x03; 319 value[2] = magnitude >> 14; 320 value[3] = magnitude >> 14; 321 value[4] = magnitude; 322 value[5] = 0x00; 323 value[6] = 0x00; 324 325 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 326 } 327 328 /* Sends command to set range compatible with G25/G27/Driving Force GT */ 329 static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) 330 { 331 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 332 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 333 __s32 *value = report->field[0]->value; 334 335 dbg_hid("G25/G27/DFGT: setting range to %u\n", range); 336 337 value[0] = 0xf8; 338 value[1] = 0x81; 339 value[2] = range & 0x00ff; 340 value[3] = (range & 0xff00) >> 8; 341 value[4] = 0x00; 342 value[5] = 0x00; 343 value[6] = 0x00; 344 345 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 346 } 347 348 /* Sends commands to set range compatible with Driving Force Pro wheel */ 349 static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) 350 { 351 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 352 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 353 int start_left, start_right, full_range; 354 __s32 *value = report->field[0]->value; 355 356 dbg_hid("Driving Force Pro: setting range to %u\n", range); 357 358 /* Prepare "coarse" limit command */ 359 value[0] = 0xf8; 360 value[1] = 0x00; /* Set later */ 361 value[2] = 0x00; 362 value[3] = 0x00; 363 value[4] = 0x00; 364 value[5] = 0x00; 365 value[6] = 0x00; 366 367 if (range > 200) { 368 report->field[0]->value[1] = 0x03; 369 full_range = 900; 370 } else { 371 report->field[0]->value[1] = 0x02; 372 full_range = 200; 373 } 374 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 375 376 /* Prepare "fine" limit command */ 377 value[0] = 0x81; 378 value[1] = 0x0b; 379 value[2] = 0x00; 380 value[3] = 0x00; 381 value[4] = 0x00; 382 value[5] = 0x00; 383 value[6] = 0x00; 384 385 if (range == 200 || range == 900) { /* Do not apply any fine limit */ 386 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 387 return; 388 } 389 390 /* Construct fine limit command */ 391 start_left = (((full_range - range + 1) * 2047) / full_range); 392 start_right = 0xfff - start_left; 393 394 value[2] = start_left >> 4; 395 value[3] = start_right >> 4; 396 value[4] = 0xff; 397 value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); 398 value[6] = 0xff; 399 400 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 401 } 402 403 static void hid_lg4ff_switch_native(struct hid_device *hid, const struct lg4ff_native_cmd *cmd) 404 { 405 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 406 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 407 __u8 i, j; 408 409 j = 0; 410 while (j < 7*cmd->cmd_num) { 411 for (i = 0; i < 7; i++) 412 report->field[0]->value[i] = cmd->cmd[j++]; 413 414 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 415 } 416 } 417 418 /* Read current range and display it in terminal */ 419 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, char *buf) 420 { 421 struct hid_device *hid = to_hid_device(dev); 422 struct lg4ff_device_entry *entry; 423 struct lg_drv_data *drv_data; 424 size_t count; 425 426 drv_data = hid_get_drvdata(hid); 427 if (!drv_data) { 428 hid_err(hid, "Private driver data not found!\n"); 429 return 0; 430 } 431 432 entry = drv_data->device_props; 433 if (!entry) { 434 hid_err(hid, "Device properties not found!\n"); 435 return 0; 436 } 437 438 count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->range); 439 return count; 440 } 441 442 /* Set range to user specified value, call appropriate function 443 * according to the type of the wheel */ 444 static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 445 { 446 struct hid_device *hid = to_hid_device(dev); 447 struct lg4ff_device_entry *entry; 448 struct lg_drv_data *drv_data; 449 __u16 range = simple_strtoul(buf, NULL, 10); 450 451 drv_data = hid_get_drvdata(hid); 452 if (!drv_data) { 453 hid_err(hid, "Private driver data not found!\n"); 454 return -EINVAL; 455 } 456 457 entry = drv_data->device_props; 458 if (!entry) { 459 hid_err(hid, "Device properties not found!\n"); 460 return -EINVAL; 461 } 462 463 if (range == 0) 464 range = entry->max_range; 465 466 /* Check if the wheel supports range setting 467 * and that the range is within limits for the wheel */ 468 if (entry->set_range != NULL && range >= entry->min_range && range <= entry->max_range) { 469 entry->set_range(hid, range); 470 entry->range = range; 471 } 472 473 return count; 474 } 475 476 #ifdef CONFIG_LEDS_CLASS 477 static void lg4ff_set_leds(struct hid_device *hid, __u8 leds) 478 { 479 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 480 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 481 __s32 *value = report->field[0]->value; 482 483 value[0] = 0xf8; 484 value[1] = 0x12; 485 value[2] = leds; 486 value[3] = 0x00; 487 value[4] = 0x00; 488 value[5] = 0x00; 489 value[6] = 0x00; 490 hid_hw_request(hid, report, HID_REQ_SET_REPORT); 491 } 492 493 static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, 494 enum led_brightness value) 495 { 496 struct device *dev = led_cdev->dev->parent; 497 struct hid_device *hid = container_of(dev, struct hid_device, dev); 498 struct lg_drv_data *drv_data = hid_get_drvdata(hid); 499 struct lg4ff_device_entry *entry; 500 int i, state = 0; 501 502 if (!drv_data) { 503 hid_err(hid, "Device data not found."); 504 return; 505 } 506 507 entry = (struct lg4ff_device_entry *)drv_data->device_props; 508 509 if (!entry) { 510 hid_err(hid, "Device properties not found."); 511 return; 512 } 513 514 for (i = 0; i < 5; i++) { 515 if (led_cdev != entry->led[i]) 516 continue; 517 state = (entry->led_state >> i) & 1; 518 if (value == LED_OFF && state) { 519 entry->led_state &= ~(1 << i); 520 lg4ff_set_leds(hid, entry->led_state); 521 } else if (value != LED_OFF && !state) { 522 entry->led_state |= 1 << i; 523 lg4ff_set_leds(hid, entry->led_state); 524 } 525 break; 526 } 527 } 528 529 static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cdev) 530 { 531 struct device *dev = led_cdev->dev->parent; 532 struct hid_device *hid = container_of(dev, struct hid_device, dev); 533 struct lg_drv_data *drv_data = hid_get_drvdata(hid); 534 struct lg4ff_device_entry *entry; 535 int i, value = 0; 536 537 if (!drv_data) { 538 hid_err(hid, "Device data not found."); 539 return LED_OFF; 540 } 541 542 entry = (struct lg4ff_device_entry *)drv_data->device_props; 543 544 if (!entry) { 545 hid_err(hid, "Device properties not found."); 546 return LED_OFF; 547 } 548 549 for (i = 0; i < 5; i++) 550 if (led_cdev == entry->led[i]) { 551 value = (entry->led_state >> i) & 1; 552 break; 553 } 554 555 return value ? LED_FULL : LED_OFF; 556 } 557 #endif 558 559 int lg4ff_init(struct hid_device *hid) 560 { 561 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); 562 struct input_dev *dev = hidinput->input; 563 struct lg4ff_device_entry *entry; 564 struct lg_drv_data *drv_data; 565 struct usb_device_descriptor *udesc; 566 int error, i, j; 567 __u16 bcdDevice, rev_maj, rev_min; 568 569 /* Check that the report looks ok */ 570 if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) 571 return -1; 572 573 /* Check what wheel has been connected */ 574 for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { 575 if (hid->product == lg4ff_devices[i].product_id) { 576 dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id); 577 break; 578 } 579 } 580 581 if (i == ARRAY_SIZE(lg4ff_devices)) { 582 hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to" 583 "LKML, Simon Wood <simon@mungewell.org> or Michal Maly <madcatxster@gmail.com>\n"); 584 return -1; 585 } 586 587 /* Attempt to switch wheel to native mode when applicable */ 588 udesc = &(hid_to_usb_dev(hid)->descriptor); 589 if (!udesc) { 590 hid_err(hid, "NULL USB device descriptor\n"); 591 return -1; 592 } 593 bcdDevice = le16_to_cpu(udesc->bcdDevice); 594 rev_maj = bcdDevice >> 8; 595 rev_min = bcdDevice & 0xff; 596 597 if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_WHEEL) { 598 dbg_hid("Generic wheel detected, can it do native?\n"); 599 dbg_hid("USB revision: %2x.%02x\n", rev_maj, rev_min); 600 601 for (j = 0; j < ARRAY_SIZE(lg4ff_revs); j++) { 602 if (lg4ff_revs[j].rev_maj == rev_maj && lg4ff_revs[j].rev_min == rev_min) { 603 hid_lg4ff_switch_native(hid, lg4ff_revs[j].command); 604 hid_info(hid, "Switched to native mode\n"); 605 } 606 } 607 } 608 609 /* Set supported force feedback capabilities */ 610 for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++) 611 set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit); 612 613 error = input_ff_create_memless(dev, NULL, hid_lg4ff_play); 614 615 if (error) 616 return error; 617 618 /* Get private driver data */ 619 drv_data = hid_get_drvdata(hid); 620 if (!drv_data) { 621 hid_err(hid, "Cannot add device, private driver data not allocated\n"); 622 return -1; 623 } 624 625 /* Initialize device properties */ 626 entry = kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL); 627 if (!entry) { 628 hid_err(hid, "Cannot add device, insufficient memory to allocate device properties.\n"); 629 return -ENOMEM; 630 } 631 drv_data->device_props = entry; 632 633 entry->product_id = lg4ff_devices[i].product_id; 634 entry->min_range = lg4ff_devices[i].min_range; 635 entry->max_range = lg4ff_devices[i].max_range; 636 entry->set_range = lg4ff_devices[i].set_range; 637 638 /* Check if autocentering is available and 639 * set the centering force to zero by default */ 640 if (test_bit(FF_AUTOCENTER, dev->ffbit)) { 641 if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ 642 dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; 643 else 644 dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; 645 646 dev->ff->set_autocenter(dev, 0); 647 } 648 649 /* Create sysfs interface */ 650 error = device_create_file(&hid->dev, &dev_attr_range); 651 if (error) 652 return error; 653 dbg_hid("sysfs interface created\n"); 654 655 /* Set the maximum range to start with */ 656 entry->range = entry->max_range; 657 if (entry->set_range != NULL) 658 entry->set_range(hid, entry->range); 659 660 #ifdef CONFIG_LEDS_CLASS 661 /* register led subsystem - G27 only */ 662 entry->led_state = 0; 663 for (j = 0; j < 5; j++) 664 entry->led[j] = NULL; 665 666 if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) { 667 struct led_classdev *led; 668 size_t name_sz; 669 char *name; 670 671 lg4ff_set_leds(hid, 0); 672 673 name_sz = strlen(dev_name(&hid->dev)) + 8; 674 675 for (j = 0; j < 5; j++) { 676 led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); 677 if (!led) { 678 hid_err(hid, "can't allocate memory for LED %d\n", j); 679 goto err; 680 } 681 682 name = (void *)(&led[1]); 683 snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1); 684 led->name = name; 685 led->brightness = 0; 686 led->max_brightness = 1; 687 led->brightness_get = lg4ff_led_get_brightness; 688 led->brightness_set = lg4ff_led_set_brightness; 689 690 entry->led[j] = led; 691 error = led_classdev_register(&hid->dev, led); 692 693 if (error) { 694 hid_err(hid, "failed to register LED %d. Aborting.\n", j); 695 err: 696 /* Deregister LEDs (if any) */ 697 for (j = 0; j < 5; j++) { 698 led = entry->led[j]; 699 entry->led[j] = NULL; 700 if (!led) 701 continue; 702 led_classdev_unregister(led); 703 kfree(led); 704 } 705 goto out; /* Let the driver continue without LEDs */ 706 } 707 } 708 } 709 out: 710 #endif 711 hid_info(hid, "Force feedback support for Logitech Gaming Wheels\n"); 712 return 0; 713 } 714 715 716 717 int lg4ff_deinit(struct hid_device *hid) 718 { 719 struct lg4ff_device_entry *entry; 720 struct lg_drv_data *drv_data; 721 722 device_remove_file(&hid->dev, &dev_attr_range); 723 724 drv_data = hid_get_drvdata(hid); 725 if (!drv_data) { 726 hid_err(hid, "Error while deinitializing device, no private driver data.\n"); 727 return -1; 728 } 729 entry = drv_data->device_props; 730 if (!entry) { 731 hid_err(hid, "Error while deinitializing device, no device properties data.\n"); 732 return -1; 733 } 734 735 #ifdef CONFIG_LEDS_CLASS 736 { 737 int j; 738 struct led_classdev *led; 739 740 /* Deregister LEDs (if any) */ 741 for (j = 0; j < 5; j++) { 742 743 led = entry->led[j]; 744 entry->led[j] = NULL; 745 if (!led) 746 continue; 747 led_classdev_unregister(led); 748 kfree(led); 749 } 750 } 751 #endif 752 753 /* Deallocate memory */ 754 kfree(entry); 755 756 dbg_hid("Device successfully unregistered\n"); 757 return 0; 758 } 759