Establishing Communication between PSLab and an Android Device using the USB Host API

In this post, we are going to learn how to establish communication between the PSLab USB device and a connected Android device. We will implement our own custom read & write methods by using functions provided by USB Host API of Android SDK.

At first we need to enable communication to PSLab device by connecting it to Android Phone by an On-The Go (OTG) cable. We are communicating via the USB Host API of Android.

About Android USB

Android supports USB peripherals through two modes:

  • Android Accessory: In this mode external USB device acts as host.
  • Android Host: In this mode Android Device acts as host and powers the external device.
Source : Android Developers Docs

Obtaining Permission to access USB device

When a USB device is connected to Android device, you need to obtain permissions to access the USB device. You have two ways, I have used intent-filter method to obtain permission in PSLab project, but you can also use the approach to implement a broadcast receiver.

Option 1:

Add a intent filter in the activity which would handle that connected USB device. This is an implicit way to obtain permission.

<activity ...>
...
    <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    </intent-filter>
    <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
        android:resource="@xml/device_filter" />
</activity>

And add device details like your vendor ID and product ID in device_filter.xml

<resources>

    <usb-device vendor-id="1240" product-id="223" />

</resources>

Now when you connect your USB device, permission dialog like below would pop up:

Option 2:

  • If you want to obtain permission explicitly, first create broadcastreceiver which would be broadcasted which you call requestPermission().

    private static final String ACTION_USB_PERMISSION =
        "com.android.example.USB_PERMISSION";
    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
    
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if(device != null){
                       }
                    }
                    else {
                        Log.d(TAG, "permission denied for device " + device);
                    }
                }
            }
        }
    };

    Register this broadcastreceiver in your onCreate method of your activity.

    UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    private static final String ACTION_USB_PERMISSION =
        "com.android.example.USB_PERMISSION";
    ...
    mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    registerReceiver(mUsbReceiver, filter);

    And call requestPermission method to show a dialog for permission

    UsbDevice device;
    ...
    mUsbManager.requestPermission(device, mPermissionIntent);

    Now when you open your App permission dialog like shown below would pop up:

Obtain Read & Write Endpoints

Now that you have permission to communicate with a USB device connected. Next step is to obtain read and write Endpoints to read and write to USB device by using bulkTransfer() function.

The definition of bulkTransfer() methods is

int bulkTransfer (UsbEndpoint endpoint, 
                byte[] buffer, 
                int length, 
                int timeout)

endpoint : Usb Endpoint ( the endpoint for this transaction )

buffer : byte ( buffer for data to send or receive )

length : int ( length of data to send/receive )

timeout : int ( in milliseconds, 0 is infinite )

For code to obtain read, write Endpoint through Data Interface of USB device. Open() method of PSLab can be referenced.

There are two ways for communication :

  • Synchronous
  • Asynchronous

In PSLab, we use synchronous communication using bulkTransfer() method. Create a USB device connection object

mConnection = mUsbManager.openDevice(mUsbDevice);

As bulkTransfer methods are exposed by USB connection object. Using these you can implement your read & write functions to meet your project’s requirements. Or use bulkTransfer() directly to read & write data.

For example:

mConnection.bulkTransfer(mReadEndpoint, mReadBuffer, bytesToRead, timeoutMillis)

So this covers the required for obtaining permission to access USB device and basics of how you can read data from and write data to USB device.

Also if this project interest you, feel free to contribute or raise any issue. PSLab-Android.

Resources