Add additional lock to use when writing output reports

This commit is contained in:
Travis Nickles 2017-11-15 02:14:20 -06:00
parent de8934f7ab
commit 9045d18092

View File

@ -548,12 +548,6 @@ namespace DS4Windows
try try
{ {
exitOutputThread = true; exitOutputThread = true;
/*lock (outputReport)
{
Monitor.PulseAll(outputReport);
}
*/
ds4Output.Interrupt(); ds4Output.Interrupt();
ds4Output.Join(); ds4Output.Join();
} }
@ -574,7 +568,6 @@ namespace DS4Windows
else else
{ {
return hDevice.WriteOutputReportViaInterrupt(outputReport, READ_STREAM_TIMEOUT); return hDevice.WriteOutputReportViaInterrupt(outputReport, READ_STREAM_TIMEOUT);
//return hDevice.WriteAsyncOutputReportViaInterrupt(outputReport);
} }
} }
@ -584,7 +577,6 @@ namespace DS4Windows
try try
{ {
int lastError = 0; int lastError = 0;
outputPendCount = 3;
while (!exitOutputThread) while (!exitOutputThread)
{ {
bool result = false; bool result = false;
@ -594,11 +586,14 @@ namespace DS4Windows
lock (outputReportBuffer) lock (outputReportBuffer)
{ {
outputReportBuffer.CopyTo(outputReport, 0); outputReportBuffer.CopyTo(outputReport, 0);
outputRumble = false;
outputPendCount--; outputPendCount--;
outputRumble = false;
} }
result = writeOutput(); lock(outputReport)
{
result = writeOutput();
}
if (!result) if (!result)
{ {
@ -617,21 +612,11 @@ namespace DS4Windows
{ {
lastError = 0; lastError = 0;
lock (outputReportBuffer) lock (outputReportBuffer)
{
Monitor.Wait(outputReportBuffer); Monitor.Wait(outputReportBuffer);
}
/*if (testRumble.IsRumbleSet()) // repeat test rumbles periodically; rumble has auto-shut-off in the DS4 firmware
Monitor.Wait(outputReport, 10000); // DS4 firmware stops it after 5 seconds, so let the motors rest for that long, too.
else
Monitor.Wait(outputReport);
*/
} }
} }
} }
catch (ThreadInterruptedException) catch (ThreadInterruptedException) { }
{
}
} }
/** Is the device alive and receiving valid sensor input reports? */ /** Is the device alive and receiving valid sensor input reports? */
@ -1043,8 +1028,6 @@ namespace DS4Windows
if (conType == ConnectionType.BT) if (conType == ConnectionType.BT)
{ {
outputReportBuffer[0] = 0x11; outputReportBuffer[0] = 0x11;
//outputReportBuffer[1] = 0x80;
//outputReportBuffer[1] = 0x84;
outputReportBuffer[1] = (byte)(0x80 | btPollRate); // input report rate outputReportBuffer[1] = (byte)(0x80 | btPollRate); // input report rate
// enable rumble (0x01), lightbar (0x02), flash (0x04) // enable rumble (0x01), lightbar (0x02), flash (0x04)
outputReportBuffer[3] = 0xf7; outputReportBuffer[3] = 0xf7;
@ -1080,22 +1063,22 @@ namespace DS4Windows
if (synchronous) if (synchronous)
{ {
outputRumble = false;
outputReportBuffer.CopyTo(outputReport, 0); outputReportBuffer.CopyTo(outputReport, 0);
outputRumble = false;
outputPendCount = outputPendCount > 0 ? outputPendCount-- : (byte)0;
try try
{ {
if (!writeOutput()) lock (outputReport)
{ {
int winError = Marshal.GetLastWin32Error(); if (!writeOutput())
Console.WriteLine(Mac.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> encountered synchronous write failure: " + winError); {
//Log.LogToGui(Mac.ToString() + " encountered synchronous write failure: " + winError, true); int winError = Marshal.GetLastWin32Error();
quitOutputThread = true; quitOutputThread = true;
}
} }
} }
catch catch { } // If it's dead already, don't worry about it.
{
// If it's dead already, don't worry about it.
}
} }
else else
{ {
@ -1106,9 +1089,7 @@ namespace DS4Windows
if (output) if (output)
{ {
if (outputPendCount == 0) if (outputPendCount == 0)
{
outputPendCount = 3; outputPendCount = 3;
}
outputRumble = true; outputRumble = true;
Monitor.Pulse(outputReportBuffer); Monitor.Pulse(outputReportBuffer);
@ -1128,7 +1109,6 @@ namespace DS4Windows
{ {
// Wait for output report to be written // Wait for output report to be written
StopOutputUpdate(); StopOutputUpdate();
Console.WriteLine("Trying to disconnect BT device " + Mac); Console.WriteLine("Trying to disconnect BT device " + Mac);
IntPtr btHandle = IntPtr.Zero; IntPtr btHandle = IntPtr.Zero;
int IOCTL_BTH_DISCONNECT_DEVICE = 0x41000c; int IOCTL_BTH_DISCONNECT_DEVICE = 0x41000c;
@ -1145,24 +1125,27 @@ namespace DS4Windows
bool success = false; bool success = false;
NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS p = new NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS(); lock (outputReport)
p.dwSize = Marshal.SizeOf(typeof(NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS));
IntPtr searchHandle = NativeMethods.BluetoothFindFirstRadio(ref p, ref btHandle);
int bytesReturned = 0;
while (!success && btHandle != IntPtr.Zero)
{ {
success = NativeMethods.DeviceIoControl(btHandle, IOCTL_BTH_DISCONNECT_DEVICE, ref lbtAddr, 8, IntPtr.Zero, 0, ref bytesReturned, IntPtr.Zero); NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS p = new NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS();
NativeMethods.CloseHandle(btHandle); p.dwSize = Marshal.SizeOf(typeof(NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS));
if (!success) IntPtr searchHandle = NativeMethods.BluetoothFindFirstRadio(ref p, ref btHandle);
{ int bytesReturned = 0;
if (!NativeMethods.BluetoothFindNextRadio(searchHandle, ref btHandle))
btHandle = IntPtr.Zero;
}
}
NativeMethods.BluetoothFindRadioClose(searchHandle); while (!success && btHandle != IntPtr.Zero)
Console.WriteLine("Disconnect successful: " + success); {
success = NativeMethods.DeviceIoControl(btHandle, IOCTL_BTH_DISCONNECT_DEVICE, ref lbtAddr, 8, IntPtr.Zero, 0, ref bytesReturned, IntPtr.Zero);
NativeMethods.CloseHandle(btHandle);
if (!success)
{
if (!NativeMethods.BluetoothFindNextRadio(searchHandle, ref btHandle))
btHandle = IntPtr.Zero;
}
}
NativeMethods.BluetoothFindRadioClose(searchHandle);
Console.WriteLine("Disconnect successful: " + success);
}
success = true; // XXX return value indicates failure, but it still works? success = true; // XXX return value indicates failure, but it still works?
if (success) if (success)
@ -1197,7 +1180,10 @@ namespace DS4Windows
if (remove) if (remove)
StopOutputUpdate(); StopOutputUpdate();
result = hDevice.WriteFeatureReport(disconnectReport); lock (outputReport)
{
result = hDevice.WriteFeatureReport(disconnectReport);
}
if (result && remove) if (result && remove)
{ {