Android USB аксессуар для усечения связи с хостом - PullRequest
0 голосов
/ 07 июня 2018

Это мой первый опыт работы с USB-интерфейсом и приложением для Android.

Я использую https://github.com/felHR85/UsbSerial, чтобы создать приложение, которое позволит планшетам / телефонам использовать USB OTG в качествехост и общение с аксессуаром.Я дошел до того, что я использую SerialInputStreams и SerialOutputStreams для отправки и получения с устройством.

Это максимальный размер пакета, который USB может отправлять, - 64 байта с кабелем, который я использую.В моем приложении аксессуар отправляет данные размером более 64 байт.Если у аксессуара нет кода, который отправляет данные в 64-байтовых пакетах, а вместо этого все сразу.Будут ли потеряны данные, поступающие после 64 байтов?

Я получаю первые 64 байта сообщения от дополнительного устройства к хосту, а затем время ожидания хоста, поскольку оно не получает полное сообщение и повторно отправляет дополнительное устройство.Первые 64 байта сообщения всегда отображаются, поэтому я знаю, что другие части сообщения не ожидают опроса.

РЕДАКТИРОВАТЬ

Устройство, к которому я подключаюсь, представляет собой регистратор данных, который считается устройством CDC.Я знаю, что для используемого соединения максимальный размер пакета составляет 64.

USBConnectActivity происходит всякий раз, когда подключено USB-устройство, и проходит фильтр, который я настроил, а интерфейс и конечные точки верны.

public class USBConnectActivity extends Activity
{
    public UsbDevice device = null;
    public UsbManager manager = null;
    public UsbDeviceConnection usbDeviceConnection = null;
    public UsbSerialDevice serialPort = null;
    public String deviceID = "";
    public boolean isUSBConnected = false;
    private PendingIntent mPermissionIntent;
    private final String ACTION_USB_PERMISSION =
            "com.android.example.USB_PERMISSION";

    private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
                stopUsbConnection();
                unregisterReceiver(usbReceiver);
            }
            if(ACTION_USB_PERMISSION.equals(action))
            {
                setupCom();
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        manager = (UsbManager) getSystemService(Context.USB_SERVICE);
        USBConnection.getInstance().setManager(manager);
        mPermissionIntent = PendingIntent.getBroadcast(
                this,0,new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter mfilter = new IntentFilter(ACTION_USB_PERMISSION);
        registerReceiver(usbReceiver,mfilter);

        IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(usbReceiver, filter);

        findDevice(mPermissionIntent);
        finish();
    }

    private void findDevice(PendingIntent i)
    {
        UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        boolean found = false;
        UsbDevice xDevice = null;
        while (deviceIterator.hasNext()) {
           UsbDevice tDevice = deviceIterator.next();

            // Loop through the interfaces of the attached USB device
            for (int count = 0; count < tDevice.getInterfaceCount(); count++) {
                if (found) break;
                // Use temp variables to check and then match with the private variables
                UsbInterface inter = tDevice.getInterface(count);
                UsbEndpoint tOut = null;
                UsbEndpoint tIn = null;

                if (inter.getEndpointCount() >= 2) {
                    for (int end_count = 0; end_count < inter.getEndpointCount(); end_count++) {
                        UsbEndpoint end = inter.getEndpoint(end_count);
                        if (end.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                            if (end.getDirection() == UsbConstants.USB_DIR_OUT) tOut = end;
                            else if (end.getDirection() == UsbConstants.USB_DIR_IN) tIn = end;
                        }
                    }
                }
                if (tOut != null && tIn != null) {
                   device = tDevice; manager.requestPermission(device, i); found = true;
                   isUSBConnected = true;
                   USBConnection.getInstance().setDevice(device);
                   USBConnection.getInstance().attach();
                }
            }
        }
        if(usbDeviceConnection == null) setupCom();
    }

    @Override
    protected void onStop()
    {
        super.onStop();
        unregisterReceiver(usbReceiver);
    }

    private void setupCom()
    {
        deviceID = device.getDeviceName();
        if(usbDeviceConnection == null) usbDeviceConnection = manager.openDevice(device);
        if(serialPort == null)
        {
            serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);
            if(serialPort != null && serialPort.open())
            {
                serialPort.setBaudRate(115200);
                serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
                USBConnection.getInstance().setSerialPort(serialPort);
                USBConnection.getInstance().setUsbDeviceConnection(usbDeviceConnection);
            }
        }
    }

    private void stopUsbConnection(){
        manager = null;
        device = null;
        isUSBConnected = false;
        USBConnection.getInstance().detach();
        deviceID = "";
        try
        {
            if(serialPort != null)
                serialPort.close();
            if(usbDeviceConnection != null)
                usbDeviceConnection.close();
        }
        finally
        {
            serialPort = null;
            usbDeviceConnection = null;
        }

    }
}

Этот класс содержит всю информацию USB

public class USBConnection
{

    // USB information
    public boolean isConnected;
    public UsbDevice device;
    public UsbManager manager;
    public UsbSerialDevice serialPort;
    public UsbDeviceConnection usbDeviceConnection;
    public String deviceName;
    public boolean waitForReading;

    private static USBConnection instance;
    public static USBConnection getInstance()
    {
        if(instance == null)
            instance = new USBConnection();
        return instance;
    }

    public void setDevice(UsbDevice device_)
    {
        device = device_;
        deviceName = device.getDeviceName();
    }

    public void setManager(UsbManager manager_)
    {
        manager = manager_;
    }

    public void attach()
    {
        isConnected = true;
    }

    public void detach()
    {
        isConnected = false;
    }

    public void setSerialPort(UsbSerialDevice serialPort_)
    {
        serialPort = serialPort_;
    }

    public void setUsbDeviceConnection(UsbDeviceConnection usbDeviceConnection_)
    {
        usbDeviceConnection = usbDeviceConnection_;
    }

    public void writing() {
        waitForReading = true;
    }

    public void reading(){
        waitForReading = false;
    }

    public boolean waitingForRead()
    {
        return waitForReading;
    }
}

Этот код я использую для настройки потоков ввода и вывода

else if(USBConnection.getInstance().isConnected)   // check if usb is connected
            {
               manager = USBConnection.getInstance().manager;
               device = USBConnection.getInstance().device;
               // Attempt at setting up a USB input and output stream
               if (manager != null) {
                 if(usbDeviceConnection == null) usbDeviceConnection = manager.openDevice(device);
                  if(serialPort == null)
                  {
                     serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);
                     if(serialPort != null && serialPort.open())
                     {
                        serialPort.setBaudRate(115200);
                        serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                        serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                        serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                        serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);

                        input = new SerialInputStream(serialPort);
                        output = new SerialOutputStream(serialPort);
                        Log.d("Direct", "Connected to the USB socket");
                     }
                  }
                 }
              } // else there is no usb connected

Этов felHR85 UsbSerialDevice, в его ReadThread, и то, что я закомментировал, это то, что я включил, думая, что он будет захватывать данные, если он будет больше, чем 64 байта

        int numberBytes, bytes;
        if(inEndpoint != null) {
            bytes = numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(),
                    SerialBuffer.DEFAULT_READ_BUFFER_SIZE, 100);

        }/*while(numberBytes >= 64) {
                numberBytes = connection.bulkTransfer(inEndpoint, serialBuffer.getBufferCompatible(), bytes,
                        124, 100);
                bytes += numberBytes;
                Log.i("Bytes", " : " + bytes);
            }*/
        else
            bytes = numberBytes = 0;

Это в его WriteThread

    while(working.get())
    {
        byte[] data = serialBuffer.getWriteBuffer();
        if(data.length > 0)
            connection.bulkTransfer(outEndpoint, data, data.length, USB_TIMEOUT);
    }

РЕДАКТИРОВАТЬ

Это решило мою проблему, но я все еще не уверен, что ответ на мой оригинальный вопрос

          if(serialPort == null)
          {
             usbDeviceConnection.claimInterface(USBConnection.getInstance().usbInterface, true);
             usbDeviceConnection.controlTransfer(64,0,1,0,null,0,0); // clear tx
             usbDeviceConnection.controlTransfer(64,0,2,0,null,0,0); // clear rx
             serialPort = UsbSerialDevice.createUsbSerialDevice(device, usbDeviceConnection);

1 Ответ

0 голосов
/ 07 июня 2018

Пожалуйста, введите ваш код.Пожалуйста, укажите любое устройство, которое вы используете в качестве аксессуара (Arduino, FPGA и т. Д.), Чтобы облегчить поиск решения.Трудно сказать, что происходит не так.Я предлагаю вам сделать следующее -

1) Проверьте дескриптор устройства аксессуара, где четко указаны максимальные байты, которые конечная точка USB может передавать за один раз.Здесь у меня есть это для моего Arduino Uno Look at the last and 3rd last lines where it shows 64 bytes. Now look at the 8th line from the end-- that endpoint can transfer mx 8 bytes!

2) Я прошу вас пройти через this вместо использования библиотеки.

3) Существует сигнал DTR, который необходимо отправить от хоста к аксессуару, чтобы указать, что передача данных завершена;чтобы можно было отправлять следующие данные. Проверьте это

4) Вам следует использовать кольцевой буфер для принимающего потока, чтобы данные не были потеряны.

...