Page 1 of 1

OSX, PB & USB-RS232 serial ports: SOLVED

Posted: Tue Aug 24, 2010 7:21 pm
by dhouston
I am ready to port my application, which is working under Windows & Linux, to OSX. It interfaces with an embedded device via RS232. I have code working under both Windows and Linux that automatically enumerates all of the serial ports on the system. Under OSX I will have to interface with USB-RS232 adapters and am hoping that someone here has a little experience with this.

It looks like my Linux code to enumerate the ports will be useless.

Code: Select all

Procedure EnumSerialPorts()                              ;enumerate serial ports 
  #O_RDONLY   = 0
  #O_WRONLY   = 1
  #O_RDWR      = 2
  #O_NOCTTY   = $100
  #O_NONBLOCK = $800
  #TIOCMGET   = $5415
  #TIOCMSET   = $5418
  #SET_DTR    = %000000000010    ;$002
  #CLR_DTR    = %111111111101    ;~#SET_DTR
  Protected dev.s,LineIn.s,found.s
  Protected ps,dmesg,fgrep,tee,i,t,s,u,c
  NewList Comports.s()
  ps=RunProgram("/bin/ps", "-A","",#PB_Program_Open|#PB_Program_Read)
  fgrep=RunProgram("/bin/fgrep", "SerialTest","",#PB_Program_Open|#PB_Program_Connect|#PB_Program_Read,ps)
  tee = RunProgram("/usr/bin/tee","PID.txt",AppPath,#PB_Program_Open|#PB_Program_Connect|#PB_Program_Read,fgrep)
  While ProgramRunning(tee)
    Pid=StringField(Trim(ReadProgramString(tee)),1," ")
  Wend 
  WaitProgram(tee)
  CloseProgram(ps):CloseProgram(tee)
  ;-----enum ports & write tty.txt-----
  DeleteFile(AppPath+"tty.txt")
  dmesg = RunProgram("/bin/dmesg","","",#PB_Program_Open|#PB_Program_Read)
  fgrep = RunProgram("/bin/fgrep","tty","",#PB_Program_Open|#PB_Program_Connect|#PB_Program_Read,Dmesg)
  tee = RunProgram("/usr/bin/tee","tty.txt",AppPath,#PB_Program_Open|#PB_Program_Connect|#PB_Program_Read,Fgrep)
  WaitProgram(tee)
  CloseProgram(Dmesg):CloseProgram(Fgrep):CloseProgram(Tee)
  ;-----parse tty.txt-----
  ports=""
  If ReadFile(0,AppPath+"tty.txt")    
    While Eof(0) = 0 
      LineIn=ReadString(0)+" "
      t=FindString(LineIn,"tty",1)                    ;Tibbo uses vspdN
      If t>0
        s=FindString(LineIn," ",t)
        dev=Trim(Mid(LineIn,t,s-t))     
        If Right(dev,1)=":":dev=Left(dev,Len(dev)-1):EndIf
        If Not IsNumeric(Mid(dev,4,1))
          c=CountString(LineIn,"tty")
          If c=1      
            ;RunProgram("stty","-F /dev/"+dev+" 19200 cread -echo -icanon","")
            ;fd=open_("/dev/"+dev,#O_NONBLOCK|#O_NOCTTY|#O_RDWR,0)  
            fd=OpenSerialPort(#PB_Any,"/dev/"+dev,19200,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,1024,1024)        
            If fd<>0 
              AddElement(ComPorts())
              ComPorts()="/dev/"+dev
              close_(fd)
            EndIf             
          ElseIf (c=2) 
            s=Val(Mid(dev,5,2))                                               ;first index
            t=FindString(LineIn,"tty",t+Len(dev))                   ;find second tty?xx
            c=Val(Mid(LineIn,t+4,2))                                       ;second index
            If (c>s)
              For i=s To c
                dev=Left(dev,4)+Str(i)       
                ;RunProgram("stty","-F /dev/"+dev+" 19200 cread -echo -icanon","")
                ;fd=open_("/dev/"+dev,#O_NONBLOCK|#O_NOCTTY|#O_RDWR,0)  
                fd=OpenSerialPort(#PB_Any,"/dev/"+dev,19200,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,1024,1024)
                If fd<>0
                  AddElement(ComPorts())
                  ComPorts()="/dev/"+dev
                  close_(fd)
                EndIf                 
              Next
            ElseIf FindString(LineIn,"-",1)>0
              MessageRequester("Serial Port Enumeration","Unexpected dmesg format - Copy tty.txt to roZetta author"+#CRLF$+LineIn)
            EndIf
          Else
            MessageRequester("Serial Port Enumeration","Unexpected dmesg format - Copy tty.txt to roZetta author"+#CRLF$+LineIn)
          EndIf  
        EndIf
      EndIf
    Wend
    CloseFile(0)
  EndIf 
  SortList(ComPorts(),0)
  ForEach ComPorts()
    If FindString(ports,ComPorts(),1)=0   ;avoid duplicates
      If Len(ports):ports+",":EndIf
      ports+ComPorts()
    EndIf
  Next
;Debug ports  
  OpenPreferences(AppPath+"serial.prf"):PreferenceGroup("port")
    WritePreferenceString("found",ports)
  ClosePreferences()  
EndProcedure
I still have to dig a couple of USB-RS232 adapters out of my parts bin and plug them in to my Mac Mini. How does OSX report their presence?

Re: OSX, PB & USB-RS232 serial ports

Posted: Tue Aug 24, 2010 8:45 pm
by dhouston
OK, installing the driver for an FTDI USB-RS232 adapter gave me enough info that I understand the serial adapter under OSX. I doubt I'll be able to automatically enumerate the ports as dmesg and fgrep seem to be missing but users can edit the app's .prf file to add any such ports.

Now, if I can resolve the PanelGadget issue (along with other cosmetic issues) I'll feel very good about PB & OSX.

Re: OSX, PB & USB-RS232 serial ports

Posted: Wed Aug 25, 2010 11:55 am
by aaron
All of your serial ports will show up as /dev/tty.* I think (but can't guarantee) that most usb to serial devices will show up at /dev/tty.usbserial.*

Rather than dmesg and fgrep, you can use the purebasic built in file system commands to grab the directory listing from /dev, throw away any entries that aren't tty. and you should be most of the way there.

Re: OSX, PB & USB-RS232 serial ports

Posted: Wed Aug 25, 2010 12:38 pm
by dhouston
aaron wrote:All of your serial ports will show up as /dev/tty.* I think (but can't guarantee) that most usb to serial devices will show up at /dev/tty.usbserial.*
Actually. my first generation FTDI (which is the only one I've tried so far) uses...
  • /dev/cu.usbserial-USAxxxxx
where xxxxx is a serial number. The FTDI documentation shows other possible variations.

I have the drivers for the Prolific PL2303 chipset but their documentation does not offer any details on how it is listed in /dev/ so I'll have to find one of mine and try it.
aaron wrote:Rather than dmesg and fgrep, you can use the purebasic built in file system commands to grab the directory listing from /dev, throw away any entries that aren't tty. and you should be most of the way there.
I hope you are right but fear it may prove too complex without knowing the specifics of each manufacturer's method. I'll probably just require users to edit a preference file. It's likely to be simpler than Linux where many multiport PCI cards have far different methods for identification. I expect the number of USB-Serial adapters to be minimal under OSX. This is one area where Windows is simpler to handle with all being listed as COMn.

Re: OSX, PB & USB-RS232 serial ports

Posted: Wed Aug 25, 2010 3:35 pm
by dhouston
Ahh! The FTDI adapter is also listed as "tty.usbserial-USA632H8" so, if the Prolific adapter uses a similar method, it might be simple to automatically enumerate them after all. I've installed the Prolific driver but still have to locate the adapter(s).

In case anyone else needs inexpensive USB-Serial adapters...

Re: OSX, PB & USB-RS232 serial ports

Posted: Fri Sep 17, 2010 7:37 pm
by dhouston
I've had a chance to test this and...

Code: Select all

If ExamineDirectory(0,"/dev/","tty.u*")
  While NextDirectoryEntry(0)
    If DirectoryEntryType(0) = #PB_DirectoryEntry_File
      MessageRequester("/dev/filename", DirectoryEntryName(0))
    EndIf
  Wend
  FinishDirectory(0)
EndIf
finds the three USB-Serial adapters I have connected. I will be modifying my Linux procedure accordingly as this is much simpler.

Re: OSX, PB & USB-RS232 serial ports

Posted: Fri Oct 08, 2010 4:45 pm
by dhouston
The code snippet below finds all the serial ports on my Intel mini but fails on my PPC iMac. I suspect I need to search a different directory(?) and/or use different search patterns. So far, I haven't figured out how to find, let alone view the contents, of /dev.

Code: Select all

  OpenPreferences(AppPath+"user.prf"):PreferenceGroup("user")
    ports = ReadPreferenceString("ports","NONE")    
    dirs = ReadPreferenceString("dirs","")    ; dirs = /dev
    patterns = ReadPreferenceString("patterns","")   ;patterns = tty.u*
  ClosePreferences()
  If ports="NONE"
    ports=""
    Protected i,j,dir.s,pattern.s
    NewList Comports.s()
    For i=1 To CountString(dirs,",")+1
      dir=StringField(dirs,i,",")
      For j=1 To CountString(patterns,",")+1
        pattern=StringField(patterns,j,",")
        If ExamineDirectory(0,dir,pattern)
          ;MessageRequester(dir,pattern)
          While NextDirectoryEntry(0)
            If DirectoryEntryType(0) = #PB_DirectoryEntry_File
              AddElement(ComPorts())
              ComPorts()=dir+"/"+DirectoryEntryName(0)              
            EndIf
          Wend
          FinishDirectory(0)
        EndIf  
      Next j
    Next i  
    SortList(ComPorts(),0)
    ForEach ComPorts()
      If FindString(ports,ComPorts(),1)=0               ;avoid duplicates
        If Len(ports):ports+",":EndIf
        ports+ComPorts()
      EndIf
    Next    
    ;MessageRequester("ports",ports)
  EndIf
EndProcedure

Re: OSX, PB & USB-RS232 serial ports

Posted: Fri Oct 08, 2010 7:16 pm
by dhouston
I had overlooked the need for drivers. Both of my test serial-USB adapters (one FTDI based, one Prolific based) showed up in System Profiler but I guess it took the installation of the drivers to actually create the /dev entries.