golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/io/i2c/devfs.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build linux 6 7 package i2c 8 9 import ( 10 "fmt" 11 "io" 12 "os" 13 "syscall" 14 15 "golang.org/x/exp/io/i2c/driver" 16 ) 17 18 // Devfs is an I2C driver that works against the devfs. 19 // You need to load the "i2c-dev" kernel module to use this driver. 20 type Devfs struct { 21 // Dev is the I2C bus device, e.g. /dev/i2c-1. Required. 22 Dev string 23 } 24 25 const ( 26 i2c_SLAVE = 0x0703 // TODO(jbd): Allow users to use I2C_SLAVE_FORCE? 27 i2c_TENBIT = 0x0704 28 ) 29 30 // TODO(jbd): Support I2C_RETRIES and I2C_TIMEOUT at the driver and implementation level. 31 32 func (d *Devfs) Open(addr int, tenbit bool) (driver.Conn, error) { 33 f, err := os.OpenFile(d.Dev, os.O_RDWR, os.ModeDevice) 34 if err != nil { 35 return nil, err 36 } 37 conn := &devfsConn{f: f} 38 if tenbit { 39 if err := conn.ioctl(i2c_TENBIT, uintptr(1)); err != nil { 40 conn.Close() 41 return nil, fmt.Errorf("cannot enable the 10-bit address mode on bus %v: %v", d.Dev, err) 42 } 43 } 44 if err := conn.ioctl(i2c_SLAVE, uintptr(addr)); err != nil { 45 conn.Close() 46 return nil, fmt.Errorf("error opening the address (%v) on the bus (%v): %v", addr, d.Dev, err) 47 } 48 return conn, nil 49 } 50 51 type devfsConn struct { 52 f *os.File 53 } 54 55 func (c *devfsConn) Tx(w, r []byte) error { 56 if w != nil { 57 if _, err := c.f.Write(w); err != nil { 58 return err 59 } 60 c.f.Sync() 61 } 62 if r != nil { 63 if _, err := io.ReadFull(c.f, r); err != nil { 64 return err 65 } 66 } 67 return nil 68 } 69 70 func (c *devfsConn) Close() error { 71 return c.f.Close() 72 } 73 74 func (c *devfsConn) ioctl(arg1, arg2 uintptr) error { 75 if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, c.f.Fd(), arg1, arg2); errno != 0 { 76 return syscall.Errno(errno) 77 } 78 return nil 79 }