2 * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
7 * USB/RS232 I-Force joysticks and wheels.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
33 * Set the magnitude of a constant force effect
36 * Note: caller must ensure exclusive access to device
39 static int make_magnitude_modifier(struct iforce
* iforce
,
40 struct resource
* mod_chunk
, int no_alloc
, __s16 level
)
42 unsigned char data
[3];
45 mutex_lock(&iforce
->mem_mutex
);
46 if (allocate_resource(&(iforce
->device_memory
), mod_chunk
, 2,
47 iforce
->device_memory
.start
, iforce
->device_memory
.end
, 2L,
49 mutex_unlock(&iforce
->mem_mutex
);
52 mutex_unlock(&iforce
->mem_mutex
);
55 data
[0] = LO(mod_chunk
->start
);
56 data
[1] = HI(mod_chunk
->start
);
57 data
[2] = HIFIX80(level
);
59 iforce_send_packet(iforce
, FF_CMD_MAGNITUDE
, data
);
61 iforce_dump_packet("magnitude: ", FF_CMD_MAGNITUDE
, data
);
66 * Upload the component of an effect dealing with the period, phase and magnitude
69 static int make_period_modifier(struct iforce
* iforce
,
70 struct resource
* mod_chunk
, int no_alloc
,
71 __s16 magnitude
, __s16 offset
, u16 period
, u16 phase
)
73 unsigned char data
[7];
75 period
= TIME_SCALE(period
);
78 mutex_lock(&iforce
->mem_mutex
);
79 if (allocate_resource(&(iforce
->device_memory
), mod_chunk
, 0x0c,
80 iforce
->device_memory
.start
, iforce
->device_memory
.end
, 2L,
82 mutex_unlock(&iforce
->mem_mutex
);
85 mutex_unlock(&iforce
->mem_mutex
);
88 data
[0] = LO(mod_chunk
->start
);
89 data
[1] = HI(mod_chunk
->start
);
91 data
[2] = HIFIX80(magnitude
);
92 data
[3] = HIFIX80(offset
);
98 iforce_send_packet(iforce
, FF_CMD_PERIOD
, data
);
104 * Uploads the part of an effect setting the envelope of the force
107 static int make_envelope_modifier(struct iforce
* iforce
,
108 struct resource
* mod_chunk
, int no_alloc
,
109 u16 attack_duration
, __s16 initial_level
,
110 u16 fade_duration
, __s16 final_level
)
112 unsigned char data
[8];
114 attack_duration
= TIME_SCALE(attack_duration
);
115 fade_duration
= TIME_SCALE(fade_duration
);
118 mutex_lock(&iforce
->mem_mutex
);
119 if (allocate_resource(&(iforce
->device_memory
), mod_chunk
, 0x0e,
120 iforce
->device_memory
.start
, iforce
->device_memory
.end
, 2L,
122 mutex_unlock(&iforce
->mem_mutex
);
125 mutex_unlock(&iforce
->mem_mutex
);
128 data
[0] = LO(mod_chunk
->start
);
129 data
[1] = HI(mod_chunk
->start
);
131 data
[2] = LO(attack_duration
);
132 data
[3] = HI(attack_duration
);
133 data
[4] = HI(initial_level
);
135 data
[5] = LO(fade_duration
);
136 data
[6] = HI(fade_duration
);
137 data
[7] = HI(final_level
);
139 iforce_send_packet(iforce
, FF_CMD_ENVELOPE
, data
);
145 * Component of spring, friction, inertia... effects
148 static int make_condition_modifier(struct iforce
* iforce
,
149 struct resource
* mod_chunk
, int no_alloc
,
150 __u16 rsat
, __u16 lsat
, __s16 rk
, __s16 lk
, u16 db
, __s16 center
)
152 unsigned char data
[10];
155 mutex_lock(&iforce
->mem_mutex
);
156 if (allocate_resource(&(iforce
->device_memory
), mod_chunk
, 8,
157 iforce
->device_memory
.start
, iforce
->device_memory
.end
, 2L,
159 mutex_unlock(&iforce
->mem_mutex
);
162 mutex_unlock(&iforce
->mem_mutex
);
165 data
[0] = LO(mod_chunk
->start
);
166 data
[1] = HI(mod_chunk
->start
);
168 data
[2] = (100*rk
)>>15; /* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */
169 data
[3] = (100*lk
)>>15; /* This code is incorrect on cpus lacking arith shift */
171 center
= (500*center
)>>15;
172 data
[4] = LO(center
);
173 data
[5] = HI(center
);
179 data
[8] = (100*rsat
)>>16;
180 data
[9] = (100*lsat
)>>16;
182 iforce_send_packet(iforce
, FF_CMD_CONDITION
, data
);
183 iforce_dump_packet("condition", FF_CMD_CONDITION
, data
);
188 static unsigned char find_button(struct iforce
*iforce
, signed short button
)
191 for (i
= 1; iforce
->type
->btn
[i
] >= 0; i
++)
192 if (iforce
->type
->btn
[i
] == button
)
198 * Analyse the changes in an effect, and tell if we need to send an condition
201 static int need_condition_modifier(struct iforce
* iforce
, struct ff_effect
* new)
204 struct ff_effect
* old
= &iforce
->core_effects
[id
].effect
;
208 if (new->type
!= FF_SPRING
&& new->type
!= FF_FRICTION
) {
209 printk(KERN_WARNING
"iforce.c: bad effect type in need_condition_modifier\n");
214 ret
|= old
->u
.condition
[i
].right_saturation
!= new->u
.condition
[i
].right_saturation
215 || old
->u
.condition
[i
].left_saturation
!= new->u
.condition
[i
].left_saturation
216 || old
->u
.condition
[i
].right_coeff
!= new->u
.condition
[i
].right_coeff
217 || old
->u
.condition
[i
].left_coeff
!= new->u
.condition
[i
].left_coeff
218 || old
->u
.condition
[i
].deadband
!= new->u
.condition
[i
].deadband
219 || old
->u
.condition
[i
].center
!= new->u
.condition
[i
].center
;
225 * Analyse the changes in an effect, and tell if we need to send a magnitude
228 static int need_magnitude_modifier(struct iforce
* iforce
, struct ff_effect
* effect
)
231 struct ff_effect
* old
= &iforce
->core_effects
[id
].effect
;
233 if (effect
->type
!= FF_CONSTANT
) {
234 printk(KERN_WARNING
"iforce.c: bad effect type in need_envelope_modifier\n");
238 return (old
->u
.constant
.level
!= effect
->u
.constant
.level
);
242 * Analyse the changes in an effect, and tell if we need to send an envelope
245 static int need_envelope_modifier(struct iforce
* iforce
, struct ff_effect
* effect
)
248 struct ff_effect
* old
= &iforce
->core_effects
[id
].effect
;
250 switch (effect
->type
) {
252 if (old
->u
.constant
.envelope
.attack_length
!= effect
->u
.constant
.envelope
.attack_length
253 || old
->u
.constant
.envelope
.attack_level
!= effect
->u
.constant
.envelope
.attack_level
254 || old
->u
.constant
.envelope
.fade_length
!= effect
->u
.constant
.envelope
.fade_length
255 || old
->u
.constant
.envelope
.fade_level
!= effect
->u
.constant
.envelope
.fade_level
)
260 if (old
->u
.periodic
.envelope
.attack_length
!= effect
->u
.periodic
.envelope
.attack_length
261 || old
->u
.periodic
.envelope
.attack_level
!= effect
->u
.periodic
.envelope
.attack_level
262 || old
->u
.periodic
.envelope
.fade_length
!= effect
->u
.periodic
.envelope
.fade_length
263 || old
->u
.periodic
.envelope
.fade_level
!= effect
->u
.periodic
.envelope
.fade_level
)
268 printk(KERN_WARNING
"iforce.c: bad effect type in need_envelope_modifier\n");
275 * Analyse the changes in an effect, and tell if we need to send a periodic
278 static int need_period_modifier(struct iforce
* iforce
, struct ff_effect
* new)
281 struct ff_effect
* old
= &iforce
->core_effects
[id
].effect
;
283 if (new->type
!= FF_PERIODIC
) {
284 printk(KERN_WARNING
"iforce.c: bad effect type in need_periodic_modifier\n");
288 return (old
->u
.periodic
.period
!= new->u
.periodic
.period
289 || old
->u
.periodic
.magnitude
!= new->u
.periodic
.magnitude
290 || old
->u
.periodic
.offset
!= new->u
.periodic
.offset
291 || old
->u
.periodic
.phase
!= new->u
.periodic
.phase
);
295 * Analyse the changes in an effect, and tell if we need to send an effect
298 static int need_core(struct iforce
* iforce
, struct ff_effect
* new)
301 struct ff_effect
* old
= &iforce
->core_effects
[id
].effect
;
303 if (old
->direction
!= new->direction
304 || old
->trigger
.button
!= new->trigger
.button
305 || old
->trigger
.interval
!= new->trigger
.interval
306 || old
->replay
.length
!= new->replay
.length
307 || old
->replay
.delay
!= new->replay
.delay
)
313 * Send the part common to all effects to the device
315 static int make_core(struct iforce
* iforce
, u16 id
, u16 mod_id1
, u16 mod_id2
,
316 u8 effect_type
, u8 axes
, u16 duration
, u16 delay
, u16 button
,
317 u16 interval
, u16 direction
)
319 unsigned char data
[14];
321 duration
= TIME_SCALE(duration
);
322 delay
= TIME_SCALE(delay
);
323 interval
= TIME_SCALE(interval
);
326 data
[1] = effect_type
;
327 data
[2] = LO(axes
) | find_button(iforce
, button
);
329 data
[3] = LO(duration
);
330 data
[4] = HI(duration
);
332 data
[5] = HI(direction
);
334 data
[6] = LO(interval
);
335 data
[7] = HI(interval
);
337 data
[8] = LO(mod_id1
);
338 data
[9] = HI(mod_id1
);
339 data
[10] = LO(mod_id2
);
340 data
[11] = HI(mod_id2
);
342 data
[12] = LO(delay
);
343 data
[13] = HI(delay
);
346 /* iforce_control_playback(iforce, id, 0);*/
348 iforce_send_packet(iforce
, FF_CMD_EFFECT
, data
);
350 /* If needed, restart effect */
351 if (test_bit(FF_CORE_SHOULD_PLAY
, iforce
->core_effects
[id
].flags
)) {
352 /* BUG: perhaps we should replay n times, instead of 1. But we do not know n */
353 iforce_control_playback(iforce
, id
, 1);
360 * Upload a periodic effect to the device
361 * See also iforce_upload_constant.
363 int iforce_upload_periodic(struct iforce
* iforce
, struct ff_effect
* effect
, int is_update
)
366 int core_id
= effect
->id
;
367 struct iforce_core_effect
* core_effect
= iforce
->core_effects
+ core_id
;
368 struct resource
* mod1_chunk
= &(iforce
->core_effects
[core_id
].mod1_chunk
);
369 struct resource
* mod2_chunk
= &(iforce
->core_effects
[core_id
].mod2_chunk
);
374 if (!is_update
|| need_period_modifier(iforce
, effect
)) {
375 param1_err
= make_period_modifier(iforce
, mod1_chunk
,
377 effect
->u
.periodic
.magnitude
, effect
->u
.periodic
.offset
,
378 effect
->u
.periodic
.period
, effect
->u
.periodic
.phase
);
379 if (param1_err
) return param1_err
;
380 set_bit(FF_MOD1_IS_USED
, core_effect
->flags
);
383 if (!is_update
|| need_envelope_modifier(iforce
, effect
)) {
384 param2_err
= make_envelope_modifier(iforce
, mod2_chunk
,
386 effect
->u
.periodic
.envelope
.attack_length
,
387 effect
->u
.periodic
.envelope
.attack_level
,
388 effect
->u
.periodic
.envelope
.fade_length
,
389 effect
->u
.periodic
.envelope
.fade_level
);
390 if (param2_err
) return param2_err
;
391 set_bit(FF_MOD2_IS_USED
, core_effect
->flags
);
394 switch (effect
->u
.periodic
.waveform
) {
395 case FF_SQUARE
: wave_code
= 0x20; break;
396 case FF_TRIANGLE
: wave_code
= 0x21; break;
397 case FF_SINE
: wave_code
= 0x22; break;
398 case FF_SAW_UP
: wave_code
= 0x23; break;
399 case FF_SAW_DOWN
: wave_code
= 0x24; break;
400 default: wave_code
= 0x20; break;
403 if (!is_update
|| need_core(iforce
, effect
)) {
404 core_err
= make_core(iforce
, effect
->id
,
409 effect
->replay
.length
,
410 effect
->replay
.delay
,
411 effect
->trigger
.button
,
412 effect
->trigger
.interval
,
416 /* If one of the parameter creation failed, we already returned an
418 * If the core creation failed, we return its error code.
419 * Else: if one parameter at least was created, we return 0
422 return core_err
< 0 ? core_err
: (param1_err
&& param2_err
);
426 * Upload a constant force effect
429 * 0 Ok, effect created or updated
430 * 1 effect did not change since last upload, and no packet was therefore sent
432 int iforce_upload_constant(struct iforce
* iforce
, struct ff_effect
* effect
, int is_update
)
434 int core_id
= effect
->id
;
435 struct iforce_core_effect
* core_effect
= iforce
->core_effects
+ core_id
;
436 struct resource
* mod1_chunk
= &(iforce
->core_effects
[core_id
].mod1_chunk
);
437 struct resource
* mod2_chunk
= &(iforce
->core_effects
[core_id
].mod2_chunk
);
442 if (!is_update
|| need_magnitude_modifier(iforce
, effect
)) {
443 param1_err
= make_magnitude_modifier(iforce
, mod1_chunk
,
445 effect
->u
.constant
.level
);
446 if (param1_err
) return param1_err
;
447 set_bit(FF_MOD1_IS_USED
, core_effect
->flags
);
450 if (!is_update
|| need_envelope_modifier(iforce
, effect
)) {
451 param2_err
= make_envelope_modifier(iforce
, mod2_chunk
,
453 effect
->u
.constant
.envelope
.attack_length
,
454 effect
->u
.constant
.envelope
.attack_level
,
455 effect
->u
.constant
.envelope
.fade_length
,
456 effect
->u
.constant
.envelope
.fade_level
);
457 if (param2_err
) return param2_err
;
458 set_bit(FF_MOD2_IS_USED
, core_effect
->flags
);
461 if (!is_update
|| need_core(iforce
, effect
)) {
462 core_err
= make_core(iforce
, effect
->id
,
467 effect
->replay
.length
,
468 effect
->replay
.delay
,
469 effect
->trigger
.button
,
470 effect
->trigger
.interval
,
474 /* If one of the parameter creation failed, we already returned an
476 * If the core creation failed, we return its error code.
477 * Else: if one parameter at least was created, we return 0
480 return core_err
< 0 ? core_err
: (param1_err
&& param2_err
);
484 * Upload an condition effect. Those are for example friction, inertia, springs...
486 int iforce_upload_condition(struct iforce
* iforce
, struct ff_effect
* effect
, int is_update
)
488 int core_id
= effect
->id
;
489 struct iforce_core_effect
* core_effect
= iforce
->core_effects
+ core_id
;
490 struct resource
* mod1_chunk
= &(core_effect
->mod1_chunk
);
491 struct resource
* mod2_chunk
= &(core_effect
->mod2_chunk
);
496 switch (effect
->type
) {
497 case FF_SPRING
: type
= 0x40; break;
498 case FF_DAMPER
: type
= 0x41; break;
502 if (!is_update
|| need_condition_modifier(iforce
, effect
)) {
503 param_err
= make_condition_modifier(iforce
, mod1_chunk
,
505 effect
->u
.condition
[0].right_saturation
,
506 effect
->u
.condition
[0].left_saturation
,
507 effect
->u
.condition
[0].right_coeff
,
508 effect
->u
.condition
[0].left_coeff
,
509 effect
->u
.condition
[0].deadband
,
510 effect
->u
.condition
[0].center
);
511 if (param_err
) return param_err
;
512 set_bit(FF_MOD1_IS_USED
, core_effect
->flags
);
514 param_err
= make_condition_modifier(iforce
, mod2_chunk
,
516 effect
->u
.condition
[1].right_saturation
,
517 effect
->u
.condition
[1].left_saturation
,
518 effect
->u
.condition
[1].right_coeff
,
519 effect
->u
.condition
[1].left_coeff
,
520 effect
->u
.condition
[1].deadband
,
521 effect
->u
.condition
[1].center
);
522 if (param_err
) return param_err
;
523 set_bit(FF_MOD2_IS_USED
, core_effect
->flags
);
527 if (!is_update
|| need_core(iforce
, effect
)) {
528 core_err
= make_core(iforce
, effect
->id
,
529 mod1_chunk
->start
, mod2_chunk
->start
,
531 effect
->replay
.length
, effect
->replay
.delay
,
532 effect
->trigger
.button
, effect
->trigger
.interval
,
536 /* If the parameter creation failed, we already returned an
538 * If the core creation failed, we return its error code.
539 * Else: if a parameter was created, we return 0
542 return core_err
< 0 ? core_err
: param_err
;