B4J Question Read ProductId and VendorId of USB/serial adapters

drgottjr

Expert
Licensed User
Longtime User
have you seen this ?
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i don't know how good you are with this stuff, but apparently jssc does support access to ProductId and VendorId.
check here those properties are specifically mentioned. the issue seems to be windows, but some quick research implies that success is possible.
i have no interest; just passing the information along in the spirit of a fellow traveler.
 
Upvote 0

raphaelcno

Active Member
Licensed User
Longtime User
Thank you :)

On https://github.com/gohai/java-simpl.../processing/src/java/jssc/SerialPortList.java I found this code related to "idVendor" and "idProduct":

C++:
    public static Map<String, String> getPortProperties(String portName) {
        if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_LINUX) {
            return getLinuxPortProperties(portName);
        } else if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_MAC_OS_X) {
            return getNativePortProperties(portName);
        } else if(SerialNativeInterface.getOsType() == SerialNativeInterface.OS_WINDOWS){
            // TODO
            return new HashMap<String, String>();
        } else {
            return new HashMap<String, String>();
        }
    }

    public static Map<String, String> getLinuxPortProperties(String portName) {
        Map<String, String> props = new HashMap<String, String>();
        try {
            // portName has the format /dev/ttyUSB0
            String dev = portName.split("/")[2];
            File sysfsNode = new File("/sys/bus/usb-serial/devices/"+dev);

            // resolve the symbolic link and store the resulting components in an array
            String[] sysfsPath = sysfsNode.getCanonicalPath().split("/");

            // walk the tree to the root
            for (int i=sysfsPath.length-2; 0 < i; i--) {
                String curPath = "/";
                for (int j=1; j <= i; j++) {
                    curPath += sysfsPath[j]+"/";
                }

                // look for specific attributes
                String[] attribs = { "idProduct", "idVendor", "manufacturer", "product", "serial" };
                for (int j=0; j < attribs.length; j++) {
                    try {
                        Scanner in = new Scanner(new FileReader(curPath+attribs[j]));
                        // we treat the values just as strings
                        props.put(attribs[j], in.next());
                    } catch (Exception e) {
                        // ignore the attribute
                    }
                }

                // stop once we have at least one attribute
                if (0 < props.size()) {
                    break;
                }
            }
        } catch (Exception e) {
            // nothing to do, return what we have so far
        }
        return props;
    }

    public static Map<String, String> getNativePortProperties(String portName) {
        Map<String, String> props = new HashMap<String, String>();
        try {
            // use JNI functions to read those properties
            String[] names = { "idProduct", "idVendor", "manufacturer", "product", "serial" };
            String[] values = SerialNativeInterface.getPortProperties(portName);

            for (int i=0; i < names.length; i++) {
                if (values[i] != null) {
                    props.put(names[i], values[i]);
                }
            }
        } catch (Exception e) {
            // nothing to do, return what we have so far
        }
        return props;
    }

As for now, this seems to be a little beyond my knowledge level.
Maybe in the future I will be able to use it :rolleyes:
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Check the updated "B4R Serial Connector": https://www.b4x.com/android/forum/threads/tool-external-serial-connector.65724/

f5CT6pMMYn.png


It calls a small .Net console app that prints the ports descriptions.
 
Upvote 0

raphaelcno

Active Member
Licensed User
Longtime User
Thank you, that looks very interesting! ?

If I understand correctly, I have to copy the 'ListPorts.exe' file from 'Files' directory (in B4R_Serial_Connector project) to 'Files' directory in my B4J project directory, then select the jShell library in my project, and use following lines in the code:

B4X:
Sub Process_Globals
    Private serial As Serial
    Private PortsNames As B4XOrderedMap
    Private DataFolder As String
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    DataFolder = File.DirData("xxxxxAppName")
    serial.Initialize("")
    Wait For (GetPortsNames) Complete (unused As Boolean)
End Sub

Sub GetPortsNames As ResumableSub
    PortsNames.Initialize
    For Each port As String In serial.ListPorts
        PortsNames.Put(port, port) 'default names  ' COM4, COM4
    Next
    ' Copy 'ListPorts.exe' from compiled jar file to DirData directory
    File.Copy(File.DirAssets, "ListPorts.exe", DataFolder, "ListPorts.exe")
    ' Use Shell to run 'ListPorts.exe'
    Dim shl As Shell
    shl.Initialize("shl", File.Combine(DataFolder, "ListPorts.exe"), Null)
    shl.Run(5000)
    ' Wait for the process to be completed, read StdOut output and extract port names and descriptions
    Wait For shl_ProcessCompleted (Success As Boolean, ExitCode As Int, StdOut As String, StdErr As String)
    If Success And ExitCode = 0 Then
        For Each line As String In Regex.Split(CRLF, StdOut)
            Log(line)
            Dim i As Int = line.IndexOf(" ")
            If i = -1 Then Continue
            Dim port As String = line.SubString2(0, i)  ' COM4
            Dim Description As String = line.Trim       ' COM4 Silicon Labs CP210x ...
            If PortsNames.ContainsKey(port) Then PortsNames.Put(port, Description)  ' COM4, COM4 Silicon Labs CP210x ...
        Next
    End If
    Return True
End Sub
 
Upvote 0
Top