Общение с пользовательским USB-устройством на Android

StackOverflow https://stackoverflow.com//questions/23042753

  •  21-12-2019
  •  | 
  •  

Вопрос

Я создаю приложение для связи с пользовательским доменем (PIC16F1454) через USB.Я проверил связь на доске с помощью терминальных приложений на телефоне и ноутбуке, и он отлично работает.

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

package com.fyp.eece502androidusb;

import java.util.HashMap;
import java.util.Iterator;

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.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.util.Log;

public class UsbController {

    private final Context mApplicationContext;
    private final UsbManager mUsbManager;
    private final IUsbConnectionHandler mConnectionHandler;
    private final int VID;
    private final int PID;
    protected static final String ACTION_USB_PERMISSION = "com.fyp.eece502androidusb.USB";

    /**
     * Activity is needed for onResult
     * 
     * @param parentActivity
     */
    public UsbController(Activity parentActivity,
            IUsbConnectionHandler connectionHandler, int vid, int pid) {
        mApplicationContext = parentActivity.getApplicationContext();
        mConnectionHandler = connectionHandler;
        mUsbManager = (UsbManager) mApplicationContext
                .getSystemService(Context.USB_SERVICE);
        VID = vid;
        PID = pid;
        init();
    }

    private void init() {
        enumerate(new IPermissionListener() {
            @Override
            public void onPermissionDenied(UsbDevice d) {
                UsbManager usbman = (UsbManager) mApplicationContext
                        .getSystemService(Context.USB_SERVICE);
                PendingIntent pi = PendingIntent.getBroadcast(
                        mApplicationContext, 0, new Intent(
                                ACTION_USB_PERMISSION), 0);
                mApplicationContext.registerReceiver(mPermissionReceiver,
                        new IntentFilter(ACTION_USB_PERMISSION));
                usbman.requestPermission(d, pi);
            }
        });
    }

    public void stop() {
        mStop = true;
        synchronized (sSendLock) {
            sSendLock.notify();
        }
        try {
            if (mUsbThread != null)
                mUsbThread.join();
        } catch (InterruptedException e) {
            e(e);
        }
        mStop = false;
        mLoop = null;
        mUsbThread = null;

        try {
            mApplicationContext.unregisterReceiver(mPermissionReceiver);
        } catch (IllegalArgumentException e) {
        }
        ;// bravo
    }

    private UsbRunnable mLoop;
    private Thread mUsbThread;

    private void startHandler(UsbDevice d) {
        if (mLoop != null) {
            mConnectionHandler.onErrorLooperRunningAlready();
            return;
        }
        mLoop = new UsbRunnable(d);
        mUsbThread = new Thread(mLoop);
        mUsbThread.start();
    }

    public void send(byte data) {
        mData = data;
        synchronized (sSendLock) {
            sSendLock.notify();
        }
    }

    private void enumerate(IPermissionListener listener) {
        l("enumerating");
        HashMap<String, UsbDevice> devlist = mUsbManager.getDeviceList();
        Iterator<UsbDevice> deviter = devlist.values().iterator();
        while (deviter.hasNext()) {
            UsbDevice d = deviter.next();
            l("Found device: "
                    + String.format("%04X:%04X", d.getVendorId(),
                            d.getProductId()));
            if (d.getVendorId() == VID && d.getProductId() == PID) {
                l("Device under: " + d.getDeviceName());
                if (!mUsbManager.hasPermission(d))
                    listener.onPermissionDenied(d);
                else {
                    startHandler(d);
                    return;
                }
                break;
            }
        }
        l("no more devices found");
        mConnectionHandler.onDeviceNotFound();
    }

    private class PermissionReceiver extends BroadcastReceiver {
        private final IPermissionListener mPermissionListener;

        public PermissionReceiver(IPermissionListener permissionListener) {
            mPermissionListener = permissionListener;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            mApplicationContext.unregisterReceiver(this);
            if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
                if (!intent.getBooleanExtra(
                        UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    mPermissionListener.onPermissionDenied((UsbDevice) intent
                            .getParcelableExtra(UsbManager.EXTRA_DEVICE));
                } else {
                    l("Permission granted");
                    UsbDevice dev = (UsbDevice) intent
                            .getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (dev != null) {
                        if (dev.getVendorId() == VID
                                && dev.getProductId() == PID) {
                            startHandler(dev);// has new thread
                        }
                    } else {
                        e("device not present!");
                    }
                }
            }
        }

    }

