aboutsummaryrefslogtreecommitdiffhomepage
path: root/osdep/ar
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2014-04-13 18:00:51 +0200
committerGravatar wm4 <wm4@nowhere>2014-04-13 18:03:01 +0200
commit78128bddda4bcea1f256fc13cc33fa2652ed277c (patch)
tree35bf6596cb8e2d7927618845833c3ee36534f890 /osdep/ar
parent44f382cf98564c0fe08bdc78579c284362cd6f3c (diff)
Kill all tabs
I hate tabs. This replaces all tabs in all source files with spaces. The only exception is old-makefile. The replacement was made by running the GNU coreutils "expand" command on every file. Since the replacement was automatic, it's possible that some formatting was destroyed (but perhaps only if it was assuming that the end of a tab does not correspond to aligning the end to multiples of 8 spaces).
Diffstat (limited to 'osdep/ar')
-rw-r--r--osdep/ar/HIDRemote.h280
-rw-r--r--osdep/ar/HIDRemote.m3450
2 files changed, 1865 insertions, 1865 deletions
diff --git a/osdep/ar/HIDRemote.h b/osdep/ar/HIDRemote.h
index 9dd16faa5a..33f59f322d 100644
--- a/osdep/ar/HIDRemote.h
+++ b/osdep/ar/HIDRemote.h
@@ -73,78 +73,78 @@
typedef enum
{
- kHIDRemoteModeNone = 0L,
- kHIDRemoteModeShared, // Share the remote with others - let's you listen to the remote control events as long as noone has an exclusive lock on it
- // (RECOMMENDED ONLY FOR SPECIAL PURPOSES)
+ kHIDRemoteModeNone = 0L,
+ kHIDRemoteModeShared, // Share the remote with others - let's you listen to the remote control events as long as noone has an exclusive lock on it
+ // (RECOMMENDED ONLY FOR SPECIAL PURPOSES)
- kHIDRemoteModeExclusive, // Try to acquire an exclusive lock on the remote (NOT RECOMMENDED)
+ kHIDRemoteModeExclusive, // Try to acquire an exclusive lock on the remote (NOT RECOMMENDED)
- kHIDRemoteModeExclusiveAuto // Try to acquire an exclusive lock on the remote whenever the application has focus. Temporarily release control over the
- // remote when another application has focus (RECOMMENDED)
+ kHIDRemoteModeExclusiveAuto // Try to acquire an exclusive lock on the remote whenever the application has focus. Temporarily release control over the
+ // remote when another application has focus (RECOMMENDED)
} HIDRemoteMode;
typedef enum
{
- /* A code reserved for "no button" (needed for tracking) */
- kHIDRemoteButtonCodeNone = 0L,
-
- /* Standard codes - available for white plastic and aluminum remote */
- kHIDRemoteButtonCodeUp,
- kHIDRemoteButtonCodeDown,
- kHIDRemoteButtonCodeLeft,
- kHIDRemoteButtonCodeRight,
- kHIDRemoteButtonCodeCenter,
- kHIDRemoteButtonCodeMenu,
-
- /* Extra codes - Only available for the new aluminum version of the remote */
- kHIDRemoteButtonCodePlay,
-
- /* Masks */
- kHIDRemoteButtonCodeCodeMask = 0xFFL,
- kHIDRemoteButtonCodeHoldMask = (1L << 16L),
- kHIDRemoteButtonCodeSpecialMask = (1L << 17L),
- kHIDRemoteButtonCodeAluminumMask = (1L << 21L), // PRIVATE - only used internally
-
- /* Hold button standard codes - available for white plastic and aluminum remote */
- kHIDRemoteButtonCodeUpHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeUp),
- kHIDRemoteButtonCodeDownHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeDown),
- kHIDRemoteButtonCodeLeftHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeLeft),
- kHIDRemoteButtonCodeRightHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeRight),
- kHIDRemoteButtonCodeCenterHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeCenter),
- kHIDRemoteButtonCodeMenuHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeMenu),
-
- /* Hold button extra codes - Only available for aluminum version of the remote */
- kHIDRemoteButtonCodePlayHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodePlay),
-
- /* DEPRECATED codes - compatibility with HIDRemote 1.0 */
- kHIDRemoteButtonCodePlus = kHIDRemoteButtonCodeUp,
- kHIDRemoteButtonCodePlusHold = kHIDRemoteButtonCodeUpHold,
- kHIDRemoteButtonCodeMinus = kHIDRemoteButtonCodeDown,
- kHIDRemoteButtonCodeMinusHold = kHIDRemoteButtonCodeDownHold,
- kHIDRemoteButtonCodePlayPause = kHIDRemoteButtonCodeCenter,
- kHIDRemoteButtonCodePlayPauseHold = kHIDRemoteButtonCodeCenterHold,
-
- /* Special purpose codes */
- kHIDRemoteButtonCodeIDChanged = (kHIDRemoteButtonCodeSpecialMask|(1L << 18L)), // (the ID of the connected remote has changed, you can safely ignore this)
- #ifdef _HIDREMOTE_EXTENSIONS
- #define _HIDREMOTE_EXTENSIONS_SECTION 1
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
+ /* A code reserved for "no button" (needed for tracking) */
+ kHIDRemoteButtonCodeNone = 0L,
+
+ /* Standard codes - available for white plastic and aluminum remote */
+ kHIDRemoteButtonCodeUp,
+ kHIDRemoteButtonCodeDown,
+ kHIDRemoteButtonCodeLeft,
+ kHIDRemoteButtonCodeRight,
+ kHIDRemoteButtonCodeCenter,
+ kHIDRemoteButtonCodeMenu,
+
+ /* Extra codes - Only available for the new aluminum version of the remote */
+ kHIDRemoteButtonCodePlay,
+
+ /* Masks */
+ kHIDRemoteButtonCodeCodeMask = 0xFFL,
+ kHIDRemoteButtonCodeHoldMask = (1L << 16L),
+ kHIDRemoteButtonCodeSpecialMask = (1L << 17L),
+ kHIDRemoteButtonCodeAluminumMask = (1L << 21L), // PRIVATE - only used internally
+
+ /* Hold button standard codes - available for white plastic and aluminum remote */
+ kHIDRemoteButtonCodeUpHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeUp),
+ kHIDRemoteButtonCodeDownHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeDown),
+ kHIDRemoteButtonCodeLeftHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeLeft),
+ kHIDRemoteButtonCodeRightHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeRight),
+ kHIDRemoteButtonCodeCenterHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeCenter),
+ kHIDRemoteButtonCodeMenuHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeMenu),
+
+ /* Hold button extra codes - Only available for aluminum version of the remote */
+ kHIDRemoteButtonCodePlayHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodePlay),
+
+ /* DEPRECATED codes - compatibility with HIDRemote 1.0 */
+ kHIDRemoteButtonCodePlus = kHIDRemoteButtonCodeUp,
+ kHIDRemoteButtonCodePlusHold = kHIDRemoteButtonCodeUpHold,
+ kHIDRemoteButtonCodeMinus = kHIDRemoteButtonCodeDown,
+ kHIDRemoteButtonCodeMinusHold = kHIDRemoteButtonCodeDownHold,
+ kHIDRemoteButtonCodePlayPause = kHIDRemoteButtonCodeCenter,
+ kHIDRemoteButtonCodePlayPauseHold = kHIDRemoteButtonCodeCenterHold,
+
+ /* Special purpose codes */
+ kHIDRemoteButtonCodeIDChanged = (kHIDRemoteButtonCodeSpecialMask|(1L << 18L)), // (the ID of the connected remote has changed, you can safely ignore this)
+ #ifdef _HIDREMOTE_EXTENSIONS
+ #define _HIDREMOTE_EXTENSIONS_SECTION 1
+ #include "HIDRemoteAdditions.h"
+ #undef _HIDREMOTE_EXTENSIONS_SECTION
+ #endif /* _HIDREMOTE_EXTENSIONS */
} HIDRemoteButtonCode;
typedef enum
{
- kHIDRemoteModelUndetermined = 0L, // Assume a white plastic remote
- kHIDRemoteModelWhitePlastic, // Signal *likely* to be coming from a white plastic remote
- kHIDRemoteModelAluminum // Signal *definitely* coming from an aluminum remote
+ kHIDRemoteModelUndetermined = 0L, // Assume a white plastic remote
+ kHIDRemoteModelWhitePlastic, // Signal *likely* to be coming from a white plastic remote
+ kHIDRemoteModelAluminum // Signal *definitely* coming from an aluminum remote
} HIDRemoteModel;
typedef enum
{
- kHIDRemoteAluminumRemoteSupportLevelNone = 0L, // This system has no support for the Aluminum Remote at all
- kHIDRemoteAluminumRemoteSupportLevelEmulation, // This system possibly has support for the Aluminum Remote (via emulation)
- kHIDRemoteAluminumRemoteSupportLevelNative // This system has native support for the Aluminum Remote
+ kHIDRemoteAluminumRemoteSupportLevelNone = 0L, // This system has no support for the Aluminum Remote at all
+ kHIDRemoteAluminumRemoteSupportLevelEmulation, // This system possibly has support for the Aluminum Remote (via emulation)
+ kHIDRemoteAluminumRemoteSupportLevelNative // This system has native support for the Aluminum Remote
} HIDRemoteAluminumRemoteSupportLevel;
@class HIDRemote;
@@ -153,46 +153,46 @@ typedef enum
@protocol HIDRemoteDelegate
// Notification of button events
-- (void)hidRemote:(HIDRemote *)hidRemote // The instance of HIDRemote sending this
- eventWithButton:(HIDRemoteButtonCode)buttonCode // Event for the button specified by code
- isPressed:(BOOL)isPressed // The button was pressed (YES) / released (NO)
- fromHardwareWithAttributes:(NSMutableDictionary *)attributes; // Information on the device this event comes from
+- (void)hidRemote:(HIDRemote *)hidRemote // The instance of HIDRemote sending this
+ eventWithButton:(HIDRemoteButtonCode)buttonCode // Event for the button specified by code
+ isPressed:(BOOL)isPressed // The button was pressed (YES) / released (NO)
+ fromHardwareWithAttributes:(NSMutableDictionary *)attributes; // Information on the device this event comes from
@optional
// Notification of ID changes
-- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when the user switched to a remote control with a different ID
- remoteIDChangedOldID:(SInt32)old
- newID:(SInt32)newID
- forHardwareWithAttributes:(NSMutableDictionary *)attributes;
+- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when the user switched to a remote control with a different ID
+ remoteIDChangedOldID:(SInt32)old
+ newID:(SInt32)newID
+ forHardwareWithAttributes:(NSMutableDictionary *)attributes;
// Notification about hardware additions/removals
-- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when new hardware was found / added to HIDRemote's pool
- foundNewHardwareWithAttributes:(NSMutableDictionary *)attributes;
+- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when new hardware was found / added to HIDRemote's pool
+ foundNewHardwareWithAttributes:(NSMutableDictionary *)attributes;
-- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when initialization of new hardware as requested failed
- failedNewHardwareWithError:(NSError *)error;
+- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when initialization of new hardware as requested failed
+ failedNewHardwareWithError:(NSError *)error;
-- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when hardware was removed from HIDRemote's pool
- releasedHardwareWithAttributes:(NSMutableDictionary *)attributes;
+- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when hardware was removed from HIDRemote's pool
+ releasedHardwareWithAttributes:(NSMutableDictionary *)attributes;
// ### WARNING: Unless you know VERY PRECISELY what you are doing, do not implement any of the delegate methods below. ###
// Matching of newly found receiver hardware
-- (BOOL)hidRemote:(HIDRemote *)hidRemote // Invoked when new hardware is inspected
- inspectNewHardwareWithService:(io_service_t)service //
- prematchResult:(BOOL)prematchResult; // Return YES if HIDRemote should go on with this hardware and try
- // to use it, or NO if it should not be persued further.
+- (BOOL)hidRemote:(HIDRemote *)hidRemote // Invoked when new hardware is inspected
+ inspectNewHardwareWithService:(io_service_t)service //
+ prematchResult:(BOOL)prematchResult; // Return YES if HIDRemote should go on with this hardware and try
+ // to use it, or NO if it should not be persued further.
// Exlusive lock lending
- (BOOL)hidRemote:(HIDRemote *)hidRemote
- lendExclusiveLockToApplicationWithInfo:(NSDictionary *)applicationInfo;
+ lendExclusiveLockToApplicationWithInfo:(NSDictionary *)applicationInfo;
- (void)hidRemote:(HIDRemote *)hidRemote
- exclusiveLockReleasedByApplicationWithInfo:(NSDictionary *)applicationInfo;
+ exclusiveLockReleasedByApplicationWithInfo:(NSDictionary *)applicationInfo;
- (BOOL)hidRemote:(HIDRemote *)hidRemote
- shouldRetryExclusiveLockWithInfo:(NSDictionary *)applicationInfo;
+ shouldRetryExclusiveLockWithInfo:(NSDictionary *)applicationInfo;
@end
@@ -201,65 +201,65 @@ typedef enum
@interface HIDRemote : NSObject
{
- // IOMasterPort
- mach_port_t _masterPort;
-
- // Notification ports
- IONotificationPortRef _notifyPort;
- CFRunLoopSourceRef _notifyRLSource;
-
- // Matching iterator
- io_iterator_t _matchingServicesIterator;
-
- // SecureInput notification
- io_object_t _secureInputNotification;
-
- // Service attributes
- NSMutableDictionary *_serviceAttribMap;
-
- // Mode
- HIDRemoteMode _mode;
- BOOL _autoRecover;
- NSTimer *_autoRecoveryTimer;
-
- // Delegate
- NSObject <HIDRemoteDelegate> *_delegate;
-
- // Last seen ID and remote model
- SInt32 _lastSeenRemoteID;
- HIDRemoteModel _lastSeenModel;
- SInt32 _lastSeenModelRemoteID;
-
- // Unused button codes
- NSArray *_unusedButtonCodes;
-
- // Simulate Plus/Minus Hold
- BOOL _simulateHoldEvents;
-
- // SecureEventInput workaround
- BOOL _secureEventInputWorkAround;
- UInt64 _lastSecureEventInputPIDSum;
- uid_t _lastFrontUserSession;
-
- // Exclusive lock lending
- BOOL _exclusiveLockLending;
- BOOL _sendExclusiveResourceReuseNotification;
- NSNumber *_waitForReturnByPID;
- NSNumber *_returnToPID;
- BOOL _isRestarting;
-
- // Status notifications
- BOOL _sendStatusNotifications;
- NSString *_pidString;
-
- // Status
- BOOL _applicationIsTerminating;
- BOOL _isStopping;
-
- // Thread safety
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING /* #define HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING if you're running your HIDRemote instance on a background thread (requires OS X 10.5 or later) */
- NSThread *_runOnThread;
- #endif
+ // IOMasterPort
+ mach_port_t _masterPort;
+
+ // Notification ports
+ IONotificationPortRef _notifyPort;
+ CFRunLoopSourceRef _notifyRLSource;
+
+ // Matching iterator
+ io_iterator_t _matchingServicesIterator;
+
+ // SecureInput notification
+ io_object_t _secureInputNotification;
+
+ // Service attributes
+ NSMutableDictionary *_serviceAttribMap;
+
+ // Mode
+ HIDRemoteMode _mode;
+ BOOL _autoRecover;
+ NSTimer *_autoRecoveryTimer;
+
+ // Delegate
+ NSObject <HIDRemoteDelegate> *_delegate;
+
+ // Last seen ID and remote model
+ SInt32 _lastSeenRemoteID;
+ HIDRemoteModel _lastSeenModel;
+ SInt32 _lastSeenModelRemoteID;
+
+ // Unused button codes
+ NSArray *_unusedButtonCodes;
+
+ // Simulate Plus/Minus Hold
+ BOOL _simulateHoldEvents;
+
+ // SecureEventInput workaround
+ BOOL _secureEventInputWorkAround;
+ UInt64 _lastSecureEventInputPIDSum;
+ uid_t _lastFrontUserSession;
+
+ // Exclusive lock lending
+ BOOL _exclusiveLockLending;
+ BOOL _sendExclusiveResourceReuseNotification;
+ NSNumber *_waitForReturnByPID;
+ NSNumber *_returnToPID;
+ BOOL _isRestarting;
+
+ // Status notifications
+ BOOL _sendStatusNotifications;
+ NSString *_pidString;
+
+ // Status
+ BOOL _applicationIsTerminating;
+ BOOL _isStopping;
+
+ // Thread safety
+ #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING /* #define HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING if you're running your HIDRemote instance on a background thread (requires OS X 10.5 or later) */
+ NSThread *_runOnThread;
+ #endif
}
#pragma mark -- PUBLIC: Shared HID Remote --
@@ -271,7 +271,7 @@ typedef enum
- (HIDRemoteAluminumRemoteSupportLevel)aluminiumRemoteSystemSupportLevel;
#pragma mark -- PUBLIC: Interface / API --
-- (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode;
+- (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode;
- (void)stopRemoteControl;
- (BOOL)isStarted;
@@ -374,5 +374,5 @@ extern NSString *kHIDRemoteDNStatusActionNoNeed;
#pragma mark -- Driver compatibility flags --
typedef enum
{
- kHIDRemoteCompatibilityFlagsStandardHIDRemoteDevice = 1L,
+ kHIDRemoteCompatibilityFlagsStandardHIDRemoteDevice = 1L,
} HIDRemoteCompatibilityFlags;
diff --git a/osdep/ar/HIDRemote.m b/osdep/ar/HIDRemote.m
index 4e5b88e770..977b9cbdb9 100644
--- a/osdep/ar/HIDRemote.m
+++ b/osdep/ar/HIDRemote.m
@@ -52,23 +52,23 @@
#import "HIDRemote.h"
// Callback Prototypes
-static void HIDEventCallback( void * target,
- IOReturn result,
- void * refcon,
- void * sender);
+static void HIDEventCallback( void * target,
+ IOReturn result,
+ void * refcon,
+ void * sender);
-static void ServiceMatchingCallback( void *refCon,
- io_iterator_t iterator);
+static void ServiceMatchingCallback( void *refCon,
+ io_iterator_t iterator);
-static void ServiceNotificationCallback(void * refCon,
- io_service_t service,
- natural_t messageType,
- void * messageArgument);
+static void ServiceNotificationCallback(void * refCon,
+ io_service_t service,
+ natural_t messageType,
+ void * messageArgument);
-static void SecureInputNotificationCallback( void * refCon,
- io_service_t service,
- natural_t messageType,
- void * messageArgument);
+static void SecureInputNotificationCallback( void * refCon,
+ io_service_t service,
+ natural_t messageType,
+ void * messageArgument);
// Shared HIDRemote instance
static HIDRemote *sHIDRemote = nil;
@@ -79,1947 +79,1947 @@ static HIDRemote *sHIDRemote = nil;
+ (HIDRemote *)sharedHIDRemote
{
- if (sHIDRemote==nil)
- {
- sHIDRemote = [[HIDRemote alloc] init];
- }
-
- return (sHIDRemote);
+ if (sHIDRemote==nil)
+ {
+ sHIDRemote = [[HIDRemote alloc] init];
+ }
+
+ return (sHIDRemote);
}
- (id)init
{
- if ((self = [super init]) != nil)
- {
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
- _runOnThread = [[NSThread currentThread] retain];
- #endif
-
- // Detect application becoming active/inactive
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationDidBecomeActiveNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillResignActiveNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillTerminateNotification object:NSApp];
-
- // Handle distributed notifications
- _pidString = [[NSString alloc] initWithFormat:@"%d", getpid()];
-
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemotePing object:nil];
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject];
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:_pidString];
-
- // Enabled by default: simulate hold events for plus/minus
- _simulateHoldEvents = YES;
-
- // Enabled by default: work around for a locking issue introduced with Security Update 2008-004 / 10.4.9 and beyond (credit for finding this workaround goes to Martin Kahr)
- _secureEventInputWorkAround = YES;
- _secureInputNotification = 0;
-
- // Initialize instance variables
- _lastSeenRemoteID = -1;
- _lastSeenModel = kHIDRemoteModelUndetermined;
- _unusedButtonCodes = [[NSMutableArray alloc] init];
- _exclusiveLockLending = NO;
- _sendExclusiveResourceReuseNotification = YES;
- _applicationIsTerminating = NO;
-
- // Send status notifications
- _sendStatusNotifications = YES;
- }
-
- return (self);
+ if ((self = [super init]) != nil)
+ {
+ #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
+ _runOnThread = [[NSThread currentThread] retain];
+ #endif
+
+ // Detect application becoming active/inactive
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationDidBecomeActiveNotification object:NSApp];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillResignActiveNotification object:NSApp];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillTerminateNotification object:NSApp];
+
+ // Handle distributed notifications
+ _pidString = [[NSString alloc] initWithFormat:@"%d", getpid()];
+
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemotePing object:nil];
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject];
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:_pidString];
+
+ // Enabled by default: simulate hold events for plus/minus
+ _simulateHoldEvents = YES;
+
+ // Enabled by default: work around for a locking issue introduced with Security Update 2008-004 / 10.4.9 and beyond (credit for finding this workaround goes to Martin Kahr)
+ _secureEventInputWorkAround = YES;
+ _secureInputNotification = 0;
+
+ // Initialize instance variables
+ _lastSeenRemoteID = -1;
+ _lastSeenModel = kHIDRemoteModelUndetermined;
+ _unusedButtonCodes = [[NSMutableArray alloc] init];
+ _exclusiveLockLending = NO;
+ _sendExclusiveResourceReuseNotification = YES;
+ _applicationIsTerminating = NO;
+
+ // Send status notifications
+ _sendStatusNotifications = YES;
+ }
+
+ return (self);
}
- (void)dealloc
{
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillTerminateNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillResignActiveNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidBecomeActiveNotification object:NSApp];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillTerminateNotification object:NSApp];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillResignActiveNotification object:NSApp];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidBecomeActiveNotification object:NSApp];
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemotePing object:nil];
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject];
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:_pidString];
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:nil object:nil]; /* As demanded by the documentation for -[NSDistributedNotificationCenter removeObserver:name:object:] */
-
- [self stopRemoteControl];
+ [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemotePing object:nil];
+ [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject];
+ [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:_pidString];
+ [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:nil object:nil]; /* As demanded by the documentation for -[NSDistributedNotificationCenter removeObserver:name:object:] */
+
+ [self stopRemoteControl];
- [self setExclusiveLockLendingEnabled:NO];
+ [self setExclusiveLockLendingEnabled:NO];
- [self setDelegate:nil];
+ [self setDelegate:nil];
- if (_unusedButtonCodes != nil)
- {
- [_unusedButtonCodes release];
- _unusedButtonCodes = nil;
- }
+ if (_unusedButtonCodes != nil)
+ {
+ [_unusedButtonCodes release];
+ _unusedButtonCodes = nil;
+ }
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
- [_runOnThread release];
- _runOnThread = nil;
- #endif
+ #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
+ [_runOnThread release];
+ _runOnThread = nil;
+ #endif
- [_pidString release];
- _pidString = nil;
+ [_pidString release];
+ _pidString = nil;
- [super dealloc];
+ [super dealloc];
}
#pragma mark -- PUBLIC: System Information --
+ (BOOL)isCandelairInstalled
{
- mach_port_t masterPort = 0;
- kern_return_t kernResult;
- io_service_t matchingService = 0;
- BOOL isInstalled = NO;
+ mach_port_t masterPort = 0;
+ kern_return_t kernResult;
+ io_service_t matchingService = 0;
+ BOOL isInstalled = NO;
- kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
- if ((kernResult!=kIOReturnSuccess) || (masterPort==0)) { return(NO); }
+ kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
+ if ((kernResult!=kIOReturnSuccess) || (masterPort==0)) { return(NO); }
- if ((matchingService = IOServiceGetMatchingService(masterPort, IOServiceMatching("IOSPIRITIRController"))) != 0)
- {
- isInstalled = YES;
- IOObjectRelease((io_object_t) matchingService);
- }
+ if ((matchingService = IOServiceGetMatchingService(masterPort, IOServiceMatching("IOSPIRITIRController"))) != 0)
+ {
+ isInstalled = YES;
+ IOObjectRelease((io_object_t) matchingService);
+ }
- mach_port_deallocate(mach_task_self(), masterPort);
+ mach_port_deallocate(mach_task_self(), masterPort);
- return (isInstalled);
+ return (isInstalled);
}
+ (BOOL)isCandelairInstallationRequiredForRemoteMode:(HIDRemoteMode)remoteMode
{
- return (NO);
+ return (NO);
}
- (HIDRemoteAluminumRemoteSupportLevel)aluminiumRemoteSystemSupportLevel
{
- HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone;
- NSEnumerator *attribDictsEnum;
- NSDictionary *hidAttribsDict;
-
- attribDictsEnum = [_serviceAttribMap objectEnumerator];
-
- while ((hidAttribsDict = [attribDictsEnum nextObject]) != nil)
- {
- NSNumber *deviceSupportLevel;
-
- if ((deviceSupportLevel = [hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel]) != nil)
- {
- if ([deviceSupportLevel intValue] > (int)supportLevel)
- {
- supportLevel = [deviceSupportLevel intValue];
- }
- }
- }
-
- return (supportLevel);
+ HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone;
+ NSEnumerator *attribDictsEnum;
+ NSDictionary *hidAttribsDict;
+
+ attribDictsEnum = [_serviceAttribMap objectEnumerator];
+
+ while ((hidAttribsDict = [attribDictsEnum nextObject]) != nil)
+ {
+ NSNumber *deviceSupportLevel;
+
+ if ((deviceSupportLevel = [hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel]) != nil)
+ {
+ if ([deviceSupportLevel intValue] > (int)supportLevel)
+ {
+ supportLevel = [deviceSupportLevel intValue];
+ }
+ }
+ }
+
+ return (supportLevel);
}
#pragma mark -- PUBLIC: Interface / API --
- (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode
{
- if ((_mode == kHIDRemoteModeNone) && (hidRemoteMode != kHIDRemoteModeNone))
- {
- kern_return_t kernReturn;
- CFMutableDictionaryRef matchDict=NULL;
- io_service_t rootService;
-
- do
- {
- // Get IOKit master port
- kernReturn = IOMasterPort(bootstrap_port, &_masterPort);
- if ((kernReturn!=kIOReturnSuccess) || (_masterPort==0)) { break; }
-
- // Setup notification port
- _notifyPort = IONotificationPortCreate(_masterPort);
-
- if ((_notifyRLSource = IONotificationPortGetRunLoopSource(_notifyPort)) != NULL)
- {
- CFRunLoopAddSource( CFRunLoopGetCurrent(),
- _notifyRLSource,
- kCFRunLoopCommonModes);
- }
- else
- {
- break;
- }
-
- // Setup SecureInput notification
- if ((hidRemoteMode == kHIDRemoteModeExclusive) || (hidRemoteMode == kHIDRemoteModeExclusiveAuto))
- {
- if ((rootService = IORegistryEntryFromPath(_masterPort, kIOServicePlane ":/")) != 0)
- {
- kernReturn = IOServiceAddInterestNotification( _notifyPort,
- rootService,
- kIOBusyInterest,
- SecureInputNotificationCallback,
- (void *)self,
- &_secureInputNotification);
- if (kernReturn != kIOReturnSuccess) { break; }
-
- [self _updateSessionInformation];
- }
- else
- {
- break;
- }
- }
-
- // Setup notification matching dict
- matchDict = IOServiceMatching(kIOHIDDeviceKey);
- CFRetain(matchDict);
-
- // Actually add notification
- kernReturn = IOServiceAddMatchingNotification( _notifyPort,
- kIOFirstMatchNotification,
- matchDict, // one reference count consumed by this call
- ServiceMatchingCallback,
- (void *) self,
- &_matchingServicesIterator);
- if (kernReturn != kIOReturnSuccess) { break; }
-
- // Setup serviceAttribMap
- _serviceAttribMap = [[NSMutableDictionary alloc] init];
- if (_serviceAttribMap==nil) { break; }
-
- // Phew .. everything went well!
- _mode = hidRemoteMode;
- CFRelease(matchDict);
-
- [self _serviceMatching:_matchingServicesIterator];
-
- [self _postStatusWithAction:kHIDRemoteDNStatusActionStart];
-
- return (YES);
-
- }while(0);
-
- // An error occured. Do necessary clean up.
- if (matchDict!=NULL)
- {
- CFRelease(matchDict);
- matchDict = NULL;
- }
-
- [self stopRemoteControl];
- }
-
- return (NO);
+ if ((_mode == kHIDRemoteModeNone) && (hidRemoteMode != kHIDRemoteModeNone))
+ {
+ kern_return_t kernReturn;
+ CFMutableDictionaryRef matchDict=NULL;
+ io_service_t rootService;
+
+ do
+ {
+ // Get IOKit master port
+ kernReturn = IOMasterPort(bootstrap_port, &_masterPort);
+ if ((kernReturn!=kIOReturnSuccess) || (_masterPort==0)) { break; }
+
+ // Setup notification port
+ _notifyPort = IONotificationPortCreate(_masterPort);
+
+ if ((_notifyRLSource = IONotificationPortGetRunLoopSource(_notifyPort)) != NULL)
+ {
+ CFRunLoopAddSource( CFRunLoopGetCurrent(),
+ _notifyRLSource,
+ kCFRunLoopCommonModes);
+ }
+ else
+ {
+ break;
+ }
+
+ // Setup SecureInput notification
+ if ((hidRemoteMode == kHIDRemoteModeExclusive) || (hidRemoteMode == kHIDRemoteModeExclusiveAuto))
+ {
+ if ((rootService = IORegistryEntryFromPath(_masterPort, kIOServicePlane ":/")) != 0)
+ {
+ kernReturn = IOServiceAddInterestNotification( _notifyPort,
+ rootService,
+ kIOBusyInterest,
+ SecureInputNotificationCallback,
+ (void *)self,
+ &_secureInputNotification);
+ if (kernReturn != kIOReturnSuccess) { break; }
+
+ [self _updateSessionInformation];
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // Setup notification matching dict
+ matchDict = IOServiceMatching(kIOHIDDeviceKey);
+ CFRetain(matchDict);
+
+ // Actually add notification
+ kernReturn = IOServiceAddMatchingNotification( _notifyPort,
+ kIOFirstMatchNotification,
+ matchDict, // one reference count consumed by this call
+ ServiceMatchingCallback,
+ (void *) self,
+ &_matchingServicesIterator);
+ if (kernReturn != kIOReturnSuccess) { break; }
+
+ // Setup serviceAttribMap
+ _serviceAttribMap = [[NSMutableDictionary alloc] init];
+ if (_serviceAttribMap==nil) { break; }
+
+ // Phew .. everything went well!
+ _mode = hidRemoteMode;
+ CFRelease(matchDict);
+
+ [self _serviceMatching:_matchingServicesIterator];
+
+ [self _postStatusWithAction:kHIDRemoteDNStatusActionStart];
+
+ return (YES);
+
+ }while(0);
+
+ // An error occured. Do necessary clean up.
+ if (matchDict!=NULL)
+ {
+ CFRelease(matchDict);
+ matchDict = NULL;
+ }
+
+ [self stopRemoteControl];
+ }
+
+ return (NO);
}
- (void)stopRemoteControl
{
- UInt32 serviceCount = 0;
-
- _autoRecover = NO;
- _isStopping = YES;
-
- if (_autoRecoveryTimer!=nil)
- {
- [_autoRecoveryTimer invalidate];
- [_autoRecoveryTimer release];
- _autoRecoveryTimer = nil;
- }
-
- if (_serviceAttribMap!=nil)
- {
- NSDictionary *cloneDict = [[NSDictionary alloc] initWithDictionary:_serviceAttribMap];
-
- if (cloneDict!=nil)
- {
- NSEnumerator *mapKeyEnum = [cloneDict keyEnumerator];
- NSNumber *serviceValue;
-
- while ((serviceValue = [mapKeyEnum nextObject]) != nil)
- {
- [self _destructService:(io_object_t)[serviceValue unsignedIntValue]];
- serviceCount++;
- };
-
- [cloneDict release];
- cloneDict = nil;
- }
-
- [_serviceAttribMap release];
- _serviceAttribMap = nil;
- }
-
- if (_matchingServicesIterator!=0)
- {
- IOObjectRelease((io_object_t) _matchingServicesIterator);
- _matchingServicesIterator = 0;
- }
-
- if (_secureInputNotification!=0)
- {
- IOObjectRelease((io_object_t) _secureInputNotification);
- _secureInputNotification = 0;
- }
-
- if (_notifyRLSource!=NULL)
- {
- CFRunLoopSourceInvalidate(_notifyRLSource);
- _notifyRLSource = NULL;
- }
-
- if (_notifyPort!=NULL)
- {
- IONotificationPortDestroy(_notifyPort);
- _notifyPort = NULL;
- }
-
- if (_masterPort!=0)
- {
- mach_port_deallocate(mach_task_self(), _masterPort);
- _masterPort = 0;
- }
-
- if (_returnToPID!=nil)
- {
- [_returnToPID release];
- _returnToPID = nil;
- }
-
- if (_mode!=kHIDRemoteModeNone)
- {
- // Post status
- [self _postStatusWithAction:kHIDRemoteDNStatusActionStop];
-
- if (_sendStatusNotifications)
- {
- // In case we were not ready to lend it earlier, tell other HIDRemote apps that the resources (if any were used) are now again available for use by other applications
- if (((_mode==kHIDRemoteModeExclusive) || (_mode==kHIDRemoteModeExclusiveAuto)) && (_sendExclusiveResourceReuseNotification==YES) && (_exclusiveLockLending==NO) && (serviceCount>0))
- {
- _mode = kHIDRemoteModeNone;
-
- if (!_isRestarting)
- {
- [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry
- object:kHIDRemoteDNHIDRemoteRetryGlobalObject
- userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
- [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
- nil]
- deliverImmediately:YES];
- }
- }
- }
- }
-
- _mode = kHIDRemoteModeNone;
- _isStopping = NO;
+ UInt32 serviceCount = 0;
+
+ _autoRecover = NO;
+ _isStopping = YES;
+
+ if (_autoRecoveryTimer!=nil)
+ {
+ [_autoRecoveryTimer invalidate];
+ [_autoRecoveryTimer release];
+ _autoRecoveryTimer = nil;
+ }
+
+ if (_serviceAttribMap!=nil)
+ {
+ NSDictionary *cloneDict = [[NSDictionary alloc] initWithDictionary:_serviceAttribMap];
+
+ if (cloneDict!=nil)
+ {
+ NSEnumerator *mapKeyEnum = [cloneDict keyEnumerator];
+ NSNumber *serviceValue;
+
+ while ((serviceValue = [mapKeyEnum nextObject]) != nil)
+ {
+ [self _destructService:(io_object_t)[serviceValue unsignedIntValue]];
+ serviceCount++;
+ };
+
+ [cloneDict release];
+ cloneDict = nil;
+ }
+
+ [_serviceAttribMap release];
+ _serviceAttribMap = nil;
+ }
+
+ if (_matchingServicesIterator!=0)
+ {
+ IOObjectRelease((io_object_t) _matchingServicesIterator);
+ _matchingServicesIterator = 0;
+ }
+
+ if (_secureInputNotification!=0)
+ {
+ IOObjectRelease((io_object_t) _secureInputNotification);
+ _secureInputNotification = 0;
+ }
+
+ if (_notifyRLSource!=NULL)
+ {
+ CFRunLoopSourceInvalidate(_notifyRLSource);
+ _notifyRLSource = NULL;
+ }
+
+ if (_notifyPort!=NULL)
+ {
+ IONotificationPortDestroy(_notifyPort);
+ _notifyPort = NULL;
+ }
+
+ if (_masterPort!=0)
+ {
+ mach_port_deallocate(mach_task_self(), _masterPort);
+ _masterPort = 0;
+ }
+
+ if (_returnToPID!=nil)
+ {
+ [_returnToPID release];
+ _returnToPID = nil;
+ }
+
+ if (_mode!=kHIDRemoteModeNone)
+ {
+ // Post status
+ [self _postStatusWithAction:kHIDRemoteDNStatusActionStop];
+
+ if (_sendStatusNotifications)
+ {
+ // In case we were not ready to lend it earlier, tell other HIDRemote apps that the resources (if any were used) are now again available for use by other applications
+ if (((_mode==kHIDRemoteModeExclusive) || (_mode==kHIDRemoteModeExclusiveAuto)) && (_sendExclusiveResourceReuseNotification==YES) && (_exclusiveLockLending==NO) && (serviceCount>0))
+ {
+ _mode = kHIDRemoteModeNone;
+
+ if (!_isRestarting)
+ {
+ [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry
+ object:kHIDRemoteDNHIDRemoteRetryGlobalObject
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
+ [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
+ nil]
+ deliverImmediately:YES];
+ }
+ }
+ }
+ }
+
+ _mode = kHIDRemoteModeNone;
+ _isStopping = NO;
}
- (BOOL)isStarted
{
- return (_mode != kHIDRemoteModeNone);
+ return (_mode != kHIDRemoteModeNone);
}
- (HIDRemoteMode)startedInMode
{
- return (_mode);
+ return (_mode);
}
- (unsigned)activeRemoteControlCount
{
- return ([_serviceAttribMap count]);
+ return ([_serviceAttribMap count]);
}
- (SInt32)lastSeenRemoteControlID
{
- return (_lastSeenRemoteID);
+ return (_lastSeenRemoteID);
}
- (HIDRemoteModel)lastSeenModel
{
- return (_lastSeenModel);
+ return (_lastSeenModel);
}
- (void)setLastSeenModel:(HIDRemoteModel)aModel
{
- _lastSeenModel = aModel;
+ _lastSeenModel = aModel;
}
- (void)setSimulateHoldEvents:(BOOL)newSimulateHoldEvents
{
- _simulateHoldEvents = newSimulateHoldEvents;
+ _simulateHoldEvents = newSimulateHoldEvents;
}
- (BOOL)simulateHoldEvents
{
- return (_simulateHoldEvents);
+ return (_simulateHoldEvents);
}
- (NSArray *)unusedButtonCodes
{
- return (_unusedButtonCodes);
+ return (_unusedButtonCodes);
}
- (void)setUnusedButtonCodes:(NSArray *)newArrayWithUnusedButtonCodesAsNSNumbers
{
- [newArrayWithUnusedButtonCodesAsNSNumbers retain];
- [_unusedButtonCodes release];
-
- _unusedButtonCodes = newArrayWithUnusedButtonCodesAsNSNumbers;
+ [newArrayWithUnusedButtonCodesAsNSNumbers retain];
+ [_unusedButtonCodes release];
+
+ _unusedButtonCodes = newArrayWithUnusedButtonCodesAsNSNumbers;
- [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate];
+ [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate];
}
- (void)setDelegate:(NSObject <HIDRemoteDelegate> *)newDelegate
{
- _delegate = newDelegate;
+ _delegate = newDelegate;
}
- (NSObject <HIDRemoteDelegate> *)delegate
{
- return (_delegate);
+ return (_delegate);
}
#pragma mark -- PUBLIC: Expert APIs --
- (void)setEnableSecureEventInputWorkaround:(BOOL)newEnableSecureEventInputWorkaround
{
- _secureEventInputWorkAround = newEnableSecureEventInputWorkaround;
+ _secureEventInputWorkAround = newEnableSecureEventInputWorkaround;
}
- (BOOL)enableSecureEventInputWorkaround
{
- return (_secureEventInputWorkAround);
+ return (_secureEventInputWorkAround);
}
- (void)setExclusiveLockLendingEnabled:(BOOL)newExclusiveLockLendingEnabled
{
- if (newExclusiveLockLendingEnabled != _exclusiveLockLending)
- {
- _exclusiveLockLending = newExclusiveLockLendingEnabled;
-
- if (_exclusiveLockLending)
- {
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteStatus object:nil];
- }
- else
- {
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteStatus object:nil];
-
- [_waitForReturnByPID release];
- _waitForReturnByPID = nil;
- }
- }
+ if (newExclusiveLockLendingEnabled != _exclusiveLockLending)
+ {
+ _exclusiveLockLending = newExclusiveLockLendingEnabled;
+
+ if (_exclusiveLockLending)
+ {
+ [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteStatus object:nil];
+ }
+ else
+ {
+ [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteStatus object:nil];
+
+ [_waitForReturnByPID release];
+ _waitForReturnByPID = nil;
+ }
+ }
}
- (BOOL)exclusiveLockLendingEnabled
{
- return (_exclusiveLockLending);
+ return (_exclusiveLockLending);
}
- (void)setSendExclusiveResourceReuseNotification:(BOOL)newSendExclusiveResourceReuseNotification
{
- _sendExclusiveResourceReuseNotification = newSendExclusiveResourceReuseNotification;
+ _sendExclusiveResourceReuseNotification = newSendExclusiveResourceReuseNotification;
}
- (BOOL)sendExclusiveResourceReuseNotification
{
- return (_sendExclusiveResourceReuseNotification);
+ return (_sendExclusiveResourceReuseNotification);
}
- (BOOL)isApplicationTerminating
{
- return (_applicationIsTerminating);
+ return (_applicationIsTerminating);
}
- (BOOL)isStopping
{
- return (_isStopping);
+ return (_isStopping);
}
#pragma mark -- PRIVATE: Application becomes active / inactive handling for kHIDRemoteModeExclusiveAuto --
- (void)_appStatusChanged:(NSNotification *)notification
{
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
- if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only
- {
- if ([NSThread currentThread] != _runOnThread)
- {
- if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification])
- {
- if (!_autoRecover)
- {
- return;
- }
- }
-
- if ([[notification name] isEqual:NSApplicationWillResignActiveNotification])
- {
- if (_mode != kHIDRemoteModeExclusiveAuto)
- {
- return;
- }
- }
-
- [self performSelector:@selector(_appStatusChanged:) onThread:_runOnThread withObject:notification waitUntilDone:[[notification name] isEqual:NSApplicationWillTerminateNotification]];
- return;
- }
- }
- #endif
-
- if (notification!=nil)
- {
- if (_autoRecoveryTimer!=nil)
- {
- [_autoRecoveryTimer invalidate];
- [_autoRecoveryTimer release];
- _autoRecoveryTimer = nil;
- }
-
- if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification])
- {
- if (_autoRecover)
- {
- // Delay autorecover by 0.1 to avoid race conditions
- if ((_autoRecoveryTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.1] interval:0.1 target:self selector:@selector(_delayedAutoRecovery:) userInfo:nil repeats:NO]) != nil)
- {
- // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes.
- // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code
- // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0.
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)_autoRecoveryTimer, kCFRunLoopCommonModes);
- }
- }
- }
-
- if ([[notification name] isEqual:NSApplicationWillResignActiveNotification])
- {
- if (_mode == kHIDRemoteModeExclusiveAuto)
- {
- [self stopRemoteControl];
- _autoRecover = YES;
- }
- }
-
- if ([[notification name] isEqual:NSApplicationWillTerminateNotification])
- {
- _applicationIsTerminating = YES;
-
- if ([self isStarted])
- {
- [self stopRemoteControl];
- }
- }
- }
+ #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
+ if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only
+ {
+ if ([NSThread currentThread] != _runOnThread)
+ {
+ if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification])
+ {
+ if (!_autoRecover)
+ {
+ return;
+ }
+ }
+
+ if ([[notification name] isEqual:NSApplicationWillResignActiveNotification])
+ {
+ if (_mode != kHIDRemoteModeExclusiveAuto)
+ {
+ return;
+ }
+ }
+
+ [self performSelector:@selector(_appStatusChanged:) onThread:_runOnThread withObject:notification waitUntilDone:[[notification name] isEqual:NSApplicationWillTerminateNotification]];
+ return;
+ }
+ }
+ #endif
+
+ if (notification!=nil)
+ {
+ if (_autoRecoveryTimer!=nil)
+ {
+ [_autoRecoveryTimer invalidate];
+ [_autoRecoveryTimer release];
+ _autoRecoveryTimer = nil;
+ }
+
+ if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification])
+ {
+ if (_autoRecover)
+ {
+ // Delay autorecover by 0.1 to avoid race conditions
+ if ((_autoRecoveryTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.1] interval:0.1 target:self selector:@selector(_delayedAutoRecovery:) userInfo:nil repeats:NO]) != nil)
+ {
+ // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes.
+ // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code
+ // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0.
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)_autoRecoveryTimer, kCFRunLoopCommonModes);
+ }
+ }
+ }
+
+ if ([[notification name] isEqual:NSApplicationWillResignActiveNotification])
+ {
+ if (_mode == kHIDRemoteModeExclusiveAuto)
+ {
+ [self stopRemoteControl];
+ _autoRecover = YES;
+ }
+ }
+
+ if ([[notification name] isEqual:NSApplicationWillTerminateNotification])
+ {
+ _applicationIsTerminating = YES;
+
+ if ([self isStarted])
+ {
+ [self stopRemoteControl];
+ }
+ }
+ }
}
- (void)_delayedAutoRecovery:(NSTimer *)aTimer
{
- [_autoRecoveryTimer invalidate];
- [_autoRecoveryTimer release];
- _autoRecoveryTimer = nil;
-
- if (_autoRecover)
- {
- [self startRemoteControl:kHIDRemoteModeExclusiveAuto];
- _autoRecover = NO;
- }
+ [_autoRecoveryTimer invalidate];
+ [_autoRecoveryTimer release];
+ _autoRecoveryTimer = nil;
+
+ if (_autoRecover)
+ {
+ [self startRemoteControl:kHIDRemoteModeExclusiveAuto];
+ _autoRecover = NO;
+ }
}
#pragma mark -- PRIVATE: Distributed notifiations handling --
- (void)_postStatusWithAction:(NSString *)action
{
- if (_sendStatusNotifications)
- {
- [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteStatus
- object:((_pidString!=nil) ? _pidString : [NSString stringWithFormat:@"%d",getpid()])
- userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithInt:1], kHIDRemoteDNStatusHIDRemoteVersionKey,
- [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
- [NSNumber numberWithInt:(int)_mode], kHIDRemoteDNStatusModeKey,
- [NSNumber numberWithUnsignedInt:(unsigned int)[self activeRemoteControlCount]], kHIDRemoteDNStatusRemoteControlCountKey,
- ((_unusedButtonCodes!=nil) ? _unusedButtonCodes : [NSArray array]), kHIDRemoteDNStatusUnusedButtonCodesKey,
- action, kHIDRemoteDNStatusActionKey,
- [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
- _returnToPID, kHIDRemoteDNStatusReturnToPIDKey,
- nil]
- deliverImmediately:YES
- ];
- }
+ if (_sendStatusNotifications)
+ {
+ [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteStatus
+ object:((_pidString!=nil) ? _pidString : [NSString stringWithFormat:@"%d",getpid()])
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInt:1], kHIDRemoteDNStatusHIDRemoteVersionKey,
+ [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
+ [NSNumber numberWithInt:(int)_mode], kHIDRemoteDNStatusModeKey,
+ [NSNumber numberWithUnsignedInt:(unsigned int)[self activeRemoteControlCount]], kHIDRemoteDNStatusRemoteControlCountKey,
+ ((_unusedButtonCodes!=nil) ? _unusedButtonCodes : [NSArray array]), kHIDRemoteDNStatusUnusedButtonCodesKey,
+ action, kHIDRemoteDNStatusActionKey,
+ [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
+ _returnToPID, kHIDRemoteDNStatusReturnToPIDKey,
+ nil]
+ deliverImmediately:YES
+ ];
+ }
}
- (void)_handleNotifications:(NSNotification *)notification
{
- NSString *notificationName;
-
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
- if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only
- {
- if ([NSThread currentThread] != _runOnThread)
- {
- [self performSelector:@selector(_handleNotifications:) onThread:_runOnThread withObject:notification waitUntilDone:NO];
- return;
- }
- }
- #endif
-
- if ((notification!=nil) && ((notificationName = [notification name]) != nil))
- {
- if ([notificationName isEqual:kHIDRemoteDNHIDRemotePing])
- {
- [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate];
- }
-
- if ([notificationName isEqual:kHIDRemoteDNHIDRemoteRetry])
- {
- if ([self isStarted])
- {
- BOOL retry = YES;
-
- // Ignore our own global retry broadcasts
- if ([[notification object] isEqual:kHIDRemoteDNHIDRemoteRetryGlobalObject])
- {
- NSNumber *fromPID;
-
- if ((fromPID = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]) != nil)
- {
- if (getpid() == (int)[fromPID unsignedIntValue])
- {
- retry = NO;
- }
- }
- }
-
- if (retry)
- {
- if (([self delegate] != nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:shouldRetryExclusiveLockWithInfo:)]))
- {
- retry = [[self delegate] hidRemote:self shouldRetryExclusiveLockWithInfo:[notification userInfo]];
- }
- }
-
- if (retry)
- {
- HIDRemoteMode restartInMode = _mode;
-
- if (restartInMode != kHIDRemoteModeNone)
- {
- _isRestarting = YES;
- [self stopRemoteControl];
-
- [_returnToPID release];
- _returnToPID = nil;
-
- [self startRemoteControl:restartInMode];
- _isRestarting = NO;
-
- if (restartInMode != kHIDRemoteModeShared)
- {
- _returnToPID = [[[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey] retain];
- }
- }
- }
- else
- {
- NSNumber *cacheReturnPID = _returnToPID;
-
- _returnToPID = [[[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey] retain];
- [self _postStatusWithAction:kHIDRemoteDNStatusActionNoNeed];
- [_returnToPID release];
-
- _returnToPID = cacheReturnPID;
- }
- }
- }
-
- if (_exclusiveLockLending)
- {
- if ([notificationName isEqual:kHIDRemoteDNHIDRemoteStatus])
- {
- NSString *action;
-
- if ((action = [[notification userInfo] objectForKey:kHIDRemoteDNStatusActionKey]) != nil)
- {
- if ((_mode == kHIDRemoteModeNone) && (_waitForReturnByPID!=nil))
- {
- NSNumber *pidNumber, *returnToPIDNumber;
-
- if ((pidNumber = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]) != nil)
- {
- returnToPIDNumber = [[notification userInfo] objectForKey:kHIDRemoteDNStatusReturnToPIDKey];
-
- if ([action isEqual:kHIDRemoteDNStatusActionStart])
- {
- if ([pidNumber isEqual:_waitForReturnByPID])
- {
- NSNumber *startMode;
-
- if ((startMode = [[notification userInfo] objectForKey:kHIDRemoteDNStatusModeKey]) != nil)
- {
- if ([startMode intValue] == kHIDRemoteModeShared)
- {
- returnToPIDNumber = [NSNumber numberWithInt:getpid()];
- action = kHIDRemoteDNStatusActionNoNeed;
- }
- }
- }
- }
-
- if (returnToPIDNumber != nil)
- {
- if ([action isEqual:kHIDRemoteDNStatusActionStop] || [action isEqual:kHIDRemoteDNStatusActionNoNeed])
- {
- if ([pidNumber isEqual:_waitForReturnByPID] && ([returnToPIDNumber intValue] == getpid()))
- {
- [_waitForReturnByPID release];
- _waitForReturnByPID = nil;
-
- if (([self delegate] != nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:exclusiveLockReleasedByApplicationWithInfo:)]))
- {
- [[self delegate] hidRemote:self exclusiveLockReleasedByApplicationWithInfo:[notification userInfo]];
- }
- else
- {
- [self startRemoteControl:kHIDRemoteModeExclusive];
- }
- }
- }
- }
- }
- }
-
- if (_mode==kHIDRemoteModeExclusive)
- {
- if ([action isEqual:kHIDRemoteDNStatusActionStart])
- {
- NSNumber *originPID = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey];
- BOOL lendLock = YES;
-
- if ([originPID intValue] != getpid())
- {
- if (([self delegate] != nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:lendExclusiveLockToApplicationWithInfo:)]))
- {
- lendLock = [[self delegate] hidRemote:self lendExclusiveLockToApplicationWithInfo:[notification userInfo]];
- }
-
- if (lendLock)
- {
- [_waitForReturnByPID release];
- _waitForReturnByPID = [originPID retain];
-
- if (_waitForReturnByPID != nil)
- {
- [self stopRemoteControl];
-
- [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry
- object:[NSString stringWithFormat:@"%d", [_waitForReturnByPID intValue]]
- userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
- [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
- nil]
- deliverImmediately:YES];
- }
- }
- }
- }
- }
- }
- }
- }
- }
+ NSString *notificationName;
+
+ #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
+ if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only
+ {
+ if ([NSThread currentThread] != _runOnThread)
+ {
+ [self performSelector:@selector(_handleNotifications:) onThread:_runOnThread withObject:notification waitUntilDone:NO];
+ return;
+ }
+ }
+ #endif
+
+ if ((notification!=nil) && ((notificationName = [notification name]) != nil))
+ {
+ if ([notificationName isEqual:kHIDRemoteDNHIDRemotePing])
+ {
+ [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate];
+ }
+
+ if ([notificationName isEqual:kHIDRemoteDNHIDRemoteRetry])
+ {
+ if ([self isStarted])
+ {
+ BOOL retry = YES;
+
+ // Ignore our own global retry broadcasts
+ if ([[notification object] isEqual:kHIDRemoteDNHIDRemoteRetryGlobalObject])
+ {
+ NSNumber *fromPID;
+
+ if ((fromPID = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]) != nil)
+ {
+ if (getpid() == (int)[fromPID unsignedIntValue])
+ {
+ retry = NO;
+ }
+ }
+ }
+
+ if (retry)
+ {
+ if (([self delegate] != nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:shouldRetryExclusiveLockWithInfo:)]))
+ {
+ retry = [[self delegate] hidRemote:self shouldRetryExclusiveLockWithInfo:[notification userInfo]];
+ }
+ }
+
+ if (retry)
+ {
+ HIDRemoteMode restartInMode = _mode;
+
+ if (restartInMode != kHIDRemoteModeNone)
+ {
+ _isRestarting = YES;
+ [self stopRemoteControl];
+
+ [_returnToPID release];
+ _returnToPID = nil;
+
+ [self startRemoteControl:restartInMode];
+ _isRestarting = NO;
+
+ if (restartInMode != kHIDRemoteModeShared)
+ {
+ _returnToPID = [[[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey] retain];
+ }
+ }
+ }
+ else
+ {
+ NSNumber *cacheReturnPID = _returnToPID;
+
+ _returnToPID = [[[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey] retain];
+ [self _postStatusWithAction:kHIDRemoteDNStatusActionNoNeed];
+ [_returnToPID release];
+
+ _returnToPID = cacheReturnPID;
+ }
+ }
+ }
+
+ if (_exclusiveLockLending)
+ {
+ if ([notificationName isEqual:kHIDRemoteDNHIDRemoteStatus])
+ {
+ NSString *action;
+
+ if ((action = [[notification userInfo] objectForKey:kHIDRemoteDNStatusActionKey]) != nil)
+ {
+ if ((_mode == kHIDRemoteModeNone) && (_waitForReturnByPID!=nil))
+ {
+ NSNumber *pidNumber, *returnToPIDNumber;
+
+ if ((pidNumber = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]) != nil)
+ {
+ returnToPIDNumber = [[notification userInfo] objectForKey:kHIDRemoteDNStatusReturnToPIDKey];
+
+ if ([action isEqual:kHIDRemoteDNStatusActionStart])
+ {
+ if ([pidNumber isEqual:_waitForReturnByPID])
+ {
+ NSNumber *startMode;
+
+ if ((startMode = [[notification userInfo] objectForKey:kHIDRemoteDNStatusModeKey]) != nil)
+ {
+ if ([startMode intValue] == kHIDRemoteModeShared)
+ {
+ returnToPIDNumber = [NSNumber numberWithInt:getpid()];
+ action = kHIDRemoteDNStatusActionNoNeed;
+ }
+ }
+ }
+ }
+
+ if (returnToPIDNumber != nil)
+ {
+ if ([action isEqual:kHIDRemoteDNStatusActionStop] || [action isEqual:kHIDRemoteDNStatusActionNoNeed])
+ {
+ if ([pidNumber isEqual:_waitForReturnByPID] && ([returnToPIDNumber intValue] == getpid()))
+ {
+ [_waitForReturnByPID release];
+ _waitForReturnByPID = nil;
+
+ if (([self delegate] != nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:exclusiveLockReleasedByApplicationWithInfo:)]))
+ {
+ [[self delegate] hidRemote:self exclusiveLockReleasedByApplicationWithInfo:[notification userInfo]];
+ }
+ else
+ {
+ [self startRemoteControl:kHIDRemoteModeExclusive];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (_mode==kHIDRemoteModeExclusive)
+ {
+ if ([action isEqual:kHIDRemoteDNStatusActionStart])
+ {
+ NSNumber *originPID = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey];
+ BOOL lendLock = YES;
+
+ if ([originPID intValue] != getpid())
+ {
+ if (([self delegate] != nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:lendExclusiveLockToApplicationWithInfo:)]))
+ {
+ lendLock = [[self delegate] hidRemote:self lendExclusiveLockToApplicationWithInfo:[notification userInfo]];
+ }
+
+ if (lendLock)
+ {
+ [_waitForReturnByPID release];
+ _waitForReturnByPID = [originPID retain];
+
+ if (_waitForReturnByPID != nil)
+ {
+ [self stopRemoteControl];
+
+ [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry
+ object:[NSString stringWithFormat:@"%d", [_waitForReturnByPID intValue]]
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
+ [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
+ nil]
+ deliverImmediately:YES];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
- (void)_setSendStatusNotifications:(BOOL)doSend
{
- _sendStatusNotifications = doSend;
+ _sendStatusNotifications = doSend;
}
- (BOOL)_sendStatusNotifications
{
- return (_sendStatusNotifications);
+ return (_sendStatusNotifications);
}
#pragma mark -- PRIVATE: Service setup and destruction --
- (BOOL)_prematchService:(io_object_t)service
{
- BOOL serviceMatches = NO;
- NSString *ioClass;
- NSNumber *candelairHIDRemoteCompatibilityMask;
-
- if (service != 0)
- {
- // IOClass matching
- if ((ioClass = (NSString *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
- CFSTR(kIOClassKey),
- kCFAllocatorDefault,
- 0)) != nil)
- {
- // Match on Apple's AppleIRController and old versions of the Remote Buddy IR Controller
- if ([ioClass isEqual:@"AppleIRController"] || [ioClass isEqual:@"RBIOKitAIREmu"])
- {
- CFTypeRef candelairHIDRemoteCompatibilityDevice;
-
- serviceMatches = YES;
-
- if ((candelairHIDRemoteCompatibilityDevice = IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityDevice"), kCFAllocatorDefault, 0)) != NULL)
- {
- if (CFEqual(kCFBooleanTrue, candelairHIDRemoteCompatibilityDevice))
- {
- serviceMatches = NO;
- }
-
- CFRelease (candelairHIDRemoteCompatibilityDevice);
- }
- }
-
- // Match on the virtual IOSPIRIT IR Controller
- if ([ioClass isEqual:@"IOSPIRITIRController"])
- {
- serviceMatches = YES;
- }
-
- CFRelease((CFTypeRef)ioClass);
- }
-
- // Match on services that claim compatibility with the HID Remote class (Candelair or third-party) by having a property of CandelairHIDRemoteCompatibilityMask = 1 <Type: Number>
- if ((candelairHIDRemoteCompatibilityMask = (NSNumber *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityMask"), kCFAllocatorDefault, 0)) != nil)
- {
- if ([candelairHIDRemoteCompatibilityMask isKindOfClass:[NSNumber class]])
- {
- if ([candelairHIDRemoteCompatibilityMask unsignedIntValue] & kHIDRemoteCompatibilityFlagsStandardHIDRemoteDevice)
- {
- serviceMatches = YES;
- }
- else
- {
- serviceMatches = NO;
- }
- }
-
- CFRelease((CFTypeRef)candelairHIDRemoteCompatibilityMask);
- }
- }
-
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:inspectNewHardwareWithService:prematchResult:)]))
- {
- serviceMatches = [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self inspectNewHardwareWithService:service prematchResult:serviceMatches];
- }
-
- return (serviceMatches);
+ BOOL serviceMatches = NO;
+ NSString *ioClass;
+ NSNumber *candelairHIDRemoteCompatibilityMask;
+
+ if (service != 0)
+ {
+ // IOClass matching
+ if ((ioClass = (NSString *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
+ CFSTR(kIOClassKey),
+ kCFAllocatorDefault,
+ 0)) != nil)
+ {
+ // Match on Apple's AppleIRController and old versions of the Remote Buddy IR Controller
+ if ([ioClass isEqual:@"AppleIRController"] || [ioClass isEqual:@"RBIOKitAIREmu"])
+ {
+ CFTypeRef candelairHIDRemoteCompatibilityDevice;
+
+ serviceMatches = YES;
+
+ if ((candelairHIDRemoteCompatibilityDevice = IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityDevice"), kCFAllocatorDefault, 0)) != NULL)
+ {
+ if (CFEqual(kCFBooleanTrue, candelairHIDRemoteCompatibilityDevice))
+ {
+ serviceMatches = NO;
+ }
+
+ CFRelease (candelairHIDRemoteCompatibilityDevice);
+ }
+ }
+
+ // Match on the virtual IOSPIRIT IR Controller
+ if ([ioClass isEqual:@"IOSPIRITIRController"])
+ {
+ serviceMatches = YES;
+ }
+
+ CFRelease((CFTypeRef)ioClass);
+ }
+
+ // Match on services that claim compatibility with the HID Remote class (Candelair or third-party) by having a property of CandelairHIDRemoteCompatibilityMask = 1 <Type: Number>
+ if ((candelairHIDRemoteCompatibilityMask = (NSNumber *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityMask"), kCFAllocatorDefault, 0)) != nil)
+ {
+ if ([candelairHIDRemoteCompatibilityMask isKindOfClass:[NSNumber class]])
+ {
+ if ([candelairHIDRemoteCompatibilityMask unsignedIntValue] & kHIDRemoteCompatibilityFlagsStandardHIDRemoteDevice)
+ {
+ serviceMatches = YES;
+ }
+ else
+ {
+ serviceMatches = NO;
+ }
+ }
+
+ CFRelease((CFTypeRef)candelairHIDRemoteCompatibilityMask);
+ }
+ }
+
+ if (([self delegate]!=nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:inspectNewHardwareWithService:prematchResult:)]))
+ {
+ serviceMatches = [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self inspectNewHardwareWithService:service prematchResult:serviceMatches];
+ }
+
+ return (serviceMatches);
}
- (HIDRemoteButtonCode)buttonCodeForUsage:(unsigned int)usage usagePage:(unsigned int)usagePage
{
- HIDRemoteButtonCode buttonCode = kHIDRemoteButtonCodeNone;
-
- switch (usagePage)
- {
- case kHIDPage_Consumer:
- switch (usage)
- {
- case kHIDUsage_Csmr_MenuPick:
- // Aluminum Remote: Center
- buttonCode = (kHIDRemoteButtonCodeCenter|kHIDRemoteButtonCodeAluminumMask);
- break;
-
- case kHIDUsage_Csmr_ModeStep:
- // Aluminium Remote: Center Hold
- buttonCode = (kHIDRemoteButtonCodeCenterHold|kHIDRemoteButtonCodeAluminumMask);
- break;
-
- case kHIDUsage_Csmr_PlayOrPause:
- // Aluminum Remote: Play/Pause
- buttonCode = (kHIDRemoteButtonCodePlay|kHIDRemoteButtonCodeAluminumMask);
- break;
-
- case kHIDUsage_Csmr_Rewind:
- buttonCode = kHIDRemoteButtonCodeLeftHold;
- break;
-
- case kHIDUsage_Csmr_FastForward:
- buttonCode = kHIDRemoteButtonCodeRightHold;
- break;
-
- case kHIDUsage_Csmr_Menu:
- buttonCode = kHIDRemoteButtonCodeMenuHold;
- break;
- }
- break;
-
- case kHIDPage_GenericDesktop:
- switch (usage)
- {
- case kHIDUsage_GD_SystemAppMenu:
- buttonCode = kHIDRemoteButtonCodeMenu;
- break;
-
- case kHIDUsage_GD_SystemMenu:
- buttonCode = kHIDRemoteButtonCodeCenter;
- break;
-
- case kHIDUsage_GD_SystemMenuRight:
- buttonCode = kHIDRemoteButtonCodeRight;
- break;
-
- case kHIDUsage_GD_SystemMenuLeft:
- buttonCode = kHIDRemoteButtonCodeLeft;
- break;
-
- case kHIDUsage_GD_SystemMenuUp:
- buttonCode = kHIDRemoteButtonCodeUp;
- break;
-
- case kHIDUsage_GD_SystemMenuDown:
- buttonCode = kHIDRemoteButtonCodeDown;
- break;
- }
- break;
-
- case 0x06: /* Reserved */
- switch (usage)
- {
- case 0x22:
- buttonCode = kHIDRemoteButtonCodeIDChanged;
- break;
- }
- break;
-
- case 0xFF01: /* Vendor specific */
- switch (usage)
- {
- case 0x23:
- buttonCode = kHIDRemoteButtonCodeCenterHold;
- break;
-
- #ifdef _HIDREMOTE_EXTENSIONS
- #define _HIDREMOTE_EXTENSIONS_SECTION 2
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
- }
- break;
- }
-
- return (buttonCode);
+ HIDRemoteButtonCode buttonCode = kHIDRemoteButtonCodeNone;
+
+ switch (usagePage)
+ {
+ case kHIDPage_Consumer:
+ switch (usage)
+ {
+ case kHIDUsage_Csmr_MenuPick:
+ // Aluminum Remote: Center
+ buttonCode = (kHIDRemoteButtonCodeCenter|kHIDRemoteButtonCodeAluminumMask);
+ break;
+
+ case kHIDUsage_Csmr_ModeStep:
+ // Aluminium Remote: Center Hold
+ buttonCode = (kHIDRemoteButtonCodeCenterHold|kHIDRemoteButtonCodeAluminumMask);
+ break;
+
+ case kHIDUsage_Csmr_PlayOrPause:
+ // Aluminum Remote: Play/Pause
+ buttonCode = (kHIDRemoteButtonCodePlay|kHIDRemoteButtonCodeAluminumMask);
+ break;
+
+ case kHIDUsage_Csmr_Rewind:
+ buttonCode = kHIDRemoteButtonCodeLeftHold;
+ break;
+
+ case kHIDUsage_Csmr_FastForward:
+ buttonCode = kHIDRemoteButtonCodeRightHold;
+ break;
+
+ case kHIDUsage_Csmr_Menu:
+ buttonCode = kHIDRemoteButtonCodeMenuHold;
+ break;
+ }
+ break;
+
+ case kHIDPage_GenericDesktop:
+ switch (usage)
+ {
+ case kHIDUsage_GD_SystemAppMenu:
+ buttonCode = kHIDRemoteButtonCodeMenu;
+ break;
+
+ case kHIDUsage_GD_SystemMenu:
+ buttonCode = kHIDRemoteButtonCodeCenter;
+ break;
+
+ case kHIDUsage_GD_SystemMenuRight:
+ buttonCode = kHIDRemoteButtonCodeRight;
+ break;
+
+ case kHIDUsage_GD_SystemMenuLeft:
+ buttonCode = kHIDRemoteButtonCodeLeft;
+ break;
+
+ case kHIDUsage_GD_SystemMenuUp:
+ buttonCode = kHIDRemoteButtonCodeUp;
+ break;
+
+ case kHIDUsage_GD_SystemMenuDown:
+ buttonCode = kHIDRemoteButtonCodeDown;
+ break;
+ }
+ break;
+
+ case 0x06: /* Reserved */
+ switch (usage)
+ {
+ case 0x22:
+ buttonCode = kHIDRemoteButtonCodeIDChanged;
+ break;
+ }
+ break;
+
+ case 0xFF01: /* Vendor specific */
+ switch (usage)
+ {
+ case 0x23:
+ buttonCode = kHIDRemoteButtonCodeCenterHold;
+ break;
+
+ #ifdef _HIDREMOTE_EXTENSIONS
+ #define _HIDREMOTE_EXTENSIONS_SECTION 2
+ #include "HIDRemoteAdditions.h"
+ #undef _HIDREMOTE_EXTENSIONS_SECTION
+ #endif /* _HIDREMOTE_EXTENSIONS */
+ }
+ break;
+ }
+
+ return (buttonCode);
}
- (BOOL)_setupService:(io_object_t)service
{
- kern_return_t kernResult;
- IOReturn returnCode;
- HRESULT hResult;
- SInt32 score;
- BOOL opened = NO, queueStarted = NO;
- IOHIDDeviceInterface122 **hidDeviceInterface = NULL;
- IOCFPlugInInterface **cfPluginInterface = NULL;
- IOHIDQueueInterface **hidQueueInterface = NULL;
- io_object_t serviceNotification = 0;
- CFRunLoopSourceRef queueEventSource = NULL;
- NSMutableDictionary *hidAttribsDict = nil;
- CFArrayRef hidElements = NULL;
- NSError *error = nil;
- UInt32 errorCode = 0;
-
- if (![self _prematchService:service])
- {
- return (NO);
- }
-
- do
- {
- // Create a plugin interface ..
- kernResult = IOCreatePlugInInterfaceForService( service,
- kIOHIDDeviceUserClientTypeID,
- kIOCFPlugInInterfaceID,
- &cfPluginInterface,
- &score);
-
- if (kernResult != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:kernResult userInfo:nil];
- errorCode = 1;
- break;
- }
-
-
- // .. use it to get the HID interface ..
- hResult = (*cfPluginInterface)->QueryInterface( cfPluginInterface,
- CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID122),
- (LPVOID)&hidDeviceInterface);
-
- if ((hResult!=S_OK) || (hidDeviceInterface==NULL))
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:hResult userInfo:nil];
- errorCode = 2;
- break;
- }
-
-
- // .. then open it ..
- switch (_mode)
- {
- case kHIDRemoteModeShared:
- hResult = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeNone);
- break;
-
- case kHIDRemoteModeExclusive:
- case kHIDRemoteModeExclusiveAuto:
- hResult = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeSeizeDevice);
- break;
-
- default:
- goto cleanUp; // Ugh! But there are no "double breaks" available in C AFAIK ..
- break;
- }
-
- if (hResult!=S_OK)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:hResult userInfo:nil];
- errorCode = 3;
- break;
- }
-
- opened = YES;
-
- // .. query the HID elements ..
- returnCode = (*hidDeviceInterface)->copyMatchingElements(hidDeviceInterface,
- NULL,
- &hidElements);
- if ((returnCode != kIOReturnSuccess) || (hidElements==NULL))
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 4;
-
- break;
- }
-
- // Setup an event queue for HID events!
- hidQueueInterface = (*hidDeviceInterface)->allocQueue(hidDeviceInterface);
- if (hidQueueInterface == NULL)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
- errorCode = 5;
-
- break;
- }
-
- returnCode = (*hidQueueInterface)->create(hidQueueInterface, 0, 32);
- if (returnCode != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 6;
-
- break;
- }
-
-
- // Setup of attributes stored for this HID device
- hidAttribsDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
- [NSValue valueWithPointer:(const void *)cfPluginInterface], kHIDRemoteCFPluginInterface,
- [NSValue valueWithPointer:(const void *)hidDeviceInterface], kHIDRemoteHIDDeviceInterface,
- [NSValue valueWithPointer:(const void *)hidQueueInterface], kHIDRemoteHIDQueueInterface,
- nil];
-
- {
- UInt32 i, hidElementCnt = CFArrayGetCount(hidElements);
- NSMutableDictionary *cookieButtonCodeLUT = [[NSMutableDictionary alloc] init];
- NSMutableDictionary *cookieCount = [[NSMutableDictionary alloc] init];
-
- if ((cookieButtonCodeLUT==nil) || (cookieCount==nil))
- {
- [cookieButtonCodeLUT release];
- cookieButtonCodeLUT = nil;
-
- [cookieCount release];
- cookieCount = nil;
-
- error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
- errorCode = 7;
-
- break;
- }
-
- // Analyze the HID elements and find matching elements
- for (i=0;i<hidElementCnt;i++)
- {
- CFDictionaryRef hidDict;
- NSNumber *usage, *usagePage, *cookie;
- HIDRemoteButtonCode buttonCode = kHIDRemoteButtonCodeNone;
-
- hidDict = CFArrayGetValueAtIndex(hidElements, i);
-
- usage = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementUsageKey));
- usagePage = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementUsagePageKey));
- cookie = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementCookieKey));
-
- if ((usage!=nil) && (usagePage!=nil) && (cookie!=nil))
- {
- // Find the button codes for the ID combos
- buttonCode = [self buttonCodeForUsage:[usage unsignedIntValue] usagePage:[usagePage unsignedIntValue]];
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Debug logging code
- #define _HIDREMOTE_EXTENSIONS_SECTION 3
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-
- // Did record match?
- if (buttonCode != kHIDRemoteButtonCodeNone)
- {
- NSString *pairString = [[NSString alloc] initWithFormat:@"%u_%u", [usagePage unsignedIntValue], [usage unsignedIntValue]];
- NSNumber *buttonCodeNumber = [[NSNumber alloc] initWithUnsignedInt:(unsigned int)buttonCode];
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Debug logging code
- #define _HIDREMOTE_EXTENSIONS_SECTION 4
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-
- [cookieCount setObject:buttonCodeNumber forKey:pairString];
- [cookieButtonCodeLUT setObject:buttonCodeNumber forKey:cookie];
-
- (*hidQueueInterface)->addElement(hidQueueInterface,
- (IOHIDElementCookie) [cookie unsignedIntValue],
- 0);
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Get current Apple Remote ID value
- #define _HIDREMOTE_EXTENSIONS_SECTION 7
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-
- [buttonCodeNumber release];
- [pairString release];
- }
- }
- }
-
- // Compare number of *unique* matches (thus the cookieCount dictionary) with required minimum
- if ([cookieCount count] < 10)
- {
- [cookieButtonCodeLUT release];
- cookieButtonCodeLUT = nil;
-
- [cookieCount release];
- cookieCount = nil;
-
- error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
- errorCode = 8;
-
- break;
- }
-
- [hidAttribsDict setObject:cookieButtonCodeLUT forKey:kHIDRemoteCookieButtonCodeLUT];
-
- [cookieButtonCodeLUT release];
- cookieButtonCodeLUT = nil;
-
- [cookieCount release];
- cookieCount = nil;
- }
-
- // Finish setup of IOHIDQueueInterface with CFRunLoop
- returnCode = (*hidQueueInterface)->createAsyncEventSource(hidQueueInterface, &queueEventSource);
- if ((returnCode != kIOReturnSuccess) || (queueEventSource == NULL))
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 9;
- break;
- }
-
- returnCode = (*hidQueueInterface)->setEventCallout(hidQueueInterface, HIDEventCallback, (void *)((intptr_t)service), (void *)self);
- if (returnCode != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 10;
- break;
- }
-
- CFRunLoopAddSource( CFRunLoopGetCurrent(),
- queueEventSource,
- kCFRunLoopCommonModes);
- [hidAttribsDict setObject:[NSValue valueWithPointer:(const void *)queueEventSource] forKey:kHIDRemoteCFRunLoopSource];
-
- returnCode = (*hidQueueInterface)->start(hidQueueInterface);
- if (returnCode != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 11;
- break;
- }
-
- queueStarted = YES;
-
- // Setup device notifications
- returnCode = IOServiceAddInterestNotification( _notifyPort,
- service,
- kIOGeneralInterest,
- ServiceNotificationCallback,
- self,
- &serviceNotification);
- if ((returnCode != kIOReturnSuccess) || (serviceNotification==0))
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 12;
- break;
- }
-
- [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)serviceNotification] forKey:kHIDRemoteServiceNotification];
-
- // Retain service
- if (IOObjectRetain(service) != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
- errorCode = 13;
- break;
- }
-
- [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)service] forKey:kHIDRemoteService];
-
- // Get some (somewhat optional) infos on the device
- {
- CFStringRef product, manufacturer, transport;
-
- if ((product = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
- (CFStringRef) @"Product",
- kCFAllocatorDefault,
- 0)) != NULL)
- {
- if (CFGetTypeID(product) == CFStringGetTypeID())
- {
- [hidAttribsDict setObject:(NSString *)product forKey:kHIDRemoteProduct];
- }
-
- CFRelease(product);
- }
-
- if ((manufacturer = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
- (CFStringRef) @"Manufacturer",
- kCFAllocatorDefault,
- 0)) != NULL)
- {
- if (CFGetTypeID(manufacturer) == CFStringGetTypeID())
- {
- [hidAttribsDict setObject:(NSString *)manufacturer forKey:kHIDRemoteManufacturer];
- }
-
- CFRelease(manufacturer);
- }
-
- if ((transport = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
- (CFStringRef) @"Transport",
- kCFAllocatorDefault,
- 0)) != NULL)
- {
- if (CFGetTypeID(transport) == CFStringGetTypeID())
- {
- [hidAttribsDict setObject:(NSString *)transport forKey:kHIDRemoteTransport];
- }
-
- CFRelease(transport);
- }
- }
-
- // Determine Aluminum Remote support
- {
- CFNumberRef aluSupport;
- HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone;
-
- if ((_mode == kHIDRemoteModeExclusive) || (_mode == kHIDRemoteModeExclusiveAuto))
- {
- // Determine if this driver offers on-demand support for the Aluminum Remote (only relevant under OS versions < 10.6.2)
- if ((aluSupport = IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
- (CFStringRef) @"AluminumRemoteSupportLevelOnDemand",
- kCFAllocatorDefault,
- 0)) != nil)
- {
- // There is => request the driver to enable it for us
- if (IORegistryEntrySetCFProperty((io_registry_entry_t)service,
- CFSTR("EnableAluminumRemoteSupportForMe"),
- [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithLongLong:(long long)getpid()], @"pid",
- [NSNumber numberWithLongLong:(long long)getuid()], @"uid",
- nil]) == kIOReturnSuccess)
- {
- if (CFGetTypeID(aluSupport) == CFNumberGetTypeID())
- {
- supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(NSNumber *)aluSupport intValue];
- }
-
- [hidAttribsDict setObject:[NSNumber numberWithBool:YES] forKey:kHIDRemoteAluminumRemoteSupportOnDemand];
- }
-
- CFRelease(aluSupport);
- }
- }
-
- if (supportLevel == kHIDRemoteAluminumRemoteSupportLevelNone)
- {
- if ((aluSupport = IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
- (CFStringRef) @"AluminumRemoteSupportLevel",
- kCFAllocatorDefault,
- 0)) != nil)
- {
- if (CFGetTypeID(aluSupport) == CFNumberGetTypeID())
- {
- supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(NSNumber *)aluSupport intValue];
- }
-
- CFRelease(aluSupport);
- }
- else
- {
- CFStringRef ioKitClassName;
-
- if ((ioKitClassName = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
- CFSTR(kIOClassKey),
- kCFAllocatorDefault,
- 0)) != nil)
- {
- if ([(NSString *)ioKitClassName isEqual:@"AppleIRController"])
- {
- supportLevel = kHIDRemoteAluminumRemoteSupportLevelNative;
- }
-
- CFRelease(ioKitClassName);
- }
- }
- }
-
- [hidAttribsDict setObject:(NSNumber *)[NSNumber numberWithInt:(int)supportLevel] forKey:kHIDRemoteAluminumRemoteSupportLevel];
- }
-
- // Add it to the serviceAttribMap
- [_serviceAttribMap setObject:hidAttribsDict forKey:[NSNumber numberWithUnsignedInt:(unsigned int)service]];
-
- // And we're done with setup ..
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:foundNewHardwareWithAttributes:)]))
- {
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self foundNewHardwareWithAttributes:hidAttribsDict];
- }
-
- [hidAttribsDict release];
- hidAttribsDict = nil;
-
- return(YES);
-
- }while(0);
-
- cleanUp:
-
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:failedNewHardwareWithError:)]))
- {
- if (error!=nil)
- {
- error = [NSError errorWithDomain:[error domain]
- code:[error code]
- userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:errorCode] forKey:@"InternalErrorCode"]
- ];
- }
-
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self failedNewHardwareWithError:error];
- }
-
- // An error occured or this device is not of interest .. cleanup ..
- if (serviceNotification!=0)
- {
- IOObjectRelease(serviceNotification);
- serviceNotification = 0;
- }
-
- if (queueEventSource!=NULL)
- {
- CFRunLoopSourceInvalidate(queueEventSource);
- queueEventSource=NULL;
- }
-
- if (hidQueueInterface!=NULL)
- {
- if (queueStarted)
- {
- (*hidQueueInterface)->stop(hidQueueInterface);
- }
- (*hidQueueInterface)->dispose(hidQueueInterface);
- (*hidQueueInterface)->Release(hidQueueInterface);
- hidQueueInterface = NULL;
- }
-
- if (hidAttribsDict!=nil)
- {
- [hidAttribsDict release];
- hidAttribsDict = nil;
- }
-
- if (hidElements!=NULL)
- {
- CFRelease(hidElements);
- hidElements = NULL;
- }
-
- if (hidDeviceInterface!=NULL)
- {
- if (opened)
- {
- (*hidDeviceInterface)->close(hidDeviceInterface);
- }
- (*hidDeviceInterface)->Release(hidDeviceInterface);
- // opened = NO;
- hidDeviceInterface = NULL;
- }
-
- if (cfPluginInterface!=NULL)
- {
- IODestroyPlugInInterface(cfPluginInterface);
- cfPluginInterface = NULL;
- }
-
- return (NO);
+ kern_return_t kernResult;
+ IOReturn returnCode;
+ HRESULT hResult;
+ SInt32 score;
+ BOOL opened = NO, queueStarted = NO;
+ IOHIDDeviceInterface122 **hidDeviceInterface = NULL;
+ IOCFPlugInInterface **cfPluginInterface = NULL;
+ IOHIDQueueInterface **hidQueueInterface = NULL;
+ io_object_t serviceNotification = 0;
+ CFRunLoopSourceRef queueEventSource = NULL;
+ NSMutableDictionary *hidAttribsDict = nil;
+ CFArrayRef hidElements = NULL;
+ NSError *error = nil;
+ UInt32 errorCode = 0;
+
+ if (![self _prematchService:service])
+ {
+ return (NO);
+ }
+
+ do
+ {
+ // Create a plugin interface ..
+ kernResult = IOCreatePlugInInterfaceForService( service,
+ kIOHIDDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &cfPluginInterface,
+ &score);
+
+ if (kernResult != kIOReturnSuccess)
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:kernResult userInfo:nil];
+ errorCode = 1;
+ break;
+ }
+
+
+ // .. use it to get the HID interface ..
+ hResult = (*cfPluginInterface)->QueryInterface( cfPluginInterface,
+ CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID122),
+ (LPVOID)&hidDeviceInterface);
+
+ if ((hResult!=S_OK) || (hidDeviceInterface==NULL))
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:hResult userInfo:nil];
+ errorCode = 2;
+ break;
+ }
+
+
+ // .. then open it ..
+ switch (_mode)
+ {
+ case kHIDRemoteModeShared:
+ hResult = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeNone);
+ break;
+
+ case kHIDRemoteModeExclusive:
+ case kHIDRemoteModeExclusiveAuto:
+ hResult = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeSeizeDevice);
+ break;
+
+ default:
+ goto cleanUp; // Ugh! But there are no "double breaks" available in C AFAIK ..
+ break;
+ }
+
+ if (hResult!=S_OK)
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:hResult userInfo:nil];
+ errorCode = 3;
+ break;
+ }
+
+ opened = YES;
+
+ // .. query the HID elements ..
+ returnCode = (*hidDeviceInterface)->copyMatchingElements(hidDeviceInterface,
+ NULL,
+ &hidElements);
+ if ((returnCode != kIOReturnSuccess) || (hidElements==NULL))
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
+ errorCode = 4;
+
+ break;
+ }
+
+ // Setup an event queue for HID events!
+ hidQueueInterface = (*hidDeviceInterface)->allocQueue(hidDeviceInterface);
+ if (hidQueueInterface == NULL)
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
+ errorCode = 5;
+
+ break;
+ }
+
+ returnCode = (*hidQueueInterface)->create(hidQueueInterface, 0, 32);
+ if (returnCode != kIOReturnSuccess)
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
+ errorCode = 6;
+
+ break;
+ }
+
+
+ // Setup of attributes stored for this HID device
+ hidAttribsDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
+ [NSValue valueWithPointer:(const void *)cfPluginInterface], kHIDRemoteCFPluginInterface,
+ [NSValue valueWithPointer:(const void *)hidDeviceInterface], kHIDRemoteHIDDeviceInterface,
+ [NSValue valueWithPointer:(const void *)hidQueueInterface], kHIDRemoteHIDQueueInterface,
+ nil];
+
+ {
+ UInt32 i, hidElementCnt = CFArrayGetCount(hidElements);
+ NSMutableDictionary *cookieButtonCodeLUT = [[NSMutableDictionary alloc] init];
+ NSMutableDictionary *cookieCount = [[NSMutableDictionary alloc] init];
+
+ if ((cookieButtonCodeLUT==nil) || (cookieCount==nil))
+ {
+ [cookieButtonCodeLUT release];
+ cookieButtonCodeLUT = nil;
+
+ [cookieCount release];
+ cookieCount = nil;
+
+ error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
+ errorCode = 7;
+
+ break;
+ }
+
+ // Analyze the HID elements and find matching elements
+ for (i=0;i<hidElementCnt;i++)
+ {
+ CFDictionaryRef hidDict;
+ NSNumber *usage, *usagePage, *cookie;
+ HIDRemoteButtonCode buttonCode = kHIDRemoteButtonCodeNone;
+
+ hidDict = CFArrayGetValueAtIndex(hidElements, i);
+
+ usage = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementUsageKey));
+ usagePage = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementUsagePageKey));
+ cookie = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementCookieKey));
+
+ if ((usage!=nil) && (usagePage!=nil) && (cookie!=nil))
+ {
+ // Find the button codes for the ID combos
+ buttonCode = [self buttonCodeForUsage:[usage unsignedIntValue] usagePage:[usagePage unsignedIntValue]];
+
+ #ifdef _HIDREMOTE_EXTENSIONS
+ // Debug logging code
+ #define _HIDREMOTE_EXTENSIONS_SECTION 3
+ #include "HIDRemoteAdditions.h"
+ #undef _HIDREMOTE_EXTENSIONS_SECTION
+ #endif /* _HIDREMOTE_EXTENSIONS */
+
+ // Did record match?
+ if (buttonCode != kHIDRemoteButtonCodeNone)
+ {
+ NSString *pairString = [[NSString alloc] initWithFormat:@"%u_%u", [usagePage unsignedIntValue], [usage unsignedIntValue]];
+ NSNumber *buttonCodeNumber = [[NSNumber alloc] initWithUnsignedInt:(unsigned int)buttonCode];
+
+ #ifdef _HIDREMOTE_EXTENSIONS
+ // Debug logging code
+ #define _HIDREMOTE_EXTENSIONS_SECTION 4
+ #include "HIDRemoteAdditions.h"
+ #undef _HIDREMOTE_EXTENSIONS_SECTION
+ #endif /* _HIDREMOTE_EXTENSIONS */
+
+ [cookieCount setObject:buttonCodeNumber forKey:pairString];
+ [cookieButtonCodeLUT setObject:buttonCodeNumber forKey:cookie];
+
+ (*hidQueueInterface)->addElement(hidQueueInterface,
+ (IOHIDElementCookie) [cookie unsignedIntValue],
+ 0);
+
+ #ifdef _HIDREMOTE_EXTENSIONS
+ // Get current Apple Remote ID value
+ #define _HIDREMOTE_EXTENSIONS_SECTION 7
+ #include "HIDRemoteAdditions.h"
+ #undef _HIDREMOTE_EXTENSIONS_SECTION
+ #endif /* _HIDREMOTE_EXTENSIONS */
+
+ [buttonCodeNumber release];
+ [pairString release];
+ }
+ }
+ }
+
+ // Compare number of *unique* matches (thus the cookieCount dictionary) with required minimum
+ if ([cookieCount count] < 10)
+ {
+ [cookieButtonCodeLUT release];
+ cookieButtonCodeLUT = nil;
+
+ [cookieCount release];
+ cookieCount = nil;
+
+ error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
+ errorCode = 8;
+
+ break;
+ }
+
+ [hidAttribsDict setObject:cookieButtonCodeLUT forKey:kHIDRemoteCookieButtonCodeLUT];
+
+ [cookieButtonCodeLUT release];
+ cookieButtonCodeLUT = nil;
+
+ [cookieCount release];
+ cookieCount = nil;
+ }
+
+ // Finish setup of IOHIDQueueInterface with CFRunLoop
+ returnCode = (*hidQueueInterface)->createAsyncEventSource(hidQueueInterface, &queueEventSource);
+ if ((returnCode != kIOReturnSuccess) || (queueEventSource == NULL))
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
+ errorCode = 9;
+ break;
+ }
+
+ returnCode = (*hidQueueInterface)->setEventCallout(hidQueueInterface, HIDEventCallback, (void *)((intptr_t)service), (void *)self);
+ if (returnCode != kIOReturnSuccess)
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
+ errorCode = 10;
+ break;
+ }
+
+ CFRunLoopAddSource( CFRunLoopGetCurrent(),
+ queueEventSource,
+ kCFRunLoopCommonModes);
+ [hidAttribsDict setObject:[NSValue valueWithPointer:(const void *)queueEventSource] forKey:kHIDRemoteCFRunLoopSource];
+
+ returnCode = (*hidQueueInterface)->start(hidQueueInterface);
+ if (returnCode != kIOReturnSuccess)
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
+ errorCode = 11;
+ break;
+ }
+
+ queueStarted = YES;
+
+ // Setup device notifications
+ returnCode = IOServiceAddInterestNotification( _notifyPort,
+ service,
+ kIOGeneralInterest,
+ ServiceNotificationCallback,
+ self,
+ &serviceNotification);
+ if ((returnCode != kIOReturnSuccess) || (serviceNotification==0))
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
+ errorCode = 12;
+ break;
+ }
+
+ [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)serviceNotification] forKey:kHIDRemoteServiceNotification];
+
+ // Retain service
+ if (IOObjectRetain(service) != kIOReturnSuccess)
+ {
+ error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
+ errorCode = 13;
+ break;
+ }
+
+ [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)service] forKey:kHIDRemoteService];
+
+ // Get some (somewhat optional) infos on the device
+ {
+ CFStringRef product, manufacturer, transport;
+
+ if ((product = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
+ (CFStringRef) @"Product",
+ kCFAllocatorDefault,
+ 0)) != NULL)
+ {
+ if (CFGetTypeID(product) == CFStringGetTypeID())
+ {
+ [hidAttribsDict setObject:(NSString *)product forKey:kHIDRemoteProduct];
+ }
+
+ CFRelease(product);
+ }
+
+ if ((manufacturer = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
+ (CFStringRef) @"Manufacturer",
+ kCFAllocatorDefault,
+ 0)) != NULL)
+ {
+ if (CFGetTypeID(manufacturer) == CFStringGetTypeID())
+ {
+ [hidAttribsDict setObject:(NSString *)manufacturer forKey:kHIDRemoteManufacturer];
+ }
+
+ CFRelease(manufacturer);
+ }
+
+ if ((transport = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
+ (CFStringRef) @"Transport",
+ kCFAllocatorDefault,
+ 0)) != NULL)
+ {
+ if (CFGetTypeID(transport) == CFStringGetTypeID())
+ {
+ [hidAttribsDict setObject:(NSString *)transport forKey:kHIDRemoteTransport];
+ }
+
+ CFRelease(transport);
+ }
+ }
+
+ // Determine Aluminum Remote support
+ {
+ CFNumberRef aluSupport;
+ HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone;
+
+ if ((_mode == kHIDRemoteModeExclusive) || (_mode == kHIDRemoteModeExclusiveAuto))
+ {
+ // Determine if this driver offers on-demand support for the Aluminum Remote (only relevant under OS versions < 10.6.2)
+ if ((aluSupport = IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
+ (CFStringRef) @"AluminumRemoteSupportLevelOnDemand",
+ kCFAllocatorDefault,
+ 0)) != nil)
+ {
+ // There is => request the driver to enable it for us
+ if (IORegistryEntrySetCFProperty((io_registry_entry_t)service,
+ CFSTR("EnableAluminumRemoteSupportForMe"),
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithLongLong:(long long)getpid()], @"pid",
+ [NSNumber numberWithLongLong:(long long)getuid()], @"uid",
+ nil]) == kIOReturnSuccess)
+ {
+ if (CFGetTypeID(aluSupport) == CFNumberGetTypeID())
+ {
+ supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(NSNumber *)aluSupport intValue];
+ }
+
+ [hidAttribsDict setObject:[NSNumber numberWithBool:YES] forKey:kHIDRemoteAluminumRemoteSupportOnDemand];
+ }
+
+ CFRelease(aluSupport);
+ }
+ }
+
+ if (supportLevel == kHIDRemoteAluminumRemoteSupportLevelNone)
+ {
+ if ((aluSupport = IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
+ (CFStringRef) @"AluminumRemoteSupportLevel",
+ kCFAllocatorDefault,
+ 0)) != nil)
+ {
+ if (CFGetTypeID(aluSupport) == CFNumberGetTypeID())
+ {
+ supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(NSNumber *)aluSupport intValue];
+ }
+
+ CFRelease(aluSupport);
+ }
+ else
+ {
+ CFStringRef ioKitClassName;
+
+ if ((ioKitClassName = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
+ CFSTR(kIOClassKey),
+ kCFAllocatorDefault,
+ 0)) != nil)
+ {
+ if ([(NSString *)ioKitClassName isEqual:@"AppleIRController"])
+ {
+ supportLevel = kHIDRemoteAluminumRemoteSupportLevelNative;
+ }
+
+ CFRelease(ioKitClassName);
+ }
+ }
+ }
+
+ [hidAttribsDict setObject:(NSNumber *)[NSNumber numberWithInt:(int)supportLevel] forKey:kHIDRemoteAluminumRemoteSupportLevel];
+ }
+
+ // Add it to the serviceAttribMap
+ [_serviceAttribMap setObject:hidAttribsDict forKey:[NSNumber numberWithUnsignedInt:(unsigned int)service]];
+
+ // And we're done with setup ..
+ if (([self delegate]!=nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:foundNewHardwareWithAttributes:)]))
+ {
+ [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self foundNewHardwareWithAttributes:hidAttribsDict];
+ }
+
+ [hidAttribsDict release];
+ hidAttribsDict = nil;
+
+ return(YES);
+
+ }while(0);
+
+ cleanUp:
+
+ if (([self delegate]!=nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:failedNewHardwareWithError:)]))
+ {
+ if (error!=nil)
+ {
+ error = [NSError errorWithDomain:[error domain]
+ code:[error code]
+ userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:errorCode] forKey:@"InternalErrorCode"]
+ ];
+ }
+
+ [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self failedNewHardwareWithError:error];
+ }
+
+ // An error occured or this device is not of interest .. cleanup ..
+ if (serviceNotification!=0)
+ {
+ IOObjectRelease(serviceNotification);
+ serviceNotification = 0;
+ }
+
+ if (queueEventSource!=NULL)
+ {
+ CFRunLoopSourceInvalidate(queueEventSource);
+ queueEventSource=NULL;
+ }
+
+ if (hidQueueInterface!=NULL)
+ {
+ if (queueStarted)
+ {
+ (*hidQueueInterface)->stop(hidQueueInterface);
+ }
+ (*hidQueueInterface)->dispose(hidQueueInterface);
+ (*hidQueueInterface)->Release(hidQueueInterface);
+ hidQueueInterface = NULL;
+ }
+
+ if (hidAttribsDict!=nil)
+ {
+ [hidAttribsDict release];
+ hidAttribsDict = nil;
+ }
+
+ if (hidElements!=NULL)
+ {
+ CFRelease(hidElements);
+ hidElements = NULL;
+ }
+
+ if (hidDeviceInterface!=NULL)
+ {
+ if (opened)
+ {
+ (*hidDeviceInterface)->close(hidDeviceInterface);
+ }
+ (*hidDeviceInterface)->Release(hidDeviceInterface);
+ // opened = NO;
+ hidDeviceInterface = NULL;
+ }
+
+ if (cfPluginInterface!=NULL)
+ {
+ IODestroyPlugInInterface(cfPluginInterface);
+ cfPluginInterface = NULL;
+ }
+
+ return (NO);
}
- (void)_destructService:(io_object_t)service
{
- NSNumber *serviceValue;
- NSMutableDictionary *serviceDict = NULL;
-
- if ((serviceValue = [NSNumber numberWithUnsignedInt:(unsigned int)service]) == nil)
- {
- return;
- }
-
- serviceDict = [_serviceAttribMap objectForKey:serviceValue];
-
- if (serviceDict!=nil)
- {
- IOHIDDeviceInterface122 **hidDeviceInterface = NULL;
- IOCFPlugInInterface **cfPluginInterface = NULL;
- IOHIDQueueInterface **hidQueueInterface = NULL;
- io_object_t serviceNotification = 0;
- CFRunLoopSourceRef queueEventSource = NULL;
- io_object_t theService = 0;
- NSMutableDictionary *cookieButtonMap = nil;
- NSTimer *simulateHoldTimer = nil;
-
- serviceNotification = (io_object_t) ([serviceDict objectForKey:kHIDRemoteServiceNotification] ? [[serviceDict objectForKey:kHIDRemoteServiceNotification] unsignedIntValue] : 0);
- theService = (io_object_t) ([serviceDict objectForKey:kHIDRemoteService] ? [[serviceDict objectForKey:kHIDRemoteService] unsignedIntValue] : 0);
- queueEventSource = (CFRunLoopSourceRef) ([serviceDict objectForKey:kHIDRemoteCFRunLoopSource] ? [[serviceDict objectForKey:kHIDRemoteCFRunLoopSource] pointerValue] : NULL);
- hidQueueInterface = (IOHIDQueueInterface **) ([serviceDict objectForKey:kHIDRemoteHIDQueueInterface] ? [[serviceDict objectForKey:kHIDRemoteHIDQueueInterface] pointerValue] : NULL);
- hidDeviceInterface = (IOHIDDeviceInterface122 **) ([serviceDict objectForKey:kHIDRemoteHIDDeviceInterface] ? [[serviceDict objectForKey:kHIDRemoteHIDDeviceInterface] pointerValue] : NULL);
- cfPluginInterface = (IOCFPlugInInterface **) ([serviceDict objectForKey:kHIDRemoteCFPluginInterface] ? [[serviceDict objectForKey:kHIDRemoteCFPluginInterface] pointerValue] : NULL);
- cookieButtonMap = (NSMutableDictionary *) [serviceDict objectForKey:kHIDRemoteCookieButtonCodeLUT];
- simulateHoldTimer = (NSTimer *) [serviceDict objectForKey:kHIDRemoteSimulateHoldEventsTimer];
-
- [serviceDict retain];
- [_serviceAttribMap removeObjectForKey:serviceValue];
-
- if (([serviceDict objectForKey:kHIDRemoteAluminumRemoteSupportOnDemand]!=nil) && [[serviceDict objectForKey:kHIDRemoteAluminumRemoteSupportOnDemand] boolValue] && (theService != 0))
- {
- // We previously requested the driver to enable Aluminum Remote support for us. Tell it to turn it off again - now that we no longer need it
- IORegistryEntrySetCFProperty( (io_registry_entry_t)theService,
- CFSTR("DisableAluminumRemoteSupportForMe"),
- [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithLongLong:(long long)getpid()], @"pid",
- [NSNumber numberWithLongLong:(long long)getuid()], @"uid",
- nil]);
- }
-
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:releasedHardwareWithAttributes:)]))
- {
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self releasedHardwareWithAttributes:serviceDict];
- }
-
- if (simulateHoldTimer!=nil)
- {
- [simulateHoldTimer invalidate];
- }
-
- if (serviceNotification!=0)
- {
- IOObjectRelease(serviceNotification);
- }
-
- if (queueEventSource!=NULL)
- {
- CFRunLoopRemoveSource( CFRunLoopGetCurrent(),
- queueEventSource,
- kCFRunLoopCommonModes);
- }
-
- if ((hidQueueInterface!=NULL) && (cookieButtonMap!=nil))
- {
- NSEnumerator *cookieEnum = [cookieButtonMap keyEnumerator];
- NSNumber *cookie;
-
- while ((cookie = [cookieEnum nextObject]) != nil)
- {
- if ((*hidQueueInterface)->hasElement(hidQueueInterface, (IOHIDElementCookie) [cookie unsignedIntValue]))
- {
- (*hidQueueInterface)->removeElement(hidQueueInterface,
- (IOHIDElementCookie) [cookie unsignedIntValue]);
- }
- };
- }
-
- if (hidQueueInterface!=NULL)
- {
- (*hidQueueInterface)->stop(hidQueueInterface);
- (*hidQueueInterface)->dispose(hidQueueInterface);
- (*hidQueueInterface)->Release(hidQueueInterface);
- }
-
- if (hidDeviceInterface!=NULL)
- {
- (*hidDeviceInterface)->close(hidDeviceInterface);
- (*hidDeviceInterface)->Release(hidDeviceInterface);
- }
-
- if (cfPluginInterface!=NULL)
- {
- IODestroyPlugInInterface(cfPluginInterface);
- }
-
- if (theService!=0)
- {
- IOObjectRelease(theService);
- }
-
- [serviceDict release];
- }
+ NSNumber *serviceValue;
+ NSMutableDictionary *serviceDict = NULL;
+
+ if ((serviceValue = [NSNumber numberWithUnsignedInt:(unsigned int)service]) == nil)
+ {
+ return;
+ }
+
+ serviceDict = [_serviceAttribMap objectForKey:serviceValue];
+
+ if (serviceDict!=nil)
+ {
+ IOHIDDeviceInterface122 **hidDeviceInterface = NULL;
+ IOCFPlugInInterface **cfPluginInterface = NULL;
+ IOHIDQueueInterface **hidQueueInterface = NULL;
+ io_object_t serviceNotification = 0;
+ CFRunLoopSourceRef queueEventSource = NULL;
+ io_object_t theService = 0;
+ NSMutableDictionary *cookieButtonMap = nil;
+ NSTimer *simulateHoldTimer = nil;
+
+ serviceNotification = (io_object_t) ([serviceDict objectForKey:kHIDRemoteServiceNotification] ? [[serviceDict objectForKey:kHIDRemoteServiceNotification] unsignedIntValue] : 0);
+ theService = (io_object_t) ([serviceDict objectForKey:kHIDRemoteService] ? [[serviceDict objectForKey:kHIDRemoteService] unsignedIntValue] : 0);
+ queueEventSource = (CFRunLoopSourceRef) ([serviceDict objectForKey:kHIDRemoteCFRunLoopSource] ? [[serviceDict objectForKey:kHIDRemoteCFRunLoopSource] pointerValue] : NULL);
+ hidQueueInterface = (IOHIDQueueInterface **) ([serviceDict objectForKey:kHIDRemoteHIDQueueInterface] ? [[serviceDict objectForKey:kHIDRemoteHIDQueueInterface] pointerValue] : NULL);
+ hidDeviceInterface = (IOHIDDeviceInterface122 **) ([serviceDict objectForKey:kHIDRemoteHIDDeviceInterface] ? [[serviceDict objectForKey:kHIDRemoteHIDDeviceInterface] pointerValue] : NULL);
+ cfPluginInterface = (IOCFPlugInInterface **) ([serviceDict objectForKey:kHIDRemoteCFPluginInterface] ? [[serviceDict objectForKey:kHIDRemoteCFPluginInterface] pointerValue] : NULL);
+ cookieButtonMap = (NSMutableDictionary *) [serviceDict objectForKey:kHIDRemoteCookieButtonCodeLUT];
+ simulateHoldTimer = (NSTimer *) [serviceDict objectForKey:kHIDRemoteSimulateHoldEventsTimer];
+
+ [serviceDict retain];
+ [_serviceAttribMap removeObjectForKey:serviceValue];
+
+ if (([serviceDict objectForKey:kHIDRemoteAluminumRemoteSupportOnDemand]!=nil) && [[serviceDict objectForKey:kHIDRemoteAluminumRemoteSupportOnDemand] boolValue] && (theService != 0))
+ {
+ // We previously requested the driver to enable Aluminum Remote support for us. Tell it to turn it off again - now that we no longer need it
+ IORegistryEntrySetCFProperty( (io_registry_entry_t)theService,
+ CFSTR("DisableAluminumRemoteSupportForMe"),
+ [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithLongLong:(long long)getpid()], @"pid",
+ [NSNumber numberWithLongLong:(long long)getuid()], @"uid",
+ nil]);
+ }
+
+ if (([self delegate]!=nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:releasedHardwareWithAttributes:)]))
+ {
+ [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self releasedHardwareWithAttributes:serviceDict];
+ }
+
+ if (simulateHoldTimer!=nil)
+ {
+ [simulateHoldTimer invalidate];
+ }
+
+ if (serviceNotification!=0)
+ {
+ IOObjectRelease(serviceNotification);
+ }
+
+ if (queueEventSource!=NULL)
+ {
+ CFRunLoopRemoveSource( CFRunLoopGetCurrent(),
+ queueEventSource,
+ kCFRunLoopCommonModes);
+ }
+
+ if ((hidQueueInterface!=NULL) && (cookieButtonMap!=nil))
+ {
+ NSEnumerator *cookieEnum = [cookieButtonMap keyEnumerator];
+ NSNumber *cookie;
+
+ while ((cookie = [cookieEnum nextObject]) != nil)
+ {
+ if ((*hidQueueInterface)->hasElement(hidQueueInterface, (IOHIDElementCookie) [cookie unsignedIntValue]))
+ {
+ (*hidQueueInterface)->removeElement(hidQueueInterface,
+ (IOHIDElementCookie) [cookie unsignedIntValue]);
+ }
+ };
+ }
+
+ if (hidQueueInterface!=NULL)
+ {
+ (*hidQueueInterface)->stop(hidQueueInterface);
+ (*hidQueueInterface)->dispose(hidQueueInterface);
+ (*hidQueueInterface)->Release(hidQueueInterface);
+ }
+
+ if (hidDeviceInterface!=NULL)
+ {
+ (*hidDeviceInterface)->close(hidDeviceInterface);
+ (*hidDeviceInterface)->Release(hidDeviceInterface);
+ }
+
+ if (cfPluginInterface!=NULL)
+ {
+ IODestroyPlugInInterface(cfPluginInterface);
+ }
+
+ if (theService!=0)
+ {
+ IOObjectRelease(theService);
+ }
+
+ [serviceDict release];
+ }
}
#pragma mark -- PRIVATE: HID Event handling --
- (void)_simulateHoldEvent:(NSTimer *)aTimer
{
- NSMutableDictionary *hidAttribsDict;
- NSTimer *shTimer;
- NSNumber *shButtonCode;
-
- if ((hidAttribsDict = (NSMutableDictionary *)[aTimer userInfo]) != nil)
- {
- if (((shTimer = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer]) != nil) &&
- ((shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode]) != nil))
- {
- [shTimer invalidate];
- [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsTimer];
-
- [self _sendButtonCode:(((HIDRemoteButtonCode)[shButtonCode unsignedIntValue])|kHIDRemoteButtonCodeHoldMask) isPressed:YES hidAttribsDict:hidAttribsDict];
- }
- }
+ NSMutableDictionary *hidAttribsDict;
+ NSTimer *shTimer;
+ NSNumber *shButtonCode;
+
+ if ((hidAttribsDict = (NSMutableDictionary *)[aTimer userInfo]) != nil)
+ {
+ if (((shTimer = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer]) != nil) &&
+ ((shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode]) != nil))
+ {
+ [shTimer invalidate];
+ [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsTimer];
+
+ [self _sendButtonCode:(((HIDRemoteButtonCode)[shButtonCode unsignedIntValue])|kHIDRemoteButtonCodeHoldMask) isPressed:YES hidAttribsDict:hidAttribsDict];
+ }
+ }
}
- (void)_handleButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict
{
- switch (buttonCode)
- {
- case kHIDRemoteButtonCodeIDChanged:
- // Do nothing, this is handled seperately
- break;
-
- case kHIDRemoteButtonCodeUp:
- case kHIDRemoteButtonCodeDown:
- if (_simulateHoldEvents)
- {
- NSTimer *shTimer = nil;
- NSNumber *shButtonCode = nil;
-
- [[hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer] invalidate];
-
- if (isPressed)
- {
- [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:buttonCode] forKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
-
- if ((shTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.7] interval:0.1 target:self selector:@selector(_simulateHoldEvent:) userInfo:hidAttribsDict repeats:NO]) != nil)
- {
- [hidAttribsDict setObject:shTimer forKey:kHIDRemoteSimulateHoldEventsTimer];
-
- // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes.
- // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code
- // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0.
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)shTimer, kCFRunLoopCommonModes);
-
- [shTimer release];
-
- break;
- }
- }
- else
- {
- shTimer = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer];
- shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
-
- if ((shTimer!=nil) && (shButtonCode!=nil))
- {
- [self _sendButtonCode:(HIDRemoteButtonCode)[shButtonCode unsignedIntValue] isPressed:YES hidAttribsDict:hidAttribsDict];
- [self _sendButtonCode:(HIDRemoteButtonCode)[shButtonCode unsignedIntValue] isPressed:NO hidAttribsDict:hidAttribsDict];
- }
- else
- {
- if (shButtonCode!=nil)
- {
- [self _sendButtonCode:(((HIDRemoteButtonCode)[shButtonCode unsignedIntValue])|kHIDRemoteButtonCodeHoldMask) isPressed:NO hidAttribsDict:hidAttribsDict];
- }
- }
- }
-
- [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsTimer];
- [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
-
- break;
- }
-
- default:
- [self _sendButtonCode:buttonCode isPressed:isPressed hidAttribsDict:hidAttribsDict];
- break;
- }
+ switch (buttonCode)
+ {
+ case kHIDRemoteButtonCodeIDChanged:
+ // Do nothing, this is handled seperately
+ break;
+
+ case kHIDRemoteButtonCodeUp:
+ case kHIDRemoteButtonCodeDown:
+ if (_simulateHoldEvents)
+ {
+ NSTimer *shTimer = nil;
+ NSNumber *shButtonCode = nil;
+
+ [[hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer] invalidate];
+
+ if (isPressed)
+ {
+ [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:buttonCode] forKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
+
+ if ((shTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.7] interval:0.1 target:self selector:@selector(_simulateHoldEvent:) userInfo:hidAttribsDict repeats:NO]) != nil)
+ {
+ [hidAttribsDict setObject:shTimer forKey:kHIDRemoteSimulateHoldEventsTimer];
+
+ // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes.
+ // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code
+ // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0.
+ CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)shTimer, kCFRunLoopCommonModes);
+
+ [shTimer release];
+
+ break;
+ }
+ }
+ else
+ {
+ shTimer = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer];
+ shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
+
+ if ((shTimer!=nil) && (shButtonCode!=nil))
+ {
+ [self _sendButtonCode:(HIDRemoteButtonCode)[shButtonCode unsignedIntValue] isPressed:YES hidAttribsDict:hidAttribsDict];
+ [self _sendButtonCode:(HIDRemoteButtonCode)[shButtonCode unsignedIntValue] isPressed:NO hidAttribsDict:hidAttribsDict];
+ }
+ else
+ {
+ if (shButtonCode!=nil)
+ {
+ [self _sendButtonCode:(((HIDRemoteButtonCode)[shButtonCode unsignedIntValue])|kHIDRemoteButtonCodeHoldMask) isPressed:NO hidAttribsDict:hidAttribsDict];
+ }
+ }
+ }
+
+ [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsTimer];
+ [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
+
+ break;
+ }
+
+ default:
+ [self _sendButtonCode:buttonCode isPressed:isPressed hidAttribsDict:hidAttribsDict];
+ break;
+ }
}
- (void)_sendButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict
{
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:eventWithButton:isPressed:fromHardwareWithAttributes:)]))
- {
- switch (buttonCode & (~kHIDRemoteButtonCodeAluminumMask))
- {
- case kHIDRemoteButtonCodePlay:
- case kHIDRemoteButtonCodeCenter:
- if (buttonCode & kHIDRemoteButtonCodeAluminumMask)
- {
- _lastSeenModel = kHIDRemoteModelAluminum;
- _lastSeenModelRemoteID = _lastSeenRemoteID;
- }
- else
- {
- switch ((HIDRemoteAluminumRemoteSupportLevel)[[hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel] intValue])
- {
- case kHIDRemoteAluminumRemoteSupportLevelNone:
- case kHIDRemoteAluminumRemoteSupportLevelEmulation:
- // Remote type can't be determined by just the Center button press
- break;
-
- case kHIDRemoteAluminumRemoteSupportLevelNative:
- // Remote type can be safely determined by just the Center button press
- if (((_lastSeenModel == kHIDRemoteModelAluminum) && (_lastSeenModelRemoteID != _lastSeenRemoteID)) ||
- (_lastSeenModel == kHIDRemoteModelUndetermined))
- {
- _lastSeenModel = kHIDRemoteModelWhitePlastic;
- }
- break;
- }
- }
- break;
- }
-
- // As soon as we have received a code that's unique to the Aluminum Remote, we can tell kHIDRemoteButtonCodePlayHold and kHIDRemoteButtonCodeCenterHold apart.
- // Prior to that, a long press of the new "Play" button will be submitted as a "kHIDRemoteButtonCodeCenterHold", not a "kHIDRemoteButtonCodePlayHold" code.
- if ((buttonCode == kHIDRemoteButtonCodeCenterHold) && (_lastSeenModel == kHIDRemoteModelAluminum))
- {
- buttonCode = kHIDRemoteButtonCodePlayHold;
- }
-
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self eventWithButton:(buttonCode & (~kHIDRemoteButtonCodeAluminumMask)) isPressed:isPressed fromHardwareWithAttributes:hidAttribsDict];
- }
+ if (([self delegate]!=nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:eventWithButton:isPressed:fromHardwareWithAttributes:)]))
+ {
+ switch (buttonCode & (~kHIDRemoteButtonCodeAluminumMask))
+ {
+ case kHIDRemoteButtonCodePlay:
+ case kHIDRemoteButtonCodeCenter:
+ if (buttonCode & kHIDRemoteButtonCodeAluminumMask)
+ {
+ _lastSeenModel = kHIDRemoteModelAluminum;
+ _lastSeenModelRemoteID = _lastSeenRemoteID;
+ }
+ else
+ {
+ switch ((HIDRemoteAluminumRemoteSupportLevel)[[hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel] intValue])
+ {
+ case kHIDRemoteAluminumRemoteSupportLevelNone:
+ case kHIDRemoteAluminumRemoteSupportLevelEmulation:
+ // Remote type can't be determined by just the Center button press
+ break;
+
+ case kHIDRemoteAluminumRemoteSupportLevelNative:
+ // Remote type can be safely determined by just the Center button press
+ if (((_lastSeenModel == kHIDRemoteModelAluminum) && (_lastSeenModelRemoteID != _lastSeenRemoteID)) ||
+ (_lastSeenModel == kHIDRemoteModelUndetermined))
+ {
+ _lastSeenModel = kHIDRemoteModelWhitePlastic;
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ // As soon as we have received a code that's unique to the Aluminum Remote, we can tell kHIDRemoteButtonCodePlayHold and kHIDRemoteButtonCodeCenterHold apart.
+ // Prior to that, a long press of the new "Play" button will be submitted as a "kHIDRemoteButtonCodeCenterHold", not a "kHIDRemoteButtonCodePlayHold" code.
+ if ((buttonCode == kHIDRemoteButtonCodeCenterHold) && (_lastSeenModel == kHIDRemoteModelAluminum))
+ {
+ buttonCode = kHIDRemoteButtonCodePlayHold;
+ }
+
+ [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self eventWithButton:(buttonCode & (~kHIDRemoteButtonCodeAluminumMask)) isPressed:isPressed fromHardwareWithAttributes:hidAttribsDict];
+ }
}
- (void)_hidEventFor:(io_service_t)hidDevice from:(IOHIDQueueInterface **)interface withResult:(IOReturn)result
{
- NSMutableDictionary *hidAttribsDict = [[[_serviceAttribMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int)hidDevice]] retain] autorelease];
-
- if (hidAttribsDict!=nil)
- {
- IOHIDQueueInterface **queueInterface = NULL;
-
- queueInterface = [[hidAttribsDict objectForKey:kHIDRemoteHIDQueueInterface] pointerValue];
-
- if (interface == queueInterface)
- {
- NSNumber *lastButtonPressedNumber = nil;
- HIDRemoteButtonCode lastButtonPressed = kHIDRemoteButtonCodeNone;
- NSMutableDictionary *cookieButtonMap = nil;
-
- cookieButtonMap = [hidAttribsDict objectForKey:kHIDRemoteCookieButtonCodeLUT];
-
- if ((lastButtonPressedNumber = [hidAttribsDict objectForKey:kHIDRemoteLastButtonPressed]) != nil)
- {
- lastButtonPressed = [lastButtonPressedNumber unsignedIntValue];
- }
-
- while (result == kIOReturnSuccess)
- {
- IOHIDEventStruct hidEvent;
- AbsoluteTime supportedTime = { 0,0 };
-
- result = (*queueInterface)->getNextEvent( queueInterface,
- &hidEvent,
- supportedTime,
- 0);
-
- if (result == kIOReturnSuccess)
- {
- NSNumber *buttonCodeNumber = [cookieButtonMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int) hidEvent.elementCookie]];
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Debug logging code
- #define _HIDREMOTE_EXTENSIONS_SECTION 5
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-
- if (buttonCodeNumber!=nil)
- {
- HIDRemoteButtonCode buttonCode = [buttonCodeNumber unsignedIntValue];
-
- if (hidEvent.value == 0)
- {
- if (buttonCode == lastButtonPressed)
- {
- [self _handleButtonCode:lastButtonPressed isPressed:NO hidAttribsDict:hidAttribsDict];
- lastButtonPressed = kHIDRemoteButtonCodeNone;
- }
- }
-
- if (hidEvent.value != 0)
- {
- if (lastButtonPressed != kHIDRemoteButtonCodeNone)
- {
- [self _handleButtonCode:lastButtonPressed isPressed:NO hidAttribsDict:hidAttribsDict];
- // lastButtonPressed = kHIDRemoteButtonCodeNone;
- }
-
- if (buttonCode == kHIDRemoteButtonCodeIDChanged)
- {
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:remoteIDChangedOldID:newID:forHardwareWithAttributes:)]))
- {
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self remoteIDChangedOldID:_lastSeenRemoteID newID:hidEvent.value forHardwareWithAttributes:hidAttribsDict];
- }
-
- _lastSeenRemoteID = hidEvent.value;
- _lastSeenModel = kHIDRemoteModelUndetermined;
- }
-
- [self _handleButtonCode:buttonCode isPressed:YES hidAttribsDict:hidAttribsDict];
- lastButtonPressed = buttonCode;
- }
- }
- }
- };
-
- [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:lastButtonPressed] forKey:kHIDRemoteLastButtonPressed];
- }
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Debug logging code
- #define _HIDREMOTE_EXTENSIONS_SECTION 6
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
- }
+ NSMutableDictionary *hidAttribsDict = [[[_serviceAttribMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int)hidDevice]] retain] autorelease];
+
+ if (hidAttribsDict!=nil)
+ {
+ IOHIDQueueInterface **queueInterface = NULL;
+
+ queueInterface = [[hidAttribsDict objectForKey:kHIDRemoteHIDQueueInterface] pointerValue];
+
+ if (interface == queueInterface)
+ {
+ NSNumber *lastButtonPressedNumber = nil;
+ HIDRemoteButtonCode lastButtonPressed = kHIDRemoteButtonCodeNone;
+ NSMutableDictionary *cookieButtonMap = nil;
+
+ cookieButtonMap = [hidAttribsDict objectForKey:kHIDRemoteCookieButtonCodeLUT];
+
+ if ((lastButtonPressedNumber = [hidAttribsDict objectForKey:kHIDRemoteLastButtonPressed]) != nil)
+ {
+ lastButtonPressed = [lastButtonPressedNumber unsignedIntValue];
+ }
+
+ while (result == kIOReturnSuccess)
+ {
+ IOHIDEventStruct hidEvent;
+ AbsoluteTime supportedTime = { 0,0 };
+
+ result = (*queueInterface)->getNextEvent( queueInterface,
+ &hidEvent,
+ supportedTime,
+ 0);
+
+ if (result == kIOReturnSuccess)
+ {
+ NSNumber *buttonCodeNumber = [cookieButtonMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int) hidEvent.elementCookie]];
+
+ #ifdef _HIDREMOTE_EXTENSIONS
+ // Debug logging code
+ #define _HIDREMOTE_EXTENSIONS_SECTION 5
+ #include "HIDRemoteAdditions.h"
+ #undef _HIDREMOTE_EXTENSIONS_SECTION
+ #endif /* _HIDREMOTE_EXTENSIONS */
+
+ if (buttonCodeNumber!=nil)
+ {
+ HIDRemoteButtonCode buttonCode = [buttonCodeNumber unsignedIntValue];
+
+ if (hidEvent.value == 0)
+ {
+ if (buttonCode == lastButtonPressed)
+ {
+ [self _handleButtonCode:lastButtonPressed isPressed:NO hidAttribsDict:hidAttribsDict];
+ lastButtonPressed = kHIDRemoteButtonCodeNone;
+ }
+ }
+
+ if (hidEvent.value != 0)
+ {
+ if (lastButtonPressed != kHIDRemoteButtonCodeNone)
+ {
+ [self _handleButtonCode:lastButtonPressed isPressed:NO hidAttribsDict:hidAttribsDict];
+ // lastButtonPressed = kHIDRemoteButtonCodeNone;
+ }
+
+ if (buttonCode == kHIDRemoteButtonCodeIDChanged)
+ {
+ if (([self delegate]!=nil) &&
+ ([[self delegate] respondsToSelector:@selector(hidRemote:remoteIDChangedOldID:newID:forHardwareWithAttributes:)]))
+ {
+ [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self remoteIDChangedOldID:_lastSeenRemoteID newID:hidEvent.value forHardwareWithAttributes:hidAttribsDict];
+ }
+
+ _lastSeenRemoteID = hidEvent.value;
+ _lastSeenModel = kHIDRemoteModelUndetermined;
+ }
+
+ [self _handleButtonCode:buttonCode isPressed:YES hidAttribsDict:hidAttribsDict];
+ lastButtonPressed = buttonCode;
+ }
+ }
+ }
+ };
+
+ [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:lastButtonPressed] forKey:kHIDRemoteLastButtonPressed];
+ }
+
+ #ifdef _HIDREMOTE_EXTENSIONS
+ // Debug logging code
+ #define _HIDREMOTE_EXTENSIONS_SECTION 6
+ #include "HIDRemoteAdditions.h"
+ #undef _HIDREMOTE_EXTENSIONS_SECTION
+ #endif /* _HIDREMOTE_EXTENSIONS */
+ }
}
#pragma mark -- PRIVATE: Notification handling --
- (void)_serviceMatching:(io_iterator_t)iterator
{
- io_object_t matchingService = 0;
+ io_object_t matchingService = 0;
- while ((matchingService = IOIteratorNext(iterator)) != 0)
- {
- [self _setupService:matchingService];
+ while ((matchingService = IOIteratorNext(iterator)) != 0)
+ {
+ [self _setupService:matchingService];
- IOObjectRelease(matchingService);
- };
+ IOObjectRelease(matchingService);
+ };
}
- (void)_serviceNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument
{
- if (messageType == kIOMessageServiceIsTerminated)
- {
- [self _destructService:service];
- }
+ if (messageType == kIOMessageServiceIsTerminated)
+ {
+ [self _destructService:service];
+ }
}
- (void)_updateSessionInformation
{
- NSArray *consoleUsersArray;
- io_service_t rootService;
-
- if (_masterPort==0) { return; }
-
- if ((rootService = IORegistryGetRootEntry(_masterPort)) != 0)
- {
- if ((consoleUsersArray = (NSArray *)IORegistryEntryCreateCFProperty((io_registry_entry_t)rootService, CFSTR("IOConsoleUsers"), kCFAllocatorDefault, 0)) != nil)
- {
- if ([consoleUsersArray isKindOfClass:[NSArray class]]) // Be careful - ensure this really is an array
- {
- NSEnumerator *consoleUsersEnum; // I *love* Obj-C2's fast enumerators, but we need to stay compatible with 10.4 :-/
-
- if ((consoleUsersEnum = [consoleUsersArray objectEnumerator]) != nil)
- {
- UInt64 secureEventInputPIDSum = 0;
- uid_t frontUserSession = 0;
- NSDictionary *consoleUserDict;
-
- while ((consoleUserDict = [consoleUsersEnum nextObject]) != nil)
- {
- if ([consoleUserDict isKindOfClass:[NSDictionary class]]) // Be careful - ensure this really is a dictionary
- {
- NSNumber *secureInputPID;
- NSNumber *onConsole;
- NSNumber *userID;
-
- if ((secureInputPID = [consoleUserDict objectForKey:@"kCGSSessionSecureInputPID"]) != nil)
- {
- if ([secureInputPID isKindOfClass:[NSNumber class]])
- {
- secureEventInputPIDSum += ((UInt64) [secureInputPID intValue]);
- }
- }
-
- if (((onConsole = [consoleUserDict objectForKey:@"kCGSSessionOnConsoleKey"]) != nil) &&
- ((userID = [consoleUserDict objectForKey:@"kCGSSessionUserIDKey"]) != nil))
- {
- if ([onConsole isKindOfClass:[NSNumber class]] && [userID isKindOfClass:[NSNumber class]])
- {
- if ([onConsole boolValue])
- {
- frontUserSession = (uid_t) [userID intValue];
- }
- }
- }
- }
- }
-
- _lastSecureEventInputPIDSum = secureEventInputPIDSum;
- _lastFrontUserSession = frontUserSession;
- }
- }
-
- CFRelease((CFTypeRef)consoleUsersArray);
- }
-
- IOObjectRelease((io_object_t) rootService);
- }
+ NSArray *consoleUsersArray;
+ io_service_t rootService;
+
+ if (_masterPort==0) { return; }
+
+ if ((rootService = IORegistryGetRootEntry(_masterPort)) != 0)
+ {
+ if ((consoleUsersArray = (NSArray *)IORegistryEntryCreateCFProperty((io_registry_entry_t)rootService, CFSTR("IOConsoleUsers"), kCFAllocatorDefault, 0)) != nil)
+ {
+ if ([consoleUsersArray isKindOfClass:[NSArray class]]) // Be careful - ensure this really is an array
+ {
+ NSEnumerator *consoleUsersEnum; // I *love* Obj-C2's fast enumerators, but we need to stay compatible with 10.4 :-/
+
+ if ((consoleUsersEnum = [consoleUsersArray objectEnumerator]) != nil)
+ {
+ UInt64 secureEventInputPIDSum = 0;
+ uid_t frontUserSession = 0;
+ NSDictionary *consoleUserDict;
+
+ while ((consoleUserDict = [consoleUsersEnum nextObject]) != nil)
+ {
+ if ([consoleUserDict isKindOfClass:[NSDictionary class]]) // Be careful - ensure this really is a dictionary
+ {
+ NSNumber *secureInputPID;
+ NSNumber *onConsole;
+ NSNumber *userID;
+
+ if ((secureInputPID = [consoleUserDict objectForKey:@"kCGSSessionSecureInputPID"]) != nil)
+ {
+ if ([secureInputPID isKindOfClass:[NSNumber class]])
+ {
+ secureEventInputPIDSum += ((UInt64) [secureInputPID intValue]);
+ }
+ }
+
+ if (((onConsole = [consoleUserDict objectForKey:@"kCGSSessionOnConsoleKey"]) != nil) &&
+ ((userID = [consoleUserDict objectForKey:@"kCGSSessionUserIDKey"]) != nil))
+ {
+ if ([onConsole isKindOfClass:[NSNumber class]] && [userID isKindOfClass:[NSNumber class]])
+ {
+ if ([onConsole boolValue])
+ {
+ frontUserSession = (uid_t) [userID intValue];
+ }
+ }
+ }
+ }
+ }
+
+ _lastSecureEventInputPIDSum = secureEventInputPIDSum;
+ _lastFrontUserSession = frontUserSession;
+ }
+ }
+
+ CFRelease((CFTypeRef)consoleUsersArray);
+ }
+
+ IOObjectRelease((io_object_t) rootService);
+ }
}
- (void)_secureInputNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument
{
- if (messageType == kIOMessageServiceBusyStateChange)
- {
- UInt64 old_lastSecureEventInputPIDSum = _lastSecureEventInputPIDSum;
- uid_t old_lastFrontUserSession = _lastFrontUserSession;
-
- [self _updateSessionInformation];
-
- if (((old_lastSecureEventInputPIDSum != _lastSecureEventInputPIDSum) || (old_lastFrontUserSession != _lastFrontUserSession)) && _secureEventInputWorkAround)
- {
- if ((_mode == kHIDRemoteModeExclusive) || (_mode == kHIDRemoteModeExclusiveAuto))
- {
- HIDRemoteMode restartInMode = _mode;
-
- _isRestarting = YES;
- [self stopRemoteControl];
- [self startRemoteControl:restartInMode];
- _isRestarting = NO;
- }
- }
- }
+ if (messageType == kIOMessageServiceBusyStateChange)
+ {
+ UInt64 old_lastSecureEventInputPIDSum = _lastSecureEventInputPIDSum;
+ uid_t old_lastFrontUserSession = _lastFrontUserSession;
+
+ [self _updateSessionInformation];
+
+ if (((old_lastSecureEventInputPIDSum != _lastSecureEventInputPIDSum) || (old_lastFrontUserSession != _lastFrontUserSession)) && _secureEventInputWorkAround)
+ {
+ if ((_mode == kHIDRemoteModeExclusive) || (_mode == kHIDRemoteModeExclusiveAuto))
+ {
+ HIDRemoteMode restartInMode = _mode;
+
+ _isRestarting = YES;
+ [self stopRemoteControl];
+ [self startRemoteControl:restartInMode];
+ _isRestarting = NO;
+ }
+ }
+ }
}
@end
#pragma mark -- PRIVATE: IOKitLib Callbacks --
-static void HIDEventCallback( void * target,
- IOReturn result,
- void * refCon,
- void * sender)
+static void HIDEventCallback( void * target,
+ IOReturn result,
+ void * refCon,
+ void * sender)
{
- HIDRemote *hidRemote = (HIDRemote *)refCon;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ HIDRemote *hidRemote = (HIDRemote *)refCon;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [hidRemote _hidEventFor:(io_service_t)((intptr_t)target) from:(IOHIDQueueInterface**)sender withResult:(IOReturn)result];
+ [hidRemote _hidEventFor:(io_service_t)((intptr_t)target) from:(IOHIDQueueInterface**)sender withResult:(IOReturn)result];
- [pool release];
+ [pool release];
}
-static void ServiceMatchingCallback( void *refCon,
- io_iterator_t iterator)
+static void ServiceMatchingCallback( void *refCon,
+ io_iterator_t iterator)
{
- HIDRemote *hidRemote = (HIDRemote *)refCon;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ HIDRemote *hidRemote = (HIDRemote *)refCon;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- [hidRemote _serviceMatching:iterator];
+ [hidRemote _serviceMatching:iterator];
- [pool release];
+ [pool release];
}
-static void ServiceNotificationCallback(void * refCon,
- io_service_t service,
- natural_t messageType,
- void * messageArgument)
+static void ServiceNotificationCallback(void * refCon,
+ io_service_t service,
+ natural_t messageType,
+ void * messageArgument)
{
- HIDRemote *hidRemote = (HIDRemote *)refCon;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [hidRemote _serviceNotificationFor:service
- messageType:messageType
- messageArgument:messageArgument];
-
- [pool release];
+ HIDRemote *hidRemote = (HIDRemote *)refCon;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [hidRemote _serviceNotificationFor:service
+ messageType:messageType
+ messageArgument:messageArgument];
+
+ [pool release];
}
-static void SecureInputNotificationCallback( void * refCon,
- io_service_t service,
- natural_t messageType,
- void * messageArgument)
+static void SecureInputNotificationCallback( void * refCon,
+ io_service_t service,
+ natural_t messageType,
+ void * messageArgument)
{
- HIDRemote *hidRemote = (HIDRemote *)refCon;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [hidRemote _secureInputNotificationFor:service
- messageType:messageType
- messageArgument:messageArgument];
-
- [pool release];
+ HIDRemote *hidRemote = (HIDRemote *)refCon;
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ [hidRemote _secureInputNotificationFor:service
+ messageType:messageType
+ messageArgument:messageArgument];
+
+ [pool release];
}
// Attribute dictionary keys
-NSString *kHIDRemoteCFPluginInterface = @"CFPluginInterface";
-NSString *kHIDRemoteHIDDeviceInterface = @"HIDDeviceInterface";
-NSString *kHIDRemoteCookieButtonCodeLUT = @"CookieButtonCodeLUT";
-NSString *kHIDRemoteHIDQueueInterface = @"HIDQueueInterface";
-NSString *kHIDRemoteServiceNotification = @"ServiceNotification";
-NSString *kHIDRemoteCFRunLoopSource = @"CFRunLoopSource";
-NSString *kHIDRemoteLastButtonPressed = @"LastButtonPressed";
-NSString *kHIDRemoteService = @"Service";
-NSString *kHIDRemoteSimulateHoldEventsTimer = @"SimulateHoldEventsTimer";
-NSString *kHIDRemoteSimulateHoldEventsOriginButtonCode = @"SimulateHoldEventsOriginButtonCode";
-NSString *kHIDRemoteAluminumRemoteSupportLevel = @"AluminumRemoteSupportLevel";
-NSString *kHIDRemoteAluminumRemoteSupportOnDemand = @"AluminumRemoteSupportLevelOnDemand";
-
-NSString *kHIDRemoteManufacturer = @"Manufacturer";
-NSString *kHIDRemoteProduct = @"Product";
-NSString *kHIDRemoteTransport = @"Transport";
+NSString *kHIDRemoteCFPluginInterface = @"CFPluginInterface";
+NSString *kHIDRemoteHIDDeviceInterface = @"HIDDeviceInterface";
+NSString *kHIDRemoteCookieButtonCodeLUT = @"CookieButtonCodeLUT";
+NSString *kHIDRemoteHIDQueueInterface = @"HIDQueueInterface";
+NSString *kHIDRemoteServiceNotification = @"ServiceNotification";
+NSString *kHIDRemoteCFRunLoopSource = @"CFRunLoopSource";
+NSString *kHIDRemoteLastButtonPressed = @"LastButtonPressed";
+NSString *kHIDRemoteService = @"Service";
+NSString *kHIDRemoteSimulateHoldEventsTimer = @"SimulateHoldEventsTimer";
+NSString *kHIDRemoteSimulateHoldEventsOriginButtonCode = @"SimulateHoldEventsOriginButtonCode";
+NSString *kHIDRemoteAluminumRemoteSupportLevel = @"AluminumRemoteSupportLevel";
+NSString *kHIDRemoteAluminumRemoteSupportOnDemand = @"AluminumRemoteSupportLevelOnDemand";
+
+NSString *kHIDRemoteManufacturer = @"Manufacturer";
+NSString *kHIDRemoteProduct = @"Product";
+NSString *kHIDRemoteTransport = @"Transport";
// Distributed notifications
-NSString *kHIDRemoteDNHIDRemotePing = @"com.candelair.ping";
-NSString *kHIDRemoteDNHIDRemoteRetry = @"com.candelair.retry";
-NSString *kHIDRemoteDNHIDRemoteStatus = @"com.candelair.status";
+NSString *kHIDRemoteDNHIDRemotePing = @"com.candelair.ping";
+NSString *kHIDRemoteDNHIDRemoteRetry = @"com.candelair.retry";
+NSString *kHIDRemoteDNHIDRemoteStatus = @"com.candelair.status";
-NSString *kHIDRemoteDNHIDRemoteRetryGlobalObject = @"global";
+NSString *kHIDRemoteDNHIDRemoteRetryGlobalObject = @"global";
// Distributed notifications userInfo keys and values
-NSString *kHIDRemoteDNStatusHIDRemoteVersionKey = @"HIDRemoteVersion";
-NSString *kHIDRemoteDNStatusPIDKey = @"PID";
-NSString *kHIDRemoteDNStatusModeKey = @"Mode";
-NSString *kHIDRemoteDNStatusUnusedButtonCodesKey = @"UnusedButtonCodes";
-NSString *kHIDRemoteDNStatusActionKey = @"Action";
-NSString *kHIDRemoteDNStatusRemoteControlCountKey = @"RemoteControlCount";
-NSString *kHIDRemoteDNStatusReturnToPIDKey = @"ReturnToPID";
-NSString *kHIDRemoteDNStatusActionStart = @"start";
-NSString *kHIDRemoteDNStatusActionStop = @"stop";
-NSString *kHIDRemoteDNStatusActionUpdate = @"update";
-NSString *kHIDRemoteDNStatusActionNoNeed = @"noneed";
+NSString *kHIDRemoteDNStatusHIDRemoteVersionKey = @"HIDRemoteVersion";
+NSString *kHIDRemoteDNStatusPIDKey = @"PID";
+NSString *kHIDRemoteDNStatusModeKey = @"Mode";
+NSString *kHIDRemoteDNStatusUnusedButtonCodesKey = @"UnusedButtonCodes";
+NSString *kHIDRemoteDNStatusActionKey = @"Action";
+NSString *kHIDRemoteDNStatusRemoteControlCountKey = @"RemoteControlCount";
+NSString *kHIDRemoteDNStatusReturnToPIDKey = @"ReturnToPID";
+NSString *kHIDRemoteDNStatusActionStart = @"start";
+NSString *kHIDRemoteDNStatusActionStop = @"stop";
+NSString *kHIDRemoteDNStatusActionUpdate = @"update";
+NSString *kHIDRemoteDNStatusActionNoNeed = @"noneed";