Files

211 lines
8.4 KiB
C#
Raw Permalink Normal View History

2024-03-03 00:27:52 +01:00
/*
* MIT License
*
* Copyright (c) 2024 The DuoWOA authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
using MadWizard.WinUSBNet;
using System;
2024-03-03 20:52:24 +01:00
using System.Diagnostics;
2024-03-03 00:27:52 +01:00
using System.Threading;
namespace AndroidDebugBridge
{
public partial class AndroidDebugBridgeTransport
{
2024-06-23 10:54:02 +02:00
private readonly USBDevice USBDevice = null;
private readonly USBPipe InputPipe = null;
private readonly USBPipe OutputPipe = null;
2024-03-03 00:27:52 +01:00
private AndroidDebugBridgeMessage ReadMessage(bool VerifyCrc = true)
{
2024-03-03 20:52:24 +01:00
try
2024-03-03 00:27:52 +01:00
{
2024-03-03 20:52:24 +01:00
byte[] IncomingMessage = ReadFromUsb(24);
(AndroidDebugBridgeCommands CommandIdentifier, uint FirstArgument, uint SecondArgument, uint CommandPayloadLength, uint CommandPayloadCrc) = AndroidDebugBridgeMessaging.ParseCommandPacket(IncomingMessage);
2024-03-03 00:27:52 +01:00
2024-03-03 20:52:24 +01:00
if (CommandPayloadLength > 0)
2024-03-03 00:27:52 +01:00
{
2024-03-03 20:52:24 +01:00
byte[] Payload = ReadFromUsb(CommandPayloadLength);
if (VerifyCrc)
{
AndroidDebugBridgeMessaging.VerifyAdbCrc(Payload, CommandPayloadCrc);
}
return new AndroidDebugBridgeMessage(CommandIdentifier, FirstArgument, SecondArgument, Payload);
2024-03-03 00:27:52 +01:00
}
2024-03-03 20:52:24 +01:00
return new AndroidDebugBridgeMessage(CommandIdentifier, FirstArgument, SecondArgument);
2024-03-03 00:27:52 +01:00
}
2024-06-23 10:54:02 +02:00
catch (Exception ex)
{
throw new AggregateException("Failed to read message!", ex);
}
2024-03-03 00:27:52 +01:00
}
2024-06-23 10:54:02 +02:00
private void ReadMessageAsync(Action<AndroidDebugBridgeMessage> asyncCallback, Action<Exception> exceptionAsyncCallback, bool VerifyCrc = true)
2024-03-03 00:27:52 +01:00
{
byte[] IncomingMessage = new byte[24];
ReadFromUsbAsync(IncomingMessage, (asyncReadCallback) =>
{
2024-03-03 20:52:24 +01:00
try
2024-03-03 00:27:52 +01:00
{
2024-03-03 20:52:24 +01:00
(AndroidDebugBridgeCommands CommandIdentifier, uint FirstArgument, uint SecondArgument, uint CommandPayloadLength, uint CommandPayloadCrc) = AndroidDebugBridgeMessaging.ParseCommandPacket(IncomingMessage);
if (CommandPayloadLength > 0)
2024-03-03 00:27:52 +01:00
{
2024-03-03 20:52:24 +01:00
byte[] Payload = new byte[CommandPayloadLength];
ReadFromUsbAsync(Payload, (_) =>
2024-03-03 00:27:52 +01:00
{
2024-03-03 20:52:24 +01:00
if (VerifyCrc)
{
AndroidDebugBridgeMessaging.VerifyAdbCrc(Payload, CommandPayloadCrc);
}
2024-03-03 00:27:52 +01:00
2024-03-03 20:52:24 +01:00
asyncCallback.Invoke(new AndroidDebugBridgeMessage(CommandIdentifier, FirstArgument, SecondArgument, Payload));
2024-06-23 10:54:02 +02:00
}, exceptionAsyncCallback, asyncReadCallback.AsyncState);
2024-03-03 20:52:24 +01:00
}
else
{
asyncCallback.Invoke(new AndroidDebugBridgeMessage(CommandIdentifier, FirstArgument, SecondArgument));
}
2024-03-03 00:27:52 +01:00
}
2024-06-23 10:54:02 +02:00
catch (Exception ex)
{
exceptionAsyncCallback(ex);
}
}, exceptionAsyncCallback);
2024-03-03 00:27:52 +01:00
}
private byte[] ReadFromUsb(uint size)
{
byte[] buffer = new byte[size];
int attempts = 0;
while (true)
{
try
{
_ = InputPipe.Read(buffer);
break;
}
2024-06-23 10:54:02 +02:00
catch (Exception ex)
2024-03-03 00:27:52 +01:00
{
attempts++;
if (attempts > 10)
{
2024-06-23 10:54:02 +02:00
throw new AggregateException("Failed to read from USB device!", ex);
2024-03-03 00:27:52 +01:00
}
Thread.Sleep(100);
2024-03-03 20:52:24 +01:00
Debug.WriteLine("Failed to read from input pipe, trying again. Attempt=" + attempts);
2024-03-03 00:27:52 +01:00
}
}
return buffer;
}
2024-06-23 10:54:02 +02:00
private void ReadFromUsbAsync(byte[] buffer, AsyncCallback asyncCallback, Action<Exception> exceptionAsyncCallback, object? stateObject = null)
2024-03-03 00:27:52 +01:00
{
2024-08-10 18:40:13 +02:00
try
2024-03-03 00:27:52 +01:00
{
2024-08-10 18:40:13 +02:00
InputPipe.BeginRead(buffer, 0, buffer.Length, (asyncWriteState) =>
2024-03-03 20:52:24 +01:00
{
2024-08-10 18:40:13 +02:00
try
{
InputPipe.EndRead(asyncWriteState);
asyncCallback(asyncWriteState);
}
catch (Exception ex)
{
exceptionAsyncCallback(ex);
}
}, stateObject);
}
catch (Exception ex)
{
exceptionAsyncCallback(ex);
}
2024-03-03 00:27:52 +01:00
}
internal void SendMessage(AndroidDebugBridgeMessage outgoingMessage)
{
2024-06-23 10:54:02 +02:00
//Debug.WriteLine($"> new AndroidDebugBridgeMessage(AndroidDebugBridgeCommands.{outgoingMessage.CommandIdentifier}, 0x{outgoingMessage.FirstArgument:X8}, 0x{outgoingMessage.FirstArgument:X8}, );");
byte[] OutgoingMessage = AndroidDebugBridgeMessaging.GetCommandPacket(outgoingMessage.CommandIdentifier, outgoingMessage.FirstArgument, outgoingMessage.SecondArgument, outgoingMessage.Payload);
WriteToUsb(OutgoingMessage);
if (outgoingMessage.Payload != null)
2024-03-03 00:27:52 +01:00
{
2024-06-23 10:54:02 +02:00
WriteToUsb(outgoingMessage.Payload);
2024-03-03 00:27:52 +01:00
}
}
2024-06-23 10:54:02 +02:00
private void SendMessageAsync(AndroidDebugBridgeMessage androidDebugBridgeMessage, Action? asyncCallback = null, Action<Exception> exceptionAsyncCallback = null)
2024-03-03 00:27:52 +01:00
{
2024-06-23 10:54:02 +02:00
byte[] OutgoingMessage = AndroidDebugBridgeMessaging.GetCommandPacket(androidDebugBridgeMessage.CommandIdentifier, androidDebugBridgeMessage.FirstArgument, androidDebugBridgeMessage.SecondArgument, androidDebugBridgeMessage.Payload);
WriteToUsbAsync(OutgoingMessage, (asyncWriteObject) =>
2024-03-03 00:27:52 +01:00
{
2024-06-23 10:54:02 +02:00
if (androidDebugBridgeMessage.Payload != null)
2024-03-03 00:27:52 +01:00
{
2024-06-23 10:54:02 +02:00
WriteToUsbAsync(androidDebugBridgeMessage.Payload, (_) => asyncCallback?.Invoke(), exceptionAsyncCallback, asyncWriteObject.AsyncState);
}
}, exceptionAsyncCallback);
2024-03-03 00:27:52 +01:00
}
private void WriteToUsb(byte[] buffer)
{
int attempts = 0;
while (true)
{
try
{
OutputPipe.Write(buffer);
break;
}
2024-06-23 10:54:02 +02:00
catch (Exception ex)
2024-03-03 00:27:52 +01:00
{
attempts++;
if (attempts > 10)
{
2024-06-23 10:54:02 +02:00
throw new AggregateException("Failed to write to USB device!", ex);
2024-03-03 00:27:52 +01:00
}
Thread.Sleep(100);
2024-03-03 20:52:24 +01:00
Debug.WriteLine("Failed to write to output pipe, trying again. Attempt=" + attempts);
2024-03-03 00:27:52 +01:00
}
}
}
2024-06-23 10:54:02 +02:00
private void WriteToUsbAsync(byte[] buffer, AsyncCallback asyncCallback, Action<Exception> exceptionAsyncCallback, object? stateObject = null)
2024-03-03 00:27:52 +01:00
{
2024-06-23 10:54:02 +02:00
OutputPipe.BeginWrite(buffer, 0, buffer.Length, (asyncWriteState) =>
2024-03-03 20:52:24 +01:00
{
try
{
OutputPipe.EndWrite(asyncWriteState);
asyncCallback(asyncWriteState);
}
2024-06-23 10:54:02 +02:00
catch (Exception ex)
2024-03-03 20:52:24 +01:00
{
2024-06-23 10:54:02 +02:00
exceptionAsyncCallback(ex);
2024-03-03 20:52:24 +01:00
}
2024-03-03 00:27:52 +01:00
}, stateObject);
}
}
}