B4A Library UsbSerial library 2.0 - supports more devices

This is an expanded version of the original UsbSerial library. It has added support for Prolific PL2303 USB to serial converters, Android ADK devices and USB permissions. All devices use the same simple interface intended to be used with AsyncStreams and AsyncStreamsText. Note that AsyncStreams prefix mode is not supported. The library is based on the same open source project Android USB host serial driver library as the existing UsbSerial library but no longer needs a separate jar file as the project source code is incorporated in the library.

The specific enhancements to the library over the original UsbSerial library are :

UsbPresent, HasPermission and RequestPermission are added to identify any attached device or Accessory available to the library and deal with permission to access it.

SetParameters, which must be used after Open(), and the constants for SetParameters provides acess to all the serial line parameters instead of just baud rate.

DeviceInfo provides a string containing information about a device. This works for slave devices only.

Android Accessories, which are host mode devices, are recognised and can be used in the same way as the other slave mode devices.

Prolific PL2303 support is added.

Silicon Labs CP210x support is added - maybe only the CP2102 as I have no hardware to test.

The FTDI "status byte" bug on reading input that existed in version 1.0 of this library is hopefully fixed.


The usb-serial-for-android project and therefore also this library is licensed under the GNU Lesser General Public License v3. http://www.gnu.org/licenses/lgpl.html|http://www.gnu.org/licenses/lgpl.html
Copies of both the General Public License and Lesser General Public License are in the provided archive.

The user has to give your application permission to access the USB device before it can be opened. You can do this in two ways.

As with the original UsbSerial library you can add the following code to the manifest editor

B4X:
AddActivityText(main, <intent-filter>
        <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
    </intent-filter>
    <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
        android:resource="@xml/device_filter" />)
Then copy device_filter.xml from the demo in the attached archive to: <your project>\objects\res\xml and mark it as read-only. Note that this is an expanded version of the original device_filter.xml file.

Finally install the program and attach the USB device. A dialog will appear asking whether you want to start your program. If you check the “Use by default…” checkbox from now on when the USB device is plugged in your program will be started. If you don’t check the checkbox then you will be asked each time the device is plugged in.

A similar procedure can be used for Accessories as detailed in the “Using an intent filter” section here USB Accessory | Android Developers


Alternatively you can use the new HasPermission and RequestPermission methods without requiring any of the above steps. The demo in the archive incorporates both ways of obtaining permission.

EDIT:- Version 2.1 now posted. See post #4 for details

EDIT:- Version 2.2 now posted. See post #14 for details

EDIT:- Version 2.3 now posted. See post #26 for details

V2.4 is available here: http://www.b4x.com/android/forum/th...pports-more-devices.28176/page-11#post-259167
This update adds support for devices connected to multiple USB adapters.


V2.5 is available as an attachment to this post. It is identical to version 2.4 referenced above but adds the required flag for Pending Intents when targeting SDK 31+.

V2.6 is available as an attachment to this post. It is identical to version 2.5 referenced above but adds the required flag for Pending Intents when targeting SDK 34+.
 

Attachments

  • UsbSerial2.3.zip
    99.2 KB · Views: 6,273
  • UsbSerial2.5.zip
    36.3 KB · Views: 953
  • UsbSerial2.6.zip
    36.3 KB · Views: 101
Last edited:

Fabrice La

Active Member
Licensed User
Longtime User
I use the cp2102 and I ahave reply form the USBSerial example:



I am not a C programmer but I can connect to it :
Sub btnOpen_Click
If usb.UsbPresent = usb.USB_NONE Then
Log("Msgbox - no device")
Msgbox("No USB device or accessory detected!", "Error")
Log("Msgbox - returned")'!%µM
Return
End If
Log("Checking permission")
If (usb.HasPermission) Then
Msgbox(usb.DeviceInfo, "Device Information")
Dim dev As Int
dev = usb.Open(115200)
If dev <> usb.USB_NONE Then
Log("Connected successfully!")
usb.SetParameters(9600, usb.DATABITS_8, usb.STOPBITS_1, usb.PARITY_NONE)
usb.UsbTimeout = 1000
Msgbox("Device connected","test")
btnOpen.Enabled = False
btnClose.Enabled = True
btnSend.Enabled = True
astreams.Initialize(usb.GetInputStream , usb.GetOutputStream, "astreams")
Else
Log("Error opening USB port")
End If
Else
usb.RequestPermission
End If
End Sub

The SetParameters and UsbTimeout come from the C program :

dc_status_t
fabric_clow_device_open (dc_device_t **out, dc_context_t *context, const char *name)
{
if (out == NULL)
return DC_STATUS_INVALIDARGS;

// Allocate memory.
fabric_clow_device_t *device = (fabric_clow_device_t *) malloc (sizeof (fabric_clow_device_t));
if (device == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
}

// Initialize the base class.
device_init (&device->base, context, &fabric_clow_device_vtable);

// Set the default values.
device->port = NULL;
memset (device->fingerprint, 0, sizeof (device->fingerprint));

// Open the device.
int rc = serial_open (&device->port, context, name);
if (rc == -1) {
ERROR (context, "Failed to open the serial port.");
free (device);
return DC_STATUS_IO;
}

// Set the serial communication protocol (9600 8N1).
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE);
if (rc == -1) {
ERROR (context, "Failed to set the terminal attributes.");
serial_close (device->port);
free (device);
return DC_STATUS_IO;
}

// Set the timeout for receiving data (1000 ms).
if (serial_set_timeout (device->port, 1000) == -1) {
ERROR (context, "Failed to set the timeout.");
serial_close (device->port);
free (device);
return DC_STATUS_IO;
}

// Set the DTR/RTS lines.
if (serial_set_dtr (device->port, 1) == -1 ||
serial_set_rts (device->port, 1) == -1) {
ERROR (context, "Failed to set the DTR/RTS line.");
serial_close (device->port);
free (device);
return DC_STATUS_IO;
}

I read that you can't parameters the DTR/RTS ...

My problem is I don't know what to send to be able to receive data (Attach the C program)
 

Attachments

  • fabric_clow.c.txt
    8.9 KB · Views: 304

agraham

Expert
Licensed User
Longtime User
1) No, you can't set DTR/RTS though it is possible you could hardwire them at the device if it needs them asserted.

2) The UsbTimeout has nothing to do with the timeout in that code. Leave UsbTimeout as the default.

3) I don't know what the device is, possibly a fingerprint or other biometric reader? To use it successfully you need more information than what is in the C code as that is just a low- level driver - and it looks like it is not complete.
 

Fabrice La

Active Member
Licensed User
Longtime User
The device is computer where data are strored.
I have to send init to be able to have the data.
The problem is I can't figure out what I have to send using astreams.Write

I am not C programmer and the only doc I have is the c program.

Attached the other C.

Extrait :
fabric_common_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size)
{
fabric_common_device_t *device = (fabric_common_device_t*) abstract;

unsigned int nbytes = 0;
while (nbytes < size) {
// Calculate the packet size.
unsigned int len = size - nbytes;
if (len > PACKETSIZE)
len = PACKETSIZE;

// Build the raw command.
unsigned char raw[] = {0x51,
(address ) & 0xFF, // Low
(address >> 8) & 0xFF, // High
len}; // Count

// Build the ascii command.
unsigned char command[2 * (sizeof (raw) + 2)] = {0};
fabric_common_make_ascii (raw, sizeof (raw), command, sizeof (command));

// Send the command and receive the answer.
unsigned char answer[2 * (PACKETSIZE + 2)] = {0};
dc_status_t rc = fabric_common_transfer (device, command, sizeof (command), answer, 2 * (len + 2));
if (rc != DC_STATUS_SUCCESS)
return rc;

// Extract the raw data from the packet.
array_convert_hex2bin (answer + 1, 2 * len, data, len);

nbytes += len;
address += len;
data += len;
}

return DC_STATUS_SUCCESS;
}
 

Attachments

  • fabric_common.c.txt
    10.1 KB · Views: 321

agraham

Expert
Licensed User
Longtime User
I'm afraid you are on your own here. It would take hours to try to go through that code to try and understand it and replicate it in B4A. Also you would need to know the meaning of some of the parameters to some of the functions, like "address" in "fabric_common_device_read".
 

krokiz

Member
Licensed User
Longtime User
I am in need to acquire a continuous stream of byte data from an Serial Device (that I made myself, although AVR MCU based,
Using a FTDI chip in between the Android Tablet and the Device)
The application should continuously receive bytes in range 0x00 to 0xF9, 0xFA is acting as a EOL mark, and draw graphics according to this data.
The issue is the following:
Since the device is sending bytes (data) continuously and might have been turned on prior the connecting to the Tablet,
after the App connects to the external device (by plugging in the micro-B USB cable), The program (UsbSerialDemo) starts, I use the Start Button, the Stop and Send buttons become enabled and then it all goes immediately to the astreams_Error subroutine and displays the following error message:
(IOException) java.io.IOException: Expected at least 2 bytes
My question is: is there a workaround in order to solve this problem and achieve my goal:
Reading the Serial data without ending up in this exception (only) indicating Subroutine (AStreams_Error) ?
(Since I am a newbie in Android and BasicForAndroid, my wildguess is that AsyncStreams are using UTF8 and it expects 2 bytes for each character/byte (of the stream received)

There is an aside question: How could one ignore/process such an exception, since Try..Catch..End Try does not apply here (the exception raises for its reasons, and I cannot trap it) ?


I hope someone could help me out (pray)
 

agraham

Expert
Licensed User
Longtime User
Which FTDI chip are you using? It looks to me as though that chip is not compatible with the driver in the library. Either it is not sending the expected two status bytes at the start of the data packet or the endpoints are reversed from what is expected.
 

krokiz

Member
Licensed User
Longtime User
Which FTDI chip are you using? It looks to me as though that chip is not compatible with the driver in the library. Either it is not sending the expected two status bytes at the start of the data packet or the endpoints are reversed from what is expected.

When the external hardware is connected to the Android tablet, and the program connects with it, the application shows that the Manifacturer of the chip is EAS (I was expecting to see FTDI ?) I know that I am using FT232RL (I see it on the hardware's PCB) and it is working great when the device communicates with a PC (I am using my own PC (Delphi) program to acquire the incoming data, Teraterm works great, too)
I think there is some encoding issue (UTF8 instead of ASCII ?), i.e., the Android/The application is expecting 2byte UTF8 encoding for each symbol, instead of 1-byte ASCII.

Do you want me to post you the full report of usb.DeviceInfo ?

Thanks for your quick respond, and I am sorry for my delay in posting this.

Edit:
Here is the full usb.DeviceInfo
Manifacurer : EAS
Product : EAS
Serial : not available

DeviceName :/dev/bus/usb/001/029
DeviceClass: USB_CLASS_PER_INTERFACE (per-interface basis)
DeviceSubClass : 0
Device ID : 0x405
ProductID : 0x6001
VendorId: 0x403

B4aInterfaceNumber : 0
InterfaceClass : USB_CLASS_VENDOR_SPEC (vendor specific)
InterfaceSubClass : 255
InterfaceProtocol : 255

EndpointNumber : 1
EndpointDirection : In
EndpointType : USB_ENDPOINT_XFER_BULK (bulk)
EndpointAttribute : 2
EndpointInterval : 0
EndpointMaxPacketSize : 64

EndpointNumber : 2
EndpointDirection : out
EndpointType : USB_ENDPOINT_XFER_BULK (bulk)
EndpointAttribute : 2
EndpointInterval : 0
EndpointMaxPacketSize : 64


Edit: I did some tests on the Android tablet it the application claimed this is a PROLIFIC Chip, though I am having FT232RL on the PCB of the external device. Here is my code snippet that I use:
....
Dim devicename As String
....
devicename = "UNKNOWN"
If (usb.USB_DEVICE = usb.DRIVER_FTDI) Then devicename = "This is FTDI"
If (usb.USB_DEVICE = usb.DRIVER_CDCACM) Then devicename = "This is CDCACM"
If (usb.USB_DEVICE = usb.DRIVER_PROLIFIC) Then devicename = "This is PROLIFIC"
If (usb.USB_DEVICE = usb.DRIVER_SILABS) Then devicename = "This is SILABS"
Msgbox(devicename & " " & usb.DeviceInfo & " " , "Connection to COM Port: Connected successfuly on 115200 bps")
....
 
Last edited:

agraham

Expert
Licensed User
Longtime User
There is no encoding issue, AsyncStreams is byte oriented.

The Product and Vendor IDs show that this is an FTDI FT232 chip.

Your test code is wrong, it is just comparing constants with constants. usb.USB_DEVICE is a constant that is returned by UsbPresent and Open to indicate that a slave USB device is connected. It does not indicate the type of that device.

Every packet send by the FTDI chip is expected to be prefixed with 2 modem status bytes so the minimum packet size is expected to be at least two bytes. That error is thrown if a data packet contains less than two bytes. I am at a loss as to why that should be in your case. Other people are successfully using the library with FTDI chips.

In case it is a startup problem you can try calling AsyncStreams.Close when that error occurs and then reinitialising your AsyncStreams object.
 

krokiz

Member
Licensed User
Longtime User
I switched from FT232RL to CP2102 and I am no longer having this workstopping error ((IOException) java.io.IOException: Expected at least 2 bytes) !
Too bad I cannot say the same when I am using the FTDI chip. I am producing devices which are equipped with FTDI chips and I won't be able to use them with the Android app that I am creating, at least the sold ones will not work with the app. And this is too bad, because I want to impress/be helpful/give more flexibility/ with this app to my current clients (people who already bought devices) as well as the future ones :( :( Would you revise your thoughts about my problem?
Have you ever come across with this error before? ((IOException) java.io.IOException: Expected at least 2 bytes) what could be the reason of it? I found on Google nothing about this, except on your forum (), but it does not help me at all.
I hope you can help me.
 

agraham

Expert
Licensed User
Longtime User
I'm sorry but I have no idea why you should have this problem. Other people have successfully used this library with FTDI chips and no-one has reported this error before. The reason for the error appears to be, as I have already said above, that the minimum packet size should be two bytes that contain status. The FTDI documentation states this so I am baffled as why you, and only you, seem to be suffering this problem
 

clackl

New Member
Hi guys,

is it possible to download this new version of the library somewhere without shelving out 49 bucks for the development tool with i don't really need?

Many thanks to he who can help me out.

/Cheers
 

Stulish

Active Member
Licensed User
Longtime User
The Library is for B4A, if you don't need the development tool (B4A) then you shouldn't need the library????
 

Marcob

Member
Licensed User
Longtime User
Some issues related to FT232RL and FT230X

Hello, I'm testing the program UsbSerialDemo on a Zopo C2 smartphone with two types of FTDI USB adapters; one uses FT232RL and the other uses FT230X.

With FT232RL the Device Information shows:

B4X:
Manifacturer : FTD
Product : FT2
Serial : A1S

DeviceName :/dev/bus/usb/001/006
DeviceClass: USB_CLASS_PER_INTERFACE (per-interface basis)
DeviceSubClass : 0
Device ID : 0x3EE
ProductID : 0x6001
VendorId: 0x403

B4aInterfaceNumber : 0
InterfaceClass : USB_CLASS_VENDOR_SPEC (vendor specific)
InterfaceSubClass : 255
InterfaceProtocol : 255

EndpointNumber : 1
EndpointDirection : In
EndpointType : USB_ENDPOINT_XFER_BULK (bulk)
EndpointAttribute : 2
EndpointInterval : 0
EndpointMaxPacketSize : 64

EndpointNumber : 2
EndpointDirection : out
EndpointType : USB_ENDPOINT_XFER_BULK (bulk)
EndpointAttribute : 2
EndpointInterval : 0
EndpointMaxPacketSize : 64

With FT230X the Device Information shows:

B4X:
Manifacturer : FTD
Product : FT2
Serial : DA0

DeviceName :/dev/bus/usb/001/007
DeviceClass: USB_CLASS_PER_INTERFACE (per-interface basis)
DeviceSubClass : 0
Device ID : 0x3EF
ProductID : 0x6015
VendorId: 0x403

B4aInterfaceNumber : 0
InterfaceClass : USB_CLASS_VENDOR_SPEC (vendor specific)
InterfaceSubClass : 255
InterfaceProtocol : 255

EndpointNumber : 1
EndpointDirection : In
EndpointType : USB_ENDPOINT_XFER_BULK (bulk)
EndpointAttribute : 2
EndpointInterval : 0
EndpointMaxPacketSize : 64

EndpointNumber : 2
EndpointDirection : out
EndpointType : USB_ENDPOINT_XFER_BULK (bulk)
EndpointAttribute : 2
EndpointInterval : 0
EndpointMaxPacketSize : 64


The FT232RL works properly.
Unfortunately with FT230X the program shows the message:

"Error opening USB port"

Any ideas on how to make the FT230X working ?

Thanks in advance for the help that you can give me.

PS
I have added into the file device_filter.xml the following lines:

<!-- 0x0403 / 0x6015: FTDI FT230X UART -->
<usb-device vendor-id="1027" product-id="24597" />
 

agraham

Expert
Licensed User
Longtime User
The UsbSerial library doesn't know about the FT230X - and neither do I. I don't know if it is progam compatible with the FT232 or not. You could try
B4X:
Dim SerialLib as UsbSerial
...
SerialLib.SetCustomDevice(SerialLib.DRIVER_FTDI, 0x403, 0x6015)
Before trying to Open the device.
 

Marcob

Member
Licensed User
Longtime User
The UsbSerial library doesn't know about the FT230X - and neither do I. I don't know if it is progam compatible with the FT232 or not. You could try
B4X:
Dim SerialLib as UsbSerial
...
SerialLib.SetCustomDevice(SerialLib.DRIVER_FTDI, 0x403, 0x6015)
Before trying to Open the device.

Thank agraham for your prompt reply.
I tried your hint but it didn't work.

Perhaps I could modify some locations in the internal EEPROM of FT230X so that it looks like for android similar to a FT232RL...
I'm thinking to contact directly FTDI and ask them what is the difference between the two devices that could explain the malfunction and if there's a workaround, this could be interesting also for other developers.
Do you have any suggestions on technical details to give to FTDI support about the android interfacing side ?
 

jimTaylor

Member
Licensed User
Longtime User
Newbie question: How do you install and run usbSerial 2.3?

agraham,

I appreciate you providing this package, but I am at a complete loss as to how to make it work. I can download and extract, but from that point forward the instructions might as well have been written in Martian.

Can you provde a step-by-step that doesn't assume I know what I'm doing?

JimT
 

jimTaylor

Member
Licensed User
Longtime User
Clarification

I should have been clearer. I know how to do the serial thing on everything from micros to mainframes. What I can't do is make head or tail out of the install instructions for this software. Everyone else seems to have managed to get it running with great success. I can't even get it to a place where I can try to use it.
 
Top