From @kedare
Hmm I could not make it work so far, I found a few issues so far:
Dev.Bounds() is always (0,0),(0,0), it's not properly set as it should automatically depending on the model (I had to force is via Opts.Height and Opts.Width)
When Drawing, it would randomly fail with the following logs :
2025/03/02 19:22:47 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
2025/03/02 19:22:48 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
2025/03/02 19:22:48 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
2025/03/02 19:22:48 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
Which apparently correspond to this : https://github.com/pimoroni/inky/issues/205
But on the python implementation this is not making the drawing fail, those are just warnings, it looks like on the Go implementation this stops the drawing (can't confirm as I can't draw at all)
When not raising the previous error, it's not actually drawing anything, it does block however the code like if it was indeed drawing something (around 40s)
This is the code I am using: https://github.com/kedare/dashink/blob/main/pkg/hardware/host.go
Thanks
To Reproduce
Steps to reproduce the behavior:
- Modify the cmd/inky program call inky.NewImpression()
- Build the program and call with an appropriate image.
Output:
2025/03/02 19:22:47 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
in my instrumented version, I get:
inky: GPIOLine(27).Out(): line_request chip_fd=7, ioctl: bad file descriptor.
Expected behavior
The program should render the image on the Display
Platform (please complete the following information):
- OS: Raspbian Bookworm
- Board Raspbery Pi 5 w/ 8GB
- Device Inky Impression 7.3
Additional context
I changed the program to use the gpioioctl package directly since the impression file depends upon WaitForEdge(). The issue is coming in this function:
// Render renders the content of the [*DevImpression.Pix] to the screen.
func (d *DevImpression) Render() error {
fmt.Println("In Render() Press Enter to begin render calls.")
fmt.Scanln()
if d.flipVertically {
for w := 0; w < len(d.Pix)/2-1; w = w + d.width {
for offset := 0; offset < d.width; offset++ {
d.Pix[w+offset], d.Pix[len(d.Pix)-d.width-w+offset] = d.Pix[len(d.Pix)-d.width-w+offset], d.Pix[w+offset]
}
}
}
if d.flipHorizontally {
for offset := 0; offset < len(d.Pix)-1; offset = offset + d.width {
for i, j := 0, d.width-1; i < j; i, j = i+1, j-1 {
d.Pix[i+offset], d.Pix[j+offset] = d.Pix[j+offset], d.Pix[i+offset]
}
}
}
log.Println("Preparing to create Merged(). Press Enter to Begin")
fmt.Scanln()
merged := make([]uint8, len(d.Pix)/2)
log.Printf("len merged=%d\n Press Enter to continue", len(merged))
fmt.Scanln()
for i, offset := 0, 0; i < len(d.Pix)-1; i, offset = i+2, offset+1 {
merged[offset] = (d.Pix[i]<<4)&0xF0 | d.Pix[i+1]&0x0F
log.Printf("offset=%d", offset)
}
log.Println("Merged created.")
log.Println("In Render() Press Enter to call Update()")
fmt.Scanln()
return d.update(merged)
}
When I run the Linux command lsof -p pid at the step Preparing to create Merged(). Press Enter to Begin, I see the following:
gsexton@raspberrypi:/proc/7019/fd $ ps xfa | grep main
14698 pts/0 Sl+ 0:00 | \_ ./main -image /home/gsexton/George.png
gsexton@raspberrypi:/proc/7019/fd $ lsof -p 14698
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
main 14698 gsexton cwd DIR 179,2 4096 649617 /home/gsexton/periph/x/cmd/inky
main 14698 gsexton rtd DIR 179,2 4096 2 /
main 14698 gsexton txt REG 179,2 4169165 657764 /home/gsexton/periph/x/cmd/inky/main
main 14698 gsexton 0u CHR 136,0 0t0 3 /dev/pts/0
main 14698 gsexton 1u CHR 136,0 0t0 3 /dev/pts/0
main 14698 gsexton 2u CHR 136,0 0t0 3 /dev/pts/0
main 14698 gsexton 3r REG 179,2 20475 95166 /home/gsexton/George.png
main 14698 gsexton 4u a_inode 0,14 0 1183 [eventpoll:5,6,7,8,9,10,11,12]
main 14698 gsexton 5u a_inode 0,14 0 1183 [eventfd:191]
main 14698 gsexton 6r CHR 254,0 0t0 132 /dev/gpiochip0
main 14698 gsexton 7r CHR 254,10 0t0 88 /dev/gpiochip10
main 14698 gsexton 8r CHR 254,11 0t0 89 /dev/gpiochip11
main 14698 gsexton 9r CHR 254,12 0t0 90 /dev/gpiochip12
main 14698 gsexton 10r CHR 254,13 0t0 91 /dev/gpiochip13
main 14698 gsexton 11r CHR 254,0 0t0 132 /dev/gpiochip0
main 14698 gsexton 12w REG 0,18 16384 3709 /sys/class/gpio/export
main 14698 gsexton 13u CHR 153,1 0t0 665 /dev/spidev0.0
when I press enter, and this is executed:
merged := make([]uint8, len(d.Pix)/2)
log.Printf("len merged=%d\n Press Enter to continue", len(merged))
fmt.Scanln()
the program output is:
2025/03/29 14:28:26 len merged=192000
Press Enter to continue
running lsof -p again shows the expected gpiochip file handles open. Pressing ENTER to execute the code:
for i, offset := 0, 0; i < len(d.Pix)-1; i, offset = i+2, offset+1 {
merged[offset] = (d.Pix[i]<<4)&0xF0 | d.Pix[i+1]&0x0F
log.Printf("offset=%d", offset)
}
log.Println("Merged created.")
log.Println("In Render() Press Enter to call Update()")
fmt.Scanln()
the output is:
2025/03/29 14:54:05 offset=191999
2025/03/29 14:54:05 Merged created.
and then re-running lsof -p shows:
gsexton@raspberrypi:/proc/7019/fd $ lsof -p 14698
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
main 14698 gsexton cwd DIR 179,2 4096 649617 /home/gsexton/periph/x/cmd/inky
main 14698 gsexton rtd DIR 179,2 4096 2 /
main 14698 gsexton txt REG 179,2 4169165 657764 /home/gsexton/periph/x/cmd/inky/main
main 14698 gsexton 0u CHR 136,0 0t0 3 /dev/pts/0
main 14698 gsexton 1u CHR 136,0 0t0 3 /dev/pts/0
main 14698 gsexton 2u CHR 136,0 0t0 3 /dev/pts/0
main 14698 gsexton 3r REG 179,2 20475 95166 /home/gsexton/George.png
main 14698 gsexton 4u a_inode 0,14 0 1183 [eventpoll:5,12]
main 14698 gsexton 5u a_inode 0,14 0 1183 [eventfd:191]
main 14698 gsexton 12w REG 0,18 16384 3709 /sys/class/gpio/export
main 14698 gsexton 13u CHR 153,1 0t0 665 /dev/spidev0.0
Note that the file descriptors to /dev/gpiochip* are gone. The error is being returned by cycleResetGPIO() because the Out() command is attempting to use the gpiochip0 file descriptor to perform an ioctl() for the pin:
func (d *DevImpression) cycleResetGPIO() error {
if err := d.r.Out(gpio.Low); err != nil {
return err
}
time.Sleep(100 * time.Millisecond)
return d.r.Out(gpio.High)
}
The behavior isn't perfectly consistent. Sometimes creating the slice is enough to change the output of lsof, sometimes it isn't until the loop is done. It is not 100% consistent that it happens, but when it does, it's in one of those two spots.
The mainImpl() function has a reference to a gpioioctl.Chip[0],
I instrumented the GPIO chip to print when Close() is called, and that's not happening.
Also, I ran it under strace and don't see close calls with any of the affected file descriptors. On ArmV6, the ioctl error does not occur, but it just doesn't work. There are probably multiple issues.
@maruel Can you look at this? I'm stumped. It seems like either some sort of memory overwrite is happening, or something is garbage collecting things. I confirmed that the length of gpioioctl.Chips[0] is still well-constructed after the error happens, so it doesn't look like Init() is called twice making things strange.
From @kedare
To Reproduce
Steps to reproduce the behavior:
Output:
2025/03/02 19:22:47 impression.go:558: Err: bcm283x-gpio (GPIO17): line_request ioctl: bad file descriptor
in my instrumented version, I get:
inky: GPIOLine(27).Out(): line_request chip_fd=7, ioctl: bad file descriptor.
Expected behavior
The program should render the image on the Display
Platform (please complete the following information):
Additional context
I changed the program to use the gpioioctl package directly since the impression file depends upon WaitForEdge(). The issue is coming in this function:
When I run the Linux command lsof -p pid at the step Preparing to create Merged(). Press Enter to Begin, I see the following:
when I press enter, and this is executed:
the program output is:
running lsof -p again shows the expected gpiochip file handles open. Pressing ENTER to execute the code:
the output is:
and then re-running lsof -p shows:
Note that the file descriptors to /dev/gpiochip* are gone. The error is being returned by cycleResetGPIO() because the Out() command is attempting to use the gpiochip0 file descriptor to perform an ioctl() for the pin:
The behavior isn't perfectly consistent. Sometimes creating the slice is enough to change the output of lsof, sometimes it isn't until the loop is done. It is not 100% consistent that it happens, but when it does, it's in one of those two spots.
The mainImpl() function has a reference to a gpioioctl.Chip[0],
I instrumented the GPIO chip to print when Close() is called, and that's not happening.
Also, I ran it under strace and don't see close calls with any of the affected file descriptors. On ArmV6, the ioctl error does not occur, but it just doesn't work. There are probably multiple issues.
@maruel Can you look at this? I'm stumped. It seems like either some sort of memory overwrite is happening, or something is garbage collecting things. I confirmed that the length of gpioioctl.Chips[0] is still well-constructed after the error happens, so it doesn't look like Init() is called twice making things strange.