Add UsbController, make logging safe with Dispatcher

This commit is contained in:
mashed-potatoes 2020-06-26 21:16:27 +05:00
parent b9b3e40346
commit cc44a41f52
8 changed files with 212 additions and 19 deletions

View file

@ -8,13 +8,19 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{2F103DCF-DFBA-48B0-BEA4-D4B845532A42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2F103DCF-DFBA-48B0-BEA4-D4B845532A42}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2F103DCF-DFBA-48B0-BEA4-D4B845532A42}.Debug|x64.ActiveCfg = Debug|x64
{2F103DCF-DFBA-48B0-BEA4-D4B845532A42}.Debug|x64.Build.0 = Debug|x64
{2F103DCF-DFBA-48B0-BEA4-D4B845532A42}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2F103DCF-DFBA-48B0-BEA4-D4B845532A42}.Release|Any CPU.Build.0 = Release|Any CPU
{2F103DCF-DFBA-48B0-BEA4-D4B845532A42}.Release|x64.ActiveCfg = Release|x64
{2F103DCF-DFBA-48B0-BEA4-D4B845532A42}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -21,7 +21,7 @@ namespace PotatoNV_next.Controls
private void TelegramButton_ButtonClicked(object sender, EventArgs e)
{
Log.Debug("Clicked to Telegram button!");
Process.Start("https://t.me/RePotato");
Process.Start("https://t.me/s/RePotato");
}
}
}

View file

@ -1,22 +1,7 @@
using PotatoNV_next.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace PotatoNV_next.Controls
{

View file

@ -9,7 +9,7 @@
<Grid Margin="4">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="16" />
<RowDefinition x:Name="progressBarRowDefinition" Height="16" />
</Grid.RowDefinitions>
<TextBox x:Name="logBox"

View file

@ -28,17 +28,33 @@ namespace PotatoNV_next.Controls
"ShowProgressBar",
typeof(bool),
typeof(LogBox),
new PropertyMetadata(false)
new PropertyMetadata(false, OnPropertyChangedCallback)
);
private static void OnPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
(sender as LogBox).OnChanged();
}
protected virtual void OnChanged()
{
progressBarRowDefinition.Height = new GridLength(ShowProgressBar ? 16 : 0);
}
private void AppendLine(LogEventArgs e)
{
if (!Dispatcher.CheckAccess())
{
Dispatcher.Invoke(() => logBox.AppendText(e.Message));
return;
}
logBox.AppendText(e.Message);
}
public LogBox()
{
InitializeComponent();
OnChanged();
#if DEBUG
Log.PrintDebug = true;
#endif

View file

@ -1,4 +1,5 @@
using PotatoNV_next.Utils;
using Potato.Fastboot;
using PotatoNV_next.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
@ -18,10 +19,22 @@ namespace PotatoNV_next
{
public partial class MainWindow : Window
{
private UsbController usbController = new UsbController();
public MainWindow()
{
Icon = MediaConverter.ImageSourceFromBitmap(Properties.Resources.Fire.ToBitmap());
InitializeComponent();
usbController.AddListener(HandleDevices);
usbController.StartWorker();
}
private void HandleDevices(UsbController.Device[] devices)
{
foreach (var device in devices)
{
Log.Debug($"{device.Mode} - {device.Description}");
}
}
}
}

View file

@ -55,6 +55,28 @@
<PropertyGroup>
<ApplicationIcon>Resources\fire.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="LibUsbDotNet, Version=3.0.0.0, Culture=neutral, PublicKeyToken=c677239abe1e02a9, processorArchitecture=MSIL">
<HintPath>..\packages\LibUsbDotNet.3.0.81-alpha\lib\net45\LibUsbDotNet.dll</HintPath>
@ -71,6 +93,7 @@
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.1\lib\netstandard2.0\System.Memory.dll</HintPath>
</Reference>
@ -108,6 +131,7 @@
</Compile>
<Compile Include="Utils\Log.cs" />
<Compile Include="Utils\MediaConverter.cs" />
<Compile Include="Utils\UsbController.cs" />
<Page Include="Controls\AboutTab.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View file

@ -0,0 +1,149 @@
using Potato.Fastboot;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace PotatoNV_next.Utils
{
class UsbController
{
public struct Device
{
public enum DMode
{
DownloadVCOM,
Fastboot
}
public Device(DMode mode, string description)
{
Mode = mode;
Description = description;
}
public DMode Mode { get; }
public string Description { get; }
}
#region USB watcher
private readonly BackgroundWorker usbWorker = new BackgroundWorker();
private readonly Stopwatch watch = new Stopwatch();
private long delta = 0;
private void Watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
if (watch.ElapsedMilliseconds - delta < 100)
{
return;
}
delta = watch.ElapsedMilliseconds;
Log.Debug("New USB event, calling listener...");
UpdateList();
}
private void UsbWorker_DoWork(object sender, DoWorkEventArgs e)
{
using (var watcher = new ManagementEventWatcher())
{
var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 OR EventType = 3");
watcher.EventArrived += Watcher_EventArrived;
watcher.Query = query;
watcher.Start();
watcher.WaitForNextEvent();
}
}
public void StartWorker()
{
usbWorker.DoWork += UsbWorker_DoWork;
watch.Start();
usbWorker.RunWorkerAsync();
}
#endregion
#region Device list
private const int VID = 0x12D1, PID = 0x3609;
private Device[] cachedDevices = null;
private Device[] GetDownloadVCOMDevices()
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE ClassGuid=\"{4d36e978-e325-11ce-bfc1-08002be10318}\"");
var list = searcher.Get();
var devices = new List<Device>();
foreach (ManagementObject obj in list)
{
// Excepted format: USB\VID_12D1&PID_3609\6&127ABA2B&0&2
var sdata = obj["DeviceID"].ToString().Split('\\');
if (sdata.Length < 2 || sdata[1] != string.Format("VID_{0:X4}&PID_{1:X4}", VID, PID))
{
continue;
}
var match = Regex.Match(obj["Name"].ToString(), @"COM\d+");
if (match.Success)
{
devices.Add(new Device(
Device.DMode.DownloadVCOM,
$"{match.Value}: {obj["Description"]}"
));
}
}
return devices.ToArray();
}
private Device[] GetFastbootDevices()
{
return Fastboot.GetDevices()
.Select(x => new Device(Device.DMode.Fastboot, x))
.ToArray();
}
#endregion
#region Caller
private List<Action<Device[]>> listeners = new List<Action<Device[]>>();
private void UpdateList()
{
try
{
var list = new List<Device>();
list.AddRange(GetDownloadVCOMDevices());
list.AddRange(GetFastbootDevices());
}
catch (Exception ex)
{
Log.Error(ex.Message);
Log.Debug(ex.StackTrace);
}
//if (!Enumerable.SequenceEqual(list, cachedDevices))
//{
// Log.Debug("Sequence equal");
// return;
//}
//foreach (var listener in listeners)
//{
// listener?.Invoke(list.ToArray());
//}
}
public void AddListener(Action<Device[]> action)
{
listeners.Add(action);
}
#endregion
}
}