io/i2c: don't enforce <bus,addr> naming at the driver level

Updates golang/go#15774.

Change-Id: Ieac185e6f409fd93a807fb5c3a0a0629f0a7c29b
Reviewed-on: https://go-review.googlesource.com/23288
Reviewed-by: Minux Ma <minux@golang.org>
Run-TryBot: Jaana Burcu Dogan <jbd@google.com>
diff --git a/io/i2c/devfs.go b/io/i2c/devfs.go
index 34d9c0a..2ddd8d6 100644
--- a/io/i2c/devfs.go
+++ b/io/i2c/devfs.go
@@ -14,7 +14,16 @@
 
 // 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{}
+type Devfs struct {
+	// Dev is the I2C bus device, e.g. /dev/i2c-1.
+	// Required.
+	Dev string
+
+	// Addr is the device's I2C address on the specified bus.
+	// Use TenBit to mark your address if your device works with 10-bit addresses.
+	// Required.
+	Addr int
+}
 
 const (
 	i2c_SLAVE  = 0x0703 // TODO(jbd): Allow users to use I2C_SLAVE_FORCE?
@@ -23,8 +32,9 @@
 
 // TODO(jbd): Support I2C_RETRIES and I2C_TIMEOUT at the driver and implementation level.
 
-func (d *Devfs) Open(bus, addr int, tenbit bool) (driver.Conn, error) {
-	f, err := os.OpenFile(fmt.Sprintf("/dev/i2c-%d", bus), os.O_RDWR, os.ModeDevice)
+func (d *Devfs) Open() (driver.Conn, error) {
+	addr, tenbit := resolveAddr(d.Addr)
+	f, err := os.OpenFile(d.Dev, os.O_RDWR, os.ModeDevice)
 	if err != nil {
 		return nil, err
 	}
@@ -32,12 +42,12 @@
 	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", bus, err)
+			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, bus, err)
+		return nil, fmt.Errorf("error opening the address (%v) on the bus (%v): %v", addr, d.Dev, err)
 	}
 	return conn, nil
 }
diff --git a/io/i2c/driver/driver.go b/io/i2c/driver/driver.go
index 09f3bd3..2a78531 100644
--- a/io/i2c/driver/driver.go
+++ b/io/i2c/driver/driver.go
@@ -5,12 +5,9 @@
 // Package driver contains interfaces to be implemented by various I2C implementations.
 package driver // import "golang.org/x/exp/io/i2c/driver"
 
-// Opener is an interface to be implemented by the I2C driver to open
-// a connection to an I2C device with the specified bus number and I2C address.
-// Open should support 7-bit addresses and should provide support for
-// 10-bit I2C addresses if tenbit is true.
+// Opener opens a connection to an I2C device.
 type Opener interface {
-	Open(bus, addr int, tenbit bool) (Conn, error)
+	Open() (Conn, error)
 }
 
 // Conn represents an active connection to an I2C device.
diff --git a/io/i2c/example/displayip/main.go b/io/i2c/example/displayip/main.go
index 779d7c2..e182726 100644
--- a/io/i2c/example/displayip/main.go
+++ b/io/i2c/example/displayip/main.go
@@ -19,12 +19,12 @@
 )
 
 func main() {
-	d, err := i2c.Open(&i2c.Devfs{}, 1, DISPLAY_RGB_ADDR)
+	d, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1", Addr: DISPLAY_RGB_ADDR})
 	if err != nil {
 		panic(err)
 	}
 
-	td, err := i2c.Open(&i2c.Devfs{}, 1, DISPLAY_TEXT_ADDR)
+	td, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1", Addr: DISPLAY_TEXT_ADDR})
 	if err != nil {
 		panic(err)
 	}
diff --git a/io/i2c/example_test.go b/io/i2c/example_test.go
index 114de32..a9783e3 100644
--- a/io/i2c/example_test.go
+++ b/io/i2c/example_test.go
@@ -9,13 +9,13 @@
 )
 
 func ExampleOpen() {
-	d, err := i2c.Open(&i2c.Devfs{}, 1, 0x39)
+	d, err := i2c.Open(&i2c.Devfs{Dev: "/dev/i2c-1", Addr: 0x39})
 	if err != nil {
 		panic(err)
 	}
 
 	// opens a 10-bit address
-	d, err = i2c.Open(&i2c.Devfs{}, 1, i2c.TenBit(0x78))
+	d, err = i2c.Open(&i2c.Devfs{Dev: "/dev-i2c-1", Addr: i2c.TenBit(0x78)})
 	if err != nil {
 		panic(err)
 	}
diff --git a/io/i2c/i2c.go b/io/i2c/i2c.go
index f8f0cf1..42ca273 100644
--- a/io/i2c/i2c.go
+++ b/io/i2c/i2c.go
@@ -47,19 +47,14 @@
 }
 
 // Close closes the device and releases the underlying sources.
-// All devices must be closed once they are no longer in use.
 func (d *Device) Close() error {
 	return d.conn.Close()
 }
 
-// Open opens an I2C device with the given I2C address on the specified bus.
-// Use TenBit to mark your address if your device works with 10-bit addresses.
-func Open(o driver.Opener, bus, addr int) (*Device, error) {
-	if o == nil {
-		o = &Devfs{}
-	}
-	addr, tenbit := resolveAddr(addr)
-	conn, err := o.Open(bus, addr, tenbit)
+// Open opens a connection to an I2C device.
+// All devices must be closed once they are no longer in use.
+func Open(o driver.Opener) (*Device, error) {
+	conn, err := o.Open()
 	if err != nil {
 		return nil, err
 	}