HIDTransaction.m   [plain text]

//
// HIDTransaction.m
// HID
//
// Created by dekom on 10/5/17.
//

#import <Foundation/Foundation.h>
#import <IOKit/hid/IOHIDLib.h>
#import "HIDTransaction.h"
#import "HIDDevicePrivate.h"
#import "HIDElementPrivate.h"
#import "NSError+IOReturn.h"
#import <IOKit/hid/IOHIDLibPrivate.h>

@implementation HIDTransaction {
IOHIDTransactionRef _transaction;
}

- (instancetype)initWithDevice:(HIDDevice *)device
{
self = [super init];

if (!self) {
return self;
}

_transaction = IOHIDTransactionCreate(kCFAllocatorDefault,
(__bridge IOHIDDeviceRef)device,
kIOHIDTransactionDirectionTypeInput,
kIOHIDTransactionOptionsWeakDevice);
if (!_transaction) {
return nil;
}

return self;
}

- (void)dealloc
{
if (_transaction) {
CFRelease(_transaction);
}
}

- (NSString *)description {
return [NSString stringWithFormat:@"%@", _transaction];
}

- (HIDTransactionDirectionType)direction
{
return (HIDTransactionDirectionType)IOHIDTransactionGetDirection(_transaction);
}

- (void)setDirection:(HIDTransactionDirectionType)direction
{
IOHIDTransactionSetDirection(_transaction,
(IOHIDTransactionDirectionType)direction);
}

- (BOOL)commitElements:(NSArray<HIDElement *> *)elements
error:(out NSError **)outError
{
IOReturn ret = kIOReturnError;

for (HIDElement *element in elements) {
IOHIDTransactionAddElement(_transaction,
(__bridge IOHIDElementRef)element);

if (self.direction == kIOHIDTransactionDirectionTypeOutput) {
IOHIDTransactionSetValue(_transaction,
(__bridge IOHIDElementRef)element,
element.valueRef,
kIOHIDOptionsTypeNone);
}
}

ret = IOHIDTransactionCommit(_transaction);

if (ret != kIOReturnSuccess) {
IOHIDTransactionClear(_transaction);

if (outError) {
*outError = [NSError errorWithIOReturn:ret];
}

return NO;
}

if (self.direction == kIOHIDTransactionDirectionTypeInput) {
for (HIDElement *element in elements) {
IOHIDValueRef val = IOHIDTransactionGetValue(
_transaction,
(__bridge IOHIDElementRef)element,
kIOHIDOptionsTypeNone);
if (val) {
[element setValueRef:val];
}
}
}

IOHIDTransactionClear(_transaction);
return (ret == kIOReturnSuccess);
}

@end