common/serialport/serialport_linux.go (77 lines of code) (raw):

//go:build linux // +build linux package serialport import ( "fmt" "os" "syscall" "unsafe" ) const ( comport = "/dev/ttyS0" comportPV = "/dev/hvc0" ) type SerialPort struct { fileHandle *os.File } // newSerialPort creates a serial port object with predefined parameters. func newSerialPort() (sp *SerialPort) { return &SerialPort{ fileHandle: nil, } } // OpenPort opens the serial port which MUST be done before WritePort is called. func (sp *SerialPort) openPort(name string) (err error) { fileHandle, err := os.OpenFile(name, syscall.O_RDWR, 0) if err != nil { return fmt.Errorf("Unable to open serial port %v: %v\n", name, err.Error()) } baudRate := uint32(syscall.B115200) state := syscall.Termios{ Cflag: syscall.CS8 | syscall.CREAD | syscall.B115200, Oflag: 0, Ospeed: baudRate, } fd := fileHandle.Fd() if _, _, err := syscall.Syscall6( syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(&state)), 0, 0, 0, ); err != 0 { return fmt.Errorf("Unable to configure serial port %v: %v\n", name, err.Error()) } sp.fileHandle = fileHandle return nil } func (sp *SerialPort) OpenPort() (err error) { if err = sp.openPort(comport); err != nil { if err = sp.openPort(comportPV); err != nil { return fmt.Errorf("Error opening serial port: %v", err.Error()) } } return nil } func (sp *SerialPort) ClosePort() { if sp.fileHandle == nil { return } sp.fileHandle.Close() return } func (sp *SerialPort) WritePort(data []byte) error { if len(data) > MaxLenOfSingleWrite { data = data[:MaxLenOfSingleWrite] } if _, err := sp.fileHandle.Write(data); err != nil { return fmt.Errorf("Error occurred while writing to serial port: %v\n", err.Error()) } sp.fileHandle.Write([]byte{'\n'}) return nil } func GetSerialPort() (*SerialPort, error) { sp := newSerialPort() if err := sp.OpenPort(); err != nil { return nil, err } return sp, nil }