V4L/DVB: ir-core: add two functions to report keyup/keydown events
[safe/jmp/linux-2.6] / drivers / media / IR / ir-keytable.c
index ddb8a0f..e59290f 100644 (file)
@@ -12,8 +12,9 @@
  *  GNU General Public License for more details.
  */
 
-#include <linux/usb/input.h>
 
+#include <linux/input.h>
+#include <linux/slab.h>
 #include <media/ir-common.h>
 
 #define IR_TAB_MIN_SIZE        32
@@ -65,7 +66,7 @@ exit:
  * In order to reduce the quantity of table resizes, it has a minimum
  * table size of IR_TAB_MIN_SIZE.
  */
-int ir_roundup_tablesize(int n_elems)
+static int ir_roundup_tablesize(int n_elems)
 {
        size_t size;
 
@@ -81,7 +82,6 @@ int ir_roundup_tablesize(int n_elems)
 
        return n_elems;
 }
-EXPORT_SYMBOL_GPL(ir_roundup_tablesize);
 
 /**
  * ir_copy_table() - copies a keytable, discarding the unused entries
@@ -89,9 +89,11 @@ EXPORT_SYMBOL_GPL(ir_roundup_tablesize);
  * @origin:    origin table
  *
  * Copies all entries where the keycode is not KEY_UNKNOWN/KEY_RESERVED
+ * Also copies table size and table protocol.
+ * NOTE: It shouldn't copy the lock field
  */
 
