2222#define PID_EFFECTS_MAX 64
2323#define PID_INFINITE 0xffff
2424
25+ /* Linux Force Feedback API uses miliseconds as time unit */
26+ #define FF_TIME_EXPONENT -3
27+
2528/* Report usage table used to put reports into an array */
2629
2730#define PID_SET_EFFECT 0
@@ -231,6 +234,24 @@ static int pidff_rescale_signed(int i, struct hid_field *field)
231234 field -> logical_minimum / -0x8000 ;
232235}
233236
237+ /*
238+ * Scale time value from Linux default (ms) to field units
239+ */
240+ static u32 pidff_rescale_time (u16 time , struct hid_field * field )
241+ {
242+ u32 scaled_time = time ;
243+ int exponent = field -> unit_exponent ;
244+ pr_debug ("time field exponent: %d\n" , exponent );
245+
246+ for (;exponent < FF_TIME_EXPONENT ; exponent ++ )
247+ scaled_time *= 10 ;
248+ for (;exponent > FF_TIME_EXPONENT ; exponent -- )
249+ scaled_time /= 10 ;
250+
251+ pr_debug ("time calculated from %d to %d\n" , time , scaled_time );
252+ return scaled_time ;
253+ }
254+
234255static void pidff_set (struct pidff_usage * usage , u16 value )
235256{
236257 usage -> value [0 ] = pidff_rescale (value , 0xffff , usage -> field );
@@ -252,6 +273,27 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value)
252273 pr_debug ("calculated from %d to %d\n" , value , usage -> value [0 ]);
253274}
254275
276+ static void pidff_set_time (struct pidff_usage * usage , u16 time )
277+ {
278+ u32 modified_time = pidff_rescale_time (time , usage -> field );
279+ usage -> value [0 ] = pidff_clamp (modified_time , usage -> field );
280+ }
281+
282+ static void pidff_set_duration (struct pidff_usage * usage , u16 duration )
283+ {
284+ /* Convert infinite length from Linux API (0)
285+ to PID standard (NULL) if needed */
286+ if (duration == 0 )
287+ duration = PID_INFINITE ;
288+
289+ if (duration == PID_INFINITE ) {
290+ usage -> value [0 ] = PID_INFINITE ;
291+ return ;
292+ }
293+
294+ pidff_set_time (usage , duration );
295+ }
296+
255297/*
256298 * Send envelope report to the device
257299 */
@@ -270,8 +312,10 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
270312 0x7fff ? 0x7fff : envelope -> fade_level , 0x7fff ,
271313 pidff -> set_envelope [PID_FADE_LEVEL ].field );
272314
273- pidff -> set_envelope [PID_ATTACK_TIME ].value [0 ] = envelope -> attack_length ;
274- pidff -> set_envelope [PID_FADE_TIME ].value [0 ] = envelope -> fade_length ;
315+ pidff_set_time (& pidff -> set_envelope [PID_ATTACK_TIME ],
316+ envelope -> attack_length );
317+ pidff_set_time (& pidff -> set_envelope [PID_FADE_TIME ],
318+ envelope -> fade_length );
275319
276320 hid_dbg (pidff -> hid , "attack %u => %d\n" ,
277321 envelope -> attack_level ,
@@ -340,14 +384,12 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
340384 pidff -> set_effect_type -> value [0 ] =
341385 pidff -> create_new_effect_type -> value [0 ];
342386
343- /* Convert infinite length from Linux API (0)
344- to PID standard (NULL) if needed */
345- pidff -> set_effect [PID_DURATION ].value [0 ] =
346- effect -> replay .length == 0 ? PID_INFINITE : effect -> replay .length ;
387+ pidff_set_duration (& pidff -> set_effect [PID_DURATION ],
388+ effect -> replay .length );
347389
348390 pidff -> set_effect [PID_TRIGGER_BUTTON ].value [0 ] = effect -> trigger .button ;
349- pidff -> set_effect [PID_TRIGGER_REPEAT_INT ]. value [ 0 ] =
350- effect -> trigger .interval ;
391+ pidff_set_time ( & pidff -> set_effect [PID_TRIGGER_REPEAT_INT ],
392+ effect -> trigger .interval ) ;
351393 pidff -> set_effect [PID_GAIN ].value [0 ] =
352394 pidff -> set_effect [PID_GAIN ].field -> logical_maximum ;
353395 pidff -> set_effect [PID_DIRECTION_ENABLE ].value [0 ] = 1 ;
@@ -360,7 +402,8 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
360402
361403 /* Omit setting delay field if it's missing */
362404 if (!(pidff -> quirks & HID_PIDFF_QUIRK_MISSING_DELAY ))
363- pidff -> set_effect [PID_START_DELAY ].value [0 ] = effect -> replay .delay ;
405+ pidff_set_time (& pidff -> set_effect [PID_START_DELAY ],
406+ effect -> replay .delay );
364407
365408 hid_hw_request (pidff -> hid , pidff -> reports [PID_SET_EFFECT ],
366409 HID_REQ_SET_REPORT );
@@ -392,15 +435,11 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
392435 pidff_set_signed (& pidff -> set_periodic [PID_OFFSET ],
393436 effect -> u .periodic .offset );
394437 pidff_set (& pidff -> set_periodic [PID_PHASE ], effect -> u .periodic .phase );
395-
396- /* Clamp period to ensure the device can play the effect */
397- pidff -> set_periodic [PID_PERIOD ].value [0 ] =
398- pidff_clamp (effect -> u .periodic .period ,
399- pidff -> set_periodic [PID_PERIOD ].field );
438+ pidff_set_time (& pidff -> set_periodic [PID_PERIOD ],
439+ effect -> u .periodic .period );
400440
401441 hid_hw_request (pidff -> hid , pidff -> reports [PID_SET_PERIODIC ],
402442 HID_REQ_SET_REPORT );
403-
404443}
405444
406445/*
0 commit comments