V4L/DVB (4854): Handle errors from input_register_device()

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>
This commit is contained in:
Dmitry Torokhov 2006-11-20 10:23:04 -03:00 committed by Mauro Carvalho Chehab
parent ff67c614e2
commit b07b4783fb
10 changed files with 257 additions and 149 deletions

View 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;

View 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);

View 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);

View 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);
}

View 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 */

View 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;

View 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);

View 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 */

View 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;

View 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)