Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b03b60e authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

Input: keyboards - handle errors when registering input devices



Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 41ad5fba
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -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)
+129 −30
Original line number Diff line number Diff line
@@ -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;
}
+10 −7
Original line number Diff line number Diff line
@@ -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)
+9 −5
Original line number Diff line number Diff line
@@ -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;
}
+16 −12
Original line number Diff line number Diff line
@@ -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)
Loading