Showing posts with label USB Host Mode. Show all posts
Showing posts with label USB Host Mode. Show all posts

Android send command to Arduino in USB Host mode

This example show how to send command from Android to Arduino Esplora board, in USB Host Mode, to control the LED and Screen of Arduino Esplora. When user toggle the LED by clicking on the button, or change the screen color by slideing the bars, the commands will be add in a command queue, and then send to Arduino in background.


In Android Side:

MainActivity.java.
package com.example.androidusbhost;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;

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.view.View;
import android.view.View.OnClickListener;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

public class MainActivity extends Activity {

ToggleButton btnLED;
SeekBar barR, barG, barB;
TextView textRx;

TextView textInfo;
TextView textSearchedEndpoint;

TextView textDeviceName;
TextView textStatus;

private static final int targetVendorID= 9025;
private static final int targetProductID = 32828;
UsbDevice deviceFound = null;
UsbInterface usbInterfaceFound = null;
UsbEndpoint endpointIn = null;
UsbEndpoint endpointOut = null;

private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
PendingIntent mPermissionIntent;

UsbInterface usbInterface;
UsbDeviceConnection usbDeviceConnection;

ThreadUsbTx threadUsbTx;

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

btnLED = (ToggleButton)findViewById(R.id.ledbutton);
btnLED.setOnClickListener(btnLEDOnClickListener);

barR = (SeekBar)findViewById(R.id.rbar);
barG = (SeekBar)findViewById(R.id.gbar);
barB = (SeekBar)findViewById(R.id.bbar);
barR.setOnSeekBarChangeListener(colorOnSeekBarChangeListener);
barG.setOnSeekBarChangeListener(colorOnSeekBarChangeListener);
barB.setOnSeekBarChangeListener(colorOnSeekBarChangeListener);

textRx = (TextView)findViewById(R.id.textrx);

textStatus = (TextView)findViewById(R.id.textstatus);

textDeviceName = (TextView)findViewById(R.id.textdevicename);
textInfo = (TextView) findViewById(R.id.info);
textSearchedEndpoint = (TextView)findViewById(R.id.searchedendpoint);

//register the broadcast receiver
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);

registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED));
registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));

connectUsb();
}

@Override
protected void onDestroy() {
releaseUsb();
unregisterReceiver(mUsbReceiver);
unregisterReceiver(mUsbDeviceReceiver);
super.onDestroy();
}

OnClickListener btnLEDOnClickListener =
new OnClickListener(){

@Override
public void onClick(View v) {
// TODO Auto-generated method stub

int usbResult;
byte[] cmdLED;
if(((ToggleButton)v).isChecked()){
cmdLED = new byte[] {(byte)'L', 'E', 'D', 'O', 'N', '\n'};
}else{
cmdLED = new byte[] {(byte)'L', 'E', 'D', 'O', 'F', 'F', '\n'};
}
threadUsbTx.insertCmd(cmdLED);
}

};

OnSeekBarChangeListener colorOnSeekBarChangeListener =
new OnSeekBarChangeListener(){

byte[] toAscii = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

byte[] cmdCol = new byte[] {(byte)'C', 'O', 'L', '#',
'0', '0', '0', '0', '0', '0', '\n'};

cmdCol[4] = toAscii[(barR.getProgress()>>4) & 0x0f];
cmdCol[5] = toAscii[barR.getProgress() & 0x0f];
cmdCol[6] = toAscii[(barG.getProgress()>>4) & 0x0f];
cmdCol[7] = toAscii[barG.getProgress() & 0x0f];
cmdCol[8] = toAscii[(barB.getProgress()>>4) & 0x0f];
cmdCol[9] = toAscii[barB.getProgress() & 0x0f];
threadUsbTx.insertCmd(cmdCol.clone());
}

};

private void connectUsb(){

btnLED.setEnabled(false);
barR.setEnabled(false);
barG.setEnabled(false);
barB.setEnabled(false);

Toast.makeText(MainActivity.this,
"connectUsb()",
Toast.LENGTH_LONG).show();
textStatus.setText("connectUsb()");

searchEndPoint();

if(usbInterfaceFound != null){
setupUsbComm();

threadUsbTx = new ThreadUsbTx(usbDeviceConnection, endpointOut);
threadUsbTx.start();

btnLED.setEnabled(true);
barR.setEnabled(true);
barG.setEnabled(true);
barB.setEnabled(true);
//Turn On LED once connected
btnLED.setChecked(true);
barR.setProgress(0x80);
barG.setProgress(0x80);
barB.setProgress(0x80);

threadUsbTx.insertCmd(
new byte[] {(byte)'L', 'E', 'D', 'O', 'N', '\n'});
threadUsbTx.insertCmd(
new byte[] {(byte)'C', 'O', 'L', '#',
'8', '0', '8', '0', '8', '0', '\n'});

}

}

private void releaseUsb(){

Toast.makeText(MainActivity.this,
"releaseUsb()",
Toast.LENGTH_LONG).show();
textStatus.setText("releaseUsb()");

if(usbDeviceConnection != null){
if(usbInterface != null){
usbDeviceConnection.releaseInterface(usbInterface);
usbInterface = null;
}
usbDeviceConnection.close();
usbDeviceConnection = null;
}

deviceFound = null;
usbInterfaceFound = null;
endpointIn = null;
endpointOut = null;

btnLED.setEnabled(false);
barR.setEnabled(false);
barG.setEnabled(false);
barB.setEnabled(false);

if(threadUsbTx!=null){
threadUsbTx.setRunning(false);
}
}

private void searchEndPoint(){

textInfo.setText("");
textSearchedEndpoint.setText("");

usbInterfaceFound = null;
endpointOut = null;
endpointIn = null;

//Search device for targetVendorID and targetProductID
if(deviceFound == null){
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();

if(device.getVendorId()==targetVendorID){
if(device.getProductId()==targetProductID){
deviceFound = device;
}
}
}
}

if(deviceFound==null){
textStatus.setText("device not found");
}else{
String s = deviceFound.toString() + "\n" +
"DeviceID: " + deviceFound.getDeviceId() + "\n" +
"DeviceName: " + deviceFound.getDeviceName() + "\n" +
"DeviceClass: " + deviceFound.getDeviceClass() + "\n" +
"DeviceSubClass: " + deviceFound.getDeviceSubclass() + "\n" +
"VendorID: " + deviceFound.getVendorId() + "\n" +
"ProductID: " + deviceFound.getProductId() + "\n" +
"InterfaceCount: " + deviceFound.getInterfaceCount();
textInfo.setText(s);

//Search for UsbInterface with Endpoint of USB_ENDPOINT_XFER_BULK,
//and direction USB_DIR_OUT and USB_DIR_IN

for(int i=0; i<deviceFound.getInterfaceCount(); i++){
UsbInterface usbif = deviceFound.getInterface(i);

UsbEndpoint tOut = null;
UsbEndpoint tIn = null;

int tEndpointCnt = usbif.getEndpointCount();
if(tEndpointCnt>=2){
for(int j=0; j<tEndpointCnt; j++){
if(usbif.getEndpoint(j).getType() ==
UsbConstants.USB_ENDPOINT_XFER_BULK){
if(usbif.getEndpoint(j).getDirection() ==
UsbConstants.USB_DIR_OUT){
tOut = usbif.getEndpoint(j);
}else if(usbif.getEndpoint(j).getDirection() ==
UsbConstants.USB_DIR_IN){
tIn = usbif.getEndpoint(j);
}
}
}

if(tOut!=null && tIn!=null){
//This interface have both USB_DIR_OUT
//and USB_DIR_IN of USB_ENDPOINT_XFER_BULK
usbInterfaceFound = usbif;
endpointOut = tOut;
endpointIn = tIn;
}
}

}

if(usbInterfaceFound==null){
textSearchedEndpoint.setText("No suitable interface found!");
}else{
textSearchedEndpoint.setText(
"UsbInterface found: " + usbInterfaceFound.toString() + "\n\n" +
"Endpoint OUT: " + endpointOut.toString() + "\n\n" +
"Endpoint IN: " + endpointIn.toString());
}
}
}

