Merge pull request #111 from cmaglie/custom-baudrate

Allow to set non-standard baud rates
This commit is contained in:
Cristian Maglie
2021-07-01 13:06:55 +02:00
committed by GitHub
5 changed files with 113 additions and 25 deletions

View File

@@ -14,3 +14,18 @@ const regexFilter = "^(cu|tty)\\..*"
const ioctlTcgetattr = unix.TIOCGETA
const ioctlTcsetattr = unix.TIOCSETA
const ioctlTcflsh = unix.TIOCFLUSH
func setTermSettingsBaudrate(speed int, settings *unix.Termios) (error, bool) {
baudrate, ok := baudrateMap[speed]
if !ok {
return nil, true
}
settings.Ispeed = toTermiosSpeedType(baudrate)
settings.Ospeed = toTermiosSpeedType(baudrate)
return nil, false
}
func (port *unixPort) setSpecialBaudrate(speed uint32) error {
const kIOSSIOSPEED = 0x80045402
return unix.IoctlSetPointerInt(port.handle, kIOSSIOSPEED, int(speed))
}

View File

@@ -60,3 +60,26 @@ const ioctlTcflsh = unix.TIOCFLUSH
func toTermiosSpeedType(speed uint32) uint32 {
return speed
}
func setTermSettingsBaudrate(speed int, settings *unix.Termios) (error, bool) {
baudrate, ok := baudrateMap[speed]
if !ok {
return nil, true
}
// XXX: Is Cflag really needed
// revert old baudrate
for _, rate := range baudrateMap {
settings.Cflag &^= rate
}
// set new baudrate
settings.Cflag |= baudrate
settings.Ispeed = toTermiosSpeedType(baudrate)
settings.Ospeed = toTermiosSpeedType(baudrate)
return nil, false
}
func (port *unixPort) setSpecialBaudrate(speed uint32) error {
// TODO: unimplemented
return &PortError{code: InvalidSpeed}
}

View File

@@ -67,3 +67,31 @@ const ioctlTcflsh = unix.TCFLSH
func toTermiosSpeedType(speed uint32) uint32 {
return speed
}
func setTermSettingsBaudrate(speed int, settings *unix.Termios) (error, bool) {
baudrate, ok := baudrateMap[speed]
if !ok {
return nil, true
}
// revert old baudrate
for _, rate := range baudrateMap {
settings.Cflag &^= rate
}
// set new baudrate
settings.Cflag |= baudrate
settings.Ispeed = toTermiosSpeedType(baudrate)
settings.Ospeed = toTermiosSpeedType(baudrate)
return nil, false
}
func (port *unixPort) setSpecialBaudrate(speed uint32) error {
settings, err := unix.IoctlGetTermios(port.handle, unix.TCGETS2)
if err != nil {
return err
}
settings.Cflag &^= unix.CBAUD
settings.Cflag |= unix.BOTHER
settings.Ispeed = speed
settings.Ospeed = speed
return unix.IoctlSetTermios(port.handle, unix.TCSETS2, settings)
}

View File

@@ -60,3 +60,26 @@ const ioctlTcflsh = unix.TIOCFLUSH
func toTermiosSpeedType(speed uint32) int32 {
return int32(speed)
}
func setTermSettingsBaudrate(speed int, settings *unix.Termios) (error, bool) {
baudrate, ok := baudrateMap[speed]
if !ok {
return nil, true
}
// XXX: Is Cflag really needed
// revert old baudrate
for _, rate := range baudrateMap {
settings.Cflag &^= rate
}
// set new baudrate
settings.Cflag |= baudrate
settings.Ispeed = toTermiosSpeedType(baudrate)
settings.Ospeed = toTermiosSpeedType(baudrate)
return nil, false
}
func (port *unixPort) setSpecialBaudrate(speed uint32) error {
// TODO: unimplemented
return &PortError{code: InvalidSpeed}
}

View File

@@ -126,9 +126,6 @@ func (port *unixPort) SetMode(mode *Mode) error {
if err != nil {
return err
}
if err := setTermSettingsBaudrate(mode.BaudRate, settings); err != nil {
return err
}
if err := setTermSettingsParity(mode.Parity, settings); err != nil {
return err
}
@@ -138,7 +135,23 @@ func (port *unixPort) SetMode(mode *Mode) error {
if err := setTermSettingsStopBits(mode.StopBits, settings); err != nil {
return err
}
return port.setTermSettings(settings)
requireSpecialBaudrate := false
if err, special := setTermSettingsBaudrate(mode.BaudRate, settings); err != nil {
return err
} else if special {
requireSpecialBaudrate = true
}
if err := port.setTermSettings(settings); err != nil {
return err
}
if requireSpecialBaudrate {
// MacOSX require this one to be the last operation otherwise an
// 'Invalid serial port' error is produced.
if err := port.setSpecialBaudrate(uint32(mode.BaudRate)); err != nil {
return err
}
}
return nil
}
func (port *unixPort) SetDTR(dtr bool) error {
@@ -206,11 +219,6 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) {
}
// Setup serial port
if port.SetMode(mode) != nil {
port.Close()
return nil, &PortError{code: InvalidSerialPort}
}
settings, err := port.getTermSettings()
if err != nil {
port.Close()
@@ -228,6 +236,13 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) {
return nil, &PortError{code: InvalidSerialPort}
}
// 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 {
port.Close()
return nil, &PortError{code: InvalidSerialPort}
}
unix.SetNonblock(h, false)
port.acquireExclusiveAccess()
@@ -289,22 +304,6 @@ func nativeGetPortsList() ([]string, error) {
// termios manipulation functions
func setTermSettingsBaudrate(speed int, settings *unix.Termios) error {
baudrate, ok := baudrateMap[speed]
if !ok {
return &PortError{code: InvalidSpeed}
}
// revert old baudrate
for _, rate := range baudrateMap {
settings.Cflag &^= rate
}
// set new baudrate
settings.Cflag |= baudrate
settings.Ispeed = toTermiosSpeedType(baudrate)
settings.Ospeed = toTermiosSpeedType(baudrate)
return nil
}
func setTermSettingsParity(parity Parity, settings *unix.Termios) error {
switch parity {
case NoParity: