diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..b544840 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,78 @@ +# 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: textarea + id: boards + attributes: + label: Please describe your hardware setup + description: | + Arduino boards, USB dongles, hubs or embedded devices you are using and how they + are connected together. + - 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 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7a43621..ea791c9 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,18 +10,28 @@ 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 }} steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 with: - go-version: "1.17" - - name: Build native + go-version: "1.22" + - 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 @@ -42,19 +52,19 @@ 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" 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 }} 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/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 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 77919bf..a051707 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 981dd6e..d4aacde 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_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/usb_windows.go b/enumerator/usb_windows.go index 7883e45..2d3793b 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. // @@ -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/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/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/example_getportlist_test.go b/example_getportlist_test.go index 1d58cd7..ec707d3 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 e7f81da..4d43056 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. // @@ -14,7 +14,7 @@ import ( "github.com/aeterlink-dev/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 69b1783..0a906e2 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. // @@ -13,7 +13,7 @@ import ( "github.com/aeterlink-dev/serial" ) -func ExampleSerialPort_SetMode() { +func ExamplePort_SetMode() { port, err := serial.Open("/dev/ttyACM0", &serial.Mode{}) if err != nil { log.Fatal(err) diff --git a/example_test.go b/example_test.go index 45f87d0..d12a78d 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 53640ce..dd725aa 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 61a7889..73adf0b 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. // @@ -164,7 +164,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_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 2817041..a87458e 100644 --- a/serial_darwin.go +++ b/serial_darwin.go @@ -1,15 +1,20 @@ // -// 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. // package serial -import "golang.org/x/sys/unix" +import ( + "regexp" + + "golang.org/x/sys/unix" +) const devFolder = "/dev" -const regexFilter = "^(cu|tty)\\..*" + +var osPortFilter = regexp.MustCompile("^(cu|tty)\\..*") const ioctlTcgetattr = unix.TIOCGETA const ioctlTcsetattr = unix.TIOCSETA 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 aceb08a..775b7a6 100644 --- a/serial_freebsd.go +++ b/serial_freebsd.go @@ -1,15 +1,20 @@ // -// 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. // package serial -import "golang.org/x/sys/unix" +import ( + "regexp" + + "golang.org/x/sys/unix" +) const devFolder = "/dev" -const regexFilter = "^(cu|tty)\\..*" + +var osPortFilter = regexp.MustCompile("^(cu|tty)\\..*") // termios manipulation functions diff --git a/serial_linux.go b/serial_linux.go index fe114d9..a1218bb 100644 --- a/serial_linux.go +++ b/serial_linux.go @@ -1,15 +1,20 @@ // -// 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. // 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_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 644dc92..ad5efd0 100644 --- a/serial_openbsd.go +++ b/serial_openbsd.go @@ -1,15 +1,20 @@ // -// 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. // package serial -import "golang.org/x/sys/unix" +import ( + "regexp" + + "golang.org/x/sys/unix" +) const devFolder = "/dev" -const regexFilter = "^(cu|tty)\\..*" + +var osPortFilter = regexp.MustCompile("^(cu|tty)\\..*") // termios manipulation functions 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 a6732e5..626762f 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. // @@ -9,8 +9,8 @@ package serial import ( - "io/ioutil" - "regexp" + "fmt" + "os" "strings" "sync" "sync/atomic" @@ -248,7 +248,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 @@ -257,15 +257,16 @@ 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} + 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 { - return nil, &PortError{code: InvalidSerialPort, causedBy: err} + port.Close() + return nil, &PortError{code: InvalidSerialPort, causedBy: fmt.Errorf("error getting modem bits status: %w", err)} } if mode.InitialStatusBits.DTR { status |= unix.TIOCM_DTR @@ -278,15 +279,16 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) { status &^= unix.TIOCM_RTS } if err := port.setModemBitsStatus(status); err != nil { - return nil, &PortError{code: InvalidSerialPort, causedBy: err} + port.Close() + 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) @@ -303,7 +305,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 @@ -311,16 +313,12 @@ 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 } 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() { @@ -328,7 +326,7 @@ func nativeGetPortsList() ([]string, error) { } // Keep only devices with the correct name - if !regex.MatchString(f.Name()) { + if !osPortFilter.MatchString(f.Name()) { continue } 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") +} diff --git a/serial_windows.go b/serial_windows.go index 3cd6b21..7865763 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. // @@ -18,48 +18,50 @@ package serial */ import ( + "errors" + "strings" "sync" "syscall" "time" + + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" ) type windowsPort struct { - mu sync.Mutex - handle syscall.Handle + mu sync.Mutex + handle windows.Handle + hasTimeout bool } 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) + 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() + + names, err := key.ReadValueNames(0) if err != nil { - return nil, &PortError{code: ErrorEnumeratingPorts} + return nil, &PortError{code: ErrorEnumeratingPorts, causedBy: err} } - 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 + var values []string + for _, n := range names { + v, _, err := key.GetStringValue(n) + if err != nil || v == "" { + continue } - return nil, &PortError{code: ErrorEnumeratingPorts} - } - defer syscall.RegCloseKey(h) - var valuesCount uint32 - if syscall.RegQueryInfoKey(h, nil, nil, nil, nil, nil, nil, &valuesCount, nil, nil, nil, nil) != nil { - return nil, &PortError{code: ErrorEnumeratingPorts} + values = append(values, v) } - 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 + return values, nil } func (port *windowsPort) Close() error { @@ -71,7 +73,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,28 +82,35 @@ 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) - } - switch err { - case nil: - // operation completed successfully - case syscall.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) { @@ -110,32 +119,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 ( @@ -152,110 +154,44 @@ const ( dcbInX = 0x00000200 dcbErrorChar = 0x00000400 dcbNull = 0x00000800 - dcbRTSControlDisbaleMask = ^uint32(0x00003000) + dcbRTSControlDisableMask = ^uint32(0x00003000) dcbRTSControlEnable = 0x00001000 dcbRTSControlHandshake = 0x00002000 dcbRTSControlToggle = 0x00003000 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 windows.SetCommState(port.handle, ¶ms) != nil { + port.Close() + return &PortError{code: InvalidSerialPort} + } + return nil +} + +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) } @@ -266,30 +202,25 @@ 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 { - // 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 (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 /* - 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 @@ -297,15 +228,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} } @@ -321,13 +252,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 @@ -335,38 +266,54 @@ 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 &= dcbRTSControlDisbaleMask + 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 } 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 !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 & MS_CTS_ON) != 0, + DCD: (bits & MS_RLSD_ON) != 0, + DSR: (bits & MS_DSR_ON) != 0, + RI: (bits & MS_RING_ON) != 0, }, nil } func (port *windowsPort) SetReadTimeout(timeout time.Duration) error { - commTimeouts := &commTimeouts{ + // 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, } @@ -375,53 +322,64 @@ 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) } - if err := setCommTimeouts(port.handle, commTimeouts); err != nil { + 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 } 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) + if !strings.HasPrefix(portName, `\\.\`) { + portName = `\\.\` + 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, - 0) + 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 @@ -432,27 +390,23 @@ 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 { + params := &windows.DCB{} + if windows.GetCommState(port.handle, params) != nil { port.Close() return nil, &PortError{code: InvalidSerialPort} } + port.setModeParams(mode, params) params.Flags &= dcbDTRControlDisableMask - params.Flags &= dcbRTSControlDisbaleMask + 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 +422,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 c814528..0000000 --- a/syscall_windows.go +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright 2014-2023 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/unixutils/pipe.go b/unixutils/pipe.go index 748de34..f54c916 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. // @@ -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") 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. // 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 -}