commit 6bad484a354ed430735733a969df3aa663e2c0b0
parent 5a718f4e0005fd215cf4362025175a187e26cdaa
Author: Matsuda Kenji <info@mtkn.jp>
Date: Mon, 25 Aug 2025 08:53:32 +0900
add cons written in go
Diffstat:
3 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/consgo/go.mod b/consgo/go.mod
@@ -0,0 +1,5 @@
+module cons
+
+go 1.24.1
+
+require golang.org/x/sys v0.35.0
diff --git a/consgo/go.sum b/consgo/go.sum
@@ -0,0 +1,2 @@
+golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
+golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
diff --git a/consgo/main.go b/consgo/main.go
@@ -0,0 +1,118 @@
+package main
+
+import (
+ "fmt"
+ "io"
+ "log"
+
+ "golang.org/x/sys/unix"
+)
+
+const ttyFile = "/dev/ttyU0"
+
+func main() {
+ fd, err := device_open(ttyFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer unix.Close(fd)
+ if err = setparms(fd, 115200); err != nil {
+ log.Fatal(err)
+ }
+ if err = flush(fd); err != nil {
+ log.Fatal(err)
+ }
+
+ go reader(fd)
+ writer(fd)
+}
+
+func reader(fd int) {
+ buf := make([]byte, 64)
+ for {
+ n, err := unix.Read(fd, buf)
+ if err == io.EOF {
+ break
+ } else if err != nil {
+ log.Printf("read from tty: %v", err)
+ break
+ }
+ log.Printf("read from tty: %q", buf[:n])
+ _, err = unix.Write(unix.Stdout, buf[:n])
+ if err != nil {
+ log.Printf("write to stdout: %v", err)
+ break
+ }
+ }
+}
+
+func writer(fd int) {
+ buf := make([]byte, 64)
+ for {
+ n, err := unix.Read(unix.Stdin, buf)
+ if n == 0 || err == io.EOF {
+ break
+ } else if err != nil {
+ log.Printf("read from stdin: %v", err)
+ break
+ }
+ log.Printf("from terminal: %q", buf[:n])
+ _, err = unix.Write(fd, buf[:n])
+ if err != nil {
+ log.Printf("write to tty: %v", err)
+ break
+ }
+ }
+}
+
+func device_open(path string) (fd int, err error) {
+ fd, err = unix.Open(path, unix.O_RDWR|unix.O_NDELAY|unix.O_NOCTTY, 0)
+ if err != nil {
+ return 0, fmt.Errorf("open: %w", err)
+ }
+ defer func() {
+ if err != nil {
+ unix.Close(fd)
+ }
+ }()
+ n, err := unix.FcntlInt(uintptr(fd), unix.F_GETFL, 0)
+ if err != nil {
+ return 0, fmt.Errorf("getfl: %w", err)
+ }
+ _, err = unix.FcntlInt(uintptr(fd), unix.F_SETFL, n&^unix.O_NDELAY)
+ if err != nil {
+ return 0, fmt.Errorf("setfl: %w", err)
+ }
+ return fd, nil
+}
+
+func setparms(fd int, baud int32) error {
+ tty, err := unix.IoctlGetTermios(fd, unix.TIOCGETA)
+ if err != nil {
+ return fmt.Errorf("gettermios: %w", err)
+ }
+ tty.Iflag = unix.IGNBRK
+ tty.Iflag &= ^(uint32(unix.IXON) | uint32(unix.IXOFF) | uint32(unix.IXANY))
+ tty.Oflag = 0
+ tty.Cflag = (tty.Cflag &^ unix.CSIZE) | unix.CS8
+ tty.Cflag |= unix.CLOCAL | unix.CREAD
+ tty.Cflag &= ^uint32(unix.CSTOPB)
+ tty.Lflag = 0
+ tty.Cc[unix.VMIN] = 1
+ tty.Cc[unix.VTIME] = 5
+ tty.Ispeed = baud
+ tty.Ospeed = baud
+ err = unix.IoctlSetTermios(fd, unix.TIOCSETA, tty)
+ if err != nil {
+ return fmt.Errorf("settermios: %w", err)
+ }
+ return nil
+}
+
+func flush(fd int) error {
+ _, err := unix.IoctlGetInt(fd, unix.TIOCFLUSH)
+ if err != nil {
+ return fmt.Errorf("tiocflush: %w", err)
+ }
+ return nil
+}