Preface: Turn ten thousand books, travel thousands of miles, will be a hundred talents.


The introduction

Before speaking android and USB_HID device use control transmission for communication, and the control transmission method of the various parameters in the detailed explanation, if you have not seen it can see this article: Android and USB_HID device through control transmission communication, this is mainly to use the method of batch transmission and in the process of using the attention to record. The last article using control transmission for communication has already said how to obtain USB devices, how to obtain android and HID device communication rights, how to obtain the interface, how to declare the interface, how to control transmission and so on. Using batch tranportation Previously, initialization was the same as control tranportation, except that before a batch tranportation can be performed, the I/O endpoints of the device need to be found so that control tranportation can be performed. We just need to know that before using bulk transport, we need to find the input and output endpoints of the device, and then call the bulk transport method.

directory

Obtaining Endpoints 1.1UsbConstants 1.2 Obtaining number of endpoints 1.3 Determining type of endpoints 1.4 Determining transmission direction of endpoints 1.5 Obtaining input and output endpoints 2. Transmitting data 2.1 APP to HID device 2.2 HID device to APP three, source code four, summary

Get the endpoint

1.1UsbConstants Before obtaining an endpoint, a few constants about the USB protocol: USB_DIR_IN: indicates that the direction of UsbEndpoint data is IN (from the device to the host). USB_DIR_OUT: indicates that the direction of data is OUT (from the host to the device). The preceding two constants are int. 1.2 to obtain the endpoint number int endpointCount = mUsbInterface. GetEndpointCount (); Int usbEndpointType = usbend.getType (); int usbEndpointType = usbend.getType (); This returns an integer constant. There are four common types: ① Control transmission: USB_ENDPOINT_XFER_CONTROL = 0 ② Real-time transmission: USB_ENDPOINT_XFER_ISOC = 1 ③ Bulk transmission: USB_ENDPOINT_XFER_BULK = 2 ④ Interrupt transmission: USB_ENDPOINT_XFER_INT = 3 1.4 Determining the endpoint transmission direction usbendpoint.getDirection () getDirection() The input and output endpoints are determined by this method. 1.5 The input and output endpoints are obtained

