From b36d2dba48d8500c80a89258ed662c2047d32d64 Mon Sep 17 00:00:00 2001 From: kai-morich Date: Mon, 26 Apr 2021 09:17:19 +0200 Subject: [PATCH] more buffer size info --- FAQ.mediawiki | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/FAQ.mediawiki b/FAQ.mediawiki index 02fb3cc..37449a6 100644 --- a/FAQ.mediawiki +++ b/FAQ.mediawiki @@ -25,7 +25,7 @@ A common issue is wrong baud rate. == Baud rate 12345 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 if (Serial) 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 /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. +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? == @@ -43,10 +43,9 @@ You don't. /dev/tty* 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. * 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. -* When using SerialInputOutputManager, each has to run in it's own Executor. * Distinguishing identical devices has some challenges: -** Use devices with different VIDs/PIDs or where they can be programmed like FTDI or CP210x . -** Use UsbDevice.getSerialNumber() and devices that come with a unique serial or 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. +** 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? == @@ -76,31 +75,26 @@ Data loss can also occur with inappropriate buffer size, as shown in next Questi == How to size the read 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 port.getReadEndpoint().getMaxPacketSize(), 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, 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 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. -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]. - -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. +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]. +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? == -You should avoid too short timeouts, as they can cause data loss! +read timeout should not be shorter then 200 to 500 milliseconds, if possible use infinite timeout. -* write timeout should be significantly larger than the required send time -* 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 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. -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. -'''Background:''' - -If you write a larger block, e.g. 10kB at 115200 baud, it will take roughly 1 second. USB packets are typically 64 byte long and bulkTransfer aborts after the write timeout is reached, so with 500 msec timeout roughly 5kB are written, but bulkTransfer returns -1 instead of the written size, so there is no chance to resume writing. - -If you read 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!'' +* 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.