Blame view

drivers/hid/hid-lg2ff.c 2.19 KB
1a59d1b8e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
c17f9c901   Anssi Hannula   HID: force feedba...
2
  /*
2c6118e43   Hendrik Iben   HID: force feedba...
3
   *  Force feedback support for Logitech RumblePad and Rumblepad 2
c17f9c901   Anssi Hannula   HID: force feedba...
4
5
6
7
8
   *
   *  Copyright (c) 2008 Anssi Hannula <anssi.hannula@gmail.com>
   */
  
  /*
c17f9c901   Anssi Hannula   HID: force feedba...
9
10
11
12
   */
  
  
  #include <linux/input.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
c17f9c901   Anssi Hannula   HID: force feedba...
14
  #include <linux/hid.h>
606bd0a86   Jiri Slaby   HID: move logitec...
15

606bd0a86   Jiri Slaby   HID: move logitec...
16
  #include "hid-lg.h"
c17f9c901   Anssi Hannula   HID: force feedba...
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  
  struct lg2ff_device {
  	struct hid_report *report;
  };
  
  static int play_effect(struct input_dev *dev, void *data,
  			 struct ff_effect *effect)
  {
  	struct hid_device *hid = input_get_drvdata(dev);
  	struct lg2ff_device *lg2ff = data;
  	int weak, strong;
  
  	strong = effect->u.rumble.strong_magnitude;
  	weak = effect->u.rumble.weak_magnitude;
  
  	if (weak || strong) {
  		weak = weak * 0xff / 0xffff;
  		strong = strong * 0xff / 0xffff;
  
  		lg2ff->report->field[0]->value[0] = 0x51;
  		lg2ff->report->field[0]->value[2] = weak;
  		lg2ff->report->field[0]->value[4] = strong;
  	} else {
  		lg2ff->report->field[0]->value[0] = 0xf3;
  		lg2ff->report->field[0]->value[2] = 0x00;
  		lg2ff->report->field[0]->value[4] = 0x00;
  	}
d88142725   Benjamin Tissoires   HID: use hid_hw_r...
44
  	hid_hw_request(hid, lg2ff->report, HID_REQ_SET_REPORT);
c17f9c901   Anssi Hannula   HID: force feedba...
45
46
  	return 0;
  }
606bd0a86   Jiri Slaby   HID: move logitec...
47
  int lg2ff_init(struct hid_device *hid)
c17f9c901   Anssi Hannula   HID: force feedba...
48
49
50
  {
  	struct lg2ff_device *lg2ff;
  	struct hid_report *report;
d9d4b1e46   Alan Stern   HID: Fix assumpti...
51
52
  	struct hid_input *hidinput;
  	struct input_dev *dev;
c17f9c901   Anssi Hannula   HID: force feedba...
53
  	int error;
d9d4b1e46   Alan Stern   HID: Fix assumpti...
54
55
56
57
58
59
60
  	if (list_empty(&hid->inputs)) {
  		hid_err(hid, "no inputs found
  ");
  		return -ENODEV;
  	}
  	hidinput = list_entry(hid->inputs.next, struct hid_input, list);
  	dev = hidinput->input;
0fb6bd06e   Kees Cook   HID: LG: validate...
61
62
63
  	/* Check that the report looks ok */
  	report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
  	if (!report)
c17f9c901   Anssi Hannula   HID: force feedba...
64
  		return -ENODEV;
c17f9c901   Anssi Hannula   HID: force feedba...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  
  	lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
  	if (!lg2ff)
  		return -ENOMEM;
  
  	set_bit(FF_RUMBLE, dev->ffbit);
  
  	error = input_ff_create_memless(dev, lg2ff, play_effect);
  	if (error) {
  		kfree(lg2ff);
  		return error;
  	}
  
  	lg2ff->report = report;
  	report->field[0]->value[0] = 0xf3;
  	report->field[0]->value[1] = 0x00;
  	report->field[0]->value[2] = 0x00;
  	report->field[0]->value[3] = 0x00;
  	report->field[0]->value[4] = 0x00;
  	report->field[0]->value[5] = 0x00;
  	report->field[0]->value[6] = 0x00;
d88142725   Benjamin Tissoires   HID: use hid_hw_r...
86
  	hid_hw_request(hid, report, HID_REQ_SET_REPORT);
c17f9c901   Anssi Hannula   HID: force feedba...
87

bd04363d3   Elias Vanderstuyft   HID: logitech - l...
88
89
  	hid_info(hid, "Force feedback for Logitech variant 2 rumble devices by Anssi Hannula <anssi.hannula@gmail.com>
  ");
c17f9c901   Anssi Hannula   HID: force feedba...
90
91
92
  
  	return 0;
  }