Compare commits

...

10 Commits

Author SHA1 Message Date
Brian S. Stephan 069aa27927
style the GUI tree widget a bit
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-02-18 00:05:16 -06:00
Brian S. Stephan 22de9ae6d6
use Textual's notify instead of a custom popup window
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-02-17 23:38:41 -06:00
Brian S. Stephan df875a5d99
rename GUI Save button as Confirm
more idiomatic this way, since it's really just "set the value", not
actually saving the config

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-02-17 23:05:51 -06:00
Brian S. Stephan 03a8235445
include the package version number in the edit-config title
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-02-17 23:05:36 -06:00
Brian S. Stephan 0ab372f9fd
version bumps
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-01-30 21:34:34 -06:00
Brian S. Stephan d12ee311bc
update CHANGELOG for v0.6.0
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-01-09 10:02:00 -06:00
Brian S. Stephan 331063d1a3
update docs regarding the protobuf precompiled files
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-01-09 10:01:45 -06:00
Brian S. Stephan b3f6f86950
ship precompiled protobuf files for convenience
current libraries seem to have problems on Windows with thinking files
are duplicated when they are not, making it impossible to compile .proto
files at runtime in this tool on that platform. this adds a fallback of
using shipped, precompiled files in the package. I was already intending
on providing this as an option anyway, so might as well start doing it
now.

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-01-09 09:40:07 -06:00
Brian S. Stephan 64d892eea0
ignore libusb NotImplementedError when detaching the driver
this is not meaningful (or possible) on Windows, so we can just ignore
it and move on

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-01-08 14:35:50 -06:00
Brian S. Stephan 933e44566c
documentation update for concatenate-ing in .uf2
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2024-01-08 13:09:49 -06:00
20 changed files with 1717 additions and 153 deletions

View File

@ -3,6 +3,26 @@
Included is a summary of changes to the project. For full details, especially on behind-the-scenes code changes and
development tools, see the commit history.
## v0.6.0
### Added
* Preliminary support for reading and writing "board config"s in the GP2040-CE binary. This will replace the precompiled
configuration for a particular board by way of `BoardConfig.h` with a second protobuf section of the flash that is
read from when a user config is not corrupt. `dump-config` can read that section, and `concatenate` can now write it;
the latter especially is expected to eventually be used by the core project's build tools.
* `concatenate` can write out to UF2 format, which is a more convenient file for end users, directly relevant to the
above goals.
* Precompiled protobuf files are now included in the Python package, so users don't need a clone of the GP2040-CE
repository in order to use the tools. This also works around a bug with the protobuf tool on Windows, where it can't
currently dynamically compile .proto files.
* Licensing/attribution errata has been added, and a DCO has been added to the repo.
### Improved
* `libusb` usage now ignores a `NotImplementedError` on Windows for something that doesn't make sense on that platform,
making operations over USB more likely to work properly on Windows.
## v0.5.1
### Added

View File

@ -4,8 +4,22 @@ Tools for working with GP2040-CE binary dumps.
## Dependencies
Interacting with your board (e.g. getting dumps, etc.) requires [picotool](https://github.com/raspberrypi/picotool), and
currently the expectation is that you can run it yourself before invoking these tools. That may change one day.
While not necessary for most tools, you may want [picotool](https://github.com/raspberrypi/picotool) as an alternative
way to dump binary data from the board. These dumps can be created with `gp2040ce-binary-tools` natively, but having an
alternative way to create a binary dump can be helpful, as these tools work as well (or better) with a binary dump as
over USB.
### Protobuf Files
All tools take `-P PATH` flag(s) in order to import Protobuf files (either precompiled Python files or raw .proto files)
if you have them locally, in order to work with the latest (or development) version of the configuration. That said,
this tool also includes a precompiled fallback version of the config structure if you cannot supply these files. Be
aware, however, that they are a point in time snapshot, and may lag the real format in undesirable ways. Supply the
latest Protobuf files if you can.
An example of this invocation is:
`visualize-storage -P ~/proj/GP2040-CE/proto -P ~/proj/GP2040-CE/lib/nanopb/generator/proto --filename memory.bin`
## Installation
@ -62,17 +76,19 @@ A quick demonstration of the editor is available [on asciinema.org](https://asci
* a config section .bin (with footer) (optionally padded) (`--binary-user-config-filename`) or
* a JSON file representing the config (`--json-user-config-filename`)
...and produces a properly-offset .bin file suitable for flashing to a board. This may be useful to ensure the board is
flashed with a particular configuration, for instances such as producing a binary to flash many boards with a particular
configuration (specific customizations, etc.), or keeping documented backups of what you're testing with during
...and produces a properly-offset firmware file suitable for flashing to a board with the provided config(s). This may
be useful to ensure the board is flashed with a particular configuration, for instances such as producing a binary to
flash many boards with a particular configuration (specific customizations, etc.), creating a file suitable for the
initial install of a fresh board (a "board config"), or keeping documented backups of what you're testing with during
development.
The `--...-board-config-filename` flags allow for shipping a default configuration as part of the binary, replacing
the need for generating these board configurations at compile time. This allows for more custom builds and less
dependency on the build jobs, and is a feature in progress in the core firmware.
The produced binary can be written to a file with `--new-binary-filename FILENAME` or straight to a RP2040 in BOOTSEL
mode with `--usb`.
The produced firmware + config(s) can be written to a file with `--new-binary-filename FILENAME` or straight to a RP2040
in BOOTSEL mode with `--usb`. The output file is a direct binary representation by default, but if `FILENAME` ends in
".uf2", it will be written in the UF2 format, which is generally more convenient to the end user.
Sample usage:
@ -89,7 +105,7 @@ This could be used with the other tools, or just to keep a backup.
Sample usage:
```
% dump-config -P ~/proj/GP2040-CE/proto -P ~/proj/GP2040-CE/lib/nanopb/generator/proto `date +%Y%m%d`-config-backup.bin
% dump-config `date +%Y%m%d`-config-backup.bin
```
### dump-gp2040ce
@ -110,21 +126,10 @@ storage section, and prints it out for visual inspection or diffing with other t
section from a GP2040-CE whole board dump, if you have that instead. Usage is simple; just connect your board in BOOTSEL
mode or pass the tool your binary file to analyze along with the path to the Protobuf files.
Because Protobuf relies on .proto files to convey the serialized structure, you must supply them from the main GP2040-CE
project, e.g. pointing this tool at your clone of the core project. Something like this would suffice for a working
invocation (note: you do not need to compile the files yourself):
```
% visualize-storage -P ~/proj/GP2040-CE/proto -P ~/proj/GP2040-CE/lib/nanopb/generator/proto --filename memory.bin
```
(In the future we will look into publishing complete packages that include the compiled `_pb2.py` files, so that you
don't need to provide them yourself.)
Sample output:
```
% visualize-storage -P ~/proj/GP2040-CE/proto -P ~/proj/GP2040-CE/lib/nanopb/generator/proto --usb
% visualize-storage --usb
boardVersion: "v0.7.2"
gamepadOptions {
inputMode: INPUT_MODE_HID

View File

@ -51,9 +51,18 @@ else:
def get_config_pb2():
"""Retrieve prebuilt _pb2 file or attempt to compile it live."""
# try to just import a precompiled module if we have been given it in our path
# (perhaps someone already compiled it for us for whatever reason)
try:
return importlib.import_module('config_pb2')
except ModuleNotFoundError:
# compile the proto files in realtime, leave them in this package
logger.info("Invoking gRPC tool to compile config.proto...")
return grpc.protos('config.proto')
# no found precompiled config, try to compile the proto files in realtime
# because it's possible someone put them on the path
try:
logger.info("Invoking gRPC tool to compile config.proto...")
return grpc.protos('config.proto')
except (ModuleNotFoundError, TypeError):
# (TypeError could be the windows bug https://github.com/protocolbuffers/protobuf/issues/14345)
# that failed, import a precompiled snapshot (may be lagging what's in GP2040-CE)
sys.path.append(os.path.join(pathlib.Path(__file__).parent.resolve(), 'proto_snapshot'))
return importlib.import_module('config_pb2')

View File

@ -10,7 +10,7 @@ Button {
margin: 0 1;
}
EditScreen, MessageScreen {
EditScreen {
align: center middle;
}
@ -20,6 +20,12 @@ EditScreen Label {
content-align: center middle;
}
#config_tree {
border: heavy gray;
padding: 1;
margin: 1;
}
.hidden {
visibility: hidden;
}
@ -33,14 +39,6 @@ EditScreen Label {
border: tall gray 100%;
}
#message-dialog {
padding: 0 1;
grid-rows: 3fr 2fr;
width: 50%;
height: 50%;
border: tall gray 100%;
}
#field-name, #field-input, #input-errors {
column-span: 2;
}

View File

@ -19,7 +19,7 @@ from textual.validation import Number
from textual.widgets import Button, Footer, Header, Input, Label, Pretty, Select, Tree
from textual.widgets.tree import TreeNode
from gp2040ce_bintools import core_parser, handler
from gp2040ce_bintools import core_parser, handler, _version
from gp2040ce_bintools.builder import write_new_config_to_filename, write_new_config_to_usb
from gp2040ce_bintools.rp2040 import get_bootsel_endpoints, read
from gp2040ce_bintools.storage import (STORAGE_SIZE, USER_CONFIG_BOOTSEL_ADDRESS, ConfigReadError, get_config,
@ -60,7 +60,7 @@ class EditScreen(ModalScreen):
Label(self.field_descriptor.full_name, id="field-name"),
self.input_field,
Pretty('', id='input-errors', classes='hidden'),
Button("Save", id='save-button'),
Button("Confirm", id='confirm-button'),
Button("Cancel", id='cancel-button'),
id='edit-dialog',
)
@ -70,7 +70,7 @@ class EditScreen(ModalScreen):
"""Update the UI to show why validation failed."""
if event.validation_result:
error_field = self.query_one(Pretty)
save_button = self.query_one('#save-button', Button)
save_button = self.query_one('#confirm-button', Button)
if not event.validation_result.is_valid:
error_field.update(event.validation_result.failure_descriptions)
error_field.classes = ''
@ -82,7 +82,7 @@ class EditScreen(ModalScreen):
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Process the button actions."""
if event.button.id == 'save-button':
if event.button.id == 'confirm-button':
logger.debug("calling _save")
self._save()
self.app.pop_screen()
@ -102,27 +102,6 @@ class EditScreen(ModalScreen):
self.node.set_label(pb_field_to_node_label(self.field_descriptor, field_value))
class MessageScreen(ModalScreen):
"""Simple screen for displaying messages."""
def __init__(self, text: str, *args, **kwargs):
"""Store the message for later display."""
self.text = text
super().__init__(*args, **kwargs)
def compose(self) -> ComposeResult:
"""Build the pop-up window with the desired message displayed."""
yield Grid(
Label(self.text, id="message-text"),
Button("OK", id='ok-button'),
id='message-dialog',
)
def on_button_pressed(self, event: Button.Pressed) -> None:
"""Process the button action (close the window)."""
self.app.pop_screen()
class ConfigEditor(App):
"""Display the GP2040-CE configuration as a tree."""
@ -132,7 +111,7 @@ class ConfigEditor(App):
('q', 'quit', "Quit"),
]
CSS_PATH = "config_tree.css"
TITLE = "GP2040-CE Configuration Editor"
TITLE = F"GP2040-CE Configuration Editor - {_version.version}"
def __init__(self, *args, **kwargs):
"""Initialize config."""
@ -162,7 +141,7 @@ class ConfigEditor(App):
"""Compose the UI."""
yield Header()
yield Footer()
yield Tree("Root")
yield Tree("Root", id='config_tree')
def on_mount(self) -> None:
"""Load the configuration object into the tree view."""
@ -218,12 +197,13 @@ class ConfigEditor(App):
"""Save the configuration."""
if self.usb:
write_new_config_to_usb(self.config, self.endpoint_out, self.endpoint_in)
self.push_screen(MessageScreen(f"Configuration saved to "
f"{hex(self.endpoint_out.device.idVendor)}:"
f"{hex(self.endpoint_out.device.idProduct)}."))
self.notify(f"Saved to {hex(self.endpoint_out.device.idVendor)}:"
f"{hex(self.endpoint_out.device.idProduct)}.",
title="Configuration Saved")
elif self.config_filename:
write_new_config_to_filename(self.config, self.config_filename, inject=self.whole_board)
self.push_screen(MessageScreen(f"Configuration saved to {self.config_filename}."))
self.notify(f"Saved to {self.config_filename}.",
title="Configuration Saved")
def action_quit(self) -> None:
"""Quit the application."""

View File

@ -0,0 +1,9 @@
"""COPIED OUTPUT OF `protoc foo.proto --python_out .`.
The .proto files here have been copied from https://github.com/OpenStickCommunity/GP2040-CE and
are a point in time import of the GP2040-CE firmware's configuration structure. THEY MAY BE OUT
OF DATE. If you are a developer, you should really use the `-P` flags to import your local copy
of the .proto files.
"""
GP2040CE_SNAPSHOT_VERSION = 'v0.7.7'

View File

@ -0,0 +1,747 @@
syntax = "proto2";
import "nanopb.proto";
import "enums.proto";
message GamepadOptions
{
optional InputMode inputMode = 1;
optional DpadMode dpadMode = 2;
optional SOCDMode socdMode = 3;
optional bool invertXAxis = 4;
optional bool invertYAxis = 5;
optional bool switchTpShareForDs4 = 6;
optional bool lockHotkeys = 7;
optional bool fourWayMode = 8;
optional uint32 profileNumber = 9;
optional PS4ControllerType ps4ControllerType = 10;
optional uint32 debounceDelay = 11;
optional int32 inputModeB1 = 12;
optional int32 inputModeB2 = 13;
optional int32 inputModeB3 = 14;
optional int32 inputModeB4 = 15;
optional int32 inputModeL1 = 16;
optional int32 inputModeL2 = 17;
optional int32 inputModeR1 = 18;
optional int32 inputModeR2 = 19;
optional bool ps4ReportHack = 20;
}
message KeyboardMapping
{
optional uint32 keyDpadUp = 1;
optional uint32 keyDpadDown = 2;
optional uint32 keyDpadLeft = 3;
optional uint32 keyDpadRight = 4;
optional uint32 keyButtonB1 = 5;
optional uint32 keyButtonB2 = 6;
optional uint32 keyButtonB3 = 7;
optional uint32 keyButtonB4 = 8;
optional uint32 keyButtonL1 = 9;
optional uint32 keyButtonR1 = 10;
optional uint32 keyButtonL2 = 11;
optional uint32 keyButtonR2 = 12;
optional uint32 keyButtonS1 = 13;
optional uint32 keyButtonS2 = 14;
optional uint32 keyButtonL3 = 15;
optional uint32 keyButtonR3 = 16;
optional uint32 keyButtonA1 = 17;
optional uint32 keyButtonA2 = 18;
}
message HotkeyEntry
{
optional uint32 dpadMask = 1;
optional GamepadHotkey action = 2;
optional uint32 buttonsMask = 3;
optional uint32 auxMask = 4;
}
message HotkeyOptions
{
optional HotkeyEntry hotkey01 = 1;
optional HotkeyEntry hotkey02 = 2;
optional HotkeyEntry hotkey03 = 3;
optional HotkeyEntry hotkey04 = 4;
optional HotkeyEntry hotkey05 = 5;
optional HotkeyEntry hotkey06 = 6;
optional HotkeyEntry hotkey07 = 7;
optional HotkeyEntry hotkey08 = 8;
optional HotkeyEntry hotkey09 = 9;
optional HotkeyEntry hotkey10 = 10;
optional HotkeyEntry hotkey11 = 11;
optional HotkeyEntry hotkey12 = 12;
optional HotkeyEntry hotkey13 = 13;
optional HotkeyEntry hotkey14 = 14;
optional HotkeyEntry hotkey15 = 15;
optional HotkeyEntry hotkey16 = 16;
}
message PeripheralOptions
{
message I2COptions {
optional bool enabled = 1;
optional int32 sda = 2;
optional int32 scl = 3;
optional uint32 speed = 4;
}
message SPIOptions {
optional bool enabled = 1;
optional int32 rx = 2;
optional int32 cs = 3;
optional int32 sck = 4;
optional int32 tx = 5;
}
message USBOptions {
optional bool enabled = 1;
optional int32 dp = 2;
optional int32 enable5v = 3;
optional uint32 order = 4;
}
optional I2COptions blockI2C0 = 1;
optional I2COptions blockI2C1 = 2;
optional SPIOptions blockSPI0 = 3;
optional SPIOptions blockSPI1 = 4;
optional USBOptions blockUSB0 = 5;
}
message ForcedSetupOptions
{
optional ForcedSetupMode mode = 1;
};
message ButtonLayoutParamsCommon
{
optional int32 startX = 1;
optional int32 startY = 2;
optional int32 buttonRadius = 3;
optional int32 buttonPadding = 4;
}
message ButtonLayoutParamsLeft
{
optional ButtonLayout layout = 1;
optional ButtonLayoutParamsCommon common = 2;
}
message ButtonLayoutParamsRight
{
optional ButtonLayoutRight layout = 1;
optional ButtonLayoutParamsCommon common = 2;
}
message ButtonLayoutCustomOptions
{
optional ButtonLayoutParamsLeft paramsLeft = 1;
optional ButtonLayoutParamsRight paramsRight = 2;
}
message PinMappings
{
optional int32 pinDpadUp = 1;
optional int32 pinDpadDown = 2;
optional int32 pinDpadLeft = 3;
optional int32 pinDpadRight = 4;
optional int32 pinButtonB1 = 5;
optional int32 pinButtonB2 = 6;
optional int32 pinButtonB3 = 7;
optional int32 pinButtonB4 = 8;
optional int32 pinButtonL1 = 9;
optional int32 pinButtonR1 = 10;
optional int32 pinButtonL2 = 11;
optional int32 pinButtonR2 = 12;
optional int32 pinButtonS1 = 13;
optional int32 pinButtonS2 = 14;
optional int32 pinButtonL3 = 15;
optional int32 pinButtonR3 = 16;
optional int32 pinButtonA1 = 17;
optional int32 pinButtonA2 = 18;
optional int32 pinButtonFn = 19;
}
message GpioMappingInfo
{
optional GpioAction action = 1;
}
message GpioMappings
{
repeated GpioMappingInfo pins = 1 [(nanopb).max_count = 30];
}
message AlternativePinMappings
{
optional int32 pinButtonB1 = 1;
optional int32 pinButtonB2 = 2;
optional int32 pinButtonB3 = 3;
optional int32 pinButtonB4 = 4;
optional int32 pinButtonL1 = 5;
optional int32 pinButtonR1 = 6;
optional int32 pinButtonL2 = 7;
optional int32 pinButtonR2 = 8;
optional int32 pinDpadUp = 9;
optional int32 pinDpadDown = 10;
optional int32 pinDpadLeft = 11;
optional int32 pinDpadRight = 12;
}
message ProfileOptions
{
repeated AlternativePinMappings deprecatedAlternativePinMappings = 1 [(nanopb).max_count = 3, deprecated = true];
repeated GpioMappings gpioMappingsSets = 2 [(nanopb).max_count = 3];
}
message DisplayOptions
{
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 i2cAddress = 5;
optional int32 deprecatedI2cSpeed = 6 [deprecated = true];
optional ButtonLayout buttonLayout = 7;
optional ButtonLayoutRight buttonLayoutRight = 8;
optional ButtonLayoutCustomOptions buttonLayoutCustomOptions = 9;
optional SplashMode splashMode = 10;
optional SplashChoice splashChoice = 11;
optional int32 splashDuration = 12;
optional bytes splashImage = 13 [(nanopb).max_size = 1024];
optional int32 size = 14;
optional int32 flip = 15;
optional bool invert = 16;
optional int32 displaySaverTimeout = 17;
optional bool turnOffWhenSuspended = 18;
}
message LEDOptions
{
optional int32 dataPin = 1;
optional LEDFormat_Proto ledFormat = 2;
optional ButtonLayout ledLayout = 3;
optional uint32 ledsPerButton = 4;
optional uint32 brightnessMaximum = 5;
optional uint32 brightnessSteps = 6;
optional int32 indexUp = 7;
optional int32 indexDown = 8;
optional int32 indexLeft = 9;
optional int32 indexRight = 10;
optional int32 indexB1 = 11;
optional int32 indexB2 = 12;
optional int32 indexB3 = 13;
optional int32 indexB4 = 14;
optional int32 indexL1 = 15;
optional int32 indexR1 = 16;
optional int32 indexL2 = 17;
optional int32 indexR2 = 18;
optional int32 indexS1 = 19;
optional int32 indexS2 = 20;
optional int32 indexL3 = 21;
optional int32 indexR3 = 22;
optional int32 indexA1 = 23;
optional int32 indexA2 = 24;
optional PLEDType pledType = 25;
optional int32 pledPin1 = 26;
optional int32 pledPin2 = 27;
optional int32 pledPin3 = 28;
optional int32 pledPin4 = 29;
optional uint32 pledColor = 30;
optional bool turnOffWhenSuspended = 31;
optional int32 pledIndex1 = 32;
optional int32 pledIndex2 = 33;
optional int32 pledIndex3 = 34;
optional int32 pledIndex4 = 35;
};
// This has to be kept in sync with AnimationOptions in AnimationStation.hpp
message AnimationOptions_Proto
{
optional uint32 baseAnimationIndex = 1;
optional uint32 brightness = 2;
optional uint32 staticColorIndex = 3;
optional uint32 buttonColorIndex = 4;
optional int32 chaseCycleTime = 5;
optional int32 rainbowCycleTime = 6;
optional uint32 themeIndex = 7;
optional bool hasCustomTheme = 8;
optional uint32 customThemeUp = 9;
optional uint32 customThemeDown = 10;
optional uint32 customThemeLeft = 11;
optional uint32 customThemeRight = 12;
optional uint32 customThemeB1 = 13;
optional uint32 customThemeB2 = 14;
optional uint32 customThemeB3 = 15;
optional uint32 customThemeB4 = 16;
optional uint32 customThemeL1 = 17;
optional uint32 customThemeR1 = 18;
optional uint32 customThemeL2 = 19;
optional uint32 customThemeR2 = 20;
optional uint32 customThemeS1 = 21;
optional uint32 customThemeS2 = 22;
optional uint32 customThemeL3 = 23;
optional uint32 customThemeR3 = 24;
optional uint32 customThemeA1 = 25;
optional uint32 customThemeA2 = 26;
optional uint32 customThemeUpPressed = 27;
optional uint32 customThemeDownPressed = 28;
optional uint32 customThemeLeftPressed = 29;
optional uint32 customThemeRightPressed = 30;
optional uint32 customThemeB1Pressed = 31;
optional uint32 customThemeB2Pressed = 32;
optional uint32 customThemeB3Pressed = 33;
optional uint32 customThemeB4Pressed = 34;
optional uint32 customThemeL1Pressed = 35;
optional uint32 customThemeR1Pressed = 36;
optional uint32 customThemeL2Pressed = 37;
optional uint32 customThemeR2Pressed = 38;
optional uint32 customThemeS1Pressed = 39;
optional uint32 customThemeS2Pressed = 40;
optional uint32 customThemeL3Pressed = 41;
optional uint32 customThemeR3Pressed = 42;
optional uint32 customThemeA1Pressed = 43;
optional uint32 customThemeA2Pressed = 44;
}
message BootselButtonOptions
{
optional bool enabled = 1;
optional uint32 buttonMap = 2;
}
message OnBoardLedOptions
{
optional OnBoardLedMode mode = 1;
optional bool enabled = 2;
}
message AnalogOptions
{
optional bool enabled = 1;
optional int32 analogAdc1PinX = 2;
optional int32 analogAdc1PinY = 3;
optional bool forced_circularity = 4;
optional uint32 analog_deadzone = 5;
optional int32 analogAdc2PinX = 6;
optional int32 analogAdc2PinY = 7;
optional DpadMode analogAdc1Mode = 8;
optional DpadMode analogAdc2Mode = 9;
optional InvertMode analogAdc1Invert = 10;
optional InvertMode analogAdc2Invert = 11;
optional bool auto_calibrate = 12;
}
message TurboOptions
{
optional bool enabled = 1;
optional int32 buttonPin = 2;
optional int32 ledPin = 3;
optional uint32 shotCount = 4;
optional int32 shmupDialPin = 5;
optional bool shmupModeEnabled = 6;
optional uint32 shmupAlwaysOn1 = 7;
optional uint32 shmupAlwaysOn2 = 8;
optional uint32 shmupAlwaysOn3 = 9;
optional uint32 shmupAlwaysOn4 = 10;
optional int32 shmupBtn1Pin = 11;
optional int32 shmupBtn2Pin = 12;
optional int32 shmupBtn3Pin = 13;
optional int32 shmupBtn4Pin = 14;
optional uint32 shmupBtnMask1 = 15;
optional uint32 shmupBtnMask2 = 16;
optional uint32 shmupBtnMask3 = 17;
optional uint32 shmupBtnMask4 = 18;
optional ShmupMixMode shmupMixMode = 19;
}
message SliderOptions
{
optional bool enabled = 1;
optional int32 deprecatedPinSliderOne = 2 [deprecated = true];
optional int32 deprecatedPinSliderTwo = 3 [deprecated = true];
optional DpadMode deprecatedModeOne = 4 [deprecated = true];
optional DpadMode deprecatedModeTwo = 5 [deprecated = true];
optional DpadMode modeDefault = 6;
}
message SOCDSliderOptions
{
optional bool enabled = 1;
optional int32 deprecatedPinOne = 2 [deprecated = true];
optional int32 deprecatedPinTwo = 3 [deprecated = true];
optional SOCDMode modeDefault = 4;
optional SOCDMode deprecatedModeOne = 5 [deprecated = true];
optional SOCDMode deprecatedModeTwo = 6 [deprecated = true];
}
message ReverseOptions
{
optional bool enabled = 1;
optional int32 buttonPin = 2;
optional int32 ledPin = 3;
optional uint32 actionUp = 4;
optional uint32 actionDown = 5;
optional uint32 actionLeft = 6;
optional uint32 actionRight = 7;
}
message AnalogADS1219Options
{
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 i2cAddress = 5;
optional int32 deprecatedI2cSpeed = 6 [deprecated = true];
}
message DualDirectionalOptions
{
optional bool enabled = 1;
optional int32 deprecatedUpPin = 2 [deprecated = true];
optional int32 deprecatedDownPin = 3 [deprecated = true];
optional int32 deprecatedLeftPin = 4 [deprecated = true];
optional int32 deprecatedRightPin = 5 [deprecated = true];
optional DpadMode dpadMode = 6;
optional uint32 combineMode = 7;
optional bool fourWayMode = 8;
}
message TiltOptions
{
optional bool enabled = 1;
optional int32 tilt1Pin = 2;
optional int32 tilt2Pin = 3;
optional int32 deprecatedTiltFunctionPin = 4 [deprecated = true];
optional int32 tiltLeftAnalogUpPin = 5;
optional int32 tiltLeftAnalogDownPin = 6;
optional int32 tiltLeftAnalogLeftPin = 7;
optional int32 tiltLeftAnalogRightPin = 8;
optional int32 tiltRightAnalogUpPin = 9;
optional int32 tiltRightAnalogDownPin = 10;
optional int32 tiltRightAnalogLeftPin = 11;
optional int32 tiltRightAnalogRightPin = 12;
optional SOCDMode tiltSOCDMode = 13;
optional int32 factorTilt1LeftX = 14;
optional int32 factorTilt1LeftY = 15;
optional int32 factorTilt1RightX = 16;
optional int32 factorTilt1RightY = 17;
optional int32 factorTilt2LeftX = 18;
optional int32 factorTilt2LeftY = 19;
optional int32 factorTilt2RightX = 20;
optional int32 factorTilt2RightY = 21;
}
message BuzzerOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
optional uint32 volume = 3;
}
message ExtraButtonOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
optional uint32 buttonMap = 3;
}
message PlayerNumberOptions
{
optional bool enabled = 1;
optional uint32 number = 2;
}
message PS4Options
{
optional bool enabled = 1;
optional bytes serial = 2 [(nanopb).max_size = 16];
optional bytes signature = 3 [(nanopb).max_size = 256];
optional bytes rsaN = 4 [(nanopb).max_size = 256];
optional bytes rsaE = 5 [(nanopb).max_size = 4];
optional bytes rsaD = 6 [(nanopb).max_size = 256];
optional bytes rsaP = 7 [(nanopb).max_size = 128];
optional bytes rsaQ = 8 [(nanopb).max_size = 128];
optional bytes rsaDP = 9 [(nanopb).max_size = 128];
optional bytes rsaDQ = 10 [(nanopb).max_size = 128];
optional bytes rsaQP = 11 [(nanopb).max_size = 128];
optional bytes rsaRN = 12 [(nanopb).max_size = 256];
}
message PSPassthroughOptions
{
optional bool enabled = 1;
optional int32 deprecatedPinDplus = 2 [deprecated = true];
optional int32 deprecatedPin5V = 3 [deprecated = true];
}
message XBOnePassthroughOptions
{
optional bool enabled = 1;
}
message WiiOptions
{
message AnalogAxis
{
optional int32 axisType = 1;
optional int32 minRange = 2;
optional int32 maxRange = 3;
}
message StickOptions
{
optional AnalogAxis x = 1;
optional AnalogAxis y = 2;
}
message NunchukOptions
{
optional int32 buttonC = 1;
optional int32 buttonZ = 2;
optional StickOptions stick = 3;
}
message ClassicOptions
{
optional int32 buttonA = 1;
optional int32 buttonB = 2;
optional int32 buttonX = 3;
optional int32 buttonY = 4;
optional int32 buttonL = 5;
optional int32 buttonZL = 6;
optional int32 buttonR = 7;
optional int32 buttonZR = 8;
optional int32 buttonMinus = 9;
optional int32 buttonPlus = 10;
optional int32 buttonHome = 11;
optional int32 buttonUp = 12;
optional int32 buttonDown = 13;
optional int32 buttonLeft = 14;
optional int32 buttonRight = 15;
optional StickOptions rightStick = 17;
optional StickOptions leftStick = 16;
optional AnalogAxis leftTrigger = 18;
optional AnalogAxis rightTrigger = 19;
}
message TaikoOptions
{
optional int32 buttonKatLeft = 1;
optional int32 buttonKatRight = 2;
optional int32 buttonDonLeft = 3;
optional int32 buttonDonRight = 4;
}
message GuitarOptions
{
optional int32 buttonRed = 1;
optional int32 buttonGreen = 2;
optional int32 buttonYellow = 3;
optional int32 buttonBlue = 4;
optional int32 buttonOrange = 5;
optional int32 buttonPedal = 6;
optional int32 buttonMinus = 7;
optional int32 buttonPlus = 8;
optional int32 strumUp = 9;
optional int32 strumDown = 10;
optional StickOptions stick = 11;
optional AnalogAxis whammyBar = 12;
}
message DrumOptions
{
optional int32 buttonRed = 1;
optional int32 buttonGreen = 2;
optional int32 buttonYellow = 3;
optional int32 buttonBlue = 4;
optional int32 buttonOrange = 5;
optional int32 buttonPedal = 6;
optional int32 buttonMinus = 7;
optional int32 buttonPlus = 8;
optional StickOptions stick = 9;
}
message TurntableOptions
{
optional int32 buttonLeftRed = 1;
optional int32 buttonLeftGreen = 2;
optional int32 buttonLeftBlue = 3;
optional int32 buttonRightRed = 4;
optional int32 buttonRightGreen = 5;
optional int32 buttonRightBlue = 6;
optional int32 buttonMinus = 7;
optional int32 buttonPlus = 8;
optional int32 buttonEuphoria = 9;
optional StickOptions stick = 10;
optional AnalogAxis leftTurntable = 11;
optional AnalogAxis rightTurntable = 12;
optional AnalogAxis effects = 13;
optional AnalogAxis fader = 14;
}
message ControllerOptions
{
optional NunchukOptions nunchuk = 1;
optional ClassicOptions classic = 2;
optional TaikoOptions taiko = 3;
optional GuitarOptions guitar = 4;
optional DrumOptions drum = 5;
optional TurntableOptions turntable = 6;
}
optional bool enabled = 1;
optional int32 i2cBlock = 2;
optional int32 deprecatedI2cSDAPin = 3 [deprecated = true];
optional int32 deprecatedI2cSCLPin = 4 [deprecated = true];
optional int32 deprecatedI2cSpeed = 5 [deprecated = true];
optional ControllerOptions controllers = 6;
}
message SNESOptions
{
optional bool enabled = 1;
optional int32 clockPin = 2;
optional int32 latchPin = 3;
optional int32 dataPin = 4;
}
message KeyboardHostOptions
{
optional bool enabled = 1;
optional int32 deprecatedPinDplus = 2 [deprecated = true];
optional KeyboardMapping mapping = 3;
optional int32 deprecatedPin5V = 4 [deprecated = true];
}
message FocusModeOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
optional int32 buttonLockMask = 3;
optional bool oledLockEnabled = 4;
optional bool rgbLockEnabled = 5;
optional bool buttonLockEnabled = 6;
optional bool macroLockEnabled = 7;
}
message MacroInput
{
optional uint32 buttonMask = 1;
optional uint32 duration = 2;
optional uint32 waitDuration = 3 [default = 0];
}
message Macro
{
optional MacroType macroType = 1;
optional string macroLabel = 2 [(nanopb).max_length = 64];
repeated MacroInput macroInputs = 3 [(nanopb).max_count = 30];
optional bool enabled = 4;
optional bool useMacroTriggerButton = 5;
optional int32 macroTriggerPin = 6 [default = -1];
optional uint32 macroTriggerButton = 7;
optional bool exclusive = 8 [default = true];
optional bool interruptible = 9 [default = true];
optional bool showFrames = 10 [default = false];
}
message MacroOptions
{
optional bool enabled = 1;
optional int32 pin = 2;
optional bool macroBoardLedEnabled = 4;
repeated Macro macroList = 3 [(nanopb).max_count = 6];
}
message InputHistoryOptions
{
optional bool enabled = 1;
optional uint32 length = 2;
optional uint32 col = 3;
optional uint32 row = 4;
}
message AddonOptions
{
optional BootselButtonOptions bootselButtonOptions = 1;
optional OnBoardLedOptions onBoardLedOptions = 2;
optional AnalogOptions analogOptions = 3;
optional TurboOptions turboOptions = 4;
optional SliderOptions sliderOptions = 5;
optional ReverseOptions reverseOptions = 6;
optional AnalogADS1219Options analogADS1219Options = 7;
optional DualDirectionalOptions dualDirectionalOptions = 8;
optional BuzzerOptions buzzerOptions = 9;
optional ExtraButtonOptions deprecatedExtraButtonOptions = 10 [deprecated = true];
optional PlayerNumberOptions playerNumberOptions = 11;
optional PS4Options ps4Options = 12 [(nanopb).disallow_export = true];
optional WiiOptions wiiOptions = 13;
optional SOCDSliderOptions socdSliderOptions = 14;
optional SNESOptions snesOptions = 15;
optional FocusModeOptions focusModeOptions = 16;
optional KeyboardHostOptions keyboardHostOptions = 17;
optional TiltOptions tiltOptions = 18;
optional PSPassthroughOptions psPassthroughOptions = 19;
optional MacroOptions macroOptions = 20;
optional InputHistoryOptions inputHistoryOptions = 21;
optional XBOnePassthroughOptions xbonePassthroughOptions = 22;
}
message MigrationHistory
{
optional bool hotkeysMigrated = 1 [default = false];
optional bool gpioMappingsMigrated = 2 [default = false];
optional bool buttonProfilesMigrated = 3 [default = false];
}
message Config
{
optional string boardVersion = 1 [(nanopb).max_length = 31];
optional GamepadOptions gamepadOptions = 2;
optional HotkeyOptions hotkeyOptions = 3;
optional PinMappings deprecatedPinMappings = 4 [deprecated = true];
optional KeyboardMapping keyboardMapping = 5;
optional DisplayOptions displayOptions = 6;
optional LEDOptions ledOptions = 7;
optional AnimationOptions_Proto animationOptions = 8;
optional AddonOptions addonOptions = 9;
optional ForcedSetupOptions forcedSetupOptions = 10;
optional ProfileOptions profileOptions = 11;
optional string boardConfig = 12 [(nanopb).max_length = 63];
optional GpioMappings gpioMappings = 13;
optional MigrationHistory migrations = 14;
optional PeripheralOptions peripheralOptions = 15;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,266 @@
syntax = "proto2";
import "nanopb.proto";
enum ButtonLayout
{
option (nanopb_enumopt).long_names = false;
BUTTON_LAYOUT_STICK = 0;
BUTTON_LAYOUT_STICKLESS = 1;
BUTTON_LAYOUT_BUTTONS_ANGLED = 2;
BUTTON_LAYOUT_BUTTONS_BASIC = 3;
BUTTON_LAYOUT_KEYBOARD_ANGLED = 4;
BUTTON_LAYOUT_KEYBOARDA = 5;
BUTTON_LAYOUT_DANCEPADA = 6;
BUTTON_LAYOUT_TWINSTICKA = 7;
BUTTON_LAYOUT_BLANKA = 8;
BUTTON_LAYOUT_VLXA = 9;
BUTTON_LAYOUT_FIGHTBOARD_STICK = 10;
BUTTON_LAYOUT_FIGHTBOARD_MIRRORED = 11;
BUTTON_LAYOUT_CUSTOMA = 12;
BUTTON_LAYOUT_OPENCORE0WASDA = 13;
}
enum ButtonLayoutRight
{
option (nanopb_enumopt).long_names = false;
BUTTON_LAYOUT_ARCADE = 0;
BUTTON_LAYOUT_STICKLESSB = 1;
BUTTON_LAYOUT_BUTTONS_ANGLEDB = 2;
BUTTON_LAYOUT_VEWLIX = 3;
BUTTON_LAYOUT_VEWLIX7 = 4;
BUTTON_LAYOUT_CAPCOM = 5;
BUTTON_LAYOUT_CAPCOM6 = 6;
BUTTON_LAYOUT_SEGA2P = 7;
BUTTON_LAYOUT_NOIR8 = 8;
BUTTON_LAYOUT_KEYBOARDB = 9;
BUTTON_LAYOUT_DANCEPADB = 10;
BUTTON_LAYOUT_TWINSTICKB = 11;
BUTTON_LAYOUT_BLANKB = 12;
BUTTON_LAYOUT_VLXB = 13;
BUTTON_LAYOUT_FIGHTBOARD = 14;
BUTTON_LAYOUT_FIGHTBOARD_STICK_MIRRORED = 15;
BUTTON_LAYOUT_CUSTOMB = 16;
BUTTON_LAYOUT_KEYBOARD8B = 17;
BUTTON_LAYOUT_OPENCORE0WASDB = 18;
}
enum SplashMode
{
option (nanopb_enumopt).long_names = false;
SPLASH_MODE_STATIC = 0;
SPLASH_MODE_CLOSEIN = 1;
SPLASH_MODE_CLOSEINCUSTOM = 2;
SPLASH_MODE_NONE = 3;
}
enum SplashChoice
{
option (nanopb_enumopt).long_names = false;
SPLASH_CHOICE_MAIN = 0;
SPLASH_CHOICE_X = 1;
SPLASH_CHOICE_Y = 2;
SPLASH_CHOICE_Z = 3;
SPLASH_CHOICE_CUSTOM = 4;
SPLASH_CHOICE_LEGACY = 5;
}
enum OnBoardLedMode
{
option (nanopb_enumopt).long_names = false;
ON_BOARD_LED_MODE_OFF = 0;
ON_BOARD_LED_MODE_MODE_INDICATOR = 1;
ON_BOARD_LED_MODE_INPUT_TEST = 2;
ON_BOARD_LED_MODE_PS_AUTH = 3;
}
enum InputMode
{
option (nanopb_enumopt).long_names = false;
INPUT_MODE_XINPUT = 0;
INPUT_MODE_SWITCH = 1;
INPUT_MODE_HID = 2;
INPUT_MODE_KEYBOARD = 3;
INPUT_MODE_PS4 = 4;
INPUT_MODE_XBONE = 5;
INPUT_MODE_MDMINI = 6;
INPUT_MODE_NEOGEO = 7;
INPUT_MODE_PCEMINI = 8;
INPUT_MODE_EGRET = 9;
INPUT_MODE_ASTRO = 10;
INPUT_MODE_PSCLASSIC = 11;
INPUT_MODE_XBOXORIGINAL = 12;
INPUT_MODE_CONFIG = 255;
}
enum DpadMode
{
option (nanopb_enumopt).long_names = false;
DPAD_MODE_DIGITAL = 0;
DPAD_MODE_LEFT_ANALOG = 1;
DPAD_MODE_RIGHT_ANALOG = 2;
}
enum InvertMode
{
option (nanopb_enumopt).long_names = false;
INVERT_NONE = 0;
INVERT_X = 1;
INVERT_Y = 2;
INVERT_XY = 3;
}
enum SOCDMode
{
option (nanopb_enumopt).long_names = false;
SOCD_MODE_UP_PRIORITY = 0; // U+D=U, L+R=N
SOCD_MODE_NEUTRAL = 1; // U+D=N, L+R=N
SOCD_MODE_SECOND_INPUT_PRIORITY = 2; // U>D=D, L>R=R (Last Input Priority, aka Last Win)
SOCD_MODE_FIRST_INPUT_PRIORITY = 3; // U>D=U, L>R=L (First Input Priority, aka First Win)
SOCD_MODE_BYPASS = 4; // U+D=UD, L+R=LR (No cleaning applied)
}
enum GpioAction
{
option (nanopb_enumopt).long_names = false;
// the lowest value is the default, which should be NONE;
// reserving some numbers in case we need more not-mapped type values
NONE = -10;
RESERVED = -5;
ASSIGNED_TO_ADDON = 0;
BUTTON_PRESS_UP = 1;
BUTTON_PRESS_DOWN = 2;
BUTTON_PRESS_LEFT = 3;
BUTTON_PRESS_RIGHT = 4;
BUTTON_PRESS_B1 = 5;
BUTTON_PRESS_B2 = 6;
BUTTON_PRESS_B3 = 7;
BUTTON_PRESS_B4 = 8;
BUTTON_PRESS_L1 = 9;
BUTTON_PRESS_R1 = 10;
BUTTON_PRESS_L2 = 11;
BUTTON_PRESS_R2 = 12;
BUTTON_PRESS_S1 = 13;
BUTTON_PRESS_S2 = 14;
BUTTON_PRESS_A1 = 15;
BUTTON_PRESS_A2 = 16;
BUTTON_PRESS_L3 = 17;
BUTTON_PRESS_R3 = 18;
BUTTON_PRESS_FN = 19;
BUTTON_PRESS_DDI_UP = 20;
BUTTON_PRESS_DDI_DOWN = 21;
BUTTON_PRESS_DDI_LEFT = 22;
BUTTON_PRESS_DDI_RIGHT = 23;
SUSTAIN_DP_MODE_DP = 24;
SUSTAIN_DP_MODE_LS = 25;
SUSTAIN_DP_MODE_RS = 26;
SUSTAIN_SOCD_MODE_UP_PRIO = 27;
SUSTAIN_SOCD_MODE_NEUTRAL = 28;
SUSTAIN_SOCD_MODE_SECOND_WIN = 29;
SUSTAIN_SOCD_MODE_FIRST_WIN = 30;
SUSTAIN_SOCD_MODE_BYPASS = 31;
}
enum GamepadHotkey
{
option (nanopb_enumopt).long_names = false;
HOTKEY_NONE = 0;
HOTKEY_DPAD_DIGITAL = 1;
HOTKEY_DPAD_LEFT_ANALOG = 2;
HOTKEY_DPAD_RIGHT_ANALOG = 3;
HOTKEY_HOME_BUTTON = 4;
HOTKEY_CAPTURE_BUTTON = 5;
HOTKEY_SOCD_UP_PRIORITY = 6;
HOTKEY_SOCD_NEUTRAL = 7;
HOTKEY_SOCD_LAST_INPUT = 8;
HOTKEY_INVERT_X_AXIS = 9;
HOTKEY_INVERT_Y_AXIS = 10;
HOTKEY_SOCD_FIRST_INPUT = 11;
HOTKEY_SOCD_BYPASS = 12;
HOTKEY_TOGGLE_4_WAY_MODE = 13;
HOTKEY_TOGGLE_DDI_4_WAY_MODE = 14;
HOTKEY_LOAD_PROFILE_1 = 15;
HOTKEY_LOAD_PROFILE_2 = 16;
HOTKEY_LOAD_PROFILE_3 = 17;
HOTKEY_LOAD_PROFILE_4 = 18;
HOTKEY_L3_BUTTON = 19;
HOTKEY_R3_BUTTON = 20;
HOTKEY_TOUCHPAD_BUTTON = 21;
HOTKEY_REBOOT_DEFAULT = 22;
HOTKEY_B1_BUTTON = 23;
HOTKEY_B2_BUTTON = 24;
HOTKEY_B3_BUTTON = 25;
HOTKEY_B4_BUTTON = 26;
HOTKEY_L1_BUTTON = 27;
HOTKEY_R1_BUTTON = 28;
HOTKEY_L2_BUTTON = 29;
HOTKEY_R2_BUTTON = 30;
HOTKEY_S1_BUTTON = 31;
HOTKEY_S2_BUTTON = 32;
HOTKEY_A1_BUTTON = 33;
HOTKEY_A2_BUTTON = 34;
}
// This has to be kept in sync with LEDFormat in NeoPico.hpp
enum LEDFormat_Proto
{
LED_FORMAT_GRB = 0;
LED_FORMAT_RGB = 1;
LED_FORMAT_GRBW = 2;
LED_FORMAT_RGBW = 3;
}
enum ShmupMixMode
{
option (nanopb_enumopt).long_names = false;
SHMUP_MIX_MODE_TURBO_PRIORITY = 0;
SHMUP_MIX_MODE_CHARGE_PRIORITY = 1;
}
enum PLEDType
{
option (nanopb_enumopt).long_names = false;
PLED_TYPE_NONE = -1;
PLED_TYPE_PWM = 0;
PLED_TYPE_RGB = 1;
};
enum ForcedSetupMode
{
option (nanopb_enumopt).long_names = false;
FORCED_SETUP_MODE_OFF = 0;
FORCED_SETUP_MODE_LOCK_MODE_SWITCH = 1;
FORCED_SETUP_MODE_LOCK_WEB_CONFIG = 2;
FORCED_SETUP_MODE_LOCK_BOTH = 3;
};
enum PS4ControllerType
{
option (nanopb_enumopt).long_names = false;
PS4_CONTROLLER = 0;
PS4_ARCADESTICK = 7;
}
enum MacroType
{
option (nanopb_enumopt).long_names = false;
ON_PRESS = 1;
ON_HOLD_REPEAT = 2;
ON_TOGGLE = 3;
};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,189 @@
// Custom options for defining:
// - Maximum size of string/bytes
// - Maximum number of elements in array
//
// These are used by nanopb to generate statically allocable structures
// for memory-limited environments.
syntax = "proto2";
import "google/protobuf/descriptor.proto";
option java_package = "fi.kapsi.koti.jpa.nanopb";
enum FieldType {
FT_DEFAULT = 0; // Automatically decide field type, generate static field if possible.
FT_CALLBACK = 1; // Always generate a callback field.
FT_POINTER = 4; // Always generate a dynamically allocated field.
FT_STATIC = 2; // Generate a static field or raise an exception if not possible.
FT_IGNORE = 3; // Ignore the field completely.
FT_INLINE = 5; // Legacy option, use the separate 'fixed_length' option instead
}
enum IntSize {
IS_DEFAULT = 0; // Default, 32/64bit based on type in .proto
IS_8 = 8;
IS_16 = 16;
IS_32 = 32;
IS_64 = 64;
}
enum TypenameMangling {
M_NONE = 0; // Default, no typename mangling
M_STRIP_PACKAGE = 1; // Strip current package name
M_FLATTEN = 2; // Only use last path component
M_PACKAGE_INITIALS = 3; // Replace the package name by the initials
}
enum DescriptorSize {
DS_AUTO = 0; // Select minimal size based on field type
DS_1 = 1; // 1 word; up to 15 byte fields, no arrays
DS_2 = 2; // 2 words; up to 4095 byte fields, 4095 entry arrays
DS_4 = 4; // 4 words; up to 2^32-1 byte fields, 2^16-1 entry arrays
DS_8 = 8; // 8 words; up to 2^32-1 entry arrays
}
// This is the inner options message, which basically defines options for
// a field. When it is used in message or file scope, it applies to all
// fields.
message NanoPBOptions {
// Allocated size for 'bytes' and 'string' fields.
// For string fields, this should include the space for null terminator.
optional int32 max_size = 1;
// Maximum length for 'string' fields. Setting this is equivalent
// to setting max_size to a value of length+1.
optional int32 max_length = 14;
// Allocated number of entries in arrays ('repeated' fields)
optional int32 max_count = 2;
// Size of integer fields. Can save some memory if you don't need
// full 32 bits for the value.
optional IntSize int_size = 7 [default = IS_DEFAULT];
// Force type of field (callback or static allocation)
optional FieldType type = 3 [default = FT_DEFAULT];
// Use long names for enums, i.e. EnumName_EnumValue.
optional bool long_names = 4 [default = true];
// Add 'packed' attribute to generated structs.
// Note: this cannot be used on CPUs that break on unaligned
// accesses to variables.
optional bool packed_struct = 5 [default = false];
// Add 'packed' attribute to generated enums.
optional bool packed_enum = 10 [default = false];
// Skip this message
optional bool skip_message = 6 [default = false];
// Generate oneof fields as normal optional fields instead of union.
optional bool no_unions = 8 [default = false];
// integer type tag for a message
optional uint32 msgid = 9;
// decode oneof as anonymous union
optional bool anonymous_oneof = 11 [default = false];
// Proto3 singular field does not generate a "has_" flag
optional bool proto3 = 12 [default = false];
// Force proto3 messages to have no "has_" flag.
// This was default behavior until nanopb-0.4.0.
optional bool proto3_singular_msgs = 21 [default = false];
// Generate an enum->string mapping function (can take up lots of space).
optional bool enum_to_string = 13 [default = false];
// Generate bytes arrays with fixed length
optional bool fixed_length = 15 [default = false];
// Generate repeated field with fixed count
optional bool fixed_count = 16 [default = false];
// Generate message-level callback that is called before decoding submessages.
// This can be used to set callback fields for submsgs inside oneofs.
optional bool submsg_callback = 22 [default = false];
// Shorten or remove package names from type names.
// This option applies only on the file level.
optional TypenameMangling mangle_names = 17 [default = M_NONE];
// Data type for storage associated with callback fields.
optional string callback_datatype = 18 [default = "pb_callback_t"];
// Callback function used for encoding and decoding.
// Prior to nanopb-0.4.0, the callback was specified in per-field pb_callback_t
// structure. This is still supported, but does not work inside e.g. oneof or pointer
// fields. Instead, a new method allows specifying a per-message callback that
// will be called for all callback fields in a message type.
optional string callback_function = 19 [default = "pb_default_field_callback"];
// Select the size of field descriptors. This option has to be defined
// for the whole message, not per-field. Usually automatic selection is
// ok, but if it results in compilation errors you can increase the field
// size here.
optional DescriptorSize descriptorsize = 20 [default = DS_AUTO];
// Set default value for has_ fields.
optional bool default_has = 23 [default = false];
// Extra files to include in generated `.pb.h`
repeated string include = 24;
// Automatic includes to exclude from generated `.pb.h`
// Same as nanopb_generator.py command line flag -x.
repeated string exclude = 26;
// Package name that applies only for nanopb.
optional string package = 25;
// Override type of the field in generated C code. Only to be used with related field types
optional google.protobuf.FieldDescriptorProto.Type type_override = 27;
// Due to historical reasons, nanopb orders fields in structs by their tag number
// instead of the order in .proto. Set this to false to keep the .proto order.
// The default value will probably change to false in nanopb-0.5.0.
optional bool sort_by_tag = 28 [default = true];
// Set the FT_DEFAULT field conversion strategy.
// A field that can become a static member of a c struct (e.g. int, bool, etc)
// will be a a static field.
// Fields with dynamic length are converted to either a pointer or a callback.
optional FieldType fallback_type = 29 [default = FT_CALLBACK];
// GP2040-CE extension
// Marks a field to be excluded when performing export operations (i.e. converting to JSON)
optional bool disallow_export = 30 [default = false];
}
// Extensions to protoc 'Descriptor' type in order to define options
// inside a .proto file.
//
// Protocol Buffers extension number registry
// --------------------------------
// Project: Nanopb
// Contact: Petteri Aimonen <jpa@kapsi.fi>
// Web site: http://kapsi.fi/~jpa/nanopb
// Extensions: 1010 (all types)
// --------------------------------
extend google.protobuf.FileOptions {
optional NanoPBOptions nanopb_fileopt = 1010;
}
extend google.protobuf.MessageOptions {
optional NanoPBOptions nanopb_msgopt = 1010;
}
extend google.protobuf.EnumOptions {
optional NanoPBOptions nanopb_enumopt = 1010;
}
extend google.protobuf.FieldOptions {
optional NanoPBOptions nanopb = 1010;
}

View File

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: nanopb.proto
"""Generated protocol buffer code."""
from google.protobuf.internal import builder as _builder
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"\xc4\x07\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x12\n\nmax_length\x18\x0e \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12&\n\x08int_size\x18\x07 \x01(\x0e\x32\x08.IntSize:\nIS_DEFAULT\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bpacked_enum\x18\n \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0cskip_message\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x18\n\tno_unions\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05msgid\x18\t \x01(\r\x12\x1e\n\x0f\x61nonymous_oneof\x18\x0b \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06proto3\x18\x0c \x01(\x08:\x05\x66\x61lse\x12#\n\x14proto3_singular_msgs\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0e\x65num_to_string\x18\r \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0c\x66ixed_length\x18\x0f \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0b\x66ixed_count\x18\x10 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0fsubmsg_callback\x18\x16 \x01(\x08:\x05\x66\x61lse\x12/\n\x0cmangle_names\x18\x11 \x01(\x0e\x32\x11.TypenameMangling:\x06M_NONE\x12(\n\x11\x63\x61llback_datatype\x18\x12 \x01(\t:\rpb_callback_t\x12\x34\n\x11\x63\x61llback_function\x18\x13 \x01(\t:\x19pb_default_field_callback\x12\x30\n\x0e\x64\x65scriptorsize\x18\x14 \x01(\x0e\x32\x0f.DescriptorSize:\x07\x44S_AUTO\x12\x1a\n\x0b\x64\x65\x66\x61ult_has\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07include\x18\x18 \x03(\t\x12\x0f\n\x07\x65xclude\x18\x1a \x03(\t\x12\x0f\n\x07package\x18\x19 \x01(\t\x12\x41\n\rtype_override\x18\x1b \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x19\n\x0bsort_by_tag\x18\x1c \x01(\x08:\x04true\x12.\n\rfallback_type\x18\x1d \x01(\x0e\x32\n.FieldType:\x0b\x46T_CALLBACK\x12\x1e\n\x0f\x64isallow_export\x18\x1e \x01(\x08:\x05\x66\x61lse*i\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03\x12\r\n\tFT_INLINE\x10\x05*D\n\x07IntSize\x12\x0e\n\nIS_DEFAULT\x10\x00\x12\x08\n\x04IS_8\x10\x08\x12\t\n\x05IS_16\x10\x10\x12\t\n\x05IS_32\x10 \x12\t\n\x05IS_64\x10@*Z\n\x10TypenameMangling\x12\n\n\x06M_NONE\x10\x00\x12\x13\n\x0fM_STRIP_PACKAGE\x10\x01\x12\r\n\tM_FLATTEN\x10\x02\x12\x16\n\x12M_PACKAGE_INITIALS\x10\x03*E\n\x0e\x44\x65scriptorSize\x12\x0b\n\x07\x44S_AUTO\x10\x00\x12\x08\n\x04\x44S_1\x10\x01\x12\x08\n\x04\x44S_2\x10\x02\x12\x08\n\x04\x44S_4\x10\x04\x12\x08\n\x04\x44S_8\x10\x08:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB\x1a\n\x18\x66i.kapsi.koti.jpa.nanopb')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'nanopb_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(nanopb_fileopt)
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(nanopb_msgopt)
google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(nanopb_enumopt)
google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(nanopb)
DESCRIPTOR._options = None
DESCRIPTOR._serialized_options = b'\n\030fi.kapsi.koti.jpa.nanopb'
_FIELDTYPE._serialized_start=1017
_FIELDTYPE._serialized_end=1122
_INTSIZE._serialized_start=1124
_INTSIZE._serialized_end=1192
_TYPENAMEMANGLING._serialized_start=1194
_TYPENAMEMANGLING._serialized_end=1284
_DESCRIPTORSIZE._serialized_start=1286
_DESCRIPTORSIZE._serialized_end=1355
_NANOPBOPTIONS._serialized_start=51
_NANOPBOPTIONS._serialized_end=1015
# @@protoc_insertion_point(module_scope)

View File

@ -56,8 +56,12 @@ def get_bootsel_endpoints() -> tuple[usb.core.Endpoint, usb.core.Endpoint]:
if not pico_device:
raise ValueError("RP2040 board in BOOTSEL mode could not be found!")
if pico_device.is_kernel_driver_active(0):
pico_device.detach_kernel_driver(0)
try:
if pico_device.is_kernel_driver_active(0):
pico_device.detach_kernel_driver(0)
except NotImplementedError:
# detaching the driver is for *nix, not possible/relevant on Windows
pass
pico_configuration = pico_device.get_active_configuration()
# two interfaces are present, we want the direct rather than mass storage

View File

@ -42,7 +42,7 @@ visualize-storage = "gp2040ce_bintools.storage:visualize"
[tool.flake8]
enable-extensions = "G,M"
exclude = [".tox/", "venv/", "_version.py", "tests/test-files/"]
exclude = [".tox/", "venv/", "_version.py", "tests/test-files/", "config_pb2.py", "enums_pb2.py", "nanopb_pb2.py"]
extend-ignore = "T101"
max-complexity = 10
max-line-length = 120
@ -51,6 +51,11 @@ max-line-length = 120
line_length = 120
[tool.mypy]
exclude = [
"config_pb2.py",
"enums_pb2.py",
"nanopb_pb2.py",
]
ignore_missing_imports = true
[[tool.mypy.overrides]]

View File

@ -1,18 +1,16 @@
#
# This file is autogenerated by pip-compile with Python 3.10
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile --extra=dev --output-file=requirements/requirements-dev.txt
# pip-compile --extra=dev --output-file=requirements/requirements-dev.txt pyproject.toml
#
aiohttp==3.8.6
aiohttp==3.9.3
# via textual-dev
aiosignal==1.3.1
# via aiohttp
async-timeout==4.0.3
attrs==23.2.0
# via aiohttp
attrs==23.1.0
# via aiohttp
bandit==1.7.5
bandit==1.7.7
# via gp2040ce-binary-tools (pyproject.toml)
build==1.0.3
# via pip-tools
@ -20,27 +18,25 @@ cachetools==5.3.2
# via tox
chardet==5.2.0
# via tox
charset-normalizer==3.3.2
# via aiohttp
click==8.1.7
# via
# pip-tools
# textual-dev
colorama==0.4.6
# via tox
coverage[toml]==7.3.2
# via pytest-cov
coverage[toml]==7.4.1
# via
# coverage
# pytest-cov
decorator==5.1.1
# via gp2040ce-binary-tools (pyproject.toml)
distlib==0.3.7
distlib==0.3.8
# via virtualenv
exceptiongroup==1.1.3
# via pytest
filelock==3.13.1
# via
# tox
# virtualenv
flake8==6.1.0
flake8==7.0.0
# via
# flake8-builtins
# flake8-docstrings
@ -67,30 +63,25 @@ flake8-mutable==1.2.0
# via gp2040ce-binary-tools (pyproject.toml)
flake8-pyproject==1.2.3
# via gp2040ce-binary-tools (pyproject.toml)
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal
gitdb==4.0.11
# via gitpython
gitpython==3.1.40
# via bandit
grpcio==1.59.2
grpcio==1.60.0
# via grpcio-tools
grpcio-tools==1.59.2
grpcio-tools==1.60.0
# via gp2040ce-binary-tools (pyproject.toml)
idna==3.4
idna==3.6
# via yarl
importlib-metadata==6.8.0
# via textual
iniconfig==2.0.0
# via pytest
isort==5.12.0
isort==5.13.2
# via flake8-isort
linkify-it-py==2.0.2
# via markdown-it-py
markdown-it-py[linkify,plugins]==3.0.0
# via
# markdown-it-py
# mdit-py-plugins
# rich
# textual
@ -106,7 +97,7 @@ multidict==6.0.4
# via
# aiohttp
# yarl
mypy==1.6.1
mypy==1.8.0
# via gp2040ce-binary-tools (pyproject.toml)
mypy-extensions==1.0.0
# via mypy
@ -117,38 +108,38 @@ packaging==23.2
# pytest
# setuptools-scm
# tox
pbr==5.11.1
pbr==6.0.0
# via stevedore
pip-tools==7.3.0
# via gp2040ce-binary-tools (pyproject.toml)
platformdirs==3.11.0
platformdirs==4.2.0
# via
# tox
# virtualenv
pluggy==1.3.0
pluggy==1.4.0
# via
# pytest
# tox
protobuf==4.25.0
protobuf==4.25.2
# via grpcio-tools
pycodestyle==2.11.1
# via flake8
pydocstyle==6.3.0
# via flake8-docstrings
pyflakes==3.1.0
pyflakes==3.2.0
# via flake8
pygments==2.16.1
pygments==2.17.2
# via rich
pyproject-api==1.6.1
# via tox
pyproject-hooks==1.0.0
# via build
pytest==7.4.3
pytest==7.4.4
# via
# gp2040ce-binary-tools (pyproject.toml)
# pytest-asyncio
# pytest-cov
pytest-asyncio==0.21.1
pytest-asyncio==0.23.4
# via gp2040ce-binary-tools (pyproject.toml)
pytest-cov==4.1.0
# via gp2040ce-binary-tools (pyproject.toml)
@ -156,39 +147,25 @@ pyusb==1.2.1
# via gp2040ce-binary-tools (pyproject.toml)
pyyaml==6.0.1
# via bandit
rich==13.6.0
rich==13.7.0
# via
# bandit
# textual
setuptools-scm==8.0.4
# via gp2040ce-binary-tools (pyproject.toml)
smmap==5.0.1
# via gitdb
snowballstemmer==2.2.0
# via pydocstyle
stevedore==5.1.0
# via bandit
textual==0.41.0
textual==0.47.1
# via
# gp2040ce-binary-tools (pyproject.toml)
# textual-dev
textual-dev==1.2.1
textual-dev==1.4.0
# via gp2040ce-binary-tools (pyproject.toml)
tomli==2.0.1
# via
# build
# coverage
# flake8-pyproject
# mypy
# pip-tools
# pyproject-api
# pyproject-hooks
# pytest
# setuptools-scm
# tox
tox==4.11.3
tox==4.12.1
# via gp2040ce-binary-tools (pyproject.toml)
typing-extensions==4.8.0
typing-extensions==4.9.0
# via
# mypy
# setuptools-scm
@ -196,14 +173,12 @@ typing-extensions==4.8.0
# textual-dev
uc-micro-py==1.0.2
# via linkify-it-py
virtualenv==20.24.6
virtualenv==20.25.0
# via tox
wheel==0.41.3
wheel==0.42.0
# via pip-tools
yarl==1.9.2
yarl==1.9.4
# via aiohttp
zipp==3.17.0
# via importlib-metadata
# The following packages are considered to be unsafe in a requirements file:
# pip

View File

@ -1,19 +1,18 @@
#
# This file is autogenerated by pip-compile with Python 3.10
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile --output-file=requirements/requirements.txt
# pip-compile --output-file=requirements/requirements.txt pyproject.toml
#
grpcio==1.59.2
grpcio==1.60.0
# via grpcio-tools
grpcio-tools==1.59.2
grpcio-tools==1.60.0
# via gp2040ce-binary-tools (pyproject.toml)
importlib-metadata==6.8.0
# via textual
linkify-it-py==2.0.2
# via markdown-it-py
markdown-it-py[linkify,plugins]==3.0.0
# via
# markdown-it-py
# mdit-py-plugins
# rich
# textual
@ -21,22 +20,20 @@ mdit-py-plugins==0.4.0
# via markdown-it-py
mdurl==0.1.2
# via markdown-it-py
protobuf==4.25.0
protobuf==4.25.2
# via grpcio-tools
pygments==2.16.1
pygments==2.17.2
# via rich
pyusb==1.2.1
# via gp2040ce-binary-tools (pyproject.toml)
rich==13.6.0
rich==13.7.0
# via textual
textual==0.41.0
textual==0.47.1
# via gp2040ce-binary-tools (pyproject.toml)
typing-extensions==4.8.0
typing-extensions==4.9.0
# via textual
uc-micro-py==1.0.2
# via linkify-it-py
zipp==3.17.0
# via importlib-metadata
# The following packages are considered to be unsafe in a requirements file:
# setuptools

View File

@ -121,7 +121,7 @@ async def test_simple_edit_via_input_field():
await pilot.wait_for_scheduled_animations()
await pilot.press('backspace', 'backspace', 'backspace', 'backspace', 'backspace', 'backspace', '5')
await pilot.wait_for_scheduled_animations()
await pilot.click('Button#save-button')
await pilot.click('Button#confirm-button')
assert pilot.app.config.displayOptions.deprecatedI2cSpeed == 5
@ -145,7 +145,7 @@ async def test_simple_edit_via_input_field_enum():
await pilot.wait_for_scheduled_animations()
await pilot.press('down', 'down', 'enter')
await pilot.wait_for_scheduled_animations()
await pilot.click('Button#save-button')
await pilot.click('Button#confirm-button')
assert pilot.app.config.gamepadOptions.dpadMode == 1
@ -166,7 +166,7 @@ async def test_simple_edit_via_input_field_string():
await pilot.wait_for_scheduled_animations()
await pilot.press('backspace', '-', 'h', 'i')
await pilot.wait_for_scheduled_animations()
await pilot.click('Button#save-button')
await pilot.click('Button#confirm-button')
assert pilot.app.config.boardVersion == 'v0.7.-hi'
@ -196,7 +196,7 @@ async def test_add_node_to_repeated():
await pilot.wait_for_scheduled_animations()
await pilot.press('backspace', 'backspace', 'backspace', 'backspace', 'backspace', 'backspace', '5')
await pilot.wait_for_scheduled_animations()
await pilot.click('Button#save-button')
await pilot.click('Button#confirm-button')
assert pilot.app.config.profileOptions.deprecatedAlternativePinMappings[0].pinButtonB4 == 5

View File

@ -6,8 +6,6 @@ SPDX-License-Identifier: MIT
import os
import sys
import pytest
from gp2040ce_bintools import get_config_pb2
HERE = os.path.dirname(os.path.abspath(__file__))
@ -30,9 +28,10 @@ def test_get_config_pb2_compile():
def test_get_config_pb2_exception():
"""Without any precompiled files or proto files on the path, test we raise an exception."""
with pytest.raises(ModuleNotFoundError):
_ = get_config_pb2()
"""Without any precompiled files or proto files on the path, test we DO NOT raise an exception."""
# this used to raise ModuleNotFoundError, but with our snapshot included now,
# we should always have a config to import
_ = get_config_pb2()
def test_get_config_pb2_precompile():

View File

@ -69,12 +69,6 @@ def test_config_footer_bad_crc(storage_dump):
_, _, _ = storage.get_config_footer(corrupt)
def test_config_fails_without_pb2s(storage_dump):
"""Test that we need the config_pb2 to exist/be compiled for reading the config to work."""
with pytest.raises(ModuleNotFoundError):
_ = storage.get_config(storage_dump)
@with_pb2s
def test_get_config_from_file_storage_dump():
"""Test that we can open a storage dump file and find its config."""

View File

@ -67,3 +67,4 @@ branch = True
omit =
**/_version.py
**/proto_snapshot/*