Skip to content

Commit

Permalink
custom baud and dtr reset
Browse files Browse the repository at this point in the history
  • Loading branch information
colinrgodsey committed Jul 20, 2020
1 parent 98f6abe commit acf5782
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 107 deletions.
64 changes: 19 additions & 45 deletions serial_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
package serial

import (
"fmt"
"os"
"time"
"unsafe"
Expand All @@ -12,46 +11,7 @@ import (
)

func openPort(name string, baud int, databits byte, parity Parity, stopbits StopBits, readTimeout time.Duration) (p *Port, err error) {
var bauds = map[int]uint32{
50: unix.B50,
75: unix.B75,
110: unix.B110,
134: unix.B134,
150: unix.B150,
200: unix.B200,
300: unix.B300,
600: unix.B600,
1200: unix.B1200,
1800: unix.B1800,
2400: unix.B2400,
4800: unix.B4800,
9600: unix.B9600,
19200: unix.B19200,
38400: unix.B38400,
57600: unix.B57600,
115200: unix.B115200,
230400: unix.B230400,
460800: unix.B460800,
500000: unix.B500000,
576000: unix.B576000,
921600: unix.B921600,
1000000: unix.B1000000,
1152000: unix.B1152000,
1500000: unix.B1500000,
2000000: unix.B2000000,
2500000: unix.B2500000,
3000000: unix.B3000000,
3500000: unix.B3500000,
4000000: unix.B4000000,
}

rate, ok := bauds[baud]

if !ok {
return nil, fmt.Errorf("Unrecognized baud rate")
}

f, err := os.OpenFile(name, unix.O_RDWR|unix.O_NOCTTY|unix.O_NONBLOCK, 0666)
f, err := os.OpenFile(name, unix.O_RDWR|unix.O_NOCTTY|unix.O_NONBLOCK, 0)
if err != nil {
return nil, err
}
Expand All @@ -63,7 +23,7 @@ func openPort(name string, baud int, databits byte, parity Parity, stopbits Stop
}()

// Base settings
cflagToUse := unix.CREAD | unix.CLOCAL | rate
var cflagToUse uint32 = unix.CREAD | unix.CLOCAL | unix.BOTHER | unix.HUPCL
switch databits {
case 5:
cflagToUse |= unix.CS5
Expand Down Expand Up @@ -100,19 +60,33 @@ func openPort(name string, baud int, databits byte, parity Parity, stopbits Stop
}
fd := f.Fd()
vmin, vtime := posixTimeoutValues(readTimeout)
speed := uint32(baud)
t := unix.Termios{
Iflag: unix.IGNPAR,
Cflag: cflagToUse,
Ispeed: rate,
Ospeed: rate,
Ispeed: speed,
Ospeed: speed,
}
t.Cc[unix.VMIN] = vmin
t.Cc[unix.VTIME] = vtime

// simulate an arduino reset using DTR
dtrFlag := unix.TIOCM_DTR
unix.Syscall(
unix.SYS_IOCTL,
uintptr(fd),
uintptr(unix.TIOCMBIS), // set DTR pin
uintptr(unsafe.Pointer(&dtrFlag)))
unix.Syscall(
unix.SYS_IOCTL,
uintptr(fd),
uintptr(unix.TIOCMBIC), // clear DTR pin
uintptr(unsafe.Pointer(&dtrFlag)))

if _, _, errno := unix.Syscall6(
unix.SYS_IOCTL,
uintptr(fd),
uintptr(unix.TCSETS),
uintptr(unix.TCSETS2),
uintptr(unsafe.Pointer(&t)),
0,
0,
Expand Down
127 changes: 65 additions & 62 deletions serial_posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ import (
"errors"
"fmt"
"os"
"runtime"
"syscall"
"time"
//"unsafe"
"unsafe"
)

func openPort(name string, baud int, databits byte, parity Parity, stopbits StopBits, readTimeout time.Duration) (p *Port, err error) {
f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666)
f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0)
if err != nil {
return
}

fd := C.int(f.Fd())
if C.isatty(fd) != 1 {
f.Close()
Expand All @@ -35,54 +35,57 @@ func openPort(name string, baud int, databits byte, parity Parity, stopbits Stop
f.Close()
return nil, err
}
var speed C.speed_t
switch baud {
case 115200:
speed = C.B115200
case 57600:
speed = C.B57600
case 38400:
speed = C.B38400
case 19200:
speed = C.B19200
case 9600:
speed = C.B9600
case 4800:
speed = C.B4800
case 2400:
speed = C.B2400
case 1200:
speed = C.B1200
case 600:
speed = C.B600
case 300:
speed = C.B300
case 200:
speed = C.B200
case 150:
speed = C.B150
case 134:
speed = C.B134
case 110:
speed = C.B110
case 75:
speed = C.B75
case 50:
speed = C.B50
default:
f.Close()
return nil, fmt.Errorf("Unknown baud rate %v", baud)
}

_, err = C.cfsetispeed(&st, speed)
if err != nil {
f.Close()
return nil, err
}
_, err = C.cfsetospeed(&st, speed)
if err != nil {
f.Close()
return nil, err
if runtime.GOOS != "darwin" {
var speed C.speed_t
switch baud {
case 115200:
speed = C.B115200
case 57600:
speed = C.B57600
case 38400:
speed = C.B38400
case 19200:
speed = C.B19200
case 9600:
speed = C.B9600
case 4800:
speed = C.B4800
case 2400:
speed = C.B2400
case 1200:
speed = C.B1200
case 600:
speed = C.B600
case 300:
speed = C.B300
case 200:
speed = C.B200
case 150:
speed = C.B150
case 134:
speed = C.B134
case 110:
speed = C.B110
case 75:
speed = C.B75
case 50:
speed = C.B50
default:
f.Close()
return nil, fmt.Errorf("Unknown baud rate %v", baud)
}

_, err = C.cfsetispeed(&st, speed)
if err != nil {
f.Close()
return nil, err
}
_, err = C.cfsetospeed(&st, speed)
if err != nil {
f.Close()
return nil, err
}
}

// Turn off break interrupts, CR->NL, Parity checks, strip, and IXON
Expand Down Expand Up @@ -145,7 +148,6 @@ func openPort(name string, baud int, databits byte, parity Parity, stopbits Stop
return nil, err
}

//fmt.Println("Tweaking", name)
r1, _, e := syscall.Syscall(syscall.SYS_FCNTL,
uintptr(f.Fd()),
uintptr(syscall.F_SETFL),
Expand All @@ -156,17 +158,18 @@ func openPort(name string, baud int, databits byte, parity Parity, stopbits Stop
return nil, errors.New(s)
}

/*
r1, _, e = syscall.Syscall(syscall.SYS_IOCTL,
uintptr(f.Fd()),
uintptr(0x80045402), // IOSSIOSPEED
uintptr(unsafe.Pointer(&baud)));
if e != 0 || r1 != 0 {
s := fmt.Sprint("Baudrate syscall error:", e, r1)
f.Close()
return nil, os.NewError(s)
}
*/
if runtime.GOOS == "darwin" {
b := C.speed_t(baud)
r1, _, e = syscall.Syscall(syscall.SYS_IOCTL,
uintptr(f.Fd()),
uintptr(0x80045402), // IOSSIOSPEED
uintptr(unsafe.Pointer(&b)))
if e != 0 || r1 != 0 {
s := fmt.Sprint("Baudrate syscall error:", e, r1)
f.Close()
return nil, errors.New(s)
}
}

return &Port{f: f}, nil
}
Expand Down

0 comments on commit acf5782

Please sign in to comment.