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 aboce but adds the required flag for Pending Intents when targeting SDK 31+.
 

Attachments

  • UsbSerial2.3.zip
    99.2 KB · Views: 5,995
  • UsbSerial2.5.zip
    36.3 KB · Views: 611
Last edited:

Scantech

Well-Known Member
Licensed User
Longtime User
Wow, Thank you Agraham.

This widens my option to play around with 9600 Baud even parity. I will give it shot. The other serial library did work with my Vag KKL but cannot change parity.
 

skywalker34

Member
Licensed User
Longtime User
Hi Agraham,

In the description you said it is now compatible with silicon lab CP120x
isn't it better CP 210x serie you mean?

Rgds

Sky
 

skywalker34

Member
Licensed User
Longtime User
I try you sample code and replace "abcde" by "1" to test the firmware "Android-Arduino_Blink"

I saw the rx led on the UNO board blinking but this did'nt light on the led (pin13)

this mean that the UNO did receive something (rx blinking) for is not understand as char==49 ( ascii code for "1" in dec)

As we use serial I can't easily see what is received by the UNO board...any idea ? maybe coding UTF8 ?
 

agraham

Expert
Licensed User
Longtime User
As you can see the demo writes and reads bytes as UTF8 codes.
B4X:
Sub btnSend_Click
   astreams.Write("abcde".GetBytes("UTF8"))
End Sub
So if you substituted "1" for "abcde" I would have expected you to get 49 at the Arduino.

You can always send the bytes directly.to send a "1" as a character you would use.
B4X:
Sub btnSend_Click
   astreams.Write(Array As Byte( 49))
End Sub
Have you tried echoing back what you receive and seeing what the log shows and are you sure you got the baud rates matching? I've tested this library on my Arduino ADK through both the slave port (Atmel CDC ACM) and host port in ADK mode so I know those work with the new library, and user yog3xx is using it with an FTDI based device of some sort so it should work with those Arduinos with an FTDI slave port.

The sketch I use on the Arduino is dead simple. Try it with the original demo code.
B4X:
void setup() 
{ 
  Serial.begin(115200);
} 

void loop() 
{ 
  byte msg[64]; 
  int len;
  len = Serial.available();
  if (len > 0)
  {
    len = Serial.readBytes((char*)msg, sizeof(msg)); // readBytes seems to need a char* not a byte*
    Serial.write(msg, len);
  }
}
 
Last edited:

skywalker34

Member
Licensed User
Longtime User
I try to replace "utf8" by "ISO-8859-1" but result look same
So I place LCD and print received message on the LCD
if I send something using the "serial monitor apk" I found on play store and this print the correct code to LCD : A=>A on LCD and 1=>1 on LCD

if I use your sample code this give me dark block....:confused:

I change back to UTF8 coding......same result :confused:

I don't have the idea to send it back trough serial port and take time to wire the LCD, it was a good idea, I will try this way too
 

Scantech

Well-Known Member
Licensed User
Longtime User
The library connects fine to FTD, however no success in response from a microcontroller.

This USB Device I am using is Vag KKL. It is a interface for the Engine Controller. Requires 9600,e,8,1 which communicated fine and the Controller responded with vb6 Mscomm. In Android, I can see the echo bytes returned, but no data from Engine Controller. This particular Engine Controller requires inner byte delay with minimum 2ms.

Here is my Settings

B4X:
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")
      Return
   End If
   Log("Checking permission")
   If (usb.HasPermission) Then
      Msgbox(usb.DeviceInfo, "Device Information")
      Dim dev As Int

      dev = usb.Open(9600)      
      If dev <> usb.USB_NONE Then
         Log("Connected successfully!")
         btnOpen.Enabled = False
         btnClose.Enabled = True
         btnSend.Enabled = True         
         astreams.Initialize(usb.GetInputStream, usb.GetOutputStream, "astreams")
         usb.SetParameters(9600, usb.DATABITS_8, usb.STOPBITS_1, usb.PARITY_EVEN)

      Else
         Log("Error opening USB port")
      End If
   Else
      usb.RequestPermission
   End If
End Sub

Here is how I send the data

B4X:
Sub btnSend_Click
   'astreams.Write("abcde".GetBytes("UTF8"))
   Dim Data, Temp As String: Data = spnCommand.GetItem(spnCommand.SelectedIndex)
   
      
   Dim x As Int
   For x = 0 To Data.Length Step 2
      If x = Data.Length Then Exit
      Temp = Data.SubString2(x, x + 2)
      Log(Temp)
      astreams.Write(Temp.GetBytes("UTF8"))
      tr.Sleep(5)
   Next
End Sub

