Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * FireDTV driver (formerly known as FireSAT)
0004  *
0005  * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
0006  */
0007 
0008 #include <linux/bitops.h>
0009 #include <linux/input.h>
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012 #include <linux/string.h>
0013 #include <linux/types.h>
0014 #include <linux/workqueue.h>
0015 
0016 #include "firedtv.h"
0017 
0018 /* fixed table with older keycodes, geared towards MythTV */
0019 static const u16 oldtable[] = {
0020 
0021     /* code from device: 0x4501...0x451f */
0022 
0023     KEY_ESC,
0024     KEY_F9,
0025     KEY_1,
0026     KEY_2,
0027     KEY_3,
0028     KEY_4,
0029     KEY_5,
0030     KEY_6,
0031     KEY_7,
0032     KEY_8,
0033     KEY_9,
0034     KEY_I,
0035     KEY_0,
0036     KEY_ENTER,
0037     KEY_RED,
0038     KEY_UP,
0039     KEY_GREEN,
0040     KEY_F10,
0041     KEY_SPACE,
0042     KEY_F11,
0043     KEY_YELLOW,
0044     KEY_DOWN,
0045     KEY_BLUE,
0046     KEY_Z,
0047     KEY_P,
0048     KEY_PAGEDOWN,
0049     KEY_LEFT,
0050     KEY_W,
0051     KEY_RIGHT,
0052     KEY_P,
0053     KEY_M,
0054 
0055     /* code from device: 0x4540...0x4542 */
0056 
0057     KEY_R,
0058     KEY_V,
0059     KEY_C,
0060 };
0061 
0062 /* user-modifiable table for a remote as sold in 2008 */
0063 static const u16 keytable[] = {
0064 
0065     /* code from device: 0x0300...0x031f */
0066 
0067     [0x00] = KEY_POWER,
0068     [0x01] = KEY_SLEEP,
0069     [0x02] = KEY_STOP,
0070     [0x03] = KEY_OK,
0071     [0x04] = KEY_RIGHT,
0072     [0x05] = KEY_1,
0073     [0x06] = KEY_2,
0074     [0x07] = KEY_3,
0075     [0x08] = KEY_LEFT,
0076     [0x09] = KEY_4,
0077     [0x0a] = KEY_5,
0078     [0x0b] = KEY_6,
0079     [0x0c] = KEY_UP,
0080     [0x0d] = KEY_7,
0081     [0x0e] = KEY_8,
0082     [0x0f] = KEY_9,
0083     [0x10] = KEY_DOWN,
0084     [0x11] = KEY_TITLE, /* "OSD" - fixme */
0085     [0x12] = KEY_0,
0086     [0x13] = KEY_F20,   /* "16:9" - fixme */
0087     [0x14] = KEY_SCREEN,    /* "FULL" - fixme */
0088     [0x15] = KEY_MUTE,
0089     [0x16] = KEY_SUBTITLE,
0090     [0x17] = KEY_RECORD,
0091     [0x18] = KEY_TEXT,
0092     [0x19] = KEY_AUDIO,
0093     [0x1a] = KEY_RED,
0094     [0x1b] = KEY_PREVIOUS,
0095     [0x1c] = KEY_REWIND,
0096     [0x1d] = KEY_PLAYPAUSE,
0097     [0x1e] = KEY_NEXT,
0098     [0x1f] = KEY_VOLUMEUP,
0099 
0100     /* code from device: 0x0340...0x0354 */
0101 
0102     [0x20] = KEY_CHANNELUP,
0103     [0x21] = KEY_F21,   /* "4:3" - fixme */
0104     [0x22] = KEY_TV,
0105     [0x23] = KEY_DVD,
0106     [0x24] = KEY_VCR,
0107     [0x25] = KEY_AUX,
0108     [0x26] = KEY_GREEN,
0109     [0x27] = KEY_YELLOW,
0110     [0x28] = KEY_BLUE,
0111     [0x29] = KEY_CHANNEL,   /* "CH.LIST" */
0112     [0x2a] = KEY_VENDOR,    /* "CI" - fixme */
0113     [0x2b] = KEY_VOLUMEDOWN,
0114     [0x2c] = KEY_CHANNELDOWN,
0115     [0x2d] = KEY_LAST,
0116     [0x2e] = KEY_INFO,
0117     [0x2f] = KEY_FORWARD,
0118     [0x30] = KEY_LIST,
0119     [0x31] = KEY_FAVORITES,
0120     [0x32] = KEY_MENU,
0121     [0x33] = KEY_EPG,
0122     [0x34] = KEY_EXIT,
0123 };
0124 
0125 int fdtv_register_rc(struct firedtv *fdtv, struct device *dev)
0126 {
0127     struct input_dev *idev;
0128     int i, err;
0129 
0130     idev = input_allocate_device();
0131     if (!idev)
0132         return -ENOMEM;
0133 
0134     fdtv->remote_ctrl_dev = idev;
0135     idev->name = "FireDTV remote control";
0136     idev->dev.parent = dev;
0137     idev->evbit[0] = BIT_MASK(EV_KEY);
0138     idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL);
0139     if (!idev->keycode) {
0140         err = -ENOMEM;
0141         goto fail;
0142     }
0143     idev->keycodesize = sizeof(keytable[0]);
0144     idev->keycodemax = ARRAY_SIZE(keytable);
0145 
0146     for (i = 0; i < ARRAY_SIZE(keytable); i++)
0147         set_bit(keytable[i], idev->keybit);
0148 
0149     err = input_register_device(idev);
0150     if (err)
0151         goto fail_free_keymap;
0152 
0153     return 0;
0154 
0155 fail_free_keymap:
0156     kfree(idev->keycode);
0157 fail:
0158     input_free_device(idev);
0159     return err;
0160 }
0161 
0162 void fdtv_unregister_rc(struct firedtv *fdtv)
0163 {
0164     cancel_work_sync(&fdtv->remote_ctrl_work);
0165     kfree(fdtv->remote_ctrl_dev->keycode);
0166     input_unregister_device(fdtv->remote_ctrl_dev);
0167 }
0168 
0169 void fdtv_handle_rc(struct firedtv *fdtv, unsigned int code)
0170 {
0171     struct input_dev *idev = fdtv->remote_ctrl_dev;
0172     u16 *keycode = idev->keycode;
0173 
0174     if (code >= 0x0300 && code <= 0x031f)
0175         code = keycode[code - 0x0300];
0176     else if (code >= 0x0340 && code <= 0x0354)
0177         code = keycode[code - 0x0320];
0178     else if (code >= 0x4501 && code <= 0x451f)
0179         code = oldtable[code - 0x4501];
0180     else if (code >= 0x4540 && code <= 0x4542)
0181         code = oldtable[code - 0x4521];
0182     else {
0183         dev_dbg(fdtv->device,
0184             "invalid key code 0x%04x from remote control\n",
0185             code);
0186         return;
0187     }
0188 
0189     input_report_key(idev, code, 1);
0190     input_sync(idev);
0191     input_report_key(idev, code, 0);
0192     input_sync(idev);
0193 }