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