diff options
Diffstat (limited to 'drivers/hid/hid-lg4ff.c')
-rw-r--r-- | drivers/hid/hid-lg4ff.c | 101 |
1 files changed, 87 insertions, 14 deletions
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 8782fe1aaa07..befe0e336471 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c | |||
@@ -196,6 +196,21 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e | |||
196 | case FF_CONSTANT: | 196 | case FF_CONSTANT: |
197 | x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ | 197 | x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ |
198 | CLAMP(x); | 198 | CLAMP(x); |
199 | |||
200 | if (x == 0x80) { | ||
201 | /* De-activate force in slot-1*/ | ||
202 | value[0] = 0x13; | ||
203 | value[1] = 0x00; | ||
204 | value[2] = 0x00; | ||
205 | value[3] = 0x00; | ||
206 | value[4] = 0x00; | ||
207 | value[5] = 0x00; | ||
208 | value[6] = 0x00; | ||
209 | |||
210 | hid_hw_request(hid, report, HID_REQ_SET_REPORT); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
199 | value[0] = 0x11; /* Slot 1 */ | 214 | value[0] = 0x11; /* Slot 1 */ |
200 | value[1] = 0x08; | 215 | value[1] = 0x08; |
201 | value[2] = x; | 216 | value[2] = x; |
@@ -218,12 +233,70 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud | |||
218 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; | 233 | struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; |
219 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); | 234 | struct hid_report *report = list_entry(report_list->next, struct hid_report, list); |
220 | __s32 *value = report->field[0]->value; | 235 | __s32 *value = report->field[0]->value; |
236 | __u32 expand_a, expand_b; | ||
237 | struct lg4ff_device_entry *entry; | ||
238 | struct lg_drv_data *drv_data; | ||
239 | |||
240 | drv_data = hid_get_drvdata(hid); | ||
241 | if (!drv_data) { | ||
242 | hid_err(hid, "Private driver data not found!\n"); | ||
243 | return; | ||
244 | } | ||
245 | |||
246 | entry = drv_data->device_props; | ||
247 | if (!entry) { | ||
248 | hid_err(hid, "Device properties not found!\n"); | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | /* De-activate Auto-Center */ | ||
253 | if (magnitude == 0) { | ||
254 | value[0] = 0xf5; | ||
255 | value[1] = 0x00; | ||
256 | value[2] = 0x00; | ||
257 | value[3] = 0x00; | ||
258 | value[4] = 0x00; | ||
259 | value[5] = 0x00; | ||
260 | value[6] = 0x00; | ||
261 | |||
262 | hid_hw_request(hid, report, HID_REQ_SET_REPORT); | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | if (magnitude <= 0xaaaa) { | ||
267 | expand_a = 0x0c * magnitude; | ||
268 | expand_b = 0x80 * magnitude; | ||
269 | } else { | ||
270 | expand_a = (0x0c * 0xaaaa) + 0x06 * (magnitude - 0xaaaa); | ||
271 | expand_b = (0x80 * 0xaaaa) + 0xff * (magnitude - 0xaaaa); | ||
272 | } | ||
273 | |||
274 | /* Adjust for non-MOMO wheels */ | ||
275 | switch (entry->product_id) { | ||
276 | case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: | ||
277 | case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: | ||
278 | break; | ||
279 | default: | ||
280 | expand_a = expand_a >> 1; | ||
281 | break; | ||
282 | } | ||
221 | 283 | ||
222 | value[0] = 0xfe; | 284 | value[0] = 0xfe; |
223 | value[1] = 0x0d; | 285 | value[1] = 0x0d; |
224 | value[2] = magnitude >> 13; | 286 | value[2] = expand_a / 0xaaaa; |
225 | value[3] = magnitude >> 13; | 287 | value[3] = expand_a / 0xaaaa; |
226 | value[4] = magnitude >> 8; | 288 | value[4] = expand_b / 0xaaaa; |
289 | value[5] = 0x00; | ||
290 | value[6] = 0x00; | ||
291 | |||
292 | hid_hw_request(hid, report, HID_REQ_SET_REPORT); | ||
293 | |||
294 | /* Activate Auto-Center */ | ||
295 | value[0] = 0x14; | ||
296 | value[1] = 0x00; | ||
297 | value[2] = 0x00; | ||
298 | value[3] = 0x00; | ||
299 | value[4] = 0x00; | ||
227 | value[5] = 0x00; | 300 | value[5] = 0x00; |
228 | value[6] = 0x00; | 301 | value[6] = 0x00; |
229 | 302 | ||
@@ -540,17 +613,6 @@ int lg4ff_init(struct hid_device *hid) | |||
540 | if (error) | 613 | if (error) |
541 | return error; | 614 | return error; |
542 | 615 | ||
543 | /* Check if autocentering is available and | ||
544 | * set the centering force to zero by default */ | ||
545 | if (test_bit(FF_AUTOCENTER, dev->ffbit)) { | ||
546 | if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ | ||
547 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; | ||
548 | else | ||
549 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; | ||
550 | |||
551 | dev->ff->set_autocenter(dev, 0); | ||
552 | } | ||
553 | |||
554 | /* Get private driver data */ | 616 | /* Get private driver data */ |
555 | drv_data = hid_get_drvdata(hid); | 617 | drv_data = hid_get_drvdata(hid); |
556 | if (!drv_data) { | 618 | if (!drv_data) { |
@@ -571,6 +633,17 @@ int lg4ff_init(struct hid_device *hid) | |||
571 | entry->max_range = lg4ff_devices[i].max_range; | 633 | entry->max_range = lg4ff_devices[i].max_range; |
572 | entry->set_range = lg4ff_devices[i].set_range; | 634 | entry->set_range = lg4ff_devices[i].set_range; |
573 | 635 | ||
636 | /* Check if autocentering is available and | ||
637 | * set the centering force to zero by default */ | ||
638 | if (test_bit(FF_AUTOCENTER, dev->ffbit)) { | ||
639 | if (rev_maj == FFEX_REV_MAJ && rev_min == FFEX_REV_MIN) /* Formula Force EX expects different autocentering command */ | ||
640 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; | ||
641 | else | ||
642 | dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; | ||
643 | |||
644 | dev->ff->set_autocenter(dev, 0); | ||
645 | } | ||
646 | |||
574 | /* Create sysfs interface */ | 647 | /* Create sysfs interface */ |
575 | error = device_create_file(&hid->dev, &dev_attr_range); | 648 | error = device_create_file(&hid->dev, &dev_attr_range); |
576 | if (error) | 649 | if (error) |