The following code shows how to Read USB device information.
Code revised from
Android Recipes:A Problem-Solution Approach
http://www.apress.com/9781430234135
ISBN13: 978-1-4302-3413-5
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.examples.usbhost" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="12" android:targetSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".USBActivity" android:label="@string/title_activity_usb" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <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_filter" /> </activity> </application> </manifest>
res\layout\main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/button_connect" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Connect" android:onClick="onConnectClick" /> <TextView android:id="@+id/text_status" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/text_data" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
res\menu\main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_settings" android:title="@string/menu_settings" android:orderInCategory="100" android:showAsAction="never" /> </menu>
\res\xml\device_filter.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <usb-device /> </resources>
USBActivity.java
import java.util.HashMap; /*www .j av a 2s . c o m*/ import android.app.Activity; import android.app.PendingIntent; import android.content.BroadcastReceiver; 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; public class MainActivity extends Activity { private static final String TAG = "UsbHost"; TextView mDeviceText, mDisplayText; Button mConnectButton; UsbManager mUsbManager; UsbDevice mDevice; PendingIntent mPermissionIntent; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mDeviceText = (TextView) findViewById(R.id.text_status); mDisplayText = (TextView) findViewById(R.id.text_data); mConnectButton = (Button) findViewById(R.id.button_connect); mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE); } @Override protected void onResume() { super.onResume(); mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); registerReceiver(mUsbReceiver, filter); //Check currently connected devices updateDeviceList(); } @Override protected void onPause() { super.onPause(); unregisterReceiver(mUsbReceiver); } public void onConnectClick(View v) { if (mDevice == null) { return; } mDisplayText.setText("---"); //This will either prompt the user with a grant permission dialog, // or immediately fire the ACTION_USB_PERMISSION broadcast if the // user has already granted it to us. mUsbManager.requestPermission(mDevice, mPermissionIntent); } /* * Receiver to catch user permission responses, which are required in order to actuall * interact with a connected device. */ private static final String ACTION_USB_PERMISSION = "com.android.recipes.USB_PERMISSION"; private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) && device != null) { //Query the device's descriptor getDeviceStatus(device); } else { Log.d(TAG, "permission denied for device " + device); } } } }; /* * Initiate a control transfer to request the first configuration * descriptor of the device. */ //Type: Indicates whether this is a read or write // Matches USB_ENDPOINT_DIR_MASK for either IN or OUT private static final int REQUEST_TYPE = 0x80; //Request: GET_CONFIGURATION_DESCRIPTOR = 0x06 private static final int REQUEST = 0x06; //Value: Descriptor Type (High) and Index (Low) // Configuration Descriptor = 0x2 // Index = 0x0 (First configuration) private static final int REQ_VALUE = 0x200; private static final int REQ_INDEX = 0x00; private static final int LENGTH = 64; private void getDeviceStatus(UsbDevice device) { UsbDeviceConnection connection = mUsbManager.openDevice(device); //Create a sufficiently large buffer for incoming data byte[] buffer = new byte[LENGTH]; connection.controlTransfer(REQUEST_TYPE, REQUEST, REQ_VALUE, REQ_INDEX, buffer, LENGTH, 2000); //Parse received data into a description String description = parseConfigDescriptor(buffer); mDisplayText.setText(description); connection.close(); } /* * Parse the USB configuration descriptor response per the * USB Specification. Return a printable description of * the connected device. */ private static final int DESC_SIZE_CONFIG = 9; private String parseConfigDescriptor(byte[] buffer) { StringBuilder sb = new StringBuilder(); //Parse configuration descriptor header int totalLength = (buffer[3] &0xFF) << 8; totalLength += (buffer[2] & 0xFF); //Interface count int numInterfaces = (buffer[5] & 0xFF); //Configuration attributes int attributes = (buffer[7] & 0xFF); //Power is given in 2mA increments int maxPower = (buffer[8] & 0xFF) * 2; sb.append("Configuration Descriptor:\n"); sb.append("Length: " + totalLength + " bytes\n"); sb.append(numInterfaces + " Interfaces\n"); sb.append(String.format("Attributes:%s%s%s\n", (attributes & 0x80) == 0x80 ? " BusPowered" : "", (attributes & 0x40) == 0x40 ? " SelfPowered" : "", (attributes & 0x20) == 0x20 ? " RemoteWakeup" : "")); sb.append("Max Power: " + maxPower + "mA\n"); //The rest of the descriptor is interfaces and endpoints int index = DESC_SIZE_CONFIG; while (index < totalLength) { //Read length and type int len = (buffer[index] & 0xFF); int type = (buffer[index+1] & 0xFF); switch (type) { case 0x04: //Interface Descriptor int intfNumber = (buffer[index+2] & 0xFF); int numEndpoints = (buffer[index+4] & 0xFF); int intfClass = (buffer[index+5] & 0xFF); sb.append(String.format("- Interface %d, %s, %d Endpoints\n", intfNumber, nameForClass(intfClass), numEndpoints)); break; case 0x05: //Endpoint Descriptor int endpointAddr = ((buffer[index+2] & 0xFF)); //Number is lower 4 bits int endpointNum = (endpointAddr & 0x0F); //Direction is high bit int direction = (endpointAddr & 0x80); int endpointAttrs = (buffer[index+3] & 0xFF); //Type is the lower two bits int endpointType = (endpointAttrs & 0x3); sb.append(String.format("-- Endpoint %d, %s %s\n", endpointNum, nameForEndpointType(endpointType), nameForDirection(direction) )); break; } //Advance to next descriptor index += len; } return sb.toString(); } private void updateDeviceList() { HashMap<String, UsbDevice> connectedDevices = mUsbManager .getDeviceList(); if (connectedDevices.isEmpty()) { mDevice = null; mDeviceText.setText("No Devices Currently Connected"); mConnectButton.setEnabled(false); } else { StringBuilder builder = new StringBuilder(); for (UsbDevice device : connectedDevices.values()) { //Use the last device detected (if multiple) to open mDevice = device; builder.append(readDevice(device)); builder.append("\n\n"); } mDeviceText.setText(builder.toString()); mConnectButton.setEnabled(true); } } /* * Enumerate the endpoints and interfaces on the connected device. * We do not need permission to do anything here, it is all "publicly available" * until we try to connect to an actual device. */ private String readDevice(UsbDevice device) { StringBuilder sb = new StringBuilder(); sb.append("Device Name: " + device.getDeviceName() + "\n"); sb.append(String.format( "Device Class: %s -> Subclass: 0x%02x -> Protocol: 0x%02x\n", nameForClass(device.getDeviceClass()), device.getDeviceSubclass(), device.getDeviceProtocol())); for (int i = 0; i < device.getInterfaceCount(); i++) { UsbInterface intf = device.getInterface(i); sb.append(String .format("+--Interface %d Class: %s -> Subclass: 0x%02x -> Protocol: 0x%02x\n", intf.getId(), nameForClass(intf.getInterfaceClass()), intf.getInterfaceSubclass(), intf.getInterfaceProtocol())); for (int j = 0; j < intf.getEndpointCount(); j++) { UsbEndpoint endpoint = intf.getEndpoint(j); sb.append(String.format(" +---Endpoint %d: %s %s\n", endpoint.getEndpointNumber(), nameForEndpointType(endpoint.getType()), nameForDirection(endpoint.getDirection()))); } } return sb.toString(); } /* Helper Methods to Provide Readable Names for USB Constants */ private String nameForClass(int classType) { switch (classType) { case UsbConstants.USB_CLASS_APP_SPEC: return String.format("Application Specific 0x%02x", classType); case UsbConstants.USB_CLASS_AUDIO: return "Audio"; case UsbConstants.USB_CLASS_CDC_DATA: return "CDC Control"; case UsbConstants.USB_CLASS_COMM: return "Communications"; case UsbConstants.USB_CLASS_CONTENT_SEC: return "Content Security"; case UsbConstants.USB_CLASS_CSCID: return "Content Smart Card"; case UsbConstants.USB_CLASS_HID: return "Human Interface Device"; case UsbConstants.USB_CLASS_HUB: return "Hub"; case UsbConstants.USB_CLASS_MASS_STORAGE: return "Mass Storage"; case UsbConstants.USB_CLASS_MISC: return "Wireless Miscellaneous"; case UsbConstants.USB_CLASS_PER_INTERFACE: return "(Defined Per Interface)"; case UsbConstants.USB_CLASS_PHYSICA: return "Physical"; case UsbConstants.USB_CLASS_PRINTER: return "Printer"; case UsbConstants.USB_CLASS_STILL_IMAGE: return "Still Image"; case UsbConstants.USB_CLASS_VENDOR_SPEC: return String.format("Vendor Specific 0x%02x", classType); case UsbConstants.USB_CLASS_VIDEO: return "Video"; case UsbConstants.USB_CLASS_WIRELESS_CONTROLLER: return "Wireless Controller"; default: return String.format("0x%02x", classType); } } private String nameForEndpointType(int type) { switch (type) { case UsbConstants.USB_ENDPOINT_XFER_BULK: return "Bulk"; case UsbConstants.USB_ENDPOINT_XFER_CONTROL: return "Control"; case UsbConstants.USB_ENDPOINT_XFER_INT: return "Interrupt"; case UsbConstants.USB_ENDPOINT_XFER_ISOC: return "Isochronous"; default: return "Unknown Type"; } } private String nameForDirection(int direction) { switch (direction) { case UsbConstants.USB_DIR_IN: return "IN"; case UsbConstants.USB_DIR_OUT: return "OUT"; default: return "Unknown Direction"; } } }