summaryrefslogtreecommitdiff
path: root/libre/linux-libre-firmware
diff options
context:
space:
mode:
authorDavid P <megver83@parabola.nu>2021-10-14 20:14:23 -0300
committerDavid P <megver83@parabola.nu>2021-10-14 20:14:23 -0300
commita2e05211157ba21d35acb27a72a0a56a2f93c6d9 (patch)
treed0e54da16ec656fcb3722eee76aa0dc3560d8ed1 /libre/linux-libre-firmware
parentb3fd4d33c63367821a8d80c05f00e5edab5a4ad4 (diff)
downloadabslibre-a2e05211157ba21d35acb27a72a0a56a2f93c6d9.tar.gz
abslibre-a2e05211157ba21d35acb27a72a0a56a2f93c6d9.tar.bz2
abslibre-a2e05211157ba21d35acb27a72a0a56a2f93c6d9.zip
updpkg: libre/linux-libre-firmware 1:1.4-1
Signed-off-by: David P <megver83@parabola.nu>
Diffstat (limited to 'libre/linux-libre-firmware')
-rw-r--r--libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch4982
-rw-r--r--libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch4893
-rw-r--r--libre/linux-libre-firmware/0003-Update-INSTALL-document.patch44
-rw-r--r--libre/linux-libre-firmware/0004-atusb-Build-updates.patch73
-rw-r--r--libre/linux-libre-firmware/0006-Makefile-Change-spaces-for-atusb-to-tab.patch25
-rw-r--r--libre/linux-libre-firmware/0007-Makefile-Add-atusb-to-all.patch25
-rw-r--r--libre/linux-libre-firmware/0008-Makefile-Set-shell-to-bin-bash.patch25
-rw-r--r--libre/linux-libre-firmware/PKGBUILD60
8 files changed, 23 insertions, 10104 deletions
diff --git a/libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch b/libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch
deleted file mode 100644
index e56707e4c..000000000
--- a/libre/linux-libre-firmware/0001-Update-carl9170-to-latest-upstream.patch
+++ /dev/null
@@ -1,4982 +0,0 @@
-From c164bf7f87f9081fee7e1a186dd7a87a9a020b9e Mon Sep 17 00:00:00 2001
-From: Jason Self <j@jxself.org>
-Date: Thu, 4 Jul 2019 15:12:33 -0700
-Subject: [PATCH 1/8] Update carl9170 to latest upstream
-
-Based on commit 001384147050b9cd9daadb4d3115cc0f13f5b319
-Dated May 5 2019.
----
- WHENCE | 4 +-
- carl9170fw/carlfw/include/wl.h | 2 +-
- carl9170fw/carlfw/src/hostif.c | 8 +-
- carl9170fw/carlfw/src/printf.c | 0
- carl9170fw/carlfw/src/wlantx.c | 5 +-
- carl9170fw/config/CMakeLists.txt | 6 +-
- carl9170fw/config/conf.c | 210 ++++++----
- carl9170fw/config/confdata.c | 329 +++++++++------
- carl9170fw/config/expr.c | 206 +++++++---
- carl9170fw/config/expr.h | 105 ++++-
- carl9170fw/config/kconf_id.c | 54 ---
- carl9170fw/config/lkc.h | 50 +--
- carl9170fw/config/lkc_proto.h | 19 +-
- carl9170fw/config/menu.c | 259 +++++++++---
- carl9170fw/config/preprocess.c | 573 +++++++++++++++++++++++++++
- carl9170fw/config/symbol.c | 255 ++++--------
- carl9170fw/config/util.c | 86 ++--
- carl9170fw/config/zconf.l | 336 ++++++++++------
- carl9170fw/config/zconf.y | 403 +++++++++----------
- carl9170fw/include/linux/ieee80211.h | 24 +-
- carl9170fw/include/shared/wlan.h | 2 +-
- carl9170fw/toolchain/Makefile | 8 +-
- carl9170fw/toolchain/SHA256SUMS | 18 +-
- 23 files changed, 1942 insertions(+), 1020 deletions(-)
- mode change 100755 => 100644 carl9170fw/carlfw/src/printf.c
- delete mode 100644 carl9170fw/config/kconf_id.c
- create mode 100644 carl9170fw/config/preprocess.c
-
-diff --git a/WHENCE b/WHENCE
-index dd8ec20..2932155 100644
---- a/WHENCE
-+++ b/WHENCE
-@@ -142,8 +142,8 @@ From https://git.kernel.org/pub/scm/utils/cis-tools/cis-tools.git
-
- Driver: carl9170 -- Atheros AR9170 802.11 draft-n USB driver
-
--Version: Based on commit 370b7919114a02149088c482c8709cafb9bf7478
--dated May 2 2018.
-+Version: Based on commit 001384147050b9cd9daadb4d3115cc0f13f5b319
-+dated May 5 2019.
-
- Licence: GPLv2 or later.
-
-diff --git a/carl9170fw/carlfw/include/wl.h b/carl9170fw/carlfw/include/wl.h
-index 8499ca2..5566be4 100644
---- a/carl9170fw/carlfw/include/wl.h
-+++ b/carl9170fw/carlfw/include/wl.h
-@@ -237,7 +237,7 @@ static inline __inline void unhide_super(struct dma_desc *desc)
- desc->totalLen += sizeof(struct carl9170_tx_superdesc);
- }
-
--static inline __inline __hot void read_tsf(uint32_t *tsf)
-+static inline __inline __hot void read_tsf(uint32_t tsf[static 2])
- {
- /*
- * "According to the [hardware] documentation:
-diff --git a/carl9170fw/carlfw/src/hostif.c b/carl9170fw/carlfw/src/hostif.c
-index 73e89c7..06726db 100644
---- a/carl9170fw/carlfw/src/hostif.c
-+++ b/carl9170fw/carlfw/src/hostif.c
-@@ -213,10 +213,14 @@ void handle_cmd(struct carl9170_rsp *resp)
- fw.reboot = 1;
- break;
-
-- case CARL9170_CMD_READ_TSF:
-+ case CARL9170_CMD_READ_TSF: {
-+ uint32_t tmptsf[2];
-+
-+ read_tsf(tmptsf);
- resp->hdr.len = 8;
-- read_tsf((uint32_t *)resp->tsf.tsf);
-+ memcpy(resp->tsf.tsf, tmptsf, sizeof(tmptsf));
- break;
-+ }
-
- case CARL9170_CMD_RX_FILTER:
- resp->hdr.len = 0;
-diff --git a/carl9170fw/carlfw/src/printf.c b/carl9170fw/carlfw/src/printf.c
-old mode 100755
-new mode 100644
-diff --git a/carl9170fw/carlfw/src/wlantx.c b/carl9170fw/carlfw/src/wlantx.c
-index 474c040..a8d0952 100644
---- a/carl9170fw/carlfw/src/wlantx.c
-+++ b/carl9170fw/carlfw/src/wlantx.c
-@@ -260,7 +260,7 @@ static void __wlan_tx(struct dma_desc *desc)
-
- if (unlikely(super->s.fill_in_tsf)) {
- struct ieee80211_mgmt *mgmt = (void *) &super->f.data.i3e;
-- uint32_t *tsf = (uint32_t *) &mgmt->u.probe_resp.timestamp;
-+ uint32_t tmptsf[2];
-
- /*
- * Truth be told: this is a hack.
-@@ -272,7 +272,8 @@ static void __wlan_tx(struct dma_desc *desc)
- * (even, if it's got an accurate atomic clock source).
- */
-
-- read_tsf(tsf);
-+ read_tsf(tmptsf);
-+ memcpy(&mgmt->u.probe_resp.timestamp, tmptsf, sizeof(tmptsf));
- }
-
- wlan_tx_ampdu(super);
-diff --git a/carl9170fw/config/CMakeLists.txt b/carl9170fw/config/CMakeLists.txt
-index 0a96a82..23e7218 100644
---- a/carl9170fw/config/CMakeLists.txt
-+++ b/carl9170fw/config/CMakeLists.txt
-@@ -11,13 +11,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-
- file(MAKE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../include/generated")
-
--BISON_TARGET(zconf zconf.y zconf.tab.c COMPILE_FLAGS "-l -b zconf -p zconf -t")
--FLEX_TARGET(zconfscan zconf.l zconf.lex.c COMPILE_FLAGS "-Pzconf -L")
-+BISON_TARGET(zconf zconf.y zconf.tab.c COMPILE_FLAGS "-l -b zconf -p yy -t")
-+FLEX_TARGET(zconfscan zconf.l zconf.lex.c COMPILE_FLAGS "-Pyy -L")
-
- SET(zconf_deps ${FLEX_zconfscan_OUTPUTS})
- SET_SOURCE_FILES_PROPERTIES(${BISON_zconf_OUTPUTS}
- PROPERTIES OBJECT_DEPENDS "${zconf_deps}")
-
--set(conf_src conf.c ${BISON_zconf_OUTPUTS})
-+set(conf_src conf.c symbol.c confdata.c expr.c preprocess.c ${BISON_zconf_OUTPUTS} ${FLEX_zconfscan_OUTPUTS})
-
- add_executable(conf ${conf_src})
-diff --git a/carl9170fw/config/conf.c b/carl9170fw/config/conf.c
-index 6be6143..2949b7d 100644
---- a/carl9170fw/config/conf.c
-+++ b/carl9170fw/config/conf.c
-@@ -1,9 +1,8 @@
-+// SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-
--#include <locale.h>
- #include <ctype.h>
- #include <limits.h>
- #include <stdio.h>
-@@ -20,10 +19,10 @@
-
- static void conf(struct menu *menu);
- static void check_conf(struct menu *menu);
--static void xfgets(char *str, int size, FILE *in);
-
- enum input_mode {
- oldaskconfig,
-+ syncconfig,
- oldconfig,
- allnoconfig,
- allyesconfig,
-@@ -33,12 +32,13 @@ enum input_mode {
- defconfig,
- savedefconfig,
- listnewconfig,
-- oldnoconfig,
--} input_mode = oldaskconfig;
-+ olddefconfig,
-+};
-+static enum input_mode input_mode = oldaskconfig;
-
- static int indent = 1;
- static int tty_stdio;
--static int valid_stdin = 1;
-+static int sync_kconfig;
- static int conf_cnt;
- static char line[PATH_MAX];
- static struct menu *rootEntry;
-@@ -70,14 +70,14 @@ static void strip(char *str)
- *p-- = 0;
- }
-
--static void check_stdin(void)
-+/* Helper function to facilitate fgets() by Jean Sacren. */
-+static void xfgets(char *str, int size, FILE *in)
- {
-- if (!valid_stdin) {
-- printf(_("aborted!\n\n"));
-- printf(_("Console input/output is redirected. "));
-- printf(_("Run 'make config' to update configuration.\n\n"));
-- exit(1);
-- }
-+ if (!fgets(str, size, in))
-+ fprintf(stderr, "\nError in reading or end of file.\n");
-+
-+ if (!tty_stdio)
-+ printf("%s", str);
- }
-
- static int conf_askvalue(struct symbol *sym, const char *def)
-@@ -85,7 +85,7 @@ static int conf_askvalue(struct symbol *sym, const char *def)
- enum symbol_type type = sym_get_type(sym);
-
- if (!sym_has_value(sym))
-- printf(_("(NEW) "));
-+ printf("(NEW) ");
-
- line[0] = '\n';
- line[1] = 0;
-@@ -99,17 +99,15 @@ static int conf_askvalue(struct symbol *sym, const char *def)
-
- switch (input_mode) {
- case oldconfig:
-+ case syncconfig:
- if (sym_has_value(sym)) {
- printf("%s\n", def);
- return 0;
- }
-- check_stdin();
- /* fall through */
- case oldaskconfig:
- fflush(stdout);
- xfgets(line, sizeof(line), stdin);
-- if (!tty_stdio)
-- printf("\n");
- return 1;
- default:
- break;
-@@ -134,7 +132,7 @@ static int conf_string(struct menu *menu)
- const char *def;
-
- while (1) {
-- printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
-+ printf("%*s%s ", indent - 1, "", menu->prompt->text);
- printf("(%s) ", sym->name);
- def = sym_get_string_value(sym);
- if (sym_get_string_value(sym))
-@@ -167,7 +165,7 @@ static int conf_sym(struct menu *menu)
- tristate oldval, newval;
-
- while (1) {
-- printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
-+ printf("%*s%s ", indent - 1, "", menu->prompt->text);
- if (sym->name)
- printf("(%s) ", sym->name);
- putchar('[');
-@@ -189,9 +187,7 @@ static int conf_sym(struct menu *menu)
- printf("/m");
- if (oldval != yes && sym_tristate_within_range(sym, yes))
- printf("/y");
-- if (menu_has_help(menu))
-- printf("/?");
-- printf("] ");
-+ printf("/?] ");
- if (!conf_askvalue(sym, sym_get_string_value(sym)))
- return 0;
- strip(line);
-@@ -254,7 +250,7 @@ static int conf_choice(struct menu *menu)
- case no:
- return 1;
- case mod:
-- printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
-+ printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
- return 0;
- case yes:
- break;
-@@ -264,7 +260,7 @@ static int conf_choice(struct menu *menu)
- while (1) {
- int cnt, def;
-
-- printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu)));
-+ printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu));
- def_sym = sym_get_choice_value(sym);
- cnt = def = 0;
- line[0] = 0;
-@@ -272,7 +268,7 @@ static int conf_choice(struct menu *menu)
- if (!menu_is_visible(child))
- continue;
- if (!child->sym) {
-- printf("%*c %s\n", indent, '*', _(menu_get_prompt(child)));
-+ printf("%*c %s\n", indent, '*', menu_get_prompt(child));
- continue;
- }
- cnt++;
-@@ -281,30 +277,27 @@ static int conf_choice(struct menu *menu)
- printf("%*c", indent, '>');
- } else
- printf("%*c", indent, ' ');
-- printf(" %d. %s", cnt, _(menu_get_prompt(child)));
-+ printf(" %d. %s", cnt, menu_get_prompt(child));
- if (child->sym->name)
- printf(" (%s)", child->sym->name);
- if (!sym_has_value(child->sym))
-- printf(_(" (NEW)"));
-+ printf(" (NEW)");
- printf("\n");
- }
-- printf(_("%*schoice"), indent - 1, "");
-+ printf("%*schoice", indent - 1, "");
- if (cnt == 1) {
- printf("[1]: 1\n");
- goto conf_childs;
- }
-- printf("[1-%d", cnt);
-- if (menu_has_help(menu))
-- printf("?");
-- printf("]: ");
-+ printf("[1-%d?]: ", cnt);
- switch (input_mode) {
- case oldconfig:
-+ case syncconfig:
- if (!is_new) {
- cnt = def;
- printf("%d\n", cnt);
- break;
- }
-- check_stdin();
- /* fall through */
- case oldaskconfig:
- fflush(stdout);
-@@ -364,9 +357,11 @@ static void conf(struct menu *menu)
-
- switch (prop->type) {
- case P_MENU:
-- if ((input_mode == listnewconfig ||
-- input_mode == oldnoconfig) &&
-- rootEntry != menu) {
-+ /*
-+ * Except in oldaskconfig mode, we show only menus that
-+ * contain new symbols.
-+ */
-+ if (input_mode != oldaskconfig && rootEntry != menu) {
- check_conf(menu);
- return;
- }
-@@ -376,7 +371,7 @@ static void conf(struct menu *menu)
- if (prompt)
- printf("%*c\n%*c %s\n%*c\n",
- indent, '*',
-- indent, '*', _(prompt),
-+ indent, '*', prompt,
- indent, '*');
- default:
- ;
-@@ -426,12 +421,22 @@ static void check_conf(struct menu *menu)
- if (sym_is_changable(sym) ||
- (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
- if (input_mode == listnewconfig) {
-- if (sym->name && !sym_is_choice_value(sym)) {
-- printf("%s%s\n", CONFIG_, sym->name);
-+ if (sym->name) {
-+ const char *str;
-+
-+ if (sym->type == S_STRING) {
-+ str = sym_get_string_value(sym);
-+ str = sym_escape_string_value(str);
-+ printf("%s%s=%s\n", CONFIG_, sym->name, str);
-+ free((void *)str);
-+ } else {
-+ str = sym_get_string_value(sym);
-+ printf("%s%s=%s\n", CONFIG_, sym->name, str);
-+ }
- }
-- } else if (input_mode != oldnoconfig) {
-+ } else {
- if (!conf_cnt++)
-- printf(_("*\n* Restart config...\n*\n"));
-+ printf("*\n* Restart config...\n*\n");
- rootEntry = menu_get_parent_menu(menu);
- conf(rootEntry);
- }
-@@ -443,8 +448,9 @@ static void check_conf(struct menu *menu)
- }
-
- static struct option long_opts[] = {
-- {"askconfig", no_argument, NULL, oldaskconfig},
-- {"config", no_argument, NULL, oldconfig},
-+ {"oldaskconfig", no_argument, NULL, oldaskconfig},
-+ {"oldconfig", no_argument, NULL, oldconfig},
-+ {"syncconfig", no_argument, NULL, syncconfig},
- {"defconfig", optional_argument, NULL, defconfig},
- {"savedefconfig", required_argument, NULL, savedefconfig},
- {"allnoconfig", no_argument, NULL, allnoconfig},
-@@ -453,7 +459,7 @@ static struct option long_opts[] = {
- {"alldefconfig", no_argument, NULL, alldefconfig},
- {"randconfig", no_argument, NULL, randconfig},
- {"listnewconfig", no_argument, NULL, listnewconfig},
-- {"noconfig", no_argument, NULL, oldnoconfig},
-+ {"olddefconfig", no_argument, NULL, olddefconfig},
- {NULL, 0, NULL, 0}
- };
-
-@@ -463,10 +469,11 @@ static void conf_usage(const char *progname)
- printf("Usage: %s [-s] [option] <kconfig-file>\n", progname);
- printf("[option] is _one_ of the following:\n");
- printf(" --listnewconfig List new options\n");
-- printf(" --askconfig Start a new configuration using a line-oriented program\n");
-- printf(" --config Update a configuration using a provided .config as base\n");
-- printf(" --silentconfig Same as config, but quietly, additionally update deps\n");
-- printf(" --noconfig Same as silentconfig but set new symbols to no\n");
-+ printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
-+ printf(" --oldconfig Update a configuration using a provided .config as base\n");
-+ printf(" --syncconfig Similar to oldconfig but generates configuration in\n"
-+ " include/{generated/,config/}\n");
-+ printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n");
- printf(" --defconfig <file> New config with default defined in <file>\n");
- printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
- printf(" --allnoconfig New config where all options are answered with no\n");
-@@ -482,12 +489,9 @@ int main(int ac, char **av)
- int opt;
- const char *name, *defconfig_file = NULL /* gcc uninit */;
- struct stat tmpstat;
-+ int no_conf_write = 0;
-
-- setlocale(LC_ALL, "");
-- bindtextdomain(PACKAGE, LOCALEDIR);
-- textdomain(PACKAGE);
--
-- tty_stdio = isatty(0) && isatty(1) && isatty(2);
-+ tty_stdio = isatty(0) && isatty(1);
-
- while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
- if (opt == 's') {
-@@ -496,6 +500,14 @@ int main(int ac, char **av)
- }
- input_mode = (enum input_mode)opt;
- switch (opt) {
-+ case syncconfig:
-+ /*
-+ * syncconfig is invoked during the build stage.
-+ * Suppress distracting "configuration written to ..."
-+ */
-+ conf_set_message_callback(NULL);
-+ sync_kconfig = 1;
-+ break;
- case defconfig:
- case savedefconfig:
- defconfig_file = optarg;
-@@ -532,7 +544,7 @@ int main(int ac, char **av)
- case allmodconfig:
- case alldefconfig:
- case listnewconfig:
-- case oldnoconfig:
-+ case olddefconfig:
- break;
- case '?':
- conf_usage(progname);
-@@ -541,30 +553,45 @@ int main(int ac, char **av)
- }
- }
- if (ac == optind) {
-- printf(_("%s: Kconfig file missing\n"), av[0]);
-+ fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
- conf_usage(progname);
- exit(1);
- }
- name = av[optind];
- conf_parse(name);
- //zconfdump(stdout);
-+ if (sync_kconfig) {
-+ name = conf_get_configname();
-+ if (stat(name, &tmpstat)) {
-+ fprintf(stderr, "***\n"
-+ "*** Configuration file \"%s\" not found!\n"
-+ "***\n"
-+ "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
-+ "*** \"make menuconfig\" or \"make xconfig\").\n"
-+ "***\n", name);
-+ exit(1);
-+ }
-+ }
-
- switch (input_mode) {
- case defconfig:
- if (!defconfig_file)
- defconfig_file = conf_get_default_confname();
- if (conf_read(defconfig_file)) {
-- printf(_("***\n"
-- "*** Can't find default configuration \"%s\"!\n"
-- "***\n"), defconfig_file);
-+ fprintf(stderr,
-+ "***\n"
-+ "*** Can't find default configuration \"%s\"!\n"
-+ "***\n",
-+ defconfig_file);
- exit(1);
- }
- break;
- case savedefconfig:
-+ case syncconfig:
- case oldaskconfig:
- case oldconfig:
- case listnewconfig:
-- case oldnoconfig:
-+ case olddefconfig:
- conf_read(NULL);
- break;
- case allnoconfig:
-@@ -578,7 +605,7 @@ int main(int ac, char **av)
- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
- if (conf_read_simple(name, S_DEF_USER)) {
- fprintf(stderr,
-- _("*** Can't read seed configuration \"%s\"!\n"),
-+ "*** Can't read seed configuration \"%s\"!\n",
- name);
- exit(1);
- }
-@@ -595,7 +622,7 @@ int main(int ac, char **av)
- if (conf_read_simple(name, S_DEF_USER) &&
- conf_read_simple("all.config", S_DEF_USER)) {
- fprintf(stderr,
-- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
-+ "*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n",
- name);
- exit(1);
- }
-@@ -604,7 +631,17 @@ int main(int ac, char **av)
- break;
- }
-
-- valid_stdin = tty_stdio;
-+ if (sync_kconfig) {
-+ name = getenv("KCONFIG_NOSILENTUPDATE");
-+ if (name && *name) {
-+ if (conf_get_changed()) {
-+ fprintf(stderr,
-+ "\n*** The configuration requires explicit update.\n\n");
-+ return 1;
-+ }
-+ no_conf_write = 1;
-+ }
-+ }
-
- switch (input_mode) {
- case allnoconfig:
-@@ -635,44 +672,51 @@ int main(int ac, char **av)
- /* fall through */
- case oldconfig:
- case listnewconfig:
-- case oldnoconfig:
-+ case syncconfig:
- /* Update until a loop caused no more changes */
- do {
- conf_cnt = 0;
- check_conf(&rootmenu);
-- } while (conf_cnt &&
-- (input_mode != listnewconfig &&
-- input_mode != oldnoconfig));
-+ } while (conf_cnt);
-+ break;
-+ case olddefconfig:
-+ default:
- break;
- }
-
- if (input_mode == savedefconfig) {
- if (conf_write_defconfig(defconfig_file)) {
-- fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
-+ fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
- defconfig_file);
- return 1;
- }
- } else if (input_mode != listnewconfig) {
-- /*
-- * build so we shall update autoconf.
-- */
-- if (conf_write(NULL)) {
-- fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
-+ if (!no_conf_write && conf_write(NULL)) {
-+ fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
- exit(1);
- }
-- if (conf_write_autoconf()) {
-- fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
-+
-+ /*
-+ * Create auto.conf if it does not exist.
-+ * This prevents GNU Make 4.1 or older from emitting
-+ * "include/generated/auto.conf: No such file or directory"
-+ * in the top-level Makefile
-+ *
-+ * syncconfig always creates or updates auto.conf because it is
-+ * used during the build.
-+ */
-+
-+ /*
-+ * In our cmake case, we always want to update the autogenerated
-+ * files.
-+ */
-+ sync_kconfig = 1;
-+
-+ if (conf_write_autoconf(sync_kconfig) && sync_kconfig) {
-+ fprintf(stderr,
-+ "\n*** Error during sync of the configuration.\n\n");
- return 1;
- }
- }
- return 0;
- }
--
--/*
-- * Helper function to facilitate fgets() by Jean Sacren.
-- */
--void xfgets(char *str, int size, FILE *in)
--{
-- if (fgets(str, size, in) == NULL)
-- fprintf(stderr, "\nError in reading or end of file.\n");
--}
-diff --git a/carl9170fw/config/confdata.c b/carl9170fw/config/confdata.c
-index e606f06..d67695d 100644
---- a/carl9170fw/config/confdata.c
-+++ b/carl9170fw/config/confdata.c
-@@ -1,12 +1,13 @@
-+// SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-
- #include <sys/stat.h>
- #include <ctype.h>
- #include <errno.h>
- #include <fcntl.h>
-+#include <limits.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
-@@ -16,6 +17,105 @@
-
- #include "lkc.h"
-
-+/* return true if 'path' exists, false otherwise */
-+static bool is_present(const char *path)
-+{
-+ struct stat st;
-+
-+ return !stat(path, &st);
-+}
-+
-+/* return true if 'path' exists and it is a directory, false otherwise */
-+static bool is_dir(const char *path)
-+{
-+ struct stat st;
-+
-+ if (stat(path, &st))
-+ return 0;
-+
-+ return S_ISDIR(st.st_mode);
-+}
-+
-+/*
-+ * Create the parent directory of the given path.
-+ *
-+ * For example, if 'include/config/auto.conf' is given, create 'include/config'.
-+ */
-+static int make_parent_dir(const char *path)
-+{
-+ char tmp[PATH_MAX + 1];
-+ char *p;
-+
-+ strncpy(tmp, path, sizeof(tmp));
-+ tmp[sizeof(tmp) - 1] = 0;
-+
-+ /* Remove the base name. Just return if nothing is left */
-+ p = strrchr(tmp, '/');
-+ if (!p)
-+ return 0;
-+ *(p + 1) = 0;
-+
-+ /* Just in case it is an absolute path */
-+ p = tmp;
-+ while (*p == '/')
-+ p++;
-+
-+ while ((p = strchr(p, '/'))) {
-+ *p = 0;
-+
-+ /* skip if the directory exists */
-+ if (!is_dir(tmp) && mkdir(tmp, 0755))
-+ return -1;
-+
-+ *p = '/';
-+ while (*p == '/')
-+ p++;
-+ }
-+
-+ return 0;
-+}
-+
-+static char depfile_path[PATH_MAX];
-+static size_t depfile_prefix_len;
-+
-+/* touch depfile for symbol 'name' */
-+static int conf_touch_dep(const char *name)
-+{
-+ int fd, ret;
-+ const char *s;
-+ char *d, c;
-+
-+ /* check overflow: prefix + name + ".h" + '\0' must fit in buffer. */
-+ if (depfile_prefix_len + strlen(name) + 3 > sizeof(depfile_path))
-+ return -1;
-+
-+ d = depfile_path + depfile_prefix_len;
-+ s = name;
-+
-+ while ((c = *s++))
-+ *d++ = (c == '_') ? '/' : tolower(c);
-+ strcpy(d, ".h");
-+
-+ /* Assume directory path already exists. */
-+ fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-+ if (fd == -1) {
-+ if (errno != ENOENT)
-+ return -1;
-+
-+ ret = make_parent_dir(depfile_path);
-+ if (ret)
-+ return ret;
-+
-+ /* Try it again. */
-+ fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-+ if (fd == -1)
-+ return -1;
-+ }
-+ close(fd);
-+
-+ return 0;
-+}
-+
- struct conf_printer {
- void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
- void (*print_comment)(FILE *, const char *, void *);
-@@ -28,7 +128,7 @@ static void conf_message(const char *fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
- static const char *conf_filename;
--static int conf_lineno, conf_warnings, conf_unsaved;
-+static int conf_lineno, conf_warnings;
-
- const char conf_defname[] = "include/generated/defconfig";
-
-@@ -43,16 +143,16 @@ static void conf_warning(const char *fmt, ...)
- conf_warnings++;
- }
-
--static void conf_default_message_callback(const char *fmt, va_list ap)
-+static void conf_default_message_callback(const char *s)
- {
- printf("#\n# ");
-- vprintf(fmt, ap);
-+ printf("%s", s);
- printf("\n#\n");
- }
-
--static void (*conf_message_callback) (const char *fmt, va_list ap) =
-+static void (*conf_message_callback)(const char *s) =
- conf_default_message_callback;
--void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
-+void conf_set_message_callback(void (*fn)(const char *s))
- {
- conf_message_callback = fn;
- }
-@@ -60,10 +160,15 @@ void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
- static void conf_message(const char *fmt, ...)
- {
- va_list ap;
-+ char buf[4096];
-+
-+ if (!conf_message_callback)
-+ return;
-
- va_start(ap, fmt);
-- if (conf_message_callback)
-- conf_message_callback(fmt, ap);
-+
-+ vsnprintf(buf, sizeof(buf), fmt, ap);
-+ conf_message_callback(buf);
- va_end(ap);
- }
-
-@@ -81,43 +186,16 @@ const char *conf_get_autoconfig_name(void)
- return name ? name : "include/generated/auto.conf";
- }
-
--static char *conf_expand_value(const char *in)
--{
-- struct symbol *sym;
-- const char *src;
-- static char res_value[SYMBOL_MAXLENGTH];
-- char *dst, name[SYMBOL_MAXLENGTH];
--
-- res_value[0] = 0;
-- dst = name;
-- while ((src = strchr(in, '$'))) {
-- strncat(res_value, in, src - in);
-- src++;
-- dst = name;
-- while (isalnum(*src) || *src == '_')
-- *dst++ = *src++;
-- *dst = 0;
-- sym = sym_lookup(name, 0);
-- sym_calc_value(sym);
-- strcat(res_value, sym_get_string_value(sym));
-- in = src;
-- }
-- strcat(res_value, in);
--
-- return res_value;
--}
--
- char *conf_get_default_confname(void)
- {
-- struct stat buf;
- static char fullname[PATH_MAX+1];
- char *env, *name;
-
-- name = conf_expand_value(conf_defname);
-+ name = expand_string(conf_defname);
- env = getenv(SRCTREE);
- if (env) {
- sprintf(fullname, "%s/%s", env, name);
-- if (!stat(fullname, &buf))
-+ if (is_present(fullname))
- return fullname;
- }
- return name;
-@@ -150,14 +228,6 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
- conf_warning("symbol value '%s' invalid for %s",
- p, sym->name);
- return 1;
-- case S_OTHER:
-- if (*p != '"') {
-- for (p2 = p; *p2 && !isspace(*p2); p2++)
-- ;
-- sym->type = S_STRING;
-- goto done;
-- }
-- /* fall through */
- case S_STRING:
- if (*p++ != '"')
- break;
-@@ -176,9 +246,8 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
- /* fall through */
- case S_INT:
- case S_HEX:
-- done:
- if (sym_string_valid(sym, p)) {
-- sym->def[def].val = strdup(p);
-+ sym->def[def].val = xstrdup(p);
- sym->flags |= def_flags;
- } else {
- if (def != S_DEF_AUTO)
-@@ -201,7 +270,7 @@ static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
- if (new_size > *n) {
- new_size += LINE_GROWTH - 1;
- new_size *= 2;
-- nline = realloc(*lineptr, new_size);
-+ nline = xrealloc(*lineptr, new_size);
- if (!nline)
- return -1;
-
-@@ -274,10 +343,11 @@ int conf_read_simple(const char *name, int def)
- if (expr_calc_value(prop->visible.expr) == no ||
- prop->expr->type != E_SYMBOL)
- continue;
-- name = conf_expand_value(prop->expr->left.sym->name);
-+ sym_calc_value(prop->expr->left.sym);
-+ name = sym_get_string_value(prop->expr->left.sym);
- in = zconf_fopen(name);
- if (in) {
-- conf_message(_("using defaults found in %s"),
-+ conf_message("using defaults found in %s",
- name);
- goto load;
- }
-@@ -290,7 +360,6 @@ load:
- conf_filename = name;
- conf_lineno = 0;
- conf_warnings = 0;
-- conf_unsaved = 0;
-
- def_flags = SYMBOL_DEF << def;
- for_all_symbols(i, sym) {
-@@ -327,7 +396,7 @@ load:
- sym = sym_find(line + 2 + strlen(CONFIG_));
- if (!sym) {
- sym_add_change_count(1);
-- goto setsym;
-+ continue;
- }
- } else {
- sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
-@@ -357,17 +426,22 @@ load:
- if (*p2 == '\r')
- *p2 = 0;
- }
-- if (def == S_DEF_USER) {
-- sym = sym_find(line + strlen(CONFIG_));
-- if (!sym) {
-+
-+ sym = sym_find(line + strlen(CONFIG_));
-+ if (!sym) {
-+ if (def == S_DEF_AUTO)
-+ /*
-+ * Reading from include/config/auto.conf
-+ * If CONFIG_FOO previously existed in
-+ * auto.conf but it is missing now,
-+ * include/config/foo.h must be touched.
-+ */
-+ conf_touch_dep(line + strlen(CONFIG_));
-+ else
- sym_add_change_count(1);
-- goto setsym;
-- }
-- } else {
-- sym = sym_lookup(line + strlen(CONFIG_), 0);
-- if (sym->type == S_UNKNOWN)
-- sym->type = S_OTHER;
-+ continue;
- }
-+
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
-@@ -380,7 +454,7 @@ load:
-
- continue;
- }
--setsym:
-+
- if (sym && sym_is_choice_value(sym)) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- switch (sym->def[def].tri) {
-@@ -409,6 +483,7 @@ setsym:
- int conf_read(const char *name)
- {
- struct symbol *sym;
-+ int conf_unsaved = 0;
- int i;
-
- sym_set_change_count(0);
-@@ -422,7 +497,7 @@ int conf_read(const char *name)
-
- for_all_symbols(i, sym) {
- sym_calc_value(sym);
-- if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
-+ if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
- continue;
- if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
- /* check that calculated value agrees with saved value */
-@@ -678,7 +753,6 @@ static void conf_write_symbol(FILE *fp, struct symbol *sym,
- const char *str;
-
- switch (sym->type) {
-- case S_OTHER:
- case S_UNKNOWN:
- break;
- case S_STRING:
-@@ -791,15 +865,14 @@ int conf_write(const char *name)
- struct menu *menu;
- const char *basename;
- const char *str;
-- char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
-+ char dirname[PATH_MAX+1], tmpname[PATH_MAX+22], newname[PATH_MAX+8];
- char *env;
-
- dirname[0] = 0;
- if (name && name[0]) {
-- struct stat st;
- char *slash;
-
-- if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
-+ if (is_dir(name)) {
- strcpy(dirname, name);
- strcat(dirname, "/");
- basename = conf_get_configname();
-@@ -877,33 +950,61 @@ next:
- return 1;
- }
-
-- conf_message(_("configuration written to %s"), newname);
-+ conf_message("configuration written to %s", newname);
-
- sym_set_change_count(0);
-
- return 0;
- }
-
--static int conf_split_config(void)
-+/* write a dependency file as used by kbuild to track dependencies */
-+static int conf_write_dep(const char *name)
-+{
-+ struct file *file;
-+ FILE *out;
-+
-+ if (!name)
-+ name = ".kconfig.d";
-+ out = fopen("..config.tmp", "w");
-+ if (!out)
-+ return 1;
-+ fprintf(out, "deps_config := \\\n");
-+ for (file = file_list; file; file = file->next) {
-+ if (file->next)
-+ fprintf(out, "\t%s \\\n", file->name);
-+ else
-+ fprintf(out, "\t%s\n", file->name);
-+ }
-+ fprintf(out, "\n%s: \\\n"
-+ "\t$(deps_config)\n\n", conf_get_autoconfig_name());
-+
-+ env_write_dep(out, conf_get_autoconfig_name());
-+
-+ fprintf(out, "\n$(deps_config): ;\n");
-+ fclose(out);
-+
-+ if (make_parent_dir(name))
-+ return 1;
-+ rename("..config.tmp", name);
-+ return 0;
-+}
-+
-+static int conf_touch_deps(void)
- {
- const char *name;
-- char path[PATH_MAX+1];
-- char *s, *d, c;
- struct symbol *sym;
-- struct stat sb;
-- int res, i, fd;
-+ int res, i;
-+
-+ strcpy(depfile_path, "include/generated/");
-+ depfile_prefix_len = strlen(depfile_path);
-
- name = conf_get_autoconfig_name();
- conf_read_simple(name, S_DEF_AUTO);
- sym_calc_value(modules_sym);
-
-- if (chdir("include/generated"))
-- return 1;
--
-- res = 0;
- for_all_symbols(i, sym) {
- sym_calc_value(sym);
-- if ((sym->flags & SYMBOL_AUTO) || !sym->name)
-+ if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
- continue;
- if (sym->flags & SYMBOL_WRITE) {
- if (sym->flags & SYMBOL_DEF_AUTO) {
-@@ -952,63 +1053,30 @@ static int conf_split_config(void)
- * different from 'no').
- */
-
-- /* Replace all '_' and append ".h" */
-- s = sym->name;
-- d = path;
-- while ((c = *s++)) {
-- c = tolower(c);
-- *d++ = (c == '_') ? '/' : c;
-- }
-- strcpy(d, ".h");
--
-- /* Assume directory path already exists. */
-- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-- if (fd == -1) {
-- if (errno != ENOENT) {
-- res = 1;
-- break;
-- }
-- /*
-- * Create directory components,
-- * unless they exist already.
-- */
-- d = path;
-- while ((d = strchr(d, '/'))) {
-- *d = 0;
-- if (stat(path, &sb) && mkdir(path, 0755)) {
-- res = 1;
-- goto out;
-- }
-- *d++ = '/';
-- }
-- /* Try it again. */
-- fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-- if (fd == -1) {
-- res = 1;
-- break;
-- }
-- }
-- close(fd);
-+ res = conf_touch_dep(sym->name);
-+ if (res)
-+ return res;
- }
--out:
-- if (chdir("../.."))
-- return 1;
-
-- return res;
-+ return 0;
- }
-
--int conf_write_autoconf(void)
-+int conf_write_autoconf(int overwrite)
- {
- struct symbol *sym;
- const char *name;
-+ const char *autoconf_name = conf_get_autoconfig_name();
- FILE *out, *tristate, *out_h, *out_c;
- int i;
-
-+ if (!overwrite && is_present(autoconf_name))
-+ return 0;
-+
- sym_clear_all_valid();
-
-- file_write_dep("include/generated/auto.conf.cmd");
-+ conf_write_dep("include/generated/auto.conf.cmd");
-
-- if (conf_split_config())
-+ if (conf_touch_deps())
- return 1;
-
- out = fopen(".tmpconfig", "w");
-@@ -1065,24 +1133,35 @@ int conf_write_autoconf(void)
- name = getenv("KCONFIG_AUTOHEADER");
- if (!name)
- name = "include/generated/autoconf.h";
-+ if (make_parent_dir(name))
-+ return 1;
- if (rename(".tmpconfig.h", name))
- return 1;
-+
- name = getenv("KCONFIG_TRISTATE");
- if (!name)
- name = "include/generated/tristate.conf";
-+ if (make_parent_dir(name))
-+ return 1;
- if (rename(".tmpconfig_tristate", name))
- return 1;
-+
-+ if (make_parent_dir(autoconf_name))
-+ return 1;
-+
- name = getenv("KCONFIG_CMAKE");
- if (!name)
- name = "config.cmake";
-+ if (make_parent_dir(name))
-+ return 1;
- if (rename(".tmpconfig.cmake", name))
- return 1;
-- name = conf_get_autoconfig_name();
-+
- /*
- * This must be the last step, kbuild has a dependency on auto.conf
- * and this marks the successful completion of the previous steps.
- */
-- if (rename(".tmpconfig", name))
-+ if (rename(".tmpconfig", autoconf_name))
- return 1;
-
- return 0;
-@@ -1186,7 +1265,7 @@ void set_all_choice_values(struct symbol *csym)
- bool conf_set_all_new_symbols(enum conf_def_mode mode)
- {
- struct symbol *sym, *csym;
-- int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y
-+ int i, cnt, pby, pty, ptm; /* pby: probability of bool = y
- * pty: probability of tristate = y
- * ptm: probability of tristate = m
- */
-diff --git a/carl9170fw/config/expr.c b/carl9170fw/config/expr.c
-index 8cee597..77ffff3 100644
---- a/carl9170fw/config/expr.c
-+++ b/carl9170fw/config/expr.c
-@@ -1,8 +1,10 @@
-+// SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-
-+#include <ctype.h>
-+#include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-@@ -94,7 +96,7 @@ struct expr *expr_copy(const struct expr *org)
- e->right.expr = expr_copy(org->right.expr);
- break;
- default:
-- printf("can't copy type %d\n", e->type);
-+ fprintf(stderr, "can't copy type %d\n", e->type);
- free(e);
- e = NULL;
- break;
-@@ -113,7 +115,7 @@ void expr_free(struct expr *e)
- break;
- case E_NOT:
- expr_free(e->left.expr);
-- return;
-+ break;
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
-@@ -127,7 +129,7 @@ void expr_free(struct expr *e)
- expr_free(e->right.expr);
- break;
- default:
-- printf("how to free type %d?\n", e->type);
-+ fprintf(stderr, "how to free type %d?\n", e->type);
- break;
- }
- free(e);
-@@ -138,8 +140,18 @@ static int trans_count;
- #define e1 (*ep1)
- #define e2 (*ep2)
-
-+/*
-+ * expr_eliminate_eq() helper.
-+ *
-+ * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
-+ * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
-+ * against all other leaves. Two equal leaves are both replaced with either 'y'
-+ * or 'n' as appropriate for 'type', to be eliminated later.
-+ */
- static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
- {
-+ /* Recurse down to leaves */
-+
- if (e1->type == type) {
- __expr_eliminate_eq(type, &e1->left.expr, &e2);
- __expr_eliminate_eq(type, &e1->right.expr, &e2);
-@@ -150,12 +162,18 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
- __expr_eliminate_eq(type, &e1, &e2->right.expr);
- return;
- }
-+
-+ /* e1 and e2 are leaves. Compare them. */
-+
- if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
- e1->left.sym == e2->left.sym &&
- (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
- return;
- if (!expr_eq(e1, e2))
- return;
-+
-+ /* e1 and e2 are equal leaves. Prepare them for elimination. */
-+
- trans_count++;
- expr_free(e1); expr_free(e2);
- switch (type) {
-@@ -172,6 +190,35 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e
- }
- }
-
-+/*
-+ * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
-+ * Example reductions:
-+ *
-+ * ep1: A && B -> ep1: y
-+ * ep2: A && B && C -> ep2: C
-+ *
-+ * ep1: A || B -> ep1: n
-+ * ep2: A || B || C -> ep2: C
-+ *
-+ * ep1: A && (B && FOO) -> ep1: FOO
-+ * ep2: (BAR && B) && A -> ep2: BAR
-+ *
-+ * ep1: A && (B || C) -> ep1: y
-+ * ep2: (C || B) && A -> ep2: y
-+ *
-+ * Comparisons are done between all operands at the same "level" of && or ||.
-+ * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
-+ * following operands will be compared:
-+ *
-+ * - 'e1', 'e2 || e3', and 'e4 || e5', against each other
-+ * - e2 against e3
-+ * - e4 against e5
-+ *
-+ * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
-+ * '(e1 && e2) && e3' are both a single level.
-+ *
-+ * See __expr_eliminate_eq() as well.
-+ */
- void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
- {
- if (!e1 || !e2)
-@@ -197,6 +244,12 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
- #undef e1
- #undef e2
-
-+/*
-+ * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
-+ * &&/|| expressions are considered equal if every operand in one expression
-+ * equals some operand in the other (operands do not need to appear in the same
-+ * order), recursively.
-+ */
- static int expr_eq(struct expr *e1, struct expr *e2)
- {
- int res, old_count;
-@@ -243,6 +296,17 @@ static int expr_eq(struct expr *e1, struct expr *e2)
- return 0;
- }
-
-+/*
-+ * Recursively performs the following simplifications in-place (as well as the
-+ * corresponding simplifications with swapped operands):
-+ *
-+ * expr && n -> n
-+ * expr && y -> expr
-+ * expr || n -> expr
-+ * expr || y -> y
-+ *
-+ * Returns the optimized expression.
-+ */
- static struct expr *expr_eliminate_yn(struct expr *e)
- {
- struct expr *tmp;
-@@ -516,12 +580,21 @@ static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
- return NULL;
- }
-
-+/*
-+ * expr_eliminate_dups() helper.
-+ *
-+ * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
-+ * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
-+ * against all other leaves to look for simplifications.
-+ */
- static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
- {
- #define e1 (*ep1)
- #define e2 (*ep2)
- struct expr *tmp;
-
-+ /* Recurse down to leaves */
-+
- if (e1->type == type) {
- expr_eliminate_dups1(type, &e1->left.expr, &e2);
- expr_eliminate_dups1(type, &e1->right.expr, &e2);
-@@ -532,6 +605,9 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
- expr_eliminate_dups1(type, &e1, &e2->right.expr);
- return;
- }
-+
-+ /* e1 and e2 are leaves. Compare and process them. */
-+
- if (e1 == e2)
- return;
-
-@@ -568,6 +644,17 @@ static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct
- #undef e2
- }
-
-+/*
-+ * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
-+ * operands.
-+ *
-+ * Example simplifications:
-+ *
-+ * A || B || A -> A || B
-+ * A && B && A=y -> A=y && B
-+ *
-+ * Returns the deduplicated expression.
-+ */
- struct expr *expr_eliminate_dups(struct expr *e)
- {
- int oldcount;
-@@ -584,6 +671,7 @@ struct expr *expr_eliminate_dups(struct expr *e)
- ;
- }
- if (!trans_count)
-+ /* No simplifications done in this pass. We're done */
- break;
- e = expr_eliminate_yn(e);
- }
-@@ -591,6 +679,12 @@ struct expr *expr_eliminate_dups(struct expr *e)
- return e;
- }
-
-+/*
-+ * Performs various simplifications involving logical operators and
-+ * comparisons.
-+ *
-+ * Allocates and returns a new expression.
-+ */
- struct expr *expr_transform(struct expr *e)
- {
- struct expr *tmp;
-@@ -805,6 +899,20 @@ bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
- return false;
- }
-
-+/*
-+ * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
-+ * expression 'e'.
-+ *
-+ * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
-+ *
-+ * A -> A!=n
-+ * !A -> A=n
-+ * A && B -> !(A=n || B=n)
-+ * A || B -> !(A=n && B=n)
-+ * A && (B || C) -> !(A=n || (B=n && C=n))
-+ *
-+ * Allocates and returns a new expression.
-+ */
- struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
- {
- struct expr *e1, *e2;
-@@ -874,7 +982,6 @@ enum string_value_kind {
- k_string,
- k_signed,
- k_unsigned,
-- k_invalid
- };
-
- union string_value {
-@@ -905,13 +1012,10 @@ static enum string_value_kind expr_parse_string(const char *str,
- val->u = strtoull(str, &tail, 16);
- kind = k_unsigned;
- break;
-- case S_STRING:
-- case S_UNKNOWN:
-+ default:
- val->s = strtoll(str, &tail, 0);
- kind = k_signed;
- break;
-- default:
-- return k_invalid;
- }
- return !errno && !*tail && tail > str && isxdigit(tail[-1])
- ? kind : k_string;
-@@ -967,13 +1071,7 @@ tristate expr_calc_value(struct expr *e)
-
- if (k1 == k_string || k2 == k_string)
- res = strcmp(str1, str2);
-- else if (k1 == k_invalid || k2 == k_invalid) {
-- if (e->type != E_EQUAL && e->type != E_UNEQUAL) {
-- printf("Cannot compare \"%s\" and \"%s\"\n", str1, str2);
-- return no;
-- }
-- res = strcmp(str1, str2);
-- } else if (k1 == k_unsigned || k2 == k_unsigned)
-+ else if (k1 == k_unsigned || k2 == k_unsigned)
- res = (lval.u > rval.u) - (lval.u < rval.u);
- else /* if (k1 == k_signed && k2 == k_signed) */
- res = (lval.s > rval.s) - (lval.s < rval.s);
-@@ -1031,49 +1129,9 @@ static int expr_compare_type(enum expr_type t1, enum expr_type t2)
- return 0;
- }
-
--static inline struct expr *
--expr_get_leftmost_symbol(const struct expr *e)
--{
--
-- if (e == NULL)
-- return NULL;
--
-- while (e->type != E_SYMBOL)
-- e = e->left.expr;
--
-- return expr_copy(e);
--}
--
--/*
-- * Given expression `e1' and `e2', returns the leaf of the longest
-- * sub-expression of `e1' not containing 'e2.
-- */
--struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2)
--{
-- struct expr *ret;
--
-- switch (e1->type) {
-- case E_OR:
-- return expr_alloc_and(
-- expr_simplify_unmet_dep(e1->left.expr, e2),
-- expr_simplify_unmet_dep(e1->right.expr, e2));
-- case E_AND: {
-- struct expr *e;
-- e = expr_alloc_and(expr_copy(e1), expr_copy(e2));
-- e = expr_eliminate_dups(e);
-- ret = (!expr_eq(e, e1)) ? e1 : NULL;
-- expr_free(e);
-- break;
-- }
-- default:
-- ret = e1;
-- break;
-- }
--
-- return expr_get_leftmost_symbol(ret);
--}
--
--void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
-+void expr_print(struct expr *e,
-+ void (*fn)(void *, struct symbol *, const char *),
-+ void *data, int prevtoken)
- {
- if (!e) {
- fn(data, NULL, "y");
-@@ -1207,3 +1265,33 @@ void expr_gstr_print(struct expr *e, struct gstr *gs)
- {
- expr_print(e, expr_print_gstr_helper, gs, E_NONE);
- }
-+
-+/*
-+ * Transform the top level "||" tokens into newlines and prepend each
-+ * line with a minus. This makes expressions much easier to read.
-+ * Suitable for reverse dependency expressions.
-+ */
-+static void expr_print_revdep(struct expr *e,
-+ void (*fn)(void *, struct symbol *, const char *),
-+ void *data, tristate pr_type, const char **title)
-+{
-+ if (e->type == E_OR) {
-+ expr_print_revdep(e->left.expr, fn, data, pr_type, title);
-+ expr_print_revdep(e->right.expr, fn, data, pr_type, title);
-+ } else if (expr_calc_value(e) == pr_type) {
-+ if (*title) {
-+ fn(data, NULL, *title);
-+ *title = NULL;
-+ }
-+
-+ fn(data, NULL, " - ");
-+ expr_print(e, fn, data, E_NONE);
-+ fn(data, NULL, "\n");
-+ }
-+}
-+
-+void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
-+ tristate pr_type, const char *title)
-+{
-+ expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
-+}
-diff --git a/carl9170fw/config/expr.h b/carl9170fw/config/expr.h
-index a73f762..999edb6 100644
---- a/carl9170fw/config/expr.h
-+++ b/carl9170fw/config/expr.h
-@@ -1,6 +1,6 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-
- #ifndef EXPR_H
-@@ -62,7 +62,7 @@ struct symbol_value {
- };
-
- enum symbol_type {
-- S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
-+ S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING
- };
-
- /* enum values are used as index to symbol.def[] */
-@@ -74,21 +74,64 @@ enum {
- S_DEF_COUNT
- };
-
-+/*
-+ * Represents a configuration symbol.
-+ *
-+ * Choices are represented as a special kind of symbol and have the
-+ * SYMBOL_CHOICE bit set in 'flags'.
-+ */
- struct symbol {
-+ /* The next symbol in the same bucket in the symbol hash table */
- struct symbol *next;
-+
-+ /* The name of the symbol, e.g. "FOO" for 'config FOO' */
- char *name;
-+
-+ /* S_BOOLEAN, S_TRISTATE, ... */
- enum symbol_type type;
-+
-+ /*
-+ * The calculated value of the symbol. The SYMBOL_VALID bit is set in
-+ * 'flags' when this is up to date. Note that this value might differ
-+ * from the user value set in e.g. a .config file, due to visibility.
-+ */
- struct symbol_value curr;
-+
-+ /*
-+ * Values for the symbol provided from outside. def[S_DEF_USER] holds
-+ * the .config value.
-+ */
- struct symbol_value def[S_DEF_COUNT];
-+
-+ /*
-+ * An upper bound on the tristate value the user can set for the symbol
-+ * if it is a boolean or tristate. Calculated from prompt dependencies,
-+ * which also inherit dependencies from enclosing menus, choices, and
-+ * ifs. If 'n', the user value will be ignored.
-+ *
-+ * Symbols lacking prompts always have visibility 'n'.
-+ */
- tristate visible;
-+
-+ /* SYMBOL_* flags */
- int flags;
-+
-+ /* List of properties. See prop_type. */
- struct property *prop;
-+
-+ /* Dependencies from enclosing menus, choices, and ifs */
- struct expr_value dir_dep;
-+
-+ /* Reverse dependencies through being selected by other symbols */
- struct expr_value rev_dep;
-+
-+ /*
-+ * "Weak" reverse dependencies through being implied by other symbols
-+ */
- struct expr_value implied;
- };
-
--#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
-+#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next)
-
- #define SYMBOL_CONST 0x0001 /* symbol is const */
- #define SYMBOL_CHECK 0x0008 /* used during dependency checking */
-@@ -98,7 +141,7 @@ struct symbol {
- #define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
- #define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
- #define SYMBOL_CHANGED 0x0400 /* ? */
--#define SYMBOL_AUTO 0x1000 /* value from environment variable */
-+#define SYMBOL_NO_WRITE 0x1000 /* Symbol for internal use only; it will not be written */
- #define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
- #define SYMBOL_WARNED 0x8000 /* warning has been issued */
-
-@@ -128,18 +171,20 @@ struct symbol {
- * config BAZ
- * int "BAZ Value"
- * range 1..255
-+ *
-+ * Please, also check zconf.y:print_symbol() when modifying the
-+ * list of property types!
- */
- enum prop_type {
- P_UNKNOWN,
- P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
- P_COMMENT, /* text associated with a comment */
-- P_MENU, /* prompt associated with a menuconfig option */
-+ P_MENU, /* prompt associated with a menu or menuconfig symbol */
- P_DEFAULT, /* default y */
- P_CHOICE, /* choice value */
- P_SELECT, /* select BAR */
- P_IMPLY, /* imply BAR */
- P_RANGE, /* range 7..100 (for a symbol) */
-- P_ENV, /* value from environment variable */
- P_SYMBOL, /* where a symbol is defined */
- };
-
-@@ -166,22 +211,67 @@ struct property {
- for (st = sym->prop; st; st = st->next) \
- if (st->text)
-
-+/*
-+ * Represents a node in the menu tree, as seen in e.g. menuconfig (though used
-+ * for all front ends). Each symbol, menu, etc. defined in the Kconfig files
-+ * gets a node. A symbol defined in multiple locations gets one node at each
-+ * location.
-+ */
- struct menu {
-+ /* The next menu node at the same level */
- struct menu *next;
-+
-+ /* The parent menu node, corresponding to e.g. a menu or choice */
- struct menu *parent;
-+
-+ /* The first child menu node, for e.g. menus and choices */
- struct menu *list;
-+
-+ /*
-+ * The symbol associated with the menu node. Choices are implemented as
-+ * a special kind of symbol. NULL for menus, comments, and ifs.
-+ */
- struct symbol *sym;
-+
-+ /*
-+ * The prompt associated with the node. This holds the prompt for a
-+ * symbol as well as the text for a menu or comment, along with the
-+ * type (P_PROMPT, P_MENU, etc.)
-+ */
- struct property *prompt;
-+
-+ /*
-+ * 'visible if' dependencies. If more than one is given, they will be
-+ * ANDed together.
-+ */
- struct expr *visibility;
-+
-+ /*
-+ * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed
-+ * together
-+ */
- struct expr *dep;
-+
-+ /* MENU_* flags */
- unsigned int flags;
-+
-+ /* Any help text associated with the node */
- char *help;
-+
-+ /* The location where the menu node appears in the Kconfig files */
- struct file *file;
- int lineno;
-+
-+ /* For use by front ends that need to store auxiliary data */
- void *data;
- };
-
-+/*
-+ * Set on a menu node when the corresponding symbol changes state in some way.
-+ * Can be checked by front ends.
-+ */
- #define MENU_CHANGED 0x0001
-+
- #define MENU_ROOT 0x0002
-
- struct jump_key {
-@@ -217,11 +307,12 @@ struct expr *expr_transform(struct expr *e);
- int expr_contains_symbol(struct expr *dep, struct symbol *sym);
- bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
- struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
--struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);
-
- void expr_fprint(struct expr *e, FILE *out);
- struct gstr; /* forward */
- void expr_gstr_print(struct expr *e, struct gstr *gs);
-+void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
-+ tristate pr_type, const char *title);
-
- static inline int expr_is_yes(struct expr *e)
- {
-diff --git a/carl9170fw/config/kconf_id.c b/carl9170fw/config/kconf_id.c
-deleted file mode 100644
-index 5abbc72..0000000
---- a/carl9170fw/config/kconf_id.c
-+++ /dev/null
-@@ -1,54 +0,0 @@
--
--static struct kconf_id kconf_id_array[] = {
-- { "mainmenu", T_MAINMENU, TF_COMMAND },
-- { "menu", T_MENU, TF_COMMAND },
-- { "endmenu", T_ENDMENU, TF_COMMAND },
-- { "source", T_SOURCE, TF_COMMAND },
-- { "choice", T_CHOICE, TF_COMMAND },
-- { "endchoice", T_ENDCHOICE, TF_COMMAND },
-- { "comment", T_COMMENT, TF_COMMAND },
-- { "config", T_CONFIG, TF_COMMAND },
-- { "menuconfig", T_MENUCONFIG, TF_COMMAND },
-- { "help", T_HELP, TF_COMMAND },
-- { "---help---", T_HELP, TF_COMMAND },
-- { "if", T_IF, TF_COMMAND|TF_PARAM },
-- { "endif", T_ENDIF, TF_COMMAND },
-- { "depends", T_DEPENDS, TF_COMMAND },
-- { "optional", T_OPTIONAL, TF_COMMAND },
-- { "default", T_DEFAULT, TF_COMMAND, S_UNKNOWN },
-- { "prompt", T_PROMPT, TF_COMMAND },
-- { "tristate", T_TYPE, TF_COMMAND, S_TRISTATE },
-- { "def_tristate", T_DEFAULT, TF_COMMAND, S_TRISTATE },
-- { "bool", T_TYPE, TF_COMMAND, S_BOOLEAN },
-- { "boolean", T_TYPE, TF_COMMAND, S_BOOLEAN },
-- { "def_bool", T_DEFAULT, TF_COMMAND, S_BOOLEAN },
-- { "int", T_TYPE, TF_COMMAND, S_INT },
-- { "hex", T_TYPE, TF_COMMAND, S_HEX },
-- { "string", T_TYPE, TF_COMMAND, S_STRING },
-- { "select", T_SELECT, TF_COMMAND },
-- { "imply", T_IMPLY, TF_COMMAND },
-- { "range", T_RANGE, TF_COMMAND },
-- { "visible", T_VISIBLE, TF_COMMAND },
-- { "option", T_OPTION, TF_COMMAND },
-- { "on", T_ON, TF_PARAM },
-- { "modules", T_OPT_MODULES, TF_OPTION },
-- { "defconfig_list", T_OPT_DEFCONFIG_LIST, TF_OPTION },
-- { "env", T_OPT_ENV, TF_OPTION },
-- { "allnoconfig_y", T_OPT_ALLNOCONFIG_Y, TF_OPTION },
--};
--
--#define KCONF_ID_ARRAY_SIZE (sizeof(kconf_id_array)/sizeof(struct kconf_id))
--
--static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len)
--{
-- int i;
--
-- for (i = 0; i < KCONF_ID_ARRAY_SIZE; i++) {
-- struct kconf_id *id = kconf_id_array+i;
-- int l = strlen(id->name);
--
-- if (len == l && !memcmp(str, id->name, len))
-- return id;
-- }
-- return NULL;
--}
-diff --git a/carl9170fw/config/lkc.h b/carl9170fw/config/lkc.h
-index cdcbe43..531ff7c 100644
---- a/carl9170fw/config/lkc.h
-+++ b/carl9170fw/config/lkc.h
-@@ -1,6 +1,6 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-
- #ifndef LKC_H
-@@ -8,15 +8,6 @@
-
- #include "expr.h"
-
--#ifndef KBUILD_NO_NLS
--# include <libintl.h>
--#else
--static inline const char *gettext(const char *txt) { return txt; }
--static inline void textdomain(const char *domainname) {}
--static inline void bindtextdomain(const char *name, const char *dir) {}
--static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; }
--#endif
--
- #ifdef __cplusplus
- extern "C" {
- #endif
-@@ -29,11 +20,6 @@ extern "C" {
- #define PACKAGE "linux"
- #endif
-
--#define LOCALEDIR "/usr/share/locale"
--
--#define _(text) gettext(text)
--#define N_(text) (text)
--
- #ifndef CONFIG_
- #define CONFIG_ "CONFIG_"
- #endif
-@@ -44,10 +30,6 @@ static inline const char *CONFIG_prefix(void)
- #undef CONFIG_
- #define CONFIG_ CONFIG_prefix()
-
--#define TF_COMMAND 0x0001
--#define TF_PARAM 0x0002
--#define TF_OPTION 0x0004
--
- enum conf_def_mode {
- def_default,
- def_yes,
-@@ -56,18 +38,7 @@ enum conf_def_mode {
- def_random
- };
-
--#define T_OPT_MODULES 1
--#define T_OPT_DEFCONFIG_LIST 2
--#define T_OPT_ENV 3
--#define T_OPT_ALLNOCONFIG_Y 4
--
--struct kconf_id {
-- const char *name;
-- int token;
-- unsigned int flags;
-- enum symbol_type stype;
--};
--
-+extern int yylineno;
- void zconfdump(FILE *out);
- void zconf_starthelp(void);
- FILE *zconf_fopen(const char *name);
-@@ -100,21 +71,27 @@ void menu_warn(struct menu *menu, const char *fmt, ...);
- struct menu *menu_add_menu(void);
- void menu_end_menu(void);
- void menu_add_entry(struct symbol *sym);
--void menu_end_entry(void);
- void menu_add_dep(struct expr *dep);
- void menu_add_visibility(struct expr *dep);
- struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
- void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
- void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
--void menu_add_option(int token, char *arg);
-+void menu_add_option_modules(void);
-+void menu_add_option_defconfig_list(void);
-+void menu_add_option_allnoconfig_y(void);
- void menu_finalize(struct menu *parent);
- void menu_set_type(int type);
-
- /* util.c */
- struct file *file_lookup(const char *name);
--int file_write_dep(const char *name);
- void *xmalloc(size_t size);
- void *xcalloc(size_t nmemb, size_t size);
-+void *xrealloc(void *p, size_t size);
-+char *xstrdup(const char *s);
-+char *xstrndup(const char *s, size_t n);
-+
-+/* zconf.l */
-+int yylex(void);
-
- struct gstr {
- size_t len;
-@@ -132,16 +109,13 @@ void str_printf(struct gstr *gs, const char *fmt, ...);
- const char *str_get(struct gstr *gs);
-
- /* symbol.c */
--extern struct expr *sym_env_list;
--
--void sym_init(void);
- void sym_clear_all_valid(void);
- struct symbol *sym_choice_default(struct symbol *sym);
-+struct property *sym_get_range_prop(struct symbol *sym);
- const char *sym_get_string_default(struct symbol *sym);
- struct symbol *sym_check_deps(struct symbol *sym);
- struct property *prop_alloc(enum prop_type type, struct symbol *sym);
- struct symbol *prop_get_symbol(struct property *prop);
--struct property *sym_get_env_prop(struct symbol *sym);
-
- static inline tristate sym_get_tristate_value(struct symbol *sym)
- {
-diff --git a/carl9170fw/config/lkc_proto.h b/carl9170fw/config/lkc_proto.h
-index 5d86e2d..86c2675 100644
---- a/carl9170fw/config/lkc_proto.h
-+++ b/carl9170fw/config/lkc_proto.h
-@@ -7,10 +7,10 @@ int conf_read(const char *name);
- int conf_read_simple(const char *name, int);
- int conf_write_defconfig(const char *name);
- int conf_write(const char *name);
--int conf_write_autoconf(void);
-+int conf_write_autoconf(int overwrite);
- bool conf_get_changed(void);
- void conf_set_changed_callback(void (*fn)(void));
--void conf_set_message_callback(void (*fn)(const char *fmt, va_list ap));
-+void conf_set_message_callback(void (*fn)(const char *s));
-
- /* menu.c */
- extern struct menu rootmenu;
-@@ -31,7 +31,6 @@ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
-
- struct symbol * sym_lookup(const char *name, int flags);
- struct symbol * sym_find(const char *name);
--const char * sym_expand_string_value(const char *in);
- const char * sym_escape_string_value(const char *in);
- struct symbol ** sym_re_search(const char *pattern);
- const char * sym_type_name(enum symbol_type type);
-@@ -49,5 +48,19 @@ const char * sym_get_string_value(struct symbol *sym);
-
- const char * prop_get_type_name(enum prop_type type);
-
-+/* preprocess.c */
-+enum variable_flavor {
-+ VAR_SIMPLE,
-+ VAR_RECURSIVE,
-+ VAR_APPEND,
-+};
-+void env_write_dep(FILE *f, const char *auto_conf_name);
-+void variable_add(const char *name, const char *value,
-+ enum variable_flavor flavor);
-+void variable_all_del(void);
-+char *expand_string(const char *in);
-+char *expand_dollar(const char **str);
-+char *expand_one_token(const char **str);
-+
- /* expr.c */
- void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
-diff --git a/carl9170fw/config/menu.c b/carl9170fw/config/menu.c
-index e935793..d9d1646 100644
---- a/carl9170fw/config/menu.c
-+++ b/carl9170fw/config/menu.c
-@@ -1,6 +1,6 @@
-+// SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-
- #include <ctype.h>
-@@ -62,13 +62,8 @@ void menu_add_entry(struct symbol *sym)
- menu_add_symbol(P_SYMBOL, sym, NULL);
- }
-
--void menu_end_entry(void)
--{
--}
--
- struct menu *menu_add_menu(void)
- {
-- menu_end_entry();
- last_entry_ptr = &current_entry->list;
- return current_menu = current_entry;
- }
-@@ -79,19 +74,23 @@ void menu_end_menu(void)
- current_menu = current_menu->parent;
- }
-
--static struct expr *menu_check_dep(struct expr *e)
-+/*
-+ * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running
-+ * without modules
-+ */
-+static struct expr *rewrite_m(struct expr *e)
- {
- if (!e)
- return e;
-
- switch (e->type) {
- case E_NOT:
-- e->left.expr = menu_check_dep(e->left.expr);
-+ e->left.expr = rewrite_m(e->left.expr);
- break;
- case E_OR:
- case E_AND:
-- e->left.expr = menu_check_dep(e->left.expr);
-- e->right.expr = menu_check_dep(e->right.expr);
-+ e->left.expr = rewrite_m(e->left.expr);
-+ e->right.expr = rewrite_m(e->right.expr);
- break;
- case E_SYMBOL:
- /* change 'm' into 'm' && MODULES */
-@@ -106,7 +105,7 @@ static struct expr *menu_check_dep(struct expr *e)
-
- void menu_add_dep(struct expr *dep)
- {
-- current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep));
-+ current_entry->dep = expr_alloc_and(current_entry->dep, dep);
- }
-
- void menu_set_type(int type)
-@@ -131,7 +130,7 @@ static struct property *menu_add_prop(enum prop_type type, char *prompt, struct
-
- prop->menu = current_entry;
- prop->expr = expr;
-- prop->visible.expr = menu_check_dep(dep);
-+ prop->visible.expr = dep;
-
- if (prompt) {
- if (isspace(*prompt)) {
-@@ -196,31 +195,26 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
- menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
- }
-
--void menu_add_option(int token, char *arg)
-+void menu_add_option_modules(void)
- {
-- switch (token) {
-- case T_OPT_MODULES:
-- if (modules_sym)
-- zconf_error("symbol '%s' redefines option 'modules'"
-- " already defined by symbol '%s'",
-- current_entry->sym->name,
-- modules_sym->name
-- );
-- modules_sym = current_entry->sym;
-- break;
-- case T_OPT_DEFCONFIG_LIST:
-- if (!sym_defconfig_list)
-- sym_defconfig_list = current_entry->sym;
-- else if (sym_defconfig_list != current_entry->sym)
-- zconf_error("trying to redefine defconfig symbol");
-- break;
-- case T_OPT_ENV:
-- prop_add_env(arg);
-- break;
-- case T_OPT_ALLNOCONFIG_Y:
-- current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
-- break;
-- }
-+ if (modules_sym)
-+ zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
-+ current_entry->sym->name, modules_sym->name);
-+ modules_sym = current_entry->sym;
-+}
-+
-+void menu_add_option_defconfig_list(void)
-+{
-+ if (!sym_defconfig_list)
-+ sym_defconfig_list = current_entry->sym;
-+ else if (sym_defconfig_list != current_entry->sym)
-+ zconf_error("trying to redefine defconfig symbol");
-+ sym_defconfig_list->flags |= SYMBOL_NO_WRITE;
-+}
-+
-+void menu_add_option_allnoconfig_y(void)
-+{
-+ current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
- }
-
- static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
-@@ -252,6 +246,16 @@ static void sym_check_prop(struct symbol *sym)
- "'%s': number is invalid",
- sym->name);
- }
-+ if (sym_is_choice(sym)) {
-+ struct property *choice_prop =
-+ sym_get_choice_prop(sym2);
-+
-+ if (!choice_prop ||
-+ prop_get_symbol(choice_prop) != sym)
-+ prop_warn(prop,
-+ "choice default symbol '%s' is not contained in the choice",
-+ sym2->name);
-+ }
- break;
- case P_SELECT:
- case P_IMPLY:
-@@ -260,13 +264,13 @@ static void sym_check_prop(struct symbol *sym)
- if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
- prop_warn(prop,
- "config symbol '%s' uses %s, but is "
-- "not boolean or tristate", sym->name, use);
-+ "not bool or tristate", sym->name, use);
- else if (sym2->type != S_UNKNOWN &&
- sym2->type != S_BOOLEAN &&
- sym2->type != S_TRISTATE)
- prop_warn(prop,
- "'%s' has wrong type. '%s' only "
-- "accept arguments of boolean and "
-+ "accept arguments of bool and "
- "tristate type", sym2->name, use);
- break;
- case P_RANGE:
-@@ -292,6 +296,11 @@ void menu_finalize(struct menu *parent)
-
- sym = parent->sym;
- if (parent->list) {
-+ /*
-+ * This menu node has children. We (recursively) process them
-+ * and propagate parent dependencies before moving on.
-+ */
-+
- if (sym && sym_is_choice(sym)) {
- if (sym->type == S_UNKNOWN) {
- /* find the first choice value to find out choice type */
-@@ -309,30 +318,83 @@ void menu_finalize(struct menu *parent)
- if (menu->sym && menu->sym->type == S_UNKNOWN)
- menu_set_type(sym->type);
- }
-+
-+ /*
-+ * Use the choice itself as the parent dependency of
-+ * the contained items. This turns the mode of the
-+ * choice into an upper bound on the visibility of the
-+ * choice value symbols.
-+ */
- parentdep = expr_alloc_symbol(sym);
- } else if (parent->prompt)
-+ /* Menu node for 'menu' */
- parentdep = parent->prompt->visible.expr;
- else
-+ /* Menu node for 'if' */
- parentdep = parent->dep;
-
-+ /* For each child menu node... */
- for (menu = parent->list; menu; menu = menu->next) {
-- basedep = expr_transform(menu->dep);
-+ /*
-+ * Propagate parent dependencies to the child menu
-+ * node, also rewriting and simplifying expressions
-+ */
-+ basedep = rewrite_m(menu->dep);
-+ basedep = expr_transform(basedep);
- basedep = expr_alloc_and(expr_copy(parentdep), basedep);
- basedep = expr_eliminate_dups(basedep);
- menu->dep = basedep;
-+
- if (menu->sym)
-+ /*
-+ * Note: For symbols, all prompts are included
-+ * too in the symbol's own property list
-+ */
- prop = menu->sym->prop;
- else
-+ /*
-+ * For non-symbol menu nodes, we just need to
-+ * handle the prompt
-+ */
- prop = menu->prompt;
-+
-+ /* For each property... */
- for (; prop; prop = prop->next) {
- if (prop->menu != menu)
-+ /*
-+ * Two possibilities:
-+ *
-+ * 1. The property lacks dependencies
-+ * and so isn't location-specific,
-+ * e.g. an 'option'
-+ *
-+ * 2. The property belongs to a symbol
-+ * defined in multiple locations and
-+ * is from some other location. It
-+ * will be handled there in that
-+ * case.
-+ *
-+ * Skip the property.
-+ */
- continue;
-- dep = expr_transform(prop->visible.expr);
-+
-+ /*
-+ * Propagate parent dependencies to the
-+ * property's condition, rewriting and
-+ * simplifying expressions at the same time
-+ */
-+ dep = rewrite_m(prop->visible.expr);
-+ dep = expr_transform(dep);
- dep = expr_alloc_and(expr_copy(basedep), dep);
- dep = expr_eliminate_dups(dep);
- if (menu->sym && menu->sym->type != S_TRISTATE)
- dep = expr_trans_bool(dep);
- prop->visible.expr = dep;
-+
-+ /*
-+ * Handle selects and implies, which modify the
-+ * dependencies of the selected/implied symbol
-+ */
- if (prop->type == P_SELECT) {
- struct symbol *es = prop_get_symbol(prop);
- es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
-@@ -344,34 +406,81 @@ void menu_finalize(struct menu *parent)
- }
- }
- }
-+
-+ if (sym && sym_is_choice(sym))
-+ expr_free(parentdep);
-+
-+ /*
-+ * Recursively process children in the same fashion before
-+ * moving on
-+ */
- for (menu = parent->list; menu; menu = menu->next)
- menu_finalize(menu);
- } else if (sym) {
-+ /*
-+ * Automatic submenu creation. If sym is a symbol and A, B, C,
-+ * ... are consecutive items (symbols, menus, ifs, etc.) that
-+ * all depend on sym, then the following menu structure is
-+ * created:
-+ *
-+ * sym
-+ * +-A
-+ * +-B
-+ * +-C
-+ * ...
-+ *
-+ * This also works recursively, giving the following structure
-+ * if A is a symbol and B depends on A:
-+ *
-+ * sym
-+ * +-A
-+ * | +-B
-+ * +-C
-+ * ...
-+ */
-+
- basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
- basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
- basedep = expr_eliminate_dups(expr_transform(basedep));
-+
-+ /* Examine consecutive elements after sym */
- last_menu = NULL;
- for (menu = parent->next; menu; menu = menu->next) {
- dep = menu->prompt ? menu->prompt->visible.expr : menu->dep;
- if (!expr_contains_symbol(dep, sym))
-+ /* No dependency, quit */
- break;
- if (expr_depends_symbol(dep, sym))
-+ /* Absolute dependency, put in submenu */
- goto next;
-+
-+ /*
-+ * Also consider it a dependency on sym if our
-+ * dependencies contain sym and are a "superset" of
-+ * sym's dependencies, e.g. '(sym || Q) && R' when sym
-+ * depends on R.
-+ *
-+ * Note that 'R' might be from an enclosing menu or if,
-+ * making this a more common case than it might seem.
-+ */
- dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no);
- dep = expr_eliminate_dups(expr_transform(dep));
- dep2 = expr_copy(basedep);
- expr_eliminate_eq(&dep, &dep2);
- expr_free(dep);
- if (!expr_is_yes(dep2)) {
-+ /* Not superset, quit */
- expr_free(dep2);
- break;
- }
-+ /* Superset, put in submenu */
- expr_free(dep2);
- next:
- menu_finalize(menu);
- menu->parent = parent;
- last_menu = menu;
- }
-+ expr_free(basedep);
- if (last_menu) {
- parent->list = parent->next;
- parent->next = last_menu->next;
-@@ -420,6 +529,35 @@ void menu_finalize(struct menu *parent)
- *ep = expr_alloc_one(E_LIST, NULL);
- (*ep)->right.sym = menu->sym;
- }
-+
-+ /*
-+ * This code serves two purposes:
-+ *
-+ * (1) Flattening 'if' blocks, which do not specify a submenu
-+ * and only add dependencies.
-+ *
-+ * (Automatic submenu creation might still create a submenu
-+ * from an 'if' before this code runs.)
-+ *
-+ * (2) "Undoing" any automatic submenus created earlier below
-+ * promptless symbols.
-+ *
-+ * Before:
-+ *
-+ * A
-+ * if ... (or promptless symbol)
-+ * +-B
-+ * +-C
-+ * D
-+ *
-+ * After:
-+ *
-+ * A
-+ * if ... (or promptless symbol)
-+ * B
-+ * C
-+ * D
-+ */
- if (menu->list && (!menu->prompt || !menu->prompt->text)) {
- for (last_menu = menu->list; ; last_menu = last_menu->next) {
- last_menu->parent = parent;
-@@ -444,6 +582,15 @@ void menu_finalize(struct menu *parent)
- sym->flags |= SYMBOL_WARNED;
- }
-
-+ /*
-+ * For non-optional choices, add a reverse dependency (corresponding to
-+ * a select) of '<visibility> && m'. This prevents the user from
-+ * setting the choice mode to 'n' when the choice is visible.
-+ *
-+ * This would also work for non-choice symbols, but only non-optional
-+ * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented
-+ * as a type of symbol.
-+ */
- if (sym && !sym_is_optional(sym) && parent->prompt) {
- sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr,
- expr_alloc_and(parent->prompt->visible.expr,
-@@ -558,7 +705,7 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
- struct menu *submenu[8], *menu, *location = NULL;
- struct jump_key *jump = NULL;
-
-- str_printf(r, _("Prompt: %s\n"), _(prop->text));
-+ str_printf(r, "Prompt: %s\n", prop->text);
- menu = prop->menu->parent;
- for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
- bool accessible = menu_is_visible(menu);
-@@ -591,16 +738,16 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
- }
-
- if (i > 0) {
-- str_printf(r, _(" Location:\n"));
-+ str_printf(r, " Location:\n");
- for (j = 4; --i >= 0; j += 2) {
- menu = submenu[i];
- if (jump && menu == location)
- jump->offset = strlen(r->s);
- str_printf(r, "%*c-> %s", j, ' ',
-- _(menu_get_prompt(menu)));
-+ menu_get_prompt(menu));
- if (menu->sym) {
- str_printf(r, " (%s [=%s])", menu->sym->name ?
-- menu->sym->name : _("<choice>"),
-+ menu->sym->name : "<choice>",
- sym_get_string_value(menu->sym));
- }
- str_append(r, "\n");
-@@ -664,27 +811,27 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
-
- prop = get_symbol_prop(sym);
- if (prop) {
-- str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
-+ str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
- prop->menu->lineno);
- if (!expr_is_yes(prop->visible.expr)) {
-- str_append(r, _(" Depends on: "));
-+ str_append(r, " Depends on: ");
- expr_gstr_print(prop->visible.expr, r);
- str_append(r, "\n");
- }
- }
-
-- get_symbol_props_str(r, sym, P_SELECT, _(" Selects: "));
-+ get_symbol_props_str(r, sym, P_SELECT, " Selects: ");
- if (sym->rev_dep.expr) {
-- str_append(r, _(" Selected by: "));
-- expr_gstr_print(sym->rev_dep.expr, r);
-- str_append(r, "\n");
-+ expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n");
-+ expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n");
-+ expr_gstr_print_revdep(sym->rev_dep.expr, r, no, " Selected by [n]:\n");
- }
-
-- get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: "));
-+ get_symbol_props_str(r, sym, P_IMPLY, " Implies: ");
- if (sym->implied.expr) {
-- str_append(r, _(" Implied by: "));
-- expr_gstr_print(sym->implied.expr, r);
-- str_append(r, "\n");
-+ expr_gstr_print_revdep(sym->implied.expr, r, yes, " Implied by [y]:\n");
-+ expr_gstr_print_revdep(sym->implied.expr, r, mod, " Implied by [m]:\n");
-+ expr_gstr_print_revdep(sym->implied.expr, r, no, " Implied by [n]:\n");
- }
-
- str_append(r, "\n\n");
-@@ -699,7 +846,7 @@ struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
- for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
- get_symbol_str(&res, sym, head);
- if (!i)
-- str_append(&res, _("No matches found.\n"));
-+ str_append(&res, "No matches found.\n");
- return res;
- }
-
-@@ -714,7 +861,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
- str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
- help_text = menu_get_help(menu);
- }
-- str_printf(help, "%s\n", _(help_text));
-+ str_printf(help, "%s\n", help_text);
- if (sym)
- get_symbol_str(help, sym, NULL);
- }
-diff --git a/carl9170fw/config/preprocess.c b/carl9170fw/config/preprocess.c
-new file mode 100644
-index 0000000..592dfbf
---- /dev/null
-+++ b/carl9170fw/config/preprocess.c
-@@ -0,0 +1,573 @@
-+// SPDX-License-Identifier: GPL-2.0
-+//
-+// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
-+
-+#include <ctype.h>
-+#include <stdarg.h>
-+#include <stdbool.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+
-+#include "list.h"
-+#include "lkc.h"
-+
-+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-+
-+static char *expand_string_with_args(const char *in, int argc, char *argv[]);
-+
-+static void __attribute__((noreturn)) pperror(const char *format, ...)
-+{
-+ va_list ap;
-+
-+ fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
-+ va_start(ap, format);
-+ vfprintf(stderr, format, ap);
-+ va_end(ap);
-+ fprintf(stderr, "\n");
-+
-+ exit(1);
-+}
-+
-+/*
-+ * Environment variables
-+ */
-+static LIST_HEAD(env_list);
-+
-+struct env {
-+ char *name;
-+ char *value;
-+ struct list_head node;
-+};
-+
-+static void env_add(const char *name, const char *value)
-+{
-+ struct env *e;
-+
-+ e = xmalloc(sizeof(*e));
-+ e->name = xstrdup(name);
-+ e->value = xstrdup(value);
-+
-+ list_add_tail(&e->node, &env_list);
-+}
-+
-+static void env_del(struct env *e)
-+{
-+ list_del(&e->node);
-+ free(e->name);
-+ free(e->value);
-+ free(e);
-+}
-+
-+/* The returned pointer must be freed when done */
-+static char *env_expand(const char *name)
-+{
-+ struct env *e;
-+ const char *value;
-+
-+ if (!*name)
-+ return NULL;
-+
-+ list_for_each_entry(e, &env_list, node) {
-+ if (!strcmp(name, e->name))
-+ return xstrdup(e->value);
-+ }
-+
-+ value = getenv(name);
-+ if (!value)
-+ return NULL;
-+
-+ /*
-+ * We need to remember all referenced environment variables.
-+ * They will be written out to include/config/auto.conf.cmd
-+ */
-+ env_add(name, value);
-+
-+ return xstrdup(value);
-+}
-+
-+void env_write_dep(FILE *f, const char *autoconfig_name)
-+{
-+ struct env *e, *tmp;
-+
-+ list_for_each_entry_safe(e, tmp, &env_list, node) {
-+ fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
-+ fprintf(f, "%s: FORCE\n", autoconfig_name);
-+ fprintf(f, "endif\n");
-+ env_del(e);
-+ }
-+}
-+
-+/*
-+ * Built-in functions
-+ */
-+struct function {
-+ const char *name;
-+ unsigned int min_args;
-+ unsigned int max_args;
-+ char *(*func)(int argc, char *argv[]);
-+};
-+
-+static char *do_error_if(int argc, char *argv[])
-+{
-+ if (!strcmp(argv[0], "y"))
-+ pperror("%s", argv[1]);
-+
-+ return NULL;
-+}
-+
-+static char *do_filename(int argc, char *argv[])
-+{
-+ return xstrdup(current_file->name);
-+}
-+
-+static char *do_info(int argc, char *argv[])
-+{
-+ printf("%s\n", argv[0]);
-+
-+ return xstrdup("");
-+}
-+
-+static char *do_lineno(int argc, char *argv[])
-+{
-+ char buf[16];
-+
-+ sprintf(buf, "%d", yylineno);
-+
-+ return xstrdup(buf);
-+}
-+
-+static char *do_shell(int argc, char *argv[])
-+{
-+ FILE *p;
-+ char buf[256];
-+ char *cmd;
-+ size_t nread;
-+ int i;
-+
-+ cmd = argv[0];
-+
-+ p = popen(cmd, "r");
-+ if (!p) {
-+ perror(cmd);
-+ exit(1);
-+ }
-+
-+ nread = fread(buf, 1, sizeof(buf), p);
-+ if (nread == sizeof(buf))
-+ nread--;
-+
-+ /* remove trailing new lines */
-+ while (nread > 0 && buf[nread - 1] == '\n')
-+ nread--;
-+
-+ buf[nread] = 0;
-+
-+ /* replace a new line with a space */
-+ for (i = 0; i < nread; i++) {
-+ if (buf[i] == '\n')
-+ buf[i] = ' ';
-+ }
-+
-+ if (pclose(p) == -1) {
-+ perror(cmd);
-+ exit(1);
-+ }
-+
-+ return xstrdup(buf);
-+}
-+
-+static char *do_warning_if(int argc, char *argv[])
-+{
-+ if (!strcmp(argv[0], "y"))
-+ fprintf(stderr, "%s:%d: %s\n",
-+ current_file->name, yylineno, argv[1]);
-+
-+ return xstrdup("");
-+}
-+
-+static const struct function function_table[] = {
-+ /* Name MIN MAX Function */
-+ { "error-if", 2, 2, do_error_if },
-+ { "filename", 0, 0, do_filename },
-+ { "info", 1, 1, do_info },
-+ { "lineno", 0, 0, do_lineno },
-+ { "shell", 1, 1, do_shell },
-+ { "warning-if", 2, 2, do_warning_if },
-+};
-+
-+#define FUNCTION_MAX_ARGS 16
-+
-+static char *function_expand(const char *name, int argc, char *argv[])
-+{
-+ const struct function *f;
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(function_table); i++) {
-+ f = &function_table[i];
-+ if (strcmp(f->name, name))
-+ continue;
-+
-+ if (argc < f->min_args)
-+ pperror("too few function arguments passed to '%s'",
-+ name);
-+
-+ if (argc > f->max_args)
-+ pperror("too many function arguments passed to '%s'",
-+ name);
-+
-+ return f->func(argc, argv);
-+ }
-+
-+ return NULL;
-+}
-+
-+/*
-+ * Variables (and user-defined functions)
-+ */
-+static LIST_HEAD(variable_list);
-+
-+struct variable {
-+ char *name;
-+ char *value;
-+ enum variable_flavor flavor;
-+ int exp_count;
-+ struct list_head node;
-+};
-+
-+static struct variable *variable_lookup(const char *name)
-+{
-+ struct variable *v;
-+
-+ list_for_each_entry(v, &variable_list, node) {
-+ if (!strcmp(name, v->name))
-+ return v;
-+ }
-+
-+ return NULL;
-+}
-+
-+static char *variable_expand(const char *name, int argc, char *argv[])
-+{
-+ struct variable *v;
-+ char *res;
-+
-+ v = variable_lookup(name);
-+ if (!v)
-+ return NULL;
-+
-+ if (argc == 0 && v->exp_count)
-+ pperror("Recursive variable '%s' references itself (eventually)",
-+ name);
-+
-+ if (v->exp_count > 1000)
-+ pperror("Too deep recursive expansion");
-+
-+ v->exp_count++;
-+
-+ if (v->flavor == VAR_RECURSIVE)
-+ res = expand_string_with_args(v->value, argc, argv);
-+ else
-+ res = xstrdup(v->value);
-+
-+ v->exp_count--;
-+
-+ return res;
-+}
-+
-+void variable_add(const char *name, const char *value,
-+ enum variable_flavor flavor)
-+{
-+ struct variable *v;
-+ char *new_value;
-+ bool append = false;
-+
-+ v = variable_lookup(name);
-+ if (v) {
-+ /* For defined variables, += inherits the existing flavor */
-+ if (flavor == VAR_APPEND) {
-+ flavor = v->flavor;
-+ append = true;
-+ } else {
-+ free(v->value);
-+ }
-+ } else {
-+ /* For undefined variables, += assumes the recursive flavor */
-+ if (flavor == VAR_APPEND)
-+ flavor = VAR_RECURSIVE;
-+
-+ v = xmalloc(sizeof(*v));
-+ v->name = xstrdup(name);
-+ v->exp_count = 0;
-+ list_add_tail(&v->node, &variable_list);
-+ }
-+
-+ v->flavor = flavor;
-+
-+ if (flavor == VAR_SIMPLE)
-+ new_value = expand_string(value);
-+ else
-+ new_value = xstrdup(value);
-+
-+ if (append) {
-+ v->value = xrealloc(v->value,
-+ strlen(v->value) + strlen(new_value) + 2);
-+ strcat(v->value, " ");
-+ strcat(v->value, new_value);
-+ free(new_value);
-+ } else {
-+ v->value = new_value;
-+ }
-+}
-+
-+static void variable_del(struct variable *v)
-+{
-+ list_del(&v->node);
-+ free(v->name);
-+ free(v->value);
-+ free(v);
-+}
-+
-+void variable_all_del(void)
-+{
-+ struct variable *v, *tmp;
-+
-+ list_for_each_entry_safe(v, tmp, &variable_list, node)
-+ variable_del(v);
-+}
-+
-+/*
-+ * Evaluate a clause with arguments. argc/argv are arguments from the upper
-+ * function call.
-+ *
-+ * Returned string must be freed when done
-+ */
-+static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
-+{
-+ char *tmp, *name, *res, *endptr, *prev, *p;
-+ int new_argc = 0;
-+ char *new_argv[FUNCTION_MAX_ARGS];
-+ int nest = 0;
-+ int i;
-+ unsigned long n;
-+
-+ tmp = xstrndup(str, len);
-+
-+ /*
-+ * If variable name is '1', '2', etc. It is generally an argument
-+ * from a user-function call (i.e. local-scope variable). If not
-+ * available, then look-up global-scope variables.
-+ */
-+ n = strtoul(tmp, &endptr, 10);
-+ if (!*endptr && n > 0 && n <= argc) {
-+ res = xstrdup(argv[n - 1]);
-+ goto free_tmp;
-+ }
-+
-+ prev = p = tmp;
-+
-+ /*
-+ * Split into tokens
-+ * The function name and arguments are separated by a comma.
-+ * For example, if the function call is like this:
-+ * $(foo,$(x),$(y))
-+ *
-+ * The input string for this helper should be:
-+ * foo,$(x),$(y)
-+ *
-+ * and split into:
-+ * new_argv[0] = 'foo'
-+ * new_argv[1] = '$(x)'
-+ * new_argv[2] = '$(y)'
-+ */
-+ while (*p) {
-+ if (nest == 0 && *p == ',') {
-+ *p = 0;
-+ if (new_argc >= FUNCTION_MAX_ARGS)
-+ pperror("too many function arguments");
-+ new_argv[new_argc++] = prev;
-+ prev = p + 1;
-+ } else if (*p == '(') {
-+ nest++;
-+ } else if (*p == ')') {
-+ nest--;
-+ }
-+
-+ p++;
-+ }
-+ new_argv[new_argc++] = prev;
-+
-+ /*
-+ * Shift arguments
-+ * new_argv[0] represents a function name or a variable name. Put it
-+ * into 'name', then shift the rest of the arguments. This simplifies
-+ * 'const' handling.
-+ */
-+ name = expand_string_with_args(new_argv[0], argc, argv);
-+ new_argc--;
-+ for (i = 0; i < new_argc; i++)
-+ new_argv[i] = expand_string_with_args(new_argv[i + 1],
-+ argc, argv);
-+
-+ /* Search for variables */
-+ res = variable_expand(name, new_argc, new_argv);
-+ if (res)
-+ goto free;
-+
-+ /* Look for built-in functions */
-+ res = function_expand(name, new_argc, new_argv);
-+ if (res)
-+ goto free;
-+
-+ /* Last, try environment variable */
-+ if (new_argc == 0) {
-+ res = env_expand(name);
-+ if (res)
-+ goto free;
-+ }
-+
-+ res = xstrdup("");
-+free:
-+ for (i = 0; i < new_argc; i++)
-+ free(new_argv[i]);
-+ free(name);
-+free_tmp:
-+ free(tmp);
-+
-+ return res;
-+}
-+
-+/*
-+ * Expand a string that follows '$'
-+ *
-+ * For example, if the input string is
-+ * ($(FOO)$($(BAR)))$(BAZ)
-+ * this helper evaluates
-+ * $($(FOO)$($(BAR)))
-+ * and returns a new string containing the expansion (note that the string is
-+ * recursively expanded), also advancing 'str' to point to the next character
-+ * after the corresponding closing parenthesis, in this case, *str will be
-+ * $(BAR)
-+ */
-+static char *expand_dollar_with_args(const char **str, int argc, char *argv[])
-+{
-+ const char *p = *str;
-+ const char *q;
-+ int nest = 0;
-+
-+ /*
-+ * In Kconfig, variable/function references always start with "$(".
-+ * Neither single-letter variables as in $A nor curly braces as in ${CC}
-+ * are supported. '$' not followed by '(' loses its special meaning.
-+ */
-+ if (*p != '(') {
-+ *str = p;
-+ return xstrdup("$");
-+ }
-+
-+ p++;
-+ q = p;
-+ while (*q) {
-+ if (*q == '(') {
-+ nest++;
-+ } else if (*q == ')') {
-+ if (nest-- == 0)
-+ break;
-+ }
-+ q++;
-+ }
-+
-+ if (!*q)
-+ pperror("unterminated reference to '%s': missing ')'", p);
-+
-+ /* Advance 'str' to after the expanded initial portion of the string */
-+ *str = q + 1;
-+
-+ return eval_clause(p, q - p, argc, argv);
-+}
-+
-+char *expand_dollar(const char **str)
-+{
-+ return expand_dollar_with_args(str, 0, NULL);
-+}
-+
-+static char *__expand_string(const char **str, bool (*is_end)(char c),
-+ int argc, char *argv[])
-+{
-+ const char *in, *p;
-+ char *expansion, *out;
-+ size_t in_len, out_len;
-+
-+ out = xmalloc(1);
-+ *out = 0;
-+ out_len = 1;
-+
-+ p = in = *str;
-+
-+ while (1) {
-+ if (*p == '$') {
-+ in_len = p - in;
-+ p++;
-+ expansion = expand_dollar_with_args(&p, argc, argv);
-+ out_len += in_len + strlen(expansion);
-+ out = xrealloc(out, out_len);
-+ strncat(out, in, in_len);
-+ strcat(out, expansion);
-+ free(expansion);
-+ in = p;
-+ continue;
-+ }
-+
-+ if (is_end(*p))
-+ break;
-+
-+ p++;
-+ }
-+
-+ in_len = p - in;
-+ out_len += in_len;
-+ out = xrealloc(out, out_len);
-+ strncat(out, in, in_len);
-+
-+ /* Advance 'str' to the end character */
-+ *str = p;
-+
-+ return out;
-+}
-+
-+static bool is_end_of_str(char c)
-+{
-+ return !c;
-+}
-+
-+/*
-+ * Expand variables and functions in the given string. Undefined variables
-+ * expand to an empty string.
-+ * The returned string must be freed when done.
-+ */
-+static char *expand_string_with_args(const char *in, int argc, char *argv[])
-+{
-+ return __expand_string(&in, is_end_of_str, argc, argv);
-+}
-+
-+char *expand_string(const char *in)
-+{
-+ return expand_string_with_args(in, 0, NULL);
-+}
-+
-+static bool is_end_of_token(char c)
-+{
-+ return !(isalnum(c) || c == '_' || c == '-');
-+}
-+
-+/*
-+ * Expand variables in a token. The parsing stops when a token separater
-+ * (in most cases, it is a whitespace) is encountered. 'str' is updated to
-+ * point to the next character.
-+ *
-+ * The returned string must be freed when done.
-+ */
-+char *expand_one_token(const char **str)
-+{
-+ return __expand_string(str, is_end_of_token, 0, NULL);
-+}
-diff --git a/carl9170fw/config/symbol.c b/carl9170fw/config/symbol.c
-index 3c8bd9b..1f9266d 100644
---- a/carl9170fw/config/symbol.c
-+++ b/carl9170fw/config/symbol.c
-@@ -1,6 +1,6 @@
-+// SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-
- #include <ctype.h>
-@@ -33,33 +33,6 @@ struct symbol *sym_defconfig_list;
- struct symbol *modules_sym;
- tristate modules_val;
-
--struct expr *sym_env_list;
--
--static void sym_add_default(struct symbol *sym, const char *def)
--{
-- struct property *prop = prop_alloc(P_DEFAULT, sym);
--
-- prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST));
--}
--
--void sym_init(void)
--{
-- struct symbol *sym;
-- struct utsname uts;
-- static bool inited = false;
--
-- if (inited)
-- return;
-- inited = true;
--
-- uname(&uts);
--
-- sym = sym_lookup("UNAME_RELEASE", 0);
-- sym->type = S_STRING;
-- sym->flags |= SYMBOL_AUTO;
-- sym_add_default(sym, uts.release);
--}
--
- enum symbol_type sym_get_type(struct symbol *sym)
- {
- enum symbol_type type = sym->type;
-@@ -77,7 +50,7 @@ const char *sym_type_name(enum symbol_type type)
- {
- switch (type) {
- case S_BOOLEAN:
-- return "boolean";
-+ return "bool";
- case S_TRISTATE:
- return "tristate";
- case S_INT:
-@@ -88,8 +61,6 @@ const char *sym_type_name(enum symbol_type type)
- return "string";
- case S_UNKNOWN:
- return "unknown";
-- case S_OTHER:
-- break;
- }
- return "???";
- }
-@@ -103,15 +74,6 @@ struct property *sym_get_choice_prop(struct symbol *sym)
- return NULL;
- }
-
--struct property *sym_get_env_prop(struct symbol *sym)
--{
-- struct property *prop;
--
-- for_all_properties(sym, prop, P_ENV)
-- return prop;
-- return NULL;
--}
--
- static struct property *sym_get_default_prop(struct symbol *sym)
- {
- struct property *prop;
-@@ -124,7 +86,7 @@ static struct property *sym_get_default_prop(struct symbol *sym)
- return NULL;
- }
-
--static struct property *sym_get_range_prop(struct symbol *sym)
-+struct property *sym_get_range_prop(struct symbol *sym)
- {
- struct property *prop;
-
-@@ -183,7 +145,7 @@ static void sym_validate_range(struct symbol *sym)
- sprintf(str, "%lld", val2);
- else
- sprintf(str, "0x%llx", val2);
-- sym->curr.val = strdup(str);
-+ sym->curr.val = xstrdup(str);
- }
-
- static void sym_set_changed(struct symbol *sym)
-@@ -243,7 +205,7 @@ static void sym_calc_visibility(struct symbol *sym)
- tri = yes;
- if (sym->dir_dep.expr)
- tri = expr_calc_value(sym->dir_dep.expr);
-- if (tri == mod)
-+ if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
- tri = yes;
- if (sym->dir_dep.tri != tri) {
- sym->dir_dep.tri = tri;
-@@ -333,6 +295,27 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
- return def_sym;
- }
-
-+static void sym_warn_unmet_dep(struct symbol *sym)
-+{
-+ struct gstr gs = str_new();
-+
-+ str_printf(&gs,
-+ "\nWARNING: unmet direct dependencies detected for %s\n",
-+ sym->name);
-+ str_printf(&gs,
-+ " Depends on [%c]: ",
-+ sym->dir_dep.tri == mod ? 'm' : 'n');
-+ expr_gstr_print(sym->dir_dep.expr, &gs);
-+ str_printf(&gs, "\n");
-+
-+ expr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes,
-+ " Selected by [y]:\n");
-+ expr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod,
-+ " Selected by [m]:\n");
-+
-+ fputs(str_get(&gs), stderr);
-+}
-+
- void sym_calc_value(struct symbol *sym)
- {
- struct symbol_value newval, oldval;
-@@ -371,11 +354,13 @@ void sym_calc_value(struct symbol *sym)
- sym->curr.tri = no;
- return;
- }
-- if (!sym_is_choice_value(sym))
-- sym->flags &= ~SYMBOL_WRITE;
-+ sym->flags &= ~SYMBOL_WRITE;
-
- sym_calc_visibility(sym);
-
-+ if (sym->visible != no)
-+ sym->flags |= SYMBOL_WRITE;
-+
- /* set default if recursively called */
- sym->curr = newval;
-
-@@ -390,7 +375,6 @@ void sym_calc_value(struct symbol *sym)
- /* if the symbol is visible use the user value
- * if available, otherwise try the default value
- */
-- sym->flags |= SYMBOL_WRITE;
- if (sym_has_value(sym)) {
- newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
- sym->visible);
-@@ -402,9 +386,10 @@ void sym_calc_value(struct symbol *sym)
- if (!sym_is_choice(sym)) {
- prop = sym_get_default_prop(sym);
- if (prop) {
-- sym->flags |= SYMBOL_WRITE;
- newval.tri = EXPR_AND(expr_calc_value(prop->expr),
- prop->visible.tri);
-+ if (newval.tri != no)
-+ sym->flags |= SYMBOL_WRITE;
- }
- if (sym->implied.tri != no) {
- sym->flags |= SYMBOL_WRITE;
-@@ -412,18 +397,8 @@ void sym_calc_value(struct symbol *sym)
- }
- }
- calc_newval:
-- if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
-- struct expr *e;
-- e = expr_simplify_unmet_dep(sym->rev_dep.expr,
-- sym->dir_dep.expr);
-- fprintf(stderr, "warning: (");
-- expr_fprint(e, stderr);
-- fprintf(stderr, ") selects %s which has unmet direct dependencies (",
-- sym->name);
-- expr_fprint(sym->dir_dep.expr, stderr);
-- fprintf(stderr, ")\n");
-- expr_free(e);
-- }
-+ if (sym->dir_dep.tri < sym->rev_dep.tri)
-+ sym_warn_unmet_dep(sym);
- newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
- }
- if (newval.tri == mod &&
-@@ -433,12 +408,9 @@ void sym_calc_value(struct symbol *sym)
- case S_STRING:
- case S_HEX:
- case S_INT:
-- if (sym->visible != no) {
-- sym->flags |= SYMBOL_WRITE;
-- if (sym_has_value(sym)) {
-- newval.val = sym->def[S_DEF_USER].val;
-- break;
-- }
-+ if (sym->visible != no && sym_has_value(sym)) {
-+ newval.val = sym->def[S_DEF_USER].val;
-+ break;
- }
- prop = sym_get_default_prop(sym);
- if (prop) {
-@@ -480,7 +452,7 @@ void sym_calc_value(struct symbol *sym)
- }
- }
-
-- if (sym->flags & SYMBOL_AUTO)
-+ if (sym->flags & SYMBOL_NO_WRITE)
- sym->flags &= ~SYMBOL_WRITE;
-
- if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
-@@ -783,7 +755,6 @@ const char *sym_get_string_default(struct symbol *sym)
- return str;
- case S_STRING:
- return str;
-- case S_OTHER:
- case S_UNKNOWN:
- break;
- }
-@@ -851,7 +822,7 @@ struct symbol *sym_lookup(const char *name, int flags)
- : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
- return symbol;
- }
-- new_name = strdup(name);
-+ new_name = xstrdup(name);
- } else {
- new_name = NULL;
- hash = 0;
-@@ -896,55 +867,6 @@ struct symbol *sym_find(const char *name)
- return symbol;
- }
-
--/*
-- * Expand symbol's names embedded in the string given in argument. Symbols'
-- * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
-- * the empty string.
-- */
--const char *sym_expand_string_value(const char *in)
--{
-- const char *src;
-- char *res;
-- size_t reslen;
--
-- reslen = strlen(in) + 1;
-- res = xmalloc(reslen);
-- res[0] = '\0';
--
-- while ((src = strchr(in, '$'))) {
-- char *p, name[SYMBOL_MAXLENGTH];
-- const char *symval = "";
-- struct symbol *sym;
-- size_t newlen;
--
-- strncat(res, in, src - in);
-- src++;
--
-- p = name;
-- while (isalnum(*src) || *src == '_')
-- *p++ = *src++;
-- *p = '\0';
--
-- sym = sym_find(name);
-- if (sym != NULL) {
-- sym_calc_value(sym);
-- symval = sym_get_string_value(sym);
-- }
--
-- newlen = strlen(res) + strlen(symval) + strlen(src) + 1;
-- if (newlen > reslen) {
-- reslen = newlen;
-- res = realloc(res, reslen);
-- }
--
-- strcat(res, symval);
-- in = src;
-- }
-- strcat(res, in);
--
-- return res;
--}
--
- const char *sym_escape_string_value(const char *in)
- {
- const char *p;
-@@ -1086,7 +1008,7 @@ static struct dep_stack {
- struct dep_stack *prev, *next;
- struct symbol *sym;
- struct property *prop;
-- struct expr *expr;
-+ struct expr **expr;
- } *check_top;
-
- static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
-@@ -1150,37 +1072,52 @@ static void sym_check_print_recursive(struct symbol *last_sym)
- if (stack->sym == last_sym)
- fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
- prop->file->name, prop->lineno);
-- fprintf(stderr, "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n");
-- fprintf(stderr, "subsection \"Kconfig recursive dependency limitations\"\n");
-- if (stack->expr) {
-- fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
-- prop->file->name, prop->lineno,
-+
-+ if (sym_is_choice(sym)) {
-+ fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
-+ menu->file->name, menu->lineno,
- sym->name ? sym->name : "<choice>",
-- prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
-- } else if (stack->prop) {
-+ } else if (sym_is_choice_value(sym)) {
-+ fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
-+ menu->file->name, menu->lineno,
-+ sym->name ? sym->name : "<choice>",
-+ next_sym->name ? next_sym->name : "<choice>");
-+ } else if (stack->expr == &sym->dir_dep.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
-- } else if (sym_is_choice(sym)) {
-- fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
-- menu->file->name, menu->lineno,
-+ } else if (stack->expr == &sym->rev_dep.expr) {
-+ fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
-+ prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
-- } else if (sym_is_choice_value(sym)) {
-- fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
-- menu->file->name, menu->lineno,
-+ } else if (stack->expr == &sym->implied.expr) {
-+ fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
-+ prop->file->name, prop->lineno,
-+ sym->name ? sym->name : "<choice>",
-+ next_sym->name ? next_sym->name : "<choice>");
-+ } else if (stack->expr) {
-+ fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
-+ prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
-+ prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
- } else {
-- fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
-+ fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
-+ prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
- }
- }
-
-+ fprintf(stderr,
-+ "For a resolution refer to Documentation/kbuild/kconfig-language.txt\n"
-+ "subsection \"Kconfig recursive dependency limitations\"\n"
-+ "\n");
-+
- if (check_top == &cv_stack)
- dep_stack_remove();
- }
-@@ -1215,7 +1152,7 @@ static struct symbol *sym_check_expr_deps(struct expr *e)
- default:
- break;
- }
-- printf("Oops! How to check %d?\n", e->type);
-+ fprintf(stderr, "Oops! How to check %d?\n", e->type);
- return NULL;
- }
-
-@@ -1228,12 +1165,26 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
-
- dep_stack_insert(&stack, sym);
-
-+ stack.expr = &sym->dir_dep.expr;
-+ sym2 = sym_check_expr_deps(sym->dir_dep.expr);
-+ if (sym2)
-+ goto out;
-+
-+ stack.expr = &sym->rev_dep.expr;
- sym2 = sym_check_expr_deps(sym->rev_dep.expr);
- if (sym2)
- goto out;
-
-+ stack.expr = &sym->implied.expr;
-+ sym2 = sym_check_expr_deps(sym->implied.expr);
-+ if (sym2)
-+ goto out;
-+
-+ stack.expr = NULL;
-+
- for (prop = sym->prop; prop; prop = prop->next) {
-- if (prop->type == P_CHOICE || prop->type == P_SELECT)
-+ if (prop->type == P_CHOICE || prop->type == P_SELECT ||
-+ prop->type == P_IMPLY)
- continue;
- stack.prop = prop;
- sym2 = sym_check_expr_deps(prop->visible.expr);
-@@ -1241,7 +1192,7 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
- break;
- if (prop->type != P_DEFAULT || sym_is_choice(sym))
- continue;
-- stack.expr = prop->expr;
-+ stack.expr = &prop->expr;
- sym2 = sym_check_expr_deps(prop->expr);
- if (sym2)
- break;
-@@ -1319,9 +1270,6 @@ struct symbol *sym_check_deps(struct symbol *sym)
- sym->flags &= ~SYMBOL_CHECK;
- }
-
-- if (sym2 && sym2 == sym)
-- sym2 = NULL;
--
- return sym2;
- }
-
-@@ -1360,8 +1308,6 @@ const char *prop_get_type_name(enum prop_type type)
- switch (type) {
- case P_PROMPT:
- return "prompt";
-- case P_ENV:
-- return "env";
- case P_COMMENT:
- return "comment";
- case P_MENU:
-@@ -1383,32 +1329,3 @@ const char *prop_get_type_name(enum prop_type type)
- }
- return "unknown";
- }
--
--static void prop_add_env(const char *env)
--{
-- struct symbol *sym, *sym2;
-- struct property *prop;
-- char *p;
--
-- sym = current_entry->sym;
-- sym->flags |= SYMBOL_AUTO;
-- for_all_properties(sym, prop, P_ENV) {
-- sym2 = prop_get_symbol(prop);
-- if (strcmp(sym2->name, env))
-- menu_warn(current_entry, "redefining environment symbol from %s",
-- sym2->name);
-- return;
-- }
--
-- prop = prop_alloc(P_ENV, sym);
-- prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST));
--
-- sym_env_list = expr_alloc_one(E_LIST, sym_env_list);
-- sym_env_list->right.sym = sym;
--
-- p = getenv(env);
-- if (p)
-- sym_add_default(sym, p);
-- else
-- menu_warn(current_entry, "environment variable %s undefined", env);
--}
-diff --git a/carl9170fw/config/util.c b/carl9170fw/config/util.c
-index 0e76042..2958539 100644
---- a/carl9170fw/config/util.c
-+++ b/carl9170fw/config/util.c
-@@ -1,8 +1,7 @@
-+// SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
- * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
-- *
-- * Released under the terms of the GNU GPL v2.0.
- */
-
- #include <stdarg.h>
-@@ -14,69 +13,21 @@
- struct file *file_lookup(const char *name)
- {
- struct file *file;
-- const char *file_name = sym_expand_string_value(name);
-
- for (file = file_list; file; file = file->next) {
- if (!strcmp(name, file->name)) {
-- free((void *)file_name);
- return file;
- }
- }
-
- file = xmalloc(sizeof(*file));
- memset(file, 0, sizeof(*file));
-- file->name = file_name;
-+ file->name = xstrdup(name);
- file->next = file_list;
- file_list = file;
- return file;
- }
-
--/* write a dependency file as used by kbuild to track dependencies */
--int file_write_dep(const char *name)
--{
-- struct symbol *sym, *env_sym;
-- struct expr *e;
-- struct file *file;
-- FILE *out;
--
-- if (!name)
-- name = ".kconfig.d";
-- out = fopen("..config.tmp", "w");
-- if (!out)
-- return 1;
-- fprintf(out, "deps_config := \\\n");
-- for (file = file_list; file; file = file->next) {
-- if (file->next)
-- fprintf(out, "\t%s \\\n", file->name);
-- else
-- fprintf(out, "\t%s\n", file->name);
-- }
-- fprintf(out, "\n%s: \\\n"
-- "\t$(deps_config)\n\n", conf_get_autoconfig_name());
--
-- expr_list_for_each_sym(sym_env_list, e, sym) {
-- struct property *prop;
-- const char *value;
--
-- prop = sym_get_env_prop(sym);
-- env_sym = prop_get_symbol(prop);
-- if (!env_sym)
-- continue;
-- value = getenv(env_sym->name);
-- if (!value)
-- value = "";
-- fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value);
-- fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name());
-- fprintf(out, "endif\n");
-- }
--
-- fprintf(out, "\n$(deps_config): ;\n");
-- fclose(out);
-- rename("..config.tmp", name);
-- return 0;
--}
--
--
- /* Allocate initial growable string */
- struct gstr str_new(void)
- {
-@@ -104,7 +55,7 @@ void str_append(struct gstr *gs, const char *s)
- if (s) {
- l = strlen(gs->s) + strlen(s) + 1;
- if (l > gs->len) {
-- gs->s = realloc(gs->s, l);
-+ gs->s = xrealloc(gs->s, l);
- gs->len = l;
- }
- strcat(gs->s, s);
-@@ -145,3 +96,34 @@ void *xcalloc(size_t nmemb, size_t size)
- fprintf(stderr, "Out of memory.\n");
- exit(1);
- }
-+
-+void *xrealloc(void *p, size_t size)
-+{
-+ p = realloc(p, size);
-+ if (p)
-+ return p;
-+ fprintf(stderr, "Out of memory.\n");
-+ exit(1);
-+}
-+
-+char *xstrdup(const char *s)
-+{
-+ char *p;
-+
-+ p = strdup(s);
-+ if (p)
-+ return p;
-+ fprintf(stderr, "Out of memory.\n");
-+ exit(1);
-+}
-+
-+char *xstrndup(const char *s, size_t n)
-+{
-+ char *p;
-+
-+ p = strndup(s, n);
-+ if (p)
-+ return p;
-+ fprintf(stderr, "Out of memory.\n");
-+ exit(1);
-+}
-diff --git a/carl9170fw/config/zconf.l b/carl9170fw/config/zconf.l
-index 9720530..c52cce8 100644
---- a/carl9170fw/config/zconf.l
-+++ b/carl9170fw/config/zconf.l
-@@ -1,13 +1,13 @@
--%option nostdinit noyywrap never-interactive full ecs
--%option 8bit nodefault perf-report perf-report
--%option noinput
--%x COMMAND HELP STRING PARAM
--%{
-+/* SPDX-License-Identifier: GPL-2.0 */
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-+%option nostdinit noyywrap never-interactive full ecs
-+%option 8bit nodefault yylineno
-+%x ASSIGN_VAL HELP STRING
-+%{
-
-+#include <assert.h>
- #include <limits.h>
- #include <stdio.h>
- #include <stdlib.h>
-@@ -15,6 +15,9 @@
- #include <unistd.h>
-
- #include "lkc.h"
-+#include "zconf.tab.h"
-+
-+#define YY_DECL static int yylex1(void)
-
- #define START_STRSIZE 16
-
-@@ -23,6 +26,8 @@ static struct {
- int lineno;
- } current_pos;
-
-+static int prev_prev_token = T_EOL;
-+static int prev_token = T_EOL;
- static char *text;
- static int text_size, text_asize;
-
-@@ -35,6 +40,8 @@ struct buffer *current_buf;
-
- static int last_ts, first_ts;
-
-+static char *expand_token(const char *in, size_t n);
-+static void append_expanded_string(const char *in);
- static void zconf_endhelp(void);
- static void zconf_endfile(void);
-
-@@ -52,7 +59,7 @@ static void append_string(const char *str, int size)
- if (new_size > text_asize) {
- new_size += START_STRSIZE - 1;
- new_size &= -START_STRSIZE;
-- text = realloc(text, new_size);
-+ text = xrealloc(text, new_size);
- text_asize = new_size;
- }
- memcpy(text + text_size, str, size);
-@@ -71,7 +78,7 @@ static void warn_ignored_character(char chr)
- {
- fprintf(stderr,
- "%s:%d:warning: ignoring unsupported character '%c'\n",
-- zconf_curname(), zconf_lineno(), chr);
-+ current_file->name, yylineno, chr);
- }
- %}
-
-@@ -81,116 +88,113 @@ n [A-Za-z0-9_-]
- int str = 0;
- int ts, i;
-
--[ \t]*#.*\n |
--[ \t]*\n {
-- current_file->lineno++;
-- return T_EOL;
--}
--[ \t]*#.*
--
--
--[ \t]+ {
-- BEGIN(COMMAND);
--}
--
--. {
-- unput(yytext[0]);
-- BEGIN(COMMAND);
--}
--
--
--<COMMAND>{
-- {n}+ {
-- const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
-- BEGIN(PARAM);
-- current_pos.file = current_file;
-- current_pos.lineno = current_file->lineno;
-- if (id && id->flags & TF_COMMAND) {
-- zconflval.id = id;
-- return id->token;
-- }
-- alloc_string(yytext, yyleng);
-- zconflval.string = text;
-- return T_WORD;
-- }
-- . warn_ignored_character(*yytext);
-- \n {
-- BEGIN(INITIAL);
-- current_file->lineno++;
-- return T_EOL;
-- }
--}
-+#.* /* ignore comment */
-+[ \t]* /* whitespaces */
-+\\\n /* escaped new line */
-+\n return T_EOL;
-+"allnoconfig_y" return T_ALLNOCONFIG_Y;
-+"bool" return T_BOOL;
-+"choice" return T_CHOICE;
-+"comment" return T_COMMENT;
-+"config" return T_CONFIG;
-+"def_bool" return T_DEF_BOOL;
-+"def_tristate" return T_DEF_TRISTATE;
-+"default" return T_DEFAULT;
-+"defconfig_list" return T_DEFCONFIG_LIST;
-+"depends" return T_DEPENDS;
-+"endchoice" return T_ENDCHOICE;
-+"endif" return T_ENDIF;
-+"endmenu" return T_ENDMENU;
-+"help"|"---help---" return T_HELP;
-+"hex" return T_HEX;
-+"if" return T_IF;
-+"imply" return T_IMPLY;
-+"int" return T_INT;
-+"mainmenu" return T_MAINMENU;
-+"menu" return T_MENU;
-+"menuconfig" return T_MENUCONFIG;
-+"modules" return T_MODULES;
-+"on" return T_ON;
-+"option" return T_OPTION;
-+"optional" return T_OPTIONAL;
-+"prompt" return T_PROMPT;
-+"range" return T_RANGE;
-+"select" return T_SELECT;
-+"source" return T_SOURCE;
-+"string" return T_STRING;
-+"tristate" return T_TRISTATE;
-+"visible" return T_VISIBLE;
-+"||" return T_OR;
-+"&&" return T_AND;
-+"=" return T_EQUAL;
-+"!=" return T_UNEQUAL;
-+"<" return T_LESS;
-+"<=" return T_LESS_EQUAL;
-+">" return T_GREATER;
-+">=" return T_GREATER_EQUAL;
-+"!" return T_NOT;
-+"(" return T_OPEN_PAREN;
-+")" return T_CLOSE_PAREN;
-+":=" return T_COLON_EQUAL;
-+"+=" return T_PLUS_EQUAL;
-+\"|\' {
-+ str = yytext[0];
-+ new_string();
-+ BEGIN(STRING);
-+ }
-+{n}+ {
-+ alloc_string(yytext, yyleng);
-+ yylval.string = text;
-+ return T_WORD;
-+ }
-+({n}|$)+ {
-+ /* this token includes at least one '$' */
-+ yylval.string = expand_token(yytext, yyleng);
-+ if (strlen(yylval.string))
-+ return T_WORD;
-+ free(yylval.string);
-+ }
-+. warn_ignored_character(*yytext);
-
--<PARAM>{
-- "&&" return T_AND;
-- "||" return T_OR;
-- "(" return T_OPEN_PAREN;
-- ")" return T_CLOSE_PAREN;
-- "!" return T_NOT;
-- "=" return T_EQUAL;
-- "!=" return T_UNEQUAL;
-- "<=" return T_LESS_EQUAL;
-- ">=" return T_GREATER_EQUAL;
-- "<" return T_LESS;
-- ">" return T_GREATER;
-- \"|\' {
-- str = yytext[0];
-- new_string();
-- BEGIN(STRING);
-- }
-- \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
-- ({n}|[/.])+ {
-- const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
-- if (id && id->flags & TF_PARAM) {
-- zconflval.id = id;
-- return id->token;
-- }
-+<ASSIGN_VAL>{
-+ [^[:blank:]\n]+.* {
- alloc_string(yytext, yyleng);
-- zconflval.string = text;
-- return T_WORD;
-- }
-- #.* /* comment */
-- \\\n current_file->lineno++;
-- [[:blank:]]+
-- . warn_ignored_character(*yytext);
-- <<EOF>> {
-- BEGIN(INITIAL);
-+ yylval.string = text;
-+ return T_ASSIGN_VAL;
- }
-+ \n { BEGIN(INITIAL); return T_EOL; }
-+ .
- }
-
- <STRING>{
-- [^'"\\\n]+/\n {
-- append_string(yytext, yyleng);
-- zconflval.string = text;
-- return T_WORD_QUOTE;
-- }
-- [^'"\\\n]+ {
-+ "$".* append_expanded_string(yytext);
-+ [^$'"\\\n]+ {
- append_string(yytext, yyleng);
- }
-- \\.?/\n {
-- append_string(yytext + 1, yyleng - 1);
-- zconflval.string = text;
-- return T_WORD_QUOTE;
-- }
- \\.? {
- append_string(yytext + 1, yyleng - 1);
- }
- \'|\" {
- if (str == yytext[0]) {
-- BEGIN(PARAM);
-- zconflval.string = text;
-+ BEGIN(INITIAL);
-+ yylval.string = text;
- return T_WORD_QUOTE;
- } else
- append_string(yytext, 1);
- }
- \n {
-- printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
-- current_file->lineno++;
-+ fprintf(stderr,
-+ "%s:%d:warning: multi-line strings not supported\n",
-+ zconf_curname(), zconf_lineno());
-+ unput('\n');
- BEGIN(INITIAL);
-- return T_EOL;
-+ yylval.string = text;
-+ return T_WORD_QUOTE;
- }
- <<EOF>> {
- BEGIN(INITIAL);
-+ yylval.string = text;
-+ return T_WORD_QUOTE;
- }
- }
-
-@@ -218,12 +222,10 @@ n [A-Za-z0-9_-]
- }
- }
- [ \t]*\n/[^ \t\n] {
-- current_file->lineno++;
- zconf_endhelp();
- return T_HELPTEXT;
- }
- [ \t]*\n {
-- current_file->lineno++;
- append_string("\n", 1);
- }
- [^ \t\n].* {
-@@ -243,6 +245,12 @@ n [A-Za-z0-9_-]
- }
-
- <<EOF>> {
-+ BEGIN(INITIAL);
-+
-+ if (prev_token != T_EOL && prev_token != T_HELPTEXT)
-+ fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
-+ current_file->name, yylineno);
-+
- if (current_file) {
- zconf_endfile();
- return T_EOL;
-@@ -252,6 +260,93 @@ n [A-Za-z0-9_-]
- }
-
- %%
-+
-+/* second stage lexer */
-+int yylex(void)
-+{
-+ int token;
-+
-+repeat:
-+ token = yylex1();
-+
-+ if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
-+ if (token == T_EOL) {
-+ /* Do not pass unneeded T_EOL to the parser. */
-+ goto repeat;
-+ } else {
-+ /*
-+ * For the parser, update file/lineno at the first token
-+ * of each statement. Generally, \n is a statement
-+ * terminator in Kconfig, but it is not always true
-+ * because \n could be escaped by a backslash.
-+ */
-+ current_pos.file = current_file;
-+ current_pos.lineno = yylineno;
-+ }
-+ }
-+
-+ if (prev_prev_token == T_EOL && prev_token == T_WORD &&
-+ (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
-+ BEGIN(ASSIGN_VAL);
-+
-+ prev_prev_token = prev_token;
-+ prev_token = token;
-+
-+ return token;
-+}
-+
-+static char *expand_token(const char *in, size_t n)
-+{
-+ char *out;
-+ int c;
-+ char c2;
-+ const char *rest, *end;
-+
-+ new_string();
-+ append_string(in, n);
-+
-+ /* get the whole line because we do not know the end of token. */
-+ while ((c = input()) != EOF) {
-+ if (c == '\n') {
-+ unput(c);
-+ break;
-+ }
-+ c2 = c;
-+ append_string(&c2, 1);
-+ }
-+
-+ rest = text;
-+ out = expand_one_token(&rest);
-+
-+ /* push back unused characters to the input stream */
-+ end = rest + strlen(rest);
-+ while (end > rest)
-+ unput(*--end);
-+
-+ free(text);
-+
-+ return out;
-+}
-+
-+static void append_expanded_string(const char *str)
-+{
-+ const char *end;
-+ char *res;
-+
-+ str++;
-+
-+ res = expand_dollar(&str);
-+
-+ /* push back unused characters to the input stream */
-+ end = str + strlen(str);
-+ while (end > str)
-+ unput(*--end);
-+
-+ append_string(res, strlen(res));
-+
-+ free(res);
-+}
-+
- void zconf_starthelp(void)
- {
- new_string();
-@@ -261,7 +356,7 @@ void zconf_starthelp(void)
-
- static void zconf_endhelp(void)
- {
-- zconflval.string = text;
-+ yylval.string = text;
- BEGIN(INITIAL);
- }
-
-@@ -294,7 +389,7 @@ void zconf_initscan(const char *name)
- {
- yyin = zconf_fopen(name);
- if (!yyin) {
-- printf("can't find file %s\n", name);
-+ fprintf(stderr, "can't find file %s\n", name);
- exit(1);
- }
-
-@@ -302,7 +397,7 @@ void zconf_initscan(const char *name)
- memset(current_buf, 0, sizeof(*current_buf));
-
- current_file = file_lookup(name);
-- current_file->lineno = 1;
-+ yylineno = 1;
- }
-
- void zconf_nextfile(const char *name)
-@@ -315,35 +410,34 @@ void zconf_nextfile(const char *name)
- current_buf->state = YY_CURRENT_BUFFER;
- yyin = zconf_fopen(file->name);
- if (!yyin) {
-- printf("%s:%d: can't open file \"%s\"\n",
-- zconf_curname(), zconf_lineno(), file->name);
-+ fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
-+ zconf_curname(), zconf_lineno(), file->name);
- exit(1);
- }
- yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
- buf->parent = current_buf;
- current_buf = buf;
-
-- for (iter = current_file->parent; iter; iter = iter->parent ) {
-- if (!strcmp(current_file->name,iter->name) ) {
-- printf("%s:%d: recursive inclusion detected. "
-- "Inclusion path:\n current file : '%s'\n",
-- zconf_curname(), zconf_lineno(),
-- zconf_curname());
-- iter = current_file->parent;
-- while (iter && \
-- strcmp(iter->name,current_file->name)) {
-- printf(" included from: '%s:%d'\n",
-- iter->name, iter->lineno-1);
-+ current_file->lineno = yylineno;
-+ file->parent = current_file;
-+
-+ for (iter = current_file; iter; iter = iter->parent) {
-+ if (!strcmp(iter->name, file->name)) {
-+ fprintf(stderr,
-+ "Recursive inclusion detected.\n"
-+ "Inclusion path:\n"
-+ " current file : %s\n", file->name);
-+ iter = file;
-+ do {
- iter = iter->parent;
-- }
-- if (iter)
-- printf(" included from: '%s:%d'\n",
-- iter->name, iter->lineno+1);
-+ fprintf(stderr, " included from: %s:%d\n",
-+ iter->name, iter->lineno - 1);
-+ } while (strcmp(iter->name, file->name));
- exit(1);
- }
- }
-- file->lineno = 1;
-- file->parent = current_file;
-+
-+ yylineno = 1;
- current_file = file;
- }
-
-@@ -352,6 +446,8 @@ static void zconf_endfile(void)
- struct buffer *parent;
-
- current_file = current_file->parent;
-+ if (current_file)
-+ yylineno = current_file->lineno;
-
- parent = current_buf->parent;
- if (parent) {
-diff --git a/carl9170fw/config/zconf.y b/carl9170fw/config/zconf.y
-index 79c4f04..60936c7 100644
---- a/carl9170fw/config/zconf.y
-+++ b/carl9170fw/config/zconf.y
-@@ -1,8 +1,8 @@
--%{
-+/* SPDX-License-Identifier: GPL-2.0 */
- /*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
-- * Released under the terms of the GNU GPL v2.0.
- */
-+%{
-
- #include <ctype.h>
- #include <stdarg.h>
-@@ -20,63 +20,69 @@
-
- int cdebug = PRINTD;
-
--extern int zconflex(void);
-+static void yyerror(const char *err);
- static void zconfprint(const char *err, ...);
- static void zconf_error(const char *err, ...);
--static void zconferror(const char *err);
--static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken);
-+static bool zconf_endtoken(const char *tokenname,
-+ const char *expected_tokenname);
-
- struct symbol *symbol_hash[SYMBOL_HASHSIZE];
-
- static struct menu *current_menu, *current_entry;
-
- %}
--%expect 32
-
- %union
- {
- char *string;
-- struct file *file;
- struct symbol *symbol;
- struct expr *expr;
- struct menu *menu;
-- const struct kconf_id *id;
-+ enum symbol_type type;
-+ enum variable_flavor flavor;
- }
-
--%token <id>T_MAINMENU
--%token <id>T_MENU
--%token <id>T_ENDMENU
--%token <id>T_SOURCE
--%token <id>T_CHOICE
--%token <id>T_ENDCHOICE
--%token <id>T_COMMENT
--%token <id>T_CONFIG
--%token <id>T_MENUCONFIG
--%token <id>T_HELP
- %token <string> T_HELPTEXT
--%token <id>T_IF
--%token <id>T_ENDIF
--%token <id>T_DEPENDS
--%token <id>T_OPTIONAL
--%token <id>T_PROMPT
--%token <id>T_TYPE
--%token <id>T_DEFAULT
--%token <id>T_SELECT
--%token <id>T_IMPLY
--%token <id>T_RANGE
--%token <id>T_VISIBLE
--%token <id>T_OPTION
--%token <id>T_ON
- %token <string> T_WORD
- %token <string> T_WORD_QUOTE
--%token T_UNEQUAL
--%token T_LESS
--%token T_LESS_EQUAL
--%token T_GREATER
--%token T_GREATER_EQUAL
-+%token T_ALLNOCONFIG_Y
-+%token T_BOOL
-+%token T_CHOICE
- %token T_CLOSE_PAREN
-+%token T_COLON_EQUAL
-+%token T_COMMENT
-+%token T_CONFIG
-+%token T_DEFAULT
-+%token T_DEFCONFIG_LIST
-+%token T_DEF_BOOL
-+%token T_DEF_TRISTATE
-+%token T_DEPENDS
-+%token T_ENDCHOICE
-+%token T_ENDIF
-+%token T_ENDMENU
-+%token T_HELP
-+%token T_HEX
-+%token T_IF
-+%token T_IMPLY
-+%token T_INT
-+%token T_MAINMENU
-+%token T_MENU
-+%token T_MENUCONFIG
-+%token T_MODULES
-+%token T_ON
- %token T_OPEN_PAREN
-+%token T_OPTION
-+%token T_OPTIONAL
-+%token T_PLUS_EQUAL
-+%token T_PROMPT
-+%token T_RANGE
-+%token T_SELECT
-+%token T_SOURCE
-+%token T_STRING
-+%token T_TRISTATE
-+%token T_VISIBLE
- %token T_EOL
-+%token <string> T_ASSIGN_VAL
-
- %left T_OR
- %left T_AND
-@@ -85,13 +91,15 @@ static struct menu *current_menu, *current_entry;
- %nonassoc T_NOT
-
- %type <string> prompt
-+%type <symbol> nonconst_symbol
- %type <symbol> symbol
-+%type <type> type logic_type default
- %type <expr> expr
- %type <expr> if_expr
--%type <id> end
--%type <id> option_name
-+%type <string> end
- %type <menu> if_entry menu_entry choice_entry
--%type <string> symbol_option_arg word_opt
-+%type <string> word_opt assign_val
-+%type <flavor> assign_op
-
- %destructor {
- fprintf(stderr, "%s:%d: missing end statement for this entry\n",
-@@ -100,71 +108,53 @@ static struct menu *current_menu, *current_entry;
- menu_end_menu();
- } if_entry menu_entry choice_entry
-
--%{
--/* Include zconf_id.c here so it can see the token constants. */
--#include "kconf_id.c"
--%}
--
- %%
--input: nl start | start;
-+input: mainmenu_stmt stmt_list | stmt_list;
-
--start: mainmenu_stmt stmt_list | stmt_list;
-+/* mainmenu entry */
-+
-+mainmenu_stmt: T_MAINMENU prompt T_EOL
-+{
-+ menu_add_prompt(P_MENU, $2, NULL);
-+};
-
- stmt_list:
- /* empty */
- | stmt_list common_stmt
- | stmt_list choice_stmt
- | stmt_list menu_stmt
-- | stmt_list end { zconf_error("unexpected end statement"); }
- | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
-- | stmt_list option_name error T_EOL
--{
-- zconf_error("unexpected option \"%s\"", $2->name);
--}
- | stmt_list error T_EOL { zconf_error("invalid statement"); }
- ;
-
--option_name:
-- T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_IMPLY | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
--;
--
- common_stmt:
-- T_EOL
-- | if_stmt
-+ if_stmt
- | comment_stmt
- | config_stmt
- | menuconfig_stmt
- | source_stmt
-+ | assignment_stmt
- ;
-
--option_error:
-- T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); }
-- | error T_EOL { zconf_error("invalid option"); }
--;
--
--
- /* config/menuconfig entry */
-
--config_entry_start: T_CONFIG T_WORD T_EOL
-+config_entry_start: T_CONFIG nonconst_symbol T_EOL
- {
-- struct symbol *sym = sym_lookup($2, 0);
-- sym->flags |= SYMBOL_OPTIONAL;
-- menu_add_entry(sym);
-- printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2);
-+ $2->flags |= SYMBOL_OPTIONAL;
-+ menu_add_entry($2);
-+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name);
- };
-
- config_stmt: config_entry_start config_option_list
- {
-- menu_end_entry();
- printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
- };
-
--menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL
-+menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
- {
-- struct symbol *sym = sym_lookup($2, 0);
-- sym->flags |= SYMBOL_OPTIONAL;
-- menu_add_entry(sym);
-- printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2);
-+ $2->flags |= SYMBOL_OPTIONAL;
-+ menu_add_entry($2);
-+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name);
- };
-
- menuconfig_stmt: menuconfig_entry_start config_option_list
-@@ -173,26 +163,22 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
- current_entry->prompt->type = P_MENU;
- else
- zconfprint("warning: menuconfig statement without prompt");
-- menu_end_entry();
- printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
- };
-
- config_option_list:
- /* empty */
- | config_option_list config_option
-- | config_option_list symbol_option
- | config_option_list depends
- | config_option_list help
-- | config_option_list option_error
-- | config_option_list T_EOL
- ;
-
--config_option: T_TYPE prompt_stmt_opt T_EOL
-+config_option: type prompt_stmt_opt T_EOL
- {
-- menu_set_type($1->stype);
-+ menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
- zconf_curname(), zconf_lineno(),
-- $1->stype);
-+ $1);
- };
-
- config_option: T_PROMPT prompt if_expr T_EOL
-@@ -201,25 +187,25 @@ config_option: T_PROMPT prompt if_expr T_EOL
- printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
- };
-
--config_option: T_DEFAULT expr if_expr T_EOL
-+config_option: default expr if_expr T_EOL
- {
- menu_add_expr(P_DEFAULT, $2, $3);
-- if ($1->stype != S_UNKNOWN)
-- menu_set_type($1->stype);
-+ if ($1 != S_UNKNOWN)
-+ menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
- zconf_curname(), zconf_lineno(),
-- $1->stype);
-+ $1);
- };
-
--config_option: T_SELECT T_WORD if_expr T_EOL
-+config_option: T_SELECT nonconst_symbol if_expr T_EOL
- {
-- menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3);
-+ menu_add_symbol(P_SELECT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
- };
-
--config_option: T_IMPLY T_WORD if_expr T_EOL
-+config_option: T_IMPLY nonconst_symbol if_expr T_EOL
- {
-- menu_add_symbol(P_IMPLY, sym_lookup($2, 0), $3);
-+ menu_add_symbol(P_IMPLY, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
- };
-
-@@ -229,34 +215,30 @@ config_option: T_RANGE symbol symbol if_expr T_EOL
- printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
- };
-
--symbol_option: T_OPTION symbol_option_list T_EOL
--;
-+config_option: T_OPTION T_MODULES T_EOL
-+{
-+ menu_add_option_modules();
-+};
-
--symbol_option_list:
-- /* empty */
-- | symbol_option_list T_WORD symbol_option_arg
-+config_option: T_OPTION T_DEFCONFIG_LIST T_EOL
- {
-- const struct kconf_id *id = kconf_id_lookup($2, strlen($2));
-- if (id && id->flags & TF_OPTION)
-- menu_add_option(id->token, $3);
-- else
-- zconfprint("warning: ignoring unknown option %s", $2);
-- free($2);
-+ menu_add_option_defconfig_list();
- };
-
--symbol_option_arg:
-- /* empty */ { $$ = NULL; }
-- | T_EQUAL prompt { $$ = $2; }
--;
-+config_option: T_OPTION T_ALLNOCONFIG_Y T_EOL
-+{
-+ menu_add_option_allnoconfig_y();
-+};
-
- /* choice entry */
-
- choice: T_CHOICE word_opt T_EOL
- {
- struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
-- sym->flags |= SYMBOL_AUTO;
-+ sym->flags |= SYMBOL_NO_WRITE;
- menu_add_entry(sym);
- menu_add_expr(P_CHOICE, NULL, NULL);
-+ free($2);
- printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
- };
-
-@@ -267,7 +249,7 @@ choice_entry: choice choice_option_list
-
- choice_end: end
- {
-- if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) {
-+ if (zconf_endtoken($1, "choice")) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
- }
-@@ -281,8 +263,6 @@ choice_option_list:
- | choice_option_list choice_option
- | choice_option_list depends
- | choice_option_list help
-- | choice_option_list T_EOL
-- | choice_option_list option_error
- ;
-
- choice_option: T_PROMPT prompt if_expr T_EOL
-@@ -291,15 +271,11 @@ choice_option: T_PROMPT prompt if_expr T_EOL
- printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
- };
-
--choice_option: T_TYPE prompt_stmt_opt T_EOL
-+choice_option: logic_type prompt_stmt_opt T_EOL
- {
-- if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) {
-- menu_set_type($1->stype);
-- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
-- zconf_curname(), zconf_lineno(),
-- $1->stype);
-- } else
-- YYERROR;
-+ menu_set_type($1);
-+ printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
-+ zconf_curname(), zconf_lineno(), $1);
- };
-
- choice_option: T_OPTIONAL T_EOL
-@@ -308,16 +284,28 @@ choice_option: T_OPTIONAL T_EOL
- printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
- };
-
--choice_option: T_DEFAULT T_WORD if_expr T_EOL
-+choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
- {
-- if ($1->stype == S_UNKNOWN) {
-- menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3);
-- printd(DEBUG_PARSE, "%s:%d:default\n",
-- zconf_curname(), zconf_lineno());
-- } else
-- YYERROR;
-+ menu_add_symbol(P_DEFAULT, $2, $3);
-+ printd(DEBUG_PARSE, "%s:%d:default\n",
-+ zconf_curname(), zconf_lineno());
- };
-
-+type:
-+ logic_type
-+ | T_INT { $$ = S_INT; }
-+ | T_HEX { $$ = S_HEX; }
-+ | T_STRING { $$ = S_STRING; }
-+
-+logic_type:
-+ T_BOOL { $$ = S_BOOLEAN; }
-+ | T_TRISTATE { $$ = S_TRISTATE; }
-+
-+default:
-+ T_DEFAULT { $$ = S_UNKNOWN; }
-+ | T_DEF_BOOL { $$ = S_BOOLEAN; }
-+ | T_DEF_TRISTATE { $$ = S_TRISTATE; }
-+
- choice_block:
- /* empty */
- | choice_block common_stmt
-@@ -325,7 +313,7 @@ choice_block:
-
- /* if entry */
-
--if_entry: T_IF expr nl
-+if_entry: T_IF expr T_EOL
- {
- printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
- menu_add_entry(NULL);
-@@ -335,29 +323,15 @@ if_entry: T_IF expr nl
-
- if_end: end
- {
-- if (zconf_endtoken($1, T_IF, T_ENDIF)) {
-+ if (zconf_endtoken($1, "if")) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
- }
- };
-
--if_stmt: if_entry if_block if_end
-+if_stmt: if_entry stmt_list if_end
- ;
-
--if_block:
-- /* empty */
-- | if_block common_stmt
-- | if_block menu_stmt
-- | if_block choice_stmt
--;
--
--/* mainmenu entry */
--
--mainmenu_stmt: T_MAINMENU prompt nl
--{
-- menu_add_prompt(P_MENU, $2, NULL);
--};
--
- /* menu entry */
-
- menu: T_MENU prompt T_EOL
-@@ -367,33 +341,33 @@ menu: T_MENU prompt T_EOL
- printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
- };
-
--menu_entry: menu visibility_list depends_list
-+menu_entry: menu menu_option_list
- {
- $$ = menu_add_menu();
- };
-
- menu_end: end
- {
-- if (zconf_endtoken($1, T_MENU, T_ENDMENU)) {
-+ if (zconf_endtoken($1, "menu")) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
- }
- };
-
--menu_stmt: menu_entry menu_block menu_end
-+menu_stmt: menu_entry stmt_list menu_end
- ;
-
--menu_block:
-+menu_option_list:
- /* empty */
-- | menu_block common_stmt
-- | menu_block menu_stmt
-- | menu_block choice_stmt
-+ | menu_option_list visible
-+ | menu_option_list depends
- ;
-
- source_stmt: T_SOURCE prompt T_EOL
- {
- printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
- zconf_nextfile($2);
-+ free($2);
- };
-
- /* comment entry */
-@@ -405,10 +379,13 @@ comment: T_COMMENT prompt T_EOL
- printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
- };
-
--comment_stmt: comment depends_list
--{
-- menu_end_entry();
--};
-+comment_stmt: comment comment_option_list
-+;
-+
-+comment_option_list:
-+ /* empty */
-+ | comment_option_list depends
-+;
-
- /* help option */
-
-@@ -420,18 +397,22 @@ help_start: T_HELP T_EOL
-
- help: help_start T_HELPTEXT
- {
-+ if (current_entry->help) {
-+ free(current_entry->help);
-+ zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
-+ current_entry->sym->name ?: "<choice>");
-+ }
-+
-+ /* Is the help text empty or all whitespace? */
-+ if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
-+ zconfprint("warning: '%s' defined with blank help text",
-+ current_entry->sym->name ?: "<choice>");
-+
- current_entry->help = $2;
- };
-
- /* depends option */
-
--depends_list:
-- /* empty */
-- | depends_list depends
-- | depends_list T_EOL
-- | depends_list option_error
--;
--
- depends: T_DEPENDS T_ON expr T_EOL
- {
- menu_add_dep($3);
-@@ -439,14 +420,7 @@ depends: T_DEPENDS T_ON expr T_EOL
- };
-
- /* visibility option */
--
--visibility_list:
-- /* empty */
-- | visibility_list visible
-- | visibility_list T_EOL
--;
--
--visible: T_VISIBLE if_expr
-+visible: T_VISIBLE if_expr T_EOL
- {
- menu_add_visibility($2);
- };
-@@ -464,14 +438,9 @@ prompt: T_WORD
- | T_WORD_QUOTE
- ;
-
--end: T_ENDMENU T_EOL { $$ = $1; }
-- | T_ENDCHOICE T_EOL { $$ = $1; }
-- | T_ENDIF T_EOL { $$ = $1; }
--;
--
--nl:
-- T_EOL
-- | nl T_EOL
-+end: T_ENDMENU T_EOL { $$ = "menu"; }
-+ | T_ENDCHOICE T_EOL { $$ = "choice"; }
-+ | T_ENDIF T_EOL { $$ = "if"; }
- ;
-
- if_expr: /* empty */ { $$ = NULL; }
-@@ -491,13 +460,31 @@ expr: symbol { $$ = expr_alloc_symbol($1); }
- | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); }
- ;
-
--symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); }
-+/* For symbol definitions, selects, etc., where quotes are not accepted */
-+nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
-+
-+symbol: nonconst_symbol
- | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
- ;
-
- word_opt: /* empty */ { $$ = NULL; }
- | T_WORD
-
-+/* assignment statement */
-+
-+assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
-+
-+assign_op:
-+ T_EQUAL { $$ = VAR_RECURSIVE; }
-+ | T_COLON_EQUAL { $$ = VAR_SIMPLE; }
-+ | T_PLUS_EQUAL { $$ = VAR_APPEND; }
-+;
-+
-+assign_val:
-+ /* empty */ { $$ = xstrdup(""); };
-+ | T_ASSIGN_VAL
-+;
-+
- %%
-
- void conf_parse(const char *name)
-@@ -507,61 +494,51 @@ void conf_parse(const char *name)
-
- zconf_initscan(name);
-
-- sym_init();
- _menu_init();
-- rootmenu.prompt = menu_add_prompt(P_MENU, "CARL9170 Firmware Configuration", NULL);
-
- if (getenv("ZCONF_DEBUG"))
-- zconfdebug = 1;
-- zconfparse();
-- if (zconfnerrs)
-+ yydebug = 1;
-+ yyparse();
-+
-+ /* Variables are expanded in the parse phase. We can free them here. */
-+ variable_all_del();
-+
-+ if (yynerrs)
- exit(1);
- if (!modules_sym)
- modules_sym = sym_find( "n" );
-
-- rootmenu.prompt->text = _(rootmenu.prompt->text);
-- rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
-+ if (!menu_has_prompt(&rootmenu)) {
-+ current_entry = &rootmenu;
-+ menu_add_prompt(P_MENU, "Main menu", NULL);
-+ }
-
- menu_finalize(&rootmenu);
- for_all_symbols(i, sym) {
- if (sym_check_deps(sym))
-- zconfnerrs++;
-+ yynerrs++;
- }
-- if (zconfnerrs)
-+ if (yynerrs)
- exit(1);
- sym_set_change_count(1);
- }
-
--static const char *zconf_tokenname(int token)
--{
-- switch (token) {
-- case T_MENU: return "menu";
-- case T_ENDMENU: return "endmenu";
-- case T_CHOICE: return "choice";
-- case T_ENDCHOICE: return "endchoice";
-- case T_IF: return "if";
-- case T_ENDIF: return "endif";
-- case T_DEPENDS: return "depends";
-- case T_VISIBLE: return "visible";
-- }
-- return "<token>";
--}
--
--static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken)
-+static bool zconf_endtoken(const char *tokenname,
-+ const char *expected_tokenname)
- {
-- if (id->token != endtoken) {
-+ if (strcmp(tokenname, expected_tokenname)) {
- zconf_error("unexpected '%s' within %s block",
-- id->name, zconf_tokenname(starttoken));
-- zconfnerrs++;
-+ tokenname, expected_tokenname);
-+ yynerrs++;
- return false;
- }
- if (current_menu->file != current_file) {
- zconf_error("'%s' in different file than '%s'",
-- id->name, zconf_tokenname(starttoken));
-+ tokenname, expected_tokenname);
- fprintf(stderr, "%s:%d: location of the '%s'\n",
- current_menu->file->name, current_menu->lineno,
-- zconf_tokenname(starttoken));
-- zconfnerrs++;
-+ expected_tokenname);
-+ yynerrs++;
- return false;
- }
- return true;
-@@ -582,7 +559,7 @@ static void zconf_error(const char *err, ...)
- {
- va_list ap;
-
-- zconfnerrs++;
-+ yynerrs++;
- fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
- va_start(ap, err);
- vfprintf(stderr, err, ap);
-@@ -590,7 +567,7 @@ static void zconf_error(const char *err, ...)
- fprintf(stderr, "\n");
- }
-
--static void zconferror(const char *err)
-+static void yyerror(const char *err)
- {
- fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
- }
-@@ -623,7 +600,7 @@ static void print_symbol(FILE *out, struct menu *menu)
- fprintf(out, "\nconfig %s\n", sym->name);
- switch (sym->type) {
- case S_BOOLEAN:
-- fputs(" boolean\n", out);
-+ fputs(" bool\n", out);
- break;
- case S_TRISTATE:
- fputs(" tristate\n", out);
-@@ -686,6 +663,10 @@ static void print_symbol(FILE *out, struct menu *menu)
- print_quoted_string(out, prop->text);
- fputc('\n', out);
- break;
-+ case P_SYMBOL:
-+ fputs( " symbol ", out);
-+ fprintf(out, "%s\n", prop->sym->name);
-+ break;
- default:
- fprintf(out, " unknown prop %d!\n", prop->type);
- break;
-@@ -746,9 +727,5 @@ void zconfdump(FILE *out)
- }
- }
-
--#include "zconf.lex.c"
- #include "util.c"
--#include "confdata.c"
--#include "expr.c"
--#include "symbol.c"
- #include "menu.c"
-diff --git a/carl9170fw/include/linux/ieee80211.h b/carl9170fw/include/linux/ieee80211.h
-index 31c59ea..46ce6cf 100644
---- a/carl9170fw/include/linux/ieee80211.h
-+++ b/carl9170fw/include/linux/ieee80211.h
-@@ -897,33 +897,33 @@ struct ieee80211_mgmt {
- __le16 status_code;
- /* possibly followed by Challenge text */
- u8 variable[0];
-- } __packed auth;
-+ } __packed __aligned(4) auth;
- struct {
- __le16 reason_code;
-- } __packed deauth;
-+ } __packed __aligned(4) deauth;
- struct {
- __le16 capab_info;
- __le16 listen_interval;
- /* followed by SSID and Supported rates */
- u8 variable[0];
-- } __packed assoc_req;
-+ } __packed __aligned(4) assoc_req;
- struct {
- __le16 capab_info;
- __le16 status_code;
- __le16 aid;
- /* followed by Supported rates */
- u8 variable[0];
-- } __packed assoc_resp, reassoc_resp;
-+ } __packed __aligned(4) assoc_resp, reassoc_resp;
- struct {
- __le16 capab_info;
- __le16 listen_interval;
- u8 current_ap[6];
- /* followed by SSID and Supported rates */
- u8 variable[0];
-- } __packed reassoc_req;
-+ } __packed __aligned(4) reassoc_req;
- struct {
- __le16 reason_code;
-- } __packed disassoc;
-+ } __packed __aligned(4) disassoc;
- struct {
- __le64 timestamp;
- __le16 beacon_int;
-@@ -931,11 +931,11 @@ struct ieee80211_mgmt {
- /* followed by some of SSID, Supported rates,
- * FH Params, DS Params, CF Params, IBSS Params, TIM */
- u8 variable[0];
-- } __packed beacon;
-+ } __packed __aligned(4) beacon;
- struct {
- /* only variable items: SSID, Supported rates */
- u8 variable[0];
-- } __packed probe_req;
-+ } __packed __aligned(4) probe_req;
- struct {
- __le64 timestamp;
- __le16 beacon_int;
-@@ -943,7 +943,7 @@ struct ieee80211_mgmt {
- /* followed by some of SSID, Supported rates,
- * FH Params, DS Params, CF Params, IBSS Params */
- u8 variable[0];
-- } __packed probe_resp;
-+ } __packed __aligned(4) probe_resp;
- struct {
- u8 category;
- union {
-@@ -1041,8 +1041,8 @@ struct ieee80211_mgmt {
- u8 variable[0];
- } __packed ftm;
- } u;
-- } __packed action;
-- } u;
-+ } __packed __aligned(4) action;
-+ } u __aligned(2);
- } __packed __aligned(2);
-
- /* Supported rates membership selectors */
-@@ -1245,7 +1245,7 @@ struct ieee80211_bar {
- __u8 ta[6];
- __le16 control;
- __le16 start_seq_num;
--} __packed __aligned(4);
-+} __packed __aligned(2);
-
- /* 802.11 BA(R) control masks */
- #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000
-diff --git a/carl9170fw/include/shared/wlan.h b/carl9170fw/include/shared/wlan.h
-index 9c6b7ff..117f005 100644
---- a/carl9170fw/include/shared/wlan.h
-+++ b/carl9170fw/include/shared/wlan.h
-@@ -273,7 +273,7 @@ struct ar9170_tx_frame {
- struct ieee80211_hdr i3e;
- u8 payload[0];
- } data;
--} __packed;
-+} __packed __aligned(4);
-
- struct carl9170_tx_superframe {
- struct carl9170_tx_superdesc s;
-diff --git a/carl9170fw/toolchain/Makefile b/carl9170fw/toolchain/Makefile
-index 11db906..43e546d 100644
---- a/carl9170fw/toolchain/Makefile
-+++ b/carl9170fw/toolchain/Makefile
-@@ -1,16 +1,16 @@
--BINUTILS_VER=2.31.1
-+BINUTILS_VER=2.32
- BINUTILS_TAR=binutils-$(BINUTILS_VER).tar.xz
- BINUTILS_URL="https://ftp.gnu.org/gnu/binutils/$(BINUTILS_TAR)"
-
--NEWLIB_VER=3.0.0
-+NEWLIB_VER=3.1.0
- NEWLIB_TAR=newlib-$(NEWLIB_VER).tar.gz
- NEWLIB_URL="ftp://sourceware.org/pub/newlib/$(NEWLIB_TAR)"
-
--GCC_VER=8.2.0
-+GCC_VER=9.1.0
- GCC_TAR=gcc-$(GCC_VER).tar.xz
- GCC_URL="https://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VER)/$(GCC_TAR)"
-
--MPFR_VER=4.0.1
-+MPFR_VER=4.0.2
- MPFR_TAR=mpfr-$(MPFR_VER).tar.xz
- MPFR_URL="https://ftp.gnu.org/gnu/mpfr/$(MPFR_TAR)"
-
-diff --git a/carl9170fw/toolchain/SHA256SUMS b/carl9170fw/toolchain/SHA256SUMS
-index 1b65040..3a53959 100644
---- a/carl9170fw/toolchain/SHA256SUMS
-+++ b/carl9170fw/toolchain/SHA256SUMS
-@@ -1,16 +1,6 @@
--1cf7adf8ff4b5aa49041c8734bbcf1ad18cc4c94d0029aae0f4e48841088479a src/gcc-7.2.0.tar.xz
--5b76a9b97c9464209772ed25ce55181a7bb144a66e5669aaec945aa64da3189b src/newlib-2.5.0.tar.gz
--0b871e271c4c620444f8264f72143b4d224aa305306d85dd77ab8dce785b1e85 src/binutils-2.29.tar.xz
- 87b565e89a9a684fe4ebeeddb8399dce2599f9c9049854ca8c0dfbdea0e21912 src/gmp-6.1.2.tar.xz
--617decc6ea09889fb08ede330917a00b16809b8db88c29c31bfbb49cbf88ecc3 src/mpc-1.0.3.tar.gz
--7a62ac1a04408614fccdc506e4844b10cf0ad2c2b1677097f8f35d3a1344a950 src/mpfr-3.1.6.tar.xz
- 6985c538143c1208dcb1ac42cedad6ff52e267b47e5f970183a3e75125b43c2e src/mpc-1.1.0.tar.gz
--fbe2cd1418b321f5c899ce4f0f0f4e73f5ecc7d02145b0e1fd096f5c3afb8a1d src/mpfr-4.0.0.tar.xz
--c8566335ee74e5fcaeb8595b4ebd0400c4b043d6acb3263ecb1314f8f5501332 src/newlib-3.0.0.tar.gz
--832ca6ae04636adbb430e865a1451adf6979ab44ca1c8374f61fba65645ce15c src/gcc-7.3.0.tar.xz
--e7010a46969f9d3e53b650a518663f98a5dde3c3ae21b7d71e5e6803bc36b577 src/binutils-2.29.1.tar.xz
--67874a60826303ee2fb6affc6dc0ddd3e749e9bfcb4c8655e3953d0458a6e16e src/mpfr-4.0.1.tar.xz
--6e46b8aeae2f727a36f0bd9505e405768a72218f1796f0d09757d45209871ae6 src/binutils-2.30.tar.xz
--1d1866f992626e61349a1ccd0b8d5253816222cdc13390dcfaa74b093aa2b153 src/gcc-8.1.0.tar.xz
--5d20086ecf5752cc7d9134246e9588fa201740d540f7eb84d795b1f7a93bca86 src/binutils-2.31.1.tar.xz
--196c3c04ba2613f893283977e6011b2345d1cd1af9abeac58e916b1aab3e0080 src/gcc-8.2.0.tar.xz
-\ No newline at end of file
-+fb4fa1cc21e9060719208300a61420e4089d6de6ef59cf533b57fe74801d102a src/newlib-3.1.0.tar.gz
-+1d3be708604eae0e42d578ba93b390c2a145f17743a744d8f3f8c2ad5855a38a src/mpfr-4.0.2.tar.xz
-+0ab6c55dd86a92ed561972ba15b9b70a8b9f75557f896446c82e8b36e473ee04 src/binutils-2.32.tar.xz
-+79a66834e96a6050d8fe78db2c3b32fb285b230b855d0a66288235bc04b327a0 src/gcc-9.1.0.tar.xz
---
-2.26.0
-
diff --git a/libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch b/libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch
deleted file mode 100644
index aa4cb07dc..000000000
--- a/libre/linux-libre-firmware/0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch
+++ /dev/null
@@ -1,4893 +0,0 @@
-From dd4bc9ff49b9a7075e579fdd62fd930d27a9a7df Mon Sep 17 00:00:00 2001
-From: Jason Self <j@jxself.org>
-Date: Thu, 4 Jul 2019 15:55:48 -0700
-Subject: [PATCH 2/8] Add firmware for the ATUSB IEEE 802.15.4 USB Adapter
-
-http://shop.sysmocom.de/products/atusb/
----
- INSTALL | 20 +-
- Makefile | 6 +-
- WHENCE | 12 ++
- atusb/Makefile | 236 +++++++++++++++++++++
- atusb/README | 94 +++++++++
- atusb/an/README | 25 +++
- atusb/an/dec.py | 127 ++++++++++++
- atusb/an/get.py | 31 +++
- atusb/an/plot | 12 ++
- atusb/atusb.c | 63 ++++++
- atusb/board.c | 120 +++++++++++
- atusb/board.h | 95 +++++++++
- atusb/board_app.c | 173 ++++++++++++++++
- atusb/board_atusb.c | 162 +++++++++++++++
- atusb/board_atusb.h | 48 +++++
- atusb/board_hulusb.c | 179 ++++++++++++++++
- atusb/board_hulusb.h | 66 ++++++
- atusb/board_rzusb.c | 169 +++++++++++++++
- atusb/board_rzusb.h | 48 +++++
- atusb/boot.c | 77 +++++++
- atusb/descr.c | 104 ++++++++++
- atusb/ep0.c | 338 ++++++++++++++++++++++++++++++
- atusb/flash.c | 97 +++++++++
- atusb/include/at86rf230.h | 402 ++++++++++++++++++++++++++++++++++++
- atusb/include/atusb/atusb.h | 97 +++++++++
- atusb/include/atusb/ep0.h | 64 ++++++
- atusb/mac.c | 250 ++++++++++++++++++++++
- atusb/mac.h | 26 +++
- atusb/sernum.c | 47 +++++
- atusb/sernum.h | 37 ++++
- atusb/spi.c | 51 +++++
- atusb/spi.h | 30 +++
- atusb/uart.c | 64 ++++++
- atusb/uart.h | 25 +++
- atusb/usb/atu2.c | 247 ++++++++++++++++++++++
- atusb/usb/dfu.c | 260 +++++++++++++++++++++++
- atusb/usb/dfu.h | 119 +++++++++++
- atusb/usb/dfu_common.c | 101 +++++++++
- atusb/usb/usb.c | 181 ++++++++++++++++
- atusb/usb/usb.h | 189 +++++++++++++++++
- atusb/version.h | 23 +++
- 42 files changed, 4512 insertions(+), 3 deletions(-)
- create mode 100644 atusb/Makefile
- create mode 100644 atusb/README
- create mode 100644 atusb/an/README
- create mode 100755 atusb/an/dec.py
- create mode 100755 atusb/an/get.py
- create mode 100755 atusb/an/plot
- create mode 100644 atusb/atusb.c
- create mode 100644 atusb/board.c
- create mode 100644 atusb/board.h
- create mode 100644 atusb/board_app.c
- create mode 100644 atusb/board_atusb.c
- create mode 100644 atusb/board_atusb.h
- create mode 100644 atusb/board_hulusb.c
- create mode 100644 atusb/board_hulusb.h
- create mode 100644 atusb/board_rzusb.c
- create mode 100644 atusb/board_rzusb.h
- create mode 100644 atusb/boot.c
- create mode 100644 atusb/descr.c
- create mode 100644 atusb/ep0.c
- create mode 100644 atusb/flash.c
- create mode 100644 atusb/include/at86rf230.h
- create mode 100644 atusb/include/atusb/atusb.h
- create mode 100644 atusb/include/atusb/ep0.h
- create mode 100644 atusb/mac.c
- create mode 100644 atusb/mac.h
- create mode 100644 atusb/sernum.c
- create mode 100644 atusb/sernum.h
- create mode 100644 atusb/spi.c
- create mode 100644 atusb/spi.h
- create mode 100644 atusb/uart.c
- create mode 100644 atusb/uart.h
- create mode 100644 atusb/usb/atu2.c
- create mode 100644 atusb/usb/dfu.c
- create mode 100644 atusb/usb/dfu.h
- create mode 100644 atusb/usb/dfu_common.c
- create mode 100644 atusb/usb/usb.c
- create mode 100644 atusb/usb/usb.h
- create mode 100644 atusb/version.h
-
-diff --git a/INSTALL b/INSTALL
-index 74c5cfd..7fb1116 100644
---- a/INSTALL
-+++ b/INSTALL
-@@ -16,6 +16,8 @@ In order to build everything you will need the following on the host
- system:
-
- * A C/C++ compiler, like GCC
-+ * AVR-GCC
-+ * Standard C library for AVR-GCC
- * Cmake
- * GNU Bison/YACC
- * GNU Flex
-@@ -32,13 +34,27 @@ system:
-
- On GNU/Linux distros that use apt you can install these with:
-
-- apt install binutils-arm-linux-gnueabi binutils-arm-none-eabi bison \
-- cmake flex g++ gcc gcc-arm-linux-gnueabi gcc-arm-none-eabi gperf make wget
-+ apt install avr-gcc avr-libc binutils-arm-linux-gnueabi \
-+ binutils-arm-none-eabi bison cmake flex g++ gcc \
-+ gcc-arm-linux-gnueabi gcc-arm-none-eabi gperf make wget
-
- CARL9170 Firmware Configuration
-+-------------------------------
- When building the carl9170 firmware you will be prompted with
- configuration questions.
-
-+atusb: Firmware for the ATUSB IEEE 802.15.4 USB Adapter
-+-------------------------------------------------------
-+
-+To flash the firmware you need dfu-util on the host. Issue
-+
-+ make dfu
-+
-+right after plugging the device into the USB port while the red led is
-+still on.
-+
-+Refer to the included README file for more information.
-+
- Licensing
- ---------
-
-diff --git a/Makefile b/Makefile
-index 21d16fb..8474b30 100644
---- a/Makefile
-+++ b/Makefile
-@@ -17,7 +17,7 @@ shell=/bin/sh
- prefix=/lib/firmware
- install_program=install
-
--.PHONY: all test clean install a56 as31 aica ath9k_htc_toolchain ath9k_htc av7110 b43-tools carl9170fw-toolchain carl9170fw cis-tools cis dsp56k ihex2fw isci keyspan_pda openfwwf usbdux
-+.PHONY: all test clean install a56 as31 aica ath9k_htc_toolchain ath9k_htc atusb av7110 b43-tools carl9170fw-toolchain carl9170fw cis-tools cis dsp56k ihex2fw isci keyspan_pda openfwwf usbdux
-
- all: aica ath9k_htc av7110 carl9170fw cis dsp56k isci keyspan_pda openfwwf usbdux
-
-@@ -36,6 +36,9 @@ ath9k_htc_toolchain:
- ath9k_htc: ath9k_htc_toolchain
- cd ath9k_htc && $(MAKE) -C target_firmware
-
-+atusb:
-+ cd atusb && $(MAKE)
-+
- av7110:
- cd av7110 && $(MAKE)
-
-@@ -81,6 +84,7 @@ clean:
- if [ -a as31/Makefile ]; then cd as31 && $(MAKE) clean; fi;
- cd ath9k_htc && $(MAKE) toolchain-clean
- cd ath9k_htc && $(MAKE) -C target_firmware clean
-+ cd atusb && $(MAKE) clean
- cd av7110 && $(MAKE) clean
- cd carl9170fw/toolchain && $(MAKE) clean
- if [ -a carl9170fw/Makefile ]; then cd carl9170fw && $(MAKE) clean; fi;
-diff --git a/WHENCE b/WHENCE
-index 2932155..756de43 100644
---- a/WHENCE
-+++ b/WHENCE
-@@ -112,6 +112,18 @@ From https://github.com/qca/open-ath9k-htc-firmware
-
- --------------------------------------------------------------------------
-
-+atusb: Firmware for the ATUSB IEEE 802.15.4 USB Adapter
-+http://shop.sysmocom.de/products/atusb/
-+
-+From http://projects.qi-hardware.com/index.php/p/ben-wpan/source/tree/master/atusb/fw
-+
-+License: GPL-2.0-or-later
-+
-+Version: Based on commit 805db6ebf5d80692158acadf88e239da9d3e67af
-+dated September 13 2017
-+
-+--------------------------------------------------------------------------
-+
- Driver: b43 - OpenFWWF -- Free firmware for some Broadcom 43xx series WLAN chips
-
- License: GPLv2
-diff --git a/atusb/Makefile b/atusb/Makefile
-new file mode 100644
-index 0000000..c79cb26
---- /dev/null
-+++ b/atusb/Makefile
-@@ -0,0 +1,236 @@
-+#
-+# Makefile - Makefile of the ATUSB firmware
-+#
-+# Written 2010-2011, 2013 by Werner Almesberger
-+# Copyright 2010-2011, 2013 by Werner Almesberger
-+#
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 2 of the License, or
-+# (at your option) any later version.
-+#
-+
-+SHELL = /bin/bash
-+
-+NAME = atusb
-+DEBUG = false
-+
-+CFLAGS = -g -mmcu=$(CHIP) -DBOOT_ADDR=$(BOOT_ADDR) \
-+ -Wall -Wextra -Wshadow -Werror -Wno-unused-parameter \
-+ -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes
-+
-+ifeq ($(DEBUG),true)
-+CFLAGS += -DDEBUG
-+endif
-+
-+ifeq ($(NAME),rzusb)
-+CHIP=at90usb1287
-+CFLAGS += -DRZUSB -DAT86RF230
-+else ifeq ($(NAME),hulusb)
-+CHIP=at90usb1287
-+CFLAGS += -DHULUSB -DAT86RF212
-+else
-+CHIP=atmega32u2
-+CFLAGS += -DATUSB -DAT86RF231
-+endif
-+HOST=jlime
-+BOOT_ADDR=0x7000
-+
-+AVR_PREFIX = $(BIN_PATH) avr-
-+CC = $(AVR_PREFIX)gcc
-+OBJCOPY = $(AVR_PREFIX)objcopy
-+#OBJDUMP = $(AVR_PREFIX)objdump
-+SIZE = $(AVR_PREFIX)size
-+
-+# BCD notion is 0xJJMM with JJ being major and MM being minor. Thus 0x0020 is
-+# version 0.2 */
-+USB_BCD_VERSION = 0030
-+USB_VENDOR_ID = 20b7
-+USB_PRODUCT_ID = 1540
-+USB_ID = $(USB_VENDOR_ID):$(USB_PRODUCT_ID)
-+
-+OBJS = atusb.o board.o board_app.o sernum.o spi.o descr.o ep0.o \
-+ dfu_common.o usb.o app-atu2.o mac.o
-+BOOT_OBJS = boot.o board.o sernum.o spi.o flash.o dfu.o \
-+ dfu_common.o usb.o boot-atu2.o
-+
-+ifeq ($(DEBUG),true)
-+OBJS += uart.o
-+endif
-+
-+ifeq ($(NAME),rzusb)
-+OBJS += board_rzusb.o
-+BOOT_OBJS += board_rzusb.o
-+else ifeq ($(NAME),hulusb)
-+OBJS += board_hulusb.o
-+BOOT_OBJS += board_hulusb.o
-+else
-+OBJS += board_atusb.o
-+BOOT_OBJS += board_atusb.o
-+endif
-+
-+
-+vpath %.c usb/
-+
-+CFLAGS += -Iinclude -Iusb -I.
-+
-+# ----- Verbosity control -----------------------------------------------------
-+
-+CC_normal := $(CC)
-+BUILD_normal :=
-+DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG
-+
-+CC_quiet = @echo " CC " $@ && $(CC_normal)
-+BUILD_quiet = @echo " BUILD " $@ && $(BUILD_normal)
-+DEPEND_quiet = @$(DEPEND_normal)
-+
-+ifeq ($(V),1)
-+ CC = $(CC_normal)
-+ BUILD = $(BUILD_normal)
-+ DEPEND = $(DEPEND_normal)
-+else
-+ CC = $(CC_quiet)
-+ BUILD = $(BUILD_quiet)
-+ DEPEND = $(DEPEND_quiet)
-+endif
-+
-+# ----- Rules -----------------------------------------------------------------
-+
-+.PHONY: all clean upload prog dfu update version.c bindist
-+.PHONY: prog-app prog-read on off reset
-+
-+all: $(NAME).bin boot.hex
-+
-+$(NAME).elf: $(OBJS)
-+ $(MAKE) version.o
-+ $(CC) $(CFLAGS) -o $@ $(OBJS) version.o
-+ $(SIZE) $@
-+
-+boot.elf: $(BOOT_OBJS)
-+ $(CC) $(CFLAGS) -o $@ $(BOOT_OBJS) \
-+ -Wl,--section-start=.text=$(BOOT_ADDR)
-+ $(SIZE) $@
-+
-+%.bin: %.elf
-+ $(BUILD) $(OBJCOPY) -j .text -j .data -O binary $< $@
-+ @echo "build #`cat .version`, `ls -l $@`"
-+
-+%.dfu: %.bin
-+ cp $(NAME).bin $(NAME).dfu
-+ dfu-suffix -a $(NAME).dfu -d 0x$(USB_BCD_VERSION) \
-+ -p 0x$(USB_PRODUCT_ID) -v 0x$(USB_VENDOR_ID)
-+
-+%.hex: %.elf
-+ $(BUILD) $(OBJCOPY) -j .text -j .data -O ihex $< $@
-+ @echo "Size: `$(SIZE) -A boot.hex | sed '/Total */s///p;d'` B"
-+
-+# ----- Cleanup ---------------------------------------------------------------
-+
-+clean:
-+ rm -f $(NAME).bin $(NAME).elf $(NAME).dfu
-+ rm -f $(OBJS) $(OBJS:.o=.d)
-+ rm -f boot.hex boot.elf
-+ rm -f $(BOOT_OBJS) $(BOOT_OBJS:.o=.d)
-+ rm -f version.c version.d version.o
-+
-+# ----- Build version ---------------------------------------------------------
-+
-+version.c:
-+ @if [ -f .version ]; then \
-+ v=`cat .version`; \
-+ expr $$v + 1 >.version; \
-+ else \
-+ echo 0 >.version; \
-+ fi
-+ @[ -s .version ] || echo 0 >.version
-+ @echo '/* MACHINE-GENERATED. DO NOT EDIT ! */' >version.c
-+ @echo '#include "version.h"' >>version.c
-+ @echo "const char *build_date = \"`date`\";" >>version.c
-+ @echo "const uint16_t build_number = `cat .version`;" \
-+ >>version.c
-+
-+# ----- Dependencies ----------------------------------------------------------
-+
-+MKDEP = \
-+ $(DEPEND) $< | \
-+ sed \
-+ -e 's|^$(basename $(notdir $<)).o:|$@:|' \
-+ -e '/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \
-+ -e '$${g;p;}' \
-+ -e d >$(basename $@).d; \
-+ [ "$${PIPESTATUS[*]}" = "0 0" ] || \
-+ { rm -f $(basename $@).d; exit 1; }
-+
-+%.o: %.c
-+ $(CC) $(CFLAGS) -Os -c $<
-+ $(MKDEP)
-+
-+-include $(OBJS:.o=.d)
-+
-+# ----- Object file variants --------------------------------------------------
-+
-+app-%.o: usb/%.c
-+ $(CC) $(CFLAGS) -Os -o $@ -c $<
-+ $(MKDEP)
-+
-+boot-%.o: usb/%.c
-+ $(CC) $(CFLAGS) -DBOOT_LOADER -Os -o $@ -c $<
-+ $(MKDEP)
-+
-+# ----- Distribution ----------------------------------------------------------
-+
-+BINDIST_BASE=http://downloads.qi-hardware.com/people/werner/wpan/bindist
-+ATUSB_BIN_NAME=atusb-`git rev-parse HEAD | cut -c 1-7`.bin
-+
-+bindist:
-+ qippl atusb.bin wpan/bindist/$(ATUSB_BIN_NAME)
-+ @echo $(BINDIST_BASE)/$(ATUSB_BIN_NAME)
-+ @echo md5sum: `md5sum atusb.bin | sed 's/ .*//'`
-+ @echo atrf-id: \
-+ `sed '/.*number = \(.*\);/s//#\1/p;d' version.c` \
-+ `sed '/.*date = "\(.*\)";/s//\1/p;d' version.c`
-+
-+# ----- Programming and device control ----------------------------------------
-+
-+upload: $(NAME).bin boot.hex
-+ scp $(NAME).bin boot.hex $(HOST):
-+
-+# lfuse: external clock, slow start-up
-+# hfuse: 4 kB boot loader, reset into boot loader
-+# lock: allow everything but SPM to the boot loader
-+# Note: when trying to program 0xef, we get back 0x2f, failing
-+# verification. So we just program 0x2f.
-+
-+prog-app:
-+ ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb -e \
-+ -U flash:w:atusb.bin:r \
-+ -U lfuse:w:0x60:m
-+
-+prog:
-+ ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb -e \
-+ -U flash:w:boot.hex:i \
-+ -U lfuse:w:0x60:m \
-+ -U hfuse:w:0xd8:m \
-+ -U lock:w:0x2f:m
-+
-+prog-read:
-+ ssh $(HOST) avrdude -F -p $(CHIP) -c nanonote_atusb \
-+ -U flash:r:mcu.bin:r
-+
-+dfu: $(NAME).dfu
-+ dfu-util -d $(USB_ID) -D $(NAME).dfu
-+
-+update: $(NAME).bin
-+ -atrf-reset -a
-+ usbwait -r -i 0.01 -t 5 $(USB_ID)
-+ $(MAKE) dfu
-+
-+on:
-+ ssh $(HOST) poke 0x10010318 4
-+
-+off:
-+ ssh $(HOST) poke 0x10010314 4
-+
-+reset:
-+ ssh $(HOST) poke 0x10010318 2048
-+ ssh $(HOST) poke 0x10010314 2048
-diff --git a/atusb/README b/atusb/README
-new file mode 100644
-index 0000000..99ceb22
---- /dev/null
-+++ b/atusb/README
-@@ -0,0 +1,94 @@
-+Requires a very recent toolchain, because ATmega32U2 is relatively new.
-+
-+- Building:
-+
-+ make
-+
-+- Uploading the firmware to a Ben (for flashing with the atusb-pgm cable):
-+
-+ make HOST=<hostname> upload
-+
-+ Example:
-+
-+ make HOST=ben upload
-+
-+ HOST defaults to "jlime".
-+
-+- Flashing the boot loader:
-+
-+ Prerequisite: avrdude on the Ben.
-+
-+ Disconnect the atusb board from USB. Insert the atusb-pgm connector into
-+ the Ben. Place the atusb-pgm adapter on the exposed contact pads of the
-+ atusb board and push it down. Then run
-+
-+ make prog
-+
-+ This takes about 30 seconds. If the programming fails with an error
-+ message like "Yikes! Invalid device signature.", verify that the
-+ atusb-pgm board is properly connected and placed, then try again.
-+
-+- Uploading the application:
-+
-+ Prerequisite: dfu-util installed on the PC.
-+
-+ Insert atusb into the PC, then run
-+
-+ make dfu
-+
-+ Note: since the boot loader resets the USB bus after timing out,
-+ this operation can fail with a message like "No DFU capable USB device
-+ found". Just retry, and it will eventually get through.
-+
-+
-+HULUSB notes:
-+-------------
-+To prepare and flash the firmware on a HULUSB device some additional steps are
-+needed;
-+
-+avr-objcopy -O ihex -R .signature -R .fuse -R .eeprom hulusb.elf hulusb.hex
-+dfu-programmer at90usb1287 flash hulusb.hex
-+dfu-programmer at90usb1287 reset
-+
-+--------------------------
-+
-+Making the toolchain:
-+
-+# patches according to
-+# http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=789527
-+
-+# some gcc prerequisites
-+
-+apt-get remove avr-libc gcc-avr binutils-avr
-+apt-get install libmpfr-dev libmpc-dev
-+
-+# binutils
-+
-+wget http://ftp.gnu.org/gnu/binutils/binutils-2.21.tar.bz2
-+tar xfj binutils-2.21.tar.bz2
-+cd binutils-2.21
-+./configure --target=avr --disable-nls
-+make
-+make install
-+
-+# gcc
-+
-+wget http://ftpmirror.gnu.org/gcc/gcc-4.5.2/gcc-4.5.2.tar.bz2
-+wget -O gcc_452_avr.patch http://gcc.gnu.org/bugzilla/attachment.cgi?id=23050
-+tar xfj gcc-4.5.2.tar.bz2
-+cd gcc-4.5.2
-+patch -p1 -s <../gcc_452_avr.patch
-+mkdir obj-avr
-+cd obj-avr
-+../configure --target=avr --enable-languages=c \
-+ --disable-nls --disable-libssp --with-dwarf2
-+make
-+make install
-+
-+wget http://download.savannah.gnu.org/releases/avr-libc/avr-libc-1.7.1.tar.bz2
-+tar xfj avr-libc-1.7.1.tar.bz2
-+cd avr-libc-1.7.1
-+./bootstrap # the automake at the end takes a while
-+./configure --build=`./config.guess` --host=avr
-+make
-+make install
-diff --git a/atusb/an/README b/atusb/an/README
-new file mode 100644
-index 0000000..8e0d2fc
---- /dev/null
-+++ b/atusb/an/README
-@@ -0,0 +1,25 @@
-+workflow:
-+
-+- connect zprobe (note: it currently inverts because it didn't have any
-+ other chips around. this may change later.)
-+
-+- capture the USB signals at an interesting moment with a sample rate of
-+ 50 MSa/s
-+
-+- zoom into the frame(s) of interest
-+
-+- download the data with
-+ ./get.py
-+
-+- decode with
-+ ./dec.py
-+
-+ For manual decoding, set the coders to D+ and D- (we need D- for SE0
-+ and SE1 detection), then click on a rising clock edge left of the
-+ packet and move the cursor to the right.
-+
-+- if there are problems with the clock, the analog signal and digital
-+ signals derived from it can be examined after running dec.py with
-+ ./plot
-+
-+ (Note that the digital zprobe hides any analog anomalies.)
-diff --git a/atusb/an/dec.py b/atusb/an/dec.py
-new file mode 100755
-index 0000000..8534857
---- /dev/null
-+++ b/atusb/an/dec.py
-@@ -0,0 +1,127 @@
-+#!/usr/bin/python
-+
-+from tmc.wave import *
-+from tmc.dxplore import dxplore
-+from tmc.decode import d_usb_stream
-+
-+
-+#
-+# Clock recovery: we assume that each change in the wave is triggered by a
-+# clock edge. We know the clock's nominal period and resynchronize on each
-+# edge. Additionally, we can obtain a list of times when a timing violation
-+# has occurred.
-+#
-+# Note that the timing violations logic doesn't make much sense in its present
-+# form, since it mainly measures noise (particularly if we're digitizing slow
-+# edges) and not clock drift.
-+#
-+# A more useful metric would be accumulated error from some point of reference
-+# or at least the timing of same edges, to eliminate (generally harmless) time
-+# offsets introduced by digitizing.
-+#
-+# So it would probably make more sense for "recover" not to check for timing
-+# violations at all, and leave this to more specialized functions.
-+#
-+def recover(self, period, min = None, max = None, t0 = None):
-+ if t0 is None:
-+ t0 = self.data[0]
-+ v = not self.initial
-+ res = []
-+ violations = []
-+ for t in self.data:
-+ v = not v
-+ if t <= t0:
-+ continue
-+ n = 0
-+ while t0 < t-period/2:
-+ res.append(t0)
-+ t0 += period
-+ n += 1
-+ if min is not None:
-+ if t0-t > n*min:
-+ violations.append(t)
-+ if max is not None:
-+ if t-t0 > n*max:
-+ violations.append(t)
-+ t0 = t
-+ return res, violations
-+
-+
-+#
-+# Load the analog waves saved by get.py
-+#
-+wv = waves()
-+wv.load("_wv")
-+
-+#
-+# Digitize the waves and save the result.
-+#
-+dp = wv[0].digitize(1.5, 1.8)
-+dm = wv[1].digitize(1.5, 1.8)
-+wv = waves(dp, dm, dp-dm)
-+wv.save("_dig")
-+
-+#
-+# Also record the differential signal.
-+#
-+wd = wv[1]-wv[0]
-+dd = wd.digitize(-0.5, 0.5)
-+wd.save("_diff")
-+
-+#
-+# Run clock recovery on D+/D-. We only need one, but check both to be sure.
-+#
-+#p = 1/1.5e6
-+p = 1/12e6
-+dp_t, viol = recover(dp, p, p*0.9, p*1.1)
-+print viol
-+dm_t, viol = recover(dm, p, p*.9, p*1.1, t0 = dp.data[0])
-+print viol
-+
-+#
-+# Shift the clock by half a period, add a few periods to get steady state and
-+# SE0s (if any), and then sample the data lines.
-+#
-+clk = map(lambda t: t+p/2, dp_t)
-+clk.extend((clk[-1]+p, clk[-1]+2*p, clk[-1]+3*p))
-+dp_bv = dp.get(clk)
-+dm_bv = dm.get(clk)
-+
-+#
-+# Save a wave with the recovered clock to make it easier to find the bits in
-+# analog graphs.
-+#
-+dd.data = dp_t;
-+dd.save("_clk")
-+
-+#
-+# For decoding, we need a fake bit clock. We generate it by doubling each data
-+# bit and generating a L->H transition during this bit.
-+#
-+dpd = []
-+dmd = []
-+dck = []
-+
-+# err, silly, seems that we've mixed up D+ and D- all over the place :-)
-+print d_usb_stream(dm_bv[:], dp_bv[:])
-+
-+for v in dp_bv:
-+ dpd.append(v)
-+ dpd.append(v)
-+ dck.append(0)
-+ dck.append(1)
-+
-+for v in dm_bv:
-+ dmd.append(v)
-+ dmd.append(v)
-+
-+#
-+# Display the reconstructed digital signal. Note that the absolute time is only
-+# correct at the beginning and that relative time is only accurate over
-+# intervals in which no significant clock resynchronization has occurred.
-+#
-+# In fact, dxplore should probably have an option to either turn off time
-+# entirely or to display a user-provided time axis. The latter may be a bit
-+# tricky to implement.
-+#
-+dxplore((dmd, dpd, dck), 0, p/2, labels = ("D+", "D-", "CLK"))
-diff --git a/atusb/an/get.py b/atusb/an/get.py
-new file mode 100755
-index 0000000..685e00f
---- /dev/null
-+++ b/atusb/an/get.py
-@@ -0,0 +1,31 @@
-+#!/usr/bin/python
-+
-+from tmc.scope import rigol_ds1000c
-+
-+#-800, +1600
-+s = rigol_ds1000c()
-+#s.debug = False
-+
-+pos = s.hor.pos
-+scale = s.hor.scale
-+t0 = pos-scale*s.div_hor/2
-+t1 = pos+scale*s.div_hor/2
-+print t0, t1
-+
-+#zoom = 10
-+#step = scale/s.samples_per_div/zoom
-+#print step
-+step = 4e-9
-+step = 2e-9
-+
-+w = s.wave((s.ch[0], s.ch[1]), start = t0, end = t1, step = step)
-+w[0] = 3.3-w[0]
-+w[1] = 3.3-w[1]
-+
-+s.hor.pos = pos
-+s.hor.scale = scale
-+
-+w[0].label = "D+";
-+w[1].label = "D-";
-+
-+w.save("_wv")
-diff --git a/atusb/an/plot b/atusb/an/plot
-new file mode 100755
-index 0000000..1dea789
---- /dev/null
-+++ b/atusb/an/plot
-@@ -0,0 +1,12 @@
-+#!/bin/sh
-+#
-+# Plot output of "dec"
-+#
-+gnuplot -persist <<EOF
-+set style data lines
-+plot "_wv" using 1:(\$2-4), \
-+ "_dig" using 1:(\$2*3.3-4) lw 2, \
-+ "_wv" using 1:3, \
-+ "_dig" using 1:(\$3*3.3) lw 2, \
-+ "_clk" using 1:(\$2+1) lt 7
-+EOF
-diff --git a/atusb/atusb.c b/atusb/atusb.c
-new file mode 100644
-index 0000000..28faf40
---- /dev/null
-+++ b/atusb/atusb.c
-@@ -0,0 +1,63 @@
-+/*
-+ * fw/atusb.c - ATUSB initialization and main loop
-+ *
-+ * Written 2008-2011 by Werner Almesberger
-+ * Copyright 2008-2011 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdint.h>
-+
-+#include <avr/io.h>
-+#include <avr/sleep.h>
-+#include <avr/interrupt.h>
-+
-+#include "usb.h"
-+
-+#include "board.h"
-+#include "sernum.h"
-+#include "spi.h"
-+#include "atusb/ep0.h"
-+
-+#ifdef DEBUG
-+#include "uart.h"
-+#endif
-+
-+
-+int main(void)
-+{
-+ board_init();
-+ board_app_init();
-+ reset_rf();
-+
-+ user_get_descriptor = sernum_get_descr;
-+
-+ /* now we should be at 8 MHz */
-+
-+#ifdef DEBUG
-+ uart_init();
-+ static FILE atben_stdout = FDEV_SETUP_STREAM(uart_write_char, NULL,
-+ _FDEV_SETUP_WRITE);
-+ stdout = &atben_stdout;
-+#endif
-+
-+ usb_init();
-+ ep0_init();
-+#ifdef ATUSB
-+ timer_init();
-+
-+ /* move interrupt vectors to 0 */
-+ MCUCR = 1 << IVCE;
-+ MCUCR = 0;
-+#endif
-+
-+ sei();
-+
-+ while (1)
-+ sleep_mode();
-+}
-diff --git a/atusb/board.c b/atusb/board.c
-new file mode 100644
-index 0000000..c3b8d26
---- /dev/null
-+++ b/atusb/board.c
-@@ -0,0 +1,120 @@
-+/*
-+ * fw/board.c - Board-specific functions (for boot loader and application)
-+ *
-+ * Written 2011, 2013 by Werner Almesberger
-+ * Copyright 2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include <avr/io.h>
-+#include <avr/interrupt.h>
-+#include <avr/boot.h>
-+
-+#define F_CPU 8000000UL
-+#include <util/delay.h>
-+
-+#include "usb.h"
-+#include "at86rf230.h"
-+#include "board.h"
-+#include "spi.h"
-+
-+
-+uint8_t board_sernum[42] = { 42, USB_DT_STRING };
-+
-+/* ----- Register access --------------------------------------------------- */
-+
-+void change_state(uint8_t new)
-+{
-+ while ((reg_read(REG_TRX_STATUS) & TRX_STATUS_MASK) ==
-+ TRX_STATUS_TRANSITION);
-+ reg_write(REG_TRX_STATE, new);
-+}
-+
-+
-+uint8_t reg_read(uint8_t reg)
-+{
-+ uint8_t value;
-+
-+ spi_begin();
-+ spi_send(AT86RF230_REG_READ | reg);
-+ value = spi_recv();
-+ spi_end();
-+
-+ return value;
-+}
-+
-+
-+uint8_t subreg_read(uint8_t address, uint8_t mask, uint8_t position)
-+{
-+ /* Read current register value and mask out subregister. */
-+ uint8_t register_value = reg_read(address);
-+ register_value &= mask;
-+ register_value >>= position; /* Align subregister value. */
-+
-+ return register_value;
-+}
-+
-+
-+void reg_write(uint8_t reg, uint8_t value)
-+{
-+ spi_begin();
-+ spi_send(AT86RF230_REG_WRITE | reg);
-+ spi_send(value);
-+ spi_end();
-+}
-+
-+
-+void subreg_write(uint8_t address, uint8_t mask, uint8_t position, uint8_t value)
-+{
-+ /* Read current register value and mask area outside the subregister. */
-+ uint8_t register_value = reg_read(address);
-+ register_value &= ~mask;
-+
-+ /* Start preparing the new subregister value. shift in place and mask. */
-+ value <<= position;
-+ value &= mask;
-+
-+ value |= register_value; /* Set the new subregister value. */
-+
-+ /* Write the modified register value. */
-+ reg_write(address, value);
-+}
-+
-+
-+void panic(void)
-+{
-+ cli();
-+ while (1) {
-+ SET(LED);
-+ _delay_ms(100);
-+ CLR(LED);
-+ _delay_ms(100);
-+ }
-+}
-+
-+
-+static char hex(uint8_t nibble)
-+{
-+ return nibble < 10 ? '0'+nibble : 'a'+nibble-10;
-+}
-+
-+
-+void get_sernum(void)
-+{
-+ uint8_t sig;
-+ uint8_t i;
-+
-+ for (i = 0; i != 10; i++) {
-+ sig = boot_signature_byte_get(i+0xe);
-+ board_sernum[(i << 2)+2] = hex(sig >> 4);
-+ board_sernum[(i << 2)+4] = hex(sig & 0xf);
-+ }
-+}
-diff --git a/atusb/board.h b/atusb/board.h
-new file mode 100644
-index 0000000..dbcd410
---- /dev/null
-+++ b/atusb/board.h
-@@ -0,0 +1,95 @@
-+/*
-+ * fw/board.h - Board-specific functions and definitions
-+ *
-+ * Written 2008-2011, 2013, 2013 by Werner Almesberger
-+ * Copyright 2008-2011, 2013, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef BOARD_H
-+#define BOARD_H
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include <atusb/atusb.h>
-+
-+#ifdef ATUSB
-+#include "board_atusb.h"
-+#endif
-+#ifdef RZUSB
-+#include "board_rzusb.h"
-+#endif
-+#ifdef HULUSB
-+#include "board_hulusb.h"
-+#endif
-+
-+#define SET_2(p, b) PORT##p |= 1 << (b)
-+#define CLR_2(p, b) PORT##p &= ~(1 << (b))
-+#define IN_2(p, b) DDR##p &= ~(1 << (b))
-+#define OUT_2(p, b) DDR##p |= 1 << (b)
-+#define PIN_2(p, b) ((PIN##p >> (b)) & 1)
-+
-+#define SET_1(p, b) SET_2(p, b)
-+#define CLR_1(p, b) CLR_2(p, b)
-+#define IN_1(p, b) IN_2(p, b)
-+#define OUT_1(p, b) OUT_2(p, b)
-+#define PIN_1(p, b) PIN_2(p, b)
-+
-+#define SET(n) SET_1(n##_PORT, n##_BIT)
-+#define CLR(n) CLR_1(n##_PORT, n##_BIT)
-+#define IN(n) IN_1(n##_PORT, n##_BIT)
-+#define OUT(n) OUT_1(n##_PORT, n##_BIT)
-+#define PIN(n) PIN_1(n##_PORT, n##_BIT)
-+
-+
-+#define USB_VENDOR ATUSB_VENDOR_ID
-+#define USB_PRODUCT ATUSB_PRODUCT_ID
-+
-+#define DFU_USB_VENDOR USB_VENDOR
-+#define DFU_USB_PRODUCT USB_PRODUCT
-+
-+
-+#define BOARD_MAX_mA 40
-+
-+#ifdef BOOT_LOADER
-+#define NUM_EPS 1
-+#else
-+#define NUM_EPS 2
-+#endif
-+
-+#define HAS_BOARD_SERNUM
-+
-+extern uint8_t board_sernum[42];
-+extern uint8_t irq_serial;
-+
-+
-+void reset_rf(void);
-+void reset_cpu(void);
-+uint8_t read_irq(void);
-+void slp_tr(void);
-+
-+void led(bool on);
-+void panic(void);
-+
-+uint64_t timer_read(void);
-+void timer_init(void);
-+
-+bool gpio(uint8_t port, uint8_t data, uint8_t dir, uint8_t mask, uint8_t *res);
-+void gpio_cleanup(void);
-+
-+void get_sernum(void);
-+
-+void board_app_init(void);
-+
-+uint8_t reg_read(uint8_t reg);
-+uint8_t subreg_read(uint8_t address, uint8_t mask, uint8_t position);
-+void reg_write(uint8_t reg, uint8_t value);
-+void subreg_write(uint8_t address, uint8_t mask, uint8_t position, uint8_t value);
-+void change_state(uint8_t new);
-+
-+#endif /* !BOARD_H */
-diff --git a/atusb/board_app.c b/atusb/board_app.c
-new file mode 100644
-index 0000000..1fa9bf4
---- /dev/null
-+++ b/atusb/board_app.c
-@@ -0,0 +1,173 @@
-+/*
-+ * fw/board_app.c - Board-specific functions (for the application)
-+ *
-+ * Written 2011, 2013 by Werner Almesberger
-+ * Copyright 2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stddef.h>
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include <avr/io.h>
-+#include <avr/interrupt.h>
-+
-+#define F_CPU 8000000UL
-+#include <util/delay.h>
-+
-+#include "usb.h"
-+#include "at86rf230.h"
-+#include "spi.h"
-+#include "mac.h"
-+#include "board.h"
-+
-+
-+static volatile uint32_t timer_h = 0; /* 2^(16+32) / 8 MHz = ~1.1 years */
-+
-+
-+void reset_cpu(void)
-+{
-+ WDTCSR = 1 << WDE;
-+}
-+
-+
-+uint8_t read_irq(void)
-+{
-+ return PIN(IRQ_RF);
-+}
-+
-+
-+void slp_tr(void)
-+{
-+ SET(SLP_TR);
-+ CLR(SLP_TR);
-+}
-+
-+
-+ISR(TIMER1_OVF_vect)
-+{
-+ timer_h++;
-+}
-+
-+
-+uint64_t timer_read(void)
-+{
-+ uint32_t high;
-+ uint8_t low, mid;
-+
-+ do {
-+ if (TIFR1 & (1 << TOV1)) {
-+ TIFR1 = 1 << TOV1;
-+ timer_h++;
-+ }
-+ high = timer_h;
-+ low = TCNT1L;
-+ mid = TCNT1H;
-+ }
-+ while (TIFR1 & (1 << TOV1));
-+
-+ /*
-+ * We need all these casts because the intermediate results are handled
-+ * as if they were signed and thus get sign-expanded. Sounds wrong-ish.
-+ */
-+ return (uint64_t) high << 16 | (uint64_t) mid << 8 | (uint64_t) low;
-+}
-+
-+
-+void timer_init(void)
-+{
-+ /* configure timer 1 as a free-running CLK counter */
-+
-+ TCCR1A = 0;
-+ TCCR1B = 1 << CS10;
-+
-+ /* enable timer overflow interrupt */
-+
-+ TIMSK1 = 1 << TOIE1;
-+}
-+
-+
-+bool gpio(uint8_t port, uint8_t data, uint8_t dir, uint8_t mask, uint8_t *res)
-+{
-+ EIMSK = 0; /* recover INT_RF to ATUSB_GPIO_CLEANUP or an MCU reset */
-+
-+ switch (port) {
-+ case 1:
-+ DDRB = (DDRB & ~mask) | dir;
-+ PORTB = (PORTB & ~mask) | data;
-+ break;
-+ case 2:
-+ DDRC = (DDRC & ~mask) | dir;
-+ PORTC = (PORTC & ~mask) | data;
-+ break;
-+ case 3:
-+ DDRD = (DDRD & ~mask) | dir;
-+ PORTD = (PORTD & ~mask) | data;
-+ break;
-+ default:
-+ return 0;
-+ }
-+
-+ /* disable the UART so that we can meddle with these pins as well. */
-+ spi_off();
-+ _delay_ms(1);
-+
-+ switch (port) {
-+ case 1:
-+ res[0] = PINB;
-+ res[1] = PORTB;
-+ res[2] = DDRB;
-+ break;
-+ case 2:
-+ res[0] = PINC;
-+ res[1] = PORTC;
-+ res[2] = DDRC;
-+ break;
-+ case 3:
-+ res[0] = PIND;
-+ res[1] = PORTD;
-+ res[2] = DDRD;
-+ break;
-+ }
-+
-+ return 1;
-+}
-+
-+
-+void gpio_cleanup(void)
-+{
-+ EIMSK = 1 << 0;
-+}
-+
-+
-+static void done(void *user)
-+{
-+ led(0);
-+}
-+
-+
-+uint8_t irq_serial;
-+
-+#if defined(ATUSB) || defined(HULUSB)
-+ISR(INT0_vect)
-+#endif
-+#ifdef RZUSB
-+ISR(TIMER1_CAPT_vect)
-+#endif
-+{
-+ if (mac_irq) {
-+ if (mac_irq())
-+ return;
-+ }
-+ if (eps[1].state == EP_IDLE) {
-+ led(1);
-+ irq_serial = (irq_serial+1) | 0x80;
-+ usb_send(&eps[1], &irq_serial, 1, done, NULL);
-+ }
-+}
-diff --git a/atusb/board_atusb.c b/atusb/board_atusb.c
-new file mode 100644
-index 0000000..a02fb7f
---- /dev/null
-+++ b/atusb/board_atusb.c
-@@ -0,0 +1,162 @@
-+/*
-+ * fw/board_atusb.c - ATUSB Board-specific functions (for boot loader and application)
-+ *
-+ * Written 2016 by Stefan Schmidt
-+ * Copyright 2016 Stefan Schmidt
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include <avr/io.h>
-+#include <avr/interrupt.h>
-+#include <avr/boot.h>
-+
-+#define F_CPU 8000000UL
-+#include <util/delay.h>
-+
-+#include "usb.h"
-+#include "at86rf230.h"
-+#include "board.h"
-+#include "spi.h"
-+#include "usb/usb.h"
-+
-+static bool spi_initialized = 0;
-+
-+void reset_rf(void)
-+{
-+ /* set up all the outputs; default port value is 0 */
-+
-+ DDRB = 0;
-+ DDRC = 0;
-+ DDRD = 0;
-+ PORTB = 0;
-+ PORTC = 0;
-+ PORTD = 0;
-+
-+ OUT(LED);
-+ OUT(nRST_RF); /* this also resets the transceiver */
-+ OUT(SLP_TR);
-+
-+ spi_init();
-+
-+ /* AT86RF231 data sheet, 12.4.13, reset pulse width: 625 ns (min) */
-+
-+ CLR(nRST_RF);
-+ _delay_us(2);
-+ SET(nRST_RF);
-+
-+ /* 12.4.14: SPI access latency after reset: 625 ns (min) */
-+
-+ _delay_us(2);
-+
-+ /* we must restore TRX_CTRL_0 after each reset (9.6.4) */
-+
-+ set_clkm();
-+}
-+
-+void led(bool on)
-+{
-+ if (on)
-+ SET(LED);
-+ else
-+ CLR(LED);
-+}
-+
-+void set_clkm(void)
-+{
-+ /* switch CLKM to 8 MHz */
-+
-+ /*
-+ * @@@ Note: Atmel advise against changing the external clock in
-+ * mid-flight. We should therefore switch to the RC clock first, then
-+ * crank up the external clock, and finally switch back to the external
-+ * clock. The clock switching procedure is described in the ATmega32U2
-+ * data sheet in secton 8.2.2.
-+ */
-+ spi_begin();
-+ spi_send(AT86RF230_REG_WRITE | REG_TRX_CTRL_0);
-+ spi_send(CLKM_CTRL_8MHz);
-+ spi_end();
-+}
-+
-+void board_init(void)
-+{
-+ /* Disable the watchdog timer */
-+
-+ MCUSR = 0; /* Remove override */
-+ WDTCSR |= 1 << WDCE; /* Enable change */
-+ WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling
-+ change */
-+
-+ CLKPR = 1 << CLKPCE;
-+ /* We start with a 1 MHz/8 clock. Disable the prescaler. */
-+ CLKPR = 0;
-+
-+ get_sernum();
-+}
-+
-+void spi_begin(void)
-+{
-+ if (!spi_initialized)
-+ spi_init();
-+ CLR(nSS);
-+}
-+
-+void spi_off(void)
-+{
-+ spi_initialized = 0;
-+ UCSR1B = 0;
-+}
-+
-+void spi_init(void)
-+{
-+ SET(nSS);
-+ OUT(SCLK);
-+ OUT(MOSI);
-+ OUT(nSS);
-+ IN(MISO);
-+
-+ UBRR1 = 0; /* set bit rate to zero to begin */
-+ UCSR1C = 1 << UMSEL11 | 1 << UMSEL10;
-+ /* set MSPI, MSB first, SPI data mode 0 */
-+ UCSR1B = 1 << RXEN1 | 1 << TXEN1;
-+ /* enable receiver and transmitter */
-+ UBRR1 = 0; /* reconfirm the bit rate */
-+
-+ spi_initialized = 1;
-+}
-+
-+void usb_init(void)
-+{
-+ USBCON |= 1 << FRZCLK; /* freeze the clock */
-+
-+ /* enable the PLL and wait for it to lock */
-+ PLLCSR &= ~(1 << PLLP2 | 1 << PLLP1 | 1 << PLLP0);
-+ PLLCSR |= 1 << PLLE;
-+ while (!(PLLCSR & (1 << PLOCK)));
-+
-+ USBCON &= ~(1 << USBE); /* reset the controller */
-+ USBCON |= 1 << USBE;
-+
-+ USBCON &= ~(1 << FRZCLK); /* thaw the clock */
-+
-+ UDCON &= ~(1 << DETACH); /* attach the pull-up */
-+ UDIEN = 1 << EORSTE; /* enable device interrupts */
-+// UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */
-+
-+ ep_init();
-+}
-+
-+void board_app_init(void)
-+{
-+ /* enable INT0, trigger on rising edge */
-+ EICRA = 1 << ISC01 | 1 << ISC00;
-+ EIMSK = 1 << 0;
-+}
-diff --git a/atusb/board_atusb.h b/atusb/board_atusb.h
-new file mode 100644
-index 0000000..e5974c7
---- /dev/null
-+++ b/atusb/board_atusb.h
-@@ -0,0 +1,48 @@
-+/*
-+ * fw/board_atusb.h - ATUSB Board-specific functions and definitions
-+ *
-+ * Written 2016 by Stefan Schmidt
-+ * Copyright 2016 Stefan Schmidt
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef BOARD_ATUSB_H
-+#define BOARD_ATUSB_H
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#define LED_PORT B
-+#define LED_BIT 6
-+#define nRST_RF_PORT C
-+#define nRST_RF_BIT 7
-+#define SLP_TR_PORT B
-+#define SLP_TR_BIT 4
-+
-+#define SCLK_PORT D
-+#define SCLK_BIT 5
-+#define MOSI_PORT D
-+#define MOSI_BIT 3
-+
-+#define MISO_PORT D
-+#define MISO_BIT 2
-+#define nSS_PORT D
-+#define nSS_BIT 1
-+#define IRQ_RF_PORT D
-+#define IRQ_RF_BIT 0
-+
-+#define SPI_WAIT_DONE() while (!(UCSR1A & 1 << RXC1))
-+#define SPI_DATA UDR1
-+
-+void set_clkm(void);
-+void board_init(void);
-+
-+void spi_begin(void);
-+void spi_off(void);
-+void spi_init(void);
-+
-+#endif /* !BOARD_H */
-diff --git a/atusb/board_hulusb.c b/atusb/board_hulusb.c
-new file mode 100644
-index 0000000..084714e
---- /dev/null
-+++ b/atusb/board_hulusb.c
-@@ -0,0 +1,179 @@
-+/*
-+ * fw/board_hulusb.c - Busware HUL Board-specific functions (for boot loader and application)
-+ *
-+ * Written 2017 by Filzmaier Josef
-+ * Based on fw/board_rzusb written and Copyright 2016 Stefan Schmidt
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include <avr/io.h>
-+#include <avr/interrupt.h>
-+#include <avr/boot.h>
-+
-+#define F_CPU 8000000UL
-+#include <util/delay.h>
-+
-+#include "usb.h"
-+#include "at86rf230.h"
-+#include "board.h"
-+#include "spi.h"
-+#include "usb/usb.h"
-+
-+static bool spi_initialized = 0;
-+
-+void reset_rf(void)
-+{
-+ /* set up all the outputs; default port value is 0 */
-+
-+ DDRB = 0;
-+ DDRC = 0;
-+ DDRD = 0;
-+ PORTB = 0;
-+ PORTC = 0;
-+ PORTD = 0;
-+
-+ OUT(LED_RED);
-+ OUT(LED_GREEN);
-+ SET(LED_RED); /* Leds are active low on HULUSB board */
-+ CLR(LED_GREEN); /* Green Led indicates the dongle is running */
-+ OUT(nRST_RF); /* this also resets the transceiver */
-+ OUT(SLP_TR);
-+
-+ spi_init();
-+
-+ /* AT86RF212 data sheet, Appendix B, p166 Power-On Reset procedure */
-+ /*-----------------------------------------------------------------*/
-+ CLR(SLP_TR);
-+ SET(nRST_RF);
-+ SET(nSS);
-+ _delay_us(400);
-+
-+ CLR(nRST_RF);
-+ _delay_us(2);
-+ SET(nRST_RF);
-+
-+ /* 5.1.4.5: Wait t10: 625 ns (min) */
-+
-+ _delay_us(2);
-+
-+ reg_write(REG_TRX_CTRL_0, 0x19);
-+
-+ change_state(TRX_CMD_FORCE_TRX_OFF);
-+ /*-----------------------------------------------------------------*/
-+
-+ /* we must restore TRX_CTRL_0 after each reset (7.7.4) */
-+
-+ set_clkm();
-+}
-+
-+void led_red(bool on) {
-+ if (on)
-+ CLR(LED_RED);
-+ else
-+ SET(LED_RED);
-+}
-+
-+void led_green(bool on) {
-+ if (on)
-+ CLR(LED_GREEN);
-+ else
-+ SET(LED_GREEN);
-+}
-+
-+void led(bool on)
-+{
-+ led_red(on);
-+}
-+
-+void set_clkm(void)
-+{
-+ /* CLKM is not connected on BUSWARE HUL and therefore it is running in
-+ * async mode. */
-+ reg_write(REG_TRX_CTRL_0, 0x00);
-+
-+ /* TX_AUTO_CRC_ON, default disabled */
-+ subreg_write(SR_TX_AUTO_CRC_ON, 1);
-+}
-+
-+void board_init(void)
-+{
-+ /* Disable the watchdog timer */
-+
-+ MCUSR = 0; /* Remove override */
-+ WDTCSR |= 1 << WDCE; /* Enable change */
-+ WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling
-+ change */
-+
-+ CLKPR = 1 << CLKPCE;
-+ /* We start with a 16 MHz/8 clock. Put the prescaler to 2. */
-+ CLKPR = 1 << CLKPS0;
-+
-+ get_sernum();
-+}
-+
-+void spi_begin(void)
-+{
-+ if (!spi_initialized)
-+ spi_init();
-+ CLR(nSS);
-+}
-+
-+void spi_off(void)
-+{
-+ spi_initialized = 0;
-+ SPCR &= ~(1 << SPE);
-+}
-+
-+void spi_init(void)
-+{
-+ SET(nSS);
-+ OUT(SCLK);
-+ OUT(MOSI);
-+ OUT(nSS);
-+ IN(MISO);
-+
-+ SPCR = (1 << SPE) | (1 << MSTR);
-+ SPSR = (1 << SPI2X);
-+
-+ spi_initialized = 1;
-+}
-+
-+void usb_init(void)
-+{
-+ USBCON |= 1 << FRZCLK; /* freeze the clock */
-+
-+ /* enable the PLL and wait for it to lock */
-+ /* TODO sheet page 50 For Atmel AT90USB128x only. Do not use with Atmel AT90USB64x. */
-+ /* FOR 8 XTAL Mhz only!!! */
-+ PLLCSR = ((1 << PLLP1) | (1 << PLLP0));
-+ PLLCSR |= 1 << PLLE;
-+ while (!(PLLCSR & (1 << PLOCK)));
-+
-+ UHWCON |= (1 << UVREGE);
-+
-+ USBCON &= ~((1 << USBE) | (1 << OTGPADE)); /* reset the controller */
-+ USBCON |= ((1 << USBE) | (1 << OTGPADE));
-+
-+ USBCON &= ~(1 << FRZCLK); /* thaw the clock */
-+
-+ UDCON &= ~(1 << DETACH); /* attach the pull-up */
-+ UDIEN = 1 << EORSTE; /* enable device interrupts */
-+ // UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */
-+
-+ ep_init();
-+}
-+
-+void board_app_init(void)
-+{
-+ /* enable INT0, trigger on rising edge */
-+ EICRA = 1 << ISC01 | 1 << ISC00;
-+ EIMSK = 1 << INT0;
-+}
-diff --git a/atusb/board_hulusb.h b/atusb/board_hulusb.h
-new file mode 100644
-index 0000000..a1dadf0
---- /dev/null
-+++ b/atusb/board_hulusb.h
-@@ -0,0 +1,66 @@
-+/*
-+ * fw/board_hulusb.h - Busware HUL Board-specific functions (for boot loader and application)
-+ *
-+ * Written 2017 by Filzmaier Josef
-+ * Based on fw/board_rzusb written and Copyright 2016 Stefan Schmidt
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef BOARD_HULUSB_H
-+#define BOARD_HULUSB_H
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#define LED_RED_PORT A
-+#define LED_GREEN_PORT A
-+#define LED_RED_BIT 3
-+#define LED_GREEN_BIT 4
-+#define LED_PORT LED_RED_PORT
-+#define LED_BIT LED_RED_BIT
-+
-+#define nRST_RF_PORT B
-+#define nRST_RF_BIT 5
-+#define SLP_TR_PORT B
-+#define SLP_TR_BIT 4
-+
-+#define SCLK_PORT B
-+#define SCLK_BIT 1
-+#define MOSI_PORT B
-+#define MOSI_BIT 2
-+
-+#define MISO_PORT B
-+#define MISO_BIT 3
-+#define nSS_PORT B
-+#define nSS_BIT 0
-+#define IRQ_RF_PORT D
-+#define IRQ_RF_BIT 4
-+
-+#define SR_TX_AUTO_CRC_ON 0x04, 0x20, 5
-+#define SR_CHANNEL 0x08, 0x1f, 0
-+
-+#define RG_CC_CTRL_1 (0x14)
-+
-+#define SPI_WAIT_DONE() while ((SPSR & (1 << SPIF)) == 0)
-+#define SPI_DATA SPDR
-+
-+void set_clkm(void);
-+void board_init(void);
-+
-+void led_red(bool on);
-+void led_green(bool on);
-+
-+void spi_begin(void);
-+void spi_off(void);
-+void spi_init(void);
-+
-+#ifdef DEBUG
-+void printStatus(void);
-+#define PRINT_STATUS() printStatus()
-+#endif
-+
-+#endif /* !BOARD_HULUSB_H */
-diff --git a/atusb/board_rzusb.c b/atusb/board_rzusb.c
-new file mode 100644
-index 0000000..e83d6fa
---- /dev/null
-+++ b/atusb/board_rzusb.c
-@@ -0,0 +1,169 @@
-+/*
-+ * fw/board_rzusb.c - RZUSB Board-specific functions (for boot loader and application)
-+ *
-+ * Written 2016 by Stefan Schmidt
-+ * Copyright 2016 Stefan Schmidt
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include <avr/io.h>
-+#include <avr/interrupt.h>
-+#include <avr/boot.h>
-+
-+#define F_CPU 8000000UL
-+#include <util/delay.h>
-+
-+#include "usb.h"
-+#include "at86rf230.h"
-+#include "board.h"
-+#include "spi.h"
-+#include "usb/usb.h"
-+
-+static bool spi_initialized = 0;
-+
-+void reset_rf(void)
-+{
-+ /* set up all the outputs; default port value is 0 */
-+
-+ DDRB = 0;
-+ DDRC = 0;
-+ DDRD = 0;
-+ PORTB = 0;
-+ PORTC = 0;
-+ PORTD = 0;
-+
-+ OUT(LED);
-+ OUT(nRST_RF); /* this also resets the transceiver */
-+ OUT(SLP_TR);
-+
-+ spi_init();
-+
-+ /* AT86RF231 data sheet, 12.4.13, reset pulse width: 625 ns (min) */
-+
-+ CLR(nRST_RF);
-+ _delay_us(2);
-+ SET(nRST_RF);
-+
-+ /* 12.4.14: SPI access latency after reset: 625 ns (min) */
-+
-+ _delay_us(2);
-+
-+ /* we must restore TRX_CTRL_0 after each reset (9.6.4) */
-+
-+ set_clkm();
-+}
-+
-+void led(bool on)
-+{
-+ if (on)
-+ SET(LED);
-+ else
-+ CLR(LED);
-+}
-+
-+void set_clkm(void)
-+{
-+ /* switch CLKM to 8 MHz */
-+
-+ /*
-+ * @@@ Note: Atmel advise against changing the external clock in
-+ * mid-flight. We should therefore switch to the RC clock first, then
-+ * crank up the external clock, and finally switch back to the external
-+ * clock. The clock switching procedure is described in the ATmega32U2
-+ * data sheet in secton 8.2.2.
-+ */
-+ spi_begin();
-+ spi_send(AT86RF230_REG_WRITE | REG_TRX_CTRL_0);
-+ spi_send(0x10);
-+ spi_end();
-+
-+ /* TX_AUTO_CRC_ON, default disabled */
-+ spi_begin();
-+ spi_send(AT86RF230_REG_WRITE | 0x05);
-+ spi_send(0x80);
-+ spi_end();
-+}
-+
-+void board_init(void)
-+{
-+ /* Disable the watchdog timer */
-+
-+ MCUSR = 0; /* Remove override */
-+ WDTCSR |= 1 << WDCE; /* Enable change */
-+ WDTCSR = 1 << WDCE; /* Disable watchdog while still enabling
-+ change */
-+
-+ CLKPR = 1 << CLKPCE;
-+ /* We start with a 16 MHz/8 clock. Put the prescaler to 2. */
-+ CLKPR = 1 << CLKPS0;
-+
-+ get_sernum();
-+}
-+
-+void spi_begin(void)
-+{
-+ if (!spi_initialized)
-+ spi_init();
-+ CLR(nSS);
-+}
-+
-+void spi_off(void)
-+{
-+ spi_initialized = 0;
-+ SPCR &= ~(1 << SPE);
-+}
-+
-+void spi_init(void)
-+{
-+ SET(nSS);
-+ OUT(SCLK);
-+ OUT(MOSI);
-+ OUT(nSS);
-+ IN(MISO);
-+
-+ SPCR = (1 << SPE) | (1 << MSTR);
-+ SPSR = (1 << SPI2X);
-+
-+ spi_initialized = 1;
-+}
-+
-+void usb_init(void)
-+{
-+ USBCON |= 1 << FRZCLK; /* freeze the clock */
-+
-+ /* enable the PLL and wait for it to lock */
-+ /* TODO sheet page 50 For Atmel AT90USB128x only. Do not use with Atmel AT90USB64x. */
-+ /* FOR 8 XTAL Mhz only!!! */
-+ PLLCSR = ((1 << PLLP1) | (1 << PLLP0));
-+ PLLCSR |= 1 << PLLE;
-+ while (!(PLLCSR & (1 << PLOCK)));
-+
-+ UHWCON |= (1 << UVREGE);
-+
-+ USBCON &= ~((1 << USBE) | (1 << OTGPADE)); /* reset the controller */
-+ USBCON |= ((1 << USBE) | (1 << OTGPADE));
-+
-+ USBCON &= ~(1 << FRZCLK); /* thaw the clock */
-+
-+ UDCON &= ~(1 << DETACH); /* attach the pull-up */
-+ UDIEN = 1 << EORSTE; /* enable device interrupts */
-+// UDCON |= 1 << RSTCPU; /* reset CPU on bus reset */
-+
-+ ep_init();
-+}
-+
-+void board_app_init(void)
-+{
-+ /* enable timer input capture 1, trigger on rising edge */
-+ TCCR1B = (1 << ICES1);
-+ TIFR1 = (1 << ICF1);
-+ TIMSK1 = (1 << ICIE1);
-+}
-diff --git a/atusb/board_rzusb.h b/atusb/board_rzusb.h
-new file mode 100644
-index 0000000..c2e518f
---- /dev/null
-+++ b/atusb/board_rzusb.h
-@@ -0,0 +1,48 @@
-+/*
-+ * fw/board_rzusb.h - RZUSB Board-specific functions and definitions
-+ *
-+ * Written 2016 by Stefan Schmidt
-+ * Copyright 2016 Stefan Schmidt
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef BOARD_RZUSB_H
-+#define BOARD_RZUSB_H
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#define LED_PORT D
-+#define LED_BIT 7
-+#define nRST_RF_PORT B
-+#define nRST_RF_BIT 5
-+#define SLP_TR_PORT B
-+#define SLP_TR_BIT 4
-+
-+#define SCLK_PORT B
-+#define SCLK_BIT 1
-+#define MOSI_PORT B
-+#define MOSI_BIT 2
-+
-+#define MISO_PORT B
-+#define MISO_BIT 3
-+#define nSS_PORT B
-+#define nSS_BIT 0
-+#define IRQ_RF_PORT D
-+#define IRQ_RF_BIT 4
-+
-+#define SPI_WAIT_DONE() while ((SPSR & (1 << SPIF)) == 0)
-+#define SPI_DATA SPDR
-+
-+void set_clkm(void);
-+void board_init(void);
-+
-+void spi_begin(void);
-+void spi_off(void);
-+void spi_init(void);
-+
-+#endif /* !BOARD_H */
-diff --git a/atusb/boot.c b/atusb/boot.c
-new file mode 100644
-index 0000000..6826ac6
---- /dev/null
-+++ b/atusb/boot.c
-@@ -0,0 +1,77 @@
-+/*
-+ * fw/boot.c - DFU boot loader for ATUSB
-+ *
-+ * Written 2008-2011 by Werner Almesberger
-+ * Copyright 2008-2011 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdint.h>
-+
-+#include <avr/io.h>
-+#include <avr/interrupt.h>
-+#include <avr/pgmspace.h>
-+
-+#define F_CPU 8000000UL
-+#include <util/delay.h>
-+
-+#include "usb.h"
-+#include "dfu.h"
-+
-+#include "board.h"
-+#include "spi.h"
-+#include "atusb/ep0.h"
-+
-+
-+#define MS_TO_LOOPS(ms) ((uint32_t) (ms)*335)
-+
-+
-+static void (*run_payload)(void) = 0;
-+
-+
-+int main(void)
-+{
-+ /*
-+ * pgm_read_byte gets cached and there doesn't seem to be any other
-+ * way to dissuade gcc from doing this.
-+ */
-+ volatile int zero = 0;
-+ uint32_t loop = 0;
-+
-+ board_init();
-+ reset_rf();
-+
-+ /* now we should be at 8 MHz */
-+
-+ usb_init();
-+ dfu_init();
-+
-+ /* move interrupt vectors to the boot loader */
-+ MCUCR = 1 << IVCE;
-+ MCUCR = 1 << IVSEL;
-+
-+ sei();
-+
-+ led(1);
-+
-+ while (loop != MS_TO_LOOPS(2500)) {
-+ if (dfu.state == dfuIDLE && pgm_read_byte(zero) != 0xff)
-+ loop++;
-+ else
-+ loop = 0;
-+ }
-+
-+ led(0);
-+
-+ cli();
-+
-+ usb_reset();
-+ run_payload();
-+
-+ while (1); /* not reached */
-+}
-diff --git a/atusb/descr.c b/atusb/descr.c
-new file mode 100644
-index 0000000..f96b0ee
---- /dev/null
-+++ b/atusb/descr.c
-@@ -0,0 +1,104 @@
-+/*
-+ * fw/descr.c - USB descriptors
-+ *
-+ * Written 2008-2011, 2014 by Werner Almesberger
-+ * Copyright 2008-2011, 2014 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include "usb.h"
-+#include "dfu.h"
-+#include "board.h"
-+
-+
-+#define LE(x) ((uint16_t) (x) & 0xff), ((uint16_t) (x) >> 8)
-+
-+/*
-+ * Device descriptor
-+ */
-+
-+const uint8_t device_descriptor[18] = {
-+ 18, /* bLength */
-+ USB_DT_DEVICE, /* bDescriptorType */
-+ LE(0x200), /* bcdUSB */
-+ USB_CLASS_VENDOR_SPEC, /* bDeviceClass */
-+ 0x00, /* bDeviceSubClass */
-+ 0x00, /* bDeviceProtocol */
-+ EP0_SIZE, /* bMaxPacketSize */
-+ LE(USB_VENDOR), /* idVendor */
-+ LE(USB_PRODUCT), /* idProduct */
-+ LE(0x0001), /* bcdDevice */
-+ 0, /* iManufacturer */
-+ 0, /* iProduct */
-+#ifdef HAS_BOARD_SERNUM
-+ 1, /* iSerialNumber */
-+#else
-+ 0, /* iSerialNumber */
-+#endif
-+ 1 /* bNumConfigurations */
-+};
-+
-+
-+/*
-+ * Our configuration
-+ *
-+ * We're always bus-powered.
-+ */
-+
-+const uint8_t config_descriptor[] = {
-+ 9, /* bLength */
-+ USB_DT_CONFIG, /* bDescriptorType */
-+#if 0
-+ LE(9+9+7+7), /* wTotalLength */
-+#else
-+ LE(9+9+7+9), /* wTotalLength */
-+#endif
-+ 2, /* bNumInterfaces */
-+ 1, /* bConfigurationValue (> 0 !) */
-+ 0, /* iConfiguration */
-+ USB_ATTR_BUS_POWERED, /* bmAttributes */
-+ ((BOARD_MAX_mA)+1)/2, /* bMaxPower */
-+
-+ /* Interface #0 */
-+
-+ 9, /* bLength */
-+ USB_DT_INTERFACE, /* bDescriptorType */
-+ 0, /* bInterfaceNumber */
-+ 0, /* bAlternateSetting */
-+ 1, /* bNumEndpoints */
-+ USB_CLASS_VENDOR_SPEC, /* bInterfaceClass */
-+ 0, /* bInterfaceSubClass */
-+ 0, /* bInterfaceProtocol */
-+ 0, /* iInterface */
-+
-+#if 0
-+ /* EP OUT */
-+
-+ 7, /* bLength */
-+ USB_DT_ENDPOINT, /* bDescriptorType */
-+ 0x01, /* bEndPointAddress */
-+ 0x02, /* bmAttributes (bulk) */
-+ LE(EP1_SIZE), /* wMaxPacketSize */
-+ 0, /* bInterval */
-+#endif
-+
-+#if 1
-+ /* EP IN */
-+
-+ 7, /* bLength */
-+ USB_DT_ENDPOINT, /* bDescriptorType */
-+ 0x81, /* bEndPointAddress */
-+ 0x02, /* bmAttributes (bulk) */
-+ LE(EP1_SIZE), /* wMaxPacketSize */
-+ 0, /* bInterval */
-+#endif
-+
-+ /* Interface #1 */
-+
-+ DFU_ITF_DESCR(1, 0, dfu_proto_runtime, 0)
-+};
-diff --git a/atusb/ep0.c b/atusb/ep0.c
-new file mode 100644
-index 0000000..fa43f3b
---- /dev/null
-+++ b/atusb/ep0.c
-@@ -0,0 +1,338 @@
-+/*
-+ * fw/ep0.c - EP0 extension protocol
-+ *
-+ * Written 2008-2011, 2013 by Werner Almesberger
-+ * Copyright 2008-2011, 2013 Werner Almesberger
-+ * Copyright 2015-2016 Stefan Schmidt
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+#include <string.h>
-+
-+#include <avr/io.h>
-+#include <avr/eeprom.h>
-+
-+#define F_CPU 8000000UL
-+#include <util/delay.h>
-+
-+#ifndef NULL
-+#define NULL 0
-+#endif
-+
-+#include "usb.h"
-+#include "dfu.h"
-+
-+#include "at86rf230.h"
-+#include "atusb/ep0.h"
-+#include "version.h"
-+#include "board.h"
-+#include "sernum.h"
-+#include "spi.h"
-+#include "mac.h"
-+
-+#ifdef ATUSB
-+#define HW_TYPE ATUSB_HW_TYPE_110131
-+#endif
-+
-+#ifdef RZUSB
-+#define HW_TYPE ATUSB_HW_TYPE_RZUSB
-+#endif
-+
-+#ifdef HULUSB
-+#define HW_TYPE ATUSB_HW_TYPE_HULUSB
-+#endif
-+
-+#ifdef DEBUG
-+#include "uart.h"
-+#include <stdio.h>
-+#define debug(FORMAT,args...) printf(FORMAT,##args)
-+#define error(FORMAT,args...) printf(FORMAT,##args)
-+#else
-+#define debug(...)
-+#define error(...)
-+#endif
-+
-+
-+static const uint8_t id[] = { EP0ATUSB_MAJOR, EP0ATUSB_MINOR, HW_TYPE };
-+static uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQI */
-+static uint8_t size;
-+
-+
-+static void do_eeprom_write(void *user)
-+{
-+ int i;
-+
-+ for (i = 0; i < size; i++)
-+ eeprom_update_byte((uint8_t*)i, buf[i]);
-+}
-+
-+static void do_buf_write(void *user)
-+{
-+ uint8_t i;
-+
-+ spi_begin();
-+ for (i = 0; i != size; i++)
-+ spi_send(buf[i]);
-+ spi_end();
-+}
-+
-+
-+#define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */
-+
-+
-+static bool my_setup(const struct setup_request *setup)
-+{
-+ uint16_t req = setup->bmRequestType | setup->bRequest << 8;
-+ unsigned tmp;
-+ uint8_t i;
-+ uint64_t tmp64;
-+
-+ switch (req) {
-+ case ATUSB_FROM_DEV(ATUSB_ID):
-+ debug("ATUSB_ID\n");
-+ if (setup->wLength > 3)
-+ return 0;
-+ usb_send(&eps[0], id, setup->wLength, NULL, NULL);
-+ return 1;
-+ case ATUSB_FROM_DEV(ATUSB_BUILD):
-+ debug("ATUSB_BUILD\n");
-+ tmp = build_number;
-+ for (i = BUILD_OFFSET-2; tmp; i--) {
-+ buf[i] = (tmp % 10)+'0';
-+ tmp /= 10;
-+ }
-+ buf[i] = '#';
-+ buf[BUILD_OFFSET-1] = ' ';
-+ for (size = 0; build_date[size]; size++)
-+ buf[BUILD_OFFSET+size] = build_date[size];
-+ size += BUILD_OFFSET-i;
-+ if (size > setup->wLength)
-+ return 0;
-+ usb_send(&eps[0], buf+i, size, NULL, NULL);
-+ return 1;
-+
-+ case ATUSB_TO_DEV(ATUSB_RESET):
-+ debug("ATUSB_RESET\n");
-+ reset_cpu();
-+ while (1);
-+
-+ case ATUSB_TO_DEV(ATUSB_RF_RESET):
-+ debug("ATUSB_RF_RESET\n");
-+ reset_rf();
-+ mac_reset();
-+ //ep_send_zlp(EP_CTRL);
-+ return 1;
-+
-+ case ATUSB_FROM_DEV(ATUSB_POLL_INT):
-+ debug("ATUSB_POLL_INT\n");
-+ if (setup->wLength < 1)
-+ return 0;
-+ *buf = read_irq();
-+ usb_send(&eps[0], buf, 1, NULL, NULL);
-+ return 1;
-+
-+ case ATUSB_FROM_DEV(ATUSB_TIMER):
-+ debug("ATUSB_TIMER\n");
-+ size = setup->wLength;
-+ if (size > sizeof(tmp64))
-+ size = sizeof(tmp64);
-+ tmp64 = timer_read();
-+ memcpy(buf, &tmp64, sizeof(tmp64));
-+ usb_send(&eps[0], buf, size, NULL, NULL);
-+ return 1;
-+
-+ case ATUSB_FROM_DEV(ATUSB_GPIO):
-+ debug("ATUSB_GPIO\n");
-+ if (setup->wLength < 3)
-+ return 0;
-+ if (!gpio(setup->wIndex, setup->wValue, setup->wValue >> 8,
-+ setup->wIndex >> 8, buf))
-+ return 0;
-+ usb_send(&eps[0], buf, 3, NULL, NULL);
-+ return 1;
-+ case ATUSB_TO_DEV(ATUSB_GPIO_CLEANUP):
-+ gpio_cleanup();
-+ return 1;
-+
-+ case ATUSB_TO_DEV(ATUSB_SLP_TR):
-+ debug("ATUSB_SLP_TR\n");
-+ slp_tr();
-+ return 1;
-+
-+ case ATUSB_TO_DEV(ATUSB_REG_WRITE):
-+ debug("ATUSB_REG_WRITE\n");
-+ spi_begin();
-+ spi_send(AT86RF230_REG_WRITE | setup->wIndex);
-+ spi_send(setup->wValue);
-+ spi_end();
-+ //ep_send_zlp(EP_CTRL);
-+ return 1;
-+ case ATUSB_FROM_DEV(ATUSB_REG_READ):
-+ debug("ATUSB_REG_READ\n");
-+ spi_begin();
-+ spi_send(AT86RF230_REG_READ | setup->wIndex);
-+ *buf = spi_recv();
-+ spi_end();
-+ usb_send(&eps[0], buf, 1, NULL, NULL);
-+ return 1;
-+
-+ case ATUSB_TO_DEV(ATUSB_BUF_WRITE):
-+ debug("ATUSB_BUF_WRITE\n");
-+ if (setup->wLength < 1)
-+ return 0;
-+ if (setup->wLength > MAX_PSDU)
-+ return 0;
-+ buf[0] = AT86RF230_BUF_WRITE;
-+ buf[1] = setup->wLength;
-+ size = setup->wLength+2;
-+ usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL);
-+ return 1;
-+ case ATUSB_FROM_DEV(ATUSB_BUF_READ):
-+ debug("ATUSB_BUF_READ\n");
-+ if (setup->wLength < 2) /* PHR+LQI */
-+ return 0;
-+ if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQI */
-+ return 0;
-+ spi_begin();
-+ spi_send(AT86RF230_BUF_READ);
-+ size = spi_recv();
-+ if (size >= setup->wLength)
-+ size = setup->wLength-1;
-+ for (i = 0; i != size+1; i++)
-+ buf[i] = spi_recv();
-+ spi_end();
-+ usb_send(&eps[0], buf, size+1, NULL, NULL);
-+ return 1;
-+
-+ case ATUSB_TO_DEV(ATUSB_SRAM_WRITE):
-+ debug("ATUSB_SRAM_WRITE\n");
-+ if (setup->wIndex > SRAM_SIZE)
-+ return 0;
-+ if (setup->wIndex+setup->wLength > SRAM_SIZE)
-+ return 0;
-+ buf[0] = AT86RF230_SRAM_WRITE;
-+ buf[1] = setup->wIndex;
-+ size = setup->wLength+2;
-+ usb_recv(&eps[0], buf+2, setup->wLength, do_buf_write, NULL);
-+ return 1;
-+ case ATUSB_FROM_DEV(ATUSB_SRAM_READ):
-+ debug("ATUSB_SRAM_READ\n");
-+ if (setup->wIndex > SRAM_SIZE)
-+ return 0;
-+ if (setup->wIndex+setup->wLength > SRAM_SIZE)
-+ return 0;
-+ spi_begin();
-+ spi_send(AT86RF230_SRAM_READ);
-+ spi_send(setup->wIndex);
-+ for (i = 0; i != setup->wLength; i++)
-+ buf[i] = spi_recv();
-+ spi_end();
-+ usb_send(&eps[0], buf, setup->wLength, NULL, NULL);
-+ return 1;
-+
-+ case ATUSB_TO_DEV(ATUSB_SPI_WRITE):
-+ size = setup->wLength+2;
-+ if (size > sizeof(buf))
-+ return 0;
-+ buf[0] = setup->wValue;
-+ buf[1] = setup->wIndex;
-+ if (setup->wLength)
-+ usb_recv(&eps[0], buf+2, setup->wLength,
-+ do_buf_write, NULL);
-+ else
-+ do_buf_write(NULL);
-+ return 1;
-+ case ATUSB_FROM_DEV(ATUSB_SPI_WRITE2_SYNC):
-+ spi_begin();
-+ spi_send(setup->wValue);
-+ spi_send(setup->wIndex);
-+ spi_end();
-+ buf[0] = irq_serial;
-+ if (setup->wLength)
-+ usb_send(&eps[0], buf, 1, NULL, NULL);
-+ return 1;
-+
-+ case ATUSB_FROM_DEV(ATUSB_SPI_READ1):
-+ case ATUSB_FROM_DEV(ATUSB_SPI_READ2):
-+ spi_begin();
-+ spi_send(setup->wValue);
-+ if (req == ATUSB_FROM_DEV(ATUSB_SPI_READ2))
-+ spi_send(setup->wIndex);
-+ for (i = 0; i != setup->wLength; i++)
-+ buf[i] = spi_recv();
-+ spi_end();
-+ usb_send(&eps[0], buf, setup->wLength, NULL, NULL);
-+ return 1;
-+
-+ case ATUSB_TO_DEV(ATUSB_RX_MODE):
-+ return mac_rx(setup->wValue);
-+ case ATUSB_TO_DEV(ATUSB_TX):
-+ return mac_tx(setup->wValue, setup->wIndex, setup->wLength);
-+ case ATUSB_TO_DEV(ATUSB_EUI64_WRITE):
-+ debug("ATUSB_EUI64_WRITE\n");
-+ usb_recv(&eps[0], buf, setup->wLength, do_eeprom_write, NULL);
-+ _delay_ms(100);
-+ reset_cpu();
-+ return 1;
-+
-+ case ATUSB_FROM_DEV(ATUSB_EUI64_READ):
-+ debug("ATUSB_EUI64_READ\n");
-+ eeprom_read_block(buf, (const void*)0, 8);
-+ usb_send(&eps[0], buf, 8, NULL, NULL);
-+ return 1;
-+
-+ default:
-+ error("Unrecognized SETUP: 0x%02x 0x%02x ...\n",
-+ setup->bmRequestType, setup->bRequest);
-+ return 0;
-+ }
-+}
-+
-+
-+static bool my_dfu_setup(const struct setup_request *setup)
-+{
-+ switch (setup->bmRequestType | setup->bRequest << 8) {
-+ case DFU_TO_DEV(DFU_DETACH):
-+ /* @@@ should use wTimeout */
-+ dfu.state = appDETACH;
-+ return 1;
-+ default:
-+ return dfu_setup_common(setup);
-+ }
-+}
-+
-+
-+static void my_set_interface(int nth)
-+{
-+ if (nth) {
-+ user_setup = my_dfu_setup;
-+ user_get_descriptor = dfu_my_descr;
-+ dfu.state = appIDLE;
-+ } else {
-+ user_setup = my_setup;
-+ user_get_descriptor = sernum_get_descr;
-+ }
-+}
-+
-+
-+static void my_reset(void)
-+{
-+ if (dfu.state == appDETACH)
-+ reset_cpu();
-+}
-+
-+
-+void ep0_init(void)
-+{
-+ user_setup = my_setup;
-+ user_set_interface = my_set_interface;
-+ my_set_interface(0);
-+ user_reset = my_reset;
-+}
-diff --git a/atusb/flash.c b/atusb/flash.c
-new file mode 100644
-index 0000000..1f8e59d
---- /dev/null
-+++ b/atusb/flash.c
-@@ -0,0 +1,97 @@
-+/*
-+ * fw/flash.c - Board-specific flash functions
-+ *
-+ * Written 2011, 2013-2015 by Werner Almesberger
-+ * Copyright 2011, 2013-2015 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include <avr/boot.h>
-+#include <avr/pgmspace.h>
-+
-+#include "dfu.h"
-+#include "board.h"
-+
-+
-+static uint32_t payload;
-+
-+
-+static void flash_start(void)
-+{
-+ payload = 0;
-+}
-+
-+
-+static bool flash_can_write(uint16_t size)
-+{
-+ return payload+size <= BOOT_ADDR;
-+}
-+
-+
-+static void flash_write(const uint8_t *buf, uint16_t size)
-+{
-+ static uint8_t last;
-+ const uint8_t *p;
-+
-+ for (p = buf; p != buf+size; p++) {
-+ if (!(payload & (SPM_PAGESIZE-1))) {
-+ boot_page_erase(payload);
-+ boot_spm_busy_wait();
-+ }
-+
-+ if (payload & 1)
-+ boot_page_fill(payload, last | (*p << 8));
-+ else
-+ last = *p;
-+ payload++;
-+
-+ if (!(payload & (SPM_PAGESIZE-1))) {
-+ boot_page_write(payload-SPM_PAGESIZE);
-+ boot_spm_busy_wait();
-+ }
-+ }
-+}
-+
-+
-+static void flash_end_write(void)
-+{
-+ if (payload & (SPM_PAGESIZE-1)) {
-+ boot_page_write(payload & ~(SPM_PAGESIZE-1));
-+ boot_spm_busy_wait();
-+ }
-+ boot_rww_enable();
-+}
-+
-+
-+static uint16_t flash_read(uint8_t *buf, uint16_t size)
-+{
-+ uint16_t got = 0;
-+
-+ while (size && payload != (uint32_t) FLASHEND+1) {
-+ *buf++ = pgm_read_byte(payload);
-+ payload++;
-+ size--;
-+ got++;
-+ }
-+ return got;
-+}
-+
-+
-+static const struct dfu_flash_ops flash_ops = {
-+ .start = flash_start,
-+ .can_write = flash_can_write,
-+ .write = flash_write,
-+ .end_write = flash_end_write,
-+ .read = flash_read,
-+};
-+
-+
-+const struct dfu_flash_ops *dfu_flash_ops = &flash_ops;
-diff --git a/atusb/include/at86rf230.h b/atusb/include/at86rf230.h
-new file mode 100644
-index 0000000..4c3ae22
---- /dev/null
-+++ b/atusb/include/at86rf230.h
-@@ -0,0 +1,402 @@
-+/*
-+ * include/at86rf230.h - AT86RF230/AT86RF231 protocol and register definitions
-+ *
-+ * Written 2008-2011 by Werner Almesberger
-+ * Copyright 2008-2011 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#ifndef AT86RF230_H
-+#define AT86RF230_H
-+
-+enum {
-+ AT86RF230_REG_WRITE = 0xc0, /* 11... */
-+ AT86RF230_REG_READ = 0x80, /* 10... */
-+ AT86RF230_BUF_WRITE = 0x60, /* 011... */
-+ AT86RF230_BUF_READ = 0x20, /* 001... */
-+ AT86RF230_SRAM_WRITE = 0x40, /* 010... */
-+ AT86RF230_SRAM_READ = 0x00 /* 000... */
-+};
-+
-+#define MAX_PSDU 127 /* octets, see AT86RF230 manual section 8.1 */
-+#define SRAM_SIZE 128
-+
-+
-+/* --- Registers ----------------------------------------------------------- */
-+
-+enum {
-+ REG_TRX_STATUS = 0x01,
-+ REG_TRX_STATE = 0x02,
-+ REG_TRX_CTRL_0 = 0x03,
-+
-+ REG_TRX_CTRL_1 = 0x04, /* 231 only */
-+
-+ REG_PHY_TX_PWR = 0x05,
-+ REG_PHY_RSSI = 0x06,
-+ REG_PHY_ED_LEVEL = 0x07,
-+ REG_PHY_CC_CCA = 0x08,
-+ REG_CCA_THRES = 0x09,
-+
-+ REG_RX_CTRL = 0x0a, /* 231 only */
-+ REG_SFD_VALUE = 0x0b, /* 231 only */
-+ REG_TRX_CTRL_2 = 0x0c, /* 231 only */
-+ REG_ANT_DIV = 0x0d, /* 231 only */
-+
-+ REG_IRQ_MASK = 0x0e,
-+ REG_IRQ_STATUS = 0x0f,
-+ REG_VREG_CTRL = 0x10,
-+ REG_BATMON = 0x11,
-+ REG_XOSC_CTRL = 0x12,
-+
-+ REG_RX_SYN = 0x15, /* 231 only */
-+ REG_XAH_CTRL_1 = 0x17, /* 231 only */
-+ REG_FTN_CTRL = 0x18, /* 231 only */
-+
-+ REG_PLL_CF = 0x1a,
-+ REL_PLL_DCU = 0x1b,
-+ REG_PART_NUM = 0x1c,
-+ REG_VERSION_NUM = 0x1d,
-+ REG_MAN_ID_0 = 0x1e,
-+ REG_MAN_ID_1 = 0x1f,
-+ REG_SHORT_ADDR_0 = 0x20,
-+ REG_SHORT_ADDR_1 = 0x21,
-+ REG_PAN_ID_0 = 0x22,
-+ REG_PAN_ID_1 = 0x23,
-+ REG_IEEE_ADDR_0 = 0x24,
-+ REG_IEEE_ADDR_1 = 0x25,
-+ REG_IEEE_ADDR_2 = 0x26,
-+ REG_IEEE_ADDR_3 = 0x27,
-+ REG_IEEE_ADDR_4 = 0x28,
-+ REG_IEEE_ADDR_5 = 0x29,
-+ REG_IEEE_ADDR_6 = 0x2a,
-+ REG_IEEE_ADDR_7 = 0x2b,
-+
-+ REG_XAH_CTRL_0 = 0x2c, /* XAH_CTRL in 230 */
-+ REG_CSMA_SEED_0 = 0x2d,
-+ REG_CSMA_SEED_1 = 0x2e,
-+ REG_CSMA_BE = 0x2f, /* 231 only */
-+
-+ REG_CONT_TX_0 = 0x36,
-+ REG_CONT_TX_1 = 0x3d, /* 230 only */
-+};
-+
-+/* --- TRX_STATUS --- ------------------------------------------------------ */
-+
-+#define CCA_DONE (1 << 7)
-+#define CCA_STATUS (1 << 6)
-+
-+#define TRX_STATUS_SHIFT 0
-+#define TRX_STATUS_MASK 0x1f
-+
-+enum {
-+ TRX_STATUS_P_ON = 0x00, /* reset default */
-+ TRX_STATUS_BUSY_RX = 0x01,
-+ TRX_STATUS_BUSY_TX = 0x02,
-+ TRX_STATUS_RX_ON = 0x06,
-+ TRX_STATUS_TRX_OFF = 0x08,
-+ TRX_STATUS_PLL_ON = 0x09,
-+ TRX_STATUS_SLEEP = 0x0f,
-+ TRX_STATUS_BUSY_RX_AACK = 0x11,
-+ TRX_STATUS_BUSY_TX_ARET = 0x12,
-+ TRX_STATUS_RX_AACK_ON = 0x16,
-+ TRX_STATUS_TX_ARET_ON = 0x19,
-+ TRX_STATUS_RX_ON_NOCLK = 0x1c,
-+ TRX_STATUS_RX_AACK_ON_NOCLK = 0x1d,
-+ TRX_STATUS_BUSY_RX_AACK_NOCLK = 0x1e,
-+ TRX_STATUS_TRANSITION = 0x1f /* ..._IN_PROGRESS */
-+};
-+
-+/* --- TRX_STATE ----------------------------------------------------------- */
-+
-+#define TRAC_STATUS_SHIFT 5
-+#define TRAC_STATUS_MASK 7
-+
-+enum {
-+ TRAC_STATUS_SUCCESS = 0, /* reset default */
-+ TRAC_STATUS_SUCCESS_DATA_PENDING = 1,
-+ TRAC_STATUS_SUCCESS_WAIT_FOR_ACK = 2, /* 231 only */
-+ TRAC_STATUS_CHANNEL_ACCESS_FAILURE = 3,
-+ TRAC_STATUS_NO_ACK = 5,
-+ TRAC_STATUS_INVALID = 7
-+};
-+
-+#define TRX_CMD_SHIFT 0
-+#define TRX_CMD_MASK 0x1f
-+
-+enum {
-+ TRX_CMD_NOP = 0x00, /* reset default */
-+ TRX_CMD_TX_START = 0x02,
-+ TRX_CMD_FORCE_TRX_OFF = 0x03,
-+ TRX_CMD_FORCE_PLL_ON = 0x04, /* 231 only */
-+ TRX_CMD_RX_ON = 0x06,
-+ TRX_CMD_TRX_OFF = 0x08,
-+ TRX_CMD_PLL_ON = 0x09,
-+ TRX_CMD_RX_AACK_ON = 0x16,
-+ TRX_CMD_TX_ARET_ON = 0x19,
-+};
-+
-+/* --- TRX_CTRL_0 ---------------------------------------------------------- */
-+
-+#define PAD_IO_SHIFT 6
-+#define PAD_IO_MASK 3
-+
-+enum {
-+ PAD_IO_2mA, /* reset default */
-+ PAD_IO_4mA,
-+ PAD_IO_6mA,
-+ PAD_IO_8mA
-+};
-+
-+#define PAD_IO_CLKM_SHIFT 4
-+#define PAD_IO_CLKM_MASK 3
-+
-+enum {
-+ PAD_IO_CLKM_2mA,
-+ PAD_IO_CLKM_4mA, /* reset default */
-+ PAD_IO_CLKM_5mA,
-+ PAD_IO_CLKM_8mA,
-+};
-+
-+#define CLKM_SHA_SEL (1 << 3)
-+
-+#define CLKM_CTRL_SHIFT 0
-+#define CLKM_CTRL_MASK 7
-+
-+enum {
-+ CLKM_CTRL_OFF = 0,
-+ CLKM_CTRL_1MHz = 1, /* reset default */
-+ CLKM_CTRL_2MHz = 2,
-+ CLKM_CTRL_4MHz = 3,
-+ CLKM_CTRL_8MHz = 4,
-+ CLKM_CTRL_16MHz = 5
-+};
-+
-+/* --- TRX_CTRL_1 (231 only) ----------------------------------------------- */
-+
-+#define PA_EXT_EN (1 << 7)
-+#define IRQ_2_EXT_EN (1 << 6)
-+#define TX_AUTO_CRC_ON (1 << 5) /* 231 location */
-+#define RX_BL_CTRL (1 << 4)
-+
-+#define SPI_CMD_MODE_SHIFT 2
-+#define SPI_CMD_MODE_MASK 3
-+
-+enum {
-+ SPI_CMD_MODE_EMPTY = 0, /* reset default */
-+ SPI_CMD_MODE_TRX_STATUS = 1,
-+ SPI_CMD_MODE_PHY_RSSI = 2,
-+ SPI_CMD_MODE_IRQ_STATUS = 3,
-+};
-+
-+#define IRQ_MASK_MODE (1 << 1)
-+#define IRQ_POLARITY (1 << 0)
-+
-+/* --- PHY_TX_PWR ---------------------------------------------------------- */
-+
-+#define TX_AUTO_CRC_ON_230 (1 << 7) /* 230 location */
-+
-+#define PA_BUF_LT_SHIFT 6
-+#define PA_BUF_LT_MASK 3
-+
-+#define PA_LT_SHIFT 4
-+#define PA_LT_MASK 3
-+
-+#define TX_PWR_SHIFT 0
-+#define TX_PWR_MASK 0x0f
-+
-+/* --- PHY_RSSI ------------------------------------------------------------ */
-+
-+#define RX_CRC_VALID (1 << 7)
-+
-+#define RND_VALUE_SHIFT 5 /* 231 only */
-+#define RND_VALUE_MASK 3
-+
-+#define RSSI_SHIFT 0
-+#define RSSI_MASK 0x1f
-+
-+/* --- PHY_CC_CCA ---------------------------------------------------------- */
-+
-+#define CCA_REQUEST (1 << 7)
-+
-+#define CCA_MODE_SHIFT 5
-+#define CCA_MODE_MASK 3
-+
-+enum {
-+ CCA_MODE_CARRIER_OR_ENERGY = 0, /* 231 only */
-+ CCA_MODE_ENERGY = 1, /* reset default */
-+ CCA_MODE_CARRIER = 2,
-+ CCA_MODE_CARRIER_AND_ENERGY = 3
-+};
-+
-+#define CHANNEL_SHIFT 0
-+#define CHANNEL_MASK 0x1f
-+
-+/* --- CCA_THRES ----------------------------------------------------------- */
-+
-+#define CCA_ED_THRES_SHIFT 0
-+#define CCA_ED_THRES_MASK 0x0f
-+
-+/* --- RX_CTRL (231 only) -------------------------------------------------- */
-+
-+#define PDT_THRES_SHIFT 0
-+#define PDT_THRES_MASK 0x0f
-+
-+enum {
-+ PDT_THRES_DEFAULT = 0x07, /* reset default */
-+ PDT_THRES_DIVERSITY = 0x03,
-+};
-+
-+/* --- TRX_CTRL_2 (231 only) ----------------------------------------------- */
-+
-+#define RX_SAFE_MODE (1 << 7)
-+
-+#define OQPSK_DATA_RATE_SHIFT 0
-+#define OQPSK_DATA_RATE_MASK 3
-+
-+enum {
-+ OQPSK_DATA_RATE_250 = 0, /* reset default */
-+ OQPSK_DATA_RATE_500 = 1,
-+ OQPSK_DATA_RATE_1000 = 2,
-+ OQPSK_DATA_RATE_2000 = 3
-+};
-+
-+/* --- ANT_DIV (231 only) -------------------------------------------------- */
-+
-+#define ANT_SEL (1 << 7)
-+#define ANT_DIV_EN (1 << 3)
-+#define ANT_EXT_SW_EN (1 << 2)
-+
-+#define ANT_CTRL_SHIFT 0
-+#define ANT_CTRL_MASK 3
-+
-+enum {
-+ ANT_CTRL_ANT_0 = 1,
-+ ANT_CTRL_ANT_1 = 2,
-+ ANT_CTRL_NODIV = 3, /* reset default */
-+};
-+
-+/* --- IRQ_MASK/IRQ_STATUS ------------------------------------------------- */
-+
-+enum {
-+ IRQ_PLL_LOCK = 1 << 0,
-+ IRQ_PLL_UNLOCK = 1 << 1,
-+ IRQ_RX_START = 1 << 2,
-+ IRQ_TRX_END = 1 << 3,
-+ IRQ_CCA_ED_DONE = 1 << 4, /* 231 only */
-+ IRQ_AMI = 1 << 5, /* 231 only */
-+ IRQ_TRX_UR = 1 << 6,
-+ IRQ_BAT_LOW = 1 << 7
-+};
-+
-+/* --- VREG_CTRL ----------------------------------------------------------- */
-+
-+#define AVREG_EXT (1 << 7)
-+#define AVDD_OK (1 << 6)
-+#define DVREG_EXT (1 << 3)
-+#define DVDD_OK (1 << 2)
-+
-+/* --- BATMON -------------------------------------------------------------- */
-+
-+#define BATMON_OK (1 << 5)
-+#define BATMON_HR (1 << 4)
-+
-+#define BATMON_VTH_SHIFT 0
-+#define BATMON_VTH_MASK 0x0f
-+
-+/* --- XOSC_CTRL ----------------------------------------------------------- */
-+
-+#define XTAL_MODE_SHIFT 4
-+#define XTAL_MODE_MASK 0x0f
-+
-+enum {
-+ XTAL_MODE_OFF = 0x0, /* 230 only */
-+ XTAL_MODE_EXT = 0x4,
-+ XTAL_MODE_INT = 0xf /* reset default */
-+};
-+
-+#define XTAL_TRIM_SHIFT 4
-+#define XTAL_TRIM_MASK 0x0f
-+
-+/* --- RX_SYN (231 only) --------------------------------------------------- */
-+
-+#define RX_PDT_DIS (1 << 7)
-+
-+#define RX_PDT_LEVEL_SHIFT 0
-+#define RX_PDT_LEVEL_MASK 0xf
-+
-+/* --- XAH_CTRL_1 (231 only) ----------------------------------------------- */
-+
-+#define AACK_FLTR_RES_FT (1 << 5)
-+#define AACK_UPLD_RES_FT (1 << 4)
-+#define AACK_ACK_TIME (1 << 2)
-+#define AACK_PROM_MODE (1 << 1)
-+
-+/* --- FTN_CTRL (231 only) ------------------------------------------------- */
-+
-+#define FTN_START (1 << 7)
-+
-+/* --- PLL_CF -------------------------------------------------------------- */
-+
-+#define PLL_CF_START (1 << 7)
-+
-+/* --- PLL_DCU ------------------------------------------------------------- */
-+
-+#define PLL_DCU_START (1 << 7)
-+
-+/* --- XAH_CTRL_0 (XAH_CTRL in 230) ---------------------------------------- */
-+
-+#define MAX_FRAME_RETRIES_SHIFT 4
-+#define MAX_FRAME_RETRIES_MASK 0x0f
-+
-+#define MAX_CSMA_RETRIES_SHIFT 1
-+#define MAX_CSMA_RETRIES_MASK 0x07
-+
-+#define SLOTTED_OPERATION (1 << 0) /* 231 only */
-+
-+/* --- CSMA_SEED_1 --------------------------------------------------------- */
-+
-+#define MIN_BE_SHIFT_230 6 /* 230 location */
-+#define MIN_BE_MASK_230 3
-+
-+#define AACK_FVN_MODE_SHIFT 6 /* 231 only */
-+#define AACK_FVN_MODE_MASK 3
-+
-+enum {
-+ AACK_FVN_MODE_0 = 0,
-+ AACK_FVN_MODE_01 = 1, /* reset default */
-+ AACK_FVN_MODE_012 = 2,
-+ AACK_FVN_MODE_ANY = 3
-+};
-+
-+#define AACK_SET_PD (1 << 5)
-+#define AACK_DIS_ACK (1 << 4) /* 231 only */
-+#define I_AM_COORD (1 << 3)
-+
-+#define CSMA_SEED_1_SHIFT 0
-+#define CSMA_SEED_1_MASK 7
-+
-+/* --- CSMA_BE ------------------------------------------------------------- */
-+
-+#define MAX_BE_SHIFT 4
-+#define MAX_BE_MASK 0x0f
-+
-+#define MIN_BE_SHIFT 0 /* 231 location */
-+#define MIN_BE_MASK 0x0f
-+
-+/* --- REG_CONT_TX_0 ------------------------------------------------------- */
-+
-+#define CONT_TX_MAGIC 0x0f
-+
-+/* --- REG_CONT_TX_1 (230 only) -------------------------------------------- */
-+
-+#define CONT_TX_MOD 0x00 /* modulated */
-+#define CONT_TX_M2M 0x10 /* f_CH-2 MHz */
-+#define CONT_TX_M500K 0x80 /* f_CH-0.5 MHz */
-+#define CONT_TX_P500K 0xc0 /* f_CH+0.5 MHz */
-+
-+#endif /* !AT86RF230_H */
-diff --git a/atusb/include/atusb/atusb.h b/atusb/include/atusb/atusb.h
-new file mode 100644
-index 0000000..555d14b
---- /dev/null
-+++ b/atusb/include/atusb/atusb.h
-@@ -0,0 +1,97 @@
-+/*
-+ * atusb.h - Definitions shared between kernel and ATUSB firmware
-+ *
-+ * Written 2013 by Werner Almesberger <werner@almesberger.net>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation, version 2, or
-+ * (at your option) any later version.
-+ *
-+ * This file should be identical for kernel and firmware.
-+ * Kernel: drivers/net/ieee802154/atusb.h
-+ * Firmware: ben-wpan/atusb/fw/include/atusb/atusb.h
-+ */
-+
-+#ifndef _ATUSB_H
-+#define _ATUSB_H
-+
-+#define ATUSB_VENDOR_ID 0x20b7 /* Qi Hardware*/
-+#define ATUSB_PRODUCT_ID 0x1540 /* 802.15.4, device 0 */
-+ /* -- - - */
-+
-+#define ATUSB_BUILD_SIZE 256 /* maximum build version/date message length */
-+
-+/* Commands to our device. Make sure this is synced with the firmware */
-+enum atusb_requests {
-+ ATUSB_ID = 0x00, /* system status/control grp */
-+ ATUSB_BUILD,
-+ ATUSB_RESET,
-+ ATUSB_RF_RESET = 0x10, /* debug/test group */
-+ ATUSB_POLL_INT,
-+ ATUSB_TEST, /* atusb-sil only */
-+ ATUSB_TIMER,
-+ ATUSB_GPIO,
-+ ATUSB_SLP_TR,
-+ ATUSB_GPIO_CLEANUP,
-+ ATUSB_REG_WRITE = 0x20, /* transceiver group */
-+ ATUSB_REG_READ,
-+ ATUSB_BUF_WRITE,
-+ ATUSB_BUF_READ,
-+ ATUSB_SRAM_WRITE,
-+ ATUSB_SRAM_READ,
-+ ATUSB_SPI_WRITE = 0x30, /* SPI group */
-+ ATUSB_SPI_READ1,
-+ ATUSB_SPI_READ2,
-+ ATUSB_SPI_WRITE2_SYNC,
-+ ATUSB_RX_MODE = 0x40, /* HardMAC group */
-+ ATUSB_TX,
-+ ATUSB_EUI64_WRITE = 0x50, /* Parameter in EEPROM grp */
-+ ATUSB_EUI64_READ,
-+};
-+
-+enum {
-+ ATUSB_HW_TYPE_100813, /* 2010-08-13 */
-+ ATUSB_HW_TYPE_101216, /* 2010-12-16 */
-+ ATUSB_HW_TYPE_110131, /* 2011-01-31, ATmega32U2-based */
-+ ATUSB_HW_TYPE_RZUSB, /* Atmel Raven USB dongle with at86rf230 */
-+ ATUSB_HW_TYPE_HULUSB, /* Busware HUL USB dongle with at86rf212 */
-+};
-+
-+/*
-+ * Direction bRequest wValue wIndex wLength
-+ *
-+ * ->host ATUSB_ID - - 3
-+ * ->host ATUSB_BUILD - - #bytes
-+ * host-> ATUSB_RESET - - 0
-+ *
-+ * host-> ATUSB_RF_RESET - - 0
-+ * ->host ATUSB_POLL_INT - - 1
-+ * host-> ATUSB_TEST - - 0
-+ * ->host ATUSB_TIMER - - #bytes (6)
-+ * ->host ATUSB_GPIO dir+data mask+p# 3
-+ * host-> ATUSB_SLP_TR - - 0
-+ * host-> ATUSB_GPIO_CLEANUP - - 0
-+ *
-+ * host-> ATUSB_REG_WRITE value addr 0
-+ * ->host ATUSB_REG_READ - addr 1
-+ * host-> ATUSB_BUF_WRITE - - #bytes
-+ * ->host ATUSB_BUF_READ - - #bytes
-+ * host-> ATUSB_SRAM_WRITE - addr #bytes
-+ * ->host ATUSB_SRAM_READ - addr #bytes
-+ *
-+ * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes
-+ * ->host ATUSB_SPI_READ1 byte0 - #bytes
-+ * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes
-+ * ->host ATUSB_SPI_WRITE2_SYNC byte0 byte1 0/1
-+ *
-+ * host-> ATUSB_RX_MODE on - 0
-+ * host-> ATUSB_TX flags ack_seq #bytes
-+ * host-> ATUSB_EUI64_WRITE - - #bytes (8)
-+ * ->host ATUSB_EUI64_READ - - #bytes (8)
-+ */
-+
-+#define ATUSB_REQ_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN)
-+#define ATUSB_REQ_TO_DEV (USB_TYPE_VENDOR | USB_DIR_OUT)
-+
-+#endif /* !_ATUSB_H */
-diff --git a/atusb/include/atusb/ep0.h b/atusb/include/atusb/ep0.h
-new file mode 100644
-index 0000000..7777345
---- /dev/null
-+++ b/atusb/include/atusb/ep0.h
-@@ -0,0 +1,64 @@
-+/*
-+ * include/atusb/ep0.h - EP0 extension protocol
-+ *
-+ * Written 2008-2011, 2013 by Werner Almesberger
-+ * Copyright 2008-2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#ifndef EP0_H
-+#define EP0_H
-+
-+#include <atusb/atusb.h>
-+
-+
-+/*
-+ * EP0 protocol:
-+ *
-+ * 0.0 initial release
-+ * 0.1 addition of ATUSB_TEST
-+ * 0.2 First public release
-+ * 0.3 ATUSB_EUI64_READ/WRITE for permanent EUI64 handling
-+ * Support to run the firmware on Atmel Raven USB dongles
-+ * Remove FCS frame check from firmware and leave it to the driver
-+ * Use extended operation mode for TX for automatic ACK handling
-+ */
-+
-+#define EP0ATUSB_MAJOR 0 /* EP0 protocol, major revision */
-+#define EP0ATUSB_MINOR 3 /* EP0 protocol, minor revision */
-+
-+
-+/*
-+ * bmRequestType:
-+ *
-+ * D7 D6..5 D4...0
-+ * | | |
-+ * direction (0 = host->dev)
-+ * type (2 = vendor)
-+ * recipient (0 = device)
-+ */
-+
-+#ifndef USB_TYPE_VENDOR
-+#define USB_TYPE_VENDOR 0x40
-+#endif
-+
-+#ifndef USB_DIR_IN
-+#define USB_DIR_IN 0x80
-+#endif
-+
-+#ifndef USB_DIR_OUT
-+#define USB_DIR_OUT 0x00
-+#endif
-+
-+#define ATUSB_FROM_DEV(req) (ATUSB_REQ_FROM_DEV | (req) << 8)
-+#define ATUSB_TO_DEV(req) (ATUSB_REQ_TO_DEV | (req) << 8)
-+
-+
-+void ep0_init(void);
-+
-+#endif /* !EP0_H */
-diff --git a/atusb/mac.c b/atusb/mac.c
-new file mode 100644
-index 0000000..835002c
---- /dev/null
-+++ b/atusb/mac.c
-@@ -0,0 +1,250 @@
-+/*
-+ * fw/mac.c - HardMAC functions
-+ *
-+ * Written 2011, 2013 by Werner Almesberger
-+ * Copyright 2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#include <stddef.h>
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include "usb.h"
-+
-+#include "at86rf230.h"
-+#include "spi.h"
-+#include "board.h"
-+#include "mac.h"
-+
-+#define RX_BUFS 3
-+
-+
-+bool (*mac_irq)(void) = NULL;
-+
-+
-+static uint8_t rx_buf[RX_BUFS][MAX_PSDU+2]; /* PHDR+payload+LQ */
-+static uint8_t tx_buf[MAX_PSDU];
-+static uint8_t tx_size = 0;
-+static bool txing = 0;
-+static bool queued_tx_ack = 0;
-+static uint8_t next_seq, this_seq, queued_seq;
-+
-+
-+/* ----- Receive buffer management ----------------------------------------- */
-+
-+
-+static uint8_t rx_in = 0, rx_out = 0;
-+
-+
-+static inline void next_buf(uint8_t *index)
-+{
-+ *index = (*index+1) % RX_BUFS;
-+}
-+
-+
-+/* ----- Interrupt handling ------------------------------------------------ */
-+
-+
-+static void rx_done(void *user);
-+static void tx_ack_done(void *user);
-+
-+
-+static void usb_next(void)
-+{
-+ const uint8_t *buf;
-+
-+ if (rx_in != rx_out) {
-+ buf = rx_buf[rx_out];
-+ led(1);
-+ usb_send(&eps[1], buf, buf[0]+2, rx_done, NULL);
-+ }
-+
-+ if (queued_tx_ack) {
-+ usb_send(&eps[1], &queued_seq, 1, tx_ack_done, NULL);
-+ queued_tx_ack = 0;
-+ }
-+}
-+
-+
-+static void tx_ack_done(void *user)
-+{
-+ usb_next();
-+}
-+
-+static void rx_done(void *user)
-+{
-+ led(0);
-+ next_buf(&rx_out);
-+ usb_next();
-+#ifdef AT86RF230
-+ /* slap at86rf230 - reduce fragmentation issue */
-+ change_state(TRX_STATUS_RX_AACK_ON);
-+#endif
-+}
-+
-+
-+static void receive_frame(void)
-+{
-+ uint8_t size;
-+ uint8_t *buf;
-+
-+ spi_begin();
-+ spi_io(AT86RF230_BUF_READ);
-+
-+ size = spi_recv();
-+ if (!size || (size & 0x80)) {
-+ spi_end();
-+ return;
-+ }
-+
-+ buf = rx_buf[rx_in];
-+ spi_recv_block(buf+1, size+1);
-+ spi_end();
-+
-+ buf[0] = size;
-+ next_buf(&rx_in);
-+
-+ if (eps[1].state == EP_IDLE)
-+ usb_next();
-+}
-+
-+
-+static bool handle_irq(void)
-+{
-+ uint8_t irq;
-+
-+ irq = reg_read(REG_IRQ_STATUS);
-+ if (!(irq & IRQ_TRX_END))
-+ return 1;
-+
-+ if (txing) {
-+ if (eps[1].state == EP_IDLE) {
-+ usb_send(&eps[1], &this_seq, 1, tx_ack_done, NULL);
-+ } else {
-+ queued_tx_ack = 1;
-+ queued_seq = this_seq;
-+ }
-+ txing = 0;
-+ return 1;
-+ }
-+
-+ /* likely */
-+ if (eps[1].state == EP_IDLE || rx_in != rx_out)
-+ receive_frame();
-+
-+ return 1;
-+}
-+
-+
-+/* ----- TX/RX ------------------------------------------------------------- */
-+
-+
-+bool mac_rx(int on)
-+{
-+ if (on) {
-+ mac_irq = handle_irq;
-+ reg_read(REG_IRQ_STATUS);
-+ change_state(TRX_CMD_RX_AACK_ON);
-+ } else {
-+ mac_irq = NULL;
-+ change_state(TRX_CMD_FORCE_TRX_OFF);
-+ txing = 0;
-+ }
-+ return 1;
-+}
-+
-+
-+static void do_tx(void *user)
-+{
-+ uint16_t timeout = 0xffff;
-+ uint8_t status;
-+ uint8_t i;
-+
-+ /*
-+ * If we time out here, the host driver will time out waiting for the
-+ * TRX_END acknowledgement.
-+ */
-+ do {
-+ if (!--timeout)
-+ return;
-+ status = reg_read(REG_TRX_STATUS) & TRX_STATUS_MASK;
-+ }
-+ while (status != TRX_STATUS_RX_ON && status != TRX_STATUS_RX_AACK_ON);
-+
-+#ifdef AT86RF231
-+ /*
-+ * We use TRX_CMD_FORCE_PLL_ON instead of TRX_CMD_PLL_ON because a new
-+ * reception may have begun while we were still working on the previous
-+ * one.
-+ */
-+ reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON);
-+#endif
-+#ifdef AT86RF230
-+ /*
-+ * at86rf230 doesn't support force change, nevetherless this works
-+ * somehow
-+ */
-+ reg_write(REG_TRX_STATE, TRX_CMD_PLL_ON);
-+#endif
-+#ifdef AT86RF212
-+ /*
-+ * We use TRX_CMD_FORCE_PLL_ON instead of TRX_CMD_PLL_ON because a new
-+ * reception may have begun while we were still working on the previous
-+ * one.
-+ */
-+ reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON);
-+#endif
-+
-+ handle_irq();
-+
-+ spi_begin();
-+ spi_send(AT86RF230_BUF_WRITE);
-+ spi_send(tx_size+2); /* CRC */
-+ for (i = 0; i != tx_size; i++)
-+ spi_send(tx_buf[i]);
-+ spi_end();
-+
-+ change_state(TRX_STATUS_TX_ARET_ON);
-+
-+ slp_tr();
-+
-+ txing = 1;
-+ this_seq = next_seq;
-+
-+ /*
-+ * Wait until we reach BUSY_TX_ARET, so that we command the transition to
-+ * RX_AACK_ON which will be executed upon TX completion.
-+ */
-+ change_state(TRX_CMD_PLL_ON);
-+ change_state(TRX_CMD_RX_AACK_ON);
-+}
-+
-+
-+bool mac_tx(uint16_t flags, uint8_t seq, uint16_t len)
-+{
-+ if (len > MAX_PSDU)
-+ return 0;
-+ tx_size = len;
-+ next_seq = seq;
-+ usb_recv(&eps[0], tx_buf, len, do_tx, NULL);
-+ return 1;
-+}
-+
-+
-+void mac_reset(void)
-+{
-+ mac_irq = NULL;
-+ txing = 0;
-+ queued_tx_ack = 0;
-+ rx_in = rx_out = 0;
-+ next_seq = this_seq = queued_seq = 0;
-+
-+ /* enable CRC and PHY_RSSI (with RX_CRC_VALID) in SPI status return */
-+ reg_write(REG_TRX_CTRL_1,
-+ TX_AUTO_CRC_ON | SPI_CMD_MODE_PHY_RSSI << SPI_CMD_MODE_SHIFT);
-+}
-diff --git a/atusb/mac.h b/atusb/mac.h
-new file mode 100644
-index 0000000..f3c92fb
---- /dev/null
-+++ b/atusb/mac.h
-@@ -0,0 +1,26 @@
-+/*
-+ * fw/mac.h - HardMAC functions
-+ *
-+ * Written 2011, 2013 by Werner Almesberger
-+ * Copyright 2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef MAC_H
-+#define MAC_H
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+
-+extern bool (*mac_irq)(void);
-+
-+bool mac_rx(int on);
-+bool mac_tx(uint16_t flags, uint8_t seq, uint16_t len);
-+void mac_reset(void);
-+
-+#endif /* !MAC_H */
-diff --git a/atusb/sernum.c b/atusb/sernum.c
-new file mode 100644
-index 0000000..41e434c
---- /dev/null
-+++ b/atusb/sernum.c
-@@ -0,0 +1,47 @@
-+/*
-+ * fw/sernum.c - ATUSB serial number
-+ *
-+ * Written 2008-2011, 2013 by Werner Almesberger
-+ * Copyright 2008-2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include "usb.h"
-+
-+#include "board.h"
-+#include "sernum.h"
-+
-+
-+static const uint8_t string_descriptor_0[] = {
-+ 4, /* blength */
-+ USB_DT_STRING, /* bDescriptorType */
-+ LE(USB_LANGID_ENGLISH_US) /* wLANGID[0] */
-+};
-+
-+
-+bool sernum_get_descr(uint8_t type, uint8_t index, const uint8_t **reply,
-+ uint8_t *size)
-+{
-+ if (type != USB_DT_STRING)
-+ return 0;
-+ switch (index) {
-+ case 0:
-+ *reply = string_descriptor_0;
-+ *size = sizeof(string_descriptor_0);
-+ return 1;
-+ case 1:
-+ *reply = board_sernum;
-+ *size = sizeof(board_sernum);
-+ return 1;
-+ default:
-+ return 0;
-+ }
-+}
-diff --git a/atusb/sernum.h b/atusb/sernum.h
-new file mode 100644
-index 0000000..31a8e27
---- /dev/null
-+++ b/atusb/sernum.h
-@@ -0,0 +1,37 @@
-+/*
-+ * fw/sernum.h - ATUSB serial number
-+ *
-+ * Written 2011, 2013 by Werner Almesberger
-+ * Copyright 2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef SERNUM_H
-+#define SERNUM_H
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include "board.h"
-+
-+
-+#ifdef HAS_BOARD_SERNUM
-+
-+bool sernum_get_descr(uint8_t type, uint8_t index, const uint8_t **reply,
-+ uint8_t *size);
-+
-+#else /* HAS_BOARD_SERNUM */
-+
-+static inline bool sernum_get_descr(uint8_t type, uint8_t index,
-+ const uint8_t **reply, uint8_t *size)
-+{
-+ return 0;
-+}
-+
-+#endif /* !HAS_BOARD_SERNUM */
-+
-+#endif /* !SERNUM_H */
-diff --git a/atusb/spi.c b/atusb/spi.c
-new file mode 100644
-index 0000000..3fa5715
---- /dev/null
-+++ b/atusb/spi.c
-@@ -0,0 +1,51 @@
-+/*
-+ * fw/spi.c - ATmega8 family SPI I/O
-+ *
-+ * Written 2011, 2013 by Werner Almesberger
-+ * Copyright 2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include <avr/io.h>
-+
-+#include "board.h"
-+#include "spi.h"
-+
-+
-+uint8_t spi_io(uint8_t v)
-+{
-+// while (!(UCSR1A & 1 << UDRE1));
-+ SPI_DATA = v;
-+ SPI_WAIT_DONE();
-+ return SPI_DATA;
-+}
-+
-+
-+void spi_end(void)
-+{
-+// while (!(UCSR1A & 1 << TXC1));
-+ SET(nSS);
-+}
-+
-+
-+void spi_recv_block(uint8_t *buf, uint8_t n)
-+{
-+ if (!n)
-+ return;
-+ SPI_DATA = 0;
-+ while (--n) {
-+ SPI_WAIT_DONE();
-+ *buf++ = SPI_DATA;
-+ SPI_DATA = 0;
-+ }
-+ SPI_WAIT_DONE();
-+ *buf++ = SPI_DATA;
-+}
-diff --git a/atusb/spi.h b/atusb/spi.h
-new file mode 100644
-index 0000000..6e04f4e
---- /dev/null
-+++ b/atusb/spi.h
-@@ -0,0 +1,30 @@
-+/*
-+ * fw/spi.h - ATmega8 family SPI I/O
-+ *
-+ * Written 2011, 2013 by Werner Almesberger
-+ * Copyright 2011, 2013 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+#ifndef SPI_H
-+#define SPI_H
-+
-+#include <stdint.h>
-+
-+
-+void spi_begin(void);
-+uint8_t spi_io(uint8_t v);
-+void spi_end(void);
-+void spi_off(void);
-+void spi_init(void);
-+
-+#define spi_send(v) (void) spi_io(v)
-+#define spi_recv(v) spi_io(0)
-+
-+void spi_recv_block(uint8_t *buf, uint8_t n);
-+
-+#endif /* !SPI_H */
-diff --git a/atusb/uart.c b/atusb/uart.c
-new file mode 100644
-index 0000000..44bec27
---- /dev/null
-+++ b/atusb/uart.c
-@@ -0,0 +1,64 @@
-+/*
-+ * fw/uart.h - Functions needed for debugging over uart
-+ *
-+ * Code adapted from http://www.roboternetz.de/wissen/index.php/UART_mit_avr-gcc
-+ * and http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
-+ *
-+ * Published under the Creative Commons Share-Alike licence
-+ * https://creativecommons.org/licenses/by-sa/2.0/de/
-+ *
-+ * S. Salewski 2007
-+ *
-+ * Adapted by
-+ * Josef Filzmaier 2017
-+ */
-+
-+#include <avr/io.h>
-+#include "uart.h"
-+
-+#define USART_BAUD 38400UL
-+#define F_CPU 8000000UL
-+
-+#define Wait_USART_Ready() while (!(UCSR1A & (1<<UDRE1)))
-+#define UART_UBRR (F_CPU/(16L*USART_BAUD)-1)
-+
-+// initialize USART, 8N1 mode
-+void
-+uart_init(void)
-+{
-+/* TODO: Find a working configuration for uart for the atmega32u2 */
-+#if CHIP == at90usb1287
-+ CLKPR = (1 << CLKPCE);
-+ CLKPR = 0; // clock prescaler == 0, so we have 16 MHz mpu frequency
-+ UBRR1 = UART_UBRR;
-+ UCSR1C = (1 << UCSZ10) | (1 << UCSZ11);
-+ UCSR1B = (1 << TXEN1);
-+ do
-+ {
-+ UDR1;
-+ }
-+ while (UCSR1A & (1 << RXC1));
-+#endif
-+
-+}
-+
-+int uart_write_char(char c, FILE* stream)
-+{
-+ if (c == '\n'){
-+ uart_new_line();
-+ }
-+ else {
-+ Wait_USART_Ready();
-+ UDR1 = c;
-+ }
-+ return 0;
-+}
-+
-+void
-+uart_new_line(void)
-+{
-+ Wait_USART_Ready();
-+ UDR1 = '\r';
-+ Wait_USART_Ready();
-+ UDR1 = '\n';
-+}
-diff --git a/atusb/uart.h b/atusb/uart.h
-new file mode 100644
-index 0000000..4810f9c
---- /dev/null
-+++ b/atusb/uart.h
-@@ -0,0 +1,25 @@
-+/*
-+ * fw/uart.h - Functions needed for debugging over uart
-+ *
-+ * Code adapted from http://www.roboternetz.de/wissen/index.php/UART_mit_avr-gcc
-+ * and http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
-+ *
-+ * Published under the Creative Commons Share-Alike licence
-+ * https://creativecommons.org/licenses/by-sa/2.0/de/
-+ *
-+ * S. Salewski 2007
-+ *
-+ * Adapted by
-+ * Josef Filzmaier 2017
-+ */
-+
-+#ifndef UART_H_
-+#define UART_H_
-+
-+#include <stdio.h>
-+
-+void uart_init(void);
-+int uart_write_char(char c, FILE* stream);
-+void uart_new_line(void);
-+
-+#endif /* UART_H_ */
-diff --git a/atusb/usb/atu2.c b/atusb/usb/atu2.c
-new file mode 100644
-index 0000000..98158bf
---- /dev/null
-+++ b/atusb/usb/atu2.c
-@@ -0,0 +1,247 @@
-+/*
-+ * fw/usb/atu2.c - Chip-specific driver for Atmel ATxxxU2 USB chips
-+ *
-+ * Written 2008-2011, 2013-2014 by Werner Almesberger
-+ * Copyright 2008-2011, 2013-2014 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+/*
-+ * Known issues:
-+ * - no suspend/resume
-+ * - we don't call back after failed transmissions,
-+ * - we don't reset the EP buffer after failed receptions
-+ * - enumeration often encounters an error -71 (from which it recovers)
-+ */
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#define F_CPU 8000000UL
-+#include <util/delay.h>
-+
-+#include <avr/io.h>
-+#include <avr/interrupt.h>
-+#include "usb.h"
-+#include "board.h"
-+
-+
-+#ifndef NULL
-+#define NULL 0
-+#endif
-+
-+#if 1
-+#define BUG_ON(cond) do { if (cond) panic(); } while (0)
-+#else
-+#define BUG_ON(cond)
-+#endif
-+
-+
-+struct ep_descr eps[NUM_EPS];
-+
-+
-+static uint16_t usb_read_word(void)
-+{
-+ uint8_t low;
-+
-+ low = UEDATX;
-+ return low | UEDATX << 8;
-+}
-+
-+
-+static void enable_addr(void *user)
-+{
-+ while (!(UEINTX & (1 << TXINI)));
-+ UDADDR |= 1 << ADDEN;
-+}
-+
-+
-+void set_addr(uint8_t addr)
-+{
-+ UDADDR = addr;
-+ usb_send(&eps[0], NULL, 0, enable_addr, NULL);
-+}
-+
-+
-+void usb_ep_change(struct ep_descr *ep)
-+{
-+ if (ep->state == EP_TX) {
-+ UENUM = ep-eps;
-+ UEIENX |= 1 << TXINE;
-+ }
-+}
-+
-+
-+static bool ep_setup(void)
-+{
-+ struct setup_request setup;
-+
-+ BUG_ON(UEBCLX < 8);
-+
-+ setup.bmRequestType = UEDATX;
-+ setup.bRequest = UEDATX;
-+ setup.wValue = usb_read_word();
-+ setup.wIndex = usb_read_word();
-+ setup.wLength = usb_read_word();
-+
-+ if (!handle_setup(&setup))
-+ return 0;
-+ if (!(setup.bmRequestType & 0x80) && eps[0].state == EP_IDLE)
-+ usb_send(&eps[0], NULL, 0, NULL, NULL);
-+ return 1;
-+}
-+
-+
-+static bool ep_rx(struct ep_descr *ep)
-+{
-+ uint8_t size;
-+
-+ size = UEBCLX;
-+ if (size > ep->end-ep->buf)
-+ return 0;
-+ while (size--)
-+ *ep->buf++ = UEDATX;
-+ if (ep->buf == ep->end) {
-+ ep->state = EP_IDLE;
-+ if (ep->callback)
-+ ep->callback(ep->user);
-+// if (ep == &eps[0])
-+ usb_send(ep, NULL, 0, NULL, NULL);
-+ }
-+ return 1;
-+}
-+
-+
-+static void ep_tx(struct ep_descr *ep)
-+{
-+ uint8_t size = ep->end-ep->buf;
-+ uint8_t left;
-+
-+ if (size > ep->size)
-+ size = ep->size;
-+ for (left = size; left; left--)
-+ UEDATX = *ep->buf++;
-+ if (size == ep->size)
-+ return;
-+ ep->state = EP_IDLE;
-+}
-+
-+
-+static void handle_ep(int n)
-+{
-+ struct ep_descr *ep = eps+n;
-+ uint8_t mask;
-+
-+ UENUM = n;
-+ if (UEINTX & (1 << RXSTPI)) {
-+ /* @@@ EP_RX. EP_TX: cancel */
-+ ep->state = EP_IDLE;
-+ if (!ep_setup())
-+ goto stall;
-+ UEINTX = ~(1 << RXSTPI);
-+ }
-+ if (UEINTX & (1 << RXOUTI)) {
-+ /* @@ EP_TX: cancel */
-+ if (ep->state != EP_RX)
-+ goto stall;
-+ if (!ep_rx(ep))
-+ goto stall;
-+ /* @@@ gcc 4.5.2 wants this cast */
-+ UEINTX = (uint8_t) ~(1 << RXOUTI | 1 << FIFOCON);
-+ }
-+ if (UEINTX & (1 << STALLEDI)) {
-+ ep->state = EP_IDLE;
-+ UEINTX = ~(1 << STALLEDI);
-+ }
-+ if (UEINTX & (1 << TXINI)) {
-+ /* @@ EP_RX: cancel (?) */
-+ if (ep->state == EP_TX) {
-+ ep_tx(ep);
-+ mask = 1 << TXINI;
-+ if (n)
-+ mask |= 1 << FIFOCON;
-+ UEINTX = ~mask;
-+ if (ep->state == EP_IDLE && ep->callback)
-+ ep->callback(ep->user);
-+ } else {
-+ UEIENX &= ~(1 << TXINE);
-+ }
-+ }
-+ return;
-+
-+stall:
-+ UEINTX = ~(1 << RXSTPI | 1 << RXOUTI | 1 << STALLEDI);
-+ ep->state = EP_IDLE;
-+ UECONX |= 1 << STALLRQ;
-+}
-+
-+
-+void ep_init(void)
-+{
-+ UENUM = 0;
-+ UECONX = (1 << RSTDT) | (1 << EPEN); /* enable */
-+ UECFG0X = 0; /* control, direction is ignored */
-+ UECFG1X = 3 << EPSIZE0; /* 64 bytes */
-+ UECFG1X |= 1 << ALLOC;
-+
-+ while (!(UESTA0X & (1 << CFGOK)));
-+
-+ UEIENX =
-+ (1 << RXSTPE) | (1 << RXOUTE) | (1 << STALLEDE) | (1 << TXINE);
-+
-+ eps[0].state = EP_IDLE;
-+ eps[0].size = 64;
-+
-+#ifndef BOOT_LOADER
-+
-+ UENUM = 1;
-+ UECONX = (1 << RSTDT) | (1 << EPEN); /* enable */
-+ UECFG0X = (1 << EPTYPE1) | (1 << EPDIR); /* bulk IN */
-+ UECFG1X = 3 << EPSIZE0; /* 64 bytes */
-+ UECFG1X |= 1 << ALLOC;
-+
-+ while (!(UESTA0X & (1 << CFGOK)));
-+
-+ UEIENX = (1 << STALLEDE) | (1 << TXINE);
-+
-+ eps[1].state = EP_IDLE;
-+ eps[1].size = 64;
-+
-+#endif
-+}
-+
-+
-+ISR(USB_GEN_vect)
-+{
-+ uint8_t flags;
-+
-+ flags = UDINT;
-+ if (flags & (1 << EORSTI)) {
-+ if (user_reset)
-+ user_reset();
-+ ep_init();
-+ UDINT = ~(1 << EORSTI);
-+ }
-+}
-+
-+
-+ISR(USB_COM_vect)
-+{
-+ uint8_t flags, i;
-+
-+ flags = UEINT;
-+ for (i = 0; i != NUM_EPS; i++)
-+ if (flags & (1 << i))
-+ handle_ep(i);
-+}
-+
-+
-+void usb_reset(void)
-+{
-+ UDCON |= 1 << DETACH; /* detach the pull-up */
-+ _delay_ms(1);
-+}
-diff --git a/atusb/usb/dfu.c b/atusb/usb/dfu.c
-new file mode 100644
-index 0000000..c84a28d
---- /dev/null
-+++ b/atusb/usb/dfu.c
-@@ -0,0 +1,260 @@
-+/*
-+ * boot/dfu.c - DFU protocol engine
-+ *
-+ * Written 2008-2011, 2013-2015 by Werner Almesberger
-+ * Copyright 2008-2011, 2013-2015 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+/*
-+ * http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf
-+ */
-+
-+/*
-+ * A few, erm, shortcuts:
-+ *
-+ * - we don't bother with the app* states since DFU is all this firmware does
-+ * - after DFU_DNLOAD, we just block until things are written, so we never
-+ * enter dfuDNLOAD_SYNC or dfuDNBUSY
-+ * - no dfuMANIFEST_SYNC, dfuMANIFEST, or dfuMANIFEST_WAIT_RESET
-+ * - to keep our buffers small, we only accept EP0-sized blocks
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include "usb.h"
-+#include "dfu.h"
-+
-+#include "board.h"
-+
-+
-+#ifndef NULL
-+#define NULL 0
-+#endif
-+
-+#define debug(...)
-+#define error(...)
-+
-+
-+#ifndef DFU_ALT_SETTINGS
-+#define DFU_ALT_SETTINGS 1
-+#endif
-+
-+#ifndef DFU_ALT_NAME_0_IDX
-+#define DFU_ALT_NAME_0_IDX 0
-+#endif
-+
-+#ifndef DFU_ALT_NAME_1_IDX
-+#define DFU_ALT_NAME_1_IDX 0
-+#endif
-+
-+#ifndef DFU_ALT_NAME_2_IDX
-+#define DFU_ALT_NAME_2_IDX 0
-+#endif
-+
-+
-+const uint8_t device_descriptor[] = {
-+ 18, /* bLength */
-+ USB_DT_DEVICE, /* bDescriptorType */
-+ LE(0x100), /* bcdUSB */
-+ USB_CLASS_APP_SPEC, /* bDeviceClass */
-+ 0x00, /* bDeviceSubClass (per interface) */
-+ 0x00, /* bDeviceProtocol (per interface) */
-+ EP0_SIZE, /* bMaxPacketSize */
-+ LE(DFU_USB_VENDOR), /* idVendor */
-+ LE(DFU_USB_PRODUCT), /* idProduct */
-+ LE(0x0001), /* bcdDevice */
-+ 0, /* iManufacturer */
-+ 0, /* iProduct */
-+#ifdef HAS_BOARD_SERNUM
-+ 1, /* iSerialNumber */
-+#else
-+ 0, /* iSerialNumber */
-+#endif
-+ 1 /* bNumConfigurations */
-+};
-+
-+
-+const uint8_t config_descriptor[] = {
-+ 9, /* bLength */
-+ USB_DT_CONFIG, /* bDescriptorType */
-+ LE(9+9*DFU_ALT_SETTINGS), /* wTotalLength */
-+ 1, /* bNumInterfaces */
-+ 1, /* bConfigurationValue (> 0 !) */
-+ 0, /* iConfiguration */
-+// USB_ATTR_SELF_POWERED | USB_ATTR_BUS_POWERED,
-+ USB_ATTR_BUS_POWERED, /* bmAttributes */
-+ ((BOARD_MAX_mA)+1)/2, /* bMaxPower */
-+
-+ /* Interface #0 */
-+
-+ DFU_ITF_DESCR(0, 0, dfu_proto_dfu, DFU_ALT_NAME_0_IDX)
-+#if DFU_ALT_SETTINGS > 1
-+ DFU_ITF_DESCR(0, 1, dfu_proto_dfu, DFU_ALT_NAME_1_IDX)
-+#endif
-+#if DFU_ALT_SETTINGS > 2
-+ DFU_ITF_DESCR(0, 2, dfu_proto_dfu, DFU_ALT_NAME_2_IDX)
-+#endif
-+};
-+
-+
-+static uint16_t next_block = 0;
-+static bool did_download;
-+
-+
-+static uint8_t buf[EP0_SIZE];
-+
-+
-+static void block_write(void *user)
-+{
-+ uint16_t *size = user;
-+
-+ dfu_flash_ops->write(buf, *size);
-+}
-+
-+
-+static bool block_receive(uint16_t length)
-+{
-+ static uint16_t size;
-+
-+ if (!dfu_flash_ops->can_write(length)) {
-+ dfu.state = dfuERROR;
-+ dfu.status = errADDRESS;
-+ return 0;
-+ }
-+ if (length > EP0_SIZE) {
-+ dfu.state = dfuERROR;
-+ dfu.status = errUNKNOWN;
-+ return 0;
-+ }
-+ size = length;
-+ usb_recv(&eps[0], buf, size, block_write, &size);
-+ return 1;
-+}
-+
-+
-+static bool block_transmit(uint16_t length)
-+{
-+ uint16_t got;
-+
-+ if (length > EP0_SIZE) {
-+ dfu.state = dfuERROR;
-+ dfu.status = errUNKNOWN;
-+ return 1;
-+ }
-+ got = dfu_flash_ops->read(buf, length);
-+ if (got < length) {
-+ length = got;
-+ dfu.state = dfuIDLE;
-+ }
-+ usb_send(&eps[0], buf, length, NULL, NULL);
-+ return 1;
-+}
-+
-+
-+static bool my_setup(const struct setup_request *setup)
-+{
-+ bool ok;
-+
-+ switch (setup->bmRequestType | setup->bRequest << 8) {
-+ case DFU_TO_DEV(DFU_DETACH):
-+ debug("DFU_DETACH\n");
-+ /*
-+ * The DFU spec says thay this is sent in protocol 1 only.
-+ * However, dfu-util also sends it to get out of DFU mode,
-+ * so we just don't make a fuss and ignore it.
-+ */
-+ return 1;
-+ case DFU_TO_DEV(DFU_DNLOAD):
-+ debug("DFU_DNLOAD\n");
-+ if (dfu.state == dfuIDLE) {
-+ next_block = setup->wValue;
-+ dfu_flash_ops->start();
-+ }
-+ else if (dfu.state != dfuDNLOAD_IDLE) {
-+ error("bad state\n");
-+ return 0;
-+ }
-+ if (dfu.state != dfuIDLE && setup->wValue == next_block-1) {
-+ debug("retransmisson\n");
-+ return 1;
-+ }
-+ if (setup->wValue != next_block) {
-+ debug("bad block (%d vs. %d)\n",
-+ setup->wValue, next_block);
-+ dfu.state = dfuERROR;
-+ dfu.status = errUNKNOWN;
-+ return 1;
-+ }
-+ if (!setup->wLength) {
-+ debug("DONE\n");
-+ dfu_flash_ops->end_write();
-+ dfu.state = dfuIDLE;
-+ did_download = 1;
-+ return 1;
-+ }
-+ ok = block_receive(setup->wLength);
-+ next_block++;
-+ dfu.state = dfuDNLOAD_IDLE;
-+ return ok;
-+ case DFU_FROM_DEV(DFU_UPLOAD):
-+ debug("DFU_UPLOAD\n");
-+ if (dfu.state == dfuIDLE) {
-+ next_block = setup->wValue;
-+ dfu_flash_ops->start();
-+ }
-+ else if (dfu.state != dfuUPLOAD_IDLE)
-+ return 0;
-+ if (dfu.state != dfuIDLE && setup->wValue == next_block-1) {
-+ debug("retransmisson\n");
-+ /* @@@ try harder */
-+ dfu.state = dfuERROR;
-+ dfu.status = errUNKNOWN;
-+ return 1;
-+ }
-+ if (setup->wValue != next_block) {
-+ debug("bad block (%d vs. %d)\n",
-+ setup->wValue, next_block);
-+ dfu.state = dfuERROR;
-+ dfu.status = errUNKNOWN;
-+ return 1;
-+ }
-+ ok = block_transmit(setup->wLength);
-+ next_block++;
-+ dfu.state = dfuUPLOAD_IDLE;
-+ return ok;
-+ case DFU_TO_DEV(DFU_ABORT):
-+ debug("DFU_ABORT\n");
-+ dfu.state = dfuIDLE;
-+ dfu.status = OK;
-+ return 1;
-+ default:
-+ return dfu_setup_common(setup);
-+ }
-+}
-+
-+
-+static void my_reset(void)
-+{
-+#if 0
-+ /* @@@ not nice -- think about where this should go */
-+ extern void run_payload(void);
-+
-+ if (did_download)
-+ run_payload();
-+#endif
-+}
-+
-+
-+void dfu_init(void)
-+{
-+ user_setup = my_setup;
-+ user_get_descriptor = dfu_my_descr;
-+ user_reset = my_reset;
-+}
-diff --git a/atusb/usb/dfu.h b/atusb/usb/dfu.h
-new file mode 100644
-index 0000000..bc35bbc
---- /dev/null
-+++ b/atusb/usb/dfu.h
-@@ -0,0 +1,119 @@
-+/*
-+ * boot/dfu.h - DFU protocol constants and data structures
-+ *
-+ * Written 2008, 2011, 2013-2015 by Werner Almesberger
-+ * Copyright 2008, 2011, 2013-2015 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#ifndef DFU_H
-+#define DFU_H
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include "usb.h"
-+
-+
-+enum dfu_request {
-+ DFU_DETACH,
-+ DFU_DNLOAD,
-+ DFU_UPLOAD,
-+ DFU_GETSTATUS,
-+ DFU_CLRSTATUS,
-+ DFU_GETSTATE,
-+ DFU_ABORT,
-+};
-+
-+
-+enum dfu_status {
-+ OK,
-+ errTARGET,
-+ errFILE,
-+ errWRITE,
-+ errERASE,
-+ errCHECK_ERASED,
-+ errPROG,
-+ errVERIFY,
-+ errADDRESS,
-+ errNOTDONE,
-+ errFIRMWARE,
-+ errVENDOR,
-+ errUSBR,
-+ errPOR,
-+ errUNKNOWN,
-+ errSTALLEDPKT,
-+};
-+
-+
-+enum dfu_state {
-+ appIDLE,
-+ appDETACH,
-+ dfuIDLE,
-+ dfuDNLOAD_SYNC,
-+ dfuDNBUSY,
-+ dfuDNLOAD_IDLE,
-+ dfuMANIFEST_SYNC,
-+ dfuMANIFEST,
-+ dfuMANIFEST_WAIT_RESET,
-+ dfuUPLOAD_IDLE,
-+ dfuERROR
-+};
-+
-+enum dfu_itf_proto {
-+ dfu_proto_runtime = 1, /* Runtime protocol */
-+ dfu_proto_dfu = 2, /* DFU mode protocol */
-+};
-+
-+
-+#define DFU_DT_FUNCTIONAL 0x21 /* DFU FUNCTIONAL descriptor type */
-+
-+
-+#define DFU_TO_DEV(req) (0x21 | (req) << 8)
-+#define DFU_FROM_DEV(req) (0xa1 | (req) << 8)
-+
-+
-+struct dfu {
-+ uint8_t status; /* bStatus */
-+ uint8_t toL, toM, toH; /* bwPollTimeout */
-+ uint8_t state; /* bState */
-+ uint8_t iString;
-+};
-+
-+
-+#define DFU_ITF_DESCR(itf, alt, proto, idx) \
-+ 9, /* bLength */ \
-+ USB_DT_INTERFACE, /* bDescriptorType */ \
-+ (itf), /* bInterfaceNumber */ \
-+ (alt), /* bAlternateSetting */ \
-+ 0, /* bNumEndpoints */ \
-+ 0xfe, /* bInterfaceClass (application specific) */ \
-+ 0x01, /* bInterfaceSubClass (device fw upgrade) */ \
-+ (proto), /* bInterfaceProtocol (dfu_proto_*) */ \
-+ (idx), /* iInterface */
-+
-+
-+struct dfu_flash_ops {
-+ void (*start)(void);
-+ bool (*can_write)(uint16_t size);
-+ void (*write)(const uint8_t *buf, uint16_t size);
-+ void (*end_write)(void);
-+ uint16_t (*read)(uint8_t *buf, uint16_t size);
-+};
-+
-+extern struct dfu dfu;
-+extern const struct dfu_flash_ops *dfu_flash_ops;
-+
-+
-+bool dfu_setup_common(const struct setup_request *setup);
-+bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
-+ uint8_t *size);
-+
-+void dfu_init(void);
-+
-+#endif /* !DFU_H */
-diff --git a/atusb/usb/dfu_common.c b/atusb/usb/dfu_common.c
-new file mode 100644
-index 0000000..9b6feef
---- /dev/null
-+++ b/atusb/usb/dfu_common.c
-@@ -0,0 +1,101 @@
-+/*
-+ * boot/dfu_common.c - DFU protocol engine parts common to App/DFU
-+ *
-+ * Written 2008-2011, 2013-2014 by Werner Almesberger
-+ * Copyright 2008-2011, 2013-2014 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+/*
-+ * http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf
-+ */
-+
-+/*
-+ * A few, erm, shortcuts:
-+ *
-+ * - we don't bother with the app* states since DFU is all this firmware does
-+ * - after DFU_DNLOAD, we just block until things are written, so we never
-+ * enter dfuDNLOAD_SYNC or dfuDNBUSY
-+ * - no dfuMANIFEST_SYNC, dfuMANIFEST, or dfuMANIFEST_WAIT_RESET
-+ * - to keep our buffers small, we only accept EP0-sized blocks
-+ */
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include "usb.h"
-+#include "dfu.h"
-+
-+#include "board.h"
-+#include "../sernum.h"
-+
-+
-+#ifndef NULL
-+#define NULL 0
-+#endif
-+
-+#define debug(...)
-+#define error(...)
-+
-+
-+static const uint8_t functional_descriptor[] = {
-+ 9, /* bLength */
-+ DFU_DT_FUNCTIONAL, /* bDescriptorType */
-+ 0xf, /* bmAttributes (claim omnipotence :-) */
-+ LE(0xffff), /* wDetachTimeOut (we're very patient) */
-+ LE(EP0_SIZE), /* wTransferSize */
-+ LE(0x101), /* bcdDFUVersion */
-+};
-+
-+
-+/*
-+ * The worst-case activity would be flashing a one page and erasing another
-+ * one, would should take less than 10 ms. A 100 ms timeout ought to be plenty.
-+ */
-+
-+struct dfu dfu = {
-+ OK, /* bStatus */
-+ LE(100), 0, /* bwPollTimeout, 100 ms */
-+ dfuIDLE, /* bState */
-+ 0, /* iString */
-+};
-+
-+
-+bool dfu_setup_common(const struct setup_request *setup)
-+{
-+ switch (setup->bmRequestType | setup->bRequest << 8) {
-+ case DFU_FROM_DEV(DFU_GETSTATUS):
-+ debug("DFU_GETSTATUS\n");
-+ usb_send(&eps[0], (uint8_t *) &dfu, sizeof(dfu), NULL, NULL);
-+ return 1;
-+ case DFU_TO_DEV(DFU_CLRSTATUS):
-+ debug("DFU_CLRSTATUS\n");
-+ dfu.state = dfuIDLE;
-+ dfu.status = OK;
-+ return 1;
-+ case DFU_FROM_DEV(DFU_GETSTATE):
-+ debug("DFU_GETSTATE\n");
-+ usb_send(&eps[0], &dfu.state, 1, NULL, NULL);
-+ return 1;
-+ default:
-+ error("DFU rt %x, rq%x ?\n",
-+ setup->bmRequestType, setup->bRequest);
-+ return 0;
-+ }
-+}
-+
-+
-+bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
-+ uint8_t *size)
-+{
-+ if (type != DFU_DT_FUNCTIONAL)
-+ return sernum_get_descr(type, index, reply, size);
-+ *reply = functional_descriptor;
-+ *size = sizeof(functional_descriptor);
-+ return 1;
-+}
-diff --git a/atusb/usb/usb.c b/atusb/usb/usb.c
-new file mode 100644
-index 0000000..543d8c2
---- /dev/null
-+++ b/atusb/usb/usb.c
-@@ -0,0 +1,181 @@
-+/*
-+ * fw/usb/usb.c - USB hardware setup and standard device requests
-+ *
-+ * Written 2008-2011, 2013, 2015 by Werner Almesberger
-+ * Copyright 2008-2011, 2013, 2015 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+/*
-+ * Known issues:
-+ * - no suspend/resume
-+ * - should support EP clearing and stalling
-+ */
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+#include "usb.h"
-+#include "board.h"
-+
-+
-+#ifndef NULL
-+#define NULL 0
-+#endif
-+
-+#if 1
-+extern void panic(void);
-+#define BUG_ON(cond) do { if (cond) panic(); } while (0)
-+#else
-+#define BUG_ON(cond)
-+#endif
-+
-+bool (*user_setup)(const struct setup_request *setup);
-+void (*user_set_interface)(int nth);
-+bool (*user_get_descriptor)(uint8_t type, uint8_t index,
-+ const uint8_t **reply, uint8_t *size);
-+void (*user_reset)(void);
-+
-+
-+void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf,
-+ uint8_t size, void (*callback)(void *user), void *user)
-+{
-+ BUG_ON(ep->state);
-+ ep->state = state;
-+ ep->buf = buf;
-+ ep->end = buf+size;
-+ ep->callback = callback;
-+ ep->user = user;
-+ usb_ep_change(ep);
-+}
-+
-+
-+static bool get_descriptor(uint8_t type, uint8_t index, uint16_t length)
-+{
-+ const uint8_t *reply;
-+ uint8_t size;
-+
-+ switch (type) {
-+ case USB_DT_DEVICE:
-+ reply = device_descriptor;
-+ size = reply[0];
-+ break;
-+ case USB_DT_CONFIG:
-+ if (index)
-+ return 0;
-+ reply = config_descriptor;
-+ size = reply[2];
-+ break;
-+ default:
-+ if (!user_get_descriptor)
-+ return 0;
-+ if (!user_get_descriptor(type, index, &reply, &size))
-+ return 0;
-+ }
-+ if (length < size)
-+ size = length;
-+ usb_send(&eps[0], reply, size, NULL, NULL);
-+ return 1;
-+}
-+
-+
-+bool handle_setup(const struct setup_request *setup)
-+{
-+ switch (setup->bmRequestType | setup->bRequest << 8) {
-+
-+ /*
-+ * Device request
-+ *
-+ * See http://www.beyondlogic.org/usbnutshell/usb6.htm
-+ */
-+
-+ case FROM_DEVICE(GET_STATUS):
-+ if (setup->wLength != 2)
-+ return 0;
-+ usb_send(&eps[0], "\000", 2, NULL, NULL);
-+ break;
-+ case TO_DEVICE(CLEAR_FEATURE):
-+ break;
-+ case TO_DEVICE(SET_FEATURE):
-+ return 0;
-+ case TO_DEVICE(SET_ADDRESS):
-+ set_addr(setup->wValue);
-+ break;
-+ case FROM_DEVICE(GET_DESCRIPTOR):
-+ case FROM_INTERFACE(GET_DESCRIPTOR):
-+ if (!get_descriptor(setup->wValue >> 8, setup->wValue,
-+ setup->wLength))
-+ return 0;
-+ break;
-+ case TO_DEVICE(SET_DESCRIPTOR):
-+ return 0;
-+ case FROM_DEVICE(GET_CONFIGURATION):
-+ usb_send(&eps[0], "", 1, NULL, NULL);
-+ break;
-+ case TO_DEVICE(SET_CONFIGURATION):
-+ if (setup->wValue != config_descriptor[5])
-+ return 0;
-+ break;
-+
-+ /*
-+ * Interface request
-+ */
-+
-+ case FROM_INTERFACE(GET_STATUS):
-+ return 0;
-+ case TO_INTERFACE(CLEAR_FEATURE):
-+ return 0;
-+ case TO_INTERFACE(SET_FEATURE):
-+ return 0;
-+ case FROM_INTERFACE(GET_INTERFACE):
-+ return 0;
-+ case TO_INTERFACE(SET_INTERFACE):
-+ {
-+ const uint8_t *interface_descriptor =
-+ config_descriptor+9;
-+ const uint8_t *p;
-+ int i;
-+
-+ i = 0;
-+ for (p = interface_descriptor;
-+ p != config_descriptor+config_descriptor[2];
-+ p += p[0]) {
-+ if (p[1] != USB_DT_INTERFACE)
-+ continue;
-+ if (p[2] == setup->wIndex &&
-+ p[3] == setup->wValue) {
-+ if (user_set_interface)
-+ user_set_interface(i);
-+ return 1;
-+ }
-+ i++;
-+ }
-+ return 0;
-+ }
-+ break;
-+
-+ /*
-+ * Endpoint request
-+ */
-+
-+ case FROM_ENDPOINT(GET_STATUS):
-+ return 0;
-+ case TO_ENDPOINT(CLEAR_FEATURE):
-+ return 0;
-+ case TO_ENDPOINT(SET_FEATURE):
-+ return 0;
-+ case FROM_ENDPOINT(SYNCH_FRAME):
-+ return 0;
-+
-+ default:
-+ if (user_setup)
-+ return user_setup(setup);
-+ return 0;
-+ }
-+
-+ return 1;
-+}
-diff --git a/atusb/usb/usb.h b/atusb/usb/usb.h
-new file mode 100644
-index 0000000..cb40f9e
---- /dev/null
-+++ b/atusb/usb/usb.h
-@@ -0,0 +1,189 @@
-+/*
-+ * fw/usb//usb.h - USB hardware setup and standard device requests
-+ *
-+ * Written 2008, 2009, 2011, 2013, 2015 by Werner Almesberger
-+ * Copyright 2008, 2009, 2011, 2013, 2015 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#ifndef USB_H
-+#define USB_H
-+
-+
-+#include <stdbool.h>
-+#include <stdint.h>
-+
-+
-+/*
-+ * Packet identifier types
-+ */
-+
-+#define PID_OUT 0x1
-+#define PID_IN 0x9
-+#define PID_SOF 0x5
-+#define PID_SETUP 0xd
-+#define PID_DATA0 0x3
-+#define PID_DATA1 0xb
-+#define PID_ACK 0x2
-+#define PID_NAK 0xa
-+#define PID_STALL 0xe
-+
-+/*
-+ * Descriptor types
-+ *
-+ * Reuse libusb naming scheme (/usr/include/usb.h)
-+ */
-+
-+#define USB_DT_DEVICE 1
-+#define USB_DT_CONFIG 2
-+#define USB_DT_STRING 3
-+#define USB_DT_INTERFACE 4
-+#define USB_DT_ENDPOINT 5
-+
-+/*
-+ * Device classes
-+ *
-+ * Reuse libusb naming scheme (/usr/include/usb.h)
-+ */
-+
-+#define USB_CLASS_PER_INTERFACE 0
-+#define USB_CLASS_COMM 2
-+#define USB_CLASS_HID 3
-+#define USB_CLASS_MASS_STORAGE 8
-+#define USB_CLASS_HUB 9
-+#define USB_CLASS_DATA 10
-+#define USB_CLASS_APP_SPEC 0xfe
-+#define USB_CLASS_VENDOR_SPEC 0xff
-+
-+/*
-+ * Configuration attributes
-+ */
-+
-+#define USB_ATTR_BUS_POWERED 0x80
-+#define USB_ATTR_SELF_POWERED 0x40
-+#define USB_ATTR_REMOTE_WAKEUP 0x20
-+
-+/*
-+ * Endpoint type
-+ */
-+
-+#define USB_ENDPOINT_TYPE_CONTROL 0
-+#define USB_ENDPOINT_TYPE_ISOCHRONOUS 1
-+#define USB_ENDPOINT_TYPE_BULK 2
-+#define USB_ENDPOINT_TYPE_INTERRUPT 3
-+
-+/*
-+ * Setup request types
-+ */
-+
-+#define TO_DEVICE(req) (0x00 | (req) << 8)
-+#define FROM_DEVICE(req) (0x80 | (req) << 8)
-+#define TO_INTERFACE(req) (0x01 | (req) << 8)
-+#define FROM_INTERFACE(req) (0x81 | (req) << 8)
-+#define TO_ENDPOINT(req) (0x02 | (req) << 8)
-+#define FROM_ENDPOINT(req) (0x82 | (req) << 8)
-+
-+/*
-+ * Setup requests
-+ */
-+
-+#define GET_STATUS 0x00
-+#define CLEAR_FEATURE 0x01
-+#define SET_FEATURE 0x03
-+#define SET_ADDRESS 0x05
-+#define GET_DESCRIPTOR 0x06
-+#define SET_DESCRIPTOR 0x07
-+#define GET_CONFIGURATION 0x08
-+#define SET_CONFIGURATION 0x09
-+#define GET_INTERFACE 0x0a
-+#define SET_INTERFACE 0x0b
-+#define SYNCH_FRAME 0x0c
-+
-+/*
-+ * USB Language ID codes
-+ *
-+ * http://www.usb.org/developers/docs/USB_LANGIDs.pdf
-+ */
-+
-+#define USB_LANGID_ENGLISH_US 0x409
-+
-+
-+/*
-+ * Odd. sdcc seems to think "x" assumes the size of the destination, i.e.,
-+ * uint8_t. Hence the cast.
-+ */
-+
-+#define LE(x) ((uint16_t) (x) & 0xff), ((uint16_t) (x) >> 8)
-+
-+#define LO(x) (((uint8_t *) &(x))[0])
-+#define HI(x) (((uint8_t *) &(x))[1])
-+
-+
-+#ifdef LOW_SPEED
-+#define EP0_SIZE 8
-+#else
-+#define EP0_SIZE 64
-+#endif
-+
-+#define EP1_SIZE 64 /* simplify */
-+
-+
-+enum ep_state {
-+ EP_IDLE,
-+ EP_RX,
-+ EP_TX,
-+ EP_STALL,
-+};
-+
-+struct ep_descr {
-+ enum ep_state state;
-+ uint8_t *buf;
-+ uint8_t *end;
-+ uint8_t size;
-+ void (*callback)(void *user);
-+ void *user;
-+};
-+
-+struct setup_request {
-+ uint8_t bmRequestType;
-+ uint8_t bRequest;
-+ uint16_t wValue;
-+ uint16_t wIndex;
-+ uint16_t wLength;
-+};
-+
-+
-+extern const uint8_t device_descriptor[];
-+extern const uint8_t config_descriptor[];
-+extern struct ep_descr eps[];
-+
-+extern bool (*user_setup)(const struct setup_request *setup);
-+extern void (*user_set_interface)(int nth);
-+extern bool (*user_get_descriptor)(uint8_t type, uint8_t index,
-+ const uint8_t **reply, uint8_t *size);
-+extern void (*user_reset)(void);
-+
-+
-+#define usb_left(ep) ((ep)->end-(ep)->buf)
-+#define usb_send(ep, buf, size, callback, user) \
-+ usb_io(ep, EP_TX, (void *) buf, size, callback, user)
-+#define usb_recv(ep, buf, size, callback, user) \
-+ usb_io(ep, EP_RX, buf, size, callback, user)
-+
-+void usb_io(struct ep_descr *ep, enum ep_state state, uint8_t *buf,
-+ uint8_t size, void (*callback)(void *user), void *user);
-+
-+bool handle_setup(const struct setup_request *setup);
-+void set_addr(uint8_t addr);
-+void usb_ep_change(struct ep_descr *ep);
-+void usb_reset(void);
-+void usb_init(void);
-+
-+void ep_init(void);
-+
-+#endif /* !USB_H */
-diff --git a/atusb/version.h b/atusb/version.h
-new file mode 100644
-index 0000000..8fd6a2c
---- /dev/null
-+++ b/atusb/version.h
-@@ -0,0 +1,23 @@
-+/*
-+ * fw/version.h - Automatically generated version string
-+ *
-+ * Written 2008, 2011 by Werner Almesberger
-+ * Copyright 2008, 2011 Werner Almesberger
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ */
-+
-+
-+#ifndef VERSION_H
-+#define VERSION_H
-+
-+#include <stdint.h>
-+
-+
-+extern const char *build_date;
-+extern const uint16_t build_number;
-+
-+#endif /* !VERSION_H */
---
-2.26.0
-
diff --git a/libre/linux-libre-firmware/0003-Update-INSTALL-document.patch b/libre/linux-libre-firmware/0003-Update-INSTALL-document.patch
deleted file mode 100644
index 038b518ca..000000000
--- a/libre/linux-libre-firmware/0003-Update-INSTALL-document.patch
+++ /dev/null
@@ -1,44 +0,0 @@
-From 02054c86c9fce8978cc7372b758339191cc9f6d6 Mon Sep 17 00:00:00 2001
-From: Jason Self <j@jxself.org>
-Date: Thu, 4 Jul 2019 16:34:28 -0700
-Subject: [PATCH 3/8] Update INSTALL document
-
-To include the correct package name for GCC-AVR and improved
-descriptions.
----
- INSTALL | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/INSTALL b/INSTALL
-index 7fb1116..9ea6dad 100644
---- a/INSTALL
-+++ b/INSTALL
-@@ -16,14 +16,14 @@ In order to build everything you will need the following on the host
- system:
-
- * A C/C++ compiler, like GCC
-- * AVR-GCC
-- * Standard C library for AVR-GCC
- * Cmake
- * GNU Bison/YACC
- * GNU Flex
- * GNU Gperf
- * GNU Make
- * GNU Wget
-+ * GNU C cross-compiler for AVR
-+ * Standard C library for Atmel AVR
- * GNU C cross-compiler for ARM:
- - arm-linux-gnueabi-gcc
- - arm-linux-gnueabi-ld
-@@ -34,7 +34,7 @@ system:
-
- On GNU/Linux distros that use apt you can install these with:
-
-- apt install avr-gcc avr-libc binutils-arm-linux-gnueabi \
-+ apt install gcc-avr avr-libc binutils-arm-linux-gnueabi \
- binutils-arm-none-eabi bison cmake flex g++ gcc \
- gcc-arm-linux-gnueabi gcc-arm-none-eabi gperf make wget
-
---
-2.26.0
-
diff --git a/libre/linux-libre-firmware/0004-atusb-Build-updates.patch b/libre/linux-libre-firmware/0004-atusb-Build-updates.patch
deleted file mode 100644
index 641183577..000000000
--- a/libre/linux-libre-firmware/0004-atusb-Build-updates.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-From d6bb7bf71810db1b02dec985e8383594c193f55f Mon Sep 17 00:00:00 2001
-From: Jason Self <j@jxself.org>
-Date: Thu, 4 Jul 2019 16:57:58 -0700
-Subject: [PATCH 4/8] atusb: Build updates
-
-Update the root level Makefile to both invoke "make atusb.dfu" when
-building.
-
-Update the INSTALL document to mention the dependency on dfu-util.
-
-Update the root level Makefile to install atusb.dfu if it's compiled.
-Even though the kernel itself doesn't load the firmware into the
-device this will ensure that pre-compiled firmware is included in the
-release tarballs.
----
- INSTALL | 5 +++--
- Makefile | 3 ++-
- 2 files changed, 5 insertions(+), 3 deletions(-)
-
-diff --git a/INSTALL b/INSTALL
-index 9ea6dad..70c4381 100644
---- a/INSTALL
-+++ b/INSTALL
-@@ -17,6 +17,7 @@ system:
-
- * A C/C++ compiler, like GCC
- * Cmake
-+ * dfu-util - Device Firmware Upgrade Utilities
- * GNU Bison/YACC
- * GNU Flex
- * GNU Gperf
-@@ -35,7 +36,7 @@ system:
- On GNU/Linux distros that use apt you can install these with:
-
- apt install gcc-avr avr-libc binutils-arm-linux-gnueabi \
-- binutils-arm-none-eabi bison cmake flex g++ gcc \
-+ binutils-arm-none-eabi bison cmake dfu-util flex g++ gcc \
- gcc-arm-linux-gnueabi gcc-arm-none-eabi gperf make wget
-
- CARL9170 Firmware Configuration
-@@ -48,7 +49,7 @@ atusb: Firmware for the ATUSB IEEE 802.15.4 USB Adapter
-
- To flash the firmware you need dfu-util on the host. Issue
-
-- make dfu
-+ dfu-util -d 20b7:1540 -D atusb.dfu
-
- right after plugging the device into the USB port while the red led is
- still on.
-diff --git a/Makefile b/Makefile
-index 8474b30..51f708d 100644
---- a/Makefile
-+++ b/Makefile
-@@ -37,7 +37,7 @@ ath9k_htc: ath9k_htc_toolchain
- cd ath9k_htc && $(MAKE) -C target_firmware
-
- atusb:
-- cd atusb && $(MAKE)
-+ cd atusb && $(MAKE) atusb.dfu
-
- av7110:
- cd av7110 && $(MAKE)
-@@ -103,6 +103,7 @@ install:
- ln -s ath9k_htc/htc_9271-1.4.0.fw $(prefix)/htc_9271.fw; fi;
- if [ -a ath9k_htc/target_firmware/htc_7010.fw ]; then $(install_program) -D ath9k_htc/target_firmware/htc_7010.fw $(prefix)/ath9k_htc/htc_7010-1.4.0.fw && \
- ln -s ath9k_htc/htc_7010-1.4.0.fw $(prefix)/htc_7010.fw; fi;
-+ if [ -a atusb/atusb.dfu ]; then $(install_program) -D atusb/atusb.dfu $(prefix)/atusb/atusb.dfu; fi;
- if [ -a av7110/bootcode.bin ]; then $(install_program) -D av7110/bootcode.bin $(prefix)/av7110/bootcode.bin; fi;
- if [ -a cis/3CCFEM556.cis ]; then $(install_program) -D cis/3CCFEM556.cis $(prefix)/cis/3CCFEM556.cis; fi;
- if [ -a cis/3CXEM556.cis ]; then $(install_program) -D cis/3CXEM556.cis $(prefix)/cis/3CXEM556.cis; fi;
---
-2.26.0
-
diff --git a/libre/linux-libre-firmware/0006-Makefile-Change-spaces-for-atusb-to-tab.patch b/libre/linux-libre-firmware/0006-Makefile-Change-spaces-for-atusb-to-tab.patch
deleted file mode 100644
index 8dafb6bda..000000000
--- a/libre/linux-libre-firmware/0006-Makefile-Change-spaces-for-atusb-to-tab.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 06147f83be16e7ab5e08c280c61e015b60bd0acc Mon Sep 17 00:00:00 2001
-From: Jason Self <j@jxself.org>
-Date: Thu, 4 Jul 2019 17:14:30 -0700
-Subject: [PATCH 6/8] Makefile: Change spaces for atusb to tab
-
----
- Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index 51f708d..b5c5d05 100644
---- a/Makefile
-+++ b/Makefile
-@@ -103,7 +103,7 @@ install:
- ln -s ath9k_htc/htc_9271-1.4.0.fw $(prefix)/htc_9271.fw; fi;
- if [ -a ath9k_htc/target_firmware/htc_7010.fw ]; then $(install_program) -D ath9k_htc/target_firmware/htc_7010.fw $(prefix)/ath9k_htc/htc_7010-1.4.0.fw && \
- ln -s ath9k_htc/htc_7010-1.4.0.fw $(prefix)/htc_7010.fw; fi;
-- if [ -a atusb/atusb.dfu ]; then $(install_program) -D atusb/atusb.dfu $(prefix)/atusb/atusb.dfu; fi;
-+ if [ -a atusb/atusb.dfu ]; then $(install_program) -D atusb/atusb.dfu $(prefix)/atusb/atusb.dfu; fi;
- if [ -a av7110/bootcode.bin ]; then $(install_program) -D av7110/bootcode.bin $(prefix)/av7110/bootcode.bin; fi;
- if [ -a cis/3CCFEM556.cis ]; then $(install_program) -D cis/3CCFEM556.cis $(prefix)/cis/3CCFEM556.cis; fi;
- if [ -a cis/3CXEM556.cis ]; then $(install_program) -D cis/3CXEM556.cis $(prefix)/cis/3CXEM556.cis; fi;
---
-2.26.0
-
diff --git a/libre/linux-libre-firmware/0007-Makefile-Add-atusb-to-all.patch b/libre/linux-libre-firmware/0007-Makefile-Add-atusb-to-all.patch
deleted file mode 100644
index 1da3c0028..000000000
--- a/libre/linux-libre-firmware/0007-Makefile-Add-atusb-to-all.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From b43de635d524d519e47bcba78d081a0f811584b1 Mon Sep 17 00:00:00 2001
-From: Jason Self <j@jxself.org>
-Date: Thu, 4 Jul 2019 18:34:05 -0700
-Subject: [PATCH 7/8] Makefile: Add atusb to 'all'
-
----
- Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index b5c5d05..b5bfb47 100644
---- a/Makefile
-+++ b/Makefile
-@@ -19,7 +19,7 @@ install_program=install
-
- .PHONY: all test clean install a56 as31 aica ath9k_htc_toolchain ath9k_htc atusb av7110 b43-tools carl9170fw-toolchain carl9170fw cis-tools cis dsp56k ihex2fw isci keyspan_pda openfwwf usbdux
-
--all: aica ath9k_htc av7110 carl9170fw cis dsp56k isci keyspan_pda openfwwf usbdux
-+all: aica ath9k_htc atusb av7110 carl9170fw cis dsp56k isci keyspan_pda openfwwf usbdux
-
- a56:
- cd a56 && $(MAKE)
---
-2.26.0
-
diff --git a/libre/linux-libre-firmware/0008-Makefile-Set-shell-to-bin-bash.patch b/libre/linux-libre-firmware/0008-Makefile-Set-shell-to-bin-bash.patch
deleted file mode 100644
index 6029cd5b4..000000000
--- a/libre/linux-libre-firmware/0008-Makefile-Set-shell-to-bin-bash.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From a4d24e3a224a19404bc3ac98389ff376198c85ef Mon Sep 17 00:00:00 2001
-From: Jason Self <j@jxself.org>
-Date: Thu, 4 Jul 2019 18:37:45 -0700
-Subject: [PATCH 8/8] Makefile: Set shell to /bin/bash
-
----
- Makefile | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/Makefile b/Makefile
-index b5bfb47..5e38d94 100644
---- a/Makefile
-+++ b/Makefile
-@@ -13,7 +13,7 @@
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
-
--shell=/bin/sh
-+shell=/bin/bash
- prefix=/lib/firmware
- install_program=install
-
---
-2.26.0
-
diff --git a/libre/linux-libre-firmware/PKGBUILD b/libre/linux-libre-firmware/PKGBUILD
index 68e91458f..1c995074b 100644
--- a/libre/linux-libre-firmware/PKGBUILD
+++ b/libre/linux-libre-firmware/PKGBUILD
@@ -4,18 +4,18 @@
# Contributor: Luke Shumaker <lukeshu@sbcglobal.net>
pkgname=linux-libre-firmware
-pkgver=1.3.1
-pkgrel=2
+pkgver=1.4
+pkgrel=1
epoch=1
pkgdesc='Firmware files for Linux-libre'
arch=(any)
url='https://jxself.org/firmware'
license=(GPL3)
-makedepends=(arm-linux-gnueabi-gcc # av7110
- arm-none-eabi-gcc # aica
- avr-gcc avr-libc dfu-util # atusb
- sh-elf-gcc sh-elf-newlib cmake # carl9170fw
- xtensa-elf-gcc # ath9k_htc
+makedepends=(arm-linux-gnueabi-gcc # av7110
+ arm-none-eabi-gcc # aica
+ avr-gcc avr-libc dfu-util # atusb
+ sh-elf-gcc sh-elf-newlib cmake # carl9170fw
+ xtensa-elf-gcc # ath9k_htc
)
optdepends=('dfu-util: to flash the atusb firmware')
provides=(linux-firmware)
@@ -36,29 +36,13 @@ conflicts=(linux-firmware
ath9k-htc-firmware)
replaces=(${conflicts[@]})
options=(!buildflags !makeflags)
-source=(
- "$url/$pkgname-$pkgver.tar.lz"{,.asc}
- 0001-Update-carl9170-to-latest-upstream.patch
- 0002-Add-firmware-for-the-ATUSB-IEEE-802.15.4-USB-Adapter.patch
- 0003-Update-INSTALL-document.patch
- 0004-atusb-Build-updates.patch
- 0006-Makefile-Change-spaces-for-atusb-to-tab.patch
- 0007-Makefile-Add-atusb-to-all.patch
- 0008-Makefile-Set-shell-to-bin-bash.patch
-)
-sha512sums=('d827ec7024b4900dcdf6af8cdd4e72b02596d0ade5c2262460cd573785300498e6aa655b9a59cd22e38a6a787826a564ae33acfac52e68df1d082445e66f18df'
- 'SKIP'
- '07263a406cb15c9f91f41c8fb6d4307875665b8106adf526353d64306611458e11ce311842caa9efa623091c897ec9f87cfe54584c9c47590195867958cf4086'
- 'a4e8752cfee8dfd0b17ff798d2b5ea7a773ebcf688f7614d1c1a92fe7f092c626a289069a472bc873a77c9cf52f1e37953b0ba47c37a9dfb2a763a695ca77625'
- '1665ce62de148383fe4f30aa5714ef6bb1dfd4eed110415995069830b36a4b1aafb05e4cd6cf428dc0817e2affb91740e41b3fab8d2385683d6c18790bbf5afd'
- '0168ba0f3a8f3938a96b7f72d081283ca04b7ba90c5474d8ccf0716d6964137980f49623c5489271158a48827319a20ee4f19bd94f5bb956ee97d5ba637070c1'
- 'fa006627935beb7ae78fad5b63423a54e4eae384761ff618fff173250fb5d0c7eef9d5a707733d037edc95259ef59c9053c4245b80a004928b6809ea1cb43cf8'
- '8014d9eccb4c5193d1b4b056e163b5631c207adc78522e413650eb053c90e7b9e333c9e5cb6f73b63985e27020f4c69e7b791176702c55f711f6db95387e6bff'
- '59560f16978b2fd7d8c828d7609ee4f71cbdc902b70cfb87feca686958dd4df05c61c5e1bfa5e0c2a060f23185a0b9e5d07d487e172764767cdc4b26a6240b79')
+source=("$url/$pkgname-$pkgver.tar.lz"{,.asc})
+sha512sums=('3b4c8afb63c55f05df0b2686459c6bb2c0cb56db8384d5527506ff4a14b8de80e1a3037a9b57cccccd6953d869c6a71a6500c4c7b735253ea0b57c79854d9457'
+ 'SKIP')
validpgpkeys=('F611A908FFA165C699584ED49D0DB31B545A3198') # Jason Self
prepare(){
- cd $pkgname-$pkgver/src
+ cd "$pkgname-$pkgver/src"
local src
for src in "${source[@]}"; do
@@ -69,25 +53,27 @@ prepare(){
patch -Np1 < "$srcdir/$src"
done
- # Use our cross compilers and build carl9170fw with the default config
+ # Use our cross compilers
sed -e 's|$PWD/../toolchain/inst/bin/||g' \
- -e 's|${CMAKE_SOURCE_DIR}/toolchain/inst/bin/||g' \
+ -i ath9k_htc/target_firmware/configure
+ sed -e 's|${CMAKE_SOURCE_DIR}/toolchain/inst/bin/||g' \
-e '/CMAKE_FIND_ROOT_PATH/d' \
- -e 's/: ath9k_htc_toolchain$/:/' \
+ -i carl9170fw/extra/sh-elf-linux.cmake
+
+ # Remove toolchains and build carl9170fw with the default config
+ sed -e 's/: ath9k_htc_toolchain$/:/' \
-e 's/: carl9170fw-toolchain$/:/' \
-e '/cd carl9170fw && .\/autogen.sh$/ s/$/ --alldefconfig/' \
- -i Makefile \
- ath9k_htc/target_firmware/configure \
- carl9170fw/extra/sh-elf-linux.cmake
+ -i Makefile
}
build(){
- make -C $pkgname-$pkgver/src
+ make -C "$pkgname-$pkgver/src"
}
package(){
- cd $pkgname-$pkgver/src
+ cd "$pkgname-$pkgver/src"
- make prefix=$pkgdir/usr/lib/firmware install
- install -Dm644 WHENCE $pkgdir/usr/share/licenses/$pkgname/WHENCE
+ make prefix="$pkgdir/usr/lib/firmware install"
+ install -Dm644 WHENCE "$pkgdir/usr/share/licenses/$pkgname/WHENCE"
}