Skip to content
kai-morich edited this page May 14, 2021 · 14 revisions

This is a collection of FAQ-style troubleshooting tips.

Table of Contents

My USB device is not recognized

Check with an App that uses this library and shows all USB devices, e.g. Serial USB Terminal. The Serial Example app in this project is not sufficient, as it does not show devices where no driver is detected.

If still no USB device is shown, check the web for USB Host Mode aka. USB OTG support for your Android device. Missing support is more likely for older devices.

For an incomplete list of Android devices with known issues look here.

My USB device is recognized, but no driver is detected

The library includes a list of USB vendor and device ID's (VID/PID) that are typically used by the supported chips. In case of unusual ID's, use a Custom Prober or specify a fixed driver.

Non USB-to-Serial devices like mass-storage, mouse, GPC receivers, ... and rarely used USB-to-Serial chips including Hoitek HE2325U and FTDI FT312D are not supported.

My device is connected, but I receive no / wrong data

A common issue is wrong baud rate.

Baud rate 12345 does not work

Not all drivers / devices support non-standard baud rates. See Feature Matrix for details.

I am using an Arduino Uno, Sparkfun Pro Micro, or other Arduino and if (Serial) doesn't work.

Most Arduinos with CDC driver use the DTR line to determine serial channel readiness. In your Android code, call setDTR(true);

How do I access /dev/ttyUSB0?

You don't. /dev/tty* is the Linux kernel's driver interface to various serial devices. Certain devices and custom ROMs may expose serial devices this way, but this library does not use this interface.

Can I open multiple connections in one application?

You can connect to multiple devices and to multiple ports of a multi-port device in one App.

  • When connecting to different ports in a multi-port device, each connection needs it's own UsbDeviceConnection, else the first close will also close all other ports.
  • Distinguishing identical devices has some challenges:
    • Use devices with different VIDs/PIDs or devices where it can be programmed like FTDI or CP210x .
    • Use UsbDevice.getSerialNumber() and devices that come with a unique serial or devices where it can be programmed like FTDI or CP210x.
      Note: Starting with Android 10, the serial number is only accessible after device access permission has been granted.
    • Using UsbDevice.getDeviceName() or UsbDevice.getDeviceId() is not an option as the numbers increase when re-attaching a device.

When reading a message, why don't all bytes arrive at the same time?

The protocol layer does not guarantee that all bytes will arrive in a single message. In fact the protocol layer doesn't have any knowledge of what your "message" is — it is just an interface for sending a serial stream of bytes.

To reduce the number of USB requests, devices usually buffer data until some size or idle time is reached. Therefore request sizes heavily depend on the device type and actual data transfer pattern.

For example, to receive a 100 byte string, you might read 64 bytes, then 36 bytes, instead of a single message of 100 bytes. You need to account for this problem when designing your protocol. Some common techniques:

  • Fixed length messages: If you a message is always going to be 100 bytes, just keep reading until you have all 100.
  • Length-prefixed messages: Prefix every message with a fixed-length size value; your message is complete after you've read size more bytes.
  • Newline-terminated messages: Read until you see a \n (or any other "terminal" character).

I observed read data loss with continuous transfer at high baud rates

Android is not a real time OS. The thread responsible for receiving data might not be scheduled by the OS or garbage collection might be ongoing or … Therefore data loss can happen for continues read at high baud rates. If data is lost, typically some smaller fragments in the middle of the data are missing.

This effect is more likely for slower Android device and USB devices with smaller buffer size and typically starts with higher baud rates like 115k2 baud, but is hardly predictable. For low baud rates or non-continuous transfers this issue was not observed as the USB device will not run into a read buffer overflow before the next USB read transfer.

Using a higher thread priority (default for SerialInputOutputManager since usb-serial-for-android v3.1.0) and offloading work from onNewData to other threads can mitigates the issue.

Data loss can also occur with inappropriate buffer size, as shown in next Question.

How to size the read buffer?

USB data transfers have a fixed packet size which is 64 for most devices. You can get the respective size with port.getReadEndpoint().getMaxPacketSize(), and it's recommended to use it as buffer size.

A smaller buffer size is ok, as long as the received messages fits into the buffer. If it doesn't fit into the buffer, read returns an empty result. Due to poor error propagation in Android USB code, this cannot be distinguished from timeout or real communication errors.

A larger buffer size can make your app lagging. In particular FTDI devices tend to queue data until the buffer is completely filled on continous transfer at higher baud rates. This can be mitigated by choosing appropriate buffer size and setting the latency timer as also recommended by FTDI.

When using smaller buffer sizes with FTDI devices, you have to take into account that each response starts with 2 header bytes. The header bytes will be stripped from the final result.

How to set timeout in read/write methods?

read timeout should not be shorter then 200 to 500 milliseconds, if possible use infinite timeout.

  • read with infinite timeout blocks until data is available, so it should be avoided in the UI thread, instead use SerialInputOutputManager to be notified on new data.
  • read with timeout is typically used in the UI thread, if you send a request and know that there is a timely response and the blocking time is acceptable.
write timeout should typically be significantly larger than the required send time.
  • write with short timeout is ok, if you use port.getReadEndpoint().getMaxPacketSize() as buffer size and resend the remaining data after getting a SerialTimeoutException. With larger buffer size, the packeting is done in the Linux kernel which returns -1 instead of the written size, so there is no chance to resume writing.
Android is not a realtime OS, e.g. garbage collection can easily take 100 msec.

Is write synchronous?

It's typically not.

Write consists of 2 phases:

  1. from android to usb device
  2. from usb device to serial port
If the send buffer on the usb device is not full, the write call returns after phase 1. If the buffer is full, e.g. your write is larger or older data is still to be send, the write call returns when enough data has been send over the serial port and the rest is in the buffer.

Waiting for write completion is typically done with application specific protocols, like request-response pattern.

Does this library work with Ionic/Cordova/Xamarin/App Inventor/... development framework?

If your framework can import Java .jar files, look here for instructions about creating a .jar file.

Feature Matrix

Basic Features are supported by all drivers / devices

Method / Feature Supported
open, close 🟢
setParameters 🟢
read, write 🟢
event based read with SerialInputOutputManager 🟢

Some Features are not supported by all drivers / devices

Feature FTDI CH34x CP210x PL2303 CDC
setParameters with non-standard baud rates 🟢 🟢 🟢 for CP2105
🔴 for CP2102. fallback to unknown baud rate without exception
🟢 🟢
set BREAK condition 🟢 🟢 🟢 for CP2102, CP2105 first port
🔴 for CP2105 second port. resends last byte without exception
🟢 🟢
set/get flow control lines RTS, CTS, DTR, DSR, CD, RI 🟢 🟢 🟢 🟢 🟡 only output lines RTS, DTR
purgeHwBuffers 🟢 🔴 🟢 🟢 🟢
multi port devices 🟢 n.a. 🟢 n.a. 🟢
device specific methods get/setLatencyTimer - - - -

Some Features are not implemented (yet)

Feature Supported
flow control (RTS/CTS or DTS/DTR or XON/XOFF based flow control) 🔴
Clone this wiki locally