Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gpioioctl: Improve Registration #64

Merged
merged 3 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions gpioioctl/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,16 @@
package gpioioctl

import (
"log"
"testing"

"periph.io/x/conn/v3/gpio"
"periph.io/x/conn/v3/gpio/gpioreg"
)

var testLine *GPIOLine

func init() {
var err error

if len(Chips) == 0 {
makeDummyChip()
line := GPIOLine{
number: 0,
name: "DummyGPIOLine",
consumer: "",
edge: gpio.NoEdge,
pull: gpio.PullNoChange,
direction: LineDirNotSet,
}

chip := GPIOChip{name: "DummyGPIOChip",
path: "/dev/gpiochipdummy",
label: "Dummy GPIOChip for Testing Purposes",
lineCount: 1,
lines: []*GPIOLine{&line},
}
Chips = append(Chips, &chip)
if err = gpioreg.Register(&line); err != nil {
nameStr := chip.Name()
lineStr := line.String()
log.Println("chip", nameStr, " gpioreg.Register(line) ", lineStr, " returned ", err)
}
}
}

Expand Down
1 change: 0 additions & 1 deletion gpioioctl/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ func makeDummyChip() {
lines: []*GPIOLine{&line},
}
Chips = append(Chips, &chip)
Chips = append(Chips, &chip)
if err := gpioreg.Register(&line); err != nil {
nameStr := chip.Name()
lineStr := line.String()
Expand Down
85 changes: 71 additions & 14 deletions gpioioctl/gpio.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"path"
"path/filepath"
"runtime"
"sort"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -402,6 +403,9 @@

chip.name = strings.Trim(string(info.name[:]), "\x00")
chip.label = strings.Trim(string(info.label[:]), "\x00")
if len(chip.label) == 0 {
chip.label = chip.name
}

Check warning on line 408 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L406-L408

Added lines #L406 - L408 were not covered by tests
chip.lineCount = int(info.lines)
var line_info gpio_v2_line_info
for line := 0; line < int(info.lines); line++ {
Expand Down Expand Up @@ -591,32 +595,85 @@
//
// https://docs.kernel.org/userspace-api/gpio/chardev.html
func (d *driverGPIO) Init() (bool, error) {
if runtime.GOOS == "linux" {
items, err := filepath.Glob("/dev/gpiochip*")
if err != nil {
return true, err
}
if len(items) == 0 {
return false, errors.New("no GPIO chips found")
Chips = make([]*GPIOChip, 0)
gsexton marked this conversation as resolved.
Show resolved Hide resolved
if runtime.GOOS != "linux" {
return true, nil
}
items, err := filepath.Glob("/dev/gpiochip*")
if err != nil {
return true, fmt.Errorf("gpioioctl: %w", err)
}
if len(items) == 0 {
return false, errors.New("no GPIO chips found")
}

Check warning on line 608 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L598-L608

Added lines #L598 - L608 were not covered by tests
// First, get all of the chips on the system.
chips := make([]*GPIOChip, 0)
gsexton marked this conversation as resolved.
Show resolved Hide resolved
var chip *GPIOChip
for _, item := range items {
chip, err = newGPIOChip(item)
if err == nil {
chips = append(chips, chip)
} else {
log.Println("gpioioctl.driverGPIO.Init() Error", err)

Check warning on line 617 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L610-L617

Added lines #L610 - L617 were not covered by tests
}
Chips = make([]*GPIOChip, 0)
for _, item := range items {
chip, err := newGPIOChip(item)
if err != nil {
log.Println("gpioioctl.driverGPIO.Init() Error", err)
return false, err
}
// Now, sort the chips so that those labeled with pinctrl- ( a Pi kernel standard)
// come first. Otherwise, sort them by label. This _should_ protect us from any
// random changes in chip naming/ordering.
sort.Slice(chips, func(i, j int) bool {
I := chips[i]
J := chips[j]
if I.Label()[:8] == "pinctrl-" {
gsexton marked this conversation as resolved.
Show resolved Hide resolved
if J.Label()[:8] == "pinctrl-" {
return I.Label() < J.Label()
} else {
gsexton marked this conversation as resolved.
Show resolved Hide resolved
return true

Check warning on line 630 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L623-L630

Added lines #L623 - L630 were not covered by tests
}
} else if J.Label()[:8] == "pinctrl-" {
return false
} else {
gsexton marked this conversation as resolved.
Show resolved Hide resolved
return I.Label() < J.Label()
}

Check warning on line 636 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L632-L636

Added lines #L632 - L636 were not covered by tests
})

mName := make(map[string]bool, 0)
gsexton marked this conversation as resolved.
Show resolved Hide resolved
// Get a list of already registered GPIO Line names.
registeredPins := make(map[string]bool)
gsexton marked this conversation as resolved.
Show resolved Hide resolved
for _, pin := range gpioreg.All() {
registeredPins[pin.Name()] = true
}

Check warning on line 644 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L639-L644

Added lines #L639 - L644 were not covered by tests

// Now, iterate over the chips we found and add their lines to conn/gpio/gpioreg
for _, chip := range chips {
// On a pi, gpiochip0 is also symlinked to gpiochip4, checking the map
// ensures we don't duplicate the chip.
if _, found := mName[chip.Name()]; !found {

Check warning on line 650 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L647-L650

Added lines #L647 - L650 were not covered by tests
Chips = append(Chips, chip)
mName[chip.Name()] = true
// Now, iterate over the lines on this chip.

Check warning on line 653 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L652-L653

Added lines #L652 - L653 were not covered by tests
for _, line := range chip.lines {
// If the line has some sort of reasonable name...

Check warning on line 655 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L655

Added line #L655 was not covered by tests
if len(line.name) > 0 && line.name != "_" && line.name != "-" {
// See if the name is already registered. On the Pi5, there are at
// least two chips that export "2712_WAKE" as the line name.
if _, ok := registeredPins[line.Name()]; ok {
// This is a duplicate name. Prefix the line name with the
// chip name.
line.name = chip.Name() + "-" + line.Name()
if _, found := registeredPins[line.Name()]; found {
// It's still not unique. Skip it.
continue

Check warning on line 665 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L657-L665

Added lines #L657 - L665 were not covered by tests
}
}
registeredPins[line.Name()] = true

Check warning on line 668 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L668

Added line #L668 was not covered by tests
if err = gpioreg.Register(line); err != nil {
log.Println("chip", chip.Name(), " gpioreg.Register(line) ", line, " returned ", err)
}
}
}
}
}
return true, nil
return len(Chips) > 0, nil

Check warning on line 676 in gpioioctl/gpio.go

View check run for this annotation

Codecov / codecov/patch

gpioioctl/gpio.go#L676

Added line #L676 was not covered by tests
}

var drvGPIO driverGPIO
Expand Down
Loading