private boolean setupUsbComm(){

//for more info, search SET_LINE_CODING and
//SET_CONTROL_LINE_STATE in the document:
//"Universal Serial Bus Class Definitions for Communication Devices"
//at http://adf.ly/dppFt
final int RQSID_SET_LINE_CODING = 0x20;
final int RQSID_SET_CONTROL_LINE_STATE = 0x22;

boolean success = false;

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
Boolean permitToRead = manager.hasPermission(deviceFound);

if(permitToRead){
usbDeviceConnection = manager.openDevice(deviceFound);
if(usbDeviceConnection != null){
usbDeviceConnection.claimInterface(usbInterfaceFound, true);

showRawDescriptors(); //skip it if you no need show RawDescriptors

int usbResult;

/*
* D7: 0 - Host to Device
* 1 = Device to Host
* D6..5 Type
* 0 = Standard
* 1 = Class
* 2 = Vendor
* 3 = Reserved
* D4..0 Recipient
* 0 = Device
* 1 = Interface
* 2 = Endpoint
* 3 = Other
*/

//int requestType = 0x21;
int requestType = 0x42;

usbResult = usbDeviceConnection.controlTransfer(
requestType,
RQSID_SET_CONTROL_LINE_STATE, //SET_CONTROL_LINE_STATE
0, //value
0, //index
null, //buffer
0, //length
0); //timeout

//baud rate = 9600
//8 data bit
//1 stop bit
byte[] encodingSetting =
new byte[] {(byte)0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08 };
usbResult = usbDeviceConnection.controlTransfer(
requestType,
RQSID_SET_LINE_CODING, //SET_LINE_CODING
0, //value
0, //index
encodingSetting, //buffer
7, //length
0); //timeout

}

}else{
manager.requestPermission(deviceFound, mPermissionIntent);
Toast.makeText(MainActivity.this,
"Permission: " + permitToRead,
Toast.LENGTH_LONG).show();
textStatus.setText("Permission: " + permitToRead);
}

return success;
}

private void showRawDescriptors(){
final int STD_USB_REQUEST_GET_DESCRIPTOR = 0x06;
final int LIBUSB_DT_STRING = 0x03;

byte[] buffer = new byte[255];
int indexManufacturer = 14;
int indexProduct = 15;
String stringManufacturer = "";
String stringProduct = "";

byte[] rawDescriptors = usbDeviceConnection.getRawDescriptors();

int lengthManufacturer = usbDeviceConnection.controlTransfer(
UsbConstants.USB_DIR_IN|UsbConstants.USB_TYPE_STANDARD, //requestType
STD_USB_REQUEST_GET_DESCRIPTOR, //request ID for this transaction
(LIBUSB_DT_STRING << 8) | rawDescriptors[indexManufacturer], //value
0, //index
buffer, //buffer
0xFF, //length
0); //timeout
try {
stringManufacturer = new String(buffer, 2, lengthManufacturer-2, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
textStatus.setText(e.toString());
}

int lengthProduct = usbDeviceConnection.controlTransfer(
UsbConstants.USB_DIR_IN|UsbConstants.USB_TYPE_STANDARD,
STD_USB_REQUEST_GET_DESCRIPTOR,
(LIBUSB_DT_STRING << 8) | rawDescriptors[indexProduct],
0,
buffer,
0xFF,
0);
try {
stringProduct = new String(buffer, 2, lengthProduct-2, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

textStatus.setText("Manufacturer: " + stringManufacturer + "\n" +
"Product: " + stringProduct);
}

private final BroadcastReceiver mUsbReceiver =
new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {

textStatus.setText("ACTION_USB_PERMISSION");

synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
connectUsb();
}
}
else {
Toast.makeText(MainActivity.this,
"permission denied for device " + device,
Toast.LENGTH_LONG).show();
textStatus.setText("permission denied for device " + device);
}
}
}
}
};

private final BroadcastReceiver mUsbDeviceReceiver =
new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {

deviceFound = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
Toast.makeText(MainActivity.this,
"ACTION_USB_DEVICE_ATTACHED: \n" +
deviceFound.toString(),
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_DEVICE_ATTACHED: \n" +
deviceFound.toString());

connectUsb();
}else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {

UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

Toast.makeText(MainActivity.this,
"ACTION_USB_DEVICE_DETACHED: \n" +
device.toString(),
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_DEVICE_DETACHED: \n" +
device.toString());

if(device!=null){
if(device == deviceFound){
releaseUsb();
}
}

textInfo.setText("");
}
}

};

class ThreadUsbTx extends Thread{
boolean running;

UsbDeviceConnection txConnection;
UsbEndpoint txEndpoint;
Queue<byte[]> cmdQueue;
byte[] cmdToSent;

ThreadUsbTx(UsbDeviceConnection conn, UsbEndpoint endpoint){
txConnection = conn;
txEndpoint = endpoint;
cmdQueue = new LinkedList<byte[]>();
cmdToSent = null;
running = true;
}

public void setRunning(boolean r){
running = r;
}

public void insertCmd(byte[] cmd){
synchronized(cmdQueue){
cmdQueue.add(cmd);
}
}

@Override
public void run() {

while(running){

synchronized(cmdQueue){
if(cmdQueue.size()>0){
cmdToSent = cmdQueue.remove();
}
}

if(cmdToSent!=null){
int usbResult = usbDeviceConnection.bulkTransfer(
endpointOut,
cmdToSent,
cmdToSent.length,
0);

final String s = new String(cmdToSent);

runOnUiThread(new Runnable(){

@Override
public void run() {
Toast.makeText(MainActivity.this,
s,
Toast.LENGTH_SHORT).show();
}});

cmdToSent = null;
}
}
}
}
}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<ToggleButton
android:id="@+id/ledbutton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textOn="LED ON"
android:textOff="LED OFF" />
<SeekBar
android:id="@+id/rbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="0"/>
<SeekBar
android:id="@+id/gbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="0"/>
<SeekBar
android:id="@+id/bbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="255"
android:progress="0"/>
<TextView
android:id="@+id/textrx"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="#ff0000" />

<TextView
android:id="@+id/textstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

<TextView
android:id="@+id/textdevicename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold|italic" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<TextView
android:id="@+id/info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/searchedendpoint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

</LinearLayout>
</ScrollView>

</LinearLayout>

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidusbhost"
android:versionCode="1"
android:versionName="1.0" >

<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk
android:minSdkVersion="13"
android:targetSdkVersion="18" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidusbhost.MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|orientation" >
<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" />

<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>

</activity>
</application>

</manifest>

download filesDownload the files.

In Arduino Side: re-use the code in my another blog Node.js + Arduino, running on PC.
#include <Esplora.h>
#include <TFT.h>
#include <SPI.h>

int MAX_CMD_LENGTH = 10;
char cmd[10];
int cmdIndex;
char incomingByte;

int prevSlider = 0;

void setup() {

EsploraTFT.begin();
EsploraTFT.background(0,0,0);
EsploraTFT.stroke(255,255,255); //preset stroke color

//Setup Serial Port with baud rate of 9600
Serial.begin(9600);

//indicate start
Esplora.writeRGB(255, 255, 255);
delay(250);
Esplora.writeRGB(0, 0, 0);

cmdIndex = 0;

}

void loop() {

if (incomingByte=Serial.available()>0) {

char byteIn = Serial.read();
cmd[cmdIndex] = byteIn;

if(byteIn=='\n'){
//command finished
cmd[cmdIndex] = '\0';
//Serial.println(cmd);
cmdIndex = 0;

String stringCmd = String(cmd);

if(strcmp(cmd, "LEDON") == 0){
//Serial.println("Command received: LEDON");
Esplora.writeRGB(255, 255, 255);
}else if (strcmp(cmd, "LEDOFF") == 0) {
//Serial.println("Command received: LEDOFF");
Esplora.writeRGB(0, 0, 0);
}else if(stringCmd.substring(0,4)="COL#"){
//Serial.println("Command received: COL#");
if(stringCmd.length()==10){
char * pEnd;
long int rgb = strtol(&cmd[4], &pEnd, 16);
int r = (rgb & 0xff0000) >> 16;
int g = (rgb & 0xff00) >> 8;
int b = rgb & 0xff;
//Serial.println(r);
//Serial.println(g);
//Serial.println(b);
EsploraTFT.background(b,g,r);
}
}else{
//Serial.println("Command received: unknown!");
}

}else{
if(cmdIndex++ >= MAX_CMD_LENGTH){
cmdIndex = 0;
}
}
}

//Read Slider
int slider = Esplora.readSlider();
//convert slider value from [0-1023] to [0x00-0xFF]
slider = slider>>2 & 0xff;

if(slider!=prevSlider){
prevSlider = slider;

String stringSlider = String(slider, HEX);
Serial.println("SLD#" + stringSlider +"\n");
}

}

Remark:
The device-to-host (Arduino-to-Android) communication have NOT been implemented on Android side in this example.


Step-by-step: Android USB Host Mode programming

Send Hello to Arduino from Android in USB Host Mode

This example send bytes of "Hello..." to Arduino Esplora board from Android in USB Host Mode. Please notice that it's just a middle stage in my exercise in USB Host Mode, not a final and mature example.


In Android Side:

MainActivity.java
package com.example.androidusbhost;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;

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.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

public class MainActivity extends Activity {

TextView textInfo;
TextView textSearchedEndpoint;

TextView textDeviceName;
TextView textStatus;

private static final int targetVendorID= 9025;
private static final int targetProductID = 32828;
UsbDevice deviceFound = null;
UsbInterface usbInterfaceFound = null;
UsbEndpoint endpointIn = null;
UsbEndpoint endpointOut = null;

private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
PendingIntent mPermissionIntent;

UsbInterface usbInterface;
UsbDeviceConnection usbDeviceConnection;

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

textStatus = (TextView)findViewById(R.id.textstatus);

textDeviceName = (TextView)findViewById(R.id.textdevicename);
textInfo = (TextView) findViewById(R.id.info);
textSearchedEndpoint = (TextView)findViewById(R.id.searchedendpoint);

//register the broadcast receiver
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);

registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED));
registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));

connectUsb();
}

@Override
protected void onDestroy() {
releaseUsb();
unregisterReceiver(mUsbReceiver);
unregisterReceiver(mUsbDeviceReceiver);
super.onDestroy();
}

private void connectUsb(){

Toast.makeText(MainActivity.this,
"connectUsb()",
Toast.LENGTH_LONG).show();
textStatus.setText("connectUsb()");

searchEndPoint();

if(usbInterfaceFound != null){
setupUsbComm();
}

}

private void releaseUsb(){

Toast.makeText(MainActivity.this,
"releaseUsb()",
Toast.LENGTH_LONG).show();
textStatus.setText("releaseUsb()");

if(usbDeviceConnection != null){
if(usbInterface != null){
usbDeviceConnection.releaseInterface(usbInterface);
usbInterface = null;
}
usbDeviceConnection.close();
usbDeviceConnection = null;
}

deviceFound = null;
usbInterfaceFound = null;
endpointIn = null;
endpointOut = null;
}

private void searchEndPoint(){

textInfo.setText("");
textSearchedEndpoint.setText("");

usbInterfaceFound = null;
endpointOut = null;
endpointIn = null;

//Search device for targetVendorID and targetProductID
if(deviceFound == null){
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();

if(device.getVendorId()==targetVendorID){
if(device.getProductId()==targetProductID){
deviceFound = device;
}
}
}
}

if(deviceFound==null){
Toast.makeText(MainActivity.this,
"device not found",
Toast.LENGTH_LONG).show();
textStatus.setText("device not found");
}else{
String s = deviceFound.toString() + "\n" +
"DeviceID: " + deviceFound.getDeviceId() + "\n" +
"DeviceName: " + deviceFound.getDeviceName() + "\n" +
"DeviceClass: " + deviceFound.getDeviceClass() + "\n" +
"DeviceSubClass: " + deviceFound.getDeviceSubclass() + "\n" +
"VendorID: " + deviceFound.getVendorId() + "\n" +
"ProductID: " + deviceFound.getProductId() + "\n" +
"InterfaceCount: " + deviceFound.getInterfaceCount();
textInfo.setText(s);

//Search for UsbInterface with Endpoint of USB_ENDPOINT_XFER_BULK,
//and direction USB_DIR_OUT and USB_DIR_IN

for(int i=0; i<deviceFound.getInterfaceCount(); i++){
UsbInterface usbif = deviceFound.getInterface(i);

UsbEndpoint tOut = null;
UsbEndpoint tIn = null;

int tEndpointCnt = usbif.getEndpointCount();
if(tEndpointCnt>=2){
for(int j=0; j<tEndpointCnt; j++){
if(usbif.getEndpoint(j).getType() ==
UsbConstants.USB_ENDPOINT_XFER_BULK){
if(usbif.getEndpoint(j).getDirection() ==
UsbConstants.USB_DIR_OUT){
tOut = usbif.getEndpoint(j);
}else if(usbif.getEndpoint(j).getDirection() ==
UsbConstants.USB_DIR_IN){
tIn = usbif.getEndpoint(j);
}
}
}

if(tOut!=null && tIn!=null){
//This interface have both USB_DIR_OUT
//and USB_DIR_IN of USB_ENDPOINT_XFER_BULK
usbInterfaceFound = usbif;
endpointOut = tOut;
endpointIn = tIn;
}
}

}

if(usbInterfaceFound==null){
textSearchedEndpoint.setText("No suitable interface found!");
}else{
textSearchedEndpoint.setText(
"UsbInterface found: " + usbInterfaceFound.toString() + "\n\n" +
"Endpoint OUT: " + endpointOut.toString() + "\n\n" +
"Endpoint IN: " + endpointIn.toString());
}
}
}

private boolean setupUsbComm(){

//for more info, search SET_LINE_CODING and
//SET_CONTROL_LINE_STATE in the document:
//"Universal Serial Bus Class Definitions for Communication Devices"
//at http://adf.ly/dppFt
final int RQSID_SET_LINE_CODING = 0x20;
final int RQSID_SET_CONTROL_LINE_STATE = 0x22;

boolean success = false;

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
Boolean permitToRead = manager.hasPermission(deviceFound);

if(permitToRead){
usbDeviceConnection = manager.openDevice(deviceFound);
if(usbDeviceConnection != null){
usbDeviceConnection.claimInterface(usbInterfaceFound, true);

showRawDescriptors(); //skip it if you no need show RawDescriptors

int usbResult;
usbResult = usbDeviceConnection.controlTransfer(
0x21, //requestType
RQSID_SET_CONTROL_LINE_STATE, //SET_CONTROL_LINE_STATE
0, //value
0, //index
null, //buffer
0, //length
0); //timeout

Toast.makeText(MainActivity.this,
"controlTransfer(SET_CONTROL_LINE_STATE): " + usbResult,
Toast.LENGTH_LONG).show();

//baud rate = 9600
//8 data bit
//1 stop bit
byte[] encodingSetting =
new byte[] {(byte)0x80, 0x25, 0x00, 0x00, 0x00, 0x00, 0x08 };
usbResult = usbDeviceConnection.controlTransfer(
0x21, //requestType
RQSID_SET_LINE_CODING, //SET_LINE_CODING
0, //value
0, //index
encodingSetting, //buffer
7, //length
0); //timeout
Toast.makeText(MainActivity.this,
"controlTransfer(RQSID_SET_LINE_CODING): " + usbResult,
Toast.LENGTH_LONG).show();

byte[] bytesHello =
new byte[] {(byte)'H', 'e', 'l', 'l', 'o', ' ',
'f', 'r', 'o', 'm', ' ',
'A', 'n', 'd', 'r', 'o', 'i', 'd'};
usbResult = usbDeviceConnection.bulkTransfer(
endpointOut,
bytesHello,
bytesHello.length,
0);
Toast.makeText(MainActivity.this,
"bulkTransfer: " + usbResult,
Toast.LENGTH_LONG).show();
}

}else{
manager.requestPermission(deviceFound, mPermissionIntent);
Toast.makeText(MainActivity.this,
"Permission: " + permitToRead,
Toast.LENGTH_LONG).show();
textStatus.setText("Permission: " + permitToRead);
}



return success;
}

private void showRawDescriptors(){
final int STD_USB_REQUEST_GET_DESCRIPTOR = 0x06;
final int LIBUSB_DT_STRING = 0x03;

byte[] buffer = new byte[255];
int indexManufacturer = 14;
int indexProduct = 15;
String stringManufacturer = "";
String stringProduct = "";

byte[] rawDescriptors = usbDeviceConnection.getRawDescriptors();

int lengthManufacturer = usbDeviceConnection.controlTransfer(
UsbConstants.USB_DIR_IN|UsbConstants.USB_TYPE_STANDARD, //requestType
STD_USB_REQUEST_GET_DESCRIPTOR, //request ID for this transaction
(LIBUSB_DT_STRING << 8) | rawDescriptors[indexManufacturer], //value
0, //index
buffer, //buffer
0xFF, //length
0); //timeout
try {
stringManufacturer = new String(buffer, 2, lengthManufacturer-2, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
textStatus.setText(e.toString());
}

int lengthProduct = usbDeviceConnection.controlTransfer(
UsbConstants.USB_DIR_IN|UsbConstants.USB_TYPE_STANDARD,
STD_USB_REQUEST_GET_DESCRIPTOR,
(LIBUSB_DT_STRING << 8) | rawDescriptors[indexProduct],
0,
buffer,
0xFF,
0);
try {
stringProduct = new String(buffer, 2, lengthProduct-2, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

textStatus.setText("Manufacturer: " + stringManufacturer + "\n" +
"Product: " + stringProduct);
}

private final BroadcastReceiver mUsbReceiver =
new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {

Toast.makeText(MainActivity.this,
"ACTION_USB_PERMISSION",
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_PERMISSION");

synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
connectUsb();
}
}
else {
Toast.makeText(MainActivity.this,
"permission denied for device " + device,
Toast.LENGTH_LONG).show();
textStatus.setText("permission denied for device " + device);
}
}
}
}
};

private final BroadcastReceiver mUsbDeviceReceiver =
new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {

deviceFound = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
Toast.makeText(MainActivity.this,
"ACTION_USB_DEVICE_ATTACHED: \n" +
deviceFound.toString(),
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_DEVICE_ATTACHED: \n" +
deviceFound.toString());

connectUsb();

}else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {

UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

Toast.makeText(MainActivity.this,
"ACTION_USB_DEVICE_DETACHED: \n" +
device.toString(),
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_DEVICE_DETACHED: \n" +
device.toString());

if(device!=null){
if(device == deviceFound){
releaseUsb();
}
}

textInfo.setText("");
}
}

};

}

The setting of usbDeviceConnection.controlTransfer() inside setupUsbComm() is copied from the post: Android USB Host + Arduino: How to communicate without rooting your Android Tablet or Phone

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<TextView
android:id="@+id/textstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

<TextView
android:id="@+id/textdevicename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold|italic" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<TextView
android:id="@+id/info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/searchedendpoint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

</LinearLayout>
</ScrollView>

</LinearLayout>


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidusbhost"
android:versionCode="1"
android:versionName="1.0" >

<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk
android:minSdkVersion="13"
android:targetSdkVersion="18" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidusbhost.MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|orientation" >
<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" />

<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>

</activity>
</application>

</manifest>


download filesDownload the files.

In Arduino Side:

testSerial.ino
#include <Esplora.h>
#include <TFT.h>
#include <SPI.h>

int prevSw1 = HIGH;
int incomingByte = 0;
String charsIn = "";
char printout[20]; //max char to print: 20

void setup() {

EsploraTFT.begin();
EsploraTFT.background(0,0,0);
EsploraTFT.stroke(255,255,255); //preset stroke color

//Setup Serial Port with baud rate of 9600
Serial.begin(9600);

//indicate start
Esplora.writeRGB(255, 255, 255);
delay(250);
Esplora.writeRGB(0, 0, 0);

}

void loop() {
int sw1 = Esplora.readButton(SWITCH_1);
if(sw1 != prevSw1){
if(sw1 == LOW){
Serial.println("Hello from Arduino Esplora");
}
prevSw1 = sw1;
}

while (Serial.available()) {
char charRead = Serial.read();
charsIn.concat(charRead);
}
if(charsIn != ""){
Serial.println("How are you, " + charsIn);
charsIn.toCharArray(printout, 21);
EsploraTFT.background(0,0,0);
EsploraTFT.text(printout, 0, 10);
charsIn = "";
}
}

It's same as the code in my another blog: Serial communication between Arduino Esplora and PC



Step-by-step: Android USB Host Mode programming



Search UsbInterface and UsbEndpoint, of USB_ENDPOINT_XFER_BULK type, with both USB_DIR_OUT and USB_DIR_IN

This example scan USB devices in USB Host mode, search for any UsbInterface and UsbEndpoint, of USB_ENDPOINT_XFER_BULK type, with both USB_DIR_OUT and USB_DIR_IN.

Search UsbInterface and UsbEndpoint automatically
Search UsbInterface and UsbEndpoint
Modify MainActivity.java in "Use intent filter to detect a specified USB device and auto start application", implement searchEndPoint() and remove un-necessary function.
package com.example.androidusbhost;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;

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.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

public class MainActivity extends Activity {

TextView textInfo;
TextView textSearchedEndpoint;

TextView textDeviceName;
TextView textStatus;

private static final int targetVendorID= 9025;
private static final int targetProductID = 32828;
UsbDevice deviceFound = null;
UsbInterface usbInterfaceFound = null;
UsbEndpoint endpointIn = null;
UsbEndpoint endpointOut = null;

private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
PendingIntent mPermissionIntent;

UsbInterface usbInterface;
UsbDeviceConnection usbDeviceConnection;

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

textStatus = (TextView)findViewById(R.id.textstatus);

textDeviceName = (TextView)findViewById(R.id.textdevicename);
textInfo = (TextView) findViewById(R.id.info);
textSearchedEndpoint = (TextView)findViewById(R.id.searchedendpoint);

//register the broadcast receiver
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);

registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED));
registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));

connectUsb();
}

@Override
protected void onDestroy() {
releaseUsb();
unregisterReceiver(mUsbReceiver);
unregisterReceiver(mUsbDeviceReceiver);
super.onDestroy();
}

