commit b75bff36f7a910da3cce4ddaecee31f02deae9ed
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Mon Mar 9 02:02:59 2026 -0400

    Update GRUB documentation to reflect working braille support.
    
    README.Grub:
    - Add sections on key table installation, configuration via
      environment variables, QEMU testing, and how the module works.
    - Update troubleshooting with key table and xHCI guidance.
    - Document the go-grub and grub-test scripts.
    - Update USB controller guidance (UHCI/OHCI/EHCI, not xHCI).
    
    GRUB-Module-Design.md:
    - Update section 5.4 to reflect actual implementation (direct
      brlttyConstruct from GRUB_MOD_INIT with hardcoded argv).
    - Rewrite section 8 to reflect working end-to-end status.
    - Document known limitations (snprintf %.*s, xHCI, EFI handles).
    - Add future work items (command registration, real hardware).
    - Update getopt and system_grub.c descriptions.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit e20e71532a582689a6254c923a3394d23e9a66e4
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Mon Mar 9 01:58:51 2026 -0400

    Update test scripts: all tables, auto-detect device, faster hotplug.
    
    grub-test:
    - Copy all key tables and text tables to disk image instead of only
      HumanWare files, matching the full driver list.
    - Replace hotplug blind sleep with serial log polling — wait for
      GRUB to print "brltty module loaded" before hotplugging the USB
      device.
    - Update hotplug comment explaining why it is necessary (OVMF claims
      devices present at startup).
    
    go-grub:
    - Auto-detect the braille USB device from /sys/bus/usb/drivers/usbfs
      instead of hardcoding vendor:product ID. BRLTTY claims devices via
      usbfs, so its bindings in sysfs reveal the device.
    - Log all output to grub-test.d/go.log for review after the host
      BRLTTY restarts (braille display is unavailable during the test).
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit adfee8a47c74797fa57ba999c3f6aa15e413935e
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Mon Mar 9 01:56:01 2026 -0400

    Improve GRUB USB backend: logging, write delay, and error handling.
    
    - Add debug logging throughout USB operations (control transfers,
      bulk reads/writes, device iteration) for diagnosability.
    - Add formatHex() helper for logging raw USB data.
    - Add 50ms delay after bulk writes: GRUB's USB stack does synchronous
      polled transfers with no hardware queuing, so the host can read
      before the device has processed a command and prepared its reply.
    - Clear grub_errno before USB operations to prevent stale file I/O
      errors from being misinterpreted as USB failures.
    - Initialize bulk read actual length to 0 before the call.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit dedb53368c8d2fe184ccd575825de14b5860cdbd
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Mon Mar 9 01:55:09 2026 -0400

    Configure tables directory and clean up GRUB module entry point.
    
    - Pass -T /boot/grub/brltty to brlttyConstruct() so key tables are
      found on the GRUB filesystem. Without this, BRLTTY cannot load
      key bindings and display keys are unresponsive.
    - Remove stale debug printf and verbose comment block.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 9347967c3c412885ad2c61d5dd536347f2d15064
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Mon Mar 9 01:54:27 2026 -0400

    Fix POSIX shims for GRUB: memcmp, qsort, and path normalization.
    
    - Add memcmp() implementation: GRUB's posix_wrap #defines memcmp to
      grub_memcmp, but the macro is suppressed when we define the real
      function, so we need our own byte-comparison loop.
    - Fix qsort() to allocate the temp buffer once via grub_malloc instead
      of using a VLA inside the inner loop (redundant allocation per
      iteration).
    - Add normalize_path() to resolve "." and ".." components in file
      paths. GRUB's grub_file_open does not handle ".." — key table
      files use relative includes like "../chords.kti" which fail without
      normalization.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit e43e0dd3839e280eb0696fea9131f7b5149542fe
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Mon Mar 9 01:54:05 2026 -0400

    Add GRUB build target and fix cross-compilation attribute detection.
    
    - Add GRUB_BUILD autoconf substitution so `make all` in Programs/
      builds brltty.mod instead of the normal host targets when
      configured for the GRUB (elf*) platform.
    - Force-enable packed and unused variable attributes in cfg-grub:
      autoconf's test program compiles but can't link/run in freestanding
      mode, so detection fails. Without packed, USB protocol structs like
      USB_CDC_ACM_LineCoding gain padding and break the wire protocol.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit d9c6678001806b115021d7a0b3364387c3409f21
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Mon Mar 9 01:18:23 2026 -0400

    Always send SET_INTERFACE even for a single alternate setting.
    
    When an interface has only one alternate setting, the code previously
    skipped the SET_INTERFACE request entirely ("nothing to choose").
    However, USB 2.0 §9.1.1.5 specifies that SET_INTERFACE resets the
    data toggle for all endpoints in the interface to DATA0. Without
    this reset, stale toggle state (from a previous session, a failed
    transfer, or an incomplete reset) can cause the device and host to
    disagree on the expected DATA0/DATA1 sequence, silently dropping
    bulk packets.
    
    Linux's cdc_acm driver always issues SET_INTERFACE regardless of
    the alternate setting count, for exactly this reason.
    
    This was observed with HumanWare Brailliant displays under GRUB's
    minimal USB stack, which does not always reset toggles during
    SET_CONFIGURATION. The fix follows the spec and should be harmless
    on well-behaved devices, since SET_INTERFACE(0, 0) is a valid
    no-op selection that every compliant device must accept.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit b0f5ff5b79be3ce76ae58dac1a5fc8661be291e9
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Mon Mar 9 01:06:39 2026 -0400

    Fix include path construction for GRUB's limited snprintf.
    
    GRUB's grub_snprintf does not support the %.*s format specifier
    (precision via * argument), which misaligns the argument stack and
    produces garbage output. Replace with direct memcpy operations —
    the buffer is already correctly sized via VLA.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 65511be4d7482eb34aa85d820b275dd829abe530
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sun Mar 8 11:18:55 2026 -0400

    Implement getopt for GRUB and bootstrap the event loop.
    
    The getopt() stub returned -1 immediately, leaving all argv entries
    as unparsed positional parameters ("too many parameters" error).
    Replace with a minimal implementation that handles short options
    with required arguments, enough for brlttyConstruct()'s -l and -n.
    
    After brlttyConstruct(), pump brlttyWait(0) several times so the
    async alarm system fires and transitions the screen and braille
    driver activities from scheduled to started. The screen driver
    registers a grub_term_input whose getkey() callback calls
    brlttyWait(0) on every GRUB input poll, sustaining the event loop.
    
    Result: screen driver starts ("shadow terminal active 160x42"),
    braille driver autodetection cycles through all compiled-in drivers
    probing usb: transport, retrying periodically as designed.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 181dd63f90f8ed94a5d25c0328a7d0816eb78300
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sat Mar 7 23:39:47 2026 -0500

    Fix GRUB module loading: license, relocations, and build flags.
    
    Three bugs prevented brltty.mod from initializing inside GRUB:
    
    1. License string was "gpl3+" but GRUB's dl.c only accepts the
       exact strings "GPLv3", "GPLv3+", or "GPLv2+" (case-sensitive).
    
    2. Missing -mcmodel=large and -fno-PIC caused GCC to emit
       R_X86_64_REX_GOTPCRELX relocations that GRUB's x86_64 module
       loader does not implement. Added the full set of GRUB-required
       flags to cfg-grub (-mcmodel=large, -fno-PIC, -mno-red-zone,
       -msoft-float, etc.) and suppressed -fPIC in LIBCFLAGS for the
       elf* host target in configure.ac.
    
    3. Float division in cmd_touch.c failed with "SSE register return
       with SSE disabled" under -msoft-float. Replaced with equivalent
       integer comparison.
    
    Also: route BRLTTY log output to grub_printf() under GRUB_RUNTIME,
    update grub-test to embed modules via grub-mkimage (USB host-controller
    init invalidates EFI disk handles, breaking subsequent insmod), and
    prefer a locally-built GRUB tree when available.
    
    Tested: brlttyConstruct() returns PROG_EXIT_SUCCESS in QEMU/OVMF.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit a39c5652aff7e49e84e890b541446218822e139b
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sat Mar 7 22:23:19 2026 -0500

    Add GRUB module QEMU test script.
    
    grub-test builds an EFI disk image with GRUB + brltty.mod and boots it
    in QEMU for testing. Uses mtools (no root needed) to populate a FAT32
    ESP with the GRUB bootloader, USB stack modules, and brltty.mod. Serial
    console output is captured to a log file for analysis.
    
    Commands: build-image, run [--graphic|--usb-host=V:P], log, clean.
    
    Also add /grub-test.d to .gitignore for test artifacts.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 9f766c95580b2357504f45ae35587df612960c5c
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sat Mar 7 19:15:42 2026 -0500

    Add GRUB build artifacts to .gitignore.
    
    Ignore .mod/.module (GRUB loadable module outputs) and grub-root
    (symlink to local GRUB source tree used for header includes).
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit a204ff8abb1fd014f0391c4b56a9440c9c783486
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sat Mar 7 19:14:35 2026 -0500

    Fix GRUB .mod build: working objcopy/strip, resolve link errors.
    
    The brltty.mod target now produces a correct GRUB loadable module with
    .modname/.moddeps ELF sections and properly stripped symbols.
    
    Makefile.in: Replace undefined TARGET_OBJCOPY/TARGET_STRIP with explicit
    GRUB_OBJCOPY/GRUB_STRIP defaults. The old variables were never set by
    configure, causing objcopy to silently skip and strip to run as a broken
    command. Also add section removals from GRUB's upstream genmod.sh.
    
    prologue.h: Fix three compiler warnings in GRUB freestanding mode:
    - ARRAY_SIZE redefinition: #undef before sys/types.h pulls in grub/misc.h
    - PRIdPTR redefinition: consolidate into single #ifdef __INTPTR_FMTd__ block
    - __builtin_popcount: undef HAVE_BUILTIN_POPCOUNT to avoid __popcountdi2
      libgcc dependency (use manual bit-counting loop instead)
    
    async_io.c: Add asyncExecuteIoCallback stub for non-ASYNC_CAN_MONITOR_IO
    platforms (GRUB has no poll/select). Called unconditionally from
    async_wait.c but only defined inside #ifdef ASYNC_CAN_MONITOR_IO.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 8628899ea82e1e7b5c73971bc521dba7f72acdfd
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sat Mar 7 18:49:22 2026 -0500

    Complete GRUB freestanding POSIX compatibility layer.
    
    All BRLTTY source files now compile with zero errors and zero
    warnings in the GRUB freestanding environment (-nostdinc -nostdlib
    -ffreestanding). This required:
    
    POSIX stub headers (Headers/grub/):
    - time.h: struct tm, time_t, timespec/timeval; chains to GRUB's
      real grub/time.h for grub_get_time_ms()/grub_millisleep()
    - termios.h: struct termios and terminal control constants
    - signal.h: sig_atomic_t, sigset_t, signal numbers
    - fcntl.h: O_RDONLY etc., open() stub
    - sys/stat.h: struct stat with st_dev/st_ino
    - sys/ioctl.h: TIOCGWINSZ, struct winsize, ioctl() stub
    - strings.h, search.h: minimal stubs
    
    prologue.h GRUB_RUNTIME additions:
    - inttypes.h format macros (PRI[duxX]{8,16,32,64,PTR,MAX})
    - errno codes (EAGAIN, EIO, ENODEV, EBUSY, EINTR, EROFS, EPIPE)
    - Missing types (intptr_t, ino_t, dev_t, sig_atomic_t)
    - ffs() via __builtin_ffs
    - UINT16_C, INT16_MIN, UINT32_MAX
    - stdio stubs (fopen/fclose/fread/fwrite/fprintf/feof/ferror/
      fflush/fgets/fgetc/fputs/fputc/fileno, stdin/stdout/stderr)
    - fd I/O stubs (close/write/read)
    - getopt/optarg/optind/opterr/optopt
    - select()/fd_set/FD_ZERO/FD_SET/FD_ISSET
    - setvbuf/_IONBF
    - Locale stubs (setlocale, LC_ALL, LC_CTYPE)
    - Force HAVE_WCHAR_H and WCHAR_MAX for GRUB so wchar.h is
      included and wcs* macros don't conflict with GRUB's definitions
    - Wide-char functions (wcslen, wmemcpy, wmemcmp, wmemchr, wmemset,
      wcsncmp, wcschr, wcsrchr, wcscpy, wcstok, isw*, tow*)
    - Variadic ARRAY_SIZE macro supporting both GRUB's 1-arg and
      BRLTTY's 2-arg calling conventions
    
    system_grub.c additions:
    - strpbrk, strncasecmp, atoi
    - time/localtime/gmtime/strftime stubs
    - FILE operations via grub_file_open/grub_file_read/grub_file_close
    - fprintf routes stdout/stderr to grub_printf
    - getopt stub (returns -1; GRUB uses grub_register_command)
    - setlocale, vprintf, srand, unlink, rename, pipe, fdopen, freopen
    - setvbuf, select stubs
    
    NO_FLOAT guards:
    - color_types.h: guard HSVColor/HLSColor structs
    - color.h: guard float-using function declarations
    - color_internal.h: guard HSVComponentRange and related
    - color.c: guard all HSV/HLS conversion functions
    - cmdargs.h/cmdargs.c: guard parseFloat/parseDegrees/parsePercent
    - scr.c: guard RGB color name path (VGA path still works)
    
    Other fixes:
    - cfg-grub: add -Wno-incompatible-pointer-types for GRUB's
      strtol/strtoul const char** vs char** mismatch
    - timing.c: fix GRUB_RUNTIME struct tm member names
    - async_io.c: add MonitorEntry stub for platforms without poll/select
    - dynld_grub.c: stub findSharedSymbol (no GRUB symbol lookup API)
    - brltty-ttb.c: guard linux/kd.h with !GRUB_RUNTIME
    - charset_grub.c: add missing langinfo.h include
    
    Build reaches the link stage; link failure is expected because GRUB
    runtime symbols (grub_malloc, grub_free, etc.) are only available
    when loaded as a GRUB module (.mod), not as a standalone executable.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit c7bb92058bf4f732e0e5087a40fc3a8858eaf115
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sat Mar 7 17:42:31 2026 -0500

    Add GRUB system package with POSIX compatibility functions.
    
    Create system_grub.c providing implementations of POSIX functions
    that GRUB's freestanding environment lacks:
    
    - getenv() wrapping grub_env_get() for BRLTTY_* configuration
    - exit() mapping to grub_fatal()
    - strdup(), strtok(), strerror() string functions
    - qsort() and bsearch() for configuration file processing
    
    Register system_package="grub" for the elf* host case in configure.ac.
    
    Add corresponding function declarations and missing constants
    (UINT16_MAX, ENOENT, ENOSYS) to the GRUB_RUNTIME block in prologue.h
    so all BRLTTY source files see them.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 3256a56dc87af78d46b2473b88a7f0269da9ff7b
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sat Mar 7 17:20:17 2026 -0500

    Document GRUB environment variable support for BRLTTY configuration.
    
    BRLTTY has three configuration methods: command line, brltty.conf, and
    environment variables. All three can work under GRUB: command line via
    grub_register_command, brltty.conf via grub_file_open, and environment
    variables by mapping getenv() to grub_env_get(). The same BRLTTY_*
    variable names are used (e.g. set BRLTTY_BRAILLE_DRIVER=hw in grub.cfg).
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit d5563d15e09e1d7939108690981e91c9e899d99d
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Sat Mar 7 17:15:45 2026 -0500

    Add command registration and file access design for GRUB module.
    
    Document that GRUB's insmod doesn't pass arguments to modules, so
    BRLTTY registers a grub_register_command("brltty") that receives
    argc/argv for configuration (e.g. "brltty -b hw -q -n" in grub.cfg).
    
    Add Section 6 documenting how GRUB's file API (grub_file_open/read/
    close) can be used to load brltty.conf, key tables, and text tables
    from disk at boot time.
    
    Update POSIX compatibility strategy to distinguish dead code paths
    (compile out), GRUB-replaceable paths (wrap with grub_file_* API),
    and linker stubs. Update remaining work list accordingly.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit d8e901b2e18a0a7325e0787eab46dce861cc3277
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 22:01:42 2026 -0500

    Update documentation and fix build for configured GRUB tree.
    
    Update README.Grub to document that a configured GRUB source tree is
    required (bootstrap + configure), add multi-platform build instructions,
    and add autoconf to prerequisites.
    
    Rewrite GRUB-Module-Design.md to reflect current implementation status,
    document the freestanding POSIX compatibility issues found during the
    first build attempt, and describe the resolution strategy.
    
    Fix configure.ac include path ordering so -nostdinc comes before -isystem
    and -I flags, add -I for GRUB root (for config.h), and fix posix_wrap
    path. Fix cfg-grub to strip --with-grub-platform from configure args
    and override CPP.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit ac630eb1236f31588444485be06b3775a3da3a50
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 21:36:14 2026 -0500

    Create GRUB header symlinks for correct architecture targeting.
    
    GRUB headers use #include <grub/cpu/types.h> where "cpu" is a symlink
    to the target architecture directory. This symlink is normally created
    by GRUB's own configure, but since we only need the headers (not a full
    GRUB build), cfg-grub now creates it based on the detected platform.
    Also creates the grub/machine symlink for platform-specific headers,
    and validates that grub-root exists before proceeding.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 062d6e61470273d78ce2cb008f61517f0bb80983
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 21:29:00 2026 -0500

    Use native GCC toolchain for GRUB module builds.
    
    GRUB itself uses the native system GCC with -m32 or -m64 rather than
    a separate cross-compiler. Adapt cfg-grub to do the same:
    
    - Auto-detect the installed GRUB platform (x86_64-efi, i386-pc, etc.)
      from /boot/grub/ or allow override via --with-grub-platform=
    - Use the native gcc with appropriate -m32/-m64 flag
    - Override CC, LD, STRIP, RANLIB so autoconf doesn't look for
      i386-elf-* prefixed cross tools
    - Keep --host=i386-elf to trigger GRUB_RUNTIME detection in configure.ac
    - Document prerequisites: just gcc and make, no cross-compiler needed
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 0bda2a6c54a60b9b3db62c62eb4c92273850d605
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 21:20:52 2026 -0500

    Fix cfg-grub to build drivers as internal (statically linked).
    
    GRUB has no shared library loader, so all braille drivers must be
    built-in. The previous configuration used --with-braille-driver=-lt,
    -tt,-vd which excluded those three but left everything else as
    external (.so), silently failing at runtime.
    
    Changes:
    - Add --enable-standalone-programs to prevent shared object loading
    - List all USB/serial-capable braille drivers as internal, ending
      with -all to exclude the rest (27 drivers included)
    - Add --with-screen-driver=gb,-all to only build the Grub screen
      driver as internal
    - Exclude drivers that need unavailable dependencies: ba (BrlAPI),
      lb (Libbraille), tt (curses), vd (video), xw (X11), lt (LogText)
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 386cc9f704704ef7de18b54356830288e693e51e
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 21:16:25 2026 -0500

    Integrate BRLTTY event loop into GRUB input polling.
    
    Call brlttyWait(0) from the brltty_keys input terminal's getkey()
    callback. This runs one non-blocking BRLTTY poll cycle each time
    GRUB polls for keyboard input, which:
    
    - Fires expired timer alarms (braille display refresh, keepalive)
    - Processes pending USB I/O (reading braille key events)
    - Updates the braille display with current screen contents
    
    Without this, BRLTTY was never actually polled — the key injection
    buffer existed but nothing drove the event loop to read from the
    braille device or update the display.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit e4f9e7806dba56ead08af784d874f8de9bcfccbf
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 21:09:25 2026 -0500

    Add GRUB loadable module entry point and build rules.
    
    Add grub_module.c with GRUB_MOD_INIT/GRUB_MOD_FINI hooks that call
    brlttyConstruct()/brlttyDestruct() when the module is loaded/unloaded
    via "insmod brltty".
    
    Add Makefile rules for "brltty.module" (relocatable ELF linked with
    -Wl,-r) and "brltty.mod" (post-processed with .modname/.moddeps
    sections and stripped, matching GRUB's genmod.sh process).
    
    This replaces the previous approach of building a standalone brltty
    executable that had to be linked into GRUB at build time.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 5648e914a7b506c5837e8c30d97287df539a240e
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 20:57:44 2026 -0500

    Implement GRUB screen driver with shadow terminal.
    
    The GRUB screen driver intercepts terminal output by registering a
    shadow grub_term_output that wraps the real terminal. All putchar,
    gotoxy, cls, and setcolorstate calls are recorded into an in-memory
    text buffer and forwarded to the original terminal unchanged.
    
    BRLTTY reads screen contents from this shadow buffer via describe()
    and readCharacters(). Key injection is supported through a
    grub_term_input whose getkey() drains a ring buffer filled by
    insertKey().
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit ca537503c271a5e719b84ee24272ade87a65a1f7
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 20:47:35 2026 -0500

    Implement USB platform backend for GRUB.
    
    Replace the stub functions in usb_grub.c with a real implementation
    using GRUB's USB subsystem API. This enables all USB braille displays
    that BRLTTY supports to work within the GRUB bootloader environment.
    
    Key function mappings:
    - usbFindDevice: grub_usb_iterate() for device enumeration
    - usbSetConfiguration: grub_usb_set_configuration()
    - usbControlTransfer: grub_usb_control_msg()
    - usbReadEndpoint: grub_usb_bulk_read_extended() with timeout
    - usbWriteEndpoint: grub_usb_bulk_write()
    - usbClearHalt: grub_usb_clear_halt()
    
    Functions without GRUB equivalents (usbDisableAutosuspend,
    usbClaimInterface, usbReleaseInterface) return success as no-ops
    since there is no power management or competing drivers in the
    bootloader. Async I/O functions (usbSubmitRequest, usbReapResponse)
    remain unsupported as BRLTTY uses synchronous polling in GRUB.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

commit 52f8ddf6ee7bfd38a23f4b69d112c8db5926a281
Author: Nicolas Pitre <npitre@baylibre.com>
Date:   Fri Mar 6 20:43:34 2026 -0500

    Add GRUB module documentation.
    
    Add user-facing documentation (README.Grub) covering how to build,
    install, and use BRLTTY as a loadable GRUB module for braille display
    accessibility during the boot menu.
    
    Add a detailed design document (GRUB-Module-Design.md) describing the
    architecture: shadow terminal screen capture, USB backend mapping,
    event loop integration, and phased implementation plan.
    
    Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