Only Echo bytes returned. No Data from ECM. Anyone can confirm the SetParameters function is working properly? Perhaps Parity problems?

Thank you

UPDATE: It works fine. I was not sending the bytes correctly. Should not be using UTF8.
 
Last edited:

skywalker34

Member
Licensed User
Longtime User
Agraham,

Sorry, I must go to bed and have a long rest......:sign0137:
it was the usb speed....you set it a 115kb all examples and the arduino code was at 9600 baud !

So this is working GREAT !!!!!:sign0060::sign0060::sign0060:

I will investigate your lib further more but this sound really great
 

Scantech

Well-Known Member
Licensed User
Longtime User
It seems to have few unwanted extra bytes slipping through. I am still investigating the matter. Anyone have any ideas how the ffffff is slipping by?? look at the log below. The Engine controller shows 0x2e = length byte which is 46 data bytes. it shows 52 with 6 bytes slipping in.


This is how I decode the incoming data to a viewable hex format

B4X:
Sub Astreams_NewData (Buffer() As Byte)
   Dim temp As String
      
   Dim y As Int
   For y = 0 To Buffer.Length -1
      temp = Buffer(y)
      temp = Bit.ToHexString(temp)
      If temp.Length = 1 Then temp = "0" & temp
      temp = temp.ToUpperCase
      Log("RECEIVE: " & temp)
      txtLog.Text = txtLog.Text & temp
   Next

End Sub


This is how I send the data

B4X:
Sub btnSend_Click
   txtLog.Text = txtLog.Text & Chr(10)
   'DataResult = ""

   Dim Data As String: Data = spnCommand.GetItem(spnCommand.SelectedIndex)
   Data = "12040016"
   Dim len As Int: len = Data.Length /2
   Log("LEN = " & len)
   Dim b(len) As Byte
   
   'GET THE DATA FROM SPINNER AND PARSE IT TO INT
   Dim x, y As Int
   y = 0
   Dim temp As String
   For x = 0 To Data.Length Step 2
      If x = Data.Length Then Exit
      temp = Data.SubString2(x, x+2)
      Log("TEMP: " & temp)
      b(y) = Bit.ParseInt(temp, 16)
      Log("PARSE: " & b(y))
      y = y + 1
   Next 
   
   
   Dim DataByte(1) As Byte
   For x = 0 To b.Length -1
      Log("SEND: " & b(x))
      DataByte(0) = b(x)
      astreams.Write(DataByte)
      tr.Sleep(5)
   Next
End Sub


Check the Log. ffffffa0 ??? should be A0 only and ffffff9f should be 9f only

B4X:
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
** Activity (main) Resume **
Checking permission
Connected successfully!
LEN = 4
TEMP: 12
PARSE: 18
TEMP: 04
PARSE: 4
TEMP: 00
PARSE: 0
TEMP: 16
PARSE: 22
SEND: 18
SEND: 4
SEND: 0
SEND: 22
RECEIVE: 12
RECEIVE: 04
RECEIVE: 00
RECEIVE: 16
RECEIVE: 12
RECEIVE: 2e
RECEIVE: ffffffa0
RECEIVE: 31
RECEIVE: 34
RECEIVE: 33
RECEIVE: 37
RECEIVE: 38
RECEIVE: 30
RECEIVE: 34
RECEIVE: 31
RECEIVE: 31
RECEIVE: 30
RECEIVE: 31
RECEIVE: 38
RECEIVE: 30
RECEIVE: 32
RECEIVE: 31
RECEIVE: 32
RECEIVE: 37
RECEIVE: 39
RECEIVE: 38
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 31
RECEIVE: 31
RECEIVE: 35
RECEIVE: 38
RECEIVE: 35
RECEIVE: 32
RECEIVE: 38
RECEIVE: 35
RECEIVE: 30
RECEIVE: 30
RECEIVE: 39
RECEIVE: 38
RECEIVE: 32
RECEIVE: 37
RECEIVE: 34
RECEIVE: 33
RECEIVE: 39
RECEIVE: 34
RECEIVE: 39
RECEIVE: ffffff9f
LEN = 4
TEMP: 12
PARSE: 18
TEMP: 04
PARSE: 4
TEMP: 00
PARSE: 0
TEMP: 16
PARSE: 22
SEND: 18
SEND: 4
SEND: 0
SEND: 22
RECEIVE: 12
RECEIVE: 04
RECEIVE: 00
RECEIVE: 16
RECEIVE: 12
RECEIVE: 2e
RECEIVE: ffffffa0
RECEIVE: 31
RECEIVE: 34
RECEIVE: 33
RECEIVE: 37
RECEIVE: 38
RECEIVE: 30
RECEIVE: 34
RECEIVE: 31
RECEIVE: 31
RECEIVE: 30
RECEIVE: 31
RECEIVE: 38
RECEIVE: 30
RECEIVE: 32
RECEIVE: 31
RECEIVE: 32
RECEIVE: 37
RECEIVE: 39
RECEIVE: 38
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 31
RECEIVE: 31
RECEIVE: 35
RECEIVE: 38
RECEIVE: 35
RECEIVE: 32
RECEIVE: 38
RECEIVE: 35
RECEIVE: 30
RECEIVE: 30
RECEIVE: 39
RECEIVE: 38
RECEIVE: 32
RECEIVE: 37
RECEIVE: 34
RECEIVE: 33
RECEIVE: 39
RECEIVE: 34
RECEIVE: 39
RECEIVE: ffffff9f
LEN = 4
TEMP: 12
PARSE: 18
TEMP: 04
PARSE: 4
TEMP: 00
PARSE: 0
TEMP: 16
PARSE: 22
SEND: 18
SEND: 4
SEND: 0
SEND: 22
RECEIVE: 12
RECEIVE: 04
RECEIVE: 00
RECEIVE: 16
RECEIVE: 12
RECEIVE: 2e
RECEIVE: ffffffa0
RECEIVE: 31
RECEIVE: 34
RECEIVE: 33
RECEIVE: 37
RECEIVE: 38
RECEIVE: 30
RECEIVE: 34
RECEIVE: 31
RECEIVE: 31
RECEIVE: 30
RECEIVE: 31
RECEIVE: 38
RECEIVE: 30
RECEIVE: 32
RECEIVE: 31
RECEIVE: 32
RECEIVE: 37
RECEIVE: 39
RECEIVE: 38
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 31
RECEIVE: 31
RECEIVE: 35
RECEIVE: 38
RECEIVE: 35
RECEIVE: 32
RECEIVE: 38
RECEIVE: 35
RECEIVE: 30
RECEIVE: 30
RECEIVE: 39
RECEIVE: 38
RECEIVE: 32
RECEIVE: 37
RECEIVE: 34
RECEIVE: 33
RECEIVE: 39
RECEIVE: 34
RECEIVE: 39
RECEIVE: ffffff9f
LEN = 4
TEMP: 12
PARSE: 18
TEMP: 04
PARSE: 4
TEMP: 00
PARSE: 0
TEMP: 16
PARSE: 22
SEND: 18
SEND: 4
SEND: 0
SEND: 22
RECEIVE: 12
RECEIVE: 04
RECEIVE: 00
RECEIVE: 16
RECEIVE: 12
RECEIVE: 2e
RECEIVE: ffffffa0
RECEIVE: 31
RECEIVE: 34
RECEIVE: 33
RECEIVE: 37
RECEIVE: 38
RECEIVE: 30
RECEIVE: 34
RECEIVE: 31
RECEIVE: 31
RECEIVE: 30
RECEIVE: 31
RECEIVE: 38
RECEIVE: 30
RECEIVE: 32
RECEIVE: 31
RECEIVE: 32
RECEIVE: 37
RECEIVE: 39
RECEIVE: 38
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 31
RECEIVE: 31
RECEIVE: 35
RECEIVE: 38
RECEIVE: 35
RECEIVE: 32
RECEIVE: 38
RECEIVE: 35
RECEIVE: 30
RECEIVE: 30
RECEIVE: 39
RECEIVE: 38
RECEIVE: 32
RECEIVE: 37
RECEIVE: 34
RECEIVE: 33
RECEIVE: 39
RECEIVE: 34
RECEIVE: 39
RECEIVE: ffffff9f
LEN = 4
TEMP: 12
PARSE: 18
TEMP: 04
PARSE: 4
TEMP: 00
PARSE: 0
TEMP: 16
PARSE: 22
SEND: 18
SEND: 4
SEND: 0
SEND: 22
RECEIVE: 12
RECEIVE: 04
RECEIVE: 00
RECEIVE: 16
RECEIVE: 12
RECEIVE: 2e
RECEIVE: ffffffa0
RECEIVE: 31
RECEIVE: 34
RECEIVE: 33
RECEIVE: 37
RECEIVE: 38
RECEIVE: 30
RECEIVE: 34
RECEIVE: 31
RECEIVE: 31
RECEIVE: 30
RECEIVE: 31
RECEIVE: 38
RECEIVE: 30
RECEIVE: 32
RECEIVE: 31
RECEIVE: 32
RECEIVE: 37
RECEIVE: 39
RECEIVE: 38
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 30
RECEIVE: 31
RECEIVE: 31
RECEIVE: 35
RECEIVE: 38
RECEIVE: 35
RECEIVE: 32
RECEIVE: 38
RECEIVE: 35
RECEIVE: 30
RECEIVE: 30
RECEIVE: 39
RECEIVE: 38
RECEIVE: 32
RECEIVE: 37
RECEIVE: 34
RECEIVE: 33
RECEIVE: 39
RECEIVE: 34
RECEIVE: 39
RECEIVE: ffffff9f
Error: (IOException) java.io.IOException: Expected at least 2 bytes
** Activity (main) Pause, UserClosed = false **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = true **
Connected to B4A-Bridge (Wifi)
sending message to waiting queue (CallSubDelayed - UpdateStatus)
Ignoring event (too many queued events: CallSubDelayed - UpdateStatus)

Update: I believe it is parse error and have something to do with byte. Above 0x80 is reported as negative value in java if I am correct
 
Last edited:

agraham

Expert
Licensed User
Longtime User
. Above 0x80 is reported as negative value in java if I am correct
Yes. Bytes are regarded as signed in Java so get sign extended when cast to a wider type like Int. You can mask the result with Bit.And. Try
B4X:
 b(y) = Bit.ParseInt(Bit.And(temp, 255), 16)
 

agraham

Expert
Licensed User
Longtime User
Version 2.2 now posted adds the SetCustomDevice method.

There are four individual USB drivers in the library and it recognises which driver to use for a device by looking in a list of VendorID and ProductID pairs. This list is part of the source code and so is compiled into the library. However it is possible that a device might be known to be compatible with one of the drivers but will not be recognised as it is not in the list. This is especially likely for ADC ACM (Communications Device Class Abstract Control Model) devices which implement a vendor-independent publicly documented protocol. Some Arduino and Roboclaw devices implement this protocol and are known to the library but other devices that might also implement ADC ACM will not be recognised even though they may be compatible.

SetCustomDevice allows you to specify which driver a device unknown to the library might support and its VendorID and ProductID so allowing the device to be recognised by the library. Note that this does not guarantee that the device will work correctly as it must exactly implement what the specified driver expects.
 
Last edited:

michw

Member
Licensed User
Longtime User
USB to AVR UART

hi guys!
Is the library USBSerial2.2 and cable PL2303 will allow me to connect to the AVR microcontroller UART?
I have a tablet GO CLEVER TAB A73 Android 4.0.4 and after installation of the program from this post on and connected PL2303 get the message "No USB device or accessory detected."
Do I need ROOT on my tablet?
I need a solution that will allow you to transfer data between the tablet and the AVR.
Please help!

greetings!
Michal
 

Quaki

Member
Licensed User
Longtime User
michw to determine is your goclever capable of working with this library go to the google market and install "usb host diagnostics".
If it will show you that the otg host works fine and your golcvere dont recognize the serial chip then you will probably have to try the solution mentioned in here
http://www.b4x.com/forum/additional...03-usb-rs232-adaptor-driver-5.html#post120979
everything depends on your ROM and the configuration of your Goclever
I have done this on my GC A93 and it work with FT232 but :(
I have got problem with this library it snends data to AVR it recives data from AVR but the recived data are choped and the worst thing is that they are choped randomly, usualy there are two parts with difrent part of the sended string, some times the string is sended as a full mesage.
I have tried everything from althering the usbtime (cannot set lower then 30ms), to change the method of sending from avr (I use the hardware UART) but the results are the same. In the BT_serial library it looked the same way until, I canged the async to the ordinary serial method without async. Now it work fine under the BT so I presume the the problem is between AVR and the async method.
Best regards
 
Last edited:

agraham

Expert
Licensed User
Longtime User

Scantech

Well-Known Member
Licensed User
Longtime User
What is minimum API for this library?

I wanted to see what happens if I start usb with older api (OS 2.3.6).

Is there any way to trap the error and prevent the app from force close everytime you click open on older device?

B4X:
java.lang.NoSuchMethodError: android.hardware.usb.UsbManager.getDeviceList
   at anywheresoftware.b4a.objects.UsbSerial.UsbPresent(UsbSerial.java:341)
   at scantech.bmcom.main._btnopen_click(main.java:521)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:507)
   at anywheresoftware.b4a.BA.raiseEvent2(BA.java:167)
   at anywheresoftware.b4a.BA.raiseEvent2(BA.java:155)
   at anywheresoftware.b4a.BA.raiseEvent(BA.java:151)
   at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:59)
   at android.view.View.performClick(View.java:2538)
   at android.view.View$PerformClick.run(View.java:9152)
   at android.os.Handler.handleCallback(Handler.java:587)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:130)
   at android.app.ActivityThread.main(ActivityThread.java:3691)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:507)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
   at dalvik.system.NativeStart.main(Native Method)
 
Top