mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-03 06:27:47 +00:00
237 lines
4.9 KiB
Go
237 lines
4.9 KiB
Go
package rtl8720dn
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
|
|
"tinygo.org/x/drivers/net/http"
|
|
)
|
|
|
|
func (rtl *RTL8720DN) setupHTTPServer() error {
|
|
_, err := rtl.Rpc_lwip_close(-1)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = rtl.Rpc_lwip_socket(0x00000002, 0x00000001, 0x00000000)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
name := []byte{0x00, 0x02, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0xA5, 0x42, 0x00, 0x00, 0xC7, 0x61, 0x01, 0x00}
|
|
_, err = rtl.Rpc_lwip_bind(0, name, uint32(len(name)))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = rtl.Rpc_lwip_listen(0, 4)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = rtl.Rpc_lwip_fcntl(0, 4, 1)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (rtl *RTL8720DN) accept() (bool, error) {
|
|
addr := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0xD7, 0x00, 0x20, 0x00, 0xD8, 0x00, 0x20}
|
|
length := uint32(len(addr))
|
|
ret, err := rtl.Rpc_lwip_accept(0, addr, &length)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return ret == 1, nil
|
|
}
|
|
|
|
func (rtl *RTL8720DN) handleHTTP() error {
|
|
socket := int32(1)
|
|
optval := []byte{0x01, 0x00, 0x00, 0x00}
|
|
_, err := rtl.Rpc_lwip_setsockopt(socket, 0x00000FFF, 8, optval, uint32(len(optval)))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
_, err = rtl.Rpc_lwip_setsockopt(socket, 6, 1, optval, uint32(len(optval)))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
buf := make([]byte, 4096)
|
|
for {
|
|
_, err = rtl.Rpc_lwip_recv(socket, &buf, uint32(len(buf)), 8, 0)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if len(buf) > 0 {
|
|
break
|
|
}
|
|
|
|
_, err = rtl.Rpc_lwip_errno()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
|
|
buf2 := make([]byte, 4096)
|
|
result, err := rtl.Rpc_lwip_recv(socket, &buf2, uint32(len(buf2)), 8, 0)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if result != -1 && result != 0 {
|
|
return fmt.Errorf("Rpc_lwip_recv error")
|
|
}
|
|
|
|
result, err = rtl.Rpc_lwip_errno()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if result != 11 {
|
|
return fmt.Errorf("Rpc_lwip_errno error")
|
|
}
|
|
|
|
b := bufio.NewReader(bytes.NewReader(buf))
|
|
req, err := http.ReadRequest(b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rtl.debug {
|
|
fmt.Printf("%s %s %s\r\n", req.Method, req.RequestURI, req.Proto)
|
|
}
|
|
|
|
pos := bytes.Index(buf, []byte("\r\n\r\n"))
|
|
if pos > 0 {
|
|
body := bytes.NewReader(buf[pos+4:])
|
|
req.Body = io.NopCloser(body)
|
|
}
|
|
|
|
handler, _ := http.DefaultServeMux.Handler(req)
|
|
rwx := responseWriter{
|
|
header: http.Header{},
|
|
statusCode: 200,
|
|
}
|
|
rwx.header.Add(`Content-Type`, `text/html; charset=UTF-8`)
|
|
rwx.header.Add(`Connection`, `close`)
|
|
handler.ServeHTTP(&rwx, req)
|
|
rwx.header.Add(`Content-Length`, fmt.Sprintf("%d", len(rwx.Buf)))
|
|
|
|
optval = []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xA5, 0xA5, 0xA5}
|
|
_, err = rtl.Rpc_lwip_setsockopt(socket, 0x00000FFF, 0x1006, optval, uint32(len(optval)))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
optval = []byte{0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xA5, 0xA5, 0xA5}
|
|
_, err = rtl.Rpc_lwip_setsockopt(socket, 0x00000FFF, 0x1005, optval, uint32(len(optval)))
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
maxfdp1 := int32(2)
|
|
writeset := []byte{0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
timeout := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x0A, 0x00, 0x00, 0x00}
|
|
_, err = rtl.Rpc_lwip_select(maxfdp1, []byte{}, writeset, []byte{}, timeout)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
msg := rwx.Buf
|
|
hb := bytes.Buffer{}
|
|
err = rwx.header.Write(&hb)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
data := []byte(fmt.Sprintf("HTTP/1.1 %d OK\n", rwx.statusCode))
|
|
data = append(data, hb.Bytes()...)
|
|
data = append(data, byte('\n'))
|
|
|
|
_, err = rtl.Rpc_lwip_send(socket, data, 8)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
if len(msg) > 0 {
|
|
timeout = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0F, 0x00, 0x54, 0x00, 0x00, 0x00}
|
|
_, err = rtl.Rpc_lwip_select(maxfdp1, []byte{}, writeset, []byte{}, timeout)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
_, err = rtl.Rpc_lwip_send(socket, msg, 8)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
for i := 0; i < 4; i++ {
|
|
buf := make([]byte, 4096)
|
|
_, err = rtl.Rpc_lwip_recv(socket, &buf, uint32(len(buf)), 8, 0)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
_, err = rtl.Rpc_lwip_errno()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
_, err = rtl.Rpc_lwip_close(socket)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (rtl *RTL8720DN) ListenAndServe(addr string, handler http.Handler) error {
|
|
err := rtl.setupHTTPServer()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for {
|
|
connected, err := rtl.accept()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if connected {
|
|
err := rtl.handleHTTP()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
type responseWriter struct {
|
|
Buf []byte
|
|
header http.Header
|
|
statusCode int
|
|
}
|
|
|
|
func (r *responseWriter) Header() http.Header {
|
|
return r.header
|
|
}
|
|
|
|
func (r *responseWriter) Write(b []byte) (int, error) {
|
|
r.Buf = append(r.Buf, b...)
|
|
return len(b), nil
|
|
}
|
|
|
|
func (r *responseWriter) WriteHeader(statusCode int) {
|
|
r.statusCode = statusCode
|
|
}
|