Android Xamarin USB Host

I recently acquired some Casio keyboards for an alternative setup. The idea was to build a setup with a master keyboard (WK1200) and a lead keyboard (XW-P1). It turned out the XW-P1 is a very versatile and a fantastic multitimbral midikeyboard.


I modified the WK1200 keyboard with an OLED display, some knobs and a Arduino Mega 2560 to make it possible to send patch changes for both keyboards. However, it was a somewhat clumsy interface so I decided to grab an Android Tablet to make a nicer control device. First, I wanted to interface the Android tablet with the WK1200, eg. over Bluetooth, Wireless or Android Accesory mode. But then I thought it should be possible to control the XW-P1 from a tablet directly, where the tablet is in USB Host mode. I had done things like that in the past, on PC based systems. But this time, on to Android. I decided to do some tests on Android development as that was quite some time ago. Here are my results:

  • Android Studio: This is for me the default Android Java IDE. I tried to create an application with a button with an OnClick event, designing the form in the UI designer. Now this has improved a lot since my past Android experiences! But still, adding the event handler still needs to be done manually and I again saw a lot of code to do some simple things. It's just not my cup of tea.
  • Xamarin. Xamarin is free now and can be used in one of my favorite IDEs, Visual Studio. As you may know it uses C# as programming language. As a windows UI programmer this is much easier to handle. Unfortunately at the moment of writing there is no nice UI designer for Xamarin.Forms so XAML is the only possibility, unless you create the UI in code. I have opted for the latter, since I am writing a simple application. I even omitted the MVVM pattern, because when you create the UI yourself, that also needs to be done. So, no binding, just a simple programming model, not unlike Delphi's paradigm.
  • There are quite a lot Xamarin examples to be found and the seperation of Android specific code and Xamarin.Forms is really workout great. I created my own Depency Injection system, but the provided one is ok as well.
  • Unfortunately there are quite a few bugs in Xamarin when deploying to several devices at once. This maybe also Android related.
  • If I had to start again, I think I would opt for the Android Java way.

But for now, it's Xamarin and the interesting part now follows: There are a few examples on USB Host with Android, but almost none with Xamarin. Note that my tablets are somewhat older and running Jellybean, so I could not use the new MIDI layer. But for study, that's more interesting!

So, the crucial part of the USB Host connection are a few concepts:

  • Finding the USB Device (in our case the Casio XW-P1)
  • Getting the correct endpoints
  • Write to an endpoint
  • Read from an endpoint (if necessary)

So let's look at the various parts:

First, before finding the devices, USB Host should be enabled. This involves that some permissions are granted on your tablet and that the user grants the use of device. The first part, is part of your tablet setup. For me it meant I had to root my tablet and put some permission files on it (See here for how to do this).

The software to achieve our goal should reside in the Droid part of your application

Finding the usbDevice is by examining the Usb Device tree:

UsbManager manager = (UsbManager)GetSystemService(Context.UsbService);
const int VENDOR_ID = 0x07CF;
const int PRODUCT_ID = 0x6803;
var matchingDevice = manager.DeviceList.FirstOrDefault(item => item.Value.VendorId == VENDOR_ID && item.Value.ProductId == PRODUCT_ID);
return matchingDevice.Value;

If the device is missing, null will be returned. But if successful, we can proceed: We first have to check permissions and open a dialog if they have not been granted (yet)

if (!manager.HasPermission(usbDevice))
      manager.RequestPermission(usbDevice, null);

Now, the Casio XW-P1 has a few interfaces, which you can check with some USB viewer. It turns out we need interface 1, which has two endpoints, endpoint 0 for writing and endpoint 1 for reading:

usbInterface = usbDevice.GetInterface(1);
usbDeviceConnection.ClaimInterface(usbInterface, true);
endpointOut = usbInterface.GetEndpoint(0);
endpointIn = usbInterface.GetEndpoint(1);

We now can write to the device with a bulktransfer like:

private bool WriteBuffer(byte[] buffer)
  int written = usbDeviceConnection.BulkTransfer(endpointOut, buffer, buffer.Length, 500);

But, we are not there yet... In my case I want to write several things to the XW-P1, like Program changes, Control changes and even SysEx messages.

Note that the endpoint does not use midi directly, but is close. See example here for the JAVA version of this stuff: USB-MIDI-Driver.

Here I will only show how to send a program change, see the code for all other possibilities. Just pre-attached the byte = 12 to your message. Since the total of bytes does not exceed 4 this can be send as one message. Things become harder (or more interesting? with sysex messages). Anyway:

private bool WritePRG(int midi, byte program)
  byte[] buffer = new byte[3];
  buffer[0] = 12;
  buffer[1] = (byte)(0xC0 + midi);
  buffer[2] = program;
  return WriteBuffer(buffer);

That's all for writing to the device. I have not developed reading from the device completely, but in the code you can see it not too difficult: Just run an extra read thread and do bulkTransfers on the endpointIn. Of course, you must implement the midi protocol here as well. 

The code is available at GitHub on my account. It contains more than only this code. I also created the wireless solution where the Android tablet (or phone) communicates with the Arduino Mega 2560, with the famous ESP8266 chip, which turns out to be a very solid connection.

 Techniques Used

  • Xamarin, C#, Dependency injection.
  • USB Host protocol, MIDI protocol
  • IDEs used: Visual Studio with Xamarin extension