diff --git a/JoyKit/JOYController.m b/JoyKit/JOYController.m index b4810ab..f9f0775 100644 --- a/JoyKit/JOYController.m +++ b/JoyKit/JOYController.m @@ -5,6 +5,8 @@ #import "JOYEmulatedButton.h" #include +#define PWM_RESOLUTION 16 + static NSString const *JOYAxisGroups = @"JOYAxisGroups"; static NSString const *JOYReportIDFilters = @"JOYReportIDFilters"; static NSString const *JOYButtonUsageMapping = @"JOYButtonUsageMapping"; @@ -130,7 +132,7 @@ typedef struct __attribute__((packed)) { _physicallyConnected = true; _logicallyConnected = true; - _device = device; + _device = (IOHIDDeviceRef)CFRetain(device); _serialSuffix = suffix; IOHIDDeviceRegisterInputValueCallback(device, HIDInput, (void *)self); @@ -603,11 +605,17 @@ typedef struct __attribute__((packed)) { - (void)pwmThread { - while (_rumblePWMRatio != 0) { - [_rumbleElement setValue:1]; - [NSThread sleepForTimeInterval:_rumblePWMRatio / 10]; - [_rumbleElement setValue:0]; - [NSThread sleepForTimeInterval:(1 - _rumblePWMRatio) / 10]; + /* TODO: This does not handle correctly the case of having a multi-port controller where more than one controller + uses rumble. */ + unsigned rumbleCounter = 0; + while (self.connected) { + if ([_rumbleElement setValue:rumbleCounter < round(_rumblePWMRatio * PWM_RESOLUTION)]) { + break; + } + rumbleCounter += round(_rumblePWMRatio * PWM_RESOLUTION); + if (rumbleCounter >= PWM_RESOLUTION) { + rumbleCounter -= PWM_RESOLUTION; + } } [_rumblePWMThreadLock lock]; _rumblePWMThreadRunning = false; @@ -659,6 +667,7 @@ typedef struct __attribute__((packed)) { else { if (_rumbleElement.max == 1 && _rumbleElement.min == 0) { [_rumblePWMThreadLock lock]; + _rumblePWMRatio = amp; if (!_rumblePWMThreadRunning) { // PWM thread not running, start it. if (amp != 0) { _rumblePWMRatio = amp; @@ -666,14 +675,6 @@ typedef struct __attribute__((packed)) { [self performSelectorInBackground:@selector(pwmThread) withObject:nil]; } } - else { - if (amp == 0) { // Thread is running, signal it to stop - _rumblePWMRatio = 0; - } - else { - _rumblePWMRatio = amp; - } - } [_rumblePWMThreadLock unlock]; } else { @@ -771,4 +772,12 @@ typedef struct __attribute__((packed)) { IOHIDManagerRegisterDeviceRemovalCallback(manager, HIDDeviceRemoved, NULL); IOHIDManagerScheduleWithRunLoop(manager, [runloop getCFRunLoop], kCFRunLoopDefaultMode); } + +- (void)dealloc +{ + if (_device) { + CFRelease(_device); + _device = NULL; + } +} @end diff --git a/JoyKit/JOYElement.h b/JoyKit/JOYElement.h index 860c247..0e917dd 100644 --- a/JoyKit/JOYElement.h +++ b/JoyKit/JOYElement.h @@ -5,8 +5,8 @@ - (instancetype)initWithElement:(IOHIDElementRef)element; - (int32_t)value; - (NSData *)dataValue; -- (void)setValue:(uint32_t)value; -- (void)setDataValue:(NSData *)value; +- (IOReturn)setValue:(uint32_t)value; +- (IOReturn)setDataValue:(NSData *)value; @property (readonly) uint16_t usage; @property (readonly) uint16_t usagePage; @property (readonly) uint32_t uniqueID; diff --git a/JoyKit/JOYElement.m b/JoyKit/JOYElement.m index 6539c2e..4050312 100644 --- a/JoyKit/JOYElement.m +++ b/JoyKit/JOYElement.m @@ -81,18 +81,20 @@ return [NSData dataWithBytes:IOHIDValueGetBytePtr(value) length:IOHIDValueGetLength(value)]; } -- (void)setValue:(uint32_t)value +- (IOReturn)setValue:(uint32_t)value { IOHIDValueRef ivalue = IOHIDValueCreateWithIntegerValue(NULL, (__bridge IOHIDElementRef)_element, 0, value); - IOHIDDeviceSetValue(_device, (__bridge IOHIDElementRef)_element, ivalue); + IOReturn ret = IOHIDDeviceSetValue(_device, (__bridge IOHIDElementRef)_element, ivalue); CFRelease(ivalue); + return ret; } -- (void)setDataValue:(NSData *)value +- (IOReturn)setDataValue:(NSData *)value { IOHIDValueRef ivalue = IOHIDValueCreateWithBytes(NULL, (__bridge IOHIDElementRef)_element, 0, value.bytes, value.length); - IOHIDDeviceSetValue(_device, (__bridge IOHIDElementRef)_element, ivalue); + IOReturn ret = IOHIDDeviceSetValue(_device, (__bridge IOHIDElementRef)_element, ivalue); CFRelease(ivalue); + return ret; } /* For use as a dictionary key */ diff --git a/JoyKit/JOYSubElement.m b/JoyKit/JOYSubElement.m index 55e289e..c94badc 100644 --- a/JoyKit/JOYSubElement.m +++ b/JoyKit/JOYSubElement.m @@ -65,15 +65,15 @@ return ret; } -- (void)setValue: (uint32_t) value +- (IOReturn)setValue: (uint32_t) value { NSMutableData *dataValue = [[_parent dataValue] mutableCopy]; - if (!dataValue) return; - if (_size > 32) return; - if (_size + (_offset % 8) > 32) return; + if (!dataValue) return -1; + if (_size > 32) return -1; + if (_size + (_offset % 8) > 32) return -1; size_t parentLength = dataValue.length; - if (_size > parentLength * 8) return; - if (_size + _offset >= parentLength * 8) return; + if (_size > parentLength * 8) return -1; + if (_size + _offset >= parentLength * 8) return -1; uint8_t *bytes = dataValue.mutableBytes; uint8_t temp[4] = {0,}; @@ -81,7 +81,7 @@ (*(uint32_t *)temp) &= ~((1 << (_size - 1)) << (_offset % 8)); (*(uint32_t *)temp) |= (value) << (_offset % 8); memcpy(bytes + _offset / 8, temp, (_offset + _size - 1) / 8 - _offset / 8 + 1); - [_parent setDataValue:dataValue]; + return [_parent setDataValue:dataValue]; } - (NSData *)dataValue @@ -90,9 +90,10 @@ return nil; } -- (void)setDataValue:(NSData *)data +- (IOReturn)setDataValue:(NSData *)data { [self doesNotRecognizeSelector:_cmd]; + return -1; }