for (int i = 0; i < endpointCount; I++) {/ / traverse all endpoints, find the input ends with the output end UsbEndpoint UsbEndpoint = mUsbInterface. GetEndpoint (I); if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) { mUsbEndpointOut = usbEndpoint; Else if (usbend.getDirection () == UsbConstants.USB_DIR_IN) {mUsbEndpointIn = usbEndpoint; // Assign input endpoint}}Copy the code

Second, data transmission

2.1 APP to HID Device

if (manager ! = null) { if (mUsbDevice ! = null) {if (manager.hasPermission(mUsbDevice)) {// Get the communication connection of the current USB device mUsbDeviceConnection = manager.openDevice(mUsbDevice); if (mUsbDeviceConnection ! = null) { mUsbInterface = mUsbDevice.getInterface(0); mUsbDeviceConnection.claimInterface(mUsbInterface,true); X07 final byte [] sendData publishes the event = {0, 0 x00 to 0 x00 to 0 x00 to 0 x00 to 0 x00 to 0 x00 to 0 x00 to 0 x07, 0 x00 to 0 x00 to 0 x00 to 0 x00 to 0 x00 to 0 x00 to 0 x00}; new Thread(new Runnable() { @Override public void run() { int j = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut,sendData,sendData.length,3000); If (j > 0) {showResponse("ConnectToBootloader succeeds "); }else {// failed to receive showResponse("ConnectToBootloader failed "); } } }).start(); }}}}Copy the code

2.2 HID Device to APP

if (manager ! = null) { if (mUsbDevice ! = null) {if (manager.hasPermission(mUsbDevice)) {// Get the communication connection of the current USB device mUsbDeviceConnection = manager.openDevice(mUsbDevice); if (mUsbDeviceConnection ! = null) { mUsbInterface = mUsbDevice.getInterface(0); mUsbDeviceConnection.claimInterface(mUsbInterface,true); new Thread(new Runnable() { @Override public void run() { int j = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut,receiveData,receiveData.length,3000); If (j > 0) {showResponse("SetPageSize32Words succeeded "); }else {showResponse("SetPageSize32Words failed "); } } }).start(); }}}}Copy the code

The length of the data transmitted by the endpoint is determined by the wMaxPcketSize in the endpoint descriptor, as shown in the figure below:



So I’m sending 16byte data, and I’m receiving 16byte arrays, depending on the endpoint descriptor on the hardware side.

The source code

The code inside mainActivity.java is modified from the previous article, and the layout is the same as in the previous article. The last article is about control transmission, this article has been modified to batch transmission.

package com.example.usbhidapp;

import androidx.appcompat.app.AppCompatActivity;

import android.app.PendingIntent;
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.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.example.usbhidapp.myInterface.CommunicationListener;

import java.util.HashMap;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "UsbHid";

    private static final String USB_ACTION = "com.wiseasy.communication.usb.hostchart";

    private final byte[] receiveData = new byte[16];

    private UsbManager manager;//USB管理器
    private UsbDevice mUsbDevice;//找到的USB设备
    private UsbInterface mUsbInterface;
    private UsbDeviceConnection mUsbDeviceConnection;
    private UsbEndpoint mUsbEndpointIn;
    private UsbEndpoint mUsbEndpointOut;
    private UsbCommunication usbCommunication;

    private TextView mTvState;
    private TextView mTvDataReceive;
    private Button mButton;
    private Button mBtnReceive;

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

        mTvState = findViewById(R.id.tv_state);
        mTvDataReceive = findViewById(R.id.tv_data_receive);
        mButton = findViewById(R.id.btn_send);
        mButton.setOnClickListener(this);

        mBtnReceive = findViewById(R.id.btn_receive);
        mBtnReceive.setOnClickListener(this);

        manager = (UsbManager) getSystemService(Context.USB_SERVICE);
        if (manager == null) {
            Log.e(TAG,"不支持OTG");
            Toast.makeText(MainActivity.this,"不支持OTG",Toast.LENGTH_SHORT).show();
            return;
        }else {
            Log.e(TAG,"usb设备:" + manager.toString());
            Toast.makeText(MainActivity.this,manager.toString(),Toast.LENGTH_SHORT).show();
            mTvState.setText(manager.toString());
        }

        usbCommunication = UsbCommunication.getInstance(this);//初始化usb连接对象
        mTvState.setText("初始化usb连接对象");
        usbCommunication.openCommunication(new CommunicationListener() {
            @Override
            public void onSuccess(int code, String msg) {

            }

            @Override
            public void onFaild(String msg) {

            }
        },0x04d9,0xf541);

        HashMap<String,UsbDevice> deviceList = manager.getDeviceList();
        if (!deviceList.isEmpty()) {
            mTvState.setText("deviceList不为空");
            for (UsbDevice device : deviceList.values()) {
                if (device.getVendorId() == 0x04d9 && device.getProductId() == 0xf541) {
                    mUsbDevice = device;
                    mTvState.setText("找到设备" + mUsbDevice);
                    mTvState.setText("hasPermission的状态" + manager.hasPermission(mUsbDevice));
                    if (manager.hasPermission(mUsbDevice)) {
                        //获取当前usb设备的通讯连接
                        mUsbDeviceConnection = manager.openDevice(mUsbDevice);
                        mTvState.setText("获取当前usb设备的通讯连接");
                        if (mUsbDeviceConnection != null) {
                            mTvState.setText("当前usb设备的通讯连接不为空");
                            //获取通讯连接端点数量
                            int endpointCount = mUsbInterface.getEndpointCount();
                            mTvState.setText("获取通讯连接端点数量:" + endpointCount);

                            for (int i = 0; i < endpointCount; i++) {
                                //遍历所有端点,找到输入端点与输出端点
                                UsbEndpoint usbEndpoint = mUsbInterface.getEndpoint(i);
                                if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                                    mUsbEndpointOut = usbEndpoint;//赋值输出端点
                                    mTvState.setText("赋值输出端点:" + mUsbEndpointOut);
                                }else if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_IN) {
                                    mUsbEndpointIn = usbEndpoint;//赋值输入端点
                                    mTvState.setText("赋值输入端点:" + mUsbEndpointIn);
                                }
                            }

                            //当输出端点和输入端点都不为空时,表示usb连接成功,初始化完成,可以进行数据收发
                            if (mUsbEndpointOut != null && mUsbEndpointIn != null) {
                                mTvState.setText("初始化完成");
                                Toast.makeText(MainActivity.this,"初始化完成",Toast.LENGTH_SHORT).show();
                            }
                        }
                    }

                }else {
                    Toast.makeText(MainActivity.this,"NotFind VID and PID",Toast.LENGTH_SHORT).show();
                }
            }
        }else {
            Toast.makeText(MainActivity.this,"请连接USB",Toast.LENGTH_SHORT).show();
        }
    }
    
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_send://发送
                if (manager != null) {
                    if (mUsbDevice != null) {
                        if (manager.hasPermission(mUsbDevice)) {
                            //获取当前usb设备的通讯连接
                            mUsbDeviceConnection = manager.openDevice(mUsbDevice);
                            if (mUsbDeviceConnection != null) {
                                mUsbInterface = mUsbDevice.getInterface(0);
                                mUsbDeviceConnection.claimInterface(mUsbInterface,true);
                                final byte[] sendData = {0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        int j = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut,sendData,sendData.length,3000);//发送数据
                                        if (j > 0) {
                                            //接收成功
                                            showResponse("发送成功");

                                        }else {
                                            //接收失败
                                            showResponse("发送失败");
                                        }
                                    }
                                }).start();
                            }
                        }
                    }
                }
                break;
            case R.id.btn_receive://接收
                if (manager != null) {
                    if (mUsbDevice != null) {
                        if (manager.hasPermission(mUsbDevice)) {
                            //获取当前usb设备的通讯连接
                            mUsbDeviceConnection = manager.openDevice(mUsbDevice);
                            if (mUsbDeviceConnection != null) {
                                mUsbInterface = mUsbDevice.getInterface(0);
                                mUsbDeviceConnection.claimInterface(mUsbInterface,true);
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        int j = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut,receiveData,receiveData.length,3000);//发送数据
                                        if (j > 0) {
                                            //接收成功
                                            showResponse("接收成功");
                                        }else {
                                            //接收失败
                                            showResponse("接收失败");
                                        }
                                    }
                                }).start();
                            }
                        }
                    }
                }
                break;
            default:
                break;
        }
    }

    private void showResponse(final String response) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                switch (response) {
                    case "发送成功":
                        mTvDataReceive.setText("发送成功");
                        break;
                    case "发送失败":
                        mTvDataReceive.setText("发送失败");
                        break;
                    case "接收成功":
                        mTvDataReceive.setText("接收成功");
                        break;
                    case "接收失败":
                        mTvDataReceive.setText("接收失败");
                        break;
                    default:
                        break;
                }
            }
        });
    }
}

Copy the code

conclusion

This is the use of batch transmission data communication, there are some attention points, mainly in their own development of the project useful to batch transmission code into the IC, since the control of transmission are written, simply even batch transmission also write up. See here, some friends found that I have written wrong places, please point out, modestly modify, if you help friends, give a praise ~