gpio

package module
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 7, 2023 License: CC0-1.0 Imports: 9 Imported by: 4

README

What

gpio-cdev-go is pure Go library to access Linux 4.8+ GPIO chardev interface. GoDoc

Tested on:

  • ARMv6,7 RaspberryPi 1, OrangePi Lite
  • ARM64 RaspberryPi 3 B+

If you know how to make this work useful for more people, please take a minute to communicate:

Ultimate success would be to merge this functionality into periph.io lib.

Usage

Low level, bare ioctl API is provided by set of Raw* functions.

High-level wrapper (see api.go) is recommended way to use library.

// Open GPIO chip device.
// Default consumer tag will be used if one is not provided to line management functions.
chip, err := gpio.Open("/dev/gpiochip0", "default-consumer")
defer chip.Close()

// Set lines via either `SetBulk(values ...byte)`
// or create setter closure with `SetFunc(line) -> func(bool)`
// Either way you should call `Flush()` to commit changes to hardware.
pins, err := chip.OpenLines(
  gpio.GPIOHANDLE_REQUEST_OUTPUT, "hd44780",
  nRS, nRW, nE, nD4, nD5, nD6, nD7,
)
defer pins.Close()

pins.SetBulk(1, 0, 0, 1, 1, 1, 1)
err := pins.Flush()

set_pin_d4 := pins.SetFunc(nD4)
set_pin_d4(true)
err := pins.Flush()

// Reading current lines state
pins, err := chip.OpenLines(gpio.GPIOHANDLE_REQUEST_INPUT, "consumer", uint32(line))
defer pins.Close()
data, err := pins.Read()
lineActive := data.Values[0] == 1

// Waiting for edge. REQUEST_INPUT flag is implied.
lineEvent, err := chip.GetLineEvent(uint32(notifyLine), /*RequestFlag*/ 0,
  gpio.GPIOEVENT_REQUEST_RISING_EDGE, "consumer")
defer lineEvent.Close()
currentValue, err := lineEvent.Read()
eventData, err := lineEvent.Wait(timeout) // 0 to block forever
ok := eventData.ID == GPIOEVENT_EVENT_RISING_EDGE

Possible issues

  • may leak req.fd descriptors, TODO test

Testing

  • get 2 free GPIO pins
  • jumper them
  • set environment variables and run tests
export GPIO_TEST_DEV="/dev/gpiochip0"
export GPIO_TEST_PIN="19"
export GPIO_TEST_PIN_LOOP="16"
go test ./...

Flair

Build status Coverage Go Report Card

Documentation

Index

Constants

View Source
const (
	GPIOEVENT_EVENT_RISING_EDGE  = 0x01
	GPIOEVENT_EVENT_FALLING_EDGE = 0x02
)
View Source
const (
	GPIO_GET_CHIPINFO_IOCTL          uintptr = 0x8044b401
	GPIO_GET_LINEINFO_IOCTL          uintptr = 0xc048b402
	GPIO_GET_LINEHANDLE_IOCTL        uintptr = 0xc16cb403
	GPIO_GET_LINEEVENT_IOCTL         uintptr = 0xc030b404
	GPIOHANDLE_GET_LINE_VALUES_IOCTL uintptr = 0xc040b408
	GPIOHANDLE_SET_LINE_VALUES_IOCTL uintptr = 0xc040b409
)

From <include/uapi/linux/gpio.h> tested to be same on 386,arm,arm64,amd64 see ioctl_linux_test.go to see how they were generated

View Source
const GPIOHANDLES_MAX = 64

Variables

View Source
var ErrClosed = errors.New("already closed")
View Source
var ErrTimeout error = errTimeout{}

Functions

func IsClosed added in v0.10.0

func IsClosed(err error) bool

Please use this to check whether gpio.*.Close() was already called.

func IsTimeout added in v0.12.0

func IsTimeout(err error) bool

Or use any timeout error check you know, and please report if some doesn't work.

func RawGetChipInfo

func RawGetChipInfo(fd int, arg *ChipInfo) error

func RawGetLineEvent

func RawGetLineEvent(fd int, arg *EventRequest) error

func RawGetLineHandle

func RawGetLineHandle(fd int, arg *HandleRequest) error

func RawGetLineInfo

func RawGetLineInfo(fd int, arg *LineInfo) error

func RawGetLineValues

func RawGetLineValues(fd int, arg *HandleData) error

func RawSetLineValues

func RawSetLineValues(fd int, arg *HandleData) error

Types

type ChipInfo

type ChipInfo struct {
	// the Linux kernel name of this GPIO chip
	Name [32]byte

	// a functional name for this GPIO chip, such as a product number, may be NULL
	Label [32]byte

	// number of GPIO lines on this chip
	Lines uint32
}

struct gpiochip_info - Information about a certain GPIO chip

func (*ChipInfo) String

func (self *ChipInfo) String() string

type Chiper added in v0.9.0

type Chiper interface {
	io.Closer
	Info() ChipInfo
	LineInfo(line uint32) (LineInfo, error)
	OpenLines(flag RequestFlag, consumerLabel string, lines ...uint32) (Lineser, error)
	GetLineEvent(line uint32, flag RequestFlag, events EventFlag, consumerLabel string) (Eventer, error)
}

func Open

func Open(path, defaultConsumer string) (Chiper, error)

The entry point to this library. `path` is likely "/dev/gpiochipN" `defaultConsumer` will be used in absence of more specific consumer label

to OpenLines/GetLineEvent.

Makes two syscalls: open(path), ioctl(GET_CHIPINFO) You must call Chiper.Close()

type EventData

type EventData struct {
	// best estimate of time of event occurrence, in nanoseconds
	Timestamp uint64

	// event identifier (e.g. rising/falling edge)
	ID EventID
	// contains filtered or unexported fields
}

