so close daddy uwu

This commit is contained in:
Maff 2019-08-27 01:20:54 +01:00
parent 714ef45350
commit a606010f98
12 changed files with 397 additions and 213 deletions

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using Vadavo.NEscPos;
using Vadavo.NEscPos.Printable;
using Crc;
namespace libsharperang {
public abstract class Base {
@ -12,15 +8,14 @@ namespace libsharperang {
USB,
Bluetooth
}
public Printer printer;
internal DataTransforms transform=new DataTransforms();
//public Printer printer;
public string Model { get; internal set; }
public string FirmwareVer { get; internal set; }
public int Battery { get; internal set; }
public ConnectionType ActiveConnectionType { get; internal set; } = ConnectionType.None;
internal bool InitialiseConnection() => false;
internal bool DestroyConnection() => false;
public Base() => InitialiseConnection();
~Base() => DestroyConnection();
}

View File

@ -0,0 +1,26 @@
using System;
using Crc;
namespace libsharperang {
public class DataTransforms {
public class CrcSum : Crc32Base {
public uint CrcKey;
public CrcSum() : base(0x77c40d4d^0x35769521, 0xffffffff, 0xffffffff, false, false) => CrcKey=0x77c40d4d;
public CrcSum(uint Key) : base(Key^0x35769521, 0xffffffff, 0xffffffff, false, false) => CrcKey=Key;
public CrcSum(uint Key, bool _) : base(Key, 0xffffffff, 0xffffffff, false, false) => CrcKey=Key;
}
public CrcSum CRC;
public bool IsCrcInitialised() => (CRC!=null);
public void InitialiseCrc() => CRC=new CrcSum();
public void InitialiseCrc(uint Key) => CRC=new CrcSum(Key);
public void InitialiseCrc(uint Key, bool _) => CRC=new CrcSum(Key, _);
public uint GetCrcKey() {
if (!IsCrcInitialised()) InitialiseCrc();
return CRC.CrcKey;
}
public byte[] GetCrcKeyBytes() {
if (!IsCrcInitialised()) InitialiseCrc();
return BitConverter.GetBytes(GetCrcKey());
}
}
}

12
libsharperang/IPrinter.cs Normal file
View File

@ -0,0 +1,12 @@
using LibUsbDotNet;
namespace libsharperang {
interface IPrinter {
UsbDevice uDv { get; set; }
UsbEndpointWriter uWr { get; set; }
UsbEndpointReader uRd { get; set; }
bool Initialised();
bool WriteBytes(byte[]Frame);
byte[] ReadBytes();
}
}

View File

@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using LibUsbDotNet;
using Vadavo.NEscPos.Connectors;
namespace libsharperang
{
public class IUsb : IPrinterConnector
{
internal UsbDevice iPrinter;
private UsbEndpointReader pReader;
private UsbEndpointWriter pWriter;
public bool Initialised() => (bool)iPrinter?.IsOpen;
public void Dispose()
{
pReader?.Dispose();
pWriter?.Dispose();
IUsbDevice p = iPrinter as IUsbDevice;
_ = p?.ReleaseInterface(0);
_ = iPrinter?.Close();
throw new NotImplementedException();
}
public byte[] Read()
{
if (pReader == null) pReader = iPrinter?.OpenEndpointReader(LibUsbDotNet.Main.ReadEndpointID.Ep01);
byte[] bRead = new byte[1024];
_ = pReader.Read(bRead, 100, out int _);
return bRead;
}
public void Write(byte[] data)
{
if (pWriter == null) pWriter = iPrinter?.OpenEndpointWriter(LibUsbDotNet.Main.WriteEndpointID.Ep01);
pWriter?.Write(data, 100, out int _);
}
}
}

View File

@ -5,11 +5,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Device.Net" Version="3.0.0" />
<PackageReference Include="CrcDotNET" Version="1.0.3" />
<PackageReference Include="LibUsbDotNet" Version="2.2.29" />
<PackageReference Include="NativeUsbLib" Version="1.4.6" />
<PackageReference Include="Vadavo.NEscPos" Version="0.0.4" />
<PackageReference Include="WinUSBNet" Version="1.0.3" />
</ItemGroup>
</Project>

View File

@ -1,64 +1,166 @@
using System;
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using LibUsbDotNet;
using LibUsbDotNet.Main;
using Vadavo.NEscPos;
/*
* the official software seems to transmit a CRC "token" on first detecting the printer (Paperang P1; MiaoMiaoJi):
* Frame.Begin, PrinterCmd.TransmitCrc, 0x4d0dc477, 0x699295ed, Frame.End
* This differs when connected to a Paperang P2:
* Frame.Begin, PrinterCmd.TransmitCrc, 0x18d2a3df, 0x4ec92265, Frame.End
*
* It's not immediately clear to me whether the segment normally containing the CRC is itself a CRC of the token
* or if the token is simply 8 bytes rather than 4 and the CRC segment of the frame is omitted for this operation
*
* From what I can tell, calculation of a CRC32 checksum can involve a polynomial and a 'check' value.
* It may thus be possible that the Data value is the 'check' value, and the CRC value is the polynomial..
* In ihciah/miaomiaoji:message_process:crc32(data), the CRC32 value is generated by the zlib.crc32(d,v) function
* however I've been unable to reproduce a checksum of 0x906f4576 from a starting value of 0x00 and a polynomial
* of any variation of 0x4d0dc477, 0x699295ed
* Disassembly of the official software indicates it -is- crc32 that's in use, however further investigation is needed
* Finally, it's not clear whether this value transmitted is required to remain the same at all times
* or if the software may use whatever value it wants (whether this is simply a handshake, or whether the specific
* value "unlocks" communication with the printer
*
* standard presence checks performed by the official software consist of simply sending two messages every two seconds:
* Frame.Begin, PrinterCmd.SessionStart, 0x0000, 0x906f4576, Frame.End
* Frame.Begin, PrinterCmd.SessionEnd, 0x00, 0x906f4576, Frame.End
*
* printing out a blank page yields a 1018-byte payload formed of:
* Frame.Begin, PrinterCmd.BeginPrint, 0x00*1008, 0x83c0e20f, Frame.End
* followed by a 634-byte payload formed of:
* Frame.Begin, PrinterCmd.ContinuePrint, 0x00*624, 0xbc1b6bf4, Frame.End
* followed by a 12-byte payload formed of:
* Frame.Begin, PrinterCmd.SessionEnd, 0x2c01, 0xa8347338, Frame.end
*
* printing out a single dash ('-') yields a 1018-byte payload formed of:
* Frame.Begin, PrinterCmd.BeginPrint, 0x00*858, 0x0fe0, 0x00*46, 0xfe0, 0x00*94, 0xc53ad770, Frame.End
* followed by a 634-byte payload formed of:
* Frame.Begin, PrinterCmd.ContinuePrint, 0x00*624, 0xbc1b6bf4, Frame.End
* followed by a 12-byte payload formed of:
* Frame.Begin, PrinterCmd.SessionEnd, 0x2c01, 0xa8347338, Frame.end
*
* based on the above we can extrapolate that:
* - 12 bytes is the minimum size of a payload, and 1018 bytes is the maximum
* - all frames sent to the printer follow the structure of:
* -- Frame.Begin (1 byte)
* -- PrinterCmd.* (4 bytes)
* -- Data (min. 2 bytes? max. 1008 bytes)
* -- CRC32 sum of the Data block (4 bytes)
* -- Frame.End (1 byte)
*
* Also of interest is that, when a model P2 is connected, the printer will actually reply to messages
* eg., for the standard presence check of Frame.Begin, 0x1a000200, 0x0000, CRC, Frame.End
* the printer will reply with an almost identical message:
* Frame.Begin, 0x1a000100, 0x00, CRC, Frame.End
* The Data segment is a different size (one byte) and the printer appears to be doing its own CRC calculation
* Finally, the command, 0x1a000100, appears to be an acknowledgement of sorts in response to PrinterCmd.SessionEnd (byte 3 changing from 0x02 to 0x01)
*/
namespace libsharperang {
public class USB : Base {
//both P1 and P2 models share the same idV and idP over USB
public readonly ushort idVendor=0x4348;
public readonly ushort idProduct=0x5584;
//differentiating between the two is a case of checking the product name
//P1 is identified as "MiaoMiaoji" or "MTTII Printer"
//P2 is identified as "Paperang_P2"
//Notable is that the idV and idP appear to belong not to Paperang, but to a generic CH34x printer adaptor device
// so it should be a constraint to check that the device descriptors match known details for supported devices,
// not just idV and idP
public UsbDevice pDevice;
public List<UsbRegistry> pInstances;
public List<Guid> pIds;
public IUsb pUsb;
public USB() {
ActiveConnectionType=ConnectionType.USB;
InitUSB();
public class Frame {
public DataTransforms transformer=new DataTransforms();
public enum Opcode {
SessionBegin = 10,
SessionEnd,
PrintBegin = 20,
PrintContinue,
CrcTransmit = 30
}
~USB() => CloseUSB();
private byte[] ResolveOpcode(Opcode opcode) {
switch (opcode) {
case Opcode.SessionBegin: return new byte[] { 0x06, 0x00, 0x02, 0x00 };
case Opcode.SessionEnd: return new byte[] { 0x1a, 0x00, 0x02, 0x00 };
case Opcode.PrintBegin: return new byte[] { 0x00, 0x01, 0xf0, 0x03 };
case Opcode.PrintContinue: return new byte[] { 0x00, 0x01, 0xf0, 0x02 };
case Opcode.CrcTransmit: return new byte[] { 0x18, 0x01, 0x04, 0x00 };
default: throw new NullReferenceException();
}
}
private byte[] SwapEndianness(uint value) {
uint b1 = (value >> 0) & 0xff;
uint b2 = (value >> 8) & 0xff;
uint b3 = (value >> 16) & 0xff;
uint b4 = (value >> 24) & 0xff;
return BitConverter.GetBytes((b1 << 24) | (b2 << 16) | (b3 << 8) | (b4 << 0));
}
public byte[] Build(Opcode opcode, byte[] data) => Build(opcode, data, transformer);
public byte[] Build(Opcode opcode, byte[] data, DataTransforms transformer) {
if (!transformer.IsCrcInitialised()) transformer.InitialiseCrc();
byte[] result=new byte[data.Length+10];
result[0]=0x02;
result[result.Length-1]=0x03;
Buffer.BlockCopy(ResolveOpcode(opcode), 0, result, 1, 4);
Buffer.BlockCopy(data, 0, result, 5, data.Length);
Buffer.BlockCopy(transformer.CRC.ComputeHash(data), 0, result, result.Length-5, 4);
return result;
}
public byte[] BuildTransmitCrc() {
DataTransforms _=new DataTransforms();
_.InitialiseCrc(0x35769521, true);
return Build(Opcode.CrcTransmit, transformer.GetCrcKeyBytes(), _);
}
}
public class USBPrinter : Base, IPrinter {
private UsbDevice _uDv;
private UsbEndpointWriter _uWr;
private UsbEndpointReader _uRd;
UsbDevice IPrinter.uDv { get => _uDv; set { } }
UsbEndpointWriter IPrinter.uWr { get => _uWr; set { } }
UsbEndpointReader IPrinter.uRd { get => _uRd; set { } }
new internal bool InitialiseConnection() => InitUSB();
private ushort idVendor=0x4348;
private ushort idProduct=0x5584;
public Frame builder=new Frame();
public List<Guid> IDs;
public List<UsbRegistry> Devices;
public USBPrinter() {
ActiveConnectionType=ConnectionType.USB;
Initialise();
}
~USBPrinter() {
Close();
ActiveConnectionType=ConnectionType.None;
}
public bool InitUSB() {
//NOTE - in order for this to work, you must use Zadig to change the driver for
// the printer from usbprint to WinUSB
//On MacOS and Linux libusb should "just work" here - testing is pending however.
if (UsbDevice.AllDevices.Count == 0) return false;
//genuinely just having some fun with Linq, don't judge me.
//TODO: work out a way of distinguishing multiple devices with same GUID
// which happens when two of the same device are connected
// the only thing that differs seemingly is the Address
pInstances = (from d in UsbDevice.AllDevices
public void Initialise() {
if (UsbDevice.AllDevices.Count == 0) throw new KeyNotFoundException("No WinUSB or LibUSB devices found");
Devices=(from d in UsbDevice.AllDevices
where d.Vid == idVendor && d.Pid == idProduct
select d)
.ToList<UsbRegistry>();
pIds = (from d in pInstances
if (Devices.Count == 0) throw new KeyNotFoundException("No supported devices found!");
IDs=(from d in Devices
select d.DeviceInterfaceGuids[0])
.Distinct()
.ToList<Guid>();
return (pIds.Count > 0);
}
public List<int> GetAddressesFromGuid(Guid deviceId) => (from d in UsbDevice.AllDevices
where d.DeviceInterfaceGuids.Contains(deviceId)
select d.DeviceProperties.Where(k => k.Key=="Address").FirstOrDefault().Value).ToList().ConvertAll(v => (int)v);
public bool OpenUSB() {
if (UsbDevice.AllDevices.Count == 0) return false;
if (pIds.Count == 0) return false;
return OpenUSB(pIds.FirstOrDefault());
select d.DeviceProperties
.Where(k => k.Key=="Address")
.FirstOrDefault().Value)
.ToList().ConvertAll(v => (int)v);
public string FoundPrinterGuids() => IDs?
.ConvertAll(p => p.ToString())
.Aggregate((a, b) => a+","+b);
public string FoundPrinterGuidAddrs(Guid deviceId) => GetAddressesFromGuid(deviceId)
.ConvertAll(a => a.ToString())
.Aggregate((a, b) => a+","+b);
public string FoundProdIds() => _uDv?.Info.ProductString;
public bool Open() {
if (UsbDevice.AllDevices.Count == 0 ||
!IsPrinterPresent()) return false;
return Open(IDs.FirstOrDefault());
}
public bool OpenUSB(Guid deviceId) => OpenUSB(deviceId, GetAddressesFromGuid(deviceId).FirstOrDefault());
public bool OpenUSB(Guid deviceId, int deviceIndex) {
public bool Open(Guid deviceId) => Open(deviceId,
GetAddressesFromGuid(deviceId).FirstOrDefault());
public bool Open(Guid deviceId, int deviceIndex) {
if (!IsPrinterPresent()) return false;
//first thought is to say "forgive me lord for i have sinned" but i am absolutely not repentant for this
bool OpenResult = (from d in UsbDevice.AllDevices
where d.DeviceInterfaceGuids.Contains(deviceId) &&
@ -66,34 +168,40 @@ namespace libsharperang {
select d)
.FirstOrDefault()
.Open(out UsbDevice handle);
pDevice=handle;
_uDv=handle;
return OpenResult;
}
public bool ClaimUSB()
{
if (pDevice is null || pDevice.IsOpen) return false;
IUsbDevice p = pDevice as IUsbDevice;
public bool Claim() {
if (!IsPrinterPresent() ||
_uDv is null ||
!_uDv.IsOpen) return false;
IUsbDevice p = _uDv as IUsbDevice;
p?.SetConfiguration(1);
p?.ClaimInterface(0);
pUsb.iPrinter = pDevice;
printer = new Printer(pUsb);
return true;
}
public bool CloseUSB()
{
pUsb?.Dispose();
pDevice?.Close();
return true;
public void Close() {
_uWr?.Dispose();
_uRd?.Dispose();
IUsbDevice p=_uDv as IUsbDevice;
_=p?.ReleaseInterface(0);
_=p?.Close();
_uDv?.Close();
}
public bool IsPrinterPresent() => (Devices != null && Devices.Count > 0);
bool IPrinter.Initialised() => Initialised();
byte[] IPrinter.ReadBytes() => ReadBytes();
bool IPrinter.WriteBytes(byte[] Frame) => WriteBytes(Frame);
public bool Initialised() => (_uDv!=null);
public byte[] ReadBytes() {
if (_uRd==null) _uRd=_uDv?.OpenEndpointReader(ReadEndpointID.Ep01);
byte[] bRead=new byte[1024];
_=_uRd.Read(bRead, 100, out int _);
return bRead;
}
public bool WriteBytes(byte[] Frame) {
if (_uWr==null) _uWr=_uDv?.OpenEndpointWriter(WriteEndpointID.Ep02);
return (_uWr.Write(Frame, 100, out int _) == ErrorCode.None);
}
public string FoundPrinterGuids() => pIds
.ConvertAll(p => p.ToString())
.Aggregate((a, b) => a+","+b);
public string FoundPrinterGuidAddrs(Guid deviceId) => GetAddressesFromGuid(deviceId)
.ConvertAll(a => a.ToString())
.Aggregate((a, b) => a+","+b);
public string FoundProdIds() => pDevice?.Info.ProductString;
}
}

View File

@ -1,17 +1,9 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows;
namespace sharperang
{
namespace sharperang {
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public partial class App : Application {
}
}

View File

@ -16,6 +16,7 @@
<Grid Margin="10,10,10,10">
<Button x:Name="btClearLog" Content="Clear Log" HorizontalAlignment="Left" Width="75" Margin="0,2,0,152.2" Click="BtClearLog_Click"/>
<Button x:Name="btInitUSB" Content="Initialise USB" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,23,0,0" IsDefault="True" Height="21" Click="BtInitUSB_Click"/>
<Button x:Name="btTestLine" Content="Print test" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,44,0,0" IsDefault="True" Height="21" Click="BtTestLine_Click"/>
</Grid>
</GroupBox>
<TextBox x:Name="tbLog" HorizontalAlignment="Left" Margin="10,232,0,10" TextWrapping="Wrap" Width="774" Grid.ColumnSpan="3" AllowDrop="False" IsReadOnly="True" IsUndoEnabled="False" VerticalScrollBarVisibility="Visible" ScrollViewer.CanContentScroll="True" Text="{Binding Path=LogBuffer}"/>

View File

@ -1,5 +1,6 @@
using System.Windows;
using libsharperang;
using libsharperang;
using System;
using System.Windows;
namespace sharperang {
/// <summary>
@ -7,28 +8,25 @@ namespace sharperang {
/// </summary>
public partial class MainWindow : Window {
private LogBridge logger;
//private LibSharperang printer;
private libsharperang.USB printer;
private USBPrinter printer=new USBPrinter();
public MainWindow() {
InitializeComponent();
logger = new LogBridge();
gMain.DataContext = logger;
logger.Info("Application started");
}
private void BtClearLog_Click(object sender, RoutedEventArgs e) =>
logger.ClearBuffer();
private void BtInitUSB_Click(object sender, RoutedEventArgs e) {
logger.Info("USB Initialising");
//printer = new LibSharperang(logger);
printer = new libsharperang.USB();
logger.Debug("found Guids are "+printer.FoundPrinterGuids());
printer.pIds.ForEach(p => logger.Debug("found Addrs for guid "+p.ToString()+" are "+printer.FoundPrinterGuidAddrs(p)));
logger.Debug("open gave "+printer.OpenUSB(printer.pIds[0]));
logger.Debug("claim gave " + printer.ClaimUSB());
logger.Debug("IUsb gave " + printer.pUsb.Initialised());
logger.Debug("Printer done init " + printer.printer);
}
logger.Debug("IsPrinterPresent => "+printer.IsPrinterPresent());
logger.Debug("FoundPrinterGuids => "+printer.FoundPrinterGuids());
printer?.IDs?.ForEach(p => logger.Debug("FoundPrinterGuidAddrs "+p.ToString()+" => "+printer?.FoundPrinterGuidAddrs(p)));
logger.Debug("OpenUSB => "+printer?.Open());
logger.Debug("ClaimUSB => " + printer?.Claim());
//logger.Debug("IUsb::Initialised => " + printer?.pUsb?.Initialised());
}
private void BtTestLine_Click(object sender, RoutedEventArgs e) => logger.Debug("printer::TestCRC() => "+BitConverter.ToString(printer.builder.BuildTransmitCrc()).Replace('-',' '));
}
}

View File

@ -1,6 +1,4 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;

View File

@ -1,11 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Device.Net" version="3.0.0" targetFramework="net472" />
<package id="Device.Net.LibUsb" version="3.0.0" targetFramework="net472" />
<package id="JetBrains.Annotations" version="10.2.1" targetFramework="net472" />
<package id="LibUsbDotNet" version="2.2.29" targetFramework="net472" />
<package id="NativeUsbLib" version="1.4.6" targetFramework="net472" />
<package id="Usb.Net" version="3.0.0" targetFramework="net472" />
<package id="UsbInfo" version="1.0.1" targetFramework="net472" />
<package id="WinUSBNet" version="1.0.3" targetFramework="net472" />
<package id="Microsoft.Win32.Registry" version="4.5.0" targetFramework="net472" />
<package id="System.Collections" version="4.3.0" targetFramework="net472" />
<package id="System.Collections.Specialized" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.FileVersionInfo" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net472" />
<package id="System.Diagnostics.TraceSource" version="4.3.0" targetFramework="net472" />
<package id="System.Drawing.Common" version="4.5.1" targetFramework="net472" />
<package id="System.IO" version="4.3.0" targetFramework="net472" />
<package id="System.IO.FileSystem" version="4.3.0" targetFramework="net472" />
<package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime" version="4.3.1" targetFramework="net472" />
<package id="System.Runtime.Extensions" version="4.3.1" targetFramework="net472" />
<package id="System.Runtime.Handles" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net472" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net472" />
<package id="System.Security.AccessControl" version="4.5.0" targetFramework="net472" />
<package id="System.Security.Principal.Windows" version="4.5.1" targetFramework="net472" />
<package id="System.Text.Encoding" version="4.3.0" targetFramework="net472" />
<package id="System.Threading" version="4.3.0" targetFramework="net472" />
<package id="System.Threading.Overlapped" version="4.3.0" targetFramework="net472" />
<package id="System.Threading.Thread" version="4.3.0" targetFramework="net472" />
<package id="System.Threading.ThreadPool" version="4.3.0" targetFramework="net472" />
</packages>

View File

@ -14,6 +14,21 @@
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -35,23 +50,87 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Device.Net, Version=3.0.0.0, Culture=neutral, PublicKeyToken=7b6bc3f8fb80505e, processorArchitecture=MSIL">
<HintPath>..\packages\Device.Net.3.0.0\lib\net45\Device.Net.dll</HintPath>
</Reference>
<Reference Include="Device.Net.LibUsb, Version=3.0.0.0, Culture=neutral, PublicKeyToken=7b6bc3f8fb80505e, processorArchitecture=MSIL">
<HintPath>..\packages\Device.Net.LibUsb.3.0.0\lib\netstandard2.0\Device.Net.LibUsb.dll</HintPath>
</Reference>
<Reference Include="JetBrains.Annotations, Version=10.2.1.0, Culture=neutral, PublicKeyToken=1010a0d8d6380325, processorArchitecture=MSIL">
<HintPath>..\packages\JetBrains.Annotations.10.2.1\lib\net\JetBrains.Annotations.dll</HintPath>
</Reference>
<Reference Include="LibUsbDotNet.LibUsbDotNet, Version=2.2.0.0, Culture=neutral, PublicKeyToken=c677239abe1e02a9, processorArchitecture=MSIL">
<HintPath>..\packages\LibUsbDotNet.2.2.29\lib\net45\LibUsbDotNet.LibUsbDotNet.dll</HintPath>
</Reference>
<Reference Include="NativeUsbLib, Version=1.4.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NativeUsbLib.1.4.6\lib\net46\NativeUsbLib.dll</HintPath>
<Reference Include="Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Win32.Registry.4.5.0\lib\net461\Microsoft.Win32.Registry.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Specialized, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Specialized.4.3.0\lib\net46\System.Collections.Specialized.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Data" />
<Reference Include="System.Diagnostics.FileVersionInfo, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.FileVersionInfo.4.3.0\lib\net46\System.Diagnostics.FileVersionInfo.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Diagnostics.TraceSource, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.TraceSource.4.3.0\lib\net46\System.Diagnostics.TraceSource.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Drawing.Common, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Drawing.Common.4.5.1\lib\net461\System.Drawing.Common.dll</HintPath>
</Reference>
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.Extensions, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.Extensions.4.3.1\lib\net462\System.Runtime.Extensions.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.InteropServices, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Security.AccessControl, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.AccessControl.4.5.0\lib\net461\System.Security.AccessControl.dll</HintPath>
</Reference>
<Reference Include="System.Security.Principal.Windows, Version=4.1.1.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Principal.Windows.4.5.1\lib\net461\System.Security.Principal.Windows.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Overlapped, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Overlapped.4.3.0\lib\net46\System.Threading.Overlapped.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Threading.Thread, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Thread.4.3.0\lib\net46\System.Threading.Thread.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Threading.ThreadPool, Version=4.0.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.ThreadPool.4.3.0\lib\net46\System.Threading.ThreadPool.dll</HintPath>
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
@ -62,18 +141,9 @@
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="Usb.Net, Version=3.0.0.0, Culture=neutral, PublicKeyToken=7b6bc3f8fb80505e, processorArchitecture=MSIL">
<HintPath>..\packages\Usb.Net.3.0.0\lib\net45\Usb.Net.dll</HintPath>
</Reference>
<Reference Include="UsbInfo, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UsbInfo.1.0.1\lib\net471\UsbInfo.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="WinUSBNet, Version=1.0.3.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\WinUSBNet.1.0.3\lib\net35\WinUSBNet.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
@ -88,7 +158,6 @@
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="LibSharperang.cs" />
<Compile Include="LogBridge.cs" />
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
@ -128,5 +197,17 @@
<Name>libsharperang</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.7.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.7.2 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>