daily pastebin goal
30%
SHARE
TWEET

CompetitionProUSB_Swift

a guest Oct 9th, 2017 49 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Cocoa
  2. import Foundation
  3. import IOKit.hid
  4.  
  5.  
  6. //Struct to store vendor and product ID of the device to be recognized
  7. public struct HIDMonitorData {
  8.     public let vendorId:Int
  9.     public let productId:Int
  10.    
  11.     public init (vendorId:Int, productId:Int) {
  12.         self.vendorId = vendorId
  13.         self.productId = productId
  14.     }
  15. }
  16.  
  17. //Struct to save all data of the HID-Device
  18. public struct HIDDevice {
  19.     public let id:String
  20.     public let vendorId:Int
  21.     public let productId:Int
  22.     public let reportSize:Int
  23.     public let device:IOHIDDevice
  24.     public let name:String
  25.    
  26.     public init(device:IOHIDDevice) {
  27.         self.device = device
  28.         //Get all Data from IOKit
  29.         self.id = IOHIDDeviceGetProperty(self.device, kIOHIDLocationIDKey as CFString) as? String ?? ""
  30.         self.name = IOHIDDeviceGetProperty(device, kIOHIDProductKey as CFString) as? String ?? ""
  31.         self.vendorId = IOHIDDeviceGetProperty(self.device, kIOHIDVendorIDKey as CFString) as? Int ?? 0
  32.         self.productId = IOHIDDeviceGetProperty(self.device, kIOHIDProductIDKey as CFString) as? Int ?? 0
  33.         self.reportSize = IOHIDDeviceGetProperty(self.device, kIOHIDMaxInputReportSizeKey as CFString) as? Int ?? 0
  34.     }
  35. }
  36.  
  37. //Class that monitors IOKit Inputs
  38. open class HIDDeviceMonitor: NSObject {
  39.     public let vp:[HIDMonitorData]
  40.     public let reportSize:Int
  41.     public var senderList: [String]
  42.    
  43.     //Initialize with Data of desired Device
  44.     public init(_ vp:[HIDMonitorData], reportSize:Int) {
  45.         self.vp = vp
  46.         self.reportSize = reportSize
  47.         self.senderList = []
  48.     }
  49.    
  50.    
  51.     open func start() {
  52.         print("ready")
  53.         //Create IOHIDManager Object for managing HID devices
  54.         let managerRef = IOHIDManagerCreate(kCFAllocatorDefault, IOOptionBits(kIOHIDOptionsTypeNone))
  55.         var deviceMatches:[[String:Any]] = []
  56.         for vp in self.vp {
  57.             deviceMatches.append([kIOHIDProductIDKey: vp.productId, kIOHIDVendorIDKey: vp.vendorId])
  58.         }
  59.         //Set matching criteria to only get notified with desired device
  60.         IOHIDManagerSetDeviceMatchingMultiple(managerRef, deviceMatches as CFArray)
  61.         //Schedule HID Manager with current run loop
  62.         IOHIDManagerScheduleWithRunLoop(managerRef, CFRunLoopGetCurrent(), CFRunLoopMode.defaultMode.rawValue);
  63.         //Opens all Current and Future HID Devices
  64.         IOHIDManagerOpen(managerRef, IOOptionBits(kIOHIDOptionsTypeNone));
  65.        
  66.         //Callback Function for Device Match
  67.         let matchingCallback:IOHIDDeviceCallback = { inContext, inResult, inSender, inIOHIDDeviceRef in
  68.             let this:HIDDeviceMonitor = unsafeBitCast(inContext, to: HIDDeviceMonitor.self)
  69.             this.rawDeviceAdded(inResult, inSender: inSender!, inIOHIDDeviceRef: inIOHIDDeviceRef)
  70.         }
  71.         //Callback Function for Device Removed
  72.         let removalCallback:IOHIDDeviceCallback = { inContext, inResult, inSender, inIOHIDDeviceRef in
  73.             let this:HIDDeviceMonitor = unsafeBitCast(inContext, to: HIDDeviceMonitor.self)
  74.             this.rawDeviceRemoved(inResult, inSender: inSender!, inIOHIDDeviceRef: inIOHIDDeviceRef)
  75.         }
  76.         //Register a Callback when a device is matching the criteria above
  77.         IOHIDManagerRegisterDeviceMatchingCallback(managerRef, matchingCallback, unsafeBitCast(self, to: UnsafeMutableRawPointer.self))
  78.         //Register a Callback when a device that is matching the criteria is removed
  79.         IOHIDManagerRegisterDeviceRemovalCallback(managerRef, removalCallback, unsafeBitCast(self, to: UnsafeMutableRawPointer.self))
  80.        
  81.        
  82.         RunLoop.current.run();
  83. }
  84.     //Is called in input callback function
  85.     open func read(_ inResult: IOReturn, inSender: UnsafeMutableRawPointer, type: IOHIDReportType, reportId: UInt32, report: UnsafeMutablePointer<UInt8>, reportLength: CFIndex) {
  86.         let data = Data(bytes: UnsafePointer<UInt8>(report), count: reportLength)
  87.         var playerIndex = 0
  88.         //Distinguishing between two similar controllers. Bit dirty via Pointer Address
  89.         //First Controller to input data is Player 0, next is player 1, ...
  90.         if (!senderList.contains(inSender.debugDescription)) {
  91.             senderList.append(inSender.debugDescription)
  92.         }
  93.         playerIndex = senderList.index(of: inSender.debugDescription)!
  94.        
  95.  
  96.         let count = data.count / MemoryLayout<UInt8>.size
  97.         var array = [UInt8](repeating: 0, count: count)
  98.         data.copyBytes(to: &array, count:count * MemoryLayout<UInt8>.size)
  99.  
  100.         //print(array)
  101.         if (array == [128,128,0]) {
  102.             print("Player \(playerIndex): No Buttons Pressed")
  103.             return
  104.         }
  105.        
  106.         //Do Stuff with Device Data. For demo, just print Commands:
  107.         var resultArray: [String] = []
  108.         //Y-Axis
  109.         switch array[0] {
  110.             case 255:
  111.                 resultArray.append("Left")
  112.             case 0:
  113.                 resultArray.append("Right")
  114.             case 128:
  115.                 break
  116.             default:
  117.                 print("Unexpected Value")
  118.            
  119.         }
  120.         //X-Axis
  121.         switch array[1] {
  122.             case 255:
  123.                 resultArray.append("Up")
  124.             case 0:
  125.                 resultArray.append("Down")
  126.             case 128:
  127.                 break
  128.             default:
  129.                 print("Unexpected Value")
  130.  
  131.            
  132.         }
  133.         //Buttons
  134.         var buttonInt = array[2]
  135.             if (buttonInt >= 8) {
  136.                 resultArray.append("Button Small Left")
  137.                 buttonInt = buttonInt - 8
  138.             }
  139.             if (buttonInt >= 4) {
  140.                 resultArray.append("Button Small Right")
  141.                 buttonInt = buttonInt - 4
  142.             }
  143.             if (buttonInt >= 2) {
  144.                 resultArray.append("Button Big Left")
  145.                 buttonInt = buttonInt - 2
  146.             }
  147.             if (buttonInt >= 1) {
  148.                 resultArray.append("Button Big Right")
  149.                 buttonInt = buttonInt - 1
  150.             }
  151.  
  152.         print("Player \(playerIndex): \(resultArray)")
  153.        
  154.        
  155.  
  156.     }
  157.    
  158.     //Is executed in Device Match Callback
  159.     open func rawDeviceAdded(_ inResult: IOReturn, inSender: UnsafeMutableRawPointer, inIOHIDDeviceRef: IOHIDDevice!) {
  160.         //Get Device Data
  161.         let device = HIDDevice(device:inIOHIDDeviceRef)
  162.         // Create memory chunk with reportSize
  163.         let report = UnsafeMutablePointer<UInt8>.allocate(capacity: reportSize)
  164.         //Callback Function on Input Report
  165.         let inputCallback : IOHIDReportCallback = { inContext, inResult, inSender, type, reportId, report, reportLength in
  166.             let this:HIDDeviceMonitor = unsafeBitCast(inContext, to: HIDDeviceMonitor.self)
  167.             this.read(inResult, inSender: inSender!, type: type, reportId: reportId, report: report, reportLength: reportLength)
  168.         }
  169.        
  170.         //Hook up inputcallback when device issues a report
  171.         IOHIDDeviceRegisterInputReportCallback(inIOHIDDeviceRef!, report, reportSize, inputCallback, unsafeBitCast(self, to: UnsafeMutableRawPointer.self))
  172.        
  173.         print("HID Device Recognized: \(device.name)")
  174.        
  175.     }
  176.     //Callback: Removed Matched Device
  177.     open func rawDeviceRemoved(_ inResult: IOReturn, inSender: UnsafeMutableRawPointer, inIOHIDDeviceRef: IOHIDDevice!) {
  178.         let device = HIDDevice(device:inIOHIDDeviceRef)
  179.         print("HID Device Removed: \(device.name)")
  180.         //Reset Sender List for Player Recognition
  181.         senderList = []
  182.  
  183.     }
  184. }
  185.  
  186. let rfDeviceMonitor = HIDDeviceMonitor([
  187.     HIDMonitorData(vendorId: 0x040b, productId: 0x6533)
  188.     ], reportSize: 64)
  189. rfDeviceMonitor.start()
RAW Paste Data
Top