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

Commit 72155615 authored by Dmitry Torokhov's avatar Dmitry Torokhov
Browse files

Input: mice - handle errors when registering input devices



Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent 127278ce
Loading
Loading
Loading
Loading
+9 −2
Original line number Original line Diff line number Diff line
@@ -95,10 +95,13 @@ static void amimouse_close(struct input_dev *dev)


static int __init amimouse_init(void)
static int __init amimouse_init(void)
{
{
	int err;

	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
		return -ENODEV;
		return -ENODEV;


	if (!(amimouse_dev = input_allocate_device()))
	amimouse_dev = input_allocate_device();
	if (!amimouse_dev)
		return -ENOMEM;
		return -ENOMEM;


	amimouse_dev->name = "Amiga mouse";
	amimouse_dev->name = "Amiga mouse";
@@ -114,7 +117,11 @@ static int __init amimouse_init(void)
	amimouse_dev->open = amimouse_open;
	amimouse_dev->open = amimouse_open;
	amimouse_dev->close = amimouse_close;
	amimouse_dev->close = amimouse_close;


	input_register_device(amimouse_dev);
	err = input_register_device(amimouse_dev);
	if (err) {
		input_free_device(amimouse_dev);
		return err;
	}


	return 0;
	return 0;
}
}
+17 −6
Original line number Original line Diff line number Diff line
@@ -135,6 +135,7 @@ static void inport_close(struct input_dev *dev)
static int __init inport_init(void)
static int __init inport_init(void)
{
{
	unsigned char a, b, c;
	unsigned char a, b, c;
	int err;


	if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
	if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
		printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
		printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
@@ -145,15 +146,16 @@ static int __init inport_init(void)
	b = inb(INPORT_SIGNATURE_PORT);
	b = inb(INPORT_SIGNATURE_PORT);
	c = inb(INPORT_SIGNATURE_PORT);
	c = inb(INPORT_SIGNATURE_PORT);
	if (a == b || a != c) {
	if (a == b || a != c) {
		release_region(INPORT_BASE, INPORT_EXTENT);
		printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
		printk(KERN_ERR "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
		return -ENODEV;
		err = -ENODEV;
		goto err_release_region;
	}
	}


	if (!(inport_dev = input_allocate_device())) {
	inport_dev = input_allocate_device();
	if (!inport_dev) {
		printk(KERN_ERR "inport.c: Not enough memory for input device\n");
		printk(KERN_ERR "inport.c: Not enough memory for input device\n");
		release_region(INPORT_BASE, INPORT_EXTENT);
		err = -ENOMEM;
		return -ENOMEM;
		goto err_release_region;
	}
	}


	inport_dev->name = INPORT_NAME;
	inport_dev->name = INPORT_NAME;
@@ -174,9 +176,18 @@ static int __init inport_init(void)
	outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
	outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
	outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
	outb(INPORT_MODE_BASE, INPORT_DATA_PORT);


	input_register_device(inport_dev);
	err = input_register_device(inport_dev);
	if (err)
		goto err_free_dev;


	return 0;
	return 0;

 err_free_dev:
	input_free_device(inport_dev);
 err_release_region:
	release_region(INPORT_BASE, INPORT_EXTENT);

	return err;
}
}


static void __exit inport_exit(void)
static void __exit inport_exit(void)
+18 −6
Original line number Original line Diff line number Diff line
@@ -124,6 +124,8 @@ static void logibm_close(struct input_dev *dev)


static int __init logibm_init(void)
static int __init logibm_init(void)
{
{
	int err;

	if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
	if (!request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
		printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
		printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
		return -EBUSY;
		return -EBUSY;
@@ -134,18 +136,19 @@ static int __init logibm_init(void)
	udelay(100);
	udelay(100);


	if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
	if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
		release_region(LOGIBM_BASE, LOGIBM_EXTENT);
		printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
		printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
		return -ENODEV;
		err = -ENODEV;
		goto err_release_region;
	}
	}


	outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
	outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
	outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
	outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);


	if (!(logibm_dev = input_allocate_device())) {
	logibm_dev = input_allocate_device();
	if (!logibm_dev) {
		printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
		printk(KERN_ERR "logibm.c: Not enough memory for input device\n");
		release_region(LOGIBM_BASE, LOGIBM_EXTENT);
		err = -ENOMEM;
		return -ENOMEM;
		goto err_release_region;
	}
	}


	logibm_dev->name = "Logitech bus mouse";
	logibm_dev->name = "Logitech bus mouse";
@@ -162,9 +165,18 @@ static int __init logibm_init(void)
	logibm_dev->open  = logibm_open;
	logibm_dev->open  = logibm_open;
	logibm_dev->close = logibm_close;
	logibm_dev->close = logibm_close;


	input_register_device(logibm_dev);
	err = input_register_device(logibm_dev);
	if (err)
		goto err_free_dev;


	return 0;
	return 0;

 err_free_dev:
	input_free_device(logibm_dev);
 err_release_region:
	release_region(LOGIBM_BASE, LOGIBM_EXTENT);

	return err;
}
}


