Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds wireless disconnect button to UI #79

Merged
merged 6 commits into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions DSHMC/MVVM/DeviceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,21 +210,24 @@ public string DisplayName
}
}

/// <summary>
/// The connection protocol used by this device.
/// </summary>
public EFontAwesomeIcon ConnectionType
public bool IsWireless
{
get
{
var enumerator = _device.GetProperty<string>(DevicePropertyDevice.EnumeratorName);

return enumerator.Equals("USB", StringComparison.InvariantCultureIgnoreCase)
? EFontAwesomeIcon.Brands_Usb
: EFontAwesomeIcon.Brands_Bluetooth;
return !enumerator.Equals("USB", StringComparison.InvariantCultureIgnoreCase);
}
}

/// <summary>
/// The connection protocol used by this device.
/// </summary>
public EFontAwesomeIcon ConnectionType =>
!IsWireless
? EFontAwesomeIcon.Brands_Usb
: EFontAwesomeIcon.Brands_Bluetooth;

/// <summary>
/// Last time this device has been seen connected (applies to Bluetooth connected devices only).
/// </summary>
Expand Down
15 changes: 15 additions & 0 deletions DSHMC/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# DsHidMini Control Utility (DSHMC)

Portable single-executable .NET Framework 4.6 application to read and alter driver properties.

## Sources & 3rd party credits

