Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
6a8c650
FEAT - added serial Cdc Driver (tested on Atmel and GigaDevice)
alex3696 Nov 5, 2025
f03699f
Merge branch 'AddCdcDriver' into MyMaster
alex3696 Nov 5, 2025
af08e1d
Merge branch 'CustomizibleIdDriver' into MyMaster
alex3696 Nov 5, 2025
1eb4fdf
FEAT - remove min android = 26
alex3696 Nov 5, 2025
85570f9
Merge branch 'AddCdcDriver' into MyMaster
alex3696 Nov 5, 2025
03cf92e
fix - CH341A buffers data until a full endpoint-size packet (32 bytes…
alex3696 Nov 5, 2025
17d23e8
FEAT - add vendors (Atmel, GigaDevice, Arduino, Nrf) link to Cdc driv…
alex3696 Nov 6, 2025
4cb3db0
Merge branch 'ftdifix' into MyMaster
alex3696 Nov 6, 2025
0e00977
FEAT - add native android async read and write
alex3696 Nov 6, 2025
0fac7be
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 6, 2025
25961b2
Merge branch 'ftdifix' into MyMaster
alex3696 Nov 6, 2025
7fa1e20
FEAT - add native android async read and write to Cdc Driver and Ftdi
alex3696 Nov 6, 2025
edb587a
Merge branch 'fix-ch341' into MyMaster
alex3696 Nov 6, 2025
8a8fd79
Merge branch 'ftdifix' into MyMaster
alex3696 Nov 6, 2025
200b304
Merge branch 'ftdifix' into MyMaster
alex3696 Nov 6, 2025
94ad46b
update ftri filter
alex3696 Nov 6, 2025
b059595
fix ftdi filter
alex3696 Nov 6, 2025
eb6d64f
fix reader
alex3696 Nov 6, 2025
8fde2e4
fix reader
alex3696 Nov 6, 2025
8b612d8
fix reader min count
alex3696 Nov 6, 2025
28e36be
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 6, 2025
30314b4
add FIFO buffer
alex3696 Nov 7, 2025
b9af3a3
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 7, 2025
b8c06dd
introduce delegate filter for in-place filter data
alex3696 Nov 7, 2025
719fd55
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 7, 2025
fe8afc9
use filter for in-place filter data
alex3696 Nov 7, 2025
71814a2
FEAT - add FIFO buffer and tests
alex3696 Nov 10, 2025
350c57f
Merge branch 'fix-CP2102N' into MyMaster
alex3696 Nov 10, 2025
ca4008e
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 10, 2025
5057615
introduce NetDirectByteBuffer - Implemented DirectByteBuffer with a s…
alex3696 Nov 13, 2025
1e3ad2d
FEAT - replace FIFO buffer with ConcurrentQueue
alex3696 Nov 13, 2025
02f8903
Merge branch 'ftdifix' into MyMaster
alex3696 Nov 13, 2025
12afbc3
Merge branch 'fix-CP2102N' into MyMaster
alex3696 Nov 13, 2025
f682814
Merge branch 'fix-CP2102N' into MyMaster
alex3696 Nov 13, 2025
a6994d0
Merge remote-tracking branch 'origin/MyMaster' into MyMaster
alex3696 Nov 13, 2025
a158cb7
Revert "Merge remote-tracking branch 'origin/MyMaster' into MyMaster"
alex3696 Nov 13, 2025
04d002a
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 13, 2025
2156b0d
FIX - filter task start
alex3696 Nov 13, 2025
74c1767
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 13, 2025
7c97cd0
REFR - update Close and errors handle
alex3696 Nov 13, 2025
ff6f28b
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 13, 2025
654a249
REFR - add simple logger, + small fixes
alex3696 Nov 14, 2025
4bf650e
Merge branch 'LUJIAN2020:master' into AsyncReadWrite
alex3696 Nov 15, 2025
7381863
Merge branch 'LUJIAN2020:master' into fix-ch341
alex3696 Nov 15, 2025
26118ae
Merge branch 'AsyncReadWrite' into MyMaster
alex3696 Nov 17, 2025
0c3d2c6
Merge branch 'fix-ch341' into MyMaster
alex3696 Nov 17, 2025
91f6c40
FEAT - replace ConcurrentQueue buffer with Cannel
alex3696 Nov 17, 2025
e8740a3
FEAT - make FIFO Channel , fix exception, fix UsbRequest.Cancel
alex3696 Nov 21, 2025
81681c7
FEAT - introduce OpenAsync DisposeAsync
alex3696 Nov 24, 2025
c6be943
Merge commit '43ea539fa61abf5e78cf4ff80159eb45351ce60c' into MyMaster
alex3696 Nov 24, 2025
fdc0ffc
add test: IO speed
alex3696 Nov 28, 2025
916f0f6
Don't let the OS queue starve
alex3696 Nov 28, 2025
eb72c87
remove filter task
alex3696 Dec 1, 2025
3fbce24
update simple logger
alex3696 Dec 2, 2025
b26e9ff
optimizations: remove unnecessary queue, add send receive in differen…
alex3696 Dec 3, 2025
901acc1
fix: FIFO data buffers
alex3696 Dec 3, 2025
d04c551
remove unused extension
alex3696 Dec 3, 2025
40ad9a8
fix: closing does not lead to dispose
alex3696 Dec 3, 2025
9f72cd0
fix: return request to queue(sendRqWriter) when ReadAsync canceled
alex3696 Dec 5, 2025
d3cbf15
fix: stop await RequestWaitAsync , when no data processing
alex3696 Dec 5, 2025
97ea1e5
fix: Close port on when device disconnected
alex3696 Dec 5, 2025
30f2281
refr: IO tasks (UsbSendAsync, UsbReceiveAsync) do not catch exceptio…
alex3696 Dec 18, 2025
1566ed2
fix: FlushAsync - now clear all buffers
alex3696 Dec 18, 2025
5f1cb60
refr: logging removed, and replaced with Console.WriteLine where poss…
alex3696 Dec 18, 2025
f8a602d
fix: try return current first dequeued item
alex3696 Dec 18, 2025
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
35 changes: 34 additions & 1 deletion Demo/MauiDemo/MainPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
<x:Int32>57600</x:Int32>
<x:Int32>115200</x:Int32>
<x:Int32>194000</x:Int32>
<x:Int32>460800</x:Int32>
<x:Int32>921600</x:Int32>
<x:Int32>1843200</x:Int32>
<x:Int32>2000000</x:Int32>
</x:Array>
</Picker.ItemsSource>
</Picker>
Expand Down Expand Up @@ -106,7 +110,7 @@
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource mvc}">
<Binding Source="{x:Reference devicePicker}" Path="SelectedItem" x:DataType = "Picker"/>
<Binding Source="{x:Reference baudRatePicker}" Path="SelectedItem" x:DataType = "Picker "/>
<Binding Source="{x:Reference baudRatePicker}" Path="SelectedItem" x:DataType = "Picker"/>
<Binding Source="{x:Reference dataBitsPicker }" Path="SelectedItem" x:DataType = "Picker"/>
<Binding Source="{x:Reference stopBitsPicker}" Path="SelectedItem" x:DataType = "Picker"/>
<Binding Source="{x:Reference parityPicker}" Path="SelectedItem" x:DataType = "Picker"/>
Expand Down Expand Up @@ -147,6 +151,35 @@
<Editor Text="{Binding ReceivedText}" />
</StackLayout>

<StackLayout>
<Label Text="High load speed test" FontSize="20"
HorizontalTextAlignment="Center" TextColor="MediumPurple"/>

<Label Text="Write speed"/>
<Editor Text="{Binding WriteSpeed}" />
<Label Text="Read speed"/>
<Editor Text="{Binding ReadSpeed}" />

<Grid ColumnDefinitions="*,*" RowDefinitions="auto"
ColumnSpacing="4" RowSpacing="4">
<Button Grid.Row="0" Grid.Column="0" Text="Start"
Command="{Binding SendReceiveCommand}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource mvc}">
<Binding Source="{x:Reference devicePicker}" Path="SelectedItem" x:DataType = "Picker"/>
<Binding Source="{x:Reference baudRatePicker}" Path="SelectedItem" x:DataType = "Picker"/>
<Binding Source="{x:Reference dataBitsPicker }" Path="SelectedItem" x:DataType = "Picker"/>
<Binding Source="{x:Reference stopBitsPicker}" Path="SelectedItem" x:DataType = "Picker"/>
<Binding Source="{x:Reference parityPicker}" Path="SelectedItem" x:DataType = "Picker"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
<Button Grid.Row="0" Grid.Column="1" Text="Stop"
Command="{Binding SendReceiveCancelCommand}">
</Button>
</Grid>
</StackLayout>

<StackLayout>
<Label Text="{Binding SelectedDeviceInfo.DeviceName, StringFormat='DeviceName:{0}'}" />
<Label Text="{Binding SelectedDeviceInfo.ProductName, StringFormat='ProductName:{0}'}" />
Expand Down
16 changes: 14 additions & 2 deletions Demo/MauiDemo/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@ public partial class MainPage : ContentPage
public MainPage(MainViewModel vm)
{
InitializeComponent();
this.BindingContext = vm;
baudRatePicker.SelectedIndex = 6;
BindingContext = vm;
baudRatePicker.SelectedIndex = 9;
dataBitsPicker.SelectedIndex = 3;
stopBitsPicker.SelectedIndex = 0;
parityPicker.SelectedIndex = 0;
}
protected override void OnAppearing()
{
base.OnAppearing();
if (BindingContext is not MainViewModel vm)
return;
// if device already connected
// get all devices to list
// and select first
vm.GetAllCommand.Execute(null);
if (0 < vm.UsbDeviceInfos.Count)
vm.SelectedDeviceInfo = vm.UsbDeviceInfos[0];
}
}
}
120 changes: 120 additions & 0 deletions Demo/MauiDemo/Models/IOTestModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System.Diagnostics;
using UsbSerialForAndroid.Net;
using UsbSerialForAndroid.Net.Drivers;

namespace MauiDemo.Models;

public partial class IOTestModel : ObservableObject
{
//private UsbDriverBase? _usbDriver;
[ObservableProperty] public partial string? WriteSpeed { get; set; }
[ObservableProperty] public partial string? ReadSpeed { get; set; }
public IOTestModel() { }

public static TimeSpan UpdatePreiod = TimeSpan.FromMilliseconds(1000);

public async Task StartTestAsync(int deviceId, int baudRate, byte dataBits, byte stopBits, byte parity,
CancellationToken ct)
{
using var usbDriver = UsbDriverFactory.CreateUsbDriver(deviceId);
var _stopBits = (UsbSerialForAndroid.Net.Enums.StopBits)stopBits;
var _parity = (UsbSerialForAndroid.Net.Enums.Parity)parity;
await usbDriver.OpenAsync(baudRate, dataBits, _stopBits, _parity);
await Task.WhenAny(ExecReadAsync(usbDriver, ct), ExecWriteAsync(usbDriver, ct));
}
public async Task ExecReadAsync(UsbDriverBase usbDriver, CancellationToken ct)
{
try
{
await ReadAsync(usbDriver, ct);
}
catch (Exception ex)
{
Console.WriteLine($"[err] {ex}");
}
}
public async Task ExecWriteAsync(UsbDriverBase usbDriver, CancellationToken ct)
{
try
{
await WriteAsync(usbDriver, ct);
}
catch (Exception ex)
{
Console.WriteLine($"[err] {ex}");
}
}
public const int SampleBufLength = 256;
public async Task WriteAsync(UsbDriverBase usbDriver, CancellationToken ct)
{
byte[] writeBuf = new byte[SampleBufLength];
// fill buf
for (int i = 0; i < writeBuf.Length; i++)
writeBuf[i] = (byte)i;

double speed = 0;
long sentTotal = 0;
long sentPrev = 0;
var sw = Stopwatch.StartNew();
TimeSpan tickPrev = sw.Elapsed;
while (!ct.IsCancellationRequested)
{
TimeSpan now = sw.Elapsed;
TimeSpan difTime = now - tickPrev;
if (UpdatePreiod < difTime)
{
double difBytes = sentTotal - sentPrev;
speed = (speed + (difBytes / difTime.TotalSeconds)) / 2;
WriteSpeed = $"{speed:N0} byte/sec, sent total={sentTotal}";// {difBytes:N0} {difTime}
tickPrev = now;
sentPrev = sentTotal;
}
if (SampleBufLength != await usbDriver.WriteAsync(writeBuf, 0, writeBuf.Length, ct))
throw new Exception("Something write wrong");
sentTotal += SampleBufLength;
}
}
private async Task ReadAsync(UsbDriverBase usbDriver, CancellationToken ct)
{
byte[] buf = new byte[SampleBufLength];
byte[] testDataSample = new byte[SampleBufLength];
// fill buf
for (int i = 0; i < testDataSample.Length; i++)
testDataSample[i] = (byte)i;
double speed = 0;
long readTotal = 0;
long readPrev = 0;
var sw = Stopwatch.StartNew();
TimeSpan tickPrev = sw.Elapsed;
while (!ct.IsCancellationRequested)
{
TimeSpan now = sw.Elapsed;
TimeSpan difTime = now - tickPrev;
if (UpdatePreiod < difTime)
{
double difBytes = readTotal - readPrev;
speed = (speed + (difBytes / difTime.TotalSeconds)) / 2;
ReadSpeed = $"{speed:N0} byte/sec read total={readTotal}";// {difBytes:N0} {difTime}
tickPrev = now;
readPrev = readTotal;
}
int currOffset = 0;
int currLen = SampleBufLength;
while (0 < currLen)
{
int currReadLen = await usbDriver.ReadAsync(buf, currOffset, currLen, ct);
currOffset += currReadLen;
currLen -= currReadLen;
readTotal += currReadLen;
}
if (!testDataSample.SequenceEqual(buf))
{
Console.WriteLine($"[err] {BitConverter.ToString(buf)}");
Console.WriteLine($"[err] Read {readTotal} not equal write sequence");
throw new Exception($"Read {readTotal} not equal write sequence");
}
}
}

}
38 changes: 38 additions & 0 deletions Demo/MauiDemo/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,44 @@ items[3] is byte stopBits &&
ShowMessage(ex.Message);
}
});
[ObservableProperty] public partial string? WriteSpeed { get; set; }
[ObservableProperty] public partial string? ReadSpeed { get; set; }
[RelayCommand(IncludeCancelCommand = true)]
public async Task SendReceive(object[] items, CancellationToken ct)
{
try
{
if (items is null
|| items.Length != 5
|| items[0] is not UsbDeviceInfo usbDeviceInfo
|| items[1] is not int baudRate
|| items[2] is not byte dataBits
|| items[3] is not byte stopBits
|| items[4] is not Parity parity)
return;
var test = new IOTestModel();
test.PropertyChanged += (obj, arg) =>
{
MainThread.BeginInvokeOnMainThread(() =>
{
switch (arg.PropertyName)
{
default: break;
case nameof(WriteSpeed): WriteSpeed = test.WriteSpeed; break;
case nameof(ReadSpeed): ReadSpeed = test.ReadSpeed; break;
}
});
};
await Task.Run(() => test.StartTestAsync(usbDeviceInfo.DeviceId,
baudRate, dataBits, stopBits, (byte)parity, ct), ct);
}
catch (Exception ex)
{
ShowMessage(ex.Message);
}
WriteSpeed = null;
ReadSpeed = null;
}
public RelayCommand TestConnectCommand => new(() =>
{
try
Expand Down
Loading