/
Program.cs
212 lines (180 loc) · 7.69 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
using System;
using System.Threading.Tasks;
using Usb.Net.Sample;
using Device.Net;
using Microsoft.Extensions.Logging;
using System.Reactive.Linq;
using System.Collections.Generic;
using System.Linq;
using Device.Net.Windows;
#if !LIBUSB
using SerialPort.Net.Windows;
using Hid.Net.Windows;
using Usb.Net.Windows;
#else
using Device.Net.LibUsb;
#endif
namespace Usb.Net.WindowsSample
{
internal class Program
{
#region Fields
private static ILoggerFactory _loggerFactory;
private static IDeviceFactory _trezorFactories;
#if !LIBUSB
private static readonly IDeviceFactory _allFactories = new WindowsSerialPortDeviceFactory(_loggerFactory)
.Aggregate(WindowsUsbDeviceFactoryExtensions.CreateWindowsUsbDeviceFactory(_loggerFactory))
.Aggregate(WindowsUsbDeviceFactoryExtensions.CreateWindowsUsbDeviceFactory(_loggerFactory, classGuid: WindowsDeviceConstants.GUID_DEVINTERFACE_USB_DEVICE))
.Aggregate(WindowsHidDeviceFactoryExtensions.CreateWindowsHidDeviceFactory(_loggerFactory));
#endif
private static TrezorExample _DeviceConnectionExample;
#endregion
#region Main
private static async Task Main()
{
_loggerFactory = LoggerFactory.Create((builder) => builder.AddDebug());
//Register the factories for creating Usb devices. This only needs to be done once.
#if LIBUSB
_trezorFactories = new List<IDeviceFactory>
{
TrezorExample.UsbDeviceDefinitions.CreateLibUsbDeviceFactory(_loggerFactory)
}.Aggregate(_loggerFactory);
#else
_trezorFactories = new List<IDeviceFactory>
{
TrezorExample.UsbDeviceDefinitions.CreateWindowsUsbDeviceFactory(_loggerFactory),
TrezorExample.HidDeviceDefinitions.CreateWindowsHidDeviceFactory(_loggerFactory),
}.Aggregate(_loggerFactory);
#endif
_DeviceConnectionExample = new TrezorExample(_trezorFactories, _loggerFactory);
_DeviceConnectionExample.TrezorInitialized += DeviceConnectionExample_TrezorInitialized;
_DeviceConnectionExample.TrezorDisconnected += DeviceConnectionExample_TrezorDisconnected;
Go().Wait();
}
private static async Task Go()
{
var menuOption = await Menu();
switch (menuOption)
{
case 1:
try
{
await _DeviceConnectionExample.InitializeTrezorAsync();
await DisplayDataAsync();
_DeviceConnectionExample.Dispose();
GC.Collect();
await Task.Delay(10000);
}
catch (Exception ex)
{
Console.Clear();
Console.WriteLine(ex.ToString());
}
Console.ReadKey();
break;
case 2:
Console.Clear();
DisplayWaitMessage();
_DeviceConnectionExample.StartListening();
break;
#if !LIBUSB
case 3:
Console.Clear();
await DisplayTemperature();
while (true)
{
await Task.Delay(1000);
}
#endif
default:
Console.WriteLine("That's not an option");
break;
}
}
#if !LIBUSB
#pragma warning disable CA2000
private static async Task DisplayTemperature()
{
//Connect to the device by product id and vendor id
var temperDevice = await new FilterDeviceDefinition(vendorId: 0x413d, productId: 0x2107, usagePage: 65280)
.CreateWindowsHidDeviceManager(_loggerFactory)
.ConnectFirstAsync()
.ConfigureAwait(false);
//Create the observable
var observable = Observable
.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(.1))
.SelectMany(_ => Observable.FromAsync(() => temperDevice.WriteAndReadAsync(new byte[] { 0x00, 0x01, 0x80, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00 })))
.Select(data => (data.Data[4] & 0xFF) + (data.Data[3] << 8))
//Only display the temperature when it changes
.Distinct()
.Select(temperatureTimesOneHundred => Math.Round(temperatureTimesOneHundred / 100.0m, 2, MidpointRounding.ToEven));
//Subscribe to the observable
observable.Subscribe(t => Console.WriteLine($"Temperature is {t}"));
//Note: in a real scenario, we would dispose of the subscription afterwards. This method runs forever.
}
#pragma warning restore CA2000
#endif
#endregion
#region Event Handlers
private static void DeviceConnectionExample_TrezorDisconnected(object sender, EventArgs e)
{
Console.Clear();
Console.WriteLine("Disconnected.");
DisplayWaitMessage();
}
private static async void DeviceConnectionExample_TrezorInitialized(object sender, EventArgs e)
{
try
{
Console.Clear();
await DisplayDataAsync();
}
catch (Exception ex)
{
Console.Clear();
Console.WriteLine(ex.ToString());
}
}
#endregion
#region Private Methods
private static async Task<int> Menu()
{
while (true)
{
Console.Clear();
#if !LIBUSB
var devices = await _allFactories.GetConnectedDeviceDefinitionsAsync();
Console.WriteLine("Currently connected devices:\r\n");
Console.WriteLine(string.Join("\r\n",
devices
.OrderBy(d => d.Manufacturer)
.ThenBy(d => d.ProductName)
.Select(d => $"{d.Manufacturer} - {d.ProductName} ({d.DeviceType} - {d.ClassGuid})\r\nDevice Path: {d.DeviceId}\r\nVendor: {d.VendorId} Product Id: {d.ProductId}\r\n")));
#endif
Console.WriteLine("Console sample. This sample demonstrates either writing to the first found connected device, or listening for a device and then writing to it. If you listen for the device, you will be able to connect and disconnect multiple times. This represents how users may actually use the device.");
Console.WriteLine();
Console.WriteLine("1. Write To Connected Device");
Console.WriteLine("2. Listen For Device");
Console.WriteLine("3. Temperature Monitor (Observer Design Pattern - https://docs.microsoft.com/en-us/dotnet/standard/events/how-to-implement-a-provider#example)");
var consoleKey = Console.ReadKey();
if (consoleKey.KeyChar == '1') return 1;
if (consoleKey.KeyChar == '2') return 2;
if (consoleKey.KeyChar == '3') return 3;
}
}
private static async Task DisplayDataAsync()
{
var bytes = await _DeviceConnectionExample.WriteAndReadFromDeviceAsync();
Console.Clear();
Console.WriteLine("Device connected. Output:");
DisplayData(bytes);
}
private static void DisplayData(byte[] readBuffer)
{
Console.WriteLine(string.Join(' ', readBuffer));
Console.ReadKey();
}
private static void DisplayWaitMessage() => Console.WriteLine("Waiting for device to be plugged in...");
#endregion
}
}