keyboard stuff
at master 148 lines 5.1 kB view raw view rendered
1# OS Detection 2 3This feature makes a best guess at the host OS based on OS specific behavior during USB setup. It may not always get the correct OS, and shouldn't be relied on as for critical functionality. 4 5Using it you can have OS specific key mappings or combos which work differently on different devices. 6 7It is available for keyboards which use ChibiOS, LUFA and V-USB. 8 9## Usage 10 11In your `rules.mk` add: 12 13```make 14OS_DETECTION_ENABLE = yes 15``` 16 17It will automatically include the required headers file. 18It declares `os_variant_t detected_host_os(void);` which you can call to get detected OS. 19 20It returns one of the following values: 21 22```c 23enum { 24 OS_UNSURE, 25 OS_LINUX, 26 OS_WINDOWS, 27 OS_MACOS, 28 OS_IOS, 29} os_variant_t; 30``` 31 32::: tip 33Note that it takes some time after firmware is booted to detect the OS. 34::: 35This time is quite short, probably hundreds of milliseconds, but this data may be not ready in keyboard and layout setup functions which run very early during firmware startup. 36 37## Callbacks {#callbacks} 38 39If you want to perform custom actions when the OS is detected, then you can use the `process_detected_host_os_kb` function on the keyboard level source file, or `process_detected_host_os_user` function in the user `keymap.c`. 40 41```c 42bool process_detected_host_os_kb(os_variant_t detected_os) { 43 if (!process_detected_host_os_user(detected_os)) { 44 return false; 45 } 46 switch (detected_os) { 47 case OS_MACOS: 48 case OS_IOS: 49 rgb_matrix_set_color_all(RGB_WHITE); 50 break; 51 case OS_WINDOWS: 52 rgb_matrix_set_color_all(RGB_BLUE); 53 break; 54 case OS_LINUX: 55 rgb_matrix_set_color_all(RGB_ORANGE); 56 break; 57 case OS_UNSURE: 58 rgb_matrix_set_color_all(RGB_RED); 59 break; 60 } 61 62 return true; 63} 64``` 65 66## OS detection stability 67 68The OS detection is currently handled while the USB device descriptor is being assembled. 69The process is done in steps, generating a number of intermediate results until it stabilizes. 70We therefore resort to debouncing the result until it has been stable for a given amount of milliseconds. 71This amount can be configured, in case your board is not stable within the default debouncing time of 200ms. 72 73## Configuration Options 74 75* `#define OS_DETECTION_DEBOUNCE 250` 76 * defined the debounce time for OS detection, in milliseconds 77 * defaults to 250ms 78* `#define OS_DETECTION_KEYBOARD_RESET` 79 * enables the keyboard reset upon a USB device reinitilization 80 * this setting may help with detection issues when switching between devices on some KVMs (see [Troubleshooting](#troubleshooting)) 81* `#define OS_DETECTION_SINGLE_REPORT` 82 * allows the report callbacks to be called only once, when the OS detection result is considered stable 83 * subsequent changes in the detection results, if any, are ignored 84 * this setting may help with delayed stability issues when switching devices on some KVMs (see [Troubleshooting](#troubleshooting)) 85 86## Troubleshooting 87 88Some KVMs and USB switches may cause issues when the OS detection is turned on. 89Here is a list of common issues and how to fix them: 90 91* **Problem**: _keyboard won't redetect the OS when switching between machines using a KVM_ 92 * **Explanation**: some KVMs keep the USB controller powered on during the switch and OS 93 detection happens when the USB device description is being assembled. 94 * **Solution**: use `OS_DETECTION_KEYBOARD_RESET` to force the keyboard to reset upon switching. 95* **Problem**: _keyboard OS detection callback gets invoked even minuted after startup_ 96 * **Explanation**: some OSes, notably macOS on ARM-based Macs, may cause this behavior. 97 The actual cause is not known at this time.' 98 * **Solution**: use `OS_DETECTION_SINGLE_REPORT` to suppress repeated callback invocations. 99 100 101## Debug 102 103If OS is guessed incorrectly, you may want to collect data about USB setup packets to refine the detection logic. 104 105To do so in your `config.h` add: 106 107```c 108#define OS_DETECTION_DEBUG_ENABLE 109``` 110 111And in your `rules.mk` add: 112 113```make 114CONSOLE_ENABLE = yes 115``` 116 117And also include `"os_detection.h"` in your `keymap.c`. 118 119Then you can define custom keycodes to store data about USB setup packets in EEPROM (persistent memory) and to print it later on host where you can run `qmk console`: 120 121```c 122enum custom_keycodes { 123 STORE_SETUPS = SAFE_RANGE, 124 PRINT_SETUPS, 125}; 126 127bool process_record_user(uint16_t keycode, keyrecord_t *record) { 128 switch (keycode) { 129 case STORE_SETUPS: 130 if (record->event.pressed) { 131 store_setups_in_eeprom(); 132 } 133 return false; 134 case PRINT_SETUPS: 135 if (record->event.pressed) { 136 print_stored_setups(); 137 } 138 return false; 139 } 140} 141``` 142 143Then please open an issue on Github with this information and tell what OS was not detected correctly and if you have any intermediate devices between keyboard and your computer. 144 145 146## Credits 147 148Original idea is coming from [FingerprintUSBHost](https://github.com/keyboardio/FingerprintUSBHost) project.