MacOS Open() Fails Occasionally w/ Non-Standard Baud Rate
Describe the problem
Opening a serial port with non-standard baud rate 25000 fails occasionally. The failure occurs in nativeOpen() https://github.com/bugst/go-serial/blob/f12391c01f39791f85712bad01e6781276ff0f64/serial_unix.go#L232-L247 due to tcsetattr() rejecting non-standard baudrates.
Scenario: Sometimes, getTermSettings() populates with a non-standard baud rate. Once the settings struct is populated with a non-standard baud rate, setTermSettings() and thus nativeOpen() will fail with EINVAL. This appears to be a MacOS specific behavior for tcsetattr rejecting non-standard baud rates (see related tcsetattr() issue in avrdude)
Note that a workaround for non-standard baud rate, setSpecialBaudRate(), is already called out in SetMode(), but it does not apply properly when getTermSettings (tcgetattr()) populates with a non-standard baud rate: https://github.com/bugst/go-serial/blob/f12391c01f39791f85712bad01e6781276ff0f64/serial_unix.go#L271-L276
This problem also applies to subsequent calls to SetMode w/ non-standard baud rate on a port that was Open()'d successfully. Please see the example code that I attached to reproduce this issue.
Possible Solution: We could replace the Ispeed and Ospeed fields with a standard baud rate before calling setTermSettings() if they are non-standard, then allow the setSpecialBaudRate() to set the non-standard baud rates.
To reproduce
package main
import (
"fmt"
"go.bug.st/serial"
)
func t1() error {
// setting non-standard baud-rate a second time fails on MacOS
// baud rate was set first in serial.Open()
// baud rate attempted to set again in SetMode()
Port := "/dev/tty.usbserial-DK0FPOX4"
port, err := serial.Open(Port, &serial.Mode{BaudRate: 250000})
if err != nil {
fmt.Println("Open() failed", err.Error())
return err
}
defer port.Close()
err = port.SetMode(&serial.Mode{BaudRate: 250000})
if err != nil {
fmt.Println("SetMode() failed", err.Error())
return err
}
fmt.Println("no error")
return nil
}
func t2() error {
// setting non-standard baud-rate works once on MacOS
// baud rate was set first in serial.Open()
// baud rate attempted to set again in SetMode()
Port := "/dev/tty.usbserial-DK0FPOX4"
port, err := serial.Open(Port, &serial.Mode{BaudRate: 9600})
if err != nil {
fmt.Println("Open() failed", err.Error())
return err
}
defer port.Close()
err = port.SetMode(&serial.Mode{BaudRate: 250000})
if err != nil {
fmt.Println("SetMode() failed", err.Error())
return err
}
fmt.Println("no error")
return nil
}
func main() {
fmt.Println("t1():")
t1()
fmt.Println("t2():")
t2()
}
t1():
SetMode() failed invalid argument
t2():
no error
Please double-check that you have reported each of the following
before submitting the issue.
- [x] I've provided the FULL source code that causes the problem
- [x] I've provided all the actions required to reproduce the problem
Expected behavior
Serial port should Open, and the workaround for MacOS non-standard baud rates should apply even when the port already has a non-standard baudrate.
Operating system and version
MacOS: Sequoia 15.5
Please describe your hardware setup
No response
Additional context
No response
Issue checklist
- [x] I searched for previous requests in the issue tracker
- [x] My request contains all necessary details