Android-USB通信
本文记录下,Android平台上如何与USB设备进行通信。我这里使用的USB设备是一个USB加密设备(简称Ukey),通过与Ukey通信,对数据进行加密,提供一些加密算法。
USB API介绍
- UsbManager:获得USB的状态,与连接的USB设备通信。
- UsbDevice:USB设备的抽象,它包含了一个或多个的UsbInterface,而每个UsbInterface包含多个UsbEndpoint。Host与其通信,先打开UsbDeviceConnection,使用UsbRequest在一个端点(UsbEndpoint)发送和接受数据。
- UsbDeviceConnection:host与device建立的连接,并在endpoint传输数据。
- UsbEndpoint:endpoint是interface的通信信道。
- UsbInterface : 定理设备的功能集,一个UsbDevice包含多个UsbInterface,每个UsbInterface都是独立的。
- UsbRequest:usb请求包。可以在UsbDeviceConnection上异步传输数据。注意是只在异步通信时才会使用到它。
UsbManager常用方法 | 说明 |
---|
getDeviceList() | 获得设备列表,返回的是一个HashMap | hasPermission(UsbDevice device) | 判断你的应用程序是否有接入此USB设备的权限,如果有则返回真,否则返回false | openDevice(UsbDevice device) | 打开USB设备,以便向此USB设备发送和接受数据,返回一个关于此USB设备的连接 | requestPermission(UsbDevice device, PendingIntent pi) | 向USB设备请求临时的接入权限 |
UsbDevice常用方法 | 说明 |
---|
getDeviceClass() | 返回此USB设备的类别,用一个整型来表示 | getDeviceId() | 返回唯一标识此设备的ID号,也用一个整型来表示 | getDeviceName() | 返回此设备的名称,用一个字符串来表示 | getDeviceProtocol() | 返回此设备的协议类别,用一个整型来表示 | getDeviceSubclass() | 返回此设备的子类别,用一个整型来表示 | getVendorId() | 返回生产商ID | getProductId() | 返回产品ID | getInterfaceCount() | 返回此设备的接口数量 | getInterface(int index) | 得到此设备的一个接口,返回一个UsbInterface |
UsbDeviceConnection常用方法 | 说明 |
---|
bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) | 通过给定的endpoint来进行大量的数据传输,传输的方向取决于该节点的方向,buffer是要发送或接收的字节数组,length是该字节数组的长度。传输成功则返回所传输的字节数组的长度,失败则返回负数 | controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout | 该方法通过0节点向此设备传输数据,传输的方向取决于请求的类别,如果requestType为USB_DIR_OUT则为写数据,USB_DIR_IN, 则为读数据 |
UsbEndpoint常用方法 | 说明 |
---|
getAddress() | 获得此节点的地址 | getAttributes() | 获得此节点的属性 | getDirection() | 获得此节点的数据传输方向 |
UsbInterface常用方法 | 说明 |
---|
getId() | 得到给接口的id号。 | getInterfaceClass() | 得到该接口的类别 | getInterfaceSubclass() | 得到该接口的子类 | getInterfaceProtocol() | 得到该接口的协议类别。 | getEndpointCount() | 获得关于此接口的节点数量 | getEndpoint(int index) | 对于指定的index获得此接口的一个节点,返回一个UsbEndpoint |
获取USB设备权限
- 首先在AndroidManifest.xml中添加权限
<uses-feature
android:name="android.hardware.usb.host"
android:required="true"/>
<uses-permission android:name="android.permission.MANAGE_USB"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.HARDWARE_TEST"
tools:ignore="ProtectedPermissions" />
在标签中添加:
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_USB" />
在res下创建xml名称的文件夹。 device_USB.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="9840" product-id="1030"/>
</resources>
- 申请USB权限
private static final String ACTION_USB_PERMISSION = "com.android.usb.USB_PERMISSION";
private void getUsbPermission(UsbDevice mUSBDevice) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(mUsbReceiver, filter);
usbManager.requestPermission(mUSBDevice, pendingIntent);
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
unregisterReceiver(mUsbReceiver);
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) && device.equals(device)) {
initUSB();
} else {
Toast.makeText(MainActivity.this, "拒绝权限会造成与UKey通信失败!", Toast.LENGTH_SHORT).show();
}
}
}
}
};
初始化设备
- 获取USB设备
UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
List<UsbDevice> usbDevices = new ArrayList<UsbDevice>();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
usbDevices.add(device);
Log.e("USB_Test", "getDeviceList: " + device.getDeviceId());
}
device = usbDevices.get(0);
- 获取设备功能节点
UsbInterface usbInterface = device.getInterface(0);
UsbEndpoint epBulkIn = usbInterface.getEndpoint(0);
UsbEndpoint epBulkOut = usbInterface.getEndpoint(1);
f (usbInterface != null) {
if (usbManager.hasPermission(device)) {
usbDeviceConnection = usbManager.openDevice(device);
}
if (usbDeviceConnection != null && usbDeviceConnection.claimInterface(usbInterface, true)) {
usbDeviceConnection = conn;
if (usbDeviceConnection != null) {
Log.e("USB_Test", "android设备已经连接硬件设备.");
}
} else {
}
}
USB交互
发送测试指令
private void sendToUsb(UsbEndpoint usbEpOut, UsbEndpoint usbEpIn) {
byte[] buffer = new byte[320];
buffer[0] = 0x02;
buffer[1] = 0x00;
buffer[2] = 0x05;
buffer[3] = 0x00;
buffer[4] = (byte) 0x84;
buffer[5] = 0x00;
buffer[6] = 0x00;
buffer[7] = 0x10;
int ret = -1;
ret = usbDeviceConnection.bulkTransfer(usbEpOut, buffer, buffer.length, 5000);
byte[] receiveytes = new byte[320];
ret = usbDeviceConnection.bulkTransfer(usbEpIn, receiveytes, receiveytes.length, 10000);
try {
String strHex = DataUtils.getByteHexString(receiveytes);
tv.setText(ret + "\n " + strHex);
} catch (Exception e) {
e.printStackTrace();
}
}
运行效果:
|