gary/debugger/serial/serial.go

87 lines
1.6 KiB
Go

package serial
import (
"errors"
"sync"
"time"
"go.bug.st/serial"
)
const portDev = "/dev/ttyUSB0"
const maxAddr = 1 << 17
type Serial struct {
portMu sync.Mutex
port serial.Port
}
func Open() (*Serial, error) {
mode := &serial.Mode{
BaudRate: 115_200,
}
port, err := serial.Open(portDev, mode)
if err != nil {
return nil, err
}
return &Serial{port: port}, nil
}
func (d *Serial) Close() error {
d.portMu.Lock()
defer d.portMu.Unlock()
return d.port.Close()
}
func encode(addr int, write bool, data byte) [4]byte {
writeVal := uint8(0)
if write {
writeVal = 1
}
var ret [4]byte
ret[3] = data
ret[2] = byte(addr<<1) | writeVal
ret[1] = byte(addr >> 7)
ret[0] = byte(addr >> 15)
return ret
}
func (d *Serial) ReadAt(bs []byte, off int64) (int, error) {
d.portMu.Lock()
defer d.portMu.Unlock()
if off+int64(len(bs)) >= maxAddr {
return 0, errors.New("OOB read")
}
for i := range bs {
packet := encode(int(off)+i, false, 0)
if _, err := d.port.Write(packet[:]); err != nil {
return i, err
}
d.port.SetReadTimeout(2 * time.Second)
n, err := d.port.Read(packet[:1])
if err != nil {
return i, err
} else if n == 0 {
return i, errors.New("short read")
}
bs[i] = packet[0]
}
return len(bs), nil
}
func (d *Serial) WriteAt(bs []byte, off int64) (int, error) {
d.portMu.Lock()
defer d.portMu.Unlock()
if off+int64(len(bs)) >= maxAddr {
return 0, errors.New("OOB write")
}
for i, v := range bs {
packet := encode(int(off)+i, true, v)
if _, err := d.port.Write(packet[:]); err != nil {
return i, err
}
}
return len(bs), nil
}