Improve PWM quality, fix a crash

This commit is contained in:
Lior Halphon 2020-05-01 18:08:44 +03:00
parent 5a56c3b882
commit 4bf252800e
4 changed files with 40 additions and 28 deletions

View File

@ -5,6 +5,8 @@
#import "JOYEmulatedButton.h"
#include <IOKit/hid/IOHIDLib.h>
#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

View File

@ -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;

View File

@ -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 */

View File

@ -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;
}