3
3
# SPDX-FileCopyrightText: 2008 Bjoern Hartmann
4
4
# SPDX-FileCopyrightText: 2018 Paul Stoffregen
5
5
# SPDX-FileCopyrightText: 2020 Brent Rubell for Adafruit Industries
6
+ # SPDX-FileCopyrightText: 2021 Patrick Van Oosterwijck
6
7
#
7
8
# SPDX-License-Identifier: MIT
8
9
12
13
13
14
Pure-Python interface for WIZNET 5k ethernet modules.
14
15
15
- * Author(s): WIZnet, Arduino LLC, Bjoern Hartmann, Paul Stoffregen, Brent Rubell
16
+ * Author(s): WIZnet, Arduino LLC, Bjoern Hartmann, Paul Stoffregen, Brent Rubell,
17
+ Patrick Van Oosterwijck
16
18
17
19
Implementation Notes
18
20
--------------------
113
115
114
116
# Maximum number of sockets to support, differs between chip versions.
115
117
W5200_W5500_MAX_SOCK_NUM = const (0x08 )
118
+ SOCKET_INVALID = const (255 )
116
119
117
120
# UDP socket struct.
118
121
UDP_SOCK = {"bytes_remaining" : 0 , "remote_ip" : 0 , "remote_port" : 0 }
@@ -144,7 +147,7 @@ def __init__(
144
147
is_dhcp = True ,
145
148
mac = DEFAULT_MAC ,
146
149
hostname = None ,
147
- dhcp_timeout = 3 ,
150
+ dhcp_timeout = 30 ,
148
151
debug = False ,
149
152
):
150
153
self ._debug = debug
@@ -240,7 +243,7 @@ def get_host_by_name(self, hostname):
240
243
print ("* Get host by name" )
241
244
if isinstance (hostname , str ):
242
245
hostname = bytes (hostname , "utf-8" )
243
- self ._src_port = int (time .monotonic ())
246
+ self ._src_port = int (time .monotonic ()) & 0xFFFF
244
247
# Return IP assigned by DHCP
245
248
_dns_client = dns .DNS (self , self ._dns , debug = self ._debug )
246
249
ret = _dns_client .gethostbyname (hostname )
@@ -475,7 +478,6 @@ def socket_available(self, socket_num, sock_type=SNMR_TCP):
475
478
476
479
res = self ._get_rx_rcv_size (socket_num )
477
480
478
- res = int .from_bytes (res , "b" )
479
481
if sock_type == SNMR_TCP :
480
482
return res
481
483
if res > 0 :
@@ -546,21 +548,22 @@ def _send_socket_cmd(self, socket, cmd):
546
548
if self ._debug :
547
549
print ("waiting for sncr to clear..." )
548
550
549
- def get_socket (self , sockets ):
551
+ def get_socket (self ):
550
552
"""Requests, allocates and returns a socket from the W5k
551
553
chip. Returned socket number may not exceed max_sockets.
552
- :parm int socket_num: Desired socket number
553
554
"""
554
555
if self ._debug :
555
556
print ("*** Get socket" )
556
557
557
- sock = 0
558
- for _sock in range (len (sockets ), self .max_sockets ):
559
- status = self .socket_status (_sock )
560
- if (
561
- status [0 ] == SNSR_SOCK_CLOSED
562
- or status [0 ] == SNSR_SOCK_FIN_WAIT
563
- or status [0 ] == SNSR_SOCK_CLOSE_WAIT
558
+ sock = SOCKET_INVALID
559
+ for _sock in range (self .max_sockets ):
560
+ status = self .socket_status (_sock )[0 ]
561
+ if status in (
562
+ SNSR_SOCK_CLOSED ,
563
+ SNSR_SOCK_TIME_WAIT ,
564
+ SNSR_SOCK_FIN_WAIT ,
565
+ SNSR_SOCK_CLOSE_WAIT ,
566
+ SNSR_SOCK_CLOSING ,
564
567
):
565
568
sock = _sock
566
569
break
@@ -569,14 +572,47 @@ def get_socket(self, sockets):
569
572
print ("Allocated socket #{}" .format (sock ))
570
573
return sock
571
574
575
+ def socket_listen (self , socket_num , port ):
576
+ """Start listening on a socket (TCP mode only).
577
+ :parm int socket_num: socket number
578
+ :parm int port: port to listen on
579
+ """
580
+ assert self .link_status , "Ethernet cable disconnected!"
581
+ if self ._debug :
582
+ print (
583
+ "* Listening on port={}, ip={}" .format (
584
+ port , self .pretty_ip (self .ip_address )
585
+ )
586
+ )
587
+ # Initialize a socket and set the mode
588
+ self ._src_port = port
589
+ res = self .socket_open (socket_num , conn_mode = SNMR_TCP )
590
+ if res == 1 :
591
+ raise RuntimeError ("Failed to initalize the socket." )
592
+ # Send listen command
593
+ self ._send_socket_cmd (socket_num , CMD_SOCK_LISTEN )
594
+ # Wait until ready
595
+ status = [SNSR_SOCK_CLOSED ]
596
+ while status [0 ] != SNSR_SOCK_LISTEN :
597
+ status = self ._read_snsr (socket_num )
598
+ if status [0 ] == SNSR_SOCK_CLOSED :
599
+ raise RuntimeError ("Listening socket closed." )
600
+
572
601
def socket_open (self , socket_num , conn_mode = SNMR_TCP ):
573
602
"""Opens a TCP or UDP socket. By default, we use
574
603
'conn_mode'=SNMR_TCP but we may also use SNMR_UDP.
575
604
"""
576
605
assert self .link_status , "Ethernet cable disconnected!"
577
606
if self ._debug :
578
607
print ("*** Opening socket %d" % socket_num )
579
- if self ._read_snsr (socket_num )[0 ] == SNSR_SOCK_CLOSED :
608
+ status = self ._read_snsr (socket_num )[0 ]
609
+ if status in (
610
+ SNSR_SOCK_CLOSED ,
611
+ SNSR_SOCK_TIME_WAIT ,
612
+ SNSR_SOCK_FIN_WAIT ,
613
+ SNSR_SOCK_CLOSE_WAIT ,
614
+ SNSR_SOCK_CLOSING ,
615
+ ):
580
616
if self ._debug :
581
617
print ("* Opening W5k Socket, protocol={}" .format (conn_mode ))
582
618
time .sleep (0.00025 )
@@ -624,7 +660,6 @@ def socket_read(self, socket_num, length):
624
660
625
661
# Check if there is data available on the socket
626
662
ret = self ._get_rx_rcv_size (socket_num )
627
- ret = int .from_bytes (ret , "b" )
628
663
if self ._debug :
629
664
print ("Bytes avail. on sock: " , ret )
630
665
if ret == 0 :
@@ -675,7 +710,7 @@ def read_udp(self, socket_num, length):
675
710
return ret , resp
676
711
return - 1
677
712
678
- def socket_write (self , socket_num , buffer ):
713
+ def socket_write (self , socket_num , buffer , timeout = 0 ):
679
714
"""Writes a bytearray to a provided socket."""
680
715
assert self .link_status , "Ethernet cable disconnected!"
681
716
assert socket_num <= self .max_sockets , "Provided socket exceeds max_sockets."
@@ -686,13 +721,16 @@ def socket_write(self, socket_num, buffer):
686
721
ret = SOCK_SIZE
687
722
else :
688
723
ret = len (buffer )
724
+ stamp = time .monotonic ()
689
725
690
726
# if buffer is available, start the transfer
691
727
free_size = self ._get_tx_free_size (socket_num )
692
728
while free_size < ret :
693
729
free_size = self ._get_tx_free_size (socket_num )
694
- status = self .socket_status (socket_num )
695
- if status not in (SNSR_SOCK_ESTABLISHED , SNSR_SOCK_CLOSE_WAIT ):
730
+ status = self .socket_status (socket_num )[0 ]
731
+ if status not in (SNSR_SOCK_ESTABLISHED , SNSR_SOCK_CLOSE_WAIT ) or (
732
+ timeout and time .monotonic () - stamp > timeout
733
+ ):
696
734
ret = 0
697
735
break
698
736
@@ -702,7 +740,7 @@ def socket_write(self, socket_num, buffer):
702
740
dst_addr = offset + (socket_num * 2048 + 0x8000 )
703
741
704
742
# update sn_tx_wr to the value + data size
705
- ptr += len (buffer )
743
+ ptr = ( ptr + len (buffer )) & 0xFFFF
706
744
self ._write_sntx_wr (socket_num , ptr )
707
745
708
746
cntl_byte = 0x14 + (socket_num << 5 )
@@ -715,7 +753,17 @@ def socket_write(self, socket_num, buffer):
715
753
while (
716
754
self ._read_socket (socket_num , REG_SNIR )[0 ] & SNIR_SEND_OK
717
755
) != SNIR_SEND_OK :
718
- if self .socket_status (socket_num ) == SNSR_SOCK_CLOSED :
756
+ if (
757
+ self .socket_status (socket_num )[0 ]
758
+ in (
759
+ SNSR_SOCK_CLOSED ,
760
+ SNSR_SOCK_TIME_WAIT ,
761
+ SNSR_SOCK_FIN_WAIT ,
762
+ SNSR_SOCK_CLOSE_WAIT ,
763
+ SNSR_SOCK_CLOSING ,
764
+ )
765
+ or (timeout and time .monotonic () - stamp > timeout )
766
+ ):
719
767
# self.socket_close(socket_num)
720
768
return 0
721
769
time .sleep (0.01 )
@@ -733,17 +781,17 @@ def _get_rx_rcv_size(self, sock):
733
781
val_1 = self ._read_snrx_rsr (sock )
734
782
if val_1 != 0 :
735
783
val = self ._read_snrx_rsr (sock )
736
- return val
784
+ return int . from_bytes ( val , "b" )
737
785
738
786
def _get_tx_free_size (self , sock ):
739
787
"""Get free size of sock's tx buffer block."""
740
788
val = 0
741
- val_1 = 0
789
+ val_1 = self . _read_sntx_fsr ( sock )
742
790
while val != val_1 :
743
791
val_1 = self ._read_sntx_fsr (sock )
744
792
if val_1 != 0 :
745
793
val = self ._read_sntx_fsr (sock )
746
- return val
794
+ return int . from_bytes ( val , "b" )
747
795
748
796
def _read_snrx_rd (self , sock ):
749
797
self ._pbuff [0 ] = self ._read_socket (sock , REG_SNRX_RD )[0 ]
@@ -809,12 +857,10 @@ def _read_sncr(self, sock):
809
857
def _read_snmr (self , sock ):
810
858
return self ._read_socket (sock , REG_SNMR )
811
859
812
- def _write_socket (self , sock , address , data , length = None ):
860
+ def _write_socket (self , sock , address , data ):
813
861
"""Write to a W5k socket register."""
814
862
base = self ._ch_base_msb << 8
815
863
cntl_byte = (sock << 5 ) + 0x0C
816
- if length is None :
817
- return self .write (base + sock * CH_SIZE + address , cntl_byte , data )
818
864
return self .write (base + sock * CH_SIZE + address , cntl_byte , data )
819
865
820
866
def _read_socket (self , sock , address ):
0 commit comments