Read data from pen drive through android USB host mode

6.3k views Asked by At

I need to read file from pen drive, my code is as follow:

private static final String ACTION_USB_PERMISSION = "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (ACTION_USB_PERMISSION.equals(action)) {
            synchronized (this) {
                UsbDevice device = (UsbDevice) intent
                        .getParcelableExtra(UsbManager.EXTRA_DEVICE);
                if (intent.getBooleanExtra(
                        UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if (device != null) {
                        // call method to set up device communication
                    }
                } else {
                    Log.d(TAG, "permission denied for device " + device);
                }
            }
        }
    }
};

To detect device i use:

mgr = (UsbManager) getSystemService(Context.USB_SERVICE);
devs = new HashMap<String, UsbDevice>();
devs = mgr.getDeviceList();

And after getting device and interface, i get endpoint as follows:

public void getEndpointCount(View v) {
    itf = value.getInterface(0);
    endPointCount = itf.getEndpointCount();

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage("No. of Endpoints: " + endPointCount)
            .setTitle("Endpoint Count").setCancelable(true)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
    AlertDialog alert = builder.create();
    alert.show();
    ((Button) findViewById(R.id.button4)).setEnabled(true);
}

public void getEndpointDirections(View v) {
    endPoint = null;


    UsbDeviceConnection conn = null;

    if (mgr.hasPermission(value)) {
        conn = mgr.openDevice(value);
        conn.claimInterface(itf, true);
    }

    String str = null;
    for (int i = 0; i < endPointCount; i++) {
        ((TextView) findViewById(R.id.tvLoopVal)).setText("" + i);
        endPoint = itf.getEndpoint(i);
        str = str + " Endpoint: " + i + " - " + endPoint.getDirection()
                + "\n";

if (endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
            ((TextView) findViewById(R.id.tvLoopVal)).setText("" + (i - 1));
            if (endPoint.getDirection() == UsbConstants.USB_DIR_IN) {
                Toast.makeText(this, "epin", Toast.LENGTH_SHORT).show();
                epIn = endPoint;
            } else {
                epOut = endPoint;
                Toast.makeText(this, "epout", Toast.LENGTH_SHORT).show();
            }
        }

    }

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(
            str + " Mac packet Size = " + endPointUsed.getMaxPacketSize())
            .setTitle("Endpoints Directions").setCancelable(true)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
    AlertDialog alert = builder.create();
    alert.show();

}

At the end i get the endpoint now where i am stuck is what is the next step to either read or write the data to the pendrive. I am getting no clue on this and need guidance where to look now.

Also if i do not attach any usb device to my tablet still it says 1 device found and when i attach pendrive through OTG cable it says 2 device found!! That is also strange

EDIT:

I also initialized request using USB request method but still I do not get how it works

public void initializeRequest(View v) {
    UsbRequest uReq = new UsbRequest();
    Toast.makeText(this, "" + uReq.initialize(conn, epIn),
            Toast.LENGTH_SHORT).show();
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(
            " Is Request Initialized: = " + uReq.initialize(conn, epIn))
            .setTitle("Request Initialization").setCancelable(true)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    dialog.cancel();
                }
            });
    AlertDialog alert = builder.create();
    alert.show();
    byte[] bb = new String("Hello").getBytes();
    ByteBuffer bBuffer = ByteBuffer.allocate(5);
    // bBuffer.put(bb);
    uReq.queue(bBuffer, 5);

    UsbRequest request = conn.requestWait();
    // Object obj = uReq.getClientData();
    // Log.v("Client Data", "" + obj.toString());
    if (request != null) {
        Toast.makeText(this, "Not null request", Toast.LENGTH_SHORT).show();
        Log.v("Response of request wait", ""
                + request.getClientData().toString());
        request.close();
    }
    uReq.close();

    // Log.v("Response of request wait", "" + conn.requestWait());
    // uReq.close();
}

I verified that endpoints are getting assigned, but when this method gets executed the application simply waits, does nothing. After sometime Android asks to close the app. Is it like because of requestWait() function application waits for some type of event?

EDIT

Okay, if we forget reading from pen drive and simply need to get audio stream from a USB device, lets say microphone where i am not going to read anything i will catch whatever the microphone will give, then still i have to do something else then what i have done here??

2

There are 2 answers

5
Michael On

It doesn't look like you're actually reading any data. If you've got an EndPoint going from the device to the host you should be able to read data from it with the bulkTransfer method.

I'm not all that familiar with low-level USB communication, but I'd assume that you need to handle file system parsing yourself. If you read the first sector (512 bytes) on the drive and the last two bytes of that sector are 0x55,0xAA the drive is probably formatted with a FAT file system, and you'll have to work your way from there.

0
Omar Zanhour On

Since there was no accepted answer, I will post mine.

There is an open source library called libaums that implement usb mass storage mode (UMS) for Android and also the Fat32 file system. You can use this library in your android app to read/write files from USB devices. The library handle low level communication with the USB device..

https://github.com/magnusja/libaums

Basic Example:

UsbMassStorageDevice[] devices = UsbMassStorageDevice.getMassStorageDevices(this /* Context or Activity */);

for(UsbMassStorageDevice device: devices) {

   // before interacting with a device you need to call init()!
   device.init();

   // Only uses the first partition on the device
   FileSystem currentFs = device.getPartitions().get(0).getFileSystem();
   Log.d(TAG, "Capacity: " + currentFs.getCapacity());
   Log.d(TAG, "Occupied Space: " + currentFs.getOccupiedSpace());
   Log.d(TAG, "Free Space: " + currentFs.getFreeSpace());
   Log.d(TAG, "Chunk size: " + currentFs.getChunkSize());
}