如何使用IOConnectCallScalarMethod只读取值?

iqih9akk  于 2023-05-16  发布在  Scala
关注(0)|答案(1)|浏览(256)

我正在尝试从macOS的启动守护程序中读取当前的kPMSetClamshellSleepState设置。我尝试了以下方法:

io_connect_t connection = IO_OBJECT_NULL;
io_service_t pmRootDomain = IOServiceGetMatchingService(kIOMainPortDefault,
                                       IOServiceMatching("IOPMrootDomain"));

if(pmRootDomain)
{
    kern_return_t res = IOServiceOpen(pmRootDomain, current_task(), 0, &connection);
    if(res == KERN_SUCCESS)
    {
        uint64_t outputs[1] = { };
        uint32_t num_outputs = 1;

        res = IOConnectCallScalarMethod(connection,
                                        kPMSetClamshellSleepState,
                                        NULL,
                                        0,
                                        outputs,
                                        &num_outputs);
        
        if(res == KERN_SUCCESS)
        {
            //Done
        }

        //Close connection
        IOServiceClose(connection);
    }

    IOObjectRelease(pmRootDomain);
}

但在本例中,对IOConnectCallScalarMethod的调用返回0xE00002C2-536870206kIOReturnBadArgument
如何读取设置?任何建议。

wgx48brx

wgx48brx1#

I/O Kit用户客户端外部方法

对于I/O Kit用户/客户端的外部方法API以及可以传递给它的标量和结构输入或输出的组合,没有通用的语义可以推断。这个always取决于你要连接的特定IOUserClient子类,以及你要传递的特定方法选择器。
在您的例子中,您正在处理RootDomainUserClient和选择器kPMSetClamshellSleepState,其允许的参数定义如下:

[kPMSetClamshellSleepState] = {
            .function                 = &RootDomainUserClient::externalMethodDispatched,
            .checkScalarInputCount    = 1,
            .checkStructureInputSize  = 0,
            .checkScalarOutputCount   = 0,
            .checkStructureOutputSize = 0,
            .allowAsync               = false,
            .checkEntitlement         = NULL,
        },

因此,您只能使用精确的1个标量输入来调用此选择器,而不能使用其他参数。而且,它的返回值不依赖于先前的状态。没有办法破解这个特定的界面来做你想做的事情。

翻盖状态

如果跟踪外部方法,您将发现状态存储在IOPMRootDomain对象的clamshellSleepDisableMask字段中。我没有看到一个直接的用户空间访问器。
它在IOPMrootDomain::shouldSleepOnClamshellClosed()函数中被引用,其状态反映在kAppleClamshellCausesSleepKey/"AppleClamshellCausesSleep"属性中。可以从用户空间使用IORegistryEntryCreateCFProperty查询此属性。
暴露属性的确切值还取决于一系列其他标志:

  • 要使属性为trueclamshellSleepDisableMask必须为false
  • 除了clamshellSleepDisableMasktrue之外,属性也可以是false

因此,你不能仅从这个属性100%准确地推断出clamshellSleepDisableMask,但也许这已经足够了。您还可以从我停止的IOPMRootDomain源代码中找到线索,也许在另一个地方您可以推断出有关此标志状态的信息。值得注意的是,当更新上述值时,kIOPMMessageClamshellStateChange消息显然会被传递给侦听器--也许响应这样的变化会让您找到一个可靠的解决方案。

相关问题