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 }