func (t *tScreen) termioInit() error { var e error var rv C.int var newtios C.struct_termios var fd C.int if t.in, e = os.OpenFile("/dev/tty", os.O_RDONLY, 0); e != nil { goto failed } if t.out, e = os.OpenFile("/dev/tty", os.O_WRONLY, 0); e != nil { goto failed } t.tiosp = &termiosPrivate{} fd = C.int(t.out.Fd()) if rv, e = C.tcgetattr(fd, &t.tiosp.tios); rv != 0 { goto failed } t.baud = int(C.getbaud(&t.tiosp.tios)) newtios = t.tiosp.tios newtios.c_iflag &^= C.IGNBRK | C.BRKINT | C.PARMRK | C.ISTRIP | C.INLCR | C.IGNCR | C.ICRNL | C.IXON newtios.c_oflag &^= C.OPOST newtios.c_lflag &^= C.ECHO | C.ECHONL | C.ICANON | C.ISIG | C.IEXTEN newtios.c_cflag &^= C.CSIZE | C.PARENB newtios.c_cflag |= C.CS8 // We wake up at the earliest of 100 msec or when data is received. // We need to wake up frequently to permit us to exit cleanly and // close file descriptors on systems like Darwin, where close does // cause a wakeup. (Probably we could reasonably increase this to // something like 1 sec or 500 msec.) newtios.c_cc[C.VMIN] = 0 newtios.c_cc[C.VTIME] = 1 if rv, e = C.tcsetattr(fd, C.TCSANOW|C.TCSAFLUSH, &newtios); rv != 0 { goto failed } signal.Notify(t.sigwinch, syscall.SIGWINCH) if w, h, e := t.getWinSize(); e == nil && w != 0 && h != 0 { t.w = w t.h = h } return nil failed: if t.in != nil { t.in.Close() } if t.out != nil { t.out.Close() } return e }
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) 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 }
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, c *Config) (rwc io.ReadWriteCloser, err error) { f, err := os.OpenFile(name, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666) if err != nil { return } defer func() { if err != nil { f.Close() } }() fd := C.int(f.Fd()) if C.isatty(fd) != 1 { return nil, errors.New("File is not a tty") } var st C.struct_termios _, err = C.tcgetattr(fd, &st) if err != nil { return nil, err } var speed C.speed_t switch c.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: return nil, fmt.Errorf("Unknown baud rate %v", c.Baud) } _, err = C.cfsetispeed(&st, speed) if err != nil { return nil, err } _, err = C.cfsetospeed(&st, speed) if err != nil { return nil, err } // Select local mode st.c_cflag |= C.CLOCAL | C.CREAD // Select stop bits switch c.StopBits { case StopBits1: st.c_cflag &^= C.CSTOPB case StopBits2: st.c_cflag |= C.CSTOPB default: panic(c.StopBits) } // Select character size st.c_cflag &^= C.CSIZE switch c.Size { case Byte5: st.c_cflag |= C.CS5 case Byte6: st.c_cflag |= C.CS6 case Byte7: st.c_cflag |= C.CS7 case Byte8: st.c_cflag |= C.CS8 default: panic(c.Size) } // Select parity mode switch c.Parity { case ParityNone: st.c_cflag &^= C.PARENB case ParityEven: st.c_cflag |= C.PARENB st.c_cflag &^= C.PARODD case ParityOdd: st.c_cflag |= C.PARENB st.c_cflag |= C.PARODD default: panic(c.Parity) } // Select CRLF translation if c.CRLFTranslate { st.c_iflag |= C.ICRNL } else { st.c_iflag &^= C.ICRNL } // Select raw mode st.c_lflag &^= C.ICANON | C.ECHO | C.ECHOE | C.ISIG st.c_oflag &^= C.OPOST _, err = C.tcsetattr(fd, C.TCSANOW, &st) if err != nil { 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) 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) return nil, os.NewError(s) } */ return f, nil }