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:

bielec

Member
Licensed User
Longtime User
I have tried the examples in both USB library 1 and 2 but I get an error at compiling....

Compiling code. Error
Unable to read beyond the end of the stream.

I am using B4A v.1.70. Is this compatible?
 
Last edited:

ChanduPatil

New Member
Licensed User
Longtime User
Great work. I am starting to develop using B4A and your library is invaluable for connecting to my custom medical device. The device has been around a while, so the electronics includes the SiLabs 2101 chip. You will be glad to hear that the library works fine with that at the baud rate of 460800.

The library works fine with a Nexus 7 tablet I have (Android 4.3). However, on the Samsung Galaxy S4 (Android 4.2.2) it does not work as expected. First it detects a USB device when none is connected and crashes on the line that shows the Device Info before or after connecting the device. I have reproduced the log below.

I have modified the Demo code to include setting of custom device and parameters and send a message to get the device Rev.

Any thoughts on what may be causing the failure on the Samsung Phone?

LogCat connected to: B4A-Bridge: samsung GT-I9505-357377053613098
--------- beginning of /dev/log/main
Connected to B4A-Bridge (Wifi)
sending message to waiting queue (CallSubDelayed - UpdateStatus)
(Intent) Intent { act=android.intent.action.MAIN flg=0x20000000 cmp=b4a.example1/.main }
no extras
Error starting intent: (Intent) Intent { act=android.intent.action.MAIN flg=0x30000000 cmp=b4a.example1/.main }
Streams_terminated
sending message to waiting queue (CallSubDelayed - UpdateStatus)
Connected to B4A-Bridge (Wifi)
sending message to waiting queue (CallSubDelayed - UpdateStatus)
** Activity (main) Create, isFirst = false **
running waiting messages (10)
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = true **
Installing file.
PackageAdded: package:b4a.example1
(Intent) Intent { act=android.intent.action.MAIN flg=0x20000000 cmp=b4a.example1/.main }
no extras
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Checking permission
Error occurred on line: 43 (main) "Msgbox(usb.DeviceInfo, "Device Information")"
java.lang.NullPointerException
at anywheresoftware.b4a.objects.UsbSerial.DeviceInfo(UsbSerial.java:382)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:485)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:229)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:174)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:93)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:158)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:154)
at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:64)
at android.view.View.performClick(View.java:4354)
at android.view.View$PerformClick.run(View.java:17962)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5328)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
at dalvik.system.NativeStart.main(Native Method)
(Intent) Intent { act=android.intent.action.MAIN flg=0x20000000 cmp=b4a.example1/.main }
no extras
 

ChanduPatil

New Member
Licensed User
Longtime User
Hi Erel, Downloaded the App and when I ran that, it downloaded some further data and now shows two devices when the device is connected to the galaxy 4. The information shown by the app for the second usb device is as follows. I tried the USB Serial demo again and it still crashes as in post #122:
Device Info
Device Path: /dev/bus/usb/002/002
Device Class: Use class information in the Interface Descriptors (0x0)
Vendor ID: 10c4
Vendor Name: Cygnal Integrated Products, Inc.
Product ID: 07d2
Product Name: not in db

Interfaces
Interface #0
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 3 (000000011)
Number : 3
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 0
Max Packet Size: 64
Attributes : 000000010
Endpoint: #1
Address : 131 (10000011)
Number : 3
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 0
Max Packet Size: 64
Attributes : 000000010

The first device listed by the App is a qualcomm (also shown when the device is not connected to the USB port) is:
Device Info
Device Path: /dev/bus/usb/001/002
Device Class: Use class information in the Interface Descriptors (0x0)
Vendor ID: 05c6
Vendor Name: Qualcomm, Inc.
Product ID: 03ea
Product Name: not in db

Interfaces
Interface #0
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 129 (10000001)
Number : 1
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #1
Address : 1 (00000001)
Number : 1
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Interface #1
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 130 (10000010)
Number : 2
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #1
Address : 2 (000000010)
Number : 2
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Interface #2
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 131 (10000011)
Number : 3
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #1
Address : 3 (000000011)
Number : 3
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Interface #3
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 132 (10000100)
Number : 4
Direction : Inbound (0x80)
Type : Intrrupt (0x3)
Poll Interval : 5
Max Packet Size: 64
Attributes : 000000011
Endpoint: #1
Address : 133 (10000101)
Number : 5
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #2
Address : 4 (0000000100)
Number : 4
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Interface #4
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 134 (10000110)
Number : 6
Direction : Inbound (0x80)
Type : Intrrupt (0x3)
Poll Interval : 5
Max Packet Size: 64
Attributes : 000000011
Endpoint: #1
Address : 135 (10000111)
Number : 7
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #2
Address : 5 (0000000101)
Number : 5
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Interface #5
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 136 (10001000)
Number : 8
Direction : Inbound (0x80)
Type : Intrrupt (0x3)
Poll Interval : 5
Max Packet Size: 64
Attributes : 000000011
Endpoint: #1
Address : 137 (10001001)
Number : 9
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #2
Address : 6 (0000000110)
Number : 6
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Interface #6
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 138 (10001010)
Number : 10
Direction : Inbound (0x80)
Type : Intrrupt (0x3)
Poll Interval : 5
Max Packet Size: 64
Attributes : 000000011
Endpoint: #1
Address : 139 (10001011)
Number : 11
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #2
Address : 7 (0000000111)
Number : 7
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Interface #7
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 140 (10001100)
Number : 12
Direction : Inbound (0x80)
Type : Intrrupt (0x3)
Poll Interval : 5
Max Packet Size: 64
Attributes : 000000011
Endpoint: #1
Address : 141 (10001101)
Number : 13
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #2
Address : 8 (00000001000)
Number : 8
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Interface #8
Class: Vendor Specific (0xff)
Endpoint: #0
Address : 142 (10001110)
Number : 14
Direction : Inbound (0x80)
Type : Intrrupt (0x3)
Poll Interval : 5
Max Packet Size: 64
Attributes : 000000011
Endpoint: #1
Address : 143 (10001111)
Number : 15
Direction : Inbound (0x80)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
Endpoint: #2
Address : 9 (00000001001)
Number : 9
Direction : Outbound (0x0)
Type : Bulk (0x2)
Poll Interval : 32
Max Packet Size: 512
Attributes : 000000010
 

agraham

Expert
Licensed User
Longtime User
You will not be able to use the library with the Galaxy S4 without modifying the library. The library assumes that the first USB device it finds is a serial port which is usually a reasonable assumption as Android should only make USB devices visible to applications if they are not handled by Android itself. In this case it is making the Qualcomm, device, probably a Wifi adaptor, visible.

You could try the workaround that I suggested for the same problem in post #54 of this thread.
 

ChanduPatil

New Member
Licensed User
Longtime User
I have tried the workaround which did not work. I am not really up to the task of modifying the library not being familair with Java or the details of Android at this stage.
I presume there must be several phones with this behaviour, so the library that handles a serial device on second device path may be a useful addition. I am happy to donate for the additional effort if it is reasonable for a small start-up like me!
chandu@trillian-dx.com
 

sunish

Member
Licensed User
Longtime User
The library on which USBSerial 2 is based has the functionality of toggling the hardware control bits. How is it possible to control RTS with CP2102 based board ?
 

agraham

Expert
Licensed User
Longtime User
It's not possible. The library implements a set of functionality common to all the included drivers. As not all the drivers can toggle the control bits the functionality is not implemented. The Java sources are in the archive if you want to make a custom library.
 

ernschd

Active Member
Licensed User
Longtime User
Hi,
I have a FTDI FT232 Device which is sending continuously data.
It's recognized by your library, but i don't receive any data - the Astreams_NewData event is never raised.
The usb.SetParameters() method is called after usb.Open(). Is it possible to see whether any data communication happens?

Thank you.
B4X:
Sub btnOpen_Click
   If usb.UsbPresent = usb.USB_NONE Then   
     Msgbox("No USB device or accessory detected!", "Error")
     Return
   End If

   usb.SetCustomDevice(usb.DRIVER_FTDI, 0x403, 0x6001)   
   If (usb.HasPermission) Then   
     Msgbox(usb.DeviceInfo, "Device Information")   

     Dim dev As Int   
     dev = usb.Open(baud)   

     If dev <> usb.USB_NONE Then
       Log("Connected successfully!")
       btnOpen.Enabled  = False
       btnClose.Enabled  = True
       btnSend.Enabled  = True
       usb.SetParameters(baud, usb.DATABITS_8, usb.STOPBITS_1, usb.PARITY_NONE)   
       astreams.Initialize(usb.GetInputStream, usb.GetOutputStream, "astreams")   
     Else
       Log("Error opening USB port: " & dev)
     End If
   Else
     usb.RequestPermission
   End If
End Sub

Sub Astreams_NewData (Buffer() As Byte)
   Log("NewData")   
   Try
     Log("Receive " & BytesToString(Buffer, 0, Buffer.Length, "UTF8"))
   Catch
     Log("Error in NewData")
   End Try
End Sub
 

ernschd

Active Member
Licensed User
Longtime User
As i wrote the recognition of the device is not the problem, but the receiving of the data stream.
Beside that i already tried both values for FTDI.

The device info shows the correct device:
Manufacturer : FTD
Product : USB
Serial : not available

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
 

ernschd

Active Member
Licensed User
Longtime User
Ok, thanks.
I have a further question: when i connect to the device with 115200 baud, i see in the value list in the IDE the mBaudRate with the value 115385.
Is this value correct?
 

agraham

Expert
Licensed User
Longtime User
The "driver" field in USB is a private field. I don't know why it is displayed in Debug mode. As mainly a library writer, I never use Debug mode in the IDE so I have never noticed this. I assume that it is intentional on Erel's part that private fields are shown. What is in that window under "driver" is internal to the driver that the library has selected to use for the connected chip.

I didn't write the FTFDI driver but looking at the source it seems that mBaudRate contains the actual hardware baud rate that is the closest to the requested baud rate that the frequency divider chain in the FTDI chip can mange. In this case it is 0.16% out which is utterly trivial for a UART. A straightforward design should be able to continously sync with, and successfully retrieve data from, baud rates that are up to 5% in error
 
Last edited:

ernschd

Active Member
Licensed User
Longtime User
Now it works!
I have to use the AsyncSteamsText because the received text has end of line characters.

Thank you for your effort.
 

mrodriguez

Member
Licensed User
Longtime User
Hi, I'm having a problem with this library. It works ok at the begining, but over a time the incomming data take more time to fire the event. At the begining the event fires inmediatly, but 3 hours later it has a delay of 2 or 3 seconds. 10 hours later it take 4 or 5 seconds (delay) and eventually crash.
I have done the same test with the native library with the "S2 Terminal for FT232 Free App" and it works perfect over the time. No delay neither crash. Test ok with https://play.google.com/store/apps/details?id=com.s2jp.apps.ftterm&hl=es

Any idea?
Thanks
PD.: I'm using FTDI library to send/recieve commads/signals to/from the Xbee (from Digi)
 
Top