V4L/DVB (4854): Handle errors from input_register_device()
authorDmitry Torokhov <dtor@insightbb.com>
Mon, 20 Nov 2006 13:23:04 +0000 (10:23 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Sun, 10 Dec 2006 11:04:52 +0000 (09:04 -0200)
Also sprinkled some input_sync() throughout the code.
Acked-by: Ricardo Cerqueira <v4l@cerqueira.org>
Acked-by: Oliver Endriss <o.endriss@gmx.de>
Acked-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-usb/dvb-usb-remote.c
drivers/media/dvb/ttpci/av7110_ir.c
drivers/media/dvb/ttpci/budget-ci.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/video/bt8xx/bttv-input.c
drivers/media/video/cx88/cx88-input.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/saa7134/saa7134-input.c
drivers/media/video/usbvideo/quickcam_messenger.c

index 9123147..d64b96c 100644 (file)
@@ -746,6 +746,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
                                dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
                                input_report_key(cinergyt2->rc_input_dev,
                                                 cinergyt2->rc_input_event, 0);
+                               input_sync(cinergyt2->rc_input_dev);
                                cinergyt2->rc_input_event = KEY_MAX;
                        }
                        cinergyt2->rc_last_code = ~0;
@@ -783,6 +784,7 @@ static void cinergyt2_query_rc (struct work_struct *work)
                        dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
                        input_report_key(cinergyt2->rc_input_dev,
                                         cinergyt2->rc_input_event, 1);
+                       input_sync(cinergyt2->rc_input_dev);
                        cinergyt2->rc_last_code = rc_events[n].value;
                }
        }
@@ -798,8 +800,9 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
 {
        struct input_dev *input_dev;
        int i;
+       int err;
 
-       cinergyt2->rc_input_dev = input_dev = input_allocate_device();
+       input_dev = input_allocate_device();
        if (!input_dev)
                return -ENOMEM;
 
@@ -817,7 +820,13 @@ static int cinergyt2_register_rc(struct cinergyt2 *cinergyt2)
        input_dev->keycodesize = 0;
        input_dev->keycodemax = 0;
 
-       input_register_device(cinergyt2->rc_input_dev);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
+
+       cinergyt2->rc_input_dev = input_dev;
        schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
 
        return 0;
index 794e447..19ff597 100644 (file)
@@ -90,7 +90,9 @@ schedule:
 
 int dvb_usb_remote_init(struct dvb_usb_device *d)
 {
+       struct input_dev *input_dev;
        int i;
+       int err;
 
        if (d->props.rc_key_map == NULL ||
                d->props.rc_query == NULL ||
@@ -100,23 +102,24 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
        usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
        strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 
-       d->rc_input_dev = input_allocate_device();
-       if (!d->rc_input_dev)
+       input_dev = input_allocate_device();
+       if (!input_dev)
                return -ENOMEM;
 
-       d->rc_input_dev->evbit[0] = BIT(EV_KEY);
-       d->rc_input_dev->keycodesize = sizeof(unsigned char);
-       d->rc_input_dev->keycodemax = KEY_MAX;
-       d->rc_input_dev->name = "IR-receiver inside an USB DVB receiver";
-       d->rc_input_dev->phys = d->rc_phys;
-       usb_to_input_id(d->udev, &d->rc_input_dev->id);
-       d->rc_input_dev->cdev.dev = &d->udev->dev;
+       input_dev->evbit[0] = BIT(EV_KEY);
+       input_dev->keycodesize = sizeof(unsigned char);
+       input_dev->keycodemax = KEY_MAX;
+       input_dev->name = "IR-receiver inside an USB DVB receiver";
+       input_dev->phys = d->rc_phys;
+       usb_to_input_id(d->udev, &input_dev->id);
+       input_dev->cdev.dev = &d->udev->dev;
 
        /* set the bits for the keys */
        deb_rc("key map size: %d\n", d->props.rc_key_map_size);
        for (i = 0; i < d->props.rc_key_map_size; i++) {
-               deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
-               set_bit(d->props.rc_key_map[i].event, d->rc_input_dev->keybit);
+               deb_rc("setting bit for event %d item %d\n",
+                       d->props.rc_key_map[i].event, i);
+               set_bit(d->props.rc_key_map[i].event, input_dev->keybit);
        }
 
        /* Start the remote-control polling. */
@@ -124,10 +127,16 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
                d->props.rc_interval = 100; /* default */
 
        /* setting these two values to non-zero, we have to manage key repeats */
-       d->rc_input_dev->rep[REP_PERIOD] = d->props.rc_interval;
-       d->rc_input_dev->rep[REP_DELAY]  = d->props.rc_interval + 150;
+       input_dev->rep[REP_PERIOD] = d->props.rc_interval;
+       input_dev->rep[REP_DELAY]  = d->props.rc_interval + 150;
 
-       input_register_device(d->rc_input_dev);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
+
+       d->rc_input_dev = input_dev;
 
        INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
 
index d54bbcd..e4544ea 100644 (file)
@@ -48,7 +48,8 @@ static void av7110_emit_keyup(unsigned long data)
        if (!data || !test_bit(data, input_dev->key))
                return;
 
-       input_event(input_dev, EV_KEY, data, !!0);
+       input_report_key(input_dev, data, 0);
+       input_sync(input_dev);
 }
 
 
@@ -115,14 +116,17 @@ static void av7110_emit_key(unsigned long parm)
                del_timer(&keyup_timer);
                if (keyup_timer.data != keycode || new_toggle != old_toggle) {
                        delay_timer_finished = 0;
-                       input_event(input_dev, EV_KEY, keyup_timer.data, !!0);
-                       input_event(input_dev, EV_KEY, keycode, !0);
-               } else
-                       if (delay_timer_finished)
-                               input_event(input_dev, EV_KEY, keycode, 2);
+                       input_event(input_dev, EV_KEY, keyup_timer.data, 0);
+                       input_event(input_dev, EV_KEY, keycode, 1);
+                       input_sync(input_dev);
+               } else if (delay_timer_finished) {
+                       input_event(input_dev, EV_KEY, keycode, 2);
+                       input_sync(input_dev);
+               }
        } else {
                delay_timer_finished = 0;
-               input_event(input_dev, EV_KEY, keycode, !0);
+               input_event(input_dev, EV_KEY, keycode, 1);
+               input_sync(input_dev);
        }
 
        keyup_timer.expires = jiffies + UP_TIMEOUT;
