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                        input_event(d->input_dev, EV_KEY, event, 1);
 135                        input_sync(d->input_dev);
 136                        input_event(d->input_dev, EV_KEY, d->last_event, 0);
 137                        input_sync(d->input_dev);
 138                        break;
 139                case REMOTE_KEY_REPEAT:
 140                        deb_rc("key repeated\n");
 141                        input_event(d->input_dev, EV_KEY, event, 1);
 142                        input_sync(d->input_dev);
 143                        input_event(d->input_dev, EV_KEY, d->last_event, 0);
 144                        input_sync(d->input_dev);
 145                        break;
 146                default:
 147                        break;
 148        }
 149
 150/* improved repeat handling ???
 151        switch (state) {
 152                case REMOTE_NO_KEY_PRESSED:
 153                        deb_rc("NO KEY PRESSED\n");
 154                        if (d->last_state != REMOTE_NO_KEY_PRESSED) {
 155                                deb_rc("releasing event %d\n",d->last_event);
 156                                input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
 157                                input_sync(d->rc_input_dev);
 158                        }
 159                        d->last_state = REMOTE_NO_KEY_PRESSED;
 160                        d->last_event = 0;
 161                        break;
 162                case REMOTE_KEY_PRESSED:
 163                        deb_rc("KEY PRESSED\n");
 164                        deb_rc("pressing event %d\n",event);
 165
 166                        input_event(d->rc_input_dev, EV_KEY, event, 1);
 167                        input_sync(d->rc_input_dev);
 168
 169                        d->last_event = event;
 170                        d->last_state = REMOTE_KEY_PRESSED;
 171                        break;
 172                case REMOTE_KEY_REPEAT:
 173                        deb_rc("KEY_REPEAT\n");
 174                        if (d->last_state != REMOTE_NO_KEY_PRESSED) {
 175                                deb_rc("repeating event %d\n",d->last_event);
 176                                input_event(d->rc_input_dev, EV_KEY, d->last_event, 2);
 177                                input_sync(d->rc_input_dev);
 178                                d->last_state = REMOTE_KEY_REPEAT;
 179                        }
 180                default:
 181                        break;
 182        }
 183*/
 184
 185schedule:
 186        schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
 187}
 188
 189static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d)
 190{
 191        int i, err, rc_interval;
 192        struct input_dev *input_dev;
 193
 194        input_dev = input_allocate_device();
 195        if (!input_dev)
 196                return -ENOMEM;
 197
 198        input_dev->evbit[0] = BIT_MASK(EV_KEY);
 199        input_dev->name = "IR-receiver inside an USB DVB receiver";
 200        input_dev->phys = d->rc_phys;
 201        usb_to_input_id(d->udev, &input_dev->id);
 202        input_dev->dev.parent = &d->udev->dev;
 203        d->input_dev = input_dev;
 204        d->rc_dev = NULL;
 205
 206        input_dev->getkeycode = legacy_dvb_usb_getkeycode;
 207        input_dev->setkeycode = legacy_dvb_usb_setkeycode;
 208
 209        /* set the bits for the keys */
 210        deb_rc("key map size: %d\n", d->props.rc.legacy.rc_map_size);
 211        for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
 212                deb_rc("setting bit for event %d item %d\n",
 213                        d->props.rc.legacy.rc_map_table[i].keycode, i);
 214                set_bit(d->props.rc.legacy.rc_map_table[i].keycode, input_dev->keybit);
 215        }
 216
 217        /* setting these two values to non-zero, we have to manage key repeats */
 218        input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval;
 219        input_dev->rep[REP_DELAY]  = d->props.rc.legacy.rc_interval + 150;
 220
 221        input_set_drvdata(input_dev, d);
 222
 223        err = input_register_device(input_dev);
 224        if (err)
 225                input_free_device(input_dev);
 226
 227        rc_interval = d->props.rc.legacy.rc_interval;
 228
 229        INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control);
 230
 231        info("schedule remote query interval to %d msecs.", rc_interval);
 232        schedule_delayed_work(&d->rc_query_work,
 233                              msecs_to_jiffies(rc_interval));
 234
 235        d->state |= DVB_USB_STATE_REMOTE;
 236
 237        return err;
 238}
 239
 240/* Remote-control poll function - called every dib->rc_query_interval ms to see
 241 * whether the remote control has received anything.
 242 *
 243 * TODO: Fix the repeat rate of the input device.
 244 */
 245static void dvb_usb_read_remote_control(struct work_struct *work)
 246{
 247        struct dvb_usb_device *d =
 248                container_of(work, struct dvb_usb_device, rc_query_work.work);
 249        int err;
 250
 251        /* TODO: need a lock here.  We can simply skip checking for the remote control
 252           if we're busy. */
 253
 254        /* when the parameter has been set to 1 via sysfs while the
 255         * driver was running, or when bulk mode is enabled after IR init
 256         */
 257        if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode)
 258                return;
 259
 260        err = d->props.rc.core.rc_query(d);
 261        if (err)
 262                err("error %d while querying for an remote control event.", err);
 263
 264        schedule_delayed_work(&d->rc_query_work,
 265                              msecs_to_jiffies(d->props.rc.core.rc_interval));
 266}
 267
 268static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d)
 269{
 270        int err, rc_interval;
 271        struct rc_dev *dev;
 272
 273        dev = rc_allocate_device(d->props.rc.core.driver_type);
 274        if (!dev)
 275                return -ENOMEM;
 276
 277        dev->driver_name = d->props.rc.core.module_name;
 278        dev->map_name = d->props.rc.core.rc_codes;
 279        dev->change_protocol = d->props.rc.core.change_protocol;
 280        dev->allowed_protocols = d->props.rc.core.allowed_protos;
 281        usb_to_input_id(d->udev, &dev->input_id);
 282        dev->input_name = "IR-receiver inside an USB DVB receiver";
 283        dev->input_phys = d->rc_phys;
 284        dev->dev.parent = &d->udev->dev;
 285        dev->priv = d;
 286
 287        err = rc_register_device(dev);
 288        if (err < 0) {
 289                rc_free_device(dev);
 290                return err;
 291        }
 292
 293        d->input_dev = NULL;
 294        d->rc_dev = dev;
 295
 296        if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
 297                return 0;
 298
 299        /* Polling mode - initialize a work queue for handling it */
 300        INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
 301
 302        rc_interval = d->props.rc.core.rc_interval;
 303
 304        info("schedule remote query interval to %d msecs.", rc_interval);
 305        schedule_delayed_work(&d->rc_query_work,
 306                              msecs_to_jiffies(rc_interval));
 307
 308        return 0;
 309}
 310
 311int dvb_usb_remote_init(struct dvb_usb_device *d)
 312{
 313        int err;
 314
 315        if (dvb_usb_disable_rc_polling)
 316                return 0;
 317
 318        if (d->props.rc.legacy.rc_map_table && d->props.rc.legacy.rc_query)
 319                d->props.rc.mode = DVB_RC_LEGACY;
 320        else if (d->props.rc.core.rc_codes)
 321                d->props.rc.mode = DVB_RC_CORE;
 322        else
 323                return 0;
 324
 325        usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
 326        strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
 327
 328        /* Start the remote-control polling. */
 329        if (d->props.rc.legacy.rc_interval < 40)
 330                d->props.rc.legacy.rc_interval = 100; /* default */
 331
 332        if (d->props.rc.mode == DVB_RC_LEGACY)
 333                err = legacy_dvb_usb_remote_init(d);
 334        else
 335                err = rc_core_dvb_usb_remote_init(d);
 336        if (err)
 337                return err;
 338
 339        d->state |= DVB_USB_STATE_REMOTE;
 340
 341        return 0;
 342}
 343
 344int dvb_usb_remote_exit(struct dvb_usb_device *d)
 345{
 346        if (d->state & DVB_USB_STATE_REMOTE) {
 347                cancel_delayed_work_sync(&d->rc_query_work);
 348                if (d->props.rc.mode == DVB_RC_LEGACY)
 349                        input_unregister_device(d->input_dev);
 350                else
 351                        rc_unregister_device(d->rc_dev);
 352        }
 353        d->state &= ~DVB_USB_STATE_REMOTE;
 354        return 0;
 355}
 356
 357#define DVB_USB_RC_NEC_EMPTY           0x00
 358#define DVB_USB_RC_NEC_KEY_PRESSED     0x01
 359#define DVB_USB_RC_NEC_KEY_REPEATED    0x02
 360int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
 361                u8 keybuf[5], u32 *event, int *state)
 362{
 363        int i;
 364        struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
 365        *event = 0;
 366        *state = REMOTE_NO_KEY_PRESSED;
 367        switch (keybuf[0]) {
 368                case DVB_USB_RC_NEC_EMPTY:
 369                        break;
 370                case DVB_USB_RC_NEC_KEY_PRESSED:
 371                        if ((u8) ~keybuf[1] != keybuf[2] ||
 372                                (u8) ~keybuf[3] != keybuf[4]) {
 373                                deb_err("remote control checksum failed.\n");
 374                                break;
 375                        }
 376                        /* See if we can match the raw key code. */
 377                        for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
 378                                if (rc5_custom(&keymap[i]) == keybuf[1] &&
 379                                        rc5_data(&keymap[i]) == keybuf[3]) {
 380                                        *event = keymap[i].keycode;
 381                                        *state = REMOTE_KEY_PRESSED;
 382                                        return 0;
 383                                }
 384                        deb_err("key mapping failed - no appropriate key found in keymapping\n");
 385                        break;
 386                case DVB_USB_RC_NEC_KEY_REPEATED:
 387                        *state = REMOTE_KEY_REPEAT;
 388                        break;
 389                default:
 390                        deb_err("unknown type of remote status: %d\n",keybuf[0]);
 391                        break;
 392        }
 393        return 0;
 394}
 395EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
 396