static void __exit logibm_exit(void)
static void __exit logibm_exit(void)
+19 −7
Original line number Original line Diff line number Diff line
@@ -108,6 +108,7 @@ static int pc110pad_open(struct input_dev *dev)
static int __init pc110pad_init(void)
static int __init pc110pad_init(void)
{
{
	struct pci_dev *dev;
	struct pci_dev *dev;
	int err;


	dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
	dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
	if (dev) {
	if (dev) {
@@ -124,16 +125,16 @@ static int __init pc110pad_init(void)
	outb(PC110PAD_OFF, pc110pad_io + 2);
	outb(PC110PAD_OFF, pc110pad_io + 2);


	if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) {
	if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", NULL)) {
		release_region(pc110pad_io, 4);
		printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
		printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
		return -EBUSY;
		err = -EBUSY;
		goto err_release_region;
	}
	}


	if (!(pc110pad_dev = input_allocate_device())) {
	pc110pad_dev = input_allocate_device();
		free_irq(pc110pad_irq, NULL);
	if (!pc110pad_dev) {
		release_region(pc110pad_io, 4);
		printk(KERN_ERR "pc110pad: Not enough memory.\n");
		printk(KERN_ERR "pc110pad: Not enough memory.\n");
		return -ENOMEM;
		err = -ENOMEM;
		goto err_free_irq;
	}
	}


	pc110pad_dev->name = "IBM PC110 TouchPad";
	pc110pad_dev->name = "IBM PC110 TouchPad";
@@ -153,9 +154,20 @@ static int __init pc110pad_init(void)
	pc110pad_dev->open = pc110pad_open;
	pc110pad_dev->open = pc110pad_open;
	pc110pad_dev->close = pc110pad_close;
	pc110pad_dev->close = pc110pad_close;


	input_register_device(pc110pad_dev);
	err = input_register_device(pc110pad_dev);
	if (err)
		goto err_free_dev;


	return 0;
	return 0;

 err_free_dev:
	input_free_device(pc110pad_dev);
 err_free_irq:
	free_irq(pc110pad_irq, NULL);
 err_release_region:
	release_region(pc110pad_io, 4);

	return err;
}
}


static void __exit pc110pad_exit(void)
static void __exit pc110pad_exit(void)
+59 −25
Original line number Original line Diff line number Diff line
@@ -1102,7 +1102,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
{
{
	struct psmouse *psmouse, *parent = NULL;
	struct psmouse *psmouse, *parent = NULL;
	struct input_dev *input_dev;
	struct input_dev *input_dev;
	int retval = -ENOMEM;
	int retval = 0, error = -ENOMEM;


	mutex_lock(&psmouse_mutex);
	mutex_lock(&psmouse_mutex);


@@ -1118,7 +1118,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
	psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL);
	psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL);
	input_dev = input_allocate_device();
	input_dev = input_allocate_device();
	if (!psmouse || !input_dev)
	if (!psmouse || !input_dev)
		goto out;
		goto err_free;


	ps2_init(&psmouse->ps2dev, serio);
	ps2_init(&psmouse->ps2dev, serio);
	INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);
	INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);
@@ -1129,14 +1129,13 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)


	serio_set_drvdata(serio, psmouse);
	serio_set_drvdata(serio, psmouse);


	retval = serio_open(serio, drv);
	error = serio_open(serio, drv);
	if (retval)
	if (error)
		goto out;
		goto err_clear_drvdata;


	if (psmouse_probe(psmouse) < 0) {
	if (psmouse_probe(psmouse) < 0) {
		serio_close(serio);
		error = -ENODEV;
		retval = -ENODEV;
		goto err_close_serio;
		goto out;
	}
	}


	psmouse->rate = psmouse_rate;
	psmouse->rate = psmouse_rate;
@@ -1150,30 +1149,44 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
	psmouse_initialize(psmouse);
	psmouse_initialize(psmouse);


	input_register_device(psmouse->dev);
	error = input_register_device(psmouse->dev);
	if (error)
		goto err_protocol_disconnect;


	if (parent && parent->pt_activate)
	if (parent && parent->pt_activate)
		parent->pt_activate(parent);
		parent->pt_activate(parent);


	sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
	error = sysfs_create_group(&serio->dev.kobj, &psmouse_attribute_group);
	if (error)
		goto err_pt_deactivate;


	psmouse_activate(psmouse);
	psmouse_activate(psmouse);


	retval = 0;

 out:
 out:
	if (retval) {
		serio_set_drvdata(serio, NULL);
		input_free_device(input_dev);
		kfree(psmouse);
	}

	/* If this is a pass-through port the parent needs to be re-activated */
	/* If this is a pass-through port the parent needs to be re-activated */
	if (parent)
	if (parent)
		psmouse_activate(parent);
		psmouse_activate(parent);


	mutex_unlock(&psmouse_mutex);
	mutex_unlock(&psmouse_mutex);
	return retval;
	return retval;

 err_pt_deactivate:
	if (parent && parent->pt_deactivate)
		parent->pt_deactivate(parent);
 err_protocol_disconnect:
	if (psmouse->disconnect)
		psmouse->disconnect(psmouse);
	psmouse_set_state(psmouse, PSMOUSE_IGNORE);
 err_close_serio:
	serio_close(serio);
 err_clear_drvdata:
	serio_set_drvdata(serio, NULL);
 err_free:
	input_free_device(input_dev);
	kfree(psmouse);

	retval = error;
	goto out;
}
}




@@ -1365,17 +1378,20 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
{
{
	struct serio *serio = psmouse->ps2dev.serio;
	struct serio *serio = psmouse->ps2dev.serio;
	struct psmouse *parent = NULL;
	struct psmouse *parent = NULL;
	struct input_dev *new_dev;
	struct input_dev *old_dev, *new_dev;
	const struct psmouse_protocol *proto;
	const struct psmouse_protocol *proto, *old_proto;
	int error;
	int retry = 0;
	int retry = 0;


	if (!(proto = psmouse_protocol_by_name(buf, count)))
	proto = psmouse_protocol_by_name(buf, count);
	if (!proto)
		return -EINVAL;
		return -EINVAL;


	if (psmouse->type == proto->type)
	if (psmouse->type == proto->type)
		return count;
		return count;


	if (!(new_dev = input_allocate_device()))
	new_dev = input_allocate_device();
	if (!new_dev)
		return -ENOMEM;
		return -ENOMEM;


	while (serio->child) {
	while (serio->child) {
@@ -1408,11 +1424,13 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
			parent->pt_deactivate(parent);
			parent->pt_deactivate(parent);
	}
	}


	old_dev = psmouse->dev;
	old_proto = psmouse_protocol_by_type(psmouse->type);

	if (psmouse->disconnect)
	if (psmouse->disconnect)
		psmouse->disconnect(psmouse);
		psmouse->disconnect(psmouse);


	psmouse_set_state(psmouse, PSMOUSE_IGNORE);
	psmouse_set_state(psmouse, PSMOUSE_IGNORE);
	input_unregister_device(psmouse->dev);


	psmouse->dev = new_dev;
	psmouse->dev = new_dev;
	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
@@ -1426,7 +1444,23 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
	psmouse_initialize(psmouse);
	psmouse_initialize(psmouse);
	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);


	input_register_device(psmouse->dev);
	error = input_register_device(psmouse->dev);
	if (error) {
		if (psmouse->disconnect)
			psmouse->disconnect(psmouse);

		psmouse_set_state(psmouse, PSMOUSE_IGNORE);
		input_free_device(new_dev);
		psmouse->dev = old_dev;
		psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
		psmouse_switch_protocol(psmouse, old_proto);
		psmouse_initialize(psmouse);
		psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);

		return error;
	}

	input_unregister_device(old_dev);


	if (parent && parent->pt_activate)
	if (parent && parent->pt_activate)
		parent->pt_activate(parent);
		parent->pt_activate(parent);
Loading