Advertisement
Guest User

Untitled

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