private void connectUsb(){

Toast.makeText(MainActivity.this,
"connectUsb()",
Toast.LENGTH_LONG).show();
textStatus.setText("connectUsb()");

searchEndPoint();
if(deviceFound != null){
doRawDescriptors();
}
}

private void releaseUsb(){

Toast.makeText(MainActivity.this,
"releaseUsb()",
Toast.LENGTH_LONG).show();
textStatus.setText("releaseUsb()");

if(usbDeviceConnection != null){
if(usbInterface != null){
usbDeviceConnection.releaseInterface(usbInterface);
usbInterface = null;
}
usbDeviceConnection.close();
usbDeviceConnection = null;
}

deviceFound = null;
usbInterfaceFound = null;
endpointIn = null;
endpointOut = null;
}

private void searchEndPoint(){

textInfo.setText("");
textSearchedEndpoint.setText("");

usbInterfaceFound = null;
endpointOut = null;
endpointIn = null;

//Search device for targetVendorID and targetProductID
if(deviceFound == null){
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();

if(device.getVendorId()==targetVendorID){
if(device.getProductId()==targetProductID){
deviceFound = device;
}
}
}
}

if(deviceFound==null){
Toast.makeText(MainActivity.this,
"device not found",
Toast.LENGTH_LONG).show();
textStatus.setText("device not found");
}else{
String s = deviceFound.toString() + "\n" +
"DeviceID: " + deviceFound.getDeviceId() + "\n" +
"DeviceName: " + deviceFound.getDeviceName() + "\n" +
"DeviceClass: " + deviceFound.getDeviceClass() + " - "
+ translateDeviceClass(deviceFound.getDeviceClass()) + "\n" +
"DeviceSubClass: " + deviceFound.getDeviceSubclass() + "\n" +
"VendorID: " + deviceFound.getVendorId() + "\n" +
"ProductID: " + deviceFound.getProductId() + "\n" +
"InterfaceCount: " + deviceFound.getInterfaceCount();
textInfo.setText(s);

//Search for UsbInterface with Endpoint of USB_ENDPOINT_XFER_BULK,
//and direction USB_DIR_OUT and USB_DIR_IN

for(int i=0; i<deviceFound.getInterfaceCount(); i++){
UsbInterface usbif = deviceFound.getInterface(i);

UsbEndpoint tOut = null;
UsbEndpoint tIn = null;

int tEndpointCnt = usbif.getEndpointCount();
if(tEndpointCnt>=2){
for(int j=0; j<tEndpointCnt; j++){
if(usbif.getEndpoint(j).getType() ==
UsbConstants.USB_ENDPOINT_XFER_BULK){
if(usbif.getEndpoint(j).getDirection() ==
UsbConstants.USB_DIR_OUT){
tOut = usbif.getEndpoint(j);
}else if(usbif.getEndpoint(j).getDirection() ==
UsbConstants.USB_DIR_IN){
tIn = usbif.getEndpoint(j);
}
}
}

if(tOut!=null && tIn!=null){
//This interface have both USB_DIR_OUT
//and USB_DIR_IN of USB_ENDPOINT_XFER_BULK
usbInterfaceFound = usbif;
endpointOut = tOut;
endpointIn = tIn;
}
}

}

if(usbInterfaceFound==null){
textSearchedEndpoint.setText("No suitable interface found!");
}else{
textSearchedEndpoint.setText(
"UsbInterface found: " + usbInterfaceFound.toString() + "\n\n" +
"Endpoint OUT: " + endpointOut.toString() + "\n\n" +
"Endpoint IN: " + endpointIn.toString());
}
}
}

private final BroadcastReceiver mUsbReceiver =
new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {

Toast.makeText(MainActivity.this,
"ACTION_USB_PERMISSION",
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_PERMISSION");

synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
doReadRawDescriptors(device);
}
}
else {
Toast.makeText(MainActivity.this,
"permission denied for device " + device,
Toast.LENGTH_LONG).show();
textStatus.setText("permission denied for device " + device);
}
}
}
}
};

private final BroadcastReceiver mUsbDeviceReceiver =
new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {

deviceFound = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
Toast.makeText(MainActivity.this,
"ACTION_USB_DEVICE_ATTACHED: \n" +
deviceFound.toString(),
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_DEVICE_ATTACHED: \n" +
deviceFound.toString());

connectUsb();

}else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {

UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

Toast.makeText(MainActivity.this,
"ACTION_USB_DEVICE_DETACHED: \n" +
device.toString(),
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_DEVICE_DETACHED: \n" +
device.toString());

if(device!=null){
if(device == deviceFound){
releaseUsb();
}
}

textInfo.setText("");
}
}

};

private void doRawDescriptors(){
UsbDevice deviceToRead = deviceFound;
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

Boolean permitToRead = manager.hasPermission(deviceToRead);

if(permitToRead){
doReadRawDescriptors(deviceToRead);
}else{
manager.requestPermission(deviceToRead, mPermissionIntent);
Toast.makeText(MainActivity.this,
"Permission: " + permitToRead,
Toast.LENGTH_LONG).show();
textStatus.setText("Permission: " + permitToRead);
}
}