- [Adonis UI](https://benruehl.github.io/adonis-ui/)
- [ControlzEx](https://github.com/ControlzEx/ControlzEx)
- [Fody](https://github.com/Fody/Fody)
- [Costura](https://github.com/Fody/Costura)
- [FontAwesome5](https://github.com/MartinTopfstedt/FontAwesome5)
- [Json.NET](https://www.newtonsoft.com/json)
- [PInvoke.Kernel32](https://github.com/dotnet/pinvoke)
- [PropertyChanged](https://github.com/Fody/PropertyChanged)
- [Serilog](https://serilog.net/)
49 changes: 36 additions & 13 deletions DSHMC/UI/Devices/DeviceDetailsView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@
TextOptions.TextRenderingMode="ClearType" />
</DockPanel>
</StackPanel>


</Grid>
</ControlTemplate>
</ToolTip.Template>
Expand Down Expand Up @@ -236,8 +234,6 @@
TextOptions.TextRenderingMode="ClearType" />
</DockPanel>
</StackPanel>


</Grid>
</ControlTemplate>
</ToolTip.Template>
Expand Down Expand Up @@ -284,14 +280,28 @@
</DockPanel.ToolTip>
</DockPanel>

<!-- Last seen -->
<!-- Last seen and Disconnect -->
<TextBlock Grid.Row="4" Grid.Column="0">Last connected (wireless):</TextBlock>
<TextBox Grid.Row="4" Grid.Column="2"
Width="165"
Margin="{adonisUi:Space 1}"
extensions:WatermarkExtension.Watermark="Unavailable"
Text="{Binding Path=SelectedDevice.LastConnected, Mode=OneWay}">
<TextBox.ToolTip>
<DockPanel Grid.Row="4" Grid.Column="2" LastChildFill="False">
<TextBox Width="165"
Margin="{adonisUi:Space 1}"
extensions:WatermarkExtension.Watermark="Unavailable"
Text="{Binding Path=SelectedDevice.LastConnected, Mode=OneWay}" />
<Button Click="DeviceDisconnect_OnClick"
Visibility="{Binding Path=SelectedDevice.IsWireless, Converter={StaticResource VisibleIfTrueConverter}}">
<Button.Template>
<ControlTemplate>
<Border>
<fa5:ImageAwesome
Icon="Regular_SadTear"
VerticalAlignment="Center"
Width="16" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>

<DockPanel.ToolTip>
<ToolTip controlzex:ToolTipAssist.AutoMove="True">
<ToolTip.Template>
<ControlTemplate>
Expand All @@ -309,13 +319,26 @@
Text="Last time this device has been connected via Bluetooth"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="ClearType" />
<DockPanel LastChildFill="False">
<fa5:ImageAwesome
Icon="Regular_SadTear"
VerticalAlignment="Center"
Margin="{adonisUi:Space 1}"
Width="16" />
<TextBlock Margin="{adonisUi:Space 1}"
Foreground="WhiteSmoke"
FontSize="16"
Text="= Click to disconnect this device now."
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="ClearType" />
</DockPanel>
</StackPanel>
</Grid>
</ControlTemplate>
</ToolTip.Template>
</ToolTip>
</TextBox.ToolTip>
</TextBox>
</DockPanel.ToolTip>
</DockPanel>

<!-- HID Device Mode -->
<TextBlock Grid.Row="5" Grid.Column="0">HID device mode:</TextBlock>
Expand Down
14 changes: 13 additions & 1 deletion DSHMC/UI/Devices/DeviceDetailsView.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using Nefarius.DsHidMini.MVVM;
using Nefarius.DsHidMini.Util;

namespace Nefarius.DsHidMini.UI.Devices
{
Expand Down Expand Up @@ -32,5 +34,15 @@ await Task.Run(() =>
}
});
}

private void DeviceDisconnect_OnClick(object sender, RoutedEventArgs e)
{
var tb = (Button) e.OriginalSource;
var vm = (MainViewModel) tb.DataContext;

var mac = PhysicalAddress.Parse(vm.SelectedDevice.DeviceAddress);

BluetoothHelper.DisconnectRemoteDevice(mac);
}
}
}
50 changes: 50 additions & 0 deletions DSHMC/Util/BluetoothHelper.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
using System;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using PInvoke;

namespace Nefarius.DsHidMini.Util
{
public static class BluetoothHelper
{
private const uint IOCTL_BTH_DISCONNECT_DEVICE = 0x41000C;

public static bool IsBluetoothRadioAvailable
{
get
Expand All @@ -25,6 +30,51 @@ public static bool IsBluetoothRadioAvailable
}
}

/// <summary>
/// Instruct host radio to disconnect a given remote device.
/// </summary>
/// <param name="device">The MAC address of the remote device.</param>
public static void DisconnectRemoteDevice(PhysicalAddress device)
{
var radioParams = new BLUETOOTH_FIND_RADIO_PARAMS();
radioParams.Init();

var findHandle = BluetoothFindFirstRadio(ref radioParams, out var radioHandle);

if (findHandle == IntPtr.Zero)
return;

var payloadSize = Marshal.SizeOf<ulong>();
var payload = Marshal.AllocHGlobal(payloadSize);
var raw = new byte[] {0x00, 0x00}.Concat(device.GetAddressBytes()).Reverse().ToArray();
var value = (long) BitConverter.ToUInt64(raw, 0);

Marshal.WriteInt64(payload, value);

try
{
using (var safeHandle = new Kernel32.SafeObjectHandle(radioHandle))
{
Kernel32.DeviceIoControl(
safeHandle,
unchecked((int)IOCTL_BTH_DISCONNECT_DEVICE),
payload,
payloadSize,
IntPtr.Zero,
0,
out _,
IntPtr.Zero
);
}
}
finally
{
Marshal.FreeHGlobal(payload);
}

BluetoothFindRadioClose(findHandle);
}

[DllImport("BluetoothApis.dll", SetLastError = true)]
private static extern IntPtr
BluetoothFindFirstRadio(ref BLUETOOTH_FIND_RADIO_PARAMS pbtfrp, out IntPtr phRadio);
Expand Down
11 changes: 0 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ Pre-built binaries and instructions are provided [on the releases page](../../re

The following awesome resources have made this project possible:

### References

- [Eleccelerator Wiki - DualShock 3](http://eleccelerator.com/wiki/index.php?title=DualShock_3)
- [Eleccelerator - USB Descriptor and Request Parser](http://eleccelerator.com/usbdescreqparser/)
- [HID Usage Tables](https://usb.org/sites/default/files/documents/hut1_12v2.pdf)
Expand All @@ -103,12 +101,3 @@ The following awesome resources have made this project possible:
- [The HID Page](http://janaxelson.com/hidpage.htm)
- [uthash - a hash table for C structures](https://github.com/troydhanson/uthash)
- [FirstPlatoLV/EmuController](https://github.com/FirstPlatoLV/EmuController)

### .NET Dependencies

- [Adonis UI](https://benruehl.github.io/adonis-ui/)
- [FontAwesome5](https://github.com/MartinTopfstedt/FontAwesome5)
- [ControlzEx](https://github.com/ControlzEx/ControlzEx)
- [Fody](https://github.com/Fody/Fody)
- [Costura](https://github.com/Fody/Costura)
- [Serilog](https://serilog.net/)