626 lines
16 KiB
Go
626 lines
16 KiB
Go
|
// SPDX-FileCopyrightText: 2020 Kent Gibson <warthog618@gmail.com>
|
||
|
//
|
||
|
// SPDX-License-Identifier: MIT
|
||
|
|
||
|
//go:build linux
|
||
|
// +build linux
|
||
|
|
||
|
package uapi
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"time"
|
||
|
"unsafe"
|
||
|
|
||
|
"golang.org/x/sys/unix"
|
||
|
)
|
||
|
|
||
|
// GetLineInfoV2 returns the LineInfoV2 for one line from the GPIO character device.
|
||
|
//
|
||
|
// The fd is an open GPIO character device.
|
||
|
// The offset is zero based.
|
||
|
func GetLineInfoV2(fd uintptr, offset int) (LineInfoV2, error) {
|
||
|
li := LineInfoV2{Offset: uint32(offset)}
|
||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL,
|
||
|
fd,
|
||
|
uintptr(getLineInfoV2Ioctl),
|
||
|
uintptr(unsafe.Pointer(&li)))
|
||
|
if errno != 0 {
|
||
|
return LineInfoV2{}, errno
|
||
|
}
|
||
|
return li, nil
|
||
|
}
|
||
|
|
||
|
// GetLine requests a line from the GPIO character device.
|
||
|
//
|
||
|
// The fd is an open GPIO character device.
|
||
|
// The lines must not already be requested.
|
||
|
// The flags in the request will be applied to all lines in the request.
|
||
|
// If successful, the fd for the line is returned in the request.fd.
|
||
|
func GetLine(fd uintptr, request *LineRequest) error {
|
||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL,
|
||
|
fd,
|
||
|
uintptr(getLineIoctl),
|
||
|
uintptr(unsafe.Pointer(request)))
|
||
|
if errno != 0 {
|
||
|
return errno
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// GetLineValuesV2 returns the values of a set of requested lines.
|
||
|
//
|
||
|
// The fd is a requested line, as returned by GetLine.
|
||
|
//
|
||
|
// The values returned are the logical values, with inactive being 0.
|
||
|
func GetLineValuesV2(fd uintptr, values *LineValues) error {
|
||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL,
|
||
|
fd,
|
||
|
uintptr(getLineValuesV2Ioctl),
|
||
|
uintptr(unsafe.Pointer(values)))
|
||
|
if errno != 0 {
|
||
|
return errno
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// SetLineValuesV2 sets the values of a set of requested lines.
|
||
|
//
|
||
|
// The fd is a requested line, as returned by GetLine.
|
||
|
func SetLineValuesV2(fd uintptr, values LineValues) error {
|
||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL,
|
||
|
fd,
|
||
|
uintptr(setLineValuesV2Ioctl),
|
||
|
uintptr(unsafe.Pointer(&values)))
|
||
|
if errno != 0 {
|
||
|
return errno
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// SetLineConfigV2 sets the config of an existing handle request.
|
||
|
//
|
||
|
// The config flags in the request will be applied to all lines in the request.
|
||
|
func SetLineConfigV2(fd uintptr, config *LineConfig) error {
|
||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL,
|
||
|
fd,
|
||
|
uintptr(setLineConfigV2Ioctl),
|
||
|
uintptr(unsafe.Pointer(config)))
|
||
|
if errno != 0 {
|
||
|
return errno
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// WatchLineInfoV2 sets a watch on info of a line.
|
||
|
//
|
||
|
// A watch is set on the line indicated by info.Offset. If successful the
|
||
|
// current line info is returned, else an error is returned.
|
||
|
func WatchLineInfoV2(fd uintptr, info *LineInfoV2) error {
|
||
|
_, _, errno := unix.Syscall(unix.SYS_IOCTL,
|
||
|
fd,
|
||
|
uintptr(watchLineInfoV2Ioctl),
|
||
|
uintptr(unsafe.Pointer(info)))
|
||
|
if errno != 0 {
|
||
|
return errno
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// ReadLineEvent reads a single event from a requested line.
|
||
|
//
|
||
|
// The fd is a requested line, as returned by GetLine.
|
||
|
//
|
||
|
// This function is blocking and should only be called when the fd is known to
|
||
|
// be ready to read.
|
||
|
func ReadLineEvent(fd uintptr) (LineEvent, error) {
|
||
|
var le LineEvent
|
||
|
err := binary.Read(fdReader(fd), nativeEndian, &le)
|
||
|
return le, err
|
||
|
}
|
||
|
|
||
|
// ReadLineInfoChangedV2 reads a line info changed event from a chip.
|
||
|
//
|
||
|
// The fd is an open GPIO character device.
|
||
|
//
|
||
|
// This function is blocking and should only be called when the fd is known to
|
||
|
// be ready to read.
|
||
|
func ReadLineInfoChangedV2(fd uintptr) (LineInfoChangedV2, error) {
|
||
|
var lic LineInfoChangedV2
|
||
|
err := binary.Read(fdReader(fd), nativeEndian, &lic)
|
||
|
return lic, err
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
getLineInfoV2Ioctl ioctl
|
||
|
getLineIoctl ioctl
|
||
|
getLineValuesV2Ioctl ioctl
|
||
|
setLineValuesV2Ioctl ioctl
|
||
|
setLineConfigV2Ioctl ioctl
|
||
|
watchLineInfoV2Ioctl ioctl
|
||
|
)
|
||
|
|
||
|
func init() {
|
||
|
// ioctls require struct sizes which are only available at runtime.
|
||
|
var liv2 LineInfoV2
|
||
|
getLineInfoV2Ioctl = iorw(0xB4, 0x05, unsafe.Sizeof(liv2))
|
||
|
watchLineInfoV2Ioctl = iorw(0xB4, 0x06, unsafe.Sizeof(liv2))
|
||
|
var lr LineRequest
|
||
|
getLineIoctl = iorw(0xB4, 0x07, unsafe.Sizeof(lr))
|
||
|
var lc LineConfig
|
||
|
setLineConfigV2Ioctl = iorw(0xB4, 0x0D, unsafe.Sizeof(lc))
|
||
|
var lv LineValues
|
||
|
getLineValuesV2Ioctl = iorw(0xB4, 0x0E, unsafe.Sizeof(lv))
|
||
|
setLineValuesV2Ioctl = iorw(0xB4, 0x0F, unsafe.Sizeof(lv))
|
||
|
}
|
||
|
|
||
|
// LineInfoV2 contains the details of a single line of a GPIO chip.
|
||
|
type LineInfoV2 struct {
|
||
|
// The system name for this line.
|
||
|
Name [nameSize]byte
|
||
|
|
||
|
// If requested, a string added by the requester to identify the
|
||
|
// owner of the request.
|
||
|
Consumer [nameSize]byte
|
||
|
|
||
|
// The offset of the line within the chip.
|
||
|
Offset uint32
|
||
|
|
||
|
NumAttrs uint32
|
||
|
|
||
|
Flags LineFlagV2
|
||
|
|
||
|
Attrs [10]LineAttribute
|
||
|
|
||
|
// reserved for future use.
|
||
|
Padding [lineInfoV2PadSize]uint32
|
||
|
}
|
||
|
|
||
|
// LineInfoChangedV2 contains the details of a change to line info.
|
||
|
//
|
||
|
// This is returned via the chip fd in response to changes to watched lines.
|
||
|
type LineInfoChangedV2 struct {
|
||
|
// The updated info.
|
||
|
Info LineInfoV2
|
||
|
|
||
|
// The time the change occurred.
|
||
|
Timestamp uint64
|
||
|
|
||
|
// The type of change.
|
||
|
Type ChangeType
|
||
|
|
||
|
// reserved for future use.
|
||
|
Padding [lineInfoChangedV2PadSize]uint32
|
||
|
}
|
||
|
|
||
|
// LineFlagV2 are the flags for a line.
|
||
|
type LineFlagV2 uint64
|
||
|
|
||
|
const (
|
||
|
// LineFlagV2Used indicates that the line is already in use.
|
||
|
// It may have been requested by this process or another process,
|
||
|
// or may be reserved by the kernel.
|
||
|
//
|
||
|
// The line cannot be requested until this flag is clear.
|
||
|
LineFlagV2Used LineFlagV2 = 1 << iota
|
||
|
|
||
|
// LineFlagV2ActiveLow indicates that the line is active low.
|
||
|
LineFlagV2ActiveLow
|
||
|
|
||
|
// LineFlagV2Input indicates that the line direction is an input.
|
||
|
LineFlagV2Input
|
||
|
|
||
|
// LineFlagV2Output indicates that the line direction is an output.
|
||
|
LineFlagV2Output
|
||
|
|
||
|
// LineFlagV2EdgeRising indicates that edge detection is enabled for rising
|
||
|
// edges.
|
||
|
LineFlagV2EdgeRising
|
||
|
|
||
|
// LineFlagV2EdgeFalling indicates that edge detection is enabled for
|
||
|
// falling edges.
|
||
|
LineFlagV2EdgeFalling
|
||
|
|
||
|
// LineFlagV2OpenDrain indicates that the line drive is open drain.
|
||
|
LineFlagV2OpenDrain
|
||
|
|
||
|
// LineFlagV2OpenSource indicates that the line drive is open source.
|
||
|
LineFlagV2OpenSource
|
||
|
|
||
|
// LineFlagV2BiasPullUp indicates that the line bias is pull-up.
|
||
|
LineFlagV2BiasPullUp
|
||
|
|
||
|
// LineFlagV2BiasPullDown indicates that the line bias is set pull-down.
|
||
|
LineFlagV2BiasPullDown
|
||
|
|
||
|
// LineFlagV2BiasDisabled indicates that the line bias is disabled.
|
||
|
LineFlagV2BiasDisabled
|
||
|
|
||
|
// LineFlagV2EventClockRealtime indicates that the CLOCK_REALTIME will be
|
||
|
// the source for event timestamps.
|
||
|
LineFlagV2EventClockRealtime
|
||
|
|
||
|
// LineFlagV2DirectionMask is a mask for all direction flags.
|
||
|
LineFlagV2DirectionMask = LineFlagV2Input | LineFlagV2Output
|
||
|
|
||
|
// LineFlagV2EdgeMask is a mask for all edge flags.
|
||
|
LineFlagV2EdgeMask = LineFlagV2EdgeRising | LineFlagV2EdgeFalling
|
||
|
|
||
|
// LineFlagV2EdgeBoth is a helper value for selecting edge detection on
|
||
|
// both edges.
|
||
|
LineFlagV2EdgeBoth = LineFlagV2EdgeMask
|
||
|
|
||
|
// LineFlagV2DriveMask is a mask for all drive flags.
|
||
|
LineFlagV2DriveMask = LineFlagV2OpenDrain | LineFlagV2OpenSource
|
||
|
|
||
|
// LineFlagV2BiasMask is a mask for all bias flags.
|
||
|
LineFlagV2BiasMask = LineFlagV2BiasDisabled | LineFlagV2BiasPullUp | LineFlagV2BiasPullDown
|
||
|
)
|
||
|
|
||
|
// IsAvailable returns true if the line is available to be requested.
|
||
|
func (f LineFlagV2) IsAvailable() bool {
|
||
|
return f&LineFlagV2Used == 0
|
||
|
}
|
||
|
|
||
|
// IsUsed returns true if the line is not available to be requested.
|
||
|
func (f LineFlagV2) IsUsed() bool {
|
||
|
return f&LineFlagV2Used != 0
|
||
|
}
|
||
|
|
||
|
// IsActiveLow returns true if the line is active low.
|
||
|
func (f LineFlagV2) IsActiveLow() bool {
|
||
|
return f&LineFlagV2ActiveLow != 0
|
||
|
}
|
||
|
|
||
|
// IsInput returns true if the line is an input.
|
||
|
func (f LineFlagV2) IsInput() bool {
|
||
|
return f&LineFlagV2Input != 0
|
||
|
}
|
||
|
|
||
|
// IsOutput returns true if the line is an output.
|
||
|
func (f LineFlagV2) IsOutput() bool {
|
||
|
return f&LineFlagV2Output != 0
|
||
|
}
|
||
|
|
||
|
// IsOpenDrain returns true if the line is an open drain.
|
||
|
func (f LineFlagV2) IsOpenDrain() bool {
|
||
|
return f&LineFlagV2OpenDrain != 0
|
||
|
}
|
||
|
|
||
|
// IsOpenSource returns true if the line is an open source.
|
||
|
func (f LineFlagV2) IsOpenSource() bool {
|
||
|
return f&LineFlagV2OpenSource != 0
|
||
|
}
|
||
|
|
||
|
// IsRisingEdge returns true if the line has edge detection on the rising edge.
|
||
|
func (f LineFlagV2) IsRisingEdge() bool {
|
||
|
return f&LineFlagV2EdgeRising != 0
|
||
|
}
|
||
|
|
||
|
// IsFallingEdge returns true if the line has edge detection on the falling edge.
|
||
|
func (f LineFlagV2) IsFallingEdge() bool {
|
||
|
return f&LineFlagV2EdgeFalling != 0
|
||
|
}
|
||
|
|
||
|
// IsBothEdges returns true if the line has edge detection on both edges.
|
||
|
func (f LineFlagV2) IsBothEdges() bool {
|
||
|
return f&LineFlagV2EdgeBoth == LineFlagV2EdgeBoth
|
||
|
}
|
||
|
|
||
|
// IsBiasDisabled returns true if the line has bias disabled.
|
||
|
func (f LineFlagV2) IsBiasDisabled() bool {
|
||
|
return f&LineFlagV2BiasDisabled != 0
|
||
|
}
|
||
|
|
||
|
// IsBiasPullUp returns true if the line has pull-up bias enabled.
|
||
|
func (f LineFlagV2) IsBiasPullUp() bool {
|
||
|
return f&LineFlagV2BiasPullUp != 0
|
||
|
}
|
||
|
|
||
|
// IsBiasPullDown returns true if the line has pull-down bias enabled.
|
||
|
func (f LineFlagV2) IsBiasPullDown() bool {
|
||
|
return f&LineFlagV2BiasPullDown != 0
|
||
|
}
|
||
|
|
||
|
// HasRealtimeEventClock returns true if the line events will contain real-time
|
||
|
// timestamps.
|
||
|
func (f LineFlagV2) HasRealtimeEventClock() bool {
|
||
|
return f&LineFlagV2EventClockRealtime != 0
|
||
|
}
|
||
|
|
||
|
// Encode creates a LineAttribute with the value from the LineFlagV2.
|
||
|
func (f LineFlagV2) Encode() (la LineAttribute) {
|
||
|
la.Encode64(LineAttributeIDFlags, uint64(f))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Decode populates the LineFlagV2 with value from the LineAttribute.
|
||
|
func (f *LineFlagV2) Decode(la LineAttribute) {
|
||
|
*f = LineFlagV2(la.Value64())
|
||
|
}
|
||
|
|
||
|
const (
|
||
|
// LinesMax is the maximum number of lines that can be requested in a single
|
||
|
// request.
|
||
|
LinesMax int = 64
|
||
|
|
||
|
// the pad sizes of each struct
|
||
|
lineConfigPadSize int = 5
|
||
|
lineRequestPadSize int = 5
|
||
|
lineEventPadSize int = 6
|
||
|
lineInfoV2PadSize int = 4
|
||
|
lineInfoChangedV2PadSize int = 5
|
||
|
)
|
||
|
|
||
|
// LineAttribute defines a configuration attribute for a line.
|
||
|
type LineAttribute struct {
|
||
|
ID LineAttributeID
|
||
|
|
||
|
Padding [1]uint32
|
||
|
|
||
|
Value [8]byte
|
||
|
}
|
||
|
|
||
|
// Encode32 populates the LineAttribute using the id and 32-bit value.
|
||
|
func (la *LineAttribute) Encode32(id LineAttributeID, value uint32) {
|
||
|
la.ID = id
|
||
|
nativeEndian.PutUint32(la.Value[:], value)
|
||
|
}
|
||
|
|
||
|
// Encode64 populates the LineAttribute using the id and 64-bit value.
|
||
|
func (la *LineAttribute) Encode64(id LineAttributeID, value uint64) {
|
||
|
la.ID = id
|
||
|
nativeEndian.PutUint64(la.Value[:], value)
|
||
|
}
|
||
|
|
||
|
// Value32 returns the 32-bit value from the LineAttribute.
|
||
|
func (la LineAttribute) Value32() uint32 {
|
||
|
return nativeEndian.Uint32(la.Value[:])
|
||
|
}
|
||
|
|
||
|
// Value64 returns the 64-bit value from the LineAttribute.
|
||
|
func (la LineAttribute) Value64() uint64 {
|
||
|
return nativeEndian.Uint64(la.Value[:])
|
||
|
}
|
||
|
|
||
|
// LineAttributeID identfies the type of a configuration attribute.
|
||
|
type LineAttributeID uint32
|
||
|
|
||
|
const (
|
||
|
// LineAttributeIDFlags indicates the attribute contains LineFlagV2 flags.
|
||
|
LineAttributeIDFlags LineAttributeID = iota + 1
|
||
|
|
||
|
// LineAttributeIDOutputValues indicates the attribute contains line output values.
|
||
|
LineAttributeIDOutputValues
|
||
|
|
||
|
// LineAttributeIDDebounce indicates the attribute contains a debounce period.
|
||
|
LineAttributeIDDebounce
|
||
|
)
|
||
|
|
||
|
// DebouncePeriod specifies the time the line must be stable before a level
|
||
|
// transition is recognized.
|
||
|
type DebouncePeriod time.Duration
|
||
|
|
||
|
// Encode creates a LineAttribute with the value from the DebouncePeriod.
|
||
|
func (d DebouncePeriod) Encode() (la LineAttribute) {
|
||
|
la.Encode32(LineAttributeIDDebounce, uint32(d/1000))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Decode populates the DebouncePeriod with value from the LineAttribute.
|
||
|
func (d *DebouncePeriod) Decode(la LineAttribute) {
|
||
|
*d = DebouncePeriod(la.Value32() * 1000)
|
||
|
}
|
||
|
|
||
|
// OutputValues specify the active level of output lines.
|
||
|
type OutputValues LineBitmap
|
||
|
|
||
|
// Encode creates a LineAttribute with the values from the OutputValues.
|
||
|
func (ov OutputValues) Encode() (la LineAttribute) {
|
||
|
la.Encode64(LineAttributeIDOutputValues, uint64(ov))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Decode populates the OutputValues with values from the LineAttribute.
|
||
|
func (ov *OutputValues) Decode(la LineAttribute) {
|
||
|
*ov = OutputValues(la.Value64())
|
||
|
}
|
||
|
|
||
|
// LineConfigAttribute associates a configuration attribute with one or more
|
||
|
// requested lines.
|
||
|
type LineConfigAttribute struct {
|
||
|
// Attr contains the configuration attribute.
|
||
|
Attr LineAttribute
|
||
|
|
||
|
// Mask identifies the lines to which this attribute applies.
|
||
|
//
|
||
|
// This is a bitmap of lines in LineRequest.Offsets.
|
||
|
Mask LineBitmap
|
||
|
}
|
||
|
|
||
|
// LineConfig contains the configuration of a line.
|
||
|
type LineConfig struct {
|
||
|
// The flags to be applied to the lines.
|
||
|
Flags LineFlagV2
|
||
|
|
||
|
NumAttrs uint32
|
||
|
|
||
|
// reserved for future use.
|
||
|
Padding [lineConfigPadSize]uint32
|
||
|
|
||
|
Attrs [10]LineConfigAttribute
|
||
|
}
|
||
|
|
||
|
// AddAttribute adds an attribute to the configuration.
|
||
|
//
|
||
|
// This is an unconditional add - it performs no filtering or consistency
|
||
|
// checking other than limiting the number of attributes.
|
||
|
func (lc *LineConfig) AddAttribute(lca LineConfigAttribute) {
|
||
|
if lc.NumAttrs < 10 {
|
||
|
lc.Attrs[lc.NumAttrs] = lca
|
||
|
lc.NumAttrs++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// RemoveAttribute removes an attribute from the configuration.
|
||
|
func (lc *LineConfig) RemoveAttribute(lca LineConfigAttribute) {
|
||
|
d := 0
|
||
|
for s := 0; s < int(lc.NumAttrs); s++ {
|
||
|
if lc.Attrs[s] != lca {
|
||
|
if d != s {
|
||
|
lc.Attrs[d] = lc.Attrs[s]
|
||
|
}
|
||
|
d++
|
||
|
}
|
||
|
}
|
||
|
lc.NumAttrs = uint32(d)
|
||
|
}
|
||
|
|
||
|
// RemoveAttributeID removes all attributes with a given ID from the configuration.
|
||
|
func (lc *LineConfig) RemoveAttributeID(id LineAttributeID) {
|
||
|
d := 0
|
||
|
for s := 0; s < int(lc.NumAttrs); s++ {
|
||
|
if lc.Attrs[s].Attr.ID != id {
|
||
|
if d != s {
|
||
|
lc.Attrs[d] = lc.Attrs[s]
|
||
|
}
|
||
|
d++
|
||
|
}
|
||
|
}
|
||
|
lc.NumAttrs = uint32(d)
|
||
|
}
|
||
|
|
||
|
// LineRequest is a request for control of a set of lines.
|
||
|
// The lines must all be on the same GPIO chip.
|
||
|
type LineRequest struct {
|
||
|
// The lines to be requested.
|
||
|
Offsets [LinesMax]uint32
|
||
|
|
||
|
// The string identifying the requester to be applied to the lines.
|
||
|
Consumer [nameSize]byte
|
||
|
|
||
|
// The configuration for the requested lines
|
||
|
Config LineConfig
|
||
|
|
||
|
// The number of lines being requested.
|
||
|
Lines uint32
|
||
|
|
||
|
// Minimum size of the event buffer.
|
||
|
EventBufferSize uint32
|
||
|
|
||
|
// reserved for future use.
|
||
|
Padding [lineRequestPadSize]uint32
|
||
|
|
||
|
// The file handle for the requested lines.
|
||
|
// Set if the request is successful.
|
||
|
Fd int32
|
||
|
}
|
||
|
|
||
|
// LineBitmap is a bitmap containing a bit for each line.
|
||
|
type LineBitmap uint64
|
||
|
|
||
|
// NewLineBits creates a new LineBitmap from an array of bit numbers.
|
||
|
func NewLineBits(vv ...int) LineBitmap {
|
||
|
var lb LineBitmap
|
||
|
for _, bit := range vv {
|
||
|
lb = lb.Set(bit, 1)
|
||
|
}
|
||
|
return lb
|
||
|
}
|
||
|
|
||
|
// NewLineBitmap creates a bitmap from an array of bit values.
|
||
|
func NewLineBitmap(vv ...int) LineBitmap {
|
||
|
var lb LineBitmap
|
||
|
for i, v := range vv {
|
||
|
lb = lb.Set(i, v)
|
||
|
}
|
||
|
return lb
|
||
|
}
|
||
|
|
||
|
// NewLineBitMask returns a mask of n bits.
|
||
|
func NewLineBitMask(n int) LineBitmap {
|
||
|
if n >= LinesMax {
|
||
|
n = LinesMax
|
||
|
}
|
||
|
if n == LinesMax {
|
||
|
return 0xffffffffffffffff
|
||
|
}
|
||
|
return (LineBitmap(1) << uint(n)) - 1
|
||
|
}
|
||
|
|
||
|
// Get returns the value of the nth bit.
|
||
|
func (lb LineBitmap) Get(n int) int {
|
||
|
mask := LineBitmap(1) << uint(n)
|
||
|
if lb&mask != 0 {
|
||
|
return 1
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
// Set sets the value of the nth bit.
|
||
|
func (lb LineBitmap) Set(n, v int) LineBitmap {
|
||
|
mask := LineBitmap(1) << uint(n)
|
||
|
if v == 0 {
|
||
|
return lb &^ mask
|
||
|
}
|
||
|
return lb | mask
|
||
|
}
|
||
|
|
||
|
// LineValues contains the output values for a set of lines.
|
||
|
type LineValues struct {
|
||
|
// Bits contains the logical value of the the lines.
|
||
|
//
|
||
|
// Zero is a logical low (inactive) and 1 is a logical high (active).
|
||
|
//
|
||
|
// This is a bitmap of lines in LineRequest.Offsets.
|
||
|
Bits LineBitmap
|
||
|
|
||
|
// Mask identifies the lines to which this attribute applies.
|
||
|
//
|
||
|
// This is a bitmap of lines in LineRequest.Offsets.
|
||
|
Mask LineBitmap
|
||
|
}
|
||
|
|
||
|
// Get returns the value of the nth bit.
|
||
|
func (lv LineValues) Get(n int) int {
|
||
|
mask := LineBitmap(1) << uint(n)
|
||
|
if lv.Bits&mask != 0 {
|
||
|
return 1
|
||
|
}
|
||
|
return 0
|
||
|
}
|
||
|
|
||
|
// LineEventID indicates the type of event detected.
|
||
|
type LineEventID uint32
|
||
|
|
||
|
const (
|
||
|
// LineEventRisingEdge indicates the event is a rising edge.
|
||
|
LineEventRisingEdge LineEventID = iota + 1
|
||
|
|
||
|
// LineEventFallingEdge indicates the event is a falling edge.
|
||
|
LineEventFallingEdge
|
||
|
)
|
||
|
|
||
|
// LineEvent contains the details of a particular line event.
|
||
|
//
|
||
|
// This is returned via the event request fd in response to events.
|
||
|
type LineEvent struct {
|
||
|
// The time the event was detected.
|
||
|
Timestamp uint64
|
||
|
|
||
|
// The type of event detected.
|
||
|
ID LineEventID
|
||
|
|
||
|
// The line that triggered the event.
|
||
|
Offset uint32
|
||
|
|
||
|
// The seqno for this event in all events on all lines in this line request.
|
||
|
Seqno uint32
|
||
|
|
||
|
// The seqno for this event in all events in this line.
|
||
|
LineSeqno uint32
|
||
|
|
||
|
// reserved for future use
|
||
|
Padding [lineEventPadSize]uint32
|
||
|
}
|