Any way to get the serial port name from USB info?

I tried several methods to watch USB ports for changes – i.e. MacUSBNotificationMBS, libUSB running as a port watcher. Both make me get VendorID and ProductID which is necessary for me to determine the attached device‘s type.
Both do show me a product name, which in this case is “USB Serial”.
The Mac port name, anyway, can be something like “usbserial-113210” or similar.
I tried to figure out if there is any resemblance between usb properties (address, bus etc.) and serial name but could not find any.

Therefore: Is it possible to translate usb info into Mac pro name?
Or is there any way to read pID and vID from a serial port?
Maybe with MBS, @Christian_Schmitz ?

WMI classes may help.

See blog post where we used it for USB Sticks
https://www.mbsplugins.de/archive/2012-02-24/Detecting_drive_letter_for_an_/monkeybreadsoftware_blog_xojo

Thank you, Christian. Any idea to have a similar feature for macOS?
I tried FTDI/D2XX access too but sadly the mentioned devices, although some of them using an FTDI chip internally, are to listed here.

To do this, open a Terminal window, type ls /dev/tty.usb*, and press enter. You should see two entries of the form tty.usbmodem<number> (e.g. /dev/tty.usbmodem00022331). These entries represent virtual serial ports created by the programmer.

from

also possible
ls -al /dev
and check for port names beginning with cu.

1 Like

Thank you, and a big step forward for my issue!
Any ideas if there is a console app to ask pID and vID from a virtual serial port too?

you should get anything possible from
system_profiler SPUSBDataType

2 Likes

Excellent! Thank you!

How would one go about querying System Profiler data programmatically?

it could be easier with the -json or the -xml option to parse the result.

system_profiler -json SPUSBDataType
1 Like

Using Shell class to run command line tool and parse result.

1 Like

Bingo.

"_items" : [
        {
          "_name" : "FT232R USB UART",
          "bcd_device" : "6.00",
          "bus_power" : "500",
          "bus_power_used" : "90",
          "device_speed" : "full_speed",
          "extra_current_used" : "0",
          "location_id" : "0x01140000 / 3",
          "manufacturer" : "FTDI",
          "product_id" : "0x6001",
          "serial_num" : "AB89UL00",
          "vendor_id" : "0x0403  (Future Technology Devices International Limited)"
        },

@Roger_Meier

Nice! Now to correlate the output of system_profiler -json SPUSBDataType with SerialDevice.Name :slightly_smiling_face:.

In my case, where name is reported as USB Serial, I found the serial port name to be usbserial-[locationID.Left(locationID.netlength -1)]
With net length I mean the hex value of locationID only, without slash and USB Address (“/ 3” in Julia’s example). So with Julia’s example my serial port name would be “usbserial-0114000” probably. (One trailing 0 removed).

Yes, for SOME of them this is true. Others, however, use the serial number instead of the location ID (and some add an index number in case of an adapter with multiple ports). Some may also use the string “usbmodem” rather than “usbserial-”.

So, the approach to look up the description and manufacturer for a given port name is to strip those strings from the port name, like this

var ID as string = PortName
ID = ID.Replace("wchusbserial", "")
ID = ID.Replace("usbmodem", "")
ID = ID.Replace("usbserial-", "")

and then to iterate through the JSON structure to find the item that contains the remaining string in either the 'serial_num" or “location_id” strings.

if item.HasKey("serial_num") or item.hasKey("location_id") then
  var serNo as string = if(item.HasKey("serial_num"), item.Value("serial_num"), "There is no serial number")
  var locID as string = item.Value("location_id")
  var locIDs() as string = locID.Split(" ")
  locID = locIDs(0).Replace("0x", "")
  if ID.IndexOf(serNo) >= 0 or ID.IndexOf(locID) >= 0 then
    var name as string = item.Value("_name")
    var manufacturer as string
    if item.HasKey("manufacturer") then
      manufacturer = item.Value("manufacturer")
    end if
    return new Pair(name, manufacturer)
  else 
    return nil
  end if
end if

I’m sure this is not the sexiest implementation, but this seems to work ok, at least for the plethora of USB/Serial devices I have at my disposal.

1 Like

Just found a weird bug on macOS Ventura on an Intel iMac – Sonoma & M1 works great, which seems to be related to Xojo’s shell class.
On the iMac, system_profiler -json SPUSBDataType produces some errors first. I can see them when I run the command in terminal too. But followed by the JSON as requested which I can see in Debugger in Shell.Result:

2023-11-02 12:55:05.141 system_profiler[2812:58324] SPUSBDevice: IOCreatePlugInInterfaceForService failed 0xe00002be
2023-11-02 12:55:05.142 system_profiler[2812:58324] SPUSBDevice: IOCreatePlugInInterfaceForService failed 0xe00002be
{
  "SPUSBDataType" : [
    {
      "_items" : [
        {
          "_items" : [
            {
              "_name" : "Bluetooth USB Host Controller",
              "bcd_device" : "1.50",
              "location_id" : "0x14630000",
              "manufacturer" : "Apple Inc.",
              "product_id" : "0x828d",
              "vendor_id" : "apple_vendor_id"
            }
          ], 
(//and so on)
}}}

when I read Shell.Result into a string where I want to remove the failure lines, the string is truncated to 256 characters:

2023-11-02 12:55:05.141 system_profiler[2812:58324] SPUSBDevice: IOCreatePlugInInterfaceForService failed 0xe00002be
2023-11-02 12:55:05.142 system_profiler[2812:58324] SPUSBDevice: IOCreatePlugInInterfaceForService failed 0xe00002be
{
  "SPUSBDataType" :

Someone able to confirm this?

I just tried this code in 2023r4 beta and it returns lots of lines (far greater than 256 chars). Ah, sorry, I’m on Sanoma. so I don’t think that helps.

Var she As New shell
she.Execute "system_profiler -json SPUSBDataType"
MessageBox she.result

What mode are you using and did you try shell.ReadAll?

I just tried it on an old Intel Mini running 12.7.1 (Monterey) and it also worked fine. Not sure if that helps.

Thank you. I could in between find that the error does not appear with Xojo2023r2. The profiler errors persist of course, but neither Result nor ReadAll are truncated.

It’s a synchronous shell and I am debugging remotely on my old iMac. Will try 2023r3 and r3.1 for when the error occurs. I can even see the full text in my copied string flath briefly when I switch to debugger but the rest appears after a fraction of a second. And error exists for me and a customer in build too.

1 Like

hmm … Count this under “oddities”.
I created a demo project, and no truncation error anymore. Differences were that in my original project, the shell containing method is triggered by a macUSBNotification event, and a different order of checking ExitCode and Result. I copied the code order to my main project and now do not see that bug anymore. Weird, but at least working, it seems.

odd indeed. If you can still reproduce the original issue, it would be worth posting a bug report.