├── Changelog.md ├── ClevoService.xcodeproj └── project.pbxproj ├── ClevoService ├── ClevoService.cpp ├── ClevoService.hpp └── Info.plist ├── ClevoServiceAgent ├── BezelServices.h ├── OSD.h ├── com.fjhk.ClevoService.agent.plist └── main.m ├── LICENSE ├── README.md └── SSDT-ClevoService.dsl /Changelog.md: -------------------------------------------------------------------------------- 1 | ClevoService Changelog 2 | ====================================== 3 | #### v1.2.0 4 | - Added ClevoServiceAgent for user-land activities 5 | - Added backlight OSD icon 6 | - Added Wifi/BT power on/off using Airplane key (Fn + Airplane) 7 | - Added Wifi/BT OSD icon 8 | - Added init keyboard backlight at first key stroke for BIOS colors cycle compatibility 9 | - Updated SSDT-ClevoService file 10 | - Updated linked libraries version 11 | - SDK & Min OSX 10.11 12 | - Fixed non-native NVRAM property reading 13 | - Minor code clean-up 14 | - Bump version to 1.2.0 15 | 16 | #### v1.1.0 17 | - Fully customizable 18 | - Added Keyboard AutoDim feature 19 | - Added AutoDim configuration in SSDT-ClevoService.dsl 20 | - Some minor code clean-up 21 | - Bump version to 1.1.0 22 | 23 | #### v1.0.0a 24 | - Added support for WMBB method in SSDT-ClevoService.dsl (Device WMI required in DSDT) 25 | - Updated ReadMe file 26 | - Added Changelog file 27 | 28 | #### v1.0.0 29 | - Initial release 30 | -------------------------------------------------------------------------------- /ClevoService.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5214FDAD230FF3A200E33053 /* ClevoService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5214FDAA230FF3A100E33053 /* ClevoService.cpp */; }; 11 | 5214FDAE230FF3A200E33053 /* ClevoService.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 5214FDAB230FF3A200E33053 /* ClevoService.hpp */; }; 12 | 523BD5A0247671940080B129 /* ClevoServiceAgent in CopyFiles */ = {isa = PBXBuildFile; fileRef = 526EE3582475E33A00C378D6 /* ClevoServiceAgent */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 13 | 523BD5A3247671E50080B129 /* com.fjhk.ClevoService.agent.plist in CopyFiles */ = {isa = PBXBuildFile; fileRef = 524BF39F2475E27D00FE294D /* com.fjhk.ClevoService.agent.plist */; }; 14 | 5240E1CB24766FDE00F00505 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5240E1CA24766FDE00F00505 /* main.m */; }; 15 | 526EE3632475E42F00C378D6 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 526EE3622475E42F00C378D6 /* AppKit.framework */; }; 16 | 526EE3652475E43B00C378D6 /* CoreWLAN.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 526EE3642475E43B00C378D6 /* CoreWLAN.framework */; }; 17 | 526EE3672475E44700C378D6 /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 526EE3662475E44700C378D6 /* IOBluetooth.framework */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 523BD59E247671630080B129 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 5214FD95230FF31800E33053 /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = 526EE3572475E33A00C378D6; 26 | remoteInfo = ClevoServiceAgent; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXCopyFilesBuildPhase section */ 31 | 523BD5A1247671D40080B129 /* CopyFiles */ = { 32 | isa = PBXCopyFilesBuildPhase; 33 | buildActionMask = 2147483647; 34 | dstPath = ""; 35 | dstSubfolderSpec = 16; 36 | files = ( 37 | 523BD5A3247671E50080B129 /* com.fjhk.ClevoService.agent.plist in CopyFiles */, 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | 526EE3562475E33A00C378D6 /* CopyFiles */ = { 42 | isa = PBXCopyFilesBuildPhase; 43 | buildActionMask = 2147483647; 44 | dstPath = /usr/share/man/man1/; 45 | dstSubfolderSpec = 0; 46 | files = ( 47 | ); 48 | runOnlyForDeploymentPostprocessing = 1; 49 | }; 50 | 529D7EB624744D8B00F8E485 /* CopyFiles */ = { 51 | isa = PBXCopyFilesBuildPhase; 52 | buildActionMask = 2147483647; 53 | dstPath = ""; 54 | dstSubfolderSpec = 13; 55 | files = ( 56 | 523BD5A0247671940080B129 /* ClevoServiceAgent in CopyFiles */, 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXCopyFilesBuildPhase section */ 61 | 62 | /* Begin PBXFileReference section */ 63 | 5214FD9E230FF31800E33053 /* ClevoService.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ClevoService.kext; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | 5214FDA9230FF3A100E33053 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65 | 5214FDAA230FF3A100E33053 /* ClevoService.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClevoService.cpp; sourceTree = ""; }; 66 | 5214FDAB230FF3A200E33053 /* ClevoService.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClevoService.hpp; sourceTree = ""; }; 67 | 5214FDAF230FF43100E33053 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 68 | 5214FDB0230FF43100E33053 /* SSDT-ClevoService.dsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "SSDT-ClevoService.dsl"; sourceTree = ""; }; 69 | 5240E1CA24766FDE00F00505 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 70 | 524BF39E2475E27D00FE294D /* install_agent.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = install_agent.sh; sourceTree = ""; }; 71 | 524BF39F2475E27D00FE294D /* com.fjhk.ClevoService.agent.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.fjhk.ClevoService.agent.plist; sourceTree = ""; }; 72 | 524BF3A12475E27D00FE294D /* OSD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSD.h; sourceTree = ""; }; 73 | 524BF3A22475E27D00FE294D /* BezelServices.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BezelServices.h; sourceTree = ""; }; 74 | 526EE3582475E33A00C378D6 /* ClevoServiceAgent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ClevoServiceAgent; sourceTree = BUILT_PRODUCTS_DIR; }; 75 | 526EE3622475E42F00C378D6 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 76 | 526EE3642475E43B00C378D6 /* CoreWLAN.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreWLAN.framework; path = System/Library/Frameworks/CoreWLAN.framework; sourceTree = SDKROOT; }; 77 | 526EE3662475E44700C378D6 /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = System/Library/Frameworks/IOBluetooth.framework; sourceTree = SDKROOT; }; 78 | 52FB894B246C49CE0087A567 /* Changelog.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Changelog.md; sourceTree = ""; }; 79 | /* End PBXFileReference section */ 80 | 81 | /* Begin PBXFrameworksBuildPhase section */ 82 | 5214FD9B230FF31800E33053 /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | 526EE3552475E33A00C378D6 /* Frameworks */ = { 90 | isa = PBXFrameworksBuildPhase; 91 | buildActionMask = 2147483647; 92 | files = ( 93 | 526EE3672475E44700C378D6 /* IOBluetooth.framework in Frameworks */, 94 | 526EE3652475E43B00C378D6 /* CoreWLAN.framework in Frameworks */, 95 | 526EE3632475E42F00C378D6 /* AppKit.framework in Frameworks */, 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | /* End PBXFrameworksBuildPhase section */ 100 | 101 | /* Begin PBXGroup section */ 102 | 5214FD94230FF31800E33053 = { 103 | isa = PBXGroup; 104 | children = ( 105 | 5214FDAF230FF43100E33053 /* README.md */, 106 | 52FB894B246C49CE0087A567 /* Changelog.md */, 107 | 5214FDB0230FF43100E33053 /* SSDT-ClevoService.dsl */, 108 | 5214FDA0230FF31800E33053 /* ClevoService */, 109 | 524BF39D2475E27D00FE294D /* ClevoServiceAgent */, 110 | 5214FD9F230FF31800E33053 /* Products */, 111 | 529D7EA52474472300F8E485 /* Frameworks */, 112 | ); 113 | sourceTree = ""; 114 | }; 115 | 5214FD9F230FF31800E33053 /* Products */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 5214FD9E230FF31800E33053 /* ClevoService.kext */, 119 | 526EE3582475E33A00C378D6 /* ClevoServiceAgent */, 120 | ); 121 | name = Products; 122 | sourceTree = ""; 123 | }; 124 | 5214FDA0230FF31800E33053 /* ClevoService */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 5214FDAB230FF3A200E33053 /* ClevoService.hpp */, 128 | 5214FDAA230FF3A100E33053 /* ClevoService.cpp */, 129 | 5214FDA9230FF3A100E33053 /* Info.plist */, 130 | ); 131 | path = ClevoService; 132 | sourceTree = ""; 133 | }; 134 | 524BF39D2475E27D00FE294D /* ClevoServiceAgent */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 524BF39E2475E27D00FE294D /* install_agent.sh */, 138 | 524BF39F2475E27D00FE294D /* com.fjhk.ClevoService.agent.plist */, 139 | 524BF3A22475E27D00FE294D /* BezelServices.h */, 140 | 524BF3A12475E27D00FE294D /* OSD.h */, 141 | 5240E1CA24766FDE00F00505 /* main.m */, 142 | ); 143 | path = ClevoServiceAgent; 144 | sourceTree = ""; 145 | }; 146 | 529D7EA52474472300F8E485 /* Frameworks */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 526EE3662475E44700C378D6 /* IOBluetooth.framework */, 150 | 526EE3642475E43B00C378D6 /* CoreWLAN.framework */, 151 | 526EE3622475E42F00C378D6 /* AppKit.framework */, 152 | ); 153 | name = Frameworks; 154 | sourceTree = ""; 155 | }; 156 | /* End PBXGroup section */ 157 | 158 | /* Begin PBXHeadersBuildPhase section */ 159 | 5214FD99230FF31800E33053 /* Headers */ = { 160 | isa = PBXHeadersBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | 5214FDAE230FF3A200E33053 /* ClevoService.hpp in Headers */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXHeadersBuildPhase section */ 168 | 169 | /* Begin PBXNativeTarget section */ 170 | 5214FD9D230FF31800E33053 /* ClevoService */ = { 171 | isa = PBXNativeTarget; 172 | buildConfigurationList = 5214FDA6230FF31800E33053 /* Build configuration list for PBXNativeTarget "ClevoService" */; 173 | buildPhases = ( 174 | 5214FD99230FF31800E33053 /* Headers */, 175 | 5214FD9A230FF31800E33053 /* Sources */, 176 | 5214FD9B230FF31800E33053 /* Frameworks */, 177 | 5214FD9C230FF31800E33053 /* Resources */, 178 | 529D7EB624744D8B00F8E485 /* CopyFiles */, 179 | 523BD5A1247671D40080B129 /* CopyFiles */, 180 | 52167116248959A4002DCCE1 /* Archive */, 181 | ); 182 | buildRules = ( 183 | ); 184 | dependencies = ( 185 | 523BD59F247671630080B129 /* PBXTargetDependency */, 186 | ); 187 | name = ClevoService; 188 | productName = ClevoService; 189 | productReference = 5214FD9E230FF31800E33053 /* ClevoService.kext */; 190 | productType = "com.apple.product-type.kernel-extension"; 191 | }; 192 | 526EE3572475E33A00C378D6 /* ClevoServiceAgent */ = { 193 | isa = PBXNativeTarget; 194 | buildConfigurationList = 526EE35C2475E33A00C378D6 /* Build configuration list for PBXNativeTarget "ClevoServiceAgent" */; 195 | buildPhases = ( 196 | 526EE3542475E33A00C378D6 /* Sources */, 197 | 526EE3552475E33A00C378D6 /* Frameworks */, 198 | 526EE3562475E33A00C378D6 /* CopyFiles */, 199 | ); 200 | buildRules = ( 201 | ); 202 | dependencies = ( 203 | ); 204 | name = ClevoServiceAgent; 205 | productName = ClevoServiceAgent; 206 | productReference = 526EE3582475E33A00C378D6 /* ClevoServiceAgent */; 207 | productType = "com.apple.product-type.tool"; 208 | }; 209 | /* End PBXNativeTarget section */ 210 | 211 | /* Begin PBXProject section */ 212 | 5214FD95230FF31800E33053 /* Project object */ = { 213 | isa = PBXProject; 214 | attributes = { 215 | DefaultBuildSystemTypeForWorkspace = Original; 216 | LastSwiftUpdateCheck = 1020; 217 | LastUpgradeCheck = 1020; 218 | ORGANIZATIONNAME = none; 219 | TargetAttributes = { 220 | 5214FD9D230FF31800E33053 = { 221 | CreatedOnToolsVersion = 10.2.1; 222 | }; 223 | 526EE3572475E33A00C378D6 = { 224 | CreatedOnToolsVersion = 10.2.1; 225 | }; 226 | }; 227 | }; 228 | buildConfigurationList = 5214FD98230FF31800E33053 /* Build configuration list for PBXProject "ClevoService" */; 229 | compatibilityVersion = "Xcode 10.0"; 230 | developmentRegion = en; 231 | hasScannedForEncodings = 0; 232 | knownRegions = ( 233 | en, 234 | Base, 235 | ); 236 | mainGroup = 5214FD94230FF31800E33053; 237 | productRefGroup = 5214FD9F230FF31800E33053 /* Products */; 238 | projectDirPath = ""; 239 | projectRoot = ""; 240 | targets = ( 241 | 5214FD9D230FF31800E33053 /* ClevoService */, 242 | 526EE3572475E33A00C378D6 /* ClevoServiceAgent */, 243 | ); 244 | }; 245 | /* End PBXProject section */ 246 | 247 | /* Begin PBXResourcesBuildPhase section */ 248 | 5214FD9C230FF31800E33053 /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | }; 255 | /* End PBXResourcesBuildPhase section */ 256 | 257 | /* Begin PBXShellScriptBuildPhase section */ 258 | 52167116248959A4002DCCE1 /* Archive */ = { 259 | isa = PBXShellScriptBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | ); 263 | inputFileListPaths = ( 264 | ); 265 | inputPaths = ( 266 | ); 267 | name = Archive; 268 | outputFileListPaths = ( 269 | ); 270 | outputPaths = ( 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | shellPath = /bin/bash; 274 | shellScript = "cd \"${TARGET_BUILD_DIR}\"\n\nrm ClevoServiceAgent\n\ndist=(\"$FULL_PRODUCT_NAME\")\nif [ -d \"$DWARF_DSYM_FILE_NAME\" ]; then dist+=(\"$DWARF_DSYM_FILE_NAME\"); fi\n\narchive=\"${PRODUCT_NAME}-${MODULE_VERSION}-$(echo $CONFIGURATION | tr /a-z/ /A-Z/).zip\"\nrm -rf *.zip\nif [ \"$CONFIGURATION\" == \"Release\" ]; then\nstrip -x -T \"${EXECUTABLE_PATH}\" &>/dev/null || strip -x \"${EXECUTABLE_PATH}\"\nfi\nzip -qry -FS \"${archive}\" *\n\n"; 275 | }; 276 | /* End PBXShellScriptBuildPhase section */ 277 | 278 | /* Begin PBXSourcesBuildPhase section */ 279 | 5214FD9A230FF31800E33053 /* Sources */ = { 280 | isa = PBXSourcesBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | 5214FDAD230FF3A200E33053 /* ClevoService.cpp in Sources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | 526EE3542475E33A00C378D6 /* Sources */ = { 288 | isa = PBXSourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | 5240E1CB24766FDE00F00505 /* main.m in Sources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | /* End PBXSourcesBuildPhase section */ 296 | 297 | /* Begin PBXTargetDependency section */ 298 | 523BD59F247671630080B129 /* PBXTargetDependency */ = { 299 | isa = PBXTargetDependency; 300 | target = 526EE3572475E33A00C378D6 /* ClevoServiceAgent */; 301 | targetProxy = 523BD59E247671630080B129 /* PBXContainerItemProxy */; 302 | }; 303 | /* End PBXTargetDependency section */ 304 | 305 | /* Begin XCBuildConfiguration section */ 306 | 5214FDA4230FF31800E33053 /* Debug */ = { 307 | isa = XCBuildConfiguration; 308 | buildSettings = { 309 | ALWAYS_SEARCH_USER_PATHS = NO; 310 | CLANG_ANALYZER_NONNULL = YES; 311 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 312 | CLANG_ENABLE_MODULES = YES; 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | CLANG_ENABLE_OBJC_WEAK = YES; 315 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 316 | CLANG_WARN_BOOL_CONVERSION = YES; 317 | CLANG_WARN_COMMA = YES; 318 | CLANG_WARN_CONSTANT_CONVERSION = YES; 319 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 320 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 321 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 322 | CLANG_WARN_EMPTY_BODY = YES; 323 | CLANG_WARN_ENUM_CONVERSION = YES; 324 | CLANG_WARN_INFINITE_RECURSION = YES; 325 | CLANG_WARN_INT_CONVERSION = YES; 326 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 328 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 330 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 331 | CLANG_WARN_STRICT_PROTOTYPES = YES; 332 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 333 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 334 | CLANG_WARN_UNREACHABLE_CODE = YES; 335 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 336 | COPY_PHASE_STRIP = NO; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | ENABLE_STRICT_OBJC_MSGSEND = YES; 339 | ENABLE_TESTABILITY = YES; 340 | GCC_DYNAMIC_NO_PIC = NO; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_OPTIMIZATION_LEVEL = 0; 343 | GCC_PREPROCESSOR_DEFINITIONS = ( 344 | "DEBUG=1", 345 | "$(inherited)", 346 | ); 347 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 348 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 349 | GCC_WARN_UNDECLARED_SELECTOR = YES; 350 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 351 | GCC_WARN_UNUSED_FUNCTION = YES; 352 | GCC_WARN_UNUSED_VARIABLE = YES; 353 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 354 | MTL_FAST_MATH = YES; 355 | ONLY_ACTIVE_ARCH = YES; 356 | SDKROOT = macosx10.11; 357 | }; 358 | name = Debug; 359 | }; 360 | 5214FDA5230FF31800E33053 /* Release */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ALWAYS_SEARCH_USER_PATHS = NO; 364 | CLANG_ANALYZER_NONNULL = YES; 365 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 366 | CLANG_ENABLE_MODULES = YES; 367 | CLANG_ENABLE_OBJC_ARC = YES; 368 | CLANG_ENABLE_OBJC_WEAK = YES; 369 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 370 | CLANG_WARN_BOOL_CONVERSION = YES; 371 | CLANG_WARN_COMMA = YES; 372 | CLANG_WARN_CONSTANT_CONVERSION = YES; 373 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 374 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 375 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 376 | CLANG_WARN_EMPTY_BODY = YES; 377 | CLANG_WARN_ENUM_CONVERSION = YES; 378 | CLANG_WARN_INFINITE_RECURSION = YES; 379 | CLANG_WARN_INT_CONVERSION = YES; 380 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 381 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 382 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 383 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 384 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 385 | CLANG_WARN_STRICT_PROTOTYPES = YES; 386 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 387 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 388 | CLANG_WARN_UNREACHABLE_CODE = YES; 389 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 390 | COPY_PHASE_STRIP = NO; 391 | DEBUG_INFORMATION_FORMAT = dwarf; 392 | ENABLE_NS_ASSERTIONS = NO; 393 | ENABLE_STRICT_OBJC_MSGSEND = YES; 394 | GCC_NO_COMMON_BLOCKS = YES; 395 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 396 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 397 | GCC_WARN_UNDECLARED_SELECTOR = YES; 398 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 399 | GCC_WARN_UNUSED_FUNCTION = YES; 400 | GCC_WARN_UNUSED_VARIABLE = YES; 401 | MTL_ENABLE_DEBUG_INFO = NO; 402 | MTL_FAST_MATH = YES; 403 | SDKROOT = macosx10.11; 404 | }; 405 | name = Release; 406 | }; 407 | 5214FDA7230FF31800E33053 /* Debug */ = { 408 | isa = XCBuildConfiguration; 409 | buildSettings = { 410 | CODE_SIGN_IDENTITY = ""; 411 | CODE_SIGN_STYLE = Automatic; 412 | COMBINE_HIDPI_IMAGES = YES; 413 | DEVELOPMENT_TEAM = ""; 414 | INFOPLIST_FILE = ClevoService/Info.plist; 415 | MODULE_NAME = com.none.ClevoService; 416 | MODULE_VERSION = 1.2.0; 417 | PRODUCT_BUNDLE_IDENTIFIER = com.none.ClevoService; 418 | PRODUCT_NAME = "$(TARGET_NAME)"; 419 | PROVISIONING_PROFILE_SPECIFIER = ""; 420 | WRAPPER_EXTENSION = kext; 421 | }; 422 | name = Debug; 423 | }; 424 | 5214FDA8230FF31800E33053 /* Release */ = { 425 | isa = XCBuildConfiguration; 426 | buildSettings = { 427 | CODE_SIGN_IDENTITY = ""; 428 | CODE_SIGN_STYLE = Automatic; 429 | COMBINE_HIDPI_IMAGES = YES; 430 | DEVELOPMENT_TEAM = ""; 431 | INFOPLIST_FILE = ClevoService/Info.plist; 432 | MODULE_NAME = com.none.ClevoService; 433 | MODULE_VERSION = 1.2.0; 434 | PRODUCT_BUNDLE_IDENTIFIER = com.none.ClevoService; 435 | PRODUCT_NAME = "$(TARGET_NAME)"; 436 | PROVISIONING_PROFILE_SPECIFIER = ""; 437 | WRAPPER_EXTENSION = kext; 438 | }; 439 | name = Release; 440 | }; 441 | 526EE35D2475E33A00C378D6 /* Debug */ = { 442 | isa = XCBuildConfiguration; 443 | buildSettings = { 444 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 445 | CLANG_CXX_LIBRARY = "libc++"; 446 | CODE_SIGN_STYLE = Automatic; 447 | GCC_C_LANGUAGE_STANDARD = gnu11; 448 | MACOSX_DEPLOYMENT_TARGET = 10.11; 449 | PRODUCT_NAME = "$(TARGET_NAME)"; 450 | }; 451 | name = Debug; 452 | }; 453 | 526EE35E2475E33A00C378D6 /* Release */ = { 454 | isa = XCBuildConfiguration; 455 | buildSettings = { 456 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 457 | CLANG_CXX_LIBRARY = "libc++"; 458 | CODE_SIGN_STYLE = Automatic; 459 | GCC_C_LANGUAGE_STANDARD = gnu11; 460 | MACOSX_DEPLOYMENT_TARGET = 10.11; 461 | PRODUCT_NAME = "$(TARGET_NAME)"; 462 | }; 463 | name = Release; 464 | }; 465 | /* End XCBuildConfiguration section */ 466 | 467 | /* Begin XCConfigurationList section */ 468 | 5214FD98230FF31800E33053 /* Build configuration list for PBXProject "ClevoService" */ = { 469 | isa = XCConfigurationList; 470 | buildConfigurations = ( 471 | 5214FDA4230FF31800E33053 /* Debug */, 472 | 5214FDA5230FF31800E33053 /* Release */, 473 | ); 474 | defaultConfigurationIsVisible = 0; 475 | defaultConfigurationName = Release; 476 | }; 477 | 5214FDA6230FF31800E33053 /* Build configuration list for PBXNativeTarget "ClevoService" */ = { 478 | isa = XCConfigurationList; 479 | buildConfigurations = ( 480 | 5214FDA7230FF31800E33053 /* Debug */, 481 | 5214FDA8230FF31800E33053 /* Release */, 482 | ); 483 | defaultConfigurationIsVisible = 0; 484 | defaultConfigurationName = Release; 485 | }; 486 | 526EE35C2475E33A00C378D6 /* Build configuration list for PBXNativeTarget "ClevoServiceAgent" */ = { 487 | isa = XCConfigurationList; 488 | buildConfigurations = ( 489 | 526EE35D2475E33A00C378D6 /* Debug */, 490 | 526EE35E2475E33A00C378D6 /* Release */, 491 | ); 492 | defaultConfigurationIsVisible = 0; 493 | defaultConfigurationName = Release; 494 | }; 495 | /* End XCConfigurationList section */ 496 | }; 497 | rootObject = 5214FD95230FF31800E33053 /* Project object */; 498 | } 499 | -------------------------------------------------------------------------------- /ClevoService/ClevoService.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | OSDefineMetaClassAndStructors(ClevoService, IOService) 4 | 5 | #pragma mark ---------- Main Kernel Routines ---------- 6 | 7 | bool ClevoService::init(OSDictionary * dict) 8 | { 9 | bool result = IOService::init(dict); 10 | 11 | device = NULL; 12 | gWorkLoop = NULL; 13 | gNVRAMTimer = NULL; 14 | gKBDTimer = NULL; 15 | gKBDTime = KBD_DEF_TIME; 16 | gKBDInUse = 0; 17 | gKBLT = 0; 18 | gOldKBLT = 0; 19 | vendorID = 0; 20 | notify = NULL; 21 | gKBDService = NULL; 22 | gKBDIsOFF = false; 23 | gDimTimerActive = true; 24 | gKBDimmed = true; 25 | gKBDJustDim = true; 26 | 27 | origCallback = NULL; 28 | origSpecialCallback = NULL; 29 | 30 | gKBDDimmingLevel = KBD_DIM_LEVEL; 31 | gKBDLevel[0] = KBD_L0_LEVEL; 32 | gKBDLevel[1] = KBD_L1_LEVEL; 33 | gKBDLevel[2] = KBD_L2_LEVEL; 34 | gKBDLevel[3] = KBD_L3_LEVEL; 35 | 36 | return result; 37 | } 38 | 39 | IOService* ClevoService::probe(IOService * provider, SInt32 * score) 40 | { 41 | IOService *result = IOService::probe(provider, score); 42 | 43 | //Check our SSDT methods... 44 | device = OSDynamicCast(IOACPIPlatformDevice, provider); 45 | if (kIOReturnSuccess != device->validateObject(ACPI_METD_NAME)) { 46 | IOLog( "%s: SSDT method CLVE not found\n", device->getName() ); 47 | return NULL; 48 | } 49 | 50 | return result; 51 | } 52 | 53 | bool ClevoService::start(IOService * provider) 54 | { 55 | DEBUG_LOG( "%s: Starting...\n", getName() ); 56 | 57 | //device = OSDynamicCast(IOACPIPlatformDevice, provider); 58 | if (device == NULL || !IOService::start(provider)) return false; 59 | 60 | setName( "ClevoService" ); 61 | setVendorID( ClevoVendorSTR ); 62 | 63 | /* 64 | //Not too early KB on, we just wait for DisplayMangler... 65 | if (RunningKernel() >= MakeKernelVersion(17,0,0)) { 66 | waitForMatchingService(serviceMatching("IODisplayWrangler")); 67 | } else { 68 | IOSleep(3000); 69 | } 70 | */ 71 | 72 | gWorkLoop = getWorkLoop(); 73 | if (gWorkLoop == NULL) return false; 74 | gWorkLoop->retain(); 75 | 76 | gNVRAMTimer = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ClevoService::saveNVRAM) ); 77 | if ((gNVRAMTimer == NULL) || (kIOReturnSuccess != gWorkLoop->addEventSource(gNVRAMTimer))) { 78 | DEBUG_LOG( "%s: gNVRAMTimer failed...\n", getName() ); 79 | return false; 80 | } 81 | 82 | gKBDTimer = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ClevoService::kbdTimerFired) ); 83 | if ((gKBDTimer == NULL) || (kIOReturnSuccess != gWorkLoop->addEventSource(gKBDTimer))) { 84 | DEBUG_LOG( "%s: gKBDTimer failed...\n", getName() ); 85 | return false; 86 | } 87 | 88 | // KBLT bytes: 0x0ABC A: 0÷8 keyboard color, B: 0/1 backlight OFF/ON, C: 0÷3 backlight level 89 | gKBLT = 0x12; // Default value: color BLUE, keybord ON, backlight level 2 90 | 91 | //Trying to read KBLT variable from NVRAM... 92 | if (IORegistryEntry *nvram = OSDynamicCast(IORegistryEntry, fromPath("/options", gIODTPlane))) { 93 | bool genericNVRAM = (0 == strncmp(nvram->getName(), "AppleNVRAM", sizeof("AppleNVRAM"))); 94 | OSObject* obj = NULL; 95 | if (genericNVRAM) { 96 | obj = nvram->IORegistryEntry::getProperty(KBD_VAR_NAME); 97 | } else { 98 | obj = nvram->getProperty(KBD_VAR_NAME); 99 | } 100 | if (obj != NULL) { 101 | if (OSData* number = OSDynamicCast(OSData, obj)) { 102 | int length = number->getLength(); 103 | if (length > 0) bcopy(number->getBytesNoCopy(), &gKBLT, length); 104 | } 105 | } 106 | OSSafeReleaseNULL(nvram); 107 | } 108 | 109 | //The standard _INI method turn OFF dual GPU RX2070 & airplane led (used for Shift-lock indication) 110 | //Remove from SSDT if not necessary... 111 | gOldKBLT = gKBLT; 112 | //We're going to get user's configuration... 113 | loadConfiguration(); 114 | //Set-up backlight... 115 | kbdSetUpBacklight(); 116 | 117 | gKBDService = this; 118 | 119 | loggedKeyboards = new OSArray(); 120 | loggedKeyboards->initWithCapacity(1); 121 | 122 | DEBUG_LOG( "%s: gIOTerminatedNotification...\n", getName() ); 123 | notifyTerm = addMatchingNotification(gIOTerminatedNotification, 124 | serviceMatching("IOHIKeyboard"), 125 | (IOServiceMatchingNotificationHandler) &ClevoService::kbdTerminatedNotificationHandler, 126 | this, 0); 127 | 128 | DEBUG_LOG( "%s: gIOPublishNotification...\n", getName() ); 129 | notify = addMatchingNotification(gIOPublishNotification, 130 | serviceMatching("IOHIKeyboard"), 131 | (IOServiceMatchingNotificationHandler) &ClevoService::kbdNotificationHandler, 132 | this, 0); 133 | 134 | setProperty(KBD_VAR_NAME, gKBLT, 8 * sizeof(gKBLT)); 135 | setProperty("KbdAutoDimActive", gKBDJustDim); 136 | setProperty("KbdAutoDimTimerActive", gDimTimerActive); 137 | setProperty("KbdAutoDimTime", gKBDTime, 8 * sizeof(gKBDTime)); 138 | setProperty("KbdDimmingLevel", gKBDDimmingLevel, 8 * sizeof(gKBDDimmingLevel)); 139 | 140 | extern kmod_info_t kmod_info; 141 | char buf[128]; 142 | #ifdef DEBUG 143 | snprintf(buf, sizeof(buf), "FJHK Debug %s", kmod_info.version); 144 | #else 145 | snprintf(buf, sizeof(buf), "FJHK Release %s", kmod_info.version); 146 | #endif 147 | setProperty("Version", buf); 148 | 149 | OSArray * levelsArray = new OSArray(); 150 | if (levelsArray != NULL) { 151 | levelsArray->initWithCapacity(1); 152 | for (UInt8 i = 0; i < 4; i++) { 153 | OSNumber * myNum = OSNumber::withNumber(gKBDLevel[i], 8); 154 | if (myNum) levelsArray->setObject(i, myNum); 155 | } 156 | setProperty("KbdLevels", levelsArray); 157 | levelsArray->release(); 158 | } 159 | 160 | registerService(0); 161 | 162 | IOLog( "%s: AutoDim %s\n", getName(), (gDimTimerActive ? "activated" : "not activated") ); 163 | IOLog( "%s: AutoDim %s\n", getName(), (gKBDJustDim ? "dimming activated" : "OFF activated") ); 164 | IOLog( "%s: Backlighting activated: KBLT=0x%x", getName(), gKBLT); 165 | 166 | return true; 167 | } 168 | 169 | void ClevoService::stop(IOService *provider) 170 | { 171 | DEBUG_LOG( "%s: Stopping...\n", getName() ); 172 | saveNVRAM(); 173 | 174 | if (gNVRAMTimer != NULL) 175 | { 176 | gNVRAMTimer->cancelTimeout(); 177 | gWorkLoop->disableAllEventSources(); 178 | gNVRAMTimer->release(); 179 | gNVRAMTimer = NULL; 180 | DEBUG_LOG( "%s: gNVRAMTimer Removed\n", getName() ); 181 | } 182 | 183 | if (gKBDTimer != NULL) 184 | { 185 | gKBDTimer->cancelTimeout(); 186 | gWorkLoop->disableAllEventSources(); 187 | gKBDTimer->release(); 188 | gKBDTimer = NULL; 189 | DEBUG_LOG( "%s: gKBDTimer Removed\n", getName() ); 190 | } 191 | 192 | if (gWorkLoop != NULL) 193 | { 194 | gWorkLoop->release(); 195 | gWorkLoop = NULL; 196 | DEBUG_LOG( "%s: WorkLoop Removed\n", getName() ); 197 | } 198 | 199 | if (notifyTerm) notifyTerm->remove(); 200 | notifyTerm = NULL; 201 | DEBUG_LOG( "%s: TerminatedNotification Removed TerminatedNotification\n", getName() ); 202 | 203 | if (notify) notify->remove(); 204 | notify = NULL; 205 | DEBUG_LOG( "%s: PublishNotification Removed\n", getName() ); 206 | 207 | gKBDService = NULL; 208 | 209 | kbdClearKeyboards(); 210 | loggedKeyboards->release(); 211 | DEBUG_LOG( "%s: Keyboards Removed...\n", getName() ); 212 | 213 | IOLog( "%s: Stop Complete\n", getName() ); 214 | 215 | IOService::stop(provider); 216 | } 217 | 218 | // Receive Notify message from ACPI, wait 3 secs before writing NVRAM so user may change other KB backlight settings... 219 | IOReturn ClevoService::message(UInt32 type, IOService * provider, void * argument) 220 | { 221 | UInt8 level = gKBLT & 3; 222 | UInt32 *myMsg, color = gKBLT & 0xF00; 223 | 224 | if (type == kIOACPIMessageDeviceNotification) 225 | { 226 | myMsg = (UInt32 *)argument; 227 | switch (*myMsg) { 228 | case msgKbdChangeColor: 229 | if (!gKBDIsOFF) { 230 | gKBLT &= 0xFF; 231 | if (color < 0x800) gKBLT |= (color + 0x100); 232 | kbdSetColor(); 233 | } 234 | break; 235 | case msgKbdLightDOWN: 236 | if (!gKBDIsOFF) { 237 | if (level) kbdLightLevel(--level); 238 | sendUserLandMessage( evtKeyboardBacklight, level + 1, 4 ); 239 | } 240 | break; 241 | case msgKbdLightUP: 242 | if (!gKBDIsOFF) { 243 | if (level < 3) kbdLightLevel(++level); 244 | sendUserLandMessage( evtKeyboardBacklight, level + 1, 4 ); 245 | } 246 | break; 247 | case msgKbdToggleONOFF: 248 | if (!gKBDIsOFF) { 249 | gKBLT &= 0xF0F; 250 | gKBDIsOFF = true; 251 | } else { 252 | gKBLT |= KBD_ON_MASK; 253 | gKBDIsOFF = false; 254 | } 255 | sendUserLandMessage( evtKeyboardBacklight, !gKBDIsOFF ? level + 1 : 0, 4 ); 256 | case msgKbdWakeUp: 257 | kbdSetUpBacklight(); 258 | break; 259 | case msgAirplane: 260 | sendUserLandMessage( evtAirplaneMode, 0, 0 ); 261 | break; 262 | #if DEBUG 263 | default: 264 | sendUserLandMessage( 3, *myMsg & 0xFFFF, 0 ); 265 | #endif 266 | } 267 | if (gNVRAMTimer != NULL) { 268 | gNVRAMTimer->cancelTimeout(); 269 | gNVRAMTimer->setTimeoutMS(NVRAM_WAIT_TIME); 270 | } 271 | } 272 | return IOService::message(type, provider, argument); 273 | } 274 | 275 | #pragma mark ---------- Service Routines ---------- 276 | 277 | void ClevoService::ACPI_Send(uint32_t arg0, uint32_t arg1, uint32_t arg2) 278 | { 279 | OSObject *params[3]; 280 | params[0] = OSNumber::withNumber(arg0, 8 * sizeof(uint32_t)); 281 | params[1] = OSNumber::withNumber(arg1, 8 * sizeof(uint32_t)); 282 | params[2] = OSNumber::withNumber(arg2, 8 * sizeof(uint32_t)); 283 | if (device != NULL) 284 | device->evaluateObject("CLVE", NULL, params, 3); // Call our method... 285 | else 286 | DEBUG_LOG( "%s: device NULL!\n", getName() ); 287 | } 288 | 289 | 290 | void ClevoService::saveNVRAM(void) 291 | { 292 | gKBLT &= 0xF13; 293 | if (gOldKBLT != gKBLT) { 294 | if (IORegistryEntry *nvram = OSDynamicCast(IORegistryEntry, fromPath("/options", gIODTPlane))) { 295 | 296 | bool genericNVRAM = (0 == strncmp(nvram->getName(), "AppleNVRAM", sizeof("AppleNVRAM"))); 297 | if (genericNVRAM) { 298 | nvram->IORegistryEntry::setProperty(KBD_VAR_NAME, &gKBLT, sizeof(gKBLT)); 299 | DEBUG_LOG("%s: fallback to generic NVRAM methods\n", getName()); 300 | } else 301 | nvram->setProperty(KBD_VAR_NAME, &gKBLT, sizeof(gKBLT)); 302 | OSSafeReleaseNULL(nvram); 303 | 304 | gOldKBLT = gKBLT; 305 | this->setProperty(KBD_VAR_NAME, gKBLT, 8 * sizeof(gKBLT)); 306 | IOLog("%s: NVRAM saved KBLT=0x%x", getName(), gKBLT); 307 | } 308 | } 309 | } 310 | 311 | bool ClevoService::setVendorID(const char *vendorCode) { 312 | if (KERN_SUCCESS != kev_vendor_code_find(vendorCode, &vendorID)) { 313 | DEBUG_LOG("%s: setVendorID error\n", getName()); 314 | return false; 315 | } 316 | return true; 317 | } 318 | 319 | bool ClevoService::sendUserLandMessage( int type, int param1, int param2 ) { 320 | // kernel event message 321 | struct kev_msg kEventMsg = {0}; 322 | bzero(&kEventMsg, sizeof(struct kev_msg)); 323 | 324 | kEventMsg.vendor_code = vendorID; // set vendor code 325 | if (vendorID == 0) DEBUG_LOG("%s: vendorID not set\n", getName()); 326 | 327 | kEventMsg.kev_class = KEV_ANY_CLASS; 328 | kEventMsg.kev_subclass = KEV_ANY_SUBCLASS; 329 | kEventMsg.event_code = ClevoEventCode; 330 | 331 | kEventMsg.dv[0].data_length = sizeof(int); 332 | kEventMsg.dv[0].data_ptr = &type; 333 | kEventMsg.dv[1].data_length = sizeof(int); 334 | kEventMsg.dv[1].data_ptr = ¶m1; 335 | kEventMsg.dv[2].data_length = sizeof(int); 336 | kEventMsg.dv[2].data_ptr = ¶m2; 337 | 338 | if (KERN_SUCCESS != kev_msg_post( &kEventMsg )) { 339 | DEBUG_LOG("%s: sendUserLandMessage error\n", getName()); 340 | return false; 341 | } 342 | return true; 343 | } 344 | 345 | #pragma mark ---------- Keyboard Backlight Routines ---------- 346 | 347 | void ClevoService::kbdSetUpBacklight() 348 | { 349 | if (gKBLT & KBD_ON_MASK) { //...no need level or colour if we're off 350 | kbdSetColor(); //Set backlight color... 351 | kbdLightLevel(gKBLT); //Set backlight level... 352 | } 353 | kbdONOFF(); //Turn backlight on/off... 354 | } 355 | 356 | 357 | void ClevoService::kbdONOFF() 358 | { 359 | if (gKBLT & KBD_ON_MASK) { 360 | ACPI_Send(0, SET_KB_LED, 0xE007F001); // ON 361 | if (gKBDTimer != NULL) gKBDTimer->setTimeoutMS(gKBDTime); 362 | } else { 363 | if (gKBDTimer != NULL) gKBDTimer->cancelTimeout(); 364 | ACPI_Send(0, SET_KB_LED, 0xE0003001); // OFF 365 | } 366 | } 367 | 368 | 369 | void ClevoService::kbdSetColor(void) 370 | { 371 | UInt32 newColor = 0, color = gKBLT & 0xF00; 372 | 373 | //ACPI_Send(0, SET_KB_LED, 0x10000000); 374 | 375 | switch (color) { 376 | case 0x0: newColor = 0x00FF0000; break; // Blue 377 | case 0x100: newColor = 0x0000FF00; break; // Red 378 | case 0x200: newColor = 0x00FFFFFF; break; // White 379 | case 0x300: newColor = 0x00FFFF00; break; // Pink 380 | case 0x400: newColor = 0x00FF00FF; break; // Light Blue 381 | case 0x500: newColor = 0x000000FF; break; // Green 382 | case 0x600: newColor = 0x0000FFFF; break; // Yellow 383 | case 0x700: // RGB 384 | ACPI_Send(0, SET_KB_LED, 0xF000FF00); 385 | ACPI_Send(0, SET_KB_LED, 0xF10000FF); 386 | ACPI_Send(0, SET_KB_LED, 0xF2FF0000); 387 | break; 388 | case 0x800: // Random... 389 | ACPI_Send(0, SET_KB_LED, 0x70000000); 390 | break; 391 | } 392 | if (newColor) { 393 | ACPI_Send(0, SET_KB_LED, 0xF0000000 | newColor); // Set New color 394 | ACPI_Send(0, SET_KB_LED, 0xF1000000 | newColor); 395 | ACPI_Send(0, SET_KB_LED, 0xF2000000 | newColor); 396 | } 397 | } 398 | 399 | 400 | void ClevoService::kbdLightLevel( UInt8 newLevel ) 401 | { 402 | newLevel &= 3; 403 | ACPI_Send(0, SET_KB_LED, 0xF4000000 | gKBDLevel[newLevel]); 404 | gKBLT &= 0xFF0; 405 | gKBLT |= newLevel; 406 | } 407 | 408 | 409 | bool ClevoService::kbdTerminatedNotificationHandler(void * target, void * refCon, 410 | IOService * newService, 411 | IONotifier * notifier) 412 | { 413 | ClevoService * self = OSDynamicCast( ClevoService, (OSMetaClassBase*)target ); 414 | if (!self) { 415 | DEBUG_LOG( "ClevoService: Terminated Notification handler failed...\n"); 416 | return false; 417 | } 418 | 419 | if (!self->loggedKeyboards) { 420 | DEBUG_LOG( "%s: No Keyboard logged...\n", self->getName() ); 421 | return false; 422 | } 423 | 424 | IOHIKeyboard * keyboard = OSDynamicCast( IOHIKeyboard, newService ); 425 | if (!keyboard) { 426 | DEBUG_LOG( "%s: Keyboard not found...\n", self->getName() ); 427 | return false; 428 | } 429 | 430 | int index = self->loggedKeyboards->getNextIndexOfObject(keyboard, 0); 431 | if (index >= 0) 432 | { 433 | self->gKBDInUse--; 434 | self->loggedKeyboards->removeObject(index); 435 | DEBUG_LOG( "%s: Keyboard Succesfully Removed %lu\n", self->getName(), (long) keyboard ); 436 | } 437 | return true; 438 | } 439 | 440 | 441 | bool ClevoService::kbdNotificationHandler(void * target, void * refCon, 442 | IOService * newService, 443 | IONotifier * notifier) 444 | { 445 | ClevoService * self = OSDynamicCast( ClevoService, (OSMetaClassBase *) target ); 446 | if (!self) { 447 | DEBUG_LOG( "ClevoService: KbdNotification handler failed...\n"); 448 | return false; 449 | } 450 | 451 | IOHIKeyboard * keyboard = OSDynamicCast( IOHIKeyboard, newService ); 452 | if (!keyboard) { 453 | DEBUG_LOG( "%s: Keyboard not found...\n", self->getName() ); 454 | return false; 455 | } 456 | 457 | if (!keyboard->_keyboardEventTarget) 458 | { 459 | DEBUG_LOG( "%s: No Keyboard event target\n", self->getName()); 460 | return false; 461 | } 462 | 463 | IOService * targetServ = OSDynamicCast( IOService, keyboard->_keyboardEventTarget ); 464 | if (targetServ) 465 | { 466 | DEBUG_LOG( "%s: Keyboard event target is %s\n", self->getName(), targetServ->getName()); 467 | } 468 | 469 | 470 | if (!keyboard->_keyboardEventTarget->metaCast("IOHIDSystem")) { 471 | DEBUG_LOG( "%s: IOHIDSystem failed. Continue anyway...\n", self->getName()); 472 | //return false; 473 | } 474 | 475 | int index = self->loggedKeyboards->getNextIndexOfObject(keyboard,0); 476 | if (index < 0) 477 | { 478 | self->loggedKeyboards->setObject(keyboard); 479 | self->gKBDInUse++; 480 | DEBUG_LOG( "%s::Adding keyboard %lx\n", self->getName(), (long) keyboard ); 481 | } 482 | 483 | origCallback = (KeyboardEventCallback)keyboard->_keyboardEventAction; 484 | keyboard->_keyboardEventAction = (KeyboardEventAction) logAction; 485 | 486 | origSpecialCallback = (KeyboardSpecialEventCallback)keyboard->_keyboardSpecialEventAction; 487 | keyboard->_keyboardSpecialEventAction = (KeyboardSpecialEventAction) specialAction; 488 | 489 | DEBUG_LOG( "%s: Keyboard notification complete\n", self->getName()); 490 | return true; 491 | } 492 | 493 | 494 | void ClevoService::kbdClearKeyboards() 495 | { 496 | DEBUG_LOG( "%s: Clear Keyboards in use %d!\n", getName(), gKBDInUse ); 497 | 498 | if (loggedKeyboards) 499 | { 500 | int arraySize = loggedKeyboards->getCount(); 501 | for (int i = 0; i < arraySize; i++) 502 | { 503 | IOHIKeyboard *curKeyboard = (IOHIKeyboard*)loggedKeyboards->getObject(0); 504 | 505 | if (origSpecialCallback) 506 | curKeyboard->_keyboardSpecialEventAction = (KeyboardSpecialEventAction)origSpecialCallback; 507 | if (origCallback) 508 | curKeyboard->_keyboardEventAction = (KeyboardEventAction)origCallback; 509 | 510 | loggedKeyboards->removeObject(0); 511 | } 512 | } 513 | origSpecialCallback = NULL; 514 | origCallback = NULL; 515 | gKBDInUse = 0; 516 | } 517 | 518 | 519 | void ClevoService::kbdTimerFired(void) 520 | { 521 | gKBDimmed = true; 522 | UInt32 cmd = 0xF4000000; 523 | if (gKBDJustDim) cmd |= gKBDDimmingLevel; 524 | ACPI_Send(0, SET_KB_LED, cmd); // Dimming... 525 | DEBUG_LOG( "%s: gKBDTimer Fired -> Keyboard %s\n", getName(), gKBDJustDim ? "Dimmed" : "OFF"); 526 | } 527 | 528 | 529 | #pragma mark ---------- User Configuration Routines ------------- 530 | 531 | OSObject* ClevoService::translateEntry(OSObject* obj) 532 | { 533 | if (OSArray* array = OSDynamicCast(OSArray, obj)) 534 | return translateArray(array); 535 | 536 | if (OSString* string = OSDynamicCast(OSString, obj)) 537 | { 538 | const char* sz = string->getCStringNoCopy(); 539 | if (sz[0] == '>') 540 | { 541 | if (sz[1] == 'y' && !sz[2]) 542 | return OSBoolean::withBoolean(true); 543 | else if (sz[1] == 'n' && !sz[2]) 544 | return OSBoolean::withBoolean(false); 545 | // escape case ('>>n' '>>y'), replace with just string '>n' '>y' 546 | else if (sz[1] == '>' && (sz[2] == 'y' || sz[2] == 'n') && !sz[3]) 547 | return OSString::withCString(&sz[1]); 548 | } 549 | } 550 | return NULL; 551 | } 552 | 553 | 554 | OSObject* ClevoService::translateArray(OSArray* array) 555 | { 556 | int count = array->getCount(); 557 | if (!count) return NULL; 558 | 559 | OSObject* result = array; 560 | 561 | OSArray* test = OSDynamicCast(OSArray, array->getObject(0)); 562 | if (test && test->getCount() == 0) 563 | { 564 | array->retain(); 565 | array->removeObject(0); 566 | --count; 567 | 568 | for (int i = 0; i < count; ++i) 569 | { 570 | if (OSObject* obj = translateEntry(array->getObject(i))) 571 | { 572 | array->replaceObject(i, obj); 573 | obj->release(); 574 | } 575 | } 576 | } 577 | else 578 | { 579 | if (count & 1) return NULL; // array is key/value pairs, so must be even 580 | 581 | int size = count >> 1; 582 | if (!size) size = 1; 583 | OSDictionary* dict = OSDictionary::withCapacity(size); 584 | if (!dict) return NULL; 585 | 586 | // go through each entry two at a time, building the dictionary 587 | for (int i = 0; i < count; i += 2) 588 | { 589 | OSString* key = OSDynamicCast(OSString, array->getObject(i)); 590 | if (!key) 591 | { 592 | dict->release(); 593 | return NULL; 594 | } 595 | // get value, use translated value if translated 596 | OSObject* obj = array->getObject(i+1); 597 | OSObject* trans = translateEntry(obj); 598 | if (trans) 599 | obj = trans; 600 | dict->setObject(key, obj); 601 | OSSafeReleaseNULL(trans); 602 | } 603 | result = dict; 604 | } 605 | 606 | return result; 607 | } 608 | 609 | 610 | void ClevoService::loadConfiguration() 611 | { 612 | OSObject * reply = NULL; 613 | if (kIOReturnSuccess != (device->evaluateObject(ACPI_CONF_NAME, &reply))) { 614 | DEBUG_LOG( "%s: SSDT Configuration Method not found...\n", getName() ); 615 | return; 616 | } 617 | 618 | OSObject * obj = NULL; 619 | OSArray * array = OSDynamicCast(OSArray, reply); 620 | if (array) obj = translateArray(array); 621 | OSSafeReleaseNULL(reply); 622 | 623 | OSDictionary * config = OSDynamicCast(OSDictionary, obj); 624 | if (!config) { 625 | DEBUG_LOG( "%s: unable to load Configuration data...\n", getName() ); 626 | OSSafeReleaseNULL(obj); 627 | return; 628 | } 629 | 630 | OSBoolean * osBool = OSDynamicCast(OSBoolean, config->getObject("KbdAutoDimTimerActive")); 631 | if (osBool) gDimTimerActive = osBool->isTrue(); 632 | 633 | osBool = OSDynamicCast(OSBoolean, config->getObject("KbdAutoDimActive")); 634 | if (osBool) gKBDJustDim = osBool->isTrue(); 635 | 636 | OSNumber * osNum = OSDynamicCast(OSNumber, config->getObject("KbdAutoDimTime")); 637 | if (osNum) { 638 | gKBDTime = osNum->unsigned32BitValue(); 639 | if (gKBDTime < 5) gKBDTime = 5; // Minimum 5 secs... 640 | else if (gKBDTime > 1800) gKBDTime = 1800; // Maximum 30 minutes... 641 | gKBDTime *= 1000; // Value in SSDT is in seconds, we need mS... 642 | } 643 | 644 | if (OSArray * levelsArray = OSDynamicCast(OSArray, config->getObject("KbdLevels"))) 645 | { 646 | if (levelsArray->getCount() == 4) { //We need 4 items... 647 | for (UInt8 i = 0; i < 4; i++) { 648 | osNum = OSDynamicCast(OSNumber, levelsArray->getObject(i)); 649 | if (osNum && (osNum->unsigned8BitValue() > 0)) gKBDLevel[i] = osNum->unsigned8BitValue() & 0xFF; 650 | } 651 | } 652 | } else 653 | DEBUG_LOG( "%s: KbdLevels array not found\n", getName() ); 654 | 655 | osNum = OSDynamicCast(OSNumber, config->getObject("KbdDimmingLevel")); 656 | if (osNum) gKBDDimmingLevel = osNum->unsigned8BitValue() & 0xF; // Limiting to 0xF 657 | 658 | OSSafeReleaseNULL(config); 659 | DEBUG_LOG( "%s: Configuration Succesfully Loaded\n", getName() ); 660 | } 661 | 662 | #pragma mark ---------- Keyboard Logger Actions ------------- 663 | 664 | void specialAction(OSObject * target, 665 | /* eventType */ unsigned eventType, 666 | /* flags */ unsigned flags, 667 | /* keyCode */ unsigned key, 668 | /* specialty */ unsigned flavor, 669 | /* source id */ UInt64 guid, 670 | /* repeat */ bool repeat, 671 | /* atTime */ AbsoluteTime ts, 672 | OSObject * sender, 673 | void * refcon __unused) 674 | { 675 | DEBUG_LOG( "%s: SpecialAction called with eventType %d\n", gKBDService->getName(), eventType ); 676 | 677 | // only sign of a logout (also thrown when sleeping 678 | if ((eventType == NX_SYSDEFINED) && (!flags) && (key == NX_NOSPECIALKEY)) 679 | gKBDService->kbdClearKeyboards(); 680 | 681 | if (origSpecialCallback) 682 | (* origSpecialCallback)(target, eventType, flags, key, flavor, guid, repeat, ts, sender, 0); 683 | } 684 | 685 | void logAction(OSObject * target, 686 | /* eventFlags */ unsigned eventType, 687 | /* flags */ unsigned flags, 688 | /* keyCode */ unsigned key, 689 | /* charCode */ unsigned charCode, 690 | /* charSet */ unsigned charSet, 691 | /* originalCharCode */ unsigned origCharCode, 692 | /* originalCharSet */ unsigned origCharSet, 693 | /* keyboardType */ unsigned keyboardType, 694 | /* repeat */ bool repeat, 695 | /* atTime */ AbsoluteTime ts, 696 | OSObject * sender, 697 | void * refcon __unused) 698 | { 699 | DEBUG_LOG( "%s: LogAction called with eventType %d\n", gKBDService->getName(), eventType ); 700 | 701 | bool kbdEvtFlag = (eventType == NX_KEYDOWN) || (eventType == NX_FLAGSCHANGED); 702 | 703 | if (gDimTimerActive && !gKBDIsOFF && kbdEvtFlag && gKBDService) { 704 | 705 | if (gKBDTimer != NULL) { 706 | gKBDTimer->cancelTimeout(); 707 | gKBDTimer->setTimeoutMS( gKBDTime ); 708 | DEBUG_LOG( "%s: Key Down, Timer Reloaded %d mS\n", gKBDService->getName(), gKBDTime ); 709 | 710 | if (gKBDimmed && (gKBLT & KBD_ON_MASK)) { 711 | gKBDService->kbdSetUpBacklight(); 712 | gKBDimmed = false; 713 | } 714 | } 715 | }; 716 | 717 | if (origCallback) 718 | (* origCallback) (target, eventType, flags, key, charCode, charSet, origCharCode, origCharSet, keyboardType, repeat, ts, sender, 0); 719 | } 720 | 721 | -------------------------------------------------------------------------------- /ClevoService/ClevoService.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ClevoService_hpp 3 | #define ClevoService_hpp 4 | 5 | #define ClevoService ClevoService 6 | 7 | #define EXPORT __attribute__((visibility("default"))) 8 | 9 | //#pragma clang diagnostic push 10 | #pragma clang diagnostic ignored "-Wdocumentation" 11 | #pragma clang diagnostic ignored "-Winconsistent-missing-override" 12 | #include 13 | //#pragma clang diagnostic pop 14 | #include 15 | #include 16 | 17 | #define private public 18 | #define protected public 19 | #include 20 | #undef private 21 | #undef protected 22 | 23 | //Kernel Server 24 | extern "C" { 25 | #include 26 | } 27 | 28 | #define RunningKernel() MakeKernelVersion(version_major,version_minor,version_revision) 29 | #define MakeKernelVersion(maj,min,rev) (static_cast((maj)<<16)|static_cast((min)<<8)|static_cast(rev)) 30 | 31 | #ifdef DEBUG 32 | #define DEBUG_LOG(args...) do { IOLog(args); } while (0) 33 | #else 34 | #define DEBUG_LOG(args...) do { } while (0) 35 | #endif 36 | 37 | #define SET_KB_LED 0x67 38 | #define SET_FAN 0x79 39 | 40 | #define msgKbdChangeColor 0x80 41 | #define msgKbdLightDOWN 0x81 42 | #define msgKbdLightUP 0x82 43 | #define msgKbdWakeUp 0x83 44 | #define msgAirplane 0x84 45 | #define msgKbdToggleONOFF 0x9F 46 | 47 | #define NVRAM_WAIT_TIME 3000 //3 secs. Time is in mS 48 | #define ACPI_METD_NAME "CLVE" //Our ACPI method name 49 | #define ACPI_CONF_NAME "CONF" //Configuration package name 50 | #define KBD_VAR_NAME "KBLT" //ACPI backlight var name 51 | #define ClevoVendorSTR "com.fjhk" //Server Vendor String 52 | #define ClevoEventCode 0x1962 //Server Event Code 53 | #define KBD_ON_MASK 0x10 //Kbd On/Off Mask 54 | #define KBD_DEF_TIME 180000 //Default 3 minutes. Time is in mS 55 | #define KBD_DIM_LEVEL 5 //Default backlight value when auto dimmed 56 | #define KBD_L0_LEVEL 10 //Default backlight index 0 value 57 | #define KBD_L1_LEVEL 32 //Default backlight index 1 value 58 | #define KBD_L2_LEVEL 96 //Default backlight index 2 value 59 | #define KBD_L3_LEVEL 248 //Default backlight index 3 value 60 | 61 | enum {evtKeyboardBacklight = 1, evtAirplaneMode }; //Clevo Server Event Type 62 | 63 | // Our ClevoService Class... 64 | class EXPORT ClevoService : public IOService 65 | { 66 | OSDeclareDefaultStructors(ClevoService) 67 | 68 | public: 69 | virtual bool init(OSDictionary *dictionary = 0) override; 70 | virtual IOService * probe(IOService *provider, SInt32 *score) override; 71 | virtual bool start(IOService *provider) override; 72 | virtual void stop(IOService *provider) override; 73 | virtual IOReturn message( UInt32 type, IOService *provider, void *argument) override; 74 | virtual void kbdClearKeyboards(); 75 | virtual void kbdSetUpBacklight(); 76 | virtual void kbdLightLevel(UInt8 newLevel); 77 | 78 | protected: 79 | IOWorkLoop * gWorkLoop; 80 | IOTimerEventSource * gNVRAMTimer; 81 | OSArray * loggedKeyboards; 82 | UInt32 gOldKBLT, gKBDInUse; 83 | UInt8 gKBDLevel[4], gKBDDimmingLevel; 84 | u_int32_t vendorID; 85 | 86 | bool setVendorID(const char *vendorCode); 87 | bool sendUserLandMessage(int type, int param1, int param2); 88 | void ACPI_Send(uint32_t arg0, uint32_t arg1, uint32_t arg2); 89 | void saveNVRAM(); 90 | void kbdTimerFired(); 91 | void kbdONOFF(); 92 | void kbdSetColor(); 93 | void loadConfiguration(); 94 | OSObject * translateEntry(OSObject* obj); 95 | OSObject * translateArray(OSArray* array); 96 | 97 | static bool kbdNotificationHandler(void * target, void * refCon, IOService * newService, IONotifier * notifier); 98 | static bool kbdTerminatedNotificationHandler(void * target, void * refCon, IOService * newService, IONotifier * notifier); 99 | 100 | }; 101 | 102 | static IOACPIPlatformDevice * device; 103 | IONotifier * notify, *notifyTerm; 104 | ClevoService * gKBDService; 105 | IOTimerEventSource * gKBDTimer; 106 | KeyboardEventCallback origCallback; 107 | KeyboardSpecialEventCallback origSpecialCallback; 108 | UInt32 gKBLT, gKBDTime; 109 | Boolean gKBDIsOFF, gKBDimmed, gDimTimerActive, gKBDJustDim; 110 | 111 | 112 | void logAction(OSObject *,unsigned,unsigned,unsigned,unsigned, 113 | unsigned,unsigned,unsigned,unsigned,bool,AbsoluteTime,OSObject *,void *); 114 | 115 | void specialAction(OSObject *,unsigned,unsigned, 116 | unsigned,unsigned,UInt64,bool,AbsoluteTime,OSObject *,void *); 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /ClevoService/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(MODULE_NAME) 15 | CFBundlePackageType 16 | KEXT 17 | CFBundleShortVersionString 18 | $(MODULE_VERSION) 19 | CFBundleVersion 20 | $(MODULE_VERSION) 21 | IOKitPersonalities 22 | 23 | ClevoService 24 | 25 | CFBundleIdentifier 26 | ${MODULE_NAME} 27 | IOClass 28 | ClevoService 29 | IONameMatch 30 | 31 | MON0000 32 | 33 | IOProviderClass 34 | IOACPIPlatformDevice 35 | 36 | 37 | NSHumanReadableCopyright 38 | Copyright © 2019-2020 FreeJHack. All rights reserved. 39 | OSBundleCompatibleVersion 40 | 1.0.0 41 | OSBundleLibraries 42 | 43 | com.apple.iokit.IOACPIFamily 44 | 1.0.0d1 45 | com.apple.iokit.IOHIDFamily 46 | 2.0.0 47 | com.apple.kpi.bsd 48 | 12.0.0 49 | com.apple.kpi.iokit 50 | 12.0.0 51 | com.apple.kpi.libkern 52 | 12.0.0 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /ClevoServiceAgent/BezelServices.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef BezelServices_h 7 | #define BezelServices_h 8 | 9 | typedef enum { 10 | BSGraphicBacklightMeter = 0xfffffff7, 11 | BSGraphicBacklightFailure = 0xfffffff6, 12 | BSGraphicBacklightFailureMessage = 0xfffffff3, 13 | BSGraphicBacklightDoubleFailureMessage = 0xfffffff2, 14 | BSGraphicKeyboardBacklightMeter = 0xfffffff1, 15 | BSGraphicKeyboardBacklightDisabledMeter = 0xfffffff0, 16 | BSGraphicKeyboardBacklightNotConnected = 0xffffffef, 17 | BSGraphicKeyboardBacklightDisabledNotConnected = 0xffffffee, 18 | BSGraphicMacProOpen = 0xffffffe9, 19 | BSGraphicSpeakerMuted = 0xffffffe8, 20 | BSGraphicSpeaker = 0xffffffe7, 21 | BSGraphicRemoteBattery = 0xffffffe6, 22 | BSGraphicHotspot = 0xffffffe5, 23 | BSGraphicSleep = 0xffffffe3, 24 | BSGraphicSpeakerDisabledMuted = 0xffffffe2, 25 | BSGraphicSpeakerDisabled = 0xffffffe1, 26 | BSGraphicSpeakerMeter = 0xffffffe0, 27 | BSGraphicNewRemoteBattery = 0xffffffcb, 28 | } BSGraphic; 29 | 30 | extern void *BSDoGraphicWithMessage(long arg0, BSGraphic arg1, int arg2, const char *arg3, int length); 31 | extern void *BSDoGraphicWithMeterAndTimeout(long arg0, BSGraphic arg1, int arg2, float v, int timeout); 32 | 33 | #endif /* BezelServices_h */ 34 | -------------------------------------------------------------------------------- /ClevoServiceAgent/OSD.h: -------------------------------------------------------------------------------- 1 | // 2 | // OSD.h 3 | // 4 | // Copyright © 2018-2019 Le Bao Hiep. All rights reserved. 5 | // 6 | 7 | #ifndef OSD_h 8 | #define OSD_h 9 | 10 | typedef enum { 11 | OSDGraphicBacklight = 1, // 1, 2, 7, 8 12 | OSDGraphicSpeaker = 3, // 3, 5, 17, 23 13 | OSDGraphicSpeakerMuted = 4, // 4, 16, 21, 22 14 | OSDGraphicEject = 6, 15 | OSDGraphicNoWiFi = 9, 16 | OSDGraphicKeyboardBacklightMeter = 11, // 11, 25 17 | OSDGraphicKeyboardBacklightDisabledMeter = 12, // 12, 26 18 | OSDGraphicKeyboardBacklightNotConnected = 13, // 13, 27 19 | OSDGraphicKeyboardBacklightDisabledNotConnected = 14, // 14, 28, 29 20 | OSDGraphicMacProOpen = 15, 21 | OSDGraphicHotspot = 19, 22 | OSDGraphicSleep = 20, 23 | // There may be more 24 | } OSDGraphic; 25 | 26 | typedef enum { 27 | OSDPriorityDefault = 0x1f4 28 | } OSDPriority; 29 | 30 | @interface OSDManager : NSObject 31 | + (instancetype)sharedManager; 32 | - (void)showImage:(OSDGraphic)image onDisplayID:(CGDirectDisplayID)display priority:(OSDPriority)priority msecUntilFade:(int)timeout; 33 | - (void)showImage:(OSDGraphic)image onDisplayID:(CGDirectDisplayID)display priority:(OSDPriority)priority msecUntilFade:(int)timeout withText:(NSString *)text; 34 | - (void)showImage:(OSDGraphic)image onDisplayID:(CGDirectDisplayID)display priority:(OSDPriority)priority msecUntilFade:(int)timeout filledChiclets:(int)filled totalChiclets:(int)total locked:(BOOL)locked; 35 | @end 36 | 37 | 38 | #endif /* OSD_h */ 39 | -------------------------------------------------------------------------------- /ClevoServiceAgent/com.fjhk.ClevoService.agent.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | KeepAlive 6 | 7 | Label 8 | com.fjhk.ClevoService.agent 9 | ProgramArguments 10 | 11 | /Library/Extensions/ClevoService.kext/Contents/PlugIns/ClevoServiceAgent 12 | 13 | RunAtLoad 14 | 15 | ServiceIPC 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /ClevoServiceAgent/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | * main.m 3 | * 4 | * ClevoServiceAgent 5 | * 6 | */ 7 | 8 | #import 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import "OSD.h" 14 | #include 15 | 16 | #define ClevoVendorSTR "com.fjhk" //Server Vendor Code 17 | #define ClevoEventCode 0x1962 //Server Event Code 18 | enum {evtKeyboardBacklight = 1, evtAirplaneMode }; //Clevo Server Event Type 19 | 20 | struct ClevoServiceMessage { 21 | int type; 22 | int param1; 23 | int param2; 24 | }; 25 | 26 | typedef enum { 27 | BSGraphicBacklightMeter = 0xfffffff7, 28 | BSGraphicBacklightFailure = 0xfffffff6, 29 | BSGraphicBacklightFailureMessage = 0xfffffff3, 30 | BSGraphicBacklightDoubleFailureMessage = 0xfffffff2, 31 | BSGraphicKeyboardBacklightMeter = 0xfffffff1, 32 | BSGraphicKeyboardBacklightDisabledMeter = 0xfffffff0, 33 | BSGraphicKeyboardBacklightNotConnected = 0xffffffef, 34 | BSGraphicKeyboardBacklightDisabledNotConnected = 0xffffffee, 35 | BSGraphicMacProOpen = 0xffffffe9, 36 | BSGraphicSpeakerMuted = 0xffffffe8, 37 | BSGraphicSpeaker = 0xffffffe7, 38 | BSGraphicRemoteBattery = 0xffffffe6, 39 | BSGraphicHotspot = 0xffffffe5, 40 | BSGraphicSleep = 0xffffffe3, 41 | BSGraphicSpeakerDisabledMuted = 0xffffffe2, 42 | BSGraphicSpeakerDisabled = 0xffffffe1, 43 | BSGraphicSpeakerMeter = 0xffffffe0, 44 | BSGraphicNewRemoteBattery = 0xffffffcb, 45 | } BSGraphic; 46 | 47 | #pragma mark -------------- External Functions -------------- 48 | 49 | extern void *BSDoGraphicWithMessage(long arg0, BSGraphic arg1, int arg2, const char *arg3, int length); 50 | extern void *BSDoGraphicWithMeterAndTimeout(long arg0, BSGraphic arg1, int arg2, float v, int timeout); 51 | 52 | // requires IOBluetooth.framework 53 | extern void IOBluetoothPreferenceSetControllerPowerState(int); 54 | extern int IOBluetoothPreferenceGetControllerPowerState(void); 55 | 56 | static void *(*_BSDoGraphicWithMeterAndTimeout)(CGDirectDisplayID arg0, BSGraphic arg1, int arg2, float v, int timeout) = NULL; 57 | 58 | #pragma mark -------------- Functions -------------- 59 | 60 | bool _loadBezelServices() { 61 | void *handle = dlopen("/System/Library/PrivateFrameworks/BezelServices.framework/Versions/A/BezelServices", RTLD_GLOBAL); 62 | if (!handle) { 63 | #if DEBUG 64 | NSLog(@"Error opening framework"); 65 | #endif 66 | return NO; 67 | } else { 68 | _BSDoGraphicWithMeterAndTimeout = dlsym(handle, "BSDoGraphicWithMeterAndTimeout"); 69 | return _BSDoGraphicWithMeterAndTimeout != NULL; 70 | } 71 | } 72 | 73 | bool _loadOSDFramework() { 74 | return [[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/OSD.framework"] load]; 75 | } 76 | 77 | void showBezelServices(BSGraphic image, float filled) { 78 | CGDirectDisplayID currentDisplayId = [NSScreen.mainScreen.deviceDescription [@"NSScreenNumber"] unsignedIntValue]; 79 | _BSDoGraphicWithMeterAndTimeout(currentDisplayId, image, 0x0, filled, 1); 80 | } 81 | 82 | void showOSD(OSDGraphic image, int filled, int total) { 83 | CGDirectDisplayID currentDisplayId = [NSScreen.mainScreen.deviceDescription [@"NSScreenNumber"] unsignedIntValue]; 84 | [[NSClassFromString(@"OSDManager") sharedManager] showImage:image onDisplayID:currentDisplayId priority:OSDPriorityDefault msecUntilFade:1000 filledChiclets:filled totalChiclets:total locked:NO]; 85 | } 86 | 87 | void showKBoardBLightStatus(int level, int max) { 88 | if (_BSDoGraphicWithMeterAndTimeout != NULL) { 89 | // El Capitan and probably older systems 90 | if (level) 91 | showBezelServices(BSGraphicKeyboardBacklightMeter, (float)level/max); 92 | else 93 | showBezelServices(BSGraphicKeyboardBacklightDisabledMeter, 0); 94 | } else { 95 | // Sierra+ 96 | if (level) 97 | showOSD(OSDGraphicKeyboardBacklightMeter, level, max); 98 | else 99 | showOSD(OSDGraphicKeyboardBacklightDisabledMeter, level, max); 100 | } 101 | } 102 | 103 | void showWifiStatus(bool enabled) { 104 | if (_BSDoGraphicWithMeterAndTimeout != NULL) { 105 | if (!enabled) showBezelServices(BSGraphicHotspot, 0); 106 | } else { 107 | if (!enabled) showOSD(OSDGraphicNoWiFi, 0, 1); 108 | } 109 | } 110 | 111 | BOOL airplaneModeEnabled = NO, lastWifiState; 112 | int lastBluetoothState; 113 | void toggleAirplaneMode() { 114 | airplaneModeEnabled = !airplaneModeEnabled; 115 | 116 | CWInterface *currentInterface = [CWWiFiClient.sharedWiFiClient interface]; 117 | NSError *err = nil; 118 | 119 | if (airplaneModeEnabled) { 120 | lastWifiState = currentInterface.powerOn; 121 | lastBluetoothState = IOBluetoothPreferenceGetControllerPowerState(); 122 | [currentInterface setPower:NO error:&err]; 123 | IOBluetoothPreferenceSetControllerPowerState(0); 124 | showWifiStatus( NO ); 125 | } else { 126 | [currentInterface setPower:lastWifiState error:&err]; 127 | IOBluetoothPreferenceSetControllerPowerState(lastBluetoothState); 128 | showWifiStatus( lastWifiState ); 129 | } 130 | } 131 | 132 | #pragma mark -------------- Main -------------- 133 | 134 | int main(int argc, const char *argv[]) { 135 | @autoreleasepool { 136 | //printf("ClevoServiceDaemon started...\n"); 137 | 138 | if (!_loadBezelServices()) _loadOSDFramework(); 139 | 140 | //system socket 141 | int systemSocket = -1; 142 | 143 | //create system socket to receive kernel event data 144 | systemSocket = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT); 145 | 146 | //struct for vendor code 147 | // ->set via call to ioctl/SIOCGKEVVENDOR 148 | struct kev_vendor_code vendorCode = {0}; 149 | 150 | //set vendor name string 151 | strncpy(vendorCode.vendor_string, ClevoVendorSTR, KEV_VENDOR_CODE_MAX_STR_LEN); 152 | 153 | //get vendor name -> vendor code mapping 154 | // ->vendor id, saved in 'vendorCode' variable 155 | ioctl(systemSocket, SIOCGKEVVENDOR, &vendorCode); 156 | 157 | //struct for kernel request 158 | // ->set filtering options 159 | struct kev_request kevRequest = {0}; 160 | 161 | //init filtering options 162 | // ->only interested in objective-see's events kevRequest.vendor_code = vendorCode.vendor_code; 163 | 164 | //...any class 165 | kevRequest.kev_class = KEV_ANY_CLASS; 166 | 167 | //...any subclass 168 | kevRequest.kev_subclass = KEV_ANY_SUBCLASS; 169 | 170 | //tell kernel what we want to filter on 171 | ioctl(systemSocket, SIOCSKEVFILT, &kevRequest); 172 | 173 | //bytes received from system socket 174 | ssize_t bytesReceived = -1; 175 | 176 | //message from kext 177 | // ->size is cumulation of header, struct, and max length of a proc path 178 | char kextMsg[KEV_MSG_HEADER_SIZE + sizeof(struct ClevoServiceMessage)] = {0}; 179 | 180 | struct ClevoServiceMessage *message = NULL; 181 | 182 | while (YES) { 183 | //printf("listening...\n"); 184 | 185 | bytesReceived = recv(systemSocket, kextMsg, sizeof(kextMsg), 0); 186 | if (bytesReceived != sizeof(kextMsg)) continue; 187 | 188 | //struct for broadcast data from the kext 189 | struct kern_event_msg *kernEventMsg = {0}; 190 | 191 | //type cast 192 | // ->to access kev_event_msg header 193 | kernEventMsg = (struct kern_event_msg*)kextMsg; 194 | 195 | //only care about 'process began' events 196 | if (ClevoEventCode != kernEventMsg->event_code) continue; 197 | 198 | //printf("new message\n"); 199 | 200 | //typecast custom data 201 | // ->begins right after header 202 | message = (struct ClevoServiceMessage*)&kernEventMsg->event_data[0]; 203 | 204 | #if DEBUG 205 | printf("type:%d x:%d y:%d\n", message->type, message->param1, message->param2); 206 | #endif 207 | switch (message->type) { 208 | case evtKeyboardBacklight: 209 | showKBoardBLightStatus(message->param1, message->param2); 210 | break; 211 | case evtAirplaneMode: 212 | toggleAirplaneMode(); 213 | break; 214 | #if DEBUG 215 | default: 216 | printf("unknown type %d, param1 %d\n", message->type, message->param1); 217 | //Just for testing OSD images... 218 | int a, b, c; 219 | a = (message->param1 & 0xFF00) >> 8; 220 | b = (message->param1 & 0xF0) >> 4; 221 | c = message->param1 & 0xF; 222 | showOSD(a, b, c); 223 | #endif 224 | } 225 | } 226 | } 227 | 228 | return 0; 229 | } 230 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, FreeJHack 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ClevoService 2 | 3 | [![Github release](https://img.shields.io/github/v/release/freejhack/ClevoService.svg?color=blue)](https://github.com/freejhack/ClevoService/releases/latest) 4 | [![Github downloads](https://img.shields.io/github/downloads/freejhack/ClevoService/total.svg?color=blue)](https://github.com/freejhack/ClevoService/releases) 5 | 6 | An open source kernel extension enabling keyboard backlight, AutoDim & fan control for Clevo Hackintosh. 7 | Fully tested on Clevo P9XXEN_EF_ED, but it should even work on most Clevo's laptops provided with full-colour backlight keyboard. 8 | 9 | # How it works 10 | The keyboard backlight is controlled through the numeric keypad and restored during boot and sleep/wake. 11 | Native NVRAM is necessary and supported by Clevo P9XXEN_EF_ED, however, the kext should even work with emulated NVRAM (not tested). 12 | 13 | ### The following features are supported: 14 | * Backlight directly controlled from numeric keypad (same Windows® keys) 15 | * Backlight colour, on/off and light level saved in NVRAM 16 | * Backlight automatically restored during boot and sleep/wake 17 | * Up to 9 preset keyboard backlight different colours 18 | * Airplane led used to indicate Shift-Lock enabled/disabled 19 | * Fully customizable 20 | * Configurable backlight intensity levels 21 | * AutoDim, an automatic keyboard backlight dimming including: configurable Activation, Dim or OFF and Dimming wait time, restore previous backlight intensity on key stroke, configuration customizable in SSDT-ClevoService.dsl 22 | 23 | The below features are requiring `ClevoServiceAgent` running (v. 1.2.0+): 24 | * Keyboard backliighting OSD icon 25 | * Full Airplane compatibility with Wifi/BT power on/off 26 | * Wifi/BT OSD icon 27 | 28 | The keyboard backlighting is fully controlled from numeric keypad according to Clevo's standard keys: 29 | * Change colour with `Fn /` 30 | * Turn ON/OFF with `Fn *` 31 | * Decrease backlight with `Fn -` 32 | * Increase backlight with `Fn +` 33 | 34 | ## How AutoDim works 35 | The AutoDim reduces, or completely turns OFF, the backlight If the keyboard is not used for the preset time. 36 | It is fully controlled from ACPI with three properties: `KbdAutoDimTimerActive, KbdAutoDimActive, KbdAutoDimTime` 37 | 38 | It is activated setting the property `KbdAutoDimTimerActive` to true, or false for deactivate it. 39 | The property `KbdAutoDimActive` is used to control whether the keyboard backlight will be dimmed, setting to true, or turned off, setting to false, after the waiting time is elapsed. 40 | The waiting time is set with `KbdAutoDimTime`. The number must be in the range from 5 to 1800 (seconds). 41 | 42 | Therefore, if the AutoDim is activated with `KbdAutoDimTimerActive = true`, the keyboard backlight is automatically reduced at the minimum with `KbdAutoDimActive = true`, or completely turned OFF with `KbdAutoDimActive = false`, after the wait time `KbdAutoDimTime`. Pressing any key, the backlight intensity is restored. 43 | 44 | All the above properties can be modified in the `CONF` method of `CLV0` device included into SSDT-ClevoService.dsl file. 45 | The boolean values can be set using the well known method `">y"` for true and `">n"` for false. (Thanks RM) 46 | If the `CONF` method is not found or a property is missing, the default loaded values are the following: 47 | 48 | - KbdAutoDimTimerActive = true 49 | - KbdAutoDimActive = true 50 | - KbdAutoDimTime = 180 51 | 52 | It is not mandatory to change all properties at once, only the needed ones can be changed. 53 | You may want to check all the above properties in IORegystryExplorer looking at ClevoService driver attached to CLV0 device. 54 | 55 | ## Backlight levels configuration 56 | ### For advanced users 57 | The `CONF` method may also include two properties for controlling the backlight intensity levels, `KbdDimmingLevel` and `KbdLevels`. 58 | KbdDimmingLevel is the intesity of the backlight when dimmed, if AutoDim is active. 59 | KbdLevels is an array containing four backlight levels used by ClevoService to change the backlight intesity when `Fn -` or `Fn +` keys are pressed. 60 | Index zero is the lowest, three the highest. The value is in the range 0÷255. 61 | Those properties can be added to the `CONF` method otherwise the default values will be used instead. 62 | 63 | # How to install 64 | In order to simplify the installation process, an SSDT (.dsl) file has been included in the package. 65 | However, some DSDT's methods need to be patched in order to properly work with provided SSDT. 66 | The file also includes the methods to manage the three fans. 67 | 68 | * Open the SSDT-ClevoService.dsl with MaciASL and save it as `.aml` file into Clover/OpenCore EFI ACPI/patched folder. 69 | * Install the ClevoService kext into `/Library/Extensions` folder using your preferred kext installer or using terminal 70 | * Rebuild kext cache and reboot 71 | 72 | The following methods must be patched in Clover/OpenCore config.plist ACPI section changing the method name: 73 | 74 | Rename _WAK => XWAK 75 | 76 | * Comment: _WAK to XWAK, Find: 5F57414B, Replace: 5857414B 77 | 78 | Rename _Q14 => XQ14 (Check your DSDT, Airplane key could be different) 79 | 80 | * Comment: _Q14 to XQ14, Find: 5F513134, Replace: 58513134 81 | 82 | Rename _Q50 => XQ50 83 | 84 | * Comment: _Q50 to XQ50, Find: 5F513530, Replace: 58513530 85 | 86 | ## ClevoServiceAgent installation 87 | Starting from version 1.2.0, the ClevoService kext includes in its PlugIns folder the `ClevoServiceAgent` file, which is needed for some OSD features and Wifi/Bluetooth power on/off. This is a low-level agent used by ClevoService that must be launched during boot. 88 | For an easier installation procedure, the launching `com.fjhk.ClevoService.agent.plist` file is already provided. Simply install it in the OSX `/Library/LaunchAgents/` folder with the below terminal commands (without asterisk): 89 | 90 | * sudo cp yourPath/com.fjhk.ClevoService.agent.plist /Library/LaunchAgents 91 | * sudo chmod 644 /Library/LaunchAgents/com.fjhk.ClevoService.agent.plist 92 | * sudo chown root:wheel /Library/LaunchAgents/com.fjhk.ClevoService.agent.plist 93 | 94 | then reboot. 95 | Note that you have to change `yourPath` with the full directory's path where you saved the `.plist` file. 96 | The ClevoService kext `must` be installed in the `/Library/Extensions` folder (no injecting) otherwise the agent cannot be loaded. 97 | 98 | In order to check whether the agent is correctly installed and running, open `Activity Monitor` app and search for `ClevoServiceAgent`: it must be present, otherwise OSD icons and Wifi/BT power on/off won't work. 99 | 100 | Below the terminal commands for unload and uninstall the `.plist` agent launching file (without asterisk): 101 | 102 | * launchctl unload /Library/LaunchAgents/com.fjhk.ClevoService.agent.plist 103 | * sudo rm /Library/LaunchAgents/com.fjhk.ClevoService.agent.plist 104 | 105 | ## Important Note 106 | ClevoService is using the device DCHU for backlighting and it should be available in your original DSDT. However, if missing, search for method WMBB in the device WMI. 107 | At least one method must be available in your DSDT otherwise the keyboard backlight won't work. 108 | For any issue, you may want to install the debug version checking the system log for more details. 109 | The Kext has been compiled with XCode 10.2.1 and fully tested in Mojave 10.14.6 and Catalina 10.15.5 (Min OSX 10.11). 110 | 111 | ### Credits 112 | - A big thanks deserve [Datasone](https://github.com/datasone/ClevoControl) for the reverse engineering and for discovering FAN and KBD bios commands, giving me a good starting point and saving me a lot of reversing time. 113 | - Thanks to [RehabMan](https://bitbucket.org/RehabMan/), [SlEePlEs5](https://github.com/SlEePlEs5/logKext) and [hieplpvip](https://github.com/hieplpvip) for some useful pieces of code 114 | - [Apple](https://www.apple.com) for macOS 115 | -------------------------------------------------------------------------------- /SSDT-ClevoService.dsl: -------------------------------------------------------------------------------- 1 | /* 2 | * Intel ACPI Component Architecture 3 | * AML/ASL+ Disassembler version 20180427 (64-bit version) 4 | * Copyright (c) 2000 - 2018 Intel Corporation 5 | */ 6 | 7 | DefinitionBlock ("", "SSDT", 1, "hack ", "CLEVO", 0x00000000) 8 | { 9 | External (_SB_.AC__, DeviceObj) // (from opcode) 10 | External (_SB_.AC__.ACFG, IntObj) // (from opcode) 11 | External (_SB_.DCHU.ZEVT, MethodObj) // 3 Arguments (from opcode) 12 | External (_SB_.PCI0, DeviceObj) // (from opcode) 13 | External (_SB_.PCI0.LPCB, DeviceObj) // (from opcode) 14 | External (_SB_.PCI0.LPCB.EC__, DeviceObj) // (from opcode) 15 | External (_SB_.PCI0.LPCB.EC__.AFLT, FieldUnitObj) // (from opcode) 16 | External (_SB_.PCI0.LPCB.EC__.AIRP, FieldUnitObj) // (from opcode) 17 | External (_SB_.PCI0.LPCB.EC__.BAT0, FieldUnitObj) // (from opcode) 18 | External (_SB_.PCI0.LPCB.EC__.ECOK, IntObj) // (from opcode) 19 | External (_SB_.PCI0.LPCB.EC__.OEM4, FieldUnitObj) // (from opcode) 20 | External (_SB_.PCI0.LPCB.EC__.XQ50, MethodObj) // 0 Arguments (from opcode) 21 | External (_SB_.PCI0.PEG0.PEGP._OFF, MethodObj) // 0 Arguments (from opcode) 22 | External (_SB_.PCI0.LPCB.PS2K, DeviceObj) // (from opcode) 23 | External (_SB_.WMI.WMBB, MethodObj) // (from opcode) 24 | External (XWAK, MethodObj) // 1 Arguments (from opcode) 25 | 26 | Scope (_SB.PCI0.LPCB.EC) 27 | { 28 | OperationRegion (EC82, EmbeddedControl, Zero, 0xFF) 29 | Field (EC82, ByteAcc, Lock, Preserve) 30 | { 31 | Offset (0xD0), 32 | FCP0, 8, 33 | FCP1, 8, 34 | FGP0, 8, 35 | FGP1, 8, 36 | Offset (0xE0), 37 | FGP2, 8, 38 | FGP3, 8, 39 | } 40 | } 41 | 42 | Method (_WAK, 1, Serialized) 43 | { 44 | If ((Arg0 == 0) || (Arg0 > 4)) {Arg0 = 3} //OSX also uses Arg0=3. Force 3 for _WAK compatibility... 45 | // Dual GPU OFF, remove it if not necessary 46 | \_SB.PCI0.PEG0.PEGP._OFF () 47 | // After a sleep AFLT=1 means battery fail, we need to reset... 48 | // Remove it if not necessary 49 | Store (Zero, \_SB.PCI0.LPCB.EC.AFLT) 50 | //After a sleep sleep the battery is not present, we need to set... 51 | // Remove it if not necessary 52 | Store (One, \_SB.PCI0.LPCB.EC.BAT0) 53 | Notify (\_SB.CLV0, 0x83) //Set backlight according to settings 54 | Return (XWAK (Arg0)) //We're going to call original _WAK method... 55 | } 56 | 57 | Scope (_SB.PCI0.LPCB.EC) 58 | { 59 | Method (_Q14, 0, NotSerialized) // _Qxx: EC Query 60 | { 61 | Notify (CLV0, 0x84) //Airplane key: switch-off Wifi & Bluetooth 62 | Return (Zero) 63 | } 64 | 65 | Method (_Q50, 0, NotSerialized) // _Qxx: EC Query 66 | { 67 | Store (OEM4, Local0) 68 | If (LEqual (Local0, 0x80)) 69 | { 70 | Notify (CLV0, 0x80) 71 | Return (Zero) 72 | } 73 | 74 | If (LEqual (Local0, 0x81)) 75 | { 76 | Notify (CLV0, 0x81) 77 | Return (Zero) 78 | } 79 | 80 | If (LEqual (Local0, 0x82)) 81 | { 82 | Notify (CLV0, 0x82) 83 | Return (Zero) 84 | } 85 | 86 | If (LEqual (Local0, 0x9F)) 87 | { 88 | Notify (CLV0, 0x9F) 89 | Return (Zero) 90 | } 91 | 92 | If (LEqual (Local0, 0xC9)) 93 | { 94 | And (AIRP, 0xBF, AIRP) //Set Airplane led for Shift-Lock 95 | Return (Zero) 96 | } 97 | 98 | If (LEqual (Local0, 0xCA)) 99 | { 100 | Or (AIRP, 0x40, AIRP) //Reset Airplane led for Shift-Lock 101 | Return (Zero) 102 | } 103 | 104 | XQ50 () 105 | Return (Zero) 106 | } 107 | } 108 | 109 | Device (_SB.CLV0) 110 | { 111 | Name (_HID, EisaId ("PNP0C02")) // _HID: Hardware ID 112 | Name (_CID, "MON0000") // _CID: Compatible ID 113 | Name (KLVN, Zero) 114 | 115 | //If you already have your own .dsl or .aml file, 116 | //you can just copy the below CONF package to 117 | Name (CONF, Package () //AutoDim configuration package 118 | { 119 | "KbdAutoDimTimerActive", ">y", //AutoDim Active... 120 | "KbdAutoDimActive", ">y", //Dim activated... set ">n" for OFF 121 | "KbdAutoDimTime", 180 //Two minutes, change it as you wish... 122 | //"KbdDimmingLevel", 0x5, 123 | //"KbdLevels", Package() {0x8, 0x20, 0x60, 0xFF}, 124 | }) 125 | 126 | Name (TACH, Package (0x06) //Add method for the 3 fans... 127 | { 128 | "CPU Fan", 129 | "VEN1", 130 | "GPU Fan #1", 131 | "VEN2", 132 | "GPU Fan #2", 133 | "VEN3" 134 | }) 135 | Method (VEN1, 0, Serialized) 136 | { 137 | If (\_SB.PCI0.LPCB.EC.ECOK) 138 | { 139 | Store (B1B2 (\_SB.PCI0.LPCB.EC.FCP1, \_SB.PCI0.LPCB.EC.FCP0), Local0) 140 | If (LLessEqual (Local0, Zero)) 141 | { 142 | Return (Zero) 143 | } 144 | 145 | Divide (0x0020E6BC, Local0, , Local0) 146 | Return (Local0) 147 | } 148 | 149 | Return (Zero) 150 | } 151 | 152 | Method (VEN2, 0, Serialized) 153 | { 154 | If (\_SB.PCI0.LPCB.EC.ECOK) 155 | { 156 | Store (B1B2 (\_SB.PCI0.LPCB.EC.FGP1, \_SB.PCI0.LPCB.EC.FGP0), Local0) 157 | If (LLessEqual (Local0, Zero)) 158 | { 159 | Return (Zero) 160 | } 161 | 162 | Divide (0x0020E6BC, Local0, , Local0) 163 | Return (Local0) 164 | } 165 | 166 | Return (Zero) 167 | } 168 | 169 | Method (VEN3, 0, Serialized) 170 | { 171 | If (\_SB.PCI0.LPCB.EC.ECOK) 172 | { 173 | Store (B1B2 (\_SB.PCI0.LPCB.EC.FGP3, \_SB.PCI0.LPCB.EC.FGP2), Local0) 174 | If (LLessEqual (Local0, Zero)) 175 | { 176 | Return (Zero) 177 | } 178 | 179 | Divide (0x0020E6BC, Local0, , Local0) 180 | Return (Local0) 181 | } 182 | 183 | Return (Zero) 184 | } 185 | 186 | Method (CLVE, 3, Serialized) 187 | { 188 | If (CondRefOf( \_SB.DCHU.ZEVT )) //Vers 1.0.1 17/02/2020 189 | { 190 | \_SB.DCHU.ZEVT (Arg0, Arg1, Arg2) 191 | } elseIf (CondRefOf( \_SB.WMI.WMBB )) //Added support for WMBB method 192 | { 193 | \_SB.WMI.WMBB (Arg0, Arg1, Arg2) 194 | } 195 | } 196 | 197 | Method (_INI, 0, NotSerialized) // _INI: Initialize 198 | { 199 | // DGPU OFF, Remove it or update path as necessary... 200 | If (CondRefOf (\_SB.PCI0.PEG0.PG00._OFF)) 201 | { 202 | \_SB.PCI0.PEG0.PEGP._OFF () 203 | } 204 | 205 | If (CondRefOf (\_SB.PCI0.LPCB.EC.AIRP)) 206 | { 207 | And (\_SB.PCI0.LPCB.EC.AIRP, 0xBF, \_SB.PCI0.LPCB.EC.AIRP) 208 | } 209 | } 210 | } 211 | 212 | Method (B1B2, 2, NotSerialized) 213 | { 214 | Return (Or (Arg0, ShiftLeft (Arg1, 0x08))) 215 | } 216 | } 217 | 218 | --------------------------------------------------------------------------------