Unity 中的 Avrdude Android 插件开发

问题描述 投票:0回答:0

我正在尝试创建一个可以在 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;
    }
}
Android Java 串行库
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");
                    }
                }
            }
        }
    };
}
Unity C# 串行库
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 套接字没有任何知识或经验。

java c# android unity3d avrdude
© www.soinside.com 2019 - 2024. All rights reserved.