Merged Electrobrains DS4Windows, Hectic's options, imporved custom mapping

This commit is contained in:
jays2kings 2014-03-29 01:29:08 -04:00
parent df43fd0d74
commit 768fdd0260
31 changed files with 895 additions and 801 deletions

View File

@ -13,10 +13,14 @@ namespace DS4Control
private DS4State s = new DS4State(); private DS4State s = new DS4State();
private bool buttonLock; // Toggled with a two-finger touchpad push, we accept and absorb button input without any fingers on a touchpad, helping with drag-and-drop. private bool buttonLock; // Toggled with a two-finger touchpad push, we accept and absorb button input without any fingers on a touchpad, helping with drag-and-drop.
private DS4Device dev = null; private DS4Device dev = null;
private readonly MouseCursor cursor;
private readonly MouseWheel wheel;
public ButtonMouse(int deviceID, DS4Device d) public ButtonMouse(int deviceID, DS4Device d)
{ {
deviceNum = deviceID; deviceNum = deviceID;
dev = d; dev = d;
cursor = new MouseCursor(deviceNum);
wheel = new MouseWheel(deviceNum);
} }
public override string ToString() public override string ToString()
@ -26,56 +30,36 @@ namespace DS4Control
public void touchesMoved(object sender, TouchpadEventArgs arg) public void touchesMoved(object sender, TouchpadEventArgs arg)
{ {
if (arg.touches.Length == 1) cursor.touchesMoved(arg);
{ wheel.touchesMoved(arg);
double sensitivity = Global.getTouchSensitivity(deviceNum) / 100.0; dev.getCurrentState(s);
int mouseDeltaX = (int)(sensitivity * (arg.touches[0].deltaX));
int mouseDeltaY = (int)(sensitivity * (arg.touches[0].deltaY));
InputMethods.MoveCursorBy(mouseDeltaX, mouseDeltaY);
}
else if (arg.touches.Length == 2)
{
Touch lastT0 = arg.touches[0].previousTouch;
Touch lastT1 = arg.touches[1].previousTouch;
Touch T0 = arg.touches[0];
Touch T1 = arg.touches[1];
//mouse wheel 120 == 1 wheel click according to Windows API
int lastMidX = (lastT0.hwX + lastT1.hwX) / 2, lastMidY = (lastT0.hwY + lastT1.hwY) / 2,
currentMidX = (T0.hwX + T1.hwX) / 2, currentMidY = (T0.hwY + T1.hwY) / 2; // XXX Will controller swap touch IDs?
double coefficient = Global.getScrollSensitivity(deviceNum);
// Adjust for touch distance: "standard" distance is 960 pixels, i.e. half the width. Scroll farther if fingers are farther apart, and vice versa, in linear proportion.
double touchXDistance = T1.hwX - T0.hwX, touchYDistance = T1.hwY - T0.hwY, touchDistance = Math.Sqrt(touchXDistance * touchXDistance + touchYDistance * touchYDistance);
coefficient *= touchDistance / 960.0;
InputMethods.MouseWheel((int)(coefficient * (lastMidY - currentMidY)), (int)(coefficient * (currentMidX - lastMidX)));
}
synthesizeMouseButtons(false); synthesizeMouseButtons(false);
} }
public void untouched() public void touchUnchanged(object sender, EventArgs unused)
{ {
if (buttonLock) dev.getCurrentState(s);
if (buttonLock || s.Touch1 || s.Touch2)
synthesizeMouseButtons(false); synthesizeMouseButtons(false);
else
dev.getCurrentState(s);
} }
public void touchesBegan(object sender, TouchpadEventArgs arg) public void touchesBegan(object sender, TouchpadEventArgs arg)
{ {
cursor.touchesBegan(arg);
wheel.touchesBegan(arg);
dev.getCurrentState(s);
synthesizeMouseButtons(false); synthesizeMouseButtons(false);
} }
public void touchesEnded(object sender, TouchpadEventArgs arg) public void touchesEnded(object sender, TouchpadEventArgs arg)
{ {
dev.getCurrentState(s);
if (!buttonLock) if (!buttonLock)
synthesizeMouseButtons(true); synthesizeMouseButtons(true);
else
dev.getCurrentState(s);
} }
private void synthesizeMouseButtons(bool justRelease) private void synthesizeMouseButtons(bool justRelease)
{ {
dev.getCurrentState(s);
bool previousLeftButton = leftButton, previousMiddleButton = middleButton, previousRightButton = rightButton; bool previousLeftButton = leftButton, previousMiddleButton = middleButton, previousRightButton = rightButton;
if (justRelease) if (justRelease)
{ {
@ -113,17 +97,20 @@ namespace DS4Control
{ {
if (upperDown) if (upperDown)
{ {
mapTouchPad(DS4Controls.TouchUpper, true); if (!mapTouchPad(DS4Controls.TouchUpper, true))
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP);
upperDown = false; upperDown = false;
} }
if (leftDown) if (leftDown)
{ {
mapTouchPad(DS4Controls.TouchButton, true); if (!mapTouchPad(DS4Controls.TouchButton, true))
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTUP);
leftDown = false; leftDown = false;
} }
if (rightDown) if (rightDown)
{ {
mapTouchPad(DS4Controls.TouchMulti, true); if (!mapTouchPad(DS4Controls.TouchMulti, true))
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTUP);
rightDown = false; rightDown = false;
} }
dev.setRumble(0, 0); dev.setRumble(0, 0);
@ -134,7 +121,8 @@ namespace DS4Control
byte leftRumble, rightRumble; byte leftRumble, rightRumble;
if (arg.touches == null) //No touches, finger on upper portion of touchpad if (arg.touches == null) //No touches, finger on upper portion of touchpad
{ {
mapTouchPad(DS4Controls.TouchUpper, false); if (!mapTouchPad(DS4Controls.TouchUpper, false))
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEDOWN);
upperDown = true; upperDown = true;
leftRumble = rightRumble = 127; leftRumble = rightRumble = 127;
} }
@ -142,23 +130,23 @@ namespace DS4Control
{ {
if (isLeft(arg.touches[0])) if (isLeft(arg.touches[0]))
{ {
mapTouchPad(DS4Controls.TouchButton, false); if (!mapTouchPad(DS4Controls.TouchButton, false))
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_LEFTDOWN);
leftDown = true; leftDown = true;
leftRumble = 63; leftRumble = 63;
rightRumble = 0; rightRumble = 0;
} }
else if (isRight(arg.touches[0])) else if (isRight(arg.touches[0]))
{ {
mapTouchPad(DS4Controls.TouchMulti, false); if (!mapTouchPad(DS4Controls.TouchMulti, false))
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_RIGHTDOWN);
rightDown = true; rightDown = true;
leftRumble = 0; leftRumble = 0;
rightRumble = 63; rightRumble = 63;
} }
else else
{ {
mapTouchPad(DS4Controls.TouchUpper, false); // ambiguous = same as upper leftRumble = rightRumble = 0; // Ignore ambiguous pushes.
upperDown = true;
leftRumble = rightRumble = 127;
} }
} }
else else

View File

