Input: keyboards - handle errors when registering input devices

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
This commit is contained in:
Dmitry Torokhov 2006-11-05 22:39:56 -05:00
parent 41ad5fbabd
commit 2b03b60e6b
10 changed files with 234 additions and 92 deletions

View file

@ -190,7 +190,7 @@ static int __init amikbd_init(void)
int i, j;
if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
return -EIO;
return -ENODEV;
if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb"))
return -EBUSY;
@ -198,8 +198,8 @@ static int __init amikbd_init(void)
amikbd_dev = input_allocate_device();
if (!amikbd_dev) {
printk(KERN_ERR "amikbd: not enough memory for input device\n");
release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
return -ENOMEM;
err = -ENOMEM;
goto fail1;
}
amikbd_dev->name = "Amiga Keyboard";
@ -231,10 +231,22 @@ static int __init amikbd_init(void)
memcpy(key_maps[i], temp_map, sizeof(temp_map));
}
ciaa.cra &= ~0x41; /* serial data in, turn off TA */
request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd",
amikbd_interrupt)) {
err = -EBUSY;
goto fail2;
}
err = input_register_device(amikbd_dev);
if (err)
goto fail3;
input_register_device(amikbd_dev);
return 0;
fail3: free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt);
fail2: input_free_device(amikbd_dev);
fail1: release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100);
return err;
}
static void __exit amikbd_exit(void)

View file

@ -939,7 +939,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL);
dev = input_allocate_device();
if (!atkbd || !dev)
goto fail;
goto fail1;
atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio);
@ -967,14 +967,13 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
goto fail;
goto fail2;
if (atkbd->write) {
if (atkbd_probe(atkbd)) {
serio_close(serio);
err = -ENODEV;
goto fail;
goto fail3;
}
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@ -988,16 +987,22 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
err = sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group);
if (err)
goto fail3;
atkbd_enable(atkbd);
input_register_device(atkbd->dev);
err = input_register_device(atkbd->dev);
if (err)
goto fail4;
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(dev);
fail4: sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
fail3: serio_close(serio);
fail2: serio_set_drvdata(serio, NULL);
fail1: input_free_device(dev);
kfree(atkbd);
return err;
}
@ -1133,9 +1138,11 @@ static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t count)
{
struct input_dev *new_dev;
struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
int err;
unsigned char old_extra, old_set;
if (!atkbd->write)
return -EIO;
@ -1147,17 +1154,36 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
if (atkbd->extra != value) {
/*
* Since device's properties will change we need to
* unregister old device. But allocate new one first
* to make sure we have it.
* unregister old device. But allocate and register
* new one first to make sure we have it.
*/
if (!(new_dev = input_allocate_device()))
old_dev = atkbd->dev;
old_extra = atkbd->extra;
old_set = atkbd->set;
new_dev = input_allocate_device();
if (!new_dev)
return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
input_register_device(atkbd->dev);
err = input_register_device(atkbd->dev);
if (err) {
input_free_device(new_dev);
atkbd->dev = old_dev;
atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
return err;
}
input_unregister_device(old_dev);
}
return count;
}
@ -1169,23 +1195,41 @@ static ssize_t atkbd_show_scroll(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t count)
{
struct input_dev *new_dev;
struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
int err;
unsigned char old_scroll;
value = simple_strtoul(buf, &rest, 10);
if (*rest || value > 1)
return -EINVAL;
if (atkbd->scroll != value) {
if (!(new_dev = input_allocate_device()))
old_dev = atkbd->dev;
old_scroll = atkbd->scroll;
new_dev = input_allocate_device();
if (!new_dev)
return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->scroll = value;
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
input_register_device(atkbd->dev);
err = input_register_device(atkbd->dev);
if (err) {
input_free_device(new_dev);
atkbd->scroll = old_scroll;
atkbd->dev = old_dev;
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
return err;
}
input_unregister_device(old_dev);
}
return count;
}
@ -1197,9 +1241,11 @@ static ssize_t atkbd_show_set(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
{
struct input_dev *new_dev;
struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
int err;
unsigned char old_set, old_extra;
if (!atkbd->write)
return -EIO;
@ -1209,15 +1255,32 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
return -EINVAL;
if (atkbd->set != value) {
if (!(new_dev = input_allocate_device()))
old_dev = atkbd->dev;
old_extra = atkbd->extra;
old_set = atkbd->set;
new_dev = input_allocate_device();
if (!new_dev)
return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra);
atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
input_register_device(atkbd->dev);
err = input_register_device(atkbd->dev);
if (err) {
input_free_device(new_dev);
atkbd->dev = old_dev;
atkbd->set = atkbd_select_set(atkbd, old_set, old_extra);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
return err;
}
input_unregister_device(old_dev);
}
return count;
}
@ -1229,9 +1292,11 @@ static ssize_t atkbd_show_softrepeat(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t count)
{
struct input_dev *new_dev;
struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
int err;
unsigned char old_softrepeat, old_softraw;
if (!atkbd->write)
return -EIO;
@ -1241,15 +1306,32 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
return -EINVAL;
if (atkbd->softrepeat != value) {
if (!(new_dev = input_allocate_device()))
old_dev = atkbd->dev;
old_softrepeat = atkbd->softrepeat;
old_softraw = atkbd->softraw;
new_dev = input_allocate_device();
if (!new_dev)
return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->softrepeat = value;
if (atkbd->softrepeat)
atkbd->softraw = 1;
atkbd_set_device_attrs(atkbd);
input_register_device(atkbd->dev);
err = input_register_device(atkbd->dev);
if (err) {
input_free_device(new_dev);
atkbd->dev = old_dev;
atkbd->softrepeat = old_softrepeat;
atkbd->softraw = old_softraw;
atkbd_set_device_attrs(atkbd);
return err;
}
input_unregister_device(old_dev);
}
return count;
}
@ -1262,22 +1344,39 @@ static ssize_t atkbd_show_softraw(struct atkbd *atkbd, char *buf)
static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t count)
{
struct input_dev *new_dev;
struct input_dev *old_dev, *new_dev;
unsigned long value;
char *rest;
int err;
unsigned char old_softraw;
value = simple_strtoul(buf, &rest, 10);
if (*rest || value > 1)
return -EINVAL;
if (atkbd->softraw != value) {
if (!(new_dev = input_allocate_device()))
old_dev = atkbd->dev;
old_softraw = atkbd->softraw;
new_dev = input_allocate_device();
if (!new_dev)
return -ENOMEM;
input_unregister_device(atkbd->dev);
atkbd->dev = new_dev;
atkbd->softraw = value;
atkbd_set_device_attrs(atkbd);
input_register_device(atkbd->dev);
err = input_register_device(atkbd->dev);
if (err) {
input_free_device(new_dev);
atkbd->dev = old_dev;
atkbd->softraw = old_softraw;
atkbd_set_device_attrs(atkbd);
return err;
}
input_unregister_device(old_dev);
}
return count;
}

View file

@ -291,15 +291,12 @@ static int __init corgikbd_probe(struct platform_device *pdev)
{
struct corgikbd *corgikbd;
struct input_dev *input_dev;
int i;
int i, err = -ENOMEM;
corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!corgikbd || !input_dev) {
kfree(corgikbd);
input_free_device(input_dev);
return -ENOMEM;
}
if (!corgikbd || !input_dev)
goto fail;
platform_set_drvdata(pdev, corgikbd);
@ -341,7 +338,9 @@ static int __init corgikbd_probe(struct platform_device *pdev)
set_bit(SW_TABLET_MODE, input_dev->swbit);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
input_register_device(corgikbd->input);
err = input_register_device(corgikbd->input);
if (err)
goto fail;
mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
@ -362,6 +361,10 @@ static int __init corgikbd_probe(struct platform_device *pdev)
pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
return 0;
fail: input_free_device(input_dev);
kfree(corgikbd);
return err;
}
static int corgikbd_remove(struct platform_device *pdev)

View file

@ -651,7 +651,7 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
input_dev = input_allocate_device ();
if (!lk || !input_dev) {
err = -ENOMEM;
goto fail;
goto fail1;
}
lk->serio = serio;
@ -696,15 +696,19 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv)
err = serio_open (serio, drv);
if (err)
goto fail;
goto fail2;
err = input_register_device (lk->dev);
if (err)
goto fail3;
input_register_device (lk->dev);
lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
return 0;
fail: serio_set_drvdata (serio, NULL);
input_free_device (input_dev);
fail3: serio_close (serio);
fail2: serio_set_drvdata (serio, NULL);
fail1: input_free_device (input_dev);
kfree (lk);
return err;
}

View file

@ -193,22 +193,22 @@ static int locomokbd_probe(struct locomo_dev *dev)
{
struct locomokbd *locomokbd;
struct input_dev *input_dev;
int i, ret;
int i, err;
locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!locomokbd || !input_dev) {
ret = -ENOMEM;
goto free;
err = -ENOMEM;
goto err_free_mem;
}
/* try and claim memory region */
if (!request_mem_region((unsigned long) dev->mapbase,
dev->length,
LOCOMO_DRIVER_NAME(dev))) {
ret = -EBUSY;
err = -EBUSY;
printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
goto free;
goto err_free_mem;
}
locomokbd->ldev = dev;
@ -244,24 +244,28 @@ static int locomokbd_probe(struct locomo_dev *dev)
clear_bit(0, input_dev->keybit);
/* attempt to get the interrupt */
ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
if (ret) {
err = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
if (err) {
printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n");
goto out;
goto err_release_region;
}
input_register_device(locomokbd->input);
err = input_register_device(locomokbd->input);
if (err)
goto err_free_irq;
return 0;
out:
err_free_irq:
free_irq(dev->irq[0], locomokbd);
err_release_region:
release_mem_region((unsigned long) dev->mapbase, dev->length);
locomo_set_drvdata(dev, NULL);
free:
err_free_mem:
input_free_device(input_dev);
kfree(locomokbd);
return ret;
return err;
}
static int locomokbd_remove(struct locomo_dev *dev)

