diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index db63ccf21cc8..ea2c338814fe 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -436,6 +436,7 @@ #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295 #define USB_DEVICE_ID_LOGITECH_DFP_WHEEL 0xc298 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299 +#define USB_DEVICE_ID_LOGITECH_DFGT_WHEEL 0xc29a #define USB_DEVICE_ID_LOGITECH_G27_WHEEL 0xc29b #define USB_DEVICE_ID_LOGITECH_WII_WHEEL 0xc29c #define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index a7f916e8fc32..e0ae4a09425d 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -363,7 +363,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err_free; } - if (quirks & (LG_FF | LG_FF2 | LG_FF3)) + if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4)) connect_mask &= ~HID_CONNECT_FF; ret = hid_hw_start(hdev, connect_mask); @@ -372,7 +372,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err_free; } - if (quirks & LG_FF4) { + /* Setup wireless link with Logitech Wii wheel */ + if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); @@ -431,7 +432,7 @@ static const struct hid_device_id lg_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D), .driver_data = LG_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), - .driver_data = LG_NOGET | LG_FF }, + .driver_data = LG_NOGET | LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD), .driver_data = LG_FF2 }, @@ -444,15 +445,17 @@ static const struct hid_device_id lg_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO), .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL), - .driver_data = LG_FF }, + .driver_data = LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2), - .driver_data = LG_FF }, + .driver_data = LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), - .driver_data = LG_FF }, + .driver_data = LG_FF4 }, + { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFGT_WHEEL), + .driver_data = LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL), - .driver_data = LG_FF }, + .driver_data = LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL), - .driver_data = LG_NOGET | LG_FF }, + .driver_data = LG_NOGET | LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), .driver_data = LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index fa550c8e1d1b..1fcb2da32785 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -29,17 +29,32 @@ #include "usbhid/usbhid.h" #include "hid-lg.h" +#include "hid-ids.h" -struct lg4ff_device { - struct hid_report *report; -}; - -static const signed short ff4_wheel_ac[] = { +static const signed short lg4ff_wheel_effects[] = { FF_CONSTANT, FF_AUTOCENTER, -1 }; +struct lg4ff_wheel { + const __u32 product_id; + const signed short *ff_effects; + const __u16 min_range; + const __u16 max_range; +}; + +static const struct lg4ff_wheel lg4ff_devices[] = { + {USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270}, + {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270}, + {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900}, + {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900}, + {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900}, + {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900}, + {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270}, + {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270} +}; + static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { @@ -55,13 +70,12 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ CLAMP(x); report->field[0]->value[0] = 0x11; /* Slot 1 */ - report->field[0]->value[1] = 0x10; + report->field[0]->value[1] = 0x08; report->field[0]->value[2] = x; - report->field[0]->value[3] = 0x00; + report->field[0]->value[3] = 0x80; report->field[0]->value[4] = 0x00; - report->field[0]->value[5] = 0x08; + report->field[0]->value[5] = 0x00; report->field[0]->value[6] = 0x00; - dbg_hid("Autocenter, x=0x%02X\n", x); usbhid_submit_report(hid, report, USB_DIR_OUT); break; @@ -74,15 +88,14 @@ static void hid_lg4ff_set_autocenter(struct input_dev *dev, u16 magnitude) struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; - *value++ = 0xfe; - *value++ = 0x0d; - *value++ = 0x07; - *value++ = 0x07; - *value++ = (magnitude >> 8) & 0xff; - *value++ = 0x00; - *value = 0x00; + report->field[0]->value[0] = 0xfe; + report->field[0]->value[1] = 0x0d; + report->field[0]->value[2] = magnitude >> 13; + report->field[0]->value[3] = magnitude >> 13; + report->field[0]->value[4] = magnitude >> 8; + report->field[0]->value[5] = 0x00; + report->field[0]->value[6] = 0x00; usbhid_submit_report(hid, report, USB_DIR_OUT); } @@ -95,9 +108,7 @@ int lg4ff_init(struct hid_device *hid) struct input_dev *dev = hidinput->input; struct hid_report *report; struct hid_field *field; - const signed short *ff_bits = ff4_wheel_ac; - int error; - int i; + int error, i, j; /* Find the report to use */ if (list_empty(report_list)) { @@ -117,9 +128,24 @@ int lg4ff_init(struct hid_device *hid) hid_err(hid, "NULL field\n"); return -1; } + + /* Check what wheel has been connected */ + for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { + if (hid->product == lg4ff_devices[i].product_id) { + dbg_hid("Found compatible device, product ID %04X\n", lg4ff_devices[i].product_id); + break; + } + } - for (i = 0; ff_bits[i] >= 0; i++) - set_bit(ff_bits[i], dev->ffbit); + if (i == ARRAY_SIZE(lg4ff_devices)) { + hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to" + "LKML, Simon Wood or Michal Maly \n"); + return -1; + } + + /* Set supported force feedback capabilities */ + for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++) + set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit); error = input_ff_create_memless(dev, NULL, hid_lg4ff_play); diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 088f85049290..27bc54f92f44 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -58,12 +58,6 @@ static const signed short ff_joystick_ac[] = { -1 }; -static const signed short ff_wheel[] = { - FF_CONSTANT, - FF_AUTOCENTER, - -1 -}; - static const struct dev_type devices[] = { { 0x046d, 0xc211, ff_rumble }, { 0x046d, 0xc219, ff_rumble }, @@ -71,14 +65,7 @@ static const struct dev_type devices[] = { { 0x046d, 0xc286, ff_joystick_ac }, { 0x046d, 0xc287, ff_joystick_ac }, { 0x046d, 0xc293, ff_joystick }, - { 0x046d, 0xc294, ff_wheel }, - { 0x046d, 0xc298, ff_wheel }, - { 0x046d, 0xc299, ff_wheel }, - { 0x046d, 0xc29b, ff_wheel }, { 0x046d, 0xc295, ff_joystick }, - { 0x046d, 0xc298, ff_wheel }, - { 0x046d, 0xc299, ff_wheel }, - { 0x046d, 0xca03, ff_wheel }, }; static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)