获取usb设备类型

项目中需要区分USB的连接设备是打印机还是电子秤,然后上网搜索到了一篇博客,根据这个博客写的一个小的例子:非常感谢hao2014_的这篇博客http://blog.csdn.net/u013686019/article/details/50409421


MainActivity:

[java]  view plain  copy
 
  1. package com.example.administrator.usbmanagertest;  
  2.   
  3. import android.content.Context;  
  4. import android.hardware.usb.UsbDevice;  
  5. import android.hardware.usb.UsbInterface;  
  6. import android.hardware.usb.UsbManager;  
  7. import android.support.v7.app.AppCompatActivity;  
  8. import android.os.Bundle;  
  9. import android.view.View;  
  10. import android.widget.TextView;  
  11.   
  12. import java.util.HashMap;  
  13. import java.util.Iterator;  
  14.   
  15. public class MainActivity extends AppCompatActivity {  
  16.   
  17.     private TextView textView;  
  18.   
  19.     @Override  
  20.     protected void onCreate(Bundle savedInstanceState) {  
  21.         super.onCreate(savedInstanceState);  
  22.         setContentView(R.layout.activity_main);  
  23.         textView = (TextView) findViewById(R.id.sb);  
  24.     }  
  25.   
  26.     public void showUsbList(View view) {  
  27.         UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);  
  28.   
  29.         HashMap deviceList = manager.getDeviceList();  
  30.   
  31.         Iterator deviceIterator = deviceList.values().iterator();  
  32.   
  33.         StringBuilder sb = new StringBuilder();  
  34.         while (deviceIterator.hasNext()){  
  35.             UsbDevice usbDevice = deviceIterator.next();  
  36.             sb.append("DeviceName="+usbDevice.getDeviceName()+"\n");  
  37.             sb.append("DeviceId="+usbDevice.getDeviceId()+"\n");  
  38.             sb.append("VendorId="+usbDevice.getVendorId()+"\n");  
  39.             sb.append("ProductId="+usbDevice.getProductId()+"\n");  
  40.             sb.append("DeviceClass="+usbDevice.getDeviceClass()+"\n");  
  41.             int deviceClass = usbDevice.getDeviceClass();  
  42.             if(deviceClass==0) {  
  43.                 UsbInterface anInterface = usbDevice.getInterface(0);  
  44.                 int interfaceClass = anInterface.getInterfaceClass();  
  45.   
  46.                 sb.append("device Class 为0-------------\n");  
  47.                 sb.append("Interface.describeContents()="+anInterface.describeContents()+"\n");  
  48.                 sb.append("Interface.getEndpointCount()="+anInterface.getEndpointCount()+"\n");  
  49.                 sb.append("Interface.getId()="+anInterface.getId()+"\n");  
  50.                 //http://blog.csdn.net/u013686019/article/details/50409421  
  51.                 //http://www.usb.org/developers/defined_class/#BaseClassFFh  
  52.                 //通过下面的InterfaceClass 来判断到底是哪一种的,例如7就是打印机,8就是usb的U盘  
  53.                 sb.append("Interface.getInterfaceClass()="+anInterface.getInterfaceClass()+"\n");  
  54.                 if(anInterface.getInterfaceClass()==7){  
  55.                     sb.append("此设备是打印机\n");  
  56.                 }else if(anInterface.getInterfaceClass()==8){  
  57.                     sb.append("此设备是U盘\n");  
  58.                 }  
  59.                 sb.append("anInterface.getInterfaceProtocol()="+anInterface.getInterfaceProtocol()+"\n");  
  60.                 sb.append("anInterface.getInterfaceSubclass()="+anInterface.getInterfaceSubclass()+"\n");  
  61.                 sb.append("device Class 为0------end-------\n");  
  62.             }  
  63.   
  64.             sb.append("DeviceProtocol="+usbDevice.getDeviceProtocol()+"\n");  
  65.             sb.append("DeviceSubclass="+usbDevice.getDeviceSubclass()+"\n");  
  66.             sb.append("+++++++++++++++++++++++++++\n");  
  67.             sb.append("                           \n");  
  68.         }  
  69.   
  70.         textView.setText(sb);  
  71.     }  
  72. }  


activity_main.xml

[html]  view plain  copy
 
  1. xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:paddingBottom="@dimen/activity_vertical_margin"  
  7.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  8.     android:paddingRight="@dimen/activity_horizontal_margin"  
  9.     android:paddingTop="@dimen/activity_vertical_margin"  
  10.     tools:context="com.example.administrator.usbmanagertest.MainActivity">  
  11.   
  12.     <Button  
  13.         android:layout_width="wrap_content"  
  14.         android:layout_height="wrap_content"  
  15.         android:onClick="showUsbList"  
  16.         android:text="Show USB List" />  
  17.     <ScrollView  
  18.         android:layout_width="match_parent"  
  19.         android:layout_height="match_parent">  
  20.     <TextView  
  21.         android:textSize="25sp"  
  22.         android:id="@+id/sb"  
  23.         android:layout_width="match_parent"  
  24.         android:layout_height="wrap_content" />  
  25.     ScrollView>  
  26.   
  27. LinearLayout>  


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


参考博客地址:


http://blog.csdn.net/u013686019/article/details/50409421

一、问题

现在有USB设备插入Android系统,那么如何得知插入的设备类型?是USB打印机,U盘,还是USB鼠标


二、USB类型规定

对于USB类型,USB组织是有规定的,见:http://www.usb.org/

比如:

Base Class

Descriptor Usage

Description

00h

Device

Use class information in the Interface Descriptors

01h

Interface

Audio 

02h

Both

Communications and CDC Control

03h

Interface

HID (Human Interface Device)

05h

Interface

Physical

06h

Interface

Image

07h

Interface

Printer

三、Linux对USB设备类型定义

在kernel中,有两个结构体的相关成员表征USB设备的类型,第一个usb_device_descriptor

[cpp]  view plain  copy
 
 
  1. include/uapi/linux/usb/ch9.h  
  2. /* USB_DT_DEVICE: Device descriptor */  
  3. struct usb_device_descriptor {  
  4.     __u8  bDeviceClass;  
  5.     __u8  bDeviceSubClass;  
  6.     __u8  bDeviceProtocol;  
  7. } __attribute__ ((packed));  
bDeviceClass成员值区别不同的USB设备,如果该值为0呢?看上边:

Base Class

Descriptor Usage

Description

00h

Device

Use class information in the Interface Descriptors

就在第二个结构体usb_interface_descriptor中:

[cpp]  view plain  copy
 
 
  1. include/uapi/linux/usb/ch9.h  
  2. struct usb_interface_descriptor {  
  3.     __u8  bInterfaceClass;  
  4.     __u8  bInterfaceSubClass;  
  5.     __u8  bInterfaceProtocol;  
  6. } __attribute__ ((packed));  
bInterfaceClass成员即是。

比如,对于USB打印机设备,定义如下:

[cpp]  view plain  copy
 
 
  1. include/uapi/linux/usb/ch9.h  
  2. /* 
  3.  * Device and/or Interface Class codes 
  4.  * as found in bDeviceClass or bInterfaceClass 
  5.  * and defined by www.usb.org documents 
  6.  */  
  7. #define USB_CLASS_PER_INTERFACE     0   /* for DeviceClass */  
  8. #define USB_CLASS_AUDIO         1  
  9. #define USB_CLASS_COMM          2  
  10. #define USB_CLASS_HID           3  
  11. #define USB_CLASS_PHYSICAL      5  
  12. #define USB_CLASS_STILL_IMAGE       6  
  13. #define USB_CLASS_PRINTER       7  
  14. #define USB_CLASS_MASS_STORAGE      8  
  15. #define USB_CLASS_HUB           9  
  16. #define USB_CLASS_CDC_DATA      0x0a  
  17. #define USB_CLASS_CSCID         0x0b    /* chip+ smart card */  
  18. #define USB_CLASS_CONTENT_SEC       0x0d    /* content security */  
  19. #define USB_CLASS_VIDEO         0x0e  
  20. #define USB_CLASS_WIRELESS_CONTROLLER   0xe0  
  21. #define USB_CLASS_MISC          0xef  
  22. #define USB_CLASS_APP_SPEC      0xfe  
  23. #define USB_CLASS_VENDOR_SPEC       0xff  
  24.   
  25. drivers/usb/gadget/printer.c  
  26. static struct usb_interface_descriptor intf_desc = {  
  27.     .bLength =      sizeof intf_desc,  
  28.     .bDescriptorType =  USB_DT_INTERFACE,  
  29.     .bNumEndpoints =    2,  
  30.     .bInterfaceClass =  USB_CLASS_PRINTER,  
  31.     .bInterfaceSubClass =   1,  /* Printer Sub-Class */  
  32.     .bInterfaceProtocol =   2,  /* Bi-Directional */  
  33.     .iInterface =       0  
  34. };  
对上了,不是?!

四、HAL层和Framework层

HAL层的usbhost.c文件为我们获取Linux driver中USB设备的信息提供了便利,除了USB设备类型,还可以得到USB设备的厂商名称、产品名称、序列号等:

system/core/libusbhost/usbhost.c


usbhost.c该文件中提供的方法在JNI中调用:

frameworks/base/services/jni/com_android_server_UsbHostManager.cpp


上面代码截图信息量很大!很重要!很重要!很重要!很重要!重要的地方说四遍。

1、调用usbhost.c文件中方法获取USB设备信息

2、获取的信息一部分传到UsbInterface.Java,APP部分调用UsbInterface类获取信息

