aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hid-tmff2.c45
-rw-r--r--src/hid-tmff2.h2
-rw-r--r--src/tmt300rs/hid-tmt300rs.c32
3 files changed, 57 insertions, 22 deletions
diff --git a/src/hid-tmff2.c b/src/hid-tmff2.c
index 162a30a..55e2173 100644
--- a/src/hid-tmff2.c
+++ b/src/hid-tmff2.c
@@ -43,11 +43,16 @@ MODULE_PARM_DESC(alt_mode,
"Alternate mode, eg. F1 mode");
#define GAIN_MAX 65535
-int gain = 40000;
-module_param(gain, int, 0);
+u16 gain = 40000;
+module_param(gain, ushort, 0);
MODULE_PARM_DESC(gain,
"Level of gain (0-65535)");
+static u16 tmff2_scale_gain(u16 value)
+{
+ return (u32)value * gain / GAIN_MAX;
+}
+
static spinlock_t lock;
static struct tmff2_device_entry *tmff2_from_hdev(struct hid_device *hdev)
@@ -230,20 +235,21 @@ static ssize_t gain_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct tmff2_device_entry *tmff2 = tmff2_from_hdev(to_hid_device(dev));
- unsigned int value;
+ u16 value;
int ret;
if (!tmff2)
return -ENODEV;
- if ((ret = kstrtouint(buf, 0, &value))) {
- dev_err(dev, "kstrtouint failed at gain_store: %i", ret);
+ ret = kstrtou16(buf, 0, &value);
+ if (ret) {
+ dev_err(dev, "failed to parse gain: %d\n", ret);
return ret;
}
gain = value;
if (tmff2->set_gain) /* if we can, update gain immediately */
- tmff2->set_gain(tmff2->data, (GAIN_MAX * gain) / GAIN_MAX);
+ tmff2->set_gain(tmff2->data, gain);
return count;
}
@@ -251,7 +257,7 @@ static ssize_t gain_store(struct device *dev,
static ssize_t gain_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%i\n", gain);
+ return scnprintf(buf, PAGE_SIZE, "%u\n", gain);
}
static DEVICE_ATTR_RW(gain);
@@ -267,7 +273,7 @@ static void tmff2_set_gain(struct input_dev *dev, uint16_t value)
return;
}
- if (tmff2->set_gain(tmff2->data, (value * gain) / GAIN_MAX))
+ if (tmff2->set_gain(tmff2->data, tmff2_scale_gain(value)))
hid_warn(tmff2->hdev, "unable to set gain\n");
}
@@ -643,7 +649,7 @@ static int tmff2_wheel_init(struct tmff2_device_entry *tmff2)
/* set defaults wherever possible */
if (tmff2->set_gain) {
ff->set_gain = tmff2_set_gain;
- tmff2->set_gain(tmff2->data, (GAIN_MAX * gain) / GAIN_MAX);
+ tmff2->set_gain(tmff2->data, gain);
}
if (tmff2->set_autocenter)
@@ -801,6 +807,26 @@ static void tmff2_remove(struct hid_device *hdev)
kfree(tmff2);
}
+static int tmff2_input_configured(struct hid_device *hdev,
+ struct hid_input *hidinput)
+{
+ struct input_dev *input = hidinput->input;
+ int axis;
+
+ if (!input->absinfo)
+ return 0;
+
+ for (axis = ABS_X; axis <= ABS_BRAKE; axis++) {
+ if (!test_bit(axis, input->absbit))
+ continue;
+
+ input_abs_set_fuzz(input, axis, 0);
+ input_abs_set_flat(input, axis, 0);
+ }
+
+ return 0;
+}
+
static const struct hid_device_id tmff2_devices[] = {
/* t300rs and variations */
{HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, TMT300RS_PS3_NORM_ID)},
@@ -825,6 +851,7 @@ static struct hid_driver tmff2_driver = {
.probe = tmff2_probe,
.remove = tmff2_remove,
.report_fixup = tmff2_report_fixup,
+ .input_configured = tmff2_input_configured,
};
module_hid_driver(tmff2_driver);
diff --git a/src/hid-tmff2.h b/src/hid-tmff2.h
index 6ad1d82..58ab8f3 100644
--- a/src/hid-tmff2.h
+++ b/src/hid-tmff2.h
@@ -11,7 +11,7 @@ extern int spring_level;
extern int damper_level;
extern int friction_level;
extern int range;
-extern int gain;
+extern u16 gain;
extern int alt_mode;
#define USB_VENDOR_ID_THRUSTMASTER 0x044f
diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c
index 00eecee..78e1939 100644
--- a/src/tmt300rs/hid-tmt300rs.c
+++ b/src/tmt300rs/hid-tmt300rs.c
@@ -344,30 +344,35 @@ static uint16_t t300rs_calculate_length(uint16_t length)
return length;
}
+static s32 t300rs_scale_direction(s16 level, u16 direction)
+{
+ return (s32)level * fixp_sin16(direction * 360 / 0x10000) / 0x7fff;
+}
+
static int16_t t300rs_calculate_constant_level(int16_t level, uint16_t direction)
{
- level = (level * fixp_sin16(direction * 360 / 0x10000)) / 0x7fff;
+ s32 scaled_level = t300rs_scale_direction(level, direction);
/* the Windows driver uses the range [-16385;16381] */
- level = level / 2;
-
- return level;
+ return scaled_level / 2;
}
static void t300rs_calculate_periodic_values(struct ff_effect *effect)
{
struct ff_periodic_effect *periodic = &effect->u.periodic;
- int16_t headroom;
+ s32 magnitude, headroom;
- periodic->magnitude = (periodic->magnitude * fixp_sin16(effect->direction * 360 / 0x10000)) / 0x7fff;
+ magnitude = t300rs_scale_direction(periodic->magnitude,
+ effect->direction);
- if (periodic->magnitude < 0){
+ if (magnitude < 0) {
/* the wheel handles positive magnitudes only */
- periodic->magnitude = -periodic->magnitude;
+ magnitude = -magnitude;
/* to give the expected result 180 deg is added to the phase */
periodic->phase = (periodic->phase + (0x10000 / 2)) % 0x10000;
}
+ periodic->magnitude = min_t(s32, magnitude, S16_MAX);
/* the interval [0; 32677[ is used by the wheel for the [0; 360[ degree phase shift */
periodic->phase = periodic->phase * 32677 / 0x10000;
@@ -443,13 +448,16 @@ static void t300rs_calculate_ramp_parameters(uint16_t *out_slope,
{
struct ff_ramp_effect *ramp = &effect->u.ramp;
- int16_t start_level, end_level;
+ s32 start_level, end_level;
- start_level = (ramp->start_level * fixp_sin16(effect->direction * 360 / 0x10000)) / 0x7fff;
- end_level = (ramp->end_level * fixp_sin16(effect->direction * 360 / 0x10000)) / 0x7fff;
+ start_level = t300rs_scale_direction(ramp->start_level,
+ effect->direction);
+ end_level = t300rs_scale_direction(ramp->end_level,
+ effect->direction);
*out_slope = abs(start_level - end_level) / 2;
- *out_center = (start_level + end_level) / 2;
+ *out_center = clamp_t(s32, (start_level + end_level) / 2,
+ S16_MIN, S16_MAX);
*out_invert = (start_level < end_level) ? 0x04 : 0x05;
}