diff --git a/serial_linux.go b/serial_linux.go index 65420f3..28fc00a 100644 --- a/serial_linux.go +++ b/serial_linux.go @@ -3,7 +3,6 @@ package serial import ( - "fmt" "os" "time" "unsafe" @@ -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 } @@ -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 @@ -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 + /* + Raise DTR (open modem) on open. DTR will be set low + again when the connection is closed due to HUPCL. + This should guarantee a correct "restart" action + on some devices. + */ + dtrFlag := unix.TIOCM_DTR + unix.Syscall( + unix.SYS_IOCTL, + uintptr(fd), + uintptr(unix.TIOCMBIS), // set/raise 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, diff --git a/serial_posix.go b/serial_posix.go index d733f0f..a81e766 100644 --- a/serial_posix.go +++ b/serial_posix.go @@ -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() @@ -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 @@ -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), @@ -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 }