Skip to content

Commit

Permalink
g923: fake friction effect using damper effect
Browse files Browse the repository at this point in the history
This is what the Logitech Windows driver does. Fixes #86
  • Loading branch information
poisotf committed Oct 5, 2024
1 parent 54d2299 commit 9cb6c20
Showing 1 changed file with 50 additions and 22 deletions.
72 changes: 50 additions & 22 deletions hid-lg4ff.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#define LG4FF_MMODE_SWITCHED 1
#define LG4FF_MMODE_NOT_MULTIMODE 2

/* Device does not have a working 'friction' effect, play a 'damper' instead */
#define LG4FF_FLAG_FAKEFRICTION 1

#define LG4FF_MODE_NATIVE_IDX 0
#define LG4FF_MODE_DFEX_IDX 1
#define LG4FF_MODE_DFP_IDX 2
Expand Down Expand Up @@ -146,6 +149,7 @@ struct lg4ff_wheel_data {
const char * const real_tag;
const char * const real_name;
const u16 real_product_id;
const u16 flags;

void (*set_range)(struct hid_device *hid, u16 range);
};
Expand Down Expand Up @@ -192,6 +196,7 @@ struct lg4ff_wheel {
const signed short *ff_effects;
const u16 min_range;
const u16 max_range;
const u16 flags;
void (*set_range)(struct hid_device *hid, u16 range);
};

Expand Down Expand Up @@ -227,18 +232,30 @@ static void lg4ff_set_leds(struct hid_device *hid, u8 leds);
#endif

static const struct lg4ff_wheel lg4ff_devices[] = {
{USB_DEVICE_ID_LOGITECH_WINGMAN_FG, no_wheel_effects, 40, 180, NULL},
{USB_DEVICE_ID_LOGITECH_WINGMAN_FFG, lg4ff_wheel_effects, 40, 180, NULL},
{USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270, NULL},
{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270, NULL},
{USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_dfp},
{USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G29_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G923_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL},
{USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}
{USB_DEVICE_ID_LOGITECH_WINGMAN_FG,
no_wheel_effects, 40, 180, 0, NULL},
{USB_DEVICE_ID_LOGITECH_WINGMAN_FFG,
lg4ff_wheel_effects, 40, 180, 0, NULL},
{USB_DEVICE_ID_LOGITECH_WHEEL,
lg4ff_wheel_effects, 40, 270, 0, NULL},
{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL,
lg4ff_wheel_effects, 40, 270, 0, NULL},
{USB_DEVICE_ID_LOGITECH_DFP_WHEEL,
lg4ff_wheel_effects, 40, 900, 0, lg4ff_set_range_dfp},
{USB_DEVICE_ID_LOGITECH_G25_WHEEL,
lg4ff_wheel_effects, 40, 900, 0, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL,
lg4ff_wheel_effects, 40, 900, 0, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G27_WHEEL,
lg4ff_wheel_effects, 40, 900, 0, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G29_WHEEL,
lg4ff_wheel_effects, 40, 900, 0, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G923_WHEEL,
lg4ff_wheel_effects, 40, 900, LG4FF_FLAG_FAKEFRICTION, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2,
lg4ff_wheel_effects, 40, 270, 0, NULL},
{USB_DEVICE_ID_LOGITECH_WII_WHEEL,
lg4ff_wheel_effects, 40, 270, 0, NULL}
};

static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = {
Expand Down Expand Up @@ -495,7 +512,8 @@ static void lg4ff_send_cmd(struct lg4ff_device_entry *entry, u8 *cmd)
DEBUG("send_cmd: %02X %02X %02X %02X %02X %02X %02X", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
}

static void lg4ff_update_slot(struct lg4ff_slot *slot, struct lg4ff_effect_parameters *parameters)
static void lg4ff_update_slot(struct lg4ff_device_entry *entry,
struct lg4ff_slot *slot, struct lg4ff_effect_parameters *parameters)
{
u8 original_cmd[7];
int d1;
Expand Down Expand Up @@ -584,12 +602,21 @@ static void lg4ff_update_slot(struct lg4ff_slot *slot, struct lg4ff_effect_param
case FF_FRICTION:
s1 = parameters->k1 < 0;
s2 = parameters->k2 < 0;
slot->current_cmd[1] = 0x0e;
slot->current_cmd[2] = SCALE_COEFF(parameters->k1, 8);
slot->current_cmd[3] = SCALE_COEFF(parameters->k2, 8);
slot->current_cmd[4] = SCALE_VALUE_U16(parameters->clip, 8);
slot->current_cmd[5] = (s2 << 4) + s1;
slot->current_cmd[6] = 0;
if (entry->wdata.flags & LG4FF_FLAG_FAKEFRICTION) {
slot->current_cmd[1] = 0x0c;
slot->current_cmd[2] = SCALE_COEFF(parameters->k1, 4);
slot->current_cmd[3] = s1;
slot->current_cmd[4] = SCALE_COEFF(parameters->k2, 4);
slot->current_cmd[5] = s2;
slot->current_cmd[6] = SCALE_VALUE_U16(parameters->clip, 8);
} else {
slot->current_cmd[1] = 0x0e;
slot->current_cmd[2] = SCALE_COEFF(parameters->k1, 8);
slot->current_cmd[3] = SCALE_COEFF(parameters->k2, 8);
slot->current_cmd[4] = SCALE_VALUE_U16(parameters->clip, 8);
slot->current_cmd[5] = (s2 << 4) + s1;
slot->current_cmd[6] = 0;
}
break;
}
}
Expand Down Expand Up @@ -890,7 +917,7 @@ static __always_inline int lg4ff_timer(struct lg4ff_device_entry *entry)

for (i = 0; i < 4; i++) {
slot = &entry->slots[i];
lg4ff_update_slot(slot, &parameters[i]);
lg4ff_update_slot(entry, slot, &parameters[i]);
if (slot->is_updated) {
lg4ff_send_cmd(entry, slot->current_cmd);
slot->is_updated = 0;
Expand Down Expand Up @@ -987,7 +1014,7 @@ static void lg4ff_init_slots(struct lg4ff_device_entry *entry)

for (i = 0; i < 4; i++) {
entry->slots[i].id = i;
lg4ff_update_slot(&entry->slots[i], &parameters);
lg4ff_update_slot(entry, &entry->slots[i], &parameters);
lg4ff_send_cmd(entry, entry->slots[i].current_cmd);
entry->slots[i].is_updated = 0;
}
Expand Down Expand Up @@ -1226,7 +1253,8 @@ static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const s
.set_range = wheel->set_range,
.alternate_modes = alternate_modes,
.real_tag = real_tag,
.real_name = real_name };
.real_name = real_name,
.flags = wheel->flags };

memcpy(wdata, &t_wdata, sizeof(t_wdata));
}
Expand Down

0 comments on commit 9cb6c20

Please sign in to comment.