├── HidSample.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── alexander.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── HidSample.xcscheme └── project.pbxproj ├── HidSample ├── HidSample-Prefix.pch ├── HidSample.1 ├── HidUtils.h └── main.m └── config.h /HidSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HidSample/HidSample-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | // 2 | // config.h 3 | // HidSample 4 | // 5 | // Created by Alexander Tarasikov on 23.11.13. 6 | // Copyright (c) 2013 Alexander Tarasikov. All rights reserved. 7 | // 8 | 9 | #ifndef HidSample_config_h 10 | #define HidSample_config_h 11 | 12 | #define TOUCH_REPORT 1 13 | 14 | #define NUM_TOUCHES 1 15 | 16 | #define TOUCH_VID 0x596 17 | #define TOUCH_PID 0x524 18 | 19 | #define SCREEN_RESX 1920 20 | #define SCREEN_RESY 1080 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /HidSample.xcodeproj/xcuserdata/alexander.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HidSample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 113F64D5183E93B20041DE1B 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /HidSample/HidSample.1: -------------------------------------------------------------------------------- 1 | .\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. 2 | .\"See Also: 3 | .\"man mdoc.samples for a complete listing of options 4 | .\"man mdoc for the short list of editing options 5 | .\"/usr/share/misc/mdoc.template 6 | .Dd 21.11.13 \" DATE 7 | .Dt HidSample 1 \" Program name and manual section number 8 | .Os Darwin 9 | .Sh NAME \" Section Header - required - don't modify 10 | .Nm HidSample, 11 | .\" The following lines are read in generating the apropos(man -k) database. Use only key 12 | .\" words here as the database is built based on the words here and in the .ND line. 13 | .Nm Other_name_for_same_program(), 14 | .Nm Yet another name for the same program. 15 | .\" Use .Nm macro to designate other names for the documented program. 16 | .Nd This line parsed for whatis database. 17 | .Sh SYNOPSIS \" Section Header - required - don't modify 18 | .Nm 19 | .Op Fl abcd \" [-abcd] 20 | .Op Fl a Ar path \" [-a path] 21 | .Op Ar file \" [file] 22 | .Op Ar \" [file ...] 23 | .Ar arg0 \" Underlined argument - use .Ar anywhere to underline 24 | arg2 ... \" Arguments 25 | .Sh DESCRIPTION \" Section Header - required - don't modify 26 | Use the .Nm macro to refer to your program throughout the man page like such: 27 | .Nm 28 | Underlining is accomplished with the .Ar macro like this: 29 | .Ar underlined text . 30 | .Pp \" Inserts a space 31 | A list of items with descriptions: 32 | .Bl -tag -width -indent \" Begins a tagged list 33 | .It item a \" Each item preceded by .It macro 34 | Description of item a 35 | .It item b 36 | Description of item b 37 | .El \" Ends the list 38 | .Pp 39 | A list of flags and their descriptions: 40 | .Bl -tag -width -indent \" Differs from above in tag removed 41 | .It Fl a \"-a flag as a list item 42 | Description of -a flag 43 | .It Fl b 44 | Description of -b flag 45 | .El \" Ends the list 46 | .Pp 47 | .\" .Sh ENVIRONMENT \" May not be needed 48 | .\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 49 | .\" .It Ev ENV_VAR_1 50 | .\" Description of ENV_VAR_1 51 | .\" .It Ev ENV_VAR_2 52 | .\" Description of ENV_VAR_2 53 | .\" .El 54 | .Sh FILES \" File used or created by the topic of the man page 55 | .Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact 56 | .It Pa /usr/share/file_name 57 | FILE_1 description 58 | .It Pa /Users/joeuser/Library/really_long_file_name 59 | FILE_2 description 60 | .El \" Ends the list 61 | .\" .Sh DIAGNOSTICS \" May not be needed 62 | .\" .Bl -diag 63 | .\" .It Diagnostic Tag 64 | .\" Diagnostic informtion here. 65 | .\" .It Diagnostic Tag 66 | .\" Diagnostic informtion here. 67 | .\" .El 68 | .Sh SEE ALSO 69 | .\" List links in ascending order by section, alphabetically within a section. 70 | .\" Please do not reference files that do not exist without filing a bug report 71 | .Xr a 1 , 72 | .Xr b 1 , 73 | .Xr c 1 , 74 | .Xr a 2 , 75 | .Xr b 2 , 76 | .Xr a 3 , 77 | .Xr b 3 78 | .\" .Sh BUGS \" Document known, unremedied bugs 79 | .\" .Sh HISTORY \" Document history if command behaves in a unique manner -------------------------------------------------------------------------------- /HidSample.xcodeproj/xcuserdata/alexander.xcuserdatad/xcschemes/HidSample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /HidSample/HidUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // HidUtils.h 3 | // HidSample 4 | // 5 | // Created by Alexander Tarasikov on 23.11.13. 6 | // Copyright (c) 2013 Alexander Tarasikov. All rights reserved. 7 | // 8 | 9 | #ifndef HidSample_HidUtils_h 10 | #define HidSample_HidUtils_h 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "config.h" 20 | 21 | typedef enum CalibrationState { 22 | kCalibrationStateInactive = 0, 23 | kCalibrationStateTopLeft, 24 | kCalibrationStateTopRight, 25 | kCalibrationStateBottomRight, 26 | kCalibrationStateBottomLeft 27 | } CalibrationState; 28 | 29 | typedef struct HIDData 30 | { 31 | io_object_t notification; 32 | IOHIDDeviceInterface122 ** hidDeviceInterface; 33 | IOHIDQueueInterface ** hidQueueInterface; 34 | CFDictionaryRef hidElementDictionary; 35 | CFRunLoopSourceRef eventSource; 36 | CalibrationState state; 37 | SInt32 minx; 38 | SInt32 maxx; 39 | SInt32 miny; 40 | SInt32 maxy; 41 | UInt8 buffer[256]; 42 | } HIDData; 43 | 44 | typedef HIDData * HIDDataRef; 45 | 46 | typedef struct HIDElement { 47 | SInt32 currentValue; 48 | SInt32 usagePage; 49 | SInt32 usage; 50 | IOHIDElementType type; 51 | IOHIDElementCookie cookie; 52 | HIDDataRef owner; 53 | }HIDElement; 54 | typedef HIDElement * HIDElementRef; 55 | 56 | static const char *translateHIDType(IOHIDElementType type) { 57 | switch (type) { 58 | case 1: 59 | return "MISC"; 60 | case 2: 61 | return "Button"; 62 | case 3: 63 | return "Axis"; 64 | case 4: 65 | return "ScanCodes"; 66 | case 129: 67 | return "Output"; 68 | case 257: 69 | return "Feature"; 70 | case 513: 71 | return "Collection"; 72 | 73 | default: 74 | return "unknown"; 75 | break; 76 | } 77 | }; 78 | 79 | static void printHidElement(const char *fname, HIDElement *element) { 80 | if (!element) { 81 | return; 82 | } 83 | 84 | const char *hidType = translateHIDType(element->type); 85 | const char *hidUsage = "unknown"; 86 | 87 | #define USAGE(__page, __usage, name) do {\ 88 | if (element->usagePage == __page && element->usage == __usage) {\ 89 | hidUsage = name;\ 90 | break;\ 91 | } \ 92 | } while (0) 93 | 94 | do { 95 | USAGE(0x1, 0x30, "X"); 96 | USAGE(0x1, 0x31, "Y"); 97 | USAGE(0xd, kHIDUsage_Dig_TouchScreen, "Touchscreen"); 98 | USAGE(0xd, 0x1, "Digitizer"); 99 | USAGE(0xd, 2, "Pen"); 100 | USAGE(0xd, 0x3, "Config"); 101 | USAGE(0xd, 0x20, "stylus"); 102 | USAGE(0xd, 0x22, "finger"); 103 | USAGE(0xd, 0x23, "DevSettings"); 104 | USAGE(0xd, 0x30, "pressure"); 105 | USAGE(0xd, 0x32, "InRange"); 106 | USAGE(0xd, kHIDUsage_Dig_Touch, "Touch"); 107 | USAGE(0xd, 0x3c, "Invert"); 108 | USAGE(0xd, 0x3f, "Azimuth"); 109 | USAGE(0xd, 0x42, "TipSwitch"); 110 | USAGE(0xd, 0x47, "Confidence"); 111 | USAGE(0xd, 0x48, "MT Widght"); 112 | USAGE(0xd, 0x49, "MT Height"); 113 | USAGE(0xd, 0x51, "ContactID"); 114 | USAGE(0xd, 0x53, "DevIndex"); 115 | USAGE(0xd, 0x54, "TouchCount"); 116 | USAGE(0xd, 0x55, "Contact Count Maximum"); 117 | USAGE(0xd, 0x56, "ScanTime"); 118 | } while (0); 119 | 120 | #undef USAGE 121 | 122 | #if TOUCH_REPORT 123 | printf("[%s]: <%x:%x> [%s] %s=0x%x (%d)\n", 124 | fname ? fname : "unknown", 125 | element->usagePage, element->usage, 126 | hidType, 127 | hidUsage, 128 | element->currentValue, 129 | element->currentValue); 130 | fflush(stdout); 131 | #endif 132 | } 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /HidSample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 113D4CE0183FFFC30051122B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 113D4CDF183FFFC30051122B /* CoreFoundation.framework */; }; 11 | 113D4CE2183FFFC60051122B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 113D4CE1183FFFC60051122B /* IOKit.framework */; }; 12 | 113D4CE4184000800051122B /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 113D4CE3184000800051122B /* ApplicationServices.framework */; }; 13 | 113F64DA183E93B20041DE1B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 113F64D9183E93B20041DE1B /* Foundation.framework */; }; 14 | 113F64DD183E93B20041DE1B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 113F64DC183E93B20041DE1B /* main.m */; }; 15 | 113F64E1183E93B20041DE1B /* HidSample.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 113F64E0183E93B20041DE1B /* HidSample.1 */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 113F64D4183E93B20041DE1B /* CopyFiles */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = /usr/share/man/man1/; 23 | dstSubfolderSpec = 0; 24 | files = ( 25 | 113F64E1183E93B20041DE1B /* HidSample.1 in CopyFiles */, 26 | ); 27 | runOnlyForDeploymentPostprocessing = 1; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 113D4CDF183FFFC30051122B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 33 | 113D4CE1183FFFC60051122B /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 34 | 113D4CE3184000800051122B /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; }; 35 | 113D4CE51840DF7A0051122B /* config.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../config.h; sourceTree = ""; }; 36 | 113D4CE61840E8600051122B /* HidUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HidUtils.h; sourceTree = ""; }; 37 | 113D4CE71842AE330051122B /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; 38 | 113F64D6183E93B20041DE1B /* HidSample */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = HidSample; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | 113F64D9183E93B20041DE1B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 40 | 113F64DC183E93B20041DE1B /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 41 | 113F64DF183E93B20041DE1B /* HidSample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HidSample-Prefix.pch"; sourceTree = ""; }; 42 | 113F64E0183E93B20041DE1B /* HidSample.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = HidSample.1; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | 113F64D3183E93B20041DE1B /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | 113D4CE4184000800051122B /* ApplicationServices.framework in Frameworks */, 51 | 113D4CE2183FFFC60051122B /* IOKit.framework in Frameworks */, 52 | 113D4CE0183FFFC30051122B /* CoreFoundation.framework in Frameworks */, 53 | 113F64DA183E93B20041DE1B /* Foundation.framework in Frameworks */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | 113F64CD183E93B20041DE1B = { 61 | isa = PBXGroup; 62 | children = ( 63 | 113F64DB183E93B20041DE1B /* HidSample */, 64 | 113F64D8183E93B20041DE1B /* Frameworks */, 65 | 113F64D7183E93B20041DE1B /* Products */, 66 | ); 67 | sourceTree = ""; 68 | }; 69 | 113F64D7183E93B20041DE1B /* Products */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 113F64D6183E93B20041DE1B /* HidSample */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | 113F64D8183E93B20041DE1B /* Frameworks */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 113D4CE71842AE330051122B /* Cocoa.framework */, 81 | 113D4CE3184000800051122B /* ApplicationServices.framework */, 82 | 113D4CE1183FFFC60051122B /* IOKit.framework */, 83 | 113D4CDF183FFFC30051122B /* CoreFoundation.framework */, 84 | 113F64D9183E93B20041DE1B /* Foundation.framework */, 85 | ); 86 | name = Frameworks; 87 | sourceTree = ""; 88 | }; 89 | 113F64DB183E93B20041DE1B /* HidSample */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 113D4CE51840DF7A0051122B /* config.h */, 93 | 113D4CE61840E8600051122B /* HidUtils.h */, 94 | 113F64DC183E93B20041DE1B /* main.m */, 95 | 113F64E0183E93B20041DE1B /* HidSample.1 */, 96 | 113F64DE183E93B20041DE1B /* Supporting Files */, 97 | ); 98 | path = HidSample; 99 | sourceTree = ""; 100 | }; 101 | 113F64DE183E93B20041DE1B /* Supporting Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 113F64DF183E93B20041DE1B /* HidSample-Prefix.pch */, 105 | ); 106 | name = "Supporting Files"; 107 | sourceTree = ""; 108 | }; 109 | /* End PBXGroup section */ 110 | 111 | /* Begin PBXNativeTarget section */ 112 | 113F64D5183E93B20041DE1B /* HidSample */ = { 113 | isa = PBXNativeTarget; 114 | buildConfigurationList = 113F64E4183E93B20041DE1B /* Build configuration list for PBXNativeTarget "HidSample" */; 115 | buildPhases = ( 116 | 113F64D2183E93B20041DE1B /* Sources */, 117 | 113F64D3183E93B20041DE1B /* Frameworks */, 118 | 113F64D4183E93B20041DE1B /* CopyFiles */, 119 | ); 120 | buildRules = ( 121 | ); 122 | dependencies = ( 123 | ); 124 | name = HidSample; 125 | productName = HidSample; 126 | productReference = 113F64D6183E93B20041DE1B /* HidSample */; 127 | productType = "com.apple.product-type.tool"; 128 | }; 129 | /* End PBXNativeTarget section */ 130 | 131 | /* Begin PBXProject section */ 132 | 113F64CE183E93B20041DE1B /* Project object */ = { 133 | isa = PBXProject; 134 | attributes = { 135 | LastUpgradeCheck = 0500; 136 | ORGANIZATIONNAME = "Alexander Tarasikov"; 137 | }; 138 | buildConfigurationList = 113F64D1183E93B20041DE1B /* Build configuration list for PBXProject "HidSample" */; 139 | compatibilityVersion = "Xcode 3.2"; 140 | developmentRegion = English; 141 | hasScannedForEncodings = 0; 142 | knownRegions = ( 143 | en, 144 | ); 145 | mainGroup = 113F64CD183E93B20041DE1B; 146 | productRefGroup = 113F64D7183E93B20041DE1B /* Products */; 147 | projectDirPath = ""; 148 | projectRoot = ""; 149 | targets = ( 150 | 113F64D5183E93B20041DE1B /* HidSample */, 151 | ); 152 | }; 153 | /* End PBXProject section */ 154 | 155 | /* Begin PBXSourcesBuildPhase section */ 156 | 113F64D2183E93B20041DE1B /* Sources */ = { 157 | isa = PBXSourcesBuildPhase; 158 | buildActionMask = 2147483647; 159 | files = ( 160 | 113F64DD183E93B20041DE1B /* main.m in Sources */, 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | /* End PBXSourcesBuildPhase section */ 165 | 166 | /* Begin XCBuildConfiguration section */ 167 | 113F64E2183E93B20041DE1B /* Debug */ = { 168 | isa = XCBuildConfiguration; 169 | buildSettings = { 170 | ALWAYS_SEARCH_USER_PATHS = NO; 171 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 172 | CLANG_CXX_LIBRARY = "libc++"; 173 | CLANG_ENABLE_OBJC_ARC = YES; 174 | CLANG_WARN_BOOL_CONVERSION = YES; 175 | CLANG_WARN_CONSTANT_CONVERSION = YES; 176 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 177 | CLANG_WARN_EMPTY_BODY = YES; 178 | CLANG_WARN_ENUM_CONVERSION = YES; 179 | CLANG_WARN_INT_CONVERSION = YES; 180 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 181 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 182 | COPY_PHASE_STRIP = NO; 183 | GCC_C_LANGUAGE_STANDARD = gnu99; 184 | GCC_DYNAMIC_NO_PIC = NO; 185 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 186 | GCC_OPTIMIZATION_LEVEL = 0; 187 | GCC_PREPROCESSOR_DEFINITIONS = ( 188 | "DEBUG=1", 189 | "$(inherited)", 190 | ); 191 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 192 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 193 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 194 | GCC_WARN_UNDECLARED_SELECTOR = YES; 195 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 196 | GCC_WARN_UNUSED_FUNCTION = YES; 197 | GCC_WARN_UNUSED_VARIABLE = YES; 198 | MACOSX_DEPLOYMENT_TARGET = 10.9; 199 | ONLY_ACTIVE_ARCH = YES; 200 | SDKROOT = macosx; 201 | }; 202 | name = Debug; 203 | }; 204 | 113F64E3183E93B20041DE1B /* Release */ = { 205 | isa = XCBuildConfiguration; 206 | buildSettings = { 207 | ALWAYS_SEARCH_USER_PATHS = NO; 208 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 209 | CLANG_CXX_LIBRARY = "libc++"; 210 | CLANG_ENABLE_OBJC_ARC = YES; 211 | CLANG_WARN_BOOL_CONVERSION = YES; 212 | CLANG_WARN_CONSTANT_CONVERSION = YES; 213 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 214 | CLANG_WARN_EMPTY_BODY = YES; 215 | CLANG_WARN_ENUM_CONVERSION = YES; 216 | CLANG_WARN_INT_CONVERSION = YES; 217 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 218 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 219 | COPY_PHASE_STRIP = YES; 220 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 221 | ENABLE_NS_ASSERTIONS = NO; 222 | GCC_C_LANGUAGE_STANDARD = gnu99; 223 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 224 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 225 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 226 | GCC_WARN_UNDECLARED_SELECTOR = YES; 227 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 228 | GCC_WARN_UNUSED_FUNCTION = YES; 229 | GCC_WARN_UNUSED_VARIABLE = YES; 230 | MACOSX_DEPLOYMENT_TARGET = 10.9; 231 | SDKROOT = macosx; 232 | }; 233 | name = Release; 234 | }; 235 | 113F64E5183E93B20041DE1B /* Debug */ = { 236 | isa = XCBuildConfiguration; 237 | buildSettings = { 238 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 239 | GCC_PREFIX_HEADER = "HidSample/HidSample-Prefix.pch"; 240 | PRODUCT_NAME = "$(TARGET_NAME)"; 241 | SDKROOT = macosx10.8; 242 | }; 243 | name = Debug; 244 | }; 245 | 113F64E6183E93B20041DE1B /* Release */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 249 | GCC_PREFIX_HEADER = "HidSample/HidSample-Prefix.pch"; 250 | "INFOPLIST_FILE[sdk=macosx10.8]" = ""; 251 | PRODUCT_NAME = "$(TARGET_NAME)"; 252 | SDKROOT = macosx10.8; 253 | }; 254 | name = Release; 255 | }; 256 | /* End XCBuildConfiguration section */ 257 | 258 | /* Begin XCConfigurationList section */ 259 | 113F64D1183E93B20041DE1B /* Build configuration list for PBXProject "HidSample" */ = { 260 | isa = XCConfigurationList; 261 | buildConfigurations = ( 262 | 113F64E2183E93B20041DE1B /* Debug */, 263 | 113F64E3183E93B20041DE1B /* Release */, 264 | ); 265 | defaultConfigurationIsVisible = 0; 266 | defaultConfigurationName = Release; 267 | }; 268 | 113F64E4183E93B20041DE1B /* Build configuration list for PBXNativeTarget "HidSample" */ = { 269 | isa = XCConfigurationList; 270 | buildConfigurations = ( 271 | 113F64E5183E93B20041DE1B /* Debug */, 272 | 113F64E6183E93B20041DE1B /* Release */, 273 | ); 274 | defaultConfigurationIsVisible = 0; 275 | defaultConfigurationName = Release; 276 | }; 277 | /* End XCConfigurationList section */ 278 | }; 279 | rootObject = 113F64CE183E93B20041DE1B /* Project object */; 280 | } 281 | -------------------------------------------------------------------------------- /HidSample/main.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "config.h" 10 | #include "HidUtils.h" 11 | 12 | //--------------------------------------------------------------------------- 13 | // Globals 14 | //--------------------------------------------------------------------------- 15 | static IONotificationPortRef gNotifyPort = NULL; 16 | static io_iterator_t gAddedIter = 0; 17 | static NSLock *gLock = 0; 18 | 19 | //--------------------------------------------------------------------------- 20 | // TypeDefs 21 | //--------------------------------------------------------------------------- 22 | 23 | typedef enum { 24 | UP, 25 | DOWN, 26 | NO_CHANGE, 27 | } ButtonState; 28 | 29 | static void simulateClick(int x, int y, ButtonState button) { 30 | printf("CLICK %d %d %d\n", x, y, button); 31 | static int eventNumber = 0; 32 | if (button == DOWN) { 33 | CGEventRef move = CGEventCreateMouseEvent(NULL, 34 | kCGEventLeftMouseDown, 35 | CGPointMake(x, y), 36 | kCGMouseButtonLeft); 37 | CGEventSetIntegerValueField(move, kCGMouseEventNumber, eventNumber); 38 | CGEventPost(kCGHIDEventTap, move); 39 | CFRelease(move); 40 | eventNumber++; 41 | } 42 | else if (button == UP) { 43 | CGEventRef move_up = CGEventCreateMouseEvent(NULL, 44 | kCGEventLeftMouseUp, 45 | CGPointMake(x, y), 46 | kCGMouseButtonLeft); 47 | CGEventSetIntegerValueField(move_up, kCGMouseEventNumber, eventNumber); 48 | CGEventPost(kCGHIDEventTap, move_up); 49 | CFRelease(move_up); 50 | //eventNumber++; 51 | } 52 | if (button == NO_CHANGE) { 53 | CGEventRef move = CGEventCreateMouseEvent(NULL, 54 | kCGEventLeftMouseDragged, 55 | CGPointMake(x, y), 56 | kCGMouseButtonLeft); 57 | CGEventSetIntegerValueField(move, kCGMouseEventNumber, eventNumber); 58 | CGEventPost(kCGHIDEventTap, move); 59 | CFRelease(move); 60 | //eventNumber++; 61 | } 62 | } 63 | 64 | static void submitTouch(int fingerId, int x, int y, ButtonState button) { 65 | printf("%s: <%d, %d> state=%d\n", __func__, x, y, button); 66 | static int last_x[NUM_TOUCHES] = { 67 | 0, 68 | }; 69 | static int last_y[NUM_TOUCHES] = { 70 | 0, 71 | }; 72 | 73 | if (button == DOWN || button == UP) { 74 | if (last_x[fingerId] >0 && last_y[fingerId] > 0) { 75 | printf("last <%d %d>\n", last_x[fingerId], last_y[fingerId]); 76 | simulateClick(last_x[fingerId], last_y[fingerId], button); 77 | last_x[fingerId] = last_y[fingerId] = -1; 78 | } 79 | } 80 | else { 81 | if (x > 0) { 82 | last_x[fingerId] = x; 83 | } 84 | if (y > 0) { 85 | last_y[fingerId] = y; 86 | } 87 | if (last_x[fingerId] > 0 && last_y[fingerId] > 0) { 88 | simulateClick(last_x[fingerId], last_y[fingerId], NO_CHANGE); 89 | } 90 | } 91 | } 92 | 93 | static bool acceptHidElement(HIDElement *element) { 94 | printHidElement("acceptHidElement", element); 95 | 96 | switch (element->usagePage) { 97 | case kHIDPage_GenericDesktop: 98 | switch (element->usage) { 99 | case kHIDUsage_GD_X: 100 | case kHIDUsage_GD_Y: 101 | return true; 102 | } 103 | break; 104 | case kHIDPage_Button: 105 | switch (element->usage) { 106 | case kHIDUsage_Button_1: 107 | return true; 108 | break; 109 | } 110 | break; 111 | case kHIDPage_Digitizer: 112 | return true; 113 | break; 114 | } 115 | 116 | return false; 117 | } 118 | 119 | static void reportHidElement(HIDElement *element) { 120 | if (!element) { 121 | return; 122 | } 123 | 124 | [gLock lock]; 125 | 126 | printf("\n+++++++++++\n"); 127 | printHidElement("report element", element); 128 | printf("------------\n"); 129 | 130 | static int fingerId = 0; 131 | static ButtonState button = NO_CHANGE; 132 | 133 | //button 134 | if (element->type == 2) { 135 | button = element->currentValue ? DOWN : UP; 136 | submitTouch(fingerId, 0, 0, button); 137 | } 138 | else { 139 | button = NO_CHANGE; 140 | } 141 | 142 | if (element->usagePage == 0xd && element->usage == 0x22) { 143 | //fingerId = element->currentValue; 144 | } 145 | 146 | if (element->usagePage == 1 && element->currentValue < 0x10000) { 147 | float scale_x = SCREEN_RESX / 32768.0f; 148 | float scale_y = SCREEN_RESY / 32768.0f; 149 | 150 | short value = element->currentValue & 0xffff; 151 | 152 | if (element->usage == kHIDUsage_GD_X) { 153 | int x = (int)(value * scale_x); 154 | submitTouch(fingerId, x, 0, NO_CHANGE); 155 | } 156 | else if (element->usage == kHIDUsage_GD_Y) { 157 | int y = (int)(value * scale_y); 158 | submitTouch(fingerId, 0, y, NO_CHANGE); 159 | } 160 | } 161 | 162 | [gLock unlock]; 163 | } 164 | 165 | #ifndef max 166 | #define max(a, b) \ 167 | ((a > b) ? a:b) 168 | #endif 169 | 170 | #ifndef min 171 | #define min(a, b) \ 172 | ((a < b) ? a:b) 173 | #endif 174 | 175 | //--------------------------------------------------------------------------- 176 | // Methods 177 | //--------------------------------------------------------------------------- 178 | static void InitHIDNotifications(); 179 | static void HIDDeviceAdded(void *refCon, io_iterator_t iterator); 180 | static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument); 181 | static bool FindHIDElements(HIDDataRef hidDataRef); 182 | static bool SetupQueue(HIDDataRef hidDataRef); 183 | static void QueueCallbackFunction( 184 | void * target, 185 | IOReturn result, 186 | void * refcon, 187 | void * sender); 188 | 189 | int main (int argc, const char * argv[]) { 190 | gLock = [[NSLock alloc] init]; 191 | InitHIDNotifications(TOUCH_VID, TOUCH_PID); 192 | CFRunLoopRun(); 193 | 194 | return 0; 195 | } 196 | 197 | 198 | //--------------------------------------------------------------------------- 199 | // InitHIDNotifications 200 | // 201 | // This routine just creates our master port for IOKit and turns around 202 | // and calls the routine that will alert us when a HID Device is plugged in. 203 | //--------------------------------------------------------------------------- 204 | 205 | static void InitHIDNotifications(SInt32 vendorID, SInt32 productID) 206 | { 207 | CFMutableDictionaryRef matchingDict; 208 | CFNumberRef refProdID; 209 | CFNumberRef refVendorID; 210 | mach_port_t masterPort; 211 | kern_return_t kr; 212 | 213 | // first create a master_port for my task 214 | // 215 | kr = IOMasterPort(bootstrap_port, &masterPort); 216 | if (kr || !masterPort) 217 | return; 218 | 219 | // Create a notification port and add its run loop event source to our run loop 220 | // This is how async notifications get set up. 221 | // 222 | gNotifyPort = IONotificationPortCreate(masterPort); 223 | CFRunLoopAddSource( CFRunLoopGetCurrent(), 224 | IONotificationPortGetRunLoopSource(gNotifyPort), 225 | kCFRunLoopDefaultMode); 226 | 227 | // Create the IOKit notifications that we need 228 | // 229 | /* Create a matching dictionary that (initially) matches all HID devices. */ 230 | matchingDict = IOServiceMatching(kIOHIDDeviceKey); 231 | 232 | if (!matchingDict) 233 | return; 234 | 235 | /* Create objects for product and vendor IDs. */ 236 | refProdID = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &productID); 237 | refVendorID = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &vendorID); 238 | 239 | /* Add objects to matching dictionary and clean up. */ 240 | CFDictionarySetValue (matchingDict, CFSTR (kIOHIDVendorIDKey), refVendorID); 241 | CFDictionarySetValue (matchingDict, CFSTR (kIOHIDProductIDKey), refProdID); 242 | 243 | CFRelease(refProdID); 244 | CFRelease(refVendorID); 245 | 246 | // Now set up a notification to be called when a device is first matched by I/O Kit. 247 | // Note that this will not catch any devices that were already plugged in so we take 248 | // care of those later. 249 | kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort 250 | kIOFirstMatchNotification, // notificationType 251 | matchingDict, // matching 252 | HIDDeviceAdded, // callback 253 | NULL, // refCon 254 | &gAddedIter // notification 255 | ); 256 | 257 | if (kr != kIOReturnSuccess) 258 | return; 259 | 260 | HIDDeviceAdded(NULL, gAddedIter); 261 | } 262 | 263 | //--------------------------------------------------------------------------- 264 | // HIDDeviceAdded 265 | // 266 | // This routine is the callback for our IOServiceAddMatchingNotification. 267 | // When we get called we will look at all the devices that were added and 268 | // we will: 269 | // 270 | // Create some private data to relate to each device 271 | // 272 | // Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for 273 | // this device using the refCon field to store a pointer to our private data. 274 | // When we get called with this interest notification, we can grab the refCon 275 | // and access our private data. 276 | //--------------------------------------------------------------------------- 277 | 278 | static void HIDDeviceAdded(void *refCon, io_iterator_t iterator) 279 | { 280 | io_object_t hidDevice = 0; 281 | IOCFPlugInInterface ** plugInInterface = NULL; 282 | IOHIDDeviceInterface122 ** hidDeviceInterface = NULL; 283 | HRESULT result = S_FALSE; 284 | HIDDataRef hidDataRef = NULL; 285 | IOReturn kr; 286 | SInt32 score; 287 | bool pass; 288 | 289 | /* Interate through all the devices that matched */ 290 | while (0 != (hidDevice = IOIteratorNext(iterator))) 291 | { 292 | // Create the CF plugin for this device 293 | kr = IOCreatePlugInInterfaceForService(hidDevice, kIOHIDDeviceUserClientTypeID, 294 | kIOCFPlugInInterfaceID, &plugInInterface, &score); 295 | 296 | if (kr != kIOReturnSuccess) 297 | goto HIDDEVICEADDED_NONPLUGIN_CLEANUP; 298 | 299 | /* Obtain a device interface structure (hidDeviceInterface). */ 300 | result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID122), 301 | (LPVOID *)&hidDeviceInterface); 302 | 303 | // Got the interface 304 | if ((result == S_OK) && hidDeviceInterface) 305 | { 306 | /* Create a custom object to keep data around for later. */ 307 | hidDataRef = malloc(sizeof(HIDData)); 308 | bzero(hidDataRef, sizeof(HIDData)); 309 | 310 | hidDataRef->hidDeviceInterface = hidDeviceInterface; 311 | 312 | /* Open the device interface. */ 313 | result = (*(hidDataRef->hidDeviceInterface))->open (hidDataRef->hidDeviceInterface, kIOHIDOptionsTypeSeizeDevice); 314 | 315 | if (result != S_OK) 316 | goto HIDDEVICEADDED_FAIL; 317 | 318 | /* Find the HID elements for this device and set up a receive queue. */ 319 | pass = FindHIDElements(hidDataRef); 320 | pass = SetupQueue(hidDataRef); 321 | 322 | printf("Please touch screen to continue.\n\n"); 323 | 324 | 325 | /* Register an interest in finding out anything that happens with this device (disconnection, for example) */ 326 | IOServiceAddInterestNotification( 327 | gNotifyPort, // notifyPort 328 | hidDevice, // service 329 | kIOGeneralInterest, // interestType 330 | DeviceNotification, // callback 331 | hidDataRef, // refCon 332 | &(hidDataRef->notification) // notification 333 | ); 334 | 335 | goto HIDDEVICEADDED_CLEANUP; 336 | } 337 | 338 | HIDDEVICEADDED_FAIL: 339 | // Failed to allocated a UPS interface. Do some cleanup 340 | if (hidDeviceInterface) 341 | { 342 | (*hidDeviceInterface)->Release(hidDeviceInterface); 343 | hidDeviceInterface = NULL; 344 | } 345 | 346 | if (hidDataRef) 347 | free (hidDataRef); 348 | 349 | HIDDEVICEADDED_CLEANUP: 350 | // Clean up 351 | (*plugInInterface)->Release(plugInInterface); 352 | 353 | HIDDEVICEADDED_NONPLUGIN_CLEANUP: 354 | IOObjectRelease(hidDevice); 355 | } 356 | } 357 | 358 | //--------------------------------------------------------------------------- 359 | // DeviceNotification 360 | // 361 | // This routine will get called whenever any kIOGeneralInterest notification 362 | // happens. 363 | //--------------------------------------------------------------------------- 364 | 365 | static void DeviceNotification(void * refCon, 366 | io_service_t service, 367 | natural_t messageType, 368 | void * messageArgument) 369 | { 370 | kern_return_t kr; 371 | HIDDataRef hidDataRef = (HIDDataRef) refCon; 372 | 373 | /* Check to see if a device went away and clean up. */ 374 | if ((hidDataRef != NULL) && 375 | (messageType == kIOMessageServiceIsTerminated)) 376 | { 377 | if (hidDataRef->hidQueueInterface != NULL) 378 | { 379 | kr = (*(hidDataRef->hidQueueInterface))->stop((hidDataRef->hidQueueInterface)); 380 | kr = (*(hidDataRef->hidQueueInterface))->dispose((hidDataRef->hidQueueInterface)); 381 | kr = (*(hidDataRef->hidQueueInterface))->Release (hidDataRef->hidQueueInterface); 382 | hidDataRef->hidQueueInterface = NULL; 383 | } 384 | 385 | if (hidDataRef->hidDeviceInterface != NULL) 386 | { 387 | kr = (*(hidDataRef->hidDeviceInterface))->close (hidDataRef->hidDeviceInterface); 388 | kr = (*(hidDataRef->hidDeviceInterface))->Release (hidDataRef->hidDeviceInterface); 389 | hidDataRef->hidDeviceInterface = NULL; 390 | } 391 | 392 | if (hidDataRef->notification) 393 | { 394 | kr = IOObjectRelease(hidDataRef->notification); 395 | hidDataRef->notification = 0; 396 | } 397 | 398 | } 399 | } 400 | 401 | //--------------------------------------------------------------------------- 402 | // FindHIDElements 403 | //--------------------------------------------------------------------------- 404 | static bool FindHIDElements(HIDDataRef hidDataRef) 405 | { 406 | CFArrayRef elementArray = NULL; 407 | CFMutableDictionaryRef hidElements = NULL; 408 | CFMutableDataRef newData = NULL; 409 | CFNumberRef number = NULL; 410 | CFDictionaryRef element = NULL; 411 | HIDElement newElement; 412 | IOReturn ret = kIOReturnError; 413 | unsigned i; 414 | 415 | if (!hidDataRef) 416 | return false; 417 | 418 | /* Create a mutable dictionary to hold HID elements. */ 419 | hidElements = CFDictionaryCreateMutable( 420 | kCFAllocatorDefault, 421 | 0, 422 | &kCFTypeDictionaryKeyCallBacks, 423 | &kCFTypeDictionaryValueCallBacks); 424 | if (!hidElements) 425 | return false; 426 | 427 | // Let's find the elements 428 | ret = (*hidDataRef->hidDeviceInterface)->copyMatchingElements( 429 | hidDataRef->hidDeviceInterface, 430 | NULL, 431 | &elementArray); 432 | 433 | 434 | if ((ret != kIOReturnSuccess) || !elementArray) 435 | goto FIND_ELEMENT_CLEANUP; 436 | 437 | //CFShow(elementArray); 438 | 439 | /* Iterate through the elements and read their values. */ 440 | for (i=0; ihidElementDictionary = hidElements; 503 | } 504 | 505 | return hidDataRef->hidElementDictionary; 506 | } 507 | 508 | //--------------------------------------------------------------------------- 509 | // SetupQueue 510 | //--------------------------------------------------------------------------- 511 | static bool SetupQueue(HIDDataRef hidDataRef) 512 | { 513 | CFIndex count = 0; 514 | CFIndex i = 0; 515 | CFMutableDataRef * elements = NULL; 516 | CFStringRef * keys = NULL; 517 | IOReturn ret; 518 | HIDElementRef tempHIDElement = NULL; 519 | bool cookieAdded = false; 520 | bool boolRet = true; 521 | 522 | if (!hidDataRef->hidElementDictionary || (((count = CFDictionaryGetCount(hidDataRef->hidElementDictionary)) <= 0))) 523 | return false; 524 | 525 | keys = (CFStringRef *)malloc(sizeof(CFStringRef) * count); 526 | elements = (CFMutableDataRef *)malloc(sizeof(CFMutableDataRef) * count); 527 | 528 | CFDictionaryGetKeysAndValues(hidDataRef->hidElementDictionary, (const void **)keys, (const void **)elements); 529 | 530 | hidDataRef->hidQueueInterface = (*hidDataRef->hidDeviceInterface)->allocQueue(hidDataRef->hidDeviceInterface); 531 | if (!hidDataRef->hidQueueInterface) 532 | { 533 | boolRet = false; 534 | goto SETUP_QUEUE_CLEANUP; 535 | } 536 | 537 | ret = (*hidDataRef->hidQueueInterface)->create(hidDataRef->hidQueueInterface, 0, 8); 538 | if (ret != kIOReturnSuccess) 539 | { 540 | boolRet = false; 541 | goto SETUP_QUEUE_CLEANUP; 542 | } 543 | 544 | for (i=0; itype < kIOHIDElementTypeInput_Misc) || (tempHIDElement->type > kIOHIDElementTypeInput_ScanCodes)) 553 | continue; 554 | 555 | ret = (*hidDataRef->hidQueueInterface)->addElement(hidDataRef->hidQueueInterface, tempHIDElement->cookie, 0); 556 | 557 | if (ret == kIOReturnSuccess) 558 | cookieAdded = true; 559 | } 560 | 561 | if (cookieAdded) 562 | { 563 | ret = (*hidDataRef->hidQueueInterface)->createAsyncEventSource(hidDataRef->hidQueueInterface, &hidDataRef->eventSource); 564 | if (ret != kIOReturnSuccess) 565 | { 566 | boolRet = false; 567 | goto SETUP_QUEUE_CLEANUP; 568 | } 569 | 570 | ret = (*hidDataRef->hidQueueInterface)->setEventCallout(hidDataRef->hidQueueInterface, QueueCallbackFunction, NULL, hidDataRef); 571 | if (ret != kIOReturnSuccess) 572 | { 573 | boolRet = false; 574 | goto SETUP_QUEUE_CLEANUP; 575 | } 576 | 577 | CFRunLoopAddSource(CFRunLoopGetCurrent(), hidDataRef->eventSource, kCFRunLoopDefaultMode); 578 | 579 | ret = (*hidDataRef->hidQueueInterface)->start(hidDataRef->hidQueueInterface); 580 | if (ret != kIOReturnSuccess) 581 | { 582 | boolRet = false; 583 | goto SETUP_QUEUE_CLEANUP; 584 | } 585 | } 586 | else 587 | { 588 | (*hidDataRef->hidQueueInterface)->stop(hidDataRef->hidQueueInterface); 589 | (*hidDataRef->hidQueueInterface)->dispose(hidDataRef->hidQueueInterface); 590 | (*hidDataRef->hidQueueInterface)->Release(hidDataRef->hidQueueInterface); 591 | hidDataRef->hidQueueInterface = NULL; 592 | } 593 | 594 | SETUP_QUEUE_CLEANUP: 595 | 596 | free(keys); 597 | free(elements); 598 | 599 | return boolRet; 600 | } 601 | 602 | 603 | //--------------------------------------------------------------------------- 604 | // QueueCallbackFunction 605 | //--------------------------------------------------------------------------- 606 | static void QueueCallbackFunction( 607 | void * target, 608 | IOReturn result, 609 | void * refcon, 610 | void * sender) 611 | { 612 | HIDDataRef hidDataRef = (HIDDataRef)refcon; 613 | AbsoluteTime zeroTime = {0,0}; 614 | CFNumberRef number = NULL; 615 | CFMutableDataRef element = NULL; 616 | HIDElementRef tempHIDElement = NULL;//(HIDElementRef)refcon; 617 | IOHIDEventStruct event; 618 | bool change; 619 | 620 | if (!hidDataRef || (sender != hidDataRef->hidQueueInterface)) 621 | return; 622 | 623 | while (result == kIOReturnSuccess) 624 | { 625 | result = (*hidDataRef->hidQueueInterface)->getNextEvent( 626 | hidDataRef->hidQueueInterface, 627 | &event, 628 | zeroTime, 629 | 0); 630 | 631 | if (result != kIOReturnSuccess) 632 | continue; 633 | 634 | // Only intersted in 32 values right now 635 | if ((event.longValueSize != 0) && (event.longValue != NULL)) 636 | { 637 | free(event.longValue); 638 | continue; 639 | } 640 | 641 | number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &event.elementCookie); 642 | if (!number) continue; 643 | element = (CFMutableDataRef)CFDictionaryGetValue(hidDataRef->hidElementDictionary, number); 644 | CFRelease(number); 645 | 646 | if (!element || 647 | !(tempHIDElement = (HIDElement *)CFDataGetMutableBytePtr(element))) 648 | continue; 649 | 650 | change = (tempHIDElement->currentValue != event.value); 651 | tempHIDElement->currentValue = event.value; 652 | 653 | reportHidElement(tempHIDElement); 654 | } 655 | 656 | } 657 | --------------------------------------------------------------------------------