private void doReadRawDescriptors(UsbDevice device){
final int STD_USB_REQUEST_GET_DESCRIPTOR = 0x06;
final int LIBUSB_DT_STRING = 0x03;

boolean forceClaim = true;

byte[] buffer = new byte[255];
int indexManufacturer = 14;
int indexProduct = 15;
String stringManufacturer = "";
String stringProduct = "";

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
usbDeviceConnection = manager.openDevice(device);
if(usbDeviceConnection != null){
usbInterface = device.getInterface(0);
usbDeviceConnection.claimInterface(usbInterface, forceClaim);

byte[] rawDescriptors = usbDeviceConnection.getRawDescriptors();

int lengthManufacturer = usbDeviceConnection.controlTransfer(
UsbConstants.USB_DIR_IN|UsbConstants.USB_TYPE_STANDARD,
STD_USB_REQUEST_GET_DESCRIPTOR,
(LIBUSB_DT_STRING << 8) | rawDescriptors[indexManufacturer],
0,
buffer,
0xFF,
0);
try {
stringManufacturer = new String(buffer, 2, lengthManufacturer-2, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
textStatus.setText(e.toString());
}

int lengthProduct = usbDeviceConnection.controlTransfer(
UsbConstants.USB_DIR_IN|UsbConstants.USB_TYPE_STANDARD,
STD_USB_REQUEST_GET_DESCRIPTOR,
(LIBUSB_DT_STRING << 8) | rawDescriptors[indexProduct],
0,
buffer,
0xFF,
0);
try {
stringProduct = new String(buffer, 2, lengthProduct-2, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Toast.makeText(MainActivity.this,
"Manufacturer: " + stringManufacturer + "\n" +
"Product: " + stringProduct,
Toast.LENGTH_LONG).show();
textStatus.setText("Manufacturer: " + stringManufacturer + "\n" +
"Product: " + stringProduct);
}else{
Toast.makeText(MainActivity.this,
"open failed",
Toast.LENGTH_LONG).show();
textStatus.setText("open failed");
}
}

private String translateDeviceClass(int deviceClass){
switch(deviceClass){
case UsbConstants.USB_CLASS_APP_SPEC:
return "Application specific USB class";
case UsbConstants.USB_CLASS_AUDIO:
return "USB class for audio devices";
case UsbConstants.USB_CLASS_CDC_DATA:
return "USB class for CDC devices (communications device class)";
case UsbConstants.USB_CLASS_COMM:
return "USB class for communication devices";
case UsbConstants.USB_CLASS_CONTENT_SEC:
return "USB class for content security devices";
case UsbConstants.USB_CLASS_CSCID:
return "USB class for content smart card devices";
case UsbConstants.USB_CLASS_HID:
return "USB class for human interface devices (for example, mice and keyboards)";
case UsbConstants.USB_CLASS_HUB:
return "USB class for USB hubs";
case UsbConstants.USB_CLASS_MASS_STORAGE:
return "USB class for mass storage devices";
case UsbConstants.USB_CLASS_MISC:
return "USB class for wireless miscellaneous devices";
case UsbConstants.USB_CLASS_PER_INTERFACE:
return "USB class indicating that the class is determined on a per-interface basis";
case UsbConstants.USB_CLASS_PHYSICA:
return "USB class for physical devices";
case UsbConstants.USB_CLASS_PRINTER:
return "USB class for printers";
case UsbConstants.USB_CLASS_STILL_IMAGE:
return "USB class for still image devices (digital cameras)";
case UsbConstants.USB_CLASS_VENDOR_SPEC:
return "Vendor specific USB class";
case UsbConstants.USB_CLASS_VIDEO:
return "USB class for video devices";
case UsbConstants.USB_CLASS_WIRELESS_CONTROLLER:
return "USB class for wireless controller devices";
default: return "Unknown USB class!";

}
}

}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<TextView
android:id="@+id/textstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

<TextView
android:id="@+id/textdevicename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold|italic" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<TextView
android:id="@+id/info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/searchedendpoint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

</LinearLayout>
</ScrollView>

</LinearLayout>




download filesDownload the files.



Step-by-step: Android USB Host Mode programming

USB Host exercise: get type and direction of UsbEndpoint

TO get type of a Endpoint, call its getType() method. The return int will be USB_ENDPOINT_XFER_CONTROL(endpoint zero), USB_ENDPOINT_XFER_ISOC(isochronous endpoint), USB_ENDPOINT_XFER_BULK(bulk endpoint) or USB_ENDPOINT_XFER_INT(interrupt endpoint).

To get direction of the Endpoiny, call its getDirection() method. It return USB_DIR_OUT(host to device), or USB_DIR_IN(device to host).

Update the last exercise of USB Host Mode "Use intent filter to detect a specified USB device and auto start application", modify endpointOnItemSelectedListener in MainActivity.java to read type and direction.

 OnItemSelectedListener endpointOnItemSelectedListener = 
new OnItemSelectedListener(){

@Override
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id) {

UsbEndpoint selectedEndpoint = listUsbEndpoint.get(position);

String sEndpoint = "\n" + selectedEndpoint.toString() + "\n"
+ translateEndpointType(selectedEndpoint.getType());

//Read Endpoint direction
String sEndpointDir = "";
switch(selectedEndpoint.getDirection()){
case UsbConstants.USB_DIR_OUT:
sEndpointDir = "USB_DIR_OUT";
break;
case UsbConstants.USB_DIR_IN:
sEndpointDir = "USB_DIR_IN";
break;
default:
sEndpointDir = "unknown!";
}

textEndPoint.setText(sEndpoint + "\n" + sEndpointDir);
}

@Override
public void onNothingSelected(AdapterView<?> parent) {}

};


Tested with Arduino Esplora connected:
- There are 3 UsbInterface.
- Both the 1st and 3rd UsbInterface have one Endpoint, of type USB_ENDPOINT_XFER_INT (interrupt endpoint), with direction of USB_DIR_IN.
- The 2nd UsbInterface have two Endpoint, both have type of USB_ENDPOINT_XFER_BULK (bulk endpoint), the 1st one have direction of USB_DIR_OUT, and the 2nd one have type of USB_DIR_IN. It will be used send and receive data in future exercise.





download filesDownload the files.



Step-by-step: Android USB Host Mode programming

cat /system/etc/permissions/handheld_core_hardware.xml on your Android device

This example simple display the file /system/etc/permissions/handheld_core_hardware.xml on my Android device.

handheld_core_hardware.xml of HTC One X
For what:
In my old post "List attached USB devices in USB Host mode", Anonymous commented have to check the xml file "/system/etc/permissions/handheld_core_hardware.xml" for < feature name="android.hardware.usb.host" />. Coincidentally I have a post to "Run Linux command with ProcessBuilder", so I modify it to display the content of "/system/etc/permissions/handheld_core_hardware.xml" using Linux command "cat".

package com.example.androidruncommand;

import java.io.IOException;
import java.io.InputStream;

import android.os.Bundle;
import android.app.Activity;
import android.widget.TextView;

public class MainActivity extends Activity {

TextView textCommand, textReturn;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textCommand = (TextView) findViewById(R.id.textcommand);
textReturn = (TextView) findViewById(R.id.textreturn);

String[] command = { "cat", "/system/etc/permissions/handheld_core_hardware.xml" };
StringBuilder cmdReturn = new StringBuilder();

String stringCommand = "$ ";
for(int i=0; i<command.length; i++){
stringCommand += command[i] + " ";
}
textCommand.setText(stringCommand);

try {
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();

InputStream inputStream = process.getInputStream();
int c;
while ((c = inputStream.read()) != -1) {
cmdReturn.append((char) c);
}

textReturn.setText(cmdReturn.toString());

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<TextView
android:id="@+id/textcommand"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<TextView
android:id="@+id/textreturn"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>

</LinearLayout>

Or, you can pull the file from your device using DDMS of Android Development Tools.

/system/etc/permissions/handheld_core_hardware.xml in HTC One X
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2009 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.
-->

<!-- These are the hardware components that all handheld devices
must include. Devices with optional hardware must also include extra
hardware files, per the comments below.

Handheld devices include phones, mobile Internet devices (MIDs),
Personal Media Players (PMPs), small tablets (7" or less), and similar
devices.
-->
<permissions>
<feature name="android.hardware.camera" />
<feature name="android.hardware.location" />
<feature name="android.hardware.location.network" />
<feature name="android.hardware.sensor.compass" />
<feature name="android.hardware.sensor.accelerometer" />
<feature name="android.hardware.bluetooth" />
<feature name="android.hardware.touchscreen" />
<feature name="android.hardware.microphone" />
<feature name="android.hardware.screen.portrait" />
<feature name="android.hardware.screen.landscape" />
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with an autofocus camera and/or flash must include either
android.hardware.camera.autofocus.xml or
android.hardware.camera.autofocus-flash.xml -->
<!-- devices with a front facing camera must include
android.hardware.camera.front.xml -->
<!-- devices with WiFi must also include android.hardware.wifi.xml -->
<!-- devices that support multitouch must include the most appropriate one
of these files:

If only partial (non-independent) pointers are supported:
android.hardware.touchscreen.multitouch.xml

If up to 4 independently tracked pointers are supported:
include android.hardware.touchscreen.multitouch.distinct.xml

If 5 or more independently tracked pointers are supported:
include android.hardware.touchscreen.multitouch.jazzhand.xml

ONLY ONE of the above should be included. -->
<!-- devices with an ambient light sensor must also include
android.hardware.sensor.light.xml -->
<!-- devices with a proximity sensor must also include
android.hardware.sensor.proximity.xml -->
<!-- GSM phones must also include android.hardware.telephony.gsm.xml -->
<!-- CDMA phones must also include android.hardware.telephony.cdma.xml -->
<!-- Devices that have low-latency audio stacks suitable for apps like
VoIP may include android.hardware.audio.low_latency.xml. ONLY apps
that meet the requirements specified in the CDD may include this. -->
</permissions>

But...I can't find < feature name="android.hardware.usb.host" /> in my handheld_core_hardware.xml. But it support USB Host mode actually.

Use intent filter to detect a specified USB device and auto start application

My former exercise show how to "Search USB device for specified Vendor ID and Product ID". In this post,  is added in AndroidManifest.xml, to discover specified device. If USB device with specified vendor-id and product-id inserted, user will be prompted to enable auto-start the app.


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidusbhost"
android:versionCode="1"
android:versionName="1.0" >

<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk
android:minSdkVersion="13"
android:targetSdkVersion="18" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidusbhost.MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|orientation" >
<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" />

<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>

</activity>
</application>

</manifest>

Create /res/xml/device_filter.xml to define our target vendor-id and product-id. The file name, device_filter, should be matched with android:resource inside <meta-data> of AndroidManifest.xml. Here vendor-id="9025" and product-id="32828" target to Arduino Esplora board.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device
vendor-id="9025"
product-id="32828" />
</resources>

MainActivity.java
package com.example.androidusbhost;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

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.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

public class MainActivity extends Activity {

TextView textInfo;
TextView textInfoInterface;
TextView textEndPoint;

TextView textDeviceName;
TextView textStatus;

Spinner spInterface;
ArrayList<String> listInterface;
ArrayList<UsbInterface> listUsbInterface;
ArrayAdapter<String> adapterInterface;

Spinner spEndPoint;
ArrayList<String> listEndPoint;
ArrayList<UsbEndpoint> listUsbEndpoint;
ArrayAdapter<String> adapterEndpoint;

private static final int targetVendorID= 9025;
private static final int targetProductID = 32828;
UsbDevice deviceFound = null;

private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION";
PendingIntent mPermissionIntent;

UsbInterface usbInterface;
UsbDeviceConnection usbDeviceConnection;

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

textStatus = (TextView)findViewById(R.id.textstatus);

textDeviceName = (TextView)findViewById(R.id.textdevicename);
spInterface = (Spinner)findViewById(R.id.spinnerinterface);
spEndPoint = (Spinner)findViewById(R.id.spinnerendpoint);
textInfo = (TextView) findViewById(R.id.info);
textInfoInterface = (TextView)findViewById(R.id.infointerface);
textEndPoint = (TextView)findViewById(R.id.infoendpoint);

//register the broadcast receiver
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);

registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED));
registerReceiver(mUsbDeviceReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED));

connectUsb();
}

@Override
protected void onDestroy() {
releaseUsb();
unregisterReceiver(mUsbReceiver);
unregisterReceiver(mUsbDeviceReceiver);
super.onDestroy();
}

private void connectUsb(){

Toast.makeText(MainActivity.this,
"connectUsb()",
Toast.LENGTH_LONG).show();
textStatus.setText("connectUsb()");

checkDeviceInfo();
if(deviceFound != null){
doRawDescriptors();
}
}

private void releaseUsb(){

Toast.makeText(MainActivity.this,
"releaseUsb()",
Toast.LENGTH_LONG).show();
textStatus.setText("releaseUsb()");

if(usbDeviceConnection != null){
if(usbInterface != null){
usbDeviceConnection.releaseInterface(usbInterface);
usbInterface = null;
}
usbDeviceConnection.close();
usbDeviceConnection = null;
}
deviceFound = null;
}

private void doRawDescriptors(){
UsbDevice deviceToRead = deviceFound;
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);

Boolean permitToRead = manager.hasPermission(deviceToRead);

if(permitToRead){
doReadRawDescriptors(deviceToRead);
}else{
manager.requestPermission(deviceToRead, mPermissionIntent);
Toast.makeText(MainActivity.this,
"Permission: " + permitToRead,
Toast.LENGTH_LONG).show();
textStatus.setText("Permission: " + permitToRead);
}
}

private final BroadcastReceiver mUsbReceiver =
new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {

Toast.makeText(MainActivity.this,
"ACTION_USB_PERMISSION",
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_PERMISSION");

synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
doReadRawDescriptors(device);
}
}
else {
Toast.makeText(MainActivity.this,
"permission denied for device " + device,
Toast.LENGTH_LONG).show();
textStatus.setText("permission denied for device " + device);
}
}
}
}
};

private final BroadcastReceiver mUsbDeviceReceiver =
new BroadcastReceiver() {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {

deviceFound = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
Toast.makeText(MainActivity.this,
"ACTION_USB_DEVICE_ATTACHED: \n" +
deviceFound.toString(),
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_DEVICE_ATTACHED: \n" +
deviceFound.toString());

checkDeviceInfoSkipDeviceSearching();
doRawDescriptors();
}else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {

UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

Toast.makeText(MainActivity.this,
"ACTION_USB_DEVICE_DETACHED: \n" +
device.toString(),
Toast.LENGTH_LONG).show();
textStatus.setText("ACTION_USB_DEVICE_DETACHED: \n" +
device.toString());

if(device!=null){
if(device == deviceFound){
releaseUsb();
}
}

textInfo.setText("");
textInfoInterface.setText("");
textEndPoint.setText("");

listInterface.clear();
listUsbInterface.clear();
adapterInterface.notifyDataSetChanged();

listEndPoint.clear();
listUsbEndpoint.clear();
adapterEndpoint.notifyDataSetChanged();
}
}

};

private void doReadRawDescriptors(UsbDevice device){
final int STD_USB_REQUEST_GET_DESCRIPTOR = 0x06;
final int LIBUSB_DT_STRING = 0x03;

boolean forceClaim = true;

byte[] buffer = new byte[255];
int indexManufacturer = 14;
int indexProduct = 15;
String stringManufacturer = "";
String stringProduct = "";

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
usbDeviceConnection = manager.openDevice(device);
if(usbDeviceConnection != null){
usbInterface = device.getInterface(0);
usbDeviceConnection.claimInterface(usbInterface, forceClaim);

byte[] rawDescriptors = usbDeviceConnection.getRawDescriptors();

int lengthManufacturer = usbDeviceConnection.controlTransfer(
UsbConstants.USB_DIR_IN|UsbConstants.USB_TYPE_STANDARD,
STD_USB_REQUEST_GET_DESCRIPTOR,
(LIBUSB_DT_STRING << 8) | rawDescriptors[indexManufacturer],
0,
buffer,
0xFF,
0);
try {
stringManufacturer = new String(buffer, 2, lengthManufacturer-2, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
textStatus.setText(e.toString());
}

int lengthProduct = usbDeviceConnection.controlTransfer(
UsbConstants.USB_DIR_IN|UsbConstants.USB_TYPE_STANDARD,
STD_USB_REQUEST_GET_DESCRIPTOR,
(LIBUSB_DT_STRING << 8) | rawDescriptors[indexProduct],
0,
buffer,
0xFF,
0);
try {
stringProduct = new String(buffer, 2, lengthProduct-2, "UTF-16LE");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Toast.makeText(MainActivity.this,
"Manufacturer: " + stringManufacturer + "\n" +
"Product: " + stringProduct,
Toast.LENGTH_LONG).show();
textStatus.setText("Manufacturer: " + stringManufacturer + "\n" +
"Product: " + stringProduct);
}else{
Toast.makeText(MainActivity.this,
"open failed",
Toast.LENGTH_LONG).show();
textStatus.setText("open failed");
}
}

private void checkDeviceInfo() {

deviceFound = null;

UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();

while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();

if(device.getVendorId()==targetVendorID){
if(device.getProductId()==targetProductID){
deviceFound = device;
}
}
}

textInfo.setText("");
textInfoInterface.setText("");
textEndPoint.setText("");

if(deviceFound==null){
Toast.makeText(MainActivity.this,
"device not found",
Toast.LENGTH_LONG).show();
textStatus.setText("device not found");
}else{
String i = deviceFound.toString() + "\n" +
"DeviceID: " + deviceFound.getDeviceId() + "\n" +
"DeviceName: " + deviceFound.getDeviceName() + "\n" +
"DeviceClass: " + deviceFound.getDeviceClass() + " - "
+ translateDeviceClass(deviceFound.getDeviceClass()) + "\n" +
"DeviceSubClass: " + deviceFound.getDeviceSubclass() + "\n" +
"VendorID: " + deviceFound.getVendorId() + "\n" +
"ProductID: " + deviceFound.getProductId() + "\n" +
"InterfaceCount: " + deviceFound.getInterfaceCount();
textInfo.setText(i);

checkUsbDevicve(deviceFound);
}

}

private void checkDeviceInfoSkipDeviceSearching() {
//called when ACTION_USB_DEVICE_ATTACHED,
//device already found, skip device searching

textInfo.setText("");
textInfoInterface.setText("");
textEndPoint.setText("");

String i = deviceFound.toString() + "\n" +
"DeviceID: " + deviceFound.getDeviceId() + "\n" +
"DeviceName: " + deviceFound.getDeviceName() + "\n" +
"DeviceClass: " + deviceFound.getDeviceClass() + " - "
+ translateDeviceClass(deviceFound.getDeviceClass()) + "\n" +
"DeviceSubClass: " + deviceFound.getDeviceSubclass() + "\n" +
"VendorID: " + deviceFound.getVendorId() + "\n" +
"ProductID: " + deviceFound.getProductId() + "\n" +
"InterfaceCount: " + deviceFound.getInterfaceCount();
textInfo.setText(i);

checkUsbDevicve(deviceFound);

}

OnItemSelectedListener deviceOnItemSelectedListener =
new OnItemSelectedListener(){

@Override
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id) {
UsbDevice device = deviceFound;

String i = device.toString() + "\n" +
"DeviceID: " + device.getDeviceId() + "\n" +
"DeviceName: " + device.getDeviceName() + "\n" +
"DeviceClass: " + device.getDeviceClass() + " - "
+ translateDeviceClass(device.getDeviceClass()) + "\n" +
"DeviceSubClass: " + device.getDeviceSubclass() + "\n" +
"VendorID: " + device.getVendorId() + "\n" +
"ProductID: " + device.getProductId() + "\n" +
"InterfaceCount: " + device.getInterfaceCount();
textInfo.setText(i);

checkUsbDevicve(device);
}

@Override
public void onNothingSelected(AdapterView<?> parent) {}

};

private void checkUsbDevicve(UsbDevice d) {
listInterface = new ArrayList<String>();
listUsbInterface = new ArrayList<UsbInterface>();

for(int i=0; i<d.getInterfaceCount(); i++){
UsbInterface usbif = d.getInterface(i);
listInterface.add(usbif.toString());
listUsbInterface.add(usbif);
}

adapterInterface = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, listInterface);
adapterInterface.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spInterface.setAdapter(adapterInterface);
spInterface.setOnItemSelectedListener(interfaceOnItemSelectedListener);
}

OnItemSelectedListener interfaceOnItemSelectedListener =
new OnItemSelectedListener(){

@Override
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id) {

UsbInterface selectedUsbIf = listUsbInterface.get(position);

String sUsbIf = "\n" + selectedUsbIf.toString() + "\n"
+ "Id: " + selectedUsbIf.getId() + "\n"
+ "InterfaceClass: " + selectedUsbIf.getInterfaceClass() + "\n"
+ "InterfaceProtocol: " + selectedUsbIf.getInterfaceProtocol() + "\n"
+ "InterfaceSubclass: " + selectedUsbIf.getInterfaceSubclass() + "\n"
+ "EndpointCount: " + selectedUsbIf.getEndpointCount();

textInfoInterface.setText(sUsbIf);
checkUsbInterface(selectedUsbIf);
}

@Override
public void onNothingSelected(AdapterView<?> parent) {}

};

private void checkUsbInterface(UsbInterface uif) {
listEndPoint = new ArrayList<String>();
listUsbEndpoint = new ArrayList<UsbEndpoint>();

for(int i=0; i<uif.getEndpointCount(); i++){
UsbEndpoint usbEndpoint = uif.getEndpoint(i);
listEndPoint.add(usbEndpoint.toString());
listUsbEndpoint.add(usbEndpoint);
}

adapterEndpoint = new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_item, listEndPoint);
adapterEndpoint.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spEndPoint.setAdapter(adapterEndpoint);
spEndPoint.setOnItemSelectedListener(endpointOnItemSelectedListener);
}

OnItemSelectedListener endpointOnItemSelectedListener =
new OnItemSelectedListener(){

@Override
public void onItemSelected(AdapterView<?> parent,
View view, int position, long id) {

UsbEndpoint selectedEndpoint = listUsbEndpoint.get(position);

String sEndpoint = "\n" + selectedEndpoint.toString() + "\n"
+ translateEndpointType(selectedEndpoint.getType());

textEndPoint.setText(sEndpoint);
}

@Override
public void onNothingSelected(AdapterView<?> parent) {}

};

private String translateEndpointType(int type){
switch(type){
case UsbConstants.USB_ENDPOINT_XFER_CONTROL:
return "USB_ENDPOINT_XFER_CONTROL (endpoint zero)";
case UsbConstants.USB_ENDPOINT_XFER_ISOC:
return "USB_ENDPOINT_XFER_ISOC (isochronous endpoint)";
case UsbConstants.USB_ENDPOINT_XFER_BULK :
return "USB_ENDPOINT_XFER_BULK (bulk endpoint)";
case UsbConstants.USB_ENDPOINT_XFER_INT:
return "USB_ENDPOINT_XFER_INT (interrupt endpoint)";
default:
return "unknown";
}
}

private String translateDeviceClass(int deviceClass){
switch(deviceClass){
case UsbConstants.USB_CLASS_APP_SPEC:
return "Application specific USB class";
case UsbConstants.USB_CLASS_AUDIO:
return "USB class for audio devices";
case UsbConstants.USB_CLASS_CDC_DATA:
return "USB class for CDC devices (communications device class)";
case UsbConstants.USB_CLASS_COMM:
return "USB class for communication devices";
case UsbConstants.USB_CLASS_CONTENT_SEC:
return "USB class for content security devices";
case UsbConstants.USB_CLASS_CSCID:
return "USB class for content smart card devices";
case UsbConstants.USB_CLASS_HID:
return "USB class for human interface devices (for example, mice and keyboards)";
case UsbConstants.USB_CLASS_HUB:
return "USB class for USB hubs";
case UsbConstants.USB_CLASS_MASS_STORAGE:
return "USB class for mass storage devices";
case UsbConstants.USB_CLASS_MISC:
return "USB class for wireless miscellaneous devices";
case UsbConstants.USB_CLASS_PER_INTERFACE:
return "USB class indicating that the class is determined on a per-interface basis";
case UsbConstants.USB_CLASS_PHYSICA:
return "USB class for physical devices";
case UsbConstants.USB_CLASS_PRINTER:
return "USB class for printers";
case UsbConstants.USB_CLASS_STILL_IMAGE:
return "USB class for still image devices (digital cameras)";
case UsbConstants.USB_CLASS_VENDOR_SPEC:
return "Vendor specific USB class";
case UsbConstants.USB_CLASS_VIDEO:
return "USB class for video devices";
case UsbConstants.USB_CLASS_WIRELESS_CONTROLLER:
return "USB class for wireless controller devices";
default: return "Unknown USB class!";

}
}

}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<TextView
android:id="@+id/textstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

<TextView
android:id="@+id/textdevicename"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold|italic" />

<Spinner
android:id="@+id/spinnerinterface"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<Spinner
android:id="@+id/spinnerendpoint"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<TextView
android:id="@+id/info"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:id="@+id/infointerface"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="italic" />

<TextView
android:id="@+id/infoendpoint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold" />

</LinearLayout>
</ScrollView>

</LinearLayout>

download filesDownload the files.




Step-by-step: Android USB Host Mode programming