Skip to content

Commit

Permalink
Fix parsing of USB bus file and remove USB reset
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAirBlow committed Jun 29, 2023
1 parent 0ae7cef commit 79fe100
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 33 deletions.
75 changes: 46 additions & 29 deletions TheAirBlow.Thor.Library/Platform/Linux.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public async Task<List<DeviceInfo>> GetDevices() {
}

private uint _interface;
private uint _alternate;
private uint? _readEndpoint;
private uint? _writeEndpoint;
private int? _deviceFd;
Expand Down Expand Up @@ -94,7 +95,7 @@ public void Initialize(string? id, byte[]? direct = null) {
validity = false;
}
_interface = reader.ReadByte();
file.Seek(1, SeekOrigin.Current);
_alternate = reader.ReadByte();
var numEndpoints = (int)reader.ReadByte();
Log.Debug("Number of endpoints: {0}", numEndpoints);
var clss = reader.ReadByte();
Expand All @@ -107,9 +108,10 @@ public void Initialize(string? id, byte[]? direct = null) {
Log.Debug("$$ Endpoint index {0} $$", j);
var len = reader.ReadByte();
var type = reader.ReadByte();
if (type == 0x24) {
while (type == 0x24) {
Log.Debug("!! Class-dependant descriptor, skipping (len = {0} - 2)", len);
file.Seek(len - 2, SeekOrigin.Current); continue;
file.Seek(len - 2, SeekOrigin.Current);
len = reader.ReadByte(); type = reader.ReadByte();
}
if (type != 0x05) {
Log.Debug("!! USB_DT_ENDPOINT fail (value = {0:X2})", type);
Expand Down Expand Up @@ -140,27 +142,23 @@ public void Initialize(string? id, byte[]? direct = null) {

file.Dispose();
if (!found) throw new InvalidOperationException("Failed to find valid endpoints!");
Log.Debug("Interface: 0x{0:X2}, Read Endpoint: 0x{1:X2}, Write Endpoint: 0x{2:X2}",
_interface, _readEndpoint, _writeEndpoint);
Log.Debug("Interface: 0x{0:X2}, Alternate: 0x{1:X2}, Read Endpoint: 0x{2:X2}, Write Endpoint: 0x{3:X2}",
_interface, _alternate, _readEndpoint, _writeEndpoint);

// Return in case of direct
if (direct != null) return;

// Create a device file handle
if ((_deviceFd = Interop.Open(path, Interop.O_RDWR)) < 0)
Interop.HandleError("Failed to open the device for RW");

// Reset USB device
var zeroRef = 0u;
if (Interop.IoCtl(_deviceFd.Value, Interop.USBDEVFS_RESET, ref zeroRef) < 0)
Interop.HandleError("Failed to reset USB device");


// Detach kernel driver if present
var driver = new Interop.GetDriver {
Interface = (int)_interface
};

if (Interop.IoCtl(_deviceFd.Value, Interop.USBDEVFS_GETDRIVER, ref driver) > 0) {
Log.Debug("Kernel driver detected, detaching it!");
var ioctl = new Interop.UsbIoCtl {
CommandCode = (int)Interop.USBDEVFS_DISCONNECT,
Interface = (int)_interface,
Expand All @@ -172,7 +170,7 @@ public void Initialize(string? id, byte[]? direct = null) {

_detached = true;
}

// Claim interface
if (Interop.IoCtl(_deviceFd.Value, Interop.USBDEVFS_CLAIMINTERFACE, ref _interface) < 0)
Interop.HandleError("Failed to claim interface");
Expand Down Expand Up @@ -249,26 +247,33 @@ public void ReadZLP() {

public void Dispose() {
// Release the interface
if (_connected && _deviceFd.HasValue)
if (Interop.IoCtl(_deviceFd.Value, Interop.USBDEVFS_RELEASEINTERFACE, ref _interface) < 0)
Interop.HandleError("Failed to release interface");
try {
if (_connected && _deviceFd.HasValue)
if (Interop.IoCtl(_deviceFd.Value, Interop.USBDEVFS_RELEASEINTERFACE, ref _interface) < 0)
Interop.HandleError("Failed to release interface");
} catch { /* Ignored */ }

// Attach the kernel driver back
if (_detached) {
var ioctl = new Interop.UsbIoCtl {
CommandCode = (int)Interop.USBDEVFS_CONNECT,
Interface = (int)_interface,
Data = nint.Zero
};
if (Interop.IoCtl(_deviceFd!.Value, Interop.USBDEVFS_IOCTL, ref ioctl) < 0)
Interop.HandleError("Failed to attach kernel driver");
}

try {
if (_detached) {
var ioctl = new Interop.UsbIoCtl {
CommandCode = (int)Interop.USBDEVFS_CONNECT,
Interface = (int)_interface,
Data = nint.Zero
};
if (Interop.IoCtl(_deviceFd!.Value, Interop.USBDEVFS_IOCTL, ref ioctl) < 0)
Interop.HandleError("Failed to attach kernel driver");
}
} catch { /* Ignored */ }

// Close device file handle
if (_deviceFd.HasValue && Interop.Close(_deviceFd.Value) < 0)
Interop.HandleError("Failed to close device descriptor");
try {
if (_deviceFd.HasValue && Interop.Close(_deviceFd.Value) < 0)
Interop.HandleError("Failed to close device descriptor");
} catch { /* Ignored */ }

_connected = false;
_detached = false;
}

public static unsafe class Interop {
Expand All @@ -291,11 +296,12 @@ private static uint _IOR(uint type, uint nr, uint size)
private static uint _IOW(uint type, uint nr, uint size)
=> (1U << _IOC_DIRSHIFT) | (type << _IOC_TYPESHIFT)
| (nr << _IOC_NRSHIFT) | (size << _IOC_SIZESHIFT);
public static uint USBDEVFS_SETINTERFACE = _IOR('U', 4, (uint)sizeof(SetInterface));
public static uint USBDEVFS_GETDRIVER = _IOW('U', 8, (uint)sizeof(GetDriver));
public static uint USBDEVFS_BULK = _IOWR('U', 2, (uint)sizeof(BulkTransfer));
public static uint USBDEVFS_IOCTL = _IOWR('U', 18, (uint)sizeof(UsbIoCtl));
public static uint USBDEVFS_CLAIMINTERFACE = _IOR('U', 15, sizeof(uint));
public static uint USBDEVFS_RELEASEINTERFACE = _IOR('U', 16, sizeof(uint));
public static uint USBDEVFS_GETDRIVER = _IOW('U', 8, (uint)sizeof(GetDriver));
public static uint USBDEVFS_CLAIMINTERFACE = _IOR('U', 15, sizeof(uint));
public static uint USBDEVFS_DISCONNECT = _IO('U', 22);
public static uint USBDEVFS_CONNECT = _IO('U', 23);
public static uint USBDEVFS_RESET = _IO('U', 20);
Expand All @@ -306,6 +312,11 @@ public struct BulkTransfer {
public uint Timeout;
public nint Data;
}

public struct SetInterface {
public uint Interface;
public uint Alternate;
}

public struct GetDriver {
public int Interface;
Expand Down Expand Up @@ -336,9 +347,15 @@ public static extern int Open([MarshalAs(UnmanagedType.LPStr)]
[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
public static extern int IoCtl(int fd, ulong request, ref GetDriver driver);

[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
public static extern int IoCtl(int fd, ulong request, ref SetInterface ioctl);

[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
public static extern int IoCtl(int fd, ulong request, ref uint iface);

[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
public static extern int IoCtl(int fd, ulong request, nint ptr);

[DllImport("libc", EntryPoint = "strerror")]
public static extern nint StrError(int code);

Expand Down
2 changes: 1 addition & 1 deletion TheAirBlow.Thor.Library/TheAirBlow.Thor.Library.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>1.0.3</Version>
<Version>1.0.4</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion TheAirBlow.Thor.Shell/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
.MinimumLevel.Information()
.WriteTo.Console()
.CreateLogger();
AnsiConsole.MarkupLine("[green]Welcome to Thor Shell v1.0.3![/]");
AnsiConsole.MarkupLine("[green]Welcome to Thor Shell v1.0.4![/]");
if (!USB.TryGetHandler(out var handler)) {
AnsiConsole.MarkupLine("[red]A USB handler wasn't written for your platform![/]");
AnsiConsole.MarkupLine($"[red]Currently supported platforms: {USB.GetSupported()}.[/]");
Expand Down
2 changes: 1 addition & 1 deletion TheAirBlow.Thor.Shell/TheAirBlow.Thor.Shell.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RootNamespace>ThorRewrite.Shell</RootNamespace>
<Version>1.0.3</Version>
<Version>1.0.4</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 2 additions & 1 deletion Thor.sln.DotSettings.user
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=EMMC/@EntryIndexedValue">True</s:Boolean>

<s:Boolean x:Key="/Default/UserDictionary/Words/=Movi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=tflash/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=tflash/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=USBDEVFS/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

0 comments on commit 79fe100

Please sign in to comment.