UPDATE: 12 March 2017
Android things developer preview 3 adds support for USB-serial devices, making this method redundant for single USB-Serial adapters. This may be still useful for the QUAD UART used in this post. Read more about it here.
There’s nothing quite like the good old fashioned UART for connecting things together. It’s a technology that persists because it’s simple and it works. The Raspberry Pi has one UART. With it you can connect to exactly one peripheral. That’s not enough. We need more UARTs.
One solution to the ‘not enough UART’ problem is to use a USB-Serial converter. There’s been a Linux kernel driver for the FTDI USB-serial converters for years now, these are a well supported, mature technology. The aim of this experiment is to see if I can get an FTDI USB-Serial converter working with the Raspberry Pi 3 running the Android Things preview image 1.
![](http://android.geek.nz/wp-content/uploads/2017/01/ft4232h.png)
4 port FTDI UART
The Hardware
- Raspberry Pi 3 running developer preview of Android Things
- an FT4232H mini module from FTDI
Step 1 – Plug in a USB-Serial converter and see what happens
The best case scenario here is that everything just magically works, it’s not likely but will give us the direction we need to follow. This is a simple procedure; plug in the USB module and check the kernel messages to see if it gets detected.
Result
The Linux kernel on the Raspberry Pi developer preview image 1 has support for FTDI USB-Serial converters. Device special files are created for the 4 additional UARTS /dev/ttyUSB0 to /dev/ttyUSB3.
usb 1-1.3: new high-speed USB device number 4 using dwc_otg
usb 1-1.3: New USB device found, idVendor=0403, idProduct=6011
usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1.3: Product: Quad RS232-HS
usb 1-1.3: Manufacturer: FTDI
ftdi_sio 1-1.3:1.0: FTDI USB Serial Device converter detected
usb 1-1.3: Detected FT4232H
usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB0
ftdi_sio 1-1.3:1.1: FTDI USB Serial Device converter detected
usb 1-1.3: Detected FT4232H
usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB1
ftdi_sio 1-1.3:1.2: FTDI USB Serial Device converter detected
usb 1-1.3: Detected FT4232H
usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB2
ftdi_sio 1-1.3:1.3: FTDI USB Serial Device converter detected
usb 1-1.3: Detected FT4232H
usb 1-1.3: FTDI USB Serial Device converter now attached to ttyUSB3
Here the USB-Serial converter has been detected by the kernel and device files /dev/ttyUSB0
to /dev/ttyUSB3
have been created. Lets see if they can be used.
user@dev-laptop ~ $ adb shell ls -all /dev/ttyUSB*
crw------- 1 root root 188, 0 2017-01-04 18:33 /dev/ttyUSB0
crw------- 1 root root 188, 1 2017-01-04 18:33 /dev/ttyUSB1
crw------- 1 root root 188, 2 2017-01-04 18:33 /dev/ttyUSB2
crw------- 1 root root 188, 3 2017-01-04 18:33 /dev/ttyUSB3
With these permissions we won’t be able to read or write to the UARTS from an Android app without getting root privileges.
Step 2 – change permissions on /dev/ttyUSB*
The default permissions of the device special files created for the FTDI UARTs on the Android Things preview image are 0600, with root as owner. This means we won’t be able to access the files from an Android app. To change the permissions on these files we need to specify what permissions to use.
To change file permissions of the /dev/ttyUSB* files we can add a line to uevent.rpi3.rc
on the root file system of the Raspberry Pi. I added the following line to that file.
/dev/ttyUSB* 0666 root root
Result
With the file permissions changed in uevent.rpi3.rc
the first experiment is repeated; plug in the USB-Serial converter and see what happens. The result is that we have read/write access to the UARTS.
user@dev-laptop ~ $ adb shell ls -all /dev/ttyUSB*
crw-rw-rw- 1 root root 188, 0 1970-01-01 00:00 /dev/ttyUSB0
crw-rw-rw- 1 root root 188, 1 1970-01-01 00:00 /dev/ttyUSB1
crw-rw-rw- 1 root root 188, 2 1970-01-01 00:00 /dev/ttyUSB2
crw-rw-rw- 1 root root 188, 3 1970-01-01 00:00 /dev/ttyUSB3
OK, good, now we (and all and sundry) have access to the UARTs.
Step 3 – Adding Software to support Serial Ports
Accessing the UARTs from java means adding a wafer thin layer of C using the ndk. No need to re-invent the wheel here, we can use the android-serialport-api project. I’ve created an example project that uses the serial port api to open one of the UARTs and periodically write a message to it.
A note about SELinux
The preview image of Android Things has SELinux operating in permissive mode. This means that security policy violations are logged but no action is taken to enforce permissions. When we access the UART we can see the following messages in logcat, which indicate that SELinux has detected our shenanigans.
avc: denied { read } for name=”ttyUSB0″ dev=”tmpfs” ino=8915 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
avc: denied { write } for name=”ttyUSB0″ dev=”tmpfs” ino=8915 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
avc: denied { open } for path=”/dev/ttyUSB0″ dev=”tmpfs” ino=8915 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
avc: denied { ioctl } for path=”/dev/ttyUSB0″ dev=”tmpfs” ino=8915 ioctlcmd=5401 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
Once SELinux is run in enforcing mode we will be denied access to the UARTs regardless of how we set the file permissions. We would need to write an SELinux policy to get access. I don’t know if such customisation will be allowed on a real device running Android Things in production. (spooky voice) Who knows what the future holds, do, do , do , do.
Example Project
The source code for the example project is here.
Conclusion
It is possible to use an FTDI USB-serial converter on the Raspberry Pi 3 running the preview image of Android Things. This is probably not something you will be able to achieve with production images of Android Things. I have not seen any indication from Google that device developers will be able to tailor SELinux policies or modify *.rc files to setup services or set permissions of device files, or that any native user space changes will be possible, or even if kernel configuration modifications will be possible to enable kernel features and/or drivers. Only time and future announcements from the Android Things team will tell…
Hi,
The great post. I need some more information. How to add the line “/dev/ttyUSB* 0666 root root” into file “uevent.rpi3.rc “.
“adb push” says it is “read only memory”
Thanks in advance.
Hi, what I did was remove the micro SD card from the Raspberry Pi and edit the file on my laptop. Cheers.