@ -5,7 +5,7 @@ using System.Text;
using DS4Library; using DS4Library;
namespace DS4Control namespace DS4Control
{ {
public class Control: IDisposable public class Control
{ {
X360Device x360Bus; X360Device x360Bus;
DS4Device[] DS4Controllers = new DS4Device[4]; DS4Device[] DS4Controllers = new DS4Device[4];
@ -38,6 +38,17 @@ namespace DS4Control
} }
} }
private void WarnExclusiveModeFailure(DS4Device device)
{
if (DS4Devices.isExclusiveMode && !device.IsExclusive)
{
String message = "Warning: Could not open DS4 " + device.MacAddress + " exclusively. " +
"You must quit other applications like Steam, Uplay before activating the 'Hide DS4 Controller' option.";
LogDebug(message);
Log.LogToTray(message);
}
}
public bool Start() public bool Start()
{ {
if (x360Bus.Open() && x360Bus.Start()) if (x360Bus.Open() && x360Bus.Start())
@ -53,33 +64,29 @@ namespace DS4Control
int ind = 0; int ind = 0;
foreach (DS4Device device in devices) foreach (DS4Device device in devices)
{ {
LogDebug("Found Controller: " + device.MacAddress); LogDebug("Found Controller: " + device.MacAddress + " (" + device.ConnectionType + ")");
if (device.MacAddress == "00:00:00:00:00:00") WarnExclusiveModeFailure(device);
{
LogDebug("WARNING: If you are seing all zeroes as controller ID");
LogDebug("You might be running not fully supported BT dongle");
LogDebug("Only some basic functionality is enabled");
}
DS4Controllers[ind] = device; DS4Controllers[ind] = device;
device.Removal += this.On_DS4Removal; device.Removal += this.On_DS4Removal;
TPadModeSwitcher m_switcher = new TPadModeSwitcher(device, ind); TPadModeSwitcher m_switcher = new TPadModeSwitcher(device, ind);
m_switcher.Debug += OnDebug; m_switcher.Debug += OnDebug;
m_switcher.setMode(Global.getTouchEnabled(ind) ? 1 : 0);
modeSwitcher[ind] = m_switcher; modeSwitcher[ind] = m_switcher;
DS4Color color = Global.loadColor(ind); DS4Color color = Global.loadColor(ind);
device.LightBarColor = color; device.LightBarColor = color;
x360Bus.Plugin(ind + 1); x360Bus.Plugin(ind + 1);
device.Report += this.On_Report; device.Report += this.On_Report;
m_switcher.setMode(Global.getTouchEnabled(ind) ? 1 : 0);
ind++; ind++;
LogDebug("Controller: " + device.MacAddress + " is ready to use"); LogDebug("Controller: " + device.MacAddress + " is ready to use");
Log.LogToTray("Controller: " + device.MacAddress + " is ready to use"); Log.LogToTray("Controller: " + device.MacAddress + " is ready to use");
if (ind >= 4) if (ind >= 4) // out of Xinput devices!
break; break;
} }
} }
catch (Exception e) catch (Exception e)
{ {
LogDebug(e.Message); LogDebug(e.Message);
Log.LogToTray(e.Message);
} }
running = true; running = true;
@ -106,19 +113,28 @@ namespace DS4Control
LogDebug("Stopping DS4 Controllers"); LogDebug("Stopping DS4 Controllers");
DS4Devices.stopControllers(); DS4Devices.stopControllers();
LogDebug("Stopped DS4 Tool"); LogDebug("Stopped DS4 Tool");
Global.ControllerStatusChanged(this);
} }
return true; return true;
} }
private volatile bool justRemoved; // inhibits HotPlug temporarily when a device is being torn down
public bool HotPlug() public bool HotPlug()
{ {
if(running) if (running)
{ {
if (justRemoved)
{
justRemoved = false;
System.Threading.Thread.Sleep(200);
}
DS4Devices.findControllers(); DS4Devices.findControllers();
IEnumerable<DS4Device> devices = DS4Devices.getDS4Controllers(); IEnumerable<DS4Device> devices = DS4Devices.getDS4Controllers();
foreach (DS4Device device in devices) foreach (DS4Device device in devices)
{ {
if (device.IsDisconnecting)
continue;
if (((Func<bool>)delegate if (((Func<bool>)delegate
{ {
for (Int32 Index = 0; Index < DS4Controllers.Length; Index++) for (Int32 Index = 0; Index < DS4Controllers.Length; Index++)
@ -131,15 +147,19 @@ namespace DS4Control
for (Int32 Index = 0; Index < DS4Controllers.Length; Index++) for (Int32 Index = 0; Index < DS4Controllers.Length; Index++)
if (DS4Controllers[Index] == null) if (DS4Controllers[Index] == null)
{ {
LogDebug("Found Controller: " + device.MacAddress + " (" + device.ConnectionType + ")");
WarnExclusiveModeFailure(device);
DS4Controllers[Index] = device; DS4Controllers[Index] = device;
device.Removal += this.On_DS4Removal; device.Removal += this.On_DS4Removal;
TPadModeSwitcher m_switcher = new TPadModeSwitcher(device, Index); TPadModeSwitcher m_switcher = new TPadModeSwitcher(device, Index);
m_switcher.Debug += OnDebug; m_switcher.Debug += OnDebug;
modeSwitcher[Index] = m_switcher; modeSwitcher[Index] = m_switcher;
m_switcher.setMode(Global.getTouchEnabled(Index) ? 1 : 0);
device.LightBarColor = Global.loadColor(Index); device.LightBarColor = Global.loadColor(Index);
device.Report += this.On_Report; device.Report += this.On_Report;
x360Bus.Plugin(Index + 1); x360Bus.Plugin(Index + 1);
m_switcher.setMode(Global.getTouchEnabled(Index) ? 1 : 0);
LogDebug("Controller: " + device.MacAddress + " is ready to use");
Log.LogToTray("Controller: " + device.MacAddress + " is ready to use");
break; break;
} }
} }
@ -152,7 +172,21 @@ namespace DS4Control
if (DS4Controllers[index] != null) if (DS4Controllers[index] != null)
{ {
DS4Device d = DS4Controllers[index]; DS4Device d = DS4Controllers[index];
return d.MacAddress + ", Battery = " + d.Battery + "%," + " Touchpad = " + modeSwitcher[index].ToString() + " (" + d.ConnectionType + ")"; if (!d.IsAlive())
return null; // awaiting the first battery charge indication
String battery;
if (d.Charging)
{
if (d.Battery >= 100)
battery = "fully-charged";
else
battery = "charging at ~" + d.Battery + "%";
}
else
{
battery = "draining at ~" + d.Battery + "%";
}
return d.MacAddress + " (" + d.ConnectionType + "), Battery is " + battery + ", Touchpad in " + modeSwitcher[index].ToString();
} }
else else
return null; return null;
@ -168,11 +202,13 @@ namespace DS4Control
ind = i; ind = i;
if (ind != -1) if (ind != -1)
{ {
justRemoved = true;
x360Bus.Unplug(ind + 1); x360Bus.Unplug(ind + 1);
LogDebug("Controller " + device.MacAddress + " was removed or lost connection"); LogDebug("Controller " + device.MacAddress + " was removed or lost connection");
Log.LogToTray("Controller " + device.MacAddress + " was removed or lost connection"); Log.LogToTray("Controller " + device.MacAddress + " was removed or lost connection");
DS4Controllers[ind] = null; DS4Controllers[ind] = null;
modeSwitcher[ind] = null; modeSwitcher[ind] = null;
Global.ControllerStatusChanged(this);
} }
} }
@ -189,28 +225,24 @@ namespace DS4Control
if (ind!=-1) if (ind!=-1)
{ {
DS4State cState; device.getExposedState(ExposedState[ind], CurrentState[ind]);
DS4State cState = CurrentState[ind];
device.getPreviousState(PreviousState[ind]);
DS4State pState = PreviousState[ind];
if (modeSwitcher[ind].getCurrentMode() is ButtonMouse) if (modeSwitcher[ind].getCurrentMode() is ButtonMouse)
{ {
device.getExposedState(ExposedState[ind], CurrentState[ind]);
cState = CurrentState[ind];
ButtonMouse mode = (ButtonMouse)modeSwitcher[ind].getCurrentMode(); ButtonMouse mode = (ButtonMouse)modeSwitcher[ind].getCurrentMode();
if (!cState.Touch1 && !cState.Touch2 && !cState.TouchButton) // XXX so disgusting, need to virtualize this again
mode.untouched(); mode.getDS4State().Copy(cState);
cState = mode.getDS4State();
} }
else else
{ {
device.getExposedState(ExposedState[ind], CurrentState[ind]); device.getExposedState(ExposedState[ind], CurrentState[ind]);
cState = CurrentState[ind]; cState = CurrentState[ind];
} }
device.getPreviousState(PreviousState[ind]);
DS4State pState = PreviousState[ind];
CheckForHotkeys(ind, cState, pState); CheckForHotkeys(ind, cState, pState);
DS4LightBar.updateBatteryStatus(cState.Battery, device, ind);
if (Global.getHasCustomKeysorButtons(ind)) if (Global.getHasCustomKeysorButtons(ind))
{ {
@ -218,7 +250,14 @@ namespace DS4Control
cState = MappedState[ind]; cState = MappedState[ind];
} }
// Update the GUI/whatever.
DS4LightBar.updateLightBar(device, ind);
if (pState.Battery != cState.Battery)
Global.ControllerStatusChanged(this);
x360Bus.Parse(cState, processingData[ind].Report, ind); x360Bus.Parse(cState, processingData[ind].Report, ind);
// We push the translated Xinput state, and simultaneously we
// pull back any possible rumble data coming from Xinput consumers.
if (x360Bus.Report(processingData[ind].Report, processingData[ind].Rumble)) if (x360Bus.Report(processingData[ind].Report, processingData[ind].Rumble))
{ {
Byte Big = (Byte)(processingData[ind].Rumble[3]); Byte Big = (Byte)(processingData[ind].Rumble[3]);
@ -272,16 +311,5 @@ namespace DS4Control
heavyBoosted = 255; heavyBoosted = 255;
DS4Controllers[deviceNum].setRumble((byte)lightBoosted, (byte)heavyBoosted); DS4Controllers[deviceNum].setRumble((byte)lightBoosted, (byte)heavyBoosted);
} }
public DS4Device getDS4Controller(int deviceNum)
{
return DS4Controllers[deviceNum];
}
//CA1001 TypesThatOwnDisposableFieldsShouldBeDisposable
public void Dispose()
{
x360Bus.Dispose();
}
} }
} }

View File

@ -9,9 +9,14 @@ namespace DS4Control
public class MouseCursorOnly : ITouchpadBehaviour public class MouseCursorOnly : ITouchpadBehaviour
{ {
private int deviceNum; private int deviceNum;
private readonly MouseCursor cursor;
private readonly MouseWheel wheel;
public MouseCursorOnly(int deviceID) public MouseCursorOnly(int deviceID)
{ {
deviceNum = deviceID; deviceNum = deviceID;
cursor = new MouseCursor(deviceNum);
wheel = new MouseWheel(deviceNum);
} }
public override string ToString() public override string ToString()
@ -21,16 +26,15 @@ namespace DS4Control
public void touchesMoved(object sender, TouchpadEventArgs arg) public void touchesMoved(object sender, TouchpadEventArgs arg)
{ {
if (arg.touches.Length == 1) cursor.touchesMoved(arg);
{ wheel.touchesMoved(arg);
double sensitivity = Global.getTouchSensitivity(deviceNum) / 100.0;
int mouseDeltaX = (int)(sensitivity * (arg.touches[0].deltaX));
int mouseDeltaY = (int)(sensitivity * (arg.touches[0].deltaY));
InputMethods.MoveCursorBy(mouseDeltaX, mouseDeltaY);
}
} }
public void touchesBegan(object sender, TouchpadEventArgs arg) { } public void touchesBegan(object sender, TouchpadEventArgs arg)
{
cursor.touchesBegan(arg);
wheel.touchesBegan(arg);
}
public void touchesEnded(object sender, TouchpadEventArgs arg) { } public void touchesEnded(object sender, TouchpadEventArgs arg) { }
@ -38,6 +42,6 @@ namespace DS4Control
public void touchButtonDown(object sender, TouchpadEventArgs arg) { } public void touchButtonDown(object sender, TouchpadEventArgs arg) { }
public void untouched(object sender, TouchpadEventArgs nullUnused) { } public void touchUnchanged(object sender, EventArgs unused) { }
} }
} }

View File

@ -45,6 +45,8 @@
<Compile Include="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="CursorOnlyMode.cs" /> <Compile Include="CursorOnlyMode.cs" />
<Compile Include="DragMouse.cs" /> <Compile Include="DragMouse.cs" />
<Compile Include="MouseCursor.cs" />
<Compile Include="MouseWheel.cs" />
<Compile Include="TouchpadDisabled.cs" /> <Compile Include="TouchpadDisabled.cs" />
<Compile Include="TPadModeSwitcher.cs" /> <Compile Include="TPadModeSwitcher.cs" />
<Compile Include="DS4LightBar.cs" /> <Compile Include="DS4LightBar.cs" />

View File

@ -9,7 +9,7 @@ namespace DS4Control
{ {
private readonly static byte[/* Light On duration */, /* Light Off duration */] BatteryIndicatorDurations = private readonly static byte[/* Light On duration */, /* Light Off duration */] BatteryIndicatorDurations =
{ {
{ 255, 255 }, // 0 doesn't happen { 0, 0 }, // 0 is for "charging" OR anything sufficiently-"charged"
{ 28, 252 }, { 28, 252 },
{ 56, 224 }, { 56, 224 },
{ 84, 196 }, { 84, 196 },
@ -18,45 +18,76 @@ namespace DS4Control
{ 168, 112 }, { 168, 112 },
{ 196, 84 }, { 196, 84 },
{ 224, 56}, // on 80% of the time at 80, etc. { 224, 56}, // on 80% of the time at 80, etc.
{ 252, 28 }, // on 90% of the time at 90 { 252, 28 } // on 90% of the time at 90
{ 0, 0 } // no flash at 100
}; };
static double[] counters = new double[4];
public static void updateBatteryStatus(int battery, DS4Device device, int deviceNum) public static void updateLightBar(DS4Device device, int deviceNum)
{ {
DS4Color color;
if (Global.getLedAsBatteryIndicator(deviceNum)) if (Global.getLedAsBatteryIndicator(deviceNum))
{ {
byte[] fullColor = { if (device.Charging == false || device.Battery >= 100) // when charged, don't show the charging animation
Global.loadColor(deviceNum).red, {
Global.loadColor(deviceNum).green, DS4Color fullColor = new DS4Color
Global.loadColor(deviceNum).blue {
}; red = Global.loadColor(deviceNum).red,
green = Global.loadColor(deviceNum).green,
// New Setting blue = Global.loadColor(deviceNum).blue
DS4Color color = Global.loadLowColor(deviceNum); };
byte[] lowColor = { color.red, color.green, color.blue };
uint ratio = (uint)battery;
color = Global.getTransitionedColor(lowColor, fullColor, ratio);
device.LightBarColor = color;
color = Global.loadLowColor(deviceNum);
DS4Color lowColor = new DS4Color
{
red = color.red,
green = color.green,
blue = color.blue
};
color = Global.getTransitionedColor(lowColor, fullColor, (uint)device.Battery);
}
else // Display rainbow when charging.
{
counters[deviceNum]++;
double theta = Math.PI * 2.0 * counters[deviceNum] / 1800.0;
const double brightness = Math.PI; // small brightness numbers (far from max 128.0) mean less light steps and slower output reports; also, the lower the brightness the faster you can charge
color = new DS4Color
{
red = (byte)(brightness * Math.Sin(theta) + brightness - 0.5),
green = (byte)(brightness * Math.Sin(theta + (Math.PI * 2.0) / 3.0) + brightness - 0.5),
blue = (byte)(brightness * Math.Sin(theta + 2.0 * (Math.PI * 2.0) / 3.0) + brightness - 0.5)
};
}
} }
else else
{ {
DS4Color color = Global.loadColor(deviceNum); color = Global.loadColor(deviceNum);
device.LightBarColor = color;
} }
if (Global.getFlashWhenLowBattery(deviceNum)) DS4HapticState haptics = new DS4HapticState
{ {
device.LightBarOnDuration = BatteryIndicatorDurations[battery / 10, 0]; LightBarColor = color
device.LightBarOffDuration = BatteryIndicatorDurations[battery / 10, 1]; };
if (haptics.IsLightBarSet())
{
if (Global.getFlashWhenLowBattery(deviceNum))
{
int level = device.Battery / 10;
if (level >= 10)
level = 0; // all values of ~0% or >~100% are rendered the same
haptics.LightBarFlashDurationOn = BatteryIndicatorDurations[level, 0];
haptics.LightBarFlashDurationOff = BatteryIndicatorDurations[level, 1];
}
else
{
haptics.LightBarFlashDurationOff = haptics.LightBarFlashDurationOn = 0;
}
} }
else else
{ {
device.LightBarOffDuration = device.LightBarOnDuration = 0; haptics.LightBarExplicitlyOff = true;
} }
device.pushHapticState(haptics);
} }
} }

View File

@ -8,10 +8,12 @@ using System.Threading;
namespace DS4Control namespace DS4Control
{ {
class DragMouse: Mouse, IDisposable class DragMouse: Mouse
{ {
protected bool leftClick = false; protected bool leftClick = false;
protected Timer timer; protected Timer timer;
private readonly MouseCursor cursor;
private readonly MouseWheel wheel;
public DragMouse(int deviceID):base(deviceID) public DragMouse(int deviceID):base(deviceID)
{ {
@ -21,7 +23,9 @@ namespace DS4Control
leftClick = false; leftClick = false;
}, null, }, null,
System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite,
System.Threading.Timeout.Infinite); System.Threading.Timeout.Infinite);
cursor = new MouseCursor(deviceNum);
wheel = new MouseWheel(deviceNum);
} }
public override string ToString() public override string ToString()
@ -29,44 +33,9 @@ namespace DS4Control
return "Drag Mode"; return "Drag Mode";
} }
public override void touchesMoved(object sender, TouchpadEventArgs arg)
{
if (arg.touches.Length == 1)
{
double sensitivity = Global.getTouchSensitivity(deviceNum) / 100.0;
int mouseDeltaX = (int)(sensitivity * (arg.touches[0].deltaX));
int mouseDeltaY = (int)(sensitivity * (arg.touches[0].deltaY));
InputMethods.MoveCursorBy(mouseDeltaX, mouseDeltaY);
}
else if (arg.touches.Length == 2 && !leftClick)
{
Touch lastT0 = arg.touches[0].previousTouch;
Touch lastT1 = arg.touches[1].previousTouch;
Touch T0 = arg.touches[0];
Touch T1 = arg.touches[1];
//mouse wheel 120 == 1 wheel click according to Windows API
int lastMidX = (lastT0.hwX + lastT1.hwX) / 2, lastMidY = (lastT0.hwY + lastT1.hwY) / 2,
currentMidX = (T0.hwX + T1.hwX) / 2, currentMidY = (T0.hwY + T1.hwY) / 2; // XXX Will controller swap touch IDs?
double coefficient = Global.getScrollSensitivity(deviceNum);
// Adjust for touch distance: "standard" distance is 960 pixels, i.e. half the width. Scroll farther if fingers are farther apart, and vice versa, in linear proportion.
double touchXDistance = T1.hwX - T0.hwX, touchYDistance = T1.hwY - T0.hwY, touchDistance = Math.Sqrt(touchXDistance * touchXDistance + touchYDistance * touchYDistance);
coefficient *= touchDistance / 960.0;
InputMethods.MouseWheel((int)(coefficient * (lastMidY - currentMidY)), (int)(coefficient * (currentMidX - lastMidX)));
}
else
{
double sensitivity = Global.getTouchSensitivity(deviceNum) / 100.0;
int mouseDeltaX = (int)(sensitivity * (arg.touches[1].deltaX));
int mouseDeltaY = (int)(sensitivity * (arg.touches[1].deltaY));
InputMethods.MoveCursorBy(mouseDeltaX, mouseDeltaY);
}
}
public override void touchesBegan(object sender, TouchpadEventArgs arg) public override void touchesBegan(object sender, TouchpadEventArgs arg)
{ {
pastTime = arg.timeStamp; base.touchesBegan(sender, arg);
firstTouch = arg.touches[0];
if (leftClick) if (leftClick)
timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); timer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
} }
@ -139,11 +108,5 @@ namespace DS4Control
leftClick = true; leftClick = true;
} }
} }
//CA1001 TypesThatOwnDisposableFieldsShouldBeDisposable
public void Dispose()
{
timer.Dispose();
}
} }
} }

View File

@ -12,5 +12,6 @@ namespace DS4Control
void touchButtonUp(object sender, TouchpadEventArgs arg); void touchButtonUp(object sender, TouchpadEventArgs arg);
void touchButtonDown(object sender, TouchpadEventArgs arg); void touchButtonDown(object sender, TouchpadEventArgs arg);
void touchesEnded(object sender, TouchpadEventArgs arg); void touchesEnded(object sender, TouchpadEventArgs arg);
void touchUnchanged(object sender, EventArgs unused);
} }
} }

View File

@ -40,8 +40,6 @@ namespace DS4Control
MappedState.LY = 127; MappedState.LY = 127;
MappedState.RX = 127; MappedState.RX = 127;
MappedState.RY = 127; MappedState.RY = 127;
int MouseDeltaX = 0;
int MouseDeltaY = 0;
foreach (KeyValuePair<DS4Controls, X360Controls> customButton in Global.getCustomButtons()) foreach (KeyValuePair<DS4Controls, X360Controls> customButton in Global.getCustomButtons())
{ {
@ -183,34 +181,6 @@ namespace DS4Control
else if (PrevOn && !CurOn) else if (PrevOn && !CurOn)
InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP); InputMethods.MouseEvent(InputMethods.MOUSEEVENTF_MIDDLEUP);
break; break;
case X360Controls.MouseUp:
if (MouseDeltaY == 0)
{
MouseDeltaY = calculateRelativeMouseDelta(customButton.Key, cState, prevState);
MouseDeltaY = -Math.Abs(MouseDeltaY);
}
break;
case X360Controls.MouseDown:
if (MouseDeltaY == 0)
{
MouseDeltaY = calculateRelativeMouseDelta(customButton.Key, cState, prevState);
MouseDeltaY = Math.Abs(MouseDeltaY);
}
break;
case X360Controls.MouseLeft:
if (MouseDeltaX == 0)
{
MouseDeltaX = calculateRelativeMouseDelta(customButton.Key, cState, prevState);
MouseDeltaX = -Math.Abs(MouseDeltaX);
}
break;
case X360Controls.MouseRight:
if (MouseDeltaX == 0)
{
MouseDeltaX = calculateRelativeMouseDelta(customButton.Key, cState, prevState);
MouseDeltaX = Math.Abs(MouseDeltaX);
}
break;
case X360Controls.Unbound: case X360Controls.Unbound:
resetToDefaultValue(customButton.Key, MappedState); resetToDefaultValue(customButton.Key, MappedState);
break; break;
@ -225,54 +195,6 @@ namespace DS4Control
MappedState.RX = cState.RX; MappedState.RX = cState.RX;
if (!RY) if (!RY)
MappedState.RY = cState.RY; MappedState.RY = cState.RY;
InputMethods.MoveCursorBy(MouseDeltaX, MouseDeltaY);
}
private static int calculateRelativeMouseDelta(DS4Controls control, DS4State cState, DS4State pState)
{
int axisVal = -1;
int DEAD_ZONE = 10;
float SPEED_MULTIPLIER = 0.000004f;
bool positive = false;
float deltaTime = cState.ReportTimeStamp.Ticks - pState.ReportTimeStamp.Ticks;
switch (control)
{
case DS4Controls.LXNeg:
axisVal = cState.LX;
break;
case DS4Controls.LXPos:
positive = true;
axisVal = cState.LX;
break;
case DS4Controls.RXNeg:
axisVal = cState.RX;
break;
case DS4Controls.RXPos:
positive = true;
axisVal = cState.RX;
break;
case DS4Controls.LYNeg:
axisVal = cState.LY;
break;
case DS4Controls.LYPos:
positive = true;
axisVal = cState.LY;
break;
case DS4Controls.RYNeg:
axisVal = cState.RY;
break;
case DS4Controls.RYPos:
positive = true;
axisVal = cState.RY;
break;
}
axisVal = axisVal - 127;
int delta = 0;
if ( (!positive && axisVal < -DEAD_ZONE ) || (positive && axisVal > DEAD_ZONE))
{
delta = (int)(float) (axisVal * SPEED_MULTIPLIER * deltaTime);
}
return delta;
} }
public static bool compare(byte b1, byte b2) public static bool compare(byte b1, byte b2)

View File

@ -11,11 +11,15 @@ namespace DS4Control
protected DateTime pastTime; protected DateTime pastTime;
protected Touch firstTouch; protected Touch firstTouch;
protected int deviceNum; protected int deviceNum;
private readonly MouseCursor cursor;
private readonly MouseWheel wheel;
protected bool rightClick = false; protected bool rightClick = false;
public Mouse(int deviceID) public Mouse(int deviceID)
{ {
deviceNum = deviceID; deviceNum = deviceID;
cursor = new MouseCursor(deviceNum);
wheel = new MouseWheel(deviceNum);
} }
public override string ToString() public override string ToString()
@ -25,39 +29,23 @@ namespace DS4Control
public virtual void touchesMoved(object sender, TouchpadEventArgs arg) public virtual void touchesMoved(object sender, TouchpadEventArgs arg)
{ {
if (arg.touches.Length == 1) cursor.touchesMoved(arg);
{ wheel.touchesMoved(arg);
double sensitivity = Global.getTouchSensitivity(deviceNum) / 100.0; //Log.LogToGui("moved to " + arg.touches[0].hwX + "," + arg.touches[0].hwY);
int mouseDeltaX = (int)(sensitivity * (arg.touches[0].deltaX));
int mouseDeltaY = (int)(sensitivity * (arg.touches[0].deltaY));
InputMethods.MoveCursorBy(mouseDeltaX, mouseDeltaY);
}
else if (arg.touches.Length == 2)
{
Touch lastT0 = arg.touches[0].previousTouch;
Touch lastT1 = arg.touches[1].previousTouch;
Touch T0 = arg.touches[0];
Touch T1 = arg.touches[1];
//mouse wheel 120 == 1 wheel click according to Windows API
int lastMidX = (lastT0.hwX + lastT1.hwX) / 2, lastMidY = (lastT0.hwY + lastT1.hwY) / 2,
currentMidX = (T0.hwX + T1.hwX) / 2, currentMidY = (T0.hwY + T1.hwY) / 2; // XXX Will controller swap touch IDs?
double coefficient = Global.getScrollSensitivity(deviceNum);
// Adjust for touch distance: "standard" distance is 960 pixels, i.e. half the width. Scroll farther if fingers are farther apart, and vice versa, in linear proportion.
double touchXDistance = T1.hwX - T0.hwX, touchYDistance = T1.hwY - T0.hwY, touchDistance = Math.Sqrt(touchXDistance * touchXDistance + touchYDistance * touchYDistance);
coefficient *= touchDistance / 960.0;
InputMethods.MouseWheel((int)(coefficient * (lastMidY - currentMidY)), (int)(coefficient * (currentMidX - lastMidX)));
}
} }
public virtual void touchesBegan(object sender, TouchpadEventArgs arg) public virtual void touchesBegan(object sender, TouchpadEventArgs arg)
{ {
cursor.touchesBegan(arg);
wheel.touchesBegan(arg);
pastTime = arg.timeStamp; pastTime = arg.timeStamp;
firstTouch = arg.touches[0]; firstTouch = arg.touches[0];
//Log.LogToGui("began at " + arg.touches[0].hwX + "," + arg.touches[0].hwY);
} }
public virtual void touchesEnded(object sender, TouchpadEventArgs arg) public virtual void touchesEnded(object sender, TouchpadEventArgs arg)
{ {
//Log.LogToGui("ended at " + arg.touches[0].hwX + "," + arg.touches[0].hwY);
if (Global.getTapSensitivity(deviceNum) != 0) if (Global.getTapSensitivity(deviceNum) != 0)
{ {
DateTime test = arg.timeStamp; DateTime test = arg.timeStamp;
@ -111,6 +99,8 @@ namespace DS4Control
} }
} }
public void touchUnchanged(object sender, EventArgs unused) { }
protected bool mapTouchPad(DS4Controls padControl, bool release = false) protected bool mapTouchPad(DS4Controls padControl, bool release = false)
{ {
ushort key = Global.getCustomKey(padControl); ushort key = Global.getCustomKey(padControl);

View File

@ -12,8 +12,7 @@ namespace DS4Control
public enum DS4KeyType : byte { None = 0, ScanCode = 1, Repeat = 2 }; //Increment by exponents of 2*, starting at 2^0 public enum DS4KeyType : byte { None = 0, ScanCode = 1, Repeat = 2 }; //Increment by exponents of 2*, starting at 2^0
public enum Ds3PadId : byte { None = 0xFF, One = 0x00, Two = 0x01, Three = 0x02, Four = 0x03, All = 0x04 }; public enum Ds3PadId : byte { None = 0xFF, One = 0x00, Two = 0x01, Three = 0x02, Four = 0x03, All = 0x04 };
public enum DS4Controls : byte { LXNeg, LXPos, LYNeg, LYPos, RXNeg, RXPos, RYNeg, RYPos, L1, L2, L3, R1, R2, R3, Square, Triangle, Circle, Cross, DpadUp, DpadRight, DpadDown, DpadLeft, PS, TouchButton, TouchUpper, TouchMulti, Share, Options }; public enum DS4Controls : byte { LXNeg, LXPos, LYNeg, LYPos, RXNeg, RXPos, RYNeg, RYPos, L1, L2, L3, R1, R2, R3, Square, Triangle, Circle, Cross, DpadUp, DpadRight, DpadDown, DpadLeft, PS, TouchButton, TouchUpper, TouchMulti, Share, Options };
public enum X360Controls : byte { LXNeg, LXPos, LYNeg, LYPos, RXNeg, RXPos, RYNeg, RYPos, LB, LT, LS, RB, RT, RS, X, Y, B, A, DpadUp, DpadRight, DpadDown, DpadLeft, Guide, Back, Start, LeftMouse, RightMouse, MiddleMouse, Unbound, public enum X360Controls : byte { LXNeg, LXPos, LYNeg, LYPos, RXNeg, RXPos, RYNeg, RYPos, LB, LT, LS, RB, RT, RS, X, Y, B, A, DpadUp, DpadRight, DpadDown, DpadLeft, Guide, Back, Start, LeftMouse, RightMouse, MiddleMouse, Unbound };
MouseLeft, MouseRight, MouseDown, MouseUp};
public class DebugEventArgs : EventArgs public class DebugEventArgs : EventArgs
{ {
@ -82,6 +81,13 @@ namespace DS4Control
protected static BackingStore m_Config = new BackingStore(); protected static BackingStore m_Config = new BackingStore();
protected static Int32 m_IdleTimeout = 600000; protected static Int32 m_IdleTimeout = 600000;
public static event EventHandler<EventArgs> ControllerStatusChange; // called when a controller is added/removed/battery or touchpad mode changes/etc.
public static void ControllerStatusChanged(object sender)
{
if (ControllerStatusChange != null)
ControllerStatusChange(sender, EventArgs.Empty);
}
public static DS4Color loadColor(int device) public static DS4Color loadColor(int device)
{ {
DS4Color color = new DS4Color(); DS4Color color = new DS4Color();
@ -327,22 +333,12 @@ namespace DS4Control
byte bdif = (byte)(bmax - bmin); byte bdif = (byte)(bmax - bmin);
return (byte)(bmin + (bdif * ratio / 100)); return (byte)(bmin + (bdif * ratio / 100));
} }
public static DS4Color getTransitionedColor(byte[] c1, byte[] c2, uint ratio) public static DS4Color getTransitionedColor(DS4Color c1, DS4Color c2, uint ratio)
{ {;
DS4Color color = new DS4Color(); c1.red = applyRatio(c1.red, c2.red, ratio);
color.red = 255; c1.green = applyRatio(c1.green, c2.green, ratio);
color.green = 255; c1.blue = applyRatio(c1.blue, c2.blue, ratio);
color.blue = 255; return c1;
uint r = ratio % 101;
if (c1.Length != 3 || c2.Length != 3 || ratio < 0)
{
return color;
}
color.red = applyRatio(c1[0], c2[0], ratio);
color.green = applyRatio(c1[1], c2[1], ratio);
color.blue = applyRatio(c1[2], c2[2], ratio);
return color;
} }
} }
@ -655,10 +651,6 @@ namespace DS4Control
case "Click": return X360Controls.LeftMouse; case "Click": return X360Controls.LeftMouse;
case "Right Click": return X360Controls.RightMouse; case "Right Click": return X360Controls.RightMouse;
case "Middle Click": return X360Controls.MiddleMouse; case "Middle Click": return X360Controls.MiddleMouse;
case "Mouse Up": return X360Controls.MouseUp;
case "Mouse Down": return X360Controls.MouseDown;
case "Mouse Left": return X360Controls.MouseLeft;
case "Mouse Right": return X360Controls.MouseRight;
case "(Unbound)": return X360Controls.Unbound; case "(Unbound)": return X360Controls.Unbound;
} }

View File

@ -29,6 +29,7 @@ namespace DS4Control
device.Touchpad.TouchesBegan -= currentMode.touchesBegan; device.Touchpad.TouchesBegan -= currentMode.touchesBegan;
device.Touchpad.TouchesMoved -= currentMode.touchesMoved; device.Touchpad.TouchesMoved -= currentMode.touchesMoved;
device.Touchpad.TouchesEnded -= currentMode.touchesEnded; device.Touchpad.TouchesEnded -= currentMode.touchesEnded;
device.Touchpad.TouchUnchanged -= currentMode.touchUnchanged;
setMode(ind); setMode(ind);
} }
@ -40,9 +41,11 @@ namespace DS4Control
device.Touchpad.TouchesBegan += tmode.touchesBegan; device.Touchpad.TouchesBegan += tmode.touchesBegan;
device.Touchpad.TouchesMoved += tmode.touchesMoved; device.Touchpad.TouchesMoved += tmode.touchesMoved;
device.Touchpad.TouchesEnded += tmode.touchesEnded; device.Touchpad.TouchesEnded += tmode.touchesEnded;
device.Touchpad.TouchUnchanged += tmode.touchUnchanged;
currentTypeInd = ind; currentTypeInd = ind;
LogDebug("Touchpad mode for " + device.MacAddress + " is now " + tmode.ToString()); LogDebug("Touchpad mode for " + device.MacAddress + " is now " + tmode.ToString());
Log.LogToTray("Touchpad mode for " + device.MacAddress + " is now " + tmode.ToString()); Log.LogToTray("Touchpad mode for " + device.MacAddress + " is now " + tmode.ToString());
Global.ControllerStatusChanged(this);
} }
public override string ToString() public override string ToString()

View File

@ -25,6 +25,6 @@ namespace DS4Control
public void touchButtonDown(object sender, TouchpadEventArgs arg) { } public void touchButtonDown(object sender, TouchpadEventArgs arg) { }
public void untouched(object sender, TouchpadEventArgs nullUnused) { } public void touchUnchanged(object sender, EventArgs unused) { }
} }
} }

View File

@ -23,7 +23,28 @@ namespace DS4Library
public byte blue; public byte blue;
} }
public enum ConnectionType : byte { USB, BT }; public enum ConnectionType : byte { BT, USB }; // Prioritize Bluetooth when both are connected.
/**
* The haptics engine uses a stack of these states representing the light bar and rumble motor settings.
* It (will) handle composing them and the details of output report management.
*/
public struct DS4HapticState
{
public DS4Color LightBarColor;
public bool LightBarExplicitlyOff;
public byte LightBarFlashDurationOn, LightBarFlashDurationOff;
public byte RumbleMotorStrengthLeftHeavySlow, RumbleMotorStrengthRightLightFast;
public bool RumbleMotorsExplicitlyOff;
public bool IsLightBarSet()
{
return LightBarExplicitlyOff || LightBarColor.red != 0 || LightBarColor.green != 0 || LightBarColor.blue != 0;
}
public bool IsRumbleSet()
{
return RumbleMotorsExplicitlyOff || RumbleMotorStrengthLeftHeavySlow != 0 || RumbleMotorStrengthRightLightFast != 0;
}
}
public class DS4Device public class DS4Device
{ {
@ -36,31 +57,30 @@ namespace DS4Library
private ConnectionType conType; private ConnectionType conType;
private byte[] accel = new byte[6]; private byte[] accel = new byte[6];
private byte[] gyro = new byte[6]; private byte[] gyro = new byte[6];
private byte[] inputReport = new byte[64]; private byte[] inputReport;
private byte[] btInputReport = null; private byte[] btInputReport = null;
private byte[] outputReport = null; private byte[] outputReportBuffer, outputReport;
private readonly DS4Touchpad touchpad = null; private readonly DS4Touchpad touchpad = null;
private byte rightLightFastRumble; private byte rightLightFastRumble;
private byte leftHeavySlowRumble; private byte leftHeavySlowRumble;
private DS4Color ligtBarColor; private DS4Color ligtBarColor;
private byte ledFlashOn, ledFlashOff; private byte ledFlashOn, ledFlashOff;
private bool isDirty = false; private Thread ds4Input, ds4Output;
private Thread updaterThread = null;
private int battery; private int battery;
private int idleTimeout = 1200; private bool charging;
private DateTime lastActive = DateTime.Now;
public event EventHandler<EventArgs> Report = null; public event EventHandler<EventArgs> Report = null;
public event EventHandler<EventArgs> Removal = null; public event EventHandler<EventArgs> Removal = null;
public int IdleTimeout { get { return idleTimeout; }
set { idleTimeout = value; } }
public HidDevice HidDevice { get { return hDevice; } } public HidDevice HidDevice { get { return hDevice; } }
public bool IsExclusive { get { return HidDevice.IsExclusive; } }
public bool IsDisconnecting { get; private set; }
public string MacAddress { get { return Mac; } } public string MacAddress { get { return Mac; } }
public ConnectionType ConnectionType { get { return conType; } } public ConnectionType ConnectionType { get { return conType; } }
public int Battery { get { return battery; } } public int Battery { get { return battery; } }
public bool Charging { get { return charging; } }
public byte RightLightFastRumble public byte RightLightFastRumble
{ {
@ -69,7 +89,6 @@ namespace DS4Library
{ {
if (value == rightLightFastRumble) return; if (value == rightLightFastRumble) return;
rightLightFastRumble = value; rightLightFastRumble = value;
isDirty = true;
} }
} }
@ -80,7 +99,6 @@ namespace DS4Library
{ {
if (value == leftHeavySlowRumble) return; if (value == leftHeavySlowRumble) return;
leftHeavySlowRumble = value; leftHeavySlowRumble = value;
isDirty = true;
} }
} }
@ -92,7 +110,6 @@ namespace DS4Library
if (ligtBarColor.red != value.red || ligtBarColor.green != value.green || ligtBarColor.blue != value.blue) if (ligtBarColor.red != value.red || ligtBarColor.green != value.green || ligtBarColor.blue != value.blue)
{ {
ligtBarColor = value; ligtBarColor = value;
isDirty = true;
} }
} }
} }
@ -105,7 +122,6 @@ namespace DS4Library
if (ledFlashOn != value) if (ledFlashOn != value)
{ {
ledFlashOn = value; ledFlashOn = value;
isDirty = true;
} }
} }
} }
@ -118,41 +134,51 @@ namespace DS4Library
if (ledFlashOff != value) if (ledFlashOff != value)
{ {
ledFlashOff = value; ledFlashOff = value;
isDirty = true;
} }
} }
} }
public DS4Touchpad Touchpad { get { return touchpad; } } public DS4Touchpad Touchpad { get { return touchpad; } }
public static ConnectionType HidConnectionType(HidDevice hidDevice)
{
return hidDevice.Capabilities.InputReportByteLength == 64 ? ConnectionType.USB : ConnectionType.BT;
}
public DS4Device(HidDevice hidDevice) public DS4Device(HidDevice hidDevice)
{ {
hDevice = hidDevice; hDevice = hidDevice;
hDevice.MonitorDeviceEvents = true; hDevice.MonitorDeviceEvents = true;
conType = hDevice.Capabilities.InputReportByteLength == 64 ? ConnectionType.USB : ConnectionType.BT; conType = HidConnectionType(hDevice);
Mac = hDevice.readSerial(); Mac = hDevice.readSerial();
if (conType == ConnectionType.USB) if (conType == ConnectionType.USB)
{ {
inputReport = new byte[64];
outputReport = new byte[hDevice.Capabilities.OutputReportByteLength]; outputReport = new byte[hDevice.Capabilities.OutputReportByteLength];
outputReportBuffer = new byte[hDevice.Capabilities.OutputReportByteLength];
} }
else else
{ {
btInputReport = new byte[BT_INPUT_REPORT_LENGTH]; btInputReport = new byte[BT_INPUT_REPORT_LENGTH];
inputReport = new byte[btInputReport.Length - 2];
outputReport = new byte[BT_OUTPUT_REPORT_LENGTH]; outputReport = new byte[BT_OUTPUT_REPORT_LENGTH];
outputReportBuffer = new byte[BT_OUTPUT_REPORT_LENGTH];
} }
touchpad = new DS4Touchpad(); touchpad = new DS4Touchpad();
isDirty = true;
sendOutputReport();
} }
public void StartUpdate() public void StartUpdate()
{ {
if (updaterThread == null) if (ds4Input == null)
{ {
updaterThread = new Thread(updateCurrentState); Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> start");
updaterThread.Name = "DS4 Update thread :" + Mac; sendOutputReport(true); // request the particular kind of input report we want
Console.WriteLine(updaterThread.Name + " has started"); ds4Output = new Thread(performDs4Output);
updaterThread.Start(); ds4Output.Name = "DS4 Output thread: " + Mac;
ds4Output.Start();
ds4Input = new Thread(performDs4Input);
ds4Input.Name = "DS4 Input thread: " + Mac;
ds4Input.Start();
} }
else else
Console.WriteLine("Thread already running for DS4: " + Mac); Console.WriteLine("Thread already running for DS4: " + Mac);
@ -160,12 +186,29 @@ namespace DS4Library
public void StopUpdate() public void StopUpdate()
{ {
if (updaterThread.ThreadState != System.Threading.ThreadState.Stopped || updaterThread.ThreadState != System.Threading.ThreadState.Aborted) if (ds4Input.ThreadState != System.Threading.ThreadState.Stopped || ds4Input.ThreadState != System.Threading.ThreadState.Aborted)
{ {
try try
{ {
updaterThread.Abort(); ds4Input.Abort();
updaterThread = null; ds4Input.Join();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
StopOutputUpdate();
}
private void StopOutputUpdate()
{
if (ds4Output.ThreadState != System.Threading.ThreadState.Stopped || ds4Output.ThreadState != System.Threading.ThreadState.Aborted)
{
try
{
ds4Output.Abort();
ds4Output.Join();
} }
catch (Exception e) catch (Exception e)
{ {
@ -174,177 +217,225 @@ namespace DS4Library
} }
} }
private void updateCurrentState() private bool writeOutput()
{
if (conType == ConnectionType.BT)
{
return hDevice.WriteOutputReportViaControl(outputReport);
}
else
{
return hDevice.WriteOutputReportViaInterrupt(outputReport, 8);
}
}
private void performDs4Output()
{
lock (outputReport)
{
while (writeOutput())
{
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);
}
}
}
/** Is the device alive and receiving valid sensor input reports? */
public bool IsAlive()
{
return priorInputReport30 != 0xff;
}
private byte priorInputReport30 = 0xff;
private void performDs4Input()
{ {
while (true) while (true)
{ {
if (conType != ConnectionType.USB) if (conType != ConnectionType.USB)
if (hDevice.ReadFile(btInputReport) == HidDevice.ReadStatus.Success) if (hDevice.ReadFile(btInputReport) == HidDevice.ReadStatus.Success)
{ {
Array.Copy(btInputReport, 2, inputReport, 0, 64); Array.Copy(btInputReport, 2, inputReport, 0, inputReport.Length);
} }
else else
{ {
isDirty = true; Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> disconnect");
sendOutputReport(); // not sure why but without this Windows sendOutputReport(true); // Kick Windows into noticing the disconnection.
//will not mark timed out controller as disonnected StopOutputUpdate();
if (Removal != null) if (!IsDisconnecting && Removal != null)
Removal(this, EventArgs.Empty); Removal(this, EventArgs.Empty);
return; return;
} }
else if (hDevice.ReadFile(inputReport) != HidDevice.ReadStatus.Success) else if (hDevice.ReadFile(inputReport) != HidDevice.ReadStatus.Success)
{ {
if (Removal != null) StopOutputUpdate();
if (!IsDisconnecting && Removal != null)
Removal(this, EventArgs.Empty); Removal(this, EventArgs.Empty);
return; return;
} }
if (ConnectionType == ConnectionType.BT && btInputReport[0] != 0x11) if (ConnectionType == ConnectionType.BT && btInputReport[0] != 0x11)
{
//Received incorrect report, skip it
continue;
}
DateTime utcNow = System.DateTime.UtcNow; // timestamp with UTC in case system time zone changes
resetHapticState();
if (cState == null)
cState = new DS4State();
cState.ReportTimeStamp = utcNow;
cState.LX = inputReport[1];
cState.LY = inputReport[2];
cState.RX = inputReport[3];
cState.RY = inputReport[4];
cState.L2 = inputReport[8];
cState.R2 = inputReport[9];
cState.Triangle = ((byte)inputReport[5] & (1 << 7)) != 0;
cState.Circle = ((byte)inputReport[5] & (1 << 6)) != 0;
cState.Cross = ((byte)inputReport[5] & (1 << 5)) != 0;
cState.Square = ((byte)inputReport[5] & (1 << 4)) != 0;
cState.DpadUp = ((byte)inputReport[5] & (1 << 3)) != 0;
cState.DpadDown = ((byte)inputReport[5] & (1 << 2)) != 0;
cState.DpadLeft = ((byte)inputReport[5] & (1 << 1)) != 0;
cState.DpadRight = ((byte)inputReport[5] & (1 << 0)) != 0;
//Convert dpad into individual On/Off bits instead of a clock representation
byte dpad_state = 0;
dpad_state = (byte)(
((cState.DpadRight ? 1 : 0) << 0) |
((cState.DpadLeft ? 1 : 0) << 1) |
((cState.DpadDown ? 1 : 0) << 2) |
((cState.DpadUp ? 1 : 0) << 3));
switch (dpad_state)
{ {
//Received incorrect report, skip it case 0: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = false; break;
continue; case 1: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = true; break;
case 2: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = true; break;
case 3: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = false; cState.DpadRight = true; break;
case 4: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = false; cState.DpadRight = false; break;
case 5: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = true; cState.DpadRight = false; break;
case 6: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = true; cState.DpadRight = false; break;
case 7: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = true; cState.DpadRight = false; break;
case 8: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = false; break;
} }
lock (cState) cState.R3 = ((byte)inputReport[6] & (1 << 7)) != 0;
cState.L3 = ((byte)inputReport[6] & (1 << 6)) != 0;
cState.Options = ((byte)inputReport[6] & (1 << 5)) != 0;
cState.Share = ((byte)inputReport[6] & (1 << 4)) != 0;
cState.R1 = ((byte)inputReport[6] & (1 << 1)) != 0;
cState.L1 = ((byte)inputReport[6] & (1 << 0)) != 0;
cState.PS = ((byte)inputReport[7] & (1 << 0)) != 0;
cState.TouchButton = (inputReport[7] & (1 << 2 - 1)) != 0;
cState.FrameCounter = (byte)(inputReport[7] >> 2);
// Store Gyro and Accel values
Array.Copy(inputReport, 14, accel, 0, 6);
Array.Copy(inputReport, 20, gyro, 0, 6);
charging = (inputReport[30] & 0x10) != 0;
battery = (inputReport[30] & 0x0f) * 10;
cState.Battery = (byte)battery;
if (inputReport[30] != priorInputReport30)
{ {
if (cState == null) priorInputReport30 = inputReport[30];
cState = new DS4State(); Console.WriteLine(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + "> power subsystem octet: 0x" + inputReport[30].ToString("x02"));
cState.LX = inputReport[1];
cState.LY = inputReport[2];
cState.RX = inputReport[3];
cState.RY = inputReport[4];
cState.L2 = inputReport[8];
cState.R2 = inputReport[9];
cState.Triangle = ((byte)inputReport[5] & (1 << 7)) != 0;
cState.Circle = ((byte)inputReport[5] & (1 << 6)) != 0;
cState.Cross = ((byte)inputReport[5] & (1 << 5)) != 0;
cState.Square = ((byte)inputReport[5] & (1 << 4)) != 0;
cState.DpadUp = ((byte)inputReport[5] & (1 << 3)) != 0;
cState.DpadDown = ((byte)inputReport[5] & (1 << 2)) != 0;
cState.DpadLeft = ((byte)inputReport[5] & (1 << 1)) != 0;
cState.DpadRight = ((byte)inputReport[5] & (1 << 0)) != 0;
//Convert dpad into individual On/Off bits instead of a clock representation
byte dpad_state = 0;
dpad_state = (byte)(
((cState.DpadRight ? 1 : 0) << 0) |
((cState.DpadLeft ? 1 : 0) << 1) |
((cState.DpadDown ? 1 : 0) << 2) |
((cState.DpadUp ? 1 : 0) << 3));
switch (dpad_state)
{
case 0: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = false; break;
case 1: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = true; break;
case 2: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = true; break;
case 3: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = false; cState.DpadRight = true; break;
case 4: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = false; cState.DpadRight = false; break;
case 5: cState.DpadUp = false; cState.DpadDown = true; cState.DpadLeft = true; cState.DpadRight = false; break;
case 6: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = true; cState.DpadRight = false; break;
case 7: cState.DpadUp = true; cState.DpadDown = false; cState.DpadLeft = true; cState.DpadRight = false; break;
case 8: cState.DpadUp = false; cState.DpadDown = false; cState.DpadLeft = false; cState.DpadRight = false; break;
}
cState.R3 = ((byte)inputReport[6] & (1 << 7)) != 0;
cState.L3 = ((byte)inputReport[6] & (1 << 6)) != 0;
cState.Options = ((byte)inputReport[6] & (1 << 5)) != 0;
cState.Share = ((byte)inputReport[6] & (1 << 4)) != 0;
cState.R1 = ((byte)inputReport[6] & (1 << 1)) != 0;
cState.L1 = ((byte)inputReport[6] & (1 << 0)) != 0;
cState.PS = ((byte)inputReport[7] & (1 << 0)) != 0;
cState.TouchButton = (inputReport[7] & (1 << 2 - 1)) != 0;
// Store Gyro and Accel values
Array.Copy(inputReport, 14, accel, 0, 6);
Array.Copy(inputReport, 20, gyro, 0, 6);
int charge = 0;
if (conType == ConnectionType.USB)
{
charge = (inputReport[30] - 16) * 10;
if (charge > 100)
charge = 100;
}
else
{
charge = (inputReport[30] + 1) * 10;
if (charge > 100)
charge = 100;
}
cState.Battery = charge;
battery = charge;
cState.Touch1 = (inputReport[0 + DS4Touchpad.TOUCHPAD_DATA_OFFSET] >> 7) != 0 ? false : true; // >= 1 touch detected
cState.Touch2 = (inputReport[4 + DS4Touchpad.TOUCHPAD_DATA_OFFSET] >> 7) != 0 ? false : true; // 2 touches detected
cState.ReportTimeStamp = DateTime.UtcNow;
}
if (ConnectionType == ConnectionType.BT && !isIdle(cState))
{
lastActive = DateTime.Now;
}
if (ConnectionType == ConnectionType.BT && lastActive + TimeSpan.FromSeconds(idleTimeout) < DateTime.Now)
{
DisconnectBT();
} }
touchpad.handleTouchpad(inputReport, cState); // XXX DS4State mapping needs fixup, turn touches into an array[4] of structs. And include the touchpad details there instead.
for (int touches = inputReport[-1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET - 1], touchOffset = 0; touches > 0; touches--, touchOffset += 9)
sendOutputReport();
if ((!pState.PS || !pState.Options) && cState.PS && cState.Options)
{ {
DisconnectBT(); cState.TouchPacketCounter = inputReport[-1 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset];
cState.Touch1 = (inputReport[0 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] >> 7) != 0 ? false : true; // >= 1 touch detected
cState.Touch1Identifier = (byte)(inputReport[0 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0x7f);
cState.Touch2 = (inputReport[4 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] >> 7) != 0 ? false : true; // 2 touches detected
cState.Touch2Identifier = (byte)(inputReport[4 + DS4Touchpad.TOUCHPAD_DATA_OFFSET + touchOffset] & 0x7f);
// Even when idling there is still a touch packet indicating no touch 1 or 2
touchpad.handleTouchpad(inputReport, cState, touchOffset);
} }
/* Debug output of incoming HID data:
if (cState.L2 == 0xff && cState.R2 == 0xff)
{
Console.Write(MacAddress.ToString() + " " + System.DateTime.UtcNow.ToString("o") + ">");
for (int i = 0; i < inputReport.Length; i++)
Console.Write(" " + inputReport[i].ToString("x2"));
Console.WriteLine();
} */
if (conType == ConnectionType.BT && (!pState.PS || !pState.Options) && cState.PS && cState.Options)
{
if (DisconnectBT())
return; // all done
}
// XXX fix initialization ordering so the null checks all go away
if (Report != null) if (Report != null)
Report(this, EventArgs.Empty); Report(this, EventArgs.Empty);
lock (pState) sendOutputReport(false);
{
if (pState == null) if (pState == null)
pState = new DS4State(); pState = new DS4State();
cState.Copy(pState); cState.Copy(pState);
}
} }
} }
private void sendOutputReport() private void sendOutputReport(bool synchronous)
{ {
if (isDirty) setTestRumble();
setHapticState();
if (conType == ConnectionType.BT)
{ {
if (conType == ConnectionType.BT) outputReportBuffer[0] = 0x11;
outputReportBuffer[1] = 0x80;
outputReportBuffer[3] = 0xff;
outputReportBuffer[6] = rightLightFastRumble; //fast motor
outputReportBuffer[7] = leftHeavySlowRumble; //slow motor
outputReportBuffer[8] = LightBarColor.red; //red
outputReportBuffer[9] = LightBarColor.green; //green
outputReportBuffer[10] = LightBarColor.blue; //blue
outputReportBuffer[11] = ledFlashOn; //flash on duration
outputReportBuffer[12] = ledFlashOff; //flash off duration
}
else
{
outputReportBuffer[0] = 0x05;
outputReportBuffer[1] = 0xff;
outputReportBuffer[4] = rightLightFastRumble; //fast motor
outputReportBuffer[5] = leftHeavySlowRumble; //slow motor
outputReportBuffer[6] = LightBarColor.red; //red
outputReportBuffer[7] = LightBarColor.green; //green
outputReportBuffer[8] = LightBarColor.blue; //blue
outputReportBuffer[9] = ledFlashOn; //flash on duration
outputReportBuffer[10] = ledFlashOff; //flash off duration
}
lock (outputReport)
{
if (synchronous)
{ {
outputReport[0] = 0x11; outputReportBuffer.CopyTo(outputReport, 0);
outputReport[1] = 128; try
outputReport[3] = 0xff; {
outputReport[6] = rightLightFastRumble; //fast motor writeOutput();
outputReport[7] = leftHeavySlowRumble; //slow motor }
outputReport[8] = LightBarColor.red; //red catch
outputReport[9] = LightBarColor.green; //green {
outputReport[10] = LightBarColor.blue; //blue // If it's dead already, don't worry about it.
outputReport[11] = ledFlashOn; //flash on duration }
outputReport[12] = ledFlashOff; //flash off duration
if (hDevice.WriteOutputReportViaControl(outputReport))
isDirty = false;
} }
else else
{ {
outputReport[0] = 0x5; bool output = false;
outputReport[1] = 0xFF; for (int i = 0; !output && i < outputReport.Length; i++)
outputReport[4] = rightLightFastRumble; //fast motor output = outputReport[i] != outputReportBuffer[i];
outputReport[5] = leftHeavySlowRumble; //slow motor if (output)
outputReport[6] = LightBarColor.red; //red
outputReport[7] = LightBarColor.green; //green
outputReport[8] = LightBarColor.blue; //blue
outputReport[9] = ledFlashOn; //flash on duration
outputReport[10] = ledFlashOff; //flash off duration
if (hDevice.WriteOutputReportViaInterrupt(outputReport))
{ {
isDirty = false; outputReportBuffer.CopyTo(outputReport, 0);
Monitor.Pulse(outputReport);
} }
} }
} }
@ -367,7 +458,6 @@ namespace DS4Library
} }
long lbtAddr = BitConverter.ToInt64(btAddr, 0); long lbtAddr = BitConverter.ToInt64(btAddr, 0);
NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS p = new NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS(); NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS p = new NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS();
p.dwSize = Marshal.SizeOf(typeof(NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS)); p.dwSize = Marshal.SizeOf(typeof(NativeMethods.BLUETOOTH_FIND_RADIO_PARAMS));
IntPtr searchHandle = NativeMethods.BluetoothFindFirstRadio(ref p, ref btHandle); IntPtr searchHandle = NativeMethods.BluetoothFindFirstRadio(ref p, ref btHandle);
@ -383,52 +473,46 @@ namespace DS4Library
} }
NativeMethods.BluetoothFindRadioClose(searchHandle); NativeMethods.BluetoothFindRadioClose(searchHandle);
Console.WriteLine("Disconnect successul: " + success); Console.WriteLine("Disconnect successful: " + success);
success = true; // XXX return value indicates failure, but it still works?
if(success) if(success)
{
IsDisconnecting = true;
StopOutputUpdate();
if (Removal != null) if (Removal != null)
Removal(this, EventArgs.Empty); Removal(this, EventArgs.Empty);
}
return success; return success;
} }
return false; return false;
} }
public void setLightbarColor(byte red, byte green, byte blue) private DS4HapticState testRumble = new DS4HapticState();
{
if (red != ligtBarColor.red || green != ligtBarColor.green || blue != ligtBarColor.blue)
{
isDirty = true;
ligtBarColor.red = red;
ligtBarColor.green = green;
ligtBarColor.blue = blue;
}
}
public void setLightbarDuration(byte onDuration, byte offDuration)
{
LightBarOffDuration = offDuration;
LightBarOnDuration = onDuration;
}
public void setRumble(byte rightLightFastMotor, byte leftHeavySlowMotor) public void setRumble(byte rightLightFastMotor, byte leftHeavySlowMotor)
{ {
RightLightFastRumble = rightLightFastMotor; testRumble.RumbleMotorStrengthRightLightFast = rightLightFastMotor;
LeftHeavySlowRumble = leftHeavySlowMotor; testRumble.RumbleMotorStrengthLeftHeavySlow = leftHeavySlowMotor;
testRumble.RumbleMotorsExplicitlyOff = rightLightFastMotor == 0 && leftHeavySlowMotor == 0;
}
private void setTestRumble()
{
if (testRumble.IsRumbleSet())
{
pushHapticState(testRumble);
if (testRumble.RumbleMotorsExplicitlyOff)
testRumble.RumbleMotorsExplicitlyOff = false;
}
} }
public DS4State getCurrentState() public DS4State getCurrentState()
{ {
lock (cState) return cState.Clone();
{
return cState.Clone();
}
} }
public DS4State getPreviousState() public DS4State getPreviousState()
{ {
lock (pState) return pState.Clone();
{
return pState.Clone();
}
} }
public void getExposedState(DS4StateExposed expState, DS4State state) public void getExposedState(DS4StateExposed expState, DS4State state)
@ -440,37 +524,60 @@ namespace DS4Library
public void getCurrentState(DS4State state) public void getCurrentState(DS4State state)
{ {
lock (cState) cState.Copy(state);
{
cState.Copy(state);
}
} }
public void getPreviousState(DS4State state) public void getPreviousState(DS4State state)
{ {
lock (pState) pState.Copy(state);
{
pState.Copy(state);
}
} }
private bool isIdle(DS4State cState) private DS4HapticState[] hapticState = new DS4HapticState[1];
private int hapticStackIndex = 0;
private void resetHapticState()
{ {
if (cState.Square || cState.Cross || cState.Circle || cState.Triangle) hapticStackIndex = 0;
return false; }
if (cState.DpadUp || cState.DpadLeft || cState.DpadDown || cState.DpadRight)
return false; // Use the "most recently set" haptic state for each of light bar/motor.
if (cState.L3 || cState.R3 || cState.L1 || cState.R1 || cState.Share || cState.Options) private void setHapticState()
return false; {
if (cState.L2 != 0 || cState.R2 != 0) int i = 0;
return false; DS4Color lightBarColor = LightBarColor;
if (Math.Abs(cState.LX - 127) > 10 || (Math.Abs(cState.LY - 127) > 10 )) byte lightBarFlashDurationOn = LightBarOnDuration, lightBarFlashDurationOff = LightBarOffDuration;
return false; byte rumbleMotorStrengthLeftHeavySlow = LeftHeavySlowRumble, rumbleMotorStrengthRightLightFast = rightLightFastRumble;
if (Math.Abs(cState.RX - 127) > 10 || (Math.Abs(cState.RY - 127) > 10)) foreach (DS4HapticState haptic in hapticState)
return false; {
if (cState.Touch1 || cState.Touch2 || cState.TouchButton) if (i++ == hapticStackIndex)
return false; break; // rest haven't been used this time
return true; if (haptic.IsLightBarSet())
{
lightBarColor = haptic.LightBarColor;
lightBarFlashDurationOn = haptic.LightBarFlashDurationOn;
lightBarFlashDurationOff = haptic.LightBarFlashDurationOff;
}
if (haptic.IsRumbleSet())
{
rumbleMotorStrengthLeftHeavySlow = haptic.RumbleMotorStrengthLeftHeavySlow;
rumbleMotorStrengthRightLightFast = haptic.RumbleMotorStrengthRightLightFast;
}
}
LightBarColor = lightBarColor;
LightBarOnDuration = lightBarFlashDurationOn;
LightBarOffDuration = lightBarFlashDurationOff;
LeftHeavySlowRumble = rumbleMotorStrengthLeftHeavySlow;
RightLightFastRumble = rumbleMotorStrengthRightLightFast;
}
public void pushHapticState(DS4HapticState hs)
{
if (hapticStackIndex == hapticState.Length)
{
DS4HapticState[] newHaptics = new DS4HapticState[hapticState.Length + 1];
Array.Copy(hapticState, newHaptics, hapticState.Length);
hapticState = newHaptics;
}
hapticState[hapticStackIndex++] = hs;
} }
override override

View File

@ -8,6 +8,7 @@ namespace DS4Library
public class DS4Devices public class DS4Devices
{ {
private static Dictionary<string, DS4Device> Devices = new Dictionary<string, DS4Device>(); private static Dictionary<string, DS4Device> Devices = new Dictionary<string, DS4Device>();
private static HashSet<String> DevicePaths = new HashSet<String>();
public static bool isExclusiveMode = false; public static bool isExclusiveMode = false;
//enumerates ds4 controllers in the system //enumerates ds4 controllers in the system
@ -17,30 +18,33 @@ namespace DS4Library
{ {
int[] pid = { 0x5C4 }; int[] pid = { 0x5C4 };
IEnumerable<HidDevice> hDevices = HidDevices.Enumerate(0x054C, pid); IEnumerable<HidDevice> hDevices = HidDevices.Enumerate(0x054C, pid);
// Sort Bluetooth first in case USB is also connected on the same controller.
hDevices = hDevices.OrderBy<HidDevice, ConnectionType>((HidDevice d) => { return DS4Device.HidConnectionType(d); });
foreach (HidDevice hDevice in hDevices) foreach (HidDevice hDevice in hDevices)
{ {
if (DevicePaths.Contains(hDevice.DevicePath))
continue; // BT/USB endpoint already open once
if (!hDevice.IsOpen) if (!hDevice.IsOpen)
{
hDevice.OpenDevice(isExclusiveMode); hDevice.OpenDevice(isExclusiveMode);
// TODO in exclusive mode, try to hold both open when both are connected
if (isExclusiveMode && !hDevice.IsOpen)
hDevice.OpenDevice(false);
}
if (hDevice.IsOpen) if (hDevice.IsOpen)
{ {
byte[] buffer = new byte[38];
buffer[0] = 0x2;
hDevice.readFeatureData(buffer);
if (Devices.ContainsKey(hDevice.readSerial())) if (Devices.ContainsKey(hDevice.readSerial()))
continue; continue; // happens when the BT endpoint already is open and the USB is plugged into the same host
else else
{ {
DS4Device ds4Device = new DS4Device(hDevice); DS4Device ds4Device = new DS4Device(hDevice);
ds4Device.StartUpdate();
ds4Device.Removal += On_Removal; ds4Device.Removal += On_Removal;
Devices.Add(ds4Device.MacAddress, ds4Device); Devices.Add(ds4Device.MacAddress, ds4Device);
DevicePaths.Add(hDevice.DevicePath);
ds4Device.StartUpdate();
} }
} }
else
{
throw new Exception("ERROR: Can't open DS4 Controller. Try quitting other applications like Steam, Uplay, etc.)");
}
} }
} }
@ -49,31 +53,43 @@ namespace DS4Library
//allows to get DS4Device by specifying unique MAC address //allows to get DS4Device by specifying unique MAC address
//format for MAC address is XX:XX:XX:XX:XX:XX //format for MAC address is XX:XX:XX:XX:XX:XX
public static DS4Device getDS4Controller(string mac) public static DS4Device getDS4Controller(string mac)
{ {
DS4Device device = null; lock (Devices)
try
{ {
Devices.TryGetValue(mac, out device); DS4Device device = null;
try
{
Devices.TryGetValue(mac, out device);
}
catch (ArgumentNullException) { }
return device;
} }
catch (ArgumentNullException) { }
return device;
} }
//returns DS4 controllers that were found and are running //returns DS4 controllers that were found and are running
public static IEnumerable<DS4Device> getDS4Controllers() public static IEnumerable<DS4Device> getDS4Controllers()
{ {
return Devices.Values; lock (Devices)
{
DS4Device[] controllers = new DS4Device[Devices.Count];
Devices.Values.CopyTo(controllers, 0);
return controllers;
}
} }
public static void stopControllers() public static void stopControllers()
{ {
IEnumerable<DS4Device> devices = getDS4Controllers(); lock (Devices)
foreach (DS4Device device in devices)
{ {
device.StopUpdate(); IEnumerable<DS4Device> devices = getDS4Controllers();
device.HidDevice.CloseDevice(); foreach (DS4Device device in devices)
{
device.StopUpdate();
device.HidDevice.CloseDevice();
}
Devices.Clear();
DevicePaths.Clear();
} }
Devices.Clear();
} }
//called when devices is diconnected, timed out or has input reading failure //called when devices is diconnected, timed out or has input reading failure
@ -84,6 +100,7 @@ namespace DS4Library
DS4Device device = (DS4Device)sender; DS4Device device = (DS4Device)sender;
device.HidDevice.CloseDevice(); device.HidDevice.CloseDevice();
Devices.Remove(device.MacAddress); Devices.Remove(device.MacAddress);
DevicePaths.Remove(device.HidDevice.DevicePath);
} }
} }
} }

