linux/drivers/media/video/em28xx/em28xx-input.c
<<
>>
Prefs
   1/*
   2  handle em28xx IR remotes via linux kernel input layer.
   3
   4   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
   5                      Markus Rechberger <mrechberger@gmail.com>
   6                      Mauro Carvalho Chehab <mchehab@infradead.org>
   7                      Sascha Sommer <saschasommer@freenet.de>
   8
   9  This program is free software; you can redistribute it and/or modify
  10  it under the terms of the GNU General Public License as published by
  11  the Free Software Foundation; either version 2 of the License, or
  12  (at your option) any later version.
  13
  14  This program is distributed in the hope that it will be useful,
  15  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17  GNU General Public License for more details.
  18
  19  You should have received a copy of the GNU General Public License
  20  along with this program; if not, write to the Free Software
  21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22 */
  23
  24#include <linux/module.h>
  25#include <linux/init.h>
  26#include <linux/delay.h>
  27#include <linux/interrupt.h>
  28#include <linux/usb.h>
  29#include <linux/slab.h>
  30
  31#include "em28xx.h"
  32
  33#define EM28XX_SNAPSHOT_KEY KEY_CAMERA
  34#define EM28XX_SBUTTON_QUERY_INTERVAL 500
  35#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20
  36
  37static unsigned int ir_debug;
  38module_param(ir_debug, int, 0644);
  39MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
  40
  41#define MODULE_NAME "em28xx"
  42
  43#define i2cdprintk(fmt, arg...) \
  44        if (ir_debug) { \
  45                printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
  46        }
  47
  48#define dprintk(fmt, arg...) \
  49        if (ir_debug) { \
  50                printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
  51        }
  52
  53/**********************************************************
  54 Polling structure used by em28xx IR's
  55 **********************************************************/
  56
  57struct em28xx_ir_poll_result {
  58        unsigned int toggle_bit:1;
  59        unsigned int read_count:7;
  60        u8 rc_address;
  61        u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */
  62};
  63
  64struct em28xx_IR {
  65        struct em28xx *dev;
  66        struct rc_dev *rc;
  67        char name[32];
  68        char phys[32];
  69
  70        /* poll external decoder */
  71        int polling;
  72        struct delayed_work work;
  73        unsigned int full_code:1;
  74        unsigned int last_readcount;
  75
  76        int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
  77};
  78
  79/**********************************************************
  80 I2C IR based get keycodes - should be used with ir-kbd-i2c
  81 **********************************************************/
  82
  83static int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
  84{
  85        unsigned char b;
  86
  87        /* poll IR chip */
  88        if (1 != i2c_master_recv(ir->c, &b, 1)) {
  89                i2cdprintk("read error\n");
  90                return -EIO;
  91        }
  92
  93        /* it seems that 0xFE indicates that a button is still hold
  94           down, while 0xff indicates that no button is hold
  95           down. 0xfe sequences are sometimes interrupted by 0xFF */
  96
  97        i2cdprintk("key %02x\n", b);
  98
  99        if (b == 0xff)
 100                return 0;
 101
 102        if (b == 0xfe)
 103                /* keep old data */
 104                return 1;
 105
 106        *ir_key = b;
 107        *ir_raw = b;
 108        return 1;
 109}
 110
 111static int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 112{
 113        unsigned char buf[2];
 114        u16 code;
 115        int size;
 116
 117        /* poll IR chip */
 118        size = i2c_master_recv(ir->c, buf, sizeof(buf));
 119
 120        if (size != 2)
 121                return -EIO;
 122
 123        /* Does eliminate repeated parity code */
 124        if (buf[1] == 0xff)
 125                return 0;
 126
 127        ir->old = buf[1];
 128
 129        /*
 130         * Rearranges bits to the right order.
 131         * The bit order were determined experimentally by using
 132         * The original Hauppauge Grey IR and another RC5 that uses addr=0x08
 133         * The RC5 code has 14 bits, but we've experimentally determined
 134         * the meaning for only 11 bits.
 135         * So, the code translation is not complete. Yet, it is enough to
 136         * work with the provided RC5 IR.
 137         */
 138        code =
 139                 ((buf[0] & 0x01) ? 0x0020 : 0) | /*            0010 0000 */
 140                 ((buf[0] & 0x02) ? 0x0010 : 0) | /*            0001 0000 */
 141                 ((buf[0] & 0x04) ? 0x0008 : 0) | /*            0000 1000 */
 142                 ((buf[0] & 0x08) ? 0x0004 : 0) | /*            0000 0100 */
 143                 ((buf[0] & 0x10) ? 0x0002 : 0) | /*            0000 0010 */
 144                 ((buf[0] & 0x20) ? 0x0001 : 0) | /*            0000 0001 */
 145                 ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000            */
 146                 ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000            */
 147                 ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100            */
 148                 ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010            */
 149                 ((buf[1] & 0x80) ? 0x0100 : 0);  /* 0000 0001            */
 150
 151        i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n",
 152                        code, buf[1], buf[0]);
 153
 154        /* return key */
 155        *ir_key = code;
 156        *ir_raw = code;
 157        return 1;
 158}
 159
 160static int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
 161                                     u32 *ir_raw)
 162{
 163        unsigned char buf[3];
 164
 165        /* poll IR chip */
 166
 167        if (3 != i2c_master_recv(ir->c, buf, 3)) {
 168                i2cdprintk("read error\n");
 169                return -EIO;
 170        }
 171
 172        i2cdprintk("key %02x\n", buf[2]&0x3f);
 173        if (buf[0] != 0x00)
 174                return 0;
 175
 176        *ir_key = buf[2]&0x3f;
 177        *ir_raw = buf[2]&0x3f;
 178
 179        return 1;
 180}
 181
 182static int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key,
 183                                        u32 *ir_raw)
 184{
 185        unsigned char subaddr, keydetect, key;
 186
 187        struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, .buf = &subaddr, .len = 1},
 188
 189                                { .addr = ir->c->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} };
 190
 191        subaddr = 0x10;
 192        if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
 193                i2cdprintk("read error\n");
 194                return -EIO;
 195        }
 196        if (keydetect == 0x00)
 197                return 0;
 198
 199        subaddr = 0x00;
 200        msg[1].buf = &key;
 201        if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
 202                i2cdprintk("read error\n");
 203        return -EIO;
 204        }
 205        if (key == 0x00)
 206                return 0;
 207
 208        *ir_key = key;
 209        *ir_raw = key;
 210        return 1;
 211}
 212
 213/**********************************************************
 214 Poll based get keycode functions
 215 **********************************************************/
 216
 217/* This is for the em2860/em2880 */
 218static int default_polling_getkey(struct em28xx_IR *ir,
 219                                  struct em28xx_ir_poll_result *poll_result)
 220{
 221        struct em28xx *dev = ir->dev;
 222        int rc;
 223        u8 msg[3] = { 0, 0, 0 };
 224
 225        /* Read key toggle, brand, and key code
 226           on registers 0x45, 0x46 and 0x47
 227         */
 228        rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR,
 229                                          msg, sizeof(msg));
 230        if (rc < 0)
 231                return rc;
 232
 233        /* Infrared toggle (Reg 0x45[7]) */
 234        poll_result->toggle_bit = (msg[0] >> 7);
 235
 236        /* Infrared read count (Reg 0x45[6:0] */
 237        poll_result->read_count = (msg[0] & 0x7f);
 238
 239        /* Remote Control Address (Reg 0x46) */
 240        poll_result->rc_address = msg[1];
 241
 242        /* Remote Control Data (Reg 0x47) */
 243        poll_result->rc_data[0] = msg[2];
 244
 245        return 0;
 246}
 247
 248static int em2874_polling_getkey(struct em28xx_IR *ir,
 249                                 struct em28xx_ir_poll_result *poll_result)
 250{
 251        struct em28xx *dev = ir->dev;
 252        int rc;
 253        u8 msg[5] = { 0, 0, 0, 0, 0 };
 254
 255        /* Read key toggle, brand, and key code
 256           on registers 0x51-55
 257         */
 258        rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR,
 259                                          msg, sizeof(msg));
 260        if (rc < 0)
 261                return rc;
 262
 263        /* Infrared toggle (Reg 0x51[7]) */
 264        poll_result->toggle_bit = (msg[0] >> 7);
 265
 266        /* Infrared read count (Reg 0x51[6:0] */
 267        poll_result->read_count = (msg[0] & 0x7f);
 268
 269        /* Remote Control Address (Reg 0x52) */
 270        poll_result->rc_address = msg[1];
 271
 272        /* Remote Control Data (Reg 0x53-55) */
 273        poll_result->rc_data[0] = msg[2];
 274        poll_result->rc_data[1] = msg[3];
 275        poll_result->rc_data[2] = msg[4];
 276
 277        return 0;
 278}
 279
 280/**********************************************************
 281 Polling code for em28xx
 282 **********************************************************/
 283
 284static void em28xx_ir_handle_key(struct em28xx_IR *ir)
 285{
 286        int result;
 287        struct em28xx_ir_poll_result poll_result;
 288
 289        /* read the registers containing the IR status */
 290        result = ir->get_key(ir, &poll_result);
 291        if (unlikely(result < 0)) {
 292                dprintk("ir->get_key() failed %d\n", result);
 293                return;
 294        }
 295
 296        if (unlikely(poll_result.read_count != ir->last_readcount)) {
 297                dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__,
 298                        poll_result.toggle_bit, poll_result.read_count,
 299                        poll_result.rc_address, poll_result.rc_data[0]);
 300                if (ir->full_code)
 301                        rc_keydown(ir->rc,
 302                                   poll_result.rc_address << 8 |
 303                                   poll_result.rc_data[0],
 304                                   poll_result.toggle_bit);
 305                else
 306                        rc_keydown(ir->rc,
 307                                   poll_result.rc_data[0],
 308                                   poll_result.toggle_bit);
 309
 310                if (ir->dev->chip_id == CHIP_ID_EM2874 ||
 311                    ir->dev->chip_id == CHIP_ID_EM2884)
 312                        /* The em2874 clears the readcount field every time the
 313                           register is read.  The em2860/2880 datasheet says that it
 314                           is supposed to clear the readcount, but it doesn't.  So with
 315                           the em2874, we are looking for a non-zero read count as
 316                           opposed to a readcount that is incrementing */
 317                        ir->last_readcount = 0;
 318                else
 319                        ir->last_readcount = poll_result.read_count;
 320        }
 321}
 322
 323static void em28xx_ir_work(struct work_struct *work)
 324{
 325        struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work.work);
 326
 327        em28xx_ir_handle_key(ir);
 328        schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
 329}
 330
 331static int em28xx_ir_start(struct rc_dev *rc)
 332{
 333        struct em28xx_IR *ir = rc->priv;
 334
 335        INIT_DELAYED_WORK(&ir->work, em28xx_ir_work);
 336        schedule_delayed_work(&ir->work, 0);
 337
 338        return 0;
 339}
 340
 341static void em28xx_ir_stop(struct rc_dev *rc)
 342{
 343        struct em28xx_IR *ir = rc->priv;
 344
 345        cancel_delayed_work_sync(&ir->work);
 346}
 347
 348static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
 349{
 350        int rc = 0;
 351        struct em28xx_IR *ir = rc_dev->priv;
 352        struct em28xx *dev = ir->dev;
 353        u8 ir_config = EM2874_IR_RC5;
 354
 355        /* Adjust xclk based o IR table for RC5/NEC tables */
 356
 357        if (rc_type == RC_TYPE_RC5) {
 358                dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
 359                ir->full_code = 1;
 360        } else if (rc_type == RC_TYPE_NEC) {
 361                dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
 362                ir_config = EM2874_IR_NEC;
 363                ir->full_code = 1;
 364        } else if (rc_type != RC_TYPE_UNKNOWN)
 365                rc = -EINVAL;
 366
 367        em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
 368                              EM28XX_XCLK_IR_RC5_MODE);
 369
 370        /* Setup the proper handler based on the chip */
 371        switch (dev->chip_id) {
 372        case CHIP_ID_EM2860:
 373        case CHIP_ID_EM2883:
 374                ir->get_key = default_polling_getkey;
 375                break;
 376        case CHIP_ID_EM2884:
 377        case CHIP_ID_EM2874:
 378        case CHIP_ID_EM28174:
 379                ir->get_key = em2874_polling_getkey;
 380                em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
 381                break;
 382        default:
 383                printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
 384                        dev->chip_id);
 385                rc = -EINVAL;
 386        }
 387
 388        return rc;
 389}
 390
 391static void em28xx_register_i2c_ir(struct em28xx *dev)
 392{
 393        /* Leadtek winfast tv USBII deluxe can find a non working IR-device */
 394        /* at address 0x18, so if that address is needed for another board in */
 395        /* the future, please put it after 0x1f. */
 396        struct i2c_board_info info;
 397        const unsigned short addr_list[] = {
 398                 0x1f, 0x30, 0x47, I2C_CLIENT_END
 399        };
 400
 401        memset(&info, 0, sizeof(struct i2c_board_info));
 402        memset(&dev->init_data, 0, sizeof(dev->init_data));
 403        strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
 404
 405        /* detect & configure */
 406        switch (dev->model) {
 407        case EM2800_BOARD_TERRATEC_CINERGY_200:
 408        case EM2820_BOARD_TERRATEC_CINERGY_250:
 409                dev->init_data.ir_codes = RC_MAP_EM_TERRATEC;
 410                dev->init_data.get_key = em28xx_get_key_terratec;
 411                dev->init_data.name = "i2c IR (EM28XX Terratec)";
 412                break;
 413        case EM2820_BOARD_PINNACLE_USB_2:
 414                dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY;
 415                dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
 416                dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
 417                break;
 418        case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
 419                dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
 420                dev->init_data.get_key = em28xx_get_key_em_haup;
 421                dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
 422                break;
 423        case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
 424                dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;
 425                dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe;
 426                dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)";
 427                break;
 428        }
 429
 430        if (dev->init_data.name)
 431                info.platform_data = &dev->init_data;
 432        i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL);
 433}
 434
 435/**********************************************************
 436 Handle Webcam snapshot button
 437 **********************************************************/
 438
 439static void em28xx_query_sbutton(struct work_struct *work)
 440{
 441        /* Poll the register and see if the button is depressed */
 442        struct em28xx *dev =
 443                container_of(work, struct em28xx, sbutton_query_work.work);
 444        int ret;
 445
 446        ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP);
 447
 448        if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) {
 449                u8 cleared;
 450                /* Button is depressed, clear the register */
 451                cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT;
 452                em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1);
 453
 454                /* Not emulate the keypress */
 455                input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
 456                                 1);
 457                /* Now unpress the key */
 458                input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
 459                                 0);
 460        }
 461
 462        /* Schedule next poll */
 463        schedule_delayed_work(&dev->sbutton_query_work,
 464                              msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
 465}
 466
 467static void em28xx_register_snapshot_button(struct em28xx *dev)
 468{
 469        struct input_dev *input_dev;
 470        int err;
 471
 472        em28xx_info("Registering snapshot button...\n");
 473        input_dev = input_allocate_device();
 474        if (!input_dev) {
 475                em28xx_errdev("input_allocate_device failed\n");
 476                return;
 477        }
 478
 479        usb_make_path(dev->udev, dev->snapshot_button_path,
 480                      sizeof(dev->snapshot_button_path));
 481        strlcat(dev->snapshot_button_path, "/sbutton",
 482                sizeof(dev->snapshot_button_path));
 483        INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton);
 484
 485        input_dev->name = "em28xx snapshot button";
 486        input_dev->phys = dev->snapshot_button_path;
 487        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
 488        set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit);
 489        input_dev->keycodesize = 0;
 490        input_dev->keycodemax = 0;
 491        input_dev->id.bustype = BUS_USB;
 492        input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
 493        input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
 494        input_dev->id.version = 1;
 495        input_dev->dev.parent = &dev->udev->dev;
 496
 497        err = input_register_device(input_dev);
 498        if (err) {
 499                em28xx_errdev("input_register_device failed\n");
 500                input_free_device(input_dev);
 501                return;
 502        }
 503
 504        dev->sbutton_input_dev = input_dev;
 505        schedule_delayed_work(&dev->sbutton_query_work,
 506                              msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
 507        return;
 508
 509}
 510
 511static void em28xx_deregister_snapshot_button(struct em28xx *dev)
 512{
 513        if (dev->sbutton_input_dev != NULL) {
 514                em28xx_info("Deregistering snapshot button\n");
 515                cancel_delayed_work_sync(&dev->sbutton_query_work);
 516                input_unregister_device(dev->sbutton_input_dev);
 517                dev->sbutton_input_dev = NULL;
 518        }
 519        return;
 520}
 521
 522static int em28xx_ir_init(struct em28xx *dev)
 523{
 524        struct em28xx_IR *ir;
 525        struct rc_dev *rc;
 526        int err = -ENOMEM;
 527
 528        if (dev->board.ir_codes == NULL) {
 529                /* No remote control support */
 530                em28xx_warn("Remote control support is not available for "
 531                                "this card.\n");
 532                return 0;
 533        }
 534
 535        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
 536        rc = rc_allocate_device();
 537        if (!ir || !rc)
 538                goto err_out_free;
 539
 540        /* record handles to ourself */
 541        ir->dev = dev;
 542        dev->ir = ir;
 543        ir->rc = rc;
 544
 545        /*
 546         * em2874 supports more protocols. For now, let's just announce
 547         * the two protocols that were already tested
 548         */
 549        rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
 550        rc->priv = ir;
 551        rc->change_protocol = em28xx_ir_change_protocol;
 552        rc->open = em28xx_ir_start;
 553        rc->close = em28xx_ir_stop;
 554
 555        /* By default, keep protocol field untouched */
 556        err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
 557        if (err)
 558                goto err_out_free;
 559
 560        /* This is how often we ask the chip for IR information */
 561        ir->polling = 100; /* ms */
 562
 563        /* init input device */
 564        snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)",
 565                                                dev->name);
 566
 567        usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
 568        strlcat(ir->phys, "/input0", sizeof(ir->phys));
 569
 570        rc->input_name = ir->name;
 571        rc->input_phys = ir->phys;
 572        rc->input_id.bustype = BUS_USB;
 573        rc->input_id.version = 1;
 574        rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
 575        rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
 576        rc->dev.parent = &dev->udev->dev;
 577        rc->map_name = dev->board.ir_codes;
 578        rc->driver_name = MODULE_NAME;
 579
 580        /* all done */
 581        err = rc_register_device(rc);
 582        if (err)
 583                goto err_out_stop;
 584
 585        em28xx_register_i2c_ir(dev);
 586
 587#if defined(CONFIG_MODULES) && defined(MODULE)
 588        if (dev->board.has_ir_i2c)
 589                request_module("ir-kbd-i2c");
 590#endif
 591        if (dev->board.has_snapshot_button)
 592                em28xx_register_snapshot_button(dev);
 593
 594        return 0;
 595
 596 err_out_stop:
 597        dev->ir = NULL;
 598 err_out_free:
 599        rc_free_device(rc);
 600        kfree(ir);
 601        return err;
 602}
 603
 604static int em28xx_ir_fini(struct em28xx *dev)
 605{
 606        struct em28xx_IR *ir = dev->ir;
 607
 608        em28xx_deregister_snapshot_button(dev);
 609
 610        /* skip detach on non attached boards */
 611        if (!ir)
 612                return 0;
 613
 614        if (ir->rc)
 615                rc_unregister_device(ir->rc);
 616
 617        /* done */
 618        kfree(ir);
 619        dev->ir = NULL;
 620        return 0;
 621}
 622
 623static struct em28xx_ops rc_ops = {
 624        .id   = EM28XX_RC,
 625        .name = "Em28xx Input Extension",
 626        .init = em28xx_ir_init,
 627        .fini = em28xx_ir_fini,
 628};
 629
 630static int __init em28xx_rc_register(void)
 631{
 632        return em28xx_register_extension(&rc_ops);
 633}
 634
 635static void __exit em28xx_rc_unregister(void)
 636{
 637        em28xx_unregister_extension(&rc_ops);
 638}
 639
 640MODULE_LICENSE("GPL");
 641MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
 642MODULE_DESCRIPTION("Em28xx Input driver");
 643
 644module_init(em28xx_rc_register);
 645module_exit(em28xx_rc_unregister);
 646