Showing posts with label Android code sample: usb. Show all posts
Showing posts with label Android code sample: usb. 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

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