@@ -28,6 +28,16 @@
#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
#define NECX_REPEAT_BITS 1
+static bool csum = true;
+module_param(csum, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(csum, "Whether or not to perform NEC chucksum checks "
+ "(default: true)");
+
+static bool pair;
+module_param(pair, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(pair, "Whether or not the Apple Pairing ID byte should "
+ "be evaluated for scancode lookups (default: false)");
+
enum nec_state {
STATE_INACTIVE,
STATE_HEADER_SPACE,
@@ -49,6 +59,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
struct nec_dec *data = &dev->raw->nec;
u32 scancode;
u8 address, not_address, command, not_command;
+ bool checksum = csum;
if (!(dev->raw->enabled_protocols & IR_TYPE_NEC))
return 0;
@@ -157,22 +168,37 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
command = bitrev8((data->bits >> 8) & 0xff);
not_command = bitrev8((data->bits >> 0) & 0xff);
- if ((command ^ not_command) != 0xff) {
+ if ((address == 0xee) && (not_address == 0x87)) {
+ IR_dprintk(1, "Apple remote detected, pair ID 0x%02x\n",
+ not_command);
+ checksum = false;
+ /* We have a default non-paired keymap using 0x00 */
+ if (!pair)
+ not_command = 0x00;
+ }
+
+ if (checksum && ((command ^ not_command) != 0xff)) {
IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
data->bits);
break;
}
- if ((address ^ not_address) != 0xff) {
- /* Extended NEC */
+ if (checksum && ((address ^ not_address) == 0xff)) {
+ /* Normal NEC */
+ scancode = address << 8 | command;
+ IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
+ } else if (!checksum) {
+ /* Extended NEC, no checksum */
+ scancode = address << 24 | not_address << 16 |
+ command << 8 | not_command;
+ IR_dprintk(1, "NEC (Ext, no csum) scancode 0x%08x\n",
+ scancode);
+ } else {
+ /* Extended NEC, standard */
scancode = address << 16 |
not_address << 8 |
command;
IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
- } else {
- /* Normal NEC */
- scancode = address << 8 | command;
- IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
}
if (data->is_nec_x)
@@ -53,6 +53,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-msi-tvanywhere.o \
rc-msi-tvanywhere-plus.o \
rc-nebula.o \
+ rc-nec-apple.o \
rc-nec-terratec-cinergy-xs.o \
rc-norwood.o \
rc-npgtech.o \
new file mode 100644
@@ -0,0 +1,51 @@
+/* rc-nec-apple.c - Keytable for Apple Remote Controls
+ *
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <media/rc-map.h>
+
+static struct ir_scancode nec_apple[] = {
+ { 0xee870002, KEY_MENU},
+ { 0xee870003, KEY_MENU},
+ { 0xee870004, KEY_PLAYPAUSE},
+ { 0xee870005, KEY_PLAYPAUSE},
+ { 0xee870006, KEY_FORWARD},
+ { 0xee870007, KEY_FORWARD},
+ { 0xee870008, KEY_BACK},
+ { 0xee870009, KEY_BACK},
+ { 0xee87000a, KEY_VOLUMEUP},
+ { 0xee87000b, KEY_VOLUMEUP},
+ { 0xee87000c, KEY_VOLUMEDOWN},
+ { 0xee87000d, KEY_VOLUMEDOWN},
+};
+
+static struct rc_keymap nec_apple_map = {
+ .map = {
+ .scan = nec_apple,
+ .size = ARRAY_SIZE(nec_apple),
+ .ir_type = IR_TYPE_NEC,
+ .name = RC_MAP_NEC_APPLE,
+ }
+};
+
+static int __init init_rc_map_nec_apple(void)
+{
+ return ir_register_map(&nec_apple_map);
+}
+
+static void __exit exit_rc_map_nec_apple(void)
+{
+ ir_unregister_map(&nec_apple_map);
+}
+
+module_init(init_rc_map_nec_apple)
+module_exit(exit_rc_map_nec_apple)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
@@ -110,6 +110,7 @@ void rc_map_init(void);
#define RC_MAP_MSI_TVANYWHERE_PLUS "rc-msi-tvanywhere-plus"
#define RC_MAP_MSI_TVANYWHERE "rc-msi-tvanywhere"
#define RC_MAP_NEBULA "rc-nebula"
+#define RC_MAP_NEC_APPLE "rc-nec-apple"
#define RC_MAP_NEC_TERRATEC_CINERGY_XS "rc-nec-terratec-cinergy-xs"
#define RC_MAP_NORWOOD "rc-norwood"
#define RC_MAP_NPGTECH "rc-npgtech"