Skip to content

USB-HID keyboard: Write can drop/corrupt HID reports, leaving keys stuck #5459

@rdon-key

Description

@rdon-key

machine/usb/hid/keyboard.Write can produce corrupted host-visible output even when called from a single goroutine.

In one run, the host started repeating 7, which looks like a stuck key state.

Environment

tinygo version 0.41.1 windows/amd64 (using go version go1.26.4 and LLVM version 20.1.1)
target: pico
scheduler: tasks
host: Windows

Reproducer

package main

import (
	"machine/usb/hid/keyboard"
	"time"
)

var kb = keyboard.Port()

func append3(b []byte, n int) []byte {
	b = append(b, byte('0'+(n/100)%10))
	b = append(b, byte('0'+(n/10)%10))
	b = append(b, byte('0'+n%10))
	return b
}

func main() {
	time.Sleep(3 * time.Second)

	kb.Write([]byte("\nBEGIN 100 WRITES\n"))

	var line [16]byte

	for i := 0; i < 100; i++ {
		b := line[:0]
		b = append3(b, i)
		b = append(b, ':', ' ')
		b = append(b, 'a', 'b', '\n')

		// Single goroutine, 100 writes only.
		kb.Write(b)
	}

	kb.Write([]byte("END 100 WRITES\n"))

	for {
		time.Sleep(time.Second)
	}
}

Run:

tinygo flash -target=pico -scheduler=tasks main.go

Expected output

The host should receive the lines in order:

BEGIN 100 WRITES
000: ab
001: ab
002: ab
003: ab
004: ab
005: ab
...
099: ab
END 100 WRITES

Actual output

One run produced:

BEGIN 100 WRITES
000: ab
001: ab
002: ab
003: ab
004: ab
005: ab0a77777777777777777777777777777

After that, the host appeared to keep repeating 7, as if the key was still pressed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions