-/*
-The MIT License (MIT)
-
-Copyright (c) 2016 Markus Zehnder
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-/* IR to USB keyboard optimized for KODI openELEC running on Asus Chromebox.
- * IR device: Logitech Harmony 880 with remote profile: 'Plex Player'
- * Testing with:
- * - SparkFun Pro Micro, ATmega32u4 (5V, 16MHz)
- * - MattairTech MT-DB-U4 (ATmega 32U4), 16MHZ 5V, CDC_HID
- *
- * Arduino IDE 1.6.7
- * HID Project 2.4.3
- * IRRemote 2.0.1
- *
- * Initial proof of concept:
- * - Kodi control works pretty well already :-)
- * - key repeat works
- * - boot protocol mode works (tested on a MacMini)
- *
- * ISSUES:
- * - Stability issues: program hangs within 0..60 minutes
- * (Watch dog reset didn't work either, according to Google this is most likely a bootloader bug)
- *
- * TODO:
- * - Stable operation: continue testing with an Arduino Leonardo
- * - Power off / sleep / wakeup
- * - CTRL+D / CTRL+W key combinations for boot selection on the Asus Chromebox
- * - Chromebox hardware modification to control power toggle switch with Arduino
- */
-
-#ifdef WATCHDOG
- #include <avr/wdt.h>
-#endif
-
-// hack for MattairTech MT-DB-U4 1.6.9-mt1
-#ifndef USB_EP_SIZE
- #define USB_EP_SIZE USB_DEFAULT_EP_SIZE
-#endif
-
-#include <HID-Project.h>
-#include <IRremote.h>
-
-//#define DEBUG_SKETCH
-#include "Debug.h"
-
-// --------CONSTANTS ---------------
-
-// pin assignments
-#define RECV_PIN 20
-
-struct CodeMap {
- unsigned long irCode;
- KeyboardKeycode keyCode;
-};
-
-// Logitech "Plex Player" device as KODI remote
-#define IR_CLEAR 0x77E12059
-#define IR_ENTER 0x77E14099
-#define IR_LEFT 0x77E11069
-#define IR_RIGHT 0x77E1E069
-#define IR_UP 0x77E1D069
-#define IR_DOWN 0x77E1B069
-#define IR_OK 0x77E12069
-#define IR_MENU 0x77E14069
-#define IR_EXIT 0x77E150D9
-#define IR_POWER_OFF 0x77E14059
-#define IR_GUIDE 0x77E1A0B9
-#define IR_INFO 0x77E1D099
-#define IR_STOP 0x77E1A0E9
-#define IR_PLAY 0x77E1C0E9
-#define IR_PAUSE 0x77E1C019
-#define IR_REC 0x77E130D9
-#define IR_REW 0x77E1D059
-#define IR_FWD 0x77E1B059
-#define IR_REPLAY 0x77E1D005
-#define IR_SKIP 0x77E1B005
-#define IR_PREV 0x77E1B099
-#define IR_PGDOWN 0x77E1B0F9
-#define IR_PGUP 0x77E1D0F9
-#define IR_BLUE 0x77E140F9
-#define IR_RED 0x77E110F9
-#define IR_GREEN 0x77E1E0F9
-#define IR_YELLOW 0x77E120F9
-#define IR_1 0x77E150E9
-#define IR_2 0x77E130E9
-#define IR_3 0x77E190E9
-#define IR_4 0x77E160E9
-#define IR_5 0x77E19019
-#define IR_6 0x77E16019
-#define IR_7 0x77E11099
-#define IR_8 0x77E1E099
-#define IR_9 0x77E11059
-#define IR_0 0x77E1E059
-#define IR_F1 0x77E190D9
-#define IR_F2 0x77E160D9
-#define IR_F3 0x77E1A0D9
-#define IR_F4 0x77E1C0D9
-#define IR_F5 0x77E11005
-#define IR_F6 0x77E1E005
-#define IR_F7 0x77E12005
-#define IR_F8 0x77E14005
-#define IR_MUTE 0x77E1A019
-#define IR_VOL_UP 0x77E15019
-#define IR_VOL_DOWN 0x77E13019
-#define IR_CH_UP 0x77E15079
-#define IR_CH_DOWN 0x77E13079
-#define IR_POWER_TOGGLE 0x77E1C0B9
-#define IR_SLEEP 0x77E14059
-#define IR_QUEUE 0x77E130B9
-#define IR_ASPECT 0x77E150B9
-
-// Key press time must be slightly higher then the repeat IR code duration.
-// My Logitech resends the first repeat after 40ms and afterwards every 110ms
-const int KEY_PRESS_TIME = 150;
-
-// IR code to key mapping
-// Kodi keyboard controls: http://kodi.wiki/view/Keyboard_controls
-const CodeMap irToKeyMap[] = {
- {IR_LEFT , KEY_LEFT_ARROW},
- {IR_RIGHT , KEY_RIGHT_ARROW},
- {IR_UP , HID_KEYBOARD_UPARROW},
- {IR_DOWN , KEY_DOWN_ARROW},
- {IR_OK , KEY_RETURN},
- {IR_ENTER , KEY_TAB}, // Fullscreen playback
- {IR_MENU , KEY_C},
- {IR_EXIT , KEY_ESC},
- {IR_F8 , KEY_BACKSPACE},
- {IR_GUIDE , KEY_E},
- {IR_INFO , KEY_I},
- {IR_STOP , KEY_X},
- {IR_PLAY , KEY_P},
- {IR_PAUSE , KEY_SPACE},
- {IR_REC , KEY_B},
- {IR_REW , KEY_R},
- {IR_FWD , KEY_F},
- {IR_PREV , KEY_QUOTE}, // FIXME doesn't seem to work with non-us keyboard layout
- {IR_SKIP , KEY_PERIOD},
- {IR_REPLAY, KEY_COMMA},
- {IR_PGDOWN, KEY_PAGE_DOWN},
- {IR_PGUP , KEY_PAGE_UP},
- {IR_BLUE , KEY_T}, // toggle subtitles
- {IR_RED , KEY_W}, // Marked as watched / unwatched
- {IR_GREEN , KEY_S}, // Shutdown menu
- {IR_YELLOW, KEY_DELETE},
- {IR_1 , KEY_1},
- {IR_2 , KEY_2},
- {IR_3 , KEY_3},
- {IR_4 , KEY_4},
- {IR_5 , KEY_5},
- {IR_6 , KEY_6},
- {IR_7 , KEY_7},
- {IR_8 , KEY_8},
- {IR_9 , KEY_9},
- {IR_0 , KEY_0},
-
-// TODO:
-// CTRL + D -> boot ChromeOS
-// CTRL + W -> boot openELEC
-};
-
-const int IR_KEY_MAP_SIZE = sizeof(irToKeyMap) / sizeof(CodeMap);
-
-//------------ VARIABLES ---------------------
-
-IRrecv irrecv(RECV_PIN);
-decode_results results;
-
-unsigned long lastIRValue = 0; // previously received IR code value
-unsigned long timeKeyDown = 0; // time of key press initiation
-
-//========================================
-
-void setup() {
- // open debug console
- #ifndef DEBUG
- Serial.begin(115200); // afaik the baudrate is ignored on a 32u4
- #endif
- DEBUG_PRINTLN("Chromebox_IR_USB_Keyboard");
-
- // initialize control over the keyboard:
- BootKeyboard.begin();
-
- // Start the receiver
- irrecv.enableIRIn();
-
-#ifdef WATCHDOG
- // enable watch dog
- // maybe this solves the frequent hangs on the Pro Micro...
- wdt_enable(WDTO_1S);
-#endif
-}
-
-//========================================
-
-void loop() {
-#ifdef WATCHDOG
- //Test if watchdog interrupt enabled
- // http://forum.arduino.cc/index.php?topic=295345.msg2628807#msg2628807
- if (WDTCSR & (1<<WDIE)) {
- //Prolong wtachdog timer
- wdt_reset();
- }
- //No interrupt enabled - Test if watchdog reset enabled
- else if (WDTCSR & (1<<WDE)) {
- //Bootloader about to reset - do not prolong watchdog
- }
- //It has ben disabled - Enable and prolong
- else {
- //Watchdog disabled - Enable again
- wdt_enable(WDTO_1S);
- }
-#endif
-
- if (irrecv.decode(&results) && results.decode_type == NEC) {
- // check if it's a NEC repeat code
- if (results.value == 0xFFFFFFFF) {
- results.value = lastIRValue;
- } else {
- lastIRValue = results.value;
- }
-
- if (results.value != lastIRValue) {
- // immediately release last key if a different IR value is received. We don't want multiple keys pressed at the same time.
- releaseKeys();
- }
-
- for (int i = 0; i < IR_KEY_MAP_SIZE; i++) {
- if (irToKeyMap[i].irCode == results.value) {
- // only press key if not yet pressed
- if (timeKeyDown == 0) {
- KeyboardKeycode keyCode = irToKeyMap[i].keyCode;
- DEBUG_PRINT(millis()); DEBUG_PRINT(" Press key: 0x"); DEBUG_PRINTLN(keyCode, HEX);
- BootKeyboard.press(keyCode);
- }
- timeKeyDown = millis();
- break;
- }
- }
-
- DEBUG_PRINT(millis()); DEBUG_PRINT(" IR: 0x"); DEBUG_PRINTLN(results.value, HEX);
-
- irrecv.resume(); // restarts decoding state machine
- } else {
- // check if it's time to release a previously pressed key
- if (timeKeyDown > 0 && (millis() - timeKeyDown >= KEY_PRESS_TIME)) {
- releaseKeys();
- }
- }
-}
-
-//========================================
-
-void releaseKeys() {
- timeKeyDown = 0;
- BootKeyboard.releaseAll();
- DEBUG_PRINT(millis()); DEBUG_PRINTLN(" Release keys");
-}
-
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 Markus Zehnder
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/* IR to USB keyboard optimized for KODI openELEC running on Asus Chromebox.
+ * IR device: Logitech Harmony 880 with remote profile: 'Panasonic TV TX-43CXW754'
+ *
+ * Initial proof of concept.
+ *
+ * Testing with:
+ * - SparkFun Pro Micro, ATmega32u4 (5V, 16MHz)
+ * - Arduino IDE 1.6.7
+ * - HID Project 2.4.3
+ * - IRLremote 1.7.4
+ *
+ * ISSUES:
+ * - Most promising branch yet :)
+ * - IRLremote doesn't work with Logitech Plex Remote profile. Now (ab)using Panasonic TV TX-43CXW754 device template.
+ * - Watch dog reset doesn't work, according to Google this is most likely an Arduino bootloader bug.
+ */
+// --------GLOBAL FLAGS ---------------
+// enable debugging output over usb
+#define DEBUG_SKETCH
+//#define WATCHDOG
+
+// hack for MattairTech MT-DB-U4 1.6.9-mt1
+#ifndef USB_EP_SIZE
+ #define USB_EP_SIZE USB_DEFAULT_EP_SIZE
+#endif
+
+// --------INCLUDES ---------------
+
+#ifdef WATCHDOG
+ #include <avr/wdt.h>
+#endif
+#include <HID-Project.h>
+#include <IRLremote.h>
+#include "Debug.h"
+// either include Panasonic or Sony definitions
+#include "Panasonic.h"
+//#include "Sony.h"
+
+// --------CONSTANTS ---------------
+
+// pin assignments
+#define RECV_PIN 7
+
+struct CodeMap {
+ uint32_t irCommand;
+ KeyboardKeycode keyCode;
+};
+
+// Key press time must be slightly higher then the repeat IR code duration.
+// My Logitech resends the first repeat after 40ms and afterwards every 110ms
+const int KEY_PRESS_TIME = 150;
+
+// TODO not sure yet if a loop delay is required. With the IRRemote library it increased realibility...
+const int LOOP_DELAY = KEY_PRESS_TIME / 3;
+
+// IR code to key mapping
+// Kodi keyboard controls: http://kodi.wiki/view/Keyboard_controls
+const CodeMap irToKeyMap[] = {
+ {REMOTE_LEFT , KEY_LEFT_ARROW},
+ {REMOTE_RIGHT , KEY_RIGHT_ARROW},
+ {REMOTE_UP , KEY_UP_ARROW},
+ {REMOTE_DOWN , KEY_DOWN_ARROW},
+ {REMOTE_OK , KEY_RETURN},
+ {REMOTE_ENTER , KEY_TAB}, // Fullscreen playback
+ {REMOTE_MENU , KEY_C},
+ {REMOTE_BACK , KEY_BACKSPACE},
+ {REMOTE_EXIT , KEY_ESC},
+ {REMOTE_GUIDE , KEY_E},
+ {REMOTE_INFO , KEY_I},
+ {REMOTE_STOP , KEY_X},
+ {REMOTE_PLAY , KEY_P},
+ {REMOTE_PAUSE , KEY_SPACE},
+ {REMOTE_REC , KEY_B},
+ {REMOTE_REW , KEY_R},
+ {REMOTE_FWD , KEY_F},
+ {REMOTE_PREV , KEY_QUOTE}, // FIXME doesn't seem to work with non-us keyboard layout
+ {REMOTE_SKIP , KEY_PERIOD},
+ {REMOTE_REPLAY, KEY_COMMA},
+ {REMOTE_BLUE , KEY_T}, // toggle subtitles
+ {REMOTE_RED , KEY_W}, // Marked as watched / unwatched
+ {REMOTE_GREEN , KEY_S}, // Shutdown menu
+ {REMOTE_YELLOW, KEY_DELETE},
+ {REMOTE_1 , KEY_1},
+ {REMOTE_2 , KEY_2},
+ {REMOTE_3 , KEY_3},
+ {REMOTE_4 , KEY_4},
+ {REMOTE_5 , KEY_5},
+ {REMOTE_6 , KEY_6},
+ {REMOTE_7 , KEY_7},
+ {REMOTE_8 , KEY_8},
+ {REMOTE_9 , KEY_9},
+ {REMOTE_0 , KEY_0},
+
+// TODO:
+// CTRL + D -> boot ChromeOS
+// CTRL + W -> boot openELEC
+};
+
+const int IR_KEY_MAP_SIZE = sizeof(irToKeyMap) / sizeof(CodeMap);
+
+//------------ VARIABLES ---------------------
+
+unsigned long lastIRValue = 0; // previously received IR code value
+unsigned long timeKeyDown = 0; // time of key press initiation
+
+// temporary variables to save latest IR input
+uint8_t IRProtocol = 0;
+uint16_t IRAddress = 0;
+uint32_t IRCommand = 0;
+
+//========================================
+
+void setup() {
+ // open debug console
+ #ifdef DEBUG_SKETCH
+ delay(3000);
+ Serial.begin(115200); // afaik the baudrate is ignored on a 32u4
+ #endif
+ DEBUG_PRINTLN("Chromebox_REMOTE_USB_Keyboard");
+
+ // initialize control over the keyboard:
+ BootKeyboard.begin();
+
+ // Start the receiver
+ attachInterrupt(digitalPinToInterrupt(RECV_PIN), IRLinterrupt<irType>, CHANGE);
+
+ #ifdef WATCHDOG
+ // enable watch dog
+ wdt_enable(WDTO_1S);
+ #endif
+}
+
+//========================================
+
+void loop() {
+#ifdef WATCHDOG
+ //Test if watchdog interrupt enabled
+ // http://forum.arduino.cc/index.php?topic=295345.msg2628807#msg2628807
+ if (WDTCSR & (1<<WDIE)) {
+ //Prolong wtachdog timer
+ wdt_reset();
+ }
+ //No interrupt enabled - Test if watchdog reset enabled
+ else if (WDTCSR & (1<<WDE)) {
+ //Bootloader about to reset - do not prolong watchdog
+ }
+ //It has ben disabled - Enable and prolong
+ else {
+ //Watchdog disabled - Enable again
+ wdt_enable(WDTO_1S);
+ }
+#endif
+
+ // temporary disable interrupts and print newest input
+ // TODO read up on interrup handling
+ uint8_t oldSREG = SREG;
+ cli();
+
+ if (IRProtocol) {
+ DEBUG_PRINT(IRProtocol);DEBUG_PRINT("/0x");DEBUG_PRINT(IRAddress, HEX);DEBUG_PRINT("/0x");DEBUG_PRINTLN(IRCommand, HEX);
+
+ if (IRProtocol == irType) {
+ // check if it's a NEC repeat code
+ if (IRCommand == 0xFFFF) {
+ IRCommand = lastIRValue;
+ } else {
+ lastIRValue = IRCommand;
+ }
+
+ if (IRCommand != lastIRValue) {
+ // immediately release last key if a different IR value is received. We don't want multiple keys pressed at the same time.
+ releaseKeys();
+ }
+
+ for (int i = 0; i < IR_KEY_MAP_SIZE; i++) {
+ if (irToKeyMap[i].irCommand == IRCommand) { // irToKeyMap[i].irAddress == IRAddress &&
+ // only press key if not yet pressed
+ if (timeKeyDown == 0) {
+ KeyboardKeycode keyCode = irToKeyMap[i].keyCode;
+ DEBUG_PRINT(millis()); DEBUG_PRINT(" Press key: 0x"); DEBUG_PRINTLN(keyCode, HEX);
+ BootKeyboard.press(keyCode);
+ }
+ timeKeyDown = millis();
+ break;
+ }
+ }
+ }
+
+ } else {
+ // check if it's time to release a previously pressed key
+ if (timeKeyDown > 0 && (millis() - timeKeyDown >= KEY_PRESS_TIME)) {
+ releaseKeys();
+ }
+ }
+
+ IRProtocol = 0;
+ SREG = oldSREG;
+
+ sei();
+
+ // TODO required?
+ delay(LOOP_DELAY);
+}
+
+//========================================
+
+void releaseKeys() {
+ timeKeyDown = 0;
+ BootKeyboard.releaseAll();
+ DEBUG_PRINT(millis()); DEBUG_PRINTLN(" Release keys");
+}
+
+//========================================
+
+// IR decoding callback: update the values to the newest valid input
+void IREvent(uint8_t protocol, uint16_t address, uint32_t command) {
+ // called when directly received a valid IR signal.
+ // do not use Serial inside, it can crash your program!
+
+ // dont update value if not yet processed
+ if (!IRProtocol) {
+ IRProtocol = protocol;
+ IRAddress = address;
+ IRCommand = command;
+ }
+}
--- /dev/null
+
+const IRType irType = IR_PANASONIC;
+
+// address: 0x2002
+#define IR_PANA_1 0x90100080
+#define IR_PANA_2 0x91110080
+#define IR_PANA_3 0x92120080
+#define IR_PANA_4 0x93130080
+#define IR_PANA_5 0x94140080
+#define IR_PANA_6 0x95150080
+#define IR_PANA_7 0x96160080
+#define IR_PANA_8 0x97170080
+#define IR_PANA_9 0x98180080
+#define IR_PANA_0 0x99190080
+#define IR_PANA_CH_UP 0xB4340080
+#define IR_PANA_CH_DOWN 0xB5350080
+#define IR_PANA_VOL_UP 0xA0200080
+#define IR_PANA_VOL_DOWN 0xA1210080
+#define IR_PANA_MUTE 0xB2320080
+#define IR_PANA_POWER_TOGGLE 0xBD3D0080
+#define IR_PANA_STOP 0x4BC20980
+#define IR_PANA_PAUSE 0x48C10980
+#define IR_PANA_PLAY 0x49C00980
+#define IR_PANA_REW 0x4DC40980
+#define IR_PANA_FWD 0x4AC30980
+#define IR_PANA_REC 0x4CC50980
+#define IR_PANA_BACK 0x54D40080
+#define IR_PANA_BLUE 0xF3730080
+#define IR_PANA_RED 0xF0700080
+#define IR_PANA_GREEN 0xF1710080
+#define IR_PANA_YELLOW 0xF2720080
+#define IR_PANA_SUBTITLE 0x84050180
+#define IR_PANA_POWER_ON 0xBE3E0080
+#define IR_PANA_POWER_OFF 0xBD3D0080
+#define IR_PANA_RIGHT 0xCF4F0080
+#define IR_PANA_LEFT 0xCE4E0080
+#define IR_PANA_INFO 0xB9390080
+#define IR_PANA_PREV 0xB7370080
+#define IR_PANA_REPLAY 0x55DC0980
+#define IR_PANA_SKIP 0x54DD0980
+#define IR_PANA_ASPECT 0x5ADE0480
+#define IR_PANA_GUIDE 0xE870980
+#define IR_PANA_MENU 0xD2520080
+#define IR_PANA_EXIT 0x139A0980
+#define IR_PANA_HOME 0x1C950980
+#define IR_PANA_OK 0xC9490080
+#define IR_PANA_UP 0xCA4A0080
+#define IR_PANA_DOWN 0xCB4B0080
+
+// Standard Logitech 880 buttons
+#define REMOTE_MUTE IR_PANA_MUTE
+#define REMOTE_VOL_UP IR_PANA_VOL_UP
+#define REMOTE_VOL_DOWN IR_PANA_VOL_DOWN
+#define REMOTE_PG_DOWN 0
+#define REMOTE_PG_UP 0
+#define REMOTE_CH_DOWN IR_PANA_CH_DOWN
+#define REMOTE_CH_UP IR_PANA_CH_UP
+#define REMOTE_PREV IR_PANA_PREV
+#define REMOTE_UP IR_PANA_UP
+#define REMOTE_DOWN IR_PANA_DOWN
+#define REMOTE_LEFT IR_PANA_LEFT
+#define REMOTE_RIGHT IR_PANA_RIGHT
+#define REMOTE_OK IR_PANA_OK
+#define REMOTE_MENU IR_PANA_MENU
+#define REMOTE_EXIT IR_PANA_EXIT
+#define REMOTE_GUIDE IR_PANA_GUIDE
+#define REMOTE_INFO IR_PANA_INFO
+#define REMOTE_STOP IR_PANA_STOP
+#define REMOTE_REPLAY IR_PANA_REPLAY
+#define REMOTE_SKIP IR_PANA_SKIP
+#define REMOTE_PLAY IR_PANA_PLAY
+#define REMOTE_REC IR_PANA_REC
+#define REMOTE_REW IR_PANA_REW
+#define REMOTE_FWD IR_PANA_FWD
+#define REMOTE_PAUSE IR_PANA_PAUSE
+#define REMOTE_1 IR_PANA_1
+#define REMOTE_2 IR_PANA_2
+#define REMOTE_3 IR_PANA_3
+#define REMOTE_4 IR_PANA_4
+#define REMOTE_5 IR_PANA_5
+#define REMOTE_6 IR_PANA_6
+#define REMOTE_7 IR_PANA_7
+#define REMOTE_8 IR_PANA_8
+#define REMOTE_9 IR_PANA_9
+#define REMOTE_PLUS 0
+#define REMOTE_0 IR_PANA_0
+#define REMOTE_ENTER 0
+
+// Additional buttons
+#define REMOTE_POWER_TOGGLE IR_PANA_POWER_TOGGLE
+#define REMOTE_POWER_ON IR_PANA_POWER_ON
+#define REMOTE_POWER_OFF IR_PANA_POWER_OFF
+#define REMOTE_BACK IR_PANA_BACK
+#define REMOTE_RED IR_PANA_RED
+#define REMOTE_GREEN IR_PANA_GREEN
+#define REMOTE_YELLOW IR_PANA_YELLOW
+#define REMOTE_BLUE IR_PANA_BLUE
+#define REMOTE_SUBTITLE IR_PANA_SUBTITLE
+#define REMOTE_ASPECT IR_PANA_ASPECT
+
--- /dev/null
+const IRType irType = IR_SONY12;
+
+#define IR_SONY_1 0x0000
+#define IR_SONY_2 0x0001
+#define IR_SONY_3 0x0002
+#define IR_SONY_4 0x0003
+#define IR_SONY_5 0x0004
+#define IR_SONY_6 0x0005
+#define IR_SONY_7 0x0006
+#define IR_SONY_8 0x0007
+#define IR_SONY_9 0x0008
+#define IR_SONY_0 0x0009
+#define IR_SONY_CH_UP 0x0010
+#define IR_SONY_CH_DOWN 0x0011
+#define IR_SONY_VOL_UP 0x0012
+#define IR_SONY_VOL_DOWN 0x0013
+#define IR_SONY_MUTE 0x0014
+#define IR_SONY_POWER_TOGGLE 0x0015
+#define IR_SONY_STOP 0x0018
+#define IR_SONY_PAUSE 0x0019
+#define IR_SONY_PLAY 0x001A
+#define IR_SONY_REW 0x001B
+#define IR_SONY_FWD 0x001C
+#define IR_SONY_REC 0x0020
+#define IR_SONY_BACK 0x0023
+#define IR_SONY_BLUE 0x0024
+#define IR_SONY_RED 0x0025
+#define IR_SONY_GREEN 0x0026
+#define IR_SONY_YELLOW 0x0027
+#define IR_SONY_SUBTITLE 0x0028
+#define IR_SONY_POWER_ON 0x002E
+#define IR_SONY_POWER_OFF 0x002F
+#define IR_SONY_RIGHT 0x0033
+#define IR_SONY_LEFT 0x0034
+#define IR_SONY_INFO 0x003A
+#define IR_SONY_PREV 0x003B
+#define IR_SONY_REPLAY 0x003C
+#define IR_SONY_SKIP 0x003D
+#define IR_SONY_GUIDE 0x005B
+#define IR_SONY_SYNC_MENU 0x0058
+#define IR_SONY_MENU 0x0060
+#define IR_SONY_EXIT 0x0063
+#define IR_SONY_OK 0x0065
+#define IR_SONY_UP 0x0074
+#define IR_SONY_DOWN 0x0075
+
+// Standard Logitech 880 buttons
+#define REMOTE_MUTE IR_SONY_MUTE
+#define REMOTE_VOL_UP IR_SONY_VOL_UP
+#define REMOTE_VOL_DOWN IR_SONY_VOL_DOWN
+#define REMOTE_PG_DOWN 0
+#define REMOTE_PG_UP 0
+#define REMOTE_CH_DOWN IR_SONY_CH_DOWN
+#define REMOTE_CH_UP IR_SONY_CH_UP
+#define REMOTE_PREV IR_SONY_PREV
+#define REMOTE_UP IR_SONY_UP
+#define REMOTE_DOWN IR_SONY_DOWN
+#define REMOTE_LEFT IR_SONY_LEFT
+#define REMOTE_RIGHT IR_SONY_RIGHT
+#define REMOTE_OK IR_SONY_OK
+#define REMOTE_MENU IR_SONY_MENU
+#define REMOTE_EXIT IR_SONY_EXIT
+#define REMOTE_GUIDE IR_SONY_GUIDE
+#define REMOTE_INFO IR_SONY_INFO
+#define REMOTE_STOP IR_SONY_STOP
+#define REMOTE_REPLAY IR_SONY_REPLAY
+#define REMOTE_SKIP IR_SONY_SKIP
+#define REMOTE_PLAY IR_SONY_PLAY
+#define REMOTE_REC IR_SONY_REC
+#define REMOTE_REW IR_SONY_REW
+#define REMOTE_FWD IR_SONY_FWD
+#define REMOTE_PAUSE IR_SONY_PAUSE
+#define REMOTE_1 IR_SONY_1
+#define REMOTE_2 IR_SONY_2
+#define REMOTE_3 IR_SONY_3
+#define REMOTE_4 IR_SONY_4
+#define REMOTE_5 IR_SONY_5
+#define REMOTE_6 IR_SONY_6
+#define REMOTE_7 IR_SONY_7
+#define REMOTE_8 IR_SONY_8
+#define REMOTE_9 IR_SONY_9
+#define REMOTE_PLUS 0
+#define REMOTE_0 IR_SONY_0
+#define REMOTE_ENTER IR_SONY_SYNC_MENU
+
+// Additional buttons
+#define REMOTE_POWER_TOGGLE IR_SONY_POWER_TOGGLE
+#define REMOTE_POWER_ON IR_SONY_POWER_ON
+#define REMOTE_POWER_OFF IR_SONY_POWER_OFF
+#define REMOTE_BACK IR_SONY_BACK
+#define REMOTE_RED IR_SONY_RED
+#define REMOTE_GREEN IR_SONY_GREEN
+#define REMOTE_YELLOW IR_SONY_YELLOW
+#define REMOTE_BLUE IR_SONY_BLUE
+#define REMOTE_SUBTITLE IR_SONY_SUBTITLE
+#define REMOTE_ASPECT 0
+