whatcanGOwrong

This commit is contained in:
2024-09-19 21:38:24 -04:00
commit d0ae4d841d
17908 changed files with 4096831 additions and 0 deletions
@@ -0,0 +1,80 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux
// +build linux
package i2c
import (
"fmt"
"io"
"os"
"syscall"
"golang.org/x/exp/io/i2c/driver"
)
// Devfs is an I2C driver that works against the devfs.
// You need to load the "i2c-dev" kernel module to use this driver.
type Devfs struct {
// Dev is the I2C bus device, e.g. /dev/i2c-1. Required.
Dev string
}
const (
i2c_SLAVE = 0x0703 // TODO(jbd): Allow users to use I2C_SLAVE_FORCE?
i2c_TENBIT = 0x0704
)
// TODO(jbd): Support I2C_RETRIES and I2C_TIMEOUT at the driver and implementation level.
func (d *Devfs) Open(addr int, tenbit bool) (driver.Conn, error) {
f, err := os.OpenFile(d.Dev, os.O_RDWR, os.ModeDevice)
if err != nil {
return nil, err
}
conn := &devfsConn{f: f}
if tenbit {
if err := conn.ioctl(i2c_TENBIT, uintptr(1)); err != nil {
conn.Close()
return nil, fmt.Errorf("cannot enable the 10-bit address mode on bus %v: %v", d.Dev, err)
}
}
if err := conn.ioctl(i2c_SLAVE, uintptr(addr)); err != nil {
conn.Close()
return nil, fmt.Errorf("error opening the address (%v) on the bus (%v): %v", addr, d.Dev, err)
}
return conn, nil
}
type devfsConn struct {
f *os.File
}
func (c *devfsConn) Tx(w, r []byte) error {
if w != nil {
if _, err := c.f.Write(w); err != nil {
return err
}
c.f.Sync()
}
if r != nil {
if _, err := io.ReadFull(c.f, r); err != nil {
return err
}
}
return nil
}
func (c *devfsConn) Close() error {
return c.f.Close()
}
func (c *devfsConn) ioctl(arg1, arg2 uintptr) error {
if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, c.f.Fd(), arg1, arg2); errno != 0 {
return syscall.Errno(errno)
}
return nil
}
@@ -0,0 +1,25 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !linux
// +build !linux
package i2c
import (
"errors"
"golang.org/x/exp/io/i2c/driver"
)
// Devfs is no-implementation so developers using cross compilation
// can rely on local tools even though the real implementation isn't
// available on their platform.
type Devfs struct {
Dev string
}
func (d *Devfs) Open(addr int, tenbit bool) (driver.Conn, error) {
return nil, errors.New("not implemented on this platform")
}
@@ -0,0 +1,24 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package driver contains interfaces to be implemented by various I2C implementations.
package driver // import "golang.org/x/exp/io/i2c/driver"
// Opener opens a connection to an I2C device to communicate with
// the I2C address given. If the address is an 10-bit I2C address,
// tenbit is true.
type Opener interface {
Open(addr int, tenbit bool) (Conn, error)
}
// Conn represents an active connection to an I2C device.
type Conn interface {
// Tx first writes w (if not nil), then reads len(r)
// bytes from device into r (if not nil) in a single
// I2C transaction.
Tx(w, r []byte) error
// Close closes the connection.
Close() error
}
@@ -0,0 +1,89 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package main contains a program that displays the IPv4 address
// of the machine on an a Grove-LCD RGB backlight.
package main
import (
"fmt"
"net"
"golang.org/x/exp/io/i2c"
)
const (
DISPLAY_RGB_ADDR = 0x62
DISPLAY_TEXT_ADDR = 0x3e
)
func main() {
d, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, DISPLAY_RGB_ADDR)
if err != nil {
panic(err)
}
td, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, DISPLAY_TEXT_ADDR)
if err != nil {
panic(err)
}
// Set the backlight color to 100,100,100.
write(d, []byte{0, 0})
write(d, []byte{1, 0})
write(d, []byte{0x08, 0xaa})
write(d, []byte{4, 100}) // R value
write(d, []byte{3, 100}) // G value
write(d, []byte{2, 100}) // B value
ip, err := resolveIP()
if err != nil {
panic(err)
}
fmt.Printf("host machine IP is %v\n", ip)
write(td, []byte{0x80, 0x02}) // return home
write(td, []byte{0x80, 0x01}) // clean the display
write(td, []byte{0x80, 0x08 | 0x04}) // no cursor
write(td, []byte{0x80, 0x28}) // two lines
for _, s := range ip {
write(td, []byte{0x40, byte(s)})
}
}
func write(d *i2c.Device, buf []byte) {
err := d.Write(buf)
if err != nil {
panic(err)
}
}
func resolveIP() (string, error) {
var ip net.IP
ifaces, err := net.Interfaces()
if err != nil {
panic(err)
}
for _, i := range ifaces {
addrs, err := i.Addrs()
if err != nil {
panic(err)
}
for _, addr := range addrs {
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
ip = ip.To4()
if ip != nil && ip.String() != "127.0.0.1" {
return ip.String(), nil
}
}
}
return "", fmt.Errorf("cannot resolve the IP")
}
@@ -0,0 +1,24 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package i2c_test
import (
"golang.org/x/exp/io/i2c"
)
func ExampleOpen() {
d, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, 0x39)
if err != nil {
panic(err)
}
// opens a 10-bit address
d, err = i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1"}, i2c.TenBit(0x78))
if err != nil {
panic(err)
}
_ = d
}
@@ -0,0 +1,75 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package i2c allows users to read from and write to a slave I2C device.
//
// # Deprecated
//
// This package is not maintained anymore. An actively supported cross-platform
// alternative is https://periph.io/.
package i2c // import "golang.org/x/exp/io/i2c"
import (
"golang.org/x/exp/io/i2c/driver"
)
const tenbitMask = 1 << 12
// Device represents an I2C device. Devices must be closed once
// they are no longer in use.
type Device struct {
conn driver.Conn
}
// TenBit marks an I2C address as a 10-bit address.
func TenBit(addr int) int {
return addr | tenbitMask
}
// Read reads len(buf) bytes from the device.
func (d *Device) Read(buf []byte) error {
return d.conn.Tx(nil, buf)
}
// ReadReg is similar to Read but it reads from a register.
func (d *Device) ReadReg(reg byte, buf []byte) error {
return d.conn.Tx([]byte{reg}, buf)
}
// Write writes the buffer to the device. If it is required to write to a
// specific register, the register should be passed as the first byte in the
// given buffer.
func (d *Device) Write(buf []byte) (err error) {
return d.conn.Tx(buf, nil)
}
// WriteReg is similar to Write but writes to a register.
func (d *Device) WriteReg(reg byte, buf []byte) (err error) {
// TODO(jbd): Do not allocate, not optimal.
return d.conn.Tx(append([]byte{reg}, buf...), nil)
}
// Close closes the device and releases the underlying sources.
func (d *Device) Close() error {
return d.conn.Close()
}
// Open opens a connection to an I2C device.
// All devices must be closed once they are no longer in use.
// For devices that use 10-bit I2C addresses, addr can be marked
// as a 10-bit address with TenBit.
func Open(o driver.Opener, addr int) (*Device, error) {
unmasked, tenbit := resolveAddr(addr)
conn, err := o.Open(unmasked, tenbit)
if err != nil {
return nil, err
}
return &Device{conn: conn}, nil
}
// resolveAddr returns whether the addr is 10-bit masked or not.
// It also returns the unmasked address.
func resolveAddr(addr int) (unmasked int, tenbit bool) {
return addr & (tenbitMask - 1), addr&tenbitMask == tenbitMask
}
@@ -0,0 +1,31 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package i2c
import (
"testing"
)
func TestTenBit(t *testing.T) {
tc := []struct {
masked int
addrWant int
tenbitWant bool
}{
{TenBit(0x5), 0x5, true},
{0x5, 0x5, false},
{TenBit(0x200), 0x200, true},
}
for _, tt := range tc {
unmasked, tenbit := resolveAddr(tt.masked)
if want, got := tt.tenbitWant, tenbit; got != want {
t.Errorf("want address %x as 10-bit; got non 10-bit", tt.masked)
}
if want, got := tt.addrWant, unmasked; got != want {
t.Errorf("want address %v; got %v", want, got)
}
}
}