android usb 异步请求理解

来源:互联网 发布:java中间件 是什么 编辑:程序博客网 时间:2024/06/10 09:00

先贴这个adbtest的例子,用android的usb sdk传输adb协议数据,将android的logcat信息打印再屏幕上。
我研究这个例子的目的是为了实现usb传输tcpip数据,需要借用adb。

http://www.java2s.com/Code/Android/Hardware/USBdevicethatsupportstheadbprotocol.htm

这例子具体有几个类:adbdeviceadbmessage`adbsocket
其中adbdevice是主类,里面有个线程WaitThread主要是用到usb异步读的地方。
huesb异步操作的主要流程是:
1. 调用initialize(UsbDeviceConnection connection, UsbEndpoint endpoint)初始化好1个request,connection是指明连接的,endpoint可以是相应的in或out;
2. 调用queue(ByteBuffer buffer, int length)提交Buffer去读或者写数据;
3. 调用setClientData(Object data)可以做标记,具体作用在下面代码的注释里。
4. 调用usbDeviceConection的requestWait()等待request异步请求生效;注意requestWait()对所有endpoint提交的request都可能生效。很重要的一点是要判断提交的request是否是wait到的request,才能控制不同endpoint的数据流。
贴代码和注释:

        private class WaiterThread extends Thread {        public boolean mStop;        public void run() {            // start out with a command read            AdbMessage currentCommand = new AdbMessage();            AdbMessage currentData = null;            //封装了usbRequest.setClientData和queue,请求读adb协议的command header数据段            currentCommand.readCommand(getInRequest());            while (true) {                synchronized (this) {                    if (mStop) {                        return;                    }                }                //阻塞等待request被响应,                UsbRequest request = mDeviceConnection.requestWait();                if (request == null) {                    break;                }                AdbMessage message = (AdbMessage)request.getClientData();                request.setClientData(null);                AdbMessage messageToDispatch = null;                /*                 *为何要如此检查?因为requestWait()等的是所有endpoint提交的request,任何1个都有可能                 *怎么检查的?在queque的时候,用setclientdata做了标记,然后再比较request的时候,用                 *getclientdata的结果进行对比                 */                if (message == currentCommand) {                    int dataLength = message.getDataLength();                    // read data if length > 0                    if (dataLength > 0) {                        //请求读adb协议的command data数据段                        message.readData(getInRequest(), dataLength);                        currentData = message;                    } else {                        messageToDispatch = message;                    }                    currentCommand = null;                //只需关注自己提交的、而不是其他endpoint的 command data request                } else if (message == currentData) {                    messageToDispatch = message;                    currentData = null;                }                //command data字段 准备解析并处理                if (messageToDispatch != null) {                    // queue another read first                    //先提交一次read command header, 为下一次接收做准备                    currentCommand = new AdbMessage();                    currentCommand.readCommand(getInRequest());                    // then dispatch the current message                    dispatchMessage(messageToDispatch);                }                // put request back into the appropriate pool                //in or out request用完了 重新放回List中;                       if (request.getEndpoint() == mEndpointOut) {                    releaseOutRequest(request);                } else {                    synchronized (mInRequestPool) {                        mInRequestPool.add(request);                    }                }            }        }    }

再看如何dispatch消息的,这个就和adb协议直接相关了:

    void dispatchMessage(AdbMessage message) {        int command = message.getCommand();        switch (command) {              case AdbMessage.A_SYNC:                log("got A_SYNC");//收到同步command                break;            case AdbMessage.A_CNXN:                handleConnect(message);//收到connect response,处理下                break;            case AdbMessage.A_OPEN:            case AdbMessage.A_OKAY:                AdbSocket socket = getSocket(message.getArg1());                if (socket == null) {                    log("ERROR socket not found");                } else {                    mPeerId = message.getArg0(); //收到ok response                     synchronized (this) {                        notify();                    }                }                break;            case AdbMessage.A_CLSE:            case AdbMessage.A_WRTE:                AdbSocket socket = getSocket(message.getArg1());                if (socket == null) {                    log("ERROR socket not found");                } else {                    //device往host write,即 host接收数据,这里的数据就是logcat的消息;                      mDevice.log(message.getDataString());                    sendReady();                }                break;        }    }
0 0