[media] cx231xx-input: stop polling if the device got removed.
Mauro Carvalho Chehab [Tue, 10 Jan 2012 00:28:13 +0000 (22:28 -0200)]
If the device got removed, stops polling it. Also, un-registers
it at input/evdev, as it won't work anymore. We can't free the
IR structure yet, as the ir_remove method will be called later.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

drivers/media/video/cx231xx/cx231xx-input.c
drivers/media/video/ir-kbd-i2c.c

index 45e14ca..8a75a90 100644 (file)
 static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
                         u32 *ir_raw)
 {
+       int     rc;
        u8      cmd, scancode;
 
        dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__);
 
                /* poll IR chip */
-       if (1 != i2c_master_recv(ir->c, &cmd, 1))
+       rc = i2c_master_recv(ir->c, &cmd, 1);
+       if (rc < 0)
+               return rc;
+       if (rc != 1)
                return -EIO;
 
        /* it seems that 0xFE indicates that a button is still hold
index 3ab875d..37d0c20 100644 (file)
@@ -244,7 +244,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir,
 
 /* ----------------------------------------------------------------------- */
 
-static void ir_key_poll(struct IR_i2c *ir)
+static int ir_key_poll(struct IR_i2c *ir)
 {
        static u32 ir_key, ir_raw;
        int rc;
@@ -253,20 +253,28 @@ static void ir_key_poll(struct IR_i2c *ir)
        rc = ir->get_key(ir, &ir_key, &ir_raw);
        if (rc < 0) {
                dprintk(2,"error\n");
-               return;
+               return rc;
        }
 
        if (rc) {
                dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key);
                rc_keydown(ir->rc, ir_key, 0);
        }
+       return 0;
 }
 
 static void ir_work(struct work_struct *work)
 {
+       int rc;
        struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work);
 
-       ir_key_poll(ir);
+       rc = ir_key_poll(ir);
+       if (rc == -ENODEV) {
+               rc_unregister_device(ir->rc);
+               ir->rc = NULL;
+               return;
+       }
+
        schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval));
 }
 
@@ -446,7 +454,8 @@ static int ir_remove(struct i2c_client *client)
        cancel_delayed_work_sync(&ir->work);
 
        /* unregister device */
-       rc_unregister_device(ir->rc);
+       if (ir->rc)
+               rc_unregister_device(ir->rc);
 
        /* free memory */
        kfree(ir);