64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
package serialport
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func Open115200(path string) (*os.File, error) {
|
|
file, err := os.OpenFile(path, os.O_RDWR|unix.O_NOCTTY, 0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
termios, err := unix.IoctlGetTermios(int(file.Fd()), unix.TCGETS)
|
|
if err != nil {
|
|
file.Close()
|
|
return nil, err
|
|
}
|
|
|
|
configureRaw115200(termios)
|
|
|
|
if err := unix.IoctlSetTermios(int(file.Fd()), unix.TCSETS, termios); err != nil {
|
|
file.Close()
|
|
return nil, fmt.Errorf("configure %s: %w", path, err)
|
|
}
|
|
|
|
effective, err := unix.IoctlGetTermios(int(file.Fd()), unix.TCGETS)
|
|
if err != nil {
|
|
file.Close()
|
|
return nil, fmt.Errorf("read back %s: %w", path, err)
|
|
}
|
|
if err := verifyBaud(*effective, unix.B115200); err != nil {
|
|
file.Close()
|
|
return nil, fmt.Errorf("verify %s: %w", path, err)
|
|
}
|
|
return file, nil
|
|
}
|
|
|
|
// configureRaw115200 keeps the raw 115200 8N1 blocking-read configuration.
|
|
// On Linux TCSETS takes the line speed from the CBAUD bits in Cflag, so
|
|
// CBAUD must be cleared and B115200 selected there; Ispeed/Ospeed alone
|
|
// leave an inherited baud (for example 9600 from boot defaults) in effect.
|
|
func configureRaw115200(termios *unix.Termios) {
|
|
termios.Iflag = 0
|
|
termios.Oflag = 0
|
|
termios.Lflag = 0
|
|
termios.Cflag &^= unix.CSIZE | unix.PARENB | unix.CSTOPB | unix.CRTSCTS | unix.CBAUD
|
|
termios.Cflag |= unix.B115200
|
|
termios.Cflag |= unix.CS8 | unix.CREAD | unix.CLOCAL
|
|
termios.Ispeed = unix.B115200
|
|
termios.Ospeed = unix.B115200
|
|
termios.Cc[unix.VMIN] = 1
|
|
termios.Cc[unix.VTIME] = 0
|
|
}
|
|
|
|
func verifyBaud(termios unix.Termios, baud uint32) error {
|
|
if got := termios.Cflag & unix.CBAUD; got != baud {
|
|
return fmt.Errorf("effective baud bits %#o, want %#o", got, baud)
|
|
}
|
|
return nil
|
|
}
|