tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/wifinina/wifinina.go (about)

     1  // Package wifinina implements TCP wireless communication over SPI with an
     2  // attached separate ESP32 SoC using the Arduino WiFiNINA protocol.
     3  //
     4  // In order to use this driver, the ESP32 must be flashed with specific
     5  // firmware from Arduino.  For more information:
     6  // https://github.com/arduino/nina-fw
     7  //
     8  // 12/2022    sfeldma@gmail.com    Heavily modified to use netdev interface
     9  
    10  package wifinina // import "tinygo.org/x/drivers/wifinina"
    11  
    12  import (
    13  	"encoding/binary"
    14  	"encoding/hex"
    15  	"fmt"
    16  	"io"
    17  	"machine"
    18  	"math/bits"
    19  	"net"
    20  	"net/netip"
    21  	"sync"
    22  	"time"
    23  
    24  	"tinygo.org/x/drivers"
    25  	"tinygo.org/x/drivers/netdev"
    26  	"tinygo.org/x/drivers/netlink"
    27  )
    28  
    29  var _debug debug = debugBasic
    30  
    31  //var _debug debug = debugBasic | debugNetdev
    32  //var _debug debug = debugBasic | debugNetdev | debugCmd
    33  //var _debug debug = debugBasic | debugNetdev | debugCmd | debugDetail
    34  
    35  var (
    36  	driverName = "Tinygo ESP32 Wifi network device driver (WiFiNINA)"
    37  )
    38  
    39  const (
    40  	maxNetworks = 10
    41  
    42  	statusNoShield       connectionStatus = 255
    43  	statusIdle           connectionStatus = 0
    44  	statusNoSSIDAvail    connectionStatus = 1
    45  	statusScanCompleted  connectionStatus = 2
    46  	statusConnected      connectionStatus = 3
    47  	statusConnectFailed  connectionStatus = 4
    48  	statusConnectionLost connectionStatus = 5
    49  	statusDisconnected   connectionStatus = 6
    50  	statusAPListening    connectionStatus = 7
    51  	statusAPConnected    connectionStatus = 8
    52  	statusAPFailed       connectionStatus = 9
    53  
    54  	encTypeTKIP encryptionType = 2
    55  	encTypeCCMP encryptionType = 4
    56  	encTypeWEP  encryptionType = 5
    57  	encTypeNone encryptionType = 7
    58  	encTypeAuto encryptionType = 8
    59  
    60  	tcpStateClosed      = 0
    61  	tcpStateListen      = 1
    62  	tcpStateSynSent     = 2
    63  	tcpStateSynRcvd     = 3
    64  	tcpStateEstablished = 4
    65  	tcpStateFinWait1    = 5
    66  	tcpStateFinWait2    = 6
    67  	tcpStateCloseWait   = 7
    68  	tcpStateClosing     = 8
    69  	tcpStateLastACK     = 9
    70  	tcpStateTimeWait    = 10
    71  
    72  	flagCmd   = 0
    73  	flagReply = 1 << 7
    74  	flagData  = 0x40
    75  
    76  	cmdStart = 0xE0
    77  	cmdEnd   = 0xEE
    78  	cmdErr   = 0xEF
    79  
    80  	dummyData = 0xFF
    81  
    82  	cmdSetNet            = 0x10
    83  	cmdSetPassphrase     = 0x11
    84  	cmdSetKey            = 0x12
    85  	cmdSetIPConfig       = 0x14
    86  	cmdSetDNSConfig      = 0x15
    87  	cmdSetHostname       = 0x16
    88  	cmdSetPowerMode      = 0x17
    89  	cmdSetAPNet          = 0x18
    90  	cmdSetAPPassphrase   = 0x19
    91  	cmdSetDebug          = 0x1A
    92  	cmdGetTemperature    = 0x1B
    93  	cmdGetReasonCode     = 0x1F
    94  	cmdGetConnStatus     = 0x20
    95  	cmdGetIPAddr         = 0x21
    96  	cmdGetMACAddr        = 0x22
    97  	cmdGetCurrSSID       = 0x23
    98  	cmdGetCurrBSSID      = 0x24
    99  	cmdGetCurrRSSI       = 0x25
   100  	cmdGetCurrEncrType   = 0x26
   101  	cmdScanNetworks      = 0x27
   102  	cmdStartServerTCP    = 0x28
   103  	cmdGetStateTCP       = 0x29
   104  	cmdDataSentTCP       = 0x2A
   105  	cmdAvailDataTCP      = 0x2B
   106  	cmdGetDataTCP        = 0x2C
   107  	cmdStartClientTCP    = 0x2D
   108  	cmdStopClientTCP     = 0x2E
   109  	cmdGetClientStateTCP = 0x2F
   110  	cmdDisconnect        = 0x30
   111  	cmdGetIdxRSSI        = 0x32
   112  	cmdGetIdxEncrType    = 0x33
   113  	cmdReqHostByName     = 0x34
   114  	cmdGetHostByName     = 0x35
   115  	cmdStartScanNetworks = 0x36
   116  	cmdGetFwVersion      = 0x37
   117  	cmdSendDataUDP       = 0x39
   118  	cmdGetRemoteData     = 0x3A
   119  	cmdGetTime           = 0x3B
   120  	cmdGetIdxBSSID       = 0x3C
   121  	cmdGetIdxChannel     = 0x3D
   122  	cmdPing              = 0x3E
   123  	cmdGetSocket         = 0x3F
   124  
   125  	// All commands with DATA_FLAG 0x4x send a 16bit Len
   126  	cmdSendDataTCP   = 0x44
   127  	cmdGetDatabufTCP = 0x45
   128  	cmdInsertDataBuf = 0x46
   129  
   130  	// Regular format commands
   131  	cmdSetPinMode      = 0x50
   132  	cmdSetDigitalWrite = 0x51
   133  	cmdSetAnalogWrite  = 0x52
   134  
   135  	errTimeoutChipReady  hwerr = 0x01
   136  	errTimeoutChipSelect hwerr = 0x02
   137  	errCheckStartCmd     hwerr = 0x03
   138  	errWaitRsp           hwerr = 0x04
   139  	errUnexpectedLength  hwerr = 0xE0
   140  	errNoParamsReturned  hwerr = 0xE1
   141  	errIncorrectSentinel hwerr = 0xE2
   142  	errCmdErrorReceived  hwerr = 0xEF
   143  	errNotImplemented    hwerr = 0xF0
   144  	errUnknownHost       hwerr = 0xF1
   145  	errSocketAlreadySet  hwerr = 0xF2
   146  	errConnectionTimeout hwerr = 0xF3
   147  	errNoData            hwerr = 0xF4
   148  	errDataNotWritten    hwerr = 0xF5
   149  	errCheckDataError    hwerr = 0xF6
   150  	errBufferTooSmall    hwerr = 0xF7
   151  	errNoSocketAvail     hwerr = 0xFF
   152  
   153  	noSocketAvail sock = 0xFF
   154  )
   155  
   156  const (
   157  	protoModeTCP = iota
   158  	protoModeUDP
   159  	protoModeTLS
   160  	protoModeMul
   161  )
   162  
   163  type connectionStatus uint8
   164  type encryptionType uint8
   165  type sock uint8
   166  type hwerr uint8
   167  
   168  type Socket struct {
   169  	protocol        int
   170  	clientConnected bool
   171  	laddr           netip.AddrPort // Set in Bind()
   172  	raddr           netip.AddrPort // Set in Connect()
   173  	sock                           // Device socket, as returned from w.getSocket()
   174  }
   175  
   176  type Config struct {
   177  	// SPI config
   178  	Spi  drivers.SPI
   179  	Freq uint32
   180  	Sdo  machine.Pin
   181  	Sdi  machine.Pin
   182  	Sck  machine.Pin
   183  
   184  	// Device config
   185  	Cs     machine.Pin
   186  	Ack    machine.Pin
   187  	Gpio0  machine.Pin
   188  	Resetn machine.Pin
   189  	// ResetIsHigh controls if the RESET signal to the processor should be
   190  	// High or Low (the default). Set this to true for boards such as the
   191  	// Arduino MKR 1010, where the reset signal needs to go high instead of
   192  	// low.
   193  	ResetIsHigh bool
   194  }
   195  
   196  type wifinina struct {
   197  	cfg      *Config
   198  	notifyCb func(netlink.Event)
   199  	mu       sync.Mutex
   200  
   201  	spi    drivers.SPI
   202  	cs     machine.Pin
   203  	ack    machine.Pin
   204  	gpio0  machine.Pin
   205  	resetn machine.Pin
   206  
   207  	buf   [64]byte
   208  	ssids [maxNetworks]string
   209  
   210  	params *netlink.ConnectParams
   211  
   212  	netConnected bool
   213  	driverShown  bool
   214  	deviceShown  bool
   215  	spiSetup     bool
   216  
   217  	killWatchdog chan bool
   218  	fault        error
   219  
   220  	sockets map[int]*Socket // keyed by sockfd
   221  }
   222  
   223  func New(cfg *Config) *wifinina {
   224  	w := wifinina{
   225  		cfg:          cfg,
   226  		sockets:      make(map[int]*Socket),
   227  		killWatchdog: make(chan bool),
   228  		cs:           cfg.Cs,
   229  		ack:          cfg.Ack,
   230  		gpio0:        cfg.Gpio0,
   231  		resetn:       cfg.Resetn,
   232  	}
   233  
   234  	return &w
   235  }
   236  
   237  func (err hwerr) Error() string {
   238  	return "[wifinina] error: 0x" + hex.EncodeToString([]byte{uint8(err)})
   239  }
   240  
   241  func (w *wifinina) reason() string {
   242  	reason := w.getReasonCode()
   243  	switch reason {
   244  	case 0:
   245  		return "unknown failure"
   246  	case 201:
   247  		return "no AP found"
   248  	case 202:
   249  		return "auth failed"
   250  	}
   251  	return fmt.Sprintf("%d", reason)
   252  }
   253  
   254  func (w *wifinina) connectToAP() error {
   255  
   256  	timeout := w.params.ConnectTimeout
   257  	if timeout == 0 {
   258  		timeout = netlink.DefaultConnectTimeout
   259  	}
   260  
   261  	if len(w.params.Ssid) == 0 {
   262  		return netlink.ErrMissingSSID
   263  	}
   264  
   265  	if debugging(debugBasic) {
   266  		fmt.Printf("Connecting to Wifi SSID '%s'...", w.params.Ssid)
   267  	}
   268  
   269  	start := time.Now()
   270  
   271  	// Start the connection process
   272  	w.setPassphrase(w.params.Ssid, w.params.Passphrase)
   273  
   274  	// Check if we connected
   275  	for {
   276  		status := w.getConnectionStatus()
   277  		switch status {
   278  		case statusConnected:
   279  			if debugging(debugBasic) {
   280  				fmt.Printf("CONNECTED\r\n")
   281  			}
   282  			if w.notifyCb != nil {
   283  				w.notifyCb(netlink.EventNetUp)
   284  			}
   285  			return nil
   286  		case statusConnectFailed:
   287  			if debugging(debugBasic) {
   288  				fmt.Printf("FAILED (%s)\r\n", w.reason())
   289  			}
   290  			return netlink.ErrConnectFailed
   291  		}
   292  		if time.Since(start) > timeout {
   293  			break
   294  		}
   295  		time.Sleep(1 * time.Second)
   296  	}
   297  
   298  	if debugging(debugBasic) {
   299  		fmt.Printf("FAILED (timed out)\r\n")
   300  	}
   301  
   302  	return netlink.ErrConnectTimeout
   303  }
   304  
   305  func (w *wifinina) startAP() error {
   306  	timeout := w.params.ConnectTimeout
   307  	if timeout == 0 {
   308  		timeout = netlink.DefaultConnectTimeout
   309  	}
   310  
   311  	if len(w.params.Ssid) == 0 {
   312  		return netlink.ErrMissingSSID
   313  	}
   314  
   315  	if debugging(debugBasic) {
   316  		fmt.Printf("Starting Wifi AP as SSID '%s'...", w.params.Ssid)
   317  	}
   318  
   319  	start := time.Now()
   320  
   321  	// Start the connection process
   322  	switch {
   323  	case w.params.Passphrase != "":
   324  		w.setPassphraseForAP(w.params.Ssid, w.params.Passphrase)
   325  	default:
   326  		w.setNetworkForAP(w.params.Ssid)
   327  	}
   328  
   329  	// Check if we are listening
   330  	for {
   331  		status := w.getConnectionStatus()
   332  		switch status {
   333  		case statusAPListening:
   334  			if debugging(debugBasic) {
   335  				fmt.Printf("LISTENING\r\n")
   336  			}
   337  			if w.notifyCb != nil {
   338  				w.notifyCb(netlink.EventNetUp)
   339  			}
   340  			return nil
   341  		case statusAPFailed:
   342  			if debugging(debugBasic) {
   343  				fmt.Printf("FAILED (%s)\r\n", w.reason())
   344  			}
   345  			return netlink.ErrConnectFailed
   346  		}
   347  		if time.Since(start) > timeout {
   348  			break
   349  		}
   350  		time.Sleep(1 * time.Second)
   351  	}
   352  
   353  	if debugging(debugBasic) {
   354  		fmt.Printf("FAILED (timed out)\r\n")
   355  	}
   356  
   357  	return netlink.ErrConnectTimeout
   358  }
   359  
   360  func (w *wifinina) netDisconnect() {
   361  	w.disconnect()
   362  }
   363  
   364  func (w *wifinina) showDriver() {
   365  	if w.driverShown {
   366  		return
   367  	}
   368  	if debugging(debugBasic) {
   369  		fmt.Printf("\r\n")
   370  		fmt.Printf("%s\r\n\r\n", driverName)
   371  		fmt.Printf("Driver version           : %s\r\n", drivers.Version)
   372  	}
   373  	w.driverShown = true
   374  }
   375  
   376  func (w *wifinina) setupSPI() {
   377  	if w.spiSetup {
   378  		return
   379  	}
   380  	spi := machine.NINA_SPI
   381  	spi.Configure(machine.SPIConfig{
   382  		Frequency: w.cfg.Freq,
   383  		SDO:       w.cfg.Sdo,
   384  		SDI:       w.cfg.Sdi,
   385  		SCK:       w.cfg.Sck,
   386  	})
   387  	w.spi = spi
   388  	w.spiSetup = true
   389  }
   390  
   391  func (w *wifinina) start() {
   392  
   393  	pinUseDevice(w)
   394  
   395  	w.cs.Configure(machine.PinConfig{Mode: machine.PinOutput})
   396  	w.ack.Configure(machine.PinConfig{Mode: machine.PinInput})
   397  	w.resetn.Configure(machine.PinConfig{Mode: machine.PinOutput})
   398  	w.gpio0.Configure(machine.PinConfig{Mode: machine.PinOutput})
   399  
   400  	w.gpio0.High()
   401  	w.cs.High()
   402  	w.resetn.Set(w.cfg.ResetIsHigh)
   403  	time.Sleep(10 * time.Millisecond)
   404  	w.resetn.Set(!w.cfg.ResetIsHigh)
   405  	time.Sleep(750 * time.Millisecond)
   406  
   407  	w.gpio0.Low()
   408  	w.gpio0.Configure(machine.PinConfig{Mode: machine.PinInput})
   409  }
   410  
   411  func (w *wifinina) stop() {
   412  	w.resetn.Low()
   413  	w.cs.Configure(machine.PinConfig{Mode: machine.PinInput})
   414  }
   415  
   416  func (w *wifinina) showDevice() {
   417  	if w.deviceShown {
   418  		return
   419  	}
   420  	if debugging(debugBasic) {
   421  		fmt.Printf("ESP32 firmware version   : %s\r\n", w.getFwVersion())
   422  		mac := w.getMACAddr()
   423  		fmt.Printf("MAC address              : %s\r\n", mac.String())
   424  		fmt.Printf("\r\n")
   425  	}
   426  	w.deviceShown = true
   427  }
   428  
   429  func (w *wifinina) showIP() {
   430  	if debugging(debugBasic) {
   431  		ip, subnet, gateway := w.getIP()
   432  		fmt.Printf("\r\n")
   433  		fmt.Printf("DHCP-assigned IP         : %s\r\n", ip)
   434  		fmt.Printf("DHCP-assigned subnet     : %s\r\n", subnet)
   435  		fmt.Printf("DHCP-assigned gateway    : %s\r\n", gateway)
   436  		fmt.Printf("\r\n")
   437  	}
   438  }
   439  
   440  func (w *wifinina) networkDown() bool {
   441  	switch w.getConnectionStatus() {
   442  	case statusConnected, statusAPListening, statusAPConnected:
   443  		return false
   444  	default:
   445  		return true
   446  	}
   447  }
   448  
   449  func (w *wifinina) watchdog() {
   450  	ticker := time.NewTicker(w.params.WatchdogTimeout)
   451  	for {
   452  		select {
   453  		case <-w.killWatchdog:
   454  			return
   455  		case <-ticker.C:
   456  			w.mu.Lock()
   457  			if w.fault != nil {
   458  				if debugging(debugBasic) {
   459  					fmt.Printf("Watchdog: FAULT: %s\r\n", w.fault)
   460  				}
   461  				w.netDisconnect()
   462  				w.netConnect(true)
   463  				w.fault = nil
   464  			} else if w.networkDown() {
   465  				if debugging(debugBasic) {
   466  					fmt.Printf("Watchdog: Wifi NOT CONNECTED, trying again...\r\n")
   467  				}
   468  				if w.notifyCb != nil {
   469  					w.notifyCb(netlink.EventNetDown)
   470  				}
   471  				w.netConnect(false)
   472  			}
   473  			w.mu.Unlock()
   474  		}
   475  	}
   476  }
   477  
   478  func (w *wifinina) netConnect(reset bool) error {
   479  	if reset {
   480  		w.start()
   481  	}
   482  	w.showDevice()
   483  
   484  retry:
   485  	for i := 0; w.params.Retries == 0 || i < w.params.Retries; i++ {
   486  		switch w.params.ConnectMode {
   487  		case netlink.ConnectModeAP:
   488  			if err := w.startAP(); err != nil {
   489  				switch err {
   490  				case netlink.ErrConnectTimeout, netlink.ErrConnectFailed:
   491  					continue
   492  				}
   493  				return err
   494  			}
   495  			break retry
   496  		default:
   497  			if err := w.connectToAP(); err != nil {
   498  				switch err {
   499  				case netlink.ErrConnectTimeout, netlink.ErrConnectFailed:
   500  					continue
   501  				}
   502  				return err
   503  			}
   504  			break retry
   505  		}
   506  	}
   507  
   508  	if w.networkDown() {
   509  		return netlink.ErrConnectFailed
   510  	}
   511  
   512  	w.showIP()
   513  	return nil
   514  }
   515  
   516  func (w *wifinina) NetConnect(params *netlink.ConnectParams) error {
   517  
   518  	w.mu.Lock()
   519  	defer w.mu.Unlock()
   520  
   521  	if w.netConnected {
   522  		return netlink.ErrConnected
   523  	}
   524  
   525  	w.params = params
   526  
   527  	w.showDriver()
   528  	w.setupSPI()
   529  
   530  	if err := w.netConnect(true); err != nil {
   531  		return err
   532  	}
   533  
   534  	w.netConnected = true
   535  
   536  	if w.params.WatchdogTimeout != 0 {
   537  		go w.watchdog()
   538  	}
   539  
   540  	return nil
   541  }
   542  
   543  func (w *wifinina) NetDisconnect() {
   544  
   545  	w.mu.Lock()
   546  	defer w.mu.Unlock()
   547  
   548  	if !w.netConnected {
   549  		return
   550  	}
   551  
   552  	if w.params.WatchdogTimeout != 0 {
   553  		w.killWatchdog <- true
   554  	}
   555  
   556  	w.netDisconnect()
   557  	w.stop()
   558  
   559  	w.netConnected = false
   560  
   561  	if debugging(debugBasic) {
   562  		fmt.Printf("\r\nDisconnected from Wifi SSID '%s'\r\n\r\n", w.params.Ssid)
   563  	}
   564  
   565  	if w.notifyCb != nil {
   566  		w.notifyCb(netlink.EventNetDown)
   567  	}
   568  }
   569  
   570  func (w *wifinina) NetNotify(cb func(netlink.Event)) {
   571  	w.notifyCb = cb
   572  }
   573  
   574  func (w *wifinina) GetHostByName(name string) (netip.Addr, error) {
   575  
   576  	if debugging(debugNetdev) {
   577  		fmt.Printf("[GetHostByName] name: %s\r\n", name)
   578  	}
   579  
   580  	// If it's already in dotted-decimal notation, return a copy
   581  	// per gethostbyname(3).
   582  	if ip, err := netip.ParseAddr(name); err == nil {
   583  		return ip, nil
   584  	}
   585  
   586  	w.mu.Lock()
   587  	defer w.mu.Unlock()
   588  
   589  	ip := w.getHostByName(name)
   590  	if ip == "" {
   591  		return netip.Addr{}, netdev.ErrHostUnknown
   592  	}
   593  
   594  	addr, ok := netip.AddrFromSlice([]byte(ip))
   595  	if !ok {
   596  		return netip.Addr{}, netdev.ErrMalAddr
   597  	}
   598  
   599  	return addr, nil
   600  }
   601  
   602  func (w *wifinina) GetHardwareAddr() (net.HardwareAddr, error) {
   603  
   604  	if debugging(debugNetdev) {
   605  		fmt.Printf("[GetHardwareAddr]\r\n")
   606  	}
   607  
   608  	w.mu.Lock()
   609  	defer w.mu.Unlock()
   610  
   611  	return w.getMACAddr(), nil
   612  }
   613  
   614  func (w *wifinina) Addr() (netip.Addr, error) {
   615  
   616  	if debugging(debugNetdev) {
   617  		fmt.Printf("[GetIPAddr]\r\n")
   618  	}
   619  
   620  	w.mu.Lock()
   621  	defer w.mu.Unlock()
   622  
   623  	ip, _, _ := w.getIP()
   624  
   625  	return ip, nil
   626  }
   627  
   628  // newSockfd returns the next available sockfd, or -1 if none available
   629  func (w *wifinina) newSockfd() int {
   630  	if len(w.sockets) >= maxNetworks {
   631  		return -1
   632  	}
   633  	// Search for the next available sockfd starting at 0
   634  	for sockfd := 0; ; sockfd++ {
   635  		if _, ok := w.sockets[sockfd]; !ok {
   636  			return sockfd
   637  		}
   638  	}
   639  	return -1
   640  }
   641  
   642  // See man socket(2) for standard Berkely sockets for Socket, Bind, etc.
   643  // The driver strives to meet the function and semantics of socket(2).
   644  
   645  func (w *wifinina) Socket(domain int, stype int, protocol int) (int, error) {
   646  
   647  	if debugging(debugNetdev) {
   648  		fmt.Printf("[Socket] domain: %d, type: %d, protocol: %d\r\n",
   649  			domain, stype, protocol)
   650  	}
   651  
   652  	switch domain {
   653  	case netdev.AF_INET:
   654  	default:
   655  		return -1, netdev.ErrFamilyNotSupported
   656  	}
   657  
   658  	switch {
   659  	case protocol == netdev.IPPROTO_TCP && stype == netdev.SOCK_STREAM:
   660  	case protocol == netdev.IPPROTO_TLS && stype == netdev.SOCK_STREAM:
   661  	case protocol == netdev.IPPROTO_UDP && stype == netdev.SOCK_DGRAM:
   662  	default:
   663  		return -1, netdev.ErrProtocolNotSupported
   664  	}
   665  
   666  	w.mu.Lock()
   667  	defer w.mu.Unlock()
   668  
   669  	sockfd := w.newSockfd()
   670  	if sockfd == -1 {
   671  		return -1, netdev.ErrNoMoreSockets
   672  	}
   673  
   674  	w.sockets[sockfd] = &Socket{
   675  		protocol: protocol,
   676  		sock:     noSocketAvail,
   677  	}
   678  
   679  	if debugging(debugNetdev) {
   680  		fmt.Printf("[Socket] <-- sockfd %d\r\n", sockfd)
   681  	}
   682  
   683  	return sockfd, nil
   684  }
   685  
   686  func (w *wifinina) Bind(sockfd int, ip netip.AddrPort) error {
   687  
   688  	if debugging(debugNetdev) {
   689  		fmt.Printf("[Bind] sockfd: %d, addr: %s:%d\r\n", sockfd, ip.Addr(), ip.Port())
   690  	}
   691  
   692  	w.mu.Lock()
   693  	defer w.mu.Unlock()
   694  
   695  	socket, ok := w.sockets[sockfd]
   696  	if !ok {
   697  		return netdev.ErrInvalidSocketFd
   698  	}
   699  
   700  	switch socket.protocol {
   701  	case netdev.IPPROTO_TCP:
   702  	case netdev.IPPROTO_TLS:
   703  	case netdev.IPPROTO_UDP:
   704  		socket.sock = w.getSocket()
   705  		if socket.sock == noSocketAvail {
   706  			return netdev.ErrNoMoreSockets
   707  		}
   708  		w.startServer(socket.sock, ip.Port(), protoModeUDP)
   709  	}
   710  
   711  	socket.laddr = ip
   712  
   713  	return nil
   714  }
   715  
   716  func toUint32(ip [4]byte) uint32 {
   717  	return uint32(ip[0])<<24 |
   718  		uint32(ip[1])<<16 |
   719  		uint32(ip[2])<<8 |
   720  		uint32(ip[3])
   721  }
   722  
   723  func (w *wifinina) Connect(sockfd int, host string, ip netip.AddrPort) error {
   724  
   725  	if debugging(debugNetdev) {
   726  		if host == "" {
   727  			fmt.Printf("[Connect] sockfd: %d, addr: %s\r\n", sockfd, ip)
   728  		} else {
   729  			fmt.Printf("[Connect] sockfd: %d, host: %s:%d\r\n", sockfd, host, ip.Port())
   730  		}
   731  	}
   732  
   733  	w.mu.Lock()
   734  	defer w.mu.Unlock()
   735  
   736  	socket, ok := w.sockets[sockfd]
   737  	if !ok {
   738  		return netdev.ErrInvalidSocketFd
   739  	}
   740  
   741  	// Start the connection
   742  	switch socket.protocol {
   743  
   744  	case netdev.IPPROTO_TCP:
   745  		socket.sock = w.getSocket()
   746  		if socket.sock == noSocketAvail {
   747  			return netdev.ErrNoMoreSockets
   748  		}
   749  		w.startClient(socket.sock, "", toUint32(ip.Addr().As4()), ip.Port(), protoModeTCP)
   750  
   751  	case netdev.IPPROTO_TLS:
   752  		socket.sock = w.getSocket()
   753  		if socket.sock == noSocketAvail {
   754  			return netdev.ErrNoMoreSockets
   755  		}
   756  		w.startClient(socket.sock, host, 0, ip.Port(), protoModeTLS)
   757  
   758  	case netdev.IPPROTO_UDP:
   759  		if socket.sock == noSocketAvail {
   760  			return fmt.Errorf("Must Bind before Connecting")
   761  		}
   762  		// See start in sendUDP()
   763  		socket.raddr = ip
   764  		socket.clientConnected = true
   765  		return nil
   766  	}
   767  
   768  	if w.getClientState(socket.sock) == tcpStateEstablished {
   769  		socket.clientConnected = true
   770  		return nil
   771  	}
   772  
   773  	if host == "" {
   774  		return fmt.Errorf("Connect to %s failed", ip)
   775  	} else {
   776  		return fmt.Errorf("Connect to %s:%d failed", host, ip.Port())
   777  	}
   778  }
   779  
   780  func (w *wifinina) Listen(sockfd int, backlog int) error {
   781  
   782  	if debugging(debugNetdev) {
   783  		fmt.Printf("[Listen] sockfd: %d\r\n", sockfd)
   784  	}
   785  
   786  	w.mu.Lock()
   787  	defer w.mu.Unlock()
   788  
   789  	socket, ok := w.sockets[sockfd]
   790  	if !ok {
   791  		return netdev.ErrInvalidSocketFd
   792  	}
   793  
   794  	switch socket.protocol {
   795  	case netdev.IPPROTO_TCP:
   796  		socket.sock = w.getSocket()
   797  		if socket.sock == noSocketAvail {
   798  			return netdev.ErrNoMoreSockets
   799  		}
   800  		w.startServer(socket.sock, socket.laddr.Port(), protoModeTCP)
   801  	case netdev.IPPROTO_UDP:
   802  	default:
   803  		return netdev.ErrProtocolNotSupported
   804  	}
   805  
   806  	return nil
   807  }
   808  
   809  func (w *wifinina) Accept(sockfd int) (int, netip.AddrPort, error) {
   810  
   811  	if debugging(debugNetdev) {
   812  		fmt.Printf("[Accept] sockfd: %d\r\n", sockfd)
   813  	}
   814  
   815  	w.mu.Lock()
   816  	defer w.mu.Unlock()
   817  
   818  	socket, ok := w.sockets[sockfd]
   819  	if !ok {
   820  		return -1, netip.AddrPort{}, netdev.ErrInvalidSocketFd
   821  	}
   822  
   823  	switch socket.protocol {
   824  	case netdev.IPPROTO_TCP:
   825  	default:
   826  		return -1, netip.AddrPort{}, netdev.ErrProtocolNotSupported
   827  	}
   828  
   829  skip:
   830  	for {
   831  		// Accept() will be sleeping most of the time, checking for
   832  		// new clients every 1/10 sec.
   833  		w.mu.Unlock()
   834  		time.Sleep(100 * time.Millisecond)
   835  		w.mu.Lock()
   836  
   837  		// Check if we've faulted
   838  		if w.fault != nil {
   839  			return -1, netip.AddrPort{}, w.fault
   840  		}
   841  
   842  		// Check if a client has data
   843  		var client sock = w.accept(socket.sock)
   844  		if client == noSocketAvail {
   845  			// None ready
   846  			continue
   847  		}
   848  
   849  		// If we already have a socket for the client, skip
   850  		for _, s := range w.sockets {
   851  			if s.sock == client {
   852  				continue skip
   853  			}
   854  		}
   855  
   856  		// Otherwise, create a new socket
   857  		clientfd := w.newSockfd()
   858  		if clientfd == -1 {
   859  			return -1, netip.AddrPort{}, netdev.ErrNoMoreSockets
   860  		}
   861  
   862  		w.sockets[clientfd] = &Socket{
   863  			protocol:        netdev.IPPROTO_TCP,
   864  			sock:            client,
   865  			clientConnected: true,
   866  		}
   867  
   868  		raddr := w.getRemoteData(client)
   869  
   870  		return clientfd, raddr, nil
   871  	}
   872  }
   873  
   874  func (w *wifinina) sockDown(socket *Socket) bool {
   875  	if socket.protocol == netdev.IPPROTO_UDP {
   876  		return false
   877  	}
   878  	return w.getClientState(socket.sock) != tcpStateEstablished
   879  }
   880  
   881  func (w *wifinina) sendTCP(sock sock, buf []byte, deadline time.Time) (int, error) {
   882  
   883  	var timeoutDataSent = 25
   884  
   885  	// Send it
   886  	n := int(w.sendData(sock, buf))
   887  	if n == 0 {
   888  		return -1, io.EOF
   889  	}
   890  
   891  	// Check if data was sent
   892  	for i := 0; i < timeoutDataSent; i++ {
   893  		sent := w.checkDataSent(sock)
   894  		if sent {
   895  			return n, nil
   896  		}
   897  
   898  		// Check if we've timed out
   899  		if !deadline.IsZero() {
   900  			if time.Now().After(deadline) {
   901  				return -1, netdev.ErrTimeout
   902  			}
   903  		}
   904  
   905  		// Check if socket went down
   906  		if w.getClientState(sock) != tcpStateEstablished {
   907  			return -1, io.EOF
   908  		}
   909  
   910  		// Check if we've faulted
   911  		if w.fault != nil {
   912  			return -1, w.fault
   913  		}
   914  
   915  		// Unlock while we sleep, so others can make progress
   916  		w.mu.Unlock()
   917  		time.Sleep(100 * time.Millisecond)
   918  		w.mu.Lock()
   919  	}
   920  
   921  	return -1, netdev.ErrTimeout
   922  }
   923  
   924  func (w *wifinina) sendUDP(sock sock, raddr netip.AddrPort, buf []byte, deadline time.Time) (int, error) {
   925  
   926  	// Start a client for each send
   927  	w.startClient(sock, "", toUint32(raddr.Addr().As4()), raddr.Port(), protoModeUDP)
   928  
   929  	// Queue it
   930  	ok := w.insertDataBuf(sock, buf)
   931  	if !ok {
   932  		return -1, fmt.Errorf("Insert UDP data failed, len(buf)=%d", len(buf))
   933  	}
   934  
   935  	// Send it
   936  	ok = w.sendUDPData(sock)
   937  	if !ok {
   938  		return -1, fmt.Errorf("Send UDP data failed, len(buf)=%d", len(buf))
   939  	}
   940  
   941  	return len(buf), nil
   942  }
   943  
   944  func (w *wifinina) sendChunk(sockfd int, buf []byte, deadline time.Time) (int, error) {
   945  	socket, ok := w.sockets[sockfd]
   946  	if !ok {
   947  		return -1, netdev.ErrInvalidSocketFd
   948  	}
   949  
   950  	// Check if we've timed out
   951  	if !deadline.IsZero() {
   952  		if time.Now().After(deadline) {
   953  			return -1, netdev.ErrTimeout
   954  		}
   955  	}
   956  
   957  	switch socket.protocol {
   958  	case netdev.IPPROTO_TCP, netdev.IPPROTO_TLS:
   959  		return w.sendTCP(socket.sock, buf, deadline)
   960  	case netdev.IPPROTO_UDP:
   961  		return w.sendUDP(socket.sock, socket.raddr, buf, deadline)
   962  	}
   963  
   964  	return -1, netdev.ErrProtocolNotSupported
   965  }
   966  
   967  func (w *wifinina) Send(sockfd int, buf []byte, flags int,
   968  	deadline time.Time) (int, error) {
   969  
   970  	if debugging(debugNetdev) {
   971  		fmt.Printf("[Send] sockfd: %d, len(buf): %d, flags: %d\r\n",
   972  			sockfd, len(buf), flags)
   973  	}
   974  
   975  	w.mu.Lock()
   976  	defer w.mu.Unlock()
   977  
   978  	// Break large bufs into chunks so we don't overrun the hw queue
   979  
   980  	chunkSize := 1436
   981  	for i := 0; i < len(buf); i += chunkSize {
   982  		end := i + chunkSize
   983  		if end > len(buf) {
   984  			end = len(buf)
   985  		}
   986  		_, err := w.sendChunk(sockfd, buf[i:end], deadline)
   987  		if err != nil {
   988  			return -1, err
   989  		}
   990  	}
   991  
   992  	return len(buf), nil
   993  }
   994  
   995  func (w *wifinina) Recv(sockfd int, buf []byte, flags int,
   996  	deadline time.Time) (int, error) {
   997  
   998  	if debugging(debugNetdev) {
   999  		fmt.Printf("[Recv] sockfd: %d, len(buf): %d, flags: %d\r\n",
  1000  			sockfd, len(buf), flags)
  1001  	}
  1002  
  1003  	w.mu.Lock()
  1004  	defer w.mu.Unlock()
  1005  
  1006  	socket, ok := w.sockets[sockfd]
  1007  	if !ok {
  1008  		return -1, netdev.ErrInvalidSocketFd
  1009  	}
  1010  
  1011  	// Limit max read size to chunk large read requests
  1012  	var max = len(buf)
  1013  	if max > 1436 {
  1014  		max = 1436
  1015  	}
  1016  
  1017  	for {
  1018  		// Check if we've timed out
  1019  		if !deadline.IsZero() {
  1020  			if time.Now().After(deadline) {
  1021  				return -1, netdev.ErrTimeout
  1022  			}
  1023  		}
  1024  
  1025  		// Receive into buf, if any data available.  It's ok if no data
  1026  		// is available, we'll just sleep a bit and recheck.  Recv()
  1027  		// doesn't return unless there is data, even a single byte, or
  1028  		// on error such as timeout or EOF.
  1029  
  1030  		n := int(w.getDataBuf(socket.sock, buf[:max]))
  1031  		if n > 0 {
  1032  			if debugging(debugNetdev) {
  1033  				fmt.Printf("[<--Recv] sockfd: %d, n: %d\r\n",
  1034  					sockfd, n)
  1035  			}
  1036  			return n, nil
  1037  		}
  1038  
  1039  		// Check if socket went down
  1040  		if w.sockDown(socket) {
  1041  			// Get any last bytes
  1042  			n = int(w.getDataBuf(socket.sock, buf[:max]))
  1043  			if debugging(debugNetdev) {
  1044  				fmt.Printf("[<--Recv] sockfd: %d, n: %d, EOF\r\n",
  1045  					sockfd, n)
  1046  			}
  1047  			if n > 0 {
  1048  				return n, io.EOF
  1049  			}
  1050  			return -1, io.EOF
  1051  		}
  1052  
  1053  		// Check if we've faulted
  1054  		if w.fault != nil {
  1055  			return -1, w.fault
  1056  		}
  1057  
  1058  		// Unlock while we sleep, so others can make progress
  1059  		w.mu.Unlock()
  1060  		time.Sleep(100 * time.Millisecond)
  1061  		w.mu.Lock()
  1062  	}
  1063  }
  1064  
  1065  func (w *wifinina) Close(sockfd int) error {
  1066  
  1067  	if debugging(debugNetdev) {
  1068  		fmt.Printf("[Close] sockfd: %d\r\n", sockfd)
  1069  	}
  1070  
  1071  	w.mu.Lock()
  1072  	defer w.mu.Unlock()
  1073  
  1074  	socket, ok := w.sockets[sockfd]
  1075  	if !ok {
  1076  		return netdev.ErrInvalidSocketFd
  1077  	}
  1078  
  1079  	if socket.clientConnected {
  1080  		w.stopClient(socket.sock)
  1081  	}
  1082  
  1083  	delete(w.sockets, sockfd)
  1084  
  1085  	return nil
  1086  }
  1087  
  1088  func (w *wifinina) SetSockOpt(sockfd int, level int, opt int, value interface{}) error {
  1089  
  1090  	if debugging(debugNetdev) {
  1091  		fmt.Printf("[SetSockOpt] sockfd: %d\r\n", sockfd)
  1092  	}
  1093  
  1094  	return netdev.ErrNotSupported
  1095  }
  1096  
  1097  func (w *wifinina) startClient(sock sock, hostname string, addr uint32, port uint16, mode uint8) {
  1098  	if debugging(debugCmd) {
  1099  		fmt.Printf("    [cmdStartClientTCP] sock: %d, hostname: \"%s\", addr: % 02X, port: %d, mode: %d\r\n",
  1100  			sock, hostname, addr, port, mode)
  1101  	}
  1102  
  1103  	w.waitForChipReady()
  1104  	w.spiChipSelect()
  1105  
  1106  	if len(hostname) > 0 {
  1107  		w.sendCmd(cmdStartClientTCP, 5)
  1108  		w.sendParamStr(hostname, false)
  1109  	} else {
  1110  		w.sendCmd(cmdStartClientTCP, 4)
  1111  	}
  1112  
  1113  	w.sendParam32(addr, false)
  1114  	w.sendParam16(port, false)
  1115  	w.sendParam8(uint8(sock), false)
  1116  	w.sendParam8(mode, true)
  1117  
  1118  	if len(hostname) > 0 {
  1119  		w.padTo4(17 + len(hostname))
  1120  	}
  1121  
  1122  	w.spiChipDeselect()
  1123  	w.waitRspCmd1(cmdStartClientTCP)
  1124  }
  1125  
  1126  func (w *wifinina) getSocket() sock {
  1127  	if debugging(debugCmd) {
  1128  		fmt.Printf("    [cmdGetSocket]\r\n")
  1129  	}
  1130  	return sock(w.getUint8(w.req0(cmdGetSocket)))
  1131  }
  1132  
  1133  func (w *wifinina) getClientState(sock sock) uint8 {
  1134  	if debugging(debugCmd) {
  1135  		fmt.Printf("    [cmdGetClientStateTCP] sock: %d\r\n", sock)
  1136  	}
  1137  	return w.getUint8(w.reqUint8(cmdGetClientStateTCP, uint8(sock)))
  1138  }
  1139  
  1140  func (w *wifinina) sendData(sock sock, buf []byte) uint16 {
  1141  	if debugging(debugCmd) {
  1142  		fmt.Printf("    [cmdSendDataTCP] sock: %d, len(buf): %d\r\n",
  1143  			sock, len(buf))
  1144  	}
  1145  
  1146  	w.waitForChipReady()
  1147  	w.spiChipSelect()
  1148  	l := w.sendCmd(cmdSendDataTCP, 2)
  1149  	l += w.sendParamBuf([]byte{uint8(sock)}, false)
  1150  	l += w.sendParamBuf(buf, true)
  1151  	w.addPadding(l)
  1152  	w.spiChipDeselect()
  1153  
  1154  	sent := w.getUint16(w.waitRspCmd1(cmdSendDataTCP))
  1155  	return bits.RotateLeft16(sent, 8)
  1156  }
  1157  
  1158  func (w *wifinina) checkDataSent(sock sock) bool {
  1159  	if debugging(debugCmd) {
  1160  		fmt.Printf("    [cmdDataSentTCP] sock: %d\r\n", sock)
  1161  	}
  1162  	sent := w.getUint8(w.reqUint8(cmdDataSentTCP, uint8(sock)))
  1163  	return sent > 0
  1164  }
  1165  
  1166  func (w *wifinina) getDataBuf(sock sock, buf []byte) uint16 {
  1167  	if debugging(debugCmd) {
  1168  		fmt.Printf("    [cmdGetDatabufTCP] sock: %d, len(buf): %d\r\n",
  1169  			sock, len(buf))
  1170  	}
  1171  
  1172  	w.waitForChipReady()
  1173  	w.spiChipSelect()
  1174  	p := uint16(len(buf))
  1175  	l := w.sendCmd(cmdGetDatabufTCP, 2)
  1176  	l += w.sendParamBuf([]byte{uint8(sock)}, false)
  1177  	l += w.sendParamBuf([]byte{uint8(p & 0x00FF), uint8((p) >> 8)}, true)
  1178  	w.addPadding(l)
  1179  	w.spiChipDeselect()
  1180  
  1181  	w.waitForChipReady()
  1182  	w.spiChipSelect()
  1183  	n := w.waitRspBuf16(cmdGetDatabufTCP, buf)
  1184  	w.spiChipDeselect()
  1185  
  1186  	if n > 0 {
  1187  		if debugging(debugCmd) {
  1188  			fmt.Printf("    [<--cmdGetDatabufTCP] sock: %d, got n: %d\r\n",
  1189  				sock, n)
  1190  		}
  1191  	}
  1192  
  1193  	return n
  1194  }
  1195  
  1196  func (w *wifinina) stopClient(sock sock) {
  1197  	if debugging(debugCmd) {
  1198  		fmt.Printf("    [cmdStopClientTCP] sock: %d\r\n", sock)
  1199  	}
  1200  	w.getUint8(w.reqUint8(cmdStopClientTCP, uint8(sock)))
  1201  }
  1202  
  1203  func (w *wifinina) startServer(sock sock, port uint16, mode uint8) {
  1204  	if debugging(debugCmd) {
  1205  		fmt.Printf("    [cmdStartServerTCP] sock: %d, port: %d, mode: %d\r\n",
  1206  			sock, port, mode)
  1207  	}
  1208  
  1209  	w.waitForChipReady()
  1210  	w.spiChipSelect()
  1211  	l := w.sendCmd(cmdStartServerTCP, 3)
  1212  	l += w.sendParam16(port, false)
  1213  	l += w.sendParam8(uint8(sock), false)
  1214  	l += w.sendParam8(mode, true)
  1215  	w.addPadding(l)
  1216  	w.spiChipDeselect()
  1217  
  1218  	w.waitRspCmd1(cmdStartServerTCP)
  1219  }
  1220  
  1221  func (w *wifinina) accept(s sock) sock {
  1222  
  1223  	if debugging(debugCmd) {
  1224  		fmt.Printf("    [cmdAvailDataTCP] sock: %d\r\n", s)
  1225  	}
  1226  
  1227  	w.waitForChipReady()
  1228  	w.spiChipSelect()
  1229  	l := w.sendCmd(cmdAvailDataTCP, 1)
  1230  	l += w.sendParam8(uint8(s), true)
  1231  	w.addPadding(l)
  1232  	w.spiChipDeselect()
  1233  
  1234  	newsock16 := w.getUint16(w.waitRspCmd1(cmdAvailDataTCP))
  1235  	newsock := sock(uint8(bits.RotateLeft16(newsock16, 8)))
  1236  
  1237  	if newsock != noSocketAvail {
  1238  		if debugging(debugCmd) {
  1239  			fmt.Printf("    [cmdAvailDataTCP-->] sock: %d, got sock: %d\r\n",
  1240  				s, newsock)
  1241  		}
  1242  	}
  1243  
  1244  	return newsock
  1245  }
  1246  
  1247  func (w *wifinina) getRemoteData(s sock) netip.AddrPort {
  1248  
  1249  	if debugging(debugCmd) {
  1250  		fmt.Printf("    [cmdGetRemoteData] sock: %d\r\n", s)
  1251  	}
  1252  
  1253  	sl := make([]string, 2)
  1254  	l := w.reqRspStr1(cmdGetRemoteData, uint8(s), sl)
  1255  	if l != 2 {
  1256  		w.faultf("getRemoteData wanted l=2, got l=%d", l)
  1257  		return netip.AddrPort{}
  1258  	}
  1259  	ip, _ := netip.AddrFromSlice([]byte(sl[0])[:4])
  1260  	port := binary.BigEndian.Uint16([]byte(sl[1]))
  1261  	return netip.AddrPortFrom(ip, port)
  1262  }
  1263  
  1264  // insertDataBuf adds data to the buffer used for sending UDP data
  1265  func (w *wifinina) insertDataBuf(sock sock, buf []byte) bool {
  1266  
  1267  	if debugging(debugCmd) {
  1268  		fmt.Printf("    [cmdInsertDataBuf] sock: %d, len(buf): %d\r\n",
  1269  			sock, len(buf))
  1270  	}
  1271  
  1272  	w.waitForChipReady()
  1273  	w.spiChipSelect()
  1274  	l := w.sendCmd(cmdInsertDataBuf, 2)
  1275  	l += w.sendParamBuf([]byte{uint8(sock)}, false)
  1276  	l += w.sendParamBuf(buf, true)
  1277  	w.addPadding(l)
  1278  	w.spiChipDeselect()
  1279  
  1280  	n := w.getUint8(w.waitRspCmd1(cmdInsertDataBuf))
  1281  	return n == 1
  1282  }
  1283  
  1284  // sendUDPData sends the data previously added to the UDP buffer
  1285  func (w *wifinina) sendUDPData(sock sock) bool {
  1286  
  1287  	if debugging(debugCmd) {
  1288  		fmt.Printf("    [cmdSendDataUDP] sock: %d\r\n", sock)
  1289  	}
  1290  
  1291  	w.waitForChipReady()
  1292  	w.spiChipSelect()
  1293  	l := w.sendCmd(cmdSendDataUDP, 1)
  1294  	l += w.sendParam8(uint8(sock), true)
  1295  	w.addPadding(l)
  1296  	w.spiChipDeselect()
  1297  
  1298  	n := w.getUint8(w.waitRspCmd1(cmdSendDataUDP))
  1299  	return n == 1
  1300  }
  1301  
  1302  func (w *wifinina) disconnect() {
  1303  	if debugging(debugCmd) {
  1304  		fmt.Printf("    [cmdDisconnect]\r\n")
  1305  	}
  1306  	w.req1(cmdDisconnect)
  1307  }
  1308  
  1309  func (w *wifinina) getFwVersion() string {
  1310  	if debugging(debugCmd) {
  1311  		fmt.Printf("    [cmdGetFwVersion]\r\n")
  1312  	}
  1313  	return w.getString(w.req0(cmdGetFwVersion))
  1314  }
  1315  
  1316  func (w *wifinina) getConnectionStatus() connectionStatus {
  1317  	if debugging(debugCmd) {
  1318  		fmt.Printf("    [cmdGetConnStatus]\r\n")
  1319  	}
  1320  	status := w.getUint8(w.req0(cmdGetConnStatus))
  1321  	return connectionStatus(status)
  1322  }
  1323  
  1324  func (w *wifinina) getCurrentencryptionType() encryptionType {
  1325  	enctype := w.getUint8(w.req1(cmdGetCurrEncrType))
  1326  	return encryptionType(enctype)
  1327  }
  1328  
  1329  func (w *wifinina) getCurrentBSSID() net.HardwareAddr {
  1330  	return w.getMACAddress(w.req1(cmdGetCurrBSSID))
  1331  }
  1332  
  1333  func (w *wifinina) getCurrentRSSI() int32 {
  1334  	return w.getInt32(w.req1(cmdGetCurrRSSI))
  1335  }
  1336  
  1337  func (w *wifinina) getCurrentSSID() string {
  1338  	return w.getString(w.req1(cmdGetCurrSSID))
  1339  }
  1340  
  1341  func (w *wifinina) getMACAddr() net.HardwareAddr {
  1342  	if debugging(debugCmd) {
  1343  		fmt.Printf("    [cmdGetMACAddr]\r\n")
  1344  	}
  1345  	return w.getMACAddress(w.req1(cmdGetMACAddr))
  1346  }
  1347  
  1348  func (w *wifinina) faultf(f string, args ...any) {
  1349  	// Only record the first fault
  1350  	if w.fault == nil {
  1351  		w.fault = fmt.Errorf(f, args...)
  1352  	}
  1353  }
  1354  
  1355  func (w *wifinina) getIP() (ip, subnet, gateway netip.Addr) {
  1356  	if debugging(debugCmd) {
  1357  		fmt.Printf("    [cmdGetIPAddr]\r\n")
  1358  	}
  1359  	sl := make([]string, 3)
  1360  	l := w.reqRspStr1(cmdGetIPAddr, dummyData, sl)
  1361  	if l != 3 {
  1362  		w.faultf("getIP wanted l=3, got l=%d", l)
  1363  		return
  1364  	}
  1365  	ip, _ = netip.AddrFromSlice([]byte(sl[0])[:4])
  1366  	subnet, _ = netip.AddrFromSlice([]byte(sl[1])[:4])
  1367  	gateway, _ = netip.AddrFromSlice([]byte(sl[2])[:4])
  1368  	return
  1369  }
  1370  
  1371  func (w *wifinina) getHostByName(name string) string {
  1372  	if debugging(debugCmd) {
  1373  		fmt.Printf("    [cmdGetHostByName]\r\n")
  1374  	}
  1375  	ok := w.getUint8(w.reqStr(cmdReqHostByName, name))
  1376  	if ok != 1 {
  1377  		return ""
  1378  	}
  1379  	return w.getString(w.req0(cmdGetHostByName))
  1380  }
  1381  
  1382  func (w *wifinina) getNetworkBSSID(idx int) net.HardwareAddr {
  1383  	if idx < 0 || idx >= maxNetworks {
  1384  		return net.HardwareAddr{}
  1385  	}
  1386  	return w.getMACAddress(w.reqUint8(cmdGetIdxBSSID, uint8(idx)))
  1387  }
  1388  
  1389  func (w *wifinina) getNetworkChannel(idx int) uint8 {
  1390  	if idx < 0 || idx >= maxNetworks {
  1391  		return 0
  1392  	}
  1393  	return w.getUint8(w.reqUint8(cmdGetIdxChannel, uint8(idx)))
  1394  }
  1395  
  1396  func (w *wifinina) getNetworkEncrType(idx int) encryptionType {
  1397  	if idx < 0 || idx >= maxNetworks {
  1398  		return 0
  1399  	}
  1400  	enctype := w.getUint8(w.reqUint8(cmdGetIdxEncrType, uint8(idx)))
  1401  	return encryptionType(enctype)
  1402  }
  1403  
  1404  func (w *wifinina) getNetworkRSSI(idx int) int32 {
  1405  	if idx < 0 || idx >= maxNetworks {
  1406  		return 0
  1407  	}
  1408  	return w.getInt32(w.reqUint8(cmdGetIdxRSSI, uint8(idx)))
  1409  }
  1410  
  1411  func (w *wifinina) getNetworkSSID(idx int) string {
  1412  	if idx < 0 || idx >= maxNetworks {
  1413  		return ""
  1414  	}
  1415  	return w.ssids[idx]
  1416  }
  1417  
  1418  func (w *wifinina) getReasonCode() uint8 {
  1419  	return w.getUint8(w.req0(cmdGetReasonCode))
  1420  }
  1421  
  1422  // getTime is the time as a Unix timestamp
  1423  func (w *wifinina) getTime() uint32 {
  1424  	return w.getUint32(w.req0(cmdGetTime))
  1425  }
  1426  
  1427  func (w *wifinina) getTemperature() float32 {
  1428  	return w.getFloat32(w.req0(cmdGetTemperature))
  1429  }
  1430  
  1431  func (w *wifinina) setDebug(on bool) {
  1432  	var v uint8
  1433  	if on {
  1434  		v = 1
  1435  	}
  1436  	w.reqUint8(cmdSetDebug, v)
  1437  }
  1438  
  1439  func (w *wifinina) setNetwork(ssid string) {
  1440  	w.reqStr(cmdSetNet, ssid)
  1441  }
  1442  
  1443  func (w *wifinina) setPassphrase(ssid string, passphrase string) {
  1444  
  1445  	if debugging(debugCmd) {
  1446  		fmt.Printf("    [cmdSetPassphrase] ssid: %s, passphrase: ******\r\n",
  1447  			ssid)
  1448  	}
  1449  
  1450  	// Dont' show passphrase in debug output
  1451  	saveDebug := _debug
  1452  	_debug = _debug & ^debugDetail
  1453  	w.reqStr2(cmdSetPassphrase, ssid, passphrase)
  1454  	_debug = saveDebug
  1455  }
  1456  
  1457  func (w *wifinina) setKey(ssid string, index uint8, key string) {
  1458  
  1459  	w.waitForChipReady()
  1460  	w.spiChipSelect()
  1461  	w.sendCmd(cmdSetKey, 3)
  1462  	w.sendParamStr(ssid, false)
  1463  	w.sendParam8(index, false)
  1464  	w.sendParamStr(key, true)
  1465  	w.padTo4(8 + len(ssid) + len(key))
  1466  	w.spiChipDeselect()
  1467  
  1468  	w.waitRspCmd1(cmdSetKey)
  1469  }
  1470  
  1471  func (w *wifinina) setNetworkForAP(ssid string) {
  1472  	w.reqStr(cmdSetAPNet, ssid)
  1473  }
  1474  
  1475  func (w *wifinina) setPassphraseForAP(ssid string, passphrase string) {
  1476  	w.reqStr2(cmdSetAPPassphrase, ssid, passphrase)
  1477  }
  1478  
  1479  func (w *wifinina) setDNS(which uint8, dns1 uint32, dns2 uint32) {
  1480  	w.waitForChipReady()
  1481  	w.spiChipSelect()
  1482  	w.sendCmd(cmdSetDNSConfig, 3)
  1483  	w.sendParam8(which, false)
  1484  	w.sendParam32(dns1, false)
  1485  	w.sendParam32(dns2, true)
  1486  	//pad??
  1487  	w.spiChipDeselect()
  1488  
  1489  	w.waitRspCmd1(cmdSetDNSConfig)
  1490  }
  1491  
  1492  func (w *wifinina) setHostname(hostname string) {
  1493  	w.waitForChipReady()
  1494  	w.spiChipSelect()
  1495  	w.sendCmd(cmdSetHostname, 3)
  1496  	w.sendParamStr(hostname, true)
  1497  	w.padTo4(5 + len(hostname))
  1498  	w.spiChipDeselect()
  1499  
  1500  	w.waitRspCmd1(cmdSetHostname)
  1501  }
  1502  
  1503  func (w *wifinina) setPowerMode(mode uint8) {
  1504  	w.reqUint8(cmdSetPowerMode, mode)
  1505  }
  1506  
  1507  func (w *wifinina) scanNetworks() uint8 {
  1508  	return w.reqRspStr0(cmdScanNetworks, w.ssids[:])
  1509  }
  1510  
  1511  func (w *wifinina) startScanNetworks() uint8 {
  1512  	return w.getUint8(w.req0(cmdStartScanNetworks))
  1513  }
  1514  
  1515  func (w *wifinina) PinMode(pin uint8, mode uint8) {
  1516  	if debugging(debugCmd) {
  1517  		fmt.Printf("    [cmdSetPinMode] pin: %d, mode: %d\r\n", pin, mode)
  1518  	}
  1519  	w.req2Uint8(cmdSetPinMode, pin, mode)
  1520  }
  1521  
  1522  func (w *wifinina) DigitalWrite(pin uint8, value uint8) {
  1523  	if debugging(debugCmd) {
  1524  		fmt.Printf("    [cmdSetDigitialWrite] pin: %d, value: %d\r\n", pin, value)
  1525  	}
  1526  	w.req2Uint8(cmdSetDigitalWrite, pin, value)
  1527  }
  1528  
  1529  func (w *wifinina) AnalogWrite(pin uint8, value uint8) {
  1530  	w.req2Uint8(cmdSetAnalogWrite, pin, value)
  1531  }
  1532  
  1533  func (w *wifinina) getString(l uint8) string {
  1534  	return string(w.buf[0:l])
  1535  }
  1536  
  1537  func (w *wifinina) getUint8(l uint8) uint8 {
  1538  	if l == 1 {
  1539  		return w.buf[0]
  1540  	}
  1541  	w.faultf("expected length 1, was actually %d", l)
  1542  	return 0
  1543  }
  1544  
  1545  func (w *wifinina) getUint16(l uint8) uint16 {
  1546  	if l == 2 {
  1547  		return binary.BigEndian.Uint16(w.buf[0:2])
  1548  	}
  1549  	w.faultf("expected length 2, was actually %d", l)
  1550  	return 0
  1551  }
  1552  
  1553  func (w *wifinina) getUint32(l uint8) uint32 {
  1554  	if l == 4 {
  1555  		return binary.BigEndian.Uint32(w.buf[0:4])
  1556  	}
  1557  	w.faultf("expected length 4, was actually %d", l)
  1558  	return 0
  1559  }
  1560  
  1561  func (w *wifinina) getInt32(l uint8) int32 {
  1562  	return int32(w.getUint32(l))
  1563  }
  1564  
  1565  func (w *wifinina) getFloat32(l uint8) float32 {
  1566  	return float32(w.getUint32(l))
  1567  }
  1568  
  1569  func (w *wifinina) getMACAddress(l uint8) net.HardwareAddr {
  1570  	if l == 6 {
  1571  		mac := w.buf[0:6]
  1572  		// Reverse the bytes
  1573  		for i, j := 0, len(mac)-1; i < j; i, j = i+1, j-1 {
  1574  			mac[i], mac[j] = mac[j], mac[i]
  1575  		}
  1576  		return mac
  1577  	}
  1578  	w.faultf("expected length 6, was actually %d", l)
  1579  	return net.HardwareAddr{}
  1580  }
  1581  
  1582  func (w *wifinina) transfer(b byte) byte {
  1583  	v, err := w.spi.Transfer(b)
  1584  	if err != nil {
  1585  		w.faultf("SPI.Transfer")
  1586  		return 0
  1587  	}
  1588  	return v
  1589  }
  1590  
  1591  // Cmd Struct Message */
  1592  // ._______________________________________________________________________.
  1593  // | START CMD | C/R  | CMD  | N.PARAM | PARAM LEN | PARAM  | .. | END CMD |
  1594  // |___________|______|______|_________|___________|________|____|_________|
  1595  // |   8 bit   | 1bit | 7bit |  8bit   |   8bit    | nbytes | .. |   8bit  |
  1596  // |___________|______|______|_________|___________|________|____|_________|
  1597  
  1598  // req0 sends a command to the device with no request parameters
  1599  func (w *wifinina) req0(cmd uint8) uint8 {
  1600  	w.sendCmd0(cmd)
  1601  	return w.waitRspCmd1(cmd)
  1602  }
  1603  
  1604  // req1 sends a command to the device with a single dummy parameters of 0xFF
  1605  func (w *wifinina) req1(cmd uint8) uint8 {
  1606  	return w.reqUint8(cmd, dummyData)
  1607  }
  1608  
  1609  // reqUint8 sends a command to the device with a single uint8 parameter
  1610  func (w *wifinina) reqUint8(cmd uint8, data uint8) uint8 {
  1611  	w.sendCmdPadded1(cmd, data)
  1612  	return w.waitRspCmd1(cmd)
  1613  }
  1614  
  1615  // req2Uint8 sends a command to the device with two uint8 parameters
  1616  func (w *wifinina) req2Uint8(cmd, p1, p2 uint8) uint8 {
  1617  	w.sendCmdPadded2(cmd, p1, p2)
  1618  	return w.waitRspCmd1(cmd)
  1619  }
  1620  
  1621  // reqStr sends a command to the device with a single string parameter
  1622  func (w *wifinina) reqStr(cmd uint8, p1 string) uint8 {
  1623  	w.sendCmdStr(cmd, p1)
  1624  	return w.waitRspCmd1(cmd)
  1625  }
  1626  
  1627  // reqStr2 sends a command to the device with 2 string parameters
  1628  func (w *wifinina) reqStr2(cmd uint8, p1 string, p2 string) {
  1629  	w.sendCmdStr2(cmd, p1, p2)
  1630  	w.waitRspCmd1(cmd)
  1631  }
  1632  
  1633  // reqStrRsp0 sends a command passing a string slice for the response
  1634  func (w *wifinina) reqRspStr0(cmd uint8, sl []string) (l uint8) {
  1635  	w.sendCmd0(cmd)
  1636  	w.waitForChipReady()
  1637  	w.spiChipSelect()
  1638  	l = w.waitRspStr(cmd, sl)
  1639  	w.spiChipDeselect()
  1640  	return
  1641  }
  1642  
  1643  // reqStrRsp1 sends a command with a uint8 param and a string slice for the response
  1644  func (w *wifinina) reqRspStr1(cmd uint8, data uint8, sl []string) uint8 {
  1645  	w.sendCmdPadded1(cmd, data)
  1646  	w.waitForChipReady()
  1647  	w.spiChipSelect()
  1648  	l := w.waitRspStr(cmd, sl)
  1649  	w.spiChipDeselect()
  1650  	return l
  1651  }
  1652  
  1653  func (w *wifinina) sendCmd0(cmd uint8) {
  1654  	w.waitForChipReady()
  1655  	w.spiChipSelect()
  1656  	w.sendCmd(cmd, 0)
  1657  	w.spiChipDeselect()
  1658  }
  1659  
  1660  func (w *wifinina) sendCmdPadded1(cmd uint8, data uint8) {
  1661  	w.waitForChipReady()
  1662  	w.spiChipSelect()
  1663  	w.sendCmd(cmd, 1)
  1664  	w.sendParam8(data, true)
  1665  	w.transfer(dummyData)
  1666  	w.transfer(dummyData)
  1667  	w.spiChipDeselect()
  1668  	return
  1669  }
  1670  
  1671  func (w *wifinina) sendCmdPadded2(cmd, data1, data2 uint8) {
  1672  	w.waitForChipReady()
  1673  	w.spiChipSelect()
  1674  	w.sendCmd(cmd, 1)
  1675  	w.sendParam8(data1, false)
  1676  	w.sendParam8(data2, true)
  1677  	w.transfer(dummyData)
  1678  	w.spiChipDeselect()
  1679  }
  1680  
  1681  func (w *wifinina) sendCmdStr(cmd uint8, p1 string) {
  1682  	w.waitForChipReady()
  1683  	w.spiChipSelect()
  1684  	w.sendCmd(cmd, 1)
  1685  	w.sendParamStr(p1, true)
  1686  	w.padTo4(5 + len(p1))
  1687  	w.spiChipDeselect()
  1688  }
  1689  
  1690  func (w *wifinina) sendCmdStr2(cmd uint8, p1 string, p2 string) {
  1691  	w.waitForChipReady()
  1692  	w.spiChipSelect()
  1693  	w.sendCmd(cmd, 2)
  1694  	w.sendParamStr(p1, false)
  1695  	w.sendParamStr(p2, true)
  1696  	w.padTo4(6 + len(p1) + len(p2))
  1697  	w.spiChipDeselect()
  1698  }
  1699  
  1700  func (w *wifinina) waitRspCmd1(cmd uint8) uint8 {
  1701  	w.waitForChipReady()
  1702  	w.spiChipSelect()
  1703  	l := w.waitRspCmd(cmd, 1)
  1704  	w.spiChipDeselect()
  1705  	return l
  1706  }
  1707  
  1708  func (w *wifinina) sendCmd(cmd uint8, numParam uint8) (l int) {
  1709  	if debugging(debugDetail) {
  1710  		fmt.Printf("        sendCmd: %02X %02X %02X",
  1711  			cmdStart, cmd & ^(uint8(flagReply)), numParam)
  1712  	}
  1713  
  1714  	l = 3
  1715  	w.transfer(cmdStart)
  1716  	w.transfer(cmd & ^(uint8(flagReply)))
  1717  	w.transfer(numParam)
  1718  	if numParam == 0 {
  1719  		w.transfer(cmdEnd)
  1720  		l += 1
  1721  		if debugging(debugDetail) {
  1722  			fmt.Printf(" %02X", cmdEnd)
  1723  		}
  1724  	}
  1725  
  1726  	if debugging(debugDetail) {
  1727  		fmt.Printf(" (%d)\r\n", l)
  1728  	}
  1729  	return
  1730  }
  1731  
  1732  func (w *wifinina) sendParamLen16(p uint16) (l int) {
  1733  	w.transfer(uint8(p >> 8))
  1734  	w.transfer(uint8(p & 0xFF))
  1735  	if debugging(debugDetail) {
  1736  		fmt.Printf("        %02X %02X", uint8(p>>8), uint8(p&0xFF))
  1737  	}
  1738  	return 2
  1739  }
  1740  
  1741  func (w *wifinina) sendParamBuf(p []byte, isLastParam bool) (l int) {
  1742  	if debugging(debugDetail) {
  1743  		fmt.Printf("        sendParamBuf:")
  1744  	}
  1745  	l += w.sendParamLen16(uint16(len(p)))
  1746  	for _, b := range p {
  1747  		if debugging(debugDetail) {
  1748  			fmt.Printf(" %02X", b)
  1749  		}
  1750  		w.transfer(b)
  1751  		l += 1
  1752  	}
  1753  	if isLastParam {
  1754  		if debugging(debugDetail) {
  1755  			fmt.Printf(" %02X", cmdEnd)
  1756  		}
  1757  		w.transfer(cmdEnd)
  1758  		l += 1
  1759  	}
  1760  	if debugging(debugDetail) {
  1761  		fmt.Printf(" (%d) \r\n", l)
  1762  	}
  1763  	return
  1764  }
  1765  
  1766  func (w *wifinina) sendParamStr(p string, isLastParam bool) (l int) {
  1767  	if debugging(debugDetail) {
  1768  		fmt.Printf("        sendParamStr: p: %s, lastParam: %t\r\n", p, isLastParam)
  1769  	}
  1770  	l = len(p)
  1771  	w.transfer(uint8(l))
  1772  	if l > 0 {
  1773  		w.spi.Tx([]byte(p), nil)
  1774  	}
  1775  	if isLastParam {
  1776  		w.transfer(cmdEnd)
  1777  		l += 1
  1778  	}
  1779  	return
  1780  }
  1781  
  1782  func (w *wifinina) sendParam8(p uint8, isLastParam bool) (l int) {
  1783  	if debugging(debugDetail) {
  1784  		fmt.Printf("        sendParam8: p: %d, lastParam: %t\r\n", p, isLastParam)
  1785  	}
  1786  	l = 2
  1787  	w.transfer(1)
  1788  	w.transfer(p)
  1789  	if isLastParam {
  1790  		w.transfer(cmdEnd)
  1791  		l += 1
  1792  	}
  1793  	return
  1794  }
  1795  
  1796  func (w *wifinina) sendParam16(p uint16, isLastParam bool) (l int) {
  1797  	if debugging(debugDetail) {
  1798  		fmt.Printf("        sendParam16: p: %d, lastParam: %t\r\n", p, isLastParam)
  1799  	}
  1800  	l = 3
  1801  	w.transfer(2)
  1802  	w.transfer(uint8(p >> 8))
  1803  	w.transfer(uint8(p & 0xFF))
  1804  	if isLastParam {
  1805  		w.transfer(cmdEnd)
  1806  		l += 1
  1807  	}
  1808  	return
  1809  }
  1810  
  1811  func (w *wifinina) sendParam32(p uint32, isLastParam bool) (l int) {
  1812  	if debugging(debugDetail) {
  1813  		fmt.Printf("        sendParam32: p: %d, lastParam: %t\r\n", p, isLastParam)
  1814  	}
  1815  	l = 5
  1816  	w.transfer(4)
  1817  	w.transfer(uint8(p >> 24))
  1818  	w.transfer(uint8(p >> 16))
  1819  	w.transfer(uint8(p >> 8))
  1820  	w.transfer(uint8(p & 0xFF))
  1821  	if isLastParam {
  1822  		w.transfer(cmdEnd)
  1823  		l += 1
  1824  	}
  1825  	return
  1826  }
  1827  
  1828  func (w *wifinina) waitForChipReady() {
  1829  	if debugging(debugDetail) {
  1830  		fmt.Printf("        waitForChipReady\r\n")
  1831  	}
  1832  
  1833  	for i := 0; w.ack.Get(); i++ {
  1834  		time.Sleep(1 * time.Millisecond)
  1835  		if i == 10000 {
  1836  			w.faultf("hung in waitForChipReady")
  1837  			return
  1838  		}
  1839  	}
  1840  }
  1841  
  1842  func (w *wifinina) spiChipSelect() {
  1843  	if debugging(debugDetail) {
  1844  		fmt.Printf("        spiChipSelect\r\n")
  1845  	}
  1846  	w.cs.Low()
  1847  	start := time.Now()
  1848  	for time.Since(start) < 10*time.Millisecond {
  1849  		if w.ack.Get() {
  1850  			return
  1851  		}
  1852  		time.Sleep(100 * time.Microsecond)
  1853  	}
  1854  	w.faultf("hung in spiChipSelect")
  1855  }
  1856  
  1857  func (w *wifinina) spiChipDeselect() {
  1858  	if debugging(debugDetail) {
  1859  		fmt.Printf("        spiChipDeselect\r\n")
  1860  	}
  1861  	w.cs.High()
  1862  }
  1863  
  1864  func (w *wifinina) waitSpiChar(desired byte) {
  1865  
  1866  	if debugging(debugDetail) {
  1867  		fmt.Printf("        waitSpiChar: desired: %02X\r\n", desired)
  1868  	}
  1869  
  1870  	var read byte
  1871  
  1872  	for i := 0; i < 10; i++ {
  1873  		w.readParam(&read)
  1874  		switch read {
  1875  		case cmdErr:
  1876  			w.faultf("cmdErr received, waiting for %d", desired)
  1877  			return
  1878  		case desired:
  1879  			return
  1880  		}
  1881  		time.Sleep(10 * time.Millisecond)
  1882  	}
  1883  
  1884  	w.faultf("timeout waiting for SPI char %02X\r\n", desired)
  1885  }
  1886  
  1887  func (w *wifinina) waitRspCmd(cmd uint8, np uint8) (l uint8) {
  1888  
  1889  	if debugging(debugDetail) {
  1890  		fmt.Printf("        waitRspCmd: cmd: %02X, np: %d\r\n", cmd, np)
  1891  	}
  1892  
  1893  	var data byte
  1894  
  1895  	w.waitSpiChar(cmdStart)
  1896  
  1897  	if !w.readAndCheckByte(cmd|flagReply, &data) {
  1898  		w.faultf("expected cmd %02X, read %02X", cmd, data)
  1899  		return
  1900  	}
  1901  
  1902  	if w.readAndCheckByte(np, &data) {
  1903  		w.readParam(&l)
  1904  		for i := uint8(0); i < l; i++ {
  1905  			w.readParam(&w.buf[i])
  1906  		}
  1907  		if !w.readAndCheckByte(cmdEnd, &data) {
  1908  			w.faultf("expected cmdEnd, read %02X", data)
  1909  		}
  1910  	}
  1911  
  1912  	return
  1913  }
  1914  
  1915  func (w *wifinina) waitRspBuf16(cmd uint8, buf []byte) (l uint16) {
  1916  
  1917  	if debugging(debugDetail) {
  1918  		fmt.Printf("        waitRspBuf16: cmd: %02X, len(buf): %d\r\n", cmd, len(buf))
  1919  	}
  1920  
  1921  	var data byte
  1922  
  1923  	w.waitSpiChar(cmdStart)
  1924  
  1925  	if !w.readAndCheckByte(cmd|flagReply, &data) {
  1926  		w.faultf("expected cmd %02X, read %02X", cmd, data)
  1927  		return
  1928  	}
  1929  
  1930  	if w.readAndCheckByte(1, &data) {
  1931  		l = w.readParamLen16()
  1932  		for i := uint16(0); i < l; i++ {
  1933  			w.readParam(&buf[i])
  1934  		}
  1935  		if !w.readAndCheckByte(cmdEnd, &data) {
  1936  			w.faultf("expected cmdEnd, read %02X", data)
  1937  		}
  1938  	}
  1939  
  1940  	return
  1941  }
  1942  
  1943  func (w *wifinina) waitRspStr(cmd uint8, sl []string) (numRead uint8) {
  1944  
  1945  	if debugging(debugDetail) {
  1946  		fmt.Printf("        waitRspStr: cmd: %02X, len(sl): %d\r\n", cmd, len(sl))
  1947  	}
  1948  
  1949  	var data byte
  1950  
  1951  	w.waitSpiChar(cmdStart)
  1952  
  1953  	if !w.readAndCheckByte(cmd|flagReply, &data) {
  1954  		w.faultf("expected cmd %02X, read %02X", cmd, data)
  1955  		return
  1956  	}
  1957  
  1958  	numRead = w.transfer(dummyData)
  1959  	if numRead == 0 {
  1960  		w.faultf("waitRspStr numRead == 0")
  1961  		return
  1962  	}
  1963  
  1964  	maxNumRead := uint8(len(sl))
  1965  	for j, l := uint8(0), uint8(0); j < numRead; j++ {
  1966  		w.readParam(&l)
  1967  		for i := uint8(0); i < l; i++ {
  1968  			w.readParam(&w.buf[i])
  1969  		}
  1970  		if j < maxNumRead {
  1971  			sl[j] = string(w.buf[0:l])
  1972  			if debugging(debugDetail) {
  1973  				fmt.Printf("            str: %d (%d) - %08X\r\n", j, l, []byte(sl[j]))
  1974  			}
  1975  		}
  1976  	}
  1977  
  1978  	for j := numRead; j < maxNumRead; j++ {
  1979  		if debugging(debugDetail) {
  1980  			fmt.Printf("            str: ", j, "\"\"\r")
  1981  		}
  1982  		sl[j] = ""
  1983  	}
  1984  
  1985  	if !w.readAndCheckByte(cmdEnd, &data) {
  1986  		w.faultf("expected cmdEnd, read %02X", data)
  1987  		return
  1988  	}
  1989  
  1990  	if numRead > maxNumRead {
  1991  		numRead = maxNumRead
  1992  	}
  1993  	return
  1994  }
  1995  
  1996  func (w *wifinina) readAndCheckByte(check byte, read *byte) bool {
  1997  	w.readParam(read)
  1998  	return *read == check
  1999  }
  2000  
  2001  // readParamLen16 reads 2 bytes from the SPI bus (MSB first), returning uint16
  2002  func (w *wifinina) readParamLen16() (v uint16) {
  2003  	b := w.transfer(0xFF)
  2004  	v = uint16(b) << 8
  2005  	b = w.transfer(0xFF)
  2006  	v |= uint16(b)
  2007  	return
  2008  }
  2009  
  2010  func (w *wifinina) readParam(b *byte) {
  2011  	*b = w.transfer(0xFF)
  2012  }
  2013  
  2014  func (w *wifinina) addPadding(l int) {
  2015  	if debugging(debugDetail) {
  2016  		fmt.Printf("        addPadding: l: %d\r\n", l)
  2017  	}
  2018  	for i := (4 - (l % 4)) & 3; i > 0; i-- {
  2019  		if debugging(debugDetail) {
  2020  			fmt.Printf("            padding\r\n")
  2021  		}
  2022  		w.transfer(dummyData)
  2023  	}
  2024  }
  2025  
  2026  func (w *wifinina) padTo4(l int) {
  2027  	if debugging(debugDetail) {
  2028  		fmt.Printf("        padTo4: l: %d\r\n", l)
  2029  	}
  2030  
  2031  	for l%4 != 0 {
  2032  		if debugging(debugDetail) {
  2033  			fmt.Printf("            padding\r\n")
  2034  		}
  2035  		w.transfer(dummyData)
  2036  		l++
  2037  	}
  2038  }