aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorNick Brassel <nick@tzarc.org>2021-08-29 08:20:25 +1000
committerNick Brassel <nick@tzarc.org>2021-08-29 08:20:25 +1000
commitf061ca497464fe85284906fb163a33eaee7a91ef (patch)
tree33ef1bfb529aed382e8526c607c4e18717f92571 /util
parentff65185dec6f97be1eb49f17cea526a0d0bbf3d6 (diff)
parent4bad375d7c09d949a9dcdd4feba147c9c7a67ec6 (diff)
downloadqmk_firmware-f061ca497464fe85284906fb163a33eaee7a91ef.tar.gz
qmk_firmware-f061ca497464fe85284906fb163a33eaee7a91ef.zip
Breaking changes develop merge to master, 2021Q3 edition. (#14196)
Diffstat (limited to 'util')
-rwxr-xr-xutil/new_keyboard.sh12
-rw-r--r--util/nix/poetry.lock467
-rw-r--r--util/nix/pyproject.toml32
-rw-r--r--util/nix/sources.json38
-rw-r--r--util/nix/sources.nix174
-rw-r--r--util/reset.eep9
-rwxr-xr-xutil/stm32eeprom_parser.py317
-rw-r--r--util/udev/50-qmk.rules6
-rwxr-xr-xutil/update_chibios_mirror.sh83
9 files changed, 1135 insertions, 3 deletions
diff --git a/util/new_keyboard.sh b/util/new_keyboard.sh
index d0db23bb4..62e8cb9e1 100755
--- a/util/new_keyboard.sh
+++ b/util/new_keyboard.sh
@@ -1,7 +1,7 @@
1#!/usr/bin/env bash 1#!/usr/bin/env bash
2 2
3# This script generates a new keyboard directory under keyboards/, 3# This script generates a new keyboard directory under keyboards/,
4# and copies the template files from quantum/template/ into it. 4# and copies the template files from data/templates/ into it.
5 5
6# Print an error message with the word "ERROR" in red. 6# Print an error message with the word "ERROR" in red.
7echo_error() { 7echo_error() {
@@ -35,11 +35,11 @@ copy_templates() {
35 mkdir -p "$keyboard_dir" 35 mkdir -p "$keyboard_dir"
36 36
37 echo -n "Copying base template files..." 37 echo -n "Copying base template files..."
38 cp -r "quantum/template/base/." "${keyboard_dir}" 38 cp -r "data/templates/base/." "${keyboard_dir}"
39 echo " done" 39 echo " done"
40 40
41 echo -n "Copying $keyboard_type template files..." 41 echo -n "Copying $keyboard_type template files..."
42 cp -r "quantum/template/${keyboard_type}/." "${keyboard_dir}" 42 cp -r "data/templates/${keyboard_type}/." "${keyboard_dir}"
43 echo " done" 43 echo " done"
44 44
45 echo -n "Renaming keyboard files..." 45 echo -n "Renaming keyboard files..."
@@ -129,6 +129,12 @@ if [ ! -d "quantum" ]; then
129 exit 1 129 exit 1
130fi 130fi
131 131
132echo_bold "########################################"
133echo_bold "# NOTICE #"
134echo_bold "# This script has been deprecated. #"
135echo_bold "# Please use qmk new-keyboard instead. #"
136echo_bold "########################################"
137echo
132echo_bold "Generating a new QMK keyboard directory" 138echo_bold "Generating a new QMK keyboard directory"
133echo 139echo
134 140
diff --git a/util/nix/poetry.lock b/util/nix/poetry.lock
new file mode 100644
index 000000000..1a1aefe21
--- /dev/null
+++ b/util/nix/poetry.lock
@@ -0,0 +1,467 @@
1[[package]]
2name = "appdirs"
3version = "1.4.4"
4description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
5category = "main"
6optional = false
7python-versions = "*"
8
9[[package]]
10name = "argcomplete"
11version = "1.12.3"
12description = "Bash tab completion for argparse"
13category = "main"
14optional = false
15python-versions = "*"
16
17[package.extras]
18test = ["coverage", "flake8", "pexpect", "wheel"]
19
20[[package]]
21name = "attrs"
22version = "21.2.0"
23description = "Classes Without Boilerplate"
24category = "main"
25optional = false
26python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
27
28[package.extras]
29dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"]
30docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
31tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
32tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
33
34[[package]]
35name = "colorama"
36version = "0.4.4"
37description = "Cross-platform colored terminal text."
38category = "main"
39optional = false
40python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
41
42[[package]]
43name = "coverage"
44version = "5.5"
45description = "Code coverage measurement for Python"
46category = "main"
47optional = false
48python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
49
50[package.extras]
51toml = ["toml"]
52
53[[package]]
54name = "dotty-dict"
55version = "1.3.0"
56description = "Dictionary wrapper for quick access to deeply nested keys."
57category = "main"
58optional = false
59python-versions = "*"
60
61[package.dependencies]
62setuptools_scm = "*"
63
64[[package]]
65name = "flake8"
66version = "3.9.2"
67description = "the modular source code checker: pep8 pyflakes and co"
68category = "main"
69optional = false
70python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
71
72[package.dependencies]
73mccabe = ">=0.6.0,<0.7.0"
74pycodestyle = ">=2.7.0,<2.8.0"
75pyflakes = ">=2.3.0,<2.4.0"
76
77[[package]]
78name = "flake8-polyfill"
79version = "1.0.2"
80description = "Polyfill package for Flake8 plugins"
81category = "dev"
82optional = false
83python-versions = "*"
84
85[package.dependencies]
86flake8 = "*"
87
88[[package]]
89name = "halo"
90version = "0.0.31"
91description = "Beautiful terminal spinners in Python"
92category = "main"
93optional = false
94python-versions = ">=3.4"
95
96[package.dependencies]
97colorama = ">=0.3.9"
98log-symbols = ">=0.0.14"
99six = ">=1.12.0"
100spinners = ">=0.0.24"
101termcolor = ">=1.1.0"
102
103[package.extras]
104ipython = ["IPython (==5.7.0)", "ipywidgets (==7.1.0)"]
105
106[[package]]
107name = "hid"
108version = "1.0.4"
109description = "ctypes bindings for hidapi"
110category = "main"
111optional = false
112python-versions = "*"
113
114[[package]]
115name = "hjson"
116version = "3.0.2"
117description = "Hjson, a user interface for JSON."
118category = "main"
119optional = false
120python-versions = "*"
121
122[[package]]
123name = "jsonschema"
124version = "3.2.0"
125description = "An implementation of JSON Schema validation for Python"
126category = "main"
127optional = false
128python-versions = "*"
129
130[package.dependencies]
131attrs = ">=17.4.0"
132pyrsistent = ">=0.14.0"
133six = ">=1.11.0"
134
135[package.extras]
136format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"]
137format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"]
138
139[[package]]
140name = "log-symbols"
141version = "0.0.14"
142description = "Colored symbols for various log levels for Python"
143category = "main"
144optional = false
145python-versions = "*"
146
147[package.dependencies]
148colorama = ">=0.3.9"
149
150[[package]]
151name = "mccabe"
152version = "0.6.1"
153description = "McCabe checker, plugin for flake8"
154category = "main"
155optional = false
156python-versions = "*"
157
158[[package]]
159name = "milc"
160version = "1.4.2"
161description = "Opinionated Batteries-Included Python 3 CLI Framework."
162category = "main"
163optional = false
164python-versions = "*"
165
166[package.dependencies]
167appdirs = "*"
168argcomplete = "*"
169colorama = "*"
170halo = "*"
171spinners = "*"
172
173[[package]]
174name = "nose2"
175version = "0.10.0"
176description = "unittest2 with plugins, the succesor to nose"
177category = "main"
178optional = false
179python-versions = "*"
180
181[package.dependencies]
182coverage = ">=4.4.1"
183six = ">=1.7"
184
185[package.extras]
186coverage_plugin = ["coverage (>=4.4.1)"]
187dev = ["Sphinx (>=1.6.5)", "sphinx-rtd-theme", "mock", "coverage"]
188
189[[package]]
190name = "pep8-naming"
191version = "0.11.1"
192description = "Check PEP-8 naming conventions, plugin for flake8"
193category = "dev"
194optional = false
195python-versions = "*"
196
197[package.dependencies]
198flake8-polyfill = ">=1.0.2,<2"
199
200[[package]]
201name = "pycodestyle"
202version = "2.7.0"
203description = "Python style guide checker"
204category = "main"
205optional = false
206python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
207
208[[package]]
209name = "pyflakes"
210version = "2.3.1"
211description = "passive checker of Python programs"
212category = "main"
213optional = false
214python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
215
216[[package]]
217name = "pygments"
218version = "2.9.0"
219description = "Pygments is a syntax highlighting package written in Python."
220category = "main"
221optional = false
222python-versions = ">=3.5"
223
224[[package]]
225name = "pyrsistent"
226version = "0.17.3"
227description = "Persistent/Functional/Immutable data structures"
228category = "main"
229optional = false
230python-versions = ">=3.5"
231
232[[package]]
233name = "pyusb"
234version = "1.1.1"
235description = "Python USB access module"
236category = "main"
237optional = false
238python-versions = "*"
239
240[[package]]
241name = "qmk"
242version = "0.0.51"
243description = "A program to help users work with QMK Firmware."
244category = "main"
245optional = false
246python-versions = ">=3.7"
247
248[package.dependencies]
249dotty-dict = "*"
250flake8 = "*"
251hid = "*"
252hjson = "*"
253jsonschema = ">=3"
254milc = ">=1.4.0"
255nose2 = "*"
256pygments = "*"
257pyusb = "*"
258yapf = "*"
259
260[[package]]
261name = "setuptools-scm"
262version = "6.0.1"
263description = "the blessed package to manage your versions by scm tags"
264category = "main"
265optional = false
266python-versions = ">=3.6"
267
268[package.extras]
269toml = ["toml"]
270
271[[package]]
272name = "six"
273version = "1.16.0"
274description = "Python 2 and 3 compatibility utilities"
275category = "main"
276optional = false
277python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
278
279[[package]]
280name = "spinners"
281version = "0.0.24"
282description = "Spinners for terminals"
283category = "main"
284optional = false
285python-versions = "*"
286
287[[package]]
288name = "termcolor"
289version = "1.1.0"
290description = "ANSII Color formatting for output in terminal."
291category = "main"
292optional = false
293python-versions = "*"
294
295[[package]]
296name = "yapf"
297version = "0.30.0"
298description = "A formatter for Python code."
299category = "main"
300optional = false
301python-versions = "*"
302
303[metadata]
304lock-version = "1.1"
305python-versions = "^3.8"
306content-hash = "5e181d51536240d08c74ba6a46bd0988ee4ca72ac3d5b388965ca8023e9b9a99"
307
308[metadata.files]
309appdirs = [
310 {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
311 {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
312]
313argcomplete = [
314 {file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"},
315 {file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"},
316]
317attrs = [
318 {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
319 {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
320]
321colorama = [
322 {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
323 {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
324]
325coverage = [
326 {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"},
327 {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"},
328 {file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"},
329 {file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"},
330 {file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"},
331 {file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"},
332 {file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"},
333 {file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"},
334 {file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"},
335 {file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"},
336 {file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"},
337 {file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"},
338 {file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"},
339 {file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"},
340 {file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"},
341 {file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"},
342 {file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"},
343 {file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"},
344 {file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"},
345 {file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"},
346 {file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"},
347 {file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"},
348 {file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"},
349 {file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"},
350 {file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"},
351 {file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"},
352 {file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"},
353 {file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"},
354 {file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"},
355 {file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"},
356 {file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"},
357 {file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"},
358 {file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"},
359 {file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"},
360 {file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"},
361 {file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"},
362 {file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"},
363 {file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"},
364 {file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"},
365 {file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"},
366 {file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"},
367 {file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"},
368 {file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"},
369 {file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"},
370 {file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"},
371 {file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"},
372 {file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"},
373 {file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"},
374 {file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"},
375 {file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"},
376 {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"},
377 {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"},
378]
379dotty-dict = [
380 {file = "dotty_dict-1.3.0.tar.gz", hash = "sha256:eb0035a3629ecd84397a68f1f42f1e94abd1c34577a19cd3eacad331ee7cbaf0"},
381]
382flake8 = [
383 {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"},
384 {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"},
385]
386flake8-polyfill = [
387 {file = "flake8-polyfill-1.0.2.tar.gz", hash = "sha256:e44b087597f6da52ec6393a709e7108b2905317d0c0b744cdca6208e670d8eda"},
388 {file = "flake8_polyfill-1.0.2-py2.py3-none-any.whl", hash = "sha256:12be6a34ee3ab795b19ca73505e7b55826d5f6ad7230d31b18e106400169b9e9"},
389]
390halo = [
391 {file = "halo-0.0.31-py2-none-any.whl", hash = "sha256:5350488fb7d2aa7c31a1344120cee67a872901ce8858f60da7946cef96c208ab"},
392 {file = "halo-0.0.31.tar.gz", hash = "sha256:7b67a3521ee91d53b7152d4ee3452811e1d2a6321975137762eb3d70063cc9d6"},
393]
394hid = [
395 {file = "hid-1.0.4-py2-none-any.whl", hash = "sha256:fba9913f07030b01059b822b24c83b370ca3f444e9e6443bd662f9f1aa3f0780"},
396 {file = "hid-1.0.4.tar.gz", hash = "sha256:f61b0382f37a334bc8ba8604bc84b94875ee4f594fbbaf82b2c3b3e827883fc1"},
397]
398hjson = [
399 {file = "hjson-3.0.2-py3-none-any.whl", hash = "sha256:5546438bf4e1b52bc964c6a47c4ed10fa5fba8a1b264e22efa893e333baad2db"},
400 {file = "hjson-3.0.2.tar.gz", hash = "sha256:2838fd7200e5839ea4516ece953f3a19892c41089f0d933ba3f68e596aacfcd5"},
401]
402jsonschema = [
403 {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"},
404 {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"},
405]
406log-symbols = [
407 {file = "log_symbols-0.0.14-py3-none-any.whl", hash = "sha256:4952106ff8b605ab7d5081dd2c7e6ca7374584eff7086f499c06edd1ce56dcca"},
408 {file = "log_symbols-0.0.14.tar.gz", hash = "sha256:cf0bbc6fe1a8e53f0d174a716bc625c4f87043cc21eb55dd8a740cfe22680556"},
409]
410mccabe = [
411 {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
412 {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
413]
414milc = [
415 {file = "milc-1.4.2-py2.py3-none-any.whl", hash = "sha256:65ee004caa769b1ee144b15be7908d1f623920ab6f356e5c5c95be9457aa15d8"},
416 {file = "milc-1.4.2.tar.gz", hash = "sha256:c6b2f19e3196b00a0060f8c883533e356f2054a9f81692b7b97ccee0d01626fd"},
417]
418nose2 = [
419 {file = "nose2-0.10.0-py2.py3-none-any.whl", hash = "sha256:aa620e759f2c5018d9ba041340391913e282ecebd3c392027f1575847b093ec6"},
420 {file = "nose2-0.10.0.tar.gz", hash = "sha256:886ba617a96de0130c54b24479bd5c2d74d5c940d40f3809c3a275511a0c4a60"},
421]
422pep8-naming = [
423 {file = "pep8-naming-0.11.1.tar.gz", hash = "sha256:a1dd47dd243adfe8a83616e27cf03164960b507530f155db94e10b36a6cd6724"},
424 {file = "pep8_naming-0.11.1-py2.py3-none-any.whl", hash = "sha256:f43bfe3eea7e0d73e8b5d07d6407ab47f2476ccaeff6937c84275cd30b016738"},
425]
426pycodestyle = [
427 {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
428 {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
429]
430pyflakes = [
431 {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"},
432 {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"},
433]
434pygments = [
435 {file = "Pygments-2.9.0-py3-none-any.whl", hash = "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"},
436 {file = "Pygments-2.9.0.tar.gz", hash = "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f"},
437]
438pyrsistent = [
439 {file = "pyrsistent-0.17.3.tar.gz", hash = "sha256:2e636185d9eb976a18a8a8e96efce62f2905fea90041958d8cc2a189756ebf3e"},
440]
441pyusb = [
442 {file = "pyusb-1.1.1-py3-none-any.whl", hash = "sha256:f18eb813d3a1439918071234589162c2f209a19adbeffeb1377ce078a4aebc70"},
443 {file = "pyusb-1.1.1.tar.gz", hash = "sha256:7d449ad916ce58aff60b89aae0b65ac130f289c24d6a5b7b317742eccffafc38"},
444]
445qmk = [
446 {file = "qmk-0.0.51-py2.py3-none-any.whl", hash = "sha256:5f676f389b2450b0956d7eb8e7e378d2e6690d5859a887c91876da0a5faf75ed"},
447 {file = "qmk-0.0.51.tar.gz", hash = "sha256:efeef209cde1df92b9823db686d9684962cd00aae9f45ba5e3d494aa5b3c6b9a"},
448]
449setuptools-scm = [
450 {file = "setuptools_scm-6.0.1-py3-none-any.whl", hash = "sha256:c3bd5f701c8def44a5c0bfe8d407bef3f80342217ef3492b951f3777bd2d915c"},
451 {file = "setuptools_scm-6.0.1.tar.gz", hash = "sha256:d1925a69cb07e9b29416a275b9fadb009a23c148ace905b2fb220649a6c18e92"},
452]
453six = [
454 {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
455 {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
456]
457spinners = [
458 {file = "spinners-0.0.24-py3-none-any.whl", hash = "sha256:2fa30d0b72c9650ad12bbe031c9943b8d441e41b4f5602b0ec977a19f3290e98"},
459 {file = "spinners-0.0.24.tar.gz", hash = "sha256:1eb6aeb4781d72ab42ed8a01dcf20f3002bf50740d7154d12fb8c9769bf9e27f"},
460]
461termcolor = [
462 {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"},
463]
464yapf = [
465 {file = "yapf-0.30.0-py2.py3-none-any.whl", hash = "sha256:3abf61ba67cf603069710d30acbc88cfe565d907e16ad81429ae90ce9651e0c9"},
466 {file = "yapf-0.30.0.tar.gz", hash = "sha256:3000abee4c28daebad55da6c85f3cd07b8062ce48e2e9943c8da1b9667d48427"},
467]
diff --git a/util/nix/pyproject.toml b/util/nix/pyproject.toml
new file mode 100644
index 000000000..a81336189
--- /dev/null
+++ b/util/nix/pyproject.toml
@@ -0,0 +1,32 @@
1# This file should be kept in sync with requirements.txt and requirements-dev.txt
2# It is particularly required by the Nix environment (see shell.nix). To update versions,
3# normally one would run "poetry update --lock"
4[tool.poetry]
5name = "qmk_firmware"
6version = "0.1.0"
7description = ""
8authors = []
9
10[tool.poetry.dependencies]
11python = "^3.8"
12appdirs = "^1.4.4"
13argcomplete = "^1.12.2"
14colorama = "^0.4.4"
15dotty-dict = "^1.3.0"
16hjson = "^3.0.2"
17jsonschema = "^3.2.0"
18milc = "^1.3.0"
19Pygments = "^2.8.0"
20qmk = "*"
21
22[tool.poetry.dev-dependencies]
23nose2 = "^0.10.0"
24flake8 = "^3.8.4"
25hid = "^1.0.4"
26pep8-naming = "^0.11.1"
27pyusb = "^1.1.1"
28yapf = "^0.30.0"
29
30[build-system]
31requires = ["poetry-core>=1.0.0"]
32build-backend = "poetry.core.masonry.api"
diff --git a/util/nix/sources.json b/util/nix/sources.json
new file mode 100644
index 000000000..caf5cb7d2
--- /dev/null
+++ b/util/nix/sources.json
@@ -0,0 +1,38 @@
1{
2 "niv": {
3 "branch": "master",
4 "description": "Easy dependency management for Nix projects",
5 "homepage": "https://github.com/nmattia/niv",
6 "owner": "nmattia",
7 "repo": "niv",
8 "rev": "af958e8057f345ee1aca714c1247ef3ba1c15f5e",
9 "sha256": "1qjavxabbrsh73yck5dcq8jggvh3r2jkbr6b5nlz5d9yrqm9255n",
10 "type": "tarball",
11 "url": "https://github.com/nmattia/niv/archive/af958e8057f345ee1aca714c1247ef3ba1c15f5e.tar.gz",
12 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
13 },
14 "nixpkgs": {
15 "branch": "nixpkgs-unstable",
16 "description": "Nix Packages collection",
17 "homepage": "",
18 "owner": "NixOS",
19 "repo": "nixpkgs",
20 "rev": "c0e881852006b132236cbf0301bd1939bb50867e",
21 "sha256": "0fy7z7yxk5n7yslsvx5cyc6h21qwi4bhxf3awhirniszlbvaazy2",
22 "type": "tarball",
23 "url": "https://github.com/NixOS/nixpkgs/archive/c0e881852006b132236cbf0301bd1939bb50867e.tar.gz",
24 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
25 },
26 "poetry2nix": {
27 "branch": "master",
28 "description": "Convert poetry projects to nix automagically [maintainer=@adisbladis] ",
29 "homepage": "",
30 "owner": "nix-community",
31 "repo": "poetry2nix",
32 "rev": "2d27d44397242b28c3f0081e0432e4f6c951f3a1",
33 "sha256": "06syfg150r59m4kksj5547b5kwxjxjaif5hiljcq966kb9hxsvmv",
34 "type": "tarball",
35 "url": "https://github.com/nix-community/poetry2nix/archive/2d27d44397242b28c3f0081e0432e4f6c951f3a1.tar.gz",
36 "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
37 }
38}
diff --git a/util/nix/sources.nix b/util/nix/sources.nix
new file mode 100644
index 000000000..1938409dd
--- /dev/null
+++ b/util/nix/sources.nix
@@ -0,0 +1,174 @@
1# This file has been generated by Niv.
2
3let
4
5 #
6 # The fetchers. fetch_<type> fetches specs of type <type>.
7 #
8
9 fetch_file = pkgs: name: spec:
10 let
11 name' = sanitizeName name + "-src";
12 in
13 if spec.builtin or true then
14 builtins_fetchurl { inherit (spec) url sha256; name = name'; }
15 else
16 pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
17
18 fetch_tarball = pkgs: name: spec:
19 let
20 name' = sanitizeName name + "-src";
21 in
22 if spec.builtin or true then
23 builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
24 else
25 pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
26
27 fetch_git = name: spec:
28 let
29 ref =
30 if spec ? ref then spec.ref else
31 if spec ? branch then "refs/heads/${spec.branch}" else
32 if spec ? tag then "refs/tags/${spec.tag}" else
33 abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
34 in
35 builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
36
37 fetch_local = spec: spec.path;
38
39 fetch_builtin-tarball = name: throw
40 ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
41 $ niv modify ${name} -a type=tarball -a builtin=true'';
42
43 fetch_builtin-url = name: throw
44 ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
45 $ niv modify ${name} -a type=file -a builtin=true'';
46
47 #
48 # Various helpers
49 #
50
51 # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
52 sanitizeName = name:
53 (
54 concatMapStrings (s: if builtins.isList s then "-" else s)
55 (
56 builtins.split "[^[:alnum:]+._?=-]+"
57 ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
58 )
59 );
60
61 # The set of packages used when specs are fetched using non-builtins.
62 mkPkgs = sources: system:
63 let
64 sourcesNixpkgs =
65 import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
66 hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
67 hasThisAsNixpkgsPath = <nixpkgs> == ./.;
68 in
69 if builtins.hasAttr "nixpkgs" sources
70 then sourcesNixpkgs
71 else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
72 import <nixpkgs> {}
73 else
74 abort
75 ''
76 Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
77 add a package called "nixpkgs" to your sources.json.
78 '';
79
80 # The actual fetching function.
81 fetch = pkgs: name: spec:
82
83 if ! builtins.hasAttr "type" spec then
84 abort "ERROR: niv spec ${name} does not have a 'type' attribute"
85 else if spec.type == "file" then fetch_file pkgs name spec
86 else if spec.type == "tarball" then fetch_tarball pkgs name spec
87 else if spec.type == "git" then fetch_git name spec
88 else if spec.type == "local" then fetch_local spec
89 else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
90 else if spec.type == "builtin-url" then fetch_builtin-url name
91 else
92 abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
93
94 # If the environment variable NIV_OVERRIDE_${name} is set, then use
95 # the path directly as opposed to the fetched source.
96 replace = name: drv:
97 let
98 saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
99 ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
100 in
101 if ersatz == "" then drv else
102 # this turns the string into an actual Nix path (for both absolute and
103 # relative paths)
104 if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
105
106 # Ports of functions for older nix versions
107
108 # a Nix version of mapAttrs if the built-in doesn't exist
109 mapAttrs = builtins.mapAttrs or (
110 f: set: with builtins;
111 listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
112 );
113
114 # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
115 range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
116
117 # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
118 stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
119
120 # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
121 stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
122 concatMapStrings = f: list: concatStrings (map f list);
123 concatStrings = builtins.concatStringsSep "";
124
125 # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
126 optionalAttrs = cond: as: if cond then as else {};
127
128 # fetchTarball version that is compatible between all the versions of Nix
129 builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
130 let
131 inherit (builtins) lessThan nixVersion fetchTarball;
132 in
133 if lessThan nixVersion "1.12" then
134 fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
135 else
136 fetchTarball attrs;
137
138 # fetchurl version that is compatible between all the versions of Nix
139 builtins_fetchurl = { url, name ? null, sha256 }@attrs:
140 let
141 inherit (builtins) lessThan nixVersion fetchurl;
142 in
143 if lessThan nixVersion "1.12" then
144 fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
145 else
146 fetchurl attrs;
147
148 # Create the final "sources" from the config
149 mkSources = config:
150 mapAttrs (
151 name: spec:
152 if builtins.hasAttr "outPath" spec
153 then abort
154 "The values in sources.json should not have an 'outPath' attribute"
155 else
156 spec // { outPath = replace name (fetch config.pkgs name spec); }
157 ) config.sources;
158
159 # The "config" used by the fetchers
160 mkConfig =
161 { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
162 , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
163 , system ? builtins.currentSystem
164 , pkgs ? mkPkgs sources system
165 }: rec {
166 # The sources, i.e. the attribute set of spec name to spec
167 inherit sources;
168
169 # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
170 inherit pkgs;
171 };
172
173in
174mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }
diff --git a/util/reset.eep b/util/reset.eep
new file mode 100644
index 000000000..a8a75389f
--- /dev/null
+++ b/util/reset.eep
@@ -0,0 +1,9 @@
1:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
2:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
3:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
4:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
5:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
6:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
7:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
8:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
9:00000001FF
diff --git a/util/stm32eeprom_parser.py b/util/stm32eeprom_parser.py
new file mode 100755
index 000000000..b124f713d
--- /dev/null
+++ b/util/stm32eeprom_parser.py
@@ -0,0 +1,317 @@
1#!/usr/bin/env python
2#
3# Copyright 2021 Don Kjer
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17#
18
19from __future__ import print_function
20
21import argparse
22from struct import pack, unpack
23import os, sys
24
25MAGIC_FEEA = '\xea\xff\xfe\xff'
26
27MAGIC_FEE9 = '\x16\x01'
28EMPTY_WORD = '\xff\xff'
29WORD_ENCODING = 0x8000
30VALUE_NEXT = 0x6000
31VALUE_RESERVED = 0x4000
32VALUE_ENCODED = 0x2000
33BYTE_RANGE = 0x80
34
35CHUNK_SIZE = 1024
36
37STRUCT_FMTS = {
38 1: 'B',
39 2: 'H',
40 4: 'I'
41}
42PRINTABLE='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ '
43
44EECONFIG_V1 = [
45 ("MAGIC", 0, 2),
46 ("DEBUG", 2, 1),
47 ("DEFAULT_LAYER", 3, 1),
48 ("KEYMAP", 4, 1),
49 ("MOUSEKEY_ACCEL", 5, 1),
50 ("BACKLIGHT", 6, 1),
51 ("AUDIO", 7, 1),
52 ("RGBLIGHT", 8, 4),
53 ("UNICODEMODE", 12, 1),
54 ("STENOMODE", 13, 1),
55 ("HANDEDNESS", 14, 1),
56 ("KEYBOARD", 15, 4),
57 ("USER", 19, 4),
58 ("VELOCIKEY", 23, 1),
59 ("HAPTIC", 24, 4),
60 ("MATRIX", 28, 4),
61 ("MATRIX_EXTENDED", 32, 2),
62 ("KEYMAP_UPPER_BYTE", 34, 1),
63]
64VIABASE_V1 = 35
65
66VERBOSE = False
67
68def parseArgs():
69 parser = argparse.ArgumentParser(description='Decode an STM32 emulated eeprom dump')
70 parser.add_argument('-s', '--size', type=int,
71 help='Size of the emulated eeprom (default: input_size / 2)')
72 parser.add_argument('-o', '--output', help='File to write decoded eeprom to')
73 parser.add_argument('-y', '--layout-options-size', type=int,
74 help='VIA layout options size (default: 1)', default=1)
75 parser.add_argument('-t', '--custom-config-size', type=int,
76 help='VIA custom config size (default: 0)', default=0)
77 parser.add_argument('-l', '--layers', type=int,
78 help='VIA keyboard layers (default: 4)', default=4)
79 parser.add_argument('-r', '--rows', type=int, help='VIA matrix rows')
80 parser.add_argument('-c', '--cols', type=int, help='VIA matrix columns')
81 parser.add_argument('-m', '--macros', type=int,
82 help='VIA macro count (default: 16)', default=16)
83 parser.add_argument('-C', '--canonical', action='store_true',
84 help='Canonical hex+ASCII display.')
85 parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output')
86 parser.add_argument('input', help='Raw contents of the STM32 flash area used to emulate eeprom')
87 return parser.parse_args()
88
89
90def decodeEepromFEEA(in_file, size):
91 decoded=size*[None]
92 pos = 0
93 while True:
94 chunk = in_file.read(CHUNK_SIZE)
95 for i in range(0, len(chunk), 2):
96 decoded[pos] = unpack('B', chunk[i])[0]
97 pos += 1
98 if pos >= size:
99 break
100
101 if len(chunk) < CHUNK_SIZE or pos >= size:
102 break
103 return decoded
104
105def decodeEepromFEE9(in_file, size):
106 decoded=size*[None]
107 pos = 0
108 # Read compacted flash
109 while True:
110 read_size = min(size - pos, CHUNK_SIZE)
111 chunk = in_file.read(read_size)
112 for i in range(len(chunk)):
113 decoded[pos] = unpack('B', chunk[i])[0] ^ 0xFF
114 pos += 1
115 if pos >= size:
116 break
117
118 if len(chunk) < read_size or pos >= size:
119 break
120 if VERBOSE:
121 print("COMPACTED EEPROM:")
122 dumpBinary(decoded, True)
123 print("WRITE LOG:")
124 # Read write log
125 while True:
126 entry = in_file.read(2)
127 if len(entry) < 2:
128 print("Partial log address at position 0x%04x" % pos, file=sys.stderr)
129 break
130 pos += 2
131
132 if entry == EMPTY_WORD:
133 break
134
135 be_entry = unpack('>H', entry)[0]
136 entry = unpack('H', entry)[0]
137 if not (entry & WORD_ENCODING):
138 address = entry >> 8
139 decoded[address] = entry & 0xFF
140 if VERBOSE:
141 print("[0x%04x]: BYTE 0x%02x = 0x%02x" % (be_entry, address, decoded[address]))
142 else:
143 if (entry & VALUE_NEXT) == VALUE_NEXT:
144 # Read next word as value
145 value = in_file.read(2)
146 if len(value) < 2:
147 print("Partial log value at position 0x%04x" % pos, file=sys.stderr)
148 break
149 pos += 2
150 address = entry & 0x1FFF
151 address <<= 1
152 address += BYTE_RANGE
153 decoded[address] = unpack('B', value[0])[0] ^ 0xFF
154 decoded[address+1] = unpack('B', value[1])[0] ^ 0xFF
155 be_value = unpack('>H', value)[0]
156 if VERBOSE:
157 print("[0x%04x 0x%04x]: WORD 0x%04x = 0x%02x%02x" % (be_entry, be_value, address, decoded[address+1], decoded[address]))
158 else:
159 # Reserved for future use
160 if entry & VALUE_RESERVED:
161 if VERBOSE:
162 print("[0x%04x]: RESERVED 0x%04x" % (be_entry, address))
163 continue
164 address = entry & 0x1FFF
165 address <<= 1
166 decoded[address] = (entry & VALUE_ENCODED) >> 13
167 decoded[address+1] = 0
168 if VERBOSE:
169 print("[0x%04x]: ENCODED 0x%04x = 0x%02x%02x" % (be_entry, address, decoded[address+1], decoded[address]))
170
171 return decoded
172
173def dumpBinary(data, canonical):
174 def display(pos, row):
175 print("%04x" % pos, end='')
176 for i in range(len(row)):
177 if i % 8 == 0:
178 print(" ", end='')
179 char = row[i]
180 if char is None:
181 print(" ", end='')
182 else:
183 print(" %02x" % row[i], end='')
184 if canonical:
185 print(" |", end='')
186 for i in range(len(row)):
187 char = row[i]
188 if char is None:
189 char = " "
190 else:
191 char = chr(char)
192 if char not in PRINTABLE:
193 char = "."
194 print(char, end='')
195 print("|", end='')
196
197 print("")
198
199 size = len(data)
200 empty_rows = 0
201 prev_row = ''
202 first_repeat = True
203 for pos in range(0, size, 16):
204 row=data[pos:pos+16]
205 row[len(row):16] = (16-len(row))*[None]
206 if row == prev_row:
207 if first_repeat:
208 print("*")
209 first_repeat = False
210 else:
211 first_repeat = True
212 display(pos, row)
213 prev_row = row
214 print("%04x" % (pos+16))
215
216def dumpEeconfig(data, eeconfig):
217 print("EECONFIG:")
218 for (name, pos, length) in eeconfig:
219 fmt = STRUCT_FMTS[length]
220 value = unpack(fmt, ''.join([chr(x) for x in data[pos:pos+length]]))[0]
221 print(("%%04x %%s = 0x%%0%dx" % (length * 2)) % (pos, name, value))
222
223def dumpVia(data, base, layers, cols, rows, macros,
224 layout_options_size, custom_config_size):
225 magicYear = data[base + 0]
226 magicMonth = data[base + 1]
227 magicDay = data[base + 2]
228 # Sanity check
229 if not 10 <= magicYear <= 0x99 or \
230 not 0 <= magicMonth <= 0x12 or \
231 not 0 <= magicDay <= 0x31:
232 print("ERROR: VIA Signature is not valid; Year:%x, Month:%x, Day:%x" % (magicYear, magicMonth, magicDay))
233 return
234 if cols is None or rows is None:
235 print("ERROR: VIA dump requires specifying --rows and --cols", file=sys.stderr)
236 return 2
237 print("VIA:")
238 # Decode magic
239 print("%04x MAGIC = 20%02x-%02x-%02x" % (base, magicYear, magicMonth, magicDay))
240 # Decode layout options
241 options = 0
242 pos = base + 3
243 for i in range(base+3, base+3+layout_options_size):
244 options = options << 8
245 options |= data[i]
246 print(("%%04x LAYOUT_OPTIONS = 0x%%0%dx" % (layout_options_size * 2)) % (pos, options))
247 pos += layout_options_size + custom_config_size
248 # Decode keycodes
249 keymap_size = layers * rows * cols * 2
250 if (pos + keymap_size) >= (len(data) - 1):
251 print("ERROR: VIA keymap requires %d bytes, but only %d available" % (keymap_size, len(data) - pos))
252 return 3
253 for layer in range(layers):
254 print("%s LAYER %d %s" % ('-'*int(cols*2.5), layer, '-'*int(cols*2.5)))
255 for row in range(rows):
256 print("%04x | " % pos, end='')
257 for col in range(cols):
258 keycode = (data[pos] << 8) | (data[pos+1])
259 print(" %04x" % keycode, end='')
260 pos += 2
261 print("")
262 # Decode macros
263 for macro_num in range(macros):
264 macro = ""
265 macro_pos = pos
266 while pos < len(data):
267 char = chr(data[pos])
268 pos += 1
269 if char == '\x00':
270 print("%04x MACRO[%d] = '%s'" % (macro_pos, macro_num, macro))
271 break
272 else:
273 macro += char
274 return 0
275
276
277def decodeSTM32Eeprom(input, canonical, size=None, output=None, **kwargs):
278 input_size = os.path.getsize(input)
279 if size is None:
280 size = input_size >> 1
281
282 # Read the first few bytes to check magic signature
283 with open(input, 'rb') as in_file:
284 magic=in_file.read(4)
285 in_file.seek(0)
286
287 if magic == MAGIC_FEEA:
288 decoded = decodeEepromFEEA(in_file, size)
289 eeconfig = EECONFIG_V1
290 via_base = VIABASE_V1
291 elif magic[:2] == MAGIC_FEE9:
292 decoded = decodeEepromFEE9(in_file, size)
293 eeconfig = EECONFIG_V1
294 via_base = VIABASE_V1
295 else:
296 print("Unknown magic signature: %s" % " ".join(["0x%02x" % ord(x) for x in magic]), file=sys.stderr)
297 return 1
298
299 if output is not None:
300 with open(output, 'wb') as out_file:
301 out_file.write(pack('%dB' % len(decoded), *decoded))
302 print("DECODED EEPROM:")
303 dumpBinary(decoded, canonical)
304 dumpEeconfig(decoded, eeconfig)
305 if kwargs['rows'] is not None and kwargs['cols'] is not None:
306 return dumpVia(decoded, via_base, **kwargs)
307
308 return 0
309
310def main():
311 global VERBOSE
312 kwargs = vars(parseArgs())
313 VERBOSE = kwargs.pop('verbose')
314 return decodeSTM32Eeprom(**kwargs)
315
316if __name__ == '__main__':
317 sys.exit(main())
diff --git a/util/udev/50-qmk.rules b/util/udev/50-qmk.rules
index 679fe4ced..db27d4dc8 100644
--- a/util/udev/50-qmk.rules
+++ b/util/udev/50-qmk.rules
@@ -63,3 +63,9 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="2a03", ATTRS{idProduct}=="0037", TAG+="uacc
63 63
64# hid_listen 64# hid_listen
65KERNEL=="hidraw*", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl" 65KERNEL=="hidraw*", MODE="0660", GROUP="plugdev", TAG+="uaccess", TAG+="udev-acl"
66
67# hid bootloaders
68## QMK HID
69SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2067", TAG+="uaccess"
70## PJRC's HalfKay
71SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="0478", TAG+="uaccess"
diff --git a/util/update_chibios_mirror.sh b/util/update_chibios_mirror.sh
new file mode 100755
index 000000000..d4593a843
--- /dev/null
+++ b/util/update_chibios_mirror.sh
@@ -0,0 +1,83 @@
1#!/bin/bash
2
3################################
4# Configuration
5
6# The ChibiOS branches to mirror
7chibios_branches="trunk stable_20.3.x stable_21.6.x"
8
9# The ChibiOS tags to mirror
10chibios_tags="ver20.3.1 ver20.3.2 ver20.3.3 ver21.6.0"
11
12# The ChibiOS-Contrib branches to mirror
13contrib_branches="master chibios-20.3.x"
14
15################################
16# Actions
17
18set -eEuo pipefail
19umask 022
20
21this_script="$(realpath "${BASH_SOURCE[0]}")"
22script_dir="$(realpath "$(dirname "$this_script")")"
23qmk_firmware_dir="$(realpath "$script_dir/../")"
24chibios_dir="$qmk_firmware_dir/lib/chibios"
25contrib_dir="$qmk_firmware_dir/lib/chibios-contrib"
26
27chibios_git_location=$(realpath "$chibios_dir/$(cat "$chibios_dir/.git" | awk '/gitdir:/ {print $2}')")
28chibios_git_config=$(realpath "$chibios_git_location/config")
29contrib_git_location=$(realpath "$contrib_dir/$(cat "$contrib_dir/.git" | awk '/gitdir:/ {print $2}')")
30contrib_git_config=$(realpath "$contrib_git_location/config")
31
32cd "$chibios_dir"
33
34if [[ -z "$(cat "$chibios_git_config" | grep '\[svn-remote "svn"\]')" ]] ; then
35 git svn init --stdlayout --prefix='svn/' http://svn.osdn.net/svnroot/chibios/
36fi
37
38if [[ -z "$(cat "$chibios_git_config" | grep '\[remote "qmk"\]')" ]] ; then
39 git remote add qmk git@github.com:qmk/ChibiOS.git
40 git remote set-url qmk git@github.com:qmk/ChibiOS.git --push
41fi
42
43echo "Updating remotes..."
44git fetch --all --tags --prune
45
46echo "Fetching latest from subversion..."
47git svn fetch
48
49echo "Updating ChibiOS branches..."
50for branch in $chibios_branches ; do
51 echo "Creating branch 'svn-mirror/$branch' from 'svn/$branch'..."
52 git branch -f svn-mirror/$branch svn/$branch \
53 && git push qmk svn-mirror/$branch
54done
55
56echo "Updating ChibiOS tags..."
57for tagname in $chibios_tags ; do
58 echo "Creating tag 'svn-mirror/$tagname' from 'svn/tags/$tagname'..."
59 GIT_COMMITTER_DATE="$(git log -n1 --pretty=format:'%ad' svn/tags/$tagname)" git tag -f -a -m "Tagging $tagname" svn-mirror/$tagname svn/tags/$tagname
60 git push qmk svn-mirror/$tagname
61done
62
63cd "$contrib_dir"
64
65if [[ -z "$(cat "$contrib_git_config" | grep '\[remote "qmk"\]')" ]] ; then
66 git remote add qmk git@github.com:qmk/ChibiOS-Contrib.git
67 git remote set-url qmk git@github.com:qmk/ChibiOS-Contrib.git --push
68fi
69
70if [[ -z "$(cat "$contrib_git_config" | grep '\[remote "upstream"\]')" ]] ; then
71 git remote add upstream git@github.com:ChibiOS/ChibiOS-Contrib.git
72 git remote set-url upstream git@github.com:ChibiOS/ChibiOS-Contrib.git --push
73fi
74
75echo "Updating remotes..."
76git fetch --all --tags --prune
77
78echo "Updating ChibiOS-Contrib branches..."
79for branch in $contrib_branches ; do
80 echo "Creating branch 'mirror/$branch' from 'upstream/$branch'..."
81 git branch -f mirror/$branch upstream/$branch \
82 && git push qmk mirror/$branch
83done