mirror of
https://github.com/kwsch/NHSE.git
synced 2026-04-19 23:17:24 -05:00
161 lines
4.5 KiB
C#
161 lines
4.5 KiB
C#
using System;
|
|
using System.Threading;
|
|
using LibUsbDotNet;
|
|
using LibUsbDotNet.Main;
|
|
using static System.Buffers.Binary.BinaryPrimitives;
|
|
|
|
namespace NHSE.Injection;
|
|
|
|
public sealed class USBBot : IRAMReadWriter
|
|
{
|
|
private UsbDevice? SwDevice;
|
|
private UsbEndpointReader? reader;
|
|
private UsbEndpointWriter? writer;
|
|
|
|
public bool Connected { get; private set; }
|
|
|
|
private readonly Lock _sync = new();
|
|
|
|
public bool Connect()
|
|
{
|
|
lock (_sync)
|
|
{
|
|
// Find and open the usb device.
|
|
//SwDevice = UsbDevice.OpenUsbDevice(SwFinder);
|
|
foreach (UsbRegistry ur in UsbDevice.AllDevices)
|
|
{
|
|
if (ur is { Vid: 1406, Pid: 12288 })
|
|
SwDevice = ur.Device;
|
|
}
|
|
//SwDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
|
|
|
|
// If the device is open and ready
|
|
if (SwDevice == null)
|
|
{
|
|
throw new Exception("Device Not Found.");
|
|
}
|
|
|
|
if (SwDevice.IsOpen)
|
|
SwDevice.Close();
|
|
SwDevice.Open();
|
|
|
|
if (SwDevice is IUsbDevice wholeUsbDevice)
|
|
{
|
|
// This is a "whole" USB device. Before it can be used,
|
|
// the desired configuration and interface must be selected.
|
|
|
|
// Select config #1
|
|
wholeUsbDevice.SetConfiguration(1);
|
|
|
|
// Claim interface #0.
|
|
bool resagain = wholeUsbDevice.ClaimInterface(0);
|
|
if (!resagain)
|
|
{
|
|
wholeUsbDevice.ReleaseInterface(0);
|
|
wholeUsbDevice.ClaimInterface(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Disconnect();
|
|
throw new Exception("Device is using WinUSB driver. Use libusbK and create a filter");
|
|
}
|
|
|
|
// open read write endpoints 1.
|
|
reader = SwDevice.OpenEndpointReader(ReadEndpointID.Ep01);
|
|
writer = SwDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
|
|
|
|
Connected = true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public void Disconnect()
|
|
{
|
|
lock (_sync)
|
|
{
|
|
if (SwDevice is { IsOpen: true })
|
|
{
|
|
if (SwDevice is IUsbDevice wholeUsbDevice)
|
|
wholeUsbDevice.ReleaseInterface(0);
|
|
SwDevice.Close();
|
|
}
|
|
|
|
reader?.Dispose();
|
|
writer?.Dispose();
|
|
Connected = false;
|
|
}
|
|
}
|
|
|
|
private int ReadInternal(byte[] buffer)
|
|
{
|
|
//read size, no error checking yet, should be the required 368 bytes
|
|
if (reader == null)
|
|
throw new Exception("USB writer is null, you may have disconnected the device during previous function");
|
|
|
|
var sizeOfReturn = new byte[4];
|
|
reader.Read(sizeOfReturn, 5000, out _);
|
|
|
|
//read stack
|
|
reader.Read(buffer, 5000, out var lenVal);
|
|
return lenVal;
|
|
}
|
|
|
|
private int SendInternal(byte[] buffer)
|
|
{
|
|
if (writer == null)
|
|
throw new Exception("USB writer is null, you may have disconnected the device during previous function");
|
|
|
|
uint pack = (uint)buffer.Length + 2;
|
|
var lengthBytes = new byte[sizeof(uint)];
|
|
WriteUInt32LittleEndian(lengthBytes, pack);
|
|
var ec = writer.Write(lengthBytes, 2000, out _);
|
|
if (ec != ErrorCode.None)
|
|
{
|
|
Disconnect();
|
|
throw new Exception(UsbDevice.LastErrorString);
|
|
}
|
|
ec = writer.Write(buffer, 2000, out var l);
|
|
if (ec != ErrorCode.None)
|
|
{
|
|
Disconnect();
|
|
throw new Exception(UsbDevice.LastErrorString);
|
|
}
|
|
return l;
|
|
}
|
|
|
|
public int Read(byte[] buffer)
|
|
{
|
|
lock (_sync)
|
|
{
|
|
return ReadInternal(buffer);
|
|
}
|
|
}
|
|
|
|
public byte[] ReadBytes(uint offset, int length)
|
|
{
|
|
lock (_sync)
|
|
{
|
|
var cmd = SwitchCommand.PeekRaw(offset, length);
|
|
SendInternal(cmd);
|
|
|
|
// give it time to push data back
|
|
Thread.Sleep((length / 256) + 100);
|
|
|
|
var buffer = new byte[length];
|
|
_ = ReadInternal(buffer);
|
|
return buffer;
|
|
}
|
|
}
|
|
|
|
public void WriteBytes(byte[] data, uint offset)
|
|
{
|
|
lock (_sync)
|
|
{
|
|
SendInternal(SwitchCommand.PokeRaw(offset, data));
|
|
|
|
// give it time to push data back
|
|
Thread.Sleep((data.Length / 256) + 100);
|
|
}
|
|
}
|
|
} |