Squashed 'Apple2Mac/DDHidLib/' content from commit e6a9848

git-subtree-dir: Apple2Mac/DDHidLib
git-subtree-split: e6a9848859fc84e689afb85799658f4980651106
This commit is contained in:
Aaron Culliney 2014-11-09 17:08:23 -08:00
commit 7d64531b89
81 changed files with 16864 additions and 0 deletions

18
.gitignore vendored Normal file
View File

@ -0,0 +1,18 @@
# Xcode
.DS_Store
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
*.xcworkspace
!default.xcworkspace
xcuserdata
profile
*.moved-aside
DerivedData
.idea/

22
DDHidLib-Info.plist Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.dribin.dave.DDHidLib</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${CURRENT_MARKETING_VERSION}</string>
</dict>
</plist>

File diff suppressed because it is too large Load Diff

BIN
Icon.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

181
LICENSE.html Normal file
View File

@ -0,0 +1,181 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" version="XHTML+RDFa 1.0" dir="ltr">
<head profile="http://www.w3.org/1999/xhtml/vocab">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="http://opensource.org/files/garland_favicon.png" type="image/png" />
<link rel="shortlink" href="/node/66" />
<link rel="canonical" href="/licenses/MIT" />
<meta name="Generator" content="Drupal 7 (http://drupal.org)" />
<title>The MIT License (MIT) | Open Source Initiative</title>
<link type="text/css" rel="stylesheet" href="http://opensource.org/files/css/css_pbm0lsQQJ7A7WCCIMgxLho6mI_kBNgznNUWmTWcnfoE.css" media="all" />
<link type="text/css" rel="stylesheet" href="http://opensource.org/files/css/css_Frms3llKkCDMuuCHUzEHGgSAc59B2At_Y3KWbmFS9k4.css" media="all" />
<link type="text/css" rel="stylesheet" href="http://opensource.org/files/css/css_2wI77kyP-rJKVpFW5M3KFcj7Cb99lZalmubKIwWwsmU.css" media="all" />
<link type="text/css" rel="stylesheet" href="http://opensource.org/files/css/css_k3snrbsthqot7V7ccRZHS9OkCZkwBv4adtNieIVlbEU.css" media="print" />
<!--[if lt IE 7]>
<link type="text/css" rel="stylesheet" href="http://opensource.org/themes/garland/fix-ie.css?mg005b" media="all" />
<![endif]-->
<script type="text/javascript" src="http://opensource.org/files/js/js_3jHghlMLrjr9xXAC0JufqSSch3oAbkZstSqYdc4uuck.js"></script>
<script type="text/javascript">
<!--//--><![CDATA[//><!--
jQuery.extend(Drupal.settings, {"basePath":"\/","pathPrefix":"","ajaxPageState":{"theme":"garland","theme_token":"oU3oKgkO9Kxh34R6sHTF4WSsGPlfgkgK1fMLCpEJ72I","js":{"misc\/jquery.js":1,"misc\/jquery.once.js":1,"misc\/drupal.js":1},"css":{"modules\/system\/system.base.css":1,"modules\/system\/system.menus.css":1,"modules\/system\/system.messages.css":1,"modules\/system\/system.theme.css":1,"modules\/aggregator\/aggregator.css":1,"modules\/comment\/comment.css":1,"modules\/field\/theme\/field.css":1,"sites\/all\/modules\/mollom\/mollom.css":1,"modules\/node\/node.css":1,"modules\/search\/search.css":1,"modules\/user\/user.css":1,"themes\/garland\/style.css":1,"themes\/garland\/print.css":1,"themes\/garland\/fix-ie.css":1}}});
//--><!]]>
</script>
</head>
<body class="html not-front not-logged-in one-sidebar sidebar-first page-node page-node- page-node-66 node-type-page fluid-width" >
<div id="skip-link">
<a href="#main-content" class="element-invisible element-focusable">Skip to main content</a>
</div>
<div id="wrapper">
<div id="container" class="clearfix">
<div id="header">
<div id="logo-floater">
<div id="branding"><strong><a href="/">
<img src="http://opensource.org/files/garland_logo.png" alt="Open Source Initiative " title="Open Source Initiative " id="logo" />
<span>Open Source Initiative</span> </a></strong></div>
</div>
</div> <!-- /#header -->
<div id="sidebar-first" class="sidebar">
<div class="region region-sidebar-first">
<div id="block-search-form" class="block block-search clearfix">
<h2 class="title">Search this site:</h2>
<div class="content">
<form action="/licenses/mit-license.php" method="post" id="search-block-form" accept-charset="UTF-8"><div><div class="container-inline">
<div class="form-item form-type-textfield form-item-search-block-form">
<label class="element-invisible" for="edit-search-block-form--2">Search </label>
<input title="Enter the terms you wish to search for." type="text" id="edit-search-block-form--2" name="search_block_form" value="" size="15" maxlength="128" class="form-text" />
</div>
<div class="form-actions form-wrapper" id="edit-actions"><input type="submit" id="edit-submit" name="op" value="Search" class="form-submit" /></div><input type="hidden" name="form_build_id" value="form-ADm3Z4uyEPhRis8sKsUf9Oqq50FP1ae1rX3NnMchpDM" />
<input type="hidden" name="form_id" value="search_block_form" />
</div>
</div></form> </div>
</div>
<div id="block-system-navigation" class="block block-system block-menu clearfix">
<h2 class="title">Navigation</h2>
<div class="content">
<ul class="menu"><li class="first collapsed"><a href="/about" title="About the Open Source Initiative">About the OSI</a></li>
<li class="collapsed"><a href="/osd" title="The actual OSD defining what constitutes an Open Source licence">The Open Source Definition</a></li>
<li class="collapsed"><a href="/licenses">Open Source Licenses</a></li>
<li class="collapsed"><a href="/trademark" title="Information about trademark and logo usage ">Trademark and Logo Usage</a></li>
<li class="leaf"><a href="/faq" title="Frequently Asked Questions about open source and about the OSI.">FAQ</a></li>
<li class="collapsed"><a href="/osr-intro" title="Open Standards Requirement for Software">Open Standards</a></li>
<li class="leaf"><a href="/osi-open-source-education" title="OSI&#039;s Open Source Education Initiative and Activities">Open Source Education</a></li>
<li class="collapsed"><a href="/lists" title="The virtual committees where the OSI&#039;s work gets done">Mailing lists</a></li>
<li class="collapsed"><a href="/help" title="Resources for questions and further exploration">Getting Help</a></li>
<li class="collapsed"><a href="http://opensource.org/donate" title="">Donate to the OSI</a></li>
<li class="leaf"><a href="/members">OSI Individual Membership</a></li>
<li class="collapsed"><a href="/affiliates" title="Home page for OSI&#039;s membership scheme for non-profits and not-for-profits">OSI Affiliate Membership</a></li>
<li class="leaf"><a href="/contact" title="">Contact OSI</a></li>
<li class="last leaf"><a href="/ToS" title="Rules for posting content on this site">Terms of Service</a></li>
</ul> </div>
</div>
</div>
</div>
<div id="center"><div id="squeeze"><div class="right-corner"><div class="left-corner">
<h2 class="element-invisible">You are here</h2><div class="breadcrumb"><a href="/">Home</a></div> <a id="main-content"></a>
<div id="tabs-wrapper" class="clearfix"> <h1 class="with-tabs">The MIT License (MIT)</h1>
</div> <div class="clearfix">
<div class="region region-content">
<div id="block-system-main" class="block block-system clearfix">
<div class="content">
<div id="node-66" class="node node-page">
<div class="content clearfix">
<img style="float: right; margin: 1em;" width="100" height="137" alt="[OSI Approved License]" src="/trademarks/opensource/OSI-Appro
ved-License-100x137.png"/>
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><h1>The MIT License (MIT)</h1>
<tt>
<p>Copyright (c) &lt;year&gt; &lt;copyright holders&gt;</p>
<p>Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:</p>
<p>The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.</p>
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.</p>
</div></div></div> </div>
<div class="clearfix">
<div class="links"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="region region-footer">
<div id="block-block-11" class="block block-block clearfix">
<div class="content">
<!-- Creative Commons License --><a rel="license" href="http://creativecommons.org/licenses/by/3.0/"><img alt="Creative Commons License" style="border-width: 0" src="http://i.creativecommons.org/l/by/3.0/88x31.png" /></a><br />Opensource.org site content is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 License</a>.<!-- /Creative Commons License -->
<!-- <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<Work rdf:about="">
<license rdf:resource="http://creativecommons.org/licenses/by/3.0/" />
</Work>
<License rdf:about="http://creativecommons.org/licenses/by/3.0/"><permits rdf:resource="http://web.resource.org/cc/Reproduction"/><permits rdf:resource="http://web.resource.org/cc/Distribution"/><requires rdf:resource="http://web.resource.org/cc/Notice"/><requires rdf:resource="http://web.resource.org/cc/Attribution"/><permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/></License></rdf:RDF>
-->
| <a href="../ToS">Terms of Service</a>
</div>
</div>
<div id="block-block-7" class="block block-block clearfix">
<div class="content">
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
<!--//--><![CDATA[// ><!--
//--><!]]>
</script><script type="text/javascript">
<!--//--><![CDATA[// ><!--
_uacct = "UA-3916956-1";
urchinTracker();
//--><!]]>
</script> </div>
</div>
</div>
</div></div></div></div> <!-- /.left-corner, /.right-corner, /#squeeze, /#center -->
</div> <!-- /#container -->
</div> <!-- /#wrapper -->
</body>
</html>

11
README.md Normal file
View File

@ -0,0 +1,11 @@
DDHidLib
=====
###by Dave Dribin
An Objective-C wrapper around IOHIDLib.
http://www.dribin.org/dave/software/
###Modifications in the repo:
- added experimental support for (apple) mics with built-in keys.
- dropped ppc and added x64 support

View File

@ -0,0 +1,13 @@
{
IBClasses = (
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{
ACTIONS = {clearHistory = id; };
CLASS = WatcherWindowController;
LANGUAGE = ObjC;
OUTLETS = {mEventHistoryController = NSArrayController; };
SUPERCLASS = NSWindowController;
}
);
IBVersion = 1;
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>69 14 356 240 0 0 1440 878 </string>
<key>IBFramework Version</key>
<string>446.1</string>
<key>IBOpenObjects</key>
<array>
<integer>5</integer>
</array>
<key>IBSystem Version</key>
<string>8N1037</string>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,19 @@
{
IBClasses = (
{CLASS = DDHidElement; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
{CLASS = HexFormatter; LANGUAGE = ObjC; SUPERCLASS = NSFormatter; },
{
ACTIONS = {exportPlist = id; watchSelected = id; };
CLASS = HidBrowserController;
LANGUAGE = ObjC;
OUTLETS = {
mDevicesController = NSArrayController;
mElementsController = NSTreeController;
mWindow = NSWindow;
};
SUPERCLASS = NSObject;
}
);
IBVersion = 1;
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>110 86 356 240 0 0 1440 878 </string>
<key>IBEditorPositions</key>
<dict>
<key>29</key>
<string>95 721 310 44 0 0 1440 878 </string>
</dict>
<key>IBFramework Version</key>
<string>446.1</string>
<key>IBOpenObjects</key>
<array>
<integer>21</integer>
<integer>29</integer>
</array>
<key>IBSystem Version</key>
<string>8N1037</string>
</dict>
</plist>

Binary file not shown.

View File

@ -0,0 +1,7 @@
//
// Prefix header for all source files of the 'HIDBrowser' target in the 'HIDBrowser' project
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif

34
browser/HexFormatter.h Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@interface HexFormatter : NSFormatter {
}
+ (NSString*)format:(long)number;
@end

49
browser/HexFormatter.m Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "HexFormatter.h"
@implementation HexFormatter
+ (NSString*)format:(long)number;
{
return [NSString stringWithFormat: @"0x%02X", number];
}
- (NSString *)stringForObjectValue:(id)anObject {
return [HexFormatter format:[anObject longValue]];
}
- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error {
return NO;
}
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes:(NSDictionary *)attributes {
return [[[NSAttributedString alloc] initWithString:[self stringForObjectValue:anObject]] autorelease];
}
@end

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@interface HidBrowserController : NSObject
{
IBOutlet NSWindow * mWindow;
IBOutlet NSArrayController * mDevicesController;
IBOutlet NSTreeController * mElementsController;
NSArray * mDevices;
}
- (NSArray *) devices;
- (IBAction) watchSelected: (id) sender;
- (IBAction) exportPlist: (id) sender;
@end

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "HidBrowserController.h"
#import "DDHidUsageTables.h"
#import "DDHidDevice.h"
#import "DDHidElement.h"
#import "WatcherWindowController.h"
@implementation HidBrowserController
static BOOL sSleepAtExit = NO;
static void exit_sleeper()
{
while (sSleepAtExit) sleep(60);
}
- (void) awakeFromNib
{
sSleepAtExit = [[NSUserDefaults standardUserDefaults] boolForKey: @"SleepAtExit"];
atexit(exit_sleeper);
[self willChangeValueForKey: @"devices"];
mDevices = [[DDHidDevice allDevices] retain];
[self didChangeValueForKey: @"devices"];
[mWindow center];
[mWindow makeKeyAndOrderFront: self];
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mDevices release];
mDevices = nil;
[super dealloc];
}
//===========================================================
// - devices
//===========================================================
- (NSArray *) devices
{
return mDevices;
}
- (DDHidDevice *) selectedDevice;
{
NSArray * selectedDevices = [mDevicesController selectedObjects];
if ([selectedDevices count] > 0)
return [selectedDevices objectAtIndex: 0];
else
return nil;
}
- (IBAction) watchSelected: (id) sender;
{
NSArray * selectedElements = [mElementsController selectedObjects];
if ([selectedElements count] == 0)
return;
WatcherWindowController * controller =
[[WatcherWindowController alloc] init];
[controller setDevice: [self selectedDevice]];
[controller setElements: selectedElements];
[controller showWindow: self];
}
- (IBAction) exportPlist: (id) sender;
{
DDHidDevice * selectedDevice = [self selectedDevice];
if (selectedDevice == nil)
return;
NSSavePanel * panel = [NSSavePanel savePanel];
/* set up new attributes */
[panel setRequiredFileType: @"plist"];
[panel setAllowsOtherFileTypes: NO];
[panel setCanSelectHiddenExtension: YES];
/* display the NSSavePanel */
[panel beginSheetForDirectory: NSHomeDirectory()
file: @""
modalForWindow: [NSApp mainWindow]
modalDelegate: self
didEndSelector: @selector(exportPlistPanelDidEnd:returnCode:contextInfo:)
contextInfo: selectedDevice];
}
- (void) exportPlistPanelDidEnd: (NSSavePanel *) panel
returnCode: (int) returnCode
contextInfo: (void *) contextInfo;
{
DDHidDevice * selectedDevice = contextInfo;
/* if successful, save file under designated name */
if (returnCode != NSOKButton)
return;
NSDictionary * deviceProperties = [selectedDevice properties];
if (![deviceProperties writeToFile: [panel filename] atomically: YES])
NSBeep();
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
{
return YES;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
[self willChangeValueForKey: @"devices"];
[mDevices release];
mDevices = nil;
[self didChangeValueForKey: @"devices"];
}
@end

30
browser/Info.plist Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>org.dribin.dave.ddhidlib.HIDBrowser</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${CURRENT_MARKETING_VERSION}</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidDevice.h"
#import "DDHidElement.h"
@class DDHidQueue;
@interface WatcherWindowController : NSWindowController
{
IBOutlet NSArrayController * mEventHistoryController;
DDHidDevice * mDevice;
NSArray * mElements;
DDHidQueue * mQueue;
NSMutableArray * mEventHistory;
int mNextIndex;
}
- (DDHidDevice *) device;
- (void) setDevice: (DDHidDevice *) newDevice;
- (NSArray *) elements;
- (void) setElements: (NSArray *) newElements;
- (NSMutableArray *) eventHistory;
- (void) setEventHistory: (NSMutableArray *) anEventHistory;
- (void) addToEventHistory: (id)mEventHistoryObject;
- (void) removeFromEventHistory: (id)mEventHistoryObject;
- (BOOL) isWatching;
- (void) setWatching: (BOOL) watching;
- (IBAction) clearHistory: (id) sender;
@end

View File

@ -0,0 +1,269 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "WatcherWindowController.h"
#import "DDHidQueue.h"
#import "DDHidEvent.h"
#import "DDHidUsage.h"
@interface WatcherEvent : NSObject
{
NSString * mUsageDescription;
DDHidEvent * mEvent;
int mIndex;
}
- (id) initWithUsageDescription: (NSString *) anUsageDecription
event: (DDHidEvent *) anEvent
index: (int) index;
- (NSString *) usageDescription;
- (DDHidEvent *) event;
- (int) index;
@end
@implementation WatcherEvent : NSObject
- (id) initWithUsageDescription: (NSString *) anUsageDescription
event: (DDHidEvent *) anEvent
index: (int) index
{
if (self = [super init])
{
mUsageDescription = [anUsageDescription retain];
mEvent = [anEvent retain];
mIndex = index;
}
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mUsageDescription release];
[mEvent release];
mUsageDescription = nil;
mEvent = nil;
[super dealloc];
}
//===========================================================
// - usageDescription
//===========================================================
- (NSString *) usageDescription
{
return mUsageDescription;
}
//===========================================================
// - event
//===========================================================
- (DDHidEvent *) event
{
return mEvent;
}
//===========================================================
// - index
//===========================================================
- (int) index
{
return mIndex;
}
@end
@implementation WatcherWindowController
- (id) init
{
self = [super initWithWindowNibName: @"EventWatcher" owner: self];
if (self == nil)
return nil;
mEventHistory = [[NSMutableArray alloc] init];
mNextIndex = 1;
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mQueue release];
[mDevice release];
[mElements release];
[mEventHistory release];
mQueue = nil;
mDevice = nil;
mElements = nil;
mEventHistory = nil;
[super dealloc];
}
- (void)windowWillClose:(NSNotification *)notification
{
[mQueue release];
mQueue = nil;
[mDevice close];
[self autorelease];
}
- (IBAction)showWindow:(id)sender
{
[super showWindow: sender];
}
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
{
WatcherEvent * watcherEvent;
watcherEvent =
[[WatcherEvent alloc] initWithUsageDescription: @"-----------------------------"
event: nil
index: mNextIndex++];
[watcherEvent autorelease];
[mEventHistoryController addObject: watcherEvent];
NSMutableArray * newEvents = [NSMutableArray array];
DDHidEvent * event;
while (event = [hidQueue nextEvent])
{
DDHidElement * element = [mDevice elementForCookie: [event elementCookie]];
watcherEvent =
[[WatcherEvent alloc] initWithUsageDescription: [[element usage] usageNameWithIds]
event: event
index: mNextIndex++];
[watcherEvent autorelease];
[newEvents addObject: watcherEvent];
}
[mEventHistoryController addObjects: newEvents];
}
- (void) windowDidLoad;
{
[mDevice open];
mQueue = [[mDevice createQueueWithSize: 30] retain];
[mQueue setDelegate: self];
[mQueue addElements: mElements];
[self willChangeValueForKey: @"watching"];
[mQueue startOnCurrentRunLoop];
[self didChangeValueForKey: @"watching"];
}
//===========================================================
// device
//===========================================================
- (DDHidDevice *) device
{
return [[mDevice retain] autorelease];
}
- (void) setDevice: (DDHidDevice *) newDevice
{
if (mDevice != newDevice)
{
[mDevice release];
mDevice = [newDevice retain];
}
}
//===========================================================
// elements
//===========================================================
- (NSArray *) elements
{
return [[mElements retain] autorelease];
}
- (void) setElements: (NSArray *) newElements
{
if (mElements != newElements)
{
[mElements release];
mElements = [newElements retain];
}
}
//===========================================================
// eventHistory
//===========================================================
- (NSMutableArray *) eventHistory
{
return mEventHistory;
}
- (void) setEventHistory: (NSMutableArray *) anEventHistory
{
if (mEventHistory != anEventHistory)
{
[mEventHistory release];
mEventHistory = [anEventHistory retain];
}
}
- (void) addToEventHistory: (id)mEventHistoryObject
{
[[self eventHistory] addObject: mEventHistoryObject];
}
- (void) removeFromEventHistory: (id)mEventHistoryObject
{
[[self eventHistory] removeObject: mEventHistoryObject];
}
- (BOOL) isWatching;
{
if (mQueue == nil)
return NO;
return [mQueue isStarted];
}
- (void) setWatching: (BOOL) watching;
{
BOOL isStarted = [mQueue isStarted];
if (isStarted == watching)
return;
if (watching)
[mQueue startOnCurrentRunLoop];
else
[mQueue stop];
}
- (IBAction) clearHistory: (id) sender;
{
[self willChangeValueForKey: @"eventHistory"];
[mEventHistory removeAllObjects];
mNextIndex = 1;
[self didChangeValueForKey: @"eventHistory"];
}
@end

30
browser/main.m Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **) argv);
}

24
changelog.yml Normal file
View File

@ -0,0 +1,24 @@
- version: "1.1"
date: 2008-04-22
changes:
- Added logical joysticks for devices with multiple top-level elements.
Should allow devices like PS/2 to USB converters to work better.
- Change joystick normalized values to +/- 65536.
- Update Apple Remote codes for Leopard.
- Improved keyboard barcode scanning for certain devices.
- Added internal debugging code to help detect memory leaks.
- version: "1.0.1"
date: 2007-04-03
changes:
- "Replace deprecated stringWithCString: with stringWithUTF8String:."
- Make DDHidKeyboard.h public so it gets copied to the framework.
- Plugged some memory leaks.
- Added a class for barcode scanners, thanks to Lucas Newman of Delicious
Monster.
- Add support for point of view hat switches on joysticks.
- version: "1.0"
date: 2007-03-19
changes:
- Initial release.

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@class DDHidAppleMikey;
@interface AppleMikeyPaneController : NSObject
{
IBOutlet NSArrayController * mMikeysController;
IBOutlet NSArrayController * mMikeysEventsController;
NSArray * mMikeys;
NSUInteger mMikeyIndex;
NSMutableArray * mEvents;
// Don't retain these
DDHidAppleMikey * mCurrentMikey;
}
- (NSArray *) mikeys;
- (void) setMikeys: (NSArray *) theMikeys;
- (NSUInteger) mikeyIndex;
- (void) setMikeyIndex: (NSUInteger) theMikeyIndex;
- (NSMutableArray *) events;
- (void) setEvents: (NSMutableArray *) theEvents;
- (void) addEvent: (id)theEvent;
- (void) removeEvent: (id)theEvent;
@end
@interface AppleMikeyPaneController (DDHidAppleMikeyDelegate)
- (void) ddhidAppleMikey: (DDHidAppleMikey *) mikey
press: (unsigned) usageId
upOrDown:(BOOL)upOrDown;
@end

View File

@ -0,0 +1,160 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "AppleMikeyPaneController.h"
#import "DDHidLib.h"
#include <IOKit/hid/IOHIDUsageTables.h>
@implementation AppleMikeyPaneController
- (id) init;
{
self = [super init];
if (self == nil)
return nil;
mEvents = [[NSMutableArray alloc] init];
return self;
}
- (void) awakeFromNib;
{
NSArray * mikeys = [DDHidAppleMikey allMikeys];
[mikeys makeObjectsPerformSelector: @selector(setDelegate:)
withObject: self];
[self setMikeys: mikeys];
if ([mikeys count] > 0)
[self setMikeyIndex: 0];
else
[self setMikeyIndex: NSNotFound];
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mMikeys release];
[mEvents release];
mMikeys = nil;
mEvents = nil;
[super dealloc];
}
//===========================================================
// mikeys
//===========================================================
- (NSArray *) mikeys
{
return mMikeys;
}
- (void) setMikeys: (NSArray *) theMikeys
{
if (mMikeys != theMikeys)
{
[mMikeys release];
mMikeys = [theMikeys retain];
}
}
//===========================================================
// mikeyIndex
//===========================================================
- (NSUInteger) mikeyIndex
{
return mMikeyIndex;
}
- (void) setMikeyIndex: (NSUInteger) theMikeyIndex
{
if (mCurrentMikey != nil)
{
[mCurrentMikey stopListening];
mCurrentMikey = nil;
}
mMikeyIndex = theMikeyIndex;
[mMikeysController setSelectionIndex: mMikeyIndex];
[self willChangeValueForKey: @"events"];
[mEvents removeAllObjects];
[self didChangeValueForKey: @"events"];
if (mMikeyIndex != NSNotFound)
{
mCurrentMikey = [mMikeys objectAtIndex: mMikeyIndex];
[mCurrentMikey startListening];
}
}
//===========================================================
// events
//===========================================================
- (NSMutableArray *) events
{
return mEvents;
}
- (void) setEvents: (NSMutableArray *) theEvents
{
if (mEvents != theEvents)
{
[mEvents release];
mEvents = [theEvents retain];
}
}
- (void) addEvent: (id)theEvent
{
[[self events] addObject: theEvent];
}
- (void) removeEvent: (id)theEvent
{
[[self events] removeObject: theEvent];
}
@end
@implementation AppleMikeyPaneController (DDHidAppleMikeyDelegate)
- (void) ddhidAppleMikey:(DDHidAppleMikey *)mikey press:(unsigned int)usageId upOrDown:(BOOL)upOrDown
{
NSString *usage = nil;
if(usageId==kHIDUsage_GD_SystemMenuDown) {
usage = @"MenuDown";
}
else if(usageId == kHIDUsage_GD_SystemMenuUp) {
usage = @"MenuUp";
}
if(!usage)
return;
NSMutableDictionary * row = [[mMikeysEventsController newObject] autorelease];
[row setObject: upOrDown ? @"Down" : @"Up" forKey: @"event"];
[row setObject:usage forKey: @"description"];
[mMikeysEventsController addObject: row];
}
@end

Binary file not shown.

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidLib.h"
@class DDHidAppleRemote;
@class RemoteFeedbackView;
@interface AppleRemotePaneController : NSObject
{
IBOutlet NSButton * mStartStopButton;
IBOutlet RemoteFeedbackView * mFeedbackView;
IBOutlet NSTextField * mFeedbackText;
DDHidAppleRemote * mRemote;
BOOL mOpenInExclusiveMode;
}
- (DDHidAppleRemote *) remote;
- (IBAction) toggleListening: (id) sender;
- (BOOL) openInExclusiveMode;
- (void) setOpenInExclusiveMode: (BOOL) flag;
- (void) ddhidAppleRemoteButton: (DDHidAppleRemoteEventIdentifier) buttonIdentifier
pressedDown: (BOOL) pressedDown;
@end

View File

@ -0,0 +1,145 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "AppleRemotePaneController.h"
#import "RemoteFeedbackView.h"
@implementation AppleRemotePaneController
- (void) awakeFromNib;
{
[self willChangeValueForKey: @"remote"];
mRemote = [[DDHidAppleRemote firstRemote] retain];
[self didChangeValueForKey: @"remote"];
[mRemote setDelegate: self];
[self setOpenInExclusiveMode: YES];
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mRemote release];
mRemote = nil;
[super dealloc];
}
- (DDHidAppleRemote *) remote;
{
return mRemote;
}
- (IBAction) toggleListening: (id) sender;
{
NSAssert(mRemote != nil, @"Remote is nil");
if ([mRemote isListening])
{
[mRemote stopListening];
[mStartStopButton setTitle: @"Start Listening"];
}
else
{
[mRemote setListenInExclusiveMode: mOpenInExclusiveMode];
[mRemote startListening];
[mStartStopButton setTitle: @"Stop Listening"];
}
}
//===========================================================
// openInExclusiveMode
//===========================================================
- (BOOL) openInExclusiveMode
{
return mOpenInExclusiveMode;
}
- (void) setOpenInExclusiveMode: (BOOL) flag
{
mOpenInExclusiveMode = flag;
}
- (void) ddhidAppleRemoteButton: (DDHidAppleRemoteEventIdentifier) buttonIdentifier
pressedDown: (BOOL) pressedDown;
{
NSString * buttonName= nil;
NSString * pressed = @"";
switch(buttonIdentifier)
{
case kDDHidRemoteButtonVolume_Plus:
buttonName = @"Volume up";
if (pressedDown) pressed = @"(down)"; else pressed = @"(up)";
break;
case kDDHidRemoteButtonVolume_Minus:
buttonName = @"Volume down";
if (pressedDown) pressed = @"(down)"; else pressed = @"(up)";
break;
case kDDHidRemoteButtonMenu:
buttonName = @"Menu";
break;
case kDDHidRemoteButtonPlay:
buttonName = @"Play";
break;
case kDDHidRemoteButtonRight:
buttonName = @"Right";
break;
case kDDHidRemoteButtonLeft:
buttonName = @"Left";
break;
case kDDHidRemoteButtonRight_Hold:
buttonName = @"Right holding";
if (pressedDown) pressed = @"(down)"; else pressed = @"(up)";
break;
case kDDHidRemoteButtonLeft_Hold:
buttonName = @"Left holding";
if (pressedDown) pressed = @"(down)"; else pressed = @"(up)";
break;
case kDDHidRemoteButtonPlay_Sleep:
buttonName = @"Play (sleep mode)";
break;
case kDDHidRemoteButtonMenu_Hold:
buttonName = @"Menu (long)";
break;
case kDDHidRemoteControl_Switched:
buttonName = @"Remote Control Switched";
break;
case kDDHidRemoteControl_Paired:
buttonName = @"Remote Control Paired";
break;
default:
NSLog(@"Unmapped event for button %d", buttonIdentifier);
break;
}
[mFeedbackText setStringValue:[NSString stringWithFormat:@"%@ %@",
buttonName, pressed]];
[mFeedbackView ddhidAppleRemoteButton: buttonIdentifier
pressedDown: pressedDown];
}
@end

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@interface BoolFormatter : NSFormatter
{
id labels;
}
- (id)initWithLables:(id)_l;
@end

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "BoolFormatter.h"
@implementation BoolFormatter
- (id)initWithLables:(id)_l {
if ((self = [super init]) != nil) {
self->labels = [_l retain];
}
return self;
}
- (void)dealloc {
[self->labels release];
[super dealloc];
}
- (BOOL) boolForObjectValue: (id) object
{
BOOL result;
if ([object respondsToSelector: @selector(boolValue)])
result = [object boolValue] ? YES : NO;
else
result = NO;
return result;
}
- (NSString *)stringForObjectValue:(id)_obj
{
NSString *str;
if ([self boolForObjectValue: _obj])
str = @"Yes";
else
str = @"No";
return (self->labels != nil)
? (NSString *)[self->labels valueForKey:str] : str;
}
- (NSAttributedString *)attributedStringForObjectValue:(id)anObject
withDefaultAttributes:(NSDictionary *)defaultAttributes
{
NSDictionary * yesAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSColor redColor], NSBackgroundColorAttributeName,
nil];
NSDictionary * attributes = defaultAttributes;
if ([self boolForObjectValue: anObject])
attributes = yesAttributes;
NSAttributedString * string =
[[NSAttributedString alloc] initWithString: [self stringForObjectValue: anObject]
attributes: attributes];
[string autorelease];
return string;
}
@end

39
device_test/ButtonState.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@interface ButtonState : NSObject
{
NSString * mName;
BOOL mPressed;
}
- (id) initWithName: (NSString *) name;
- (NSString *) name;
- (BOOL) pressed;
- (void) setPressed: (BOOL) flag;
@end

77
device_test/ButtonState.m Normal file
View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "ButtonState.h"
@implementation ButtonState
- (id) initWithName: (NSString *) name
{
self = [super init];
if (self == nil)
return nil;
mName = [name retain];
mPressed = NO;
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mName release];
mName = nil;
[super dealloc];
}
//===========================================================
// - name
//===========================================================
- (NSString *) name
{
return mName;
}
//===========================================================
// - pressed
//===========================================================
- (BOOL) pressed
{
return mPressed;
}
//===========================================================
// - setPressed:
//===========================================================
- (void) setPressed: (BOOL) flag
{
mPressed = flag;
}
@end

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@class MousePaneController;
@interface DeviceTestController : NSObject
{
IBOutlet NSWindow * mWindow;
IBOutlet MousePaneController * mMousePaneController;
}
@end

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DeviceTestController.h"
static BOOL sSleepAtExit = NO;
static void exit_sleeper()
{
while (sSleepAtExit) sleep(60);
}
@implementation DeviceTestController
- (void) awakeFromNib
{
sSleepAtExit = [[NSUserDefaults standardUserDefaults] boolForKey: @"SleepAtExit"];
atexit(exit_sleeper);
[mWindow center];
[mWindow makeKeyAndOrderFront: self];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
{
return YES;
}
@end

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

26
device_test/Info.plist Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.dribin.dave.ddhidlib.HIDDeviceTest</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>CFBundleShortVersionString</key>
<string>${CURRENT_MARKETING_VERSION}</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidLib.h"
@interface JoystickPaneController : NSObject
{
IBOutlet NSArrayController * mJoysticksController;
NSArray * mJoysticks;
NSMutableArray * mJoystickButtons;
int mXAxis;
int mYAxis;
NSUInteger mJoystickIndex;
// Don't retain these
DDHidJoystick * mCurrentJoystick;
}
- (NSArray *) joysticks;
- (NSArray *) joystickButtons;
- (NSUInteger) joystickIndex;
- (void) setJoystickIndex: (NSUInteger) theJoystickIndex;
- (int) xAxis;
- (int) yAxis;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
xChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
yChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
otherAxis: (unsigned) otherAxis
valueChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonDown: (unsigned) buttonNumber;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonUp: (unsigned) buttonNumber;
@end

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "JoystickPaneController.h"
#import "DDHidJoystick.h"
#import "ButtonState.h"
@interface JoystickPaneController (Private)
- (void) setJoysticks: (NSArray *) theJoysticks;
@end
@implementation JoystickPaneController
- (void) awakeFromNib;
{
NSArray * joysticks = [DDHidJoystick allJoysticks];
mJoystickButtons = [[NSMutableArray alloc] init];
[joysticks makeObjectsPerformSelector: @selector(setDelegate:)
withObject: self];
[self setJoysticks: joysticks];
if ([mJoysticks count] > 0)
[self setJoystickIndex: 0];
else
[self setJoystickIndex: NSNotFound];
}
//===========================================================
// joysticks
//===========================================================
- (NSArray *) joysticks
{
return mJoysticks;
}
- (NSArray *) joystickButtons;
{
return mJoystickButtons;
}
//===========================================================
// joystickIndex
//===========================================================
- (NSUInteger) joystickIndex
{
return mJoystickIndex;
}
- (void) setJoystickIndex: (NSUInteger) theJoystickIndex
{
if (mCurrentJoystick != nil)
{
[mCurrentJoystick stopListening];
mCurrentJoystick = nil;
}
mJoystickIndex = theJoystickIndex;
[mJoysticksController setSelectionIndex: mJoystickIndex];
if (mJoystickIndex != NSNotFound)
{
mCurrentJoystick = [mJoysticks objectAtIndex: mJoystickIndex];
[mCurrentJoystick startListening];
[self willChangeValueForKey: @"joystickButtons"];
[mJoystickButtons removeAllObjects];
NSArray * buttons = [mCurrentJoystick buttonElements];
NSEnumerator * e = [buttons objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
ButtonState * state = [[ButtonState alloc] initWithName: [[element usage] usageName]];
[state autorelease];
[mJoystickButtons addObject: state];
}
[self didChangeValueForKey: @"joystickButtons"];
}
}
- (int) xAxis;
{
return mXAxis;
}
- (int) yAxis;
{
return mYAxis;
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
xChanged: (int) value;
{
[self willChangeValueForKey: @"xAxis"];
mXAxis = value;
[self didChangeValueForKey: @"xAxis"];
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
yChanged: (int) value;
{
[self willChangeValueForKey: @"yAxis"];
mYAxis = value;
[self didChangeValueForKey: @"yAxis"];
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
otherAxis: (unsigned) otherAxis
valueChanged: (int) value;
{
// Somehow display values here
NSLog(@"Stick: %d, other axis: %d, changed: %d", stick, otherAxis, value);
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
povNumber: (unsigned) povNumber
valueChanged: (int) value;
{
// Somehow display values here
NSLog(@"Stick: %d, POV number: %d, changed: %d", stick, povNumber, value);
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonDown: (unsigned) buttonNumber;
{
ButtonState * state = [mJoystickButtons objectAtIndex: buttonNumber];
[state setPressed: YES];
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonUp: (unsigned) buttonNumber;
{
ButtonState * state = [mJoystickButtons objectAtIndex: buttonNumber];
[state setPressed: NO];
}
@end
@implementation JoystickPaneController (Private)
- (void) setJoysticks: (NSArray *) theJoysticks
{
if (mJoysticks != theJoysticks)
{
[mJoysticks release];
mJoysticks = [theJoysticks retain];
}
}
@end

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@class DDHidKeyboard;
@interface KeyboardPaneController : NSObject
{
IBOutlet NSArrayController * mKeyboardsController;
IBOutlet NSArrayController * mKeyboardEventsController;
NSArray * mKeyboards;
NSUInteger mKeyboardIndex;
NSMutableArray * mEvents;
// Don't retain these
DDHidKeyboard * mCurrentKeyboard;
}
- (NSArray *) keyboards;
- (void) setKeyboards: (NSArray *) theKeyboards;
- (NSUInteger) keyboardIndex;
- (void) setKeyboardIndex: (NSUInteger) theKeyboardIndex;
- (NSMutableArray *) events;
- (void) setEvents: (NSMutableArray *) theEvents;
- (void) addEvent: (id)theEvent;
- (void) removeEvent: (id)theEvent;
@end
@interface KeyboardPaneController (DDHidKeyboardDelegate)
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyDown: (unsigned) usageId;
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyUp: (unsigned) usageId;
@end

View File

@ -0,0 +1,179 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "KeyboardPaneController.h"
#import "DDHidLib.h"
#include <IOKit/hid/IOHIDUsageTables.h>
@interface KeyboardPaneController (Private)
- (void) addEvent: (NSString *) event usageId: (unsigned) usageId;
@end
@implementation KeyboardPaneController
- (id) init;
{
self = [super init];
if (self == nil)
return nil;
mEvents = [[NSMutableArray alloc] init];
return self;
}
- (void) awakeFromNib;
{
NSArray * keyboards = [DDHidKeyboard allKeyboards];
[keyboards makeObjectsPerformSelector: @selector(setDelegate:)
withObject: self];
[self setKeyboards: keyboards];
if ([keyboards count] > 0)
[self setKeyboardIndex: 0];
else
[self setKeyboardIndex: NSNotFound];
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mKeyboards release];
[mEvents release];
mKeyboards = nil;
mEvents = nil;
[super dealloc];
}
//===========================================================
// keyboards
//===========================================================
- (NSArray *) keyboards
{
return mKeyboards;
}
- (void) setKeyboards: (NSArray *) theKeyboards
{
if (mKeyboards != theKeyboards)
{
[mKeyboards release];
mKeyboards = [theKeyboards retain];
}
}
//===========================================================
// keyboardIndex
//===========================================================
- (NSUInteger) keyboardIndex
{
return mKeyboardIndex;
}
- (void) setKeyboardIndex: (NSUInteger) theKeyboardIndex
{
if (mCurrentKeyboard != nil)
{
[mCurrentKeyboard stopListening];
mCurrentKeyboard = nil;
}
mKeyboardIndex = theKeyboardIndex;
[mKeyboardsController setSelectionIndex: mKeyboardIndex];
[self willChangeValueForKey: @"events"];
[mEvents removeAllObjects];
[self didChangeValueForKey: @"events"];
if (mKeyboardIndex != NSNotFound)
{
mCurrentKeyboard = [mKeyboards objectAtIndex: mKeyboardIndex];
[mCurrentKeyboard startListening];
}
}
//===========================================================
// events
//===========================================================
- (NSMutableArray *) events
{
return mEvents;
}
- (void) setEvents: (NSMutableArray *) theEvents
{
if (mEvents != theEvents)
{
[mEvents release];
mEvents = [theEvents retain];
}
}
- (void) addEvent: (id)theEvent
{
[[self events] addObject: theEvent];
}
- (void) removeEvent: (id)theEvent
{
[[self events] removeObject: theEvent];
}
@end
@implementation KeyboardPaneController (DDHidKeyboardDelegate)
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyDown: (unsigned) usageId;
{
[self addEvent: @"Key Down" usageId: usageId];
}
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyUp: (unsigned) usageId;
{
[self addEvent: @"Key Up" usageId: usageId];
}
@end
@implementation KeyboardPaneController (Private)
- (void) addEvent: (NSString *) event usageId: (unsigned) usageId;
{
DDHidUsageTables * usageTables = [DDHidUsageTables standardUsageTables];
NSString * description = [NSString stringWithFormat: @"%@ (0x%04X)",
[usageTables descriptionForUsagePage: kHIDPage_KeyboardOrKeypad
usage: usageId],
usageId];
NSMutableDictionary * row = [[mKeyboardEventsController newObject] autorelease];
[row setObject: event forKey: @"event"];
[row setObject: description forKey: @"description"];
[mKeyboardEventsController addObject: row];
}
@end

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@class DDHidQueue;
@class DDHidMouse;
@interface MousePaneController : NSObject
{
IBOutlet NSArrayController * mMiceController;
NSArray * mMice;
DDHidMouse * mCurrentMouse;
NSUInteger mMouseIndex;
int mMouseX;
int mMouseY;
int mMouseWheel;
NSMutableArray * mMouseButtons;
}
- (BOOL) no;
- (NSArray *) mice;
- (void) setMice: (NSArray *) newMice;
- (NSArray *) mouseButtons;
- (NSUInteger) mouseIndex;
- (void) setMouseIndex: (NSUInteger) theMouseIndex;
- (int) maxValue;
- (int) mouseX;
- (int) mouseY;
- (int) mouseWheel;
- (void) ddhidMouse: (DDHidMouse *) mouse xChanged: (SInt32) deltaX;
- (void) ddhidMouse: (DDHidMouse *) mouse yChanged: (SInt32) deltaY;
- (void) ddhidMouse: (DDHidMouse *) mouse wheelChanged: (SInt32) deltaWheel;
- (void) ddhidMouse: (DDHidMouse *) mouse buttonDown: (unsigned) buttonNumber;
- (void) ddhidMouse: (DDHidMouse *) mouse buttonUp: (unsigned) buttonNumber;
@end

View File

@ -0,0 +1,211 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "MousePaneController.h"
#import "DDHidLib.h"
#import "ButtonState.h"
@interface MousePaneController (Private)
- (void) setMouseX: (int) mouseX;
- (void) setMouseY: (int) mouseY;
- (void) setMouseWheel: (int) mouseWheel;
@end
@implementation MousePaneController
static int sMaxValue = 2500;
static int applyDelta(int current, int delta)
{
int newValue = (current + delta) % sMaxValue;
if (newValue < 0)
newValue = sMaxValue + newValue;
return newValue;
}
- (void) awakeFromNib;
{
mCurrentMouse = 0;
mMouseButtons = [[NSMutableArray alloc] init];
NSArray * mice = [DDHidMouse allMice];
[mice makeObjectsPerformSelector: @selector(setDelegate:)
withObject: self];
[self setMice: mice];
[self setMouseIndex: 0];
}
//===========================================================
// mice
//===========================================================
- (NSArray *) mice
{
return mMice;
}
- (void) setMice: (NSArray *) theMice
{
if (mMice != theMice)
{
[mMice release];
mMice = [theMice retain];
}
}
- (NSArray *) mouseButtons;
{
return mMouseButtons;
}
- (BOOL) no;
{
return NO;
}
//===========================================================
// - mouseIndex
//===========================================================
- (NSUInteger) mouseIndex
{
return mMouseIndex;
}
//===========================================================
// - setMouseIndex:
//===========================================================
- (void) setMouseIndex: (NSUInteger) theMouseIndex
{
if (mCurrentMouse != nil)
{
[mCurrentMouse stopListening];
mCurrentMouse = nil;
}
mMouseIndex = theMouseIndex;
[mMiceController setSelectionIndex: mMouseIndex];
if (mMouseIndex != NSNotFound)
{
mCurrentMouse = [mMice objectAtIndex: mMouseIndex];
[mCurrentMouse startListening];
[self setMouseX: sMaxValue/2];
[self setMouseY: sMaxValue/2];
[self setMouseWheel: sMaxValue/2];
[self willChangeValueForKey: @"mouseButtons"];
[mMouseButtons removeAllObjects];
NSArray * buttons = [mCurrentMouse buttonElements];
NSEnumerator * e = [buttons objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
ButtonState * state = [[ButtonState alloc] initWithName: [[element usage] usageName]];
[state autorelease];
[mMouseButtons addObject: state];
}
[self didChangeValueForKey: @"mouseButtons"];
}
}
- (int) maxValue;
{
return sMaxValue;
}
//===========================================================
// - mouseX
//===========================================================
- (int) mouseX
{
return mMouseX;
}
//===========================================================
// - mouseY
//===========================================================
- (int) mouseY
{
return mMouseY;
}
//===========================================================
// - mouseWheel
//===========================================================
- (int) mouseWheel
{
return mMouseWheel;
}
- (void) ddhidMouse: (DDHidMouse *) mouse xChanged: (SInt32) deltaX;
{
[self setMouseX: applyDelta(mMouseX, deltaX)];
}
- (void) ddhidMouse: (DDHidMouse *) mouse yChanged: (SInt32) deltaY;
{
[self setMouseY: applyDelta(mMouseY, deltaY)];
}
- (void) ddhidMouse: (DDHidMouse *) mouse wheelChanged: (SInt32) deltaWheel;
{
// Some wheels only output -1 or +1, some output a more analog value.
// Normalize wheel to -1%/+1% movement.
deltaWheel = (deltaWheel/abs(deltaWheel))*(sMaxValue/100);
[self setMouseWheel: applyDelta(mMouseWheel, deltaWheel)];
}
- (void) ddhidMouse: (DDHidMouse *) mouse buttonDown: (unsigned) buttonNumber;
{
ButtonState * state = [mMouseButtons objectAtIndex: buttonNumber];
[state setPressed: YES];
}
- (void) ddhidMouse: (DDHidMouse *) mouse buttonUp: (unsigned) buttonNumber;
{
ButtonState * state = [mMouseButtons objectAtIndex: buttonNumber];
[state setPressed: NO];
}
@end
@implementation MousePaneController (Private)
- (void) setMouseX: (int) mouseX;
{
mMouseX = mouseX;
}
- (void) setMouseY: (int) mouseY;
{
mMouseY = mouseY;
}
- (void) setMouseWheel: (int) mouseWheel;
{
mMouseWheel = mouseWheel;
}
@end

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// Based on Martin Kahr's Apple Remote wrapper
// http://www.martinkahr.com/source-code/
#import <Cocoa/Cocoa.h>
#import "DDHidAppleRemote.h"
@interface RemoteFeedbackView : NSView
{
NSImage* remoteImage;
DDHidAppleRemoteEventIdentifier lastButtonIdentifier;
BOOL drawn;
BOOL clearAfterDraw;
}
- (void) ddhidAppleRemoteButton: (DDHidAppleRemoteEventIdentifier)buttonIdentifier
pressedDown: (BOOL) pressedDown;
@end

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// Based on Martin Kahr's Apple Remote wrapper
// http://www.martinkahr.com/source-code/
#import "RemoteFeedbackView.h"
@implementation RemoteFeedbackView
- (id)initWithFrame:(NSRect)frameRect
{
if ((self = [super initWithFrame:frameRect]) != nil) {
remoteImage = [[NSImage imageNamed:@"AppleRemote"] retain];
lastButtonIdentifier = -1;
}
return self;
}
- (void) dealloc {
[remoteImage release];
[super dealloc];
}
- (void) clearAfterRedraw: (id) sender
{
clearAfterDraw = NO;
[self ddhidAppleRemoteButton: lastButtonIdentifier pressedDown: NO];
}
- (void) ddhidAppleRemoteButton: (DDHidAppleRemoteEventIdentifier)buttonIdentifier
pressedDown: (BOOL) pressedDown;
{
clearAfterDraw = NO;
if (pressedDown) {
lastButtonIdentifier = buttonIdentifier;
} else {
if (drawn)
lastButtonIdentifier = -1;
else {
lastButtonIdentifier = buttonIdentifier;
clearAfterDraw = YES;
}
}
drawn = NO;
[self setNeedsDisplay:YES];
}
- (void)drawRect:(NSRect)rect
{
drawn = YES;
NSRect imageRect;
NSRect drawingRect;
imageRect.origin = NSZeroPoint;
imageRect.size = [remoteImage size];
int x = ([self bounds].size.width - [remoteImage size].width)/2;
int y = ([self bounds].size.height - [remoteImage size].height)/2;
drawingRect.origin = NSMakePoint(x, y);
drawingRect.size = imageRect.size;
[remoteImage drawInRect: drawingRect
fromRect: imageRect
operation: NSCompositeSourceOver
fraction: 1.0];
if (lastButtonIdentifier == -1) {
return;
}
DDHidAppleRemoteEventIdentifier buttonToSelect = lastButtonIdentifier;
NSPoint buttonPos = NSZeroPoint;
float opacity = 0.5;
switch(buttonToSelect) {
case kDDHidRemoteButtonVolume_Plus:
buttonPos.x = 53;
buttonPos.y = 240;
break;
case kDDHidRemoteButtonVolume_Minus:
buttonPos.x = 53;
buttonPos.y = 180;
break;
case kDDHidRemoteButtonMenu_Hold:
opacity = 0.8;
case kDDHidRemoteButtonMenu:
buttonPos.x = 53;
buttonPos.y = 137;
clearAfterDraw = YES;
break;
case kDDHidRemoteButtonPlay_Sleep:
opacity = 0.8;
case kDDHidRemoteButtonPlay:
buttonPos.x = 53;
buttonPos.y = 210;
clearAfterDraw = YES;
break;
case kDDHidRemoteButtonRight_Hold:
opacity = 0.8;
buttonPos.x = 83;
buttonPos.y = 210;
break;
case kDDHidRemoteButtonRight:
buttonPos.x = 83;
buttonPos.y = 210;
clearAfterDraw = YES;
break;
case kDDHidRemoteButtonLeft_Hold:
opacity = 0.8;
buttonPos.x = 23;
buttonPos.y = 210;
break;
case kDDHidRemoteButtonLeft:
buttonPos.x = 23;
buttonPos.y = 210;
clearAfterDraw = YES;
break;
default:
break;
}
float width = 20.0;
float height= 20.0;
NSRect r = NSMakeRect(buttonPos.x + x - (width/2), buttonPos.y + y - (height/2), width, height);
NSBezierPath* bp = [NSBezierPath bezierPathWithOvalInRect:r];
[[NSColor colorWithCalibratedRed:1.0 green:0.0 blue:0.0 alpha:opacity] set];
[bp fill];
if (clearAfterDraw) {
[self performSelector:@selector(clearAfterRedraw:) withObject:self afterDelay:0.1];
}
}
@end

30
device_test/main.m Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **) argv);
}

23
header.c Normal file
View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

66
lib/DDHidAppleMikey.h Normal file
View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidDevice.h"
@class DDHidElement;
@class DDHidQueue;
@interface DDHidAppleMikey : DDHidDevice
{
NSMutableArray * mPressElements;
id mDelegate;
}
+ (NSArray *) allMikeys;
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
#pragma mark -
#pragma mark Elements
- (NSArray *) pressElements;
- (unsigned) numberOfKeys;
- (void) addElementsToQueue: (DDHidQueue *) queue;
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
- (void) addElementsToDefaultQueue;
@end
@interface NSObject (DDHidAppleMikeyDelegate)
- (void) ddhidAppleMikey: (DDHidAppleMikey *) mikey
press: (unsigned) usageId
upOrDown:(BOOL)upOrDown;
@end

164
lib/DDHidAppleMikey.m Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidAppleMikey.h"
#import "DDHidElement.h"
#import "DDHidUsage.h"
#import "DDHidQueue.h"
#import "DDHidEvent.h"
#include <IOKit/hid/IOHIDUsageTables.h>
#define APPLE_MIC_ONLY 1
@interface DDHidAppleMikey (DDHidAppleMikeyDelegate)
- (void) ddhidAppleMikey: (DDHidAppleMikey *) mikey
press: (unsigned) usageId
upOrDown:(BOOL)upOrDown;
@end
@interface DDHidAppleMikey (Private)
- (void) initPressElements: (NSArray *) elements;
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
@end
@implementation DDHidAppleMikey
+ (NSArray *) allMikeys;
{
//add mikeys
id a2 = [self allDevicesMatchingUsagePage:12 usageId:1 withClass:self skipZeroLocations:NO];
#if APPLE_MIC_ONLY
a2 = [a2 filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"productName == \"Apple Mikey HID Driver\""]];
#endif
return a2;
}
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
{
self = [super initWithDevice: device error: error_];
if (self == nil)
return nil;
mPressElements = [[NSMutableArray alloc] init];
[self initPressElements: [self elements]];
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mPressElements release];
mPressElements = nil;
[super dealloc];
}
#pragma mark -
#pragma mark Elements
- (NSArray *) pressElements;
{
return mPressElements;
}
- (unsigned) numberOfKeys;
{
return [mPressElements count];
}
- (void) addElementsToQueue: (DDHidQueue *) queue;
{
[queue addElements: mPressElements];
}
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
{
mDelegate = delegate;
}
- (void) addElementsToDefaultQueue;
{
[self addElementsToQueue: mDefaultQueue];
}
@end
@implementation DDHidAppleMikey (DDHidAppleMikeyDelegate)
- (void) ddhidAppleMikey:(DDHidAppleMikey *)mikey press:(unsigned int)usageId upOrDown:(BOOL)upOrDown
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidAppleMikey: mikey press: usageId upOrDown:(BOOL)upOrDown];
}
@end
@implementation DDHidAppleMikey (Private)
- (void) initPressElements: (NSArray *) elements;
{
NSEnumerator * e = [elements objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
// unsigned usagePage = [[element usage] usagePage];
// unsigned usageId = [[element usage] usageId];
// if (usagePage == kHIDPage_KeyboardOrKeypad)
// {
// if ((usageId >= 0x04) && (usageId <= 0xA4) ||
// (usageId >= 0xE0) && (usageId <= 0xE7))
{
[mPressElements addObject: element];
}
// }
NSArray * subElements = [element elements];
if (subElements != nil)
[self initPressElements: subElements];
}
}
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
{
DDHidEvent * event;
while ((event = [hidQueue nextEvent]))
{
DDHidElement * element = [self elementForCookie: [event elementCookie]];
unsigned usageId = [[element usage] usageId];
SInt32 value = [event value];
[self ddhidAppleMikey:self press:usageId upOrDown:value==1];
}
}
@end

84
lib/DDHidAppleRemote.h Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidDevice.h"
@class DDHidElement;
enum DDHidAppleRemoteEventIdentifier
{
kDDHidRemoteButtonVolume_Plus=0,
kDDHidRemoteButtonVolume_Minus,
kDDHidRemoteButtonMenu,
kDDHidRemoteButtonPlay,
kDDHidRemoteButtonRight,
kDDHidRemoteButtonLeft,
kDDHidRemoteButtonRight_Hold,
kDDHidRemoteButtonLeft_Hold,
kDDHidRemoteButtonMenu_Hold,
kDDHidRemoteButtonPlay_Sleep,
kDDHidRemoteControl_Switched,
kDDHidRemoteControl_Paired,
};
typedef enum DDHidAppleRemoteEventIdentifier DDHidAppleRemoteEventIdentifier;
@interface DDHidAppleRemote : DDHidDevice
{
NSMutableDictionary * mCookieToButtonMapping;
NSArray * mButtonElements;
DDHidElement * mIdElement;
int mRemoteId;
id mDelegate;
}
+ (NSArray *) allRemotes;
+ (DDHidAppleRemote *) firstRemote;
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
- (void) addElementsToDefaultQueue;
#pragma mark -
#pragma mark Properties
- (int) remoteId;
- (void) setRemoteId: (int) theRemoteId;
@end
@interface NSObject (DDHidAppleRemoteDelegate)
- (void) ddhidAppleRemoteButton: (DDHidAppleRemoteEventIdentifier) buttonIdentifier
pressedDown: (BOOL) pressedDown;
@end

236
lib/DDHidAppleRemote.m Normal file
View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// Based on Martin Kahr's Apple Remote wrapper
// http://www.martinkahr.com/source-code/
#import "DDHidAppleRemote.h"
#import "DDHidElement.h"
#import "DDHidUsage.h"
#import "DDHidQueue.h"
#import "DDHidEvent.h"
#import "NSDictionary+DDHidExtras.h"
@interface DDHidAppleRemote (Private)
- (void) initRemoteElements: (NSArray *) elements;
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
- (void) handleEventWithCookieString: (NSString*) cookieString
sumOfValues: (SInt32) sumOfValues;
@end
@implementation DDHidAppleRemote
+ (NSArray *) allRemotes;
{
CFMutableDictionaryRef hidMatchDictionary =
IOServiceMatching("AppleIRController");
return
[DDHidDevice allDevicesMatchingCFDictionary: hidMatchDictionary
withClass: self
skipZeroLocations: YES];
}
+ (DDHidAppleRemote *) firstRemote;
{
NSArray * allRemotes = [self allRemotes];
if ([allRemotes count] > 0)
return [allRemotes objectAtIndex: 0];
else
return nil;
}
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
{
self = [super initWithDevice: device error: error_];
if (self == nil)
return nil;
mCookieToButtonMapping = [[NSMutableDictionary alloc] init];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonVolume_Plus
forKey: @"14_12_11_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonVolume_Plus
forKey: @"31_29_28_19_18_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonVolume_Minus
forKey: @"14_13_11_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonVolume_Minus
forKey: @"31_30_28_19_18_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonMenu
forKey: @"14_7_6_5_14_7_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonMenu
forKey: @"31_20_19_18_31_20_19_18_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonPlay
forKey: @"14_8_6_5_14_8_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonPlay
forKey: @"31_21_19_18_31_21_19_18_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonRight
forKey: @"14_9_6_5_14_9_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonRight
forKey: @"31_22_19_18_31_22_19_18_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonLeft
forKey: @"14_10_6_5_14_10_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonLeft
forKey: @"31_23_19_18_31_23_19_18_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonRight_Hold
forKey: @"14_6_5_4_2_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonRight_Hold
forKey: @"31_19_18_4_2_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonLeft_Hold
forKey: @"14_6_5_3_2_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonLeft_Hold
forKey: @"31_19_18_3_2_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonMenu_Hold
forKey: @"14_6_5_14_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonMenu_Hold
forKey: @"31_19_18_31_19_18_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonPlay_Sleep
forKey: @"18_14_6_5_18_14_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteButtonPlay_Sleep
forKey: @"35_31_19_18_35_31_19_18_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteControl_Switched
forKey: @"19_"];
//[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteControl_Switched
// forKey: @"??_"]; // unknown for 10.5
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteControl_Paired
forKey: @"15_14_6_5_15_14_6_5_"];
[mCookieToButtonMapping ddhid_setInt: kDDHidRemoteControl_Paired
forKey: @"32_31_19_18_32_31_19_18_"];
[self initRemoteElements: [self elements]];
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mCookieToButtonMapping release];
[mButtonElements release];
[mIdElement release];
mCookieToButtonMapping = nil;
mButtonElements = nil;
mIdElement = nil;
[super dealloc];
}
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
{
mDelegate = delegate;
}
- (void) addElementsToDefaultQueue;
{
[mDefaultQueue addElements: mButtonElements];
}
#pragma mark -
#pragma mark Properties
//===========================================================
// remoteId
//===========================================================
- (int) remoteId
{
return mRemoteId;
}
- (void) setRemoteId: (int) theRemoteId
{
mRemoteId = theRemoteId;
}
@end
@implementation DDHidAppleRemote (Private)
- (void) initRemoteElements: (NSArray *) elements;
{
NSAssert([elements count] == 1, @"Assume only 1 top level remote element");
DDHidElement * consumerControlsElement = [elements objectAtIndex: 0];
mButtonElements = [[consumerControlsElement elements] retain];
DDHidElement * element;
NSEnumerator * e = [mButtonElements objectEnumerator];
while (element = [e nextObject])
{
if ([[element usage] isEqualToUsagePage: 0x0006
usageId: 0x0022])
{
mIdElement = [element retain];
}
}
}
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
{
NSMutableString * cookieString = [NSMutableString string];
SInt32 sumOfValues = 0;
DDHidEvent * event;
while ((event = [hidQueue nextEvent]))
{
if ([event elementCookie] == [mIdElement cookie])
{
[self setRemoteId: [event value]];
}
else
{
sumOfValues += [event value];
[cookieString appendString:
[NSString stringWithFormat: @"%u_", [event elementCookieAsUnsigned]]];
}
}
[self handleEventWithCookieString: cookieString sumOfValues: sumOfValues];
}
- (void) handleEventWithCookieString: (NSString*) cookieString
sumOfValues: (SInt32) sumOfValues;
{
NSNumber* buttonId = [mCookieToButtonMapping objectForKey: cookieString];
if (buttonId != nil)
{
if ([mDelegate respondsToSelector: @selector(ddhidAppleRemoteButton:pressedDown:)])
{
[mDelegate ddhidAppleRemoteButton: [buttonId intValue]
pressedDown: (sumOfValues>0)];
}
}
else
NSLog(@"Unknown button for cookiestring %@", cookieString);
}
@end

131
lib/DDHidDevice.h Normal file
View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/hid/IOHIDLib.h>
#include <IOKit/hid/IOHIDKeys.h>
@class DDHidUsage;
@class DDHidElement;
@class DDHidQueue;
@interface DDHidDevice : NSObject
{
io_object_t mHidDevice;
IOHIDDeviceInterface122** mDeviceInterface;
NSMutableDictionary * mProperties;
DDHidUsage * mPrimaryUsage;
NSMutableArray * mUsages;
NSArray * mElements;
NSMutableDictionary * mElementsByCookie;
BOOL mListenInExclusiveMode;
DDHidQueue * mDefaultQueue;
int mTag;
int mLogicalDeviceNumber;
}
- (id) initWithDevice: (io_object_t) device error: (NSError **) error;
- (id) initLogicalWithDevice: (io_object_t) device
logicalDeviceNumber: (int) logicalDeviceNumber
error: (NSError **) error;
- (int) logicalDeviceCount;
#pragma mark -
#pragma mark Finding Devices
+ (NSArray *) allDevices;
+ (NSArray *) allDevicesMatchingUsagePage: (unsigned) usagePage
usageId: (unsigned) usageId
withClass: (Class) hidClass
skipZeroLocations: (BOOL) emptyLocation;
+ (NSArray *) allDevicesMatchingCFDictionary: (CFDictionaryRef) matchDictionary
withClass: (Class) hidClass
skipZeroLocations: (BOOL) emptyLocation;
#pragma mark -
#pragma mark I/O Kit Objects
- (io_object_t) ioDevice;
- (IOHIDDeviceInterface122**) deviceInterface;
#pragma mark -
#pragma mark Operations
- (void) open;
- (void) openWithOptions: (UInt32) options;
- (void) close;
- (DDHidQueue *) createQueueWithSize: (unsigned) size;
- (long) getElementValue: (DDHidElement *) element;
#pragma mark -
#pragma mark Asynchronous Notification
- (BOOL) listenInExclusiveMode;
- (void) setListenInExclusiveMode: (BOOL) flag;
- (void) startListening;
- (void) stopListening;
- (BOOL) isListening;
#pragma mark -
#pragma mark Properties
- (NSDictionary *) properties;
- (NSArray *) elements;
- (DDHidElement *) elementForCookie: (IOHIDElementCookie) cookie;
- (NSString *) productName;
- (NSString *) manufacturer;
- (NSString *) serialNumber;
- (NSString *) transport;
- (long) vendorId;
- (long) productId;
- (long) version;
- (long) locationId;
- (long) usagePage;
- (long) usage;
- (DDHidUsage *) primaryUsage;
- (NSArray *) usages;
- (NSComparisonResult) compareByLocationId: (DDHidDevice *) device;
- (int) tag;
- (void) setTag: (int) theTag;
@end
@interface DDHidDevice (Protected)
- (unsigned) sizeOfDefaultQueue;
- (void) addElementsToDefaultQueue;
@end

595
lib/DDHidDevice.m Normal file
View File

@ -0,0 +1,595 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidDevice.h"
#import "DDHidUsage.h"
#import "DDHidElement.h"
#import "DDHidQueue.h"
#import "NSDictionary+DDHidExtras.h"
#import "NSXReturnThrowError.h"
#include <IOKit/hid/IOHIDUsageTables.h>
@interface DDHidDevice (Private)
+ (void) addDevice: (io_object_t) hidDevice
withClass: (Class) hidClass
skipZeroLocations: (BOOL) skipZeroLocations
toDeviceList: (NSMutableArray *) devices;
- (BOOL) initPropertiesWithError: (NSError **) error_;
- (BOOL) createDeviceInterfaceWithError: (NSError **) error_;
@end
@implementation DDHidDevice
- (id) initWithDevice: (io_object_t) device error: (NSError **) error;
{
return [self initLogicalWithDevice: device
logicalDeviceNumber: 0
error: error];
}
- (id) initLogicalWithDevice: (io_object_t) device
logicalDeviceNumber: (int) logicalDeviceNumber
error: (NSError **) error;
{
self = [super init];
if (self == nil)
return nil;
mHidDevice = device;
IOObjectRetain(mHidDevice);
if (![self initPropertiesWithError: error])
{
[self release];
return nil;
}
if (![self createDeviceInterfaceWithError: error])
{
[self release];
return nil;
}
mLogicalDeviceNumber = logicalDeviceNumber;
mListenInExclusiveMode = NO;
mDefaultQueue = nil;
mTag = 0;
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mDefaultQueue release];
if (mDeviceInterface != NULL)
{
(*mDeviceInterface)->close(mDeviceInterface);
(*mDeviceInterface)->Release(mDeviceInterface);
}
[mElementsByCookie release];
[mElements release];
[mUsages release];
[mPrimaryUsage release];
[mProperties release];
IOObjectRelease(mHidDevice);
mProperties = nil;
mDeviceInterface = NULL;
[super dealloc];
}
#pragma mark -
#pragma mark Finding Devices
+ (NSArray *) allDevices;
{
// Set up a matching dictionary to search the I/O Registry by class
// name for all HID class devices
CFMutableDictionaryRef hidMatchDictionary =
IOServiceMatching(kIOHIDDeviceKey);
id retVal = nil;
if(hidMatchDictionary) {
retVal = [self allDevicesMatchingCFDictionary: hidMatchDictionary
withClass: [DDHidDevice class]
skipZeroLocations: NO];
//CFRelease(hidMatchDictionary);//dont free, it is freed by IOServiceGetMatchingServices
}
return retVal;
}
+ (NSArray *) allDevicesMatchingUsagePage: (unsigned) usagePage
usageId: (unsigned) usageId
withClass: (Class) hidClass
skipZeroLocations: (BOOL) skipZeroLocations;
{
// Set up a matching dictionary to search the I/O Registry by class
// name for all HID class devices
CFMutableDictionaryRef hidMatchDictionary =
IOServiceMatching(kIOHIDDeviceKey);
id retVal = nil;
if(hidMatchDictionary) {
NSMutableDictionary * objcMatchDictionary =
(NSMutableDictionary *) hidMatchDictionary;
[objcMatchDictionary ddhid_setObject: [NSNumber numberWithUnsignedInt: usagePage]
forString: kIOHIDDeviceUsagePageKey];
[objcMatchDictionary ddhid_setObject: [NSNumber numberWithUnsignedInt: usageId]
forString: kIOHIDDeviceUsageKey];
retVal = [self allDevicesMatchingCFDictionary: hidMatchDictionary
withClass: hidClass
skipZeroLocations: skipZeroLocations];
//CFRelease(hidMatchDictionary);//dont free, it is freed by IOServiceGetMatchingServices
}
return retVal;
}
+ (NSArray *) allDevicesMatchingCFDictionary: (CFDictionaryRef) matchDictionary
withClass: (Class) hidClass
skipZeroLocations: (BOOL) skipZeroLocations;
{
// Now search I/O Registry for matching devices.
io_iterator_t hidObjectIterator = MACH_PORT_NULL;
NSMutableArray * devices = [NSMutableArray array];
@try
{
NSXThrowError(IOServiceGetMatchingServices(kIOMasterPortDefault,
matchDictionary,
&hidObjectIterator));
if (hidObjectIterator == 0)
return [NSArray array];
io_object_t hidDevice;
while ((hidDevice = IOIteratorNext(hidObjectIterator)))
{
[self addDevice: hidDevice
withClass: hidClass
skipZeroLocations: skipZeroLocations
toDeviceList: devices];
}
// This makes sure the array return is consistent from run to run,
// assuming no new devices were added.
[devices sortUsingSelector: @selector(compareByLocationId:)];
}
@finally
{
if (hidObjectIterator != MACH_PORT_NULL)
IOObjectRelease(hidObjectIterator);
}
return devices;
}
- (int) logicalDeviceCount;
{
return 1;
}
#pragma mark -
#pragma mark I/O Kit Objects
- (io_object_t) ioDevice;
{
return mHidDevice;
}
- (IOHIDDeviceInterface122**) deviceInterface;
{
return mDeviceInterface;
}
#pragma mark -
#pragma mark Operations
- (void) open;
{
[self openWithOptions: kIOHIDOptionsTypeNone];
}
- (void) openWithOptions: (UInt32) options;
{
NSXThrowError((*mDeviceInterface)->open(mDeviceInterface, options));
}
- (void) close;
{
NSXThrowError((*mDeviceInterface)->close(mDeviceInterface));
}
- (DDHidQueue *) createQueueWithSize: (unsigned) size;
{
IOHIDQueueInterface ** queue =
(*mDeviceInterface)->allocQueue(mDeviceInterface);
if (queue == NULL)
return nil;
return [[[DDHidQueue alloc] initWithHIDQueue: queue
size: size] autorelease];
}
- (long) getElementValue: (DDHidElement *) element;
{
IOHIDEventStruct event;
NSXThrowError((*mDeviceInterface)->getElementValue(mDeviceInterface,
[element cookie],
&event));
return event.value;
}
#pragma mark -
#pragma mark Asynchronous Notification
//===========================================================
// listenInExclusiveMode
//===========================================================
- (BOOL) listenInExclusiveMode
{
return mListenInExclusiveMode;
}
- (void) setListenInExclusiveMode: (BOOL) flag
{
mListenInExclusiveMode = flag;
}
- (void) startListening;
{
if ([self isListening])
return;
UInt32 options = kIOHIDOptionsTypeNone;
if (mListenInExclusiveMode)
options = kIOHIDOptionsTypeSeizeDevice;
[self openWithOptions: options];
mDefaultQueue = [[self createQueueWithSize: [self sizeOfDefaultQueue]] retain];
[mDefaultQueue setDelegate: self];
[self addElementsToDefaultQueue];
[mDefaultQueue startOnCurrentRunLoop];
}
- (void) stopListening;
{
if (![self isListening])
return;
[mDefaultQueue stop];
[mDefaultQueue release];
mDefaultQueue = nil;
[self close];
}
- (BOOL) isListening;
{
return (mDefaultQueue != nil);
}
#pragma mark -
#pragma mark Properties
- (NSDictionary *) properties;
{
return mProperties;
}
//===========================================================
// - productName
//===========================================================
- (NSString *) productName
{
NSString * productName = [mProperties ddhid_stringForString: kIOHIDProductKey];
if ([self logicalDeviceCount] > 1)
{
productName = [productName stringByAppendingString:
[NSString stringWithFormat:@" #%d", mLogicalDeviceNumber + 1]];
}
return productName;
}
//===========================================================
// - manufacturer
//===========================================================
- (NSString *) manufacturer
{
return [mProperties ddhid_stringForString: kIOHIDManufacturerKey];
}
//===========================================================
// - serialNumber
//===========================================================
- (NSString *) serialNumber
{
return [mProperties ddhid_stringForString: kIOHIDSerialNumberKey];
}
//===========================================================
// - transport
//===========================================================
- (NSString *) transport
{
return [mProperties ddhid_stringForString: kIOHIDTransportKey];
}
//===========================================================
// - vendorId
//===========================================================
- (long) vendorId
{
return [mProperties ddhid_longForString: kIOHIDVendorIDKey];
}
//===========================================================
// - productId
//===========================================================
- (long) productId
{
return [mProperties ddhid_longForString: kIOHIDProductIDKey];
}
//===========================================================
// - version
//===========================================================
- (long) version
{
return [mProperties ddhid_longForString: kIOHIDVersionNumberKey];
}
//===========================================================
// - locationId
//===========================================================
- (long) locationId
{
return [mProperties ddhid_longForString: kIOHIDLocationIDKey];
}
//===========================================================
// - usagePage
//===========================================================
- (long) usagePage
{
return [mProperties ddhid_longForString: kIOHIDPrimaryUsagePageKey];
}
//===========================================================
// - usage
//===========================================================
- (long) usage
{
return [mProperties ddhid_longForString: kIOHIDPrimaryUsageKey];
}
- (NSArray *) elements;
{
return mElements;
}
- (DDHidElement *) elementForCookie: (IOHIDElementCookie) cookie;
{
NSNumber * n = [NSNumber numberWithUnsignedInt: (unsigned) cookie];
return [mElementsByCookie objectForKey: n];
}
- (DDHidUsage *) primaryUsage;
{
return mPrimaryUsage;
}
- (NSArray *) usages;
{
return mUsages;
}
- (NSComparisonResult) compareByLocationId: (DDHidDevice *) device;
{
long myLocationId = [self locationId];
long otherLocationId = [device locationId];
if (myLocationId < otherLocationId)
return NSOrderedAscending;
else if (myLocationId > otherLocationId)
return NSOrderedDescending;
else
return NSOrderedSame;
}
//===========================================================
// tag
//===========================================================
- (int) tag
{
return mTag;
}
- (void) setTag: (int) theTag
{
mTag = theTag;
}
@end
@implementation DDHidDevice (Protected)
- (unsigned) sizeOfDefaultQueue;
{
return 10;
}
- (void) addElementsToDefaultQueue;
{
[mDefaultQueue addElements: [self elements] recursively: YES];
}
@end
@implementation DDHidDevice (Private)
+ (void) addDevice: (io_object_t) hidDevice
withClass: (Class) hidClass
skipZeroLocations: (BOOL) skipZeroLocations
toDeviceList: (NSMutableArray *) devices;
{
@try
{
NSError * error = nil;
DDHidDevice * device = [[hidClass alloc] initWithDevice: hidDevice
error: &error];
if (device == nil)
{
NSXRaiseError(error);
}
[device autorelease];
if (([device locationId] == 0) && skipZeroLocations)
return;
[devices addObject: device];
// Add remainnig logical devices
int i;
for (i = 1; i < [device logicalDeviceCount]; i++)
{
device = [[hidClass alloc] initLogicalWithDevice: hidDevice
logicalDeviceNumber: i
error: &error];
if (device == nil)
{
NSXRaiseError(error);
}
[device autorelease];
[devices addObject: device];
}
}
@finally
{
IOObjectRelease(hidDevice);
}
}
- (void) indexElements: (NSArray *) elements;
{
NSEnumerator * e = [elements objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
NSNumber * n = [NSNumber numberWithUnsignedInt: [element cookieAsUnsigned]];
[mElementsByCookie setObject: element
forKey: n];
NSArray * children = [element elements];
if (children != nil)
[self indexElements: children];
}
}
- (BOOL) initPropertiesWithError: (NSError **) error_;
{
NSError * error = nil;
BOOL result = NO;
CFMutableDictionaryRef properties;
NSXReturnError(IORegistryEntryCreateCFProperties(mHidDevice, &properties,
kCFAllocatorDefault, kNilOptions));
if (error)
goto done;
mProperties = (NSMutableDictionary *) properties;
NSArray * elementProperties = [mProperties ddhid_objectForString: kIOHIDElementKey];
mElements = [DDHidElement elementsWithPropertiesArray: elementProperties];
[mElements retain];
unsigned usagePage = [mProperties ddhid_unsignedIntForString: kIOHIDPrimaryUsagePageKey];
unsigned usageId = [mProperties ddhid_unsignedIntForString: kIOHIDPrimaryUsageKey];
mPrimaryUsage = [[DDHidUsage alloc] initWithUsagePage: usagePage
usageId: usageId];
mUsages = [[NSMutableArray alloc] init];
NSArray * usagePairs = [mProperties ddhid_objectForString: kIOHIDDeviceUsagePairsKey];
NSEnumerator * e = [usagePairs objectEnumerator];
NSDictionary * usagePair;
while (usagePair = [e nextObject])
{
usagePage = [usagePair ddhid_unsignedIntForString: kIOHIDDeviceUsagePageKey];
usageId = [usagePair ddhid_unsignedIntForString: kIOHIDDeviceUsageKey];
DDHidUsage * usage = [DDHidUsage usageWithUsagePage: usagePage
usageId: usageId];
[mUsages addObject: usage];
}
mElementsByCookie = [[NSMutableDictionary alloc] init];
[self indexElements: mElements];
result = YES;
done:
if (error_)
*error_ = error;
return result;
}
- (BOOL) createDeviceInterfaceWithError: (NSError **) error_;
{
io_name_t className;
IOCFPlugInInterface ** plugInInterface = NULL;
SInt32 score = 0;
NSError * error = nil;
BOOL result = NO;
mDeviceInterface = NULL;
NSXReturnError(IOObjectGetClass(mHidDevice, className));
if (error)
goto done;
NSXReturnError(IOCreatePlugInInterfaceForService(mHidDevice,
kIOHIDDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterface,
&score));
if (error)
goto done;
//Call a method of the intermediate plug-in to create the device interface
NSXReturnError((*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (LPVOID) &mDeviceInterface));
if (error)
goto done;
result = YES;
done:
if (plugInInterface != NULL)
{
(*plugInInterface)->Release(plugInInterface);
}
if (error_)
*error_ = error;
return result;
}
@end

65
lib/DDHidElement.h Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#include <IOKit/hid/IOHIDKeys.h>
@class DDHidUsage;
@interface DDHidElement : NSObject
{
NSDictionary * mProperties;
DDHidUsage * mUsage;
NSArray * mElements;
}
+ (NSArray *) elementsWithPropertiesArray: (NSArray *) propertiesArray;
+ (DDHidElement *) elementWithProperties: (NSDictionary *) properties;
- (id) initWithProperties: (NSDictionary *) properties;
- (NSDictionary *) properties;
- (NSString *) stringForKey: (NSString *) key;
- (NSString *) description;
- (IOHIDElementCookie) cookie;
- (unsigned) cookieAsUnsigned;
- (NSArray *) elements;
- (DDHidUsage *) usage;
- (NSString *) name;
- (BOOL) hasNullState;
- (BOOL) hasPreferredState;
- (BOOL) isArray;
- (BOOL) isRelative;
- (BOOL) isWrapping;
- (long) maxValue;
- (long) minValue;
- (NSComparisonResult) compareByUsage: (DDHidElement *) device;
@end

185
lib/DDHidElement.m Normal file
View File

@ -0,0 +1,185 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidElement.h"
#import "DDHidUsage.h"
#import "NSDictionary+DDHidExtras.h"
#include <IOKit/hid/IOHIDKeys.h>
@implementation DDHidElement
+ (NSArray *) elementsWithPropertiesArray: (NSArray *) propertiesArray;
{
NSMutableArray * elements = [NSMutableArray array];
NSDictionary * properties;
NSEnumerator * e = [propertiesArray objectEnumerator];
while (properties = [e nextObject])
{
DDHidElement * element = [DDHidElement elementWithProperties: properties];
[elements addObject: element];
}
return elements;
}
+ (DDHidElement *) elementWithProperties: (NSDictionary *) properties;
{
DDHidElement * element = [[DDHidElement alloc] initWithProperties: properties];
return [element autorelease];
}
- (id) initWithProperties: (NSDictionary *) properties;
{
self = [super init];
if (self == nil)
return nil;
mProperties = [properties retain];
unsigned usagePage = [mProperties ddhid_unsignedIntForString: kIOHIDElementUsagePageKey];
unsigned usageId = [mProperties ddhid_unsignedIntForString: kIOHIDElementUsageKey];
mUsage = [[DDHidUsage alloc] initWithUsagePage: usagePage
usageId: usageId];
NSArray * elementsProperties =
[mProperties ddhid_objectForString: kIOHIDElementKey];
mElements = [[DDHidElement elementsWithPropertiesArray: elementsProperties]
retain];
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mProperties release];
[mUsage release];
[mElements release];
mProperties = nil;
mUsage = nil;
mElements = nil;
[super dealloc];
}
- (NSDictionary *) properties;
{
return mProperties;
}
- (NSString *) stringForKey: (NSString *) key;
{
return [mProperties objectForKey: key];
}
- (NSString *) description;
{
return [[self usage] usageNameWithIds];
}
- (IOHIDElementCookie) cookie;
{
return (IOHIDElementCookie)
[mProperties ddhid_unsignedIntForString: kIOHIDElementCookieKey];
}
- (unsigned) cookieAsUnsigned;
{
return [mProperties ddhid_unsignedIntForString: kIOHIDElementCookieKey];
}
- (DDHidUsage *) usage;
{
return mUsage;
}
- (NSArray *) elements;
{
return mElements;
}
- (NSString *) name;
{
return [mProperties ddhid_objectForString: kIOHIDElementNameKey];
}
- (BOOL) hasNullState;
{
return [mProperties ddhid_boolForString: kIOHIDElementHasNullStateKey];
}
- (BOOL) hasPreferredState;
{
return [mProperties ddhid_boolForString: kIOHIDElementHasNullStateKey];
}
- (BOOL) isArray;
{
return [mProperties ddhid_boolForString: kIOHIDElementIsArrayKey];
}
- (BOOL) isRelative;
{
return [mProperties ddhid_boolForString: kIOHIDElementIsRelativeKey];
}
- (BOOL) isWrapping;
{
return [mProperties ddhid_boolForString: kIOHIDElementIsWrappingKey];
}
- (long) maxValue;
{
return [mProperties ddhid_longForString: kIOHIDElementMaxKey];
}
- (long) minValue;
{
return [mProperties ddhid_longForString: kIOHIDElementMinKey];
}
- (NSComparisonResult) compareByUsage: (DDHidElement *) device;
{
unsigned myUsagePage = [[self usage] usagePage];
unsigned myUsageId = [[self usage] usageId];
unsigned otherUsagePage = [[device usage] usagePage];
unsigned otherUsageId = [[device usage] usageId];
if (myUsagePage < otherUsagePage)
return NSOrderedAscending;
else if (myUsagePage > otherUsagePage)
return NSOrderedDescending;
if (myUsageId < otherUsageId)
return NSOrderedAscending;
else if (myUsageId > otherUsageId)
return NSOrderedDescending;
return NSOrderedSame;
}
@end

45
lib/DDHidEvent.h Normal file
View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#include <IOKit/hid/IOHIDLib.h>
@interface DDHidEvent : NSObject
{
IOHIDEventStruct mEvent;
}
+ (DDHidEvent *) eventWithIOHIDEvent: (IOHIDEventStruct *) event;
- (id) initWithIOHIDEvent: (IOHIDEventStruct *) event;
- (IOHIDElementType) type;
- (IOHIDElementCookie) elementCookie;
- (unsigned) elementCookieAsUnsigned;
- (SInt32) value;
- (AbsoluteTime) timestamp;
- (UInt32) longValueSize;
- (void *) longValue;
@end

81
lib/DDHidEvent.m Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidEvent.h"
@implementation DDHidEvent
+ (DDHidEvent *) eventWithIOHIDEvent: (IOHIDEventStruct *) event;
{
return [[[self alloc] initWithIOHIDEvent: event] autorelease];
}
- (id) initWithIOHIDEvent: (IOHIDEventStruct *) event;
{
self = [super init];
if (self == nil)
return nil;
mEvent = *event;
return self;
}
- (IOHIDElementType) type;
{
return mEvent.type;
}
- (IOHIDElementCookie) elementCookie;
{
return mEvent.elementCookie;
}
- (unsigned) elementCookieAsUnsigned;
{
return (unsigned) mEvent.elementCookie;
}
- (SInt32) value;
{
return mEvent.value;
}
- (AbsoluteTime) timestamp;
{
return mEvent.timestamp;
}
- (UInt32) longValueSize;
{
return mEvent.longValueSize;
}
- (void *) longValue;
{
return mEvent.longValue;
}
@end

132
lib/DDHidJoystick.h Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidDevice.h"
@class DDHidElement;
@class DDHidQueue;
@interface DDHidJoystickStick : NSObject
{
DDHidElement * mXAxisElement;
DDHidElement * mYAxisElement;
NSMutableArray * mStickElements;
// Point of view elements (i.e. hat switches)
NSMutableArray * mPovElements;
}
- (DDHidElement *) xAxisElement;
- (DDHidElement *) yAxisElement;
#pragma mark -
#pragma mark StickElements - indexed accessors
- (unsigned int) countOfStickElements;
- (DDHidElement *) objectInStickElementsAtIndex: (unsigned int)index;
#pragma mark -
#pragma mark PovElements - indexed accessors
- (unsigned int) countOfPovElements;
- (DDHidElement *) objectInPovElementsAtIndex: (unsigned int)index;
- (NSArray *) allElements;
- (BOOL) addElement: (DDHidElement *) element;
@end
@interface DDHidJoystick : DDHidDevice
{
NSMutableArray * mSticks;
NSMutableArray * mButtonElements;
NSMutableArray * mLogicalDeviceElements;
id mDelegate;
}
+ (NSArray *) allJoysticks;
- (id) initLogicalWithDevice: (io_object_t) device
logicalDeviceNumber: (int) logicalDeviceNumber
error: (NSError **) error;
- (int) logicalDeviceCount;
#pragma mark -
#pragma mark Joystick Elements
- (unsigned) numberOfButtons;
- (NSArray *) buttonElements;
#pragma mark -
#pragma mark Sticks - indexed accessors
- (unsigned int) countOfSticks;
- (DDHidJoystickStick *) objectInSticksAtIndex: (unsigned int)index;
- (void) addElementsToQueue: (DDHidQueue *) queue;
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
- (void) addElementsToDefaultQueue;
@end
#define DDHID_JOYSTICK_VALUE_MIN -65536
#define DDHID_JOYSTICK_VALUE_MAX 65536
@interface NSObject (DDHidJoystickDelegate)
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
xChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
yChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
otherAxis: (unsigned) otherAxis
valueChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
povNumber: (unsigned) povNumber
valueChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonDown: (unsigned) buttonNumber;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonUp: (unsigned) buttonNumber;
@end

654
lib/DDHidJoystick.m Normal file
View File

@ -0,0 +1,654 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidLib.h"
#include <IOKit/hid/IOHIDUsageTables.h>
@interface DDHidJoystick (DDHidJoystickDelegate)
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
xChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
yChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
otherAxis: (unsigned) otherAxis
valueChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
povNumber: (unsigned) povNumber
valueChanged: (int) value;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonDown: (unsigned) buttonNumber;
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonUp: (unsigned) buttonNumber;
@end
@interface DDHidJoystick (Private)
- (void) initLogicalDeviceElements;
- (void) initJoystickElements: (NSArray *) elements;
- (void) addStick: (NSArray *) stickElements;
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
- (int) normalizeValue: (int) value
forElement: (DDHidElement *) element;
- (int) povValue: (int) value
forElement: (DDHidElement *) element;
- (BOOL) findStick: (unsigned *) stick
element: (DDHidElement **) elementOut
withXAxisCookie: (IOHIDElementCookie) cookie;
- (BOOL) findStick: (unsigned *) stick
element: (DDHidElement **) elementOut
withYAxisCookie: (IOHIDElementCookie) cookie;
- (BOOL) findStick: (unsigned *) stickOut
otherAxis: (unsigned *) axisOut
element: (DDHidElement **) elementOut
withCookie: (IOHIDElementCookie) cookie;
- (BOOL) findStick: (unsigned *) stickOut
povNumber: (unsigned *) povNumber
element: (DDHidElement **) elementOut
withCookie: (IOHIDElementCookie) cookie;
@end
@implementation DDHidJoystick
+ (NSArray *) allJoysticks;
{
NSArray * joysticks =
[DDHidDevice allDevicesMatchingUsagePage: kHIDPage_GenericDesktop
usageId: kHIDUsage_GD_Joystick
withClass: self
skipZeroLocations: YES];
NSArray * gamepads =
[DDHidDevice allDevicesMatchingUsagePage: kHIDPage_GenericDesktop
usageId: kHIDUsage_GD_GamePad
withClass: self
skipZeroLocations: YES];
NSMutableArray * allJoysticks = [NSMutableArray arrayWithArray: joysticks];
[allJoysticks addObjectsFromArray: gamepads];
[allJoysticks sortUsingSelector: @selector(compareByLocationId:)];
return allJoysticks;
}
- (id) initLogicalWithDevice: (io_object_t) device
logicalDeviceNumber: (int) logicalDeviceNumber
error: (NSError **) error;
{
self = [super initLogicalWithDevice: device
logicalDeviceNumber: logicalDeviceNumber
error: error];
if (self == nil)
return nil;
mButtonElements = [[NSMutableArray alloc] init];
mSticks = [[NSMutableArray alloc] init];
mLogicalDeviceElements = [[NSMutableArray alloc] init];
[self initLogicalDeviceElements];
int logicalDeviceCount = [mLogicalDeviceElements count];
if (logicalDeviceCount == 0)
{
[self release];
return nil;
}
mLogicalDeviceNumber = logicalDeviceNumber;
if (mLogicalDeviceNumber >= logicalDeviceCount)
mLogicalDeviceNumber = logicalDeviceCount - 1;
[self initJoystickElements:
[mLogicalDeviceElements objectAtIndex: mLogicalDeviceNumber]];
[mButtonElements sortUsingSelector: @selector(compareByUsage:)];
mDelegate = nil;
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mLogicalDeviceElements release];
[mSticks release];
[mButtonElements release];
mLogicalDeviceElements = nil;
mSticks = nil;
mButtonElements = nil;
[super dealloc];
}
- (int) logicalDeviceCount;
{
return [mLogicalDeviceElements count];
}
#pragma mark -
#pragma mark Joystick Elements
//===========================================================
// - buttonElements
//===========================================================
- (NSArray *) buttonElements;
{
return mButtonElements;
}
- (unsigned) numberOfButtons;
{
return [mButtonElements count];
}
#pragma mark -
#pragma mark Sticks - indexed accessors
- (unsigned int) countOfSticks
{
return [mSticks count];
}
- (DDHidJoystickStick *) objectInSticksAtIndex: (unsigned int)index
{
return [mSticks objectAtIndex: index];
}
- (void) addElementsToQueue: (DDHidQueue *) queue;
{
NSEnumerator * e = [mSticks objectEnumerator];
DDHidJoystickStick * stick;
while (stick = [e nextObject])
{
[queue addElements: [stick allElements]];
}
[queue addElements: mButtonElements];
}
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
{
mDelegate = delegate;
}
- (void) addElementsToDefaultQueue;
{
[self addElementsToQueue: mDefaultQueue];
}
@end
@implementation DDHidJoystick (Private)
- (void) initLogicalDeviceElements;
{
NSArray * topLevelElements = [self elements];
if ([topLevelElements count] == 0)
{
[mLogicalDeviceElements addObject: topLevelElements];
return;
}
NSEnumerator * e = [topLevelElements objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
unsigned usagePage = [[element usage] usagePage];
unsigned usageId = [[element usage] usageId];
if (usagePage == kHIDPage_GenericDesktop &&
(usageId == kHIDUsage_GD_Joystick || usageId == kHIDUsage_GD_GamePad))
{
[mLogicalDeviceElements addObject: [NSArray arrayWithObject: element]];
}
}
}
- (void) initJoystickElements: (NSArray *) elements;
{
NSEnumerator * e = [elements objectEnumerator];
DDHidElement * element;
DDHidJoystickStick * currentStick = [[[DDHidJoystickStick alloc] init] autorelease];
BOOL stickHasElements = NO;
while (element = [e nextObject])
{
unsigned usagePage = [[element usage] usagePage];
unsigned usageId = [[element usage] usageId];
NSArray * subElements = [element elements];
if ([subElements count] > 0)
{
[self initJoystickElements: subElements];
}
else if ((usagePage == kHIDPage_GenericDesktop) &&
(usageId == kHIDUsage_GD_Pointer))
{
[self addStick: subElements];
}
else if ([currentStick addElement: element])
{
stickHasElements = YES;
}
else if ((usagePage == kHIDPage_Button) &&
(usageId > 0))
{
[mButtonElements addObject: element];
}
}
if (stickHasElements)
{
[mSticks addObject: currentStick];
}
}
- (void) addStick: (NSArray *) elements;
{
NSEnumerator * e = [elements objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
NSLog(@"Stick element: %@", [[element usage] usageName]);
}
}
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
{
DDHidEvent * event;
while ((event = [hidQueue nextEvent]))
{
IOHIDElementCookie cookie = [event elementCookie];
SInt32 value = [event value];
DDHidElement * element;
unsigned stick;
unsigned otherAxis;
unsigned povNumber;
if ([self findStick: &stick element: &element withXAxisCookie: cookie])
{
int normalizedValue = [self normalizeValue: value forElement: element];
[self ddhidJoystick: self stick: stick xChanged: normalizedValue];
}
else if ([self findStick: &stick element: &element withYAxisCookie: cookie])
{
int normalizedValue = [self normalizeValue: value forElement: element];
[self ddhidJoystick: self stick: stick yChanged: normalizedValue];
}
else if ([self findStick: &stick otherAxis: &otherAxis element: &element
withCookie: cookie])
{
int normalizedValue = [self normalizeValue: value forElement: element];
[self ddhidJoystick: self stick: stick
otherAxis: otherAxis valueChanged: normalizedValue];
}
else if ([self findStick: &stick povNumber: &povNumber element: &element
withCookie: cookie])
{
int povValue = [self povValue: value forElement: element];
[self ddhidJoystick: self stick: stick
povNumber: povNumber valueChanged: povValue];
}
else
{
unsigned i = 0;
for (i = 0; i < [[self buttonElements] count]; i++)
{
if (cookie == [[[self buttonElements] objectAtIndex: i] cookie])
break;
}
if (value == 1)
{
[self ddhidJoystick: self buttonDown: i];
}
else if (value == 0)
{
[self ddhidJoystick: self buttonUp: i];
}
else
{
DDHidElement * element = [self elementForCookie: [event elementCookie]];
NSLog(@"Element: %@, value: %d", [[element usage] usageName], (int)[event value]);
}
}
}
}
- (int) normalizeValue: (int) value
forElement: (DDHidElement *) element;
{
int normalizedUnits = DDHID_JOYSTICK_VALUE_MAX - DDHID_JOYSTICK_VALUE_MIN;
int elementUnits = [element maxValue] - [element minValue];
int normalizedValue = (((int64_t)(value - [element minValue]) * normalizedUnits) /
elementUnits) + DDHID_JOYSTICK_VALUE_MIN;
return normalizedValue;
}
- (int) povValue: (int) value
forElement: (DDHidElement *) element;
{
long max = [element maxValue];
long min = [element minValue];
// If the value is outside the min/max range, it's probably in a
// centered/NULL state.
if ((value < min) || (value > max))
{
return -1;
}
// Do like DirectInput and express the hatswitch value in hundredths of a
// degree, clockwise from north.
return 36000 / (max - min + 1) * (value - min);
}
- (BOOL) findStick: (unsigned *) stick
element: (DDHidElement **) elementOut
withXAxisCookie: (IOHIDElementCookie) cookie;
{
unsigned i;
for (i = 0; i < [mSticks count]; i++)
{
DDHidElement * element = [[mSticks objectAtIndex: i] xAxisElement];
if ((element != nil) && ([element cookie] == cookie))
{
*stick = i;
*elementOut = element;
return YES;
}
}
return NO;
}
- (BOOL) findStick: (unsigned *) stick
element: (DDHidElement **) elementOut
withYAxisCookie: (IOHIDElementCookie) cookie;
{
unsigned i;
for (i = 0; i < [mSticks count]; i++)
{
DDHidElement * element = [[mSticks objectAtIndex: i] yAxisElement];
if ((element != nil) && ([element cookie] == cookie))
{
*stick = i;
*elementOut = element;
return YES;
}
}
return NO;
}
- (BOOL) findStick: (unsigned *) stickOut
otherAxis: (unsigned *) axisOut
element: (DDHidElement **) elementOut
withCookie: (IOHIDElementCookie) cookie;
{
unsigned i;
for (i = 0; i < [mSticks count]; i++)
{
DDHidJoystickStick * stick = [mSticks objectAtIndex: i];
unsigned j;
for (j = 0; j < [stick countOfStickElements]; j++)
{
DDHidElement * element = [stick objectInStickElementsAtIndex: j];
if ((element != nil) && ([element cookie] == cookie))
{
*stickOut = i;
*axisOut = j;
*elementOut = element;
return YES;
}
}
}
return NO;
}
- (BOOL) findStick: (unsigned *) stickOut
povNumber: (unsigned *) povNumber
element: (DDHidElement **) elementOut
withCookie: (IOHIDElementCookie) cookie;
{
unsigned i;
for (i = 0; i < [mSticks count]; i++)
{
DDHidJoystickStick * stick = [mSticks objectAtIndex: i];
unsigned j;
for (j = 0; j < [stick countOfPovElements]; j++)
{
DDHidElement * element = [stick objectInPovElementsAtIndex: j];
if ((element != nil) && ([element cookie] == cookie))
{
*stickOut = i;
*povNumber = j;
*elementOut = element;
return YES;
}
}
}
return NO;
}
@end
@implementation DDHidJoystick (DDHidJoystickDelegate)
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
xChanged: (int) value;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidJoystick: joystick stick: stick xChanged: value];
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
yChanged: (int) value;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidJoystick: joystick stick: stick yChanged: value];
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
otherAxis: (unsigned) otherAxis
valueChanged: (int) value;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidJoystick: joystick stick: stick otherAxis: otherAxis
valueChanged: value];
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
stick: (unsigned) stick
povNumber: (unsigned) povNumber
valueChanged: (int) value;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidJoystick: joystick stick: stick povNumber: povNumber
valueChanged: value];
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonDown: (unsigned) buttonNumber;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidJoystick: joystick buttonDown: buttonNumber];
}
- (void) ddhidJoystick: (DDHidJoystick *) joystick
buttonUp: (unsigned) buttonNumber;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidJoystick: joystick buttonUp: buttonNumber];
}
@end
@implementation DDHidJoystickStick
- (id) init
{
self = [super init];
if (self == nil)
return nil;
mXAxisElement = nil;
mYAxisElement = nil;
mStickElements = [[NSMutableArray alloc] init];
mPovElements = [[NSMutableArray alloc] init];
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mXAxisElement release];
[mYAxisElement release];
[mStickElements release];
[mPovElements release];
mXAxisElement = nil;
mYAxisElement = nil;
mStickElements = nil;
mPovElements = nil;
[super dealloc];
}
- (BOOL) addElement: (DDHidElement *) element;
{
DDHidUsage * usage = [element usage];
if ([usage usagePage] != kHIDPage_GenericDesktop)
return NO;
BOOL elementAdded = YES;
switch ([usage usageId])
{
case kHIDUsage_GD_X:
if (mXAxisElement == nil)
mXAxisElement = [element retain];
else
[mStickElements addObject: element];
break;
case kHIDUsage_GD_Y:
if (mYAxisElement == nil)
mYAxisElement = [element retain];
else
[mStickElements addObject: element];
break;
case kHIDUsage_GD_Z:
case kHIDUsage_GD_Rx:
case kHIDUsage_GD_Ry:
case kHIDUsage_GD_Rz:
[mStickElements addObject: element];
break;
case kHIDUsage_GD_Hatswitch:
[mPovElements addObject: element];
break;
default:
elementAdded = NO;
}
return elementAdded;
}
- (NSArray *) allElements;
{
NSMutableArray * elements = [NSMutableArray array];
if (mXAxisElement != nil)
[elements addObject: mXAxisElement];
if (mYAxisElement != nil)
[elements addObject: mYAxisElement];
[elements addObjectsFromArray: mStickElements];
[elements addObjectsFromArray: mPovElements];
return elements;
}
- (DDHidElement *) xAxisElement;
{
return mXAxisElement;
}
- (DDHidElement *) yAxisElement;
{
return mYAxisElement;
}
#pragma mark -
#pragma mark mStickElements - indexed accessors
- (unsigned int) countOfStickElements
{
return [mStickElements count];
}
- (DDHidElement *) objectInStickElementsAtIndex: (unsigned int)index
{
return [mStickElements objectAtIndex: index];
}
#pragma mark -
#pragma mark PovElements - indexed accessors
- (unsigned int) countOfPovElements;
{
return [mPovElements count];
}
- (DDHidElement *) objectInPovElementsAtIndex: (unsigned int)index;
{
return [mPovElements objectAtIndex: index];
}
- (NSString *) description;
{
return [mStickElements description];
}
@end

68
lib/DDHidKeyboard.h Normal file
View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidDevice.h"
@class DDHidElement;
@class DDHidQueue;
@interface DDHidKeyboard : DDHidDevice
{
NSMutableArray * mKeyElements;
id mDelegate;
}
+ (NSArray *) allKeyboards;
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
#pragma mark -
#pragma mark Keyboards Elements
- (NSArray *) keyElements;
- (unsigned) numberOfKeys;
- (void) addElementsToQueue: (DDHidQueue *) queue;
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
- (void) addElementsToDefaultQueue;
@end
@interface NSObject (DDHidKeyboardDelegate)
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyDown: (unsigned) usageId;
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyUp: (unsigned) usageId;
@end

173
lib/DDHidKeyboard.m Normal file
View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidKeyboard.h"
#import "DDHidElement.h"
#import "DDHidUsage.h"
#import "DDHidQueue.h"
#import "DDHidEvent.h"
#include <IOKit/hid/IOHIDUsageTables.h>
@interface DDHidKeyboard (DDHidKeyboardDelegate)
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyDown: (unsigned) usageId;
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyUp: (unsigned) usageId;
@end
@interface DDHidKeyboard (Private)
- (void) initKeyboardElements: (NSArray *) elements;
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
@end
@implementation DDHidKeyboard
+ (NSArray *) allKeyboards;
{
return
[DDHidDevice allDevicesMatchingUsagePage: kHIDPage_GenericDesktop
usageId: kHIDUsage_GD_Keyboard
withClass: self
skipZeroLocations: YES];
}
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
{
self = [super initWithDevice: device error: error_];
if (self == nil)
return nil;
mKeyElements = [[NSMutableArray alloc] init];
[self initKeyboardElements: [self elements]];
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mKeyElements release];
mKeyElements = nil;
[super dealloc];
}
#pragma mark -
#pragma mark Keyboards Elements
- (NSArray *) keyElements;
{
return mKeyElements;
}
- (unsigned) numberOfKeys;
{
return [mKeyElements count];
}
- (void) addElementsToQueue: (DDHidQueue *) queue;
{
[queue addElements: mKeyElements];
}
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
{
mDelegate = delegate;
}
- (void) addElementsToDefaultQueue;
{
[self addElementsToQueue: mDefaultQueue];
}
@end
@implementation DDHidKeyboard (DDHidKeyboardDelegate)
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyDown: (unsigned) usageId;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidKeyboard: keyboard keyDown: usageId];
}
- (void) ddhidKeyboard: (DDHidKeyboard *) keyboard
keyUp: (unsigned) usageId;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidKeyboard: keyboard keyUp: usageId];
}
@end
@implementation DDHidKeyboard (Private)
- (void) initKeyboardElements: (NSArray *) elements;
{
NSEnumerator * e = [elements objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
unsigned usagePage = [[element usage] usagePage];
unsigned usageId = [[element usage] usageId];
if (usagePage == kHIDPage_KeyboardOrKeypad)
{
if (((usageId >= 0x04) && (usageId <= 0xA4)) ||
((usageId >= 0xE0) && (usageId <= 0xE7)))
{
[mKeyElements addObject: element];
}
}
NSArray * subElements = [element elements];
if (subElements != nil)
[self initKeyboardElements: subElements];
}
}
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
{
DDHidEvent * event;
while ((event = [hidQueue nextEvent]))
{
DDHidElement * element = [self elementForCookie: [event elementCookie]];
unsigned usageId = [[element usage] usageId];
SInt32 value = [event value];
if (value == 1)
[self ddhidKeyboard: self keyDown: usageId];
else
[self ddhidKeyboard: self keyUp: usageId];
}
}
@end

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2007 Dave Dribin, Lucas Newman
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidDevice.h"
@class DDHidElement;
@class DDHidQueue;
@interface DDHidKeyboardBarcodeScanner : DDHidDevice
{
NSMutableArray * mKeyElements;
NSMutableString * mAccumulatedDigits;
NSTimer *mBarcodeInputTimer;
BOOL mIsLikelyKeyboardBarcodeScanner;
id mDelegate;
}
+ (NSArray *) allPossibleKeyboardBarcodeScanners;
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
#pragma mark -
#pragma mark Keyboard Elements
- (NSArray *) keyElements;
- (NSUInteger) numberOfKeys;
- (void) addElementsToQueue: (DDHidQueue *) queue;
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
- (void) addElementsToDefaultQueue;
#pragma mark -
#pragma mark Properties
- (BOOL) isLikelyKeyboardBarcodeScanner;
@end
@interface NSObject (DDHidKeyboardBarcodeScannerDelegate)
- (void) ddhidKeyboardBarcodeScanner: (DDHidKeyboardBarcodeScanner *) keyboardBarcodeScanner
gotBarcode: (NSString *) barcode;
@end

View File

@ -0,0 +1,222 @@
/*
* Copyright (c) 2007 Dave Dribin, Lucas Newman
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidKeyboardBarcodeScanner.h"
#import "DDHidElement.h"
#import "DDHidUsage.h"
#import "DDHidQueue.h"
#import "DDHidEvent.h"
#include <IOKit/hid/IOHIDUsageTables.h>
@interface DDHidKeyboardBarcodeScanner (DDHidKeyboardBarcodeDelegate)
- (void) ddhidKeyboardBarcodeScanner: (DDHidKeyboardBarcodeScanner *) keyboardBarcodeScanner
gotBarcode: (NSString *) barcode;
@end
@interface DDHidKeyboardBarcodeScanner (Private)
- (void) initKeyboardElements: (NSArray *) elements;
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
- (void) processBarcodeDigit: (unsigned) usageId;
- (void) clearAccumulatedInput;
- (void) invalidateBarcodeInputTimer;
@end
@implementation DDHidKeyboardBarcodeScanner
+ (NSArray *) allPossibleKeyboardBarcodeScanners;
{
return [DDHidDevice allDevicesMatchingUsagePage: kHIDPage_GenericDesktop
usageId: kHIDUsage_GD_Keyboard
withClass: self
skipZeroLocations: YES];
}
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
{
self = [super initWithDevice: device error: error_];
if (self == nil)
return nil;
mKeyElements = [[NSMutableArray alloc] init];
mAccumulatedDigits = [[NSMutableString alloc] init];
mBarcodeInputTimer = nil;
if ([[self productName] rangeOfString:@"Apple"].location != NSNotFound || [[self productName] rangeOfString:@"Internal"].location != NSNotFound)
mIsLikelyKeyboardBarcodeScanner = NO;
else
mIsLikelyKeyboardBarcodeScanner = YES; // if we see invalid barcodes, we can change our mind
[self initKeyboardElements: [self elements]];
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[self invalidateBarcodeInputTimer];
[mKeyElements release];
[mAccumulatedDigits release];
mKeyElements = nil;
mAccumulatedDigits = nil;
[super dealloc];
}
#pragma mark -
#pragma mark Keyboard Elements
- (NSArray *) keyElements;
{
return mKeyElements;
}
- (NSUInteger) numberOfKeys;
{
return [mKeyElements count];
}
- (void) addElementsToQueue: (DDHidQueue *) queue;
{
[queue addElements: mKeyElements];
}
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
{
mDelegate = delegate;
}
- (void) addElementsToDefaultQueue;
{
[self addElementsToQueue: mDefaultQueue];
}
#pragma mark -
#pragma mark Properties
- (BOOL) isLikelyKeyboardBarcodeScanner;
{
return mIsLikelyKeyboardBarcodeScanner;
}
@end
@implementation DDHidKeyboardBarcodeScanner (DDHidKeyboardDelegate)
- (void) ddhidKeyboardBarcodeScanner: (DDHidKeyboardBarcodeScanner *) keyboardBarcodeScanner
gotBarcode: (NSString *) barcode;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidKeyboardBarcodeScanner: keyboardBarcodeScanner gotBarcode: barcode];
}
@end
@implementation DDHidKeyboardBarcodeScanner (Private)
- (void) initKeyboardElements: (NSArray *) elements;
{
NSEnumerator * e = [elements objectEnumerator];
DDHidElement * element;
while ((element = [e nextObject]))
{
unsigned usagePage = [[element usage] usagePage];
unsigned usageId = [[element usage] usageId];
if (usagePage == kHIDPage_KeyboardOrKeypad)
{
if ((usageId >= kHIDUsage_KeyboardA) && (usageId <= kHIDUsage_Keyboard0))
{
[mKeyElements addObject: element];
}
}
NSArray * subElements = [element elements];
if (subElements != nil)
[self initKeyboardElements: subElements];
}
}
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
{
DDHidEvent * event;
while ((event = [hidQueue nextEvent]))
{
DDHidElement * element = [self elementForCookie: [event elementCookie]];
unsigned usageId = [[element usage] usageId];
SInt32 value = [event value];
if (value == 1) // key down
[self processBarcodeDigit: usageId];
}
}
#define UPC_A_BARCODE_LENGTH (12)
#define BARCODE_INPUT_TIMEOUT (0.5)
- (void) processBarcodeDigit: (unsigned) usageId;
{
if (usageId <= kHIDUsage_KeyboardZ || usageId >= kHIDUsage_KeyboardCapsLock) { // an alphabetic key was pressed => probably not a barcode scanner
[self willChangeValueForKey:@"isLikelyKeyboardBarcodeScanner"];
mIsLikelyKeyboardBarcodeScanner = NO;
[self didChangeValueForKey:@"isLikelyKeyboardBarcodeScanner"];
[self clearAccumulatedInput];
return;
}
if (!mBarcodeInputTimer) // schedule a timer to make sure we get the rest of the digits in a timely manner
mBarcodeInputTimer = [[NSTimer scheduledTimerWithTimeInterval:BARCODE_INPUT_TIMEOUT target:self selector:@selector(fireBarcodeInputTimeout:) userInfo:nil repeats:NO] retain];
[mAccumulatedDigits appendString:[NSString stringWithFormat:@"%d", (usageId + 1) % 10]];
}
- (void) fireBarcodeInputTimeout: (NSTimer *) timer;
{
if ([mAccumulatedDigits length] >= UPC_A_BARCODE_LENGTH)
[self ddhidKeyboardBarcodeScanner: self gotBarcode: [[mAccumulatedDigits copy] autorelease]];
[self clearAccumulatedInput];
}
- (void) clearAccumulatedInput;
{
[mAccumulatedDigits deleteCharactersInRange:NSMakeRange(0, [mAccumulatedDigits length])];
[self invalidateBarcodeInputTimer];
}
- (void) invalidateBarcodeInputTimer;
{
[mBarcodeInputTimer invalidate];
[mBarcodeInputTimer release];
mBarcodeInputTimer = nil;
}
@end

36
lib/DDHidLib.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidDevice.h"
#import "DDHidElement.h"
#import "DDHidUsage.h"
#import "DDHidQueue.h"
#import "DDHidEvent.h"
#import "DDHidUsageTables.h"
#import "DDHidMouse.h"
#import "DDHidJoystick.h"
#import "DDHidKeyboard.h"
#import "DDHidAppleRemote.h"
#import "DDHidAppleMikey.h"
#import "DDHidKeyboardBarcodeScanner.h"

78
lib/DDHidMouse.h Normal file
View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#import "DDHidDevice.h"
@class DDHidElement;
@class DDHidQueue;
@interface DDHidMouse : DDHidDevice
{
DDHidElement * mXElement;
DDHidElement * mYElement;
DDHidElement * mWheelElement;
NSMutableArray * mButtonElements;
id mDelegate;
}
+ (NSArray *) allMice;
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
#pragma mark -
#pragma mark Mouse Elements
- (DDHidElement *) xElement;
- (DDHidElement *) yElement;
- (DDHidElement *) wheelElement;
- (NSArray *) buttonElements;
- (unsigned) numberOfButtons;
- (void) addElementsToQueue: (DDHidQueue *) queue;
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
- (void) addElementsToDefaultQueue;
@end
@interface NSObject (DDHidMouseDelegate)
- (void) ddhidMouse: (DDHidMouse *) mouse xChanged: (SInt32) deltaX;
- (void) ddhidMouse: (DDHidMouse *) mouse yChanged: (SInt32) deltaY;
- (void) ddhidMouse: (DDHidMouse *) mouse wheelChanged: (SInt32) deltaWheel;
- (void) ddhidMouse: (DDHidMouse *) mouse buttonDown: (unsigned) buttonNumber;
- (void) ddhidMouse: (DDHidMouse *) mouse buttonUp: (unsigned) buttonNumber;
@end

279
lib/DDHidMouse.m Normal file
View File

@ -0,0 +1,279 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidMouse.h"
#import "DDHidUsage.h"
#import "DDHidElement.h"
#import "DDHidQueue.h"
#import "DDHidEvent.h"
#include <IOKit/hid/IOHIDUsageTables.h>
// Implement our own delegate methods
@interface DDHidMouse (DDHidMouseDelegate)
- (void) ddhidMouse: (DDHidMouse *) mouse xChanged: (SInt32) deltaX;
- (void) ddhidMouse: (DDHidMouse *) mouse yChanged: (SInt32) deltaY;
- (void) ddhidMouse: (DDHidMouse *) mouse wheelChanged: (SInt32) deltaWheel;
- (void) ddhidMouse: (DDHidMouse *) mouse buttonDown: (unsigned) buttonNumber;
- (void) ddhidMouse: (DDHidMouse *) mouse buttonUp: (unsigned) buttonNumber;
@end
@interface DDHidMouse (Private)
- (void) initMouseElements: (NSArray *) elements;
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
@end
@implementation DDHidMouse
+ (NSArray *) allMice;
{
return
[DDHidDevice allDevicesMatchingUsagePage: kHIDPage_GenericDesktop
usageId: kHIDUsage_GD_Mouse
withClass: self
skipZeroLocations: YES];
}
- (id) initWithDevice: (io_object_t) device error: (NSError **) error_;
{
self = [super initWithDevice: device error: error_];
if (self == nil)
return nil;
mXElement = mYElement = mWheelElement = nil;
mButtonElements = [[NSMutableArray alloc] init];
[self initMouseElements: [self elements]];
return self;
}
//===========================================================
// dealloc
//===========================================================
- (void) dealloc
{
[mXElement release];
[mYElement release];
[mWheelElement release];
[mButtonElements release];
mXElement = nil;
mYElement = nil;
mWheelElement = nil;
mButtonElements = nil;
[super dealloc];
}
#pragma mark -
#pragma mark Mouse Elements
//===========================================================
// - xElement
//===========================================================
- (DDHidElement *) xElement
{
return mXElement;
}
//===========================================================
// - yElement
//===========================================================
- (DDHidElement *) yElement
{
return mYElement;
}
- (DDHidElement *) wheelElement;
{
return mWheelElement;
}
//===========================================================
// - buttonElements
//===========================================================
- (NSArray *) buttonElements;
{
return mButtonElements;
}
- (unsigned) numberOfButtons;
{
return [mButtonElements count];
}
- (void) addElementsToQueue: (DDHidQueue *) queue;
{
[queue addElement: mXElement];
[queue addElement: mYElement];
[queue addElement: mWheelElement];
[queue addElements: mButtonElements];
}
#pragma mark -
#pragma mark Asynchronous Notification
- (void) setDelegate: (id) delegate;
{
mDelegate = delegate;
}
- (void) addElementsToDefaultQueue;
{
[self addElementsToQueue: mDefaultQueue];
}
@end
@implementation DDHidMouse (DDHidMouseDelegate)
- (void) ddhidMouse: (DDHidMouse *) mouse xChanged: (SInt32) deltaX;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidMouse: mouse xChanged: deltaX];
}
- (void) ddhidMouse: (DDHidMouse *) mouse yChanged: (SInt32) deltaY;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidMouse: mouse yChanged: deltaY];
}
- (void) ddhidMouse: (DDHidMouse *) mouse wheelChanged: (SInt32) deltaWheel;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidMouse: mouse wheelChanged: deltaWheel];
}
- (void) ddhidMouse: (DDHidMouse *) mouse buttonDown: (unsigned) buttonNumber;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidMouse: mouse buttonDown: buttonNumber];
}
- (void) ddhidMouse: (DDHidMouse *) mouse buttonUp: (unsigned) buttonNumber;
{
if ([mDelegate respondsToSelector: _cmd])
[mDelegate ddhidMouse: mouse buttonUp: buttonNumber];
}
@end
@implementation DDHidMouse (Private)
- (void) initMouseElements: (NSArray *) elements;
{
NSEnumerator * e = [elements objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
unsigned usagePage = [[element usage] usagePage];
unsigned usageId = [[element usage] usageId];
if ((usagePage == kHIDPage_GenericDesktop) &&
(usageId == kHIDUsage_GD_X))
{
mXElement = [element retain];
}
else if ((usagePage == kHIDPage_GenericDesktop) &&
(usageId == kHIDUsage_GD_Y))
{
mYElement = [element retain];
}
else if ((usagePage == kHIDPage_GenericDesktop) &&
(usageId == kHIDUsage_GD_Wheel))
{
mWheelElement = [element retain];
}
else if ((usagePage == kHIDPage_Button) &&
(usageId > 0))
{
[mButtonElements addObject: element];
}
NSArray * subElements = [element elements];
if (subElements != nil)
[self initMouseElements: subElements];
}
}
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
{
DDHidEvent * event;
while ((event = [hidQueue nextEvent]))
{
IOHIDElementCookie cookie = [event elementCookie];
SInt32 value = [event value];
if (cookie == [[self xElement] cookie])
{
if (value != 0)
{
[self ddhidMouse: self xChanged: value];
}
}
else if (cookie == [[self yElement] cookie])
{
if (value != 0)
{
[self ddhidMouse: self yChanged: value];
}
}
else if (cookie == [[self wheelElement] cookie])
{
if (value != 0)
{
[self ddhidMouse: self wheelChanged: value];
}
}
else
{
unsigned i = 0;
for (i = 0; i < [[self buttonElements] count]; i++)
{
if (cookie == [[[self buttonElements] objectAtIndex: i] cookie])
break;
}
if (value == 1)
{
[self ddhidMouse: self buttonDown: i];
}
else if (value == 0)
{
[self ddhidMouse: self buttonUp: i];
}
else
{
DDHidElement * element = [self elementForCookie: [event elementCookie]];
NSLog(@"Element: %@, value: %d", [[element usage] usageName], (int)[event value]);
}
}
}
}
@end

70
lib/DDHidQueue.h Normal file
View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#include <IOKit/hid/IOHIDLib.h>
@class DDHidElement;
@class DDHidEvent;
@interface DDHidQueue : NSObject
{
IOHIDQueueInterface ** mQueue;
NSRunLoop * mRunLoop;
BOOL mStarted;
id mDelegate;
CFRunLoopSourceRef mEventSource;
}
- (id) initWithHIDQueue: (IOHIDQueueInterface **) queue
size: (unsigned) size;
- (void) addElement: (DDHidElement *) element;
- (void) addElements: (NSArray *) elements;
- (void) addElements: (NSArray *) elements recursively: (BOOL) recursively;
- (void) setDelegate: (id) delegate;
- (void) startOnCurrentRunLoop;
- (void) startOnRunLoop: (NSRunLoop *) runLoop;
- (void) stop;
- (BOOL) isStarted;
- (BOOL) getNextEvent: (IOHIDEventStruct *) event;
- (DDHidEvent *) nextEvent;
@end
@interface NSObject (DDHidQueueDelegate)
- (void) ddhidQueueHasEvents: (DDHidQueue *) hidQueue;
@end

174
lib/DDHidQueue.m Normal file
View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidQueue.h"
#import "DDHidElement.h"
#import "DDHIdEvent.h"
#import "NSXReturnThrowError.h"
static void queueCallbackFunction(void* target, IOReturn result, void* refcon,
void* sender);
@interface DDHidQueue (Private)
- (void) handleQueueCallback;
@end
@implementation DDHidQueue
- (id) initWithHIDQueue: (IOHIDQueueInterface **) queue
size: (unsigned) size;
{
self = [super init];
if (self == nil)
return nil;
mQueue = queue;
IOReturn result = (*mQueue)->create(mQueue, 0, size);
if (result != kIOReturnSuccess)
{
[self release];
return nil;
}
return self;
}
- (void) dealloc;
{
[self stop];
(*mQueue)->dispose(mQueue);
(*mQueue)->Release(mQueue);
[super dealloc];
}
- (void) addElement: (DDHidElement *) element;
{
IOHIDElementCookie cookie = [element cookie];
(*mQueue)->addElement(mQueue, cookie, 0);
}
- (void) addElements: (NSArray *) elements;
{
return [self addElements: elements recursively: NO];
}
- (void) addElements: (NSArray *) elements recursively: (BOOL) recursively;
{
NSEnumerator * e = [elements objectEnumerator];
DDHidElement * element;
while (element = [e nextObject])
{
[self addElement: element];
if (recursively)
[self addElements: [element elements]];
}
}
- (void) setDelegate: (id) delegate;
{
mDelegate = delegate;
}
- (void) startOnCurrentRunLoop;
{
[self startOnRunLoop: [NSRunLoop currentRunLoop]];
}
- (void) startOnRunLoop: (NSRunLoop *) runLoop;
{
if (mStarted)
return;
mRunLoop = [runLoop retain];
NSXThrowError((*mQueue)->createAsyncEventSource(mQueue, &mEventSource));
NSXThrowError((*mQueue)->setEventCallout(mQueue, queueCallbackFunction, self, NULL));
CFRunLoopAddSource([mRunLoop getCFRunLoop], mEventSource,
kCFRunLoopDefaultMode);
(*mQueue)->start(mQueue);
mStarted = YES;
}
- (void) stop;
{
if (!mStarted)
return;
CFRunLoopRemoveSource([mRunLoop getCFRunLoop], mEventSource, kCFRunLoopDefaultMode);
(*mQueue)->stop(mQueue);
[mRunLoop release];
CFRelease(mEventSource);
mRunLoop = nil;
mStarted = NO;
}
- (BOOL) isStarted;
{
return mStarted;
}
- (BOOL) getNextEvent: (IOHIDEventStruct *) event;
{
AbsoluteTime zeroTime = {0, 0};
IOReturn result = (*mQueue)->getNextEvent(mQueue, event, zeroTime, 0);
return (result == kIOReturnSuccess);
}
- (DDHidEvent *) nextEvent;
{
AbsoluteTime zeroTime = {0, 0};
IOHIDEventStruct event;
IOReturn result = (*mQueue)->getNextEvent(mQueue, &event, zeroTime, 0);
if (result != kIOReturnSuccess)
return nil;
else
return [DDHidEvent eventWithIOHIDEvent: &event];
}
@end
@implementation DDHidQueue (Private)
- (void) handleQueueCallback;
{
if ([mDelegate respondsToSelector: @selector(ddhidQueueHasEvents:)])
{
[mDelegate ddhidQueueHasEvents: self];
}
}
@end
static void queueCallbackFunction(void* target, IOReturn result, void* refcon,
void* sender)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
DDHidQueue * queue = (DDHidQueue *) target;
[queue handleQueueCallback];
[pool release];
}

File diff suppressed because it is too large Load Diff

52
lib/DDHidUsage.h Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@interface DDHidUsage : NSObject
{
unsigned mUsagePage;
unsigned mUsageId;
}
+ (DDHidUsage *) usageWithUsagePage: (unsigned) usagePage
usageId: (unsigned) usageId;
- (id) initWithUsagePage: (unsigned) usagePage
usageId: (unsigned) usageId;
- (unsigned) usagePage;
- (unsigned) usageId;
- (NSString *) usageName;
- (NSString *) usageNameWithIds;
- (NSString *) description;
- (BOOL) isEqualToUsagePage: (unsigned) usagePage usageId: (unsigned) usageId;
@end

84
lib/DDHidUsage.m Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidUsage.h"
#import "DDHidUsageTables.h"
@implementation DDHidUsage
+ (DDHidUsage *) usageWithUsagePage: (unsigned) usagePage
usageId: (unsigned) usageId;
{
return [[[self alloc] initWithUsagePage: usagePage usageId: usageId]
autorelease];
}
- (id) initWithUsagePage: (unsigned) usagePage
usageId: (unsigned) usageId;
{
self = [super init];
if (self == nil)
return nil;
mUsagePage = usagePage;
mUsageId = usageId;
return self;
}
- (unsigned) usagePage;
{
return mUsagePage;
}
- (unsigned) usageId;
{
return mUsageId;
}
- (NSString *) usageName;
{
DDHidUsageTables * usageTables = [DDHidUsageTables standardUsageTables];
return
[usageTables descriptionForUsagePage: mUsagePage
usage: mUsageId];
}
- (NSString *) usageNameWithIds;
{
return [NSString stringWithFormat: @"%@ (0x%04x : 0x%04x)",
[self usageName], mUsagePage, mUsageId];
}
- (NSString *) description;
{
return [NSString stringWithFormat: @"HID Usage: %@", [self usageName]];
}
- (BOOL) isEqualToUsagePage: (unsigned) usagePage usageId: (unsigned) usageId;
{
return ((mUsagePage == usagePage) && (mUsageId == usageId));
}
@end

40
lib/DDHidUsageTables.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@interface DDHidUsageTables : NSObject
{
NSDictionary * mLookupTables;
}
+ (DDHidUsageTables *) standardUsageTables;
- (id) initWithLookupTables: (NSDictionary *) lookupTables;
- (NSString *) descriptionForUsagePage: (unsigned) usagePage
usage: (unsigned) usage;
@end

85
lib/DDHidUsageTables.m Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "DDHidUsageTables.h"
@implementation DDHidUsageTables
static DDHidUsageTables * sStandardUsageTables = nil;
+ (DDHidUsageTables *) standardUsageTables;
{
if (sStandardUsageTables == nil)
{
NSBundle * myBundle = [NSBundle bundleForClass: self];
NSString * usageTablesPath =
[myBundle pathForResource: @"DDHidStandardUsages" ofType: @"plist"];
NSDictionary * lookupTables =
[NSDictionary dictionaryWithContentsOfFile: usageTablesPath];
sStandardUsageTables =
[[DDHidUsageTables alloc] initWithLookupTables: lookupTables];
[sStandardUsageTables retain];
}
return sStandardUsageTables;
}
- (id) initWithLookupTables: (NSDictionary *) lookupTables;
{
self = [super init];
if (self == nil)
return nil;
mLookupTables = [lookupTables retain];
return self;
}
- (NSString *) descriptionForUsagePage: (unsigned) usagePage
usage: (unsigned) usage
{
NSString * usagePageString = [NSString stringWithFormat: @"%u", usagePage];
NSString * usageString = [NSString stringWithFormat: @"%u", usage];
// NSNumber * usagePageNumber = [NSNumber numberWithUnsignedInt: usagePage];
NSDictionary * usagePageLookup = [mLookupTables objectForKey: usagePageString];
if (usagePageLookup == nil)
return @"Unknown usage page";
NSDictionary * usageLookup = [usagePageLookup objectForKey: @"usages"];
NSString * description = [usageLookup objectForKey: usageString];
if (description != nil)
return description;
NSString * defaultUsage = [usagePageLookup objectForKey: @"default"];
if (defaultUsage != nil)
{
description = [NSString stringWithFormat: defaultUsage, usage];
return description;
}
return @"Unknown usage";
}
@end

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
@interface NSDictionary (DDHidExtras)
- (unsigned) ddhid_unsignedForKey: (NSString *) key;
- (id) ddhid_objectForString: (const char *) key;
- (NSString *) ddhid_stringForString: (const char *) key;
- (long) ddhid_longForString: (const char *) key;
- (unsigned int) ddhid_unsignedIntForString: (const char *) key;
- (BOOL) ddhid_boolForString: (const char *) key;
@end
@interface NSMutableDictionary (DDHidExtras)
- (void) ddhid_setObject: (id) object forString: (const char *) key;
- (void) ddhid_setInt: (int) i forKey: (id) key;
@end

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2007 Dave Dribin
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#import "NSDictionary+DDHidExtras.h"
@implementation NSDictionary (DDHidExtras)
- (unsigned) ddhid_unsignedForKey: (NSString *) key;
{
NSNumber * number = [self objectForKey: key];
return [number unsignedIntValue];
}
- (id) ddhid_objectForString: (const char *) key;
{
NSString * objcKey = [NSString stringWithUTF8String: key];
return [self objectForKey: objcKey];
}
- (NSString *) ddhid_stringForString: (const char *) key;
{
return [self ddhid_objectForString: key];
}
- (long) ddhid_longForString: (const char *) key;
{
NSNumber * number = [self ddhid_objectForString: key];
return [number longValue];
}
- (unsigned int) ddhid_unsignedIntForString: (const char *) key;
{
NSNumber * number = [self ddhid_objectForString: key];
return [number unsignedIntValue];
}
- (BOOL) ddhid_boolForString: (const char *) key;
{
NSNumber * number = [self ddhid_objectForString: key];
return [number boolValue];
}
@end
@implementation NSMutableDictionary (DDHidExtras)
- (void) ddhid_setObject: (id) object forString: (const char *) key;
{
NSString * objcKey = [NSString stringWithUTF8String: key];
[self setObject: object forKey: objcKey];
}
- (void) ddhid_setInt: (int) i forKey: (id) key;
{
NSNumber * number = [NSNumber numberWithInt: i];
[self setObject: number forKey: key];
}
@end

1086
usb_hid_usages.txt Normal file

File diff suppressed because it is too large Load Diff

46
usb_hid_usages2plist Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env ruby
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "vendor"))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
require 'pp'
require 'plist'
usb_hid_usages = ARGV[0]
usage_tables = {}
current_usage = 0;
current_usage_table = nil
File.open(usb_hid_usages).each_line do |line|
next if line =~ /^\s*#/
next if line =~ /^\s*$/
if (line =~ /^(\d+)\s+(.*)\s*$/)
current_usage = $1.to_i
usage_description = $2
current_usage_table = {'usages' => {}, 'ranges' => {}}
current_usage_table['description'] = usage_description
usage_tables[current_usage] = current_usage_table
elsif (line =~ /^\s+(\S+)\s+(.*)\s*$/)
usage_page = $1
usage_page_description = $2
if (usage_page =~ /^0x((?:\d|[a-fA-F])+)$/)
usage_page = $1.hex
current_usage_table['usages'][usage_page] = usage_page_description
elsif (usage_page =~ /^0x((?:\d|[a-fA-F])+)-((?:\d|[a-fA-F])+)$/)
range_start = $1.hex
range_end = $2.hex
range = "{#{range_start}, #{range_end}}";
current_usage_table['ranges'][range] = usage_page_description
elsif (usage_page == '*')
current_usage_table['default'] = usage_page_description
else
puts "Uknown page: #{usage_page}"
end
end
end
puts Plist.dump(usage_tables)

View File

@ -0,0 +1,103 @@
/***************************************************************************//**
NSXReturnThrowError.h
Copyright (c) 2007 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
Some rights reserved: <http://opensource.org/licenses/mit-license.php>
@section Overview
NSXReturnThrowError does two things:
1. Eases wrapping error codes into NSError objects.
2. Enhances NSError by adding origin information to the error instance.
Origin information includes the actual line of code that returned
the error, as well as the file+line+function/method name.
A big NSXReturnThrowError feature is that it deduces the correct NSError
error domain based on the wrapped code's return type+value. Bonus: it
does so without requiring ObjC++, relying on \@encode acrobatics
instead.
NSXReturnThrowError was coded against 10.4, but should be compatible
with 10.3 as well. However that's currently untested.
@section Usage
NSXReturnThrowError handles both types of error handling: explicit
returning of NSError objects and raising NSExceptions.
Use NSXReturnError() if you're returning NSError objects explicitly:
@code
- (id)demoReturnError:(NSError**)error_ {
id result = nil;
NSError *error = nil;
NSXReturnError(SomeCarbonFunction());
if (!error)
NSXReturnError(someposixfunction());
if (!error)
NSXReturnError(some_mach_function());
if (!error)
NSXReturnError([SomeCocoaClass sharedInstance]);
if (error_) *error_ = error;
return result;
}
@endcode
Use NSXThrowError() if you'd prefer to raise NSException objects:
@code
- (id)demo {
id result = nil;
NSXThrowError(SomeCarbonFunction());
NSXThrowError(someposixfunction());
NSXThrowError(some_mach_function());
NSXThrowError([SomeCocoaClass newObject]);
return result;
}
@endcode
The current structure of the raised NSException object is that it's a
normal NSException whose name is "NSError". The actual error object is
hung off the exception's userInfo dictionary with the key of @"error".
@mainpage NSXReturnThrowError
@todo Add a compile-time flag for whether to stuff __FILE__+friends
info into the generated NSError or not.
***************************************************************************/
#import <Foundation/Foundation.h>
extern NSString *NSXErrorExceptionName;
extern NSString *NULLPointerErrorDomain;
extern NSString *BOOLErrorDomain;
void NSXMakeErrorImp(const char *objCType_, intptr_t result_, const char *file_, unsigned line_, const char *function_, const char *code_, NSError **error_);
#define NSXMakeError(ERROR, CODE) \
do{ \
typeof(CODE) codeResult = (CODE); \
NSXMakeErrorImp(@encode(typeof(CODE)), (intptr_t)codeResult, __FILE__, __LINE__, __PRETTY_FUNCTION__, #CODE, &ERROR); \
}while(0)
#define NSXReturnError(CODE) NSXMakeError(error, CODE)
#define NSXRaiseError(ERROR) \
[[NSException exceptionWithName:NSXErrorExceptionName \
reason:[error description] \
userInfo:[NSDictionary dictionaryWithObject:error forKey:@"error"]] raise];
#define NSXThrowError(CODE) \
do{ \
NSError *error = nil; \
NSXReturnError(CODE); \
if (error) { \
NSXRaiseError(ERROR); \
} \
}while(0)

View File

@ -0,0 +1,106 @@
/*******************************************************************************
NSXReturnThrowError.m
Copyright (c) 2007 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
Some rights reserved: <http://opensource.org/licenses/mit-license.php>
***************************************************************************/
#import "NSXReturnThrowError.h"
NSString *NSXErrorExceptionName = @"NSXError";
NSString *NULLPointerErrorDomain = @"NULLPointerErrorDomain";
NSString *BOOLErrorDomain = @"BOOLErrorDomain";
typedef enum {
NSXErrorCodeType_Unknown,
NSXErrorCodeType_Cocoa, // "@"
NSXErrorCodeType_PosixOrMach, // "i" (-1 == posix+errno, otherwise mach)
NSXErrorCodeType_Carbon, // "s" || "l"
NSXErrorCodeType_ptr, // "r*" || "*" || "^"
NSXErrorCodeType_BOOL // "c"
} NSXErrorCodeType;
static NSXErrorCodeType NSXErrorCodeTypeFromObjCType(const char *objCType) {
switch (objCType[0]) {
case 's':
case 'l':
return NSXErrorCodeType_Carbon;
case 'i':
return NSXErrorCodeType_PosixOrMach;
case '@':
return NSXErrorCodeType_Cocoa;
case '^':
case '*':
return NSXErrorCodeType_ptr;
case 'r':
return '*' == objCType[1] ? NSXErrorCodeType_ptr : NSXErrorCodeType_Unknown;
case 'c':
return NSXErrorCodeType_BOOL;
default:
return NSXErrorCodeType_Unknown;
}
}
void NSXMakeErrorImp(const char *objCType_, intptr_t result_, const char *file_, unsigned line_, const char *function_, const char *code_, NSError **error_) {
NSString *errorDomain = nil;
int errorCode = (int)result_;
switch (NSXErrorCodeTypeFromObjCType(objCType_)) {
case NSXErrorCodeType_Cocoa:
// codeResult's type is an id/NSObject* pointer. 0 == nil == failure.
if (0 == result_) {
errorDomain = @"NSCocoaErrorDomain"; // Could use NSCocoaErrorDomain symbol, but that would force us to 10.4.
errorCode = -1;
}
break;
case NSXErrorCodeType_Carbon:
// codeResult's type is OSErr (short) or OSStatus (long). 0 == noErr == success.
if (0 != result_) {
errorDomain = NSOSStatusErrorDomain;
}
break;
case NSXErrorCodeType_PosixOrMach:
// codeResult's type is int, which is used for both posix error codes and mach_error_t/kern_return_t.
// 0 means success for both, and we can differentiate posix error codes since they're always -1 (the
// actual posix code stored in errno).
if (0 != result_) {
if (-1 == result_) {
// Posix error code.
errorDomain = NSPOSIXErrorDomain;
errorCode = errno;
} else {
// Mach error code.
errorDomain = NSMachErrorDomain;
}
}
break;
case NSXErrorCodeType_ptr:
// codeResult's type is some sort of non-id/non-NSObject* pointer. 0 == NULL == failure.
if (0 == result_) {
errorDomain = NULLPointerErrorDomain;
errorCode = -1;
}
break;
case NSXErrorCodeType_BOOL:
// codeResult's type is a BOOL. 0 == NO == failure.
if (0 == result_) {
errorDomain = BOOLErrorDomain;
errorCode = -1;
}
break;
default:
NSCAssert1(NO, @"NSXErrorCodeType_Unknown: \"%s\"", objCType_);
break;
}
if (errorDomain && error_) {
*error_ = [NSError errorWithDomain:errorDomain
code:errorCode
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithUTF8String:file_], @"reportingFile",
[NSNumber numberWithInt:line_], @"reportingLine",
[NSString stringWithUTF8String:function_], @"reportingMethod",
[NSString stringWithUTF8String:code_], @"origin",
nil]];
}
}

2
versions.xcconfig Normal file
View File

@ -0,0 +1,2 @@
CURRENT_MARKETING_VERSION = 1.1.1
CURRENT_PROJECT_VERSION = 1010.9.0