当前位置: 首页 > 知识库问答 >
问题:

使用Android USB主机API读取我的USB游戏控制器/或其他USB设备数据

韦阳晖
2023-03-14
TextView countDisplay;
    ArrayList<String> listItems = new ArrayList<String>();
    ArrayAdapter<String> adapter;
    String values = "";
    UsbManager mManager;
    UsbDevice device = null;
    private byte[] bytes;
    private static int TIMEOUT = 0;
    private boolean forceClaim = true;
    static PendingIntent mPermissionIntent;
    UsbDeviceConnection connection = null;
    UsbEndpoint InputEndpoint = null;
    UsbEndpoint OutputEndpoint = null;
    private Handler mHandler = new Handler();


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
            "com.android.example.USB_PERMISSION"), 0);
    IntentFilter filter = new IntentFilter();
    filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
    filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
    registerReceiver(mUsbReceiver, filter);

    HashMap<String, UsbDevice> deviceList = mManager.getDeviceList();
    values = values + "deviceListSize:" + deviceList.size() + ",tostring:"
            + deviceList.toString();
    Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
    while (deviceIterator.hasNext()) {
        device = deviceIterator.next();
        values = values + ",device id:" + device.getDeviceId()
                + ",device name:" + device.getDeviceName();
        values = values + ",Protocol:" + device.getDeviceProtocol()
                + ",ProductId:" + device.getProductId();
        values = values + ",DeviceClass:" + device.getDeviceClass()
                + ",VendorId:" + device.getVendorId();
    }
    if (device != null) {
        values = values + ",getInterfaceCount:"
                + device.getInterfaceCount();
        UsbInterface intf = device.getInterface(0);
        values = values + ",intf.getEndpointCount():"
                + intf.getEndpointCount();
        UsbEndpoint endpoint1 = intf.getEndpoint(0);
        UsbEndpoint endpoint2 = intf.getEndpoint(1);

        mManager.requestPermission(device, mPermissionIntent);
        if (mManager.hasPermission(device)) {
            values = values + ",has permission over device!";
            connection = mManager.openDevice(device);
            if (connection == null) {
                values = values + ",connection null";
            } else {
                values = values + ",getFileDescriptor:"
                        + connection.getFileDescriptor();
                if (endpoint1.getDirection() == UsbConstants.USB_DIR_IN) {
                    InputEndpoint = endpoint1;
                } else {
                    OutputEndpoint = endpoint1;
                }
                if (endpoint2.getDirection() == UsbConstants.USB_DIR_IN) {
                    InputEndpoint = endpoint2;
                } else {
                    OutputEndpoint = endpoint2;
                }
            }
            if (InputEndpoint == null) {
                countDisplay.setText(values + ",InputEndpoint is null");
            }
            if (OutputEndpoint == null) {
                countDisplay.setText(values + ",OutputEndPoint is null");
            }
            connection.claimInterface(intf, forceClaim);
            mHandler.postDelayed(runnable, 1);
        } else {
            values = values + ",Do not have permission over device!";
        }

    }

    setContentView(R.layout.activity_main);
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View v = inflater.inflate(R.layout.activity_main, null);
    LinearLayout ll = new LinearLayout(this);
    ll.setOrientation(LinearLayout.VERTICAL);
    int counter = 1;
    countDisplay = new TextView(this);
    ll.addView(countDisplay);

    countDisplay.setText(values + ",counter here");
    final Button button = new Button(this);
    button.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            if (device != null && mManager.hasPermission(device)) {
                values = values + ",device id:" + device.getDeviceId()
                        + ",device name:" + device.getDeviceName();
                values = values + ",Protocol:" + device.getDeviceProtocol()
                        + ",ProductId:" + device.getProductId();
                values = values + ",DeviceClass:" + device.getDeviceClass()
                        + ",VendorId:" + device.getVendorId();

                countDisplay.setText(values + ",okok");

            } else {
                if (device != null)
                    mManager.requestPermission(device, mPermissionIntent);
            }
        }

    });
    ll.addView(button);
    setContentView(ll);
}

