in hid-logitech-hidpp.c [2294:2438]
static int hidpp_ff_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
{
struct hidpp_ff_private_data *data = dev->ff->private;
u8 params[20];
u8 size;
int force;
/* set common parameters */
params[2] = effect->replay.length >> 8;
params[3] = effect->replay.length & 255;
params[4] = effect->replay.delay >> 8;
params[5] = effect->replay.delay & 255;
switch (effect->type) {
case FF_CONSTANT:
force = (effect->u.constant.level * fixp_sin16((effect->direction * 360) >> 16)) >> 15;
params[1] = HIDPP_FF_EFFECT_CONSTANT;
params[6] = force >> 8;
params[7] = force & 255;
params[8] = effect->u.constant.envelope.attack_level >> 7;
params[9] = effect->u.constant.envelope.attack_length >> 8;
params[10] = effect->u.constant.envelope.attack_length & 255;
params[11] = effect->u.constant.envelope.fade_level >> 7;
params[12] = effect->u.constant.envelope.fade_length >> 8;
params[13] = effect->u.constant.envelope.fade_length & 255;
size = 14;
dbg_hid("Uploading constant force level=%d in dir %d = %d\n",
effect->u.constant.level,
effect->direction, force);
dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n",
effect->u.constant.envelope.attack_level,
effect->u.constant.envelope.attack_length,
effect->u.constant.envelope.fade_level,
effect->u.constant.envelope.fade_length);
break;
case FF_PERIODIC:
{
switch (effect->u.periodic.waveform) {
case FF_SINE:
params[1] = HIDPP_FF_EFFECT_PERIODIC_SINE;
break;
case FF_SQUARE:
params[1] = HIDPP_FF_EFFECT_PERIODIC_SQUARE;
break;
case FF_SAW_UP:
params[1] = HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHUP;
break;
case FF_SAW_DOWN:
params[1] = HIDPP_FF_EFFECT_PERIODIC_SAWTOOTHDOWN;
break;
case FF_TRIANGLE:
params[1] = HIDPP_FF_EFFECT_PERIODIC_TRIANGLE;
break;
default:
hid_err(data->hidpp->hid_dev, "Unexpected periodic waveform type %i!\n", effect->u.periodic.waveform);
return -EINVAL;
}
force = (effect->u.periodic.magnitude * fixp_sin16((effect->direction * 360) >> 16)) >> 15;
params[6] = effect->u.periodic.magnitude >> 8;
params[7] = effect->u.periodic.magnitude & 255;
params[8] = effect->u.periodic.offset >> 8;
params[9] = effect->u.periodic.offset & 255;
params[10] = effect->u.periodic.period >> 8;
params[11] = effect->u.periodic.period & 255;
params[12] = effect->u.periodic.phase >> 8;
params[13] = effect->u.periodic.phase & 255;
params[14] = effect->u.periodic.envelope.attack_level >> 7;
params[15] = effect->u.periodic.envelope.attack_length >> 8;
params[16] = effect->u.periodic.envelope.attack_length & 255;
params[17] = effect->u.periodic.envelope.fade_level >> 7;
params[18] = effect->u.periodic.envelope.fade_length >> 8;
params[19] = effect->u.periodic.envelope.fade_length & 255;
size = 20;
dbg_hid("Uploading periodic force mag=%d/dir=%d, offset=%d, period=%d ms, phase=%d\n",
effect->u.periodic.magnitude, effect->direction,
effect->u.periodic.offset,
effect->u.periodic.period,
effect->u.periodic.phase);
dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n",
effect->u.periodic.envelope.attack_level,
effect->u.periodic.envelope.attack_length,
effect->u.periodic.envelope.fade_level,
effect->u.periodic.envelope.fade_length);
break;
}
case FF_RAMP:
params[1] = HIDPP_FF_EFFECT_RAMP;
force = (effect->u.ramp.start_level * fixp_sin16((effect->direction * 360) >> 16)) >> 15;
params[6] = force >> 8;
params[7] = force & 255;
force = (effect->u.ramp.end_level * fixp_sin16((effect->direction * 360) >> 16)) >> 15;
params[8] = force >> 8;
params[9] = force & 255;
params[10] = effect->u.ramp.envelope.attack_level >> 7;
params[11] = effect->u.ramp.envelope.attack_length >> 8;
params[12] = effect->u.ramp.envelope.attack_length & 255;
params[13] = effect->u.ramp.envelope.fade_level >> 7;
params[14] = effect->u.ramp.envelope.fade_length >> 8;
params[15] = effect->u.ramp.envelope.fade_length & 255;
size = 16;
dbg_hid("Uploading ramp force level=%d -> %d in dir %d = %d\n",
effect->u.ramp.start_level,
effect->u.ramp.end_level,
effect->direction, force);
dbg_hid(" envelope attack=(%d, %d ms) fade=(%d, %d ms)\n",
effect->u.ramp.envelope.attack_level,
effect->u.ramp.envelope.attack_length,
effect->u.ramp.envelope.fade_level,
effect->u.ramp.envelope.fade_length);
break;
case FF_FRICTION:
case FF_INERTIA:
case FF_SPRING:
case FF_DAMPER:
params[1] = HIDPP_FF_CONDITION_CMDS[effect->type - FF_SPRING];
params[6] = effect->u.condition[0].left_saturation >> 9;
params[7] = (effect->u.condition[0].left_saturation >> 1) & 255;
params[8] = effect->u.condition[0].left_coeff >> 8;
params[9] = effect->u.condition[0].left_coeff & 255;
params[10] = effect->u.condition[0].deadband >> 9;
params[11] = (effect->u.condition[0].deadband >> 1) & 255;
params[12] = effect->u.condition[0].center >> 8;
params[13] = effect->u.condition[0].center & 255;
params[14] = effect->u.condition[0].right_coeff >> 8;
params[15] = effect->u.condition[0].right_coeff & 255;
params[16] = effect->u.condition[0].right_saturation >> 9;
params[17] = (effect->u.condition[0].right_saturation >> 1) & 255;
size = 18;
dbg_hid("Uploading %s force left coeff=%d, left sat=%d, right coeff=%d, right sat=%d\n",
HIDPP_FF_CONDITION_NAMES[effect->type - FF_SPRING],
effect->u.condition[0].left_coeff,
effect->u.condition[0].left_saturation,
effect->u.condition[0].right_coeff,
effect->u.condition[0].right_saturation);
dbg_hid(" deadband=%d, center=%d\n",
effect->u.condition[0].deadband,
effect->u.condition[0].center);
break;
default:
hid_err(data->hidpp->hid_dev, "Unexpected force type %i!\n", effect->type);
return -EINVAL;
}
return hidpp_ff_queue_work(data, effect->id, HIDPP_FF_DOWNLOAD_EFFECT, params, size);
}