1
0
mirror of https://github.com/mik3y/usb-serial-for-android synced 2025-06-09 00:46:11 +00:00

more buffer size info

kai-morich 2021-04-26 09:17:19 +02:00
parent c50678286b
commit b36d2dba48

@ -25,7 +25,7 @@ A common issue is wrong baud rate.
== Baud rate <code>12345</code> does not work == == Baud rate <code>12345</code> does not work ==
Not all drivers / devices support non-standard baud rates. See [[Troubleshooting#Feature Matrix|Feature Matrix]] for details. Not all drivers / devices support non-standard baud rates. See [[FAQ#Feature Matrix|Feature Matrix]] for details.
== I am using an Arduino Uno, Sparkfun Pro Micro, or other Arduino and <code>if (Serial)</code> doesn't work. == == I am using an Arduino Uno, Sparkfun Pro Micro, or other Arduino and <code>if (Serial)</code> doesn't work. ==
@ -35,7 +35,7 @@ Most Arduinos with CDC driver use the DTR line to determine serial channel readi
== How do I access <code>/dev/ttyUSB0</code>? == == How do I access <code>/dev/ttyUSB0</code>? ==
You don't. <code>/dev/tty*</code> 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. You don't. <code>/dev/tty*</code> 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? == == Can I open multiple connections in one application? ==
@ -43,10 +43,9 @@ You don't. <code>/dev/tty*</code> is the Linux kernel's driver interface to var
You can connect to multiple devices and to multiple ports of a multi-port device in one App. 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 <code>UsbDeviceConnection</code>, else the first <code>close</code> will also close all other ports. * When connecting to different ports in a multi-port device, each connection needs it's own <code>UsbDeviceConnection</code>, else the first <code>close</code> will also close all other ports.
* When using <code>SerialInputOutputManager</code>, each has to run in it's own <code>Executor</code>.
* Distinguishing identical devices has some challenges: * Distinguishing identical devices has some challenges:
** Use devices with different VIDs/PIDs or where they can be programmed like FTDI or CP210x . ** Use devices with different VIDs/PIDs or devices where it can be programmed like FTDI or CP210x .
** Use <code>UsbDevice.getSerialNumber()</code> and devices that come with a unique serial or where it can be programmed like FTDI or CP210x.<br>'''Note:''' Starting with Android 10, the serial number is only accessible after device access permission has been granted. ** Use <code>UsbDevice.getSerialNumber()</code> and devices that come with a unique serial or devices where it can be programmed like FTDI or CP210x.<br>'''Note:''' Starting with Android 10, the serial number is only accessible after device access permission has been granted.
** Using <code>UsbDevice.getDeviceName()</code> or <code>UsbDevice.getDeviceId()</code> is not an option as the numbers increase when re-attaching a device. ** Using <code>UsbDevice.getDeviceName()</code> or <code>UsbDevice.getDeviceId()</code> 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? == == When reading a message, why don't all bytes arrive at the same time? ==
@ -76,31 +75,26 @@ Data loss can also occur with inappropriate buffer size, as shown in next Questi
== How to size the <code>read</code> buffer? == == How to size the <code>read</code> buffer? ==
All supported devices use a packet size of 64 bytes, so you should use a multiple of 64 bytes. USB data transfers have a fixed packet size which is 64 for most devices. You can get the respective size with <code>port.getReadEndpoint().getMaxPacketSize()</code>, and it's recommended to use it as buffer size.
A shorter size is ok, as long as the received messages fits into the buffer. If it doesn't fit into the buffer, <code>read</code> returns an empty result. Due to poor error propagation in Android USB code, this cannot be distinguished from timeout or real communication errors. A smaller buffer size is ok, as long as the received messages fits into the buffer. If it doesn't fit into the buffer, <code>read</code> returns an empty result. Due to poor error propagation in Android USB code, this cannot be distinguished from timeout or real communication errors.
Using a large buffer 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 sizes and setting the latency timer as also recommended by [https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwjTp5fQ5tTrAhVP_KQKHQNcAwQQFjABegQIAxAB&url=http%3A%2F%2Fwww.ftdichip.com%2FSupport%2FDocuments%2FAppNotes%2FAN232B-04_DataLatencyFlow.pdf&usg=AOvVaw25BTFYId5BMobgEVDZblku FTDI]. 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 [http://www.ftdichip.com/Support/Documents/AppNotes/AN232B-04_DataLatencyFlow.pdf FTDI].
For FTDI devices you have to take into account that each 64 byte response starts with 2 header bytes. The header bytes will be stripped from the final result.
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 <code>read</code>/<code>write</code> methods? == == How to set timeout in <code>read</code>/<code>write</code> methods? ==
You should avoid too short timeouts, as they can cause data loss! <code>read</code> timeout should not be shorter then 200 to 500 milliseconds, if possible use infinite timeout.
* <code>write</code> timeout should be significantly larger than the required send time * <code>read</code> with infinite timeout blocks until data is available, so it should be avoided in the UI thread, instead use <code>SerialInputOutputManager</code> to be notified on new data.
* <code>read</code> timeout should not be shorter then 200 to 500 milliseconds, if possible use infinite timeout
<code>read</code> with infinite timeout blocks until data is available, so it should be avoided in the UI thread, instead use <code>SerialInputOutputManager</code> to be notified on new data. * <code>read</code> 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.
<code>read</code> 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. <code>write</code> timeout should typically be significantly larger than the required send time.
'''Background:''' * <code>write</code> with short timeout is ok, if you use <code>port.getReadEndpoint().getMaxPacketSize()</code> as buffer size and resend the remaining data after getting a <code>SerialTimeoutException</code>. 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.
If you <code>write</code> a larger block, e.g. 10kB at 115200 baud, it will take roughly 1 second. USB packets are typically 64 byte long and <code>bulkTransfer</code> aborts after the <code>write</code> timeout is reached, so with 500 msec timeout roughly 5kB are written, but <code>bulkTransfer</code> returns -1 instead of the written size, so there is no chance to resume writing.
If you <code>read</code> with very short timeout, e.g. 10 msec, the actual USB transfer might already be finished, but some upper Android layer checks the timeout and discards the already read data. ''This data is lost!''
Android is not a realtime OS, e.g. garbage collection can easily take 100 msec. Android is not a realtime OS, e.g. garbage collection can easily take 100 msec.