func TestSetGet(t *testing.T) { if dev == "" { t.Skip("No TEST_SERIAL_DEV variable set.") } f, err := os.Open(dev) if err != nil { t.Fatal("Open:", err) } defer f.Close() var ti termios.Termios err = ti.GetFd(int(f.Fd())) if err != nil { t.Fatal("Cannot get termios:", err) } err = ti.SetOSpeed(19200) if err != nil { t.Fatal("Cannot set O speed to 19200:", err) } ti.SetISpeed(19200) if err != nil { t.Fatal("Cannot set I speed to 19200:", err) } err = ti.SetFd(int(f.Fd()), termios.TCSAFLUSH) if err != nil { t.Fatal("Cannot set termios:", err) } ti = termios.Termios{} err = ti.GetFd(int(f.Fd())) if err != nil { t.Fatal("Cannot get termios:", err) } spd, err := ti.GetOSpeed() if err != nil { t.Fatal("Cannot get O speed:", err) } if spd != 19200 { t.Fatalf("Bad O speed: %d != %d", spd, 19200) } spd, err = ti.GetISpeed() if err != nil { t.Fatal("Cannot get I speed:", err) } if spd != 19200 && spd != 0 { t.Fatalf("Bad I speed: %d != %d", spd, 19200) } }
func (p *port) confSome(conf Conf, flags ConfFlags) error { if err := p.fd.Lock(); err != nil { return ErrClosed } defer p.fd.Unlock() var tios termios.Termios err := tios.GetFd(p.fd.Sysfd()) if err != nil { return newErr("tcgetattr: " + err.Error()) } if flags&ConfBaudrate != 0 { err := tios.SetOSpeed(conf.Baudrate) if err != nil { return newErr("setospeed: " + err.Error()) } err = tios.SetISpeed(conf.Baudrate) if err != nil { return newErr("setispeed: " + err.Error()) } } if flags&ConfDatabits != 0 { switch conf.Databits { case 5: tios.CFlag().Clr(termios.CSIZE).Set(termios.CS5) case 6: tios.CFlag().Clr(termios.CSIZE).Set(termios.CS6) case 7: tios.CFlag().Clr(termios.CSIZE).Set(termios.CS7) case 8: tios.CFlag().Clr(termios.CSIZE).Set(termios.CS8) default: return newErr("invalid databits value: " + strconv.Itoa(conf.Databits)) } } if flags&ConfStopbits != 0 { switch conf.Stopbits { case 1: tios.CFlag().Clr(termios.CSTOPB) case 2: tios.CFlag().Set(termios.CSTOPB) default: return newErr("invalid stopbits value: " + strconv.Itoa(conf.Stopbits)) } } if flags&ConfParity != 0 { switch conf.Parity { case ParityEven: tios.CFlag().Clr(termios.PARODD | termios.CMSPAR) tios.CFlag().Set(termios.PARENB) case ParityOdd: tios.CFlag().Clr(termios.CMSPAR) tios.CFlag().Set(termios.PARENB | termios.PARODD) case ParityMark: if termios.CMSPAR == 0 { return newErr("ParityMark not supported") } tios.CFlag().Set(termios.PARENB | termios.PARODD | termios.CMSPAR) case ParitySpace: if termios.CMSPAR == 0 { return newErr("ParitySpace not supported") } tios.CFlag().Clr(termios.PARODD) tios.CFlag().Set(termios.PARENB | termios.CMSPAR) case ParityNone: tios.CFlag().Clr(termios.PARENB | termios.PARODD | termios.CMSPAR) default: return newErr("invalid parity mode: " + conf.Parity.String()) } } if flags&ConfFlow != 0 { switch conf.Flow { case FlowRTSCTS: if termios.CRTSCTS == 0 { return newErr("FlowRTSCTS not supported") } tios.CFlag().Set(termios.CRTSCTS) tios.IFlag().Clr(termios.IXON | termios.IXOFF | termios.IXANY) case FlowXONXOFF: tios.CFlag().Clr(termios.CRTSCTS) tios.IFlag().Set(termios.IXON | termios.IXOFF) case FlowNone: tios.CFlag().Clr(termios.CRTSCTS) tios.IFlag().Clr(termios.IXON | termios.IXOFF | termios.IXANY) default: return newErr("invalid flow-control mode: " + conf.Flow.String()) } } if flags&ConfNoReset != 0 { p.noReset = conf.NoReset if p.noReset { tios.CFlag().Clr(termios.HUPCL) } else { tios.CFlag().Set(termios.HUPCL) } } err = tios.SetFd(p.fd.Sysfd(), termios.TCSANOW) if err != nil { return newErr("tcsetattr: " + err.Error()) } return nil }
func TestMisc(t *testing.T) { if dev == "" { t.Skip("No TEST_SERIAL_DEV variable set.") } f, err := os.OpenFile(dev, os.O_RDWR, 0) if err != nil { t.Fatal("Open:", err) } defer f.Close() var ti termios.Termios err = ti.GetFd(int(f.Fd())) if err != nil { t.Fatal("Cannot get termios:", err) } /* Set low baudrate */ baudrate := 1200 ti.SetOSpeed(baudrate) ti.SetISpeed(baudrate) /* Disable flow control */ ti.CFlag().Clr(termios.CRTSCTS) ti.IFlag().Clr(termios.IXON | termios.IXOFF | termios.IXANY) err = ti.SetFd(int(f.Fd()), termios.TCSANOW) if err != nil { t.Fatal("Cannot set termios:", err) } /* Try to test Drain */ b := make([]byte, 600) start := time.Now() if _, err := f.Write(b); err != nil { t.Fatal("Cannot write:", err) } err = termios.Drain(int(f.Fd())) if err != nil { t.Fatal("Cannot drain:", err) } dur := time.Since(start) charTime := 10 * time.Second / time.Duration(baudrate) chars := int(dur / charTime) // Allow some fuzz for h/w queues and stuff. if chars < len(b)-16 || chars > len(b)+16 { t.Logf("Invalid tx time %v (%d chars):", dur, chars) } /* Try to test SendBreak */ start = time.Now() termios.SendBreak(int(f.Fd())) dur = time.Since(start) // POSIX says SendBreak should last between 0.25 and 1 Sec. if dur < 200*time.Millisecond || dur > 1100*time.Millisecond { t.Log("Bad SendBreak duration:", dur) } // Just call Flush if err := termios.Flush(int(f.Fd()), termios.TCIFLUSH); err != nil { t.Fatal("Flush In failed:", err) } if err := termios.Flush(int(f.Fd()), termios.TCOFLUSH); err != nil { t.Fatal("Flush Out failed:", err) } if err := termios.Flush(int(f.Fd()), termios.TCIOFLUSH); err != nil { t.Fatal("Flush InOut failed:", err) } // This should normally fail (depends on system tcflush() // implementation) if err := termios.Flush(int(f.Fd()), 4242); err == nil { t.Logf("Flush 4242 should fail!") } }