diff options
author | Anssi Hannula <anssi.hannula@gmail.com> | 2006-07-19 01:40:39 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2006-07-19 01:40:39 -0400 |
commit | f6a01c85965c9e6fa8fb893c1fa5db16130d0ccb (patch) | |
tree | d23d6607c6167109cffb203e8b427824c979af94 /drivers/input/joystick/iforce | |
parent | 7d928a2b14eede1f333db7b7b684c57f7fa7f456 (diff) | |
download | kernel_samsung_aries-f6a01c85965c9e6fa8fb893c1fa5db16130d0ccb.zip kernel_samsung_aries-f6a01c85965c9e6fa8fb893c1fa5db16130d0ccb.tar.gz kernel_samsung_aries-f6a01c85965c9e6fa8fb893c1fa5db16130d0ccb.tar.bz2 |
Input: iforce - switch to the new FF interface
Signed-off-by: Anssi Hannula <anssi.hannula@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/joystick/iforce')
-rw-r--r-- | drivers/input/joystick/iforce/iforce-ff.c | 118 | ||||
-rw-r--r-- | drivers/input/joystick/iforce/iforce-main.c | 226 | ||||
-rw-r--r-- | drivers/input/joystick/iforce/iforce-packets.c | 15 | ||||
-rw-r--r-- | drivers/input/joystick/iforce/iforce.h | 26 |
4 files changed, 147 insertions, 238 deletions
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c index 50c9076..8fb0c19 100644 --- a/drivers/input/joystick/iforce/iforce-ff.c +++ b/drivers/input/joystick/iforce/iforce-ff.c @@ -165,19 +165,19 @@ static int make_condition_modifier(struct iforce* iforce, data[0] = LO(mod_chunk->start); data[1] = HI(mod_chunk->start); - data[2] = (100*rk)>>15; /* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */ - data[3] = (100*lk)>>15; /* This code is incorrect on cpus lacking arith shift */ + data[2] = (100 * rk) >> 15; /* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */ + data[3] = (100 * lk) >> 15; /* This code is incorrect on cpus lacking arith shift */ - center = (500*center)>>15; + center = (500 * center) >> 15; data[4] = LO(center); data[5] = HI(center); - db = (1000*db)>>16; + db = (1000 * db) >> 16; data[6] = LO(db); data[7] = HI(db); - data[8] = (100*rsat)>>16; - data[9] = (100*lsat)>>16; + data[8] = (100 * rsat) >> 16; + data[9] = (100 * lsat) >> 16; iforce_send_packet(iforce, FF_CMD_CONDITION, data); iforce_dump_packet("condition", FF_CMD_CONDITION, data); @@ -188,6 +188,7 @@ static int make_condition_modifier(struct iforce* iforce, static unsigned char find_button(struct iforce *iforce, signed short button) { int i; + for (i = 1; iforce->type->btn[i] >= 0; i++) if (iforce->type->btn[i] == button) return i + 1; @@ -198,19 +199,17 @@ static unsigned char find_button(struct iforce *iforce, signed short button) * Analyse the changes in an effect, and tell if we need to send an condition * parameter packet */ -static int need_condition_modifier(struct iforce* iforce, struct ff_effect* new) +static int need_condition_modifier(struct ff_effect *old, struct ff_effect *new) { - int id = new->id; - struct ff_effect* old = &iforce->core_effects[id].effect; - int ret=0; + int ret = 0; int i; if (new->type != FF_SPRING && new->type != FF_FRICTION) { printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n"); - return FALSE; + return 0; } - for(i=0; i<2; i++) { + for (i = 0; i < 2; i++) { ret |= old->u.condition[i].right_saturation != new->u.condition[i].right_saturation || old->u.condition[i].left_saturation != new->u.condition[i].left_saturation || old->u.condition[i].right_coeff != new->u.condition[i].right_coeff @@ -225,35 +224,29 @@ static int need_condition_modifier(struct iforce* iforce, struct ff_effect* new) * Analyse the changes in an effect, and tell if we need to send a magnitude * parameter packet */ -static int need_magnitude_modifier(struct iforce* iforce, struct ff_effect* effect) +static int need_magnitude_modifier(struct ff_effect *old, struct ff_effect *effect) { - int id = effect->id; - struct ff_effect* old = &iforce->core_effects[id].effect; - if (effect->type != FF_CONSTANT) { printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n"); - return FALSE; + return 0; } - return (old->u.constant.level != effect->u.constant.level); + return old->u.constant.level != effect->u.constant.level; } /* * Analyse the changes in an effect, and tell if we need to send an envelope * parameter packet */ -static int need_envelope_modifier(struct iforce* iforce, struct ff_effect* effect) +static int need_envelope_modifier(struct ff_effect *old, struct ff_effect *effect) { - int id = effect->id; - struct ff_effect* old = &iforce->core_effects[id].effect; - switch (effect->type) { case FF_CONSTANT: if (old->u.constant.envelope.attack_length != effect->u.constant.envelope.attack_length || old->u.constant.envelope.attack_level != effect->u.constant.envelope.attack_level || old->u.constant.envelope.fade_length != effect->u.constant.envelope.fade_length || old->u.constant.envelope.fade_level != effect->u.constant.envelope.fade_level) - return TRUE; + return 1; break; case FF_PERIODIC: @@ -261,30 +254,26 @@ static int need_envelope_modifier(struct iforce* iforce, struct ff_effect* effec || old->u.periodic.envelope.attack_level != effect->u.periodic.envelope.attack_level || old->u.periodic.envelope.fade_length != effect->u.periodic.envelope.fade_length || old->u.periodic.envelope.fade_level != effect->u.periodic.envelope.fade_level) - return TRUE; + return 1; break; default: printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n"); } - return FALSE; + return 0; } /* * Analyse the changes in an effect, and tell if we need to send a periodic * parameter effect */ -static int need_period_modifier(struct iforce* iforce, struct ff_effect* new) +static int need_period_modifier(struct ff_effect *old, struct ff_effect *new) { - int id = new->id; - struct ff_effect* old = &iforce->core_effects[id].effect; - if (new->type != FF_PERIODIC) { - printk(KERN_WARNING "iforce.c: bad effect type in need_periodic_modifier\n"); - return FALSE; + printk(KERN_WARNING "iforce.c: bad effect type in need_period_modifier\n"); + return 0; } - return (old->u.periodic.period != new->u.periodic.period || old->u.periodic.magnitude != new->u.periodic.magnitude || old->u.periodic.offset != new->u.periodic.offset @@ -295,19 +284,16 @@ static int need_period_modifier(struct iforce* iforce, struct ff_effect* new) * Analyse the changes in an effect, and tell if we need to send an effect * packet */ -static int need_core(struct iforce* iforce, struct ff_effect* new) +static int need_core(struct ff_effect *old, struct ff_effect *new) { - int id = new->id; - struct ff_effect* old = &iforce->core_effects[id].effect; - if (old->direction != new->direction || old->trigger.button != new->trigger.button || old->trigger.interval != new->trigger.interval || old->replay.length != new->replay.length || old->replay.delay != new->replay.delay) - return TRUE; + return 1; - return FALSE; + return 0; } /* * Send the part common to all effects to the device @@ -360,7 +346,7 @@ static int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2, * Upload a periodic effect to the device * See also iforce_upload_constant. */ -int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int is_update) +int iforce_upload_periodic(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old) { u8 wave_code; int core_id = effect->id; @@ -371,23 +357,25 @@ int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int int param2_err = 1; int core_err = 0; - if (!is_update || need_period_modifier(iforce, effect)) { + if (!old || need_period_modifier(old, effect)) { param1_err = make_period_modifier(iforce, mod1_chunk, - is_update, + old != NULL, effect->u.periodic.magnitude, effect->u.periodic.offset, effect->u.periodic.period, effect->u.periodic.phase); - if (param1_err) return param1_err; + if (param1_err) + return param1_err; set_bit(FF_MOD1_IS_USED, core_effect->flags); } - if (!is_update || need_envelope_modifier(iforce, effect)) { + if (!old || need_envelope_modifier(old, effect)) { param2_err = make_envelope_modifier(iforce, mod2_chunk, - is_update, + old !=NULL, effect->u.periodic.envelope.attack_length, effect->u.periodic.envelope.attack_level, effect->u.periodic.envelope.fade_length, effect->u.periodic.envelope.fade_level); - if (param2_err) return param2_err; + if (param2_err) + return param2_err; set_bit(FF_MOD2_IS_USED, core_effect->flags); } @@ -400,7 +388,7 @@ int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int default: wave_code = 0x20; break; } - if (!is_update || need_core(iforce, effect)) { + if (!old || need_core(old, effect)) { core_err = make_core(iforce, effect->id, mod1_chunk->start, mod2_chunk->start, @@ -429,7 +417,7 @@ int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int * 0 Ok, effect created or updated * 1 effect did not change since last upload, and no packet was therefore sent */ -int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int is_update) +int iforce_upload_constant(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old) { int core_id = effect->id; struct iforce_core_effect* core_effect = iforce->core_effects + core_id; @@ -439,26 +427,28 @@ int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int int param2_err = 1; int core_err = 0; - if (!is_update || need_magnitude_modifier(iforce, effect)) { + if (!old || need_magnitude_modifier(old, effect)) { param1_err = make_magnitude_modifier(iforce, mod1_chunk, - is_update, + old != NULL, effect->u.constant.level); - if (param1_err) return param1_err; + if (param1_err) + return param1_err; set_bit(FF_MOD1_IS_USED, core_effect->flags); } - if (!is_update || need_envelope_modifier(iforce, effect)) { + if (!old || need_envelope_modifier(old, effect)) { param2_err = make_envelope_modifier(iforce, mod2_chunk, - is_update, + old != NULL, effect->u.constant.envelope.attack_length, effect->u.constant.envelope.attack_level, effect->u.constant.envelope.fade_length, effect->u.constant.envelope.fade_level); - if (param2_err) return param2_err; + if (param2_err) + return param2_err; set_bit(FF_MOD2_IS_USED, core_effect->flags); } - if (!is_update || need_core(iforce, effect)) { + if (!old || need_core(old, effect)) { core_err = make_core(iforce, effect->id, mod1_chunk->start, mod2_chunk->start, @@ -483,7 +473,7 @@ int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int /* * Upload an condition effect. Those are for example friction, inertia, springs... */ -int iforce_upload_condition(struct iforce* iforce, struct ff_effect* effect, int is_update) +int iforce_upload_condition(struct iforce *iforce, struct ff_effect *effect, struct ff_effect *old) { int core_id = effect->id; struct iforce_core_effect* core_effect = iforce->core_effects + core_id; @@ -494,37 +484,39 @@ int iforce_upload_condition(struct iforce* iforce, struct ff_effect* effect, int int core_err = 0; switch (effect->type) { - case FF_SPRING: type = 0x40; break; - case FF_DAMPER: type = 0x41; break; + case FF_SPRING: type = 0x40; break; + case FF_DAMPER: type = 0x41; break; default: return -1; } - if (!is_update || need_condition_modifier(iforce, effect)) { + if (!old || need_condition_modifier(old, effect)) { param_err = make_condition_modifier(iforce, mod1_chunk, - is_update, + old != NULL, effect->u.condition[0].right_saturation, effect->u.condition[0].left_saturation, effect->u.condition[0].right_coeff, effect->u.condition[0].left_coeff, effect->u.condition[0].deadband, effect->u.condition[0].center); - if (param_err) return param_err; + if (param_err) + return param_err; set_bit(FF_MOD1_IS_USED, core_effect->flags); param_err = make_condition_modifier(iforce, mod2_chunk, - is_update, + old != NULL, effect->u.condition[1].right_saturation, effect->u.condition[1].left_saturation, effect->u.condition[1].right_coeff, effect->u.condition[1].left_coeff, effect->u.condition[1].deadband, effect->u.condition[1].center); - if (param_err) return param_err; + if (param_err) + return param_err; set_bit(FF_MOD2_IS_USED, core_effect->flags); } - if (!is_update || need_core(iforce, effect)) { + if (!old || need_core(old, effect)) { core_err = make_core(iforce, effect->id, mod1_chunk->start, mod2_chunk->start, type, 0xc0, diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b4914e7..24c684b 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -83,103 +83,57 @@ static struct iforce_device iforce_device[] = { { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } }; - - -static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +static int iforce_playback(struct input_dev *dev, int effect_id, int value) { struct iforce* iforce = dev->private; - unsigned char data[3]; - - if (type != EV_FF) - return -1; - - switch (code) { - - case FF_GAIN: - - data[0] = value >> 9; - iforce_send_packet(iforce, FF_CMD_GAIN, data); - - return 0; - - case FF_AUTOCENTER: + struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id]; - data[0] = 0x03; - data[1] = value >> 9; - iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); + if (value > 0) + set_bit(FF_CORE_SHOULD_PLAY, core_effect->flags); + else + clear_bit(FF_CORE_SHOULD_PLAY, core_effect->flags); - data[0] = 0x04; - data[1] = 0x01; - iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); + iforce_control_playback(iforce, effect_id, value); + return 0; +} - return 0; +static void iforce_set_gain(struct input_dev *dev, u16 gain) +{ + struct iforce* iforce = dev->private; + unsigned char data[3]; - default: /* Play or stop an effect */ + data[0] = gain >> 9; + iforce_send_packet(iforce, FF_CMD_GAIN, data); +} - if (!CHECK_OWNERSHIP(code, iforce)) { - return -1; - } - if (value > 0) { - set_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags); - } - else { - clear_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags); - } +static void iforce_set_autocenter(struct input_dev *dev, u16 magnitude) +{ + struct iforce* iforce = dev->private; + unsigned char data[3]; - iforce_control_playback(iforce, code, value); - return 0; - } + data[0] = 0x03; + data[1] = magnitude >> 9; + iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); - return -1; + data[0] = 0x04; + data[1] = 0x01; + iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data); } /* * Function called when an ioctl is performed on the event dev entry. * It uploads an effect to the device */ -static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect) +static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) { struct iforce* iforce = dev->private; - int id; + struct iforce_core_effect *core_effect = &iforce->core_effects[effect->id]; int ret; - int is_update; - -/* Check this effect type is supported by this device */ - if (!test_bit(effect->type, iforce->dev->ffbit)) - return -EINVAL; - -/* - * If we want to create a new effect, get a free id - */ - if (effect->id == -1) { - - for (id = 0; id < FF_EFFECTS_MAX; ++id) - if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) - break; - - if (id == FF_EFFECTS_MAX || id >= iforce->dev->ff_effects_max) - return -ENOMEM; - - effect->id = id; - iforce->core_effects[id].owner = current->pid; - iforce->core_effects[id].flags[0] = (1 << FF_CORE_IS_USED); /* Only IS_USED bit must be set */ - - is_update = FALSE; - } - else { - /* We want to update an effect */ - if (!CHECK_OWNERSHIP(effect->id, iforce)) - return -EACCES; - - /* Parameter type cannot be updated */ - if (effect->type != iforce->core_effects[effect->id].effect.type) - return -EINVAL; + if (__test_and_set_bit(FF_CORE_IS_USED, core_effect->flags)) { /* Check the effect is not already being updated */ - if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) + if (test_bit(FF_CORE_UPDATE, core_effect->flags)) return -EAGAIN; - - is_update = TRUE; } /* @@ -188,28 +142,28 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect) switch (effect->type) { case FF_PERIODIC: - ret = iforce_upload_periodic(iforce, effect, is_update); + ret = iforce_upload_periodic(iforce, effect, old); break; case FF_CONSTANT: - ret = iforce_upload_constant(iforce, effect, is_update); + ret = iforce_upload_constant(iforce, effect, old); break; case FF_SPRING: case FF_DAMPER: - ret = iforce_upload_condition(iforce, effect, is_update); + ret = iforce_upload_condition(iforce, effect, old); break; default: return -EINVAL; } + if (ret == 0) { /* A packet was sent, forbid new updates until we are notified * that the packet was updated */ - set_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags); + set_bit(FF_CORE_UPDATE, core_effect->flags); } - iforce->core_effects[effect->id].effect = *effect; return ret; } @@ -219,20 +173,9 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect) */ static int iforce_erase_effect(struct input_dev *dev, int effect_id) { - struct iforce* iforce = dev->private; + struct iforce *iforce = dev->private; + struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id]; int err = 0; - struct iforce_core_effect* core_effect; - - if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX) - return -EINVAL; - - core_effect = &iforce->core_effects[effect_id]; - - /* Check who is trying to erase this effect */ - if (core_effect->owner != current->pid) { - printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, core_effect->owner); - return -EACCES; - } if (test_bit(FF_MOD1_IS_USED, core_effect->flags)) err = release_resource(&core_effect->mod1_chunk); @@ -240,7 +183,7 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id) if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags)) err = release_resource(&core_effect->mod2_chunk); - /*TODO: remember to change that if more FF_MOD* bits are added */ + /* TODO: remember to change that if more FF_MOD* bits are added */ core_effect->flags[0] = 0; return err; @@ -260,52 +203,31 @@ static int iforce_open(struct input_dev *dev) #endif } - /* Enable force feedback */ - iforce_send_packet(iforce, FF_CMD_ENABLE, "\004"); + if (test_bit(EV_FF, dev->evbit)) { + /* Enable force feedback */ + iforce_send_packet(iforce, FF_CMD_ENABLE, "\004"); + } return 0; } -static int iforce_flush(struct input_dev *dev, struct file *file) +static void iforce_release(struct input_dev *dev) { struct iforce *iforce = dev->private; int i; - /* Erase all effects this process owns */ - for (i=0; i<dev->ff_effects_max; ++i) { - - if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) && - current->pid == iforce->core_effects[i].owner) { - - /* Stop effect */ - input_report_ff(dev, i, 0); - - /* Free ressources assigned to effect */ - if (iforce_erase_effect(dev, i)) { - printk(KERN_WARNING "iforce_flush: erase effect %d failed\n", i); + if (test_bit(EV_FF, dev->evbit)) { + /* Check: no effects should be present in memory */ + for (i = 0; i < dev->ff->max_effects; i++) { + if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) { + printk(KERN_WARNING "iforce_release: Device still owns effects\n"); + break; } } + /* Disable force feedback playback */ + iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); } - return 0; -} - -static void iforce_release(struct input_dev *dev) -{ - struct iforce *iforce = dev->private; - int i; - - /* Check: no effect should be present in memory */ - for (i=0; i<dev->ff_effects_max; ++i) { - if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags)) - break; - } - if (i<dev->ff_effects_max) { - printk(KERN_WARNING "iforce_release: Device still owns effects\n"); - } - - /* Disable force feedback playback */ - iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); switch (iforce->bus) { #ifdef CONFIG_JOYSTICK_IFORCE_USB @@ -342,8 +264,10 @@ void iforce_delete_device(struct iforce *iforce) int iforce_init_device(struct iforce *iforce) { struct input_dev *input_dev; + struct ff_device *ff; unsigned char c[] = "CEOV"; - int i; + int i, error; + int ff_effects = 0; input_dev = input_allocate_device(); if (!input_dev) @@ -378,11 +302,6 @@ int iforce_init_device(struct iforce *iforce) input_dev->name = "Unknown I-Force device"; input_dev->open = iforce_open; input_dev->close = iforce_release; - input_dev->flush = iforce_flush; - input_dev->event = iforce_input_event; - input_dev->upload_effect = iforce_upload_effect; - input_dev->erase_effect = iforce_erase_effect; - input_dev->ff_effects_max = 10; /* * On-device memory allocation. @@ -430,15 +349,15 @@ int iforce_init_device(struct iforce *iforce) printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n"); if (!iforce_get_id_packet(iforce, "N")) - iforce->dev->ff_effects_max = iforce->edata[1]; + ff_effects = iforce->edata[1]; else printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n"); /* Check if the device can store more effects than the driver can really handle */ - if (iforce->dev->ff_effects_max > FF_EFFECTS_MAX) { - printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n", - iforce->dev->ff_effects_max, FF_EFFECTS_MAX); - iforce->dev->ff_effects_max = FF_EFFECTS_MAX; + if (ff_effects > IFORCE_EFFECTS_MAX) { + printk(KERN_WARNING "iforce: Limiting number of effects to %d (device reports %d)\n", + IFORCE_EFFECTS_MAX, ff_effects); + ff_effects = IFORCE_EFFECTS_MAX; } /* @@ -472,12 +391,10 @@ int iforce_init_device(struct iforce *iforce) * Set input device bitfields and ranges. */ - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS); + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF_STATUS); - for (i = 0; iforce->type->btn[i] >= 0; i++) { - signed short t = iforce->type->btn[i]; - set_bit(t, input_dev->keybit); - } + for (i = 0; iforce->type->btn[i] >= 0; i++) + set_bit(iforce->type->btn[i], input_dev->keybit); set_bit(BTN_DEAD, input_dev->keybit); for (i = 0; iforce->type->abs[i] >= 0; i++) { @@ -516,9 +433,24 @@ int iforce_init_device(struct iforce *iforce) } } - for (i = 0; iforce->type->ff[i] >= 0; i++) - set_bit(iforce->type->ff[i], input_dev->ffbit); + if (ff_effects) { + for (i = 0; iforce->type->ff[i] >= 0; i++) + set_bit(iforce->type->ff[i], input_dev->ffbit); + + error = input_ff_create(input_dev, ff_effects); + if (error) { + input_free_device(input_dev); + return error; + } + + ff = input_dev->ff; + ff->upload = iforce_upload_effect; + ff->erase = iforce_erase_effect; + ff->set_gain = iforce_set_gain; + ff->set_autocenter = iforce_set_autocenter; + ff->playback = iforce_playback; + } /* * Register input device. */ diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 76cb1f8..8632d47 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -140,7 +140,10 @@ static int mark_core_as_ready(struct iforce *iforce, unsigned short addr) { int i; - for (i = 0; i < iforce->dev->ff_effects_max; ++i) { + if (!iforce->dev->ff) + return 0; + + for (i = 0; i < iforce->dev->ff->max_effects; ++i) { if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) && (iforce->core_effects[i].mod1_chunk.start == addr || iforce->core_effects[i].mod2_chunk.start == addr)) { @@ -229,19 +232,17 @@ void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, i = data[1] & 0x7f; if (data[1] & 0x80) { if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { - /* Report play event */ - input_report_ff_status(dev, i, FF_STATUS_PLAYING); + /* Report play event */ + input_report_ff_status(dev, i, FF_STATUS_PLAYING); } - } - else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { + } else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) { /* Report stop event */ input_report_ff_status(dev, i, FF_STATUS_STOPPED); } if (LO(cmd) > 3) { int j; - for (j=3; j<LO(cmd); j+=2) { + for (j = 3; j < LO(cmd); j += 2) mark_core_as_ready(iforce, data[j] | (data[j+1]<<8)); - } } break; } diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index e9924d6..947df27 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h @@ -51,10 +51,7 @@ #define IFORCE_232 1 #define IFORCE_USB 2 -#define FALSE 0 -#define TRUE 1 - -#define FF_EFFECTS_MAX 32 +#define IFORCE_EFFECTS_MAX 32 /* Each force feedback effect is made of one core effect, which can be * associated to at most to effect modifiers @@ -67,24 +64,11 @@ #define FF_CORE_UPDATE 5 /* Effect is being updated */ #define FF_MODCORE_MAX 5 -#define CHECK_OWNERSHIP(i, iforce) \ - ((i) < FF_EFFECTS_MAX && i >= 0 && \ - test_bit(FF_CORE_IS_USED, (iforce)->core_effects[(i)].flags) && \ - (current->pid == 0 || \ - (iforce)->core_effects[(i)].owner == current->pid)) - struct iforce_core_effect { /* Information about where modifiers are stored in the device's memory */ struct resource mod1_chunk; struct resource mod2_chunk; unsigned long flags[NBITS(FF_MODCORE_MAX)]; - pid_t owner; - /* Used to keep track of parameters of an effect. They are needed - * to know what parts of an effect changed in an update operation. - * We try to send only parameter packets if possible, as sending - * effect parameter requires the effect to be stoped and restarted - */ - struct ff_effect effect; }; #define FF_CMD_EFFECT 0x010e @@ -145,7 +129,7 @@ struct iforce { /* Force Feedback */ wait_queue_head_t wait; struct resource device_memory; - struct iforce_core_effect core_effects[FF_EFFECTS_MAX]; + struct iforce_core_effect core_effects[IFORCE_EFFECTS_MAX]; struct mutex mem_mutex; }; @@ -182,9 +166,9 @@ void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data) ; int iforce_get_id_packet(struct iforce *iforce, char *packet); /* iforce-ff.c */ -int iforce_upload_periodic(struct iforce*, struct ff_effect*, int is_update); -int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update); -int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update); +int iforce_upload_periodic(struct iforce *, struct ff_effect *, struct ff_effect *); +int iforce_upload_constant(struct iforce *, struct ff_effect *, struct ff_effect *); +int iforce_upload_condition(struct iforce *, struct ff_effect *, struct ff_effect *); /* Public variables */ extern struct serio_driver iforce_serio_drv; |