From 0f730e491f1ffa921f4d83ed57f0d828a9fbe9f4 Mon Sep 17 00:00:00 2001 From: James Stanley Date: Sun, 11 Feb 2024 21:08:52 +0000 Subject: [PATCH 01/34] unix: nativeOpen: always close the port on errors --- serial_unix.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/serial_unix.go b/serial_unix.go index f6ec896..db6158d 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -249,6 +249,7 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { if mode.InitialStatusBits != nil { status, err := port.getModemBitsStatus() if err != nil { + port.Close() return nil, &PortError{code: InvalidSerialPort, causedBy: err} } if mode.InitialStatusBits.DTR { @@ -262,6 +263,7 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { status &^= unix.TIOCM_RTS } if err := port.setModemBitsStatus(status); err != nil { + port.Close() return nil, &PortError{code: InvalidSerialPort, causedBy: err} } } From c414e4f55c7954d5fb45f6479f2e3d858ece9231 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 16 Feb 2024 13:32:43 +0100 Subject: [PATCH 02/34] windows: Avoid double-set of communication parameters on Open --- serial_windows.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 287856a..35bb0c9 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -254,6 +254,15 @@ func (port *windowsPort) SetMode(mode *Mode) error { port.Close() return &PortError{code: InvalidSerialPort} } + port.setModeParams(mode, ¶ms) + if setCommState(port.handle, ¶ms) != nil { + port.Close() + return &PortError{code: InvalidSerialPort} + } + return nil +} + +func (port *windowsPort) setModeParams(mode *Mode, params *dcb) { if mode.BaudRate == 0 { params.BaudRate = 9600 // Default to 9600 } else { @@ -266,11 +275,6 @@ func (port *windowsPort) SetMode(mode *Mode) error { } params.StopBits = stopBitsMap[mode.StopBits] params.Parity = parityMap[mode.Parity] - if setCommState(port.handle, ¶ms) != nil { - port.Close() - return &PortError{code: InvalidSerialPort} - } - return nil } func (port *windowsPort) SetDTR(dtr bool) error { @@ -432,16 +436,12 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { } // Set port parameters - if port.SetMode(mode) != nil { - port.Close() - return nil, &PortError{code: InvalidSerialPort} - } - params := &dcb{} if getCommState(port.handle, params) != nil { port.Close() return nil, &PortError{code: InvalidSerialPort} } + port.setModeParams(mode, params) params.Flags &= dcbDTRControlDisableMask params.Flags &= dcbRTSControlDisbaleMask if mode.InitialStatusBits == nil { From 9aae282f09e92dadad494f174b9b347362c5e9e9 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Fri, 16 Feb 2024 14:17:53 +0100 Subject: [PATCH 03/34] Improved error messages --- serial_unix.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/serial_unix.go b/serial_unix.go index db6158d..e025d2d 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -9,6 +9,7 @@ package serial import ( + "fmt" "io/ioutil" "regexp" "strings" @@ -232,7 +233,7 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { settings, err := port.getTermSettings() if err != nil { port.Close() - return nil, &PortError{code: InvalidSerialPort} + return nil, &PortError{code: InvalidSerialPort, causedBy: fmt.Errorf("error getting term settings: %w", err)} } // Set raw mode @@ -243,14 +244,14 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { if port.setTermSettings(settings) != nil { port.Close() - return nil, &PortError{code: InvalidSerialPort} + return nil, &PortError{code: InvalidSerialPort, causedBy: fmt.Errorf("error setting term settings: %w", err)} } if mode.InitialStatusBits != nil { status, err := port.getModemBitsStatus() if err != nil { port.Close() - return nil, &PortError{code: InvalidSerialPort, causedBy: err} + return nil, &PortError{code: InvalidSerialPort, causedBy: fmt.Errorf("error getting modem bits status: %w", err)} } if mode.InitialStatusBits.DTR { status |= unix.TIOCM_DTR @@ -264,15 +265,15 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { } if err := port.setModemBitsStatus(status); err != nil { port.Close() - return nil, &PortError{code: InvalidSerialPort, causedBy: err} + return nil, &PortError{code: InvalidSerialPort, causedBy: fmt.Errorf("error setting modem bits status: %w", err)} } } // MacOSX require that this operation is the last one otherwise an // 'Invalid serial port' error is returned... don't know why... - if port.SetMode(mode) != nil { + if err := port.SetMode(mode); err != nil { port.Close() - return nil, &PortError{code: InvalidSerialPort} + return nil, &PortError{code: InvalidSerialPort, causedBy: fmt.Errorf("error configuring port: %w", err)} } unix.SetNonblock(h, false) @@ -283,7 +284,7 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { pipe := &unixutils.Pipe{} if err := pipe.Open(); err != nil { port.Close() - return nil, &PortError{code: InvalidSerialPort, causedBy: err} + return nil, &PortError{code: InvalidSerialPort, causedBy: fmt.Errorf("error opening signaling pipe: %w", err)} } port.closeSignal = pipe From 7f490f208a51997efee4c8d6091857a0c572b5fc Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Sun, 18 Feb 2024 19:33:23 +0100 Subject: [PATCH 04/34] Added issues templates --- .github/ISSUE_TEMPLATE/bug-report.yml | 77 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature-request.yml | 29 ++++++++ 2 files changed, 106 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature-request.yml diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..e3130ae --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,77 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/issue-templates/forms/platform-dependent/bug-report.yml +# See: https://docs.github.com/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms + +name: Bug report +description: Report a problem with the code or documentation in this repository. +labels: + - bug +body: + - type: textarea + id: description + attributes: + label: Describe the problem + validations: + required: true + - type: textarea + id: reproduce + attributes: + label: To reproduce + description: | + Provide the specific set of steps we can follow to reproduce the + problem in particular the exact golang source code you used. + validations: + required: true + - type: checkboxes + id: checklist-reproduce + attributes: + label: | + Please double-check that you have reported each of the following + before submitting the issue. + options: + - label: I've provided the FULL source code that causes the problem + required: true + - label: I've provided all the actions required to reproduce the problem + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + description: | + What would you expect to happen after following those instructions? + validations: + required: true + - type: input + id: os + attributes: + label: Operating system and version + description: | + Which operating system(s) version are you using on your computer? + validations: + required: true + - type: input + id: boards + attributes: + label: Arduino boards or embedded devices used + description: | + Which Arduino boards or embedded devices are you using (if applicable)? + - type: textarea + id: additional + attributes: + label: Additional context + description: | + Add here any additional information that you think might be relevant to + the problem. + validations: + required: false + - type: checkboxes + id: checklist + attributes: + label: Issue checklist + description: | + Please double-check that you have done each of the following things before + submitting the issue. + options: + - label: I searched for previous requests in [the issue tracker](https://github.com/bugst/go-serial/issues) + required: true + - label: My request contains all necessary details + required: true diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000..d56393d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,29 @@ +# Source: https://github.com/arduino/tooling-project-assets/blob/main/issue-templates/forms/platform-dependent/feature-request.yml +# See: https://docs.github.com/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms + +name: Feature request +description: Suggest an enhancement to this project. +labels: + - "type: enhancement" +body: + - type: textarea + id: description + attributes: + label: Describe the new feature or change suggestion + validations: + required: true + - type: textarea + id: additional + attributes: + label: Additional context + description: Add any additional information about the feature request here. + - type: checkboxes + id: checklist + attributes: + label: Issue checklist + description: Please double-check that you have done each of the following things before submitting the issue. + options: + - label: I searched for previous requests in [the issue tracker](https://github.com/bugst/go-serial/issues) + required: true + - label: My request contains all necessary details + required: true From 2aa105e32e2b1368eb0b861072af3b25dcf43cb8 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 20 Feb 2024 09:51:06 +0100 Subject: [PATCH 05/34] Improved issue template message --- .github/ISSUE_TEMPLATE/bug-report.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index e3130ae..4fe6566 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -51,9 +51,10 @@ body: - type: input id: boards attributes: - label: Arduino boards or embedded devices used + label: Please describe your hardware setup description: | - Which Arduino boards or embedded devices are you using (if applicable)? + Arduino boards, USB dongles, hubs or embedded devices you are using and how they + are connected together. - type: textarea id: additional attributes: From 674fbae95abf6b5974bf47a602ed81ff4384d54d Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 20 Feb 2024 09:52:27 +0100 Subject: [PATCH 06/34] Upgraded dependencies --- go.mod | 8 ++++---- go.sum | 20 ++++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index c3abe90..61d0d6d 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.17 require ( github.com/creack/goselect v0.1.2 - github.com/stretchr/testify v1.7.0 - golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 + github.com/stretchr/testify v1.8.4 + golang.org/x/sys v0.17.0 ) require ( - github.com/davecgh/go-spew v1.1.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index dac8e08..43d4dac 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,21 @@ github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 92703ecb02e5efc412e181c4df73afbfbf8ebeae Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 20 Feb 2024 09:55:49 +0100 Subject: [PATCH 07/34] Improved issue template message --- .github/ISSUE_TEMPLATE/bug-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index 4fe6566..b544840 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -48,7 +48,7 @@ body: Which operating system(s) version are you using on your computer? validations: required: true - - type: input + - type: textarea id: boards attributes: label: Please describe your hardware setup From bcd8695df44541e722ae4576f7be12ffd3320071 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 20 Feb 2024 15:13:12 +0100 Subject: [PATCH 08/34] Removed deprecated package io/ioutil --- serial_unix.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serial_unix.go b/serial_unix.go index e025d2d..9328656 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -10,7 +10,7 @@ package serial import ( "fmt" - "io/ioutil" + "os" "regexp" "strings" "sync" @@ -292,7 +292,7 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { } func nativeGetPortsList() ([]string, error) { - files, err := ioutil.ReadDir(devFolder) + files, err := os.ReadDir(devFolder) if err != nil { return nil, err } From 14e5ea68ce7e08e3fc27ff237e66d41ed3e502ae Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 20 Feb 2024 15:24:08 +0100 Subject: [PATCH 09/34] Precompile port-filter regexp --- serial_darwin.go | 9 +++++++-- serial_freebsd.go | 9 +++++++-- serial_linux.go | 9 +++++++-- serial_openbsd.go | 9 +++++++-- serial_unix.go | 7 +------ 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/serial_darwin.go b/serial_darwin.go index 2817041..3baa489 100644 --- a/serial_darwin.go +++ b/serial_darwin.go @@ -6,10 +6,15 @@ package serial -import "golang.org/x/sys/unix" +import ( + "regexp" + + "golang.org/x/sys/unix" +) const devFolder = "/dev" -const regexFilter = "^(cu|tty)\\..*" + +var osPortFiler = regexp.MustCompile("^(cu|tty)\\..*") const ioctlTcgetattr = unix.TIOCGETA const ioctlTcsetattr = unix.TIOCSETA diff --git a/serial_freebsd.go b/serial_freebsd.go index aceb08a..be0fa01 100644 --- a/serial_freebsd.go +++ b/serial_freebsd.go @@ -6,10 +6,15 @@ package serial -import "golang.org/x/sys/unix" +import ( + "regexp" + + "golang.org/x/sys/unix" +) const devFolder = "/dev" -const regexFilter = "^(cu|tty)\\..*" + +var osPortFiler = regexp.MustCompile("^(cu|tty)\\..*") // termios manipulation functions diff --git a/serial_linux.go b/serial_linux.go index fe114d9..93482cd 100644 --- a/serial_linux.go +++ b/serial_linux.go @@ -6,10 +6,15 @@ package serial -import "golang.org/x/sys/unix" +import ( + "regexp" + + "golang.org/x/sys/unix" +) const devFolder = "/dev" -const regexFilter = "(ttyS|ttyHS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO|ttymxc)[0-9]{1,3}" + +var osPortFilter = regexp.MustCompile("(ttyS|ttyHS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO|ttymxc)[0-9]{1,3}") // termios manipulation functions diff --git a/serial_openbsd.go b/serial_openbsd.go index 644dc92..e56a760 100644 --- a/serial_openbsd.go +++ b/serial_openbsd.go @@ -6,10 +6,15 @@ package serial -import "golang.org/x/sys/unix" +import ( + "regexp" + + "golang.org/x/sys/unix" +) const devFolder = "/dev" -const regexFilter = "^(cu|tty)\\..*" + +var osPortFiler = regexp.MustCompile("^(cu|tty)\\..*") // termios manipulation functions diff --git a/serial_unix.go b/serial_unix.go index 9328656..dffdcb4 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -11,7 +11,6 @@ package serial import ( "fmt" "os" - "regexp" "strings" "sync" "sync/atomic" @@ -298,10 +297,6 @@ func nativeGetPortsList() ([]string, error) { } ports := make([]string, 0, len(files)) - regex, err := regexp.Compile(regexFilter) - if err != nil { - return nil, err - } for _, f := range files { // Skip folders if f.IsDir() { @@ -309,7 +304,7 @@ func nativeGetPortsList() ([]string, error) { } // Keep only devices with the correct name - if !regex.MatchString(f.Name()) { + if !osPortFilter.MatchString(f.Name()) { continue } From 572f392ca94f20292ea48ab1e3884a325efa4487 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 20 Feb 2024 15:27:44 +0100 Subject: [PATCH 10/34] Updated license year --- LICENSE | 2 +- doc.go | 2 +- enumerator/doc.go | 2 +- enumerator/enumerator.go | 2 +- enumerator/example_getdetailedportlist_test.go | 2 +- enumerator/usb_darwin.go | 2 +- enumerator/usb_freebsd.go | 2 +- enumerator/usb_linux.go | 2 +- enumerator/usb_openbsd.go | 2 +- enumerator/usb_windows.go | 2 +- enumerator/usb_windows_test.go | 2 +- example_getportlist_test.go | 2 +- example_modem_bits_test.go | 2 +- example_serialport_test.go | 2 +- example_test.go | 2 +- portlist/portlist.go | 2 +- serial.go | 2 +- serial_bsd.go | 2 +- serial_darwin.go | 2 +- serial_darwin_386.go | 2 +- serial_darwin_64.go | 2 +- serial_freebsd.go | 2 +- serial_linux.go | 2 +- serial_linux_test.go | 2 +- serial_openbsd.go | 2 +- serial_resetbuf_linux_bsd.go | 2 +- serial_specialbaudrate_linux.go | 2 +- serial_specialbaudrate_linux_ppc64le.go | 2 +- serial_unix.go | 2 +- serial_windows.go | 2 +- syscall_windows.go | 2 +- unixutils/pipe.go | 2 +- unixutils/select.go | 2 +- 33 files changed, 33 insertions(+), 33 deletions(-) diff --git a/LICENSE b/LICENSE index e34cbff..5aca55c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2014-2023, Cristian Maglie. +Copyright (c) 2014-2024, Cristian Maglie. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/doc.go b/doc.go index 6e230ff..360f0cc 100644 --- a/doc.go +++ b/doc.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/doc.go b/enumerator/doc.go index a3f887d..5d27f00 100644 --- a/enumerator/doc.go +++ b/enumerator/doc.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/enumerator.go b/enumerator/enumerator.go index 420f451..2bd5043 100644 --- a/enumerator/enumerator.go +++ b/enumerator/enumerator.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/example_getdetailedportlist_test.go b/enumerator/example_getdetailedportlist_test.go index d2796fb..6d3c2db 100644 --- a/enumerator/example_getdetailedportlist_test.go +++ b/enumerator/example_getdetailedportlist_test.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/usb_darwin.go b/enumerator/usb_darwin.go index d9adb1b..1f51c47 100644 --- a/enumerator/usb_darwin.go +++ b/enumerator/usb_darwin.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/usb_freebsd.go b/enumerator/usb_freebsd.go index db5d96c..553c5a0 100644 --- a/enumerator/usb_freebsd.go +++ b/enumerator/usb_freebsd.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/usb_linux.go b/enumerator/usb_linux.go index f756367..2e3737e 100644 --- a/enumerator/usb_linux.go +++ b/enumerator/usb_linux.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/usb_openbsd.go b/enumerator/usb_openbsd.go index db5d96c..553c5a0 100644 --- a/enumerator/usb_openbsd.go +++ b/enumerator/usb_openbsd.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/usb_windows.go b/enumerator/usb_windows.go index 7883e45..c8018f9 100644 --- a/enumerator/usb_windows.go +++ b/enumerator/usb_windows.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/enumerator/usb_windows_test.go b/enumerator/usb_windows_test.go index 3160ef3..3d39e0a 100644 --- a/enumerator/usb_windows_test.go +++ b/enumerator/usb_windows_test.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/example_getportlist_test.go b/example_getportlist_test.go index beb4773..a1756ac 100644 --- a/example_getportlist_test.go +++ b/example_getportlist_test.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/example_modem_bits_test.go b/example_modem_bits_test.go index 34b212f..cc6969d 100644 --- a/example_modem_bits_test.go +++ b/example_modem_bits_test.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/example_serialport_test.go b/example_serialport_test.go index 12f68b5..b56fd7f 100644 --- a/example_serialport_test.go +++ b/example_serialport_test.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/example_test.go b/example_test.go index 27430d0..7ad5eef 100644 --- a/example_test.go +++ b/example_test.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/portlist/portlist.go b/portlist/portlist.go index 8c36e5c..845a6c9 100644 --- a/portlist/portlist.go +++ b/portlist/portlist.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial.go b/serial.go index abfd7f9..8e3ce89 100644 --- a/serial.go +++ b/serial.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_bsd.go b/serial_bsd.go index fb7c849..0368d18 100644 --- a/serial_bsd.go +++ b/serial_bsd.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_darwin.go b/serial_darwin.go index 3baa489..2398ea5 100644 --- a/serial_darwin.go +++ b/serial_darwin.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_darwin_386.go b/serial_darwin_386.go index 3594a6c..f3842b5 100644 --- a/serial_darwin_386.go +++ b/serial_darwin_386.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_darwin_64.go b/serial_darwin_64.go index d1ae7c4..c0ed76c 100644 --- a/serial_darwin_64.go +++ b/serial_darwin_64.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_freebsd.go b/serial_freebsd.go index be0fa01..591dc4b 100644 --- a/serial_freebsd.go +++ b/serial_freebsd.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_linux.go b/serial_linux.go index 93482cd..a1218bb 100644 --- a/serial_linux.go +++ b/serial_linux.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_linux_test.go b/serial_linux_test.go index 1a7e1a3..4a76fbe 100644 --- a/serial_linux_test.go +++ b/serial_linux_test.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_openbsd.go b/serial_openbsd.go index e56a760..3b396c1 100644 --- a/serial_openbsd.go +++ b/serial_openbsd.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_resetbuf_linux_bsd.go b/serial_resetbuf_linux_bsd.go index 105669d..9e24604 100644 --- a/serial_resetbuf_linux_bsd.go +++ b/serial_resetbuf_linux_bsd.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_specialbaudrate_linux.go b/serial_specialbaudrate_linux.go index ff48974..4e55fdb 100644 --- a/serial_specialbaudrate_linux.go +++ b/serial_specialbaudrate_linux.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_specialbaudrate_linux_ppc64le.go b/serial_specialbaudrate_linux_ppc64le.go index cd80b86..b31d6c5 100644 --- a/serial_specialbaudrate_linux_ppc64le.go +++ b/serial_specialbaudrate_linux_ppc64le.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_unix.go b/serial_unix.go index dffdcb4..54e55a8 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/serial_windows.go b/serial_windows.go index 35bb0c9..e350f86 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/syscall_windows.go b/syscall_windows.go index c814528..6a95dcf 100644 --- a/syscall_windows.go +++ b/syscall_windows.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/unixutils/pipe.go b/unixutils/pipe.go index 748de34..c11e0d1 100644 --- a/unixutils/pipe.go +++ b/unixutils/pipe.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // diff --git a/unixutils/select.go b/unixutils/select.go index 9f0e214..42cacc3 100644 --- a/unixutils/select.go +++ b/unixutils/select.go @@ -1,5 +1,5 @@ // -// Copyright 2014-2023 Cristian Maglie. All rights reserved. +// Copyright 2014-2024 Cristian Maglie. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // From 259bdeb6c725b44fa27b6f927d9a3c5a868d09fd Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 20 Feb 2024 15:57:58 +0100 Subject: [PATCH 11/34] Fixed typo --- serial_darwin.go | 2 +- serial_freebsd.go | 2 +- serial_openbsd.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/serial_darwin.go b/serial_darwin.go index 2398ea5..a87458e 100644 --- a/serial_darwin.go +++ b/serial_darwin.go @@ -14,7 +14,7 @@ import ( const devFolder = "/dev" -var osPortFiler = regexp.MustCompile("^(cu|tty)\\..*") +var osPortFilter = regexp.MustCompile("^(cu|tty)\\..*") const ioctlTcgetattr = unix.TIOCGETA const ioctlTcsetattr = unix.TIOCSETA diff --git a/serial_freebsd.go b/serial_freebsd.go index 591dc4b..775b7a6 100644 --- a/serial_freebsd.go +++ b/serial_freebsd.go @@ -14,7 +14,7 @@ import ( const devFolder = "/dev" -var osPortFiler = regexp.MustCompile("^(cu|tty)\\..*") +var osPortFilter = regexp.MustCompile("^(cu|tty)\\..*") // termios manipulation functions diff --git a/serial_openbsd.go b/serial_openbsd.go index 3b396c1..ad5efd0 100644 --- a/serial_openbsd.go +++ b/serial_openbsd.go @@ -14,7 +14,7 @@ import ( const devFolder = "/dev" -var osPortFiler = regexp.MustCompile("^(cu|tty)\\..*") +var osPortFilter = regexp.MustCompile("^(cu|tty)\\..*") // termios manipulation functions From 42bc112d18a52424bbf6546a4e0af53f5158bdcc Mon Sep 17 00:00:00 2001 From: Christian Stewart Date: Tue, 20 Feb 2024 15:46:44 -0800 Subject: [PATCH 12/34] fix: add shims for GOARCH=wasm with GOOS=js and GOOS=wasip1 Fixes build errors: GOOS=js GOARCH=wasm go build GOOS=wasip1 GOARCH=wasm go build Signed-off-by: Christian Stewart --- enumerator/usb_wasm.go | 11 +++++++++++ enumerator_wasm.go | 15 +++++++++++++++ serial_wasm.go | 15 +++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 enumerator/usb_wasm.go create mode 100644 enumerator_wasm.go create mode 100644 serial_wasm.go diff --git a/enumerator/usb_wasm.go b/enumerator/usb_wasm.go new file mode 100644 index 0000000..3f3b22f --- /dev/null +++ b/enumerator/usb_wasm.go @@ -0,0 +1,11 @@ +// +// Copyright 2014-2024 Cristian Maglie. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// + +package enumerator + +func nativeGetDetailedPortsList() ([]*PortDetails, error) { + return nil, &PortEnumerationError{} +} diff --git a/enumerator_wasm.go b/enumerator_wasm.go new file mode 100644 index 0000000..349d272 --- /dev/null +++ b/enumerator_wasm.go @@ -0,0 +1,15 @@ +// +// Copyright 2014-2024 Cristian Maglie. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// + +package serial + +import ( + "errors" +) + +func nativeGetPortsList() ([]string, error) { + return nil, errors.New("nativeGetPortsList is not supported on wasm") +} diff --git a/serial_wasm.go b/serial_wasm.go new file mode 100644 index 0000000..b2369f1 --- /dev/null +++ b/serial_wasm.go @@ -0,0 +1,15 @@ +// +// Copyright 2014-2024 Cristian Maglie. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// + +package serial + +import ( + "errors" +) + +func nativeOpen(portName string, mode *Mode) (Port, error) { + return nil, errors.New("nativeOpen is not supported on wasm") +} From bac809c5a1a385fa544b29a7fcabe9c980c5a7fd Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 18 Mar 2024 22:25:55 +0100 Subject: [PATCH 13/34] Fixed minor documentation typos --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b05796c..c32fa18 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,17 @@ # go.bug.st/serial -A cross-platform serial library for go-lang. +A cross-platform serial port library for Go. ## Documentation and examples -See the godoc here: https://godoc.org/go.bug.st/serial +See the package documentation here: https://pkg.go.dev/go.bug.st/serial ## go.mod transition -This library now support `go.mod` with the import `go.bug.st/serial`. +This library supports `go.mod` with the import `go.bug.st/serial`. -If you came from the pre-`go.mod` era please update your import paths from `go.bug.st/serial.v1` to `go.bug.st/serial` to receive new updates. Anyway, the latest `v1` release should still be avaiable using the old import. +If you came from the pre-`go.mod` era please update your import paths from `go.bug.st/serial.v1` to `go.bug.st/serial` to receive updates. The latest `v1` release is still available using the old import path. ## Credits @@ -20,7 +20,7 @@ If you came from the pre-`go.mod` era please update your import paths from `go.b ## License -The software is release under a [BSD 3-clause license] +This software is released under the [BSD 3-clause license]. [contributors]: https://github.com/bugst/go-serial/graphs/contributors [BSD 3-clause license]: https://github.com/bugst/go-serial/blob/master/LICENSE From 671075c6acc7965eca6d30a0ba4020683d0e6667 Mon Sep 17 00:00:00 2001 From: Andreas Deininger Date: Mon, 1 Apr 2024 16:04:53 +0200 Subject: [PATCH 14/34] Go-format source code --- portlist/portlist.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/portlist/portlist.go b/portlist/portlist.go index 845a6c9..5d58409 100644 --- a/portlist/portlist.go +++ b/portlist/portlist.go @@ -12,7 +12,7 @@ // Port: /dev/cu.usbmodemFD121 // USB ID 2341:8053 // USB serial FB7B6060504B5952302E314AFF08191A -// + package main import ( From 03c961bc8afed1fd4bd8043607d1441dee5b83e6 Mon Sep 17 00:00:00 2001 From: Andre Renaud Date: Tue, 28 May 2024 09:10:28 +1200 Subject: [PATCH 15/34] Workflows: Use CGO_ENABLED=1 for MacOS Also enable explicit ARM64 builds --- .github/workflows/test.yaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7a43621..01c4691 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -19,9 +19,18 @@ jobs: - uses: actions/setup-go@v1 with: go-version: "1.17" - - name: Build native + - name: Setup CGO Environment + run: | + if [ ${{ matrix.os }} == 'macOS-latest' ] ; then + echo "CGO_ENABLED=1" >> "$GITHUB_ENV" + fi + shell: bash + - name: Build AMD64 run: GOARCH=amd64 go build -v ./... shell: bash + - name: Build ARM64 + run: GOARCH=arm64 go build -v ./... + shell: bash - name: Install socat if: matrix.os == 'ubuntu-latest' run: sudo apt-get install socat From 1282f62c6e37fb2eed3520f9cf65bfd93dfb5a83 Mon Sep 17 00:00:00 2001 From: Andreas Deininger Date: Mon, 24 Jun 2024 17:24:35 +0200 Subject: [PATCH 16/34] Bump GitHub workflow actions to latest versions (#185) * Bump GitHub workflow actions to latest versions * Fixed typo --------- Co-authored-by: Cristian Maglie --- .github/workflows/test.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 01c4691..bfacab5 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -15,10 +15,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.17" + go-version: "1.22" - name: Setup CGO Environment run: | if [ ${{ matrix.os }} == 'macOS-latest' ] ; then @@ -60,10 +60,10 @@ jobs: runs-on: "ubuntu-latest" steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.17" + go-version: "1.22" - name: Cross-build run: | set ${{ matrix.go-os-pairs }} From 0b7848559acc54148cec234c28eb7f88612673d6 Mon Sep 17 00:00:00 2001 From: Andreas Deininger Date: Mon, 24 Jun 2024 17:33:18 +0200 Subject: [PATCH 17/34] Fix typos (#183) Co-authored-by: Cristian Maglie --- enumerator/usb_windows.go | 2 +- serial.go | 2 +- serial_windows.go | 10 +++++----- unixutils/pipe.go | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/enumerator/usb_windows.go b/enumerator/usb_windows.go index c8018f9..2d3793b 100644 --- a/enumerator/usb_windows.go +++ b/enumerator/usb_windows.go @@ -98,7 +98,7 @@ const ( spdrpUpperFilters = 0x00000011 // UpperFilters = R/W spdrpLowerFilters = 0x00000012 // LowerFilters = R/W spdrpBusTypeGUID = 0x00000013 // BusTypeGUID = R - spdrpLegactBusType = 0x00000014 // LegacyBusType = R + spdrpLegacyBusType = 0x00000014 // LegacyBusType = R spdrpBusNumber = 0x00000015 // BusNumber = R spdrpEnumeratorName = 0x00000016 // Enumerator Name = R spdrpSecurity = 0x00000017 // Security = R/W, binary form diff --git a/serial.go b/serial.go index 8e3ce89..a2f7333 100644 --- a/serial.go +++ b/serial.go @@ -147,7 +147,7 @@ const ( PortNotFound // InvalidSerialPort the requested port is not a serial port InvalidSerialPort - // PermissionDenied the user doesn't have enough priviledges + // PermissionDenied the user doesn't have enough privileges PermissionDenied // InvalidSpeed the requested speed is not valid or not supported InvalidSpeed diff --git a/serial_windows.go b/serial_windows.go index e350f86..b2c9009 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -152,7 +152,7 @@ const ( dcbInX = 0x00000200 dcbErrorChar = 0x00000400 dcbNull = 0x00000800 - dcbRTSControlDisbaleMask = ^uint32(0x00003000) + dcbRTSControlDisableMask = ^uint32(0x00003000) dcbRTSControlEnable = 0x00001000 dcbRTSControlHandshake = 0x00002000 dcbRTSControlToggle = 0x00003000 @@ -282,8 +282,8 @@ func (port *windowsPort) SetDTR(dtr bool) error { // observed behaviour was that DTR is set from false -> true // when setting RTS from true -> false // 1) Connect -> RTS = true (low) DTR = true (low) OKAY - // 2) SetDTR(false) -> RTS = true (low) DTR = false (heigh) OKAY - // 3) SetRTS(false) -> RTS = false (heigh) DTR = true (low) ERROR: DTR toggled + // 2) SetDTR(false) -> RTS = true (low) DTR = false (high) OKAY + // 3) SetRTS(false) -> RTS = false (high) DTR = true (low) ERROR: DTR toggled // // In addition this way the CommState Flags are not updated /* @@ -343,7 +343,7 @@ func (port *windowsPort) SetRTS(rts bool) error { if err := getCommState(port.handle, params); err != nil { return &PortError{causedBy: err} } - params.Flags &= dcbRTSControlDisbaleMask + params.Flags &= dcbRTSControlDisableMask if rts { params.Flags |= dcbRTSControlEnable } @@ -443,7 +443,7 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { } port.setModeParams(mode, params) params.Flags &= dcbDTRControlDisableMask - params.Flags &= dcbRTSControlDisbaleMask + params.Flags &= dcbRTSControlDisableMask if mode.InitialStatusBits == nil { params.Flags |= dcbDTRControlEnable params.Flags |= dcbRTSControlEnable diff --git a/unixutils/pipe.go b/unixutils/pipe.go index c11e0d1..f54c916 100644 --- a/unixutils/pipe.go +++ b/unixutils/pipe.go @@ -40,7 +40,7 @@ func (p *Pipe) ReadFD() int { return p.rd } -// WriteFD returns the flie handle for the write side of the pipe. +// WriteFD returns the file handle for the write side of the pipe. func (p *Pipe) WriteFD() int { if !p.opened { return -1 @@ -48,7 +48,7 @@ func (p *Pipe) WriteFD() int { return p.wr } -// Write to the pipe the content of data. Returns the numbre of bytes written. +// Write to the pipe the content of data. Returns the number of bytes written. func (p *Pipe) Write(data []byte) (int, error) { if !p.opened { return 0, fmt.Errorf("Pipe not opened") From 45e996e1b06fb0d93f64a09d13f27d0859b19000 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 9 Apr 2024 12:51:09 +0200 Subject: [PATCH 18/34] Use Windows serial comm functions from golang.org/x/sys/windows --- go.mod | 2 +- go.sum | 4 +- serial_windows.go | 261 ++++++++++++++------------------------------ syscall_windows.go | 31 ------ zsyscall_windows.go | 161 --------------------------- 5 files changed, 84 insertions(+), 375 deletions(-) delete mode 100644 syscall_windows.go delete mode 100644 zsyscall_windows.go diff --git a/go.mod b/go.mod index 61d0d6d..e89755e 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( github.com/creack/goselect v0.1.2 github.com/stretchr/testify v1.8.4 - golang.org/x/sys v0.17.0 + golang.org/x/sys v0.19.0 ) require ( diff --git a/go.sum b/go.sum index 43d4dac..4cef3dc 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/serial_windows.go b/serial_windows.go index b2c9009..a7f9a12 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -19,46 +19,29 @@ package serial import ( "sync" - "syscall" "time" + + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" ) type windowsPort struct { mu sync.Mutex - handle syscall.Handle + handle windows.Handle } func nativeGetPortsList() ([]string, error) { - subKey, err := syscall.UTF16PtrFromString("HARDWARE\\DEVICEMAP\\SERIALCOMM\\") + key, err := registry.OpenKey(windows.HKEY_LOCAL_MACHINE, `HARDWARE\DEVICEMAP\SERIALCOMM\`, windows.KEY_READ) if err != nil { - return nil, &PortError{code: ErrorEnumeratingPorts} - } - - var h syscall.Handle - if err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, subKey, 0, syscall.KEY_READ, &h); err != nil { - if errno, isErrno := err.(syscall.Errno); isErrno && errno == syscall.ERROR_FILE_NOT_FOUND { - return []string{}, nil - } - return nil, &PortError{code: ErrorEnumeratingPorts} + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} } - defer syscall.RegCloseKey(h) + defer key.Close() - var valuesCount uint32 - if syscall.RegQueryInfoKey(h, nil, nil, nil, nil, nil, nil, &valuesCount, nil, nil, nil, nil) != nil { - return nil, &PortError{code: ErrorEnumeratingPorts} + list, err := key.ReadValueNames(0) + if err != nil { + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} } - list := make([]string, valuesCount) - for i := range list { - var data [1024]uint16 - dataSize := uint32(len(data)) - var name [1024]uint16 - nameSize := uint32(len(name)) - if regEnumValue(h, uint32(i), &name[0], &nameSize, nil, nil, &data[0], &dataSize) != nil { - return nil, &PortError{code: ErrorEnumeratingPorts} - } - list[i] = syscall.UTF16ToString(data[:]) - } return list, nil } @@ -71,7 +54,7 @@ func (port *windowsPort) Close() error { if port.handle == 0 { return nil } - return syscall.CloseHandle(port.handle) + return windows.CloseHandle(port.handle) } func (port *windowsPort) Read(p []byte) (int, error) { @@ -80,16 +63,16 @@ func (port *windowsPort) Read(p []byte) (int, error) { if err != nil { return 0, err } - defer syscall.CloseHandle(ev.HEvent) + defer windows.CloseHandle(ev.HEvent) - err = syscall.ReadFile(port.handle, p, &readed, ev) - if err == syscall.ERROR_IO_PENDING { - err = getOverlappedResult(port.handle, ev, &readed, true) + err = windows.ReadFile(port.handle, p, &readed, ev) + if err == windows.ERROR_IO_PENDING { + err = windows.GetOverlappedResult(port.handle, ev, &readed, true) } switch err { case nil: // operation completed successfully - case syscall.ERROR_OPERATION_ABORTED: + case windows.ERROR_OPERATION_ABORTED: // port may have been closed return int(readed), &PortError{code: PortClosed, causedBy: err} default: @@ -110,32 +93,25 @@ func (port *windowsPort) Write(p []byte) (int, error) { if err != nil { return 0, err } - defer syscall.CloseHandle(ev.HEvent) - err = syscall.WriteFile(port.handle, p, &writed, ev) - if err == syscall.ERROR_IO_PENDING { + defer windows.CloseHandle(ev.HEvent) + err = windows.WriteFile(port.handle, p, &writed, ev) + if err == windows.ERROR_IO_PENDING { // wait for write to complete - err = getOverlappedResult(port.handle, ev, &writed, true) + err = windows.GetOverlappedResult(port.handle, ev, &writed, true) } return int(writed), err } func (port *windowsPort) Drain() (err error) { - return syscall.FlushFileBuffers(port.handle) + return windows.FlushFileBuffers(port.handle) } -const ( - purgeRxAbort uint32 = 0x0002 - purgeRxClear = 0x0008 - purgeTxAbort = 0x0001 - purgeTxClear = 0x0004 -) - func (port *windowsPort) ResetInputBuffer() error { - return purgeComm(port.handle, purgeRxClear|purgeRxAbort) + return windows.PurgeComm(port.handle, windows.PURGE_RXCLEAR|windows.PURGE_RXABORT) } func (port *windowsPort) ResetOutputBuffer() error { - return purgeComm(port.handle, purgeTxClear|purgeTxAbort) + return windows.PurgeComm(port.handle, windows.PURGE_TXCLEAR|windows.PURGE_TXABORT) } const ( @@ -159,112 +135,37 @@ const ( dcbAbortOnError = 0x00004000 ) -type dcb struct { - DCBlength uint32 - BaudRate uint32 - - // Flags field is a bitfield - // fBinary :1 - // fParity :1 - // fOutxCtsFlow :1 - // fOutxDsrFlow :1 - // fDtrControl :2 - // fDsrSensitivity :1 - // fTXContinueOnXoff :1 - // fOutX :1 - // fInX :1 - // fErrorChar :1 - // fNull :1 - // fRtsControl :2 - // fAbortOnError :1 - // fDummy2 :17 - Flags uint32 - - wReserved uint16 - XonLim uint16 - XoffLim uint16 - ByteSize byte - Parity byte - StopBits byte - XonChar byte - XoffChar byte - ErrorChar byte - EOFChar byte - EvtChar byte - wReserved1 uint16 -} - -type commTimeouts struct { - ReadIntervalTimeout uint32 - ReadTotalTimeoutMultiplier uint32 - ReadTotalTimeoutConstant uint32 - WriteTotalTimeoutMultiplier uint32 - WriteTotalTimeoutConstant uint32 -} - -const ( - noParity = 0 - oddParity = 1 - evenParity = 2 - markParity = 3 - spaceParity = 4 -) - var parityMap = map[Parity]byte{ - NoParity: noParity, - OddParity: oddParity, - EvenParity: evenParity, - MarkParity: markParity, - SpaceParity: spaceParity, + NoParity: windows.NOPARITY, + OddParity: windows.ODDPARITY, + EvenParity: windows.EVENPARITY, + MarkParity: windows.MARKPARITY, + SpaceParity: windows.SPACEPARITY, } -const ( - oneStopBit = 0 - one5StopBits = 1 - twoStopBits = 2 -) - var stopBitsMap = map[StopBits]byte{ - OneStopBit: oneStopBit, - OnePointFiveStopBits: one5StopBits, - TwoStopBits: twoStopBits, + OneStopBit: windows.ONESTOPBIT, + OnePointFiveStopBits: windows.ONE5STOPBITS, + TwoStopBits: windows.TWOSTOPBITS, } -const ( - commFunctionSetXOFF = 1 - commFunctionSetXON = 2 - commFunctionSetRTS = 3 - commFunctionClrRTS = 4 - commFunctionSetDTR = 5 - commFunctionClrDTR = 6 - commFunctionSetBreak = 8 - commFunctionClrBreak = 9 -) - -const ( - msCTSOn = 0x0010 - msDSROn = 0x0020 - msRingOn = 0x0040 - msRLSDOn = 0x0080 -) - func (port *windowsPort) SetMode(mode *Mode) error { - params := dcb{} - if getCommState(port.handle, ¶ms) != nil { + params := windows.DCB{} + if windows.GetCommState(port.handle, ¶ms) != nil { port.Close() return &PortError{code: InvalidSerialPort} } port.setModeParams(mode, ¶ms) - if setCommState(port.handle, ¶ms) != nil { + if windows.SetCommState(port.handle, ¶ms) != nil { port.Close() return &PortError{code: InvalidSerialPort} } return nil } -func (port *windowsPort) setModeParams(mode *Mode, params *dcb) { +func (port *windowsPort) setModeParams(mode *Mode, params *windows.DCB) { if mode.BaudRate == 0 { - params.BaudRate = 9600 // Default to 9600 + params.BaudRate = windows.CBR_9600 // Default to 9600 } else { params.BaudRate = uint32(mode.BaudRate) } @@ -278,22 +179,22 @@ func (port *windowsPort) setModeParams(mode *Mode, params *dcb) { } func (port *windowsPort) SetDTR(dtr bool) error { - // Like for RTS there are problems with the escapeCommFunction + // Like for RTS there are problems with the windows.EscapeCommFunction // observed behaviour was that DTR is set from false -> true // when setting RTS from true -> false // 1) Connect -> RTS = true (low) DTR = true (low) OKAY - // 2) SetDTR(false) -> RTS = true (low) DTR = false (high) OKAY - // 3) SetRTS(false) -> RTS = false (high) DTR = true (low) ERROR: DTR toggled + // 2) SetDTR(false) -> RTS = true (low) DTR = false (heigh) OKAY + // 3) SetRTS(false) -> RTS = false (heigh) DTR = true (low) ERROR: DTR toggled // // In addition this way the CommState Flags are not updated /* - var res bool + var err error if dtr { - res = escapeCommFunction(port.handle, commFunctionSetDTR) + err = windows.EscapeCommFunction(port.handle, windows.SETDTR) } else { - res = escapeCommFunction(port.handle, commFunctionClrDTR) + err = windows.EscapeCommFunction(port.handle, windows.CLTDTR) } - if !res { + if err != nil { return &PortError{} } return nil @@ -301,15 +202,15 @@ func (port *windowsPort) SetDTR(dtr bool) error { // The following seems a more reliable way to do it - params := &dcb{} - if err := getCommState(port.handle, params); err != nil { + params := &windows.DCB{} + if err := windows.GetCommState(port.handle, params); err != nil { return &PortError{causedBy: err} } params.Flags &= dcbDTRControlDisableMask if dtr { - params.Flags |= dcbDTRControlEnable + params.Flags |= windows.DTR_CONTROL_ENABLE } - if err := setCommState(port.handle, params); err != nil { + if err := windows.SetCommState(port.handle, params); err != nil { return &PortError{causedBy: err} } @@ -325,13 +226,13 @@ func (port *windowsPort) SetRTS(rts bool) error { // In addition this way the CommState Flags are not updated /* - var res bool + var err error if rts { - res = escapeCommFunction(port.handle, commFunctionSetRTS) + err = windows.EscapeCommFunction(port.handle, windows.SETRTS) } else { - res = escapeCommFunction(port.handle, commFunctionClrRTS) + err = windows.EscapeCommFunction(port.handle, windows.CLRRTS) } - if !res { + if err != nil { return &PortError{} } return nil @@ -339,15 +240,15 @@ func (port *windowsPort) SetRTS(rts bool) error { // The following seems a more reliable way to do it - params := &dcb{} - if err := getCommState(port.handle, params); err != nil { + params := &windows.DCB{} + if err := windows.GetCommState(port.handle, params); err != nil { return &PortError{causedBy: err} } params.Flags &= dcbRTSControlDisableMask if rts { - params.Flags |= dcbRTSControlEnable + params.Flags |= windows.RTS_CONTROL_ENABLE } - if err := setCommState(port.handle, params); err != nil { + if err := windows.SetCommState(port.handle, params); err != nil { return &PortError{causedBy: err} } return nil @@ -355,19 +256,19 @@ func (port *windowsPort) SetRTS(rts bool) error { func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) { var bits uint32 - if !getCommModemStatus(port.handle, &bits) { + if err := windows.GetCommModemStatus(port.handle, &bits); err != nil { return nil, &PortError{} } return &ModemStatusBits{ - CTS: (bits & msCTSOn) != 0, - DCD: (bits & msRLSDOn) != 0, - DSR: (bits & msDSROn) != 0, - RI: (bits & msRingOn) != 0, + CTS: (bits & windows.EV_CTS) != 0, + DCD: (bits & windows.EV_RLSD) != 0, + DSR: (bits & windows.EV_DSR) != 0, + RI: (bits & windows.EV_RING) != 0, }, nil } func (port *windowsPort) SetReadTimeout(timeout time.Duration) error { - commTimeouts := &commTimeouts{ + commTimeouts := &windows.CommTimeouts{ ReadIntervalTimeout: 0xFFFFFFFF, ReadTotalTimeoutMultiplier: 0xFFFFFFFF, ReadTotalTimeoutConstant: 0xFFFFFFFE, @@ -382,7 +283,7 @@ func (port *windowsPort) SetReadTimeout(timeout time.Duration) error { commTimeouts.ReadTotalTimeoutConstant = uint32(ms) } - if err := setCommTimeouts(port.handle, commTimeouts); err != nil { + if err := windows.SetCommTimeouts(port.handle, commTimeouts); err != nil { return &PortError{code: InvalidTimeoutValue, causedBy: err} } @@ -390,42 +291,42 @@ func (port *windowsPort) SetReadTimeout(timeout time.Duration) error { } func (port *windowsPort) Break(d time.Duration) error { - if err := setCommBreak(port.handle); err != nil { + if err := windows.SetCommBreak(port.handle); err != nil { return &PortError{causedBy: err} } time.Sleep(d) - if err := clearCommBreak(port.handle); err != nil { + if err := windows.ClearCommBreak(port.handle); err != nil { return &PortError{causedBy: err} } return nil } -func createOverlappedEvent() (*syscall.Overlapped, error) { - h, err := createEvent(nil, true, false, nil) - return &syscall.Overlapped{HEvent: h}, err +func createOverlappedEvent() (*windows.Overlapped, error) { + h, err := windows.CreateEvent(nil, 1, 0, nil) + return &windows.Overlapped{HEvent: h}, err } func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { portName = "\\\\.\\" + portName - path, err := syscall.UTF16PtrFromString(portName) + path, err := windows.UTF16PtrFromString(portName) if err != nil { return nil, err } - handle, err := syscall.CreateFile( + handle, err := windows.CreateFile( path, - syscall.GENERIC_READ|syscall.GENERIC_WRITE, + windows.GENERIC_READ|windows.GENERIC_WRITE, 0, nil, - syscall.OPEN_EXISTING, - syscall.FILE_FLAG_OVERLAPPED, + windows.OPEN_EXISTING, + windows.FILE_FLAG_OVERLAPPED, 0) if err != nil { switch err { - case syscall.ERROR_ACCESS_DENIED: + case windows.ERROR_ACCESS_DENIED: return nil, &PortError{code: PortBusy} - case syscall.ERROR_FILE_NOT_FOUND: + case windows.ERROR_FILE_NOT_FOUND: return nil, &PortError{code: PortNotFound} } return nil, err @@ -436,8 +337,8 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { } // Set port parameters - params := &dcb{} - if getCommState(port.handle, params) != nil { + params := &windows.DCB{} + if windows.GetCommState(port.handle, params) != nil { port.Close() return nil, &PortError{code: InvalidSerialPort} } @@ -445,14 +346,14 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { params.Flags &= dcbDTRControlDisableMask params.Flags &= dcbRTSControlDisableMask if mode.InitialStatusBits == nil { - params.Flags |= dcbDTRControlEnable - params.Flags |= dcbRTSControlEnable + params.Flags |= windows.DTR_CONTROL_ENABLE + params.Flags |= windows.RTS_CONTROL_ENABLE } else { if mode.InitialStatusBits.DTR { - params.Flags |= dcbDTRControlEnable + params.Flags |= windows.DTR_CONTROL_ENABLE } if mode.InitialStatusBits.RTS { - params.Flags |= dcbRTSControlEnable + params.Flags |= windows.RTS_CONTROL_ENABLE } } params.Flags &^= dcbOutXCTSFlow @@ -468,7 +369,7 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { params.XoffLim = 512 params.XonChar = 17 // DC1 params.XoffChar = 19 // C3 - if setCommState(port.handle, params) != nil { + if windows.SetCommState(port.handle, params) != nil { port.Close() return nil, &PortError{code: InvalidSerialPort} } diff --git a/syscall_windows.go b/syscall_windows.go deleted file mode 100644 index 6a95dcf..0000000 --- a/syscall_windows.go +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright 2014-2024 Cristian Maglie. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// - -package serial - -//sys regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, value *uint16, valueLen *uint32) (regerrno error) = advapi32.RegEnumValueW - -//sys getCommState(handle syscall.Handle, dcb *dcb) (err error) = GetCommState - -//sys setCommState(handle syscall.Handle, dcb *dcb) (err error) = SetCommState - -//sys setCommTimeouts(handle syscall.Handle, timeouts *commTimeouts) (err error) = SetCommTimeouts - -//sys escapeCommFunction(handle syscall.Handle, function uint32) (res bool) = EscapeCommFunction - -//sys getCommModemStatus(handle syscall.Handle, bits *uint32) (res bool) = GetCommModemStatus - -//sys createEvent(eventAttributes *uint32, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) = CreateEventW - -//sys resetEvent(handle syscall.Handle) (err error) = ResetEvent - -//sys getOverlappedResult(handle syscall.Handle, overlapEvent *syscall.Overlapped, n *uint32, wait bool) (err error) = GetOverlappedResult - -//sys purgeComm(handle syscall.Handle, flags uint32) (err error) = PurgeComm - -//sys setCommBreak(handle syscall.Handle) (err error) = SetCommBreak - -//sys clearCommBreak(handle syscall.Handle) (err error) = ClearCommBreak diff --git a/zsyscall_windows.go b/zsyscall_windows.go deleted file mode 100644 index a2411a6..0000000 --- a/zsyscall_windows.go +++ /dev/null @@ -1,161 +0,0 @@ -// Code generated by 'go generate'; DO NOT EDIT. - -package serial - -import ( - "syscall" - "unsafe" - - "golang.org/x/sys/windows" -) - -var _ unsafe.Pointer - -// Do the interface allocations only once for common -// Errno values. -const ( - errnoERROR_IO_PENDING = 997 -) - -var ( - errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) - errERROR_EINVAL error = syscall.EINVAL -) - -// errnoErr returns common boxed Errno values, to prevent -// allocations at runtime. -func errnoErr(e syscall.Errno) error { - switch e { - case 0: - return errERROR_EINVAL - case errnoERROR_IO_PENDING: - return errERROR_IO_PENDING - } - // TODO: add more here, after collecting data on the common - // error values see on Windows. (perhaps when running - // all.bat?) - return e -} - -var ( - modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") - modkernel32 = windows.NewLazySystemDLL("kernel32.dll") - - procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW") - procClearCommBreak = modkernel32.NewProc("ClearCommBreak") - procCreateEventW = modkernel32.NewProc("CreateEventW") - procEscapeCommFunction = modkernel32.NewProc("EscapeCommFunction") - procGetCommModemStatus = modkernel32.NewProc("GetCommModemStatus") - procGetCommState = modkernel32.NewProc("GetCommState") - procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") - procPurgeComm = modkernel32.NewProc("PurgeComm") - procResetEvent = modkernel32.NewProc("ResetEvent") - procSetCommBreak = modkernel32.NewProc("SetCommBreak") - procSetCommState = modkernel32.NewProc("SetCommState") - procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts") -) - -func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, value *uint16, valueLen *uint32) (regerrno error) { - r0, _, _ := syscall.Syscall9(procRegEnumValueW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(valueLen)), 0) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - -func clearCommBreak(handle syscall.Handle) (err error) { - r1, _, e1 := syscall.Syscall(procClearCommBreak.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func createEvent(eventAttributes *uint32, manualReset bool, initialState bool, name *uint16) (handle syscall.Handle, err error) { - var _p0 uint32 - if manualReset { - _p0 = 1 - } - var _p1 uint32 - if initialState { - _p1 = 1 - } - r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttributes)), uintptr(_p0), uintptr(_p1), uintptr(unsafe.Pointer(name)), 0, 0) - handle = syscall.Handle(r0) - if handle == 0 { - err = errnoErr(e1) - } - return -} - -func escapeCommFunction(handle syscall.Handle, function uint32) (res bool) { - r0, _, _ := syscall.Syscall(procEscapeCommFunction.Addr(), 2, uintptr(handle), uintptr(function), 0) - res = r0 != 0 - return -} - -func getCommModemStatus(handle syscall.Handle, bits *uint32) (res bool) { - r0, _, _ := syscall.Syscall(procGetCommModemStatus.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(bits)), 0) - res = r0 != 0 - return -} - -func getCommState(handle syscall.Handle, dcb *dcb) (err error) { - r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func getOverlappedResult(handle syscall.Handle, overlapEvent *syscall.Overlapped, n *uint32, wait bool) (err error) { - var _p0 uint32 - if wait { - _p0 = 1 - } - r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapEvent)), uintptr(unsafe.Pointer(n)), uintptr(_p0), 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func purgeComm(handle syscall.Handle, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procPurgeComm.Addr(), 2, uintptr(handle), uintptr(flags), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func resetEvent(handle syscall.Handle) (err error) { - r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func setCommBreak(handle syscall.Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetCommBreak.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func setCommState(handle syscall.Handle, dcb *dcb) (err error) { - r1, _, e1 := syscall.Syscall(procSetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} - -func setCommTimeouts(handle syscall.Handle, timeouts *commTimeouts) (err error) { - r1, _, e1 := syscall.Syscall(procSetCommTimeouts.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(timeouts)), 0) - if r1 == 0 { - err = errnoErr(e1) - } - return -} From 1c72447e64a43ef0d6bfd1136f04b812096a1f56 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 25 Jun 2024 10:48:18 +0200 Subject: [PATCH 19/34] Fix typos Co-authored-by: Cristian Maglie --- serial_windows.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index a7f9a12..4751c91 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -183,8 +183,8 @@ func (port *windowsPort) SetDTR(dtr bool) error { // observed behaviour was that DTR is set from false -> true // when setting RTS from true -> false // 1) Connect -> RTS = true (low) DTR = true (low) OKAY - // 2) SetDTR(false) -> RTS = true (low) DTR = false (heigh) OKAY - // 3) SetRTS(false) -> RTS = false (heigh) DTR = true (low) ERROR: DTR toggled + // 2) SetDTR(false) -> RTS = true (low) DTR = false (high) OKAY + // 3) SetRTS(false) -> RTS = false (high) DTR = true (low) ERROR: DTR toggled // // In addition this way the CommState Flags are not updated /* From 56ac2d4e76afa2d2e789f33da60395ae184eccb1 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Tue, 25 Jun 2024 11:02:05 +0200 Subject: [PATCH 20/34] Restore check for no detected serial ports on Windows --- serial_windows.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/serial_windows.go b/serial_windows.go index 4751c91..5853e51 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -18,7 +18,9 @@ package serial */ import ( + "errors" "sync" + "syscall" "time" "golang.org/x/sys/windows" @@ -32,7 +34,12 @@ type windowsPort struct { func nativeGetPortsList() ([]string, error) { key, err := registry.OpenKey(windows.HKEY_LOCAL_MACHINE, `HARDWARE\DEVICEMAP\SERIALCOMM\`, windows.KEY_READ) - if err != nil { + switch { + case errors.Is(err, syscall.ERROR_FILE_NOT_FOUND): + // On machines with no serial ports the registry key does not exist. + // Return this as no serial ports instead of an error. + return nil, nil + case err != nil: return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} } defer key.Close() From f5a4685ea0112d5230d45141c606bb49cefc75a5 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 25 Jun 2024 23:52:38 +0200 Subject: [PATCH 21/34] Fixed examples for docs --- example_modem_bits_test.go | 2 +- example_serialport_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example_modem_bits_test.go b/example_modem_bits_test.go index cc6969d..eaad39a 100644 --- a/example_modem_bits_test.go +++ b/example_modem_bits_test.go @@ -14,7 +14,7 @@ import ( "go.bug.st/serial" ) -func ExampleGetSetModemBits() { +func ExamplePort_GetModemStatusBits() { // Open the first serial port detected at 9600bps N81 mode := &serial.Mode{ BaudRate: 9600, diff --git a/example_serialport_test.go b/example_serialport_test.go index b56fd7f..937b8b9 100644 --- a/example_serialport_test.go +++ b/example_serialport_test.go @@ -13,7 +13,7 @@ import ( "go.bug.st/serial" ) -func ExampleSerialPort_SetMode() { +func ExamplePort_SetMode() { port, err := serial.Open("/dev/ttyACM0", &serial.Mode{}) if err != nil { log.Fatal(err) From b7483e31a79c068ccdafa1bd5a39ec284e74c968 Mon Sep 17 00:00:00 2001 From: Dirk007 Date: Sat, 7 Sep 2024 13:26:01 +0200 Subject: [PATCH 22/34] Report the actual error instead of nil --- serial_unix.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serial_unix.go b/serial_unix.go index 54e55a8..e6913c2 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -241,7 +241,7 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { // Explicitly disable RTS/CTS flow control setTermSettingsCtsRts(false, settings) - if port.setTermSettings(settings) != nil { + if err = port.setTermSettings(settings); err != nil { port.Close() return nil, &PortError{code: InvalidSerialPort, causedBy: fmt.Errorf("error setting term settings: %w", err)} } From fb4b111d503ec814416fa6b4514c8460b2d12b77 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 12 Mar 2025 20:50:56 +0100 Subject: [PATCH 23/34] Hack for CH340 support --- serial_windows.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/serial_windows.go b/serial_windows.go index 5853e51..9ea64b6 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -275,10 +275,19 @@ func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) { } func (port *windowsPort) SetReadTimeout(timeout time.Duration) error { + // This is a brutal hack to make the CH340 chipset work properly. + // Normally this value should be 0xFFFFFFFE but, after a lot of + // tinkering, I discovered that any value with the highest + // bit set will make the CH340 driver behave like the timeout is 0, + // in the best cases leading to a spinning loop... + // (could this be a wrong signed vs unsigned conversion in the driver?) + // https://github.com/arduino/serial-monitor/issues/112 + const MaxReadTotalTimeoutConstant = 0x7FFFFFFE + commTimeouts := &windows.CommTimeouts{ ReadIntervalTimeout: 0xFFFFFFFF, ReadTotalTimeoutMultiplier: 0xFFFFFFFF, - ReadTotalTimeoutConstant: 0xFFFFFFFE, + ReadTotalTimeoutConstant: MaxReadTotalTimeoutConstant, WriteTotalTimeoutConstant: 0, WriteTotalTimeoutMultiplier: 0, } @@ -287,6 +296,11 @@ func (port *windowsPort) SetReadTimeout(timeout time.Duration) error { if ms > 0xFFFFFFFE || ms < 0 { return &PortError{code: InvalidTimeoutValue} } + + if ms > MaxReadTotalTimeoutConstant { + ms = MaxReadTotalTimeoutConstant + } + commTimeouts.ReadTotalTimeoutConstant = uint32(ms) } From 1ff9b6fa9a7c0c0dd0f0dc5c25e2902914704a19 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 12 Mar 2025 20:52:40 +0100 Subject: [PATCH 24/34] If the timeout is set to NoTimeout, make Read wait forever. Otherwise the maximul allowed timeout is 0x7FFFFFFF milliseconds, equivalent to about 24.85 days. This patch will make a transparent repeated read in case this long timeout should ever happen. --- serial_windows.go | 53 ++++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 9ea64b6..37b3b39 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -28,8 +28,9 @@ import ( ) type windowsPort struct { - mu sync.Mutex - handle windows.Handle + mu sync.Mutex + handle windows.Handle + hasTimeout bool } func nativeGetPortsList() ([]string, error) { @@ -72,26 +73,33 @@ func (port *windowsPort) Read(p []byte) (int, error) { } defer windows.CloseHandle(ev.HEvent) - err = windows.ReadFile(port.handle, p, &readed, ev) - if err == windows.ERROR_IO_PENDING { - err = windows.GetOverlappedResult(port.handle, ev, &readed, true) - } - switch err { - case nil: - // operation completed successfully - case windows.ERROR_OPERATION_ABORTED: - // port may have been closed - return int(readed), &PortError{code: PortClosed, causedBy: err} - default: - // error happened - return int(readed), err - } - if readed > 0 { - return int(readed), nil - } + for { + err = windows.ReadFile(port.handle, p, &readed, ev) + if err == windows.ERROR_IO_PENDING { + err = windows.GetOverlappedResult(port.handle, ev, &readed, true) + } + switch err { + case nil: + // operation completed successfully + case windows.ERROR_OPERATION_ABORTED: + // port may have been closed + return int(readed), &PortError{code: PortClosed, causedBy: err} + default: + // error happened + return int(readed), err + } + if readed > 0 { + return int(readed), nil + } - // Timeout - return 0, nil + // Timeout + port.mu.Lock() + hasTimeout := port.hasTimeout + port.mu.Unlock() + if hasTimeout { + return 0, nil + } + } } func (port *windowsPort) Write(p []byte) (int, error) { @@ -304,9 +312,12 @@ func (port *windowsPort) SetReadTimeout(timeout time.Duration) error { commTimeouts.ReadTotalTimeoutConstant = uint32(ms) } + port.mu.Lock() + defer port.mu.Unlock() if err := windows.SetCommTimeouts(port.handle, commTimeouts); err != nil { return &PortError{code: InvalidTimeoutValue, causedBy: err} } + port.hasTimeout = (timeout != NoTimeout) return nil } From 5069d66aa266bdc5aa7cc5d9fed52c4584675d4a Mon Sep 17 00:00:00 2001 From: Stepan Date: Fri, 28 Mar 2025 16:28:13 +0900 Subject: [PATCH 25/34] Windows: fixed port enumeration --- serial_windows.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 37b3b39..445430d 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -45,12 +45,22 @@ func nativeGetPortsList() ([]string, error) { } defer key.Close() - list, err := key.ReadValueNames(0) + names, err := key.ReadValueNames(0) if err != nil { return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} } - return list, nil + var values []string + for _, n := range names { + v, _, err := key.GetStringValue(n) + if err != nil || v == "" { + continue + } + + values = append(values, v) + } + + return values, nil } func (port *windowsPort) Close() error { From bcb04087016ea55190c7895173b02ae204b3928a Mon Sep 17 00:00:00 2001 From: Stepan Date: Fri, 28 Mar 2025 16:42:18 +0900 Subject: [PATCH 26/34] Windows: added a check for \\.\ prefix --- serial_windows.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/serial_windows.go b/serial_windows.go index 445430d..7aa0123 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -19,6 +19,7 @@ package serial import ( "errors" + "strings" "sync" "syscall" "time" @@ -352,7 +353,9 @@ func createOverlappedEvent() (*windows.Overlapped, error) { } func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { - portName = "\\\\.\\" + portName + if !strings.HasPrefix(portName, `\\.\`) { + portName = `\\.\` + portName + } path, err := windows.UTF16PtrFromString(portName) if err != nil { return nil, err From 9710c814f629cf9836385479554d79822a1e1ec2 Mon Sep 17 00:00:00 2001 From: WarningImHack3r <43064022+WarningImHack3r@users.noreply.github.com> Date: Wed, 7 May 2025 20:44:25 +0200 Subject: [PATCH 27/34] fix: incorrect masks for modem status bits on Windows --- serial_windows.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 7aa0123..54d2a89 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -280,16 +280,24 @@ func (port *windowsPort) SetRTS(rts bool) error { return nil } +// GetCommModemStatus constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcommmodemstatus. +const ( + msCTSOn = 0x0010 + msDSROn = 0x0020 + msRingOn = 0x0040 + msRLSDOn = 0x0080 +) + func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) { var bits uint32 if err := windows.GetCommModemStatus(port.handle, &bits); err != nil { return nil, &PortError{} } return &ModemStatusBits{ - CTS: (bits & windows.EV_CTS) != 0, - DCD: (bits & windows.EV_RLSD) != 0, - DSR: (bits & windows.EV_DSR) != 0, - RI: (bits & windows.EV_RING) != 0, + CTS: (bits & msCTSOn) != 0, + DCD: (bits & msRLSDOn) != 0, + DSR: (bits & msDSROn) != 0, + RI: (bits & msRingOn) != 0, }, nil } @@ -366,7 +374,8 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { 0, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED, - 0) + 0, + ) if err != nil { switch err { case windows.ERROR_ACCESS_DENIED: From 20a47944cfa974f7ff695f355056c22e62171c95 Mon Sep 17 00:00:00 2001 From: WarningImHack3r <43064022+WarningImHack3r@users.noreply.github.com> Date: Thu, 8 May 2025 13:17:50 +0200 Subject: [PATCH 28/34] refactor: rename variables to match docs --- serial_windows.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 54d2a89..5c5a2a4 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -282,10 +282,10 @@ func (port *windowsPort) SetRTS(rts bool) error { // GetCommModemStatus constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcommmodemstatus. const ( - msCTSOn = 0x0010 - msDSROn = 0x0020 - msRingOn = 0x0040 - msRLSDOn = 0x0080 + MS_CTS_ON = 0x0010 + MS_DSR_ON = 0x0020 + MS_RING_ON = 0x0040 + MS_RLSD_ON = 0x0080 ) func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) { @@ -294,10 +294,10 @@ func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) { return nil, &PortError{} } return &ModemStatusBits{ - CTS: (bits & msCTSOn) != 0, - DCD: (bits & msRLSDOn) != 0, - DSR: (bits & msDSROn) != 0, - RI: (bits & msRingOn) != 0, + CTS: (bits & MS_CTS_ON) != 0, + DCD: (bits & MS_RLSD_ON) != 0, + DSR: (bits & MS_DSR_ON) != 0, + RI: (bits & MS_RING_ON) != 0, }, nil } From 8f447ebc07eb5bec7d0654c8a44cc6f5ed05d48f Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Mon, 19 May 2025 15:31:36 +0200 Subject: [PATCH 29/34] Make win32 internal constants private. --- serial_windows.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 5c5a2a4..d2800f8 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -280,15 +280,14 @@ func (port *windowsPort) SetRTS(rts bool) error { return nil } -// GetCommModemStatus constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcommmodemstatus. -const ( - MS_CTS_ON = 0x0010 - MS_DSR_ON = 0x0020 - MS_RING_ON = 0x0040 - MS_RLSD_ON = 0x0080 -) - func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) { + // GetCommModemStatus constants. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcommmodemstatus. + const ( + MS_CTS_ON = 0x0010 + MS_DSR_ON = 0x0020 + MS_RING_ON = 0x0040 + MS_RLSD_ON = 0x0080 + ) var bits uint32 if err := windows.GetCommModemStatus(port.handle, &bits); err != nil { return nil, &PortError{} From 4568452e98285b32f3bcb639969c496eaa7996a9 Mon Sep 17 00:00:00 2001 From: aetl-ksanagi Date: Thu, 30 Nov 2023 12:03:32 +0000 Subject: [PATCH 30/34] modify change import path (to refer to self-package --- enumerator/example_getdetailedportlist_test.go | 2 +- enumerator/usb_linux.go | 2 +- example_getportlist_test.go | 2 +- example_modem_bits_test.go | 2 +- example_serialport_test.go | 2 +- example_test.go | 2 +- go.mod | 12 ++++++++++-- go.sum | 7 ------- portlist/portlist.go | 8 ++++---- serial_unix.go | 2 +- 10 files changed, 21 insertions(+), 20 deletions(-) diff --git a/enumerator/example_getdetailedportlist_test.go b/enumerator/example_getdetailedportlist_test.go index 6d3c2db..12df7cb 100644 --- a/enumerator/example_getdetailedportlist_test.go +++ b/enumerator/example_getdetailedportlist_test.go @@ -10,7 +10,7 @@ import ( "fmt" "log" - "go.bug.st/serial/enumerator" + "github.com/aeterlink-dev/go-serial-al/serial/enumerator" ) func ExampleGetDetailedPortsList() { diff --git a/enumerator/usb_linux.go b/enumerator/usb_linux.go index 2e3737e..a120f95 100644 --- a/enumerator/usb_linux.go +++ b/enumerator/usb_linux.go @@ -12,7 +12,7 @@ import ( "os" "path/filepath" - "go.bug.st/serial" + "github.com/aeterlink-dev/go-serial-al/serial" ) func nativeGetDetailedPortsList() ([]*PortDetails, error) { diff --git a/example_getportlist_test.go b/example_getportlist_test.go index a1756ac..a7b9119 100644 --- a/example_getportlist_test.go +++ b/example_getportlist_test.go @@ -10,7 +10,7 @@ import ( "fmt" "log" - "go.bug.st/serial" + "github.com/aeterlink-dev/go-serial-al/serial" ) func ExampleGetPortsList() { diff --git a/example_modem_bits_test.go b/example_modem_bits_test.go index eaad39a..d13bb08 100644 --- a/example_modem_bits_test.go +++ b/example_modem_bits_test.go @@ -11,7 +11,7 @@ import ( "log" "time" - "go.bug.st/serial" + "github.com/aeterlink-dev/go-serial-al/serial" ) func ExamplePort_GetModemStatusBits() { diff --git a/example_serialport_test.go b/example_serialport_test.go index 937b8b9..58143ef 100644 --- a/example_serialport_test.go +++ b/example_serialport_test.go @@ -10,7 +10,7 @@ import ( "fmt" "log" - "go.bug.st/serial" + "github.com/aeterlink-dev/go-serial-al/serial" ) func ExamplePort_SetMode() { diff --git a/example_test.go b/example_test.go index 7ad5eef..6104e9f 100644 --- a/example_test.go +++ b/example_test.go @@ -11,7 +11,7 @@ import ( "log" "strings" - "go.bug.st/serial" + "github.com/aeterlink-dev/go-serial-al/serial" ) // This example prints the list of serial ports and use the first one diff --git a/go.mod b/go.mod index e89755e..1f8a5bc 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,16 @@ -module go.bug.st/serial +module github.com/aeterlink-dev/go-serial-al -go 1.17 +go 1.20 + +replace ( + github.com/aeterlink-dev/go-serial-al/enumrator => ./enumrator + github.com/aeterlink-dev/go-serial-al/portlist => ./portlist + github.com/aeterlink-dev/go-serial-al/serial => ./ + github.com/aeterlink-dev/go-serial-al/unixutils => ./unixutils +) require ( + github.com/aeterlink-dev/go-serial-al/serial v0.0.0-00010101000000-000000000000 github.com/creack/goselect v0.1.2 github.com/stretchr/testify v1.8.4 golang.org/x/sys v0.19.0 diff --git a/go.sum b/go.sum index 4cef3dc..95e5c7f 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,14 @@ github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/portlist/portlist.go b/portlist/portlist.go index 5d58409..db6d39d 100644 --- a/portlist/portlist.go +++ b/portlist/portlist.go @@ -10,16 +10,16 @@ // $ go run portlist.go // Port: /dev/cu.Bluetooth-Incoming-Port // Port: /dev/cu.usbmodemFD121 -// USB ID 2341:8053 -// USB serial FB7B6060504B5952302E314AFF08191A - +// +// USB ID 2341:8053 +// USB serial FB7B6060504B5952302E314AFF08191A package main import ( "fmt" "log" - "go.bug.st/serial/enumerator" + "github.com/aeterlink-dev/go-serial-al/serial/enumerator" ) func main() { diff --git a/serial_unix.go b/serial_unix.go index e6913c2..e3a2bda 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -16,7 +16,7 @@ import ( "sync/atomic" "time" - "go.bug.st/serial/unixutils" + "github.com/aeterlink-dev/go-serial-al/serial/unixutils" "golang.org/x/sys/unix" ) From 86c53fd8c560c54f14ace1d5a464f2314bd21ac6 Mon Sep 17 00:00:00 2001 From: aetl-ksanagi Date: Thu, 30 Nov 2023 12:46:30 +0000 Subject: [PATCH 31/34] modify enable RS485 settings (only linux) refer to https://github.com/bugst/go-serial/pull/79/files --- serial.go | 29 +++++++++++++++++++++++++++++ serial_unix.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ serial_windows.go | 10 ++++++++++ 3 files changed, 85 insertions(+) diff --git a/serial.go b/serial.go index a2f7333..73adf0b 100644 --- a/serial.go +++ b/serial.go @@ -101,6 +101,23 @@ type Mode struct { Parity Parity // Parity (see Parity type for more info) StopBits StopBits // Stop bits (see StopBits type for more info) InitialStatusBits *ModemOutputBits // Initial output modem bits status (if nil defaults to DTR=true and RTS=true) + RS485 RS485Config // RS485 configuration +} + +// RS485Config -- platform independent RS485 config. Thie structure is ignored unless Enable is true. +type RS485Config struct { + // Enable RS485 support + Enabled bool + // Delay RTS prior to send + DelayRtsBeforeSend time.Duration + // Delay RTS after send + DelayRtsAfterSend time.Duration + // Set RTS high during send + RtsHighDuringSend bool + // Set RTS high after send + RtsHighAfterSend bool + // Rx during Tx + RxDuringTx bool } // Parity describes a serial port parity setting @@ -165,6 +182,12 @@ const ( PortClosed // FunctionNotImplemented the requested function is not implemented FunctionNotImplemented + // ReadFailed indicates the read failed + ReadFailed + // ConfigureRS485Error indicates an error configuring RS485 on the platform + ConfigureRS485Error + // NoPlatformSupportForRS485 indicates no platform support for RS485 + NoPlatformSupportForRS485 ) // EncodedErrorString returns a string explaining the error code @@ -194,6 +217,12 @@ func (e PortError) EncodedErrorString() string { return "Port has been closed" case FunctionNotImplemented: return "Function not implemented" + case ReadFailed: + return "Read failed" + case ConfigureRS485Error: + return "Error configuring RS485 on the platform" + case NoPlatformSupportForRS485: + return "Platform does not support RS485" default: return "Other error" } diff --git a/serial_unix.go b/serial_unix.go index e3a2bda..178552d 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -29,6 +29,21 @@ type unixPort struct { opened uint32 } +const ( + rs485Enabled = 1 << 0 + rs485RTSOnSend = 1 << 1 + rs485RTSAfterSend = 1 << 2 + rs485RXDuringTX = 1 << 4 +) + +// rs485_ioctl_opts is used to configure RS485 options in the driver +type rs485IoctlOpts struct { + flags int + delayRtsBeforeSend int + delayRtsAfterSend int + padding [5]int +} + func (port *unixPort) Close() error { if !atomic.CompareAndSwapUint32(&port.opened, 1, 0) { return nil @@ -279,6 +294,12 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { port.acquireExclusiveAccess() + // Enable RS485, if requested + if err = port.enableRS485(&mode.RS485); err != nil { + port.Close() + return nil, err + } + // This pipe is used as a signal to cancel blocking Read pipe := &unixutils.Pipe{} if err := pipe.Open(); err != nil { @@ -465,3 +486,28 @@ func (port *unixPort) acquireExclusiveAccess() error { func (port *unixPort) releaseExclusiveAccess() error { return unix.IoctlSetInt(port.handle, unix.TIOCNXCL, 0) } + +// enableRS485 enables RS485 functionality of driver via an ioctl if the config says so +func (port *unixPort) enableRS485(config *RS485Config) error { + if !config.Enabled { + return nil + } + rs485 := rs485IoctlOpts{ + rs485Enabled, + int(config.DelayRtsBeforeSend / time.Millisecond), + int(config.DelayRtsAfterSend / time.Millisecond), + [5]int{0, 0, 0, 0, 0}, + } + + if config.RtsHighDuringSend { + rs485.flags |= rs485RTSOnSend + } + if config.RtsHighAfterSend { + rs485.flags |= rs485RTSAfterSend + } + if config.RxDuringTx { + rs485.flags |= rs485RXDuringTX + } + + return unix.IoctlSetPointerInt(port.handle, unix.TIOCSRS485, rs485.flags) +} diff --git a/serial_windows.go b/serial_windows.go index d2800f8..7865763 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -433,3 +433,13 @@ func nativeOpen(portName string, mode *Mode) (*windowsPort, error) { } return port, nil } + +// enableRS485 enables RS485 functionality of driver via an ioctl if the config says so +func (port *windowsPort) enableRS485(config *RS485Config) error { + // TODO : set dcbRTSControlToggle is true + if !config.Enabled { + return &PortError{code: NoPlatformSupportForRS485, causedBy: nil} + } + + return nil +} From 1ba2fd89adda18fbac38f7dddc7b3bffab1ee920 Mon Sep 17 00:00:00 2001 From: aetl-ksanagi Date: Fri, 1 Dec 2023 09:39:31 +0000 Subject: [PATCH 32/34] update import path and env files --- enumerator/example_getdetailedportlist_test.go | 2 +- enumerator/usb_linux.go | 2 +- example_getportlist_test.go | 2 +- example_modem_bits_test.go | 2 +- example_serialport_test.go | 2 +- example_test.go | 2 +- go.mod | 10 +--------- portlist/portlist.go | 2 +- serial_unix.go | 2 +- 9 files changed, 9 insertions(+), 17 deletions(-) diff --git a/enumerator/example_getdetailedportlist_test.go b/enumerator/example_getdetailedportlist_test.go index 12df7cb..a051707 100644 --- a/enumerator/example_getdetailedportlist_test.go +++ b/enumerator/example_getdetailedportlist_test.go @@ -10,7 +10,7 @@ import ( "fmt" "log" - "github.com/aeterlink-dev/go-serial-al/serial/enumerator" + "github.com/aeterlink-dev/serial/enumerator" ) func ExampleGetDetailedPortsList() { diff --git a/enumerator/usb_linux.go b/enumerator/usb_linux.go index a120f95..d4aacde 100644 --- a/enumerator/usb_linux.go +++ b/enumerator/usb_linux.go @@ -12,7 +12,7 @@ import ( "os" "path/filepath" - "github.com/aeterlink-dev/go-serial-al/serial" + "github.com/aeterlink-dev/serial" ) func nativeGetDetailedPortsList() ([]*PortDetails, error) { diff --git a/example_getportlist_test.go b/example_getportlist_test.go index a7b9119..ec707d3 100644 --- a/example_getportlist_test.go +++ b/example_getportlist_test.go @@ -10,7 +10,7 @@ import ( "fmt" "log" - "github.com/aeterlink-dev/go-serial-al/serial" + "github.com/aeterlink-dev/serial" ) func ExampleGetPortsList() { diff --git a/example_modem_bits_test.go b/example_modem_bits_test.go index d13bb08..4d43056 100644 --- a/example_modem_bits_test.go +++ b/example_modem_bits_test.go @@ -11,7 +11,7 @@ import ( "log" "time" - "github.com/aeterlink-dev/go-serial-al/serial" + "github.com/aeterlink-dev/serial" ) func ExamplePort_GetModemStatusBits() { diff --git a/example_serialport_test.go b/example_serialport_test.go index 58143ef..0a906e2 100644 --- a/example_serialport_test.go +++ b/example_serialport_test.go @@ -10,7 +10,7 @@ import ( "fmt" "log" - "github.com/aeterlink-dev/go-serial-al/serial" + "github.com/aeterlink-dev/serial" ) func ExamplePort_SetMode() { diff --git a/example_test.go b/example_test.go index 6104e9f..d12a78d 100644 --- a/example_test.go +++ b/example_test.go @@ -11,7 +11,7 @@ import ( "log" "strings" - "github.com/aeterlink-dev/go-serial-al/serial" + "github.com/aeterlink-dev/serial" ) // This example prints the list of serial ports and use the first one diff --git a/go.mod b/go.mod index 1f8a5bc..0e00066 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,8 @@ -module github.com/aeterlink-dev/go-serial-al +module github.com/aeterlink-dev/serial go 1.20 -replace ( - github.com/aeterlink-dev/go-serial-al/enumrator => ./enumrator - github.com/aeterlink-dev/go-serial-al/portlist => ./portlist - github.com/aeterlink-dev/go-serial-al/serial => ./ - github.com/aeterlink-dev/go-serial-al/unixutils => ./unixutils -) - require ( - github.com/aeterlink-dev/go-serial-al/serial v0.0.0-00010101000000-000000000000 github.com/creack/goselect v0.1.2 github.com/stretchr/testify v1.8.4 golang.org/x/sys v0.19.0 diff --git a/portlist/portlist.go b/portlist/portlist.go index db6d39d..dd725aa 100644 --- a/portlist/portlist.go +++ b/portlist/portlist.go @@ -19,7 +19,7 @@ import ( "fmt" "log" - "github.com/aeterlink-dev/go-serial-al/serial/enumerator" + "github.com/aeterlink-dev/serial/enumerator" ) func main() { diff --git a/serial_unix.go b/serial_unix.go index 178552d..6099795 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -16,7 +16,7 @@ import ( "sync/atomic" "time" - "github.com/aeterlink-dev/go-serial-al/serial/unixutils" + "github.com/aeterlink-dev/serial/unixutils" "golang.org/x/sys/unix" ) From 4032581fc4ee2f142b945a689c87f6be489ee391 Mon Sep 17 00:00:00 2001 From: Gaku Yasui Date: Sun, 31 Aug 2025 10:52:21 +0900 Subject: [PATCH 33/34] update go.sum --- go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index 95e5c7f..c88fa99 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 53f15d41aacf73a023d4e244b3ca84044487e3f3 Mon Sep 17 00:00:00 2001 From: Gaku Yasui Date: Sun, 31 Aug 2025 10:54:51 +0900 Subject: [PATCH 34/34] update test.yml --- .github/workflows/test.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index bfacab5..ea791c9 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,7 +10,8 @@ jobs: native-os-build: strategy: matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] + # os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ubuntu-latest] runs-on: ${{ matrix.os }} @@ -51,10 +52,10 @@ jobs: strategy: matrix: go-os-pairs: - - "freebsd amd64" - - "openbsd amd64" - - "openbsd 386" - - "openbsd arm" + # - "freebsd amd64" + # - "openbsd amd64" + # - "openbsd 386" + # - "openbsd arm" - "linux ppc64le" runs-on: "ubuntu-latest"