2014-10-30 16:06:04 -07:00
|
|
|
package sysfs
|
|
|
|
|
|
|
|
import (
|
2017-04-09 09:32:55 +02:00
|
|
|
"errors"
|
2014-10-30 16:06:04 -07:00
|
|
|
"os"
|
2017-04-09 09:29:28 +02:00
|
|
|
"syscall"
|
2014-10-30 16:06:04 -07:00
|
|
|
"testing"
|
2022-11-05 07:42:28 +01:00
|
|
|
"unsafe"
|
2014-12-31 06:12:25 -08:00
|
|
|
|
2017-07-12 09:00:35 -06:00
|
|
|
"gobot.io/x/gobot/drivers/i2c"
|
2016-12-08 13:24:03 +01:00
|
|
|
"gobot.io/x/gobot/gobottest"
|
2014-10-30 16:06:04 -07:00
|
|
|
)
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
const dev = "/dev/i2c-1"
|
|
|
|
|
2022-11-05 07:42:28 +01:00
|
|
|
func syscallFuncsImpl(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) {
|
|
|
|
if (trap == syscall.SYS_IOCTL) && (a2 == I2C_FUNCS) {
|
|
|
|
var funcPtr *uint64 = (*uint64)(unsafe.Pointer(a3))
|
|
|
|
*funcPtr = I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_READ_BYTE_DATA |
|
|
|
|
I2C_FUNC_SMBUS_READ_WORD_DATA |
|
|
|
|
I2C_FUNC_SMBUS_WRITE_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
|
|
|
|
I2C_FUNC_SMBUS_WRITE_WORD_DATA
|
|
|
|
}
|
|
|
|
// Let all operations succeed
|
|
|
|
return 0, 0, 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func initTestI2cDeviceWithMockedSys() (*i2cDevice, *mockSyscall) {
|
|
|
|
a := NewAccesser()
|
|
|
|
msc := a.UseMockSyscall()
|
|
|
|
a.UseMockFilesystem([]string{dev})
|
|
|
|
|
|
|
|
d, err := a.NewI2cDevice(dev)
|
2022-10-26 18:21:34 +02:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2017-04-07 19:59:55 +02:00
|
|
|
|
2022-11-05 07:42:28 +01:00
|
|
|
return d, msc
|
2017-04-09 09:32:55 +02:00
|
|
|
}
|
|
|
|
|
2014-10-30 16:06:04 -07:00
|
|
|
func TestNewI2cDevice(t *testing.T) {
|
2022-10-26 18:21:34 +02:00
|
|
|
var tests = map[string]struct {
|
|
|
|
dev string
|
|
|
|
wantErr string
|
|
|
|
}{
|
|
|
|
"ok": {
|
|
|
|
dev: dev,
|
2017-04-09 09:29:28 +02:00
|
|
|
},
|
2022-11-05 07:42:28 +01:00
|
|
|
"empty": {
|
|
|
|
dev: "",
|
|
|
|
wantErr: "the given character device location is empty",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
2022-11-05 07:42:28 +01:00
|
|
|
a := NewAccesser()
|
2022-10-26 18:21:34 +02:00
|
|
|
// act
|
2022-11-05 07:42:28 +01:00
|
|
|
d, err := a.NewI2cDevice(tc.dev)
|
|
|
|
// assert
|
2022-10-26 18:21:34 +02:00
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, d, (*i2cDevice)(nil))
|
2022-10-26 18:21:34 +02:00
|
|
|
} else {
|
2022-11-05 07:42:28 +01:00
|
|
|
var _ i2c.I2cDevice = d
|
2022-10-26 18:21:34 +02:00
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-07 19:59:55 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestClose(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, _ := initTestI2cDeviceWithMockedSys()
|
|
|
|
// act & assert
|
|
|
|
gobottest.Assert(t, d.Close(), nil)
|
2017-04-07 19:59:55 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestSetAddress(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
// act
|
|
|
|
err := d.SetAddress(0xff)
|
|
|
|
// assert
|
2017-04-09 09:15:09 +02:00
|
|
|
gobottest.Assert(t, err, nil)
|
2022-10-26 18:21:34 +02:00
|
|
|
gobottest.Assert(t, msc.devAddress, uintptr(0xff))
|
2017-04-09 09:15:09 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestWriteRead(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, _ := initTestI2cDeviceWithMockedSys()
|
|
|
|
wbuf := []byte{0x01, 0x02, 0x03}
|
|
|
|
rbuf := make([]byte, 4)
|
|
|
|
// act
|
|
|
|
wn, werr := d.Write(wbuf)
|
|
|
|
rn, rerr := d.Read(rbuf)
|
|
|
|
// assert
|
|
|
|
gobottest.Assert(t, werr, nil)
|
|
|
|
gobottest.Assert(t, rerr, nil)
|
|
|
|
gobottest.Assert(t, wn, len(wbuf))
|
|
|
|
gobottest.Assert(t, rn, len(wbuf)) // will read only the written values
|
|
|
|
gobottest.Assert(t, wbuf, rbuf[:len(wbuf)])
|
2017-04-07 19:59:55 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestReadByte(t *testing.T) {
|
|
|
|
var tests = map[string]struct {
|
|
|
|
funcs uint64
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
}{
|
|
|
|
"read_byte_ok": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_READ_BYTE,
|
|
|
|
},
|
|
|
|
"error_syscall": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_READ_BYTE,
|
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "SMBus access failed with syscall.Errno operation not permitted",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_not_supported": {
|
|
|
|
wantErr: "SMBus read byte not supported",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
d.funcs = tc.funcs
|
|
|
|
const want = byte(5)
|
|
|
|
msc.dataSlice = []byte{want}
|
|
|
|
// act
|
|
|
|
got, err := d.ReadByte()
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
gobottest.Assert(t, got, want)
|
|
|
|
gobottest.Assert(t, msc.lastFile, d.file)
|
|
|
|
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
|
|
|
|
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ))
|
|
|
|
gobottest.Assert(t, msc.smbus.command, byte(0)) // register is set to 0 in that case
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_BYTE))
|
2022-10-26 18:21:34 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-09 09:15:09 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestReadByteData(t *testing.T) {
|
|
|
|
var tests = map[string]struct {
|
|
|
|
funcs uint64
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
}{
|
|
|
|
"read_byte_data_ok": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_READ_BYTE_DATA,
|
|
|
|
},
|
|
|
|
"error_syscall": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_READ_BYTE_DATA,
|
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "SMBus access failed with syscall.Errno operation not permitted",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_not_supported": {
|
|
|
|
wantErr: "SMBus read byte data not supported",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
d.funcs = tc.funcs
|
|
|
|
const (
|
|
|
|
reg = byte(0x01)
|
|
|
|
want = byte(0x02)
|
|
|
|
)
|
|
|
|
msc.dataSlice = []byte{want}
|
|
|
|
// act
|
|
|
|
got, err := d.ReadByteData(reg)
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
gobottest.Assert(t, got, want)
|
|
|
|
gobottest.Assert(t, msc.lastFile, d.file)
|
|
|
|
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
|
|
|
|
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ))
|
|
|
|
gobottest.Assert(t, msc.smbus.command, reg)
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_BYTE_DATA))
|
2022-10-26 18:21:34 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-07 19:59:55 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestReadWordData(t *testing.T) {
|
|
|
|
var tests = map[string]struct {
|
|
|
|
funcs uint64
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
}{
|
|
|
|
"read_word_data_ok": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_READ_WORD_DATA,
|
|
|
|
},
|
|
|
|
"error_syscall": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_READ_WORD_DATA,
|
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "SMBus access failed with syscall.Errno operation not permitted",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_not_supported": {
|
|
|
|
wantErr: "SMBus read word data not supported",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
d.funcs = tc.funcs
|
|
|
|
const (
|
|
|
|
reg = byte(0x02)
|
|
|
|
msbyte = byte(0xD4)
|
|
|
|
lsbyte = byte(0x31)
|
|
|
|
want = uint16(54321)
|
|
|
|
)
|
|
|
|
// all common drivers read LSByte first
|
|
|
|
msc.dataSlice = []byte{lsbyte, msbyte}
|
|
|
|
// act
|
|
|
|
got, err := d.ReadWordData(reg)
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
gobottest.Assert(t, got, want)
|
|
|
|
gobottest.Assert(t, msc.lastFile, d.file)
|
|
|
|
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
|
|
|
|
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ))
|
|
|
|
gobottest.Assert(t, msc.smbus.command, reg)
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_WORD_DATA))
|
2022-10-26 18:21:34 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-09 09:15:09 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestReadBlockData(t *testing.T) {
|
2022-11-05 07:42:28 +01:00
|
|
|
// arrange
|
|
|
|
const (
|
|
|
|
reg = byte(0x03)
|
|
|
|
wantB0 = byte(11)
|
|
|
|
wantB1 = byte(22)
|
|
|
|
wantB2 = byte(33)
|
|
|
|
wantB3 = byte(44)
|
|
|
|
wantB4 = byte(55)
|
|
|
|
wantB5 = byte(66)
|
|
|
|
wantB6 = byte(77)
|
|
|
|
wantB7 = byte(88)
|
|
|
|
wantB8 = byte(99)
|
|
|
|
wantB9 = byte(111)
|
|
|
|
)
|
2022-10-26 18:21:34 +02:00
|
|
|
var tests = map[string]struct {
|
|
|
|
funcs uint64
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
}{
|
|
|
|
"read_block_data_ok": {
|
2022-11-05 07:42:28 +01:00
|
|
|
funcs: I2C_FUNC_SMBUS_READ_I2C_BLOCK,
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_syscall": {
|
2022-11-05 07:42:28 +01:00
|
|
|
funcs: I2C_FUNC_SMBUS_READ_I2C_BLOCK,
|
2022-10-26 18:21:34 +02:00
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "SMBus access failed with syscall.Errno operation not permitted",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_from_used_fallback_if_not_supported": {
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "Read 1 bytes from device by sysfs, expected 10",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
d.funcs = tc.funcs
|
2022-11-05 07:42:28 +01:00
|
|
|
msc.dataSlice = []byte{wantB0, wantB1, wantB2, wantB3, wantB4, wantB5, wantB6, wantB7, wantB8, wantB9}
|
|
|
|
buf := []byte{12, 23, 34, 45, 56, 67, 78, 89, 98, 87}
|
2022-10-26 18:21:34 +02:00
|
|
|
// act
|
|
|
|
err := d.ReadBlockData(reg, buf)
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
gobottest.Assert(t, buf, msc.dataSlice)
|
|
|
|
gobottest.Assert(t, msc.lastFile, d.file)
|
|
|
|
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.sliceSize, uint8(len(buf)+1))
|
2022-10-26 18:21:34 +02:00
|
|
|
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_READ))
|
|
|
|
gobottest.Assert(t, msc.smbus.command, reg)
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_I2C_BLOCK_DATA))
|
2022-10-26 18:21:34 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-07 19:59:55 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestWriteByte(t *testing.T) {
|
|
|
|
var tests = map[string]struct {
|
|
|
|
funcs uint64
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
}{
|
|
|
|
"write_byte_ok": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_WRITE_BYTE,
|
|
|
|
},
|
|
|
|
"error_syscall": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_WRITE_BYTE,
|
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "SMBus access failed with syscall.Errno operation not permitted",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_not_supported": {
|
|
|
|
wantErr: "SMBus write byte not supported",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
d.funcs = tc.funcs
|
|
|
|
const val = byte(0x44)
|
|
|
|
// act
|
|
|
|
err := d.WriteByte(val)
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
gobottest.Assert(t, msc.lastFile, d.file)
|
|
|
|
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
|
|
|
|
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE))
|
|
|
|
gobottest.Assert(t, msc.smbus.command, val) // in byte write, the register/command is used for the value
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_BYTE))
|
2022-10-26 18:21:34 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-09 09:15:09 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestWriteByteData(t *testing.T) {
|
|
|
|
var tests = map[string]struct {
|
|
|
|
funcs uint64
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
}{
|
|
|
|
"write_byte_data_ok": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
|
|
|
|
},
|
|
|
|
"error_syscall": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_WRITE_BYTE_DATA,
|
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "SMBus access failed with syscall.Errno operation not permitted",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_not_supported": {
|
|
|
|
wantErr: "SMBus write byte data not supported",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
d.funcs = tc.funcs
|
|
|
|
const (
|
|
|
|
reg = byte(0x04)
|
|
|
|
val = byte(0x55)
|
|
|
|
)
|
|
|
|
// act
|
|
|
|
err := d.WriteByteData(reg, val)
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
gobottest.Assert(t, msc.lastFile, d.file)
|
|
|
|
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
|
|
|
|
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE))
|
|
|
|
gobottest.Assert(t, msc.smbus.command, reg)
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_BYTE_DATA))
|
2022-10-26 18:21:34 +02:00
|
|
|
gobottest.Assert(t, len(msc.dataSlice), 1)
|
|
|
|
gobottest.Assert(t, msc.dataSlice[0], val)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-07 19:59:55 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestWriteWordData(t *testing.T) {
|
|
|
|
var tests = map[string]struct {
|
|
|
|
funcs uint64
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
}{
|
|
|
|
"write_word_data_ok": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_WRITE_WORD_DATA,
|
|
|
|
},
|
|
|
|
"error_syscall": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_WRITE_WORD_DATA,
|
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "SMBus access failed with syscall.Errno operation not permitted",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_not_supported": {
|
|
|
|
wantErr: "SMBus write word data not supported",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
d.funcs = tc.funcs
|
|
|
|
const (
|
|
|
|
reg = byte(0x05)
|
|
|
|
val = uint16(54321)
|
|
|
|
wantLSByte = byte(0x31)
|
|
|
|
wantMSByte = byte(0xD4)
|
|
|
|
)
|
|
|
|
// act
|
|
|
|
err := d.WriteWordData(reg, val)
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
gobottest.Assert(t, msc.lastFile, d.file)
|
|
|
|
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
|
|
|
|
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE))
|
|
|
|
gobottest.Assert(t, msc.smbus.command, reg)
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_WORD_DATA))
|
2022-10-26 18:21:34 +02:00
|
|
|
gobottest.Assert(t, len(msc.dataSlice), 2)
|
|
|
|
// all common drivers write LSByte first
|
|
|
|
gobottest.Assert(t, msc.dataSlice[0], wantLSByte)
|
|
|
|
gobottest.Assert(t, msc.dataSlice[1], wantMSByte)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-09 12:09:52 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestWriteBlockData(t *testing.T) {
|
2022-11-05 07:42:28 +01:00
|
|
|
// arrange
|
|
|
|
const (
|
|
|
|
reg = byte(0x06)
|
|
|
|
b0 = byte(0x09)
|
|
|
|
b1 = byte(0x11)
|
|
|
|
b2 = byte(0x22)
|
|
|
|
b3 = byte(0x33)
|
|
|
|
b4 = byte(0x44)
|
|
|
|
b5 = byte(0x55)
|
|
|
|
b6 = byte(0x66)
|
|
|
|
b7 = byte(0x77)
|
|
|
|
b8 = byte(0x88)
|
|
|
|
b9 = byte(0x99)
|
|
|
|
)
|
2022-10-26 18:21:34 +02:00
|
|
|
var tests = map[string]struct {
|
|
|
|
funcs uint64
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
}{
|
2022-11-05 07:42:28 +01:00
|
|
|
"write_block_data_ok": {
|
|
|
|
funcs: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK,
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
"error_syscall": {
|
2022-11-05 07:42:28 +01:00
|
|
|
funcs: I2C_FUNC_SMBUS_WRITE_I2C_BLOCK,
|
2022-10-26 18:21:34 +02:00
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
2022-11-05 07:42:28 +01:00
|
|
|
wantErr: "SMBus access failed with syscall.Errno operation not permitted",
|
2022-10-26 18:21:34 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
d.funcs = tc.funcs
|
2022-11-05 07:42:28 +01:00
|
|
|
data := []byte{b0, b1, b2, b3, b4, b5, b6, b7, b8, b9}
|
2022-10-26 18:21:34 +02:00
|
|
|
// act
|
|
|
|
err := d.WriteBlockData(reg, data)
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
gobottest.Assert(t, msc.lastFile, d.file)
|
|
|
|
gobottest.Assert(t, msc.lastSignal, uintptr(I2C_SMBUS))
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.sliceSize, uint8(len(data)+1)) // including size element
|
2022-10-26 18:21:34 +02:00
|
|
|
gobottest.Assert(t, msc.smbus.readWrite, byte(I2C_SMBUS_WRITE))
|
|
|
|
gobottest.Assert(t, msc.smbus.command, reg)
|
2022-11-05 07:42:28 +01:00
|
|
|
gobottest.Assert(t, msc.smbus.protocol, uint32(I2C_SMBUS_I2C_BLOCK_DATA))
|
|
|
|
gobottest.Assert(t, msc.dataSlice[0], uint8(len(data))) // data size
|
|
|
|
gobottest.Assert(t, msc.dataSlice[1:], data)
|
2022-10-26 18:21:34 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-04-09 12:09:52 +02:00
|
|
|
}
|
|
|
|
|
2022-10-26 18:21:34 +02:00
|
|
|
func TestWriteBlockDataTooMuch(t *testing.T) {
|
|
|
|
// arrange
|
2022-11-05 07:42:28 +01:00
|
|
|
d, _ := initTestI2cDeviceWithMockedSys()
|
2022-10-26 18:21:34 +02:00
|
|
|
// act
|
|
|
|
err := d.WriteBlockData(0x01, make([]byte, 33))
|
|
|
|
// assert
|
|
|
|
gobottest.Assert(t, err, errors.New("Writing blocks larger than 32 bytes (33) not supported"))
|
2014-10-30 16:06:04 -07:00
|
|
|
}
|
2022-11-05 07:42:28 +01:00
|
|
|
|
|
|
|
func Test_lazyInit(t *testing.T) {
|
|
|
|
var tests = map[string]struct {
|
|
|
|
requested uint64
|
|
|
|
dev string
|
|
|
|
syscallImpl func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
|
|
|
wantErr string
|
|
|
|
wantFile bool
|
|
|
|
wantFuncs uint64
|
|
|
|
}{
|
|
|
|
"ok": {
|
|
|
|
requested: I2C_FUNC_SMBUS_READ_BYTE,
|
|
|
|
dev: dev,
|
|
|
|
syscallImpl: syscallFuncsImpl,
|
|
|
|
wantFile: true,
|
|
|
|
wantFuncs: 0x7E0000,
|
|
|
|
},
|
|
|
|
"dev_null_error": {
|
|
|
|
dev: os.DevNull,
|
|
|
|
syscallImpl: syscallFuncsImpl,
|
|
|
|
wantErr: " : /dev/null: No such file.",
|
|
|
|
},
|
|
|
|
"query_funcs_error": {
|
|
|
|
dev: dev,
|
|
|
|
syscallImpl: func(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.Errno) { return 0, 0, 1 },
|
|
|
|
wantErr: "Querying functionality failed with syscall.Errno operation not permitted",
|
|
|
|
wantFile: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for name, tc := range tests {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
// arrange
|
|
|
|
d, msc := initTestI2cDeviceWithMockedSys()
|
|
|
|
d.location = tc.dev
|
|
|
|
msc.Impl = tc.syscallImpl
|
|
|
|
// act
|
|
|
|
err := d.queryFunctionality(tc.requested, "test"+name)
|
|
|
|
// assert
|
|
|
|
if tc.wantErr != "" {
|
|
|
|
gobottest.Assert(t, err.Error(), tc.wantErr)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, err, nil)
|
|
|
|
}
|
|
|
|
if tc.wantFile {
|
|
|
|
gobottest.Refute(t, d.file, nil)
|
|
|
|
} else {
|
|
|
|
gobottest.Assert(t, d.file, (*MockFile)(nil))
|
|
|
|
}
|
|
|
|
gobottest.Assert(t, d.funcs, tc.wantFuncs)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|