Android Question Problem with embedded Serial Port (/dev/ttyMT2)

Mike1970

Well-Known Member
Licensed User
Longtime User
Hi all,
I'm experiencing a quite huge problem using the serial port of an Android 11 Panel PC. I've used the serial library at this post:
https://www.b4x.com/android/forum/threads/gpio-and-uart.100811/#post-634049

Before I've tried that library on an Android 10 Panel PC and it was working properly using the port /dev/ttyS0.

Now, I've tried to use on an Android 11 Panel, still a rooted device, on th port /dev/ttyMT2
What it does is simply... nothing.
But even this sentence... is not completely true.
I can initialize the "myUART" and the data come in only if I simultaneously open the demo application provided with the Panel that communicate with the RFID reader attached at that port, that opens the ttyMT2 port.
If I do not open that application, data are not coming in. No errors, but even no data.

This is the code:
B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Private btnSend As Button
    
    
    Private bc As ByteConverter
    Private mBytes() As Byte
    
    
    Dim myUART As UART
    Dim eventName As String = "myUART"
    Dim devPath As String = "/dev/ttyMT2"
    Dim baudeRate As Int = 9600
    Dim flags As Int = 0
    Dim bigEndian As Boolean = False
    Dim prefix As Boolean = False
    
    Dim lastCard_Data As String
    
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    DateTime.DateFormat = "dd/MM/yyyy"   
    DateTime.TimeFormat = "HH:mm:ss"
    
    Root = Root1
    Root.LoadLayout("MainPage")
    
    myUART.Initialize(eventName, devPath, baudeRate, flags, bigEndian, prefix)

End Sub


Private Sub myUART_NewData (data() As Byte) 'the incoming data
    'This events fire only if the provided demo application is already running.
    Dim bc As ByteConverter
    Dim dati As String
    dati = bc.HexFromBytes(data)
    Log("RX: " & dati)
    'TODO... decodeTheData(data)
End Sub

Private Sub SendDataBytes(data() As Byte) 'the outgoing data
    Dim bc As ByteConverter
    Log("TX: " & bc.HexFromBytes(data))
    myUART.Write(data)
End Sub

Private Sub myUART_Terminated
    Log("UART - Terminated")
    'TODO...
End Sub

Private Sub myUART_Error
    Log("UART - Error: " & LastException)
    'TODO...
End Sub
I guess because the demo application is REALLY able to open the ttyMT2 port and also my application can read the data flow when a Tag is on the reader.

I guess that because I've tried with the AsyncStreams using this code:
B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    Dim Result As Int ' used for shell
    Dim Ph As Phone ' used for shell
    Dim Arh() As String ' used for shell
    Dim StdOut, StdErr As StringBuilder ' used for shell
    
    Dim SerialPort As AsyncStreams
    Dim stream As String
    
    Dim rp As RuntimePermissions


End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
    
    rp.CheckAndRequest(rp.PERMISSION_READ_EXTERNAL_STORAGE)
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)

    stream = "/dev/ttyMT2"
    Dim fo As OutputStream
    Dim fi As InputStream
    fo = File.OpenOutput("",stream, True) '******** Crash here: java.io.FileNotFoundException: /dev/ttyMT2: open failed: EACCES (Permission denied)
    fi = File.OpenInput("",stream)
    SerialPort.Initialize(fi,fo,"astreams")
    'SerialPort.Initialize(fi,Null,"astreams")
    StdOut.Initialize ' initialize string builder for StdOut
    StdErr.Initialize ' initialize string builder for StdErr
    Result = Ph.Shell("stty -F " & stream & " 9600 cs8 -cstopb -parenb",Arh, StdOut, StdErr) ' set 9600,N,8,1
    Log("Result " & Result)
End Sub


Sub astreams_NewData (Buffer() As Byte)
    Dim curTime As String = $"[$datetime{DateTime.Now}]"$
    Log("{" & curTime & "}" & BytesToString(Buffer, 0, Buffer.Length, "UTF8"))

End Sub

So there is some kind of permission not allowed.
Even the second code, if I switch the code to:
B4X:
    stream = "/dev/ttyMT2"
    Dim fo As OutputStream
    Dim fi As InputStream
    'fo = File.OpenOutput("",stream, True) '******** No open, No crash but.... No open!
    fi = File.OpenInput("",stream)         'Still receive data if the demo application is running
    'SerialPort.Initialize(fi,fo,"astreams")
    SerialPort.Initialize(fi,Null,"astreams")
    StdOut.Initialize ' initialize string builder for StdOut
    StdErr.Initialize ' initialize string builder for StdErr
    Result = Ph.Shell("stty -F " & stream & " 9600 cs8 -cstopb -parenb",Arh, StdOut, StdErr) ' set 9600,N,8,1
    Log("Result " & Result)

then still receive the data if the other demo application is running.
So definitively the other application have the rights to open the port and so data come in also for my application.

The question is: how to get these permissions?
I've tried to add to the manifest:
B4X:
AddPermission(android.permission.SHUTDOWN)
AddPermission(android.permission.READ_EXTERNAL_STORAGE) ' Allows an application to read from external storage.
AddPermission(android.permission.WRITE_EXTERNAL_STORAGE) ' Allows an application to write to external storage.
AddPermission(android.permission.MANAGE_EXTERNAL_STORAGE) ' Allows an application to write to external storage.
AddPermission(android.permission.ACCESS_SUPERUSER)


SetActivityAttribute(main, android:windowSoftInputMode, adjustResize|stateHidden)
AddPermission(android.permission.ACCESS_FINE_LOCATION)
AddApplicationText(<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />)

CreateResourceFromFile(Macro, Core.NetworkClearText)


AddManifestText(
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"  android:maxSdkVersion="19" />
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_LOGS"/>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
)



'AddActivityText(main,
'<intent-filter>
'    <!-- <action android:name="android.intent.action.MAIN" />   -->
'    <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
'   
'    <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
'    <!-- <category android:name="android.intent.category.HOME" />     -->
'    <!-- <category android:name="android.intent.category.LAUNCHER" />  -->
'   
'</intent-filter>
'<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" />
')
    
        
CreateResource(xml, device_filter.xml,
<resources>
    <!-- 0x0403 / 0x6001: FTDI FT232R UART -->
    <!-- <usb-device vendor-id="1027" product-id="24577" /> -->

    <!-- 0x067b / 0x2303 Prolific PL2303 -->
    <usb-device vendor-id="1659" product-id="8963" />

    <!-- Your device PID/VID -->
    <!-- <usb-device vendor-id="YourVID" product-id="YourPID" /> -->

</resources>
)
SetActivityAttribute(main, android:directBootAware, "true")

This is the full stack error:
B4X:
Error occurred on line: 48 (B4XMainPage)
java.io.FileNotFoundException: /dev/ttyMT2: open failed: EACCES (Permission denied)
    at libcore.io.IoBridge.open(IoBridge.java:492)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
    at anywheresoftware.b4a.objects.streams.File.OpenOutput(File.java:449)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at anywheresoftware.b4a.debug.Debug.delegate(Debug.java:262)
    at b4a.example.b4xmainpage._b4xpage_created(b4xmainpage.java:84)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:318)
    at anywheresoftware.b4a.debug.Debug.CallSubNew2(Debug.java:285)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.keywords.Common.CallSubDebug2(Common.java:1087)
    at b4a.example.b4xpagesmanager._createpageifneeded(b4xpagesmanager.java:1068)
    at b4a.example.b4xpagesmanager._showpage(b4xpagesmanager.java:425)
    at b4a.example.b4xpagesmanager._addpage(b4xpagesmanager.java:245)
    at b4a.example.b4xpagesmanager._addpageandcreate(b4xpagesmanager.java:259)
    at b4a.example.b4xpagesmanager._initialize(b4xpagesmanager.java:165)
    at b4a.example.main._activity_create(main.java:415)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at b4a.example.main.afterFirstLayout(main.java:105)
    at b4a.example.main.access$000(main.java:17)
    at b4a.example.main$WaitForLayout.run(main.java:83)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:223)
    at android.app.ActivityThread.main(ActivityThread.java:7700)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:997)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
    at libcore.io.Linux.open(Native Method)
    at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
    at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
    at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7584)
    at libcore.io.IoBridge.open(IoBridge.java:478)
    ... 37 more
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **


But nothing seems to work.
Can anyone help please?

Thank you.
 

MicroDrie

Well-Known Member
Licensed User
Normaly the serial port used or RTS/CTS or XON/XOFF as a handshake. If you open the serial port without the XON/XOF handshake or if you have either no RTS/CTS handshake or RTS/CTS handshae set without that the RTS or CTS pins are high, communication is impossible.

A Permission denied error may be a somewhat misleading error message because the serial protocol does not have permission to transmit with an XOFF or missing CTS flag.

The fact that you can read the data from an open RFID reader, the most obvious reason seems to be that you do not provide the correct handshake option for your situation or you provide an incorrect handshake option.

As a brute force attack, I would try to give a number of handshake values such as -1, 0, 1, 2 when opening the serial port and then see if the communication is going well.

Another possibility is that you are using the wrong driver for your specific serial UART card.
 
Upvote 0

Mike1970

Well-Known Member
Licensed User
Longtime User
Normaly the serial port used or RTS/CTS or XON/XOFF as a handshake. If you open the serial port without the XON/XOF handshake or if you have either no RTS/CTS handshake or RTS/CTS handshae set without that the RTS or CTS pins are high, communication is impossible.

A Permission denied error may be a somewhat misleading error message because the serial protocol does not have permission to transmit with an XOFF or missing CTS flag.

The fact that you can read the data from an open RFID reader, the most obvious reason seems to be that you do not provide the correct handshake option for your situation or you provide an incorrect handshake option.

As a brute force attack, I would try to give a number of handshake values such as -1, 0, 1, 2 when opening the serial port and then see if the communication is going well.

Another possibility is that you are using the wrong driver for your specific serial UART card.
Thank you MicroDrie,
about the driver I've no idea what's going under the roof there. I mean, don't know wich kind of driver is taking place, since the only things we can do is open a stream.
By the way, where to set the handshake option you're talking about?
I'm on this since 50 hours with only few interruptions for sleeping moments...

Thank you.
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
Thank you MicroDrie,
about the driver I've no idea what's going under the roof there. I mean, don't know wich kind of driver is taking place, since the only things we can do is open a stream.
By the way, where to set the handshake option you're talking about?
I'm on this since 50 hours with only few interruptions for sleeping moments...

Thank you.
Without the same hardware is hard for me to test. Google has increasingly tightened the security of the weakly secured Android OS and replaced parts of the OS in newer versions. The result is that what you have now encountered is that old solutions no longer work.

Since I don't own serial hardware in an Android environment, I recommend you choose a recent driver such as in the post UsbSerial library 2.0 - supports more devices. The version V2.5 is available as an attachment to that post. It should work with targeting SDK 31+.

If it doesn't work you will need to provide more information about the hardware and driver you are using.
 
Upvote 0

Mike1970

Well-Known Member
Licensed User
Longtime User
Without the same hardware is hard for me to test. Google has increasingly tightened the security of the weakly secured Android OS and replaced parts of the OS in newer versions. The result is that what you have now encountered is that old solutions no longer work.

Since I don't own serial hardware in an Android environment, I recommend you choose a recent driver such as in the post UsbSerial library 2.0 - supports more devices. The version V2.5 is available as an attachment to that post. It should work with targeting SDK 31+.

If it doesn't work you will need to provide more information about the hardware and driver you are using.
Thank you again MicroDrie.
I'm using that library too.
But that is related to UsbSerial (so, just USB-To-Serial converters.... or I'm missing something??)
The port I'm try to accessing is a plain standard TTL port named /dev/ttyMT2.
It is not attached to a usb converter... I guess.

By the way, how can I tell you wich driver I'm using?

Thank you.
 
Upvote 0

MicroDrie

Well-Known Member
Licensed User
U wrote:

I guess because the demo application is REALLY able to open the ttyMT2 port and also my application can read the data flow when a Tag is on the reader.
Can you post the demo app or send me via a PM so I can look to it?
 
Upvote 0

Mike1970

Well-Known Member
Licensed User
Longtime User
U wrote:


Can you post the demo app or send me via a PM so I can look to it?
Sure. I would like to add it here but the compressed file project i 11Mb and it is too large. I've sent you a message in "conversation", think that is the PM...
 
Upvote 0
Top