    // MAIN LOOP
    private static final Object[] sSendLock = new Object[] {};
    private boolean mStop = false;
    private byte mData = 0x00;

    private class UsbRunnable implements Runnable {
        private final UsbDevice mDevice;

        UsbRunnable(UsbDevice dev) {
            mDevice = dev;
        }

        @Override
        public void run() {// here the main USB functionality is implemented
            UsbDeviceConnection conn = mUsbManager.openDevice(mDevice);
            if (!conn.claimInterface(mDevice.getInterface(1), true)) {
                return;
            }

            // controlTransfer
            int baudRate = 115200;
            int stopBits = 1;
            int parity = 0;
            int dataBits = 8;
            byte[] msg = { (byte) (baudRate & 0xff),
                    (byte) ((baudRate >> 8) & 0xff),
                    (byte) ((baudRate >> 16) & 0xff),
                    (byte) ((baudRate >> 24) & 0xff),

                    (byte) stopBits, (byte) parity, (byte) dataBits };
            int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | 1;

            UsbControllerActivity.conn1Reply = conn.controlTransfer(USB_RT_ACM,
                    34, 0x03, 0, null, 0, 0);
            UsbControllerActivity.conn2Reply = conn.controlTransfer(USB_RT_ACM,
                    32, 0, 0, msg, msg != null ? msg.length : 0, 0);
            //

            UsbEndpoint epIN = null;
            UsbEndpoint epOUT = null;

            UsbInterface usbIf = mDevice.getInterface(1);
            for (int i = 0; i < usbIf.getEndpointCount(); i++) {
                if (usbIf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                    if (usbIf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) {
                        epIN = usbIf.getEndpoint(i);
                        UsbControllerActivity.epINExists = true;
                    } else {
                        epOUT = usbIf.getEndpoint(i);
                        UsbControllerActivity.epOUTExists = true;
                    }
                }
            }

            for (;;) {// this is the main loop for transferring
                synchronized (sSendLock) {
                    try {
                        sSendLock.wait();
                    } catch (InterruptedException e) {
                        if (mStop) {
                            mConnectionHandler.onUSBStopped();
                            return;
                        }
                        e.printStackTrace();
                    }
                }
                UsbControllerActivity.mDataSent = new byte[] { (byte) (0x04) };
                UsbControllerActivity.bulkXFEROutReply = conn.bulkTransfer(
                        epOUT, UsbControllerActivity.mDataSent, 1, 0);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                UsbControllerActivity.bulkXFERInReply = conn.bulkTransfer(epIN,
                        UsbControllerActivity.mDataReceived, 10, 0);

                if (mStop) {
                    mConnectionHandler.onUSBStopped();
                    return;
                }
            }
        }
    }

    // END MAIN LOOP
    private BroadcastReceiver mPermissionReceiver = new PermissionReceiver(
            new IPermissionListener() {
                @Override
                public void onPermissionDenied(UsbDevice d) {
                    l("Permission denied on " + d.getDeviceId());
                }
            });

    private static interface IPermissionListener {
        void onPermissionDenied(UsbDevice d);
    }

    public final static String TAG = "USBController";

    private void l(Object msg) {
        Log.d(TAG, ">==< " + msg.toString() + " >==<");
    }

    private void e(Object msg) {
        Log.e(TAG, ">==< " + msg.toString() + " >==<");
    }
}
.

Я получаю возвращенные значения 0 и 7 для передачи управления, а 1 для объемной передачи при отправке и ничего не получено.

Хотя объемная передача указывает на то, что значение отправляется, ничего не изменяется на приемной стороне (мигающий светодиод на доске).

Мои спекуляции - это то, что должно быть что-то не так с передачей управления:

int baudRate = 115200;
int stopBits = 1;
int parity = 0;
int dataBits = 8;
byte[] msg = { (byte) (baudRate & 0xff),
        (byte) ((baudRate >> 8) & 0xff),
        (byte) ((baudRate >> 16) & 0xff),
        (byte) ((baudRate >> 24) & 0xff),

        (byte) stopBits, (byte) parity, (byte) dataBits };