@@ -211,6 +215,7 @@ static void ir_handler(struct av7110 *av7110, u32 ircom)
 int __devinit av7110_ir_init(struct av7110 *av7110)
 {
        static struct proc_dir_entry *e;
+       int err;
 
        if (av_cnt >= sizeof av_list/sizeof av_list[0])
                return -ENOSPC;
@@ -231,7 +236,11 @@ int __devinit av7110_ir_init(struct av7110 *av7110)
                set_bit(EV_KEY, input_dev->evbit);
                set_bit(EV_REP, input_dev->evbit);
                input_register_keys();
-               input_register_device(input_dev);
+               err = input_register_device(input_dev);
+               if (err) {
+                       input_free_device(input_dev);
+                       return err;
+               }
                input_dev->timer.function = input_repeat_key;
 
                e = create_proc_entry("av7110_ir", S_IFREG | S_IRUGO | S_IWUSR, NULL);
index cd5ec48..25d0dfc 100644 (file)
@@ -143,14 +143,14 @@ static void msp430_ir_debounce(unsigned long data)
        struct input_dev *dev = (struct input_dev *) data;
 
        if (dev->rep[0] == 0 || dev->rep[0] == ~0) {
-               input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
-               return;
+               input_event(dev, EV_KEY, key_map[dev->repeat_key], 0);
+       } else {
+               dev->rep[0] = 0;
+               dev->timer.expires = jiffies + HZ * 350 / 1000;
+               add_timer(&dev->timer);
+               input_event(dev, EV_KEY, key_map[dev->repeat_key], 2);  /* REPEAT */
        }
-
-       dev->rep[0] = 0;
-       dev->timer.expires = jiffies + HZ * 350 / 1000;
-       add_timer(&dev->timer);
-       input_event(dev, EV_KEY, key_map[dev->repeat_key], 2);  /* REPEAT */
+       input_sync(dev);
 }
 
 static void msp430_ir_interrupt(unsigned long data)
@@ -169,7 +169,7 @@ static void msp430_ir_interrupt(unsigned long data)
                                return;
                        }
                        del_timer(&dev->timer);
-                       input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+                       input_event(dev, EV_KEY, key_map[dev->repeat_key], 0);
                }
 
                if (!key_map[code]) {
@@ -177,15 +177,14 @@ static void msp430_ir_interrupt(unsigned long data)
                        return;
                }
 
+               input_event(dev, EV_KEY, key_map[code], 1);
+               input_sync(dev);
+
                /* initialize debounce and repeat */
                dev->repeat_key = code;
                /* Zenith remote _always_ sends 2 sequences */
                dev->rep[0] = ~0;
-               /* 350 milliseconds */
-               dev->timer.expires = jiffies + HZ * 350 / 1000;
-               /* MAKE */
-               input_event(dev, EV_KEY, key_map[code], !0);
-               add_timer(&dev->timer);
+               mod_timer(&dev->timer, jiffies + msecs_to_jiffies(350));
        }
 }
 
@@ -194,8 +193,9 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
        struct saa7146_dev *saa = budget_ci->budget.dev;
        struct input_dev *input_dev;
        int i;
+       int err;
 
-       budget_ci->input_dev = input_dev = input_allocate_device();
+       input_dev = input_allocate_device();
        if (!input_dev)
                return -ENOMEM;
 
@@ -208,10 +208,16 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
                if (key_map[i])
                        set_bit(key_map[i], input_dev->keybit);
 
-       input_register_device(budget_ci->input_dev);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
 
        input_dev->timer.function = msp430_ir_debounce;
 
+       budget_ci->input_dev = input_dev;
+
        saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
 
@@ -226,8 +232,10 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
        saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_06);
        saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 
-       if (del_timer(&dev->timer))
-               input_event(dev, EV_KEY, key_map[dev->repeat_key], !!0);
+       if (del_timer(&dev->timer)) {
+               input_event(dev, EV_KEY, key_map[dev->repeat_key], 0);
+               input_sync(dev);
+       }
 
        input_unregister_device(dev);
 }
index 10b121a..bd6e7ba 100644 (file)
@@ -238,6 +238,7 @@ static void ttusb_dec_handle_irq( struct urb *urb)
                 * for now lets report each signal as a key down and up*/
                dprintk("%s:rc signal:%d\n", __FUNCTION__, buffer[4]);
                input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 1);
+               input_sync(dec->rc_input_dev);
                input_report_key(dec->rc_input_dev, rc_keys[buffer[4] - 1], 0);
                input_sync(dec->rc_input_dev);
        }
@@ -1187,11 +1188,12 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
        struct input_dev *input_dev;
        u8 b[] = { 0x00, 0x01 };
        int i;
+       int err;
 
        usb_make_path(dec->udev, dec->rc_phys, sizeof(dec->rc_phys));
        strlcpy(dec->rc_phys, "/input0", sizeof(dec->rc_phys));
 
-       dec->rc_input_dev = input_dev = input_allocate_device();
+       input_dev = input_allocate_device();
        if (!input_dev)
                return -ENOMEM;
 
@@ -1205,8 +1207,13 @@ static int ttusb_init_rc( struct ttusb_dec *dec)
        for (i = 0; i < ARRAY_SIZE(rc_keys); i++)
                  set_bit(rc_keys[i], input_dev->keybit);
 
-       input_register_device(input_dev);
+       err = input_register_device(input_dev);
+       if (err) {
+               input_free_device(input_dev);
+               return err;
+       }
 
+       dec->rc_input_dev = input_dev;
        if (usb_submit_urb(dec->irq_urb, GFP_KERNEL))
                printk("%s: usb_submit_urb failed\n",__FUNCTION__);
        /* enable irq pipe */
index 933d6db..cbc012f 100644 (file)
@@ -259,24 +259,59 @@ static void bttv_rc5_timer_keyup(unsigned long data)
 
 /* ---------------------------------------------------------------------- */
 