View File

@ -7,27 +7,33 @@ namespace DS4Library
{ {
public class DS4State public class DS4State
{ {
public DateTime ReportTimeStamp;
public bool Square, Triangle, Circle, Cross; public bool Square, Triangle, Circle, Cross;
public bool DpadUp, DpadDown, DpadLeft, DpadRight; public bool DpadUp, DpadDown, DpadLeft, DpadRight;
public bool L1, L3, R1, R3; public bool L1, L3, R1, R3;
public bool Share, Options, PS, Touch1, Touch2, TouchButton; public bool Share, Options, PS, Touch1, Touch2, TouchButton;
public byte Touch1Identifier, Touch2Identifier;
public byte LX, RX, LY, RY, L2, R2; public byte LX, RX, LY, RY, L2, R2;
public int Battery; public byte FrameCounter; // 0, 1, 2...62, 63, 0....
public DateTime ReportTimeStamp; public byte TouchPacketCounter; // we break these out automatically
public byte Battery; // 0 for charging, 10/20/30/40/50/60/70/80/90/100 for percentage of full
public DS4State() public DS4State()
{ {
ReportTimeStamp = DateTime.UtcNow;
Square = Triangle = Circle = Cross = false; Square = Triangle = Circle = Cross = false;
DpadUp = DpadDown = DpadLeft = DpadRight = false; DpadUp = DpadDown = DpadLeft = DpadRight = false;
L1 = L3 = R1 = R3 = false; L1 = L3 = R1 = R3 = false;
Share = Options = PS = Touch1 = Touch2 = TouchButton = false; Share = Options = PS = Touch1 = Touch2 = TouchButton = false;
LX = RX = LY = RY = 127; LX = RX = LY = RY = 127;
L2 = R2 = 0; L2 = R2 = 0;
FrameCounter = 255; // only actually has 6 bits, so this is a null indicator
TouchPacketCounter = 255; // 8 bits, no great junk value
Battery = 0; Battery = 0;
} }
public DS4State(DS4State state) public DS4State(DS4State state)
{ {
ReportTimeStamp = state.ReportTimeStamp;
Square = state.Square; Square = state.Square;
Triangle = state.Triangle; Triangle = state.Triangle;
Circle = state.Circle; Circle = state.Circle;
@ -46,14 +52,17 @@ namespace DS4Library
Options = state.Options; Options = state.Options;
PS = state.PS; PS = state.PS;
Touch1 = state.Touch1; Touch1 = state.Touch1;
Touch1Identifier = state.Touch1Identifier;
Touch2 = state.Touch2; Touch2 = state.Touch2;
Touch2Identifier = state.Touch2Identifier;
TouchButton = state.TouchButton; TouchButton = state.TouchButton;
TouchPacketCounter = state.TouchPacketCounter;
LX = state.LX; LX = state.LX;
RX = state.RX; RX = state.RX;
LY = state.LY; LY = state.LY;
RY = state.RY; RY = state.RY;
FrameCounter = state.FrameCounter;
Battery = state.Battery; Battery = state.Battery;
ReportTimeStamp = state.ReportTimeStamp;
} }
public DS4State Clone() public DS4State Clone()
@ -63,6 +72,7 @@ namespace DS4Library
public void Copy(DS4State state) public void Copy(DS4State state)
{ {
state.ReportTimeStamp = ReportTimeStamp;
state.Square = Square; state.Square = Square;
state.Triangle = Triangle; state.Triangle = Triangle;
state.Circle = Circle; state.Circle = Circle;
@ -81,14 +91,17 @@ namespace DS4Library
state.Options = Options; state.Options = Options;
state.PS = PS; state.PS = PS;
state.Touch1 = Touch1; state.Touch1 = Touch1;
state.Touch1Identifier = Touch1Identifier;
state.Touch2 = Touch2; state.Touch2 = Touch2;
state.Touch2Identifier = Touch2Identifier;
state.TouchButton = TouchButton; state.TouchButton = TouchButton;
state.TouchPacketCounter = TouchPacketCounter;
state.LX = LX; state.LX = LX;
state.RX = RX; state.RX = RX;
state.LY = LY; state.LY = LY;
state.RY = RY; state.RY = RY;
state.FrameCounter = FrameCounter;
state.Battery = Battery; state.Battery = Battery;
state.ReportTimeStamp = ReportTimeStamp;
} }
} }

View File

@ -53,21 +53,21 @@ namespace DS4Library
/// <summary> Pitch upward/backward </summary> /// <summary> Pitch upward/backward </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks> /// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int AccelX { get { return (UInt16)(accel[0] << 8) | accel[1]; } } public int AccelX { get { return (Int16)((UInt16)(accel[0] << 8) | accel[1]); } }
/// <summary> Yaw leftward/counter-clockwise/turn to port or larboard side </summary> /// <summary> Yaw leftward/counter-clockwise/turn to port or larboard side </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks> /// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int AccelY { get { return (UInt16)(accel[2] << 8) | accel[3]; } } public int AccelY { get { return (Int16)((UInt16)(accel[2] << 8) | accel[3]); } }
/// <summary> roll left/L side of controller down/starboard raising up </summary> /// <summary> roll left/L side of controller down/starboard raising up </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks> /// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int AccelZ { get { return (UInt16)(accel[4] << 8) | accel[5]; } } public int AccelZ { get { return (Int16)((UInt16)(accel[4] << 8) | accel[5]); } }
/// <summary> R side of controller upward </summary> /// <summary> R side of controller upward </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks> /// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int GyroX { get { return (UInt16)(gyro[0] << 8) | gyro[1]; } } public int GyroX { get { return (Int16)((UInt16)(gyro[0] << 8) | gyro[1]); } }
/// <summary> touchpad and button face side of controller upward </summary> /// <summary> touchpad and button face side of controller upward </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks> /// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int GyroY { get { return (UInt16)(gyro[2] << 8) | gyro[3]; } } public int GyroY { get { return (Int16)((UInt16)(gyro[2] << 8) | gyro[3]); } }
/// <summary> Audio/expansion ports upward and light bar/shoulders/bumpers/USB port downward </summary> /// <summary> Audio/expansion ports upward and light bar/shoulders/bumpers/USB port downward </summary>
/// <remarks> Add double the previous result to this delta and divide by three.</remarks> /// <remarks> Add double the previous result to this delta and divide by three.</remarks>
public int GyroZ { get { return (UInt16)(gyro[4] << 8) | gyro[5]; } } public int GyroZ { get { return (Int16)((UInt16)(gyro[4] << 8) | gyro[5]); } }
} }
} }

View File

@ -8,11 +8,10 @@ namespace DS4Library
public class TouchpadEventArgs : EventArgs public class TouchpadEventArgs : EventArgs
{ {
public readonly Touch[] touches = null; public readonly Touch[] touches = null;
public readonly System.DateTime timeStamp;
public readonly bool touchButtonPressed; public readonly bool touchButtonPressed;
public readonly DateTime timeStamp; public TouchpadEventArgs(System.DateTime utcTimestamp, bool tButtonDown, Touch t0, Touch t1 = null)
public TouchpadEventArgs(DateTime timeStamp, bool tButtonDown, Touch t0, Touch t1 = null)
{ {
this.timeStamp = timeStamp;
if (t1 != null) if (t1 != null)
{ {
touches = new Touch[2]; touches = new Touch[2];
@ -25,6 +24,7 @@ namespace DS4Library
touches[0] = t0; touches[0] = t0;
} }
touchButtonPressed = tButtonDown; touchButtonPressed = tButtonDown;
this.timeStamp = utcTimestamp;
} }
} }
@ -49,128 +49,161 @@ namespace DS4Library
public class DS4Touchpad public class DS4Touchpad
{ {
public event EventHandler<TouchpadEventArgs> TouchesBegan = null; public event EventHandler<TouchpadEventArgs> TouchesBegan = null; // finger one or two landed (or both, or one then two, or two then one; any touches[] count increase)
public event EventHandler<TouchpadEventArgs> TouchesMoved = null; public event EventHandler<TouchpadEventArgs> TouchesMoved = null; // deltaX/deltaY are set because one or both fingers were already down on a prior sensor reading
public event EventHandler<TouchpadEventArgs> TouchesEnded = null; public event EventHandler<TouchpadEventArgs> TouchesEnded = null; // all fingers lifted
public event EventHandler<TouchpadEventArgs> TouchButtonDown = null; public event EventHandler<TouchpadEventArgs> TouchButtonDown = null; // touchpad pushed down until the button clicks
public event EventHandler<TouchpadEventArgs> TouchButtonUp = null; public event EventHandler<TouchpadEventArgs> TouchButtonUp = null; // touchpad button released
public readonly static int TOUCHPAD_DATA_OFFSET = 35; public event EventHandler<EventArgs> TouchUnchanged = null; // no status change for the touchpad itself... but other sensors may have changed, or you may just want to do some processing
internal static int lastTouchPadX, lastTouchPadY,
lastTouchPadX2, lastTouchPadY2; // tracks 0, 1 or 2 touches; we maintain touch 1 and 2 separately
internal static bool lastTouchPadIsDown;
internal static bool lastIsActive;
internal static bool lastIsActive2;
internal static byte lastTouchID, lastTouchID2;
public void handleTouchpad(byte[] data, DS4State sensors) public readonly static int TOUCHPAD_DATA_OFFSET = 35;
internal int lastTouchPadX1, lastTouchPadY1,
lastTouchPadX2, lastTouchPadY2; // tracks 0, 1 or 2 touches; we maintain touch 1 and 2 separately
internal bool lastTouchPadIsDown;
internal bool lastIsActive1, lastIsActive2;
internal byte lastTouchID1, lastTouchID2;
internal byte[] previousPacket = new byte[8];
// We check everything other than the not bothering with not-very-useful TouchPacketCounter.
private bool PacketChanged(byte[] data, int touchPacketOffset)
{
bool changed = false;
for (int i = 0; i < previousPacket.Length; i++)
{
byte oldValue = previousPacket[i];
previousPacket[i] = data[i + TOUCHPAD_DATA_OFFSET + touchPacketOffset];
if (previousPacket[i] != oldValue)
changed = true;
}
return changed;
}
public void handleTouchpad(byte[] data, DS4State sensors, int touchPacketOffset = 0)
{ {
bool touchPadIsDown = sensors.TouchButton; bool touchPadIsDown = sensors.TouchButton;
byte touchID = (byte)(data[0 + TOUCHPAD_DATA_OFFSET] & 0x7F); if (!PacketChanged(data, touchPacketOffset) && touchPadIsDown == lastTouchPadIsDown)
byte touchID2 = (byte)(data[4 + TOUCHPAD_DATA_OFFSET] & 0x7F);
int currentX = data[1 + TOUCHPAD_DATA_OFFSET] + ((data[2 + TOUCHPAD_DATA_OFFSET] & 0xF) * 255);
int currentY = ((data[2 + TOUCHPAD_DATA_OFFSET] & 0xF0) >> 4) + (data[3 + TOUCHPAD_DATA_OFFSET] * 16);
int currentX2 = data[5 + TOUCHPAD_DATA_OFFSET] + ((data[6 + TOUCHPAD_DATA_OFFSET] & 0xF) * 255);
int currentY2 = ((data[6 + TOUCHPAD_DATA_OFFSET] & 0xF0) >> 4) + (data[7 + TOUCHPAD_DATA_OFFSET] * 16);
if (sensors.Touch1)
{ {
if (!lastTouchPadIsDown && touchPadIsDown && TouchButtonDown != null) if (TouchUnchanged != null)
TouchUnchanged(this, EventArgs.Empty);
return;
}
byte touchID1 = (byte)(data[0 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] & 0x7F);
byte touchID2 = (byte)(data[4 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] & 0x7F);
int currentX1 = data[1 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] + ((data[2 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] & 0xF) * 255);
int currentY1 = ((data[2 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] & 0xF0) >> 4) + (data[3 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] * 16);
int currentX2 = data[5 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] + ((data[6 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] & 0xF) * 255);
int currentY2 = ((data[6 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] & 0xF0) >> 4) + (data[7 + TOUCHPAD_DATA_OFFSET + touchPacketOffset] * 16);
TouchpadEventArgs args;
if (sensors.Touch1 || sensors.Touch2)
{
if ((sensors.Touch1 && !lastIsActive1) || (sensors.Touch2 && !lastIsActive2))
{ {
TouchpadEventArgs args = null; if (TouchesBegan != null)
Touch t0 = new Touch(currentX, currentY, touchID);
if (sensors.Touch2)
{ {
Touch t1 = new Touch(currentX2, currentY2, touchID2); if (sensors.Touch1 && sensors.Touch2)
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0, t1); args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX1, currentY1, touchID1), new Touch(currentX2, currentY2, touchID2));
else if (sensors.Touch1)
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX1, currentY1, touchID1));
else
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX2, currentY2, touchID2));
TouchesBegan(this, args);
}
}
else if (sensors.Touch1 == lastIsActive1 && sensors.Touch2 == lastIsActive2 && TouchesMoved != null)
{
Touch tPrev, t0, t1;
if (sensors.Touch1 && sensors.Touch2)
{
tPrev = new Touch(lastTouchPadX1, lastTouchPadY1, lastTouchID1);
t0 = new Touch(currentX1, currentY1, touchID1, tPrev);
tPrev = new Touch(lastTouchPadX2, lastTouchPadY2, lastTouchID2);
t1 = new Touch(currentX2, currentY2, touchID2, tPrev);
}
else if (sensors.Touch1)
{
tPrev = new Touch(lastTouchPadX1, lastTouchPadY1, lastTouchID1);
t0 = new Touch(currentX1, currentY1, touchID1, tPrev);
t1 = null;
} }
else else
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0); {
tPrev = new Touch(lastTouchPadX2, lastTouchPadY2, lastTouchID2);
t0 = new Touch(currentX2, currentY2, touchID2, tPrev);
t1 = null;
}
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0, t1);
TouchesMoved(this, args);
}
if (!lastTouchPadIsDown && touchPadIsDown && TouchButtonDown != null)
{
if (sensors.Touch1 && sensors.Touch2)
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX1, currentY1, touchID1), new Touch(currentX2, currentY2, touchID2));
else if (sensors.Touch1)
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX1, currentY1, touchID1));
else
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX2, currentY2, touchID2));
TouchButtonDown(this, args); TouchButtonDown(this, args);
} }
else if (lastTouchPadIsDown && !touchPadIsDown && TouchButtonUp != null) else if (lastTouchPadIsDown && !touchPadIsDown && TouchButtonUp != null)
{ {
TouchpadEventArgs args = null; if (sensors.Touch1 && sensors.Touch2)
Touch t0 = new Touch(currentX, currentY, touchID); args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX1, currentY1, touchID1), new Touch(currentX2, currentY2, touchID2));
if (sensors.Touch2) else if (sensors.Touch1)
{ args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX1, currentY1, touchID1));
Touch t1 = new Touch(currentX2, currentY2, touchID2);
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0, t1);
}
else else
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0); args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(currentX2, currentY2, touchID2));
TouchButtonUp(this, args); TouchButtonUp(this, args);
} }
if (!lastIsActive || (sensors.Touch2 && !lastIsActive2)) if (sensors.Touch1)
{ {
TouchpadEventArgs args = null; lastTouchPadX1 = currentX1;
Touch t0 = new Touch(currentX, currentY, touchID); lastTouchPadY1 = currentY1;
if (sensors.Touch2 && !lastIsActive2)
{
Touch t1 = new Touch(currentX2, currentY2, touchID2);
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0, t1);
}
else
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0);
if (TouchesBegan != null)
TouchesBegan(this, args);
} }
else if (lastIsActive) if (sensors.Touch2)
{ {
if (TouchesMoved != null) lastTouchPadX2 = currentX2;
{ lastTouchPadY2 = currentY2;
TouchpadEventArgs args = null;
Touch t0Prev = new Touch(lastTouchPadX, lastTouchPadY, lastTouchID);
Touch t0 = new Touch(currentX, currentY, touchID, t0Prev);
if (sensors.Touch1 && sensors.Touch2)
{
Touch t1Prev = new Touch(lastTouchPadX2, lastTouchPadY2, lastTouchID2);
Touch t1 = new Touch(currentX2, currentY2, touchID2, t1Prev);
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0, t1);
}
else
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0);
TouchesMoved(this, args);
}
} }
lastTouchPadX = currentX;
lastTouchPadY = currentY;
lastTouchPadX2 = currentX2;
lastTouchPadY2 = currentY2;
lastTouchPadIsDown = touchPadIsDown; lastTouchPadIsDown = touchPadIsDown;
} }
else else
{ {
if (lastIsActive) if (touchPadIsDown && !lastTouchPadIsDown)
{ {
TouchpadEventArgs args = null; if (TouchButtonDown != null)
Touch t0 = new Touch(currentX, currentY, touchID); TouchButtonDown(this, new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, null, null));
if (lastIsActive2) }
{ else if (!touchPadIsDown && lastTouchPadIsDown)
Touch t1 = new Touch(currentX2, currentY2, touchID2); {
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0, t1); if (TouchButtonUp != null)
} TouchButtonUp(this, new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, null, null));
else
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, t0);
if (TouchesEnded != null)
TouchesEnded(this, args);
} }
if (touchPadIsDown && !lastTouchPadIsDown && TouchButtonDown != null) if ((lastIsActive1 || lastIsActive2) && TouchesEnded != null)
{ {
TouchButtonDown(this, new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, null, null)); if (lastIsActive1 && lastIsActive2)
} args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(lastTouchPadX1, lastTouchPadY1, touchID1), new Touch(lastTouchPadX2, lastTouchPadY2, touchID2));
else if (!touchPadIsDown && lastTouchPadIsDown && TouchButtonUp != null) else if (lastIsActive1)
{ args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(lastTouchPadX1, lastTouchPadY1, touchID1));
TouchButtonUp(this, new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, null, null)); else
args = new TouchpadEventArgs(sensors.ReportTimeStamp, sensors.TouchButton, new Touch(lastTouchPadX2, lastTouchPadY2, touchID2));
TouchesEnded(this, args);
} }
} }
lastIsActive = sensors.Touch1; lastIsActive1 = sensors.Touch1;
lastIsActive2 = sensors.Touch2; lastIsActive2 = sensors.Touch2;
lastTouchID = touchID; lastTouchID1 = touchID1;
lastTouchID2 = touchID2; lastTouchID2 = touchID2;
lastTouchPadIsDown = touchPadIsDown; lastTouchPadIsDown = touchPadIsDown;
} }

View File

@ -13,13 +13,9 @@
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
if (disposing) if (disposing && (components != null))
{ {
if (components != null) components.Dispose();
components.Dispose();
//CA2213 Disposable fields should be disposed
if (rootHub != null)
rootHub.Dispose();
} }
base.Dispose(disposing); base.Dispose(disposing);
} }

View File

@ -35,7 +35,7 @@
// //
// OkButton // OkButton
// //
this.OkButton.Location = new System.Drawing.Point(113, 202); this.OkButton.Location = new System.Drawing.Point(260, 118);
this.OkButton.Name = "OkButton"; this.OkButton.Name = "OkButton";
this.OkButton.Size = new System.Drawing.Size(75, 23); this.OkButton.Size = new System.Drawing.Size(75, 23);
this.OkButton.TabIndex = 0; this.OkButton.TabIndex = 0;
@ -52,28 +52,27 @@
this.textBox1.Multiline = true; this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1"; this.textBox1.Name = "textBox1";
this.textBox1.ReadOnly = true; this.textBox1.ReadOnly = true;
this.textBox1.Size = new System.Drawing.Size(260, 155); this.textBox1.Size = new System.Drawing.Size(260, 61);
this.textBox1.TabIndex = 1; this.textBox1.TabIndex = 1;
this.textBox1.Text = "DS4 Tool 1.3 RC3\r\n\r\nCreated By:\r\nArtur Dzmitryieu(InhexSTER)\r\nelectrobrains\r\nHect" + this.textBox1.Text = "DS4Windows is Open Source software!\r\n\r\nInsert link to GPL here (at some point.)";
"icSeptic\r\nJays2Kings\r\n\r\nBased on DS3 Scp Server from\r\nScarlet.Crush";
this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
// //
// linkLabel1 // linkLabel1
// //
this.linkLabel1.AutoSize = true; this.linkLabel1.AutoSize = true;
this.linkLabel1.Location = new System.Drawing.Point(59, 175); this.linkLabel1.Location = new System.Drawing.Point(9, 86);
this.linkLabel1.Name = "linkLabel1"; this.linkLabel1.Name = "linkLabel1";
this.linkLabel1.Size = new System.Drawing.Size(183, 13); this.linkLabel1.Size = new System.Drawing.Size(324, 13);
this.linkLabel1.TabIndex = 2; this.linkLabel1.TabIndex = 2;
this.linkLabel1.TabStop = true; this.linkLabel1.TabStop = true;
this.linkLabel1.Text = "https://code.google.com/p/ds4-tool/"; this.linkLabel1.Text = "https://code.google.com/r/brianfundakowskifeldman-ds4windows/";
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
// //
// AboutBox // AboutBox
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 230); this.ClientSize = new System.Drawing.Size(347, 153);
this.Controls.Add(this.linkLabel1); this.Controls.Add(this.linkLabel1);
this.Controls.Add(this.textBox1); this.Controls.Add(this.textBox1);
this.Controls.Add(this.OkButton); this.Controls.Add(this.OkButton);

View File

@ -28,7 +28,7 @@ namespace ScpServer
private void AboutBox_Load(object sender, EventArgs e) private void AboutBox_Load(object sender, EventArgs e)
{ {
linkLabel1.Links.Add(0,35,"https://code.google.com/p/ds4-tool/"); linkLabel1.Links.Add(0, linkLabel1.Text.Length, "https://code.google.com/r/brianfundakowskifeldman-ds4windows/");
} }
} }
} }

View File

@ -62,6 +62,8 @@
this.bnRX2 = new System.Windows.Forms.Button(); this.bnRX2 = new System.Windows.Forms.Button();
this.bnL3 = new System.Windows.Forms.Button(); this.bnL3 = new System.Windows.Forms.Button();
this.bnR3 = new System.Windows.Forms.Button(); this.bnR3 = new System.Windows.Forms.Button();
this.TouchTip = new System.Windows.Forms.Label();
this.ReapTip = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
@ -300,7 +302,7 @@
this.bnDown.ForeColor = System.Drawing.SystemColors.WindowText; this.bnDown.ForeColor = System.Drawing.SystemColors.WindowText;
this.bnDown.Location = new System.Drawing.Point(85, 184); this.bnDown.Location = new System.Drawing.Point(85, 184);
this.bnDown.Name = "bnDown"; this.bnDown.Name = "bnDown";
this.bnDown.Size = new System.Drawing.Size(19, 22); this.bnDown.Size = new System.Drawing.Size(19, 29);
this.bnDown.TabIndex = 53; this.bnDown.TabIndex = 53;
this.bnDown.Text = "Down Button"; this.bnDown.Text = "Down Button";
this.bnDown.UseVisualStyleBackColor = false; this.bnDown.UseVisualStyleBackColor = false;
@ -318,7 +320,7 @@
this.bnRight.ForeColor = System.Drawing.SystemColors.WindowText; this.bnRight.ForeColor = System.Drawing.SystemColors.WindowText;
this.bnRight.Location = new System.Drawing.Point(106, 164); this.bnRight.Location = new System.Drawing.Point(106, 164);
this.bnRight.Name = "bnRight"; this.bnRight.Name = "bnRight";
this.bnRight.Size = new System.Drawing.Size(21, 18); this.bnRight.Size = new System.Drawing.Size(27, 22);
this.bnRight.TabIndex = 53; this.bnRight.TabIndex = 53;
this.bnRight.Text = "Right Button"; this.bnRight.Text = "Right Button";
this.bnRight.UseVisualStyleBackColor = false; this.bnRight.UseVisualStyleBackColor = false;
@ -336,7 +338,7 @@
this.bnLeft.ForeColor = System.Drawing.SystemColors.WindowText; this.bnLeft.ForeColor = System.Drawing.SystemColors.WindowText;
this.bnLeft.Location = new System.Drawing.Point(57, 163); this.bnLeft.Location = new System.Drawing.Point(57, 163);
this.bnLeft.Name = "bnLeft"; this.bnLeft.Name = "bnLeft";
this.bnLeft.Size = new System.Drawing.Size(26, 20); this.bnLeft.Size = new System.Drawing.Size(26, 23);
this.bnLeft.TabIndex = 53; this.bnLeft.TabIndex = 53;
this.bnLeft.Text = "Left Button"; this.bnLeft.Text = "Left Button";
this.bnLeft.UseVisualStyleBackColor = false; this.bnLeft.UseVisualStyleBackColor = false;
@ -352,9 +354,9 @@
this.bnOptions.FlatAppearance.MouseOverBackColor = System.Drawing.SystemColors.Control; this.bnOptions.FlatAppearance.MouseOverBackColor = System.Drawing.SystemColors.Control;
this.bnOptions.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.bnOptions.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.bnOptions.ForeColor = System.Drawing.SystemColors.WindowText; this.bnOptions.ForeColor = System.Drawing.SystemColors.WindowText;
this.bnOptions.Location = new System.Drawing.Point(283, 125); this.bnOptions.Location = new System.Drawing.Point(286, 121);
this.bnOptions.Name = "bnOptions"; this.bnOptions.Name = "bnOptions";
this.bnOptions.Size = new System.Drawing.Size(13, 22); this.bnOptions.Size = new System.Drawing.Size(19, 30);
this.bnOptions.TabIndex = 53; this.bnOptions.TabIndex = 53;
this.bnOptions.Text = "Start"; this.bnOptions.Text = "Start";
this.bnOptions.UseVisualStyleBackColor = false; this.bnOptions.UseVisualStyleBackColor = false;
@ -370,9 +372,9 @@
this.bnShare.FlatAppearance.MouseOverBackColor = System.Drawing.SystemColors.Control; this.bnShare.FlatAppearance.MouseOverBackColor = System.Drawing.SystemColors.Control;
this.bnShare.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.bnShare.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.bnShare.ForeColor = System.Drawing.SystemColors.WindowText; this.bnShare.ForeColor = System.Drawing.SystemColors.WindowText;
this.bnShare.Location = new System.Drawing.Point(131, 127); this.bnShare.Location = new System.Drawing.Point(131, 124);
this.bnShare.Name = "bnShare"; this.bnShare.Name = "bnShare";
this.bnShare.Size = new System.Drawing.Size(12, 23); this.bnShare.Size = new System.Drawing.Size(14, 29);
this.bnShare.TabIndex = 53; this.bnShare.TabIndex = 53;
this.bnShare.Text = "Back"; this.bnShare.Text = "Back";
this.bnShare.UseVisualStyleBackColor = false; this.bnShare.UseVisualStyleBackColor = false;
@ -388,9 +390,9 @@
this.bnTouchpad.FlatAppearance.MouseOverBackColor = System.Drawing.SystemColors.Control; this.bnTouchpad.FlatAppearance.MouseOverBackColor = System.Drawing.SystemColors.Control;
this.bnTouchpad.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.bnTouchpad.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.bnTouchpad.ForeColor = System.Drawing.SystemColors.WindowText; this.bnTouchpad.ForeColor = System.Drawing.SystemColors.WindowText;
this.bnTouchpad.Location = new System.Drawing.Point(151, 131); this.bnTouchpad.Location = new System.Drawing.Point(151, 161);
this.bnTouchpad.Name = "bnTouchpad"; this.bnTouchpad.Name = "bnTouchpad";
this.bnTouchpad.Size = new System.Drawing.Size(64, 56); this.bnTouchpad.Size = new System.Drawing.Size(128, 26);
this.bnTouchpad.TabIndex = 53; this.bnTouchpad.TabIndex = 53;
this.bnTouchpad.Text = "Click"; this.bnTouchpad.Text = "Click";
this.bnTouchpad.UseVisualStyleBackColor = false; this.bnTouchpad.UseVisualStyleBackColor = false;
@ -426,7 +428,7 @@
this.bnTouchUpper.ForeColor = System.Drawing.SystemColors.WindowText; this.bnTouchUpper.ForeColor = System.Drawing.SystemColors.WindowText;
this.bnTouchUpper.Location = new System.Drawing.Point(150, 104); this.bnTouchUpper.Location = new System.Drawing.Point(150, 104);
this.bnTouchUpper.Name = "bnTouchUpper"; this.bnTouchUpper.Name = "bnTouchUpper";
this.bnTouchUpper.Size = new System.Drawing.Size(125, 26); this.bnTouchUpper.Size = new System.Drawing.Size(129, 32);
this.bnTouchUpper.TabIndex = 53; this.bnTouchUpper.TabIndex = 53;
this.bnTouchUpper.Text = "Middle Click"; this.bnTouchUpper.Text = "Middle Click";
this.bnTouchUpper.UseVisualStyleBackColor = false; this.bnTouchUpper.UseVisualStyleBackColor = false;
@ -442,9 +444,9 @@
this.bnTouchMulti.FlatAppearance.MouseOverBackColor = System.Drawing.SystemColors.Control; this.bnTouchMulti.FlatAppearance.MouseOverBackColor = System.Drawing.SystemColors.Control;
this.bnTouchMulti.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.bnTouchMulti.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.bnTouchMulti.ForeColor = System.Drawing.SystemColors.WindowText; this.bnTouchMulti.ForeColor = System.Drawing.SystemColors.WindowText;
this.bnTouchMulti.Location = new System.Drawing.Point(215, 131); this.bnTouchMulti.Location = new System.Drawing.Point(151, 135);
this.bnTouchMulti.Name = "bnTouchMulti"; this.bnTouchMulti.Name = "bnTouchMulti";
this.bnTouchMulti.Size = new System.Drawing.Size(64, 56); this.bnTouchMulti.Size = new System.Drawing.Size(128, 26);
this.bnTouchMulti.TabIndex = 53; this.bnTouchMulti.TabIndex = 53;
this.bnTouchMulti.Text = "Right Click"; this.bnTouchMulti.Text = "Right Click";
this.bnTouchMulti.UseVisualStyleBackColor = false; this.bnTouchMulti.UseVisualStyleBackColor = false;
@ -471,12 +473,11 @@
// //
this.lbControls.FormattingEnabled = true; this.lbControls.FormattingEnabled = true;
this.lbControls.Items.AddRange(new object[] { this.lbControls.Items.AddRange(new object[] {
"<Press a button, then a key to assign>"}); "<Click a button, then a key/item to assign>"});
this.lbControls.Location = new System.Drawing.Point(418, 67); this.lbControls.Location = new System.Drawing.Point(418, 67);
this.lbControls.Name = "lbControls"; this.lbControls.Name = "lbControls";
this.lbControls.Size = new System.Drawing.Size(248, 212); this.lbControls.Size = new System.Drawing.Size(248, 212);
this.lbControls.TabIndex = 54; this.lbControls.TabIndex = 54;
this.lbControls.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
// //
// bnLY2 // bnLY2
// //
@ -640,12 +641,36 @@
this.bnR3.Text = "Right Stick"; this.bnR3.Text = "Right Stick";
this.bnR3.UseVisualStyleBackColor = false; this.bnR3.UseVisualStyleBackColor = false;
// //
// TouchTip
//
this.TouchTip.AutoSize = true;
this.TouchTip.Location = new System.Drawing.Point(164, 34);
this.TouchTip.Name = "TouchTip";
this.TouchTip.Size = new System.Drawing.Size(109, 52);
this.TouchTip.TabIndex = 55;
this.TouchTip.Text = "Touchpad:\r\nTop: Upper Pad \r\nMiddle: Multi-Touch \r\nBottom: Single Touch";
this.TouchTip.TextAlign = System.Drawing.ContentAlignment.TopCenter;
this.TouchTip.Visible = false;
//
// ReapTip
//
this.ReapTip.AutoSize = true;
this.ReapTip.Location = new System.Drawing.Point(134, 59);
this.ReapTip.Name = "ReapTip";
this.ReapTip.Size = new System.Drawing.Size(169, 26);
this.ReapTip.TabIndex = 55;
this.ReapTip.Text = "Double Tap a key to toggle repeat\r\n(Excludes TouchPad)";
this.ReapTip.TextAlign = System.Drawing.ContentAlignment.TopCenter;
this.ReapTip.Visible = false;
//
// CustomMapping // CustomMapping
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(244)))), ((int)(((byte)(244)))), ((int)(((byte)(244))))); this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(244)))), ((int)(((byte)(244)))), ((int)(((byte)(244)))));
this.ClientSize = new System.Drawing.Size(684, 310); this.ClientSize = new System.Drawing.Size(684, 310);
this.Controls.Add(this.ReapTip);
this.Controls.Add(this.TouchTip);
this.Controls.Add(this.pictureBox); this.Controls.Add(this.pictureBox);
this.Controls.Add(this.lbControls); this.Controls.Add(this.lbControls);
this.Controls.Add(this.cbScanCode); this.Controls.Add(this.cbScanCode);
@ -728,5 +753,7 @@
private System.Windows.Forms.Button bnRX2; private System.Windows.Forms.Button bnRX2;
private System.Windows.Forms.Button bnL3; private System.Windows.Forms.Button bnL3;
private System.Windows.Forms.Button bnR3; private System.Windows.Forms.Button bnR3;
private System.Windows.Forms.Label TouchTip;
private System.Windows.Forms.Label ReapTip;
} }
} }

View File

@ -16,7 +16,7 @@ namespace ScpServer
{ {
private int device; private int device;
private bool handleNextKeyPress = false; private bool handleNextKeyPress = false;
private bool MouseMoveAdded = false; private bool ReapTipShown = false;
private List<ComboBox> comboBoxes = new List<ComboBox>(); private List<ComboBox> comboBoxes = new List<ComboBox>();
private List<Button> buttons = new List<Button>(); private List<Button> buttons = new List<Button>();
private Dictionary<string, string> defaults = new Dictionary<string, string>(); private Dictionary<string, string> defaults = new Dictionary<string, string>();
@ -46,11 +46,10 @@ namespace ScpServer
// Add events here (easier for modification/addition) // Add events here (easier for modification/addition)
((Button)control).Enter += new System.EventHandler(this.EnterCommand); ((Button)control).Enter += new System.EventHandler(this.EnterCommand);
((Button)control).KeyDown += new System.Windows.Forms.KeyEventHandler(this.KeyDownCommand); ((Button)control).KeyDown += new System.Windows.Forms.KeyEventHandler(this.KeyDownCommand);
((Button)control).Enter += new System.EventHandler(this.TopofListChanged); //((Button)control).Enter += new System.EventHandler(this.TopofListChanged);
((Button)control).KeyDown += new System.Windows.Forms.KeyEventHandler(this.TopofListChanged); //((Button)control).KeyDown += new System.Windows.Forms.KeyEventHandler(this.TopofListChanged);
((Button)control).KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.KeyPressCommand); ((Button)control).KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.KeyPressCommand);
((Button)control).PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.PreviewKeyDownCommand); ((Button)control).PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.PreviewKeyDownCommand);
//lbControls.Items.Add(((Button)control).Text);
lbControls.SelectedIndexChanged += new System.EventHandler(this.SelectedIndexChangedCommand); lbControls.SelectedIndexChanged += new System.EventHandler(this.SelectedIndexChangedCommand);
} }
} }
@ -64,13 +63,15 @@ namespace ScpServer
{ {
if (sender is Button) if (sender is Button)
{ {
lbControls.SetSelected(0, true); ReapTip.Visible = false;
for (int i = 1; i < lbControls.Items.Count; i++) lbControls.SetSelected(0, true);
if (lbControls.Items[i].ToString().Contains(" (default)")) //
{ for (int i = 1; i < lbControls.Items.Count; i++)
lbControls.Items[i] = lbControls.Items[i].ToString().Remove(lbControls.Items[i].ToString().Length - 10); if (lbControls.Items[i].ToString().Contains(" (default)"))
} {
//Change image to represent button lbControls.Items[i] = lbControls.Items[i].ToString().Remove(lbControls.Items[i].ToString().Length - 10);
}
//Change image to represent button
lastSelectedBn = (Button)sender; lastSelectedBn = (Button)sender;
switch (lastSelectedBn.Name) switch (lastSelectedBn.Name)
{ {
@ -160,15 +161,29 @@ namespace ScpServer
lbControls.Items.Insert(1, temp); lbControls.Items.Insert(1, temp);
break; break;
} }
if (((Button)sender).Name.Contains("bnLX") || ((Button)sender).Name.Contains("bnLY") || ((Button)sender).Name.Contains("bnRX") || ((Button)sender).Name.Contains("bnRY"))
{
lbControls.Items.Insert(2, "Mouse Right");
lbControls.Items.Insert(2, "Mouse Left");
lbControls.Items.Insert(2, "Mouse Down");
lbControls.Items.Insert(2, "Mouse Up");
}
break; break;
}
if (((Button)sender).Name.Contains("bnLX") || ((Button)sender).Name.Contains("bnLY") || ((Button)sender).Name.Contains("bnRX") || ((Button)sender).Name.Contains("bnRY"))
{
lbControls.Items.Insert(2, "Mouse Right");
lbControls.Items.Insert(2, "Mouse Left");
lbControls.Items.Insert(2, "Mouse Down");
lbControls.Items.Insert(2, "Mouse Up");
}
if (((Button)sender).Name.Contains("Touch"))
TouchTip.Visible = true;
else
{
if (ReapTipShown == false)
{
ReapTip.Visible = true;
ReapTipShown = true;
} }
TouchTip.Visible = false;
}
if (((Button)sender).Text != "Save" && ((Button)sender).Text != "Load")
lbControls.Items[0] = ((Button)sender).Text;
} }
private void PreviewKeyDownCommand(object sender, PreviewKeyDownEventArgs e) private void PreviewKeyDownCommand(object sender, PreviewKeyDownEventArgs e)
@ -238,20 +253,19 @@ namespace ScpServer
} }
private void SelectedIndexChangedCommand(object sender, EventArgs e) private void SelectedIndexChangedCommand(object sender, EventArgs e)
{ {
if (lbControls.SelectedIndex > 0) if (lastSelectedBn != null)
{ if (lbControls.SelectedIndex > 0)
if (lastSelectedBn.Text != lbControls.Items[lbControls.SelectedIndex].ToString()) if (lastSelectedBn.Text != lbControls.Items[lbControls.SelectedIndex].ToString())
{
if (lbControls.Items[lbControls.SelectedIndex].ToString().Contains(" (default)"))
{ {
lastSelectedBn.Text = lbControls.Items[lbControls.SelectedIndex].ToString().Remove(lbControls.Items[lbControls.SelectedIndex].ToString().Length - 10); if (lbControls.Items[lbControls.SelectedIndex].ToString().Contains(" (default)"))
lastSelectedBn.Tag = lbControls.Items[lbControls.SelectedIndex].ToString().Remove(lbControls.Items[lbControls.SelectedIndex].ToString().Length - 10); {
lastSelectedBn.Text = lbControls.Items[lbControls.SelectedIndex].ToString().Remove(lbControls.Items[lbControls.SelectedIndex].ToString().Length - 10);
lastSelectedBn.Tag = lbControls.Items[lbControls.SelectedIndex].ToString().Remove(lbControls.Items[lbControls.SelectedIndex].ToString().Length - 10);
}
else
lastSelectedBn.Text = lbControls.Items[lbControls.SelectedIndex].ToString();
lastSelectedBn.Tag = lbControls.Items[lbControls.SelectedIndex].ToString();
} }
else
lastSelectedBn.Text = lbControls.Items[lbControls.SelectedIndex].ToString();
lastSelectedBn.Tag = lbControls.Items[lbControls.SelectedIndex].ToString();
}
}
} }
private void cbRepeat_CheckedChanged(object sender, EventArgs e) private void cbRepeat_CheckedChanged(object sender, EventArgs e)
{ {
@ -322,10 +336,6 @@ namespace ScpServer
} }
} }
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
} }

View File

