// modemfilesender.go
package main
import (
"os"
"syscall"
"fmt"
"log"
"serial"
"io/ioutil"
)
const (
R_SUCC = iota
R_FAIL
R_TIMEOUT
)
var rxwincnt int
var txwincnt int
var txpktcnt int
var rxpktcnt int
var prevwincnt int
var rxpktindiarr []byte
var payloadsiz int
var lastpayloadsiz int
var rbuf []byte
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage: ", os.Args[0], "</dev/ttyUSBx>")
os.Exit(1)
}
c := &serial.Config{Name: os.Args[1], Baud: 115200}
s, err := serial.OpenPort(c)
if err != nil {
log.Fatal(err)
}
s.Flush()
fd := int(s.Fd())
defer s.Close()
mfphdr := make([]byte, 8)
pktresp := make([]byte, 16)
mmtdnbuf := make([]byte, 64)
sentack := false
for {
var payloadlen int
ret := readMfpHdr(fd, mfphdr, 15e3)
if ret == R_SUCC {
if sentack == true {
sentack = false
rxwincnt = 0
}
hi := uint(mfphdr[2])
lo := uint(mfphdr[3])
if txwincnt == 0 {
txwincnt = int(mfphdr[5])
}
if txpktcnt == 0 {
txpktcnt = int(mfphdr[7])
rxpktindiarr = make([]byte, txpktcnt)
}
pktidx := int(mfphdr[6])
if rxpktindiarr[pktidx] == 0 {
rxpktindiarr[pktidx] = 1
rxpktcnt++
}
payloadlen = int((hi << 8) | lo)
if payloadsiz == 0 {
payloadsiz = payloadlen;
rbuf = make([]byte, txpktcnt * payloadlen)
}
if txpktcnt - 1 == pktidx {
lastpayloadsiz = payloadlen
}
fmt.Println("read succ: ", hi, lo, payloadlen, mfphdr)
readFully(fd, rbuf[payloadsiz*pktidx:payloadsiz*pktidx + payloadlen], 15e3)
// fmt.Println("read mfp payload passed", rbuf[:payloadlen])
rxwincnt++
pktresp[rxwincnt] = mfphdr[6]
fmt.Printf("rxwincnt = %d, mfphdr[6] = %d\n", rxwincnt, int(mfphdr[6]))
}
if rxwincnt > 0 && (txwincnt == rxwincnt || ret == R_TIMEOUT) {
pktresp[0] = byte(rxwincnt)
fmt.Println("write ack:", pktresp[:rxwincnt+1])
s.Write(pktresp[:rxwincnt+1])
read_tx_done(fd, mmtdnbuf, 15e3)
sentack = true
txwincnt = 0
if rxpktcnt == txpktcnt {
fmt.Println("fin")
ioutil.WriteFile("mfp.dat", rbuf[:payloadsiz * (txpktcnt-1) + lastpayloadsiz], 0666)
break
}
}
}
}
func readFully(fd int, buf []byte, to int) (ret int) {
var event syscall.EpollEvent
var events [16]syscall.EpollEvent
ret = R_TIMEOUT
epfd, err := syscall.EpollCreate1(0)
if err != nil {
log.Fatal(err)
}
defer syscall.Close(epfd)
event.Events = syscall.EPOLLIN
event.Fd = int32(fd)
err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event)
if err != nil {
log.Fatal(err)
}
pos := 0
length := len(buf)
fin:
for {
nevents, err := syscall.EpollWait(epfd, events[:], to)
if err != nil {
log.Fatal(err)
}
if nevents == 0 {
fmt.Println("epoll_wait = 0")
continue;
}
for ev := 0; ev < nevents; ev++ {
if int(events[ev].Fd) == fd {
nbytes, err := syscall.Read(fd, buf[pos:length])
if err != nil {
log.Fatal()
}
pos += nbytes
if pos == length {
ret = R_SUCC
break fin
}
}
}
}
return ret
}
func readMfpHdr(fd int, buf []byte, to int) (ret int) {
var event syscall.EpollEvent
var events [16]syscall.EpollEvent
ret = R_TIMEOUT
epfd, err := syscall.EpollCreate1(0)
if err != nil {
log.Fatal(err)
}
defer syscall.Close(epfd)
event.Events = syscall.EPOLLIN
event.Fd = int32(fd)
err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event)
if err != nil {
log.Fatal(err)
}
pos := 0
scanbuf := make([]byte, 1)
length := len(buf)
fin:
for {
nevents, err := syscall.EpollWait(epfd, events[:], to)
if err != nil {
log.Fatal(err)
}
if nevents == 0 {
fmt.Println("epoll_wait = 0")
continue;
}
for ev := 0; ev < nevents; ev++ {
if int(events[ev].Fd) == fd {
nbytes, err := syscall.Read(fd, scanbuf)
if err != nil {
log.Fatal()
}
if pos == 0 && scanbuf[0] != 'M' {
continue
} else if pos == 1 && scanbuf[0] != 'F' {
pos = 0
continue
}
buf[pos] = scanbuf[0]
pos += nbytes
if pos == length {
ret = R_SUCC
break fin
}
}
}
}
return ret
}
func read_tx_done(fd int, buf []byte, to int) (int, error) {
var event syscall.EpollEvent
var events [4]syscall.EpollEvent
epfd, err := syscall.EpollCreate1(0)
if err != nil {
log.Fatal(err)
}
defer syscall.Close(epfd)
event.Events = syscall.EPOLLIN
event.Fd = int32(fd)
pos := 0
err = syscall.EpollCtl(epfd, syscall.EPOLL_CTL_ADD, fd, &event)
if err != nil {
log.Fatal(err)
}
for {
nevents, err := syscall.EpollWait(epfd, events[:], to)
if err != nil {
log.Fatal(err)
}
if nevents == 0 {
fmt.Println("epoll_wait = 0")
return 0, nil
}
for ev := 0; ev < nevents; ev++ {
if int(events[ev].Fd) == fd {
// fmt.Println("begin read...")
nbytes, err := syscall.Read(fd, buf[pos:])
if err != nil {
log.Fatal(err)
return nbytes, err
}
if nbytes > 0 {
pos += nbytes
if buf[pos-1] == '\n' {
fmt.Println(string(buf[:pos]))
return pos, nil
}
} else {
return 0, nil
}
}
}
}
return 0, nil
}
有疑问加站长微信联系(非本文作者)