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:
parent
ff67c614e2
commit
b07b4783fb
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue