diff --git a/documentation/AppManifests.md b/documentation/AppManifests.md index 5e7ceb939..d17c11c0e 100644 --- a/documentation/AppManifests.md +++ b/documentation/AppManifests.md @@ -1,79 +1,17 @@ # Flipper Application Manifests (.fam) -All components of Flipper Zero firmware — services, user applications, system settings — are developed independently. Each component has a build system manifest file, named `application.fam`, defining basic properties of a components and its relations to other parts of the system. - -When building firmware, **`fbt`** collects all application manifests, processes their dependencies and builds only those components that are utilized in current build configuration. See [fbt docs](./fbt.md#firmware-application-set) for details on build configurations. - -## Application definition - -Properties of a firmware component are declared in a form of a Python code snippet, forming a call to App() function with various parameters. - -Only 2 parameters are mandatoty: ***appid*** and ***apptype***, others are optional and may be meaningful only for certain application types. - -### Keys - -* **appid**: string, application id within the build system. Used for specifying which applications to include in build configuration and to resolve dependencies and conflicts. - -* **apptype**: member of FlipperAppType.* enumeration. Valid values are: - -| Enum member | Firmware component type | -|--------------|--------------------------| -| SERVICE | System service, created at early startup | -| SYSTEM | Application not being shown in any menus. Can be started by other apps or from CLI | -| APP | Regular application for main menu | -| PLUGIN | Application to be built as .fap plugin | -| DEBUG | Application only visible in Debug menu with debug mode enabled | -| ARCHIVE | One and only Archive app | -| SETTINGS | Application to be placed in System settings menu | -| STARTUP | Callback function to run at system startup. Does not define a separate app | -| EXTERNAL | Application to be built as .fap plugin | -| METAPACKAGE | Does not define any code to be run, used for declaring dependencies and application bundles | - -* **name**: Name to show in menus. -* **entry_point**: C function to be used as applicaiton's entry point. -* **flags**: Internal flags for system apps. Do not use. -* **cdefines**: C preprocessor definitions to declare globally for other apps when current application is included in active build configuration. -* **requires**: List of application IDs to also include in build configuration, when current application is referenced in list of applications to build. -* **conflicts**: List of application IDs that current application conflicts with. If any of them is found in constructed application list, **`fbt`** will abort firmware build process. -* **provides**: Functionally identical to ***requires*** field. -* **stack_size**: Stack size, in bytes, to allocate for application on its startup. Note that allocating a stack too small for app to run will cause system crash due to stack overflow, and allocating too much stack will reduce usable heap memory size for app to process data. *Note: you can use `ps` and `free` CLI commands to profile you app's memory usage.* -* **icon**: Animated icon name from built-in assets to be used when building app as a part of firmware. -* **order**: Order of an application within its group when sorting entries in it. The lower the order is, the closer to the start of the list the items is located. Used for ordering startup hooks and menu entries. -* **sdk_headers**: List of C header files from this app's code to include in API definitions for external applicaions. - -The following parameters are used only for [FAPs](./AppsOnSDCard.md): - -* **sources**: list of file name masks, used for gathering sources within app folder. Default value of ["\*.c\*"] includes C and CPP source files. -* **version**: string, 2 numbers in form of "x.y": application version to be embedded within .fap file. -* **fap_icon**: name of .png file, 1-bit color depth, 10x10px, to be embedded within .fap file. -* **fap_libs**: list of extra libraries to link application against. Provides access to extra functions that are not exported as a part of main firmware at expense of increased .fap file size and RAM consumption. -* **fap_category**: string, may be empty. App subcategory, also works as path of FAP within apps folder in the file system. - - -## .fam file contents - -.fam file contains one or more Application definitions. For example, here's a part of `applications/service/bt/application.fam`: - -```python -App( - appid="bt_start", - apptype=FlipperAppType.STARTUP, - entry_point="bt_on_system_start", - order=70, -) - -App( - appid="bt_settings", - name="Bluetooth", - apptype=FlipperAppType.SETTINGS, - entry_point="bt_settings_app", - stack_size=1 * 1024, - requires=[ - "bt", - "gui", - ], - order=10, -) ``` - -For more examples, see application.fam files for basic firmware components. \ No newline at end of file +App( + appid="example_app", => App id, used in fbt app lists only, like applications\meta + name="My Plugin", => App name in menu + apptype=FlipperAppType.PLUGIN, => App type APP / PLUGIN / GAME (or service) + entry_point="my_example_app", => App entry point / main function + cdefines=["APP_MYEXAMPLE"], => C style define that will be used in generated file + requires=[ + "gui", + "dialogs", + ], => Requirements (other app id's that required for this app) + stack_size=2 * 1024, => Memory stack size + order=60, => App order in menu +) +``` \ No newline at end of file diff --git a/documentation/BarcodeGenerator.md b/documentation/BarcodeGenerator.md index f2b5b2213..8b51d0a01 100644 --- a/documentation/BarcodeGenerator.md +++ b/documentation/BarcodeGenerator.md @@ -2,7 +2,7 @@ ## Author: [McAzzaMan](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator) - + It will eventually be expanded into other barcode types. It currently only generates UPC-A type barcodes. diff --git a/documentation/BluetoothRemote.md b/documentation/BluetoothRemote.md new file mode 100644 index 000000000..e01b06417 --- /dev/null +++ b/documentation/BluetoothRemote.md @@ -0,0 +1,58 @@ +_### How to use the Bluetooth remote control function of your Flipper :_ + +Once your Flipper is turned on, navigate with the "up" and "down" buttons until you reach the "Plugins" menu + +![Plugins](https://user-images.githubusercontent.com/829842/187899947-29c8d41a-fc61-4a0e-85a6-6bc8b04e60cd.png) + +Enter with the "middle" button and choose the "Bluetooth Remote" function + +![BTRemote](https://user-images.githubusercontent.com/829842/187900232-493a33a1-b461-44fc-b91d-1fe17e65eaa1.png) + +From this menu (**and only this one**), you will find a new bluetooth device named _Control "Flipper Name"_ + +Pair your Phone/Tablet/Computer/... to this device and you're good to go for controlling your remote devices ! (I skip the doc on how to pair 2 bluetooth devices...) + +Once paired, the Flipper LED will remain blue/fixed throughout the session in the "Bluetooth Remote" menu. If you leave the menu, the led goes off/the Bluetooth connection disappears: The blue led is a good way to know if you are connected or not. + +You will find in the main menu the different types of remote controls available + +![Menu](https://user-images.githubusercontent.com/829842/187900725-791d2be5-75c5-45f5-8baf-19af0026e341.png) + +**Keynote** + +Ultra simplified keyboard only for moving around in a document for example, or for certain presentations (Powerpoint or others...) + +![Keynote](https://user-images.githubusercontent.com/829842/187900971-1b17e292-46c9-4fa8-826a-194aab066c8b.png) + +**Full keyboard** + +You know what it is and how to use it ;) + +![Keyboard](https://user-images.githubusercontent.com/829842/187903229-16f9b944-bad6-4856-9dbd-b1d6182becaa.png) + +**Media** + +Up : Volume increase +Down: Volume decrease +Middle : Play/Stop +Left : Rewind +Right : Forward + +![Media](https://user-images.githubusercontent.com/829842/187903415-21d9e857-56d6-4571-8ad1-186025f56272.png) + +**Mouse** + +Up : Up +Down : Down +Left : Left +Right : Right +Middle : Mouse Left button +Back : Mouse Right Button + +![Mouse](https://user-images.githubusercontent.com/829842/187903920-adcd29de-3d51-48b7-8df2-d434824dfbcb.png) + +To **exit** each menu, simply **long press the "back" button**, which gives you the option to choose to leave the Bluetooth menu for good, choose another remote or stay on the one you were on. + +![Close](https://user-images.githubusercontent.com/829842/187904268-66bb2f50-10cb-4959-b0bb-7b30d18374e0.png) + +Doc by Foul (2022). diff --git a/documentation/CustomFlipperName.md b/documentation/CustomFlipperName.md index 244c8acc9..e36e236a6 100644 --- a/documentation/CustomFlipperName.md +++ b/documentation/CustomFlipperName.md @@ -1,7 +1,8 @@ # How to change Flipper name: +## [Feature & Documentation By Unleashed/xMasterX](https://github.com/Eng1n33r/flipperzero-firmware/documentation/CustomFlipperName.md) ## Instruction -1. Read [How to build](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/HowToBuild.md) and [How to install](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/HowToInstall.md) to know how to build and install firmware +1. Read [How to build](https://github.com/RogueMaster/flipperzero-firmware/blob/dev/documentation/HowToBuild.md) and [How to install](https://github.com/RogueMaster/flipperzero-firmware/blob/dev/documentation/HowToInstall.md) to know how to build and install firmware 2. Follow how to build instructions to prepare all things before continuing 3. Run release build to verify all is ok - `./fbt COMPACT=1 DEBUG=0 updater_package` 4. Clear build files - `./fbt COMPACT=1 DEBUG=0 updater_package -c` @@ -10,7 +11,6 @@ 6. Copy `dist/f7-C/f7-update-local` folder to microSD `update/myfw/` and run `update` file on flipper from file manager app (Archive) 7. Flash from microSD card only!!!! .dfu update from qFlipper will not work properly since name and serial number will be changed 8. Done, you will have custom name, serial number and bluetooth mac address - 9. Also you can skip 5-7 and flash with `CUSTOM_FLIPPER_NAME=Name ./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full` @@ -32,4 +32,4 @@ Or - Clear build files - `./fbt COMPACT=1 DEBUG=0 updater_package -c` - Run release build - `./fbt COMPACT=1 DEBUG=0 updater_package` - Copy `dist/f7-C/f7-update-local` folder to microSD `update/myfw/` and run `update` file on flipper from file manager app (Archive) -- Flash from microSD card only, .dfu update from qFlipper will not work properly since name and serial number will be changed \ No newline at end of file +- Flash from microSD card only, .dfu update from qFlipper will not work properly since name and serial number will be changed diff --git a/documentation/DangerousSettings.md b/documentation/DangerousSettings.md deleted file mode 100644 index 780724644..000000000 --- a/documentation/DangerousSettings.md +++ /dev/null @@ -1,12 +0,0 @@ -## How to extend SubGHz supported frequency range - -#### CC1101 Frequency range specs: 300-348 MHz, 386-464 MHz, and 778-928 MHz -#### This setting will extend to: 281-361 MHz, 378-481 MHz, and 749-962 MHz - -1. Please do not do that unless you know what exactly you are doing -2. You don't need extended range for almost all use cases -3. Extending frequency range and transmitting on frequencies that outside of hardware specs can damage your hardware! -4. Flipper Devices team and/or unleashed fw developers is not responsible of any damage that can be caused by using CFW or extending frequency ranges!!! - -If you really sure you need that change, find `subghz/assets/dangerous_settings` file on your microSD, read comments on first lines -and change `false` to `true` \ No newline at end of file diff --git a/documentation/HowToBuild.md b/documentation/HowToBuild.md index be3d87763..a371127af 100644 --- a/documentation/HowToBuild.md +++ b/documentation/HowToBuild.md @@ -1,63 +1,71 @@ -# How to Build by yourself: +# How to Build by yourself ## Install required software - Git - [Download](https://git-scm.com/downloads) for Windows, on Linux/Mac install via package manager (`brew`, `apt`, ...) For development: + - Git - Python3 - VSCode ## Clone the Repository -You should clone with +You should clone with + ```shell -$ git clone --recursive https://github.com/Eng1n33r/flipperzero-firmware.git +git clone --recursive https://github.com/RogueMaster/flipperzero-firmware-wPlugins.git ``` -# Build on Linux/macOS +## Building -Check out `documentation/fbt.md` for details on building and flashing firmware. +Check out [documentation/fbt.md](fbt.md) for details on building and flashing firmware. -### Compile everything for development +### Compile -```sh +Linux.MacOS + +```shell ./fbt ``` -### Compile everything for release + get updater package to update from microSD card +Windows (powershell) -```sh -./fbt COMPACT=1 DEBUG=0 updater_package -``` - -Check `dist/` for build outputs. - -Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device. - - -# Build on Windows - -Check out `documentation/fbt.md` for details on building and flashing firmware. - -### Compile everything for development - -```sh +```powershell .\fbt.cmd ``` -### Compile everything for release + get updater package to update from microSD card +Production standard Options -```sh -.\fbt.cmd COMPACT=1 DEBUG=0 updater_package +```shell +./fbt + --with-updater + COMPACT=1 + DEBUG=0 + updater_package +``` + +Usefull options, check `./fbt -h` and [fbt.md](fbt.md) for more + +```shell +DEBUG=1 # Enable debug build +COMPACT=1 # Optimize for size +DIST_SUFFIX=custom # Suffix for binaries in build output for dist targets +CUSTOM_FLIPPER_NAME=Flipper # Replaces OTP flipper name with custom string of 8 chars +UPDATE_SPLASH=update_default # Directory name with slideshow frames to render after installing update package +LOADER_AUTOSTART= # Application name to automatically run on Flipper boot +FIRMWARE_APPS="{ + 'default': ['crypto_start', 'basic_services', 'basic_apps', 'updater_app', 'archive', 'custom_apps', 'passport', 'system_settings', 'about', 'basic_plugins', 'custom_games', 'wifi_plugins', 'external_apps', 'debug_apps'], + 'unit_tests': ['basic_services', 'updater_app', 'unit_tests'], + 'ext_apps': ['basic_services', 'external_apps']}" + # Map of (configuration_name->application_list) +-c # Clean ``` Check `dist/` for build outputs. Use **`flipper-z-{target}-full-{suffix}.dfu`** to flash your device. - - If compilation fails, make sure all submodules are all initialized. Either clone with `--recursive` or use `git submodule update --init --recursive`. diff --git a/documentation/HowToInstall.md b/documentation/HowToInstall.md index 18021418b..62cc5dfea 100644 --- a/documentation/HowToInstall.md +++ b/documentation/HowToInstall.md @@ -1,7 +1,7 @@ # Update firmware -## [Get Latest Firmware from GitHub Releases](https://github.com/Eng1n33r/flipperzero-firmware/releases) +## [Get Latest Firmware from GitHub Releases](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/releases)

@@ -11,34 +11,6 @@

-## With Web Updater - -- Be sure you updated to latest official release before(if installing for the first time), and verify that microSD card is installed -- Open latest release page - [Releases](https://github.com/Eng1n33r/flipperzero-firmware/releases/latest) -- Connect your device and select `Install via Web Updater` -after that on web updater page - press `Connect` button -- Press `Install` button - -- And wait, if all flashed successfully - you will have all needed assets pre installed -- Done - -
-
- -## With iOS mobile app - -- Be sure you updated to latest official release before(if installing for the first time), and verify that microSD card is installed -- Open latest release page - [Releases](https://github.com/Eng1n33r/flipperzero-firmware/releases/latest) -- Download `flipper-z-f7-update-(version).tgz` -- Open downloads in ios Files app, select downloaded `.tgz` file, click Share, select Flipper App -- In flipper app click green `Update` button, be sure it shows `Custom flipper-z-f7-update...` in Update Channel -- Wait until update is finished -- And if all flashed successfully - you will have all needed assets pre installed -- Done - -
-
- ## With offline update on flipper ### **Replace (CURRENT VERSION) with version that you downloaded from releases** @@ -71,7 +43,7 @@ then select **`flipper-z-f7-full-(CURRENT VERSION).dfu`** ## With USB DFU -1. Download latest [Firmware](https://github.com/Eng1n33r/flipperzero-firmware/releases) +1. Download latest [Firmware](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/releases) 2. Reboot Flipper to Bootloader - Press and hold `← Left` + `↩ Back` for reset @@ -87,7 +59,7 @@ then select **`flipper-z-f7-full-(CURRENT VERSION).dfu`**
# After install: +- ### If you installed using .dfu - unpack files from archive `sd-card-(CURRENT VERSION).zip` to your microSD card +
-- ## [Read instructions how to use plugins and more](https://github.com/Eng1n33r/flipperzero-firmware#instructions) - -- ## [How To: Configure Sub-GHz Remote App](https://github.com/Eng1n33r/flipperzero-firmware/blob/dev/documentation/SubGHzRemotePlugin.md) +- ## [How To: Configure UniversalRF Remix App](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/documentation/UniRFRemix.md) diff --git a/documentation/OTA.md b/documentation/OTA.md index 836bc1b71..2a6b09846 100644 --- a/documentation/OTA.md +++ b/documentation/OTA.md @@ -1,8 +1,8 @@ # Executing code from RAM -In Flipper firmware, we have a special boot mode that loads a specially crafted system image into RAM and transfers control to it. System image executing in RAM has full write access to whole Flipper's flash memory — something that's not possible when running main code from the same flash. +In Flipper firmware, we have a special boot mode that loads a specially crafted system image into RAM and transfers control to it. System image executing in RAM has full write access to whole Flipper's flash memory — something that's not possible when running main code from same flash. -We leverage that boot mode to perform OTA firmware updates, including operations on a radio stack running on the second MCU core. +We leverage that boot mode to perform OTA firmware updates, including operations on radio stack running on second MCU core. # How does Flipper OTA work? @@ -22,16 +22,16 @@ For that, main firmware loads an updater image - a customized build of main Flip First, if there's a Radio stack image bundled with the update, updater compares its version with currently installed one. If they don't match, updater performs stack deinstallation followed by writing and installing a new one. The installation itself is performed by proprietary software, FUS, running on Core2, and leads to a series of system restarts. -Then, updater validates and corrects Option Bytes — a special memory region containing low-level configuration for Flipper's MCU. +Then updater validates and corrects Option Bytes — a special memory region containing low-level configuration for Flipper's MCU. After that, updater loads a `.dfu` file with firmware to be flashed, checks its integrity using CRC32, writes it to system flash and validates written data. ## 3. Restoring internal storage and updating resources -After performing operations on flash memory, the system restarts into newly flashed firmware. Then it performs restoration of previously backed up `/int` contents. +After performing operations on flash memory, system restarts into newly flashed firmware. Then it performs restoration of previously backed up `/int` contents. -If the update package contains an additional resources archive, it is extracted onto SD card. +If update package contains an additional resources archive, it is extracted onto SD card. # Update manifest @@ -40,13 +40,13 @@ Update packages come with a manifest that contains a description of its contents ## Mandatory fields -An update manifest must contain the following keys in given order: +Update manifest must contain the following keys in given order: * __Filetype__: a constant string, "Flipper firmware upgrade configuration"; * __Version__: manifest version. Current value is 2; -* __Info__: arbitrary string, describing package contents; +* __Info__: arbitraty string, describing package contents; * __Target__: hardware revision the package is built for; @@ -56,7 +56,7 @@ An update manifest must contain the following keys in given order: ## Optional fields -Other fields may have empty values, is such case, updater skips all operations related to such values. +Other fields may have empty values, is such case updater skips all operations related to such values. * __Radio__: file name of radio stack image, provided by STM; @@ -66,16 +66,16 @@ Other fields may have empty values, is such case, updater skips all operations r * __Radio CRC__: CRC32 of radio image; -* __Resources__: file name of TAR archive with resources to be extracted on SD card; +* __Resources__: file name of TAR acrhive with resources to be extracted on SD card; * __OB reference__, __OB mask__, __OB write mask__: reference values for validating and correcting option bytes. # OTA update error codes -We designed the OTA update process to be as fail-safe as possible. We don't start any risky operation before validating all related pieces of data to ensure we don't leave the device in a partially updated, or bricked, state. +We designed the OTA update process to be as fail-safe as possible. We don't start any risky operation before validating all related pieces of data to ensure we don't leave the device in partially updated, or bricked, state. -Even if something goes wrong, Updater gives you an option to retry failed operations, and reports its state with an error code. These error codes have an `[XX-YY]` format, where `XX` encodes an operation that failed, and `YY` contains extra details on its progress where the error occurred. +Even if something goes wrong, Updater gives you an option to retry failed operations, and reports its state with an error code. These error codes have an `[XX-YY]` format, where `XX` encodes an operation that failed, and `YY` contains extra details on its progress where the error occured. | Stage description | Code | Progress | Description | |:-----------------------:|-------:|------------|--------------------------------------------| diff --git a/documentation/SubGHzSettings.md b/documentation/SubGHzSettings.md index e77c30ac3..ff08041d4 100644 --- a/documentation/SubGHzSettings.md +++ b/documentation/SubGHzSettings.md @@ -2,7 +2,7 @@ #### CC1101 Frequency range specs: 300-348 MHz, 386-464 MHz, and 778-928 MHz -Edit user settings file located on your microSD card - `subghz/assets/setting_user` +Edit user settings file located on your microSD card - `subghz/assets/setting_user.txt` in this file you will find we already have extra frequencies added if you need your custom one, make sure it doesnt listed here diff --git a/documentation/fbt.md b/documentation/fbt.md index 3eee6baaa..48726273e 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -38,12 +38,11 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. ## FBT targets -**`fbt`** keeps track of internal dependencies, so you only need to build the highest-level target you need, and **`fbt`** will make sure everything they depend on is up-to-date. +FBT keeps track of internal dependencies, so you only need to build the highest-level target you need, and FBT will make sure everything they depend on is up-to-date. ### High-level (what you most likely need) - `fw_dist` - build & publish firmware to `dist` folder. This is a default target, when no other are specified -- `plugin_dist` - build external plugins & publish to `dist` folder - `updater_package`, `updater_minpackage` - build self-update package. Minimal version only inclues firmware's DFU file; full version also includes radio stack & resources for SD card - `copro_dist` - bundle Core2 FUS+stack binaries for qFlipper - `flash` - flash attached device with OpenOCD over ST-Link @@ -54,7 +53,7 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. - `blackmagic` - debug firmware with Blackmagic probe (WiFi dev board) - `openocd` - just start OpenOCD - `get_blackmagic` - output blackmagic address in gdb remote format. Useful for IDE integration -- `lint`, `format` - run clang-format on C source code to check and reformat it according to `.clang-format` specs +- `lint`, `format` - run clang-tidy on C source code to check and reformat it according to `.clang-format` specs - `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on Python source code, build system files & application manifests ### Firmware targets @@ -83,7 +82,7 @@ To run cleanup (think of `make clean`) for specified targets, add `-c` option. ## Command-line parameters - `--options optionfile.py` (default value `fbt_options.py`) - load file with multiple configuration values -- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. _Explicily enabling this should no longer be required, **`fbt`** now has specific handling for updater-related targets_ +- `--with-updater` - enables updater-related targets and dependency tracking. Enabling this option introduces extra startup time costs, so use it when bundling update packages. _Explicily enabling this should no longer be required, fbt now has specific handling for updater-related targets_ - `--extra-int-apps=app1,app2,appN` - forces listed apps to be built as internal with `firmware` target - `--extra-ext-apps=app1,app2,appN` - forces listed apps to be built as external with `firmware_extapps` target diff --git a/documentation/keyboard_layout_file.md b/documentation/keyboard_layout_file.md new file mode 100644 index 000000000..b2ac6f058 --- /dev/null +++ b/documentation/keyboard_layout_file.md @@ -0,0 +1,20 @@ +## .kl file format + +A .kl file is a binary file format which stores, for each ascii code point in order from *ASCII(0)* to *ASCII(127)*, a 16 bit little endian value composed of a *USB HID code* in the low order byte and a *bit set of modifier keys* in the high order byte. + +*USB HID codes* for each key of a standard 102/105 key keyboard are (as displayed passing option `-k` to the software): + + + ---------------------------------------------------------------------- + | 35 | 1e | 1f | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 2d | 2e | <- | + ---------------------------------------------------------------------- + | -> | 14 | 1a | 08 | 15 | 17 | 1c | 18 | 0c | 12 | 13 | 2f | 30 | | + ------------------------------------------------------------------| | + | o | 04 | 16 | 07 | 09 | 0a | 0b | 0d | 0e | 0f | 33 | 34 | 31 | | + ---------------------------------------------------------------------- + | ^ | 64 | 1d | 1b | 06 | 19 | 05 | 11 | 10 | 36 | 37 | 38 | ^ | + ---------------------------------------------------------------------- + | ctrl | gui | alt | 2c | alt | gui | ctrl | + ---------------------------------------------------------------------- + +*Modifier key bits* are, in order starting from bit 1: *lctrl*, *lshift*, *lalt*, *lgui*, *rctrl*, *rshift*, *ralt*, *rgui*.