Unresponsive stock remote when eiri enabled with EIRI='ON'

I installed 1.05.04_B_WDLXTV.COM_WDLXTV_PLUS-0.5.2.2 and with EIRI='ON' discovered that some of the stock remote buttons do not work. A search of the forums shows that this is already known: http://forum.wdlxtv.com/viewtopic.php?f=38&t=5374
Some detective work shows that the last working kernel is 1.03.49 and the first kernel with this issue is 1.05.04, and the key difference between the two kernels for this issue lies in the implementation of irkernel.c:
As shown above, the root cause of the problem is that the implementation of CONFIG_IR_ALT_KEY allocates memory for the alt_key_table but fails to initialise it. The resulting uninitialised alt_key_table contains non-zero entries that can confuse the subsequent key processing code.
The obvious fix is to initialise the alt_key_table, but this will require either a kernel rebuild, or at the very least a rebuild of the kernel module irkernel.ko.
As a proof of concept, I took a different approach, which is to use the new IR_IOCSETALTKEYS ioctl to initialise the alt_key_table.
This approach is somewhat fragile since the size of the alt_key_table cannot be easily determined by the userspace code. The number 128 is not known outside the kernel module source. A slightly more robust approach would be to repeatedly probe the IR_IOCSETALTKEYS ioctl to initialise an ever increasing number of keys until failure, then use a binary search to narrow in on the exact number of keys.
The dmaosd application must use the same IR_IOCSETALTKEYS ioctl to either program or initialise the alt_key_table, so it might be regarded as a reasonable approach to solve the problem.
I think it would be good to deploy one of these fixes into the next version.
Some detective work shows that the last working kernel is 1.03.49 and the first kernel with this issue is 1.05.04, and the key difference between the two kernels for this issue lies in the implementation of irkernel.c:
- Code: Select all
diff -ur 1.03.49/bungalow_1.03.49_B/src/libs/3_8_0/linux-2.6.22.19/drivers/char/irkernel.c 1.05.04/bungalow_1.05.04_B_G/src/libs/3_8_0/linux-2.6.22.19/drivers/char/irkernel.c
--- 1.03.49/bungalow_1.03.49_B/src/libs/3_8_0/linux-2.6.22.19/drivers/char/irkernel.c 2010-10-28 20:20:16.000000000 -0700
+++ 1.05.04/bungalow_1.05.04_B_G/src/libs/3_8_0/linux-2.6.22.19/drivers/char/irkernel.c 2011-04-27 03:37:24.000000000 -0700
@@ -1,3 +1,8 @@
+#define CONFIG_IR_REPORT_RELEASE_KEY
+#ifdef CONFIG_IR_REPORT_RELEASE_KEY
+#define CONFIG_IR_ALT_KEY
+#endif // CONFIG_IR_REPORT_RELEASE_KEY
+
...
@@ -738,6 +882,9 @@
return(-ENOMEM);
#endif //CONFIG_IR_HOLD_KEY
}
+#ifdef CONFIG_IR_ALT_KEY
+ ir_priv.alt_key_table = kmalloc(max_keys * sizeof(unsigned long), GFP_KERNEL);
+#endif // CONFIG_IR_ALT_KEY
/* Register device, and may be allocating major# */
status = register_chrdev(major_num, ir_devname, &ir_fops);
As shown above, the root cause of the problem is that the implementation of CONFIG_IR_ALT_KEY allocates memory for the alt_key_table but fails to initialise it. The resulting uninitialised alt_key_table contains non-zero entries that can confuse the subsequent key processing code.
The obvious fix is to initialise the alt_key_table, but this will require either a kernel rebuild, or at the very least a rebuild of the kernel module irkernel.ko.
As a proof of concept, I took a different approach, which is to use the new IR_IOCSETALTKEYS ioctl to initialise the alt_key_table.
- Code: Select all
Index: eirid.c
===================================================================
--- eirid.c (revision 253)
+++ eirid.c (working copy)
@@ -43,18 +43,21 @@
#include <stdbool.h>
// WDTV IR sensor
-#define CONFIG_TANGO2 1
+#include <linux/autoconf.h>
#ifdef CONFIG_TANGO2
-#include <asm/tango2/tango2_gbus.h>
-#include <asm/tango2/hardware.h>
#include <asm/tango2/ir.h>
#elif defined(CONFIG_TANGO3)
-#include <asm/tango3/tango3_gbus.h>
-#include <asm/tango3/hardware.h>
#include <asm/tango3/ir.h>
#endif
+#ifndef IR_IOCSETRELEASEKEY
+#define IR_IOCSETRELEASEKEY _IO(IR_IOC_MAGIC, 6)
+#endif
+#ifndef IR_IOCSETALTKEYS
+#define IR_IOCSETALTKEYS _IO(IR_IOC_MAGIC, 7)
+#endif
+
#include "wdtv_codes.h"
#include "eiri_net.h"
#include "ir_io.h"
@@ -305,6 +308,17 @@
}
free(keys);
+ int numaltkeys = 128;
+ unsigned long *altkeys = malloc((numaltkeys + 1) * sizeof(*altkeys));
+ altkeys[0] = numaltkeys;
+ for (i = 0; i < numaltkeys; ++i)
+ altkeys[1+i] = 0;
+ if ((ret = ioctl(native_fd, IR_IOCSETALTKEYS, altkeys)) < 0) {
+ printf("IR_IOCSETALTKEYS error: %s\n", strerror(errno));
+ return 1;
+ }
+ free(altkeys);
+
int wait = atoi(argv[1]);
if ((ret = ioctl(native_fd, IR_IOCSETWAITPERIOD, wait)) < 0) {
printf("2 ioctl error: %s\n", strerror(errno));
This approach is somewhat fragile since the size of the alt_key_table cannot be easily determined by the userspace code. The number 128 is not known outside the kernel module source. A slightly more robust approach would be to repeatedly probe the IR_IOCSETALTKEYS ioctl to initialise an ever increasing number of keys until failure, then use a binary search to narrow in on the exact number of keys.
The dmaosd application must use the same IR_IOCSETALTKEYS ioctl to either program or initialise the alt_key_table, so it might be regarded as a reasonable approach to solve the problem.
I think it would be good to deploy one of these fixes into the next version.