如何调用IOCFPlugInInterface.QueryInterface()查询USB设备
How to call IOCFPlugInInterface.QueryInterface() to query USB devices
我想将此 USB 检测器转换为 Swift 3 https://gist.github.com/zachbadgett/471d72e83fee413d0f38
但是我卡在了这条线上:
let deviceInterfaceResult = plugInInterface.QueryInterface(
plugInInterfacePtrPtr,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
&deviceInterfaceVoidPtr)
Cannot call value of non-function type '(@convention(c)
(UnsafeMutableRawPointer?, REFIID, UnsafeMutablePointer?) ->
HRESULT)!'
来源QueryInterface
:
public var QueryInterface: (@convention(c) (UnsafeMutableRawPointer?, REFIID, UnsafeMutablePointer<LPVOID?>?) -> HRESULT)!
如何调用这个函数? 这个答案对我没有帮助。
完全不知道它是否正确,但这是使用 Swift 3 和 Xcode 8.0 构建的。关键是写 var deviceInterfaceVoidPtr: UnsafeMutableRawPointer? = nil
.
import IOKit
import IOKit.usb
import IOKit.usb.IOUSBLib
print("Scanning USB Bus.....\n\n\n")
//
// These constants are not imported into Swift from IOUSBLib.h as they
// are all #define constants
//
let kIOUSBDeviceUserClientTypeID: CFUUID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0x9d, 0xc7, 0xb7, 0x80, 0x9e, 0xc0, 0x11, 0xD4,
0xa5, 0x4f, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)
let kIOCFPlugInInterfaceID: CFUUID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0xC2, 0x44, 0xE8, 0x58, 0x10, 0x9C, 0x11, 0xD4,
0x91, 0xD4, 0x00, 0x50, 0xE4, 0xC6, 0x42, 0x6F)
let kIOUSBDeviceInterfaceID: CFUUID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0x5c, 0x81, 0x87, 0xd0, 0x9e, 0xf3, 0x11, 0xD4,
0x8b, 0x45, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)
var usbIterator: io_iterator_t = io_iterator_t()
var usbDevice: io_service_t = io_service_t()
var usbVendorID: UInt16 = 0
var score: Int32 = 0
func ptrFromAddress<T>(_ p: UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T> {
return p
}
var myInterface:IOCFPlugInInterface = IOCFPlugInInterface()
var plugInInterfacePtr: UnsafeMutablePointer<IOCFPlugInInterface>? = ptrFromAddress(&myInterface)
var plugInInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOCFPlugInInterface>?>? = ptrFromAddress(&plugInInterfacePtr)
// From: CFPlugInCOM.h: public typealias LPVOID = UnsafeMutablePointer<Void>()
var deviceInterfaceVoidPtr: UnsafeMutableRawPointer? = nil
// create dictionary with IOUSBDevice as IOProviderClass
let matchingDictionary: NSMutableDictionary = IOServiceMatching(kIOUSBDeviceClassName)
// get iterator for matching USB devices
let matchingServicesResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &usbIterator)
if matchingServicesResult != kIOReturnSuccess {
print("Error getting deviceList!")
exit(EXIT_FAILURE)
}
// usbDevice = 0 when finished iterating all devices
repeat {
usbDevice = IOIteratorNext(usbIterator)
// io_name_t imports to swift as a tuple (Int8, ..., Int8) 128 ints
// although in device_types.h it's defined:
// typedef char io_name_t[128];
var deviceNameCString: [CChar] = [CChar](repeating: 0, count: 128)
let deviceNameResult = IORegistryEntryGetName(usbDevice, &deviceNameCString)
if deviceNameResult != kIOReturnSuccess {
print("Error getting device name")
exit(EXIT_FAILURE)
}
let deviceName = String(cString: &deviceNameCString)
print("usb Device Name: \(deviceName)")
// Get plugInInterface for current USB device
let plugInInterfaceResult = IOCreatePlugInInterfaceForService(
usbDevice,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterfacePtrPtr,
&score)
if (plugInInterfacePtrPtr == nil) || (plugInInterfaceResult != kIOReturnSuccess) {
print("Unable to get Plug-In Interface")
continue
}
// dereference pointer for the plug in interface
let plugInInterface: IOCFPlugInInterface = plugInInterfacePtrPtr!.pointee!.pointee
// use plug in interface to get a device interface
// public var QueryInterface: (@convention(c) (UnsafeMutablePointer<Void>, REFIID, UnsafeMutablePointer<LPVOID>) -> HRESULT)!
let deviceInterfaceResult = plugInInterface.QueryInterface(
plugInInterfacePtrPtr,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
&deviceInterfaceVoidPtr)
if (deviceInterfaceResult != kIOReturnSuccess) || (deviceInterfaceVoidPtr == nil) {
print("Unable to get Device Interface")
exit(EXIT_FAILURE)
}
// dereference the IOUSBDeviceInterface struct from pointer var after
// converting from a void to a IOUSBDeviceInterface pointer
let opaquePtr = OpaquePointer(deviceInterfaceVoidPtr!)
let deviceInterface = UnsafeMutablePointer<IOUSBDeviceInterface>(opaquePtr).pointee
// get USB Vendor ID --> CRASH
let vendorResult = deviceInterface.GetDeviceVendor(deviceInterfaceVoidPtr!, &usbVendorID)
if vendorResult != kIOReturnSuccess {
print("Unable to get Device Vendor ID")
exit(EXIT_FAILURE)
}
print("usb Vendor ID: \(usbVendorID)")
usbDevice = IOIteratorNext(usbIterator)
} while (usbDevice != 0)
exit(EXIT_SUCCESS)
此外,请注意,根据 cellininicholas 的要点评论,
您应该删除两次出现的
之一
usbDevice = IOIteratorNext(usbIterator)
Cœur 的答案非常接近。 plugInInterface.QueryInterface()
期望作为最后一个参数的地址是 double-indirect pointer
UnsafeMutablePointer<UnsafeMutablePointer<IOUSBDeviceInterface>?>?
但 "disguised" 作为指向 LPVOID?
又名 UnsafeMutableRawPointer
的指针。
因此,获得的指针必须被取消引用两次。
withMemoryRebound()
可用于此指针转换。
我对代码做了一些修改:
- 使用
defer
继续使用下一个 USB 设备,即使
由于错误,当前迭代是 "aborted"。
- 删除不必要的类型注释。
- 使用
MemoryLayout<io_name_t>.size
代替 128
。
- 释放
usbDevice
和使用后的接口指针,以避免内存泄漏。
- 将一些变量声明从顶部移到需要的地方。
综合起来:
import Foundation
import IOKit
import IOKit.usb
import IOKit.usb.IOUSBLib
print("Scanning USB Bus.....\n\n\n")
//
// These constants are not imported into Swift from IOUSBLib.h as they
// are all #define constants
//
let kIOUSBDeviceUserClientTypeID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0x9d, 0xc7, 0xb7, 0x80, 0x9e, 0xc0, 0x11, 0xD4,
0xa5, 0x4f, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)
let kIOCFPlugInInterfaceID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0xC2, 0x44, 0xE8, 0x58, 0x10, 0x9C, 0x11, 0xD4,
0x91, 0xD4, 0x00, 0x50, 0xE4, 0xC6, 0x42, 0x6F)
let kIOUSBDeviceInterfaceID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0x5c, 0x81, 0x87, 0xd0, 0x9e, 0xf3, 0x11, 0xD4,
0x8b, 0x45, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)
// Create dictionary with IOUSBDevice as IOProviderClass.
let matchingDictionary: NSMutableDictionary = IOServiceMatching(kIOUSBDeviceClassName)
// Get iterator for matching USB devices.
var usbIterator = io_iterator_t()
let matchingServicesResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &usbIterator)
if matchingServicesResult != kIOReturnSuccess {
print("Error getting deviceList!")
exit(EXIT_FAILURE)
}
// Iterate devices until usbDevice == 0.
var usbDevice = IOIteratorNext(usbIterator)
while usbDevice != 0 {
defer {
usbDevice = IOIteratorNext(usbIterator)
}
// io_name_t imports to Swift as a tuple (Int8, ..., Int8) with 128 ints
// although in device_types.h it is defined as
// typedef char io_name_t[128];
var deviceNameCString = [CChar](repeating: 0, count: MemoryLayout<io_name_t>.size)
let deviceNameResult = IORegistryEntryGetName(usbDevice, &deviceNameCString)
if deviceNameResult != kIOReturnSuccess {
print("Error getting device name")
continue
}
let deviceName = String(cString: &deviceNameCString)
print("USB device name: \(deviceName)")
// Get plug-in interface for current USB device
var plugInInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOCFPlugInInterface>?>?
var score: Int32 = 0
let plugInInterfaceResult = IOCreatePlugInInterfaceForService(
usbDevice,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterfacePtrPtr,
&score)
// USB device object is no longer needed.
IOObjectRelease(usbDevice)
// Dereference pointer for the plug-in interface
guard plugInInterfaceResult == kIOReturnSuccess,
let plugInInterface = plugInInterfacePtrPtr?.pointee?.pointee else {
print("Unable to get Plug-In Interface")
continue
}
// Use plug-in interface to get a device interface.
var deviceInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOUSBDeviceInterface>?>?
let deviceInterfaceResult = withUnsafeMutablePointer(to: &deviceInterfacePtrPtr) {
[=11=].withMemoryRebound(to: Optional<LPVOID>.self, capacity: 1) {
plugInInterface.QueryInterface(
plugInInterfacePtrPtr,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
[=11=])
}
}
// Plug-in interface is no longer needed.
_ = plugInInterface.Release(plugInInterfacePtrPtr)
// Dereference pointer for the device interface.
guard deviceInterfaceResult == kIOReturnSuccess,
let deviceInterface = deviceInterfacePtrPtr?.pointee?.pointee else {
print("Unable to get Device Interface")
continue
}
// Use device interface to get vendor ID.
var usbVendorID: UInt16 = 0
let vendorResult = deviceInterface.GetDeviceVendor(deviceInterfacePtrPtr, &usbVendorID)
// Device interface is no longer needed:
_ = deviceInterface.Release(deviceInterfacePtrPtr)
if vendorResult != kIOReturnSuccess {
print("Unable to get device Vendor ID")
continue
}
print("USB Vendor ID: \(usbVendorID)")
}
exit(EXIT_SUCCESS)
我想将此 USB 检测器转换为 Swift 3 https://gist.github.com/zachbadgett/471d72e83fee413d0f38
但是我卡在了这条线上:
let deviceInterfaceResult = plugInInterface.QueryInterface(
plugInInterfacePtrPtr,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
&deviceInterfaceVoidPtr)
Cannot call value of non-function type '(@convention(c) (UnsafeMutableRawPointer?, REFIID, UnsafeMutablePointer?) -> HRESULT)!'
来源QueryInterface
:
public var QueryInterface: (@convention(c) (UnsafeMutableRawPointer?, REFIID, UnsafeMutablePointer<LPVOID?>?) -> HRESULT)!
如何调用这个函数?
完全不知道它是否正确,但这是使用 Swift 3 和 Xcode 8.0 构建的。关键是写 var deviceInterfaceVoidPtr: UnsafeMutableRawPointer? = nil
.
import IOKit
import IOKit.usb
import IOKit.usb.IOUSBLib
print("Scanning USB Bus.....\n\n\n")
//
// These constants are not imported into Swift from IOUSBLib.h as they
// are all #define constants
//
let kIOUSBDeviceUserClientTypeID: CFUUID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0x9d, 0xc7, 0xb7, 0x80, 0x9e, 0xc0, 0x11, 0xD4,
0xa5, 0x4f, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)
let kIOCFPlugInInterfaceID: CFUUID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0xC2, 0x44, 0xE8, 0x58, 0x10, 0x9C, 0x11, 0xD4,
0x91, 0xD4, 0x00, 0x50, 0xE4, 0xC6, 0x42, 0x6F)
let kIOUSBDeviceInterfaceID: CFUUID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0x5c, 0x81, 0x87, 0xd0, 0x9e, 0xf3, 0x11, 0xD4,
0x8b, 0x45, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)
var usbIterator: io_iterator_t = io_iterator_t()
var usbDevice: io_service_t = io_service_t()
var usbVendorID: UInt16 = 0
var score: Int32 = 0
func ptrFromAddress<T>(_ p: UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T> {
return p
}
var myInterface:IOCFPlugInInterface = IOCFPlugInInterface()
var plugInInterfacePtr: UnsafeMutablePointer<IOCFPlugInInterface>? = ptrFromAddress(&myInterface)
var plugInInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOCFPlugInInterface>?>? = ptrFromAddress(&plugInInterfacePtr)
// From: CFPlugInCOM.h: public typealias LPVOID = UnsafeMutablePointer<Void>()
var deviceInterfaceVoidPtr: UnsafeMutableRawPointer? = nil
// create dictionary with IOUSBDevice as IOProviderClass
let matchingDictionary: NSMutableDictionary = IOServiceMatching(kIOUSBDeviceClassName)
// get iterator for matching USB devices
let matchingServicesResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &usbIterator)
if matchingServicesResult != kIOReturnSuccess {
print("Error getting deviceList!")
exit(EXIT_FAILURE)
}
// usbDevice = 0 when finished iterating all devices
repeat {
usbDevice = IOIteratorNext(usbIterator)
// io_name_t imports to swift as a tuple (Int8, ..., Int8) 128 ints
// although in device_types.h it's defined:
// typedef char io_name_t[128];
var deviceNameCString: [CChar] = [CChar](repeating: 0, count: 128)
let deviceNameResult = IORegistryEntryGetName(usbDevice, &deviceNameCString)
if deviceNameResult != kIOReturnSuccess {
print("Error getting device name")
exit(EXIT_FAILURE)
}
let deviceName = String(cString: &deviceNameCString)
print("usb Device Name: \(deviceName)")
// Get plugInInterface for current USB device
let plugInInterfaceResult = IOCreatePlugInInterfaceForService(
usbDevice,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterfacePtrPtr,
&score)
if (plugInInterfacePtrPtr == nil) || (plugInInterfaceResult != kIOReturnSuccess) {
print("Unable to get Plug-In Interface")
continue
}
// dereference pointer for the plug in interface
let plugInInterface: IOCFPlugInInterface = plugInInterfacePtrPtr!.pointee!.pointee
// use plug in interface to get a device interface
// public var QueryInterface: (@convention(c) (UnsafeMutablePointer<Void>, REFIID, UnsafeMutablePointer<LPVOID>) -> HRESULT)!
let deviceInterfaceResult = plugInInterface.QueryInterface(
plugInInterfacePtrPtr,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
&deviceInterfaceVoidPtr)
if (deviceInterfaceResult != kIOReturnSuccess) || (deviceInterfaceVoidPtr == nil) {
print("Unable to get Device Interface")
exit(EXIT_FAILURE)
}
// dereference the IOUSBDeviceInterface struct from pointer var after
// converting from a void to a IOUSBDeviceInterface pointer
let opaquePtr = OpaquePointer(deviceInterfaceVoidPtr!)
let deviceInterface = UnsafeMutablePointer<IOUSBDeviceInterface>(opaquePtr).pointee
// get USB Vendor ID --> CRASH
let vendorResult = deviceInterface.GetDeviceVendor(deviceInterfaceVoidPtr!, &usbVendorID)
if vendorResult != kIOReturnSuccess {
print("Unable to get Device Vendor ID")
exit(EXIT_FAILURE)
}
print("usb Vendor ID: \(usbVendorID)")
usbDevice = IOIteratorNext(usbIterator)
} while (usbDevice != 0)
exit(EXIT_SUCCESS)
此外,请注意,根据 cellininicholas 的要点评论, 您应该删除两次出现的
之一usbDevice = IOIteratorNext(usbIterator)
Cœur 的答案非常接近。 plugInInterface.QueryInterface()
期望作为最后一个参数的地址是 double-indirect pointer
UnsafeMutablePointer<UnsafeMutablePointer<IOUSBDeviceInterface>?>?
但 "disguised" 作为指向 LPVOID?
又名 UnsafeMutableRawPointer
的指针。
因此,获得的指针必须被取消引用两次。
withMemoryRebound()
可用于此指针转换。
我对代码做了一些修改:
- 使用
defer
继续使用下一个 USB 设备,即使 由于错误,当前迭代是 "aborted"。 - 删除不必要的类型注释。
- 使用
MemoryLayout<io_name_t>.size
代替128
。 - 释放
usbDevice
和使用后的接口指针,以避免内存泄漏。 - 将一些变量声明从顶部移到需要的地方。
综合起来:
import Foundation
import IOKit
import IOKit.usb
import IOKit.usb.IOUSBLib
print("Scanning USB Bus.....\n\n\n")
//
// These constants are not imported into Swift from IOUSBLib.h as they
// are all #define constants
//
let kIOUSBDeviceUserClientTypeID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0x9d, 0xc7, 0xb7, 0x80, 0x9e, 0xc0, 0x11, 0xD4,
0xa5, 0x4f, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)
let kIOCFPlugInInterfaceID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0xC2, 0x44, 0xE8, 0x58, 0x10, 0x9C, 0x11, 0xD4,
0x91, 0xD4, 0x00, 0x50, 0xE4, 0xC6, 0x42, 0x6F)
let kIOUSBDeviceInterfaceID = CFUUIDGetConstantUUIDWithBytes(kCFAllocatorDefault,
0x5c, 0x81, 0x87, 0xd0, 0x9e, 0xf3, 0x11, 0xD4,
0x8b, 0x45, 0x00, 0x0a, 0x27, 0x05, 0x28, 0x61)
// Create dictionary with IOUSBDevice as IOProviderClass.
let matchingDictionary: NSMutableDictionary = IOServiceMatching(kIOUSBDeviceClassName)
// Get iterator for matching USB devices.
var usbIterator = io_iterator_t()
let matchingServicesResult = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &usbIterator)
if matchingServicesResult != kIOReturnSuccess {
print("Error getting deviceList!")
exit(EXIT_FAILURE)
}
// Iterate devices until usbDevice == 0.
var usbDevice = IOIteratorNext(usbIterator)
while usbDevice != 0 {
defer {
usbDevice = IOIteratorNext(usbIterator)
}
// io_name_t imports to Swift as a tuple (Int8, ..., Int8) with 128 ints
// although in device_types.h it is defined as
// typedef char io_name_t[128];
var deviceNameCString = [CChar](repeating: 0, count: MemoryLayout<io_name_t>.size)
let deviceNameResult = IORegistryEntryGetName(usbDevice, &deviceNameCString)
if deviceNameResult != kIOReturnSuccess {
print("Error getting device name")
continue
}
let deviceName = String(cString: &deviceNameCString)
print("USB device name: \(deviceName)")
// Get plug-in interface for current USB device
var plugInInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOCFPlugInInterface>?>?
var score: Int32 = 0
let plugInInterfaceResult = IOCreatePlugInInterfaceForService(
usbDevice,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterfacePtrPtr,
&score)
// USB device object is no longer needed.
IOObjectRelease(usbDevice)
// Dereference pointer for the plug-in interface
guard plugInInterfaceResult == kIOReturnSuccess,
let plugInInterface = plugInInterfacePtrPtr?.pointee?.pointee else {
print("Unable to get Plug-In Interface")
continue
}
// Use plug-in interface to get a device interface.
var deviceInterfacePtrPtr: UnsafeMutablePointer<UnsafeMutablePointer<IOUSBDeviceInterface>?>?
let deviceInterfaceResult = withUnsafeMutablePointer(to: &deviceInterfacePtrPtr) {
[=11=].withMemoryRebound(to: Optional<LPVOID>.self, capacity: 1) {
plugInInterface.QueryInterface(
plugInInterfacePtrPtr,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
[=11=])
}
}
// Plug-in interface is no longer needed.
_ = plugInInterface.Release(plugInInterfacePtrPtr)
// Dereference pointer for the device interface.
guard deviceInterfaceResult == kIOReturnSuccess,
let deviceInterface = deviceInterfacePtrPtr?.pointee?.pointee else {
print("Unable to get Device Interface")
continue
}
// Use device interface to get vendor ID.
var usbVendorID: UInt16 = 0
let vendorResult = deviceInterface.GetDeviceVendor(deviceInterfacePtrPtr, &usbVendorID)
// Device interface is no longer needed:
_ = deviceInterface.Release(deviceInterfacePtrPtr)
if vendorResult != kIOReturnSuccess {
print("Unable to get device Vendor ID")
continue
}
print("USB Vendor ID: \(usbVendorID)")
}
exit(EXIT_SUCCESS)