Back to index

texmacs  1.0.7.15
HIDRemote.h
Go to the documentation of this file.
00001 //
00002 //  HIDRemote.h
00003 //  HIDRemote V1.1.1
00004 //
00005 //  Created by Felix Schwarz on 06.04.07.
00006 //  Copyright 2007-2009 IOSPIRIT GmbH. All rights reserved.
00007 //
00008 //  The latest version of this class is available at
00009 //     http://www.iospirit.com/developers/hidremote/
00010 //
00011 //  ** LICENSE *************************************************************************
00012 //
00013 //  Copyright (c) 2007-2009 IOSPIRIT GmbH (http://www.iospirit.com/)
00014 //  All rights reserved.
00015 //  
00016 //  Redistribution and use in source and binary forms, with or without modification,
00017 //  are permitted provided that the following conditions are met:
00018 //  
00019 //  * Redistributions of source code must retain the above copyright notice, this list
00020 //    of conditions and the following disclaimer.
00021 //  
00022 //  * Redistributions in binary form must reproduce the above copyright notice, this
00023 //    list of conditions and the following disclaimer in the documentation and/or other
00024 //    materials provided with the distribution.
00025 //  
00026 //  * Neither the name of IOSPIRIT GmbH nor the names of its contributors may be used to
00027 //    endorse or promote products derived from this software without specific prior
00028 //    written permission.
00029 //  
00030 //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
00031 //  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00032 //  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00033 //  SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00034 //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00035 //  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
00036 //  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00037 //  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00038 //  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00039 //  DAMAGE.
00040 //
00041 //  ************************************************************************************
00042 
00043 
00044 
00045 //  ************************************************************************************
00046 //  ********************************** DOCUMENTATION ***********************************
00047 //  ************************************************************************************
00048 //
00049 //  - a reference is available at http://www.iospirit.com/developers/hidremote/reference/
00050 //  - for a guide, please see http://www.iospirit.com/developers/hidremote/guide/
00051 //
00052 //  ************************************************************************************
00053 
00054 
00055 #import <Cocoa/Cocoa.h>
00056 
00057 #include <Carbon/Carbon.h>
00058 
00059 #include <unistd.h>
00060 #include <mach/mach.h>
00061 #include <sys/types.h>
00062 
00063 #include <IOKit/IOKitLib.h>
00064 #include <IOKit/IOCFPlugIn.h>
00065 #include <IOKit/IOMessage.h>
00066 #include <IOKit/hid/IOHIDKeys.h>
00067 #include <IOKit/hid/IOHIDLib.h>
00068 #include <IOKit/hid/IOHIDUsageTables.h>
00069 #include <IOKit/hidsystem/IOHIDLib.h>
00070 #include <IOKit/hidsystem/IOHIDParameter.h>
00071 #include <IOKit/hidsystem/IOHIDShared.h>
00072 
00073 #pragma mark -- Enums / Codes  --
00074 
00075 typedef enum
00076 {
00077        kHIDRemoteModeNone = 0L,
00078        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
00079                                    // (RECOMMENDED ONLY FOR SPECIAL PURPOSES)
00080 
00081        kHIDRemoteModeExclusive,    // Try to acquire an exclusive lock on the remote (NOT RECOMMENDED)
00082 
00083        kHIDRemoteModeExclusiveAuto // Try to acquire an exclusive lock on the remote whenever the application has focus. Temporarily release control over the
00084                                    // remote when another application has focus (RECOMMENDED)
00085 } HIDRemoteMode;
00086 
00087 typedef enum
00088 {
00089        /* A code reserved for "no button" (needed for tracking) */
00090        kHIDRemoteButtonCodeNone    = 0L,
00091 
00092        /* Standard codes - available for white plastic and aluminum remote */
00093        kHIDRemoteButtonCodeUp,
00094        kHIDRemoteButtonCodeDown,
00095        kHIDRemoteButtonCodeLeft,
00096        kHIDRemoteButtonCodeRight,
00097        kHIDRemoteButtonCodeCenter,
00098        kHIDRemoteButtonCodeMenu,
00099 
00100        /* Extra codes - Only available for the new aluminum version of the remote */
00101        kHIDRemoteButtonCodePlay,
00102 
00103        /* Masks */
00104        kHIDRemoteButtonCodeCodeMask      = 0xFFL,
00105        kHIDRemoteButtonCodeHoldMask      = (1L << 16L),
00106        kHIDRemoteButtonCodeSpecialMask   = (1L << 17L),
00107        kHIDRemoteButtonCodeAluminumMask  = (1L << 21L), // PRIVATE - only used internally
00108 
00109        /* Hold button standard codes - available for white plastic and aluminum remote */
00110        kHIDRemoteButtonCodeUpHold       = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeUp),
00111        kHIDRemoteButtonCodeDownHold     = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeDown),
00112        kHIDRemoteButtonCodeLeftHold     = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeLeft),
00113        kHIDRemoteButtonCodeRightHold    = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeRight),
00114        kHIDRemoteButtonCodeCenterHold      = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeCenter),
00115        kHIDRemoteButtonCodeMenuHold        = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeMenu),
00116 
00117        /* Hold button extra codes - Only available for aluminum version of the remote */
00118        kHIDRemoteButtonCodePlayHold         = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodePlay),
00119 
00120        /* DEPRECATED codes - compatibility with HIDRemote 1.0 */
00121        kHIDRemoteButtonCodePlus      = kHIDRemoteButtonCodeUp,
00122        kHIDRemoteButtonCodePlusHold      = kHIDRemoteButtonCodeUpHold,
00123        kHIDRemoteButtonCodeMinus     = kHIDRemoteButtonCodeDown,
00124        kHIDRemoteButtonCodeMinusHold     = kHIDRemoteButtonCodeDownHold,
00125        kHIDRemoteButtonCodePlayPause        = kHIDRemoteButtonCodeCenter,
00126        kHIDRemoteButtonCodePlayPauseHold = kHIDRemoteButtonCodeCenterHold,
00127 
00128        /* Special purpose codes */
00129        kHIDRemoteButtonCodeIDChanged  = (kHIDRemoteButtonCodeSpecialMask|(1L << 18L)),     // (the ID of the connected remote has changed, you can safely ignore this)
00130        #ifdef _HIDREMOTE_EXTENSIONS
00131               #define _HIDREMOTE_EXTENSIONS_SECTION 1
00132               #include "HIDRemoteAdditions.h"
00133               #undef _HIDREMOTE_EXTENSIONS_SECTION
00134        #endif /* _HIDREMOTE_EXTENSIONS */
00135 } HIDRemoteButtonCode;
00136 
00137 typedef enum
00138 {
00139        kHIDRemoteModelUndetermined = 0L,                       // Assume a white plastic remote
00140        kHIDRemoteModelWhitePlastic,                                   // Signal *likely* to be coming from a white plastic remote
00141        kHIDRemoteModelAluminum                                        // Signal *definitely* coming from an aluminum remote
00142 } HIDRemoteModel;
00143 
00144 typedef enum
00145 {
00146        kHIDRemoteAluminumRemoteSupportLevelNone = 0L,                 // This system has no support for the Aluminum Remote at all
00147        kHIDRemoteAluminumRemoteSupportLevelEmulation,                 // This system possibly has support for the Aluminum Remote (via emulation)
00148        kHIDRemoteAluminumRemoteSupportLevelNative                     // This system has native support for the Aluminum Remote
00149 } HIDRemoteAluminumRemoteSupportLevel;
00150 
00151 @class HIDRemote;
00152 
00153 #pragma mark -- Delegate protocol (mandatory) --
00154 @protocol HIDRemoteDelegate
00155 
00156 // Notification of button events
00157 - (void)hidRemote:(HIDRemote *)hidRemote                       // The instance of HIDRemote sending this
00158         eventWithButton:(HIDRemoteButtonCode)buttonCode               // Event for the button specified by code
00159        isPressed:(BOOL)isPressed                               // The button was pressed (YES) / released (NO)
00160        fromHardwareWithAttributes:(NSMutableDictionary *)attributes;  // Information on the device this event comes from
00161 
00162 @optional
00163 
00164 // Notification of ID changes
00165 - (void)hidRemote:(HIDRemote *)hidRemote                       // Invoked when the user switched to a remote control with a different ID
00166        remoteIDChangedOldID:(SInt32)old
00167        newID:(SInt32)newID
00168        forHardwareWithAttributes:(NSMutableDictionary *)attributes;
00169 
00170 // Notification about hardware additions/removals 
00171 - (void)hidRemote:(HIDRemote *)hidRemote                       // Invoked when new hardware was found / added to HIDRemote's pool
00172        foundNewHardwareWithAttributes:(NSMutableDictionary *)attributes;
00173 
00174 - (void)hidRemote:(HIDRemote *)hidRemote                       // Invoked when initialization of new hardware as requested failed
00175        failedNewHardwareWithError:(NSError *)error;
00176 
00177 - (void)hidRemote:(HIDRemote *)hidRemote                       // Invoked when hardware was removed from HIDRemote's pool
00178        releasedHardwareWithAttributes:(NSMutableDictionary *)attributes;
00179 
00180 // ### WARNING: Unless you know VERY PRECISELY what you are doing, do not implement any of the delegate methods below. ###
00181 
00182 // Matching of newly found receiver hardware
00183 - (BOOL)hidRemote:(HIDRemote *)hidRemote                       // Invoked when new hardware is inspected
00184        inspectNewHardwareWithService:(io_service_t)service            // 
00185        prematchResult:(BOOL)prematchResult;                           // Return YES if HIDRemote should go on with this hardware and try
00186                                                                // to use it, or NO if it should not be persued further.
00187 
00188 // Exlusive lock lending
00189 - (BOOL)hidRemote:(HIDRemote *)hidRemote
00190        lendExclusiveLockToApplicationWithInfo:(NSDictionary *)applicationInfo;
00191 
00192 - (void)hidRemote:(HIDRemote *)hidRemote
00193        exclusiveLockReleasedByApplicationWithInfo:(NSDictionary *)applicationInfo;
00194 
00195 - (BOOL)hidRemote:(HIDRemote *)hidRemote
00196        shouldRetryExclusiveLockWithInfo:(NSDictionary *)applicationInfo;
00197 
00198 @end 
00199 
00200 
00201 #pragma mark -- Actual header file for class  --
00202 
00203 @interface HIDRemote : NSObject
00204 {
00205        // IOMasterPort
00206        mach_port_t _masterPort;
00207 
00208        // Notification ports
00209        IONotificationPortRef _notifyPort;
00210        CFRunLoopSourceRef _notifyRLSource;
00211        
00212        // Matching iterator
00213        io_iterator_t _matchingServicesIterator;
00214        
00215        // SecureInput notification
00216        io_object_t _secureInputNotification;
00217        
00218        // Service attributes
00219        NSMutableDictionary *_serviceAttribMap;
00220        
00221        // Mode
00222        HIDRemoteMode _mode;
00223        BOOL _autoRecover;
00224        NSTimer *_autoRecoveryTimer;
00225        
00226        // Delegate
00227        NSObject <HIDRemoteDelegate> *_delegate;
00228        
00229        // Last seen ID and remote model
00230        SInt32 _lastSeenRemoteID;
00231        HIDRemoteModel _lastSeenModel;
00232        SInt32 _lastSeenModelRemoteID;
00233        
00234        // Unused button codes
00235        NSArray *_unusedButtonCodes;
00236        
00237        // Simulate Plus/Minus Hold
00238        BOOL _simulateHoldEvents;
00239        
00240        // SecureEventInput workaround
00241        BOOL _secureEventInputWorkAround;
00242        UInt64 _lastSecureEventInputPIDSum;
00243        uid_t _lastFrontUserSession;
00244        
00245        // Exclusive lock lending
00246        BOOL _exclusiveLockLending;
00247        NSNumber *_waitForReturnByPID;
00248        NSNumber *_returnToPID;
00249 }
00250 
00251 #pragma mark -- PUBLIC: Shared HID Remote --
00252 + (HIDRemote *)sharedHIDRemote;
00253 
00254 #pragma mark -- PUBLIC: System Information --
00255 + (BOOL)isCandelairInstalled;
00256 + (BOOL)isCandelairInstallationRequiredForRemoteMode:(HIDRemoteMode)remoteMode;
00257 - (HIDRemoteAluminumRemoteSupportLevel)aluminiumRemoteSystemSupportLevel;
00258 
00259 #pragma mark -- PUBLIC: Interface / API --
00260 - (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode;       
00261 - (void)stopRemoteControl;
00262 
00263 - (BOOL)isStarted;
00264 
00265 - (unsigned)activeRemoteControlCount;
00266 
00267 - (SInt32)lastSeenRemoteControlID;
00268 
00269 - (void)setLastSeenModel:(HIDRemoteModel)aModel;
00270 - (HIDRemoteModel)lastSeenModel;
00271 
00272 - (void)setDelegate:(NSObject <HIDRemoteDelegate> *)newDelegate;
00273 - (NSObject <HIDRemoteDelegate> *)delegate;
00274 
00275 - (void)setSimulateHoldEvents:(BOOL)newSimulateHoldEvents;
00276 - (BOOL)simulateHoldEvents;
00277 
00278 - (void)setUnusedButtonCodes:(NSArray *)newArrayWithUnusedButtonCodesAsNSNumbers;
00279 - (NSArray *)unusedButtonCodes;
00280 
00281 #pragma mark -- PUBLIC: Expert APIs --
00282 - (void)setEnableSecureEventInputWorkaround:(BOOL)newEnableSecureEventInputWorkaround;
00283 - (BOOL)enableSecureEventInputWorkaround;
00284 
00285 - (void)setExclusiveLockLendingEnabled:(BOOL)newExclusiveLockLendingEnabled;
00286 - (BOOL)exclusiveLockLendingEnabled;
00287 
00288 #pragma mark -- PRIVATE: HID Event handling --
00289 - (void)_handleButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict;
00290 - (void)_sendButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict;
00291 - (void)_hidEventFor:(io_service_t)hidDevice from:(IOHIDQueueInterface **)interface withResult:(IOReturn)result;
00292 
00293 #pragma mark -- PRIVATE: Service setup and destruction --
00294 - (BOOL)_prematchService:(io_object_t)service;
00295 - (HIDRemoteButtonCode)buttonCodeForUsage:(unsigned int)usage usagePage:(unsigned int)usagePage;
00296 - (BOOL)_setupService:(io_object_t)service;
00297 - (void)_destructService:(io_object_t)service;
00298 
00299 #pragma mark -- PRIVATE: Distributed notifiations handling --
00300 - (void)_postStatusWithAction:(NSString *)action;
00301 - (void)_handleNotifications:(NSNotification *)notification;
00302 
00303 #pragma mark -- PRIVATE: Application becomes active / inactive handling for kHIDRemoteModeExclusiveAuto --
00304 - (void)_appStatusChanged:(NSNotification *)notification;
00305 - (void)_delayedAutoRecovery:(NSTimer *)aTimer;
00306 
00307 #pragma mark -- PRIVATE: Notification handling --
00308 - (void)_serviceMatching:(io_iterator_t)iterator;
00309 - (void)_serviceNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument;
00310 - (void)_updateSessionInformation;
00311 - (void)_secureInputNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument;
00312 
00313 @end
00314 
00315 #pragma mark -- Information attribute keys --
00316 extern NSString *kHIDRemoteManufacturer;
00317 extern NSString *kHIDRemoteProduct;
00318 extern NSString *kHIDRemoteTransport;
00319 
00320 #pragma mark -- Internal/Expert attribute keys (AKA: don't touch these unless you really, really, REALLY know what you do) --
00321 extern NSString *kHIDRemoteCFPluginInterface;
00322 extern NSString *kHIDRemoteHIDDeviceInterface;
00323 extern NSString *kHIDRemoteCookieButtonCodeLUT;
00324 extern NSString *kHIDRemoteHIDQueueInterface;
00325 extern NSString *kHIDRemoteServiceNotification;
00326 extern NSString *kHIDRemoteCFRunLoopSource;
00327 extern NSString *kHIDRemoteLastButtonPressed;
00328 extern NSString *kHIDRemoteService;
00329 extern NSString *kHIDRemoteSimulateHoldEventsTimer;
00330 extern NSString *kHIDRemoteSimulateHoldEventsOriginButtonCode;
00331 extern NSString *kHIDRemoteAluminumRemoteSupportLevel;
00332 extern NSString *kHIDRemoteAluminumRemoteSupportOnDemand;
00333 
00334 #pragma mark -- Distributed notifications --
00335 extern NSString *kHIDRemoteDNHIDRemotePing;
00336 extern NSString *kHIDRemoteDNHIDRemoteRetry;
00337 extern NSString *kHIDRemoteDNHIDRemoteStatus;
00338 
00339 #pragma mark -- Distributed notifications userInfo keys and values --
00340 extern NSString *kHIDRemoteDNStatusHIDRemoteVersionKey;
00341 extern NSString *kHIDRemoteDNStatusPIDKey;
00342 extern NSString *kHIDRemoteDNStatusModeKey;
00343 extern NSString *kHIDRemoteDNStatusUnusedButtonCodesKey;
00344 extern NSString *kHIDRemoteDNStatusRemoteControlCountKey;
00345 extern NSString *kHIDRemoteDNStatusReturnToPIDKey;
00346 extern NSString *kHIDRemoteDNStatusActionKey;
00347 extern NSString *kHIDRemoteDNStatusActionStart;
00348 extern NSString *kHIDRemoteDNStatusActionStop;
00349 extern NSString *kHIDRemoteDNStatusActionUpdate;
00350 extern NSString *kHIDRemoteDNStatusActionNoNeed;
00351 
00352 #pragma mark -- Driver compatibility flags --
00353 typedef enum
00354 {
00355        kHIDRemoteCompatibilityFlagsStandardHIDRemoteDevice = 1L,
00356 } HIDRemoteCompatibilityFlags;