struct gpioevent_data - The actual event being pushed to userspace

type EventFlag

type EventFlag uint32
const (
	GPIOEVENT_REQUEST_RISING_EDGE  EventFlag = 1 << 0
	GPIOEVENT_REQUEST_FALLING_EDGE EventFlag = 1 << 1
	GPIOEVENT_REQUEST_BOTH_EDGES   EventFlag = (1 << 0) | (1 << 1)
)

type EventID

type EventID uint32

type EventRequest

type EventRequest struct {
	// the desired line to subscribe to events from, specified by
	// offset index for the associated GPIO device
	LineOffset uint32

	// desired handle flags for the desired GPIO line, such as
	// GPIOHANDLE_REQUEST_ACTIVE_LOW or GPIOHANDLE_REQUEST_OPEN_DRAIN
	RequestFlags RequestFlag

	// desired flags for the desired GPIO event line, such as
	// GPIOEVENT_REQUEST_RISING_EDGE or GPIOEVENT_REQUEST_FALLING_EDGE
	EventFlags EventFlag

	// a desired consumer label for the selected GPIO line(s)
	// such as "my-listener"
	ConsumerLabel [32]byte

	// if successful this field will contain a valid anonymous file handle
	// after a GPIO_GET_LINEEVENT_IOCTL operation, zero or negative value means error
	Fd int32
}

type Eventer added in v0.9.0

type Eventer interface {
	io.Closer
	Read() (byte, error)
	Wait(timeout time.Duration) (EventData, error)
}

type HandleData

type HandleData struct {
	// GET: contains the current state of a line,
	// SET: the desired target state
	Values [GPIOHANDLES_MAX]byte
}

struct gpiohandle_data - Information of values on a GPIO handle

type HandleRequest

type HandleRequest struct {
	// an array of desired lines, specified by offset index for the associated GPIO device
	LineOffsets [GPIOHANDLES_MAX]uint32

	// desired flags for the desired GPIO lines, such as
	// GPIOHANDLE_REQUEST_OUTPUT, GPIOHANDLE_REQUEST_ACTIVE_LOW etc, OR:ed
	// together. Note that even if multiple lines are requested, the same flags
	// must be applicable to all of them, if you want lines with individual
	// flags set, request them one by one. It is possible to select
	// a batch of input or output lines, but they must all have the same
	// characteristics, i.e. all inputs or all outputs, all active low etc
	Flags RequestFlag

	// if the GPIOHANDLE_REQUEST_OUTPUT is set for a requested
	// line, this specifies the default output value, should be 0 (low) or
	// 1 (high), anything else than 0 or 1 will be interpreted as 1 (high)
	// @consumer_label: a desired consumer label for the selected GPIO line(s)
	// such as "my-bitbanged-relay"
	DefaultValues [GPIOHANDLES_MAX]byte

	// a desired consumer label for the selected GPIO line(s)
	// such as "my-bitbanged-relay"
	ConsumerLabel [32]byte

	// number of lines requested in this request, i.e. the number of
	// valid fields in the above arrays, set to 1 to request a single line
	Lines uint32

	// if successful this field will contain a valid anonymous file handle
	// after a GPIO_GET_LINEHANDLE_IOCTL operation, zero or negative value
	// means error
	Fd int32
}

struct gpiohandle_request - Information about a GPIO handle request

type LineFlag

type LineFlag uint32
const (
	GPIOLINE_FLAG_KERNEL      LineFlag = 1 << 0 /* Line used by the kernel */
	GPIOLINE_FLAG_IS_OUT      LineFlag = 1 << 1
	GPIOLINE_FLAG_ACTIVE_LOW  LineFlag = 1 << 2
	GPIOLINE_FLAG_OPEN_DRAIN  LineFlag = 1 << 3
	GPIOLINE_FLAG_OPEN_SOURCE LineFlag = 1 << 4
)

type LineInfo

type LineInfo struct {
	// the local offset on this GPIO device, fill this in when
	// requesting the line information from the kernel
	LineOffset uint32

	Flags LineFlag

	// the name of this GPIO line, such as the output pin of the line on the
	// chip, a rail or a pin header name on a board, as specified by the gpio
	// chip, may be NULL
	Name [32]byte

	// a functional name for the consumer of this GPIO line as set by
	// whatever is using it, will be NULL if there is no current user but may
	// also be NULL if the consumer doesn't set this up
	Consumer [32]byte
}

struct gpioline_info - Information about a certain GPIO line

func (*LineInfo) ConsumerString added in v0.11.0

func (li *LineInfo) ConsumerString() string

func (*LineInfo) NameString added in v0.11.0

func (li *LineInfo) NameString() string

func (*LineInfo) String added in v0.11.0

func (li *LineInfo) String() string

type LineSetFunc

type LineSetFunc func(value byte)

type Lineser added in v0.9.0

type Lineser interface {
	io.Closer
	SetFunc(line uint32) LineSetFunc
	LineOffsets() []uint32
	Read() (HandleData, error)
	Flush() error
	SetBulk(bs ...byte)
}

type RequestFlag

type RequestFlag uint32
const (
	GPIOHANDLE_REQUEST_INPUT       RequestFlag = 1 << 0
	GPIOHANDLE_REQUEST_OUTPUT      RequestFlag = 1 << 1
	GPIOHANDLE_REQUEST_ACTIVE_LOW  RequestFlag = 1 << 2
	GPIOHANDLE_REQUEST_OPEN_DRAIN  RequestFlag = 1 << 3
	GPIOHANDLE_REQUEST_OPEN_SOURCE RequestFlag = 1 << 4
)

Directories

Path Synopsis
cmd
Use to stub gpio in your tests.
Use to stub gpio in your tests.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL