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-lg4ff.h" 34 #include "hid-ids.h" 35 36 #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev) 37 38 #define LG4FF_MMODE_IS_MULTIMODE 0 39 #define LG4FF_MMODE_SWITCHED 1 40 #define LG4FF_MMODE_NOT_MULTIMODE 2 41 42 #define LG4FF_MODE_NATIVE_IDX 0 43 #define LG4FF_MODE_DFEX_IDX 1 44 #define LG4FF_MODE_DFP_IDX 2 45 #define LG4FF_MODE_G25_IDX 3 46 #define LG4FF_MODE_DFGT_IDX 4 47 #define LG4FF_MODE_G27_IDX 5 48 #define LG4FF_MODE_MAX_IDX 6 49 50 #define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX) 51 #define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX) 52 #define LG4FF_MODE_DFP BIT(LG4FF_MODE_DFP_IDX) 53 #define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX) 54 #define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX) 55 #define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX) 56 57 #define LG4FF_DFEX_TAG "DF-EX" 58 #define LG4FF_DFEX_NAME "Driving Force / Formula EX" 59 #define LG4FF_DFP_TAG "DFP" 60 #define LG4FF_DFP_NAME "Driving Force Pro" 61 #define LG4FF_G25_TAG "G25" 62 #define LG4FF_G25_NAME "G25 Racing Wheel" 63 #define LG4FF_G27_TAG "G27" 64 #define LG4FF_G27_NAME "G27 Racing Wheel" 65 #define LG4FF_DFGT_TAG "DFGT" 66 #define LG4FF_DFGT_NAME "Driving Force GT" 67 68 #define LG4FF_FFEX_REV_MAJ 0x21 69 #define LG4FF_FFEX_REV_MIN 0x00 70 71 static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range); 72 static void lg4ff_set_range_g25(struct hid_device *hid, u16 range); 73 74 struct lg4ff_wheel_data { 75 const u32 product_id; 76 u16 range; 77 const u16 min_range; 78 const u16 max_range; 79 #ifdef CONFIG_LEDS_CLASS 80 u8 led_state; 81 struct led_classdev *led[5]; 82 #endif 83 const u32 alternate_modes; 84 const char * const real_tag; 85 const char * const real_name; 86 const u16 real_product_id; 87 88 void (*set_range)(struct hid_device *hid, u16 range); 89 }; 90 91 struct lg4ff_device_entry { 92 spinlock_t report_lock; /* Protect output HID report */ 93 struct hid_report *report; 94 struct lg4ff_wheel_data wdata; 95 }; 96 97 static const signed short lg4ff_wheel_effects[] = { 98 FF_CONSTANT, 99 FF_AUTOCENTER, 100 -1 101 }; 102 103 struct lg4ff_wheel { 104 const u32 product_id; 105 const signed short *ff_effects; 106 const u16 min_range; 107 const u16 max_range; 108 void (*set_range)(struct hid_device *hid, u16 range); 109 }; 110 111 struct lg4ff_compat_mode_switch { 112 const u8 cmd_count; /* Number of commands to send */ 113 const u8 cmd[]; 114 }; 115 116 struct lg4ff_wheel_ident_info { 117 const u16 mask; 118 const u16 result; 119 const u16 real_product_id; 120 }; 121 122 struct lg4ff_wheel_ident_checklist { 123 const u32 count; 124 const struct lg4ff_wheel_ident_info *models[]; 125 }; 126 127 struct lg4ff_multimode_wheel { 128 const u16 product_id; 129 const u32 alternate_modes; 130 const char *real_tag; 131 const char *real_name; 132 }; 133 134 struct lg4ff_alternate_mode { 135 const u16 product_id; 136 const char *tag; 137 const char *name; 138 }; 139 140 static const struct lg4ff_wheel lg4ff_devices[] = { 141 {USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, 142 {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, 143 {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_dfp}, 144 {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, 145 {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, 146 {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, 147 {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL}, 148 {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL} 149 }; 150 151 static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = { 152 {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, 153 LG4FF_MODE_NATIVE | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, 154 LG4FF_DFP_TAG, LG4FF_DFP_NAME}, 155 {USB_DEVICE_ID_LOGITECH_G25_WHEEL, 156 LG4FF_MODE_NATIVE | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, 157 LG4FF_G25_TAG, LG4FF_G25_NAME}, 158 {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, 159 LG4FF_MODE_NATIVE | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, 160 LG4FF_DFGT_TAG, LG4FF_DFGT_NAME}, 161 {USB_DEVICE_ID_LOGITECH_G27_WHEEL, 162 LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, 163 LG4FF_G27_TAG, LG4FF_G27_NAME}, 164 }; 165 166 static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = { 167 [LG4FF_MODE_NATIVE_IDX] = {0, "native", ""}, 168 [LG4FF_MODE_DFEX_IDX] = {USB_DEVICE_ID_LOGITECH_WHEEL, LG4FF_DFEX_TAG, LG4FF_DFEX_NAME}, 169 [LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME}, 170 [LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME}, 171 [LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME}, 172 [LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME} 173 }; 174 175 /* Multimode wheel identificators */ 176 static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = { 177 0xf000, 178 0x1000, 179 USB_DEVICE_ID_LOGITECH_DFP_WHEEL 180 }; 181 182 static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = { 183 0xff00, 184 0x1200, 185 USB_DEVICE_ID_LOGITECH_G25_WHEEL 186 }; 187 188 static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = { 189 0xfff0, 190 0x1230, 191 USB_DEVICE_ID_LOGITECH_G27_WHEEL 192 }; 193 194 static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = { 195 0xff00, 196 0x1300, 197 USB_DEVICE_ID_LOGITECH_DFGT_WHEEL 198 }; 199 200 /* Multimode wheel identification checklists */ 201 static const struct lg4ff_wheel_ident_checklist lg4ff_main_checklist = { 202 4, 203 {&lg4ff_dfgt_ident_info, 204 &lg4ff_g27_ident_info, 205 &lg4ff_g25_ident_info, 206 &lg4ff_dfp_ident_info} 207 }; 208 209 /* Compatibility mode switching commands */ 210 /* EXT_CMD9 - Understood by G27 and DFGT */ 211 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfex = { 212 2, 213 {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* Revert mode upon USB reset */ 214 0xf8, 0x09, 0x00, 0x01, 0x00, 0x00, 0x00} /* Switch mode to DF-EX with detach */ 215 }; 216 217 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfp = { 218 2, 219 {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* Revert mode upon USB reset */ 220 0xf8, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00} /* Switch mode to DFP with detach */ 221 }; 222 223 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g25 = { 224 2, 225 {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* Revert mode upon USB reset */ 226 0xf8, 0x09, 0x02, 0x01, 0x00, 0x00, 0x00} /* Switch mode to G25 with detach */ 227 }; 228 229 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_dfgt = { 230 2, 231 {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* Revert mode upon USB reset */ 232 0xf8, 0x09, 0x03, 0x01, 0x00, 0x00, 0x00} /* Switch mode to DFGT with detach */ 233 }; 234 235 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g27 = { 236 2, 237 {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* Revert mode upon USB reset */ 238 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* Switch mode to G27 with detach */ 239 }; 240 241 /* EXT_CMD1 - Understood by DFP, G25, G27 and DFGT */ 242 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext01_dfp = { 243 1, 244 {0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00} 245 }; 246 247 /* EXT_CMD16 - Understood by G25 and G27 */ 248 static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext16_g25 = { 249 1, 250 {0xf8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00} 251 }; 252 253 /* Recalculates X axis value accordingly to currently selected range */ 254 static s32 lg4ff_adjust_dfp_x_axis(s32 value, u16 range) 255 { 256 u16 max_range; 257 s32 new_value; 258 259 if (range == 900) 260 return value; 261 else if (range == 200) 262 return value; 263 else if (range < 200) 264 max_range = 200; 265 else 266 max_range = 900; 267 268 new_value = 8192 + mult_frac(value - 8192, max_range, range); 269 if (new_value < 0) 270 return 0; 271 else if (new_value > 16383) 272 return 16383; 273 else 274 return new_value; 275 } 276 277 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, 278 struct hid_usage *usage, s32 value, struct lg_drv_data *drv_data) 279 { 280 struct lg4ff_device_entry *entry = drv_data->device_props; 281 s32 new_value = 0; 282 283 if (!entry) { 284 hid_err(hid, "Device properties not found"); 285 return 0; 286 } 287 288 switch (entry->wdata.product_id) { 289 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 290 switch (usage->code) { 291 case ABS_X: 292 new_value = lg4ff_adjust_dfp_x_axis(value, entry->wdata.range); 293 input_event(field->hidinput->input, usage->type, usage->code, new_value); 294 return 1; 295 default: 296 return 0; 297 } 298 default: 299 return 0; 300 } 301 } 302 303 static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const struct lg4ff_wheel *wheel, 304 const struct lg4ff_multimode_wheel *mmode_wheel, 305 const u16 real_product_id) 306 { 307 u32 alternate_modes = 0; 308 const char *real_tag = NULL; 309 const char *real_name = NULL; 310 311 if (mmode_wheel) { 312 alternate_modes = mmode_wheel->alternate_modes; 313 real_tag = mmode_wheel->real_tag; 314 real_name = mmode_wheel->real_name; 315 } 316 317 { 318 struct lg4ff_wheel_data t_wdata = { .product_id = wheel->product_id, 319 .real_product_id = real_product_id, 320 .min_range = wheel->min_range, 321 .max_range = wheel->max_range, 322 .set_range = wheel->set_range, 323 .alternate_modes = alternate_modes, 324 .real_tag = real_tag, 325 .real_name = real_name }; 326 327 memcpy(wdata, &t_wdata, sizeof(t_wdata)); 328 } 329 } 330 331 static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) 332 { 333 struct hid_device *hid = input_get_drvdata(dev); 334 struct lg4ff_device_entry *entry; 335 struct lg_drv_data *drv_data; 336 unsigned long flags; 337 s32 *value; 338 int x; 339 340 drv_data = hid_get_drvdata(hid); 341 if (!drv_data) { 342 hid_err(hid, "Private driver data not found!\n"); 343 return -EINVAL; 344 } 345 346 entry = drv_data->device_props; 347 if (!entry) { 348 hid_err(hid, "Device properties not found!\n"); 349 return -EINVAL; 350 } 351 value = entry->report->field[0]->value; 352 353 #define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0) 354 355 switch (effect->type) { 356 case FF_CONSTANT: 357 x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ 358 CLAMP(x); 359 360 spin_lock_irqsave(&entry->report_lock, flags); 361 if (x == 0x80) { 362 /* De-activate force in slot-1*/ 363 value[0] = 0x13; 364 value[1] = 0x00; 365 value[2] = 0x00; 366 value[3] = 0x00; 367 value[4] = 0x00; 368 value[5] = 0x00; 369 value[6] = 0x00; 370 371 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 372 spin_unlock_irqrestore(&entry->report_lock, flags); 373 return 0; 374 } 375 376 value[0] = 0x11; /* Slot 1 */ 377 value[1] = 0x08; 378 value[2] = x; 379 value[3] = 0x80; 380 value[4] = 0x00; 381 value[5] = 0x00; 382 value[6] = 0x00; 383 384 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 385 spin_unlock_irqrestore(&entry->report_lock, flags); 386 break; 387 } 388 return 0; 389 } 390 391 /* Sends default autocentering command compatible with 392 * all wheels except Formula Force EX */ 393 static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) 394 { 395 struct hid_device *hid = input_get_drvdata(dev); 396 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 397 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 398 s32 *value = report->field[0]->value; 399 u32 expand_a, expand_b; 400 struct lg4ff_device_entry *entry; 401 struct lg_drv_data *drv_data; 402 unsigned long flags; 403 404 drv_data = hid_get_drvdata(hid); 405 if (!drv_data) { 406 hid_err(hid, "Private driver data not found!\n"); 407 return; 408 } 409 410 entry = drv_data->device_props; 411 if (!entry) { 412 hid_err(hid, "Device properties not found!\n"); 413 return; 414 } 415 value = entry->report->field[0]->value; 416 417 /* De-activate Auto-Center */ 418 spin_lock_irqsave(&entry->report_lock, flags); 419 if (magnitude == 0) { 420 value[0] = 0xf5; 421 value[1] = 0x00; 422 value[2] = 0x00; 423 value[3] = 0x00; 424 value[4] = 0x00; 425 value[5] = 0x00; 426 value[6] = 0x00; 427 428 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 429 spin_unlock_irqrestore(&entry->report_lock, flags); 430 return; 431 } 432 433 if (magnitude <= 0xaaaa) { 434 expand_a = 0x0c * magnitude; 435 expand_b = 0x80 * magnitude; 436 } else { 437 expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa); 438 expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa); 439 } 440 441 /* Adjust for non-MOMO wheels */ 442 switch (entry->wdata.product_id) { 443 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: 444 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: 445 break; 446 default: 447 expand_a = expand_a >> 1; 448 break; 449 } 450 451 value[0] = 0xfe; 452 value[1] = 0x0d; 453 value[2] = expand_a / 0xaaaa; 454 value[3] = expand_a / 0xaaaa; 455 value[4] = expand_b / 0xaaaa; 456 value[5] = 0x00; 457 value[6] = 0x00; 458 459 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 460 461 /* Activate Auto-Center */ 462 value[0] = 0x14; 463 value[1] = 0x00; 464 value[2] = 0x00; 465 value[3] = 0x00; 466 value[4] = 0x00; 467 value[5] = 0x00; 468 value[6] = 0x00; 469 470 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 471 spin_unlock_irqrestore(&entry->report_lock, flags); 472 } 473 474 /* Sends autocentering command compatible with Formula Force EX */ 475 static void lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) 476 { 477 struct hid_device *hid = input_get_drvdata(dev); 478 struct lg4ff_device_entry *entry; 479 struct lg_drv_data *drv_data; 480 unsigned long flags; 481 s32 *value; 482 magnitude = magnitude * 90 / 65535; 483 484 drv_data = hid_get_drvdata(hid); 485 if (!drv_data) { 486 hid_err(hid, "Private driver data not found!\n"); 487 return; 488 } 489 490 entry = drv_data->device_props; 491 if (!entry) { 492 hid_err(hid, "Device properties not found!\n"); 493 return; 494 } 495 value = entry->report->field[0]->value; 496 497 spin_lock_irqsave(&entry->report_lock, flags); 498 value[0] = 0xfe; 499 value[1] = 0x03; 500 value[2] = magnitude >> 14; 501 value[3] = magnitude >> 14; 502 value[4] = magnitude; 503 value[5] = 0x00; 504 value[6] = 0x00; 505 506 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 507 spin_unlock_irqrestore(&entry->report_lock, flags); 508 } 509 510 /* Sends command to set range compatible with G25/G27/Driving Force GT */ 511 static void lg4ff_set_range_g25(struct hid_device *hid, u16 range) 512 { 513 struct lg4ff_device_entry *entry; 514 struct lg_drv_data *drv_data; 515 unsigned long flags; 516 s32 *value; 517 518 drv_data = hid_get_drvdata(hid); 519 if (!drv_data) { 520 hid_err(hid, "Private driver data not found!\n"); 521 return; 522 } 523 524 entry = drv_data->device_props; 525 if (!entry) { 526 hid_err(hid, "Device properties not found!\n"); 527 return; 528 } 529 value = entry->report->field[0]->value; 530 dbg_hid("G25/G27/DFGT: setting range to %u\n", range); 531 532 spin_lock_irqsave(&entry->report_lock, flags); 533 value[0] = 0xf8; 534 value[1] = 0x81; 535 value[2] = range & 0x00ff; 536 value[3] = (range & 0xff00) >> 8; 537 value[4] = 0x00; 538 value[5] = 0x00; 539 value[6] = 0x00; 540 541 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 542 spin_unlock_irqrestore(&entry->report_lock, flags); 543 } 544 545 /* Sends commands to set range compatible with Driving Force Pro wheel */ 546 static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) 547 { 548 struct lg4ff_device_entry *entry; 549 struct lg_drv_data *drv_data; 550 unsigned long flags; 551 int start_left, start_right, full_range; 552 s32 *value; 553 554 drv_data = hid_get_drvdata(hid); 555 if (!drv_data) { 556 hid_err(hid, "Private driver data not found!\n"); 557 return; 558 } 559 560 entry = drv_data->device_props; 561 if (!entry) { 562 hid_err(hid, "Device properties not found!\n"); 563 return; 564 } 565 value = entry->report->field[0]->value; 566 dbg_hid("Driving Force Pro: setting range to %u\n", range); 567 568 /* Prepare "coarse" limit command */ 569 spin_lock_irqsave(&entry->report_lock, flags); 570 value[0] = 0xf8; 571 value[1] = 0x00; /* Set later */ 572 value[2] = 0x00; 573 value[3] = 0x00; 574 value[4] = 0x00; 575 value[5] = 0x00; 576 value[6] = 0x00; 577 578 if (range > 200) { 579 value[1] = 0x03; 580 full_range = 900; 581 } else { 582 value[1] = 0x02; 583 full_range = 200; 584 } 585 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 586 587 /* Prepare "fine" limit command */ 588 value[0] = 0x81; 589 value[1] = 0x0b; 590 value[2] = 0x00; 591 value[3] = 0x00; 592 value[4] = 0x00; 593 value[5] = 0x00; 594 value[6] = 0x00; 595 596 if (range == 200 || range == 900) { /* Do not apply any fine limit */ 597 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 598 spin_unlock_irqrestore(&entry->report_lock, flags); 599 return; 600 } 601 602 /* Construct fine limit command */ 603 start_left = (((full_range - range + 1) * 2047) / full_range); 604 start_right = 0xfff - start_left; 605 606 value[2] = start_left >> 4; 607 value[3] = start_right >> 4; 608 value[4] = 0xff; 609 value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); 610 value[6] = 0xff; 611 612 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 613 spin_unlock_irqrestore(&entry->report_lock, flags); 614 } 615 616 static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(const u16 real_product_id, const u16 target_product_id) 617 { 618 switch (real_product_id) { 619 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 620 switch (target_product_id) { 621 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 622 return &lg4ff_mode_switch_ext01_dfp; 623 /* DFP can only be switched to its native mode */ 624 default: 625 return NULL; 626 } 627 break; 628 case USB_DEVICE_ID_LOGITECH_G25_WHEEL: 629 switch (target_product_id) { 630 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 631 return &lg4ff_mode_switch_ext01_dfp; 632 case USB_DEVICE_ID_LOGITECH_G25_WHEEL: 633 return &lg4ff_mode_switch_ext16_g25; 634 /* G25 can only be switched to DFP mode or its native mode */ 635 default: 636 return NULL; 637 } 638 break; 639 case USB_DEVICE_ID_LOGITECH_G27_WHEEL: 640 switch (target_product_id) { 641 case USB_DEVICE_ID_LOGITECH_WHEEL: 642 return &lg4ff_mode_switch_ext09_dfex; 643 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 644 return &lg4ff_mode_switch_ext09_dfp; 645 case USB_DEVICE_ID_LOGITECH_G25_WHEEL: 646 return &lg4ff_mode_switch_ext09_g25; 647 case USB_DEVICE_ID_LOGITECH_G27_WHEEL: 648 return &lg4ff_mode_switch_ext09_g27; 649 /* G27 can only be switched to DF-EX, DFP, G25 or its native mode */ 650 default: 651 return NULL; 652 } 653 break; 654 case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: 655 switch (target_product_id) { 656 case USB_DEVICE_ID_LOGITECH_WHEEL: 657 return &lg4ff_mode_switch_ext09_dfex; 658 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 659 return &lg4ff_mode_switch_ext09_dfp; 660 case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: 661 return &lg4ff_mode_switch_ext09_dfgt; 662 /* DFGT can only be switched to DF-EX, DFP or its native mode */ 663 default: 664 return NULL; 665 } 666 break; 667 /* No other wheels have multiple modes */ 668 default: 669 return NULL; 670 } 671 } 672 673 static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct lg4ff_compat_mode_switch *s) 674 { 675 struct lg4ff_device_entry *entry; 676 struct lg_drv_data *drv_data; 677 unsigned long flags; 678 s32 *value; 679 u8 i; 680 681 drv_data = hid_get_drvdata(hid); 682 if (!drv_data) { 683 hid_err(hid, "Private driver data not found!\n"); 684 return -EINVAL; 685 } 686 687 entry = drv_data->device_props; 688 if (!entry) { 689 hid_err(hid, "Device properties not found!\n"); 690 return -EINVAL; 691 } 692 value = entry->report->field[0]->value; 693 694 spin_lock_irqsave(&entry->report_lock, flags); 695 for (i = 0; i < s->cmd_count; i++) { 696 u8 j; 697 698 for (j = 0; j < 7; j++) 699 value[j] = s->cmd[j + (7*i)]; 700 701 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 702 } 703 spin_unlock_irqrestore(&entry->report_lock, flags); 704 hid_hw_wait(hid); 705 return 0; 706 } 707 708 static ssize_t lg4ff_alternate_modes_show(struct device *dev, struct device_attribute *attr, char *buf) 709 { 710 struct hid_device *hid = to_hid_device(dev); 711 struct lg4ff_device_entry *entry; 712 struct lg_drv_data *drv_data; 713 ssize_t count = 0; 714 int i; 715 716 drv_data = hid_get_drvdata(hid); 717 if (!drv_data) { 718 hid_err(hid, "Private driver data not found!\n"); 719 return 0; 720 } 721 722 entry = drv_data->device_props; 723 if (!entry) { 724 hid_err(hid, "Device properties not found!\n"); 725 return 0; 726 } 727 728 if (!entry->wdata.real_name) { 729 hid_err(hid, "NULL pointer to string\n"); 730 return 0; 731 } 732 733 for (i = 0; i < LG4FF_MODE_MAX_IDX; i++) { 734 if (entry->wdata.alternate_modes & BIT(i)) { 735 /* Print tag and full name */ 736 count += scnprintf(buf + count, PAGE_SIZE - count, "%s: %s", 737 lg4ff_alternate_modes[i].tag, 738 !lg4ff_alternate_modes[i].product_id ? entry->wdata.real_name : lg4ff_alternate_modes[i].name); 739 if (count >= PAGE_SIZE - 1) 740 return count; 741 742 /* Mark the currently active mode with an asterisk */ 743 if (lg4ff_alternate_modes[i].product_id == entry->wdata.product_id || 744 (lg4ff_alternate_modes[i].product_id == 0 && entry->wdata.product_id == entry->wdata.real_product_id)) 745 count += scnprintf(buf + count, PAGE_SIZE - count, " *\n"); 746 else 747 count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); 748 749 if (count >= PAGE_SIZE - 1) 750 return count; 751 } 752 } 753 754 return count; 755 } 756 757 static ssize_t lg4ff_alternate_modes_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 758 { 759 struct hid_device *hid = to_hid_device(dev); 760 struct lg4ff_device_entry *entry; 761 struct lg_drv_data *drv_data; 762 const struct lg4ff_compat_mode_switch *s; 763 u16 target_product_id = 0; 764 int i, ret; 765 char *lbuf; 766 767 drv_data = hid_get_drvdata(hid); 768 if (!drv_data) { 769 hid_err(hid, "Private driver data not found!\n"); 770 return -EINVAL; 771 } 772 773 entry = drv_data->device_props; 774 if (!entry) { 775 hid_err(hid, "Device properties not found!\n"); 776 return -EINVAL; 777 } 778 779 /* Allow \n at the end of the input parameter */ 780 lbuf = kasprintf(GFP_KERNEL, "%s", buf); 781 if (!lbuf) 782 return -ENOMEM; 783 784 i = strlen(lbuf); 785 if (lbuf[i-1] == '\n') { 786 if (i == 1) { 787 kfree(lbuf); 788 return -EINVAL; 789 } 790 lbuf[i-1] = '\0'; 791 } 792 793 for (i = 0; i < LG4FF_MODE_MAX_IDX; i++) { 794 const u16 mode_product_id = lg4ff_alternate_modes[i].product_id; 795 const char *tag = lg4ff_alternate_modes[i].tag; 796 797 if (entry->wdata.alternate_modes & BIT(i)) { 798 if (!strcmp(tag, lbuf)) { 799 if (!mode_product_id) 800 target_product_id = entry->wdata.real_product_id; 801 else 802 target_product_id = mode_product_id; 803 break; 804 } 805 } 806 } 807 808 if (i == LG4FF_MODE_MAX_IDX) { 809 hid_info(hid, "Requested mode \"%s\" is not supported by the device\n", lbuf); 810 kfree(lbuf); 811 return -EINVAL; 812 } 813 kfree(lbuf); /* Not needed anymore */ 814 815 if (target_product_id == entry->wdata.product_id) /* Nothing to do */ 816 return count; 817 818 /* Automatic switching has to be disabled for the switch to DF-EX mode to work correctly */ 819 if (target_product_id == USB_DEVICE_ID_LOGITECH_WHEEL && !lg4ff_no_autoswitch) { 820 hid_info(hid, "\"%s\" cannot be switched to \"DF-EX\" mode. Load the \"hid_logitech\" module with \"lg4ff_no_autoswitch=1\" parameter set and try again\n", 821 entry->wdata.real_name); 822 return -EINVAL; 823 } 824 825 /* Take care of hardware limitations */ 826 if ((entry->wdata.real_product_id == USB_DEVICE_ID_LOGITECH_DFP_WHEEL || entry->wdata.real_product_id == USB_DEVICE_ID_LOGITECH_G25_WHEEL) && 827 entry->wdata.product_id > target_product_id) { 828 hid_info(hid, "\"%s\" cannot be switched back into \"%s\" mode\n", entry->wdata.real_name, lg4ff_alternate_modes[i].name); 829 return -EINVAL; 830 } 831 832 s = lg4ff_get_mode_switch_command(entry->wdata.real_product_id, target_product_id); 833 if (!s) { 834 hid_err(hid, "Invalid target product ID %X\n", target_product_id); 835 return -EINVAL; 836 } 837 838 ret = lg4ff_switch_compatibility_mode(hid, s); 839 return (ret == 0 ? count : ret); 840 } 841 static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store); 842 843 /* Export the currently set range of the wheel */ 844 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, 845 char *buf) 846 { 847 struct hid_device *hid = to_hid_device(dev); 848 struct lg4ff_device_entry *entry; 849 struct lg_drv_data *drv_data; 850 size_t count; 851 852 drv_data = hid_get_drvdata(hid); 853 if (!drv_data) { 854 hid_err(hid, "Private driver data not found!\n"); 855 return 0; 856 } 857 858 entry = drv_data->device_props; 859 if (!entry) { 860 hid_err(hid, "Device properties not found!\n"); 861 return 0; 862 } 863 864 count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.range); 865 return count; 866 } 867 868 /* Set range to user specified value, call appropriate function 869 * according to the type of the wheel */ 870 static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, 871 const char *buf, size_t count) 872 { 873 struct hid_device *hid = to_hid_device(dev); 874 struct lg4ff_device_entry *entry; 875 struct lg_drv_data *drv_data; 876 u16 range = simple_strtoul(buf, NULL, 10); 877 878 drv_data = hid_get_drvdata(hid); 879 if (!drv_data) { 880 hid_err(hid, "Private driver data not found!\n"); 881 return -EINVAL; 882 } 883 884 entry = drv_data->device_props; 885 if (!entry) { 886 hid_err(hid, "Device properties not found!\n"); 887 return -EINVAL; 888 } 889 890 if (range == 0) 891 range = entry->wdata.max_range; 892 893 /* Check if the wheel supports range setting 894 * and that the range is within limits for the wheel */ 895 if (entry->wdata.set_range && range >= entry->wdata.min_range && range <= entry->wdata.max_range) { 896 entry->wdata.set_range(hid, range); 897 entry->wdata.range = range; 898 } 899 900 return count; 901 } 902 static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_range_show, lg4ff_range_store); 903 904 static ssize_t lg4ff_real_id_show(struct device *dev, struct device_attribute *attr, char *buf) 905 { 906 struct hid_device *hid = to_hid_device(dev); 907 struct lg4ff_device_entry *entry; 908 struct lg_drv_data *drv_data; 909 size_t count; 910 911 drv_data = hid_get_drvdata(hid); 912 if (!drv_data) { 913 hid_err(hid, "Private driver data not found!\n"); 914 return 0; 915 } 916 917 entry = drv_data->device_props; 918 if (!entry) { 919 hid_err(hid, "Device properties not found!\n"); 920 return 0; 921 } 922 923 if (!entry->wdata.real_tag || !entry->wdata.real_name) { 924 hid_err(hid, "NULL pointer to string\n"); 925 return 0; 926 } 927 928 count = scnprintf(buf, PAGE_SIZE, "%s: %s\n", entry->wdata.real_tag, entry->wdata.real_name); 929 return count; 930 } 931 932 static ssize_t lg4ff_real_id_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 933 { 934 /* Real ID is a read-only value */ 935 return -EPERM; 936 } 937 static DEVICE_ATTR(real_id, S_IRUGO, lg4ff_real_id_show, lg4ff_real_id_store); 938 939 #ifdef CONFIG_LEDS_CLASS 940 static void lg4ff_set_leds(struct hid_device *hid, u8 leds) 941 { 942 struct lg_drv_data *drv_data; 943 struct lg4ff_device_entry *entry; 944 unsigned long flags; 945 s32 *value; 946 947 drv_data = hid_get_drvdata(hid); 948 if (!drv_data) { 949 hid_err(hid, "Private driver data not found!\n"); 950 return; 951 } 952 953 entry = drv_data->device_props; 954 if (!entry) { 955 hid_err(hid, "Device properties not found!\n"); 956 return; 957 } 958 value = entry->report->field[0]->value; 959 960 spin_lock_irqsave(&entry->report_lock, flags); 961 value[0] = 0xf8; 962 value[1] = 0x12; 963 value[2] = leds; 964 value[3] = 0x00; 965 value[4] = 0x00; 966 value[5] = 0x00; 967 value[6] = 0x00; 968 hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); 969 spin_unlock_irqrestore(&entry->report_lock, flags); 970 } 971 972 static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, 973 enum led_brightness value) 974 { 975 struct device *dev = led_cdev->dev->parent; 976 struct hid_device *hid = container_of(dev, struct hid_device, dev); 977 struct lg_drv_data *drv_data = hid_get_drvdata(hid); 978 struct lg4ff_device_entry *entry; 979 int i, state = 0; 980 981 if (!drv_data) { 982 hid_err(hid, "Device data not found."); 983 return; 984 } 985 986 entry = drv_data->device_props; 987 988 if (!entry) { 989 hid_err(hid, "Device properties not found."); 990 return; 991 } 992 993 for (i = 0; i < 5; i++) { 994 if (led_cdev != entry->wdata.led[i]) 995 continue; 996 state = (entry->wdata.led_state >> i) & 1; 997 if (value == LED_OFF && state) { 998 entry->wdata.led_state &= ~(1 << i); 999 lg4ff_set_leds(hid, entry->wdata.led_state); 1000 } else if (value != LED_OFF && !state) { 1001 entry->wdata.led_state |= 1 << i; 1002 lg4ff_set_leds(hid, entry->wdata.led_state); 1003 } 1004 break; 1005 } 1006 } 1007 1008 static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cdev) 1009 { 1010 struct device *dev = led_cdev->dev->parent; 1011 struct hid_device *hid = container_of(dev, struct hid_device, dev); 1012 struct lg_drv_data *drv_data = hid_get_drvdata(hid); 1013 struct lg4ff_device_entry *entry; 1014 int i, value = 0; 1015 1016 if (!drv_data) { 1017 hid_err(hid, "Device data not found."); 1018 return LED_OFF; 1019 } 1020 1021 entry = drv_data->device_props; 1022 1023 if (!entry) { 1024 hid_err(hid, "Device properties not found."); 1025 return LED_OFF; 1026 } 1027 1028 for (i = 0; i < 5; i++) 1029 if (led_cdev == entry->wdata.led[i]) { 1030 value = (entry->wdata.led_state >> i) & 1; 1031 break; 1032 } 1033 1034 return value ? LED_FULL : LED_OFF; 1035 } 1036 #endif 1037 1038 static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice) 1039 { 1040 const struct lg4ff_wheel_ident_checklist *checklist; 1041 int i, from_idx, to_idx; 1042 1043 switch (reported_product_id) { 1044 case USB_DEVICE_ID_LOGITECH_WHEEL: 1045 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 1046 checklist = &lg4ff_main_checklist; 1047 from_idx = 0; 1048 to_idx = checklist->count - 1; 1049 break; 1050 case USB_DEVICE_ID_LOGITECH_G25_WHEEL: 1051 checklist = &lg4ff_main_checklist; 1052 from_idx = 0; 1053 to_idx = checklist->count - 2; /* End identity check at G25 */ 1054 break; 1055 case USB_DEVICE_ID_LOGITECH_G27_WHEEL: 1056 checklist = &lg4ff_main_checklist; 1057 from_idx = 1; /* Start identity check at G27 */ 1058 to_idx = checklist->count - 3; /* End identity check at G27 */ 1059 break; 1060 case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: 1061 checklist = &lg4ff_main_checklist; 1062 from_idx = 0; 1063 to_idx = checklist->count - 4; /* End identity check at DFGT */ 1064 break; 1065 default: 1066 return 0; 1067 } 1068 1069 for (i = from_idx; i <= to_idx; i++) { 1070 const u16 mask = checklist->models[i]->mask; 1071 const u16 result = checklist->models[i]->result; 1072 const u16 real_product_id = checklist->models[i]->real_product_id; 1073 1074 if ((bcdDevice & mask) == result) { 1075 dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id); 1076 return real_product_id; 1077 } 1078 } 1079 1080 /* No match found. This is either Driving Force or an unknown 1081 * wheel model, do not touch it */ 1082 dbg_hid("Wheel with bcdDevice %X was not recognized as multimode wheel, leaving in its current mode\n", bcdDevice); 1083 return 0; 1084 } 1085 1086 static int lg4ff_handle_multimode_wheel(struct hid_device *hid, u16 *real_product_id, const u16 bcdDevice) 1087 { 1088 const u16 reported_product_id = hid->product; 1089 int ret; 1090 1091 *real_product_id = lg4ff_identify_multimode_wheel(hid, reported_product_id, bcdDevice); 1092 /* Probed wheel is not a multimode wheel */ 1093 if (!*real_product_id) { 1094 *real_product_id = reported_product_id; 1095 dbg_hid("Wheel is not a multimode wheel\n"); 1096 return LG4FF_MMODE_NOT_MULTIMODE; 1097 } 1098 1099 /* Switch from "Driving Force" mode to native mode automatically. 1100 * Otherwise keep the wheel in its current mode */ 1101 if (reported_product_id == USB_DEVICE_ID_LOGITECH_WHEEL && 1102 reported_product_id != *real_product_id && 1103 !lg4ff_no_autoswitch) { 1104 const struct lg4ff_compat_mode_switch *s = lg4ff_get_mode_switch_command(*real_product_id, *real_product_id); 1105 1106 if (!s) { 1107 hid_err(hid, "Invalid product id %X\n", *real_product_id); 1108 return LG4FF_MMODE_NOT_MULTIMODE; 1109 } 1110 1111 ret = lg4ff_switch_compatibility_mode(hid, s); 1112 if (ret) { 1113 /* Wheel could not have been switched to native mode, 1114 * leave it in "Driving Force" mode and continue */ 1115 hid_err(hid, "Unable to switch wheel mode, errno %d\n", ret); 1116 return LG4FF_MMODE_IS_MULTIMODE; 1117 } 1118 return LG4FF_MMODE_SWITCHED; 1119 } 1120 1121 return LG4FF_MMODE_IS_MULTIMODE; 1122 } 1123 1124 1125 int lg4ff_init(struct hid_device *hid) 1126 { 1127 struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); 1128 struct input_dev *dev = hidinput->input; 1129 struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; 1130 struct hid_report *report = list_entry(report_list->next, struct hid_report, list); 1131 const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); 1132 const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice); 1133 const struct lg4ff_multimode_wheel *mmode_wheel = NULL; 1134 struct lg4ff_device_entry *entry; 1135 struct lg_drv_data *drv_data; 1136 int error, i, j; 1137 int mmode_ret, mmode_idx = -1; 1138 u16 real_product_id; 1139 1140 /* Check that the report looks ok */ 1141 if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) 1142 return -1; 1143 1144 drv_data = hid_get_drvdata(hid); 1145 if (!drv_data) { 1146 hid_err(hid, "Cannot add device, private driver data not allocated\n"); 1147 return -1; 1148 } 1149 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 1150 if (!entry) 1151 return -ENOMEM; 1152 spin_lock_init(&entry->report_lock); 1153 entry->report = report; 1154 drv_data->device_props = entry; 1155 1156 /* Check if a multimode wheel has been connected and 1157 * handle it appropriately */ 1158 mmode_ret = lg4ff_handle_multimode_wheel(hid, &real_product_id, bcdDevice); 1159 1160 /* Wheel has been told to switch to native mode. There is no point in going on 1161 * with the initialization as the wheel will do a USB reset when it switches mode 1162 */ 1163 if (mmode_ret == LG4FF_MMODE_SWITCHED) 1164 return 0; 1165 else if (mmode_ret < 0) { 1166 hid_err(hid, "Unable to switch device mode during initialization, errno %d\n", mmode_ret); 1167 error = mmode_ret; 1168 goto err_init; 1169 } 1170 1171 /* Check what wheel has been connected */ 1172 for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { 1173 if (hid->product == lg4ff_devices[i].product_id) { 1174 dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id); 1175 break; 1176 } 1177 } 1178 1179 if (i == ARRAY_SIZE(lg4ff_devices)) { 1180 hid_err(hid, "This device is flagged to be handled by the lg4ff module but this module does not know how to handle it. " 1181 "Please report this as a bug to LKML, Simon Wood <simon@mungewell.org> or " 1182 "Michal Maly <madcatxster@devoid-pointer.net>\n"); 1183 error = -1; 1184 goto err_init; 1185 } 1186 1187 if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) { 1188 for (mmode_idx = 0; mmode_idx < ARRAY_SIZE(lg4ff_multimode_wheels); mmode_idx++) { 1189 if (real_product_id == lg4ff_multimode_wheels[mmode_idx].product_id) 1190 break; 1191 } 1192 1193 if (mmode_idx == ARRAY_SIZE(lg4ff_multimode_wheels)) { 1194 hid_err(hid, "Device product ID %X is not listed as a multimode wheel", real_product_id); 1195 error = -1; 1196 goto err_init; 1197 } 1198 } 1199 1200 /* Set supported force feedback capabilities */ 1201 for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++) 1202 set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit); 1203 1204 error = input_ff_create_memless(dev, NULL, lg4ff_play); 1205 1206 if (error) 1207 goto err_init; 1208 1209 /* Initialize device properties */ 1210 if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) { 1211 BUG_ON(mmode_idx == -1); 1212 mmode_wheel = &lg4ff_multimode_wheels[mmode_idx]; 1213 } 1214 lg4ff_init_wheel_data(&entry->wdata, &lg4ff_devices[i], mmode_wheel, real_product_id); 1215 1216 /* Check if autocentering is available and 1217 * set the centering force to zero by default */ 1218 if (test_bit(FF_AUTOCENTER, dev->ffbit)) { 1219 /* Formula Force EX expects different autocentering command */ 1220 if ((bcdDevice >> 8) == LG4FF_FFEX_REV_MAJ && 1221 (bcdDevice & 0xff) == LG4FF_FFEX_REV_MIN) 1222 dev->ff->set_autocenter = lg4ff_set_autocenter_ffex; 1223 else 1224 dev->ff->set_autocenter = lg4ff_set_autocenter_default; 1225 1226 dev->ff->set_autocenter(dev, 0); 1227 } 1228 1229 /* Create sysfs interface */ 1230 error = device_create_file(&hid->dev, &dev_attr_range); 1231 if (error) 1232 hid_warn(hid, "Unable to create sysfs interface for \"range\", errno %d\n", error); 1233 if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) { 1234 error = device_create_file(&hid->dev, &dev_attr_real_id); 1235 if (error) 1236 hid_warn(hid, "Unable to create sysfs interface for \"real_id\", errno %d\n", error); 1237 error = device_create_file(&hid->dev, &dev_attr_alternate_modes); 1238 if (error) 1239 hid_warn(hid, "Unable to create sysfs interface for \"alternate_modes\", errno %d\n", error); 1240 } 1241 dbg_hid("sysfs interface created\n"); 1242 1243 /* Set the maximum range to start with */ 1244 entry->wdata.range = entry->wdata.max_range; 1245 if (entry->wdata.set_range) 1246 entry->wdata.set_range(hid, entry->wdata.range); 1247 1248 #ifdef CONFIG_LEDS_CLASS 1249 /* register led subsystem - G27 only */ 1250 entry->wdata.led_state = 0; 1251 for (j = 0; j < 5; j++) 1252 entry->wdata.led[j] = NULL; 1253 1254 if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) { 1255 struct led_classdev *led; 1256 size_t name_sz; 1257 char *name; 1258 1259 lg4ff_set_leds(hid, 0); 1260 1261 name_sz = strlen(dev_name(&hid->dev)) + 8; 1262 1263 for (j = 0; j < 5; j++) { 1264 led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); 1265 if (!led) { 1266 hid_err(hid, "can't allocate memory for LED %d\n", j); 1267 goto err_leds; 1268 } 1269 1270 name = (void *)(&led[1]); 1271 snprintf(name, name_sz, "%s::RPM%d", dev_name(&hid->dev), j+1); 1272 led->name = name; 1273 led->brightness = 0; 1274 led->max_brightness = 1; 1275 led->brightness_get = lg4ff_led_get_brightness; 1276 led->brightness_set = lg4ff_led_set_brightness; 1277 1278 entry->wdata.led[j] = led; 1279 error = led_classdev_register(&hid->dev, led); 1280 1281 if (error) { 1282 hid_err(hid, "failed to register LED %d. Aborting.\n", j); 1283 err_leds: 1284 /* Deregister LEDs (if any) */ 1285 for (j = 0; j < 5; j++) { 1286 led = entry->wdata.led[j]; 1287 entry->wdata.led[j] = NULL; 1288 if (!led) 1289 continue; 1290 led_classdev_unregister(led); 1291 kfree(led); 1292 } 1293 goto out; /* Let the driver continue without LEDs */ 1294 } 1295 } 1296 } 1297 out: 1298 #endif 1299 hid_info(hid, "Force feedback support for Logitech Gaming Wheels\n"); 1300 return 0; 1301 1302 err_init: 1303 drv_data->device_props = NULL; 1304 kfree(entry); 1305 return error; 1306 } 1307 1308 int lg4ff_deinit(struct hid_device *hid) 1309 { 1310 struct lg4ff_device_entry *entry; 1311 struct lg_drv_data *drv_data; 1312 1313 drv_data = hid_get_drvdata(hid); 1314 if (!drv_data) { 1315 hid_err(hid, "Error while deinitializing device, no private driver data.\n"); 1316 return -1; 1317 } 1318 entry = drv_data->device_props; 1319 if (!entry) 1320 goto out; /* Nothing more to do */ 1321 1322 /* Multimode devices will have at least the "MODE_NATIVE" bit set */ 1323 if (entry->wdata.alternate_modes) { 1324 device_remove_file(&hid->dev, &dev_attr_real_id); 1325 device_remove_file(&hid->dev, &dev_attr_alternate_modes); 1326 } 1327 1328 device_remove_file(&hid->dev, &dev_attr_range); 1329 #ifdef CONFIG_LEDS_CLASS 1330 { 1331 int j; 1332 struct led_classdev *led; 1333 1334 /* Deregister LEDs (if any) */ 1335 for (j = 0; j < 5; j++) { 1336 1337 led = entry->wdata.led[j]; 1338 entry->wdata.led[j] = NULL; 1339 if (!led) 1340 continue; 1341 led_classdev_unregister(led); 1342 kfree(led); 1343 } 1344 } 1345 #endif 1346 hid_hw_stop(hid); 1347 drv_data->device_props = NULL; 1348 1349 kfree(entry); 1350 out: 1351 dbg_hid("Device successfully unregistered\n"); 1352 return 0; 1353 } 1354