Files
drivers/rtl8720dn/netdriver.go
T
2021-08-09 21:11:47 +02:00

375 lines
7.9 KiB
Go

package rtl8720dn
import (
"fmt"
"strconv"
)
// Here is the implementation of tinygo-org/x/drivers/net.DeviceDriver.
func (r *RTL8720DN) GetDNS(domain string) (string, error) {
if r.debug {
fmt.Printf("GetDNS(%q)\r\n", domain)
}
ipaddr := make([]byte, 4)
_, err := r.Rpc_netconn_gethostbyname(domain, &ipaddr)
if err != nil {
return "", err
}
ret, err := fmt.Sprintf("%d.%d.%d.%d", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]), nil
if r.debug {
fmt.Printf("-> %s\r\n", ret)
fmt.Printf("-> %02X.%02X.%02X.%02X\r\n", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3])
}
return ret, err
}
func (r *RTL8720DN) ConnectTCPSocket(addr, port string) error {
if r.debug {
fmt.Printf("ConnectTCPSocket(%q, %q)\r\n", addr, port)
}
ipaddr := make([]byte, 4)
if len(addr) == 4 {
copy(ipaddr, addr)
} else {
_, err := r.Rpc_netconn_gethostbyname(addr, &ipaddr)
if err != nil {
return err
}
}
portNum, err := strconv.ParseUint(port, 0, 0)
if err != nil {
return err
}
socket, err := r.Rpc_lwip_socket(0x02, 0x01, 0x00)
if err != nil {
return err
}
r.socket = socket
r.connectionType = ConnectionTypeTCP
_, err = r.Rpc_lwip_fcntl(socket, 0x00000003, 0x00000000)
if err != nil {
return err
}
_, err = r.Rpc_lwip_fcntl(socket, 0x00000004, 0x00000001)
if err != nil {
return err
}
name := []byte{0x00, 0x02, 0x00, 0x50, 0xC0, 0xA8, 0x01, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
name[2] = byte(portNum >> 8)
name[3] = byte(portNum)
name[4] = byte(ipaddr[0])
name[5] = byte(ipaddr[1])
name[6] = byte(ipaddr[2])
name[7] = byte(ipaddr[3])
_, err = r.Rpc_lwip_connect(socket, name, uint32(len(name)))
if err != nil {
return err
}
readset := []byte{}
writeset := []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
exceptset := []byte{}
timeout := []byte{}
_, err = r.Rpc_lwip_select(0x01, readset, writeset, exceptset, timeout)
if err != nil {
return err
}
optval := make([]byte, 4)
optlen := uint32(len(optval))
_, err = r.Rpc_lwip_getsockopt(socket, 0x00000FFF, 0x00001007, []byte{0xA5, 0xA5, 0xA5, 0xA5}, &optval, &optlen)
if err != nil {
return err
}
_, err = r.Rpc_lwip_fcntl(socket, 0x00000003, 0x00000000)
if err != nil {
return err
}
_, err = r.Rpc_lwip_fcntl(socket, 0x00000004, 0x00000000)
if err != nil {
return err
}
readset = []byte{}
writeset = []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
exceptset = []byte{}
timeout = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}
_, err = r.Rpc_lwip_select(0x01, readset, writeset, exceptset, timeout)
if err != nil {
return err
}
return nil
}
func (r *RTL8720DN) ConnectSSLSocket(addr, port string) error {
if r.debug {
fmt.Printf("ConnectSSLSocket(%q, %q)\r\n", addr, port)
}
client, err := r.Rpc_wifi_ssl_client_create()
if err != nil {
return err
}
r.client = client
r.connectionType = ConnectionTypeTLS
err = r.Rpc_wifi_ssl_init(client)
if err != nil {
return err
}
err = r.Rpc_wifi_ssl_set_timeout(client, 0x0001D4C0)
if err != nil {
return err
}
_, err = r.Rpc_wifi_ssl_set_rootCA(client, *r.root_ca)
if err != nil {
return err
}
// TODO: use port
_, err = r.Rpc_wifi_start_ssl_client(client, addr, 443, 0x0001D4C0)
if err != nil {
return err
}
_, err = r.Rpc_wifi_ssl_get_socket(client)
if err != nil {
return err
}
return nil
}
func (r *RTL8720DN) ConnectUDPSocket(addr, sendport, listenport string) error {
if r.debug {
fmt.Printf("ConnectUDPSocket(\"%d.%d.%d.%d\", %q, %q)\r\n", byte(addr[0]), byte(addr[1]), byte(addr[2]), byte(addr[3]), sendport, listenport)
}
socket, err := r.Rpc_lwip_socket(0x02, 0x02, 0x00)
if err != nil {
return err
}
r.socket = socket
r.connectionType = ConnectionTypeUDP
optval := []byte{0x01, 0x00, 0x00, 0x00}
_, err = r.Rpc_lwip_setsockopt(socket, 0x00000FFF, 0x00000004, optval, uint32(len(optval)))
if err != nil {
return err
}
port, err := strconv.ParseUint(sendport, 10, 0)
if err != nil {
return err
}
ip := []byte(addr)
// remote info
r.udpInfo[0] = byte(port >> 8)
r.udpInfo[1] = byte(port)
r.udpInfo[2] = ip[0]
r.udpInfo[3] = ip[1]
r.udpInfo[4] = ip[2]
r.udpInfo[5] = ip[3]
port, err = strconv.ParseUint(listenport, 10, 0)
if err != nil {
return err
}
ip_info := make([]byte, 12)
_, err = r.Rpc_tcpip_adapter_get_ip_info(0, &ip_info)
if err != nil {
return err
}
name := []byte{0x00, 0x02, 0x0D, 0x05, 0xC0, 0xA8, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
name[2] = byte(port >> 8)
name[3] = byte(port)
name[4] = ip_info[0]
name[5] = ip_info[1]
name[6] = ip_info[2]
name[7] = ip_info[3]
_, err = r.Rpc_lwip_bind(socket, name, uint32(len(name)))
if err != nil {
return err
}
_, err = r.Rpc_lwip_fcntl(socket, 0x00000004, 0x00000000)
if err != nil {
return err
}
return nil
}
func (r *RTL8720DN) DisconnectSocket() error {
if r.debug {
fmt.Printf("DisconnectSocket()\r\n")
}
switch r.connectionType {
case ConnectionTypeTCP:
_, err := r.Rpc_lwip_close(r.socket)
if err != nil {
return err
}
case ConnectionTypeTLS:
err := r.Rpc_wifi_stop_ssl_socket(r.client)
if err != nil {
return err
}
err = r.Rpc_wifi_ssl_client_destroy(r.client)
if err != nil {
return err
}
default:
}
r.connectionType = ConnectionTypeNone
return nil
}
func (r *RTL8720DN) StartSocketSend(size int) error {
if r.debug {
fmt.Printf("StartSocketSend(%d)\r\n", size)
}
// No implementation required
return nil
}
func (r *RTL8720DN) Write(b []byte) (n int, err error) {
if r.debug {
fmt.Printf("Write(%#v)\r\n", b)
}
switch r.connectionType {
case ConnectionTypeTCP:
sn, err := r.Rpc_lwip_send(r.socket, b, 0x00000008)
if err != nil {
return 0, err
}
n = int(sn)
case ConnectionTypeUDP:
to := []byte{0x00, 0x02, 0x0D, 0x05, 0xC0, 0xA8, 0x01, 0x76, 0xEB, 0x43, 0x00, 0x00, 0xD5, 0x27, 0x01, 0x00}
copy(to[2:], r.udpInfo[:])
sn, err := r.Rpc_lwip_sendto(r.socket, b, 0x00000000, to, uint32(len(to)))
if err != nil {
return 0, err
}
n = int(sn)
case ConnectionTypeTLS:
sn, err := r.Rpc_wifi_send_ssl_data(r.client, b, uint16(len(b)))
if err != nil {
return 0, err
}
n = int(sn)
default:
return 0, nil
}
return n, nil
}
func (r *RTL8720DN) ReadSocket(b []byte) (n int, err error) {
if r.debug {
//fmt.Printf("ReadSocket(b)\r\n")
}
if r.connectionType == ConnectionTypeNone {
return 0, nil
}
switch r.connectionType {
case ConnectionTypeTCP:
length := len(b)
if length > maxUartRecvSize-16 {
length = maxUartRecvSize - 16
}
buf := b[:length]
nn, err := r.Rpc_lwip_recv(r.socket, &buf, uint32(length), 0x00000008, 0x00002800)
if err != nil {
return 0, err
}
if nn == -1 {
return 0, nil
} else if nn == 0 {
return 0, r.DisconnectSocket()
}
n = int(nn)
case ConnectionTypeUDP:
length := len(b)
if length > maxUartRecvSize-32 {
length = maxUartRecvSize - 32
}
buf := b[:length]
from := make([]byte, 16)
fromLen := uint32(len(from))
nn, err := r.Rpc_lwip_recvfrom(r.socket, &buf, uint32(length), 0x00000008, &from, &fromLen, 10000)
if err != nil {
return 0, err
}
if nn == -1 {
return 0, nil
}
n = int(nn)
case ConnectionTypeTLS:
length := len(b)
if length > maxUartRecvSize-16 {
length = maxUartRecvSize - 16
}
buf := b[:length]
nn, err := r.Rpc_wifi_get_ssl_receive(r.client, &buf, int32(length))
if err != nil {
return 0, err
}
if nn < 0 {
return 0, fmt.Errorf("error %d", n)
} else if nn == 0 || nn == -30848 {
return 0, r.DisconnectSocket()
}
n = int(nn)
default:
}
return n, nil
}
func (r *RTL8720DN) IsSocketDataAvailable() bool {
if r.debug {
fmt.Printf("IsSocketDataAvailable()\r\n")
}
ret, err := r.Rpc_lwip_available(r.socket)
if err != nil {
fmt.Printf("error: %s\r\n", err.Error())
return false
}
if ret == 1 {
return true
}
return false
}
func (r *RTL8720DN) Response(timeout int) ([]byte, error) {
if r.debug {
fmt.Printf("Response(%d))\r\n", timeout)
}
// No implementation required
return nil, nil
}