Android USB Host + USB VCP Driver [Part 2]

(Un)fortunately I have just signed a NDA (Non-Disclosure Agreement) with FTDI Chip in order to develop the Android version of their FT(2)232 chip.

This agreement was approved by FTDI so I cannot publish either the documentation I have just received, or the source code I develop based on that documentation.
I will go on writing about my experience developing the USB VCP driver for Android entirely on Java, and  may be as a result of the project an obfuscate binary will be published in order to communicate with the FT(2)232 family.
One more thing to mention: FTDI writes very clear and nice documentation.

Android USB Host + USB VCP Driver [Part 1]

I have connected a USB device that creates a USB VCP profile to my Motorola Xoom in order to enable my Xoom apps to interface with RS232 devices.
My small test program shows the following details for the USB device:

Model: /dev/bus/usb/002/002
Id: 2002
Class: 0
SubClass: 0
Protocol: 0
VendorId: 1659
ProductId: 8963
Number of Interfaces: 1
>> Interface 0 -> 3 Endpoints

With all the information we can tell the device to open a custom application when the USB device is attached. To do so, the following information should be added to the ‘activity’ tag in the Manifest.

<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/usb_device_filter" />

The XML file is a resource file that contains information about the USB Device, that should be placed in /res/xml

<resources>
<usb-device vendor-id="1659" product-id="8963" class="0" subclass="0"
 protocol="0"/>
</resources>

When the activity starts, it can retrieve the USB Device information by calling:

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

If the device is not null, then you can open an UsbInterface and get the UsbEndpoint in order to read and write information.

How Android sees an attached USB Device

In the long way that my project must walk, I decided to start testing some small things in order to understand how the Android USB Host API and Open Accessory API (two different things) work.
Basically the USB Host API lets your Android device acts as a computer. With this API you can connect from a Bluetooth USB adapter to any standard USB device that you can find in a store. The Open Accessory API works the other way, your Android acts as a device, so you have to connect a USB Host controller in the other side. I don’t find this second approach very useful. First because not all the microcontrollers in the world support USB Host (Remember, your Android is a Device for the Open Accessory API) Second because it does not allow seemless development of a product using a computer and a natural port to Android using the USB Host API. I still cannot find three nice examples of when I will prefer to use my Tablet as a USB Device, but I can find millions of application for my Tablet (and Phone) to be a USB Host.
So in this short post, I will show you how it a USB Device attached to a  Honeycomb-enabled device looks like. Take special attention to the fact that even though Android 2.x has an option USB toolkit, and the classes have the same name, they belong to a different package (so the imports are not the same).
The Motorola Xoom with Android 3.2 is USB Host capable, and even thought I connected a USB keyboard and it didn’t work in the OS, the following short example demonstrates that the Motorola Xoom detects a USB Bluetooth adapter.

When attaching the USB Bluetooth adapter the following message can be seen using “logcat” (connected via TCP as the USB port is busy with the adapter)



 

Debugging Android wirelessly

Recently I flashed my Motorola Xoom with Android 3.2 in order to start playing with USB Host API and Open Accessory API, but both functionalities are implemented on the unique USB port that the Xoom has. This is not a problem when you own a Dock, or you own a Acer A500 which has one USB host and one USB device. Debugging an Android application using abd can be done wirelessly over WiFi using the followings instructions.

When debugging applications that use USB accessory or host features, you most likely will have USB hardware connected to your Android-powered device. This will prevent you from having an adb connection to the Android-powered device via USB. You can still access adb over a network connection. To enable adb over a network connection:

  1. Connect the Android-powered device via USB to your computer.
  2. From your SDK platform-tools/ directory, enter adb tcpip 5555 at the command prompt.
  3. Enter adb connect <device-ip-address>:5555 You should now be connected to the Android-powered device and can issue the usual adb commands like adb logcat.
  4. To set your device to listen on USB, enter adb usb.

 

a Caller ID that speaks (for Android)

So I have just arrived home and while preparing a tuna fish sandwich somebody calls home and the answer machine started to say the number. This is something very normal as I had this answer machine for 5 years more or less. The first days it was amazing to be 20 meters away from the phone and listen the phone number of the person who was calling me. It is very nice, it prevents me and my family from running to the phone every time somebody calls.
So I was thinking about doing the same for a cellphone, and I am sure there are a few apps out there that does this. But I wanted to do it in a few minutes and post the code.
I choose Android as the platform as I think it is flexible enough to archive this task. This cannot be done in iPhone with such a limited API and no access to key features of the phone.
Basically you need to register a Listener which will handle “Phone State Changes”. If one of those events indicates a “Phone ringing” you have to parse the number digit by digit and play an audio file.
The audio you will find in this example is my voice, and the numbers are in German (just to make this a bit funnier, and to practice, of course).
This application does not have an activity. It has only two classes, a Broadcast Receiver and a Service. The Broadcast Receiver it will lunch the Service as soon as the phone finished booting. The Service will register a Listener to the Telephony Manager, and that Listener will handle the incoming call.
How to register the Listener for Incoming Calls

How to handle an Incoming Call event

The complete project
vCallerID

Bluetooth in pre-Android 2.0 devices

Android OS introduced Bluetooth as an open API in version 2.0, but early versions like the well known Donut (1.6) and, one of the most famous in Motorola devices, Cupcake (1.5) included Bluetooth support in the OS for hands free communications, files exchange and communication with PCss (and Macs).
Of all projects around the web that enable Bluetooth in pre-2.0 devices, I liked android-bluetooth (http://code.google.com/p/android-bluetooth/) very much. Basically because it was design for compatibility with 2.x releases of Android. This was archived by keeping an API as similar as the official one but changing the package name of the classes (Android does not allow 3rd parties classes inside android package).

It is very important to check if the Android devices allows Bluetooth comms, either because the module is not present or because it is not available. For doing so, just use this piece of code:

If everything goes right, you have to register for broadcast messages like “discovering devices”, “discovering finished”, “did finish connection with device” and so on. That is very easy to do in Android

and then, it is necessary to implement the Broadcast interface

Some other configurations are needed by this framework, including a configuration file and registering receivers and activities in the Android Manifest. For a complete working example check out my BTExample project.
BTExample