diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..c556438 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/y-ponomarev/serial + +go 1.13 + +require golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..15089f2 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/serial_linux.go b/serial_linux.go index 35606b2..45bae5b 100644 --- a/serial_linux.go +++ b/serial_linux.go @@ -101,3 +101,38 @@ func fdisset(fd int, fds *syscall.FdSet) bool { idx, pos := fdget(fd, fds) return fds.Bits[idx]&(1< 0 { + c.BaudRate = custom_baudrate + ok, errno := setSpecialBaudrate(p.fd, custom_baudrate) + if !ok { + return error(errno) + } + } + return } @@ -85,33 +100,33 @@ func (p *port) Close() (err error) { // Read reads from serial port. Port must be opened before calling this method. // It is blocked until all data received or timeout after p.timeout. func (p *port) Read(b []byte) (n int, err error) { - var rfds syscall.FdSet - - fd := p.fd - fdset(fd, &rfds) + fds := []unix.PollFd{{Fd: int32(p.fd), Events: unix.POLLIN}} + deadline := time.Now().Add(p.timeout) - var tv *syscall.Timeval - if p.timeout > 0 { - timeout := syscall.NsecToTimeval(p.timeout.Nanoseconds()) - tv = &timeout - } for { - // If syscall.Select() returns EINTR (Interrupted system call), retry it - if err = syscallSelect(fd+1, &rfds, nil, nil, tv); err == nil { - break + timeout := -1 + if p.timeout > 0 { + timeout = int(deadline.Sub(time.Now()).Milliseconds()) } - if err != syscall.EINTR { - err = fmt.Errorf("serial: could not select: %v", err) - return + + n, err := unix.Poll(fds, timeout) + if err != nil { + if errors.Is(err, syscall.EINTR) { + continue + } + return 0, fmt.Errorf("serial: could not poll: %v", err) + } + + if n == 0 { + return 0, ErrTimeout + } + + if fds[0].Revents&unix.POLLIN == unix.POLLIN { + break } } - if !fdisset(fd, &rfds) { - // Timeout - err = ErrTimeout - return - } - n, err = syscall.Read(fd, b) - return + + return syscall.Read(p.fd, b) } // Write writes data to the serial port. diff --git a/serial_windows.go b/serial_windows.go index 1eeb14b..1ff72af 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -156,13 +156,17 @@ func (p *port) setSerialConfig(c *Config) error { } func newHandle(c *Config) (handle syscall.Handle, err error) { + name := c.Address + if len(name) > 0 && name[0] != '\\' { + name = "\\\\.\\" + name + } handle, err = syscall.CreateFile( - syscall.StringToUTF16Ptr(c.Address), + syscall.StringToUTF16Ptr(name), syscall.GENERIC_READ|syscall.GENERIC_WRITE, - 0, // mode - nil, // security + 0, // mode + nil, // security syscall.OPEN_EXISTING, // create mode - 0, // attributes - 0) // templates + 0, // attributes + 0) // templates return }