57 lines
2.0 KiB
Go
57 lines
2.0 KiB
Go
package system
|
|
|
|
import (
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
// SyscallErrno wraps the "unix.Errno"
|
|
type SyscallErrno unix.Errno
|
|
|
|
// wrapping for used constants of unix package
|
|
const (
|
|
Syscall_SYS_IOCTL = unix.SYS_IOCTL
|
|
Syscall_EINVAL = unix.EINVAL
|
|
Syscall_EBUSY = unix.EBUSY
|
|
Syscall_EFAULT = unix.EFAULT
|
|
)
|
|
|
|
// nativeSyscall represents the native Syscall
|
|
type nativeSyscall struct{}
|
|
|
|
// Syscall calls the native unix.Syscall, implements the SystemCaller interface
|
|
// Note: It would be possible to transfer the address as an unsafe.Pointer to e.g. a byte, uint16 or integer variable.
|
|
// The unpack process here would be as follows:
|
|
// * convert the payload back to the pointer: addrPtr := (*byte)(payload)
|
|
// * call with the content converted to uintptr: r1, r2, errNo = unix.Syscall(trap, f.Fd(), signal, uintptr(*addrPtr))
|
|
// This has the main disadvantage, that if someone change the type of the address at caller side, the compiler will not
|
|
// detect this problem and this unpack procedure would cause unpredictable results.
|
|
// So the decision was taken to give the address here as a separate parameter, although it is not used in every call.
|
|
// Note also, that the size of the address variable at Kernel side is u16, therefore uint16 is used here.
|
|
//
|
|
//nolint:nonamedreturns // useful here
|
|
func (sys *nativeSyscall) syscall(
|
|
trap uintptr,
|
|
f File,
|
|
signal uintptr,
|
|
payload unsafe.Pointer,
|
|
address uint16,
|
|
) (r1, r2 uintptr, err SyscallErrno) {
|
|
var errNo unix.Errno
|
|
if signal == I2C_TARGET {
|
|
// this is the setup for the address, it just needs to be converted to an uintptr,
|
|
// the given payload is not used in this case, see the comment on the function
|
|
r1, r2, errNo = unix.Syscall(trap, f.Fd(), signal, uintptr(address))
|
|
} else {
|
|
r1, r2, errNo = unix.Syscall(trap, f.Fd(), signal, uintptr(payload))
|
|
}
|
|
|
|
return r1, r2, SyscallErrno(errNo)
|
|
}
|
|
|
|
// Error implements the error interface. It wraps the "unix.Errno.Error()".
|
|
func (e SyscallErrno) Error() string {
|
|
return unix.Errno(e).Error()
|
|
}
|