// HIDExample_IOKit.swift // HIDExample_IOKit // // Created by Edgars Klepers on 2/28/25. // // This example demonstrates a method that works fine using IOKit.hid. // Required Hardware: A Logitech G600 Gaming Mouse (https://support.logi.com/hc/en-ca/articles/360023465173-Logitech-G600-MMO-Gaming-Mouse-Technical-Specifications) // The purpose is to detect the macro buttons labeled G9-G20 on the side. import Foundation import IOKit.hid let DeviceVendorId: UInt32 = 0x046D // Logitech let DeviceProductId: UInt32 = 0xC24A // Gaming Mouse G600 @main struct HIDExample_IOKit { static func main() throws { let matchDict = [kIOHIDVendorIDKey: DeviceVendorId, kIOHIDProductIDKey: DeviceProductId] as Dictionary let g600HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, IOOptionBits.zero) assert(CFGetTypeID(g600HIDManager) == IOHIDManagerGetTypeID()) IOHIDManagerSetDeviceMatching(g600HIDManager,matchDict as! CFMutableDictionary) let openHidManagerResult = IOHIDManagerOpen(g600HIDManager, IOOptionBits.zero) if (openHidManagerResult != kIOReturnSuccess) { print("Error loading IOHIDManagerOpen: \(String(format:"0x%X", openHidManagerResult))") } assert(openHidManagerResult == kIOReturnSuccess) IOHIDManagerScheduleWithRunLoop(g600HIDManager, CFRunLoopGetCurrent(), CFRunLoopMode.defaultMode.rawValue) IOHIDManagerRegisterInputValueCallback(g600HIDManager,{ _, returnResult, callbackSender, valueRef in let elem = IOHIDValueGetElement(valueRef) let usage = IOHIDElementGetUsage(elem) let value = IOHIDValueGetIntegerValue(valueRef) if (usage == 0x80) { print("Success!, value: \(String(format:"0x%X", value))") // this is successful. return } }, nil) CFRunLoopRun() } }