-
-
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