parent
6e5bf54598
commit
ba4a9b22f0
@ -0,0 +1,109 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"flag" |
||||
"fmt" |
||||
"log" |
||||
) |
||||
|
||||
type CommandFunc func(tbm *TBM, args []string) error |
||||
|
||||
var ( |
||||
serial_device = flag.String("serial-device", "/dev/ttyUSB0", "Serial device to use") |
||||
serial_baudrate = flag.Int("serial-baud", 9600, "Serial baud rate") |
||||
|
||||
commands = map[string]CommandFunc{ |
||||
"ls": cmd_ls, |
||||
"cat": cmd_cat, |
||||
"stat": cmd_stat, |
||||
"cp": cmd_cp, |
||||
"rm": cmd_rm, |
||||
"mkdir": cmd_mkdir, |
||||
"rmdir": cmd_rmdir, |
||||
"date": cmd_date, |
||||
"set-date": cmd_set_date, |
||||
"time": cmd_time, |
||||
} |
||||
) |
||||
|
||||
func cmd_generic(tbm *TBM, command string, args []string) error { |
||||
cmd := &Command{command, args} |
||||
tbm.Commands <- cmd |
||||
res := <-tbm.Results |
||||
|
||||
if res.errcode[0] != '0' { |
||||
return fmt.Errorf("Error: %s", res.errcode) |
||||
} |
||||
fmt.Printf("%s", res.output) |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func cmd_ls(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "mufs ls", args) |
||||
} |
||||
|
||||
func cmd_cat(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "mufs cat", args) |
||||
} |
||||
|
||||
func cmd_stat(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "mufs stat", args) |
||||
} |
||||
|
||||
func cmd_cp(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "mufs cp", args) |
||||
} |
||||
|
||||
func cmd_rm(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "mufs rm", args) |
||||
} |
||||
|
||||
func cmd_mkdir(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "mufs mkdir", args) |
||||
} |
||||
|
||||
func cmd_rmdir(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "mufs rmdir", args) |
||||
} |
||||
|
||||
func cmd_date(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "date", args) |
||||
} |
||||
|
||||
func cmd_set_date(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "set-date", args) |
||||
} |
||||
|
||||
func cmd_time(tbm *TBM, args []string) error { |
||||
return cmd_generic(tbm, "time", args) |
||||
} |
||||
|
||||
func main() { |
||||
flag.Parse() |
||||
|
||||
args := flag.Args() |
||||
if len(args) == 0 { |
||||
log.Fatalf("Please specify at least one command") |
||||
} |
||||
command := args[0] |
||||
|
||||
command_function, ok := commands[command] |
||||
|
||||
if !ok { |
||||
log.Fatalf("Unknown command: %s", command) |
||||
} |
||||
|
||||
t := &TBM{} |
||||
err := t.Connect(*serial_device, *serial_baudrate) |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
t.Handle() |
||||
defer t.Close() |
||||
|
||||
err = command_function(t, args[1:]) |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
} |
@ -0,0 +1,158 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"io" |
||||
"log" |
||||
"strings" |
||||
|
||||
"github.com/tarm/serial" |
||||
) |
||||
|
||||
type TBM struct { |
||||
Commands chan *Command |
||||
Results chan *Result |
||||
Port *serial.Port |
||||
} |
||||
|
||||
type Command struct { |
||||
command string |
||||
args []string |
||||
} |
||||
|
||||
type Result struct { |
||||
output []byte |
||||
errcode []byte |
||||
} |
||||
|
||||
func (t *TBM) Connect(device string, baud int) error { |
||||
t.Commands = make(chan *Command) |
||||
t.Results = make(chan *Result) |
||||
|
||||
serialconfig := &serial.Config{Name: device, Baud: baud} |
||||
|
||||
port, err := serial.OpenPort(serialconfig) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
t.Port = port |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func (t *TBM) Handle() error { |
||||
go handleResults(t.Port, t.Results) |
||||
go handleCommands(t.Port, t.Commands) |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func (t *TBM) Close() { |
||||
t.Port.Close() |
||||
} |
||||
|
||||
func deserialise(in io.Reader, init []byte) (*Result, []byte, error) { |
||||
var ( |
||||
output, errorcode []byte |
||||
data, rest []byte |
||||
) |
||||
|
||||
want_output := true |
||||
_ = copy(data, init) |
||||
|
||||
for { |
||||
buf := make([]byte, 4096) |
||||
n, err := in.Read(buf) |
||||
if err != nil { |
||||
return nil, nil, err |
||||
} |
||||
|
||||
n2 := n + len(data) |
||||
|
||||
data = append(data, buf[:n]...) |
||||
|
||||
for i := 0; i < n2; i++ { |
||||
// '\r' is really '\n'
|
||||
if data[i] == '\r' { |
||||
data = append(data[:i], data[i+1:]...) |
||||
n2-- |
||||
continue |
||||
} |
||||
|
||||
if data[i] == 0x4 { |
||||
if want_output { |
||||
want_output = false |
||||
output = data[:i] |
||||
data = data[i+1:] |
||||
// The TBM gives us our own commands back
|
||||
for j := 0; j < len(output); j++ { |
||||
if output[j] == '\n' { |
||||
output = output[j+1:] |
||||
break |
||||
} |
||||
} |
||||
break |
||||
} else { |
||||
errorcode = data[:i] |
||||
|
||||
rest = data[i+1:] |
||||
return &Result{output, errorcode}, rest, nil |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
func handleResults(in io.Reader, c chan *Result) { |
||||
var ( |
||||
res *Result |
||||
rest []byte |
||||
err error |
||||
) |
||||
|
||||
for { |
||||
res, rest, err = deserialise(in, rest) |
||||
|
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
|
||||
c <- res |
||||
} |
||||
} |
||||
|
||||
func serialise(out io.Writer, command string, args []string) error { |
||||
var quoted_args []string |
||||
|
||||
quoted_args = append(quoted_args, command) |
||||
|
||||
for _, arg := range args { |
||||
quoted_args = append(quoted_args, fmt.Sprintf("\"%s\"", arg)) |
||||
} |
||||
|
||||
out_string := strings.Join(quoted_args, " ") |
||||
|
||||
output := []byte(out_string) |
||||
output = append(output, '\r') |
||||
//output = append(output, 0x4)
|
||||
|
||||
_, err := out.Write(output) |
||||
// err is non nil if n != len(output)
|
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func handleCommands(out io.Writer, c chan *Command) { |
||||
for command := range c { |
||||
err := serialise(out, command.command, command.args) |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue