-
-
Save zachbadgett/471d72e83fee413d0f38 to your computer and use it in GitHub Desktop.
| 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: 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 | |
| var plugInInterfacePtrPtr = UnsafeMutablePointer<UnsafeMutablePointer<IOCFPlugInInterface>>() | |
| // From: CFPlugInCOM.h: public typealias LPVOID = UnsafeMutablePointer<Void>() | |
| var deviceInterfaceVoidPtr = UnsafeMutablePointer<Void>() | |
| // 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](count: 128, repeatedValue: 0) | |
| let deviceNameResult = IORegistryEntryGetName(usbDevice, &deviceNameCString) | |
| if(deviceNameResult != kIOReturnSuccess) { | |
| print("Error getting device name") | |
| exit(EXIT_FAILURE) | |
| } | |
| let deviceName = String.fromCString(&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.memory.memory | |
| // 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 deviceInterface = (UnsafeMutablePointer<IOUSBDeviceInterface>(deviceInterfaceVoidPtr)).memory | |
| // 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) |
I have created USBDeviceSwift library for convenient work with IOKit.usb and IOKit.hid
@Arti3DPlayer
I started very little to study to program for Mac OSX, as by Apple's advice I'm studying Swift, I just updated to Xcode9 with swift 4.
I wanted to use the USB and found your USBDeviceSwift project interesting, only I have difficulty using it.
I followed the instructions to install the wrap only through cocoapods.
I get an error in the line:
let stm32DeviceMonitor = USBDeviceMonitor ([
VIDPID (vendorId: 0x0483, productId: 0xdf11)
])
What can it depend on?
Greetings
Mike
the VIDPID command is not recognized.
Hate to necro this gist ten years later, but this is my swift 5/6 implementation of using IOKit to find USB devices.
Hope this helps anyone else who stumbles upon this!
import Foundation
import IOKit
import IOKit.usb
import IOKit.usb.IOUSBLib
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)
let targetVendorId: UInt16 = 0x0000 // Replace with your Vendor ID
let targetProductId: UInt16 = 0x0000 // Replace with your Product ID
func findAndOpenDevice() -> UnsafeMutablePointer<
UnsafeMutablePointer<IOUSBDeviceInterface>
>? {
var iterator: io_iterator_t = 0
let matchingDict = IOServiceMatching(kIOUSBDeviceClassName)
let kIoDefaultMatchPort =
if #available(macOS 12, *) {
kIOMainPortDefault
} else {
kIOMasterPortDefault
}
guard
IOServiceGetMatchingServices(
kIoDefaultMatchPort, matchingDict, &iterator)
== KERN_SUCCESS
else {
print("Could not find matching USB devices")
return nil
}
defer { IOObjectRelease(iterator) }
while case let usbDevice = IOIteratorNext(iterator), usbDevice != 0 {
var score: Int32 = 0
var plugInPtr:
UnsafeMutablePointer<UnsafeMutablePointer<IOCFPlugInInterface>?>?
var devicePtr: LPVOID? = nil
defer { IOObjectRelease(usbDevice) }
let deviceName = String(
cString: {
var cstring: [CChar] = [CChar](repeating: 0, count: 128)
guard
IORegistryEntryGetName(usbDevice, &cstring)
== kIOReturnSuccess
else {
return [CChar](repeating: 0, count: 1)
}
return cstring
}())
let kr = IOCreatePlugInInterfaceForService(
usbDevice,
kIOUSBDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInPtr,
&score
)
guard
kr == kIOReturnSuccess, let plugInPtr = plugInPtr,
let plugInInterfacePtr = plugInPtr.pointee
else {
print("Unable to create a plug-in \(kr)")
continue
}
defer {
_ = plugInInterfacePtr.pointee.Release(plugInPtr)
}
let result = plugInInterfacePtr.pointee.QueryInterface(
plugInPtr,
CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
&devicePtr
)
guard result == 0,
let devicePtr:
UnsafeMutablePointer<UnsafeMutablePointer<IOUSBDeviceInterface>>
= devicePtr?
.assumingMemoryBound(
to: UnsafeMutablePointer<IOUSBDeviceInterface>.self)
else {
print("Couldn't create a device interface \(result)")
continue
}
let deviceInterfacePtr = devicePtr.pointee
var vid: UInt16 = 0
var pid: UInt16 = 0
_ = deviceInterfacePtr.pointee.GetDeviceVendor(devicePtr, &vid)
_ = deviceInterfacePtr.pointee.GetDeviceProduct(devicePtr, &pid)
print(
"VID: \(String(format:"%04X", vid)) | PID: \(String(format:"%04X", pid)) | Name: \(deviceName)"
)
if vid == targetVendorId && pid == targetProductId {
// Open the device before using it
let openResult = deviceInterfacePtr.pointee.USBDeviceOpen(devicePtr)
if openResult != kIOReturnSuccess {
print("Failed to open device: \(openResult)")
_ = deviceInterfacePtr.pointee.Release(devicePtr)
return nil
}
print("Found and opened \(deviceName)")
return devicePtr
} else {
_ = deviceInterfacePtr.pointee.Release(devicePtr)
}
}
return nil
}
if let devicePtr = findAndOpenDevice() {
let deviceInterface = devicePtr.pointee
// Always close and release the device interface when done
_ = deviceInterface.pointee.USBDeviceClose(devicePtr)
_ = deviceInterface.pointee.Release(devicePtr)
} else {
print("Device not found or interface setup failed.")
}
Hey!
You shouldn't have
on the first AND last line of your loop, you are skipping over elements from the iterator