Code: Select all
;
; PIC Ethernet Discover
;
; | 
#Version = "1.00"
EnableExplicit
CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    #AF_INET = 2
    #SOCK_DGRAM = 2
    #SO_BROADCAST = 6
    #SOL_SOCKET = 1
    #INADDR_ANY = 0
    #INADDR_BROADCAST = $FFFFFFFF
    
    #IPPROTO_UDP = 17
    
    #FIONBIO = $5421
    
    #INVALID_SOCKET = -1
    #SOCKET_ERROR = -1
    
    
    Structure sockaddr_in Align #PB_Structure_AlignC
      sin_family.u
      sin_port.u
      sin_addr.l
      sin_zero.a[8]
    EndStructure
    
  CompilerCase #PB_OS_MacOS
    #AF_INET = 2
    #SOCK_DGRAM = 2
    #SO_BROADCAST = $20
    #SOL_SOCKET = $FFFF
    #INADDR_ANY = 0
    #INADDR_BROADCAST = $FFFFFFFF
    
    #IPPROTO_UDP = 17
    
    #INVALID_SOCKET = -1
    #SOCKET_ERROR = -1
    
    
    Structure sockaddr_in Align #PB_Structure_AlignC
      sin_family.u
      sin_port.u
      sin_addr.l
      sin_zero.a[8]
    EndStructure
CompilerEndSelect
Define service.sockaddr_in
Define RxAddr.sockaddr_in
Define RxAddrLen.i
Define TxAddr.sockaddr_in
Define Socket.i
Define argp.l
Define *Buffer
Define Querry$, Receive$, Found$, Name$, MAC$, IP$
Define.i Starttime, Avail, First, Exit, Event, Found, i
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  Define wsaData.WSADATA
  ; initialize the WindowsSocketAPI
  If WSAStartup_($101, @wsaData) <> #NO_ERROR
    End 2
  EndIf
CompilerEndIf
; open an UDP socket
Socket = SOCKET_(#AF_INET, #SOCK_DGRAM, #IPPROTO_UDP)
If Socket = #INVALID_SOCKET
  End 3
EndIf
; set it to none blocking
argp = 1
CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    ioctl_(Socket, #FIONBIO, @argp)
  CompilerCase #PB_OS_MacOS
    #F_SETFL = 4
    #O_NONBLOCK = 4
    fcntl_(Socket, #F_SETFL, #O_NONBLOCK)
  CompilerCase #PB_OS_Windows
    ioctlsocket_(Socket, #FIONBIO, @argp)
CompilerEndSelect
; allow broadcasts on that socket
argp = $FFFFFFFF
setsockopt_(Socket, #SOL_SOCKET, #SO_BROADCAST, @argp, 4)
; bind the socket to port 30303 and listen to all incoming addresses
service\sin_family = #AF_INET
service\sin_addr = #INADDR_ANY
service\sin_port = htons_(30303)
If bind_(Socket, @service, SizeOf(sockaddr_in)) <> #SOCKET_ERROR
  
  *Buffer = AllocateMemory(1536)
  If *Buffer
    
    ; needed for recvfrom()
    RxAddrLen = SizeOf(sockaddr_in)
    
    Querry$ = "Discovery: Who is out there?"
    
    RxAddr\sin_family = #AF_INET
    RxAddr\sin_port = htons_(30303)
    RxAddr\sin_addr = #INADDR_ANY
    
    TxAddr\sin_family = #AF_INET
    TxAddr\sin_port = htons_(30303)
    TxAddr\sin_addr = #INADDR_BROADCAST
    
    
    OpenWindow(0, 0, 0, 400, 200, "Ethernet Discover V" + #Version + "   (c) 2012 Infratec AG", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
    
    ListIconGadget(0, 10, 10, 380, 180, "Name", 100, #PB_ListIcon_FullRowSelect)
    AddGadgetColumn(0, 1, "MAC", 110)
    AddGadgetColumn(0, 2, "Address", 100)
    
    SetActiveGadget(0)
    
    AddWindowTimer(0, 0, 100)
    
    First = #True
    Exit = #False
    Repeat
      Event = WaitWindowEvent(10)
      Select Event
        Case #PB_Event_Timer
          If EventTimer() = 0
            If First
              RemoveWindowTimer(0, 0)
              AddWindowTimer(0, 0, 5000)
              First = #False
            EndIf
            sendto_(Socket, @Querry$, Len(Querry$), 0, @TxAddr, SizeOf(sockaddr_in))
          EndIf
        Case #PB_Event_Gadget
          If EventType() = #PB_EventType_LeftDoubleClick
            IP$ = GetGadgetItemText(0, GetGadgetState(0), 2)
            RunProgram("http://" + IP$)
          EndIf
        Case #PB_Event_CloseWindow : Exit = #True
      EndSelect
      
      Avail = recvfrom_(Socket, *Buffer, MemorySize(*Buffer), #Null, @RxAddr, @RxAddrLen)
      If Avail > 0
        Receive$ = PeekS(*Buffer, Avail)
        If Receive$ <> Querry$
          Receive$ = ReplaceString(Receive$, #CRLF$, #LF$)
          Name$ = StringField(Receive$, 1, #LF$)
          MAC$ = StringField(Receive$, 2, #LF$)
          ;Info$ = StringField(Receive$, 3, #LF$)
          IP$ = IPString(RxAddr\sin_addr)
          
          Found = #False  
          For i = 0 To CountGadgetItems(0) - 1
            If GetGadgetItemText(0, i, 1) = MAC$
              Found = #True
              Break
            EndIf
          Next i
          
          If Found
            SetGadgetItemText(0, i, Name$, 0)
            SetGadgetItemText(0, i, IP$, 2)
          Else
            AddGadgetItem(0, -1, Name$ + #LF$ + MAC$ + #LF$ + IP$)
          EndIf
          
        EndIf
      EndIf
      
    Until Exit
    FreeMemory(*Buffer)
    
  EndIf
EndIf
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
  close_(Socket)
CompilerElse
  closesocket_(Socket)
  WSACleanup_()
CompilerEndIf
It discovers MicroChip ethernet PIC CPUs when the TCP/IP stack is running.