Advertisement
Guest User

atvclient_patched_silver_remote.cpp

a guest
Feb 24th, 2013
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 41.91 KB | None | 0 0
  1. /*
  2.  * atvclient: AppleTV Remote XBMC client
  3.  *
  4.  * Copyright (C) 2009 Christoph Cantillon <christoph.cantillon@roots.be>
  5.  * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk>
  6.  *
  7.  * This file is licensed under the terms of the GNU General Public License
  8.  * version 2.  This program is licensed "as is" without any warranty of any
  9.  * kind, whether express or implied.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <sys/socket.h>
  16. #include <unistd.h>
  17. #include <getopt.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <fcntl.h>
  21. #include <dirent.h>
  22. #include <usb.h>
  23. #include <sys/time.h>
  24.  
  25. #include "xbmcclient.h"
  26.  
  27. #define VENDOR_APPLE        0x05ac
  28. #define PRODUCT_IR      0x8241
  29.  
  30. #define LEDMODE_OFF     0
  31. #define LEDMODE_AMBER       1
  32. #define LEDMODE_AMBER_BLINK 2
  33. #define LEDMODE_WHITE       3
  34. #define LEDMODE_WHITE_BLINK 4
  35. #define LEDMODE_BOTH        5
  36. #define LEDMODE_MAX     5
  37.  
  38. #define BUTTON_TIMEOUT 150
  39. #define HOLD_TIMEOUT   500
  40.  
  41. #define EVENT_UP 1
  42. #define EVENT_DOWN 2
  43. #define EVENT_LEFT 3
  44. #define EVENT_RIGHT 4
  45. #define EVENT_PLAY 5
  46. #define EVENT_MENU 6
  47. #define EVENT_HOLD_PLAY 7
  48. #define EVENT_HOLD_MENU 8
  49.  
  50. #define EVENT_SILVER_PLAY 12
  51. #define EVENT_SILVER_HOLD_PLAY 97
  52. #define EVENT_SILVER_CENTER 11
  53. #define EVENT_SILVER_HOLD_CENTER 98
  54.  
  55. #define EVENT_RELEASE 0x80
  56.  
  57. #define EVENT_EXTRA_PLAY          70
  58. #define EVENT_EXTRA_PAUSE         71
  59. #define EVENT_EXTRA_STOP          72
  60. #define EVENT_EXTRA_REPLAY        73
  61. #define EVENT_EXTRA_SKIP          74
  62. #define EVENT_EXTRA_REWIND        75
  63. #define EVENT_EXTRA_FORWARD       76
  64. #define EVENT_EXTRA_PAGEUP        77
  65. #define EVENT_EXTRA_PAGEDOWN      78
  66.  
  67. #define EVENT_HARMONY_UP           1
  68. #define EVENT_HARMONY_DOWN         2
  69. #define EVENT_HARMONY_LEFT         3
  70. #define EVENT_HARMONY_RIGHT        4
  71. #define EVENT_HARMONY_OK           5
  72. #define EVENT_HARMONY_MENU         6
  73. #define EVENT_HARMONY_HOLD_OK      7
  74. #define EVENT_HARMONY_HOLD_MENU    8
  75. #define EVENT_HARMONY_STOP        15
  76. #define EVENT_HARMONY_PLAY        16
  77. #define EVENT_HARMONY_REPLAY      91
  78. #define EVENT_HARMONY_SKIP        92
  79. #define EVENT_HARMONY_RECORD      52
  80. #define EVENT_HARMONY_REWIND      41
  81. #define EVENT_HARMONY_FORWARD     42
  82. #define EVENT_HARMONY_PAUSE       26
  83. #define EVENT_HARMONY_PREV        32
  84. #define EVENT_HARMONY_GUIDE       65
  85. #define EVENT_HARMONY_INFO        31
  86. #define EVENT_HARMONY_EXIT        51
  87. #define EVENT_HARMONY_VOLUP       21
  88. #define EVENT_HARMONY_VOLDOWN     22
  89. #define EVENT_HARMONY_1           11
  90. #define EVENT_HARMONY_2           12
  91. #define EVENT_HARMONY_3           13
  92. #define EVENT_HARMONY_4           14
  93. #define EVENT_HARMONY_5           23
  94. #define EVENT_HARMONY_6           24
  95. #define EVENT_HARMONY_7           33
  96. #define EVENT_HARMONY_8           34
  97. #define EVENT_HARMONY_9           43
  98. #define EVENT_HARMONY_0           44
  99. #define EVENT_HARMONY_CLEAR       45
  100. #define EVENT_HARMONY_ENTER       36
  101. #define EVENT_HARMONY_MUTE        25
  102. #define EVENT_HARMONY_ASPECT      61
  103. #define EVENT_HARMONY_F1          53
  104. #define EVENT_HARMONY_F3          55
  105. #define EVENT_HARMONY_F2          54
  106. #define EVENT_HARMONY_F4          56
  107. #define EVENT_HARMONY_F5          93
  108. #define EVENT_HARMONY_F6          94
  109. #define EVENT_HARMONY_F7          95
  110. #define EVENT_HARMONY_F8          96
  111. #define EVENT_HARMONY_F9          73
  112. #define EVENT_HARMONY_F10         74
  113. #define EVENT_HARMONY_F11         75
  114. #define EVENT_HARMONY_F12         76
  115. #define EVENT_HARMONY_F13         63
  116. #define EVENT_HARMONY_F14         64
  117. #define EVENT_HARMONY_CHANUP      71
  118. #define EVENT_HARMONY_CHANDOWN    72
  119. #define EVENT_HARMONY_LRGDOWN     82
  120. #define EVENT_HARMONY_LRGUP       81
  121. #define EVENT_HARMONY_PWRTOGGLE   66
  122. #define EVENT_HARMONY_QUEUE       62
  123. #define EVENT_HARMONY_SLEEP       46
  124. #define EVENT_HARMONY_RED         83
  125. #define EVENT_HARMONY_GREEN       84
  126. #define EVENT_HARMONY_YELLOW      85
  127. #define EVENT_HARMONY_BLUE        86
  128.  
  129. bool multi_mode = 0;
  130. bool debug = 0;
  131. bool new_remote = 0;
  132. int idle_mode = LEDMODE_WHITE;
  133. int button_mode = LEDMODE_OFF;
  134. int special_mode = LEDMODE_AMBER;
  135. int hold_mode = LEDMODE_AMBER;
  136.  
  137. /* from libusb usbi.h */
  138. struct usb_dev_handle {
  139.     int fd;
  140.  
  141.     struct usb_bus *bus;
  142.     struct usb_device *device;
  143.  
  144.     int config;
  145.     int interface;
  146.     int altsetting;
  147.  
  148.     /* Added by RMT so implementations can store other per-open-device data */
  149.     void *impl_info;
  150. };
  151.  
  152. struct ir_command {
  153.   unsigned char flags;
  154.   unsigned char unused;
  155.   unsigned char event;
  156.   unsigned char address;
  157.   unsigned char eventId;
  158. };
  159.  
  160. static CAddress my_addr;
  161. static int sockfd;
  162.  
  163. static CPacketBUTTON* button_map[0xff];
  164. static CPacketBUTTON* multi_map[0xff];
  165.  
  166. static CPacketNOTIFICATION remote_paired("Remote paired", "You can now only control XBMC using the control you're holding. To unpair, hold down menu and rewind for 6 seconds.", NULL, NULL);
  167. static CPacketNOTIFICATION remote_unpaired("Remote unpaired", "You can now control XBMC with any Apple remote.", NULL, NULL);
  168. static CPacketNOTIFICATION remote_pair_failed("Remote already paired", "This AppleTV was paired to another remote. To unpair, hold down menu and rewind for 6 seconds.", NULL, NULL);
  169.  
  170. const char* remoteIdFile = "/etc/atvremoteid";
  171. static int pairedRemoteId = 0;
  172.  
  173. /* figure out kernel name corresponding to usb device */
  174. static int usb_make_kernel_name(usb_dev_handle *dev, int interface,
  175.                 char *name, int namelen)
  176. {
  177.     DIR *dir;
  178.     struct dirent *ent;
  179.     char busstr[10], devstr[10];
  180.     int buslen, devlen;
  181.  
  182.     /* kernel names are in the form of:
  183.        <busnum>-<devpath>:<config>.<interface>
  184.        We have everything besides devpath, but there doesn't seem to be
  185.        an easy of going from devnum to devpath, so we scan sysfs */
  186.  
  187.     buslen = sprintf(busstr, "%d-", atoi(dev->bus->dirname));
  188.     devlen = sprintf(devstr, "%d\n", dev->device->devnum);
  189.  
  190.     /* scan /sys/bus/usb/devices/<busnum>-* and compare devnum */
  191.     if (chdir("/sys/bus/usb/devices"))
  192.         return -1;
  193.  
  194.     dir = opendir(".");
  195.     if (!dir)
  196.         return -1;
  197.  
  198.     while ((ent = readdir(dir))) {
  199.         char buf[PATH_MAX];
  200.         int fd;
  201.  
  202.         /* only check devices on busnum bus */
  203.         if (strncmp(busstr, ent->d_name, buslen))
  204.             continue;
  205.  
  206.         sprintf(buf, "%s/devnum", ent->d_name);
  207.         fd = open(buf, O_RDONLY);
  208.         if (fd == -1)
  209.             continue;
  210.  
  211.         if ((read(fd, buf, sizeof(buf)) == devlen)
  212.             && !strncmp(buf, devstr, devlen)) {
  213.  
  214.             close(fd);
  215.  
  216.             if (snprintf(name, namelen, "%s:%d.%d", ent->d_name,
  217.                      1, interface) >= namelen)
  218.                 goto out;
  219.  
  220.             /* closedir could invalidate ent, so do it after the
  221.                snprintf */
  222.             closedir(dir);
  223.             return 0;
  224.         }
  225.  
  226.         close(fd);
  227.     }
  228.  
  229.  out:
  230.     closedir(dir);
  231.     return -1;
  232. }
  233.  
  234. /* (re)attach usb device to kernel driver (need hotplug support in kernel) */
  235. static int usb_attach_kernel_driver_np(usb_dev_handle *dev, int interface,
  236.                        const char *driver)
  237. {
  238.     char name[PATH_MAX], buf[PATH_MAX];
  239.  
  240.     if (!dev || !driver || interface < 0)
  241.         return -1;
  242.  
  243.     if (!usb_make_kernel_name(dev, interface, name, sizeof(name))) {
  244.         int fd, ret, len;
  245.  
  246.         /* (re)bind driver to device */
  247.         sprintf(buf, "/sys/bus/usb/drivers/%s/bind", driver);
  248.         len = strlen(name);
  249.  
  250.         fd = open(buf, O_WRONLY);
  251.         if (fd == -1)
  252.             return -1;
  253.  
  254.         ret = write(fd, name, len);
  255.         close(fd);
  256.  
  257.         if (ret != len)
  258.             return -1;
  259.         else
  260.             return 0;
  261.     }
  262.  
  263.     return -1;
  264. }
  265.  
  266. static usb_dev_handle *find_ir(void)
  267. {
  268.     struct usb_bus *bus;
  269.     struct usb_device *dev;
  270.  
  271.     for (bus = usb_busses; bus; bus = bus->next) {
  272.         for (dev = bus->devices; dev; dev = dev->next)
  273.             if (dev->descriptor.idVendor == VENDOR_APPLE
  274.                 && dev->descriptor.idProduct == PRODUCT_IR)
  275.                 return usb_open(dev);
  276.     }
  277.  
  278.     return NULL;
  279. }
  280.  
  281. static usb_dev_handle *get_ir(void)
  282. {
  283.     static usb_dev_handle *ir = NULL;
  284.  
  285.     if (!ir) {
  286.         usb_init();
  287.         usb_find_busses();
  288.         usb_find_devices();
  289.  
  290.         ir = find_ir();
  291.         if (!ir) {
  292.             fprintf(stderr, "IR receiver not found, quitting\n");
  293.             exit(1);
  294.         }
  295.  
  296.         /* interface is normally handled by hiddev */
  297.         usb_detach_kernel_driver_np(ir, 0);
  298.         if (usb_claim_interface(ir, 0)) {
  299.             fprintf(stderr, "error claiming interface, are you root?\n");
  300.             exit(2);
  301.         }
  302.         //usb_reset(ir);
  303.         //usb_set_configuration(ir, 0);
  304.     }
  305.  
  306.     return ir;
  307. }
  308.  
  309. static void reattach(void)
  310. {
  311.     usb_dev_handle *ir;
  312.  
  313.     ir = get_ir();
  314.     if (ir) {
  315.         usb_release_interface(ir, 0);
  316.         /* attach fails if we still have the file
  317.            descriptor open */
  318.         usb_close(ir);
  319.         usb_attach_kernel_driver_np(ir, 0, "usbhid");
  320.     }
  321. }
  322.  
  323. static int set_report(unsigned char* data, int len)
  324. {
  325.     unsigned char *type = data;
  326.     int val;
  327.  
  328.     val = 0x300 | *type;
  329.  
  330.     return (usb_control_msg(get_ir(), USB_ENDPOINT_OUT | USB_TYPE_CLASS
  331.                 | USB_RECIP_INTERFACE, 9, val, 0,
  332.                 (char*) data, len, 1000) != len);
  333. }
  334.  
  335. static void set_fan(int full)
  336. {
  337.     unsigned char buf[2];
  338.  
  339.     buf[0] = 0xf; buf[1] = full ? 1 : 0;
  340.  
  341.     set_report(buf, sizeof(buf));
  342. }
  343.  
  344. static void set_led(int mode)
  345. {
  346.     unsigned char buf[5];
  347.  
  348.     memset(buf, 0, sizeof(buf));
  349.     buf[0] = 0xd; buf[1] = mode;
  350.  
  351.     switch (mode) {
  352.     case LEDMODE_OFF:
  353.         set_report(buf, sizeof(buf));
  354.         buf[1] = 3;
  355.         set_report(buf, 3);
  356.         buf[1] = 4;
  357.         set_report(buf, 3);
  358.         break;
  359.  
  360.     case LEDMODE_AMBER:
  361.         set_report(buf, sizeof(buf));
  362.         buf[1] = 3; buf[2] = 1;
  363.         set_report(buf, 3);
  364.         buf[1] = 4; buf[2] = 0;
  365.         set_report(buf, 3);
  366.         break;
  367.  
  368.     case LEDMODE_AMBER_BLINK:
  369.         set_report(buf, sizeof(buf));
  370.         buf[1] = 3;
  371.         set_report(buf, 3);
  372.         buf[1] = 4;
  373.         set_report(buf, 3);
  374.         buf[1] = 3; buf[2] = 2;
  375.         set_report(buf, 3);
  376.         break;
  377.  
  378.     case LEDMODE_WHITE:
  379.         set_report(buf, sizeof(buf));
  380.         set_report(buf, 3);
  381.         buf[1] = 4; buf[2] = 1;
  382.         set_report(buf, 3);
  383.         break;
  384.  
  385.     case LEDMODE_WHITE_BLINK:
  386.         set_report(buf, sizeof(buf));
  387.         buf[1] = 3;
  388.         set_report(buf, 3);
  389.         buf[1] = 4;
  390.         set_report(buf, 3);
  391.         buf[1] = 4; buf[2] = 2;
  392.         set_report(buf, 3);
  393.         break;
  394.  
  395.     case LEDMODE_BOTH:
  396.         buf[1] = 7;
  397.         set_report(buf, sizeof(buf));
  398.         buf[1] = 6; buf[2] = 1;
  399.         set_report(buf, 3);
  400.         break;
  401.     }
  402. }
  403.  
  404. static void set_led_brightness(int high)
  405. {
  406.     unsigned char buf[5];
  407.  
  408.     memset(buf, 0, sizeof(buf));
  409.     buf[0] = 0xd;
  410.  
  411.     if (high) {
  412.         buf[1] = 6;
  413.         set_report(buf, sizeof(buf));
  414.         buf[1] = 5; buf[2] = 1;
  415.         set_report(buf, 3);
  416.     } else {
  417.         buf[1] = 5;
  418.         set_report(buf, sizeof(buf));
  419.         set_report(buf, 3);
  420.     }
  421. }
  422.  
  423. void dumphex(unsigned char* buf, int size) {
  424.   int i;
  425.   for(i=0; i < size; i++) {
  426.     printf("%02x ", buf[i]);
  427.   }
  428.   printf("\n");
  429. }
  430.  
  431. unsigned long millis() {
  432.   static struct timeval time;
  433.   gettimeofday(&time, NULL);
  434.   return (time.tv_sec*1000+time.tv_usec/1000);
  435. }
  436.  
  437. bool is_multi_candidate(struct ir_command command) {
  438.   switch(command.address) {
  439.     case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9d: case 0x9e: case 0x9f: case 0xa0:
  440.           if(debug) printf("Multi-remote candidate\n"); return multi_mode; break;
  441.         default:
  442.           return false;
  443.   }
  444. }
  445.  
  446. void send_multi(int button) {
  447.   printf("Sending multi-remote button %d\n", multi_map[button]->m_ButtonCode);
  448.   multi_map[button] -> Send(sockfd, my_addr);
  449. }
  450.  
  451. void send_button(int button) {
  452.   printf("Sending button %d\n\n", button_map[button]->m_ButtonCode);
  453. /*  switch(button) {
  454.     case EVENT_UP: printf("Up\n"); break;
  455.     case EVENT_DOWN: printf("Down\n"); break;
  456.     case EVENT_LEFT: printf("Left\n"); break;
  457.     case EVENT_RIGHT: printf("Right\n"); break;
  458.     case EVENT_MENU: printf("Menu\n"); break;
  459.     case EVENT_HOLD_MENU: printf("Menu hold\n"); break;
  460.     case EVENT_PLAY: printf("Play/pause\n"); break;
  461.     case EVENT_HOLD_PLAY: printf("Play/pause hold\n"); break;
  462.     case EVENT_SILVER_PLAY: printf("Play/pause (silver remote)\n"); break;
  463.     case EVENT_SILVER_HOLD_PLAY: printf("Play/pause hold (silver remote)\n"); break;
  464.     case EVENT_SILVER_CENTER: printf("Center (silver remote)\n"); break;
  465.     case EVENT_SILVER_HOLD_CENTER: printf("Center hold (silver remote)\n"); break;
  466.   }
  467. */  
  468.   button_map[button] -> Send(sockfd, my_addr);
  469. }
  470.  
  471. void handle_button(struct ir_command command) {
  472.   static unsigned short previousButton;
  473.   static unsigned char holdButtonSent;
  474.   static long buttonStart;
  475.  
  476.   if(debug) printf("Previous Button: %04x\n", previousButton);
  477.  
  478.   unsigned short eventId;
  479.   unsigned short timeout;
  480.   if(command.flags == 0x26) {
  481.     eventId = previousButton;
  482.   } else {
  483.     eventId = is_multi_candidate(command) ? command.address<<8 | command.eventId : command.eventId;
  484.     // hack for silver remote
  485.     timeout = millis() - buttonStart;
  486.     if(debug){printf("Timeout: %d ms\n", timeout); printf("Got Event id: %04x\n", eventId);};
  487.     // if new silver remote sends first 0x05c/0x05c and then 0x05 do event remapping
  488.     if((timeout < 200 && command.flags == 0x25 && eventId == 0x05) && (previousButton == 0x05f || previousButton == 0x05c)) {
  489.       if(debug) printf("Signal of new silver remote: ");
  490.       switch(previousButton) {
  491.         // map event to prevent double commands
  492.         case 0x05f: if(debug) printf("mapping 0x05f to 0x05ff\n"); eventId = 0x05ff; break;
  493.         case 0x05c: if(debug) printf("mapping 0x05c to 0x05cf\n"); eventId = 0x05cf; break;
  494.       }
  495.     }
  496.   }
  497.  
  498.   if(debug) printf("New Event id: %04x\n", eventId);
  499.  
  500.   if(previousButton != eventId && previousButton != 0 && !holdButtonSent) {
  501.     switch(previousButton) {
  502.       case 0x03: case 0x02: send_button(EVENT_MENU); break;
  503.       case 0x05: case 0x04: send_button(EVENT_PLAY); break;
  504.       case 0x05ff: send_button(EVENT_SILVER_PLAY); break;
  505.       case 0x05cf: send_button(EVENT_SILVER_CENTER); break;
  506.       case 0x9602: send_multi(EVENT_HARMONY_MENU); break;
  507.       case 0x9604: send_multi(EVENT_HARMONY_OK); break;
  508.      
  509.     }
  510.   }
  511.  
  512.   if(previousButton != eventId) {
  513.     buttonStart = millis();
  514.   }
  515.  
  516.   switch(eventId) {
  517.     case 0x0a:
  518.     case 0x0b:
  519.       if(eventId != previousButton) send_button(EVENT_UP); break;
  520.     case 0x0c:
  521.     case 0x0d:
  522.       if(eventId != previousButton) send_button(EVENT_DOWN); break;
  523.     case 0x09:
  524.     case 0x08:
  525.       if(eventId != previousButton) send_button(EVENT_LEFT); break;
  526.     case 0x06:
  527.     case 0x07:
  528.       if(eventId != previousButton) send_button(EVENT_RIGHT); break;
  529.      
  530.     // extra buttons mapped by Harmony remotes
  531.     case 0x16: if(eventId != previousButton) send_button( EVENT_EXTRA_PLAY         ); break;
  532.     case 0x32: if(eventId != previousButton) send_button( EVENT_EXTRA_PAUSE        ); break;
  533.     case 0x31: if(eventId != previousButton) send_button( EVENT_EXTRA_STOP         ); break;
  534.     case 0x25: if(eventId != previousButton) send_button( EVENT_EXTRA_REPLAY       ); break;
  535.     case 0x23: if(eventId != previousButton) send_button( EVENT_EXTRA_SKIP         ); break;
  536.     case 0x1c: if(eventId != previousButton) send_button( EVENT_EXTRA_REWIND       ); break;
  537.     case 0x1a: if(eventId != previousButton) send_button( EVENT_EXTRA_FORWARD      ); break;
  538.     case 0x2f: if(eventId != previousButton) send_button( EVENT_EXTRA_PAGEUP       ); break;
  539.     case 0x26: if(eventId != previousButton) send_button( EVENT_EXTRA_PAGEDOWN     ); break;
  540.    
  541.     // buttons mapped by new silver remotes
  542.     case 0x05c: case 0x05f: if(debug) printf("Signal of silver remote detected, waiting for remapping next event...\n"); break;
  543.      
  544.     // multi-remote buttons
  545.     // extra buttons mapped by Harmony remotes - duplicates of ATV, just in case
  546.     case 0x960b: if(eventId != previousButton) send_multi( EVENT_HARMONY_UP           ); break;
  547.     case 0x960d: if(eventId != previousButton) send_multi( EVENT_HARMONY_DOWN         ); break;
  548.     case 0x9608: if(eventId != previousButton) send_multi( EVENT_HARMONY_LEFT         ); break;
  549.     case 0x9607: if(eventId != previousButton) send_multi( EVENT_HARMONY_RIGHT        ); break;
  550.     case 0x9703: if(eventId != previousButton) send_multi( EVENT_HARMONY_PLAY         ); break;
  551.     case 0x9705: if(eventId != previousButton) send_multi( EVENT_HARMONY_STOP         ); break;
  552.     case 0x9803: if(eventId != previousButton) send_multi( EVENT_HARMONY_PAUSE        ); break;
  553.     case 0xa00b: if(eventId != previousButton) send_multi( EVENT_HARMONY_REPLAY       ); break;
  554.     case 0xa00d: if(eventId != previousButton) send_multi( EVENT_HARMONY_SKIP         ); break;
  555.     case 0x9a0b: if(eventId != previousButton) send_multi( EVENT_HARMONY_REWIND       ); break;
  556.     case 0x9a0d: if(eventId != previousButton) send_multi( EVENT_HARMONY_FORWARD      ); break;
  557.     case 0x9b0c: if(eventId != previousButton) send_multi( EVENT_HARMONY_RECORD       ); break;
  558.     case 0x990d: if(eventId != previousButton) send_multi( EVENT_HARMONY_PREV         ); break;
  559.     case 0x9d05: if(eventId != previousButton) send_multi( EVENT_HARMONY_GUIDE        ); break;
  560.     case 0x990b: if(eventId != previousButton) send_multi( EVENT_HARMONY_INFO         ); break;
  561.     case 0x9b0a: if(eventId != previousButton) send_multi( EVENT_HARMONY_EXIT         ); break;
  562.     case 0x980a: if(eventId != previousButton) send_multi( EVENT_HARMONY_VOLUP        ); break;
  563.     case 0x980c: if(eventId != previousButton) send_multi( EVENT_HARMONY_VOLDOWN      ); break;
  564.     case 0x970a: if(eventId != previousButton) send_multi( EVENT_HARMONY_1            ); break;
  565.     case 0x970c: if(eventId != previousButton) send_multi( EVENT_HARMONY_2            ); break;
  566.     case 0x9709: if(eventId != previousButton) send_multi( EVENT_HARMONY_3            ); break;
  567.     case 0x9706: if(eventId != previousButton) send_multi( EVENT_HARMONY_4            ); break;
  568.     case 0x9809: if(eventId != previousButton) send_multi( EVENT_HARMONY_5            ); break;
  569.     case 0x9806: if(eventId != previousButton) send_multi( EVENT_HARMONY_6            ); break;
  570.     case 0x9908: if(eventId != previousButton) send_multi( EVENT_HARMONY_7            ); break;
  571.     case 0x9907: if(eventId != previousButton) send_multi( EVENT_HARMONY_8            ); break;
  572.     case 0x9a08: if(eventId != previousButton) send_multi( EVENT_HARMONY_9            ); break;
  573.     case 0x9a07: if(eventId != previousButton) send_multi( EVENT_HARMONY_0            ); break;
  574.     case 0x9a04: if(eventId != previousButton) send_multi( EVENT_HARMONY_CLEAR        ); break;
  575.     case 0x9902: if(eventId != previousButton) send_multi( EVENT_HARMONY_ENTER        ); break;
  576.     case 0x9805: if(eventId != previousButton) send_multi( EVENT_HARMONY_MUTE         ); break;
  577.     case 0x9d0a: if(eventId != previousButton) send_multi( EVENT_HARMONY_ASPECT       ); break;
  578.     case 0x9b09: if(eventId != previousButton) send_multi( EVENT_HARMONY_F1           ); break;
  579.     case 0x9b06: if(eventId != previousButton) send_multi( EVENT_HARMONY_F2           ); break;
  580.     case 0x9b05: if(eventId != previousButton) send_multi( EVENT_HARMONY_F3           ); break;
  581.     case 0x9b03: if(eventId != previousButton) send_multi( EVENT_HARMONY_F4           ); break;
  582.     case 0xa008: if(eventId != previousButton) send_multi( EVENT_HARMONY_F5           ); break;
  583.     case 0xa007: if(eventId != previousButton) send_multi( EVENT_HARMONY_F6           ); break;
  584.     case 0xa004: if(eventId != previousButton) send_multi( EVENT_HARMONY_F7           ); break;
  585.     case 0xa002: if(eventId != previousButton) send_multi( EVENT_HARMONY_F8           ); break;
  586.     case 0x9e09: if(eventId != previousButton) send_multi( EVENT_HARMONY_F9           ); break;
  587.     case 0x9e06: if(eventId != previousButton) send_multi( EVENT_HARMONY_F10          ); break;
  588.     case 0x9e05: if(eventId != previousButton) send_multi( EVENT_HARMONY_F11          ); break;
  589.     case 0x9e03: if(eventId != previousButton) send_multi( EVENT_HARMONY_F12          ); break;
  590.     case 0x9d09: if(eventId != previousButton) send_multi( EVENT_HARMONY_F13          ); break;
  591.     case 0x9d06: if(eventId != previousButton) send_multi( EVENT_HARMONY_F14          ); break;
  592.     case 0x9e0c: if(eventId != previousButton) send_multi( EVENT_HARMONY_CHANDOWN     ); break;
  593.     case 0x9e0a: if(eventId != previousButton) send_multi( EVENT_HARMONY_CHANUP       ); break;
  594.     case 0x9f0d: if(eventId != previousButton) send_multi( EVENT_HARMONY_LRGDOWN      ); break;
  595.     case 0x9f0b: if(eventId != previousButton) send_multi( EVENT_HARMONY_LRGUP        ); break;
  596.     case 0x9d03: if(eventId != previousButton) send_multi( EVENT_HARMONY_PWRTOGGLE    ); break;
  597.     case 0x9d0c: if(eventId != previousButton) send_multi( EVENT_HARMONY_QUEUE        ); break;
  598.     case 0x9a02: if(eventId != previousButton) send_multi( EVENT_HARMONY_SLEEP        ); break;
  599.     case 0x9f08: if(eventId != previousButton) send_multi( EVENT_HARMONY_RED          ); break;
  600.     case 0x9f07: if(eventId != previousButton) send_multi( EVENT_HARMONY_GREEN        ); break;
  601.     case 0x9f04: if(eventId != previousButton) send_multi( EVENT_HARMONY_YELLOW       ); break;
  602.     case 0x9f02: if(eventId != previousButton) send_multi( EVENT_HARMONY_BLUE         ); break;
  603.  
  604.     case 0x03: case 0x02: case 0x05: case 0x04: case 0x05ff: case 0x05cf: case 0x9603: case 0x9602: case 0x9605: case 0x9604:
  605.       // menu and pause need special treatment
  606.       if(previousButton != eventId) {
  607.         holdButtonSent = 0;
  608.       } else {
  609.         if(millis() - buttonStart > HOLD_TIMEOUT && !holdButtonSent) {
  610.           set_led(hold_mode);
  611.           switch(eventId) {
  612.             case 0x03: case 0x02: send_button(EVENT_HOLD_MENU); break;
  613.             case 0x05: case 0x04: send_button(EVENT_HOLD_PLAY); break;
  614.             case 0x9602: send_multi(EVENT_HARMONY_HOLD_MENU); break;
  615.             case 0x9604: send_multi(EVENT_HARMONY_HOLD_OK); break;
  616.             case 0x05ff: send_button(EVENT_SILVER_HOLD_PLAY); break;
  617.             case 0x05cf: send_button(EVENT_SILVER_HOLD_CENTER); break;
  618.           }
  619.           holdButtonSent = 1;
  620.         }
  621.       }
  622.       break;
  623.     case 0x00:
  624.       // button timeout
  625.       switch(previousButton) {
  626.         case 0x0a:
  627.         case 0x0b:
  628.           send_button(EVENT_UP | EVENT_RELEASE); break;
  629.         case 0x0c:
  630.         case 0x0d:
  631.           send_button(EVENT_DOWN | EVENT_RELEASE); break;
  632.         case 0x09:
  633.         case 0x08:
  634.           send_button(EVENT_LEFT | EVENT_RELEASE); break;
  635.         case 0x06:
  636.         case 0x07:
  637.           send_button(EVENT_RIGHT | EVENT_RELEASE); break;
  638.         case 0x960b: send_multi(EVENT_HARMONY_UP        | EVENT_RELEASE); break;
  639.         case 0x960d: send_multi(EVENT_HARMONY_DOWN      | EVENT_RELEASE); break;
  640.         case 0x9608: send_multi(EVENT_HARMONY_LEFT      | EVENT_RELEASE); break;
  641.         case 0x9607: send_multi(EVENT_HARMONY_RIGHT     | EVENT_RELEASE); break;
  642.         case 0x980a: send_multi(EVENT_HARMONY_VOLUP     | EVENT_RELEASE); break;
  643.         case 0x980c: send_multi(EVENT_HARMONY_VOLDOWN   | EVENT_RELEASE); break;
  644.         case 0x9a0b: send_multi(EVENT_HARMONY_REWIND    | EVENT_RELEASE); break;
  645.         case 0x9a0d: send_multi(EVENT_HARMONY_FORWARD   | EVENT_RELEASE); break;
  646.       }
  647.       break;
  648.     default:
  649.       if(debug) printf("unknown\n");
  650.   }
  651.   previousButton = eventId;
  652. }
  653.  
  654. int readPairedAddressId() {
  655.   FILE *fp = fopen(remoteIdFile, "r");
  656.   if(fp != NULL) {
  657.     int address;
  658.     fscanf(fp, "%d", &address);
  659.     fclose(fp);  
  660.     return address;
  661.   } else {
  662.     return 0;
  663.   }  
  664. }
  665.  
  666. void writePairedAddressId(int address) {
  667.   FILE *fp = fopen(remoteIdFile, "w");
  668.   if(fp != NULL) {
  669.     fprintf(fp, "%d\n", address);
  670.     fclose(fp);  
  671.   } else {
  672.     printf("Could not open file `%s' for writing.\n", remoteIdFile);
  673.   }  
  674. }
  675.  
  676. char event_map[] = { 0x00, 0x00, 0x03, 0x02, 0x04, 0x04 };
  677.  
  678. void handle_special(struct ir_command command) {
  679.   static unsigned char previousEventId;
  680.   if(command.eventId != previousEventId) {
  681.     switch(command.eventId) {
  682.       case 0x02: case 0x03: // pair!
  683.         if(pairedRemoteId != 0) {
  684.           printf("Already paired: %d\n", command.address);
  685.           remote_pair_failed.Send(sockfd, my_addr);
  686.         } else {
  687.           printf("Pairing ID: %d\n", command.address);
  688.           writePairedAddressId(command.address);
  689.           pairedRemoteId = command.address;
  690.           remote_paired.Send(sockfd, my_addr);
  691.         }
  692.         break;
  693.       case 0x04: case 0x05: // unpair!
  694.         printf("Unpairing ID: %d\n", command.address);
  695.         writePairedAddressId(0);
  696.         pairedRemoteId = 0;
  697.         remote_unpaired.Send(sockfd, my_addr);
  698.         break;  
  699.     }
  700.     previousEventId = command.eventId;
  701.   }
  702.  
  703. }
  704.  
  705. void usage(int argc, char **argv) {
  706.   if (argc >=1) {
  707.     printf("Usage: %s [-i mode] [-s mode] [-H mode] [-b mode] [-B] [-h]\n", argv[0]);
  708.     printf("  Options:\n");
  709.     printf("      -m\tEnable multi-remote support.\n");
  710.     printf("      -i\tChange the LED mode for when the receiver is idle.\n");
  711.     printf("      -b\tChange the LED mode for when the receiver is receiving a button press.\n");
  712.     printf("      -H\tChange the LED mode for when the hold event is triggered.\n");
  713.     printf("      -s\tChange the LED mode for when a special event is received.\n");
  714.     printf("      -B\tSwitch LED to low brightness.\n");
  715.     printf("      -d\tEnable debug output,\n");
  716.     printf("      -h\tShow this help screen.\n\n");
  717.     printf("Supported LED modes:\n");
  718.     printf("  0: off\n");
  719.     printf("  1: amber\n");
  720.     printf("  2: blink amber\n");
  721.     printf("  3: white\n");
  722.     printf("  4: blink white\n");
  723.     printf("  5: blink both\n");
  724.     printf("\n");
  725.   }
  726. }
  727.  
  728. int main(int argc, char **argv) {
  729.   struct ir_command command;
  730.   struct ir_command timeoutCommand;
  731.  
  732.   int c;
  733.  
  734.   int led_brightness = 1;
  735.  
  736.   while ((c = getopt (argc, argv, "mBi:b:s:H:hd")) != -1)
  737.   switch (c) {
  738.     case 'm':
  739.       multi_mode = 1; break;
  740.     case 'i':
  741.       idle_mode = atol(optarg); break;
  742.     case 'b':
  743.       button_mode = atol(optarg); break;
  744.     case 's':
  745.       special_mode = atol(optarg); break;
  746.     case 'H':
  747.       hold_mode = atol(optarg); break;
  748.     case 'd':
  749.       debug = 1; break;
  750.     case 'h':
  751.       usage(argc,argv); exit(0); break;
  752.     case 'B':
  753.       led_brightness = 0; break;
  754.     case '?':
  755.       switch(optopt) {
  756.         case 'i': case 'b': case 's': case 'H':
  757.              fprintf (stderr, "Option -%c requires an argument.\n", optopt);
  758.              break;
  759.         default:
  760.              if (isprint (optopt))
  761.                fprintf (stderr, "Unknown option `-%c'.\n", optopt);
  762.              else
  763.                fprintf (stderr,
  764.                         "Unknown option character `\\x%x'.\n",
  765.                         optopt);
  766.       }
  767.       return 1;
  768.     default:
  769.       abort();
  770.   }
  771.  
  772.   set_led_brightness(led_brightness);
  773.  
  774.   memset(&timeoutCommand, 0, sizeof(timeoutCommand));
  775.  
  776.   if(debug) printf("Creating socket...\n");
  777.  
  778.   sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  779.   if (sockfd < 0)
  780.   {
  781.     printf("Error creating socket\n");
  782.     return -1;
  783.   }
  784.  
  785.   if(debug) printf("Preparing button map...\n");
  786.  
  787.   button_map[EVENT_UP]                                = new CPacketBUTTON(EVENT_UP,                   "JS0:AppleRemote", BTN_DOWN);
  788.   button_map[EVENT_DOWN]                              = new CPacketBUTTON(EVENT_DOWN,                 "JS0:AppleRemote", BTN_DOWN);
  789.   button_map[EVENT_LEFT]                              = new CPacketBUTTON(EVENT_LEFT,                 "JS0:AppleRemote", BTN_DOWN);
  790.   button_map[EVENT_RIGHT]                             = new CPacketBUTTON(EVENT_RIGHT,                "JS0:AppleRemote", BTN_DOWN);
  791.   button_map[EVENT_PLAY]                              = new CPacketBUTTON(EVENT_PLAY,                 "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  792.   button_map[EVENT_MENU]                              = new CPacketBUTTON(EVENT_MENU,                 "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  793.   button_map[EVENT_HOLD_PLAY]                         = new CPacketBUTTON(EVENT_HOLD_PLAY,            "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  794.   button_map[EVENT_HOLD_MENU]                         = new CPacketBUTTON(EVENT_HOLD_MENU,            "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  795.   button_map[EVENT_UP | EVENT_RELEASE    ]            = new CPacketBUTTON(EVENT_UP,                   "JS0:AppleRemote", BTN_UP);
  796.   button_map[EVENT_DOWN | EVENT_RELEASE  ]            = new CPacketBUTTON(EVENT_DOWN,                 "JS0:AppleRemote", BTN_UP);
  797.   button_map[EVENT_LEFT | EVENT_RELEASE  ]            = new CPacketBUTTON(EVENT_LEFT,                 "JS0:AppleRemote", BTN_UP);
  798.   button_map[EVENT_RIGHT | EVENT_RELEASE ]            = new CPacketBUTTON(EVENT_RIGHT,                "JS0:AppleRemote", BTN_UP);
  799.  
  800.   button_map[EVENT_SILVER_PLAY]                       = new CPacketBUTTON(EVENT_SILVER_PLAY,          "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  801.   button_map[EVENT_SILVER_HOLD_PLAY]                  = new CPacketBUTTON(EVENT_SILVER_HOLD_PLAY,     "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  802.   button_map[EVENT_SILVER_CENTER]                     = new CPacketBUTTON(EVENT_SILVER_CENTER,        "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  803.   button_map[EVENT_SILVER_HOLD_CENTER]                = new CPacketBUTTON(EVENT_SILVER_HOLD_CENTER,   "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  804.  
  805.   button_map[EVENT_EXTRA_PLAY]                        = new CPacketBUTTON(EVENT_EXTRA_PLAY,           "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  806.   button_map[EVENT_EXTRA_PAUSE]                       = new CPacketBUTTON(EVENT_EXTRA_PAUSE,          "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  807.   button_map[EVENT_EXTRA_STOP]                        = new CPacketBUTTON(EVENT_EXTRA_STOP,           "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  808.   button_map[EVENT_EXTRA_REPLAY]                      = new CPacketBUTTON(EVENT_EXTRA_REPLAY,         "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  809.   button_map[EVENT_EXTRA_SKIP]                        = new CPacketBUTTON(EVENT_EXTRA_SKIP,           "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  810.   button_map[EVENT_EXTRA_REWIND]                      = new CPacketBUTTON(EVENT_EXTRA_REWIND,         "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  811.   button_map[EVENT_EXTRA_FORWARD]                     = new CPacketBUTTON(EVENT_EXTRA_FORWARD,        "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  812.   button_map[EVENT_EXTRA_PAGEUP]                      = new CPacketBUTTON(EVENT_EXTRA_PAGEUP,         "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  813.   button_map[EVENT_EXTRA_PAGEDOWN]                    = new CPacketBUTTON(EVENT_EXTRA_PAGEDOWN,       "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  814.  
  815.   multi_map[EVENT_HARMONY_UP]                        = new CPacketBUTTON(EVENT_HARMONY_UP,           "JS0:Harmony", BTN_DOWN);
  816.   multi_map[EVENT_HARMONY_UP        | EVENT_RELEASE] = new CPacketBUTTON(EVENT_HARMONY_UP,           "JS0:Harmony", BTN_UP);
  817.   multi_map[EVENT_HARMONY_DOWN]                      = new CPacketBUTTON(EVENT_HARMONY_DOWN,         "JS0:Harmony", BTN_DOWN);
  818.   multi_map[EVENT_HARMONY_DOWN      | EVENT_RELEASE] = new CPacketBUTTON(EVENT_HARMONY_DOWN,         "JS0:Harmony", BTN_UP);
  819.   multi_map[EVENT_HARMONY_LEFT]                      = new CPacketBUTTON(EVENT_HARMONY_LEFT,         "JS0:Harmony", BTN_DOWN);
  820.   multi_map[EVENT_HARMONY_LEFT      | EVENT_RELEASE] = new CPacketBUTTON(EVENT_HARMONY_LEFT,         "JS0:Harmony", BTN_UP);
  821.   multi_map[EVENT_HARMONY_RIGHT]                     = new CPacketBUTTON(EVENT_HARMONY_RIGHT,        "JS0:Harmony", BTN_DOWN);
  822.   multi_map[EVENT_HARMONY_RIGHT     | EVENT_RELEASE] = new CPacketBUTTON(EVENT_HARMONY_RIGHT,        "JS0:Harmony", BTN_UP);
  823.   multi_map[EVENT_HARMONY_OK]                        = new CPacketBUTTON(EVENT_HARMONY_OK,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  824.   multi_map[EVENT_HARMONY_MENU]                      = new CPacketBUTTON(EVENT_HARMONY_MENU,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  825.   multi_map[EVENT_HARMONY_HOLD_OK]                   = new CPacketBUTTON(EVENT_HARMONY_HOLD_OK,      "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  826.   multi_map[EVENT_HARMONY_HOLD_MENU]                 = new CPacketBUTTON(EVENT_HARMONY_HOLD_MENU,    "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  827.   multi_map[EVENT_HARMONY_PLAY]                      = new CPacketBUTTON(EVENT_HARMONY_PLAY,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  828.   multi_map[EVENT_HARMONY_STOP]                      = new CPacketBUTTON(EVENT_HARMONY_STOP,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  829.   multi_map[EVENT_HARMONY_PAUSE]                     = new CPacketBUTTON(EVENT_HARMONY_PAUSE,        "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  830.   multi_map[EVENT_HARMONY_REPLAY]                    = new CPacketBUTTON(EVENT_HARMONY_REPLAY,       "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  831.   multi_map[EVENT_HARMONY_SKIP]                      = new CPacketBUTTON(EVENT_HARMONY_SKIP,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  832.   multi_map[EVENT_HARMONY_REWIND]                    = new CPacketBUTTON(EVENT_HARMONY_REWIND,       "JS0:Harmony", BTN_DOWN);
  833.   multi_map[EVENT_HARMONY_REWIND    | EVENT_RELEASE] = new CPacketBUTTON(EVENT_HARMONY_REWIND,       "JS0:Harmony", BTN_UP);
  834.   multi_map[EVENT_HARMONY_FORWARD]                   = new CPacketBUTTON(EVENT_HARMONY_FORWARD,      "JS0:Harmony", BTN_DOWN);
  835.   multi_map[EVENT_HARMONY_FORWARD   | EVENT_RELEASE] = new CPacketBUTTON(EVENT_HARMONY_FORWARD,      "JS0:Harmony", BTN_UP);
  836.   multi_map[EVENT_HARMONY_RECORD]                    = new CPacketBUTTON(EVENT_HARMONY_RECORD,       "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  837.   multi_map[EVENT_HARMONY_PREV]                      = new CPacketBUTTON(EVENT_HARMONY_PREV,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  838.   multi_map[EVENT_HARMONY_GUIDE]                     = new CPacketBUTTON(EVENT_HARMONY_GUIDE,        "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  839.   multi_map[EVENT_HARMONY_INFO]                      = new CPacketBUTTON(EVENT_HARMONY_INFO,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  840.   multi_map[EVENT_HARMONY_EXIT]                      = new CPacketBUTTON(EVENT_HARMONY_EXIT,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  841.   multi_map[EVENT_HARMONY_VOLUP]                     = new CPacketBUTTON(EVENT_HARMONY_VOLUP,        "JS0:Harmony", BTN_DOWN);
  842.   multi_map[EVENT_HARMONY_VOLUP     | EVENT_RELEASE] = new CPacketBUTTON(EVENT_HARMONY_VOLUP,        "JS0:Harmony", BTN_UP);
  843.   multi_map[EVENT_HARMONY_VOLDOWN]                   = new CPacketBUTTON(EVENT_HARMONY_VOLDOWN,      "JS0:Harmony", BTN_DOWN);
  844.   multi_map[EVENT_HARMONY_VOLDOWN   | EVENT_RELEASE] = new CPacketBUTTON(EVENT_HARMONY_VOLDOWN,      "JS0:Harmony", BTN_UP);
  845.   multi_map[EVENT_HARMONY_1]                         = new CPacketBUTTON(EVENT_HARMONY_1,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  846.   multi_map[EVENT_HARMONY_2]                         = new CPacketBUTTON(EVENT_HARMONY_2,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  847.   multi_map[EVENT_HARMONY_3]                         = new CPacketBUTTON(EVENT_HARMONY_3,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  848.   multi_map[EVENT_HARMONY_4]                         = new CPacketBUTTON(EVENT_HARMONY_4,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  849.   multi_map[EVENT_HARMONY_5]                         = new CPacketBUTTON(EVENT_HARMONY_5,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  850.   multi_map[EVENT_HARMONY_6]                         = new CPacketBUTTON(EVENT_HARMONY_6,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  851.   multi_map[EVENT_HARMONY_7]                         = new CPacketBUTTON(EVENT_HARMONY_7,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  852.   multi_map[EVENT_HARMONY_8]                         = new CPacketBUTTON(EVENT_HARMONY_8,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  853.   multi_map[EVENT_HARMONY_9]                         = new CPacketBUTTON(EVENT_HARMONY_9,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  854.   multi_map[EVENT_HARMONY_0]                         = new CPacketBUTTON(EVENT_HARMONY_0,            "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  855.   multi_map[EVENT_HARMONY_CLEAR]                     = new CPacketBUTTON(EVENT_HARMONY_CLEAR,        "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  856.   multi_map[EVENT_HARMONY_ENTER]                     = new CPacketBUTTON(EVENT_HARMONY_ENTER,        "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  857.   multi_map[EVENT_HARMONY_MUTE]                      = new CPacketBUTTON(EVENT_HARMONY_MUTE,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  858.   multi_map[EVENT_HARMONY_ASPECT]                    = new CPacketBUTTON(EVENT_HARMONY_ASPECT,       "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  859.   multi_map[EVENT_HARMONY_F1]                        = new CPacketBUTTON(EVENT_HARMONY_F1,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  860.   multi_map[EVENT_HARMONY_F2]                        = new CPacketBUTTON(EVENT_HARMONY_F2,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  861.   multi_map[EVENT_HARMONY_F3]                        = new CPacketBUTTON(EVENT_HARMONY_F3,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  862.   multi_map[EVENT_HARMONY_F4]                        = new CPacketBUTTON(EVENT_HARMONY_F4,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  863.   multi_map[EVENT_HARMONY_F5]                        = new CPacketBUTTON(EVENT_HARMONY_F5,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  864.   multi_map[EVENT_HARMONY_F6]                        = new CPacketBUTTON(EVENT_HARMONY_F6,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  865.   multi_map[EVENT_HARMONY_F7]                        = new CPacketBUTTON(EVENT_HARMONY_F7,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  866.   multi_map[EVENT_HARMONY_F8]                        = new CPacketBUTTON(EVENT_HARMONY_F8,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  867.   multi_map[EVENT_HARMONY_F9]                        = new CPacketBUTTON(EVENT_HARMONY_F9,           "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  868.   multi_map[EVENT_HARMONY_F10]                       = new CPacketBUTTON(EVENT_HARMONY_F10,          "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  869.   multi_map[EVENT_HARMONY_F11]                       = new CPacketBUTTON(EVENT_HARMONY_F11,          "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  870.   multi_map[EVENT_HARMONY_F12]                       = new CPacketBUTTON(EVENT_HARMONY_F12,          "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  871.   multi_map[EVENT_HARMONY_F13]                       = new CPacketBUTTON(EVENT_HARMONY_F13,          "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  872.   multi_map[EVENT_HARMONY_F14]                       = new CPacketBUTTON(EVENT_HARMONY_F14,          "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  873.   multi_map[EVENT_HARMONY_CHANUP]                    = new CPacketBUTTON(EVENT_HARMONY_CHANUP,       "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  874.   multi_map[EVENT_HARMONY_CHANDOWN]                  = new CPacketBUTTON(EVENT_HARMONY_CHANDOWN,     "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  875.   multi_map[EVENT_HARMONY_LRGDOWN]                   = new CPacketBUTTON(EVENT_HARMONY_LRGDOWN,      "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  876.   multi_map[EVENT_HARMONY_LRGUP]                     = new CPacketBUTTON(EVENT_HARMONY_LRGUP,        "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  877.   multi_map[EVENT_HARMONY_PWRTOGGLE]                 = new CPacketBUTTON(EVENT_HARMONY_PWRTOGGLE,    "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  878.   multi_map[EVENT_HARMONY_QUEUE]                     = new CPacketBUTTON(EVENT_HARMONY_QUEUE,        "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  879.   multi_map[EVENT_HARMONY_SLEEP]                     = new CPacketBUTTON(EVENT_HARMONY_SLEEP,        "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  880.   multi_map[EVENT_HARMONY_RED]                       = new CPacketBUTTON(EVENT_HARMONY_RED,          "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  881.   multi_map[EVENT_HARMONY_GREEN]                     = new CPacketBUTTON(EVENT_HARMONY_GREEN,        "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  882.   multi_map[EVENT_HARMONY_YELLOW]                    = new CPacketBUTTON(EVENT_HARMONY_YELLOW,       "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  883.   multi_map[EVENT_HARMONY_BLUE]                      = new CPacketBUTTON(EVENT_HARMONY_BLUE,         "JS0:Harmony", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE);
  884.  
  885.   pairedRemoteId = readPairedAddressId();
  886.  
  887.   if(debug) printf("Paired to: %x\n", pairedRemoteId);
  888.  
  889.   if(debug) printf("Ready!\n");
  890.  
  891.   set_led(LEDMODE_WHITE);
  892.  
  893.   int keydown = 0;
  894.  
  895.   set_led(idle_mode);
  896.    
  897.   while(1){
  898.     int result = usb_interrupt_read(get_ir(), 0x82, (char*) &command, sizeof(command), keydown ? BUTTON_TIMEOUT : 0);  
  899.     if(result > 0) {
  900.       // we have an IR code!
  901.       unsigned long start = millis();
  902.       if(debug) printf("Got result: %d\n", result);
  903.       if(debug) printf("Command event: %x\n", command.event);
  904.       if(debug) printf("Command flags: %x\n", command.flags);
  905.       if(debug) dumphex((unsigned char*) &command, result);
  906.      
  907.       if(command.flags == 0x26) {
  908.         // set
  909.         command.event = 0xee;
  910.       }
  911.  
  912.       switch(command.event) {
  913.         case 0xee:
  914.         case 0xe5:
  915.           if(pairedRemoteId == 0 || command.address == pairedRemoteId || (is_multi_candidate(command))) {
  916.             set_led(button_mode);
  917.             handle_button(command);
  918.           }
  919.           break;
  920.         case 0xe0:
  921.           set_led(special_mode);
  922.           handle_special(command);
  923.           break;
  924.         default:
  925.           if(debug) printf("Unknown event %x\n", command.event);
  926.       }
  927.       keydown = 1;
  928.      
  929.     } else if(result == -110) {
  930.       // timeout, reset led
  931.       keydown = 0;                        
  932.       set_led(idle_mode);
  933.       handle_button(timeoutCommand);
  934.       handle_special(timeoutCommand);
  935.     } else {
  936.       // something else
  937.       keydown = 0;
  938.       if(debug) printf("Got nuffing: %d\n", result);
  939.     }
  940.   }
  941.   reattach();
  942. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement