linux/drivers/media/usb/dvb-usb/dvb-usb-remote.c
<<
>>
Prefs
   1/* dvb-usb-remote.c is part of the DVB USB library.
   2 *
   3 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de)
   4 * see dvb-usb-init.c for copyright information.
   5 *
   6 * This file contains functions for initializing the input-device and for handling remote-control-queries.
   7 */
   8#include "dvb-usb-common.h"
   9#include <linux/usb/input.h>
  10
  11static unsigned int
  12legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke,
  13                                struct rc_map_table *keymap,
  14                                unsigned int keymap_size)
  15{
  16        unsigned int index;
  17        unsigned int scancode;
  18
  19        if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
  20                index = ke->index;
  21        } else {
  22                if (input_scancode_to_scalar(ke, &scancode))
  23                        return keymap_size;
  24
  25                /* See if we can match the raw key code. */
  26                for (index = 0; index < keymap_size; index++)
  27                        if (keymap[index].scancode == scancode)
  28                                break;
  29
  30                /* See if there is an unused hole in the map */
  31                if (index >= keymap_size) {
  32                        for (index = 0; index < keymap_size; index++) {
  33                                if (keymap[index].keycode == KEY_RESERVED ||
  34                                    keymap[index].keycode == KEY_UNKNOWN) {
  35                                        break;
  36                                }
  37                        }
  38                }
  39        }
  40
  41        return index;
  42}
  43
  44static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
  45                                     struct input_keymap_entry *ke)
  46{
  47        struct dvb_usb_device *d = input_get_drvdata(dev);
  48        struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
  49        unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
  50        unsigned int index;
  51
  52        index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
  53        if (index >= keymap_size)
  54                return -EINVAL;
  55
  56        ke->keycode = keymap[index].keycode;
  57        if (ke->keycode == KEY_UNKNOWN)
  58                ke->keycode = KEY_RESERVED;
  59        ke->len = sizeof(keymap[index].scancode);
  60        memcpy(&ke->scancode, &keymap[index].scancode, ke->len);
  61        ke->index = index;
  62
  63        return 0;
  64}
  65
  66static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
  67                                     const struct input_keymap_entry *ke,
  68                                     unsigned int *old_keycode)
  69{
  70        struct dvb_usb_device *d = input_get_drvdata(dev);
  71        struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
  72        unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
  73        unsigned int index;
  74
  75        index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
  76        /*
  77         * FIXME: Currently, it is not possible to increase the size of
  78         * scancode table. For it to happen, one possibility
  79         * would be to allocate a table with key_map_size + 1,
  80         * copying data, appending the new key on it, and freeing
  81         * the old one - or maybe just allocating some spare space
  82         */
  83        if (index >= keymap_size)
  84                return -EINVAL;
  85
  86        *old_keycode = keymap[index].keycode;
  87        keymap->keycode = ke->keycode;
  88        __set_bit(ke->keycode, dev->keybit);
  89
  90        if (*old_keycode != KEY_RESERVED) {
  91                __clear_bit(*old_keycode, dev->keybit);
  92                for (index = 0; index < keymap_size; index++) {
  93                        if (keymap[index].keycode == *old_keycode) {
  94                                __set_bit(*old_keycode, dev->keybit);
  95                                break;
  96                        }
  97                }
  98        }
  99
 100        return 0;
 101}
 102
 103/* Remote-control poll function - called every dib->rc_query_interval ms to see
 104 * whether the remote control has received anything.
 105 *
 106 * TODO: Fix the repeat rate of the input device.
 107 */
 108static void legacy_dvb_usb_read_remote_control(struct work_struct *work)
 109{
 110        struct dvb_usb_device *d =
 111                container_of(work, struct dvb_usb_device, rc_query_work.work);
 112        u32 event;
 113        int state;
 114
 115        /* TODO: need a lock here.  We can simply skip checking for the remote control
 116           if we're busy. */
 117
 118        /* when the parameter has been set to 1 via sysfs while the driver was running */
 119        if (dvb_usb_disable_rc_polling)
 120                return;
 121
 122        if (d->props.rc.legacy.rc_query(d,&event,&state)) {
 123                err("error while querying for an remote control event.");
 124                goto schedule;
 125        }
 126
 127
 128        switch (state) {
 129                case REMOTE_NO_KEY_PRESSED:
 130                        break;
 131                case REMOTE_KEY_PRESSED:
 132                        deb_rc("key pressed\n");
 133                        d->last_event = event;
 134                case REMOTE_KEY_REPEAT:
 135                        deb_rc("key repeated\n");
 136                        input_event(d->input_dev, EV_KEY, event, 1);
 137                        input_sync(d->input_dev);
 138                        input_event(d->input_dev, EV_KEY, d->last_event, 0);
 139                        input_sync(d->input_dev);
 140                        break;
 141                default:
 142                        break;
 143        }
 144
 145/* improved repeat handling ???
 146        switch (state) {
 147                case REMOTE_NO_KEY_PRESSED:
 148                        deb_rc("NO KEY PRESSED\n");
 149                        if (d->last_state != REMOTE_NO_KEY_PRESSED) {
 150                                deb_rc("releasing event %d\n",d->last_event);
 151                                input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
 152                                input_sync(d->rc_input_dev);
 153                        }
 154                        d->last_state = REMOTE_NO_KEY_PRESSED;
 155                        d->last_event = 0;
 156                        break;
 157                case REMOTE_KEY_PRESSED:
 158                        deb_rc("KEY PRESSED\n");
 159                        deb_rc("pressing event %d\n",event);
 160
 161                        input_event(d->rc_input_dev, EV_KEY, event, 1);
 162                        input_sync(d->rc_input_dev);
 163
 164                        d->last_event = event;
 165                        d->last_state = REMOTE_KEY_PRESSED;
 166                        break;
 167                case REMOTE_KEY_REPEAT:
 168                        deb_rc("KEY_REPEAT\n");
 169                        if (d->last_state != REMOTE_NO_KEY_PRESSED) {
 170                                deb_rc("repeating event %d\n",d->last_event);
 171                                input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
 172                                input_sync(d->rc_input_dev);
 173                                d->last_state = REMOTE_KEY_REPEAT;
 174                        }
 175                default:
 176                        break;
 177        }
 178*/
 179
 180schedule:
 181        schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
 182}
 183
 184static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d)
 185{
 186        int i, err, rc_interval;
 187        struct input_dev *input_dev;
 188
 189        input_dev = input_allocate_device();
 190        if (!input_dev)
 191                return -ENOMEM;
 192
 193        input_dev->evbit[0] = BIT_MASK(EV_KEY);
 194        input_dev->name = "IR-receiver inside an USB DVB receiver";
 195        input_dev->phys = d->rc_phys;
 196        usb_to_input_id(d->udev, &input_dev->id);
 197        input_dev->dev.parent = &d->udev->dev;
 198        d->input_dev = input_dev;
 199        d->rc_dev = NULL;
 200
 201        input_dev->getkeycode = legacy_dvb_usb_getkeycode;
 202        input_dev->setkeycode = legacy_dvb_usb_setkeycode;
 203
 204        /* set the bits for the keys */
 205        deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size);
 206        for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
 207                deb_rc("setting bit for event %d item %d\n",
 208                        d->props.rc.legacy.rc_map_table[i].keycode, i);
 209                set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit);
 210        }
 211
 212        /* setting these two values to non-zero, we have to manage key repeats */
 213        input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval;
 214        input_dev->rep[REP_DELAY]  = d->props.rc.legacy.rc_interval + 150;
 215
 216        input_set_drvdata(input_dev, d);
 217
 218        err = input_register_device(input_dev);
 219        if (err)
 220                input_free_device(input_dev);
 221
 222        rc_interval = d->props.rc.legacy.rc_interval;
 223
 224        INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control);
 225
 226        info("schedule remote query interval to %d msecs.", rc_interval);
 227        schedule_delayed_work(&d->rc_query_work,
 228                              msecs_to_jiffies(rc_interval));
 229
 230        d->state |= DVB_USB_STATE_REMOTE;
 231
 232        return err;
 233}
 234
 235/* Remote-control poll function - called every dib->rc_query_interval ms to see
 236 * whether the remote control has received anything.
 237 *
 238 * TODO: Fix the repeat rate of the input device.
 239 */
 240static void dvb_usb_read_remote_control(struct work_struct *work)
 241{
 242        struct dvb_usb_device *d =
 243                container_of(work, struct dvb_usb_device, rc_query_work.work);
 244        int err;
 245
 246        /* TODO: need a lock here.  We can simply skip checking for the remote control
 247           if we're busy. */
 248
 249        /* when the parameter has been set to 1 via sysfs while the
 250         * driver was running, or when bulk mode is enabled after IR init
 251         */
 252        if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode)
 253                return;
 254
 255        err = d->props.rc.core.rc_query(d);
 256        if (err)
 257                err("error %d while querying for an remote control event.", err);
 258
 259        schedule_delayed_work(&d->rc_query_work,
 260                              msecs_to_jiffies(d->props.rc.core.rc_interval));
 261}
 262
 263static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
 264{
 265        int err, rc_interval;
 266        struct rc_dev *dev;
 267
 268        dev = rc_allocate_device();
 269        if (!dev)
 270                return -ENOMEM;
 271
 272        dev->driver_name = d->props.rc.core.module_name;
 273        dev->map_name = d->props.rc.core.rc_codes;
 274        dev->change_protocol = d->props.rc.core.change_protocol;
 275        dev->allowed_protocols = d->props.rc.core.allowed_protos;
 276        dev->driver_type = d->props.rc.core.driver_type;
 277        usb_to_input_id(d->udev, &dev->input_id);
 278        dev->input_name = "IR-receiver inside an USB DVB receiver";
 279        dev->input_phys = d->rc_phys;
 280        dev->dev.parent = &d->udev->dev;
 281        dev->priv = d;
 282
 283        err = rc_register_device(dev);
 284        if (err < 0) {
 285                rc_free_device(dev);
 286                return err;
 287        }
 288
 289        d->input_dev = NULL;
 290        d->rc_dev = dev;
 291
 292        if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
 293                return 0;
 294
 295        /* Polling mode - initialize a work queue for handling it */
 296        INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
 297
 298        rc_interval = d->props.rc.core.rc_interval;
 299
 300        info("schedule remote query interval to %d msecs.", rc_interval);
 301        schedule_delayed_work(&d->rc_query_work,
 302                              msecs_to_jiffies(rc_interval));
 303
 304        return 0;
 305}
 306
 307int dvb_usb_remote_init(struct dvb_usb_device *d)
 308{
 309        int err;
 310
 311        if (dvb_usb_disable_rc_polling)
 312                return 0;
 313
 314        if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query)
 315                d->props.rc.mode = DVB_RC_LEGACY;
 316        else if (d->props.rc.core.rc_codes)
 317                d->props.rc.mode = DVB_RC_CORE;
 318        else
 319                return 0;
 320
 321        usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
 322        strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 323
 324        /* Start the remote-control polling. */
 325        if (d->props.rc.legacy.rc_interval < 40)
 326                d->props.rc.legacy.rc_interval = 100; /* default */
 327
 328        if (d->props.rc.mode == DVB_RC_LEGACY)
 329                err = legacy_dvb_usb_remote_init(d);
 330        else
 331                err = rc_core_dvb_usb_remote_init(d);
 332        if (err)
 333                return err;
 334
 335        d->state |= DVB_USB_STATE_REMOTE;
 336
 337        return 0;
 338}
 339
 340int dvb_usb_remote_exit(struct dvb_usb_device *d)
 341{
 342        if (d->state & DVB_USB_STATE_REMOTE) {
 343                cancel_delayed_work_sync(&d->rc_query_work);
 344                if (d->props.rc.mode == DVB_RC_LEGACY)
 345                        input_unregister_device(d->input_dev);
 346                else
 347                        rc_unregister_device(d->rc_dev);
 348        }
 349        d->state &= ~DVB_USB_STATE_REMOTE;
 350        return 0;
 351}
 352
 353#define DVB_USB_RC_NEC_EMPTY           0x00
 354#define DVB_USB_RC_NEC_KEY_PRESSED     0x01
 355#define DVB_USB_RC_NEC_KEY_REPEATED    0x02
 356int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
 357                u8 keybuf[5], u32 *event, int *state)
 358{
 359        int i;
 360        struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
 361        *event = 0;
 362        *state = REMOTE_NO_KEY_PRESSED;
 363        switch (keybuf[0]) {
 364                case DVB_USB_RC_NEC_EMPTY:
 365                        break;
 366                case DVB_USB_RC_NEC_KEY_PRESSED:
 367                        if ((u8) ~keybuf[1] != keybuf[2] ||
 368                                (u8) ~keybuf[3] != keybuf[4]) {
 369                                deb_err("remote control checksum failed.\n");
 370                                break;
 371                        }
 372                        /* See if we can match the raw key code. */
 373                        for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
 374                                if (rc5_custom(&keymap[i]) == keybuf[1] &&
 375                                        rc5_data(&keymap[i]) == keybuf[3]) {
 376                                        *event = keymap[i].keycode;
 377                                        *state = REMOTE_KEY_PRESSED;
 378                                        return 0;
 379                                }
 380                        deb_err("key mapping failed - no appropriate key found in keymapping\n");
 381                        break;
 382                case DVB_USB_RC_NEC_KEY_REPEATED:
 383                        *state = REMOTE_KEY_REPEAT;
 384                        break;
 385                default:
 386                        deb_err("unknown type of remote status: %d\n",keybuf[0]);
 387                        break;
 388        }
 389        return 0;
 390}
 391EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
 392