├── .gitignore ├── .gitmodules ├── .snitch.yaml ├── Makefile ├── README.md ├── TODO.org ├── build-and-run.sh ├── default.nix └── iso └── boot └── grub └── grub.cfg /.gitignore: -------------------------------------------------------------------------------- 1 | *.iso -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "grub"] 2 | path = grub 3 | url = git@github.com:tsoding/grub.git 4 | -------------------------------------------------------------------------------- /.snitch.yaml: -------------------------------------------------------------------------------- 1 | title: 2 | transforms: 3 | - match: (.*) \-\-\> 4 | replace: $1 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test.iso: ./iso/boot/grub/grub.cfg ./grub/grub-mkrescue 2 | ./grub/grub-mkrescue ./iso/ --directory ./grub/grub-core/ -o test.iso 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Tsoding](https://img.shields.io/badge/twitch.tv-tsoding-purple?logo=twitch&style=for-the-badge)](https://www.twitch.tv/tsoding) 2 | # Gamepad support for GRUB 3 | 4 | - Development is done on https://twitch.tv/tsoding 5 | - Archive of the streams: https://www.twitch.tv/collections/qhijEFrmqRUFvA 6 | 7 | ## Supported Gamepads 8 | 9 | - Logitech Rumble Gamepad F510 in DirectInput mode 10 | 11 | ## Quick Start 12 | 13 | ```console 14 | $ git clone --recursive git@github.com:tsoding/grub-gamepad.git 15 | $ nix-shell # On NixOS 16 | 17 | $ cd grub/ 18 | $ ./bootstrap 19 | $ ./configure 20 | $ make -j5 21 | 22 | $ cd .. 23 | $ make -B 24 | $ qemu-system-i386 -cdrom test.iso 25 | ``` 26 | 27 | ## Connecting Gamepad via USB 28 | 29 | ### VirtualBox 30 | 31 | - Create Virtual Machine with 256MB of RAM and no HDD 32 | - Attach the `test.iso` as Live CD 33 | - Connect a Gamepad as an OHCI device. 34 | - Start the machine to load into GRUB 35 | 36 | ```console 37 | grub> nativedisk pata 38 | grub> nativedisk ohci 39 | grub> insmod usb_gamepad 40 | grub> terminal_input usb_gamepad 41 | ``` 42 | 43 | ### QEMU 44 | 45 | ```console 46 | $ lsusb 47 | $ sudo qemu-system-i386 -usb -device usb-host,hostbus=,hostaddr= -cdrom test.iso # Alternatively, you can reference your device by its ids -device usb-host,vendorid=,productid= 48 | grub> nativedisk pata 49 | grub> nativedisk uhci 50 | grub> insmod usb_gamepad 51 | grub> terminal_input usb_gamepad 52 | ``` 53 | 54 | ## Architecture 55 | 56 | ### Adding New Module 57 | 58 | TBD 59 | 60 | 61 | ### Registering New Terminal Input 62 | 63 | TBD 64 | 65 | 66 | ### Attaching to a USB device 67 | 68 | TBD 69 | 70 | 71 | ## References 72 | 73 | - https://steamcommunity.com/groups/steamuniverse/discussions/0/558751660797029626/ 74 | - https://github.com/rafaelffilho/RafaOS 75 | - https://wiki.osdev.org/GRUB 76 | - The Official GRUB repo: git://git.savannah.gnu.org/grub.git 77 | - https://qemu.weilnetz.de/doc/qemu-doc.html#usb_005fdevices 78 | - https://lists.gnu.org/archive/html/help-grub/2015-01/msg00011.html 79 | - https://atariwiki.org/wiki/Wiki.jsp?page=How%2Bto%2Bwrite%2Ba%2BUSB%2BDriver 80 | - https://github.com/krislig/rumblepad2py/blob/master/pad.py 81 | 82 | ## Support 83 | 84 | You can support my work via 85 | 86 | - Twitch channel: https://www.twitch.tv/subs/tsoding 87 | - Patreon: https://www.patreon.com/tsoding 88 | -------------------------------------------------------------------------------- /TODO.org: -------------------------------------------------------------------------------- 1 | * TODO Useful links from chat 2 | 3 | #+BEGIN_SRC org 4 | 2019-06-18 16:19:46.355591809|lorymaster|Could also add this in the todo: https://tools.ietf.org/html/rfc6970 RFC for universal plug and play protocol 5 | 2019-06-18 18:42:37.673204119|x33grawl|whoops this one https://stackoverflow.com/questions/31799336/how-to-build-grub2-bootloader-from-its-source-and-test-it-with-qemu-emulator 6 | 2019-06-18 19:16:41.155079973|joshuagollaher|this says that it only happens on 32 bit https://lists.gnu.org/archive/html/help-grub/2013-11/msg00006.html 7 | 2019-06-18 19:33:59.211878178|wtfblub|theres a patch for this error http://git.savannah.gnu.org/cgit/grub.git/commit/util?id=842c390469e2c2e10b5aa36700324cd3bde25875 8 | #+END_SRC 9 | 10 | * TODO Roadmap 11 | 12 | - [-] See how GRUB 2 handles keyboard 13 | - [X] Gameport Exploration 14 | - [X] file:./grub/grub-core/commands/lspci.c::79 15 | - [X] What is Gameport Controller 16 | - [X] [[https://www.ebay.com/itm/USB-to-Joystick-15-Pin-Male-Gameport-Adapter-Converter-Adaptor-With-6ft-Cable/251010052320?epid=1943412725&hash=item3a715d70e0:g:mqEAAOSwYHxWOI1M][USB to Joystick 15 Pin Male Gameport Adapter Converter Adaptor With 6ft Cable...]] 17 | - [X] The VGA looking thing 18 | - [X] MIDI gameport 19 | - [X] [[https://en.wikipedia.org/wiki/Game_port][Game port - Wikipedia]] 20 | - [X] Some boring keyboard layout stuff 21 | - [X] file:./grub/include/grub/keyboard_layouts.h::36 22 | - [X] enum grub_keyboard_key looks like a GRUB abstraction layer over keyboards 23 | - [X] file:./grub/util/grub-mklayout.c::215 24 | - [X] grub-mklayout 25 | - [X] not sure if it's even useful 26 | - [X] How I can type anything in the GRUB if I don't have any USB devices (according to `usb`) 27 | - [X] You are using terminal_input called console 28 | - [X] Where is it located? 29 | - [X] Most probably here file:grub/grub-core/term/i386/pc/console.c::1 30 | - [X] Some kind of fake input that constantly produces some actions 31 | - [X] file:./grub/grub-core/tests/fake_input.c::1 as an example 32 | - [X] file:grub/grub-core/term/khooy.c::1 33 | - [-] How actual USB Keyboard Support works 34 | - [-] file:./grub/grub-core/term/usb_keyboard.c::1 35 | - [-] `grub_usb_keyboard_getkey` 36 | - [-] it's actually a method of `struct grub_term_input` 37 | - [-] Definition of `struct grub_term_input` file:./grub/include/grub/term.h::137 38 | - [-] How many terms do we have? 39 | - [-] file:./grub/grub-core/kern/term.c::87 40 | - [-] `grub_getkey_noblock` 41 | - [-] FOR_ACTIVE_TERM_INPUTS 42 | - [-] file:./grub/include/grub/term.h::321 43 | - [X] FOR_LIST_ELEMENTS 44 | - file:./grub/include/grub/list.h::37 45 | - It is used to iterate LinkedLists 46 | - [X] Is that X macro? 47 | - [X] No 48 | - [-] `grub_term_inputs` 49 | - [-] This is probably the global list of terminals 50 | - [-] file:./grub/include/grub/term.h::241 51 | - [X] EXPORT_VAR 52 | - file:./grub/include/grub/symbol.h::69 53 | - [X] file:./grub/grub-core/Makefile.am::298 54 | - This looks like external preprocessing 55 | - [X] ASM_PREFIX 56 | - [X] file:./grub/grub-core/Makefile.am::286 57 | - [X] Looks like a deadend. 58 | - It's probably very important. But we can simply ignore it 59 | - [-] Where grub_term_inputs are initialized 60 | - [-] fake_input file:./grub/grub-core/tests/fake_input.c::56 61 | - [-] usb_keyboard.c and fake_input.c are implementations of the same interface 62 | - [X] grub_usb_keyboard_attach looks interesting 63 | - [X] file:./grub/grub-core/term/usb_keyboard.c::147 64 | - [X] grub_usb_device_t 65 | - [X] It was a spoiler 66 | - [X] What is the interface 67 | - [X] Look at the headers they include. They probably include the interface 68 | - [X] #include 69 | - [X] There is also gfxterm.h 70 | - [X] file:./grub/include/grub/gfxterm.h::1 71 | - [X] I don't think it's important right now 72 | - [X] file:./grub/include/grub/term.h::1 73 | - [X] And we already been here 74 | - [-] They all initialize their own instance of grub_term_input 75 | - [-] How those instances are assembled into a linked list later? 76 | - [-] Do usb_keyboard and fake_input mention grub_term_inputs 77 | - [X] usb_keyboard does not 78 | - [X] fake_input 79 | - [X] file:./grub/grub-core/tests/fake_input.c::56 80 | - [ ] grub_term_register_input_active 81 | - [ ] file:./grub/include/grub/term.h::267 82 | - [ ] And it mentions grub_term_inputs 83 | - [ ] Let's go up the callstack 84 | - [ ] file:./grub/grub-core/term/usb_keyboard.c::147 85 | - [ ] grub_usb_keyboard_attach 86 | - [ ] file:./grub/grub-core/term/usb_keyboard.c::442 87 | - [ ] struct grub_usb_attach_desc 88 | - [ ] file:./grub/include/grub/usb.h::297 89 | - [ ] 90 | - [ ] Try to debug GRUB2 with gdb and see how it boots itself up 91 | - [ ] Find the way to receive stuff from gamepad 92 | - [ ] Dig down through abstractions 93 | - [ ] SDL2 94 | - [ ] X11 95 | - [ ] Linux Input 96 | - [ ] Driver 97 | - [ ] ... 98 | - [ ] it might make sense to try get some input working from the gamepad in Linux first, rather than in grub 99 | - [ ] USB vs HID 100 | - [ ] https://en.wikipedia.org/wiki/USB_human_interface_device_class 101 | - [ ] https://usb.org/sites/default/files/documents/hid1_11.pdf 102 | 103 | ** DONE Development Setup 104 | 105 | - [X] Mirror in Tsoding organization 106 | - [X] [[https://help.github.com/en/articles/about-github-mirrors][About GitHub mirrors - GitHub Help]] 107 | - [X] [[https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks][Git - Git Hooks]] 108 | - [X] Wrong way 109 | - [X] Create separate repo with submodule 110 | - [X] [[https://github.com/tsoding/grub-gamepad][GitHub - tsoding/grub-gamepad: On going effort to bring gamepad/joystick supp...]] 111 | - [X] Emulation 112 | - [X] qemu 113 | - [X] Actually the recommended way to test grub 114 | - [X] VirtualBox 115 | - [X] To heavy 116 | - [X] Build 117 | - [X] git clone git://git.savannah.gnu.org/grub.git 118 | - [X] INSTALL file 119 | - [X] The instructions mention some kind of grub-emu. What is that? 120 | - [X] [[http://www.ubuntubuzz.com/2015/06/how-to-preview-grub-bootloader-changes.html][How To Preview GRUB Bootloader Changes Without Restart with grub-emu]] 121 | - [X] I don't have it in NixOS. Can I build it from the source code? 122 | - [X] No, grub-emu is a hoax. 123 | - [X] [[https://stackoverflow.com/questions/31799336/how-to-build-grub2-bootloader-from-its-source-and-test-it-with-qemu-emulator][how to build grub2 bootloader from it's source and test it with qemu emulator...]] 124 | - [X] You have to use grub-mkrescue instead 125 | #+BEGIN_SRC bash 126 | grub-mkrescue -o test.iso 127 | qemu-system-i386 -cdrom test.iso 128 | #+END_SRC 129 | - [X] Is there any way to debug output grub instead of messing with hooking up with GBD? 130 | - [X] grub_dprintf looks like a logging system (with topic and shit) 131 | - [X] How to read GRUB logs? 132 | - [X] [[https://stackoverflow.com/questions/34938067/reading-grub2-debug-logs][grub - Reading GRUB2 debug logs - Stack Overflow]] 133 | - [X] Try to add `set pager=1` and `set debug=all` to the config 134 | - [X] It worked, it printed a lot of shite 135 | - [X] Can we add our own log entry? 136 | - [X] Yep 137 | 138 | 139 | * DONE Get rid of the grub source · Issue #4 · tsoding/grub-gamepad · GitHub 140 | 141 | - [X] [[https://github.com/tsoding/grub-gamepad/issues/4][Get rid of the grub source · Issue #4 · tsoding/grub-gamepad · GitHub]] 142 | - [X] How to build a GRUB module without GRUB source code? 143 | - [X] [[https://blog.fpmurphy.com/2010/06/grub2-modules.html][GRUB2 Modules « Musings]] 144 | - [X] This article suggests to make the module a part of the build process 145 | - [X] [[https://wiki.osdev.org/Writing_GRUB_Modules][Writing GRUB Modules - OSDev Wiki]] 146 | - [X] You can build "out-of-tree", but this is just one option 147 | - [X] Building "in-tree" is not even something that is discouraged 148 | - [X] I think we gonna keep doing "in-tree" because it 149 | handles a lot of stuff for out-of-the-box 150 | 151 | * DONE New grub version · Issue #5 · tsoding/grub-gamepad · GitHub 152 | 153 | - [X] [[https://github.com/tsoding/grub-gamepad/issues/5][New grub version · Issue #5 · tsoding/grub-gamepad · GitHub]] 154 | - [X] configure.ac:414: error: possibly undefined macro: AC_CHECK_HEADERS 155 | - [X] pkg-config 156 | * TODO usb_gamepad is not using dpad for arrows · Issue #15 · tsoding/grub-gamepad · GitHub 157 | [[https://github.com/tsoding/grub-gamepad/issues/15][usb_gamepad is not using dpad for arrows · Issue #15 · tsoding/grub-gamepad · GitHub]] 158 | ** TODO Reports 159 | 160 | - report[0-3] - sticks coordinates 161 | - report[4] 162 | - 0x18 - X 1 163 | - 0x28 - A 2 164 | - 0x48 - B 3 165 | - 0x88 - Y 4 166 | - 0x0 - dpad up 167 | - 0x1 - dpad up/right 168 | - 0x2 - dpad right 169 | - 0x3 - dpad down/right 170 | - 0x4 - dpad down 171 | - 0x5 - dpad down/left 172 | - 0x6 - dpad left 173 | - 0x7 - dpad up/left 174 | - 0x8 - dpad centered 175 | - report[5] 176 | - 0x00 - nothing 177 | - 0x01 - LB 178 | - 0x02 - RB 179 | - 0x04 - LT 180 | - 0x08 - RT 181 | - 0x10 - back 182 | - 0x20 - start 183 | - 0x40 - LS 184 | - 0x80 - RS 185 | 186 | ** DONE Is there a way to query what joystick supports 187 | 188 | [[https://github.com/tsoding/grub-gamepad/issues/17][tsoding/grub-gamepad#17 Is there a way to query what joystick supports]] 189 | 190 | ** TODO Configurable mappings 191 | 192 | - [X] down mapping does work 193 | - [ ] what are the codes for keydown 194 | * TODO The module probably works only with a single model of the gamepad · Issue #16 · tsoding/grub-gamepad · GitHub 195 | [[https://github.com/tsoding/grub-gamepad/issues/16][The module probably works only with a single model of the gamepad · Issue #16 · tsoding/grub-gamepad · GitHub]] 196 | 197 | - [X] Reject any HID devices that are not logitech rumble f510 198 | - [X] file:grub/include/grub/usbdesc.h::41 199 | - [ ] Make it easy to replace logitech_rumble_f510_state with something else? 200 | - [ ] Check out HID specs for gamepads or something? (i don't even know what I'm talking about) 201 | -------------------------------------------------------------------------------- /build-and-run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -xe 4 | 5 | # Rebuild GRUB 6 | # The grub project should be prebuilt manually before using this script 7 | pushd grub/ 8 | make -j5 9 | popd 10 | 11 | # Rebuild ISO 12 | make -B 13 | 14 | # Run QEMU 15 | 16 | # Gamepad 17 | sudo qemu-system-i386 -usb -device usb-host,vendorid=0x046d,productid=0xc218 -cdrom test.iso 18 | 19 | # Wacom 20 | # sudo qemu-system-i386 -usb -device usb-host,vendorid=0x056a,productid=0x030e -cdrom test.iso 21 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | with import {}; rec { 2 | grubEnv = stdenv.mkDerivation { 3 | name = "grub-env"; 4 | buildInputs = [ python27Full 5 | pkgconfig 6 | autoconf 7 | automake 8 | gnumake 9 | gettext 10 | libtool 11 | gnum4 12 | bison 13 | flex 14 | SDL 15 | xorriso 16 | global 17 | ]; 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /iso/boot/grub/grub.cfg: -------------------------------------------------------------------------------- 1 | # https://www.gnu.org/software/grub/manual/grub/html_node/debug.html 2 | # set debug=usb_keyboard,keystatus,atkeyb,usb,ahci,usb_gamepad 3 | # set debug=usb_gamepad 4 | 5 | # https://www.gnu.org/software/grub/manual/grub/html_node/timeout.html 6 | set timeout=-1 7 | # https://www.gnu.org/software/grub/manual/grub/html_node/default.html 8 | set default=0 9 | # https://www.gnu.org/software/grub/manual/grub/html_node/pager.html 10 | # set pager=1 11 | 12 | menuentry "Foo" { 13 | true 14 | } 15 | menuentry "Bar" { 16 | true 17 | } 18 | menuentry "Baz" { 19 | true 20 | } 21 | menuentry "Hello" { 22 | true 23 | } 24 | menuentry "World" { 25 | true 26 | } 27 | menuentry "Test" { 28 | true 29 | } 30 | 31 | nativedisk pata 32 | nativedisk uhci 33 | insmod usb_gamepad 34 | terminal_input --append usb_gamepad0 35 | 36 | gamepad_dpad U name up 37 | gamepad_dpad D name down 38 | 39 | # gamepad_btn 0 char a 40 | gamepad_btn 1 code 13 41 | # gamepad_btn 2 char a 42 | # gamepad_btn 3 char a 43 | 44 | gamepad_lb char x 45 | gamepad_rb char y 46 | 47 | gamepad_lt char i 48 | gamepad_rt char j 49 | 50 | gamepad_rs U char u 51 | gamepad_rs RU char r 52 | gamepad_rs R name space 53 | gamepad_rs DR char m 54 | gamepad_rs D char o 55 | gamepad_rs LD char m 56 | gamepad_rs P code 13 57 | 58 | gamepad_ls U char u 59 | gamepad_ls RU char r 60 | gamepad_ls R code 32 61 | gamepad_ls DR char m 62 | gamepad_ls D char o 63 | gamepad_ls LD char m 64 | 65 | gamepad_start code 13 66 | gamepad_back code 8 67 | 68 | # gamepad_rs L char g 69 | # gamepad_rs UL char h 70 | --------------------------------------------------------------------------------