func OpenSPI(channel uint8, speed uint32, mode uint8) (device SPIBus, err error) { channel &= 1 // 0 or 1 mode &= 3 // 0, 1, 2 or 3 s := &spi{channel: channel, speed: speed} defer func() { if err != nil { s.Close() } }() if channel == 0 { if s.file, err = os.OpenFile(spiDev0, os.O_RDWR, 0); err != nil { return } } else { if s.file, err = os.OpenFile(spiDev1, os.O_RDWR, 0); err != nil { return } } if err = sys.Ioctl(s.file.Fd(), SPI_IOC_WR_MODE(), uintptr(unsafe.Pointer(&mode))); err != nil { return } if err = sys.Ioctl(s.file.Fd(), SPI_IOC_WR_BITS_PER_WORD(), uintptr(unsafe.Pointer(&spiBPW))); err != nil { return } if err = sys.Ioctl(s.file.Fd(), SPI_IOC_WR_MAX_SPEED_HZ(), uintptr(unsafe.Pointer(&speed))); err != nil { return } runtime.SetFinalizer(s, func(this *spi) { this.Close() }) device = s return }
// New opens a connection to an i2c device. func NewI2C(addr uint, dev uint) (i *I2C, err error) { f, err := os.OpenFile(fmt.Sprintf("/dev/i2c-%d", dev), os.O_RDWR, 0600) if err != nil { return } defer func() { if err != nil { f.Close() } }() if addr <= 0x7F { if err = sys.Ioctl(f.Fd(), I2C_TENBIT, 0); err != nil { return } } else if addr <= 0x3FF { if err = sys.Ioctl(f.Fd(), I2C_TENBIT, 1); err != nil { return } } else { err = fmt.Errorf("address overflow: %d", addr) return } if err = sys.Ioctl(f.Fd(), I2C_SLAVE, uintptr(addr)); err != nil { return } var mask uint64 if err = sys.Ioctl(f.Fd(), I2C_FUNCS, uintptr(unsafe.Pointer(&mask))); err != nil { return } i = &I2C{f, addr, dev, mask} runtime.SetFinalizer(i, func(this *I2C) { this.Close() }) return }
func OpenSerial(device string, baud uint) (s *serial, err error) { myBaud := getBaud(baud) if myBaud == 0 { err = errInvalidBaud return } fd, err := syscall.Open( device, os.O_RDWR|syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NDELAY|syscall.O_NONBLOCK, 0666) if err != nil { return } defer func() { if err != nil { syscall.Close(fd) } }() term := syscall.Termios{} if err = sys.Ioctl(uintptr(fd), syscall.TCGETS, uintptr(unsafe.Pointer(&term))); err != nil { return } term.Ispeed = myBaud term.Ospeed = myBaud term.Cflag |= (syscall.CLOCAL | syscall.CREAD) term.Cflag = uint32(int32(term.Cflag) & ^syscall.PARENB & ^syscall.CSTOPB & ^syscall.CSIZE) term.Cflag |= syscall.CS8 term.Lflag = uint32(int32(term.Lflag) & ^(syscall.ICANON | syscall.ECHO | syscall.ECHOE | syscall.ISIG)) term.Oflag = uint32(int32(term.Oflag) & ^syscall.OPOST) term.Cc[syscall.VMIN] = 0 term.Cc[syscall.VTIME] = 100 if err = sys.Ioctl(uintptr(fd), syscall.TCSETS, uintptr(unsafe.Pointer(&term))); err != nil { return } status := 0 if err = sys.Ioctl(uintptr(fd), syscall.TIOCMGET, uintptr(unsafe.Pointer(&status))); err != nil { return } status |= syscall.TIOCM_DTR | syscall.TIOCM_RTS if err = sys.Ioctl(uintptr(fd), syscall.TIOCMSET, uintptr(unsafe.Pointer(&status))); err != nil { return } s = &serial{uintptr(fd)} runtime.SetFinalizer(s, func(this *serial) { this.Close() }) return }
func smbusAccess(fd uintptr, rw uint8, cmd uint8, size int, data *smbusData) error { d := smbusIoctlData{ rw: rw, cmd: cmd, size: size, data: data, } return sys.Ioctl(fd, I2C_SMBUS, uintptr(unsafe.Pointer(&d))) }
func SetBusFreq(hz uint) error { if hz > 400000 || hz < 10000 { return fmt.Errorf("invalid bus freq: %d", hz) } f, err := os.OpenFile("/dev/hwi2c", os.O_RDWR, 0600) if err != nil { return err } defer f.Close() err = sys.Ioctl(f.Fd(), I2CCLOCK_CHANGE, uintptr(unsafe.Pointer(&hz))) return err }
func (this *spi) WriteAndRead(p []byte) (n int, err error) { n = len(p) var transfer = spiIoctlTransfer{ TxBuf: uint64(uintptr(unsafe.Pointer(&p[0]))), RxBuf: uint64(uintptr(unsafe.Pointer(&p[0]))), Length: uint32(n), SpeedHz: this.speed, DelayUsecs: 0, BitsPerWord: spiBPW, } err = sys.Ioctl(this.file.Fd(), SPI_IOC_MESSAGE(1), uintptr(unsafe.Pointer(&transfer))) return }
func (this *serial) Available() (n int, err error) { err = sys.Ioctl(this.fd, syscall.TIOCINQ, uintptr(unsafe.Pointer(&n))) return }
func (this *serial) Flush() error { return sys.Ioctl(this.fd, syscall.TCIOFLUSH, 0) }