TestServicePlugin.swift [plain text]
//
// TestServicePlugin.swift
// IOHIDFamilyUnitTests
//
// Created by dekom on 10/1/18.
//
import Foundation
import XCTest
import HID
let VendorKeyboardDescriptor : [UInt8] = [
0x06, 0x00, 0xFF, /* (GLOBAL) USAGE_PAGE 0xFF00 Vendor-defined */
0x09, 0x28, /* (LOCAL) USAGE 0xFF000028 */
0xA1, 0x01, /* (MAIN) COLLECTION 0x01 Application (Usage=0x00010006: Page=Generic Desktop Page, Usage=Keyboard, Type=CA) */
0x05, 0x07, /* (GLOBAL) USAGE_PAGE 0x0007 Keyboard/Keypad Page */
0x19, 0xE0, /* (LOCAL) USAGE_MINIMUM 0x000700E0 Keyboard Left Control (DV=Dynamic Value) */
0x29, 0xE7, /* (LOCAL) USAGE_MAXIMUM 0x000700E7 Keyboard Right GUI (DV=Dynamic Value) */
0x15, 0x00, /* (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14 */
0x25, 0x01, /* (GLOBAL) LOGICAL_MAXIMUM 0x01 (1) */
0x75, 0x01, /* (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field */
0x95, 0x08, /* (GLOBAL) REPORT_COUNT 0x08 (8) Number of fields */
0x81, 0x02, /* (MAIN) INPUT 0x00000002 (8 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap */
0x95, 0x01, /* (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields */
0x75, 0x08, /* (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field */
0x81, 0x01, /* (MAIN) INPUT 0x00000001 (1 field x 8 bits) 1=Constant 0=Array 0=Absolute 0=Ignored 0=Ignored 0=PrefState 0=NoNull */
0x05, 0x08, /* (GLOBAL) USAGE_PAGE 0x0008 LED Indicator Page */
0x19, 0x01, /* (LOCAL) USAGE_MINIMUM 0x00080001 Num Lock (OOC=On/Off Control) */
0x29, 0x05, /* (LOCAL) USAGE_MAXIMUM 0x00080005 Kana (OOC=On/Off Control) */
0x95, 0x05, /* (GLOBAL) REPORT_COUNT 0x05 (5) Number of fields */
0x75, 0x01, /* (GLOBAL) REPORT_SIZE 0x01 (1) Number of bits per field */
0x91, 0x02, /* (MAIN) OUTPUT 0x00000002 (5 fields x 1 bit) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap */
0x95, 0x01, /* (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields */
0x75, 0x03, /* (GLOBAL) REPORT_SIZE 0x03 (3) Number of bits per field */
0x91, 0x01, /* (MAIN) OUTPUT 0x00000001 (1 field x 3 bits) 1=Constant 0=Array 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap */
0x05, 0x07, /* (GLOBAL) USAGE_PAGE 0x0007 Keyboard/Keypad Page */
0x19, 0x00, /* (LOCAL) USAGE_MINIMUM 0x00070000 Keyboard No event indicated (Sel=Selector) */
0x2A, 0xFF, 0x00, /* (LOCAL) USAGE_MAXIMUM 0x000700FF */
0x95, 0x05, /* (GLOBAL) REPORT_COUNT 0x05 (5) Number of fields */
0x75, 0x08, /* (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field */
0x15, 0x00, /* (GLOBAL) LOGICAL_MINIMUM 0x00 (0) <-- Redundant: LOGICAL_MINIMUM is already 0 <-- Info: Consider replacing 15 00 with 14 */
0x26, 0xFF, 0x00, /* (GLOBAL) LOGICAL_MAXIMUM 0x00FF (255) */
0x81, 0x00, /* (MAIN) INPUT 0x00000000 (5 fields x 8 bits) 0=Data 0=Array 0=Absolute 0=Ignored 0=Ignored 0=PrefState 0=NoNull */
0x05, 0xFF, /* (GLOBAL) USAGE_PAGE 0x00FF Reserved */
0x09, 0x03, /* (LOCAL) USAGE 0x00FF0003 */
0x75, 0x08, /* (GLOBAL) REPORT_SIZE 0x08 (8) Number of bits per field <-- Redundant: REPORT_SIZE is already 8 */
0x95, 0x01, /* (GLOBAL) REPORT_COUNT 0x01 (1) Number of fields */
0x81, 0x02, /* (MAIN) INPUT 0x00000002 (1 field x 8 bits) 0=Data 1=Variable 0=Absolute 0=NoWrap 0=Linear 0=PrefState 0=NoNull 0=NonVolatile 0=Bitmap */
0xC0, /* (MAIN) END_COLLECTION Application */
]
@objc(TestServicePlugin) class TestServicePlugin : XCTestCase {
var userDevice : HIDUserDevice!
var client : HIDEventSystemClient!
var serviceClient : HIDServiceClient!
var eventExp : XCTestExpectation!
override func setUp() {
super.setUp()
guard let client = HIDEventSystemClient(type: HIDEventSystemClientType.monitor) else {
XCTAssert(false, "Failed to create HIDEventSystemClient")
return
}
client.setMatching([kIOHIDVendorIDKey : 87654321,
kIOHIDServiceHiddenKey as String: true])
eventExp = XCTestExpectation(description: "HIDEvent handler")
client.setEventHandler { (service, event) in
print("Received event \(event)")
self.eventExp.fulfill()
}
let serviceExp = XCTestExpectation(description: "service enumerated")
client.setServiceNotificationHandler { (service) in
print("Service added: \(service)")
self.serviceClient = service;
serviceExp.fulfill()
}
client.setDispatchQueue(DispatchQueue.main)
client.activate()
let desc = NSData(bytesNoCopy: UnsafeMutableRawPointer(mutating: VendorKeyboardDescriptor),
length: VendorKeyboardDescriptor.count,
freeWhenDone: false)
let properties : [String : Any] = [kIOHIDReportDescriptorKey: desc,
kIOHIDVendorIDKey: 87654321,
kIOHIDServiceHiddenKey as String: true,
kIOHIDServiceSupportKey: true]
guard let userDevice = HIDUserDevice(properties: properties) else {
XCTAssert(false, "Failed to create HIDUserDevice")
return
}
let result = XCTWaiter.wait(for: [serviceExp], timeout: 5)
XCTAssert(result == XCTWaiter.Result.completed)
self.userDevice = userDevice
self.client = client
}
override func tearDown() {
client.cancel()
super.tearDown()
}
func testServicePlugin() {
var result : Bool = false
result = serviceClient.setProperty(1234, forKey: "TestHIDServicePluginSetProperty")
XCTAssert(result, "serviceClient.setProperty failed")
let prop = serviceClient.property(forKey: "TestHIDServicePluginGetProperty")
XCTAssert(prop != nil, "servserviceClient.property failed")
print("prop: \(String(describing: prop))")
eventExp.expectedFulfillmentCount = 10;
for i in 0..<10 {
var report = HIDKeyboardDescriptorInputReport()
if i % 2 == 0 {
report.KB_KeyboardKeyboardLeftShift = 1
} else {
report.KB_KeyboardKeyboardLeftShift = 0
}
do {
try userDevice.handleReport(Data(bytes: &report,
count: MemoryLayout.size(ofValue: report)))
} catch let error as NSError {
print("userDevice.handleReport failed: \(error)")
}
}
var waiter = XCTWaiter.wait(for: [eventExp], timeout: 5)
XCTAssert(waiter == XCTWaiter.Result.completed)
if let event = serviceClient.event(matching: ["EventType" : kIOHIDEventTypeKeyboard]) {
print("event: \(event)")
XCTAssert(event.type == kIOHIDEventTypeKeyboard)
} else {
XCTAssert(false, "serviceClient.event failed")
}
let debugInfo = serviceClient.property(forKey: kIOHIDServicePluginDebugKey) as? Dictionary<String,Any>
XCTAssert(debugInfo != nil, "serviceClient.property failed for kIOHIDServicePluginDebugKey")
print("debugInfo: \(String(describing: debugInfo))")
XCTAssert(debugInfo?["PluginName"] as! String == "HIDServicePluginExample")
XCTAssert(debugInfo?["cancelHandler"] as! Bool == true)
XCTAssert(debugInfo?["dispatchQueue"] as! Bool == true)
XCTAssert(debugInfo?["activated"] as! Bool == true)
XCTAssert(debugInfo?["clientAdded"] as! Bool == true)
let removalExp = XCTestExpectation(description: "service removed")
serviceClient.setRemovalHandler {
print("Service: \(self.serviceClient!) removed")
removalExp.fulfill()
}
userDevice = nil;
waiter = XCTWaiter.wait(for: [removalExp], timeout: 5)
XCTAssert(waiter == XCTWaiter.Result.completed)
}
}