func ReadPassphrase() string { stdin := C.int(os.Stdin.Fd()) C.tcgetattr(stdin, &C.AttrOld) C.Attr = C.AttrOld C.Attr.c_lflag = C.Attr.c_lflag&^C.ECHO | C.ECHONL C.tcsetattr(stdin, C.TCSANOW, &C.Attr) defer C.tcsetattr(stdin, C.TCSANOW, &C.AttrOld) reader := bufio.NewReader(os.Stdin) line, err := reader.ReadString('\n') if err != nil { return "" } return strings.TrimSpace(line) }
func tcset(fd uintptr, p *Termios) syscall.Errno { ret, err := C.tcsetattr(C.int(fd), C.TCSANOW, (*C.struct_termios)(unsafe.Pointer(p))) if ret != 0 { return err.(syscall.Errno) } return 0 }
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 Restore(fd int, state *State) error { ret, err := C.tcsetattr(C.int(fd), C.TCSANOW, (*C.struct_termios)(unsafe.Pointer(&state.Termios))) if ret != 0 { return err.(syscall.Errno) } return nil }
func (bp *baseport) setattr(tio *C.struct_termios) error { res, err := C.tcsetattr(C.int(bp.f.Fd()), C.TCSANOW, (*C.struct_termios)(unsafe.Pointer(tio))) if res != 0 || err != nil { return err } return nil }
// Sets terminal state. // // int tcsetattr(int fd, int optional_actions, const struct termios *termios_p); func (tc *termios) tcsetattr(optional_actions int) error { exitCode, errno := C.tcsetattr(C.int(tc.fd), C.int(optional_actions), tc.wrap) if exitCode == 0 { return nil } return errno }
// Setattr sets the parameters associated with the terminal // from the Termios structure referenced by src. The optional_actions // field is created by or'ing the desired tcsetattr commands. func Setattr(fd uintptr, optional_action int, src *Termios) error { src.i.c_iflag = src.C_iflag src.i.c_oflag = src.C_oflag src.i.c_cflag = src.C_cflag src.i.c_lflag = src.C_lflag src.i.c_cc = src.C_cc _, rv := C.tcsetattr(C.int(fd), C.int(optional_action), &src.i) return rv }
func stdin_read_password() string { stdin := C.int(os.Stdin.Fd()) C.tcgetattr(stdin, &C.T) C.T_orig = C.T C.T.c_lflag &^= C.ECHO C.T.c_lflag |= C.ECHONL C.tcsetattr(stdin, C.TCSANOW, &C.T) var passwd string fmt.Scanf("%s", &passwd) C.tcsetattr(stdin, C.TCSANOW, &C.T_orig) return passwd }
// Sets a terminal's attributes. Akin to tcsetattr(). func (t *Terminal) SetAttributes(attr *Attributes, options int) os.Error { cattr := makeCAttributes(attr) result := C.tcsetattr(C.int(t.Fd()), C.int(options), &cattr) if result < 0 { return os.NewError("Unable to set terminal attributes.") } return nil }
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 }
// SetFd configures the terminal corresponding to the file-descriptor // fd using the attributes in the Termios structure t. Argument act // must be one of the constants TCSANOW, TCSADRAIN, TCSAFLUSH. See // tcsetattr(3) for more. If the system call is interrupted by a // signal, SetFd retries it automatically. func (t *Termios) SetFd(fd int, act int) error { for { r, err := C.tcsetattr(C.int(fd), C.int(act), &t.t) if r < 0 { if err == syscall.EINTR { continue } return err } return nil } }
func (t *tScreen) termioFini() { signal.Stop(t.sigwinch) <-t.indoneq if t.out != nil { fd := C.int(t.out.Fd()) C.tcsetattr(fd, C.TCSANOW|C.TCSAFLUSH, &t.tiosp.tios) t.out.Close() } if t.in != nil { t.in.Close() } }
// SetInputAttr sets VMIN and VTIME for control serial reads. // // In non-canonical input processing mode, input is not assembled into // lines and input processing (erase, kill, delete, etc.) does not // occur. Two parameters control the behavior of this mode: // c_cc[VTIME] sets the character timer, and c_cc[VMIN] sets the // minimum number of characters to receive before satisfying the read. // // If MIN > 0 and TIME = 0, MIN sets the number of characters to //receive before the read is satisfied. As TIME is zero, the timer is //not used. // // If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read //will be satisfied if a single character is read, or TIME is exceeded //(t = TIME *0.1 s). If TIME is exceeded, no character will be //returned. // // If MIN > 0 and TIME > 0, TIME serves as an inter-character //timer. The read will be satisfied if MIN characters are received, or //the time between two characters exceeds TIME. The timer is restarted //every time a character is received and only becomes active after the //first character has been received. // // If MIN = 0 and TIME = 0, read will be satisfied immediately. The //number of characters currently available, or the number of //characters requested will be returned. According to Antonino (see //contributions), you could issue a fcntl(fd, F_SETFL, FNDELAY); //before reading to get the same result. // // By modifying newtio.c_cc[VTIME] and newtio.c_cc[VMIN] all modes //described above can be tested. // // -- copied from http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html func (port *SerialPort) SetInputAttr(minBytes int, timeout time.Duration) error { fd := port.port.Fd() var options C.struct_termios if C.tcgetattr(C.int(fd), &options) < 0 { return fmt.Errorf("tcgetattr failed") } options.c_cc[C.VMIN] = _Ctype_cc_t(minBytes) options.c_cc[C.VTIME] = _Ctype_cc_t(timeout / (time.Second / 10)) if C.tcsetattr(C.int(fd), C.TCSANOW, &options) < 0 { return fmt.Errorf("tcsetattr failed") } return nil }
func SerialChannels(name string, baud int, debug bool) (chan byte, chan byte, chan bool, chan bool, error) { var err error var serFile *os.File var chFromSerial, chToSerial chan byte var chDTRSerial, chQuitSerial chan bool serFile, err = os.OpenFile(name, os.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0666) if err == nil { fd := C.int(serFile.Fd()) var st C.struct_termios _, err = C.tcgetattr(fd, &st) if err == nil { if C.isatty(fd) != 1 { err = errors.New("Not a tty") } } var speed C.speed_t if err == nil { switch baud { case 230400: speed = C.B230400 case 115200: speed = C.B115200 case 57600: speed = C.B57600 case 19200: speed = C.B19200 case 9600: speed = C.B9600 default: err = errors.New("Invalid baud rate") } } if err == nil { _, err = C.cfsetispeed(&st, speed) if err == nil { _, err = C.cfsetospeed(&st, speed) } } if err == nil { C.cfmakeraw(&st) _, err = C.tcsetattr(fd, C.TCSANOW, &st) } if err == nil { chFromSerial = make(chan byte, 8192) chQuitFrom := make(chan bool) go func() { datain := make([]byte, 1) for q := false; q == false; { count, _ := serFile.Read(datain) for i := 0; i < count; i++ { if debug { if datain[i] == byte(0x0D) { fmt.Print("(\n)") } else { fmt.Printf("(%02X)", datain[i]) } } chFromSerial <- datain[i] } select { case q = <-chQuitFrom: default: } time.Sleep(10) } }() chToSerial = make(chan byte, 8192) chQuitTo := make(chan bool) go func() { dataout := make([]byte, 1) for q := false; q == false; { dataout[0] = <-chToSerial if debug { if dataout[0] == byte(0x0D) { fmt.Print("[\n]") } else { fmt.Printf("[%c]", dataout[0]) } } scount, serr := serFile.Write(dataout) if scount != 1 || serr != nil { fmt.Printf("SERIAL ERROR: write error [%d][%s]\n", scount, serr) } } }() chDTRSerial = make(chan bool) chQuitDTR := make(chan bool) go func() { var param uint var ep syscall.Errno for q := false; q == false; { select { case q = <-chQuitDTR: case dtr := <-chDTRSerial: param = syscall.TIOCM_DTR if dtr { _, _, ep = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TIOCMBIS, uintptr(unsafe.Pointer(¶m))) } else { _, _, ep = syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TIOCMBIC, uintptr(unsafe.Pointer(¶m))) } if ep != 0 { fmt.Printf("SERIAL ERROR: DTR error [%d]\n", ep) } } } }() go func() { <-chQuitSerial serFile.Close() chQuitFrom <- true chQuitTo <- true chQuitDTR <- true }() } } return chFromSerial, chToSerial, chDTRSerial, chQuitSerial, err }
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, 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 }
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 }
// Opens and returns a non-blocking serial port. // The device, baud rate, and SerConf is specified. // // Example: rs232.OpenPort("/dev/ttyS0", 115200, rs232.S_8N1) func OpenPort(port string, baudRate int, serconf SerConf) (*SerialPort, error) { rv := &SerialPort{} f, err := os.OpenFile(port, syscall.O_RDWR|syscall.O_NOCTTY, 0666) if err != nil { return nil, err } rv.port = f fd := rv.port.Fd() var options C.struct_termios if C.tcgetattr(C.int(fd), &options) < 0 { defer f.Close() return nil, fmt.Errorf("tcgetattr failed") } if C.cfsetispeed(&options, baudConversion(baudRate)) < 0 { defer f.Close() return nil, fmt.Errorf("cfsetispeed failed") } if C.cfsetospeed(&options, baudConversion(baudRate)) < 0 { defer f.Close() return nil, fmt.Errorf("cfsetospeed failed") } switch serconf { case S_8N1: { options.c_cflag &^= C.PARENB options.c_cflag &^= C.CSTOPB options.c_cflag &^= C.CSIZE options.c_cflag |= C.CS8 } case S_7E1: { options.c_cflag |= C.PARENB options.c_cflag &^= C.PARODD options.c_cflag &^= C.CSTOPB options.c_cflag &^= C.CSIZE options.c_cflag |= C.CS7 } case S_7O1: { options.c_cflag |= C.PARENB options.c_cflag |= C.PARODD options.c_cflag &^= C.CSTOPB options.c_cflag &^= C.CSIZE options.c_cflag |= C.CS7 } } // Local options.c_cflag |= (C.CLOCAL | C.CREAD) // no hardware flow control options.c_cflag &^= C.CRTSCTS // Don't EOF on a zero read, just block options.c_cc[C.VMIN] = 1 if C.tcsetattr(C.int(fd), C.TCSANOW, &options) < 0 { defer f.Close() return nil, fmt.Errorf("tcsetattr failed") } return rv, nil }
// Thin wrapper around tcsetattr. func setTermSettings(settings C.struct_termios) { res, err := C.tcsetattr(C.int(os.Stderr.Fd()), 0, &settings) if res != 0 { panic(fmt.Sprintf("tcsetattr returned %d: %v", res, err)) } }
// ApplyToFd applies term to the given file descriptor. func (term *Termios) ApplyToFd(fd int) error { _, err := C.tcsetattr((C.int)(fd), 0, term.c()) return err }
// Opens and returns a non-blocking serial port. // The device, baud rate, and SerConf is specified. // // Example: rs232.OpenPort("/dev/ttyS0", 115200, rs232.S_8N1) func OpenPort(port string, baudRate int, serconf SerConf) (rv SerialPort, err error) { f, open_err := os.OpenFile(port, syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NDELAY, 0666) if open_err != nil { err = open_err return } rv.port = f fd := rv.port.Fd() var options C.struct_termios if C.tcgetattr(C.int(fd), &options) < 0 { panic("tcgetattr failed") } if C.cfsetispeed(&options, baudConversion(baudRate)) < 0 { panic("cfsetispeed failed") } if C.cfsetospeed(&options, baudConversion(baudRate)) < 0 { panic("cfsetospeed failed") } switch serconf { case S_8N1: { options.c_cflag &^= C.PARENB options.c_cflag &^= C.CSTOPB options.c_cflag &^= C.CSIZE options.c_cflag |= C.CS8 } case S_7E1: { options.c_cflag |= C.PARENB options.c_cflag &^= C.PARODD options.c_cflag &^= C.CSTOPB options.c_cflag &^= C.CSIZE options.c_cflag |= C.CS7 } case S_7O1: { options.c_cflag |= C.PARENB options.c_cflag |= C.PARODD options.c_cflag &^= C.CSTOPB options.c_cflag &^= C.CSIZE options.c_cflag |= C.CS7 } } // Local options.c_cflag |= (C.CLOCAL | C.CREAD) // no hardware flow control options.c_cflag &^= C.CRTSCTS if C.tcsetattr(C.int(fd), C.TCSANOW, &options) < 0 { panic("tcsetattr failed") } if syscall.SetNonblock(int(fd), false) != nil { panic("Error disabling blocking") } return }
// Wrapper of tcsetattr(3). // The SetAttr() function sets the parameters associated with the terminal. func (t *Termios) SetAttr(fd int, opt int) error { if C.tcsetattr(C.int(fd), C.int(opt), cTermios(t)) == -1 { return errors.New("tcsetattr failure") } return 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, 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, 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 }