diff options
77 files changed, 1816 insertions, 536 deletions
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index ca094913c55..3fa0c4b4541 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -559,4 +559,12 @@ X!Idrivers/video/console/fonts.c --> </sect1> </chapter> + + <chapter id="input_subsystem"> + <title>Input Subsystem</title> +!Iinclude/linux/input.h +!Edrivers/input/input.c +!Edrivers/input/ff-core.c +!Edrivers/input/ff-memless.c + </chapter> </book> diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 20b6c8b3024..7a6c1c0b7a9 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -710,7 +710,7 @@ static void k_fn(struct vc_data *vc, unsigned char value, char up_flag) static void k_cur(struct vc_data *vc, unsigned char value, char up_flag) { - static const char *cur_chars = "BDCA"; + static const char cur_chars[] = "BDCA"; if (up_flag) return; diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 35656cadc91..783b3412cea 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -203,7 +203,7 @@ static int erase_effect(struct input_dev *dev, int effect_id, } /** - * input_ff_erase - erase an effect from device + * input_ff_erase - erase a force-feedback effect from device * @dev: input device to erase effect from * @effect_id: id of the ffect to be erased * @file: purported owner of the request @@ -347,7 +347,7 @@ EXPORT_SYMBOL_GPL(input_ff_create); /** * input_ff_free() - frees force feedback portion of input device - * @dev: input device supporintg force feedback + * @dev: input device supporting force feedback * * This function is only needed in error path as input core will * automatically free force feedback structures when device is diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index cd8b7297e6d..eba18b6ac5e 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -460,7 +460,7 @@ static void ml_ff_destroy(struct ff_device *ff) } /** - * input_ff_create_memless() - create memoryless FF device + * input_ff_create_memless() - create memoryless force-feedback device * @dev: input device supporting force-feedback * @data: driver-specific data to be passed into @play_effect * @play_effect: driver-specific method for playing FF effect diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 79dfb4b25c9..a00fe470a82 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -731,12 +731,6 @@ static int gameport_driver_remove(struct device *dev) return 0; } -static struct bus_type gameport_bus = { - .name = "gameport", - .probe = gameport_driver_probe, - .remove = gameport_driver_remove, -}; - static void gameport_add_driver(struct gameport_driver *drv) { int error; @@ -782,6 +776,15 @@ static int gameport_bus_match(struct device *dev, struct device_driver *drv) return !gameport_drv->ignore; } +static struct bus_type gameport_bus = { + .name = "gameport", + .dev_attrs = gameport_device_attrs, + .drv_attrs = gameport_driver_attrs, + .match = gameport_bus_match, + .probe = gameport_driver_probe, + .remove = gameport_driver_remove, +}; + static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv) { mutex_lock(&gameport->drv_mutex); @@ -791,7 +794,6 @@ static void gameport_set_drv(struct gameport *gameport, struct gameport_driver * int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode) { - if (gameport->open) { if (gameport->open(gameport, mode)) { return -1; @@ -819,9 +821,6 @@ static int __init gameport_init(void) { int error; - gameport_bus.dev_attrs = gameport_device_attrs; - gameport_bus.drv_attrs = gameport_driver_attrs; - gameport_bus.match = gameport_bus_match; error = bus_register(&gameport_bus); if (error) { printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error); diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c index d65d8108025..6b4d4561d46 100644 --- a/drivers/input/gameport/lightning.c +++ b/drivers/input/gameport/lightning.c @@ -309,7 +309,7 @@ static int __init l4_init(void) int i, cards = 0; if (!request_region(L4_PORT, 1, "lightning")) - return -1; + return -EBUSY; for (i = 0; i < 2; i++) if (l4_add_card(i) == 0) @@ -319,7 +319,7 @@ static int __init l4_init(void) if (!cards) { release_region(L4_PORT, 1); - return -1; + return -ENODEV; } return 0; diff --git a/drivers/input/input.c b/drivers/input/input.c index 1c8c8a5bc4a..7cf2b4f603a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -37,7 +37,7 @@ static struct input_handler *input_table[8]; /** * input_event() - report new input event - * @handle: device that generated the event + * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event @@ -900,6 +900,15 @@ struct class input_class = { }; EXPORT_SYMBOL_GPL(input_class); +/** + * input_allocate_device - allocate memory for new input device + * + * Returns prepared struct input_dev or NULL. + * + * NOTE: Use input_free_device() to free devices that have not been + * registered; input_unregister_device() should be used for already + * registered devices. + */ struct input_dev *input_allocate_device(void) { struct input_dev *dev; @@ -919,6 +928,20 @@ struct input_dev *input_allocate_device(void) } EXPORT_SYMBOL(input_allocate_device); +/** + * input_free_device - free memory occupied by input_dev structure + * @dev: input device to free + * + * This function should only be used if input_register_device() + * was not called yet or if it failed. Once device was registered + * use input_unregister_device() and memory will be freed once last + * refrence to the device is dropped. + * + * Device should be allocated by input_allocate_device(). + * + * NOTE: If there are references to the input device then memory + * will not be freed until last reference is dropped. + */ void input_free_device(struct input_dev *dev) { if (dev) { diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 704bf70f1db..6279ced8a35 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -521,11 +521,19 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) for (i = 0; i < 2; i++) if (port->adi[i].length > 0) { adi_init_center(port->adi + i); - input_register_device(port->adi[i].dev); + err = input_register_device(port->adi[i].dev); + if (err) + goto fail3; } return 0; + fail3: while (--i >= 0) { + if (port->adi[i].length > 0) { + input_unregister_device(port->adi[i].dev); + port->adi[i].dev = NULL; + } + } fail2: for (i = 0; i < 2; i++) if (port->adi[i].dev) input_free_device(port->adi[i].dev); diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index 650acf3a30b..e608691b5a6 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c @@ -147,7 +147,11 @@ static int __init amijoy_init(void) amijoy_dev[i]->absmax[ABS_X + j] = 1; } - input_register_device(amijoy_dev[i]); + err = input_register_device(amijoy_dev[i]); + if (err) { + input_free_device(amijoy_dev[i]); + goto fail; + } } return 0; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index e9a02db36ec..7ef68456d7d 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -434,6 +434,7 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i { struct input_dev *input_dev; int i, j, t, v, w, x, y, z; + int error; analog_name(analog); snprintf(analog->phys, sizeof(analog->phys), @@ -505,7 +506,11 @@ static int analog_init_device(struct analog_port *port, struct analog *analog, i analog_decode(analog, port->axes, port->initial, port->buttons); - input_register_device(analog->dev); + error = input_register_device(analog->dev); + if (error) { + input_free_device(analog->dev); + return error; + } return 0; } @@ -668,7 +673,8 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv return 0; fail3: while (--i >= 0) - input_unregister_device(port->analog[i].dev); + if (port->analog[i].mask) + input_unregister_device(port->analog[i].dev); fail2: gameport_close(gameport); fail1: gameport_set_drvdata(gameport, NULL); kfree(port); diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index d5e42eb88a2..034ec39c251 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -223,12 +223,15 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) for (j = 0; cobra_btn[j]; j++) set_bit(cobra_btn[j], input_dev->keybit); - input_register_device(cobra->dev[i]); + err = input_register_device(cobra->dev[i]); + if (err) + goto fail4; } return 0; - fail3: for (i = 0; i < 2; i++) + fail4: input_free_device(cobra->dev[i]); + fail3: while (--i >= 0) if (cobra->dev[i]) input_unregister_device(cobra->dev[i]); fail2: gameport_close(gameport); diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index e4a699f6ec8..bacbab5d1b6 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -341,7 +341,9 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) input_dev->absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; } - input_register_device(gf2k->dev); + err = input_register_device(gf2k->dev); + if (err) + goto fail2; return 0; diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 62438944a69..8120a9c4077 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -423,7 +423,10 @@ static int get_and_decode_packet(struct grip_mp *grip, int flags) if (!port->registered) { dbg("New Grip pad in multiport slot %d.\n", slot); - register_slot(slot, grip); + if (register_slot(slot, grip)) { + port->mode = GRIP_MODE_RESET; + port->dirty = 0; + } } return flags; } @@ -585,6 +588,7 @@ static int register_slot(int slot, struct grip_mp *grip) struct grip_port *port = grip->port[slot]; struct input_dev *input_dev; int j, t; + int err; port->dev = input_dev = input_allocate_device(); if (!input_dev) @@ -610,7 +614,12 @@ static int register_slot(int slot, struct grip_mp *grip) if (t > 0) set_bit(t, input_dev->keybit); - input_register_device(port->dev); + err = input_register_device(port->dev); + if (err) { + input_free_device(port->dev); + return err; + } + port->registered = 1; if (port->dirty) /* report initial state, if any */ diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 840ed9b512b..dbc5d92858b 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -250,7 +250,9 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver * for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++) set_bit(t, input_dev->keybit); - input_register_device(guillemot->dev); + err = input_register_device(guillemot->dev); + if (err) + goto fail2; return 0; diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 24c684bc633..3393a37fec3 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -325,8 +325,8 @@ int iforce_init_device(struct iforce *iforce) if (i == 20) { /* 5 seconds */ printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n"); - input_free_device(input_dev); - return -ENODEV; + error = -ENODEV; + goto fail; } /* @@ -439,10 +439,8 @@ int iforce_init_device(struct iforce *iforce) 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; - } + |