示例#1
0
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
}
示例#2
0
文件: term.go 项目: krockot/goterm
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
}
示例#3
0
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
}
示例#4
0
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)
	}
}
示例#5
0
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)
	}
}
示例#6
0
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)
		}
	}
}
示例#7
0
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
}
示例#8
0
// 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]
}
示例#9
0
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
}
示例#11
0
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
}
示例#12
0
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
}
示例#13
0
	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 */
)
示例#14
0
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
}
示例#15
0
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
}