和可运行:

private Runnable runnable = new Runnable() {
    public void run() {
        if (connection != null) {
            int count = connection.bulkTransfer(InputEndpoint, bytes,
                    bytes.length, TIMEOUT);
            countDisplay.setText(values + ",bultTransferNo:" + count);
            countDisplay.setText(values + "bulkValue:" + bytes);
        } else {
            countDisplay.setText(values + ",connection is null");
        }
    }
};

共有1个答案

孔鸿云
2023-03-14

此程序作为以下USB主机功能的示例:

>

  • 根据接口类、子类和协议匹配设备(请参阅device_filter.xml)

    大容量endpoint上的异步IO

        /*
         * Copyright (C) 2011 The Android Open Source Project
         *
         * Licensed under the Apache License, Version 2.0 (the "License");
         * you may not use this file except in compliance with the License.
         * You may obtain a copy of the License at
         *
         *      http://www.apache.org/licenses/LICENSE-2.0
         *
         * Unless required by applicable law or agreed to in writing, software
         * distributed under the License is distributed on an "AS IS" BASIS,
         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         * See the License for the specific language governing permissions and
         * limitations under the License.
         */
    
        package com.android.adb;
    
        import android.hardware.usb.UsbConstants;
        import android.hardware.usb.UsbDeviceConnection;
        import android.hardware.usb.UsbEndpoint;
        import android.hardware.usb.UsbInterface;
        import android.hardware.usb.UsbRequest;
        import android.util.SparseArray;
    
        import java.util.LinkedList;
    
        /* This class represents a USB device that supports the adb protocol. */
        public class AdbDevice {
    
            private final AdbTestActivity mActivity;
            private final UsbDeviceConnection mDeviceConnection;
            private final UsbEndpoint mEndpointOut;
            private final UsbEndpoint mEndpointIn;
    
            private String mSerial;
    
            // pool of requests for the OUT endpoint
            private final LinkedList<UsbRequest> mOutRequestPool = new LinkedList<UsbRequest>();
            // pool of requests for the IN endpoint
            private final LinkedList<UsbRequest> mInRequestPool = new LinkedList<UsbRequest>();
            // list of currently opened sockets
            private final SparseArray<AdbSocket> mSockets = new SparseArray<AdbSocket>();
            private int mNextSocketId = 1;
    
            private final WaiterThread mWaiterThread = new WaiterThread();
    
            public AdbDevice(AdbTestActivity activity, UsbDeviceConnection connection,
                    UsbInterface intf) {
                mActivity = activity;
                mDeviceConnection = connection;
                mSerial = connection.getSerial();
    
                UsbEndpoint epOut = null;
                UsbEndpoint epIn = null;
                // look for our bulk endpoints
                for (int i = 0; i < intf.getEndpointCount(); i++) {
                    UsbEndpoint ep = intf.getEndpoint(i);
                    if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                        if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                            epOut = ep;
                        } else {
                            epIn = ep;
                        }
                    }
                }
                if (epOut == null || epIn == null) {
                    throw new IllegalArgumentException("not all endpoints found");
                }
                mEndpointOut = epOut;
                mEndpointIn = epIn;
            }
    
            // return device serial number
            public String getSerial() {
                return mSerial;
            }
    
            // get an OUT request from our pool
            public UsbRequest getOutRequest() {
                synchronized(mOutRequestPool) {
                    if (mOutRequestPool.isEmpty()) {
                        UsbRequest request = new UsbRequest();
                        request.initialize(mDeviceConnection, mEndpointOut);
                        return request;
                    } else {
                        return mOutRequestPool.removeFirst();
                    }
                }
            }
    
            // return an OUT request to the pool
            public void releaseOutRequest(UsbRequest request) {
                synchronized (mOutRequestPool) {
                    mOutRequestPool.add(request);
                }
            }
    
            // get an IN request from the pool
            public UsbRequest getInRequest() {
                synchronized(mInRequestPool) {
                    if (mInRequestPool.isEmpty()) {
                        UsbRequest request = new UsbRequest();
                        request.initialize(mDeviceConnection, mEndpointIn);
                        return request;
                    } else {
                        return mInRequestPool.removeFirst();
                    }
                }
            }
    
            public void start() {
                mWaiterThread.start();
                connect();
            }
    
            public AdbSocket openSocket(String destination) {
                AdbSocket socket;
                synchronized (mSockets) {
                    int id = mNextSocketId++;
                    socket = new AdbSocket(this, id);
                    mSockets.put(id, socket);
                }
                if (socket.open(destination)) {
                    return socket;
                } else {
                    return null;
                }
            }
    
            private AdbSocket getSocket(int id) {
                synchronized (mSockets) {
                    return mSockets.get(id);
                }
            }
    
            public void socketClosed(AdbSocket socket) {
                synchronized (mSockets) {
                    mSockets.remove(socket.getId());
                }
            }
    
            // send a connect command
            private void connect() {
                AdbMessage message = new AdbMessage();
                message.set(AdbMessage.A_CNXN, AdbMessage.A_VERSION, AdbMessage.MAX_PAYLOAD, "host::\0");
                message.write(this);
            }
    
            // handle connect response
            private void handleConnect(AdbMessage message) {
                if (message.getDataString().startsWith("device:")) {
                    log("connected");
                    mActivity.deviceOnline(this);
                }
            }
    
            public void stop() {
                synchronized (mWaiterThread) {
                    mWaiterThread.mStop = true;
                }
            }
    
            // dispatch a message from the device
            void dispatchMessage(AdbMessage message) {
                int command = message.getCommand();
                switch (command) {
                    case AdbMessage.A_SYNC:
                        log("got A_SYNC");
                        break;
                    case AdbMessage.A_CNXN:
                        handleConnect(message);
                        break;
                    case AdbMessage.A_OPEN:
                    case AdbMessage.A_OKAY:
                    case AdbMessage.A_CLSE:
                    case AdbMessage.A_WRTE:
                        AdbSocket socket = getSocket(message.getArg1());
                        if (socket == null) {
                            log("ERROR socket not found");
                        } else {
                            socket.handleMessage(message);
                        }
                        break;
                }
            }
    
            void log(String s) {
                mActivity.log(s);
            }
    
    
            private class WaiterThread extends Thread {
                public boolean mStop;
    
                public void run() {
                    // start out with a command read
                    AdbMessage currentCommand = new AdbMessage();
                    AdbMessage currentData = null;
                    // FIXME error checking
                    currentCommand.readCommand(getInRequest());
    
                    while (true) {
                        synchronized (this) {
                            if (mStop) {
                                return;
                            }
                        }
                        UsbRequest request = mDeviceConnection.requestWait();
                        if (request == null) {
                            break;
                        }
    
                        AdbMessage message = (AdbMessage)request.getClientData();
                        request.setClientData(null);
                        AdbMessage messageToDispatch = null;
    
                        if (message == currentCommand) {
                            int dataLength = message.getDataLength();
                            // read data if length > 0
                            if (dataLength > 0) {
                                message.readData(getInRequest(), dataLength);
                                currentData = message;
                            } else {
                                messageToDispatch = message;
                            }
                            currentCommand = null;
                        } else if (message == currentData) {
                            messageToDispatch = message;
                            currentData = null;
                        }
    
                        if (messageToDispatch != null) {
                            // queue another read first
                            currentCommand = new AdbMessage();
                            currentCommand.readCommand(getInRequest());
    
                            // then dispatch the current message
                            dispatchMessage(messageToDispatch);
                        }
    
                        // put request back into the appropriate pool
                        if (request.getEndpoint() == mEndpointOut) {
                            releaseOutRequest(request);
                        } else {
                            synchronized (mInRequestPool) {
                                mInRequestPool.add(request);
                            }
                        }
                    }
                }
            }
        }
    
        package com.android.adb;
    
        import android.hardware.usb.UsbRequest;
    
        import java.nio.ByteBuffer;
        import java.nio.ByteOrder;
    
        /* This class encapsulates and adb command packet */
        public class AdbMessage {
    
            // command names
            public static final int A_SYNC = 0x434e5953;
            public static final int A_CNXN = 0x4e584e43;
            public static final int A_OPEN = 0x4e45504f;
            public static final int A_OKAY = 0x59414b4f;
            public static final int A_CLSE = 0x45534c43;
            public static final int A_WRTE = 0x45545257;
    
            // ADB protocol version
            public static final int A_VERSION = 0x01000000;
    
            public static final int MAX_PAYLOAD = 4096;
    
            private final ByteBuffer mMessageBuffer;
            private final ByteBuffer mDataBuffer;
    
            public AdbMessage() {
                mMessageBuffer = ByteBuffer.allocate(24);
                mDataBuffer = ByteBuffer.allocate(MAX_PAYLOAD);
                mMessageBuffer.order(ByteOrder.LITTLE_ENDIAN);
                mDataBuffer.order(ByteOrder.LITTLE_ENDIAN);
            }
    
            // sets the fields in the command header
            public void set(int command, int arg0, int arg1, byte[] data) {
                mMessageBuffer.putInt(0, command);
                mMessageBuffer.putInt(4, arg0);
                mMessageBuffer.putInt(8, arg1);
                mMessageBuffer.putInt(12, (data == null ? 0 : data.length));
                mMessageBuffer.putInt(16, (data == null ? 0 : checksum(data)));
                mMessageBuffer.putInt(20, command ^ 0xFFFFFFFF);
                if (data != null) {
                    mDataBuffer.put(data, 0, data.length);
                }
            }
    
            public void set(int command, int arg0, int arg1) {
                set(command, arg0, arg1, (byte[])null);
            }
            public void set(int command, int arg0, int arg1, String data) {
                // add trailing zero
                data += "\0";
                set(command, arg0, arg1, data.getBytes());
            }
    
            // returns the command's message ID
            public int getCommand() {
                return mMessageBuffer.getInt(0);
            }
    
            // returns command's first argument
            public int getArg0() {
                return mMessageBuffer.getInt(4);
            }
    
            // returns command's second argument
            public int getArg1() {
                return mMessageBuffer.getInt(8);
            }
    
            // returns command's data buffer
            public ByteBuffer getData() {
                return mDataBuffer;
            }
    
            // returns command's data length
            public int getDataLength() {
                return mMessageBuffer.getInt(12);
            }
    
            // returns command's data as a string
            public String getDataString() {
                int length = getDataLength();
                if (length == 0) return null;
                // trim trailing zero
                return new String(mDataBuffer.array(), 0, length - 1);
            }
    
    
            public boolean write(AdbDevice device) {
                synchronized (device) {
                    UsbRequest request = device.getOutRequest();
                    request.setClientData(this);
                    if (request.queue(mMessageBuffer, 24)) {
                        int length = getDataLength();
                        if (length > 0) {
                            request = device.getOutRequest();
                            request.setClientData(this);
                            if (request.queue(mDataBuffer, length)) {
                                return true;
                            } else {
                                device.releaseOutRequest(request);
                                return false;
                            }
                        }
                        return true;
                    } else {
                        device.releaseOutRequest(request);
                        return false;
                    }
                }
            }
    
            public boolean readCommand(UsbRequest request) {
                request.setClientData(this);
                return request.queue(mMessageBuffer, 24);
            }
    
            public boolean readData(UsbRequest request, int length) {
                request.setClientData(this);
                return request.queue(mDataBuffer, length);
            }
    
            private static String extractString(ByteBuffer buffer, int offset, int length) {
                byte[] bytes = new byte[length];
                for (int i = 0; i < length; i++) {
                    bytes[i] = buffer.get(offset++);
                }
                return new String(bytes);
            }
    
            @Override
            public String toString() {
                String commandName = extractString(mMessageBuffer, 0, 4);
                int dataLength = getDataLength();
                String result = "Adb Message: " + commandName + " arg0: " + getArg0() +
                     " arg1: " + getArg1() + " dataLength: " + dataLength;
                if (dataLength > 0) {
                    result += (" data: \"" + getDataString() + "\"");
                }
                return result;
            }
    
            private static int checksum(byte[] data) {
                int result = 0;
                for (int i = 0; i < data.length; i++) {
                    int x = data[i];
                    // dang, no unsigned ints in java
                    if (x < 0) x += 256;
                    result += x;
                }
                return result;
            }
        }
    
        package com.android.adb;
    
        /* This class represents an adb socket.  adb supports multiple independent
         * socket connections to a single device.  Typically a socket is created
         * for each adb command that is executed.
         */
        public class AdbSocket {
    
            private final AdbDevice mDevice;
            private final int mId;
            private int mPeerId;
    
            public AdbSocket(AdbDevice device, int id) {
                mDevice = device;
                mId = id;
            }
    
            public int getId() {
                return mId;
            }
    
            public boolean open(String destination) {
                AdbMessage message = new AdbMessage();
                message.set(AdbMessage.A_OPEN, mId, 0, destination);
                if (! message.write(mDevice)) {
                    return false;
                }
    
                synchronized (this) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        return false;
                    }
                }
                return true;
            }
    
            public void handleMessage(AdbMessage message) {
                switch (message.getCommand()) {
                    case AdbMessage.A_OKAY:
                        mPeerId = message.getArg0();
                        synchronized (this) {
                            notify();
                        }
                        break;
                    case AdbMessage.A_WRTE:
                        mDevice.log(message.getDataString());
                        sendReady();
                        break;
                }
            }
    
            private void sendReady() {
                AdbMessage message = new AdbMessage();
                message.set(AdbMessage.A_OKAY, mId, mPeerId);
                message.write(mDevice);
            }
        }
    

  •  类似资料:
    • 我正在尝试从连接到主机模式下的Android手机的USB设备中获取一些数据。我可以发送数据到它,但读取失败。 我一直从方法获得,它指示某种错误,它总是超时。也许问题来自于连接配置,我试了几次(读作:试错),没有一次奏效,令人惊讶的是,我不需要任何配置来发送数据到设备。 编辑 还必须注意的是,我使用的电缆是micro-USB到micro-USB的,它只能以一种方式工作,即只有当插头A连接到电话和插头

    • 问题内容: 我正在考虑制作带有旋钮,按钮和LED的物理控制器(设备?)。我想使用Java与它进行交互(响应旋钮,点亮LED等)。我提到Java的原因有两个:首先,我非常了解Java 1。其次,我已经用Java编写了我需要与之交互的程序的其余部分(尽管可以通过其他语言与Java程序进行通信)。 我希望该设备通过USB连接,并且独立于(计算机)平台。 除了开始阅读Arduino网站外,我对从哪里开始一

    • python 怎么实现监控电脑是否有usb或其他可移动设备插入,最好也能检测手机插入。 用来在办公室里防止usb设备插入内部电脑里、 试过是做了一个pyqt的程序,然后开机后读取当前盘符,并保存下来,如果出现新的盘符就报错然后提醒用户拔掉,但是这样显然是有bug。 国内暂时没有特别靠谱的解决方法。

    • 简介 USB 即 Universal Serial Bus 是一种支持热插拔的通用串行总线,在 USB 体系中又分为 USB Host 和 USB Device。本文将基于 stm32l475-atk-pandora 开发板,讲解基于 RT-Thread Studio 开发 USB Device 驱动。 USB Device 设备驱动的开发可总结为如下几个步骤: 新建 RT-Thread 完整版项

    • 上次我检查时,Docker没有任何方法让容器访问主机串行或USB端口。有没有什么诀窍可以让你这么做?

    • 问题内容: 上次我检查时,Docker没有任何方法允许容器访问主机串行或USB端口。有没有办法做到这一点? 问题答案: 有两种选择。您可以使用可用于访问无模式USB设备的标志: 或者,假设您的USB设备在主机上的驱动程序可用等情况下可用,则可以使用特权模式和volumes选项将其安装在容器中。例如: 请注意,顾名思义,它是不安全的 ,应谨慎处理。