+static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
+{
+       if (ir->polling) {
+               init_timer(&ir->timer);
+               ir->timer.function = bttv_input_timer;
+               ir->timer.data     = (unsigned long)btv;
+               ir->timer.expires  = jiffies + HZ;
+               add_timer(&ir->timer);
+       } else if (ir->rc5_gpio) {
+               /* set timer_end for code completion */
+               init_timer(&ir->timer_end);
+               ir->timer_end.function = bttv_rc5_timer_end;
+               ir->timer_end.data = (unsigned long)ir;
+
+               init_timer(&ir->timer_keyup);
+               ir->timer_keyup.function = bttv_rc5_timer_keyup;
+               ir->timer_keyup.data = (unsigned long)ir;
+       }
+}
+
+static void bttv_ir_stop(struct bttv *btv)
+{
+       if (btv->remote->polling) {
+               del_timer_sync(&btv->remote->timer);
+               flush_scheduled_work();
+       }
+
+       if (btv->remote->rc5_gpio) {
+               u32 gpio;
+
+               del_timer_sync(&btv->remote->timer_end);
+               flush_scheduled_work();
+
+               gpio = bttv_gpio_read(&btv->c);
+               bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
+       }
+}
+
 int bttv_input_init(struct bttv *btv)
 {
        struct bttv_ir *ir;
        IR_KEYTAB_TYPE *ir_codes = NULL;
        struct input_dev *input_dev;
        int ir_type = IR_TYPE_OTHER;
+       int err = -ENOMEM;
 
        if (!btv->has_remote)
                return -ENODEV;
 
        ir = kzalloc(sizeof(*ir),GFP_KERNEL);
        input_dev = input_allocate_device();
-       if (!ir || !input_dev) {
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENOMEM;
-       }
-       memset(ir,0,sizeof(*ir));
+       if (!ir || !input_dev)
+               goto err_out_free;
 
        /* detect & configure */
        switch (btv->c.type) {
@@ -348,10 +383,9 @@ int bttv_input_init(struct bttv *btv)
                break;
        }
        if (NULL == ir_codes) {
-               dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n",btv->c.type);
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENODEV;
+               dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type);
+               err = -ENODEV;
+               goto err_out_free;
        }
 
        if (ir->rc5_gpio) {
@@ -389,32 +423,26 @@ int bttv_input_init(struct bttv *btv)
        input_dev->cdev.dev = &btv->c.pci->dev;
 
        btv->remote = ir;
-       if (ir->polling) {
-               init_timer(&ir->timer);
-               ir->timer.function = bttv_input_timer;
-               ir->timer.data     = (unsigned long)btv;
-               ir->timer.expires  = jiffies + HZ;
-               add_timer(&ir->timer);
-       } else if (ir->rc5_gpio) {
-               /* set timer_end for code completion */
-               init_timer(&ir->timer_end);
-               ir->timer_end.function = bttv_rc5_timer_end;
-               ir->timer_end.data = (unsigned long)ir;
-
-               init_timer(&ir->timer_keyup);
-               ir->timer_keyup.function = bttv_rc5_timer_keyup;
-               ir->timer_keyup.data = (unsigned long)ir;
-       }
+       bttv_ir_start(btv, ir);
 
        /* all done */
-       input_register_device(btv->remote->dev);
-       printk(DEVNAME ": %s detected at %s\n",ir->name,ir->phys);
+       err = input_register_device(btv->remote->dev);
+       if (err)
+               goto err_out_stop;
 
        /* the remote isn't as bouncy as a keyboard */
        ir->dev->rep[REP_DELAY] = repeat_delay;
        ir->dev->rep[REP_PERIOD] = repeat_period;
 
        return 0;
+
+ err_out_stop:
+       bttv_ir_stop(btv);
+       btv->remote = NULL;
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
 }
 
 void bttv_input_fini(struct bttv *btv)
@@ -422,22 +450,7 @@ void bttv_input_fini(struct bttv *btv)
        if (btv->remote == NULL)
                return;
 
-       if (btv->remote->polling) {
-               del_timer_sync(&btv->remote->timer);
-               flush_scheduled_work();
-       }
-
-
-       if (btv->remote->rc5_gpio) {
-               u32 gpio;
-
-               del_timer_sync(&btv->remote->timer_end);
-               flush_scheduled_work();
-
-               gpio = bttv_gpio_read(&btv->c);
-               bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
-       }
-
+       bttv_ir_stop(btv);
        input_unregister_device(btv->remote->dev);
        kfree(btv->remote);
        btv->remote = NULL;
index e60a0a5..c6d412b 100644 (file)
@@ -155,6 +155,35 @@ static void cx88_ir_work(struct work_struct *work)
        mod_timer(&ir->timer, timeout);
 }
 
+static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
+{
+       if (ir->polling) {
+               INIT_WORK(&ir->work, cx88_ir_work, ir);
+               init_timer(&ir->timer);
+               ir->timer.function = ir_timer;
+               ir->timer.data = (unsigned long)ir;
+               schedule_work(&ir->work);
+       }
+       if (ir->sampling) {
+               core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
+               cx_write(MO_DDS_IO, 0xa80a80);  /* 4 kHz sample rate */
+               cx_write(MO_DDSCFG_IO, 0x5);    /* enable */
+       }
+}
+
+static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
+{
+       if (ir->sampling) {
+               cx_write(MO_DDSCFG_IO, 0x0);
+               core->pci_irqmask &= ~(1 << 18);
+       }
+
+       if (ir->polling) {
+               del_timer_sync(&ir->timer);
+               flush_scheduled_work();
+       }
+}
+
 /* ---------------------------------------------------------------------- */
 
 int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