[java]  view plain  copy
 
 
  1. frameworks/base/core/java/android/hardware/usb/UsbInterface.java  
  2. public class UsbInterface implements Parcelable {  
  3.     private final int mId;  
  4.     private final int mClass;  
  5.     private final int mSubclass;  
  6.     private final int mProtocol;  
  7.     private final Parcelable[] mEndpoints;  
  8. }  
3、 获取的信息另一部分通过调用 UsbHostManager.java中的usbDeviceAdded()方法,把信息写到 UsbDevice.java中, APP部分调用UsbDevice类获取信息

[java]  view plain  copy
 
 
  1. frameworks/base/core/java/android/hardware/usb/UsbDevice.java  
  2. public class UsbDevice implements Parcelable {  
  3.     private final String mName;  
  4.     private final int mVendorId;  
  5.     private final int mProductId;  
  6.     private final int mClass;  
  7.     private final int mSubclass;  
  8.     private final int mProtocol;  
  9.     private final Parcelable[] mInterfaces;  
  10. }  
接下来,我们就看下如此关键的 usbDeviceAdded()方法

[java]  view plain  copy
 
 
  1. frameworks/base/services/java/com/android/server/usb/UsbHostManager.java  
  2. /* Called from JNI in monitorUsbHostBus() to report new USB devices */  
  3. private void usbDeviceAdded(String deviceName, int vendorID, int productID,  
  4.     int deviceClass, int deviceSubclass, int deviceProtocol,  
  5.     /* array of quintuples containing id, class, subclass, protocol 
  6.        and number of endpoints for each interface */  
  7.     int[] interfaceValues,  
  8.    /* array of quadruples containing address, attributes, max packet size 
  9.       and interval for each endpoint */  
  10.     int[] endpointValues) {  
  11.     synchronized (mLock) {  
  12.         for (intf = 0; intf < numInterfaces; intf++) {  
  13.             int interfaceId = interfaceValues[ival++];  
  14.             int interfaceClass = interfaceValues[ival++];  
  15.             int interfaceSubclass = interfaceValues[ival++];  
  16.             int interfaceProtocol = interfaceValues[ival++];  
  17.             int numEndpoints = interfaceValues[ival++];  
  18.             interfaces[intf] = new UsbInterface(interfaceId, interfaceClass,  
  19.                     interfaceSubclass, interfaceProtocol, endpoints);  
  20.         }  
  21.         UsbDevice device = new UsbDevice(deviceName, vendorID, productID,  
  22.                 deviceClass, deviceSubclass, deviceProtocol, interfaces);  
  23.         mDevices.put(deviceName, device);  
  24.     }  
  25. }  

五、APP层

经过上面分析,获取USB设备类型等信息,已经心有成竹了,使用UsbDevice、UsbInterface两个类即可。其中, UsbInterface类是包含在 UsbDevice类中的:

[java]  view plain  copy
 
 
  1. frameworks/base/core/java/android/hardware/usb/UsbDevice.java  
  2. public class UsbDevice implements Parcelable {  
  3.     private final Parcelable[] mInterfaces;  
  4.       
  5.     /** 
  6.      * Returns the {@link UsbInterface} at the given index. 
  7.      * 
  8.      * @return the interface 
  9.      */  
  10.     public UsbInterface getInterface(int index) {  
  11.         return (UsbInterface)mInterfaces[index];  
  12.     }  
  13. }  
之后,就是如何使用UsbDevice类了。

USB设备属于热插拔设备,一旦系统监测到其热插拔时间,会有相应事件上报:

[java]  view plain  copy
 
 
  1. frameworks/base/core/java/android/hardware/usb/UsbManager.java  
  2. /** 
  3.  * This intent is sent when a USB device is attached to the USB bus when in host mode. 
  4.  */  
  5. public static final String ACTION_USB_DEVICE_ATTACHED =  
  6.         "android.hardware.usb.action.USB_DEVICE_ATTACHED";  
  7.   
  8. /** 
  9.  * This intent is sent when a USB device is detached from the USB bus when in host mode. 
  10.  */  
  11. public static final String ACTION_USB_DEVICE_DETACHED =  
  12.         "android.hardware.usb.action.USB_DEVICE_DETACHED";  
所以,注册监听事件的广播即可,如:


[java]  view plain  copy
 
 
  1. class UsbDeviceEventReceiver extends BroadcastReceiver {  
  2.     @Override  
  3.     public void onReceive(Context context, Intent intent) {  
  4.         UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);  
  5.     }  
  6. }  
  7.   
  8. mReceiver = new UsbDeviceEventReceiver();  
  9. IntentFilter filter = new IntentFilter();  
  10. filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);  
  11. filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);  
  12. registerReceiver(mReceiver, filter);  

六、结束

Android流程:driver->HAL->Framework->APP,几乎所有模块都是这个模式,对于一个外设,如果这几个部分都清楚的话心里会特别明亮。




转载至http://blog.csdn.net/rodulf/article/details/51916998

你可能感兴趣的:(获取usb设备类型)