func (c *Connection) open() (err error) { c.file, err = os.OpenFile(c.Name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666) if err != nil { return err } fd, err := c.getFileDescriptor() if err != nil { c.file.Close() return err } var st C.struct_termios _, err = C.tcgetattr(fd, &st) if err != nil { c.file.Close() return err } // set the baud rate of the connection err = c.setBaudRate(c.Baud) if err != nil { c.file.Close() return err } // No timeout set directly on termios st.c_cc[C.VMIN] = 0 st.c_cc[C.VTIME] = 0 // Select local mode st.c_cflag |= (C.CLOCAL | C.CREAD) // Select raw mode st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG) st.c_oflag &= ^C.tcflag_t(C.OPOST) _, err = C.tcsetattr(fd, C.TCSANOW, &st) if err != nil { c.file.Close() return err } r1, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(c.file.Fd()), uintptr(syscall.F_SETFL), uintptr(0)) if e != 0 || r1 != 0 { s := fmt.Sprint("Clearing NONBLOCK syscall error:", e, r1) c.file.Close() return errors.New(s) } return nil }
func makeCAttributes(attr *Attributes) C.struct_termios { var cattr C.struct_termios cattr.c_iflag = C.tcflag_t(attr.Input) cattr.c_oflag = C.tcflag_t(attr.Output) cattr.c_cflag = C.tcflag_t(attr.Control) cattr.c_lflag = C.tcflag_t(attr.Local) for i := 0; i < C.NCCS; i++ { cattr.c_cc[i] = C.cc_t(attr.ControlChars[i]) } return cattr }
func cTermios(goTerm *Termios) *C.struct_termios { var cTerm C.struct_termios cTerm.c_iflag = C.tcflag_t(goTerm.IFlag) cTerm.c_oflag = C.tcflag_t(goTerm.OFlag) cTerm.c_cflag = C.tcflag_t(goTerm.CFlag) cTerm.c_lflag = C.tcflag_t(goTerm.LFlag) for idx, ch := range goTerm.CC { cTerm.c_cc[idx] = C.cc_t(ch) } cTerm.c_ispeed = C.speed_t(goTerm.ISpeed) cTerm.c_ospeed = C.speed_t(goTerm.OSpeed) return &cTerm }
func (s *Serial) SetParity(p string) { if s.Opened { var tios C.struct_termios getTermios(s.f, &tios) switch p { case "n": tios.c_cflag &= C.tcflag_t(^uint16(C.PARENB)) case "o": tios.c_cflag |= C.PARENB | C.PARODD case "e": tios.c_cflag |= C.PARENB tios.c_cflag &= C.tcflag_t(^uint16(C.PARODD)) } setTermios(s.f, &tios) } }
func (s *Serial) SetStops(stops uint8) { if s.Opened { var tios C.struct_termios getTermios(s.f, &tios) if stops == 1 { tios.c_cflag &= C.tcflag_t(^uint16(C.CSTOPB)) } else if stops == 2 { tios.c_cflag |= C.CSTOPB } setTermios(s.f, &tios) } }
func (s *Serial) SetBits(b uint8) { if s.Opened { switch b { case 8: b = C.CS8 case 7: b = C.CS7 case 6: b = C.CS6 case 5: b = C.CS5 default: b = 0 } if b != 0 { var tios C.struct_termios getTermios(s.f, &tios) tios.c_cflag &= C.tcflag_t(^uint16(C.CSIZE)) tios.c_cflag |= C.tcflag_t(b) setTermios(s.f, &tios) } } }
func (s *Serial) Open(name string) bool { if !s.Opened { var err error s.f, err = os.OpenFile(name, os.O_RDWR|syscall.O_NOCTTY|syscall.O_NDELAY|syscall.O_NONBLOCK, 0666) if err == nil { s.Name = name s.Opened = true var tios C.struct_termios getTermios(s.f, &tios) tios.c_cflag |= C.CLOCAL | C.CREAD tios.c_lflag &= C.tcflag_t(^uint16(C.ICANON | C.ECHO | C.ECHOE | C.ECHOK | C.ECHONL | C.ISIG | C.IEXTEN)) tios.c_iflag &= C.tcflag_t(^uint16(C.BRKINT | C.ICRNL | C.INPCK | C.ISTRIP | C.IXON)) tios.c_oflag &= C.tcflag_t(^uint16(C.OPOST)) tios.c_cc[C.VMIN] = 1 tios.c_cc[C.VTIME] = 0 setTermios(s.f, &tios) } } return s.Opened }
// Read a password from the terminal without echoing it. No space is added // after the prompt. // // Don't mistake this function for portable; it probably doesn't work anywhere // except OS X. func ReadPassword(prompt string) string { // Grab the current terminal settings. origTermSettings := getTermSettings() // Set up a function that will restore the terminal settings exactly once. var restoreOnce sync.Once restore := func() { restoreOnce.Do(func() { setTermSettings(origTermSettings) }) } // Make sure that the settings are restored if we return normally. defer restore() // Also make sure the settings are restored if the user hits Ctrl-C while the // password is being read. The signal handler remains running even after // we're done because there is no way to re-enable the default signal // handler. signalChan := make(chan os.Signal) defer close(signalChan) go handleInterrupt(signalChan, restore) signal.Notify(signalChan, os.Interrupt) defer signal.Stop(signalChan) // Disable echoing. newTermSettings := origTermSettings newTermSettings.c_lflag = newTermSettings.c_lflag & ^C.tcflag_t(C.ECHO) setTermSettings(newTermSettings) // Display the prompt. fmt.Fprint(os.Stderr, prompt) // Read from stdin. Add a newline for the user pressing enter. reader := bufio.NewReader(os.Stdin) line, err := reader.ReadString('\n') fmt.Fprintln(os.Stderr, "") if err != nil { log.Fatalln("ReadString:", err) } return line[0 : len(line)-1] }
func openPort(name string, baud int, readTimeout time.Duration) (p *Port, err error) { f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666) if err != nil { return } fd := C.int(f.Fd()) if C.isatty(fd) != 1 { f.Close() return nil, errors.New("File is not a tty") } var st C.struct_termios _, err = C.tcgetattr(fd, &st) if err != nil { 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 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 st.c_iflag &= ^C.tcflag_t(C.BRKINT | C.ICRNL | C.INPCK | C.ISTRIP | C.IXOFF | C.IXON | C.PARMRK) // Select local mode, turn off parity, set to 8 bits st.c_cflag &= ^C.tcflag_t(C.CSIZE | C.PARENB) st.c_cflag |= (C.CLOCAL | C.CREAD | C.CS8) // Select raw mode st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG) st.c_oflag &= ^C.tcflag_t(C.OPOST) // set blocking / non-blocking read /* * http://man7.org/linux/man-pages/man3/termios.3.html * - Supports blocking read and read with timeout operations */ vmin, vtime := posixTimeoutValues(readTimeout) st.c_cc[C.VMIN] = C.cc_t(vmin) st.c_cc[C.VTIME] = C.cc_t(vtime) _, err = C.tcsetattr(fd, C.TCSANOW, &st) if err != nil { f.Close() return nil, err } //fmt.Println("Tweaking", name) r1, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(f.Fd()), uintptr(syscall.F_SETFL), uintptr(0)) if e != 0 || r1 != 0 { s := fmt.Sprint("Clearing NONBLOCK syscall error:", e, r1) f.Close() 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) } */ return &Port{f: f}, nil }
func openPort(name string, baud int) (rwc io.ReadWriteCloser, err error) { f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666) if err != nil { return } fd := C.int(f.Fd()) if C.isatty(fd) != 1 { f.Close() return nil, errors.New("File is not a tty") } var st C.struct_termios _, err = C.tcgetattr(fd, &st) if err != nil { 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 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 } // Select local mode st.c_cflag |= (C.CLOCAL | C.CREAD) // Select raw mode st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG) st.c_oflag &= ^C.tcflag_t(C.OPOST) _, err = C.tcsetattr(fd, C.TCSANOW, &st) if err != nil { f.Close() return nil, err } //fmt.Println("Tweaking", name) r1, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(f.Fd()), uintptr(syscall.F_SETFL), uintptr(0)) if e != 0 || r1 != 0 { s := fmt.Sprint("Clearing NONBLOCK syscall error:", e, r1) f.Close() 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) } */ return f, nil }
func OpenPort(name string, baud int) (rwc io.ReadWriteCloser, err error) { f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666) if err != nil { return } fd := C.int(f.Fd()) if C.isatty(fd) != 1 { f.Close() return nil, fmt.Errorf("[ERROR] not a tty/cu device") } var st C.struct_termios _, err = C.tcgetattr(fd, &st) if err != nil { 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 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 } // Select local mode st.c_cflag |= (C.CLOCAL | C.CREAD) // Select raw mode st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG) st.c_oflag &= ^C.tcflag_t(C.OPOST) _, err = C.tcsetattr(fd, C.TCSANOW, &st) if err != nil { f.Close() return nil, err } r1, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(f.Fd()), uintptr(syscall.F_SETFL), uintptr(0)) if e != 0 || r1 != 0 { s := fmt.Sprint("[WARN] clearing NONBLOCK syscall error:", e, r1) f.Close() return nil, fmt.Errorf("%s", s) } return f, nil }
func (bp *baseport) SetMode(baudrate, databits, parity, stopbits, handshake int) error { if baudrate <= 0 { return &ParameterError{"baudrate", "has to be > 0"} } var datamask uint switch databits { case 5: datamask = C.CS5 case 6: datamask = C.CS6 case 7: datamask = C.CS7 case 8: datamask = C.CS8 default: return &ParameterError{"databits", "has to be 5, 6, 7 or 8"} } if stopbits != 1 && stopbits != 2 { return &ParameterError{"stopbits", "has to be 1 or 2"} } var stopmask uint if stopbits == 2 { stopmask = C.CSTOPB } var parmask uint switch parity { case N: parmask = 0 case E: parmask = C.PARENB case O: parmask = C.PARENB | C.PARODD default: return &ParameterError{"parity", "has to be N, E or O"} } var flowmask uint switch handshake { case NO_HANDSHAKE: flowmask = 0 case RTSCTS_HANDSHAKE: flowmask = C.CRTSCTS default: return &ParameterError{"handshake", "has to be NO_HANDSHAKE or RTSCTS_HANDSHAKE"} } tio, err := bp.getattr() if err != nil { return &Error{"getattr", err} } tio.c_cflag &^= C.CSIZE tio.c_cflag |= C.tcflag_t(datamask) tio.c_cflag &^= C.PARENB | C.PARODD tio.c_cflag |= C.tcflag_t(parmask) tio.c_cflag &^= C.CSTOPB tio.c_cflag |= C.tcflag_t(stopmask) tio.c_cflag &^= C.CRTSCTS tio.c_cflag |= C.tcflag_t(flowmask) if err := bp.setattr(tio); err != nil { return &Error{"setattr", err} } if err := bp.SetBaudRate(baudrate); err != nil { return err } return nil }
VSUSP = uint(C.VSUSP) /* SUSP character */ VMIN = uint(C.VMIN) /* MIN value */ VTIME = uint(C.VTIME) /* TIME value */ NCCS = uint(C.NCCS) /* Size of the array c_cc for control characters */ //VEOL2 = uint (C.VEOL2) not-posix //VWERASE = uint (C.VWERASE) not-posix //VREPRINT = uint (C.VREPRINT); not-posix //VDSUSP = uint (C.VDSUSP); not-posix //VLNEXT = uint (C.VLNEXT); not-posix //VDISCARD = uint (C.VDISCARD); not-posix //VSTATUS = uint (C.VSTATUS); not-posix ) // Input modes - software input processing const ( BRKINT = C.tcflag_t(C.BRKINT) /* map BREAK to SIGINTR */ ICRNL = C.tcflag_t(C.ICRNL) /* map CR to NL (ala CRMOD) */ IGNBRK = C.tcflag_t(C.IGNBRK) /* ignore BREAK condition */ IGNCR = C.tcflag_t(C.IGNCR) /* ignore CR */ IGNPAR = C.tcflag_t(C.IGNPAR) /* ignore (discard) parity errors */ INLCR = C.tcflag_t(C.INLCR) /* map NL into CR */ INPCK = C.tcflag_t(C.INPCK) /* enable checking of parity errors */ ISTRIP = C.tcflag_t(C.ISTRIP) /* strip 8th bit off chars */ IXANY = C.tcflag_t(C.IXANY) /* any char will restart after stop */ IXOFF = C.tcflag_t(C.IXOFF) /* enable input flow control */ IXON = C.tcflag_t(C.IXON) /* enable output flow control */ PARMRK = C.tcflag_t(C.PARMRK) /* mark parity and framing errors */ //IMAXBEL = C.tcflag_t(C.IMAXBEL) /* ring bell on input queue full */ //IUTF8 = C.tcflag_t(C.IUTF8) /* maintain state for UTF-8 VERASE */ )
func openPort(name string, baud int) (rwc io.ReadWriteCloser, err error) { f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY, 0666) if err != nil { return } fd := C.int(f.Fd()) if C.isatty(fd) != 1 { f.Close() return nil, errors.New("File is not a tty") } var st C.struct_termios _, err = C.tcgetattr(fd, &st) if err != nil { 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 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 } // Select local mode st.c_cflag |= (C.CLOCAL | C.CREAD) // Select raw mode st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG) st.c_oflag &= ^C.tcflag_t(C.OPOST) _, err = C.tcsetattr(fd, C.TCSANOW, &st) if err != nil { f.Close() return nil, err } return f, nil }
func openPort(name string, baud int, spec []byte, flow []bool) (rwc io.ReadWriteCloser, err error) { port := new(serialPort) f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666) if err != nil { return } fd := C.int(f.Fd()) if C.isatty(fd) != 1 { f.Close() return nil, errors.New("File is not a tty") } var st C.struct_termios _, err = C.tcgetattr(fd, &st) if err != nil { 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 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 } // Select local mode st.c_cflag |= (C.CLOCAL | C.CREAD) // Select raw mode st.c_lflag &= ^C.tcflag_t(C.ICANON | C.ECHO | C.ECHOE | C.ISIG) st.c_oflag &= ^C.tcflag_t(C.OPOST) // Flow control if flow[RTS_FLAG] { st.c_cflag |= C.tcflag_t(C.CRTSCTS) } if flow[XON_FLAG] { st.c_cflag |= C.tcflag_t(C.IXON | C.IXOFF | C.IXANY) } // Defaults to 8N1 if nothing valid is given byteSize := spec[0] parity := spec[1] stopBits := spec[2] switch byteSize { case byte(5): st.c_cflag |= C.tcflag_t(C.CS5) break case byte(6): st.c_cflag |= C.tcflag_t(C.CS6) break case byte(7): st.c_cflag |= C.tcflag_t(C.CS7) break case byte(8): default: st.c_cflag |= C.tcflag_t(C.CS8) break } switch parity { case PARITY_EVEN: st.c_cflag |= C.tcflag_t(C.PARENB) st.c_cflag &= ^C.tcflag_t(C.PARODD) break case PARITY_ODD: st.c_cflag |= C.tcflag_t(C.PARENB) st.c_cflag |= C.tcflag_t(C.PARODD) break case PARITY_NONE: default: st.c_cflag &= ^C.tcflag_t(C.PARENB) break } switch stopBits { case byte(2): st.c_cflag |= C.tcflag_t(C.CSTOPB) break case byte(1): default: st.c_cflag &= ^C.tcflag_t(C.CSTOPB) break } st.c_cflag &= ^C.tcflag_t(C.CSIZE) _, err = C.tcsetattr(fd, C.TCSANOW, &st) if err != nil { f.Close() return nil, err } //fmt.Println("Tweaking", name) r1, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(f.Fd()), uintptr(syscall.F_SETFL), uintptr(0)) if e != 0 || r1 != 0 { s := fmt.Sprint("Clearing NONBLOCK syscall error:", e, r1) f.Close() 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) } */ port.f = f return port, nil }