@@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        struct input_dev *input_dev;
        IR_KEYTAB_TYPE *ir_codes = NULL;
        int ir_type = IR_TYPE_OTHER;
+       int err = -ENOMEM;
 
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
        input_dev = input_allocate_device();
-       if (!ir || !input_dev) {
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENOMEM;
-       }
+       if (!ir || !input_dev)
+               goto err_out_free;
 
        ir->input = input_dev;
 
@@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        }
 
        if (NULL == ir_codes) {
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENODEV;
+               err = -ENODEV;
+               goto err_out_free;
        }
 
        /* init input device */
@@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
        ir->core = core;
        core->ir = ir;
 
-       if (ir->polling) {
-               INIT_WORK(&ir->work, cx88_ir_work);
-               init_timer(&ir->timer);
-               ir->timer.function = ir_timer;
-               ir->timer.data = (unsigned long)ir;
-               schedule_work(&ir->work);
-       }
-       if (ir->sampling) {
-               core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
-               cx_write(MO_DDS_IO, 0xa80a80);  /* 4 kHz sample rate */
-               cx_write(MO_DDSCFG_IO, 0x5);    /* enable */
-       }
+       cx88_ir_start(core, ir);
 
        /* all done */
-       input_register_device(ir->input);
+       err = input_register_device(ir->input);
+       if (err)
+               goto err_out_stop;
 
        return 0;
+
+ err_out_stop:
+       cx88_ir_stop(core, ir);
+       core->ir = NULL;
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
 }
 
 int cx88_ir_fini(struct cx88_core *core)
@@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core)
        if (NULL == ir)
                return 0;
 
-       if (ir->sampling) {
-               cx_write(MO_DDSCFG_IO, 0x0);
-               core->pci_irqmask &= ~(1 << 18);
-       }
-       if (ir->polling) {
-               del_timer(&ir->timer);
-               flush_scheduled_work();
-       }
-
+       cx88_ir_stop(core, ir);
        input_unregister_device(ir->input);
        kfree(ir);
 
index ab87e7b..dd6341f 100644 (file)
@@ -305,15 +305,14 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
        int ir_type;
        struct IR_i2c *ir;
        struct input_dev *input_dev;
+       int err;
 
        ir = kzalloc(sizeof(struct IR_i2c),GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!ir || !input_dev) {
-               input_free_device(input_dev);
-               kfree(ir);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_out_free;
        }
-       memset(ir,0,sizeof(*ir));
 
        ir->c = client_template;
        ir->input = input_dev;
@@ -361,26 +360,27 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
                break;
        default:
                /* shouldn't happen */
-               printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n",addr);
-               kfree(ir);
-               return -1;
+               printk(DEVNAME ": Huh? unknown i2c address (0x%02x)?\n", addr);
+               err = -ENODEV;
+               goto err_out_free;
        }
 
        /* Sets name */
        snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (%s)", name);
-       ir->ir_codes=ir_codes;
+       ir->ir_codes = ir_codes;
 
        /* register i2c device
         * At device register, IR codes may be changed to be
         * board dependent.
         */
-       i2c_attach_client(&ir->c);
+       err = i2c_attach_client(&ir->c);
+       if (err)
+               goto err_out_free;
 
        /* If IR not supported or disabled, unregisters driver */
        if (ir->get_key == NULL) {
-               i2c_detach_client(&ir->c);
-               kfree(ir);
-               return -1;
+               err = -ENODEV;
+               goto err_out_detach;
        }
 
        /* Phys addr can only be set after attaching (for ir->c.dev.bus_id) */
@@ -389,15 +389,17 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
                 ir->c.dev.bus_id);
 
        /* init + register input device */
-       ir_input_init(input_dev,&ir->ir,ir_type,ir->ir_codes);
+       ir_input_init(input_dev, &ir->ir, ir_type, ir->ir_codes);
        input_dev->id.bustype = BUS_I2C;
        input_dev->name       = ir->c.name;
        input_dev->phys       = ir->phys;
 
-       /* register event device */
-       input_register_device(ir->input);
+       err = input_register_device(ir->input);
+       if (err)
+               goto err_out_detach;
+
        printk(DEVNAME ": %s detected at %s [%s]\n",
-              ir->input->name,ir->input->phys,adap->name);
+              ir->input->name, ir->input->phys, adap->name);
 
        /* start polling via eventd */
        INIT_WORK(&ir->work, ir_work);
@@ -407,6 +409,13 @@ static int ir_attach(struct i2c_adapter *adap, int addr,
        schedule_work(&ir->work);
 
        return 0;
+
+ err_out_detach:
+       i2c_detach_client(&ir->c);
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
 }
 
 static int ir_detach(struct i2c_client *client)
@@ -414,7 +423,7 @@ static int ir_detach(struct i2c_client *client)
        struct IR_i2c *ir = i2c_get_clientdata(client);
 
        /* kill outstanding polls */
-       del_timer(&ir->timer);
+       del_timer_sync(&ir->timer);
        flush_scheduled_work();
 
        /* unregister devices */
index 83887d1..5d2bf15 100644 (file)
@@ -131,6 +131,23 @@ static void saa7134_input_timer(unsigned long data)
        mod_timer(&ir->timer, timeout);
 }
 
+static void saa7134_ir_start(struct saa7134_dev *dev, struct saa7134_ir *ir)
+{
+       if (ir->polling) {
+               init_timer(&ir->timer);
+               ir->timer.function = saa7134_input_timer;
+               ir->timer.data     = (unsigned long)dev;
+               ir->timer.expires  = jiffies + HZ;
+               add_timer(&ir->timer);
+       }
+}
+
+static void saa7134_ir_stop(struct saa7134_dev *dev)
+{
+       if (dev->remote->polling)
+               del_timer_sync(&dev->remote->timer);
+}
+
 int saa7134_input_init1(struct saa7134_dev *dev)
 {
        struct saa7134_ir *ir;
@@ -141,6 +158,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        u32 mask_keyup   = 0;
        int polling      = 0;
        int ir_type      = IR_TYPE_OTHER;
+       int err;
 
        if (dev->has_remote != SAA7134_REMOTE_GPIO)
                return -ENODEV;
@@ -267,9 +285,8 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
        input_dev = input_allocate_device();
        if (!ir || !input_dev) {
-               kfree(ir);
-               input_free_device(input_dev);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_out_free;
        }
 
        ir->dev = input_dev;
@@ -300,18 +317,22 @@ int saa7134_input_init1(struct saa7134_dev *dev)
        }
        input_dev->cdev.dev = &dev->pci->dev;
 
-       /* all done */
        dev->remote = ir;
-       if (ir->polling) {
-               init_timer(&ir->timer);
-               ir->timer.function = saa7134_input_timer;
-               ir->timer.data     = (unsigned long)dev;
-               ir->timer.expires  = jiffies + HZ;
-               add_timer(&ir->timer);
-       }
+       saa7134_ir_start(dev, ir);
+
+       err = input_register_device(ir->dev);
+       if (err)
+               goto err_out_stop;
 
-       input_register_device(ir->dev);
        return 0;
+
+ err_out_stop:
+       saa7134_ir_stop(dev);
+       dev->remote = NULL;
+ err_out_free:
+       input_free_device(input_dev);
+       kfree(ir);
+       return err;
 }
 
 void saa7134_input_fini(struct saa7134_dev *dev)
@@ -319,8 +340,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
        if (NULL == dev->remote)
                return;
 
-       if (dev->remote->polling)
-               del_timer_sync(&dev->remote->timer);
+       saa7134_ir_stop(dev);
        input_unregister_device(dev->remote->dev);
        kfree(dev->remote);
        dev->remote = NULL;
index bbf2bee..ec0ff22 100644 (file)
@@ -86,6 +86,7 @@ MODULE_DEVICE_TABLE(usb, qcm_table);
 static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
 {
        struct input_dev *input_dev;
+       int error;
 
        usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
        strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
@@ -106,7 +107,13 @@ static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
 
        input_dev->private = cam;
 
-       input_register_device(cam->input);
+       error = input_register_device(cam->input);
+       if (error) {
+               warn("Failed to register camera's input device, err: %d\n",
+                    error);
+               input_free_device(cam->input);
+               cam->input = NULL;
+       }
 }
 
 static void qcm_unregister_input(struct qcm *cam)