@ -11,8 +11,7 @@
<AssemblyName>DS4Tool</AssemblyName> <AssemblyName>DS4Tool</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper> <PublishUrl>publish\</PublishUrl>
<PublishUrl>C:\Users\Jonathan\Documents\Projects\DS4Builds\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled> <UpdateEnabled>false</UpdateEnabled>
@ -22,11 +21,10 @@
<UpdatePeriodically>false</UpdatePeriodically> <UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired> <UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions> <MapFileExtensions>true</MapFileExtensions>
<AutorunEnabled>true</AutorunEnabled> <ApplicationRevision>0</ApplicationRevision>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion> <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled> <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@ -55,18 +53,6 @@
<PropertyGroup> <PropertyGroup>
<StartupObject>ScpServer.Program</StartupObject> <StartupObject>ScpServer.Program</StartupObject>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<ManifestCertificateThumbprint>82841E533FB15D122F1D1941E6264C09CDDD60F1</ManifestCertificateThumbprint>
</PropertyGroup>
<PropertyGroup>
<ManifestKeyFile>DS4Tool_TemporaryKey.pfx</ManifestKeyFile>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<SignManifests>true</SignManifests>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
@ -87,7 +73,6 @@
<DependentUpon>AboutBox.cs</DependentUpon> <DependentUpon>AboutBox.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="AdvancedColorDialog.cs" /> <Compile Include="AdvancedColorDialog.cs" />
<Compile Include="AdvancedComboBox.cs" />
<Compile Include="CustomMapping.cs"> <Compile Include="CustomMapping.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@ -108,12 +93,6 @@
</Compile> </Compile>
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReadInputForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ReadInputForm.Designer.cs">
<DependentUpon>ReadInputForm.cs</DependentUpon>
</Compile>
<Compile Include="ScpForm.cs"> <Compile Include="ScpForm.cs">
<SubType>Form</SubType> <SubType>Form</SubType>
</Compile> </Compile>
@ -143,13 +122,9 @@
<DependentUpon>Resources.resx</DependentUpon> <DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
</Compile> </Compile>
<EmbeddedResource Include="ReadInputForm.resx">
<DependentUpon>ReadInputForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ScpForm.resx"> <EmbeddedResource Include="ScpForm.resx">
<DependentUpon>ScpForm.cs</DependentUpon> <DependentUpon>ScpForm.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<None Include="DS4Tool_TemporaryKey.pfx" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
@ -194,16 +169,12 @@
<None Include="Resources\28.png" /> <None Include="Resources\28.png" />
<None Include="Resources\29.png" /> <None Include="Resources\29.png" />
<Content Include="Resources\3.png" /> <Content Include="Resources\3.png" />
<None Include="Resources\30.png" />
<None Include="Resources\31.png" />
<Content Include="Resources\4.png" /> <Content Include="Resources\4.png" />
<Content Include="Resources\5.png" /> <Content Include="Resources\5.png" />
<Content Include="Resources\6.png" /> <Content Include="Resources\6.png" />
<Content Include="Resources\7.png" /> <Content Include="Resources\7.png" />
<Content Include="Resources\8.png" /> <Content Include="Resources\8.png" />
<Content Include="Resources\9.png" /> <Content Include="Resources\9.png" />
<None Include="Resources\DS4 More Red %28small%29.png" />
<None Include="Resources\DS4 Control Shadows %28small%29.png" />
<Content Include="Resources\DS4.ico" /> <Content Include="Resources\DS4.ico" />
<Content Include="Resources\Scp_All.ico" /> <Content Include="Resources\Scp_All.ico" />
</ItemGroup> </ItemGroup>

View File

@ -9,17 +9,17 @@ namespace ScpServer
/// The main entry point for the application. /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
static void Main() static void Main()
{ {
System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.LowLatency; System.Runtime.GCSettings.LatencyMode = System.Runtime.GCLatencyMode.LowLatency;
try try
{ {
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.High; System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.High;
} }
catch catch
{ {
// Ignore problems raising the priority. // Ignore problems raising the priority.
} }
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ScpForm()); Application.Run(new ScpForm());

View File

@ -118,86 +118,65 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="_10" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="DS4" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\10.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\DS4.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Stop" xml:space="preserve">
<value>Stop</value>
<comment>To be localized.</comment>
</data>
<data name="_15" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\15.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_9" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\9.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_13" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\13.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="Start" xml:space="preserve"> <data name="Start" xml:space="preserve">
<value>Start</value> <value>Start</value>
<comment>To be localized.</comment> <comment>To be localized.</comment>
</data> </data>
<data name="_19" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="Stop" xml:space="preserve">
<value>..\Resources\19.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>Stop</value>
<comment>To be localized.</comment>
</data> </data>
<data name="_4" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_1" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\1.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_10" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\10.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_11" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_11" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\11.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_16" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_12" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\12.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_2" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_13" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\13.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_14" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_14" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\14.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\14.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_5" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_15" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\15.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_22" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_16" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\22.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\16.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_7" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_17" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\7.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\17.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_12" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\12.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_18" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_18" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\18.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\18.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_19" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\19.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_2" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\2.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_20" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_20" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\20.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_21" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_21" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\21.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\21.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_17" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_22" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\17.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\22.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_23" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_23" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\23.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\23.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_3" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_8" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\8.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_6" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\6.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="DS4" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\DS4.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_24" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_24" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\24.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
@ -216,4 +195,25 @@
<data name="_29" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="_29" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\29.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\29.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="_3" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\3.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_4" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_5" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\5.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_6" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\6.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_7" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\7.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_8" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\8.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="_9" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\9.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root> </root>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -13,13 +13,9 @@
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
if (disposing) if (disposing && (components != null))
{ {
if (components != null) components.Dispose();
components.Dispose();
//CA2213 Disposable fields should be disposed
if (rootHub != null)
rootHub.Dispose();
} }
base.Dispose(disposing); base.Dispose(disposing);
} }
@ -93,7 +89,8 @@
// //
// tmrUpdate // tmrUpdate
// //
this.tmrUpdate.Tick += new System.EventHandler(this.tmrUpdate_Tick); this.tmrUpdate.Interval = 1;
this.tmrUpdate.Tick += new System.EventHandler(this.ControllerStatusChange);
// //
// pnlButton // pnlButton
// //
@ -330,7 +327,7 @@
this.Controls.Add(this.pnlStatus); this.Controls.Add(this.pnlStatus);
this.MinimumSize = new System.Drawing.Size(750, 192); this.MinimumSize = new System.Drawing.Size(750, 192);
this.Name = "ScpForm"; this.Name = "ScpForm";
this.Text = "DS4 to XInput Mapper 1.3 RC4 - J2K Build"; this.Text = "DS4Windows 1.0 Alpha (2014-03-28.1)";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form_Close); this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form_Close);
this.Load += new System.EventHandler(this.Form_Load); this.Load += new System.EventHandler(this.Form_Load);
this.Resize += new System.EventHandler(this.Form_Resize); this.Resize += new System.EventHandler(this.Form_Resize);
@ -348,6 +345,7 @@
private System.Windows.Forms.ListView lvDebug; private System.Windows.Forms.ListView lvDebug;
private System.Windows.Forms.ColumnHeader chTime; private System.Windows.Forms.ColumnHeader chTime;
private System.Windows.Forms.ColumnHeader chData; private System.Windows.Forms.ColumnHeader chData;
private System.Windows.Forms.Timer tmrUpdate;
private System.Windows.Forms.Panel pnlButton; private System.Windows.Forms.Panel pnlButton;
private System.Windows.Forms.Button btnStop; private System.Windows.Forms.Button btnStop;
private System.Windows.Forms.Button btnStartStop; private System.Windows.Forms.Button btnStartStop;
@ -367,7 +365,6 @@
private System.Windows.Forms.Label lbLastMessage; private System.Windows.Forms.Label lbLastMessage;
private System.Windows.Forms.LinkLabel lnkControllers; private System.Windows.Forms.LinkLabel lnkControllers;
private System.Windows.Forms.Button AboutButton; private System.Windows.Forms.Button AboutButton;
private System.Windows.Forms.Timer tmrUpdate;
} }
} }

View File

@ -35,7 +35,7 @@ namespace ScpServer
protected void ShowNotification(object sender, DebugEventArgs args) protected void ShowNotification(object sender, DebugEventArgs args)
{ {
notifyIcon1.BalloonTipText = args.Data; notifyIcon1.BalloonTipText = args.Data;
notifyIcon1.BalloonTipTitle = "DS4 Tool"; notifyIcon1.BalloonTipTitle = "DS4Windows";
notifyIcon1.ShowBalloonTip(1); notifyIcon1.ShowBalloonTip(1);
} }
@ -45,15 +45,13 @@ namespace ScpServer
{ {
notifyIcon1.Visible = true; notifyIcon1.Visible = true;
this.Hide(); this.Hide();
//hide in taskbar
this.ShowInTaskbar = false; this.ShowInTaskbar = false;
} }
else if (FormWindowState.Normal == this.WindowState) else if (FormWindowState.Normal == this.WindowState)
{ {
notifyIcon1.Visible = false; notifyIcon1.Visible = false;
//show in taskbar this.Show();
this.ShowInTaskbar = true; this.ShowInTaskbar = true;
} }
//Added last message alternative //Added last message alternative
if (this.Height > 220) if (this.Height > 220)
@ -83,13 +81,11 @@ namespace ScpServer
rootHub.Debug += On_Debug; rootHub.Debug += On_Debug;
Log.GuiLog += On_Debug; Log.GuiLog += On_Debug;
Log.TrayIconLog += ShowNotification; Log.TrayIconLog += ShowNotification;
tmrUpdate.Enabled = true; // tmrUpdate.Enabled = true; TODO remove tmrUpdate and leave tick()
Global.Load(); Global.Load();
hideDS4CheckBox.CheckedChanged -= hideDS4CheckBox_CheckedChanged; hideDS4CheckBox.CheckedChanged -= hideDS4CheckBox_CheckedChanged;
hideDS4CheckBox.Checked = Global.getUseExclusiveMode(); hideDS4CheckBox.Checked = Global.getUseExclusiveMode();
hideDS4CheckBox.CheckedChanged += hideDS4CheckBox_CheckedChanged; hideDS4CheckBox.CheckedChanged += hideDS4CheckBox_CheckedChanged;
if (btnStartStop.Enabled)
btnStartStop_Click(sender, e);
// New settings // New settings
this.Width = Global.getFormWidth(); this.Width = Global.getFormWidth();
@ -104,8 +100,10 @@ namespace ScpServer
Form_Resize(sender, e); Form_Resize(sender, e);
} }
Global.loadCustomMapping(0); Global.loadCustomMapping(0);
Global.ControllerStatusChange += ControllerStatusChange;
ControllerStatusChanged();
if (btnStartStop.Enabled)
btnStartStop_Clicked();
} }
protected void Form_Close(object sender, FormClosingEventArgs e) protected void Form_Close(object sender, FormClosingEventArgs e)
{ {
@ -116,6 +114,10 @@ namespace ScpServer
} }
protected void btnStartStop_Click(object sender, EventArgs e) protected void btnStartStop_Click(object sender, EventArgs e)
{
btnStartStop_Clicked();
}
protected void btnStartStop_Clicked()
{ {
if (btnStartStop.Text == Properties.Resources.Start if (btnStartStop.Text == Properties.Resources.Start
&& rootHub.Start()) && rootHub.Start())
@ -156,17 +158,23 @@ namespace ScpServer
base.WndProc(ref m); base.WndProc(ref m);
} }
protected void tmrUpdate_Tick(object sender, EventArgs e)
{
delegate void ControllerStatusChangedDelegate(object sender, EventArgs e);
protected void ControllerStatusChange(object sender, EventArgs e)
{
if (InvokeRequired)
Invoke(new ControllerStatusChangedDelegate(ControllerStatusChange), new object[] { sender, e });
else
ControllerStatusChanged();
}
protected void ControllerStatusChanged()
{
// If controllers are detected, but not checked, automatically check #1 // If controllers are detected, but not checked, automatically check #1
bool checkFirst = true; bool checkFirst = true;
bool optionsEnabled = false; bool optionsEnabled = false;
for (Int32 Index = 0; Index < Pad.Length; Index++) for (Int32 Index = 0; Index < Pad.Length; Index++)
{ {
string contollerInfo = rootHub.getDS4ControllerInfo(Index); Pad[Index].Text = rootHub.getDS4ControllerInfo(Index);
Pad[Index].Text = contollerInfo;
if (Pad[Index].Text != null && Pad[Index].Text != "") if (Pad[Index].Text != null && Pad[Index].Text != "")
{ {
Pad[Index].Enabled = true; Pad[Index].Enabled = true;
@ -237,8 +245,8 @@ namespace ScpServer
module.Dispose(); module.Dispose();
Global.setUseExclusiveMode(hideDS4CheckBox.Checked); Global.setUseExclusiveMode(hideDS4CheckBox.Checked);
btnStartStop_Click(sender, e); btnStartStop_Clicked();
btnStartStop_Click(sender, e); btnStartStop_Clicked();
Global.Save(); Global.Save();
} }
private void startMinimizedCheckBox_CheckedChanged(object sender, EventArgs e) private void startMinimizedCheckBox_CheckedChanged(object sender, EventArgs e)

View File

@ -62,6 +62,7 @@ namespace HidLibrary
public SafeFileHandle safeReadHandle { get; private set; } public SafeFileHandle safeReadHandle { get; private set; }
public FileStream fileStream { get; private set; } public FileStream fileStream { get; private set; }
public bool IsOpen { get; private set; } public bool IsOpen { get; private set; }
public bool IsExclusive { get; private set; }
public bool IsConnected { get { return HidDevices.IsConnected(_devicePath); } } public bool IsConnected { get { return HidDevices.IsConnected(_devicePath); } }
public bool IsTimedOut { get { return idleTicks > 5; } } public bool IsTimedOut { get { return idleTicks > 5; } }
public string Description { get { return _description; } } public string Description { get { return _description; } }
@ -93,7 +94,7 @@ namespace HidLibrary
if (IsOpen) return; if (IsOpen) return;
try try
{ {
if (safeReadHandle == null) if (safeReadHandle == null || safeReadHandle.IsInvalid)
safeReadHandle = OpenHandle(_devicePath, isExclusive); safeReadHandle = OpenHandle(_devicePath, isExclusive);
} }
catch (Exception exception) catch (Exception exception)
@ -103,6 +104,7 @@ namespace HidLibrary
} }
IsOpen = !safeReadHandle.IsInvalid; IsOpen = !safeReadHandle.IsInvalid;
IsExclusive = isExclusive;
} }
public void CloseDevice() public void CloseDevice()
@ -327,15 +329,7 @@ namespace HidLibrary
} }
} }
public bool WriteFile(byte[] buffer) public bool WriteOutputReportViaInterrupt(byte[] outputBuffer, int timeout)
{
uint bytesWritten = 0;
if ( NativeMethods.WriteFile(safeReadHandle.DangerousGetHandle(), buffer, (uint)buffer.Length, out bytesWritten, IntPtr.Zero) && bytesWritten > 0)
return true;
else
return false;
}
public bool WriteOutputReportViaInterrupt(byte[] outputBuffer)
{ {
try try
{ {
@ -409,8 +403,6 @@ namespace HidLibrary
byte[] buffer = new byte[126]; byte[] buffer = new byte[126];
NativeMethods.HidD_GetSerialNumberString(safeReadHandle.DangerousGetHandle(), buffer, (ulong)buffer.Length); NativeMethods.HidD_GetSerialNumberString(safeReadHandle.DangerousGetHandle(), buffer, (ulong)buffer.Length);
string MACAddr = System.Text.Encoding.Unicode.GetString(buffer).Replace("\0", string.Empty).ToUpper(); string MACAddr = System.Text.Encoding.Unicode.GetString(buffer).Replace("\0", string.Empty).ToUpper();
if (MACAddr == null || MACAddr == String.Empty)
MACAddr = "000000000000";
MACAddr = String.Format("{0}{1}:{2}{3}:{4}{5}:{6}{7}:{8}{9}:{10}{11}", MACAddr = String.Format("{0}{1}:{2}{3}:{4}{5}:{6}{7}:{8}{9}:{10}{11}",
MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4], MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4],
MACAddr[5], MACAddr[6], MACAddr[7], MACAddr[8], MACAddr[5], MACAddr[6], MACAddr[7], MACAddr[8],

View File

@ -66,7 +66,7 @@ namespace HidLibrary
static internal extern uint WaitForSingleObject(IntPtr hHandle, int dwMilliseconds); static internal extern uint WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
[DllImport("kernel32.dll")] [DllImport("kernel32.dll")]
static internal extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped); static internal extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, [In] ref System.Threading.NativeOverlapped lpOverlapped);
internal const int DBT_DEVICEARRIVAL = 0x8000; internal const int DBT_DEVICEARRIVAL = 0x8000;
internal const int DBT_DEVICEREMOVECOMPLETE = 0x8004; internal const int DBT_DEVICEREMOVECOMPLETE = 0x8004;