I have updated my code to handle another variation in how dmesg lists ports for Moxa multi-port boards. The --parse-tty.txt-- section could be cleaner but I anticipate there will be other dmesg variations.
Code: Select all
;------------------------------------------------------------------------------------------------------
;
; PureBasic - LINUX Serial Communications
; based on post to PureBasic Linux Forum by Larry Duarte
; http://www.purebasic.fr/english/viewtopic.php?t=16847&highlight=linux+serial
;
; -------------------------------------------------------------------------------------------------------
;
EnableExplicit
#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
#WNDW_MAIN = 0
#EDT_RCV = 1
#STR_TX = 2
#DTR_LED = 3
#STATUS =4
#CBO_PORTS=5
#PB_SerialPort_NoParity=0
#PB_SerialPort_NoHandshake=0
Procedure ScrollToEnd(gadget) ;scrolls text window to last line
Protected end_mark,*buffer, end_iter.GtkTextIter
*buffer=gtk_text_view_get_buffer_(GadgetID(gadget))
gtk_text_buffer_get_end_iter_(*buffer,@end_iter)
;gtk_text_buffer_place_cursor_(*buffer,@end_iter)
end_mark=gtk_text_buffer_create_mark_(*buffer,"end_mark",@end_iter,#False)
gtk_text_view_scroll_mark_onscreen_(GadgetID(gadget),end_mark)
EndProcedure
Define.s buf=Space(5),out=Space(10),dev,Pid,output,LineIn,found,ports,key,bad
Define.l EventID,sec,i,n,Quit,returncode,fd,flags,ps,dmesg,fgrep,tee,t,s,u,c,ComID,mode,*buffer
*buffer=AllocateMemory(10)
mode=1 ;0=Linux API, 1=Mattias Groß library. 2=Native PB
If OpenWindow(#WNDW_MAIN,100,100,188,235,"SerialTest",#PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
TextGadget(#PB_Any,10,50,150,20,"Receive Data")
EditorGadget(#EDT_RCV,10,70,168,100)
TextGadget(#PB_Any,10,180,150,20,"Send Data")
StringGadget(#STR_TX,10,200,168,20,"",#PB_Text_Center)
TextGadget(#PB_Any,10,4,200,22,"Port:")
ComboBoxGadget(#CBO_PORTS,42,0,135,27)
TextGadget(#PB_Any,10,33,50,22,"DTR"):TextGadget(#DTR_LED,40,36,15,15,"",#PB_Text_Border)
TextGadget(#PB_Any,65,33,50,22,"Flags"):TextGadget(#STATUS,100,33,77,22,RSet(Bin(flags),9,"0"),#PB_Text_Border)
;-----get PID-----ONLY WORKS FOR COMPILED APPLICATION
ps=RunProgram("/bin/ps", "-A","",#PB_Program_Open|#PB_Program_Read)
fgrep=RunProgram("/bin/fgrep", "linux-serial","",#PB_Program_Open|#PB_Program_Connect|#PB_Program_Read,ps)
tee = RunProgram("/usr/bin/tee","PID.txt",GetCurrentDirectory(),#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-----
DeleteFile("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",GetCurrentDirectory(),#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,"tty.txt")
While Eof(0) = 0
LineIn=ReadString(0)+" "
t=FindString(LineIn,"tty",1)
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)
If fd>0
If FindString(ports,dev,1)=0
If Len(ports):ports+",":EndIf
ports+"/dev/"+dev
EndIf
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)
If fd>0
If FindString(ports,dev,1)=0
If Len(ports):ports+",":EndIf
ports+"/dev/"+dev
EndIf
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
;-----lock file----
OpenPreferences("serial.prf"):PreferenceGroup("port")
WritePreferenceString("ports",ports)
dev=ReadPreferenceString("dev","NONE") ;ADD THE dev KEY MANUALLY
ClosePreferences()
SetGadgetText(#CBO_PORTS,dev)
Select mode
Case 0
RunProgram("stty","-F "+dev+" 19200 cread -echo -icanon","")
fd=open_(dev,#O_NONBLOCK|#O_NOCTTY|#O_RDWR,0)
Case 1
fd=ComOpen(dev+":19200,N,8,1",0,1024,1024)
Case 2
fd=OpenSerialPort(#PB_Any,"/dev/"+dev,19200,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,1024,1024)
EndSelect
If (fd<1)
MessageRequester("ERROR!","Unable to open "+dev)
Else
Repeat
EventID=WindowEvent()
If (sec<>Second(Date()))
sec=Second(Date())
out=FormatDate("%hh:%ii:%ss",Date())+Chr(10)
Select mode
Case 0
n=write_(fd,out,9)
returncode=ioctl_(fd,#TIOCMGET,@flags)
SetGadgetText(#STATUS,RSet(Bin(flags),9,"0"))
If (flags & 2)=#SET_DTR
flags & #CLR_DTR
SetGadgetColor(#DTR_LED,#PB_Gadget_BackColor,RGB(255,0,0))
Else
flags | #SET_DTR
SetGadgetColor(#DTR_LED,#PB_Gadget_BackColor,RGB(0,255,0))
EndIf
returncode=ioctl_(fd,#TIOCMSET,@flags)
Case 1
n=ComOutput(fd,out)
If sec % 2 = 1
ComSetDTR(fd,1)
SetGadgetColor(#DTR_LED,#PB_Gadget_BackColor,RGB(255,0,0))
Else
ComSetDTR(fd,0)
SetGadgetColor(#DTR_LED,#PB_Gadget_BackColor,RGB(0,255,0))
EndIf
Case 2
n=WriteSerialPortString(fd, out)
EndSelect
If (n<1)
SetGadgetText(#STR_TX,"Write() failed! ")
Else
SetGadgetText(#STR_TX,Left(out,8))
EndIf
EndIf
Select mode
Case 0
n=read_(fd,buf,1)
Case 1
n=ComInput(fd,buf)
Case 2
If AvailableSerialPortInput(fd)
n=AvailableSerialPortInput(fd)
n=ReadSerialPortData(fd, *buffer, n)
buf=""
For i=0 To n-1
buf=buf+PeekS(*buffer+i)
Next
EndIf
EndSelect
If (n > 0)
SetGadgetText(#EDT_RCV,GetGadgetText(#EDT_RCV)+Left(buf,1))
ScrollToEnd(#EDT_RCV)
EndIf
If EventID = #PB_Event_CloseWindow
Quit = 1
EndIf
Until Quit=1
close_(fd)
EndIf
EndIf
End