Force all controllers to use a rumble thread

This commit is contained in:
Lior Halphon 2020-05-30 20:15:13 +03:00
parent 59b94b92ca
commit e678b50101
1 changed files with 49 additions and 47 deletions

View File

@ -39,7 +39,7 @@ static bool axesEmulateButtons = false;
static bool axes2DEmulateButtons = false; static bool axes2DEmulateButtons = false;
static bool hatsEmulateButtons = false; static bool hatsEmulateButtons = false;
static NSLock *globalPWMThreadLock; static NSLock *globalRumbleThreadLock;
@interface JOYController () @interface JOYController ()
+ (void)controllerAdded:(IOHIDDeviceRef) device; + (void)controllerAdded:(IOHIDDeviceRef) device;
@ -152,12 +152,12 @@ typedef union {
bool _isSwitch; // Does this controller use the Switch protocol? bool _isSwitch; // Does this controller use the Switch protocol?
bool _isDualShock3; // Does this controller use DS3 outputs? bool _isDualShock3; // Does this controller use DS3 outputs?
JOYVendorSpecificOutput _lastVendorSpecificOutput; JOYVendorSpecificOutput _lastVendorSpecificOutput;
NSLock *_rumblePWMThreadLock; NSLock *_rumbleThreadLock;
volatile double _rumblePWMRatio; volatile double _rumblePWMRatio;
bool _physicallyConnected; bool _physicallyConnected;
bool _logicallyConnected; bool _logicallyConnected;
bool _rumblePWMThreadRunning; bool _rumbleThreadRunning;
volatile bool _forceStopPWMThread; volatile bool _forceStopRumbleThread;
NSDictionary *_hacks; NSDictionary *_hacks;
NSMutableData *_lastReport; NSMutableData *_lastReport;
@ -358,7 +358,7 @@ typedef union {
_axes2DEmulatedButtons = [NSMutableDictionary dictionary]; _axes2DEmulatedButtons = [NSMutableDictionary dictionary];
_hatEmulatedButtons = [NSMutableDictionary dictionary]; _hatEmulatedButtons = [NSMutableDictionary dictionary];
_iokitToJOY = [NSMutableDictionary dictionary]; _iokitToJOY = [NSMutableDictionary dictionary];
_rumblePWMThreadLock = [[NSLock alloc] init]; _rumbleThreadLock = [[NSLock alloc] init];
//NSMutableArray *axes3d = [NSMutableArray array]; //NSMutableArray *axes3d = [NSMutableArray array];
@ -697,7 +697,7 @@ typedef union {
} }
} }
_physicallyConnected = false; _physicallyConnected = false;
[self _forceStopPWMThread]; // Stop the rumble thread. [self _forceStopRumbleThread]; // Stop the rumble thread.
[exposedControllers removeObject:self]; [exposedControllers removeObject:self];
_device = nil; _device = nil;
} }
@ -731,23 +731,30 @@ typedef union {
} }
} }
- (void)pwmThread - (void)rumbleThread
{ {
unsigned rumbleCounter = 0; unsigned rumbleCounter = 0;
while (self.connected && !_forceStopPWMThread) { if (_rumbleElement.max == 1 && _rumbleElement.min == 0) {
if ([_rumbleElement setValue:rumbleCounter < round(_rumblePWMRatio * PWM_RESOLUTION)]) { while (self.connected && !_forceStopRumbleThread) {
break; if ([_rumbleElement setValue:rumbleCounter < round(_rumblePWMRatio * PWM_RESOLUTION)]) {
} break;
rumbleCounter += round(_rumblePWMRatio * PWM_RESOLUTION); }
if (rumbleCounter >= PWM_RESOLUTION) { rumbleCounter += round(_rumblePWMRatio * PWM_RESOLUTION);
rumbleCounter -= PWM_RESOLUTION; if (rumbleCounter >= PWM_RESOLUTION) {
rumbleCounter -= PWM_RESOLUTION;
}
} }
} }
[_rumblePWMThreadLock lock]; else {
while (self.connected && !_forceStopRumbleThread) {
[_rumbleElement setValue:_rumblePWMRatio * (_rumbleElement.max - _rumbleElement.min) + _rumbleElement.min];
}
}
[_rumbleThreadLock lock];
[_rumbleElement setValue:0]; [_rumbleElement setValue:0];
_rumblePWMThreadRunning = false; _rumbleThreadRunning = false;
_forceStopPWMThread = false; _forceStopRumbleThread = false;
[_rumblePWMThreadLock unlock]; [_rumbleThreadLock unlock];
} }
- (void)setRumbleAmplitude:(double)amp /* andFrequency: (double)frequency */ - (void)setRumbleAmplitude:(double)amp /* andFrequency: (double)frequency */
@ -799,32 +806,27 @@ typedef union {
[self sendReport:[NSData dataWithBytes:&_lastVendorSpecificOutput.ds3Output length:sizeof(_lastVendorSpecificOutput.ds3Output)]]; [self sendReport:[NSData dataWithBytes:&_lastVendorSpecificOutput.ds3Output length:sizeof(_lastVendorSpecificOutput.ds3Output)]];
} }
else { else {
if (_rumbleElement.max == 1 && _rumbleElement.min == 0) { [_rumbleThreadLock lock];
[_rumblePWMThreadLock lock]; _rumblePWMRatio = amp;
_rumblePWMRatio = amp; if (!_rumbleThreadRunning) { // PWM thread not running, start it.
if (!_rumblePWMThreadRunning) { // PWM thread not running, start it. if (amp != 0) {
if (amp != 0) { /* TODO: The PWM thread does not handle correctly the case of having a multi-port controller where more
/* TODO: The PWM thread does not handle correctly the case of having a multi-port controller where more than one controller uses rumble. At least make sure any sibling controllers don't have their
than one controller uses rumble. At least make sure any sibling controllers don't have their PWM thread running. */
PWM thread running. */
[globalRumbleThreadLock lock];
[globalPWMThreadLock lock]; for (JOYController *controller in [JOYController allControllers]) {
for (JOYController *controller in [JOYController allControllers]) { if (controller != self && controller->_device == _device) {
if (controller != self && controller->_device == _device) { [controller _forceStopRumbleThread];
[controller _forceStopPWMThread];
}
} }
_rumblePWMRatio = amp;
_rumblePWMThreadRunning = true;
[self performSelectorInBackground:@selector(pwmThread) withObject:nil];
[globalPWMThreadLock unlock];
} }
_rumblePWMRatio = amp;
_rumbleThreadRunning = true;
[self performSelectorInBackground:@selector(rumbleThread) withObject:nil];
[globalRumbleThreadLock unlock];
} }
[_rumblePWMThreadLock unlock];
}
else {
[_rumbleElement setValue:amp * (_rumbleElement.max - _rumbleElement.min) + _rumbleElement.min];
} }
[_rumbleThreadLock unlock];
} }
} }
@ -833,14 +835,14 @@ typedef union {
return _logicallyConnected && _physicallyConnected; return _logicallyConnected && _physicallyConnected;
} }
- (void)_forceStopPWMThread - (void)_forceStopRumbleThread
{ {
[_rumblePWMThreadLock lock]; [_rumbleThreadLock lock];
if (_rumblePWMThreadRunning) { if (_rumbleThreadRunning) {
_forceStopPWMThread = true; _forceStopRumbleThread = true;
} }
[_rumblePWMThreadLock unlock]; [_rumbleThreadLock unlock];
while (_rumblePWMThreadRunning); while (_rumbleThreadRunning);
} }
+ (void)controllerAdded:(IOHIDDeviceRef) device + (void)controllerAdded:(IOHIDDeviceRef) device
@ -900,7 +902,7 @@ typedef union {
controllers = [NSMutableDictionary dictionary]; controllers = [NSMutableDictionary dictionary];
exposedControllers = [NSMutableArray array]; exposedControllers = [NSMutableArray array];
globalPWMThreadLock = [[NSLock alloc] init]; globalRumbleThreadLock = [[NSLock alloc] init];
NSArray *array = @[ NSArray *array = @[
CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick), CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick),
CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad), CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad),