mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-10 18:03:41 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 85a28fb937 | |||
| 9b74ecbc36 | |||
| 1690c2c2d8 | |||
| cdc76f3ea7 | |||
| 68ccd70c56 | |||
| f657269a66 | |||
| 6913eaf2b9 | |||
| d4705e501d | |||
| 728bdbba5b | |||
| b4f43b4d21 | |||
| 570e3d2b71 | |||
| 7e45551ff5 | |||
| 60cdb7fd50 | |||
| 731362a0cf |
@@ -1,231 +0,0 @@
|
|||||||
package apds9930
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"tinygo.org/x/drivers"
|
|
||||||
)
|
|
||||||
|
|
||||||
var errInvalidParam = errors.New("apds9930: invalid param")
|
|
||||||
|
|
||||||
type Dev struct {
|
|
||||||
bus drivers.I2C
|
|
||||||
_txerr error
|
|
||||||
addr uint16
|
|
||||||
buf [3]byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(bus drivers.I2C, addr uint8) Dev {
|
|
||||||
return Dev{bus: bus, addr: uint16(addr)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status contains info on:
|
|
||||||
//
|
|
||||||
// AVALID: Indicates that the ALS Ch0/Ch1 channels have completed an integration cycle.
|
|
||||||
// PSValid. Indicates that the PS has completed an integration cycle.
|
|
||||||
// AINTL ALS Interrupt. Indicates that the device is asserting an ALS interrupt
|
|
||||||
// PINT: Proximity Interrupt. Indicates that the device is asserting a proximity interrupt.
|
|
||||||
// PSAT: Proximity Saturation. Indicates that the proximity measurement is saturated
|
|
||||||
type Status uint8
|
|
||||||
|
|
||||||
func (s Status) ALSAvailable() bool { return s&(1<<0) != 0 } // AVALID
|
|
||||||
func (s Status) ProximityAvailable() bool { return s&(1<<1) != 0 } // PVALID
|
|
||||||
func (s Status) HasALSInterrupt() bool { return s&(1<<4) != 0 } // AINT
|
|
||||||
func (s Status) HasProxInterrupt() bool { return s&(1<<5) != 0 } // PINT
|
|
||||||
func (s Status) IsProximitySaturated() bool { return s&(1<<6) != 0 } // PSAT
|
|
||||||
|
|
||||||
type Enable uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
EnPower Enable = 1 << iota
|
|
||||||
EnALS
|
|
||||||
EnProx
|
|
||||||
EnWait
|
|
||||||
EnALSInt
|
|
||||||
EnProxInt
|
|
||||||
EnSleepAfterInt
|
|
||||||
)
|
|
||||||
|
|
||||||
// Luminic control gain.
|
|
||||||
type ALSGain uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
AGain1 ALSGain = iota
|
|
||||||
AGain8
|
|
||||||
AGain16
|
|
||||||
AGain120
|
|
||||||
)
|
|
||||||
|
|
||||||
type ProxGain uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
PGain1 ProxGain = iota
|
|
||||||
PGain2
|
|
||||||
PGain4
|
|
||||||
PGain8
|
|
||||||
)
|
|
||||||
|
|
||||||
type Drive uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
Drive100mA Drive = iota
|
|
||||||
Drive50mA
|
|
||||||
Drive25mA
|
|
||||||
Drive12_5mA
|
|
||||||
)
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
ProxGain ProxGain
|
|
||||||
ALSGain ALSGain
|
|
||||||
LEDDrive Drive
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) Init(cfg Config) error {
|
|
||||||
if cfg.LEDDrive > Drive100mA {
|
|
||||||
return errInvalidParam
|
|
||||||
}
|
|
||||||
d.txNew()
|
|
||||||
d.txWrite8(regENABLE, 0x00) // disable all features.
|
|
||||||
d.txWrite8(regATIME, 0xee) // set default integration time.
|
|
||||||
d.txWrite8(regPPULSE, 0x04)
|
|
||||||
d.txWrite8(regWTIME, 0xee) // set default wait time.
|
|
||||||
d.txWrite8(regPTIME, 0xff) // set default pulse count.
|
|
||||||
|
|
||||||
var ctlval uint8 = 0b10 << 4 // Use Channel 1 diode.
|
|
||||||
ctlval |= uint8(cfg.LEDDrive&0b11) << 6
|
|
||||||
ctlval |= uint8(cfg.ProxGain&0b11) << 2
|
|
||||||
ctlval |= uint8(cfg.ALSGain & 0b11)
|
|
||||||
d.txWrite8(regCONTROL, ctlval)
|
|
||||||
return d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) Status() (Status, error) {
|
|
||||||
d.txNew()
|
|
||||||
v := d.txRead8(regSTATUS)
|
|
||||||
return Status(v), d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable sets the ENABLE register used primarily to
|
|
||||||
// power the APDS-9930 device on/off, enable functions, and interrupts.
|
|
||||||
// Arguments must be ORed, i.e: d.Enable(EnPower|EnProx); to enable proximity.
|
|
||||||
func (d *Dev) Enable(en Enable) error {
|
|
||||||
en &= 0b01111111 // Seventh bit reserved.
|
|
||||||
d.txNew()
|
|
||||||
d.txWrite8(regENABLE, uint8(en))
|
|
||||||
return d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) enableLightSensor(withInterrupts bool) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) setAmbientLightGain() {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) EnableProximity() error {
|
|
||||||
return d.Enable(EnPower | EnALS | EnProx | EnWait)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) proxIntLowThresh() (uint16, error) {
|
|
||||||
d.txNew()
|
|
||||||
return d.txRead16(regPILTL), d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) setProxIntLowThresh(loThresh uint16) error {
|
|
||||||
d.txNew()
|
|
||||||
d.txWrite16(regPILTL, loThresh)
|
|
||||||
return d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) proxIntHighThresh() (uint16, error) {
|
|
||||||
d.txNew()
|
|
||||||
val := d.txRead16(regPIHTL)
|
|
||||||
return val, d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) setProxIntHighThresh(hiThresh uint16) error {
|
|
||||||
d.txNew()
|
|
||||||
d.txWrite16(regPIHTL, hiThresh)
|
|
||||||
return d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) LEDDrive() (Drive, error) {
|
|
||||||
d.txNew()
|
|
||||||
val := (d.txRead8(regCONTROL) >> 6) & 0b11
|
|
||||||
return Drive(val), d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetLEDDrive drive strength for proximity and ALS
|
|
||||||
//
|
|
||||||
// Value LED Current
|
|
||||||
// 3 100 mA
|
|
||||||
// 2 50 mA
|
|
||||||
// 1 25 mA
|
|
||||||
// 0 12.5 mA
|
|
||||||
func (d *Dev) SetLEDDrive(drive Drive) error {
|
|
||||||
if drive > 3 {
|
|
||||||
return errInvalidParam
|
|
||||||
}
|
|
||||||
current, err := d.LEDDrive()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Replace LED bits in Control register.
|
|
||||||
current &= 0b00111111
|
|
||||||
current |= drive << 6
|
|
||||||
d.txNew()
|
|
||||||
d.txWrite8(regCONTROL, uint8(current))
|
|
||||||
return d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) proxGain() (uint8, error) {
|
|
||||||
val := d.txRead8(regCONTROL)
|
|
||||||
return (val >> 2) & 0b11, d.txErr()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadProximity returns a 10-bit value (0..1023), the higher the value the closer the object
|
|
||||||
func (d *Dev) ReadProximity() uint16 {
|
|
||||||
d.txNew()
|
|
||||||
v := d.txRead16(regPDATAL)
|
|
||||||
if d.txErr() != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) txRead16(addr uint8) uint16 {
|
|
||||||
if d.txErr() != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
d.buf[0] = addr | protoAutoInc
|
|
||||||
d._txerr = d.bus.Tx(d.addr, d.buf[:1], d.buf[1:3])
|
|
||||||
return uint16(d.buf[1]) | uint16(d.buf[2])<<8
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) txRead8(addr uint8) uint8 {
|
|
||||||
if d.txErr() != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
d.buf[0] = addr | protoAutoInc
|
|
||||||
d._txerr = d.bus.Tx(d.addr, d.buf[:1], d.buf[1:2])
|
|
||||||
return d.buf[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) txWrite16(addr uint8, val uint16) {
|
|
||||||
d.txWrite8(addr, uint8(val))
|
|
||||||
d.txWrite8(addr+1, uint8(val>>8))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) txWrite8(reg uint8, val uint8) {
|
|
||||||
if d.txErr() != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
d.buf[0] = reg | 0x80
|
|
||||||
d.buf[1] = val
|
|
||||||
d._txerr = d.bus.Tx(d.addr, d.buf[:2], nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Dev) txNew() { d._txerr = nil }
|
|
||||||
|
|
||||||
func (d *Dev) txErr() error { return d._txerr }
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package apds9930
|
|
||||||
|
|
||||||
const (
|
|
||||||
protoAutoInc = 0xA0
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
regENABLE = 0x00
|
|
||||||
regATIME = 0x01
|
|
||||||
regPTIME = 0x02
|
|
||||||
regWTIME = 0x03
|
|
||||||
regPILTL = 0x08
|
|
||||||
regPILTH = 0x09
|
|
||||||
regPIHTL = 0x0A
|
|
||||||
regPIHTH = 0x0B
|
|
||||||
regCONFIG = 0x0D
|
|
||||||
regPPULSE = 0x0E
|
|
||||||
regCONTROL = 0x0F
|
|
||||||
regSTATUS = 0x13
|
|
||||||
regPDATAL = 0x18
|
|
||||||
regPDATAH = 0x19
|
|
||||||
regPOFFSET = 0x1E
|
|
||||||
)
|
|
||||||
+2
-2
@@ -218,8 +218,8 @@ func (d *Device) Listen(sockfd int, backlog int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) Accept(sockfd int) (int, netip.AddrPort, error) {
|
func (d *Device) Accept(sockfd int, ip netip.AddrPort) (int, error) {
|
||||||
return -1, netip.AddrPort{}, netdev.ErrNotSupported
|
return -1, netdev.ErrNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) sendChunk(sockfd int, buf []byte, deadline time.Time) (int, error) {
|
func (d *Device) sendChunk(sockfd int, buf []byte, deadline time.Time) (int, error) {
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"machine"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"tinygo.org/x/drivers/apds9930"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Sleep to catch any errors through the serial monitor.
|
|
||||||
time.Sleep(1000 * time.Millisecond)
|
|
||||||
bus := machine.I2C0
|
|
||||||
// use Nano 33 BLE Sense's internal I2C bus
|
|
||||||
err := bus.Configure(machine.I2CConfig{
|
|
||||||
SCL: machine.GP1,
|
|
||||||
SDA: machine.GP0,
|
|
||||||
Frequency: 100 * machine.KHz,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
sensor := apds9930.New(bus, 0x39)
|
|
||||||
|
|
||||||
err = sensor.Init(apds9930.Config{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = sensor.EnableProximity()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
println("proximity enabled!")
|
|
||||||
for {
|
|
||||||
stat, _ := sensor.Status()
|
|
||||||
if !stat.ProximityAvailable() {
|
|
||||||
time.Sleep(5 * time.Millisecond)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
prox := sensor.ReadProximity()
|
|
||||||
println("proximity:", prox)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -30,18 +30,16 @@ var (
|
|||||||
var buf [1024]byte
|
var buf [1024]byte
|
||||||
|
|
||||||
func echo(conn net.Conn) {
|
func echo(conn net.Conn) {
|
||||||
println("Client", conn.RemoteAddr(), "connected")
|
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
_, err := io.CopyBuffer(conn, conn, buf[:])
|
_, err := io.CopyBuffer(conn, conn, buf[:])
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
println("Client", conn.RemoteAddr(), "closed")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
link, _ := probe.Probe()
|
link, _ := probe.Probe()
|
||||||
|
|
||||||
@@ -53,7 +51,6 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Starting TCP server listening on", port)
|
|
||||||
l, err := net.Listen("tcp", port)
|
l, err := net.Listen("tcp", port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err.Error())
|
log.Fatal(err.Error())
|
||||||
|
|||||||
+1
-1
@@ -82,7 +82,7 @@ type Netdever interface {
|
|||||||
Bind(sockfd int, ip netip.AddrPort) error
|
Bind(sockfd int, ip netip.AddrPort) error
|
||||||
Connect(sockfd int, host string, ip netip.AddrPort) error
|
Connect(sockfd int, host string, ip netip.AddrPort) error
|
||||||
Listen(sockfd int, backlog int) error
|
Listen(sockfd int, backlog int) error
|
||||||
Accept(sockfd int) (int, netip.AddrPort, error)
|
Accept(sockfd int, ip netip.AddrPort) (int, error)
|
||||||
Send(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)
|
Send(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)
|
||||||
Recv(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)
|
Recv(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)
|
||||||
Close(sockfd int) error
|
Close(sockfd int) error
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package netif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AutoProbe(timeout time.Duration) (Stack, error) {
|
||||||
|
// This function automatically gets the first available network device
|
||||||
|
// and returns a stack for it.
|
||||||
|
// It is intended to be used by the user as a convenience function.
|
||||||
|
// Will be guarded by build tags and specific for whether the device
|
||||||
|
// is a StackWifi, InterfaceEthPollWifi or InterfaceEthPoller.
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ProbeStackWifi() StackWifi {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func ProbeEthPollWifi() InterfaceEthPollWifi {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func ProbeEthPoller() InterfaceEthPoller {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func StackForEthPoll(dev InterfaceEthPoller) Stack {
|
||||||
|
// Use seqs to generate a stack.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSI layer 4 enabled WIFI chip. i.e.: ESP32
|
||||||
|
func ExampleProbeStackWifi() {
|
||||||
|
dev := ProbeStackWifi()
|
||||||
|
wifiparams := WifiParams{
|
||||||
|
SSID: "myssid",
|
||||||
|
ConnectMode: ConnectModeSTA,
|
||||||
|
Passphrase: "mypassphrase",
|
||||||
|
Auth: AuthTypeWPA2,
|
||||||
|
CountryCode: "US",
|
||||||
|
}
|
||||||
|
err := StartWifiAutoconnect(dev, WifiAutoconnectParams{
|
||||||
|
WifiParams: wifiparams,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for dev.NetFlags()&net.FlagRunning == 0 {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
UseStack(dev)
|
||||||
|
net.Dial("tcp", "192.168.1.1:33")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simplest case, OSI layer 2 enabled WIFI chip, i.e: CYW43439
|
||||||
|
func ExampleProbeEthPollWifi() {
|
||||||
|
dev := ProbeEthPollWifi()
|
||||||
|
wifiparams := WifiParams{
|
||||||
|
SSID: "myssid",
|
||||||
|
ConnectMode: ConnectModeSTA,
|
||||||
|
Passphrase: "mypassphrase",
|
||||||
|
Auth: AuthTypeWPA2,
|
||||||
|
CountryCode: "US",
|
||||||
|
}
|
||||||
|
err := StartWifiAutoconnect(dev, WifiAutoconnectParams{
|
||||||
|
WifiParams: wifiparams,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for dev.NetFlags()&net.FlagRunning == 0 {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
stack := StackForEthPoll(dev)
|
||||||
|
UseStack(stack)
|
||||||
|
net.Dial("tcp", "192.168.1.1:33")
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSI level 2 chip with wired connection, i.e. ENC28J60.
|
||||||
|
func ExampleProbeEthPoller() {
|
||||||
|
dev := ProbeEthPoller()
|
||||||
|
if dev.NetFlags()&net.FlagRunning == 0 {
|
||||||
|
panic("ethernet not connected")
|
||||||
|
}
|
||||||
|
stack := StackForEthPoll(dev)
|
||||||
|
UseStack(stack)
|
||||||
|
net.Dial("tcp", "192.168.1.1:33")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleAutoProbe() {
|
||||||
|
stack, err := AutoProbe(10 * time.Second)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
UseStack(stack)
|
||||||
|
net.Dial("tcp", "192.168.1.1:33")
|
||||||
|
}
|
||||||
+211
@@ -0,0 +1,211 @@
|
|||||||
|
package netif
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"time"
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname UseStack net.useNetdev
|
||||||
|
func UseStack(stack Stack)
|
||||||
|
|
||||||
|
// Socket errors.
|
||||||
|
var (
|
||||||
|
ErrProtocolNotSupported = errors.New("socket protocol/type not supported")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Wifi errors.
|
||||||
|
var (
|
||||||
|
ErrAuthFailure = errors.New("wifi authentication failure")
|
||||||
|
ErrAuthUnsupported = errors.New("wifi authorization type not supported")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_AF_INET = 0x2
|
||||||
|
_SOCK_STREAM = 0x1
|
||||||
|
_SOCK_DGRAM = 0x2
|
||||||
|
_SOL_SOCKET = 0x1
|
||||||
|
_SO_KEEPALIVE = 0x9
|
||||||
|
_SOL_TCP = 0x6
|
||||||
|
_TCP_KEEPINTVL = 0x5
|
||||||
|
_IPPROTO_TCP = 0x6
|
||||||
|
_IPPROTO_UDP = 0x11
|
||||||
|
// Made up, not a real IP protocol number. This is used to create a
|
||||||
|
// TLS socket on the device, assuming the device supports mbed TLS.
|
||||||
|
_IPPROTO_TLS = 0xFE
|
||||||
|
_F_SETFL = 0x4
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface is the minimum interface that need be implemented by any network
|
||||||
|
// device driver and is based on [net.Interface].
|
||||||
|
type Interface interface {
|
||||||
|
// HardwareAddr6 returns the device's 6-byte [MAC address].
|
||||||
|
//
|
||||||
|
// [MAC address]: https://en.wikipedia.org/wiki/MAC_address
|
||||||
|
HardwareAddr6() ([6]byte, error)
|
||||||
|
// NetFlags returns the net.Flag values for the interface. It includes state of connection.
|
||||||
|
NetFlags() net.Flags
|
||||||
|
// MTU returns the maximum transmission unit size.
|
||||||
|
MTU() int
|
||||||
|
// Notify to register callback for network events. May not be supported for certain devices.
|
||||||
|
NetNotify(cb func(Event)) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfaceEthPoller is implemented by devices that send/receive ethernet packets.
|
||||||
|
type InterfaceEthPoller interface {
|
||||||
|
Interface
|
||||||
|
// SendEth sends an Ethernet packet
|
||||||
|
SendEth(pkt []byte) error
|
||||||
|
// RecvEthHandle sets recieve Ethernet packet callback function
|
||||||
|
RecvEthHandle(func(pkt []byte) error)
|
||||||
|
// PollOne tries to receive one Ethernet packet and returns true if one was
|
||||||
|
PollOne() (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfaceWifi is implemented by a interface device that has the capacity
|
||||||
|
// to connect to wifi networks.
|
||||||
|
type InterfaceWifi interface {
|
||||||
|
Interface
|
||||||
|
// Connect device to network
|
||||||
|
NetConnect(params WifiParams) error
|
||||||
|
// Disconnect device from network
|
||||||
|
NetDisconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfaceEthPollWifi is implemented by devices that connect to wifi networks
|
||||||
|
// and send/receive ethernet packets (OSI level 2).
|
||||||
|
type InterfaceEthPollWifi interface {
|
||||||
|
InterfaceWifi
|
||||||
|
InterfaceEthPoller
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stack interface {
|
||||||
|
// GetHostByName returns the IP address of either a hostname or IPv4
|
||||||
|
// address in standard dot notation
|
||||||
|
// GetHostByName(name string) (netip.Addr, error)
|
||||||
|
|
||||||
|
// Addr returns IP address assigned to the interface, either by
|
||||||
|
// DHCP or statically
|
||||||
|
Addr() (netip.Addr, error)
|
||||||
|
|
||||||
|
// Berkely Sockets-like interface, Go-ified. See man page for socket(2), etc.
|
||||||
|
Socket(domain int, stype int, protocol int) (int, error)
|
||||||
|
Bind(sockfd int, ip netip.AddrPort) error
|
||||||
|
Connect(sockfd int, host string, ip netip.AddrPort) error
|
||||||
|
Listen(sockfd int, backlog int) error
|
||||||
|
Accept(sockfd int) (int, netip.AddrPort, error)
|
||||||
|
Send(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)
|
||||||
|
Recv(sockfd int, buf []byte, flags int, deadline time.Time) (int, error)
|
||||||
|
Close(sockfd int) error
|
||||||
|
SetSockOpt(sockfd int, level int, opt int, value interface{}) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolver is implemented by DNS resolvers, notably Go's [net.DefaultResolver].
|
||||||
|
type Resolver interface {
|
||||||
|
// LookupNetIP looks up host using the local resolver.
|
||||||
|
// It returns a slice of that host's IP addresses of the type specified by
|
||||||
|
// network.
|
||||||
|
// The network must be one of "ip", "ip4" or "ip6".
|
||||||
|
LookupNetIP(ctx context.Context, network, host string) ([]netip.Addr, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StackWifi is returned by `Probe` function for devices that communicate
|
||||||
|
// on the OSI level 4 (transport) layer.
|
||||||
|
type StackWifi interface {
|
||||||
|
InterfaceWifi
|
||||||
|
Stack
|
||||||
|
}
|
||||||
|
|
||||||
|
type WifiParams struct {
|
||||||
|
// Connect mode
|
||||||
|
ConnectMode ConnectMode
|
||||||
|
|
||||||
|
// SSID of Wifi AP
|
||||||
|
SSID string
|
||||||
|
|
||||||
|
// Passphrase of Wifi AP
|
||||||
|
Passphrase string
|
||||||
|
|
||||||
|
// Wifi authorization type
|
||||||
|
Auth AuthType
|
||||||
|
|
||||||
|
// Wifi country code as two-char string. E.g. "XX" for world-wide,
|
||||||
|
// "US" for USA, etc.
|
||||||
|
CountryCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Event uint8
|
||||||
|
|
||||||
|
// Network events
|
||||||
|
const (
|
||||||
|
// The device's network connection is now UP
|
||||||
|
EventNetUp Event = iota
|
||||||
|
// The device's network connection is now DOWN
|
||||||
|
EventNetDown
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConnectMode uint8
|
||||||
|
|
||||||
|
// Connect modes
|
||||||
|
const (
|
||||||
|
ConnectModeSTA = iota // Connect as Wifi station (default)
|
||||||
|
ConnectModeAP // Connect as Wifi Access Point
|
||||||
|
)
|
||||||
|
|
||||||
|
type AuthType uint8
|
||||||
|
|
||||||
|
// Wifi authorization types. Used when setting up an access point, or
|
||||||
|
// connecting to an access point
|
||||||
|
const (
|
||||||
|
AuthTypeWPA2 = iota // WPA2 authorization (default)
|
||||||
|
AuthTypeOpen // No authorization required (open)
|
||||||
|
AuthTypeWPA // WPA authorization
|
||||||
|
AuthTypeWPA2Mixed // WPA2/WPA mixed authorization
|
||||||
|
)
|
||||||
|
|
||||||
|
type WifiAutoconnectParams struct {
|
||||||
|
WifiParams
|
||||||
|
|
||||||
|
// Retries is how many attempts to connect before returning with a
|
||||||
|
// "Connect failed" error. Zero means infinite retries.
|
||||||
|
// Retries int // Probably should be implemented as a function
|
||||||
|
|
||||||
|
// Timeout duration for each connection attempt. The default zero
|
||||||
|
// value means 10sec.
|
||||||
|
ConnectTimeout time.Duration
|
||||||
|
|
||||||
|
// Watchdog ticker duration. On tick, the watchdog will check for
|
||||||
|
// downed connection or hardware fault and try to recover the
|
||||||
|
// connection. Set to zero to disable watchodog.
|
||||||
|
WatchdogTimeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartWifiAutoconnect(dev InterfaceWifi, cfg WifiAutoconnectParams) error {
|
||||||
|
if dev == nil {
|
||||||
|
return errors.New("nil device")
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
// Wifi autoconnect algorithm in one place,
|
||||||
|
// no need to implement for every single netdever.
|
||||||
|
RECONNECT:
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
err := dev.NetConnect(cfg.WifiParams)
|
||||||
|
if err != nil {
|
||||||
|
time.Sleep(cfg.ConnectTimeout)
|
||||||
|
goto RECONNECT
|
||||||
|
}
|
||||||
|
// Once connected reset the retry counter.
|
||||||
|
i = 0
|
||||||
|
for cfg.WatchdogTimeout != 0 {
|
||||||
|
time.Sleep(cfg.WatchdogTimeout)
|
||||||
|
if dev.NetFlags()&net.FlagRunning == 0 {
|
||||||
|
goto RECONNECT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+6
-20
@@ -437,12 +437,6 @@ func ipToName(ip netip.AddrPort) []byte {
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func nameToIp(name []byte) netip.AddrPort {
|
|
||||||
port := uint16(name[2])<<8 | uint16(name[3])
|
|
||||||
addr, _ := netip.AddrFromSlice(name[4:8])
|
|
||||||
return netip.AddrPortFrom(addr, port)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *rtl8720dn) Bind(sockfd int, ip netip.AddrPort) error {
|
func (r *rtl8720dn) Bind(sockfd int, ip netip.AddrPort) error {
|
||||||
|
|
||||||
if debugging(debugNetdev) {
|
if debugging(debugNetdev) {
|
||||||
@@ -540,10 +534,10 @@ func (r *rtl8720dn) Listen(sockfd int, backlog int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rtl8720dn) Accept(sockfd int) (int, netip.AddrPort, error) {
|
func (r *rtl8720dn) Accept(sockfd int, ip netip.AddrPort) (int, error) {
|
||||||
|
|
||||||
if debugging(debugNetdev) {
|
if debugging(debugNetdev) {
|
||||||
fmt.Printf("[Accept] sockfd: %d\r\n", sockfd)
|
fmt.Printf("[Accept] sockfd: %d, peer: %s\r\n", sockfd, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
@@ -552,12 +546,12 @@ func (r *rtl8720dn) Accept(sockfd int) (int, netip.AddrPort, error) {
|
|||||||
var newSock int32
|
var newSock int32
|
||||||
var lsock = sock(sockfd)
|
var lsock = sock(sockfd)
|
||||||
var socket = r.sockets[lsock]
|
var socket = r.sockets[lsock]
|
||||||
var name = ipToName(netip.AddrPort{})
|
var name = ipToName(ip)
|
||||||
|
|
||||||
switch socket.protocol {
|
switch socket.protocol {
|
||||||
case netdev.IPPROTO_TCP:
|
case netdev.IPPROTO_TCP:
|
||||||
default:
|
default:
|
||||||
return -1, netip.AddrPort{}, netdev.ErrProtocolNotSupported
|
return -1, netdev.ErrProtocolNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -576,14 +570,6 @@ func (r *rtl8720dn) Accept(sockfd int) (int, netip.AddrPort, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get remote peer ip:port
|
|
||||||
namelen = uint32(len(name))
|
|
||||||
result := r.rpc_lwip_getpeername(int32(newSock), name, &namelen)
|
|
||||||
if result == -1 {
|
|
||||||
return -1, netip.AddrPort{}, fmt.Errorf("Getpeername failed")
|
|
||||||
}
|
|
||||||
raddr := nameToIp(name)
|
|
||||||
|
|
||||||
// If we've already seen this socket, we can re-use
|
// If we've already seen this socket, we can re-use
|
||||||
// the socket and return it. But, only if the socket
|
// the socket and return it. But, only if the socket
|
||||||
// is closed. If it's not closed, we'll just come back
|
// is closed. If it's not closed, we'll just come back
|
||||||
@@ -596,12 +582,12 @@ func (r *rtl8720dn) Accept(sockfd int) (int, netip.AddrPort, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Reuse client socket
|
// Reuse client socket
|
||||||
return int(newSock), raddr, nil
|
return int(newSock), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new socket for client and return fd
|
// Create new socket for client and return fd
|
||||||
r.sockets[sock(newSock)] = newSocket(socket.protocol)
|
r.sockets[sock(newSock)] = newSocket(socket.protocol)
|
||||||
return int(newSock), raddr, nil
|
return int(newSock), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-25
@@ -676,10 +676,10 @@ func (w *wifinina) Listen(sockfd int, backlog int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *wifinina) Accept(sockfd int) (int, netip.AddrPort, error) {
|
func (w *wifinina) Accept(sockfd int, ip netip.AddrPort) (int, error) {
|
||||||
|
|
||||||
if debugging(debugNetdev) {
|
if debugging(debugNetdev) {
|
||||||
fmt.Printf("[Accept] sockfd: %d\r\n", sockfd)
|
fmt.Printf("[Accept] sockfd: %d, peer: %s\r\n", sockfd, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
@@ -692,7 +692,7 @@ func (w *wifinina) Accept(sockfd int) (int, netip.AddrPort, error) {
|
|||||||
switch socket.protocol {
|
switch socket.protocol {
|
||||||
case netdev.IPPROTO_TCP:
|
case netdev.IPPROTO_TCP:
|
||||||
default:
|
default:
|
||||||
return -1, netip.AddrPort{}, netdev.ErrProtocolNotSupported
|
return -1, netdev.ErrProtocolNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -704,7 +704,7 @@ func (w *wifinina) Accept(sockfd int) (int, netip.AddrPort, error) {
|
|||||||
|
|
||||||
// Check if we've faulted
|
// Check if we've faulted
|
||||||
if w.fault != nil {
|
if w.fault != nil {
|
||||||
return -1, netip.AddrPort{}, w.fault
|
return -1, w.fault
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: BUG: Currently, a sock that is 100% busy will always be
|
// TODO: BUG: Currently, a sock that is 100% busy will always be
|
||||||
@@ -720,8 +720,6 @@ func (w *wifinina) Accept(sockfd int) (int, netip.AddrPort, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
raddr := w.getRemoteData(client)
|
|
||||||
|
|
||||||
// If we've already seen this socket, we can reuse
|
// If we've already seen this socket, we can reuse
|
||||||
// the socket and return it. But, only if the socket
|
// the socket and return it. But, only if the socket
|
||||||
// is closed. If it's not closed, we'll just come back
|
// is closed. If it's not closed, we'll just come back
|
||||||
@@ -734,12 +732,12 @@ func (w *wifinina) Accept(sockfd int) (int, netip.AddrPort, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Reuse client socket
|
// Reuse client socket
|
||||||
return int(client), raddr, nil
|
return int(client), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new socket for client and return fd
|
// Create new socket for client and return fd
|
||||||
w.sockets[client] = newSocket(socket.protocol)
|
w.sockets[client] = newSocket(socket.protocol)
|
||||||
return int(client), raddr, nil
|
return int(client), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1125,23 +1123,6 @@ func (w *wifinina) accept(s sock) sock {
|
|||||||
return newsock
|
return newsock
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *wifinina) getRemoteData(s sock) netip.AddrPort {
|
|
||||||
|
|
||||||
if debugging(debugCmd) {
|
|
||||||
fmt.Printf(" [cmdGetRemoteData] sock: %d\r\n", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
sl := make([]string, 2)
|
|
||||||
l := w.reqRspStr1(cmdGetRemoteData, uint8(s), sl)
|
|
||||||
if l != 2 {
|
|
||||||
w.faultf("getRemoteData wanted l=2, got l=%d", l)
|
|
||||||
return netip.AddrPort{}
|
|
||||||
}
|
|
||||||
ip, _ := netip.AddrFromSlice([]byte(sl[0])[:4])
|
|
||||||
port := binary.BigEndian.Uint16([]byte(sl[1]))
|
|
||||||
return netip.AddrPortFrom(ip, port)
|
|
||||||
}
|
|
||||||
|
|
||||||
// insertDataBuf adds data to the buffer used for sending UDP data
|
// insertDataBuf adds data to the buffer used for sending UDP data
|
||||||
func (w *wifinina) insertDataBuf(sock sock, buf []byte) bool {
|
func (w *wifinina) insertDataBuf(sock sock, buf []byte) bool {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user