View file

@ -94,13 +94,13 @@ static int dc_kbd_connect(struct maple_device *dev)
struct input_dev *input_dev;
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
int i;
int err;
dev->private_data = kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!kbd || !input_dev) {
kfree(kbd);
input_free_device(input_dev);
return -ENOMEM;
err = -ENOMEM;
goto fail;
}
kbd->dev = input_dev;
@ -113,10 +113,16 @@ static int dc_kbd_connect(struct maple_device *dev)
set_bit(dc_kbd_keycode[i], input_dev->keybit);
clear_bit(0, input_dev->keybit);
input_register_device(kbd->dev);
err = input_register_device(kbd->dev);
if (err)
goto fail;
maple_getcond_callback(dev, dc_kbd_callback, 1, MAPLE_FUNC_KEYBOARD);
return 0;
fail: input_free_device(input_dev);
kfree(kbd);
return err;
}

View file

@ -91,7 +91,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!nkbd || !input_dev)
goto fail;
goto fail1;
nkbd->serio = serio;
nkbd->dev = input_dev;
@ -119,13 +119,17 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
goto fail;
goto fail2;
err = input_register_device(nkbd->dev);
if (err)
goto fail3;
input_register_device(nkbd->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
fail3: serio_close(serio);
fail2: serio_set_drvdata(serio, NULL);
fail1: input_free_device(input_dev);
kfree(nkbd);
return err;
}

View file

@ -346,17 +346,12 @@ static int __init spitzkbd_probe(struct platform_device *dev)
{
struct spitzkbd *spitzkbd;
struct input_dev *input_dev;
int i;
int i, err = -ENOMEM;
spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
if (!spitzkbd)
return -ENOMEM;
input_dev = input_allocate_device();
if (!input_dev) {
kfree(spitzkbd);
return -ENOMEM;
}
if (!spitzkbd || !input_dev)
goto fail;
platform_set_drvdata(dev, spitzkbd);
strcpy(spitzkbd->phys, "spitzkbd/input0");
@ -400,7 +395,9 @@ static int __init spitzkbd_probe(struct platform_device *dev)
set_bit(SW_TABLET_MODE, input_dev->swbit);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
input_register_device(input_dev);
err = input_register_device(input_dev);
if (err)
goto fail;
mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
@ -434,13 +431,15 @@ static int __init spitzkbd_probe(struct platform_device *dev)
request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr,
IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"Spitzkbd SWB", spitzkbd);
request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr,
IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"Spitzkbd HP", spitzkbd);
printk(KERN_INFO "input: Spitz Keyboard Registered\n");
return 0;
fail: input_free_device(input_dev);
kfree(spitzkbd);
return err;
}
static int spitzkbd_remove(struct platform_device *dev)
@ -474,6 +473,7 @@ static struct platform_driver spitzkbd_driver = {
.resume = spitzkbd_resume,
.driver = {
.name = "spitz-keyboard",
.owner = THIS_MODULE,
},
};

View file

@ -243,7 +243,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!sunkbd || !input_dev)
goto fail;
goto fail1;
sunkbd->serio = serio;
sunkbd->dev = input_dev;
@ -255,11 +255,11 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
goto fail;
goto fail2;
if (sunkbd_initialize(sunkbd) < 0) {
serio_close(serio);
goto fail;
err = -ENODEV;
goto fail3;
}
snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type);
@ -287,11 +287,17 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
clear_bit(0, input_dev->keybit);
sunkbd_enable(sunkbd, 1);
input_register_device(sunkbd->dev);
err = input_register_device(sunkbd->dev);
if (err)
goto fail4;
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
fail4: sunkbd_enable(sunkbd, 0);
fail3: serio_close(serio);
fail2: serio_set_drvdata(serio, NULL);
fail1: input_free_device(input_dev);
kfree(sunkbd);
return err;
}

View file

@ -95,7 +95,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!xtkbd || !input_dev)
goto fail;
goto fail1;
xtkbd->serio = serio;
xtkbd->dev = input_dev;
@ -124,13 +124,17 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
err = serio_open(serio, drv);
if (err)
goto fail;
goto fail2;
err = input_register_device(xtkbd->dev);
if (err)
goto fail3;
input_register_device(xtkbd->dev);
return 0;
fail: serio_set_drvdata(serio, NULL);
input_free_device(input_dev);
fail3: serio_close(serio);
fail2: serio_set_drvdata(serio, NULL);
fail1: input_free_device(input_dev);
kfree(xtkbd);
return err;
}