0001
0002
0003
0004
0005
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
0019 static const u16 oldtable[] = {
0020
0021
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
0056
0057 KEY_R,
0058 KEY_V,
0059 KEY_C,
0060 };
0061
0062
0063 static const u16 keytable[] = {
0064
0065
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,
0085 [0x12] = KEY_0,
0086 [0x13] = KEY_F20,
0087 [0x14] = KEY_SCREEN,
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
0101
0102 [0x20] = KEY_CHANNELUP,
0103 [0x21] = KEY_F21,
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,
0112 [0x2a] = KEY_VENDOR,
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 }