NHSE/NHSE.Injection/SysBot/USBBot.cs
2020-12-24 23:53:40 -08:00

165 lines
5.0 KiB
C#

using System;
using System.Threading;
using LibUsbDotNet;
using LibUsbDotNet.Main;
namespace NHSE.Injection
{
public class USBBot : IRAMReadWriter
{
private UsbDevice? SwDevice;
private UsbEndpointReader? reader;
private UsbEndpointWriter? writer;
public bool Connected { get; private set; }
private readonly object _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.Vid == 1406 && ur.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 != null)
{
if (SwDevice.IsOpen)
{
if (SwDevice is IUsbDevice wholeUsbDevice)
wholeUsbDevice.ReleaseInterface(0);
SwDevice.Close();
}
}
reader?.Dispose();
writer?.Dispose();
Connected = false;
}
}
private int ReadInternal(byte[] buffer)
{
byte[] sizeOfReturn = new byte[4];
//read size, no error checking as of 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");
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 ec = writer.Write(BitConverter.GetBytes(pack), 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];
var _ = ReadInternal(buffer);
//return Decoder.ConvertHexByteStringToBytes(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);
}
}
}
}