int USB_RT_ACM = UsbConstants.USB_TYPE_CLASS | 1;

UsbControllerActivity.conn1Reply = conn.controlTransfer(USB_RT_ACM,
        34, 0x03, 0, null, 0, 0);
UsbControllerActivity.conn2Reply = conn.controlTransfer(USB_RT_ACM,
        32, 0, 0, msg, msg != null ? msg.length : 0, 0);
.

Устройство USB настроено как устройство CDC.

Любая помощь?

Это было полезно?

Решение

Благодаря комментарию от Chris Stratton, я смог найти проблему в моем коде.

  1. Я отправил 0x04 (ctrl-d) вместо 0x34 (4)
  2. ControlTransfer, кажется, не нужен, я использую PIC16F1454 со встроенными функциями USB
  3. Получающий буфер был меньше, чем ответ рис, который также вызвал проблемы
  4. Модифицированный код ниже:

    package com.fyp.eece502androidusb;
    
    import java.util.HashMap;
    import java.util.Iterator;
    
    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.UsbConstants;
    import android.hardware.usb.UsbDevice;
    import android.hardware.usb.UsbDeviceConnection;
    import android.hardware.usb.UsbEndpoint;
    import android.hardware.usb.UsbInterface;
    import android.hardware.usb.UsbManager;
    import android.util.Log;
    
    public class UsbController {
    
        private final Context mApplicationContext;
        private final UsbManager mUsbManager;
        private final IUsbConnectionHandler mConnectionHandler;
        private final int VID;
        private final int PID;
        protected static final String ACTION_USB_PERMISSION = "com.fyp.eece502androidusb.USB";
    
        /**
         * Activity is needed for onResult
         * 
         * @param parentActivity
         */
        public UsbController(Activity parentActivity,
                IUsbConnectionHandler connectionHandler, int vid, int pid) {
            mApplicationContext = parentActivity.getApplicationContext();
            mConnectionHandler = connectionHandler;
            mUsbManager = (UsbManager) mApplicationContext
                    .getSystemService(Context.USB_SERVICE);
            VID = vid;
            PID = pid;
            init();
        }
    
        private void init() {
            enumerate(new IPermissionListener() {
                @Override
                public void onPermissionDenied(UsbDevice d) {
                    UsbManager usbman = (UsbManager) mApplicationContext
                            .getSystemService(Context.USB_SERVICE);
                    PendingIntent pi = PendingIntent.getBroadcast(
                            mApplicationContext, 0, new Intent(
                                    ACTION_USB_PERMISSION), 0);
                    mApplicationContext.registerReceiver(mPermissionReceiver,
                            new IntentFilter(ACTION_USB_PERMISSION));
                    usbman.requestPermission(d, pi);
                }
            });
        }
    
        public void stop() {
            mStop = true;
            synchronized (sSendLock) {
                sSendLock.notify();
            }
            try {
                if (mUsbThread != null)
                    mUsbThread.join();
            } catch (InterruptedException e) {
                e(e);
            }
            mStop = false;
            mLoop = null;
            mUsbThread = null;
    
            try {
                mApplicationContext.unregisterReceiver(mPermissionReceiver);
            } catch (IllegalArgumentException e) {
            }
        }
    
        private UsbRunnable mLoop;
        private Thread mUsbThread;
    
        private void startHandler(UsbDevice d) {
            if (mLoop != null) {
                mConnectionHandler.onErrorLooperRunningAlready();
                return;
            }
            mLoop = new UsbRunnable(d);
            mUsbThread = new Thread(mLoop);
            mUsbThread.start();
        }
    
        public void send(byte data) {
            mData = data;
            synchronized (sSendLock) {
                sSendLock.notify();
            }
        }
    
        private void enumerate(IPermissionListener listener) {
            l("enumerating");
            HashMap<String, UsbDevice> devlist = mUsbManager.getDeviceList();
            Iterator<UsbDevice> deviter = devlist.values().iterator();
            while (deviter.hasNext()) {
                UsbDevice d = deviter.next();
                l("Found device: "
                        + String.format("%04X:%04X", d.getVendorId(),
                                d.getProductId()));
                if (d.getVendorId() == VID && d.getProductId() == PID) {
                    l("Device under: " + d.getDeviceName());
                    if (!mUsbManager.hasPermission(d))
                        listener.onPermissionDenied(d);
                    else {
                        startHandler(d);
                        return;
                    }
                    break;
                }
            }
            l("no more devices found");
            mConnectionHandler.onDeviceNotFound();
        }
    
        private class PermissionReceiver extends BroadcastReceiver {
            private final IPermissionListener mPermissionListener;
    
            public PermissionReceiver(IPermissionListener permissionListener) {
                mPermissionListener = permissionListener;
            }
    
            @Override
            public void onReceive(Context context, Intent intent) {
                mApplicationContext.unregisterReceiver(this);
                if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
                    if (!intent.getBooleanExtra(
                            UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        mPermissionListener.onPermissionDenied((UsbDevice) intent
                                .getParcelableExtra(UsbManager.EXTRA_DEVICE));
                    } else {
                        l("Permission granted");
                        UsbDevice dev = (UsbDevice) intent
                                .getParcelableExtra(UsbManager.EXTRA_DEVICE);
                        if (dev != null) {
                            if (dev.getVendorId() == VID
                                    && dev.getProductId() == PID) {
                                startHandler(dev);// has new thread
                            }
                        } else {
                            e("device not present!");
                        }
                    }
                }
            }
    
        }
    
        // MAIN LOOP
        private static final Object[] sSendLock = new Object[] {};
        private boolean mStop = false;
        private byte mData = 0x00;
    
        private class UsbRunnable implements Runnable {
            private final UsbDevice mDevice;
    
            UsbRunnable(UsbDevice dev) {
                mDevice = dev;
            }
    
            @Override
            public void run() {// here the main USB functionality is implemented
                UsbDeviceConnection conn = mUsbManager.openDevice(mDevice);
                if (!conn.claimInterface(mDevice.getInterface(1), true)) {
                    return;
                }
    
                UsbEndpoint epIN = null;
                UsbEndpoint epOUT = null;
    
                UsbInterface usbIf = mDevice.getInterface(1);
                for (int i = 0; i < usbIf.getEndpointCount(); i++) {
                    if (usbIf.getEndpoint(i).getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                        if (usbIf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) {
                            epIN = usbIf.getEndpoint(i);
                            UsbControllerActivity.epINExists = true;
                        } else {
                            epOUT = usbIf.getEndpoint(i);
                            UsbControllerActivity.epOUTExists = true;
                        }
                    }
                }
    
                for (;;) {// this is the main loop for transferring
                    synchronized (sSendLock) {
                        try {
                            sSendLock.wait();
                        } catch (InterruptedException e) {
                            if (mStop) {
                                mConnectionHandler.onUSBStopped();
                                return;
                            }
                            e.printStackTrace();
                        }
                    }
                    UsbControllerActivity.mDataSent = new byte[] { (byte) (0x34) };
                    UsbControllerActivity.bulkXFEROutReply = conn.bulkTransfer(
                            epOUT, UsbControllerActivity.mDataSent, 1, 0);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    UsbControllerActivity.bulkXFERInReply = conn.bulkTransfer(epIN,
                            UsbControllerActivity.mDataReceived, 20, 0);
    
                    if (mStop) {
                        mConnectionHandler.onUSBStopped();
                        return;
                    }
                }
            }
        }
    
        // END MAIN LOOP
        private BroadcastReceiver mPermissionReceiver = new PermissionReceiver(
                new IPermissionListener() {
                    @Override
                    public void onPermissionDenied(UsbDevice d) {
                        l("Permission denied on " + d.getDeviceId());
                    }
                });
    
        private static interface IPermissionListener {
            void onPermissionDenied(UsbDevice d);
        }
    
        public final static String TAG = "USBController";
    
        private void l(Object msg) {
            Log.d(TAG, ">==< " + msg.toString() + " >==<");
        }
    
        private void e(Object msg) {
            Log.e(TAG, ">==< " + msg.toString() + " >==<");
        }
    }
    
    .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top