Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: Input: psmouse - remove unneeded '\n' from psmouse.proto parameter Input: atkbd - restore LED state at reconnect Input: force LED reset on resume Input: fix locking in memoryless force-feedback devices
This commit is contained in:
commit
cd4ca27d3d
|
@ -337,16 +337,16 @@ int input_ff_create(struct input_dev *dev, int max_effects)
|
||||||
dev->ff = ff;
|
dev->ff = ff;
|
||||||
dev->flush = flush_effects;
|
dev->flush = flush_effects;
|
||||||
dev->event = input_ff_event;
|
dev->event = input_ff_event;
|
||||||
set_bit(EV_FF, dev->evbit);
|
__set_bit(EV_FF, dev->evbit);
|
||||||
|
|
||||||
/* Copy "true" bits into ff device bitmap */
|
/* Copy "true" bits into ff device bitmap */
|
||||||
for (i = 0; i <= FF_MAX; i++)
|
for (i = 0; i <= FF_MAX; i++)
|
||||||
if (test_bit(i, dev->ffbit))
|
if (test_bit(i, dev->ffbit))
|
||||||
set_bit(i, ff->ffbit);
|
__set_bit(i, ff->ffbit);
|
||||||
|
|
||||||
/* we can emulate RUMBLE with periodic effects */
|
/* we can emulate RUMBLE with periodic effects */
|
||||||
if (test_bit(FF_PERIODIC, ff->ffbit))
|
if (test_bit(FF_PERIODIC, ff->ffbit))
|
||||||
set_bit(FF_RUMBLE, dev->ffbit);
|
__set_bit(FF_RUMBLE, dev->ffbit);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -362,12 +362,14 @@ EXPORT_SYMBOL_GPL(input_ff_create);
|
||||||
*/
|
*/
|
||||||
void input_ff_destroy(struct input_dev *dev)
|
void input_ff_destroy(struct input_dev *dev)
|
||||||
{
|
{
|
||||||
clear_bit(EV_FF, dev->evbit);
|
struct ff_device *ff = dev->ff;
|
||||||
if (dev->ff) {
|
|
||||||
if (dev->ff->destroy)
|
__clear_bit(EV_FF, dev->evbit);
|
||||||
dev->ff->destroy(dev->ff);
|
if (ff) {
|
||||||
kfree(dev->ff->private);
|
if (ff->destroy)
|
||||||
kfree(dev->ff);
|
ff->destroy(ff);
|
||||||
|
kfree(ff->private);
|
||||||
|
kfree(ff);
|
||||||
dev->ff = NULL;
|
dev->ff = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,6 @@ struct ml_device {
|
||||||
struct ml_effect_state states[FF_MEMLESS_EFFECTS];
|
struct ml_effect_state states[FF_MEMLESS_EFFECTS];
|
||||||
int gain;
|
int gain;
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
spinlock_t timer_lock;
|
|
||||||
struct input_dev *dev;
|
struct input_dev *dev;
|
||||||
|
|
||||||
int (*play_effect)(struct input_dev *dev, void *data,
|
int (*play_effect)(struct input_dev *dev, void *data,
|
||||||
|
@ -368,38 +367,38 @@ static void ml_effect_timer(unsigned long timer_data)
|
||||||
{
|
{
|
||||||
struct input_dev *dev = (struct input_dev *)timer_data;
|
struct input_dev *dev = (struct input_dev *)timer_data;
|
||||||
struct ml_device *ml = dev->ff->private;
|
struct ml_device *ml = dev->ff->private;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
debug("timer: updating effects");
|
debug("timer: updating effects");
|
||||||
|
|
||||||
spin_lock(&ml->timer_lock);
|
spin_lock_irqsave(&dev->event_lock, flags);
|
||||||
ml_play_effects(ml);
|
ml_play_effects(ml);
|
||||||
spin_unlock(&ml->timer_lock);
|
spin_unlock_irqrestore(&dev->event_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets requested gain for FF effects. Called with dev->event_lock held.
|
||||||
|
*/
|
||||||
static void ml_ff_set_gain(struct input_dev *dev, u16 gain)
|
static void ml_ff_set_gain(struct input_dev *dev, u16 gain)
|
||||||
{
|
{
|
||||||
struct ml_device *ml = dev->ff->private;
|
struct ml_device *ml = dev->ff->private;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
spin_lock_bh(&ml->timer_lock);
|
|
||||||
|
|
||||||
ml->gain = gain;
|
ml->gain = gain;
|
||||||
|
|
||||||
for (i = 0; i < FF_MEMLESS_EFFECTS; i++)
|
for (i = 0; i < FF_MEMLESS_EFFECTS; i++)
|
||||||
__clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags);
|
__clear_bit(FF_EFFECT_PLAYING, &ml->states[i].flags);
|
||||||
|
|
||||||
ml_play_effects(ml);
|
ml_play_effects(ml);
|
||||||
|
|
||||||
spin_unlock_bh(&ml->timer_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start/stop specified FF effect. Called with dev->event_lock held.
|
||||||
|
*/
|
||||||
static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
|
static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
|
||||||
{
|
{
|
||||||
struct ml_device *ml = dev->ff->private;
|
struct ml_device *ml = dev->ff->private;
|
||||||
struct ml_effect_state *state = &ml->states[effect_id];
|
struct ml_effect_state *state = &ml->states[effect_id];
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&ml->timer_lock, flags);
|
|
||||||
|
|
||||||
if (value > 0) {
|
if (value > 0) {
|
||||||
debug("initiated play");
|
debug("initiated play");
|
||||||
|
@ -425,8 +424,6 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value)
|
||||||
ml_play_effects(ml);
|
ml_play_effects(ml);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&ml->timer_lock, flags);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,7 +433,7 @@ static int ml_ff_upload(struct input_dev *dev,
|
||||||
struct ml_device *ml = dev->ff->private;
|
struct ml_device *ml = dev->ff->private;
|
||||||
struct ml_effect_state *state = &ml->states[effect->id];
|
struct ml_effect_state *state = &ml->states[effect->id];
|
||||||
|
|
||||||
spin_lock_bh(&ml->timer_lock);
|
spin_lock_irq(&dev->event_lock);
|
||||||
|
|
||||||
if (test_bit(FF_EFFECT_STARTED, &state->flags)) {
|
if (test_bit(FF_EFFECT_STARTED, &state->flags)) {
|
||||||
__clear_bit(FF_EFFECT_PLAYING, &state->flags);
|
__clear_bit(FF_EFFECT_PLAYING, &state->flags);
|
||||||
|
@ -448,7 +445,7 @@ static int ml_ff_upload(struct input_dev *dev,
|
||||||
ml_schedule_timer(ml);
|
ml_schedule_timer(ml);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_bh(&ml->timer_lock);
|
spin_unlock_irq(&dev->event_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -482,7 +479,6 @@ int input_ff_create_memless(struct input_dev *dev, void *data,
|
||||||
ml->private = data;
|
ml->private = data;
|
||||||
ml->play_effect = play_effect;
|
ml->play_effect = play_effect;
|
||||||
ml->gain = 0xffff;
|
ml->gain = 0xffff;
|
||||||
spin_lock_init(&ml->timer_lock);
|
|
||||||
setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev);
|
setup_timer(&ml->timer, ml_effect_timer, (unsigned long)dev);
|
||||||
|
|
||||||
set_bit(FF_GAIN, dev->ffbit);
|
set_bit(FF_GAIN, dev->ffbit);
|
||||||
|
|
|
@ -1292,17 +1292,24 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INPUT_DO_TOGGLE(dev, type, bits, on) \
|
#define INPUT_DO_TOGGLE(dev, type, bits, on) \
|
||||||
do { \
|
do { \
|
||||||
int i; \
|
int i; \
|
||||||
if (!test_bit(EV_##type, dev->evbit)) \
|
bool active; \
|
||||||
break; \
|
\
|
||||||
for (i = 0; i < type##_MAX; i++) { \
|
if (!test_bit(EV_##type, dev->evbit)) \
|
||||||
if (!test_bit(i, dev->bits##bit) || \
|
break; \
|
||||||
!test_bit(i, dev->bits)) \
|
\
|
||||||
continue; \
|
for (i = 0; i < type##_MAX; i++) { \
|
||||||
dev->event(dev, EV_##type, i, on); \
|
if (!test_bit(i, dev->bits##bit)) \
|
||||||
} \
|
continue; \
|
||||||
|
\
|
||||||
|
active = test_bit(i, dev->bits); \
|
||||||
|
if (!active && !on) \
|
||||||
|
continue; \
|
||||||
|
\
|
||||||
|
dev->event(dev, EV_##type, i, on ? active : 0); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
|
|
@ -1174,6 +1174,18 @@ static int atkbd_reconnect(struct serio *serio)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
atkbd_activate(atkbd);
|
atkbd_activate(atkbd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore LED state and repeat rate. While input core
|
||||||
|
* will do this for us at resume time reconnect may happen
|
||||||
|
* because user requested it via sysfs or simply because
|
||||||
|
* keyboard was unplugged and plugged in again so we need
|
||||||
|
* to do it ourselves here.
|
||||||
|
*/
|
||||||
|
atkbd_set_leds(atkbd);
|
||||||
|
if (!atkbd->softrepeat)
|
||||||
|
atkbd_set_repeat_rate(atkbd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
atkbd_enable(atkbd);
|
atkbd_enable(atkbd);
|
||||||
|
@ -1422,6 +1434,7 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
|
||||||
|
|
||||||
atkbd->dev = new_dev;
|
atkbd->dev = new_dev;
|
||||||
atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
|
atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
|
||||||
|
atkbd_reset_state(atkbd);
|
||||||
atkbd_activate(atkbd);
|
atkbd_activate(atkbd);
|
||||||
atkbd_set_keycode_table(atkbd);
|
atkbd_set_keycode_table(atkbd);
|
||||||
atkbd_set_device_attrs(atkbd);
|
atkbd_set_device_attrs(atkbd);
|
||||||
|
|
|
@ -1673,7 +1673,7 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
int type = *((unsigned int *)kp->arg);
|
int type = *((unsigned int *)kp->arg);
|
||||||
|
|
||||||
return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name);
|
return sprintf(buffer, "%s", psmouse_protocol_by_type(type)->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init psmouse_init(void)
|
static int __init psmouse_init(void)
|
||||||
|
|
|
@ -1377,6 +1377,10 @@ extern struct class input_class;
|
||||||
* methods; erase() is optional. set_gain() and set_autocenter() need
|
* methods; erase() is optional. set_gain() and set_autocenter() need
|
||||||
* only be implemented if driver sets up FF_GAIN and FF_AUTOCENTER
|
* only be implemented if driver sets up FF_GAIN and FF_AUTOCENTER
|
||||||
* bits.
|
* bits.
|
||||||
|
*
|
||||||
|
* Note that playback(), set_gain() and set_autocenter() are called with
|
||||||
|
* dev->event_lock spinlock held and interrupts off and thus may not
|
||||||
|
* sleep.
|
||||||
*/
|
*/
|
||||||
struct ff_device {
|
struct ff_device {
|
||||||
int (*upload)(struct input_dev *dev, struct ff_effect *effect,
|
int (*upload)(struct input_dev *dev, struct ff_effect *effect,
|
||||||
|
|
Loading…
Reference in New Issue