diff options
Diffstat (limited to 'tools/EventClients')
-rw-r--r-- | tools/EventClients/Clients/AppleRemote/AppleRemote.cpp | 645 | ||||
-rw-r--r-- | tools/EventClients/Clients/AppleRemote/AppleRemote.h | 80 | ||||
-rw-r--r-- | tools/EventClients/Clients/AppleRemote/Makefile | 25 | ||||
-rw-r--r-- | tools/EventClients/Clients/AppleRemote/XBox360.h | 576 | ||||
-rw-r--r-- | tools/EventClients/Clients/AppleRemote/iremoted.c | 518 |
5 files changed, 0 insertions, 1844 deletions
diff --git a/tools/EventClients/Clients/AppleRemote/AppleRemote.cpp b/tools/EventClients/Clients/AppleRemote/AppleRemote.cpp deleted file mode 100644 index 1cd8baa730..0000000000 --- a/tools/EventClients/Clients/AppleRemote/AppleRemote.cpp +++ /dev/null @@ -1,645 +0,0 @@ -/* - * AppleRemote.cpp - * AppleRemote - * - * - */ - -#include <stdio.h> -#include <getopt.h> -#include <unistd.h> -#include <stdlib.h> -#include <ctype.h> -#include <sys/errno.h> -#include <sysexits.h> -#include <mach/mach.h> -#include <mach/mach_error.h> -#include <assert.h> -#include <errno.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> -#include <sys/sysctl.h> -#include <sys/stat.h> -#include <sys/time.h> - -#include "AppleRemote.h" -#include "../../lib/c++/xbmcclient.h" - -#define DEFAULT_MAX_CLICK_DURATION 0.5 - -#define LOG if (m_bVerbose) printf - -#define APPLICATION_NAME "XBMC" - -enum { - IR_Select, - IR_SelectHold, - IR_Right, - IR_Left, - IR_Up, - IR_Down, - IR_RightHold, - IR_LeftHold, - IR_Menu, - IR_MenuHold -}; -enum { - IR_Event_Term_ATV1X = 5, - IR_Event_Term_ATV20X = 5, - IR_Event_Term_ATV21 = 8, - IR_Event_Term_10_4 = 5, - IR_Event_Term_10_5 = 18 -}; -// magic HID key cookies AppleTV running r1.x (same as 10.4) -static std::string key_cookiesATV1X[] = -{ - "8_", //SelectHold = "18_" - "18_", - "9_", - "10_", - "12_", - "13_", - "4_", - "3_", - "7_", - "5_" -}; -// magic HID key cookies AppleTV running r2.0x -static std::string key_cookiesATV20X[] = -{ - "8_", //SelectHold = "18_" - "18_", - "9_", - "10_", - "12_", - "13_", - "4_", - "3_", - "5_", - "7_" -}; -// magic HID key cookies for AppleTV running r2.1 -static std::string key_cookiesATV21[] = -{ - "9_", //SelectHold = "19_" - "19_", - "10_", - "11_", - "13_", - "14_", - "5_", - "4_", - "6_", - "8_" -}; -// magic HID key cookies for 10.4 -static std::string key_cookies10_4[] = -{ - "8_", //SelectHold = "18_" - "18_", - "9_", - "10_", - "12_", - "13_", - "4_", - "3_", - "7_", - "5_" -}; - -// magic HID key cookies for 10.5 -static std::string key_cookies10_5[] = -{ - "21_", //SelectHold = "35_" - "35_", - "22_", - "23_", - "29_", - "30_", - "4_", - "3_", - "20_", - "18_" -}; - -AppleRemote::AppleRemote() :m_bVerbose(false), - m_remoteMode(REMOTE_NORMAL), - m_dMaxClickDuration(DEFAULT_MAX_CLICK_DURATION), - m_socket(-1), - m_timer(NULL) -{ - m_serverAddress = "localhost"; - m_appPath = ""; - m_appHome = ""; -} - -AppleRemote::~AppleRemote() -{ - DeInitialize(); -} - -void AppleRemote::RegisterCommand(const std::string &strSequence, CPacketBUTTON *pPacket) -{ - LOG("Registering command %s\n", strSequence.c_str()); - m_mapCommands[strSequence] = pPacket; -} - -void AppleRemote::Initialize() -{ - std::string *key; - std::string prefix; - - LOG("initializing apple remote\n"); - - DeInitialize(); - - m_socket = socket(AF_INET, SOCK_DGRAM, 0); - if (m_socket < 0) - { - fprintf(stderr, "Error opening UDP socket! error: %d\n", errno); - exit(1); - } - - LOG("udp socket (%d) opened\n", m_socket); - - // Runtime Version Check - SInt32 MacVersion; - - Gestalt(gestaltSystemVersion, &MacVersion); - - if (MacVersion < 0x1050) - { - // OSX 10.4/AppleTV - size_t len = 512; - char buffer[512]; - std::string hw_model = "unknown"; - - if (sysctlbyname("hw.model", &buffer, &len, NULL, 0) == 0) - hw_model = buffer; - - if (hw_model == "AppleTV1,1") - { - FILE *inpipe; - bool atv_version_found = false; - char linebuf[1000]; - - //Find the build version of the AppleTV OS - inpipe = popen("sw_vers -buildVersion", "r"); - if (inpipe) - { - //get output - if(fgets(linebuf, sizeof(linebuf) - 1, inpipe)) - { - if( strstr(linebuf,"8N5107") || strstr(linebuf,"8N5239")) - { - // r1.0 or r1.1 - atv_version_found = true; - fprintf(stderr, "Using key code for AppleTV r1.x\n"); - key = key_cookiesATV1X; - m_button_event_terminator = IR_Event_Term_ATV1X; - } - else if (strstr(linebuf,"8N5400") || strstr(linebuf,"8N5455") || strstr(linebuf,"8N5461")) - { - // r2.0, r2.01 or r2.02 - atv_version_found = true; - fprintf(stderr, "Using key code for AppleTV r2.0x\n"); - key = key_cookiesATV20X; - m_button_event_terminator = IR_Event_Term_ATV20X; - } - else if( strstr(linebuf,"8N5519")) - { - // r2.10 - atv_version_found = true; - fprintf(stderr, "Using key code for AppleTV r2.1\n"); - key = key_cookiesATV21; - m_button_event_terminator = IR_Event_Term_ATV21; - - } - else if( strstr(linebuf,"8N5622")) - { - // r2.10 - atv_version_found = true; - fprintf(stderr, "Using key code for AppleTV r2.2\n"); - key = key_cookiesATV21; - m_button_event_terminator = IR_Event_Term_ATV21; - } - } - pclose(inpipe); - } - - if(!atv_version_found){ - //handle fallback or just exit - fprintf(stderr, "AppletTV software version could not be determined.\n"); - fprintf(stderr, "Defaulting to using key code for AppleTV r2.1\n"); - key = key_cookiesATV21; - m_button_event_terminator = IR_Event_Term_ATV21; - } - } - else - { - fprintf(stderr, "Using key code for OSX 10.4\n"); - key = key_cookies10_4; - m_button_event_terminator = IR_Event_Term_10_4; - } - } - else - { - // OSX 10.5 - fprintf(stderr, "Using key code for OSX 10.5\n"); - key = key_cookies10_5; - m_button_event_terminator = IR_Event_Term_10_5; - } - m_launch_xbmc_button = key[IR_MenuHold]; - - RegisterCommand(key[IR_Select], new CPacketBUTTON(5, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(key[IR_SelectHold],new CPacketBUTTON(7, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(key[IR_Right], new CPacketBUTTON(4, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(key[IR_Left], new CPacketBUTTON(3, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(key[IR_Up], new CPacketBUTTON(1, "JS0:AppleRemote", BTN_DOWN)); - RegisterCommand(key[IR_Down], new CPacketBUTTON(2, "JS0:AppleRemote", BTN_DOWN)); - RegisterCommand(key[IR_RightHold], new CPacketBUTTON(4, "JS0:AppleRemote", BTN_DOWN)); - RegisterCommand(key[IR_LeftHold], new CPacketBUTTON(3, "JS0:AppleRemote", BTN_DOWN)); - - RegisterCommand(key[IR_Menu], new CPacketBUTTON(6, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - - // Menu Hold will be used both for sending "Back" and for starting universal remote combinations (if universal mode is on) - RegisterCommand(key[IR_MenuHold], new CPacketBUTTON(8, "JS0:AppleRemote", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - - // Universal commmands: - RegisterCommand(key[IR_MenuHold] + key[IR_Down], new CPacketBUTTON("Back", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - - prefix = key[IR_MenuHold] + key[IR_Select]; - RegisterCommand(prefix + key[IR_Right], new CPacketBUTTON("Info", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(prefix + key[IR_Left], new CPacketBUTTON("Title", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(prefix + key[IR_Up], new CPacketBUTTON("PagePlus", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(prefix + key[IR_Down], new CPacketBUTTON("PageMinus", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(prefix + key[IR_Select],new CPacketBUTTON("Display", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - - prefix = key[IR_MenuHold] + key[IR_Up]; - - RegisterCommand(prefix + key[IR_Select],new CPacketBUTTON("Stop", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(prefix + key[IR_Left], new CPacketBUTTON("Power", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(prefix + key[IR_Right], new CPacketBUTTON("Zero", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(prefix + key[IR_Up], new CPacketBUTTON("Play", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - RegisterCommand(prefix + key[IR_Down], new CPacketBUTTON("Pause", "R1", BTN_DOWN | BTN_NO_REPEAT | BTN_QUEUE)); - - // for universal mode - some keys are part of a key combination. - // when those keys are pressed, we'll wait for more to come - until a valid combination was entered or a timeout expired. - // the keys "leading" a combination are added to the prefix vector. - // all we need to do to turn universal mode off is clear the prefix vector and then every command will be sent immidiately. - if (m_remoteMode == REMOTE_UNIVERSAL) - { - LOG("universal mode on. registering prefixes: %s\n", key[IR_MenuHold].c_str()); - m_universalPrefixes.push_back( key[IR_MenuHold] ); - } - else - { - LOG("universal mode off.\n"); - m_universalPrefixes.clear(); - } - - m_strCombination.clear(); - m_bSendUpRequired = false; -} - -void AppleRemote::DeInitialize() -{ - LOG("uninitializing apple remote\n"); - - ResetTimer(); - - if (m_socket > 0) - close(m_socket); - - m_socket = -1; - - LOG("deleting commands map\n"); - std::map<std::string, CPacketBUTTON *>::iterator iter = m_mapCommands.begin(); - while (iter != m_mapCommands.end()) - { - delete iter->second; - iter++; - } - m_mapCommands.clear(); - m_strCombination.clear(); -} - -void AppleRemote::SetTimer() -{ - if (m_timer) - ResetTimer(); - - LOG("setting timer to expire in %.2f secs. \n", m_dMaxClickDuration); - CFRunLoopTimerContext context = { 0, this, 0, 0, 0 }; - m_timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + m_dMaxClickDuration, 0, 0, 0, TimerCallBack, &context); - CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_timer, kCFRunLoopCommonModes); -} - -void AppleRemote::ResetTimer() -{ - if (m_timer) - { - LOG("removing timer\n"); - - CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), m_timer, kCFRunLoopCommonModes); - CFRunLoopTimerInvalidate(m_timer); - CFRelease(m_timer); - } - - m_timer = NULL; -} - -void AppleRemote::SetMaxClickDuration(double dDuration) -{ - m_dMaxClickDuration = dDuration; - LOG("setting click max duration to %.2f seconds\n", dDuration); -} - -void AppleRemote::TimerCallBack (CFRunLoopTimerRef timer, void *info) -{ - if (!info) - { - fprintf(stderr, "Error. invalid argument to timer callback\n"); - return; - } - - AppleRemote *pRemote = (AppleRemote *)info; - pRemote->SendCommand(pRemote->m_strCombination); - pRemote->m_strCombination.clear(); - pRemote->ResetTimer(); -} - -bool AppleRemote::SendCommand(const std::string &key) -{ - CPacketBUTTON *pPacket = m_mapCommands[key]; - if (pPacket) - { - LOG("Sending command for Key (%s)\n", key.c_str()); - CAddress addr(m_serverAddress.c_str()); - pPacket->Send(m_socket, addr); - - if ( 0 == (pPacket->GetFlags() & BTN_NO_REPEAT) ) - m_bSendUpRequired = true; - else - m_bSendUpRequired = false; - } - - return pPacket != NULL; -} - -void AppleRemote::LaunchApp() -{ - // the path to xbmc.app is passed as an arg, - // use this to launch from a menu press - LOG("Trying to start XBMC: [%s]\n", m_appPath.c_str()); - if (!m_appPath.empty()) - { - std::string strCmd; - - // build a finder open command - strCmd = "XBMC_HOME="; - strCmd += m_appHome; - strCmd += " "; - strCmd += m_appPath; - strCmd += " &"; - LOG("xbmc open command: [%s]\n", strCmd.c_str()); - system(strCmd.c_str()); - } -} - -void AppleRemote::SendPacket(CPacketBUTTON &packet) -{ - CAddress addr(m_serverAddress.c_str()); - packet.Send(m_socket, addr); -} - -void AppleRemote::OnKeyDown(const std::string &key) -{ - if (!IsProgramRunning(APPLICATION_NAME) && (m_serverAddress == "localhost" || m_serverAddress == "127.0.0.1")) - { - if (key == m_launch_xbmc_button) - LaunchApp(); - - return; - } - - LOG("key down: %s\n", key.c_str()); - if (m_remoteMode == REMOTE_NORMAL) { - SendCommand(key); - } - else if (m_remoteMode == REMOTE_UNIVERSAL) - { - bool bCombinationStart = false; - bool bNeedTimer = false; - if (m_strCombination.empty()) - { - bNeedTimer = true; - for (size_t i=0; i<m_universalPrefixes.size(); i++) - { - if (m_universalPrefixes[i] == key) - { - LOG("start of combination (key=%s)\n", key.c_str()); - bCombinationStart = true; - break; - } - } - } - - m_strCombination += key; - - if (bCombinationStart) - SetTimer(); - else - { - if (SendCommand(m_strCombination)) - { - m_strCombination.clear(); - ResetTimer(); - } - else if (bNeedTimer) - SetTimer(); - } - } -} - -void AppleRemote::OnKeyUp(const std::string &key) -{ - LOG("key up: %s\n", key.c_str()); - if (m_bSendUpRequired) - { - LOG("sending key-up event\n"); - CPacketBUTTON btn; - CAddress addr(m_serverAddress.c_str()); - btn.Send(m_socket, addr); - } - else - { - LOG("no need to send UP event\n"); - } -} - -void AppleRemote::SetVerbose(bool bVerbose) -{ - m_bVerbose = bVerbose; -} - -bool AppleRemote::IsVerbose() -{ - return m_bVerbose; -} - -void AppleRemote::SetMaxClickTimeout(double dTimeout) -{ - m_dMaxClickDuration = dTimeout; -} - -void AppleRemote::SetServerAddress(const std::string &strAddress) -{ - m_serverAddress = strAddress; -} - -void AppleRemote::SetAppPath(const std::string &strAddress) -{ - m_appPath = strAddress; -} - -void AppleRemote::SetAppHome(const std::string &strAddress) -{ - m_appHome = strAddress; -} - -const std::string &AppleRemote::GetServerAddress() -{ - return m_serverAddress; -} - -void AppleRemote::SetRemoteMode(RemoteModes mode) -{ - m_remoteMode = mode; -} - -bool AppleRemote::IsProgramRunning(const char* strProgram, int ignorePid) -{ - kinfo_proc* mylist = (kinfo_proc *)malloc(sizeof(kinfo_proc)); - size_t mycount = 0; - bool ret = false; - - GetBSDProcessList(&mylist, &mycount); - for(size_t k = 0; k < mycount && ret == false; k++) - { - kinfo_proc *proc = NULL; - proc = &mylist[k]; - - //LOG("proc->kp_proc.p_comm: %s\n", proc->kp_proc.p_comm); - // Process names are at most sixteen characters long. - if (strncmp(proc->kp_proc.p_comm, strProgram, 16) == 0) - { - if (ignorePid == 0 || ignorePid != proc->kp_proc.p_pid) - { - //LOG("found: %s\n", proc->kp_proc.p_comm); - ret = true; - } - } - } - free(mylist); - return ret; -} - -int AppleRemote::GetBSDProcessList(kinfo_proc **procList, size_t *procCount) - // Returns a list of all BSD processes on the system. This routine - // allocates the list and puts it in *procList and a count of the - // number of entries in *procCount. You are responsible for freeing - // this list (use "free" from System framework). - // On success, the function returns 0. - // On error, the function returns a BSD errno value. -{ - int err; - kinfo_proc * result; - bool done; - static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; - // Declaring name as const requires us to cast it when passing it to - // sysctl because the prototype doesn't include the const modifier. - size_t length; - - assert( procList != NULL); - assert(procCount != NULL); - - *procCount = 0; - - // We start by calling sysctl with result == NULL and length == 0. - // That will succeed, and set length to the appropriate length. - // We then allocate a buffer of that size and call sysctl again - // with that buffer. If that succeeds, we're done. If that fails - // with ENOMEM, we have to throw away our buffer and loop. Note - // that the loop causes use to call sysctl with NULL again; this - // is necessary because the ENOMEM failure case sets length to - // the amount of data returned, not the amount of data that - // could have been returned. - - result = NULL; - done = false; - do { - assert(result == NULL); - - // Call sysctl with a NULL buffer. - - length = 0; - err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, - NULL, &length, - NULL, 0); - if (err == -1) { - err = errno; - } - - // Allocate an appropriately sized buffer based on the results - // from the previous call. - - if (err == 0) { - result = (kinfo_proc* )malloc(length); - if (result == NULL) { - err = ENOMEM; - } - } - - // Call sysctl again with the new buffer. If we get an ENOMEM - // error, toss away our buffer and start again. - - if (err == 0) { - err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1, - result, &length, - NULL, 0); - if (err == -1) { - err = errno; - } - if (err == 0) { - done = true; - } else if (err == ENOMEM) { - assert(result != NULL); - free(result); - result = NULL; - err = 0; - } - } - } while (err == 0 && ! done); - - // Clean up and establish post conditions. - - if (err != 0 && result != NULL) { - free(result); - result = NULL; - } - *procList = result; - if (err == 0) { - *procCount = length / sizeof(kinfo_proc); - } - - assert( (err == 0) == (*procList != NULL) ); - - return err; -} - -int AppleRemote::GetButtonEventTerminator(void) -{ - return(m_button_event_terminator); -} diff --git a/tools/EventClients/Clients/AppleRemote/AppleRemote.h b/tools/EventClients/Clients/AppleRemote/AppleRemote.h deleted file mode 100644 index 45e3a427bc..0000000000 --- a/tools/EventClients/Clients/AppleRemote/AppleRemote.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * AppleRemote.h - * AppleRemote - * - * - */ -#ifndef __APPLE__REMOTE__H__ -#define __APPLE__REMOTE__H__ - -#include <ctype.h> -#include <Carbon/Carbon.h> - -#include <vector> -#include <map> -#include <string> - -typedef enum { REMOTE_NONE, REMOTE_NORMAL, REMOTE_UNIVERSAL } RemoteModes; -typedef struct kinfo_proc kinfo_proc; - -class CPacketBUTTON; -class AppleRemote -{ -public: - AppleRemote(); - virtual ~AppleRemote(); - - void Initialize(); - void DeInitialize(); - - void ResetTimer(); - void SetTimer(); - - void OnKeyDown(const std::string &key); - void OnKeyUp(const std::string &key); - - int GetButtonEventTerminator(void); - - void SetMaxClickDuration(double dDuration); - - void SetVerbose(bool bVerbose); - bool IsVerbose(); - - void SetMaxClickTimeout(double dTimeout); - void SetServerAddress(const std::string &strAddress); - void SetAppPath(const std::string &strAddress); - void SetAppHome(const std::string &strAddress); - void SetRemoteMode(RemoteModes mode); - - const std::string &GetServerAddress(); - - static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount); - bool IsProgramRunning(const char* strProgram, int ignorePid=0); - void LaunchApp(); - - void SendPacket(CPacketBUTTON &packet); - -protected: - static void TimerCallBack (CFRunLoopTimerRef timer, void *info); - void RegisterCommand(const std::string &strSequence, CPacketBUTTON *pPacket); - bool SendCommand(const std::string &key); - void ParseConfig(); - - bool m_bVerbose; - bool m_bSendUpRequired; - RemoteModes m_remoteMode; - double m_dMaxClickDuration; - int m_socket; - std::string m_strCombination; - std::string m_serverAddress; - std::string m_appPath; - std::string m_appHome; - - std::map<std::string, CPacketBUTTON *> m_mapCommands; - std::vector<std::string> m_universalPrefixes; - std::string m_launch_xbmc_button; - int m_button_event_terminator; - CFRunLoopTimerRef m_timer; -}; - -#endif diff --git a/tools/EventClients/Clients/AppleRemote/Makefile b/tools/EventClients/Clients/AppleRemote/Makefile deleted file mode 100644 index 63518afe16..0000000000 --- a/tools/EventClients/Clients/AppleRemote/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -CXX=g++ -CC=g++ - -CFLAGS+=-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -CFLAGS+=-Wall -LDFLAGS+=-framework IOKit -framework Carbon -framework ForceFeedback - -OBJS = iremoted.o AppleRemote.o - -TARGET = ../../../osx/XBMCHelper -CLEAN_FILES=$(TARGET) - -all: $(TARGET) - -$(TARGET): $(OBJS) - g++ $(LDFLAGS) $(OBJS) -o $(TARGET) - -.cpp.o: - $(CXX) -c $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o ${<:.cpp=.o} - -.c.o: - $(CC) -c $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o ${<:.c=.o} - -clean: - $(RM) -rf *.o ../../../osx/XBMCHelper diff --git a/tools/EventClients/Clients/AppleRemote/XBox360.h b/tools/EventClients/Clients/AppleRemote/XBox360.h deleted file mode 100644 index 88d6a0cb94..0000000000 --- a/tools/EventClients/Clients/AppleRemote/XBox360.h +++ /dev/null @@ -1,576 +0,0 @@ -#ifndef __XBOX360_H__ -#define __XBOX360_H__ - -#include <IOKit/usb/IOUSBLib.h> -#include <IOKit/IOKitLib.h> -#include <IOKit/IOCFPlugIn.h> -#include <IOKit/hid/IOHIDLib.h> -#include <IOKit/hid/IOHIDKeys.h> -#include <IOKit/hid/IOHIDUsageTables.h> - -#include <ForceFeedback/ForceFeedback.h> - -#include <pthread.h> -#include <string> -#include <list> - -#include "AppleRemote.h" -#include "../../lib/c++/xbmcclient.h" - -#define SAFELY(expr) if ((expr) != kIOReturnSuccess) { printf("ERROR: \"%s\".\n", #expr); return; } - -extern AppleRemote g_appleRemote; - -class XBox360Controller -{ - public: - - static XBox360Controller* XBox360Controller::Create(io_service_t device, int deviceNum, bool deviceWireless) - { - XBox360Controller* controller = new XBox360Controller(); - IOReturn ret; - IOCFPlugInInterface **plugInInterface; - SInt32 score=0; - - ret = IOCreatePlugInInterfaceForService(device, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); - if (ret == kIOReturnSuccess) - { - ret = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID122), (LPVOID*)&controller->hidDevice); - (*plugInInterface)->Release(plugInInterface); - if (ret == kIOReturnSuccess) - { - controller->forceFeedback=0; - FFCreateDevice(device, &controller->forceFeedback); - controller->index = deviceNum; - controller->deviceHandle = device; - controller->wireless = deviceWireless; - - char str[128]; - sprintf(str, "%s Controller %d", deviceWireless ? "Wireless" : "Wired", deviceNum); - controller->name = str; - - return controller; - } - } - - return 0; - } - - ~XBox360Controller() - { - if (deviceHandle != 0) IOObjectRelease(deviceHandle); - if (hidDevice != 0) (*hidDevice)->Release(hidDevice); - if (forceFeedback != 0) FFReleaseDevice(forceFeedback); - } - - void start() - { - int i,j; - CFRunLoopSourceRef eventSource; - - // Get serial. - FFEFFESCAPE escape; - unsigned char c; - std::string serial; - - serial = getSerialNumber(); - //printf("SERIAL: %s, forceFeedback: 0x%08lx\n", serial.c_str(), forceFeedback); - - CFArrayRef elements; - SAFELY((*hidDevice)->copyMatchingElements(hidDevice, NULL, &elements)); - - for(i=0; i<CFArrayGetCount(elements); i++) - { - CFDictionaryRef element = (CFDictionaryRef)CFArrayGetValueAtIndex(elements, i); - long usage, usagePage, longCookie; - - // Get cookie. - if (getVal(element, CFSTR(kIOHIDElementCookieKey), longCookie) && - getVal(element, CFSTR(kIOHIDElementUsageKey), usage) && - getVal(element, CFSTR(kIOHIDElementUsagePageKey), usagePage)) - { - IOHIDElementCookie cookie = (IOHIDElementCookie)longCookie; - - // Match up items - switch (usagePage) - { - case 0x01: // Generic Desktop - j=0; - switch (usage) - { - case 0x35: j++; // Right trigger - case 0x32: j++; // Left trigger - case 0x34: j++; // Right stick Y - case 0x33: j++; // Right stick X - case 0x31: j++; // Left stick Y - case 0x30: // Left stick X - axis[j] = cookie; - break; - default: - break; - } - break; - - case 0x09: // Button - if (usage >= 1 && usage <= 15) - { - // Button 1-11 - buttons[usage-1] = cookie; - } - break; - - default: - break; - } - } - } - - // Start queue. - SAFELY((*hidDevice)->open(hidDevice, 0)); - - hidQueue = (*hidDevice)->allocQueue(hidDevice); - if (hidQueue == NULL) - { - printf("Unable to allocate queue\n"); - return; - } - - // Create queue, set callback. - SAFELY((*hidQueue)->create(hidQueue, 0, 32)); - SAFELY((*hidQueue)->createAsyncEventSource(hidQueue, &eventSource)); - SAFELY((*hidQueue)->setEventCallout(hidQueue, CallbackFunction, this, NULL)); - - // Add to runloop. - CFRunLoopAddSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopCommonModes); - - // Add the elements. - for(i=0; i<6; i++) - (*hidQueue)->addElement(hidQueue, axis[i], 0); - for(i=0; i<15; i++) - (*hidQueue)->addElement(hidQueue, buttons[i], 0); - - // Start. - SAFELY((*hidQueue)->start(hidQueue)); - -#if 0 - // Read existing properties - { -// CFDictionaryRef dict=(CFDictionaryRef)IORegistryEntryCreateCFProperty(registryEntry,CFSTR("DeviceData"),NULL,0); - CFDictionaryRef dict = (CFDictionaryRef)[GetController(GetSerialNumber(registryEntry)) retain]; - if(dict!=0) { - CFBooleanRef boolValue; - CFNumberRef intValue; - - if(CFDictionaryGetValueIfPresent(dict,CFSTR("InvertLeftX"),(void*)&boolValue)) { - [leftStickInvertX setState:CFBooleanGetValue(boolValue)?NSOnState:NSOffState]; - } else NSLog(@"No value for InvertLeftX"); - if(CFDictionaryGetValueIfPresent(dict,CFSTR("InvertLeftY"),(void*)&boolValue)) { - [leftStickInvertY setState:CFBooleanGetValue(boolValue)?NSOnState:NSOffState]; - } else NSLog(@"No value for InvertLeftY"); - if(CFDictionaryGetValueIfPresent(dict,CFSTR("RelativeLeft"),(void*)&boolValue)) { - BOOL enable=CFBooleanGetValue(boolValue); - [leftLinked setState:enable?NSOnState:NSOffState]; - [leftStick setLinked:enable]; - } else NSLog(@"No value for RelativeLeft"); - if(CFDictionaryGetValueIfPresent(dict,CFSTR("DeadzoneLeft"),(void*)&intValue)) { - UInt16 i; - - CFNumberGetValue(intValue,kCFNumberShortType,&i); - [leftStickDeadzone setIntValue:i]; - [leftStick setDeadzone:i]; - } else NSLog(@"No value for DeadzoneLeft"); - if(CFDictionaryGetValueIfPresent(dict,CFSTR("InvertRightX"),(void*)&boolValue)) { - [rightStickInvertX setState:CFBooleanGetValue(boolValue)?NSOnState:NSOffState]; - } else NSLog(@"No value for InvertRightX"); - if(CFDictionaryGetValueIfPresent(dict,CFSTR("InvertRightY"),(void*)&boolValue)) { - [rightStickInvertY setState:CFBooleanGetValue(boolValue)?NSOnState:NSOffState]; - } else NSLog(@"No value for InvertRightY"); - if(CFDictionaryGetValueIfPresent(dict,CFSTR("RelativeRight"),(void*)&boolValue)) { - BOOL enable=CFBooleanGetValue(boolValue); - [rightLinked setState:enable?NSOnState:NSOffState]; - [rightStick setLinked:enable]; - } else NSLog(@"No value for RelativeRight"); - if(CFDictionaryGetValueIfPresent(dict,CFSTR("DeadzoneRight"),(void*)&intValue)) { - UInt16 i; - - CFNumberGetValue(intValue,kCFNumberShortType,&i); - [rightStickDeadzone setIntValue:i]; - [rightStick setDeadzone:i]; - } else NSLog(@"No value for DeadzoneRight"); - CFRelease(dict); - } else NSLog(@"No settings found"); - } - - // Set LED and manual motor control - // [self updateLED:0x0a]; - [self setMotorOverride:TRUE]; - [self testMotorsLarge:0 small:0]; - largeMotor=0; - smallMotor=0; - - // Battery level? - { - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - NSString *path; - CFTypeRef prop; - - path = nil; - if (IOObjectConformsTo(registryEntry, "WirelessHIDDevice")) - { - prop = IORegistryEntryCreateCFProperty(registryEntry, CFSTR("BatteryLevel"), NULL, 0); - if (prop != nil) - { - unsigned char level; - - if (CFNumberGetValue(prop, kCFNumberCharType, &level)) - path = [bundle pathForResource:[NSString stringWithFormat:@"batt%i", level / 64] ofType:@"tif"]; - CFRelease(prop); - } - } - if (path == nil) - path = [bundle pathForResource:@"battNone" ofType:@"tif"]; - [batteryLevel setImage:[[[NSImage alloc] initByReferencingFile:path] autorelease]]; - } - } - #endif - - c = 0x0a; - if (serial.length() > 0) - { - #if 0 - for (int i = 0; i < 4; i++) - { - if ((leds[i] == nil) || ([leds[i] caseInsensitiveCompare:serial] == NSOrderedSame)) - { - c = 0x06 + i; - if (leds[i] == nil) - { - //leds[i] = [serial retain]; - printf("Added controller with LED %i\n", i); - } - break; - } - } - #endif - } - c = 0x06; - escape.dwSize = sizeof(escape); - escape.dwCommand = 0x02; - escape.cbInBuffer = sizeof(c); - escape.lpvInBuffer = &c; - escape.cbOutBuffer = 0; - escape.lpvOutBuffer = NULL; - if (FFDeviceEscape(forceFeedback, &escape) != FF_OK) - printf("Error: FF\n"); - } - - void stop() - { - if (hidQueue != 0) - { - // Stop the queue. - (*hidQueue)->stop(hidQueue); - - // Remove from the run loop. - CFRunLoopSourceRef eventSource = (*hidQueue)->getAsyncEventSource(hidQueue); - if ((eventSource != 0) && CFRunLoopContainsSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopCommonModes)) - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopCommonModes); - - // Whack. - (*hidQueue)->Release(hidQueue); - hidQueue = 0; - } - - if (hidDevice != 0) - (*hidDevice)->close(hidDevice); - } - - std::string getName() { return name; } - - private: - - XBox360Controller() - { - for (int i=0; i<15; i++) - buttons[i] = 0; - - for (int i=0; i<6; i++) - axis[i] = 0; - } - - std::string getSerialNumber() - { - CFTypeRef value = IORegistryEntrySearchCFProperty(deviceHandle, kIOServicePlane, CFSTR("SerialNumber"), kCFAllocatorDefault, kIORegistryIterateRecursively); - std::string ret = std::string(CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingMacRoman)); - CFRelease(value); - - return ret; - } - - void updateLED(int ledIndex) - { - FFEFFESCAPE escape; - unsigned char c; - - if (forceFeedback ==0 ) - return; - - c = ledIndex; - escape.dwSize = sizeof(escape); - escape.dwCommand = 0x02; - escape.cbInBuffer = sizeof(c); - escape.lpvInBuffer = &c; - escape.cbOutBuffer = 0; - escape.lpvOutBuffer = NULL; - - if (FFDeviceEscape(forceFeedback, &escape) != FF_OK) - printf("ERROR: FFDeviceEscape.\n"); - } - - static void CallbackFunction(void* me, IOReturn result, void* refCon, void* sender) - { - ((XBox360Controller* )me)->handleCallback(result, refCon, sender); - } - - void handleCallback(IOReturn result, void* refCon, void* sender) - { - AbsoluteTime zeroTime={0,0}; - IOHIDEventStruct event; - bool found = false; - int i; - - if (sender != hidQueue) - return; - - while (result == kIOReturnSuccess) - { - result = (*hidQueue)->getNextEvent(hidQueue, &event, zeroTime, 0); - if (result != kIOReturnSuccess) - continue; - - // Check axis - for (i=0, found=FALSE; (i<6) && (!found); i++) - { - if (event.elementCookie == axis[i]) - { - int amount = 0; - if (i == 4 || i == 5) - amount = event.value * (32768/256) + 32768; - else - amount = 65536 - (event.value + 32768) - 1; - - // Clip. - if (amount > 65535) - amount = 65535; - if (amount < 0) - amount = 0; - - if (g_appleRemote.IsVerbose()) - printf("Axis %d %d.\n", i+1, amount); - CPacketBUTTON btn(i+1, "JS1:Wireless 360 Controller", BTN_AXIS | BTN_NO_REPEAT | BTN_USE_AMOUNT | BTN_QUEUE, amount); - g_appleRemote.SendPacket(btn); - - found = true; - } - } - - if (found) continue; - - // Check buttons - for (i=0, found=FALSE; (i<15) && (!found); i++) - { - if (event.elementCookie == buttons[i]) - { - if (g_appleRemote.IsVerbose()) - printf("Button: %d %d.\n", i+1, (int)event.value); - - if (i+1 == 11 && !g_appleRemote.IsProgramRunning("XBMC", 0) && - (g_appleRemote.GetServerAddress() == "127.0.0.1" || g_appleRemote.GetServerAddress() == "localhost") && - event.value) - { - g_appleRemote.LaunchApp(); - return; - } - - int flags = event.value ? BTN_DOWN : BTN_UP; - CPacketBUTTON btn(i+1, "JS1:Wireless 360 Controller", flags, 0); - g_appleRemote.SendPacket(btn); - found = true; - } - } - - if (found) continue; - - // Cookie wasn't for us? - } - } - - bool getVal(CFDictionaryRef element, const CFStringRef key, long& value) - { - CFTypeRef object = CFDictionaryGetValue(element, key); - - if ((object == NULL) || (CFGetTypeID(object) != CFNumberGetTypeID())) return false; - if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &value)) return false; - - return true; - } - - IOHIDDeviceInterface122 **hidDevice; - FFDeviceObjectReference forceFeedback; - io_service_t deviceHandle; - - IOHIDQueueInterface **hidQueue; - IOHIDElementCookie axis[6]; - IOHIDElementCookie buttons[15]; - - std::string name; - int index; - bool wireless; -}; - - -class XBox360 -{ - public: - - XBox360() - { - } - - void start() - { - pthread_create(&_itsThread, NULL, Run, (void *)this); - } - - void join() - { - void* val = 0; - pthread_join(_itsThread, &val); - } - - protected: - - static void* Run(void* param) - { - ((XBox360* )param)->run(); - return 0; - } - - void run() - { - printf("XBOX360: Registering for notifications.\n"); - io_object_t object; - - // Register for wired notifications. - IONotificationPortRef notificationObject = IONotificationPortCreate(kIOMasterPortDefault); - IOServiceAddMatchingNotification(notificationObject, kIOFirstMatchNotification, IOServiceMatching(kIOUSBDeviceClassName), callbackHandleDevice, this, &_itsOnIteratorWired); - callbackHandleDevice(this, _itsOnIteratorWired); - - IOServiceAddMatchingNotification(notificationObject, kIOTerminatedNotification, IOServiceMatching(kIOUSBDeviceClassName), callbackHandleDevice, this, &_itsOffIteratorWired); - while ((object = IOIteratorNext(_itsOffIteratorWired)) != 0) - IOObjectRelease(object); - - // Wireless notifications. - IOServiceAddMatchingNotification(notificationObject, kIOFirstMatchNotification, IOServiceMatching("WirelessHIDDevice"), callbackHandleDevice, this, &_itsOnIteratorWireless); - callbackHandleDevice(this, _itsOnIteratorWireless); - - IOServiceAddMatchingNotification(notificationObject, kIOTerminatedNotification, IOServiceMatching("WirelessHIDDevice"), callbackHandleDevice, this, &_itsOffIteratorWireless); - while ((object = IOIteratorNext(_itsOffIteratorWireless)) != 0) - IOObjectRelease(object); - - // Add notifications to the run loop. - CFRunLoopSourceRef notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationObject); - CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode); - - // Run. - CFRunLoopRun(); - printf("XBOX360: Exiting.\n"); - } - - private: - - // Callback for Xbox360 device notifications. - static void callbackHandleDevice(void* param, io_iterator_t iterator) - { - io_service_t object = 0; - bool update = false; - - while ((object = IOIteratorNext(iterator))!=0) - { - IOObjectRelease(object); - update = true; - } - - if (update) - ((XBox360* )param)->updateDeviceList(); - } - - void updateDeviceList() - { - io_iterator_t iterator; - io_object_t hidDevice; - - // Scrub and whack old items. - stopDevices(); - - for (std::list<XBox360Controller*>::iterator i = controllerList.begin(); i != controllerList.end(); ++i) - delete *i; - controllerList.clear(); - - // Add new items - CFMutableDictionaryRef hidDictionary = IOServiceMatching(kIOHIDDeviceKey); - IOReturn ioReturn = IOServiceGetMatchingServices(kIOMasterPortDefault, hidDictionary, &iterator); - - if ((ioReturn != kIOReturnSuccess) || (iterator==0)) - { - printf("No devices.\n"); - return; - } - - for (int count = 1; (hidDevice = IOIteratorNext(iterator)); ) - { - bool deviceWired = IOObjectConformsTo(hidDevice, "Xbox360ControllerClass"); - bool deviceWireless = IOObjectConformsTo(hidDevice, "WirelessHIDDevice"); - - if (deviceWired || deviceWireless) - { - XBox360Controller* controller = XBox360Controller::Create(hidDevice, count, deviceWireless); - if (controller) - { - // Add to list. - printf("Adding device: %s.\n", controller->getName().c_str()); - controllerList.push_back(controller); - count++; - } - } - else - { - IOObjectRelease(hidDevice); - } - } - - IOObjectRelease(iterator); - - // Make sure all devices are started. - startDevices(); - } - - void stopDevices() - { - for (std::list<XBox360Controller*>::iterator i = controllerList.begin(); i != controllerList.end(); ++i) - (*i)->stop(); - } - - void startDevices() - { - for (std::list<XBox360Controller*>::iterator i = controllerList.begin(); i != controllerList.end(); ++i) - (*i)->start(); - } - - std::list<XBox360Controller*> controllerList; - pthread_t _itsThread; - io_iterator_t _itsOnIteratorWired, _itsOffIteratorWired; - io_iterator_t _itsOnIteratorWireless, _itsOffIteratorWireless; -}; - -#endif diff --git a/tools/EventClients/Clients/AppleRemote/iremoted.c b/tools/EventClients/Clients/AppleRemote/iremoted.c deleted file mode 100644 index 42b3258d03..0000000000 --- a/tools/EventClients/Clients/AppleRemote/iremoted.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * iremoted.c - * Display events received from the Apple Infrared Remote. - * - * gcc -Wall -o iremoted iremoted.c -framework IOKit -framework Carbon - * - * Copyright (c) 2006-2008 Amit Singh. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#define PROGNAME "iremoted" -#define PROGVERS "2.0" - -#include <stdio.h> -#include <getopt.h> -#include <unistd.h> -#include <stdlib.h> -#include <ctype.h> -#include <sys/errno.h> -#include <sysexits.h> -#include <mach/mach.h> -#include <mach/mach_error.h> -#include <assert.h> -#include <errno.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> -#include <sys/sysctl.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <mach-o/dyld.h> -#include <IOKit/IOKitLib.h> -#include <IOKit/IOCFPlugIn.h> -#include <IOKit/hid/IOHIDLib.h> -#include <IOKit/hid/IOHIDKeys.h> -#include <IOKit/hid/IOHIDUsageTables.h> - -#include <CoreFoundation/CoreFoundation.h> -#include <Carbon/Carbon.h> - -#include <iostream> -#include <fstream> -#include <map> -#include <string> -#include <iterator> -#include <sstream> -#include <set> - -#include "AppleRemote.h" -#include "XBox360.h" - -using namespace std; - -void ParseOptions(int argc, char** argv); -void ReadConfig(); - -static struct option long_options[] = { - { "help", no_argument, 0, 'h' }, - { "server", required_argument, 0, 's' }, - { "universal", no_argument, 0, 'u' }, - { "multiremote",no_argument, 0, 'm' }, - { "timeout", required_argument, 0, 't' }, - { "verbose", no_argument, 0, 'v' }, - { "externalConfig", no_argument, 0, 'x' }, - { "appPath", required_argument, 0, 'a' }, - { "appHome", required_argument, 0, 'z' }, - { 0, 0, 0, 0 }, -}; - -static const char *options = "hsumtvxaz"; - -IOHIDElementCookie buttonNextID = 0; -IOHIDElementCookie buttonPreviousID = 0; - -std::set<IOHIDElementCookie> g_registeredCookies; - -AppleRemote g_appleRemote; - -void usage(void); -inline void print_errmsg_if_io_err(int expr, char *msg); -inline void print_errmsg_if_err(int expr, char *msg); -void QueueCallbackFunction(void *target, IOReturn result, - void *refcon, void *sender); -bool addQueueCallbacks(IOHIDQueueInterface **hqi); -void processQueue(IOHIDDeviceInterface **hidDeviceInterface); -void doRun(IOHIDDeviceInterface **hidDeviceInterface); -void getHIDCookies(IOHIDDeviceInterface122 **handle); -void createHIDDeviceInterface(io_object_t hidDevice, - IOHIDDeviceInterface ***hdi); -void setupAndRun(void); - -void -usage(void) -{ - printf("%s (version %s)\n", PROGNAME, PROGVERS); - printf(" Sends Apple Remote events to XBMC.\n\n"); - printf("Usage: %s [OPTIONS...]\n\nOptions:\n", PROGNAME); - printf(" -h, --help print this help message and exit.\n"); - printf(" -s, --server <addr> send events to the specified IP.\n"); - printf(" -u, --universal runs in Universal Remote mode.\n"); - printf(" -t, --timeout <ms> timeout length for sequences (default: 500ms).\n"); - printf(" -a, --appPath path to XBMC.app (MenuPress launch support).\n"); - printf(" -z, --appHome path to XBMC.app/Content/Resources/XBMX \n"); - printf(" -v, --verbose prints lots of debugging information.\n"); -} - -inline void -print_errmsg_if_io_err(int expr, char *msg) -{ - IOReturn err = (expr); - - if (err != kIOReturnSuccess) { - fprintf(stderr, "*** %s - %s(%x, %d).\n", msg, mach_error_string(err), - err, err & 0xffffff); - fflush(stderr); - exit(EX_OSERR); - } -} - -inline void -print_errmsg_if_err(int expr, char *msg) -{ - if (expr) { - fprintf(stderr, "*** %s.\n", msg); - fflush(stderr); - exit(EX_OSERR); - } -} - -void -QueueCallbackFunction(void *target, IOReturn result, void *refcon, void *sender) -{ - HRESULT ret = kIOReturnSuccess; - AbsoluteTime zeroTime = {0,0}; - IOHIDQueueInterface **hqi; - IOHIDEventStruct event; - - std::set<int> events; - bool bKeyDown = false; - while (ret == kIOReturnSuccess) { - hqi = (IOHIDQueueInterface **)sender; - ret = (*hqi)->getNextEvent(hqi, &event, zeroTime, 0); - if (ret != kIOReturnSuccess) - continue; - - //printf("%d %d %d\n", (int)event.elementCookie, (int)event.value, (int)event.longValue); - - if (event.value > 0) - bKeyDown = true; - - events.insert((int)event.elementCookie); - } - - if (events.size() > 1) - { - std::set<int>::iterator iter = events.find( g_appleRemote.GetButtonEventTerminator() ); - if (iter != events.end()) - events.erase(iter); - } - - std::string strEvents; - std::set<int>::const_iterator iter = events.begin(); - while (iter != events.end()) - { - //printf("*iter = %d\n", *iter); - char strEvent[10]; - snprintf(strEvent, 10, "%d_", *iter); - strEvents += strEvent; - iter++; - } - - if (bKeyDown) - g_appleRemote.OnKeyDown(strEvents); - else - g_appleRemote.OnKeyUp(strEvents); -} - -bool -addQueueCallbacks(IOHIDQueueInterface **hqi) -{ - IOReturn ret; - CFRunLoopSourceRef eventSource; - IOHIDQueueInterface ***privateData; - - privateData = (IOHIDQueueInterface ***)malloc(sizeof(*privateData)); - *privateData = hqi; - - ret = (*hqi)->createAsyncEventSource(hqi, &eventSource); - if (ret != kIOReturnSuccess) - return false; - - ret = (*hqi)->setEventCallout(hqi, QueueCallbackFunction, - NULL, &privateData); - if (ret != kIOReturnSuccess) - return false; - - CFRunLoopAddSource(CFRunLoopGetCurrent(), eventSource, - kCFRunLoopDefaultMode); - return true; -} - -void -processQueue(IOHIDDeviceInterface **hidDeviceInterface) -{ - HRESULT result; - IOHIDQueueInterface **queue; - - queue = (*hidDeviceInterface)->allocQueue(hidDeviceInterface); - if (!queue) { - fprintf(stderr, "Failed to allocate event queue.\n"); - return; - } - - (void)(*queue)->create(queue, 0, 99); - - std::set<IOHIDElementCookie>::const_iterator iter = g_registeredCookies.begin(); - while (iter != g_registeredCookies.end()) - { - (void)(*queue)->addElement(queue, *iter, 0); - iter++; - } - - addQueueCallbacks(queue); - - result = (*queue)->start(queue); - - CFRunLoopRun(); - - result = (*queue)->stop(queue); - - result = (*queue)->dispose(queue); - - (*queue)->Release(queue); -} - -void -doRun(IOHIDDeviceInterface **hidDeviceInterface) -{ - IOReturn ioReturnValue; - - ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeSeizeDevice); - if (ioReturnValue == kIOReturnExclusiveAccess) { - printf("exclusive lock failed\n"); - } - - processQueue(hidDeviceInterface); - - if (ioReturnValue == KERN_SUCCESS) - ioReturnValue = (*hidDeviceInterface)->close(hidDeviceInterface); - (*hidDeviceInterface)->Release(hidDeviceInterface); -} - -void -getHIDCookies(IOHIDDeviceInterface122 **handle) -{ - IOHIDElementCookie cookie; - CFTypeRef object; - long number; - long usage; - long usagePage; - CFArrayRef elements; - CFDictionaryRef element; - IOReturn result; - - if (!handle || !(*handle)) - return ; - - result = (*handle)->copyMatchingElements(handle, NULL, &elements); - - if (result != kIOReturnSuccess) { - fprintf(stderr, "Failed to copy cookies.\n"); - exit(1); - } - - CFIndex i; - for (i = 0; i < CFArrayGetCount(elements); i++) { - element = (CFDictionaryRef)CFArrayGetValueAtIndex(elements, i); - object = (CFDictionaryGetValue(element, CFSTR(kIOHIDElementCookieKey))); - if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) - continue; - if(!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number)) - continue; - cookie = (IOHIDElementCookie)number; - object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsageKey)); - if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) - continue; - if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &number)) - continue; - usage = number; - object = CFDictionaryGetValue(element,CFSTR(kIOHIDElementUsagePageKey)); - if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) - continue; - if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &number)) - continue; - usagePage = number; - if (usagePage == 0x06 && usage == 0x22 ) // event code "39". menu+select for 5 secs - g_registeredCookies.insert(cookie); - else if (usagePage == 0xff01 && usage == 0x23 ) // event code "35". long click - select - g_registeredCookies.insert(cookie); - else if (usagePage == kHIDPage_GenericDesktop && usage >= 0x80 && usage <= 0x8d ) // regular keys - g_registeredCookies.insert(cookie); - else if (usagePage == kHIDPage_Consumer && usage >= 0xB0 && usage <= 0xBF) - g_registeredCookies.insert(cookie); - else if (usagePage == kHIDPage_Consumer && usage == kHIDUsage_Csmr_Menu ) // event code "18". long "menu" - g_registeredCookies.insert(cookie); - } -} - -void -createHIDDeviceInterface(io_object_t hidDevice, IOHIDDeviceInterface ***hdi) -{ - io_name_t className; - IOCFPlugInInterface **plugInInterface = NULL; - HRESULT plugInResult = S_OK; - SInt32 score = 0; - IOReturn ioReturnValue = kIOReturnSuccess; - - ioReturnValue = IOObjectGetClass(hidDevice, className); - print_errmsg_if_io_err(ioReturnValue, "Failed to get class name."); - - ioReturnValue = IOCreatePlugInInterfaceForService( - hidDevice, - kIOHIDDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugInInterface, - &score); - - if (ioReturnValue != kIOReturnSuccess) - return; - - plugInResult = (*plugInInterface)->QueryInterface( - plugInInterface, - CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), - (LPVOID*)hdi); - print_errmsg_if_err(plugInResult != S_OK, - "Failed to create device interface.\n"); - - (*plugInInterface)->Release(plugInInterface); -} - -void -setupAndRun(void) -{ - CFMutableDictionaryRef hidMatchDictionary = NULL; - io_service_t hidService = (io_service_t)0; - io_object_t hidDevice = (io_object_t)0; - IOHIDDeviceInterface **hidDeviceInterface = NULL; - IOReturn ioReturnValue = kIOReturnSuccess; - - //hidMatchDictionary = IOServiceNameMatching("AppleIRController"); - hidMatchDictionary = IOServiceMatching("AppleIRController"); - hidService = IOServiceGetMatchingService(kIOMasterPortDefault, - hidMatchDictionary); - - if (!hidService) { - fprintf(stderr, "Apple Infrared Remote not found.\n"); - exit(1); - } - - hidDevice = (io_object_t)hidService; - - createHIDDeviceInterface(hidDevice, &hidDeviceInterface); - getHIDCookies((IOHIDDeviceInterface122 **)hidDeviceInterface); - ioReturnValue = IOObjectRelease(hidDevice); - print_errmsg_if_io_err(ioReturnValue, "Failed to release HID."); - - if (hidDeviceInterface == NULL) { - fprintf(stderr, "No HID.\n"); - exit(1); - } - - g_appleRemote.Initialize(); - doRun(hidDeviceInterface); - - if (ioReturnValue == KERN_SUCCESS) - ioReturnValue = (*hidDeviceInterface)->close(hidDeviceInterface); - - (*hidDeviceInterface)->Release(hidDeviceInterface); -} - -void Reconfigure(int nSignal) -{ - if (nSignal == SIGHUP) { - //fprintf(stderr, "Reconfigure\n"); - ReadConfig(); - } else { - exit(0); - } -} - -void ReadConfig() -{ - // Compute filename. - string strFile = getenv("HOME"); - strFile += "/Library/Application Support/XBMC/XBMCHelper.conf"; - - // Open file. - ifstream ifs(strFile.c_str()); - if (!ifs) - return; - - // Read file. - stringstream oss; - oss << ifs.rdbuf(); - - if (!ifs && !ifs.eof()) - return; - - // Tokenize. - string strData(oss.str()); - istringstream is(strData); - vector<string> args = vector<string>(istream_iterator<string>(is), istream_iterator<string>()); - - // Convert to char**. - int argc = args.size() + 1; - char** argv = new char*[argc + 1]; - int i = 0; - argv[i++] = "XBMCHelper"; - - for (vector<string>::iterator it = args.begin(); it != args.end(); ) - argv[i++] = (char* )(*it++).c_str(); - - argv[i] = 0; - - // Parse the arguments. - ParseOptions(argc, argv); - - delete[] argv; -} - -void ParseOptions(int argc, char** argv) -{ - int c, option_index = 0; - bool readExternal = false; - - while ((c = getopt_long(argc, argv, options, long_options, &option_index)) != -1) - { - switch (c) { - case 'h': - usage(); - exit(0); - break; - case 'v': - g_appleRemote.SetVerbose(true); - break; - case 's': - g_appleRemote.SetServerAddress(optarg); - break; - case 'u': - g_appleRemote.SetRemoteMode(REMOTE_UNIVERSAL); - break; - case 'm': - break; - case 't': - if (optarg) - g_appleRemote.SetMaxClickTimeout( atof(optarg) * 0.001 ); - break; - case 'a': - g_appleRemote.SetAppPath(optarg); - break; - case 'z': - g_appleRemote.SetAppHome(optarg); - break; - case 'x': - readExternal = true; - break; - default: - usage(); - exit(1); - break; - } - } - //reset getopts state - optreset = 1; - optind = 0; - - if (readExternal == true) - ReadConfig(); -} - -int -main (int argc, char **argv) -{ - ParseOptions(argc,argv); - - signal(SIGHUP, Reconfigure); - signal(SIGINT, Reconfigure); - signal(SIGTERM, Reconfigure); - - XBox360 xbox360; - xbox360.start(); - - setupAndRun(); - - xbox360.join(); - - return 0; -} |