我正在尝试创建一个可以在 Unity 中的 Android 平台上运行的 Avrdude 插件。我使用的Unity版本是2021.3.9f1.
我计划使用 .so 文件运行 Avrdude,并利用 https://github.com/mik3y/usb-serial-for-android 库为连接到 Android 的 USB 设备打开权限和端口。
下面是我写的代码。
public class PluginManager : MonoBehaviour
{
string path;
string avrdudeconfPath;
string hexFilePath;
string avrduderunPath;
public AARManager aarManager;
private AndroidJavaObject usbManager;
private AndroidJavaObject usbInterface;
private AndroidJavaObject usbEndpoint;
private int VID;
private int PID;
string fromConfPath;
string toConfPath;
string fromHexPath;
string toHexPath;
string fromExePath;
string toExePath;
public Text soTestTxt;
public Text aarTestTxt;
public Button testBtn;
public Button testBtn2;
string teststring;
string testrunstring;
string testcomma;
[DllImport("AvrdudeJNILib")]
private static extern void avrdude_main(
int argc, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPTStr)]
string[] argv, [MarshalAs(UnmanagedType.FunctionPtr)] MsgCallback cb,
[MarshalAs(UnmanagedType.FunctionPtr)] ExitCallback ec);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void MsgCallback(string message);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void ExitCallback(int exitCode);
private void Awake()
{
}
private void Start()
{
}
void OnDestroy()
{
}
[MonoPInvokeCallback(typeof(MsgCallback))]
public static void LogMessage(string message)
{
Debug.Log(message);
}
[MonoPInvokeCallback(typeof(ExitCallback))]
static void OnExit(int exitCode)
{
Debug.Log("Exited with code: " + exitCode);
}
public void OnClickRunAvrdude()
{
StartCoroutine((new[] {
CopyFileAvrdudeConf(),
CopyFileHex()
}).GetEnumerator());
CheckUSBDevices();
}
public void OnClickRunAvrdude2()
{
}
IEnumerator CopyFileAvrdudeConf()
{
fromConfPath = Application.streamingAssetsPath + "/";
toConfPath = Application.persistentDataPath + "/";
string[] fileNamesToCopy = new string[] { "avrdude.conf" };
foreach (string fileName in fileNamesToCopy)
{
string fromFilePath = Path.Combine(fromConfPath, fileName);
string toFilePath = Path.Combine(toConfPath, fileName);
Debug.Log("Copying " + fromFilePath + " to " + toFilePath);
if (Application.platform == RuntimePlatform.Android)
{
UnityWebRequest www = UnityWebRequest.Get(fromFilePath);
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.Success)
{
File.WriteAllBytes(toFilePath, www.downloadHandler.data);
}
else
{
Debug.Log(www.error);
}
}
else
{
File.Copy(fromFilePath, toFilePath, true);
}
}
string filePath = Path.Combine(Application.persistentDataPath, "avrdude.conf");
if (File.Exists(filePath))
{
string contents = File.ReadAllText(filePath);
soTestTxt.text = Application.persistentDataPath;
Debug.Log("CONF File exists at path: " + filePath);
}
else
{
Debug.LogError("CONF File does not exist at path: " + filePath);
}
}
IEnumerator CopyFileHex()
{
fromHexPath = Application.streamingAssetsPath + "/";
toHexPath = Application.persistentDataPath + "/";
string[] fileNamesToCopy = new string[] { "main.hex" };
foreach (string fileName in fileNamesToCopy)
{
string fromFilePath = Path.Combine(fromHexPath, fileName);
string toFilePath = Path.Combine(toHexPath, fileName);
Debug.Log("Copying " + fromFilePath + " to " + toFilePath);
if (Application.platform == RuntimePlatform.Android)
{
UnityWebRequest www = UnityWebRequest.Get(fromFilePath);
yield return www.SendWebRequest();
if (www.result == UnityWebRequest.Result.Success)
{
File.WriteAllBytes(toFilePath, www.downloadHandler.data);
}
else
{
Debug.LogError(www.error);
}
}
else
{
File.Copy(fromFilePath, toFilePath, true);
}
}
string filePath = Path.Combine(Application.persistentDataPath, "main.hex");
if (File.Exists(filePath))
{
string contents = File.ReadAllText(filePath);
//soTestTxt.text = contents;
Debug.Log("HEX File exists at path: " + filePath);
}
else
{
Debug.Log("HEX File does not exist at path: " + filePath);
}
}
IEnumerator Runavrdudestart()
{
string[] argv = new string[] {
"avrdude",
"-C",
Application.persistentDataPath+"/avrdude.conf",
"-c",
"stk500v2",
"-p",
"m8",
"-P",
aarManager.getport,
"-D",
"-F",
"-U",
"flash:w:"+ Application.persistentDataPath+"/main.hex",
};
try
{
//avrdude_main(argv.Length, argv, logg, null);
avrdude_main(argv.Length, argv, LogMessage, OnExit);
}
catch (Exception e)
{
Debug.Log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + e);
}
yield break;
}
}
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import java.io.IOException;
public class GetPermission extends Activity {
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private static PendingIntent mPermissionIntent;
private static UsbDevice device;
static UsbSerialPort port;
static UsbManager manager;
private static final int READ_WAIT_MILLIS = 2000;
public static String GetPortPermission(Context unityContext){
manager = (UsbManager) unityContext.getSystemService(Context.USB_SERVICE);
mPermissionIntent = PendingIntent.getBroadcast(unityContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
unityContext.registerReceiver(mUsbReceiver, filter);
device = null;
for(UsbDevice usbDevice : manager.getDeviceList().values())
{
if(usbDevice.getVendorId()==0x1a86&&usbDevice.getProductId()==0x7523)
{
device=usbDevice;
break;
}
}
if(device!=null)
{
manager.requestPermission(device,mPermissionIntent);
UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
port = driver.getPorts().get(0);
if(manager.hasPermission(device)){
UsbDeviceConnection connection = manager.openDevice(device);
try {
port.open(connection);
port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
System.out.println(port);
System.out.println("@@@@@@@@@@@@@@@@@@"+connection.releaseInterface(device.getInterface(0)));
int fileDescriptor = connection.getFileDescriptor();
if(fileDescriptor==-1)
{
System.out.println("!!!!!NotOpen!!!!!");
}
else
{
System.out.println("!!!!!Open!!!!!");
}
} catch (IOException e) {
e.printStackTrace();
}
return device.getDeviceName();
} else {
return "PermissionDenied";
}
} else {
return "DeviceNotFound";
}
/*UsbDeviceConnection connection = manager.openDevice(device);
if (connection != null) {
System.out.println("UsbDeviceConnectOK!!!");
int fileDescriptor = connection.getFileDescriptor();
boolean isOpen = fileDescriptor >= 0;
if (isOpen) {
System.out.println("USBPortOpen!!!");
} else {
System.out.println("USBPortClose!!!");
}
} else {
System.out.println("UsbDeviceConnectFail");
}
if(device!=null)
{
manager.requestPermission(device,mPermissionIntent);
UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
UsbSerialPort port = driver.getPorts().get(0);
try {
port.open(connection);
port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
System.out.println(port);
} catch (IOException e) {
e.printStackTrace();
}
return device.getDeviceName();
}
else {
return "DeviceNotFound";
}*/
}
public static String ReadPort() throws IOException{
if(port==null||!port.isOpen())
{
return "port is Null";
}
byte[] buffer = new byte[8192];
int len = port.read(buffer,READ_WAIT_MILLIS);
new String(buffer, 0, len);
return port.toString();
}
private static final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
System.out.println("Permission OK!!!");
System.out.println(device.getDeviceId());
System.out.println(device.getInterfaceCount());
System.out.println(device.getInterface(0));
System.out.println(device.getVendorId());
System.out.println(device.getProductId());
}
}
else {
System.out.println("Permission denied");
}
}
}
}
};
}
public class AARManager : MonoBehaviour
{
string response;
public string getport;
public string read;
void Start()
{
}
public void OnclickCheckPermission()
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaObject context = activity.Call<AndroidJavaObject>("getApplicationContext");
AndroidJavaClass pluginClass = new AndroidJavaClass("com.hoho.android.usbserial.driver.GetPermission");
getport = pluginClass.CallStatic<string>("GetPortPermission", context);
Debug.Log(getport);
if(getport.Contains("dev"))
{
read = pluginClass.CallStatic<string>("ReadPort");
Debug.Log("Readport@@@@@@@@@@"+read);
}
else
{
Debug.Log("Init Failed!!!!!");
}
}
}
但是,我得到以下信息:
2023-03-27 11:59:20.551 10182 10202 Info Unity STEP:1
2023-03-27 11:59:20.552 10182 10202 Info Unity update_progress: no_tty
2023-03-27 11:59:20.552 10182 10202 Info Unity STEP:2
2023-03-27 11:59:20.552 10182 10202 Info Unity System wide configuration file is "/storage/emulated/0/Android/data/com.probo.newproed/files/avrdude.conf"
2023-03-27 11:59:20.552 10182 10202 Info Unity read_config: /storage/emulated/0/Android/data/com.probo.newproed/files/avrdude.conf
2023-03-27 11:59:20.597 10182 10202 Info Unity STEP:3
2023-03-27 11:59:20.597 10182 10202 Info Unity avrdude: ser_open(): can't open device "DeviceNotFound": No such file or directory
2023-03-27 11:59:20.597 10182 10202 Info Unity exit(1)
2023-03-27 11:59:20.599 10182 10202 Info Unity Exited with code: 0
2023-03-27 11:59:20.599 10182 10202 Info Unity avrdude: ser_open(): can't set attributes for device "DeviceNotFound": Not a typewriter
2023-03-27 11:59:20.599 10182 10202 Info Unity exit(1)
2023-03-27 11:59:20.599 10182 10202 Info Unity Exited with code: 0
0001-01-01 00:00:00.000 -1 -1 Info --------- beginning of crash
2023-03-27 11:59:20.600 10182 10202 Fatal libc FORTIFY: FD_SET: file descriptor < 0
2023-03-27 11:59:20.600 10182 10202 Info Unity exit(ABNORMAL TERMINATION)
2023-03-27 11:59:20.602 10182 10202 Info Unity Exited with code: -6
谁能给我一些建议?我已经挣扎了几个月了。我知道可以通过 TCP 套接字通信与 USB 设备通信,但我对 TCP 套接字没有任何知识或经验。