-int ir_copy_table(struct ir_scancode_table *destin,
+static int ir_copy_table(struct ir_scancode_table *destin,
                 const struct ir_scancode_table *origin)
 {
        int i, j = 0;
@@ -105,12 +107,12 @@ int ir_copy_table(struct ir_scancode_table *destin,
                j++;
        }
        destin->size = j;
+       destin->ir_type = origin->ir_type;
 
        IR_dprintk(1, "Copied %d scancodes to the new keycode table\n", destin->size);
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(ir_copy_table);
 
 /**
  * ir_getkeycode() - get a keycode at the evdev scancode ->keycode table
@@ -122,7 +124,7 @@ EXPORT_SYMBOL_GPL(ir_copy_table);
  * If the key is not found, returns -EINVAL, otherwise, returns 0.
  */
 static int ir_getkeycode(struct input_dev *dev,
-                        int scancode, int *keycode)
+                        unsigned int scancode, unsigned int *keycode)
 {
        int elem;
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
@@ -184,18 +186,14 @@ static void ir_delete_key(struct ir_scancode_table *rc_tab, int elem)
        int newsize = rc_tab->size - 1;
        int resize = ir_is_resize_needed(rc_tab, newsize);
        struct ir_scancode *oldkeymap = rc_tab->scan;
-       struct ir_scancode *newkeymap;
+       struct ir_scancode *newkeymap = NULL;
 
-       if (resize) {
+       if (resize)
                newkeymap = kzalloc(ir_roundup_tablesize(newsize) *
                                    sizeof(*newkeymap), GFP_ATOMIC);
 
-               /* There's no memory for resize. Keep the old table */
-               if (!newkeymap)
-                       resize = 0;
-       }
-
-       if (!resize) {
+       /* There's no memory for resize. Keep the old table */
+       if (!resize || !newkeymap) {
                newkeymap = oldkeymap;
 
                /* We'll modify the live table. Lock it */
@@ -294,7 +292,7 @@ static int ir_insert_key(struct ir_scancode_table *rc_tab,
  * If the key is not found, returns -EINVAL, otherwise, returns 0.
  */
 static int ir_setkeycode(struct input_dev *dev,
-                        int scancode, int keycode)
+                        unsigned int scancode, unsigned int keycode)
 {
        int rc = 0;
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
@@ -367,7 +365,7 @@ static int ir_setkeycode(struct input_dev *dev,
  *
  * This routine is used by the input routines when a key is pressed at the
  * IR. The scancode is received and needs to be converted into a keycode.
- * If the key is not found, it returns KEY_UNKNOWN. Otherwise, returns the
+ * If the key is not found, it returns KEY_RESERVED. Otherwise, returns the
  * corresponding keycode from the table.
  */
 u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
@@ -394,21 +392,79 @@ u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
 EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
 
 /**
+ * ir_keyup() - generates input event to cleanup a key press
+ * @input_dev: the struct input_dev descriptor of the device
+ *
+ * This routine is used by the input routines when a key is pressed at the
+ * IR. It reports a keyup input event via input_report_key().
+ */
+void ir_keyup(struct input_dev *dev)
+{
+       struct ir_input_dev *ir = input_get_drvdata(dev);
+
+       if (!ir->keypressed)
+               return;
+
+       input_report_key(dev, ir->keycode, 0);
+       input_sync(dev);
+       ir->keypressed = 0;
+}
+EXPORT_SYMBOL_GPL(ir_keyup);
+
+/**
+ * ir_keydown() - generates input event for a key press
+ * @input_dev: the struct input_dev descriptor of the device
+ * @scancode:  the scancode that we're seeking
+ *
+ * This routine is used by the input routines when a key is pressed at the
+ * IR. It gets the keycode for a scancode and reports an input event via
+ * input_report_key().
+ */
+void ir_keydown(struct input_dev *dev, int scancode)
+{
+       struct ir_input_dev *ir = input_get_drvdata(dev);
+
+       u32 keycode = ir_g_keycode_from_table(dev, scancode);
+
+       /* If already sent a keydown, do a keyup */
+       if (ir->keypressed)
+               ir_keyup(dev);
+
+       if (KEY_RESERVED == keycode)
+               return;
+
+       ir->keycode = keycode;
+       ir->keypressed = 1;
+
+       IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
+               dev->name, keycode, scancode);
+
+       input_report_key(dev, ir->keycode, 1);
+       input_sync(dev);
+
+}
+EXPORT_SYMBOL_GPL(ir_keydown);
+
+
+/**
  * ir_input_register() - sets the IR keycode table and add the handlers
  *                         for keymap table get/set
  * @input_dev: the struct input_dev descriptor of the device
  * @rc_tab:    the struct ir_scancode_table table of scancode/keymap
  *
- * This routine is used to initialize the input infrastructure to work with
- * an IR.
- * It should be called before registering the IR device.
+ * This routine is used to initialize the input infrastructure
+ * to work with an IR.
+ * It will register the input/evdev interface for the device and
+ * register the syfs code for IR class
  */
 int ir_input_register(struct input_dev *input_dev,
-                     struct ir_scancode_table *rc_tab)
+                     const struct ir_scancode_table *rc_tab,
+                     const struct ir_dev_props *props,
+                     const char *driver_name)
 {
        struct ir_input_dev *ir_dev;
        struct ir_scancode  *keymap    = rc_tab->scan;
-       int i;
+       int i, rc;
 
        if (rc_tab->scan == NULL || !rc_tab->size)
                return -EINVAL;
@@ -417,19 +473,27 @@ int ir_input_register(struct input_dev *input_dev,
        if (!ir_dev)
                return -ENOMEM;
 
-       spin_lock_init(&rc_tab->lock);
+       spin_lock_init(&ir_dev->rc_tab.lock);
 
+       ir_dev->driver_name = kmalloc(strlen(driver_name) + 1, GFP_KERNEL);
+       if (!ir_dev->driver_name)
+               return -ENOMEM;
+       strcpy(ir_dev->driver_name, driver_name);
+       ir_dev->rc_tab.name = rc_tab->name;
        ir_dev->rc_tab.size = ir_roundup_tablesize(rc_tab->size);
        ir_dev->rc_tab.scan = kzalloc(ir_dev->rc_tab.size *
                                    sizeof(struct ir_scancode), GFP_KERNEL);
-       if (!ir_dev->rc_tab.scan)
+       if (!ir_dev->rc_tab.scan) {
+               kfree(ir_dev);
                return -ENOMEM;
+       }
 
        IR_dprintk(1, "Allocated space for %d keycode entries (%zd bytes)\n",
                ir_dev->rc_tab.size,
                ir_dev->rc_tab.size * sizeof(ir_dev->rc_tab.scan));
 
        ir_copy_table(&ir_dev->rc_tab, rc_tab);
+       ir_dev->props = props;
 
        /* set the bits for the keys */
        IR_dprintk(1, "key map size: %d\n", rc_tab->size);
@@ -446,28 +510,45 @@ int ir_input_register(struct input_dev *input_dev,
        input_dev->setkeycode = ir_setkeycode;
        input_set_drvdata(input_dev, ir_dev);
 
+       rc = ir_register_class(input_dev);
+       if (rc < 0)
+               goto err;
+
        return 0;
+
+err:
+       kfree(rc_tab->scan);
+       kfree(ir_dev);
+       return rc;
 }
 EXPORT_SYMBOL_GPL(ir_input_register);
 
-void ir_input_free(struct input_dev *dev)
+/**
+ * ir_input_unregister() - unregisters IR and frees resources
+ * @input_dev: the struct input_dev descriptor of the device
+
+ * This routine is used to free memory and de-register interfaces.
+ */
+void ir_input_unregister(struct input_dev *dev)
 {
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
-       struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+       struct ir_scancode_table *rc_tab;
 
-       if (!rc_tab)
+       if (!ir_dev)
                return;
 
        IR_dprintk(1, "Freed keycode table\n");
 
+       rc_tab = &ir_dev->rc_tab;
        rc_tab->size = 0;
        kfree(rc_tab->scan);
        rc_tab->scan = NULL;
 
+       ir_unregister_class(dev);
+
        kfree(ir_dev);
-       input_set_drvdata(dev, NULL);
 }
-EXPORT_SYMBOL_GPL(ir_input_free);
+EXPORT_SYMBOL_GPL(ir_input_unregister);
 
 int ir_core_debug;    /* ir_debug level (0,1,2) */
 EXPORT_SYMBOL_GPL(ir_core_debug);