macos iokit在swift中通过属性名称获得服务
我想获得所有包含特定属性的服务。
AppleDeviceManagementHIDEventService <class AppleDeviceManagementHIDEventService, id 0x100000a79, registered, matched, active, busy 0 (0 ms), retain 7>
| | | | | | {
| | | | | | "IOMatchedAtBoot" = Yes
| | | | | | "LowBatteryNotificationPercentage" = 2
| | | | | | "PrimaryUsagePage" = 65280
| | | | | | "BatteryFaultNotificationType" = "TPBatteryFault"
| | | | | | "HasBattery" = Yes
| | | | | | "VendorID" = 76
| | | | | | "VersionNumber" = 0
| | | | | | "Built-In" = No
| | | | | | "DeviceAddress" = "10-94-bb-ab-b9-53"
| | | | | | "WakeReason" = "Host (0x01)"
| | | | | | "Product" = "Magic Trackpad"
| | | | | | "SerialNumber" = "10-94-bb-ab-b9-53"
| | | | | | "Transport" = "Bluetooth"
| | | | | | "BatteryLowNotificationType" = "TPLowBattery"
| | | | | | "ProductID" = 613
| | | | | | "DeviceUsagePairs" = ({"DeviceUsagePage"=65280,"DeviceUsage"=11},{"DeviceUsagePage"=65280,"DeviceUsage"=20})
| | | | | | "IOPersonalityPublisher" = "com.apple.driver.AppleTopCaseHIDEventDriver"
| | | | | | "MTFW Version" = 920
| | | | | | "BD_ADDR" = <1094bbabb953>
| | | | | | "BatteryPercent" = 42
| | | | | | "BatteryStatusNotificationType" = "BatteryStatusChanged"
| | | | | | "CriticallyLowBatteryNotificationPercentage" = 1
| | | | | | "ReportInterval" = 11250
| | | | | | "RadioFW Version" = 368
| | | | | | "VendorIDSource" = 1
| | | | | | "STFW Version" = 2144
| | | | | | "CFBundleIdentifier" = "com.apple.driver.AppleTopCaseHIDEventDriver"
| | | | | | "IOProviderClass" = "IOHIDInterface"
| | | | | | "LocationID" = 1001109843
| | | | | | "BluetoothDevice" = Yes
| | | | | | "IOClass" = "AppleDeviceManagementHIDEventService"
| | | | | | "HIDServiceSupport" = No
| | | | | | "CFBundleIdentifierKernel" = "com.apple.driver.AppleTopCaseHIDEventDriver"
| | | | | | "ProductIDArray" = (613)
| | | | | | "BatteryStatusFlags" = 0
| | | | | | "ColorID" = 5
| | | | | | "IOMatchCategory" = "IODefaultMatchCategory"
| | | | | | "CountryCode" = 0
| | | | | | "IOProbeScore" = 7175
| | | | | | "PrimaryUsage" = 11
| | | | | | "IOGeneralInterest" = "IOCommand is not serializable"
| | | | | | "BTFW Version" = 368
| | | | | | }
例如。每个包含儿童属性的服务“ BatteryPercent”
。
我知道我可以通过使用ioservicenamematching
,然后ioservicegetMatchingServices
获得特定的服务,但这似乎在服务内部的属性上不起作用。有可能吗?我想匹配BatteryPercent,然后获得ProductName。
编辑:这是我目前用来获取触控板电池的代码。
func getTrackpadBattery() -> (String, Int) {
var serialPortIterator = io_iterator_t()
var object : io_object_t
var percent: Int = 0
var productName: String = ""
let masterPort: mach_port_t = kIOMainPortDefault
let matchingDict : CFDictionary = IOServiceMatching("AppleDeviceManagementHIDEventService")
let kernResult = IOServiceGetMatchingServices(masterPort, matchingDict, &serialPortIterator)
if KERN_SUCCESS == kernResult {
repeat {
object = IOIteratorNext(serialPortIterator)
if object != 0 {
let percentProperty = IORegistryEntryCreateCFProperty(object, "BatteryPercent" as CFString, kCFAllocatorDefault, 0)
if (percentProperty != nil) {
percent = (percentProperty?.takeRetainedValue() as? Int)!
productName = (IORegistryEntryCreateCFProperty(object, "Product" as CFString, kCFAllocatorDefault, 0).takeRetainedValue() as? String)!
}
}
} while percent == 0
IOObjectRelease(object)
}
IOObjectRelease(serialPortIterator)
return (productName, percent)
}
I would like to get all services that contain specific properties.
AppleDeviceManagementHIDEventService <class AppleDeviceManagementHIDEventService, id 0x100000a79, registered, matched, active, busy 0 (0 ms), retain 7>
| | | | | | {
| | | | | | "IOMatchedAtBoot" = Yes
| | | | | | "LowBatteryNotificationPercentage" = 2
| | | | | | "PrimaryUsagePage" = 65280
| | | | | | "BatteryFaultNotificationType" = "TPBatteryFault"
| | | | | | "HasBattery" = Yes
| | | | | | "VendorID" = 76
| | | | | | "VersionNumber" = 0
| | | | | | "Built-In" = No
| | | | | | "DeviceAddress" = "10-94-bb-ab-b9-53"
| | | | | | "WakeReason" = "Host (0x01)"
| | | | | | "Product" = "Magic Trackpad"
| | | | | | "SerialNumber" = "10-94-bb-ab-b9-53"
| | | | | | "Transport" = "Bluetooth"
| | | | | | "BatteryLowNotificationType" = "TPLowBattery"
| | | | | | "ProductID" = 613
| | | | | | "DeviceUsagePairs" = ({"DeviceUsagePage"=65280,"DeviceUsage"=11},{"DeviceUsagePage"=65280,"DeviceUsage"=20})
| | | | | | "IOPersonalityPublisher" = "com.apple.driver.AppleTopCaseHIDEventDriver"
| | | | | | "MTFW Version" = 920
| | | | | | "BD_ADDR" = <1094bbabb953>
| | | | | | "BatteryPercent" = 42
| | | | | | "BatteryStatusNotificationType" = "BatteryStatusChanged"
| | | | | | "CriticallyLowBatteryNotificationPercentage" = 1
| | | | | | "ReportInterval" = 11250
| | | | | | "RadioFW Version" = 368
| | | | | | "VendorIDSource" = 1
| | | | | | "STFW Version" = 2144
| | | | | | "CFBundleIdentifier" = "com.apple.driver.AppleTopCaseHIDEventDriver"
| | | | | | "IOProviderClass" = "IOHIDInterface"
| | | | | | "LocationID" = 1001109843
| | | | | | "BluetoothDevice" = Yes
| | | | | | "IOClass" = "AppleDeviceManagementHIDEventService"
| | | | | | "HIDServiceSupport" = No
| | | | | | "CFBundleIdentifierKernel" = "com.apple.driver.AppleTopCaseHIDEventDriver"
| | | | | | "ProductIDArray" = (613)
| | | | | | "BatteryStatusFlags" = 0
| | | | | | "ColorID" = 5
| | | | | | "IOMatchCategory" = "IODefaultMatchCategory"
| | | | | | "CountryCode" = 0
| | | | | | "IOProbeScore" = 7175
| | | | | | "PrimaryUsage" = 11
| | | | | | "IOGeneralInterest" = "IOCommand is not serializable"
| | | | | | "BTFW Version" = 368
| | | | | | }
Eg. every service that contains the child property "BatteryPercent"
.
I know that I can get specific service by using IOServiceNameMatching
and then IOServiceGetMatchingServices
, but this seems to not be working on the properties inside the service. Is it possible to that? I want to match by BatteryPercent and then also get ProductName.
EDIT: This is the code I'm currently using to get the trackpad battery.
func getTrackpadBattery() -> (String, Int) {
var serialPortIterator = io_iterator_t()
var object : io_object_t
var percent: Int = 0
var productName: String = ""
let masterPort: mach_port_t = kIOMainPortDefault
let matchingDict : CFDictionary = IOServiceMatching("AppleDeviceManagementHIDEventService")
let kernResult = IOServiceGetMatchingServices(masterPort, matchingDict, &serialPortIterator)
if KERN_SUCCESS == kernResult {
repeat {
object = IOIteratorNext(serialPortIterator)
if object != 0 {
let percentProperty = IORegistryEntryCreateCFProperty(object, "BatteryPercent" as CFString, kCFAllocatorDefault, 0)
if (percentProperty != nil) {
percent = (percentProperty?.takeRetainedValue() as? Int)!
productName = (IORegistryEntryCreateCFProperty(object, "Product" as CFString, kCFAllocatorDefault, 0).takeRetainedValue() as? String)!
}
}
} while percent == 0
IOObjectRelease(object)
}
IOObjectRelease(serialPortIterator)
return (productName, percent)
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
真的不知道Swift,所以我的示例是在Objective-C中
(对不起,我 能够做自己追求的事情。在匹配词典中使用它,将匹配结果限制为具有给定属性的IOKIT服务。例如:
请注意,IOKIT属性在大多数情况下都不标准化,因此,除非您知道特定服务(Super-)类以您的代码可以处理的方式发布属性,否任意名称,不一定映射到您期望的含义。因此,您可能需要以这种方式将您处理的注册表条目限制为ioservice类的特定允许名单。 (通过添加
“ ioproviderClass”
/kioproviderClassKey
匹配匹配词典的键,这也是ioserviceMatching()
spits of of。)在解释未知服务类的数据时,您可能需要警告用户。在swift(可能是错误的)中:
对于 i/o注册表条目,带有
“ batterypercent”
属性,请尝试以下操作:(您需要
>进口基础
能够使用nsdictionary
。)仅用于将这些对象返回特定类(此处:
appledevicemanagementhidehideventserventservice
)和“ Batterypercent”
属性:(Sorry, I don't really know Swift, so my example is in Objective-C and I've attempted to provide it in Swift too but it might not be right.)
The
kIOPropertyExistsMatchKey
matching key should be able to do what you're after. Use it in your matching dictionary to constrain the match results to IOKit services which have the property given. For example:Note that IOKit properties are for the most part not standardised, so unless you know that a specific service (super-)class publishes the property in a way that your code can process, services could export just about any data via properties with arbitrary names, which does not necessarily map to the meaning you were expecting. So you might want to constrain the registry entries you process in this way to a specific allow-list of IOService classes. (By adding the
"IOProviderClass"
/kIOProviderClassKey
matching key to your match dictionary, which is also whatIOServiceMatching()
spits out.) At minimum you might want to warn the user when interpreting data from an unknown service class.In Swift (may be wrong):
For returning all I/O registry entries with the
"BatteryPercent"
property, try something like:(You'll need to
import Foundation
to be able to useNSDictionary
.)For only returning those objects with a specific class (here:
AppleDeviceManagementHIDEventService
) and the"BatteryPercent"
property:首先,有一个错字,替换
为
您只有一个
百分比
和一个productname
属性,我假设您只希望您只有一个匹配。如果是这样,请在提取两个值后添加break
语句。我的建议是此代码,如果要检索多个匹配项,请删除
break
语句,创建自定义结构的数组并附加匹配项First of all there is a typo, replace
with
As you have only one
percent
and oneproductName
property I assume that you expect only one match. If so, add abreak
statement after extracting both values. My suggestion is this codeIf you want to retrieve multiple matches remove the
break
statement, create an array of a custom struct and append the matches