安卓USB主机接收数据

6
我尝试从我的评估板上读取数据。它是 Stellaris EKK-LM4F232 评估套件。它有五个按钮。我按下板子上的一个按钮并将数据发送到我的 Android 设备。例如,我按一次,板子发送 1,第二次发送 2...当我第一次按按钮时,我从 Android 设备接收到第一个值(即 1)。但是当我再次按按钮时,我无法接收任何其他值,如 2、3、4 等。这是我的读取代码。它在启动时持续读取。你能帮帮我吗?
public void startDataRecieve() {
    new Thread(new Runnable() {

        @Override
        public void run() {

            UsbEndpoint endpoint = null;

            for (int i = 0; i < intf.getEndpointCount(); i++) {
                if (intf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN) {
                    endpoint = intf.getEndpoint(i);
                    break;
                }
            }
            UsbRequest request = new UsbRequest(); // create an URB
            boolean initilzed = request.initialize(connection, endpoint);

            if (!initilzed) {
                Log.e("USB CONNECTION FAILED", "Request initialization failed for reading");
                return;
            }
            while (true) {
                int bufferMaxLength = endpoint.getMaxPacketSize();
                ByteBuffer buffer = ByteBuffer.allocate(bufferMaxLength);


                if (request.queue(buffer, bufferMaxLength) == true) {
                    if (connection.requestWait() == request) {
                        String result = new String(buffer.array());
                            Log.i("GELEN DATA : ", result);
                            listener.readData(result);
                    }
                }
            }

        }
    }).start();
}

如果您无法很好地理解,同样的问题在这里由一个人提出:Android bulkTransfer return -1 when read data but there is really some data in the buffer 在与@Mike Ortiz讨论后,我将所有代码都放在这里。当我点击buttonSend时,android设备向设备发送“START”命令,然后开始读取。当我发送第一个值到android设备时,我可以得到它,但是在第一个值之后,我就无法从usb设备获取任何值。我确定usb设备发送了这些值。
public class MainActivity extends Activity implements Runnable {

private static final String TAG = "MAIN ACTIVITY TEST ";

private Button buttonConnect;
private Button butonSend;
private Button buttonDisconnect;
private TextView textViewResult;
private UsbDevice device;

private Thread readThread;
private UsbManager usbManager;
private UsbDeviceConnection connection;
private UsbInterface usbInterface;
private UsbEndpoint usbEndpointIn;
private UsbEndpoint usbEndpointOut;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initView();

    PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    registerReceiver(usbReceiver, filter);

    usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
    Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

    while (deviceIterator.hasNext()) {
        UsbDevice device = deviceIterator.next();

        if (device.getVendorId() == 7358 && device.getProductId() == 3) {
            this.device = device;
            usbManager.requestPermission(device, mPermissionIntent);
            break;
        }
    }

    butonSend.setOnClickListener(new OnClickListener() {


        @Override
        public void onClick(View v) {
            usbInterface = device.getInterface(0);
            connection = usbManager.openDevice(device);
            connection.claimInterface(usbInterface, false);

            for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                UsbEndpoint end = usbInterface.getEndpoint(i);
                if (end.getDirection() == UsbConstants.USB_DIR_IN) {
                    usbEndpointIn = end;

                } else {
                    usbEndpointOut = end;
                }
            }

            //SEND START COMMAND TO  THE USB DEVICE; 
            int result = connection.bulkTransfer(usbEndpointOut, "START".getBytes(), "START".getBytes().length, 1000);
            Log.e("SEND RESULT", result + "");


            //START READING in run method
            readThread = new Thread(MainActivity.this);
            readThread.start();




        }
    });

    buttonDisconnect.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            mRunning = false;
            //readThread.stop();
            connection.releaseInterface(usbInterface);
            connection.close();
            Log.e(TAG, "Connection CLosed.");

        }
    });
}

private static 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 (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) {
                        Toast.makeText(MainActivity.this, "Cihaza izin verildi", Toast.LENGTH_LONG).show();
                    }
                } else {
                    Toast.makeText(MainActivity.this, "Cihaza izin verilmedi.", Toast.LENGTH_LONG).show();
                    Log.d(TAG, "permission denied for device " + device);
                }
            }
        }
    }
};

private boolean mRunning;

private void initView() {
    butonSend = (Button) findViewById(R.id.buttonSend);
    buttonConnect = (Button) findViewById(R.id.buttonConnect);
    textViewResult = (TextView) findViewById(R.id.textViewResult);
    buttonDisconnect = (Button) findViewById(R.id.buttonDisconnect);
}

@Override
public void run() {
    mRunning = true; 

    //READ VALUE UNTIL DISCONNECT
    while (mRunning) {

        byte[] bytes = new byte[usbEndpointIn.getMaxPacketSize()];
        int result = connection.bulkTransfer(usbEndpointIn, bytes, bytes.length, 1000);
        if(result > 0)
        Log.e("RESULT : " + result, "  VALUE : " + new String(bytes));


    }
    Log.d("Thread", "STOPPPED");

} 

}


我认为这里的问题可能是您读取数据太早了(强制侦听器获取可能尚未发送的数据,读取空缓冲区(因此出现-1))。我看不到您的侦听器在哪里定义,但默认情况下,侦听器可能在主线程上运行,而不是您正在与串行设备通信的线程上。 - Rachael
我想获取打印机状态(纸张接近尽头或已用完)。我正在使用来自Android的0x1D、0x52、0x31命令。我尝试了OUT和IN两种方式,但是没有从打印机得到正确的响应。如果我使用OUT,则打印机会返回5,而对于IN,打印机会返回8。是否有任何对我有帮助的东西或指导我如何获取打印机状态?有示例代码吗? - Ajay Mehta
1个回答

5
你的循环中哪个条件失败了?是 (request.queue(buffer, bufferMaxLength) == true) 还是 (connection.requestWait() == request)? 如果是后者,我建议你使用 .equals() 替代引用比较 ==
你尝试过使用批量传输来代替请求吗?
private UsbManager mManager; 
private UsbDevice  mDevice;
private UsbDeviceConnection mDeviceConnection;
private UsbInterface mInterface;
private UsbEndpoint mEndpointIn;   

public void run() {
    while (mEndpointIn != null && mDeviceConnection != null) {
        byte[] recordIn = new byte[mEndpointIn.getMaxPacketSize()];
        int receivedLength = mDeviceConnection.bulkTransfer(mEndpointIn, recordIn,
                                                       recordIn.length, mTimeout);
        if (receivedLength > -1) passDataToListener(recordIn);
    }
}

public void initializeCommunication(Context context) throws UsbDeviceException {

    mInterface = findHidInterface();

    if (mManager != null && mDevice != null && mInterface != null) {
        mDeviceConnection = mManager.openDevice(mDevice);

        if (mDeviceConnection != null) {
            if (mDeviceConnection.claimInterface(mInterface, true)) {
                UsbEndpoint usbEndpointOut = null;
                UsbEndpoint usbEndpointIn = null;

                //
                // Look for Interrupt endpoints
                //
                for (int i = 0; i < mInterface.getEndpointCount(); i++) {
                    UsbEndpoint usbEndpoint = mInterface.getEndpoint(i);

                    if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {
                        if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                            usbEndpointOut = usbEndpoint;

                        } else {
                            usbEndpointIn = usbEndpoint;
                        }
                    }
                }

                if (usbEndpointOut == null || usbEndpointIn == null) {
                    Log.w(DEBUG, "No USB endpoints found.");
                }

                mEndpointOut = usbEndpointOut;
                mEndpointIn = usbEndpointIn;

            } else {
                mDeviceConnection.close();
                Log.w(DEBUG, "USB claim interface failed.");
            }
        } else {
            Log.w(DEBUG, "USB open device failed.");
        }
    } else {
        Log.w(DEBUG, "Some essential USB variables were null.");
    }
}

/**
 * Find the HID interface.
 * 
 * @return
 *      Return the HID interface if found, otherwise null.
 */
private UsbInterface findHidInterface() {
    if (mDevice != null) {
        final int interfaceCount = mDevice.getInterfaceCount();

        for (int interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) {
            UsbInterface usbInterface = mDevice.getInterface(interfaceIndex);

            //
            // Can add UsbInterface.getInterfaceSubclass() and 
            // UsbInterface.getInterfaceProtocol() for more specifics.
            //

            if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
                return usbInterface;
            }
        }

        Log.w(DEBUG, "HID interface not found.");
    }

    return null;
}

问题在于(connection.requestWait() == request)。但我只能得到第一个值。例如,我第一次从USB设备发送1。我可以得到它,但第二次我发送2,我无法在Android设备中获取该值。如果这个条件不正确,为什么在我得到第一个值时它能够工作? - Zapateus
我尝试了你的解决方案,使用bulktransfer后,当我获取第一个值后,receivedLenght总是返回-1。 - Zapateus
有趣的是,我在自己的项目中使用了类似于我发布的代码,并且它适用于多个消息。我的下一个建议是使用USB分析仪来确认套件在第一次按下按钮后是否实际发送数据到手机。 - Mike Ortiz
你能发布其余相关代码吗?你是否调用 mDeviceCommunication.claimInterface(intf, true); 等等?你是否使用了正确类型的接口进行通信?我认为你想要查找特定的 HID 接口,并且只从该特定接口获取端点。你可以下载应用程序“USB设备信息”以枚举您的 USB 设备的端点和接口。 - Mike Ortiz
在你的解决方案中,有一个 if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) 子句,但我的端点类型是 USB_ENDPOINT_XFER_BULK。你知道它们之间的区别吗?而且我的接口类型不是 HID 厂商特定类型。但我认为问题出在我的端点类型上,不是吗? - Zapateus
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接