aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@insightbb.com>2006-11-20 10:23:04 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 09:04:52 -0200
commitb07b4783fb30dee8c542fc76ed8993108d46d6aa (patch)
tree0e57cc5887511b31e964299820a7adf37e6e45ae /drivers/media/video
parentff67c614e23bf5a3c16968e2c42ab442121c4beb (diff)
downloadkernel_samsung_smdk4412-b07b4783fb30dee8c542fc76ed8993108d46d6aa.zip
kernel_samsung_smdk4412-b07b4783fb30dee8c542fc76ed8993108d46d6aa.tar.gz
kernel_samsung_smdk4412-b07b4783fb30dee8c542fc76ed8993108d46d6aa.tar.bz2
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>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/bt8xx/bttv-input.c101
-rw-r--r--drivers/media/video/cx88/cx88-input.c77
-rw-r--r--drivers/media/video/ir-kbd-i2c.c43
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c48
-rw-r--r--drivers/media/video/usbvideo/quickcam_messenger.c9
5 files changed, 172 insertions, 106 deletions
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 933d6db..cbc012f 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -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;
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index e60a0a5..c6d412b 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -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);
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index ab87e7b..dd6341f 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -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 */
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 83887d1..5d2bf15 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -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;
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
index bbf2bee..ec0ff22 100644
--- a/drivers/media/video/usbvideo/quickcam_messenger.c
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -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)