TestVendorMessageAndVendorPayload.m [plain text]
//
// TestEventDriverAndVendorEvent.m
// IOHIDFamily
//
// Created by YG on 10/24/16.
//
//
#import <XCTest/XCTest.h>
#include "IOHIDUnitTestUtility.h"
#import "IOHIDEventSystemTestController.h"
#import "IOHIDUserDeviceTestController.h"
#import "IOHIDDeviceTestController.h"
#define kVendorMessageBitLength 128
#define kVendorPayloadBitLength 128
#define kVendorMessageReportID 1
#define kVendorPayloadReportID 2
typedef struct __attribute__ ((packed)) {
uint8_t id;
uint8_t data [kVendorMessageBitLength/8];
} REPORT_WITH_ID;
static uint8_t descriptor[] = {
0x06, 0x00, 0xFF, // Usage Page (65280)
0x09, 0x23, // Usage 35 (0x23)
0xA1, 0x01, // Collection (Application)
0x85, kVendorMessageReportID, // ReportID................ (VendorMessageReportID)
0x09, 0x23, // Usage 35 (0x23)
0x06, 0x00, 0xFF, // Usage Page (65280)
0x95, 0x01, // Report Count............ (1)
0x75, kVendorMessageBitLength, // Report Size............. (VendorMessageBitLength)
0x81, 0x02, // Input...................(Data, Variable, Absolute)
0x06, 0x00, 0xFF, // Usage Page (65280)
0x09, 0x25, // Usage 37 (0x25)
0xA1, 0x01, // Collection (Application)
0x85, kVendorPayloadReportID, // ReportID................ (VendorPayloadReportID)
0x09, 0x25, // Usage 37 (0x25)
0x06, 0x00, 0xFF, // Usage Page (65280)
0x95, 0x01, // Report Count............ (1)
0x75, kVendorPayloadBitLength, // Report Size............. (VendorPayloadBitLength)
0x81, 0x02, // Input...................(Data, Variable, Absolute)
0xC0, // End Collection
0xC0, // End Collection
};
@interface TestVendorMessageAndVendorPayload : XCTestCase
@property IOHIDDeviceTestController * deviceController;
@property IOHIDEventSystemTestController * eventController;
@property IOHIDUserDeviceTestController * sourceController;
@property CFRunLoopRef deviceControllerRunloop;
@property dispatch_queue_t eventControllerQueue;
@property dispatch_queue_t rootQueue;
@end
@implementation TestVendorMessageAndVendorPayload
- (void)setUp {
[super setUp];
self.rootQueue = IOHIDUnitTestCreateRootQueue(31, 2);
self.eventControllerQueue = dispatch_queue_create_with_target ("IOHIDEventSystemTestController", DISPATCH_QUEUE_SERIAL, self.rootQueue);
HIDXCTAssertAndThrowTrue(self.eventControllerQueue != nil);
self.deviceControllerRunloop = IOHIDUnitTestCreateRunLoop (31);
HIDXCTAssertAndThrowTrue(self.deviceControllerRunloop != NULL);
NSData * descriptorData = [[NSData alloc] initWithBytes:descriptor length:sizeof(descriptor)];
NSString * uniqueID = [[[NSUUID alloc] init] UUIDString];
self.sourceController = [[IOHIDUserDeviceTestController alloc] initWithDescriptor:descriptorData DeviceUniqueID:uniqueID andQueue:nil];
HIDXCTAssertAndThrowTrue(self.sourceController != nil);
self.deviceController = [[IOHIDDeviceTestController alloc] initWithDeviceUniqueID:uniqueID :self.deviceControllerRunloop];
HIDXCTAssertAndThrowTrue(self.deviceController != nil);
self.eventController = [[IOHIDEventSystemTestController alloc] initWithDeviceUniqueID:uniqueID AndQueue:self.eventControllerQueue];
HIDXCTAssertAndThrowTrue(self.eventController != nil);
NSArray * elementMatching = @[
@{
@kIOHIDElementUsagePageKey:@(kHIDPage_AppleVendor),
@kIOHIDElementUsageKey:@(kHIDUsage_AppleVendor_Message) ,
},
@{
@kIOHIDElementUsagePageKey:@(kHIDPage_AppleVendor),
@kIOHIDElementUsageKey:@(kHIDUsage_AppleVendor_Payload) ,
}
];
IOHIDDeviceSetInputValueMatchingMultiple(self.deviceController.device, (CFArrayRef)elementMatching);
}
- (void)tearDown {
[self.eventController invalidate];
[self.sourceController invalidate];
[self.deviceController invalidate];
@autoreleasepool {
self.sourceController = nil;
self.eventController = nil;
self.deviceController = nil;
}
if (self.deviceControllerRunloop) {
IOHIDUnitTestDestroyRunLoop(self.deviceControllerRunloop);
}
[super tearDown];
}
- (void)testVendorDefinedMessageEvents {
IOReturn status;
REPORT_WITH_ID report;
for (NSUInteger length = 1; length < sizeof(report.data); length++) {
report.id = kVendorMessageReportID;
for (uint8_t i = 0; i < length; i++) {
report.data[i] = i;
}
NSData * reportData = [[NSData alloc] initWithBytes:&report length: (length + 1)];
status = [self.sourceController handleReport:reportData withInterval:2000];
XCTAssert(status == kIOReturnSuccess, "handleReport:
}
// Allow event to be dispatched
usleep(kDefaultReportDispatchCompletionTime);
// Check if event system reset occur
XCTAssert(self.eventController.eventSystemResetCount == 0, "IOHIDEventSystem resetCount:
// Make copy
NSArray *events = nil;
@synchronized (self.eventController.events) {
events = [self.eventController.events copy];
}
EVENTS_STATS stats = [IOHIDEventSystemTestController getEventsStats:events];
HIDTestEventLatency(stats);
XCTAssertTrue(stats.totalCount == (sizeof(report.data) - 1),
"events count: );
for (NSUInteger index = 0; index < events.count; ++index) {
IOHIDEventRef event = (__bridge IOHIDEventRef)events[index];
XCTAssertTrue(IOHIDEventConformsTo(event, kIOHIDEventTypeVendorDefined));
NSArray* children = (NSArray*)IOHIDEventGetChildren (event);
XCTAssertFalse(children && children.count !=0);
uint8_t *payload = NULL;
CFIndex lenght = 0;
IOHIDEventGetVendorDefinedData (event, &payload, &lenght);
XCTAssertTrue(payload && ((NSUInteger)lenght == (index + 1)));
}
}
- (void)testVendorDefinedPayloadElements {
IOReturn status;
REPORT_WITH_ID report;
for (NSUInteger length = 1; length < sizeof(report.data); length++) {
report.id = kVendorPayloadReportID;
for (uint8_t i = 0; i < length; i++) {
report.data[i] = length;
}
NSData * reportData = [[NSData alloc] initWithBytes:&report length: (length + 1)];
status = [self.sourceController handleReport:reportData withInterval:0];
XCTAssert(status == kIOReturnSuccess, "handleReport:
}
// Allow elements value to be dispatched
usleep(kDefaultReportDispatchCompletionTime);
// Make copy
NSArray *values = nil;
@synchronized (self.deviceController.values) {
values = [self.deviceController.values copy];
}
// Check values
XCTAssertTrue(values && values.count == (sizeof(report.data) - 1),
"values count: );
for (NSUInteger index = 0; index < values.count; ++index) {
NSDictionary *value = values[index];
NSData *data = value[@"data"];
XCTAssertTrue (data && data.length == (index + 1), "Data IOHIDElementRef element = (__bridge IOHIDElementRef)value[@"element"];
XCTAssertTrue (element && IOHIDElementGetUsagePage (element) == kHIDPage_AppleVendor && IOHIDElementGetUsage (element) == kHIDUsage_AppleVendor_Payload);
}
}
@end