tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/rtl8720dn/rtl8720dn.go (about) 1 // Package rtl8720dn implements TCP wireless communication over UART 2 // talking to a RealTek rtl8720dn module. 3 // 4 // 01/2023 sfeldma@gmail.com Heavily modified to use netdev interface 5 6 package rtl8720dn // import "tinygo.org/x/drivers/rtl8720dn" 7 8 import ( 9 "encoding/hex" 10 "errors" 11 "fmt" 12 "io" 13 "machine" 14 "net" 15 "net/netip" 16 "strings" 17 "sync" 18 "time" 19 20 "tinygo.org/x/drivers" 21 "tinygo.org/x/drivers/netdev" 22 "tinygo.org/x/drivers/netlink" 23 ) 24 25 var _debug debug = debugBasic 26 27 //var _debug debug = debugBasic | debugNetdev 28 //var _debug debug = debugBasic | debugNetdev | debugRpc 29 30 var ( 31 driverName = "Realtek rtl8720dn Wifi network device driver (rtl8720dn)" 32 ) 33 34 const ( 35 O_NONBLOCK = 1 // note: different value than syscall.O_NONBLOCK (0x800) 36 RTW_MODE_STA = 0x00000001 37 defaultChannel = 6 38 ) 39 40 type sock int32 41 42 type socket struct { 43 protocol int 44 inuse bool 45 } 46 47 type Config struct { 48 // Enable 49 En machine.Pin 50 51 // UART config 52 Uart *machine.UART 53 Tx machine.Pin 54 Rx machine.Pin 55 Baudrate uint32 56 } 57 58 type rtl8720dn struct { 59 cfg *Config 60 notifyCb func(netlink.Event) 61 mu sync.Mutex 62 63 uart *machine.UART 64 seq uint64 65 66 debug bool 67 68 params *netlink.ConnectParams 69 70 netConnected bool 71 driverShown bool 72 deviceShown bool 73 74 killWatchdog chan bool 75 76 // keyed by sock as returned by rpc_lwip_socket() 77 sockets map[sock]*socket 78 } 79 80 func newSocket(protocol int) *socket { 81 return &socket{protocol: protocol, inuse: true} 82 } 83 84 func New(cfg *Config) *rtl8720dn { 85 return &rtl8720dn{ 86 debug: (_debug & debugRpc) != 0, 87 cfg: cfg, 88 sockets: make(map[sock]*socket), 89 killWatchdog: make(chan bool), 90 } 91 } 92 93 func (r *rtl8720dn) startDhcpc() error { 94 if result := r.rpc_tcpip_adapter_dhcpc_start(0); result == -1 { 95 return netdev.ErrStartingDHCPClient 96 } 97 return nil 98 } 99 100 func (r *rtl8720dn) connectToAP() error { 101 102 if len(r.params.Ssid) == 0 { 103 return netlink.ErrMissingSSID 104 } 105 106 if len(r.params.Passphrase) != 0 && len(r.params.Passphrase) < 8 { 107 return netlink.ErrShortPassphrase 108 } 109 110 if debugging(debugBasic) { 111 fmt.Printf("Connecting to Wifi SSID '%s'...", r.params.Ssid) 112 } 113 114 // Start the connection process 115 securityType := uint32(0) // RTW_SECURITY_OPEN 116 if len(r.params.Passphrase) != 0 { 117 securityType = 0x00400004 // RTW_SECURITY_WPA2_AES_PSK 118 } 119 120 result := r.rpc_wifi_connect(r.params.Ssid, r.params.Passphrase, securityType, -1, 0) 121 if result != 0 { 122 if debugging(debugBasic) { 123 fmt.Printf("FAILED\r\n") 124 } 125 return netlink.ErrConnectFailed 126 } 127 128 if debugging(debugBasic) { 129 fmt.Printf("CONNECTED\r\n") 130 } 131 132 if r.notifyCb != nil { 133 r.notifyCb(netlink.EventNetUp) 134 } 135 136 return r.startDhcpc() 137 } 138 139 func (r *rtl8720dn) startDhcps() error { 140 if result := r.rpc_tcpip_adapter_dhcps_start(0); result == -1 { 141 return netdev.ErrStartingDHCPServer 142 } 143 return nil 144 } 145 146 func (r *rtl8720dn) startAP() error { 147 if len(r.params.Ssid) == 0 { 148 return netlink.ErrMissingSSID 149 } 150 151 if len(r.params.Passphrase) != 0 && len(r.params.Passphrase) < 8 { 152 return netlink.ErrShortPassphrase 153 } 154 155 if debugging(debugBasic) { 156 fmt.Printf("Starting Wifi AP as SSID '%s'...", r.params.Ssid) 157 } 158 159 // Start the connection process 160 securityType := uint32(0) // RTW_SECURITY_OPEN 161 if len(r.params.Passphrase) != 0 { 162 securityType = 0x00400004 // RTW_SECURITY_WPA2_AES_PSK 163 } 164 165 result := r.rpc_wifi_start_ap(r.params.Ssid, r.params.Passphrase, securityType, defaultChannel) 166 if result != 0 { 167 if debugging(debugBasic) { 168 fmt.Printf("FAILED\r\n") 169 } 170 return netlink.ErrConnectFailed 171 } 172 173 if debugging(debugBasic) { 174 fmt.Printf("LISTENING\r\n") 175 } 176 177 if r.notifyCb != nil { 178 r.notifyCb(netlink.EventNetUp) 179 } 180 181 return r.startDhcps() 182 } 183 184 func (r *rtl8720dn) showDriver() { 185 if r.driverShown { 186 return 187 } 188 if debugging(debugBasic) { 189 fmt.Printf("\r\n") 190 fmt.Printf("%s\r\n\r\n", driverName) 191 fmt.Printf("Driver version : %s\r\n", drivers.Version) 192 } 193 r.driverShown = true 194 } 195 196 func (r *rtl8720dn) initWifi() error { 197 if result := r.rpc_tcpip_adapter_init(); result == -1 { 198 return fmt.Errorf("TCP/IP adapter init failed") 199 } 200 if result := r.rpc_wifi_off(); result == -1 { 201 return errors.New("Error turning off WiFi") 202 } 203 if result := r.rpc_wifi_on(RTW_MODE_STA); result == -1 { 204 return errors.New("Error turning on WiFi") 205 } 206 if result := r.rpc_wifi_disconnect(); result == -1 { 207 return errors.New("Error disconnecting WiFi") 208 } 209 return nil 210 } 211 212 func (r *rtl8720dn) setupUART() { 213 r.uart = r.cfg.Uart 214 r.uart.Configure(machine.UARTConfig{TX: r.cfg.Tx, 215 RX: r.cfg.Rx, BaudRate: r.cfg.Baudrate}) 216 } 217 218 func (r *rtl8720dn) start() error { 219 en := r.cfg.En 220 if en == 0 { 221 return fmt.Errorf("Must set Config.En") 222 } 223 en.Configure(machine.PinConfig{Mode: machine.PinOutput}) 224 en.Low() 225 time.Sleep(100 * time.Millisecond) 226 en.High() 227 time.Sleep(1000 * time.Millisecond) 228 r.setupUART() 229 return r.initWifi() 230 } 231 232 func (r *rtl8720dn) stop() { 233 r.rpc_tcpip_adapter_stop(0) 234 r.cfg.En.Low() 235 } 236 237 func (r *rtl8720dn) showDevice() { 238 if r.deviceShown { 239 return 240 } 241 if debugging(debugBasic) { 242 fmt.Printf("RTL8720 firmware version : %s\r\n", r.getFwVersion()) 243 fmt.Printf("MAC address : %s\r\n", r.getMACAddr()) 244 fmt.Printf("\r\n") 245 } 246 r.deviceShown = true 247 } 248 249 func (r *rtl8720dn) showIP() { 250 if debugging(debugBasic) { 251 ip, subnet, gateway, _ := r.getIP() 252 fmt.Printf("\r\n") 253 fmt.Printf("DHCP-assigned IP : %s\r\n", ip) 254 fmt.Printf("DHCP-assigned subnet : %s\r\n", subnet) 255 fmt.Printf("DHCP-assigned gateway : %s\r\n", gateway) 256 fmt.Printf("\r\n") 257 } 258 } 259 260 func (r *rtl8720dn) networkDown() bool { 261 result := r.rpc_wifi_is_connected_to_ap() 262 return result != 0 263 } 264 265 func (r *rtl8720dn) watchdog() { 266 ticker := time.NewTicker(r.params.WatchdogTimeout) 267 for { 268 select { 269 case <-r.killWatchdog: 270 return 271 case <-ticker.C: 272 r.mu.Lock() 273 if r.networkDown() { 274 if debugging(debugBasic) { 275 fmt.Printf("Watchdog: Wifi NOT CONNECTED, trying again...\r\n") 276 } 277 if r.notifyCb != nil { 278 r.notifyCb(netlink.EventNetDown) 279 } 280 r.netConnect(false) 281 } 282 r.mu.Unlock() 283 } 284 } 285 } 286 287 func (r *rtl8720dn) netConnect(reset bool) error { 288 if reset { 289 if err := r.start(); err != nil { 290 return err 291 } 292 } 293 r.showDevice() 294 295 retry: 296 for i := 0; r.params.Retries == 0 || i < r.params.Retries; i++ { 297 switch r.params.ConnectMode { 298 case netlink.ConnectModeAP: 299 if err := r.startAP(); err != nil { 300 if err == netlink.ErrConnectFailed { 301 continue 302 } 303 return err 304 } 305 break retry 306 307 default: 308 if err := r.connectToAP(); err != nil { 309 if err == netlink.ErrConnectFailed { 310 continue 311 } 312 return err 313 } 314 break retry 315 } 316 } 317 318 if r.networkDown() { 319 return netlink.ErrConnectFailed 320 } 321 322 r.showIP() 323 return nil 324 } 325 326 func (r *rtl8720dn) NetConnect(params *netlink.ConnectParams) error { 327 328 r.mu.Lock() 329 defer r.mu.Unlock() 330 331 if r.netConnected { 332 return netlink.ErrConnected 333 } 334 335 r.params = params 336 337 r.showDriver() 338 339 if err := r.netConnect(true); err != nil { 340 return err 341 } 342 343 r.netConnected = true 344 345 if r.params.WatchdogTimeout != 0 { 346 go r.watchdog() 347 } 348 349 return nil 350 } 351 352 func (r *rtl8720dn) netDisconnect() { 353 r.disconnect() 354 } 355 356 func (r *rtl8720dn) NetDisconnect() { 357 358 r.mu.Lock() 359 defer r.mu.Unlock() 360 361 if !r.netConnected { 362 return 363 } 364 365 if r.params.WatchdogTimeout != 0 { 366 r.killWatchdog <- true 367 } 368 r.netDisconnect() 369 r.stop() 370 371 r.netConnected = false 372 373 if debugging(debugBasic) { 374 fmt.Printf("\r\nDisconnected from Wifi SSID '%s'\r\n\r\n", r.params.Ssid) 375 } 376 377 if r.notifyCb != nil { 378 r.notifyCb(netlink.EventNetDown) 379 } 380 } 381 382 func (r *rtl8720dn) NetNotify(cb func(netlink.Event)) { 383 r.notifyCb = cb 384 } 385 386 func (r *rtl8720dn) GetHostByName(name string) (netip.Addr, error) { 387 388 if debugging(debugNetdev) { 389 fmt.Printf("[GetHostByName] name: %s\r\n", name) 390 } 391 392 r.mu.Lock() 393 defer r.mu.Unlock() 394 395 var ip [4]byte 396 result := r.rpc_netconn_gethostbyname(name, ip[:]) 397 if result == -1 { 398 return netip.Addr{}, netdev.ErrHostUnknown 399 } 400 401 addr, ok := netip.AddrFromSlice(ip[:]) 402 if !ok { 403 return netip.Addr{}, netdev.ErrMalAddr 404 } 405 406 return addr, nil 407 } 408 409 func (r *rtl8720dn) GetHardwareAddr() (net.HardwareAddr, error) { 410 411 if debugging(debugNetdev) { 412 fmt.Printf("[GetHardwareAddr]\r\n") 413 } 414 415 r.mu.Lock() 416 defer r.mu.Unlock() 417 418 mac := strings.ReplaceAll(r.getMACAddr(), ":", "") 419 addr, err := hex.DecodeString(mac) 420 421 return net.HardwareAddr(addr), err 422 } 423 424 func (r *rtl8720dn) Addr() (netip.Addr, error) { 425 426 if debugging(debugNetdev) { 427 fmt.Printf("[GetIPAddr]\r\n") 428 } 429 430 r.mu.Lock() 431 defer r.mu.Unlock() 432 433 ip, _, _, err := r.getIP() 434 435 return ip, err 436 } 437 438 func (r *rtl8720dn) clientTLS() uint32 { 439 client := r.rpc_wifi_ssl_client_create() 440 r.rpc_wifi_ssl_init(client) 441 r.rpc_wifi_ssl_set_timeout(client, 120*1000 /* usec? */) 442 return client 443 } 444 445 // See man socket(2) for standard Berkely sockets for Socket, Bind, etc. 446 // The driver strives to meet the function and semantics of socket(2). 447 448 func (r *rtl8720dn) Socket(domain int, stype int, protocol int) (int, error) { 449 450 if debugging(debugNetdev) { 451 fmt.Printf("[Socket] domain: %d, type: %d, protocol: %d\r\n", 452 domain, stype, protocol) 453 } 454 455 switch domain { 456 case netdev.AF_INET: 457 default: 458 return -1, netdev.ErrFamilyNotSupported 459 } 460 461 var newSock int32 462 463 r.mu.Lock() 464 defer r.mu.Unlock() 465 466 switch { 467 case protocol == netdev.IPPROTO_TCP && stype == netdev.SOCK_STREAM: 468 newSock = r.rpc_lwip_socket(netdev.AF_INET, netdev.SOCK_STREAM, 469 netdev.IPPROTO_TCP) 470 case protocol == netdev.IPPROTO_TLS && stype == netdev.SOCK_STREAM: 471 // TODO Investigate: using client number as socket number; 472 // TODO this may cause a problem if mixing TLS and non-TLS sockets? 473 newSock = int32(r.clientTLS()) 474 case protocol == netdev.IPPROTO_UDP && stype == netdev.SOCK_DGRAM: 475 newSock = r.rpc_lwip_socket(netdev.AF_INET, netdev.SOCK_DGRAM, 476 netdev.IPPROTO_UDP) 477 default: 478 return -1, netdev.ErrProtocolNotSupported 479 } 480 481 if newSock == -1 { 482 return -1, netdev.ErrNoMoreSockets 483 } 484 485 socket := newSocket(protocol) 486 r.sockets[sock(newSock)] = socket 487 488 return int(newSock), nil 489 } 490 491 func ipToName(ip netip.AddrPort) []byte { 492 name := make([]byte, 16) 493 name[0] = 0x00 494 name[1] = netdev.AF_INET 495 name[2] = byte(ip.Port() >> 8) 496 name[3] = byte(ip.Port()) 497 if ip.Addr().Is4() { 498 addr := ip.Addr().As4() 499 name[4] = byte(addr[0]) 500 name[5] = byte(addr[1]) 501 name[6] = byte(addr[2]) 502 name[7] = byte(addr[3]) 503 } 504 return name 505 } 506 507 func nameToIp(name []byte) netip.AddrPort { 508 port := uint16(name[2])<<8 | uint16(name[3]) 509 addr, _ := netip.AddrFromSlice(name[4:8]) 510 return netip.AddrPortFrom(addr, port) 511 } 512 513 func (r *rtl8720dn) Bind(sockfd int, ip netip.AddrPort) error { 514 515 if debugging(debugNetdev) { 516 fmt.Printf("[Bind] sockfd: %d, addr: %s\r\n", sockfd, ip) 517 } 518 519 r.mu.Lock() 520 defer r.mu.Unlock() 521 522 var sock = sock(sockfd) 523 var socket = r.sockets[sock] 524 var name = ipToName(ip) 525 526 switch socket.protocol { 527 case netdev.IPPROTO_TCP, netdev.IPPROTO_UDP: 528 result := r.rpc_lwip_bind(int32(sock), name, uint32(len(name))) 529 if result == -1 { 530 return fmt.Errorf("Bind to %s failed", ip) 531 } 532 default: 533 return netdev.ErrProtocolNotSupported 534 } 535 536 return nil 537 } 538 539 func (r *rtl8720dn) Connect(sockfd int, host string, ip netip.AddrPort) error { 540 541 port := ip.Port() 542 543 if debugging(debugNetdev) { 544 if host == "" { 545 fmt.Printf("[Connect] sockfd: %d, addr: %s\r\n", sockfd, ip) 546 } else { 547 fmt.Printf("[Connect] sockfd: %d, host: %s:%d\r\n", sockfd, host, port) 548 } 549 } 550 551 r.mu.Lock() 552 defer r.mu.Unlock() 553 554 var sock = sock(sockfd) 555 var socket = r.sockets[sock] 556 var name = ipToName(ip) 557 558 // Start the connection 559 switch socket.protocol { 560 case netdev.IPPROTO_TCP, netdev.IPPROTO_UDP: 561 result := r.rpc_lwip_connect(int32(sock), name, uint32(len(name))) 562 if result == -1 { 563 return fmt.Errorf("Connect to %s failed", ip) 564 } 565 case netdev.IPPROTO_TLS: 566 result := r.rpc_wifi_start_ssl_client(uint32(sock), 567 host, uint32(port), 0) 568 if result == -1 { 569 return fmt.Errorf("Connect to %s:%d failed", host, port) 570 } 571 } 572 573 return nil 574 } 575 576 func (r *rtl8720dn) Listen(sockfd int, backlog int) error { 577 578 if debugging(debugNetdev) { 579 fmt.Printf("[Listen] sockfd: %d\r\n", sockfd) 580 } 581 582 r.mu.Lock() 583 defer r.mu.Unlock() 584 585 var sock = sock(sockfd) 586 var socket = r.sockets[sock] 587 588 switch socket.protocol { 589 case netdev.IPPROTO_TCP: 590 result := r.rpc_lwip_listen(int32(sock), int32(backlog)) 591 if result == -1 { 592 return fmt.Errorf("Listen failed") 593 } 594 result = r.rpc_lwip_fcntl(int32(sock), netdev.F_SETFL, O_NONBLOCK) 595 if result == -1 { 596 return fmt.Errorf("Fcntl failed") 597 } 598 case netdev.IPPROTO_UDP: 599 result := r.rpc_lwip_listen(int32(sock), int32(backlog)) 600 if result == -1 { 601 return fmt.Errorf("Listen failed") 602 } 603 default: 604 return netdev.ErrProtocolNotSupported 605 } 606 607 return nil 608 } 609 610 func (r *rtl8720dn) Accept(sockfd int) (int, netip.AddrPort, error) { 611 612 if debugging(debugNetdev) { 613 fmt.Printf("[Accept] sockfd: %d\r\n", sockfd) 614 } 615 616 r.mu.Lock() 617 defer r.mu.Unlock() 618 619 var newSock int32 620 var lsock = sock(sockfd) 621 var socket = r.sockets[lsock] 622 var name = ipToName(netip.AddrPort{}) 623 624 switch socket.protocol { 625 case netdev.IPPROTO_TCP: 626 default: 627 return -1, netip.AddrPort{}, netdev.ErrProtocolNotSupported 628 } 629 630 for { 631 // Accept() will be sleeping most of the time, checking for a 632 // new clients every 1/10 sec. 633 r.mu.Unlock() 634 time.Sleep(100 * time.Millisecond) 635 r.mu.Lock() 636 637 // Check if a client connected. O_NONBLOCK is set on lsock. 638 namelen := uint32(len(name)) 639 newSock = r.rpc_lwip_accept(int32(lsock), name, &namelen) 640 if newSock == -1 { 641 // No new client 642 time.Sleep(100 * time.Millisecond) 643 continue 644 } 645 646 // Get remote peer ip:port 647 namelen = uint32(len(name)) 648 result := r.rpc_lwip_getpeername(int32(newSock), name, &namelen) 649 if result == -1 { 650 return -1, netip.AddrPort{}, fmt.Errorf("Getpeername failed") 651 } 652 raddr := nameToIp(name) 653 654 // If we've already seen this socket, we can re-use 655 // the socket and return it. But, only if the socket 656 // is closed. If it's not closed, we'll just come back 657 // later to reuse it. 658 659 clientSocket, ok := r.sockets[sock(newSock)] 660 if ok { 661 // Wait for client to Close 662 if clientSocket.inuse { 663 continue 664 } 665 // Reuse client socket 666 return int(newSock), raddr, nil 667 } 668 669 // Create new socket for client and return fd 670 r.sockets[sock(newSock)] = newSocket(socket.protocol) 671 return int(newSock), raddr, nil 672 } 673 } 674 675 func (r *rtl8720dn) sendChunk(sockfd int, buf []byte, deadline time.Time) (int, error) { 676 var sock = sock(sockfd) 677 var socket = r.sockets[sock] 678 679 // Check if we've timed out 680 if !deadline.IsZero() { 681 if time.Now().After(deadline) { 682 return -1, netdev.ErrTimeout 683 } 684 } 685 686 switch socket.protocol { 687 case netdev.IPPROTO_TCP, netdev.IPPROTO_UDP: 688 result := r.rpc_lwip_send(int32(sock), buf, 0x00000008) 689 if result == -1 { 690 return -1, fmt.Errorf("Send error") 691 } 692 return int(result), nil 693 case netdev.IPPROTO_TLS: 694 result := r.rpc_wifi_send_ssl_data(uint32(sock), buf, uint16(len(buf))) 695 if result == -1 { 696 return -1, fmt.Errorf("TLS Send error") 697 } 698 return int(result), nil 699 } 700 701 return -1, netdev.ErrProtocolNotSupported 702 } 703 704 func (r *rtl8720dn) Send(sockfd int, buf []byte, flags int, 705 deadline time.Time) (int, error) { 706 707 if debugging(debugNetdev) { 708 fmt.Printf("[Send] sockfd: %d, len(buf): %d, flags: %d\r\n", 709 sockfd, len(buf), flags) 710 } 711 712 r.mu.Lock() 713 defer r.mu.Unlock() 714 715 // Break large bufs into chunks 716 717 chunkSize := 1436 718 for i := 0; i < len(buf); i += chunkSize { 719 end := i + chunkSize 720 if end > len(buf) { 721 end = len(buf) 722 } 723 _, err := r.sendChunk(sockfd, buf[i:end], deadline) 724 if err != nil { 725 return -1, err 726 } 727 } 728 729 return len(buf), nil 730 } 731 732 func (r *rtl8720dn) Recv(sockfd int, buf []byte, flags int, 733 deadline time.Time) (int, error) { 734 735 if debugging(debugNetdev) { 736 fmt.Printf("[Recv] sockfd: %d, len(buf): %d, flags: %d\r\n", 737 sockfd, len(buf), flags) 738 } 739 740 r.mu.Lock() 741 defer r.mu.Unlock() 742 743 var sock = sock(sockfd) 744 var socket = r.sockets[sock] 745 var length = len(buf) 746 var n int32 747 748 // Limit length read size to chunk large read requests 749 if length > 1436 { 750 length = 1436 751 } 752 753 for { 754 // Check if we've timed out 755 if !deadline.IsZero() { 756 if time.Now().After(deadline) { 757 return -1, netdev.ErrTimeout 758 } 759 } 760 761 switch socket.protocol { 762 case netdev.IPPROTO_TCP, netdev.IPPROTO_UDP: 763 n = r.rpc_lwip_recv(int32(sock), buf[:length], 764 uint32(length), 0x00000008, 0) 765 case netdev.IPPROTO_TLS: 766 n = r.rpc_wifi_get_ssl_receive(uint32(sock), 767 buf[:length], int32(length)) 768 } 769 770 if n < 0 { 771 r.mu.Unlock() 772 time.Sleep(100 * time.Millisecond) 773 r.mu.Lock() 774 continue 775 } else if n == 0 { 776 if debugging(debugNetdev) { 777 fmt.Printf("[<--Recv] sockfd: %d, n: %d EOF\r\n", 778 sock, n) 779 } 780 return -1, io.EOF 781 } 782 783 if debugging(debugNetdev) { 784 fmt.Printf("[<--Recv] sockfd: %d, n: %d\r\n", 785 sock, n) 786 } 787 788 return int(n), nil 789 } 790 } 791 792 func (r *rtl8720dn) Close(sockfd int) error { 793 794 if debugging(debugNetdev) { 795 fmt.Printf("[Close] sockfd: %d\r\n", sockfd) 796 } 797 798 r.mu.Lock() 799 defer r.mu.Unlock() 800 801 var sock = sock(sockfd) 802 var socket = r.sockets[sock] 803 var result int32 804 805 if !socket.inuse { 806 return nil 807 } 808 809 switch socket.protocol { 810 case netdev.IPPROTO_TCP, netdev.IPPROTO_UDP: 811 result = r.rpc_lwip_close(int32(sock)) 812 case netdev.IPPROTO_TLS: 813 r.rpc_wifi_stop_ssl_socket(uint32(sock)) 814 r.rpc_wifi_ssl_client_destroy(uint32(sock)) 815 } 816 817 if result == -1 { 818 return netdev.ErrClosingSocket 819 } 820 821 socket.inuse = false 822 823 return nil 824 } 825 826 func (r *rtl8720dn) SetSockOpt(sockfd int, level int, opt int, value interface{}) error { 827 828 if debugging(debugNetdev) { 829 fmt.Printf("[SetSockOpt] sockfd: %d\r\n", sockfd) 830 } 831 832 return netdev.ErrNotSupported 833 } 834 835 func (r *rtl8720dn) disconnect() error { 836 result := r.rpc_wifi_disconnect() 837 if result == -1 { 838 return fmt.Errorf("Error disconnecting Wifi") 839 } 840 return nil 841 } 842 843 func (r *rtl8720dn) getFwVersion() string { 844 return r.rpc_system_version() 845 } 846 847 func (r *rtl8720dn) getMACAddr() string { 848 var mac [18]uint8 849 r.rpc_wifi_get_mac_address(mac[:]) 850 return string(mac[:]) 851 } 852 853 func (r *rtl8720dn) getIP() (ip, subnet, gateway netip.Addr, err error) { 854 var ip_info [12]byte 855 result := r.rpc_tcpip_adapter_get_ip_info(0, ip_info[:]) 856 if result == -1 { 857 err = fmt.Errorf("Get IP info failed") 858 return 859 } 860 ip, _ = netip.AddrFromSlice(ip_info[0:4]) 861 subnet, _ = netip.AddrFromSlice(ip_info[4:8]) 862 gateway, _ = netip.AddrFromSlice(ip_info[8:12]) 863 return 864 }