summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2017-10-19 15:07:40 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2017-10-19 15:07:40 +0200
commita10a8e5e502fb5d5a6f945e208bd00a9bdeca5e2 (patch)
treecd4f007c081b7693424411cea71cb6c9e98ff379
parent7f04124c149fa4d8e8f657907c581f10987003e2 (diff)
parent05761813eff43493ee0519f0699a396de3f007a5 (diff)
downloadbarebox-a10a8e5e502fb5d5a6f945e208bd00a9bdeca5e2.tar.gz
barebox-a10a8e5e502fb5d5a6f945e208bd00a9bdeca5e2.tar.xz
Merge branch 'for-next/usbgadget'
-rw-r--r--commands/usbgadget.c20
-rw-r--r--common/bbu.c15
-rw-r--r--common/file-list.c72
-rw-r--r--drivers/usb/gadget/autostart.c25
-rw-r--r--drivers/usb/gadget/f_fastboot.c29
-rw-r--r--drivers/usb/gadget/multi.c11
-rw-r--r--include/bbu.h2
-rw-r--r--include/file-list.h5
-rw-r--r--include/usb/fastboot.h7
9 files changed, 159 insertions, 27 deletions
diff --git a/commands/usbgadget.c b/commands/usbgadget.c
index ba09f97847..507871edd2 100644
--- a/commands/usbgadget.c
+++ b/commands/usbgadget.c
@@ -33,11 +33,11 @@
static int do_usbgadget(int argc, char *argv[])
{
int opt, ret;
- int acm = 1, create_serial = 0, fastboot_set = 0;
+ int acm = 1, create_serial = 0, fastboot_set = 0, fastboot_export_bbu = 0;
const char *fastboot_opts = NULL, *dfu_opts = NULL;
struct f_multi_opts *opts;
- while ((opt = getopt(argc, argv, "asdA::D:")) > 0) {
+ while ((opt = getopt(argc, argv, "asdA::D:b")) > 0) {
switch (opt) {
case 'a':
acm = 1;
@@ -54,6 +54,9 @@ static int do_usbgadget(int argc, char *argv[])
fastboot_opts = optarg;
fastboot_set = 1;
break;
+ case 'b':
+ fastboot_export_bbu = 1;
+ break;
case 'd':
usb_multi_unregister();
return 0;
@@ -83,10 +86,15 @@ static int do_usbgadget(int argc, char *argv[])
if (fastboot_opts) {
opts->fastboot_opts.files = file_list_parse(fastboot_opts);
+ if (IS_ERR(opts->fastboot_opts.files))
+ goto err_parse;
+ opts->fastboot_opts.export_bbu = fastboot_export_bbu;
}
if (dfu_opts) {
opts->dfu_opts.files = file_list_parse(dfu_opts);
+ if (IS_ERR(opts->dfu_opts.files))
+ goto err_parse;
}
if (create_serial) {
@@ -98,6 +106,13 @@ static int do_usbgadget(int argc, char *argv[])
usb_multi_opts_release(opts);
return ret;
+
+err_parse:
+ printf("Cannot parse file list \"%s\": %s\n", fastboot_opts, strerrorp(opts->fastboot_opts.files));
+
+ free(opts);
+
+ return 1;
}
BAREBOX_CMD_HELP_START(usbgadget)
@@ -108,6 +123,7 @@ BAREBOX_CMD_HELP_OPT ("-a", "Create CDC ACM function")
BAREBOX_CMD_HELP_OPT ("-s", "Create Generic Serial function")
BAREBOX_CMD_HELP_OPT ("-A [desc]", "Create Android Fastboot function. If 'desc' is not provided,")
BAREBOX_CMD_HELP_OPT ("", "trying to use 'global.usbgadget.fastboot_function' variable.")
+BAREBOX_CMD_HELP_OPT ("-b", "include registered barebox update handlers (fastboot specific)")
BAREBOX_CMD_HELP_OPT ("-D <desc>", "Create DFU function")
BAREBOX_CMD_HELP_OPT ("-d", "Disable the currently running gadget")
BAREBOX_CMD_HELP_END
diff --git a/common/bbu.c b/common/bbu.c
index 031c433820..3b372263b1 100644
--- a/common/bbu.c
+++ b/common/bbu.c
@@ -30,6 +30,21 @@
static LIST_HEAD(bbu_image_handlers);
+int bbu_handlers_iterate(int (*fn)(struct bbu_handler *, void *), void *ctx)
+{
+ struct bbu_handler *handler;
+
+ list_for_each_entry(handler, &bbu_image_handlers, list) {
+ int ret;
+
+ ret = fn(handler, ctx);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
int bbu_force(struct bbu_data *data, const char *fmt, ...)
{
va_list args;
diff --git a/common/file-list.c b/common/file-list.c
index 90c0f429c5..8d61b76cbb 100644
--- a/common/file-list.c
+++ b/common/file-list.c
@@ -1,3 +1,16 @@
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "file_list: " fmt
+
#include <common.h>
#include <malloc.h>
#include <fs.h>
@@ -8,12 +21,44 @@
#define PARSE_NAME 1
#define PARSE_FLAGS 2
+struct file_list_entry *file_list_entry_by_name(struct file_list *files, const char *name)
+{
+ struct file_list_entry *entry;
+
+ file_list_for_each_entry(files, entry) {
+ if (!strcmp(entry->name, name))
+ return entry;
+ }
+
+ return NULL;
+}
+
+int file_list_add_entry(struct file_list *files, const char *name, const char *filename,
+ unsigned long flags)
+{
+ struct file_list_entry *entry;
+
+ entry = file_list_entry_by_name(files, name);
+ if (entry)
+ return -EEXIST;
+
+ entry = xzalloc(sizeof(*entry));
+
+ entry->name = xstrdup(name);
+ entry->filename = xstrdup(filename);
+ entry->flags = flags;
+
+ list_add_tail(&entry->list, &files->list);
+
+ return 0;
+}
+
static int file_list_parse_one(struct file_list *files, const char *partstr, const char **endstr)
{
int i = 0, state = PARSE_DEVICE;
char filename[PATH_MAX];
char name[PATH_MAX];
- struct file_list_entry *entry = xzalloc(sizeof(*entry));
+ unsigned long flags = 0;
memset(filename, 0, sizeof(filename));
memset(name, 0, sizeof(name));
@@ -39,15 +84,16 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
case PARSE_FLAGS:
switch (*partstr) {
case 's':
- entry->flags |= FILE_LIST_FLAG_SAFE;
+ flags |= FILE_LIST_FLAG_SAFE;
break;
case 'r':
- entry->flags |= FILE_LIST_FLAG_READBACK;
+ flags |= FILE_LIST_FLAG_READBACK;
break;
case 'c':
- entry->flags |= FILE_LIST_FLAG_CREATE;
+ flags |= FILE_LIST_FLAG_CREATE;
break;
default:
+ pr_err("Unknown flag '%c'\n", *partstr);
return -EINVAL;
}
break;
@@ -57,18 +103,16 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
partstr++;
}
- if (state != PARSE_FLAGS)
+ if (state != PARSE_FLAGS) {
+ pr_err("Missing ')'\n");
return -EINVAL;
+ }
- entry->name = xstrdup(name);
- entry->filename = xstrdup(filename);
if (*partstr == ',')
partstr++;
*endstr = partstr;
- list_add_tail(&entry->list, &files->list);
-
- return 0;
+ return file_list_add_entry(files, name, filename, flags);
}
struct file_list *file_list_parse(const char *str)
@@ -82,9 +126,9 @@ struct file_list *file_list_parse(const char *str)
INIT_LIST_HEAD(&files->list);
while (*str) {
- if (file_list_parse_one(files, str, &endptr)) {
- printf("parse error\n");
- ret = -EINVAL;
+ ret = file_list_parse_one(files, str, &endptr);
+ if (ret) {
+ pr_err("parse error\n");
goto out;
}
str = endptr;
@@ -94,7 +138,7 @@ struct file_list *file_list_parse(const char *str)
return files;
out:
- free(files);
+ file_list_free(files);
return ERR_PTR(ret);
}
diff --git a/drivers/usb/gadget/autostart.c b/drivers/usb/gadget/autostart.c
index 465d8fd380..f640a9667d 100644
--- a/drivers/usb/gadget/autostart.c
+++ b/drivers/usb/gadget/autostart.c
@@ -11,6 +11,8 @@
* GNU General Public License for more details.
*
*/
+#define pr_fmt(fmt) "usbgadget autostart: " fmt
+
#include <common.h>
#include <command.h>
#include <errno.h>
@@ -28,6 +30,7 @@
static int autostart;
static int acm;
static char *fastboot_function;
+static int fastboot_bbu;
static int usbgadget_autostart(void)
{
@@ -37,16 +40,28 @@ static int usbgadget_autostart(void)
if (!autostart)
return 0;
- setenv("otg.mode", "peripheral");
-
opts = xzalloc(sizeof(*opts));
opts->release = usb_multi_opts_release;
- if (fastboot_function)
+ if (fastboot_function) {
opts->fastboot_opts.files = file_list_parse(fastboot_function);
+ if (IS_ERR(opts->fastboot_opts.files)) {
+ pr_err("Parsing file list \"%s\" failed: %s\n", fastboot_function,
+ strerrorp(opts->fastboot_opts.files));
+ opts->fastboot_opts.files = NULL;
+ }
+
+ opts->fastboot_opts.export_bbu = fastboot_bbu;
+ }
opts->create_acm = acm;
+ if (!opts->fastboot_opts.files && !opts->create_acm) {
+ pr_warn("No functions to register\n");
+ return 0;
+ }
+
+ setenv("otg.mode", "peripheral");
ret = usb_multi_register(opts);
if (ret)
@@ -63,6 +78,7 @@ static int usbgadget_globalvars_init(void)
globalvar_add_simple_bool("usbgadget.acm", &acm);
globalvar_add_simple_string("usbgadget.fastboot_function",
&fastboot_function);
+ globalvar_add_simple_bool("usbgadget.fastboot_bbu", &fastboot_bbu);
return 0;
}
@@ -77,3 +93,6 @@ BAREBOX_MAGICVAR_NAMED(global_usbgadget_acm,
BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_function,
global.usbgadget.fastboot_function,
"usbgadget: Create Android Fastboot function");
+BAREBOX_MAGICVAR_NAMED(global_usbgadget_fastboot_bbu,
+ global.usbgadget.fastboot_bbu,
+ "usbgadget: export barebox update handlers via fastboot");
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 598637619d..85c64c05c8 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -283,6 +283,21 @@ out:
return ret;
}
+static int fastboot_add_bbu_variables(struct bbu_handler *handler, void *ctx)
+{
+ struct f_fastboot *f_fb = ctx;
+ char *name;
+ int ret;
+
+ name = basprintf("bbu-%s", handler->name);
+
+ ret = file_list_add_entry(f_fb->files, name, handler->devicefile, 0);
+
+ free(name);
+
+ return ret;
+}
+
static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@@ -302,6 +317,9 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
var = fb_addvar(f_fb, "bootloader-version");
fb_setvar(var, release_string);
+ if (IS_ENABLED(CONFIG_BAREBOX_UPDATE) && opts->export_bbu)
+ bbu_handlers_iterate(fastboot_add_bbu_variables, f_fb);
+
file_list_for_each_entry(f_fb->files, fentry) {
ret = fastboot_add_partition_variables(f_fb, fentry);
if (ret)
@@ -679,18 +697,15 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req, const char *cmd
fastboot_tx_print(f_fb, "INFOCopying file to %s...", cmd);
- file_list_for_each_entry(f_fb->files, fentry) {
- if (!strcmp(cmd, fentry->name)) {
- filename = fentry->filename;
- break;
- }
- }
+ fentry = file_list_entry_by_name(f_fb->files, cmd);
- if (!filename) {
+ if (!fentry) {
fastboot_tx_print(f_fb, "FAILNo such partition: %s", cmd);
return;
}
+ filename = fentry->filename;
+
if (filetype == filetype_ubi) {
int fd;
struct mtd_info_user meminfo;
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 6385c16186..44969be0c9 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -128,6 +128,7 @@ static int multi_bind_fastboot(struct usb_composite_dev *cdev)
opts = container_of(fi_fastboot, struct f_fastboot_opts, func_inst);
opts->files = gadget_multi_opts->fastboot_opts.files;
+ opts->export_bbu = gadget_multi_opts->fastboot_opts.export_bbu;
f_fastboot = usb_get_function(fi_fastboot);
if (IS_ERR(f_fastboot)) {
@@ -234,6 +235,8 @@ static struct usb_composite_driver multi_driver = {
int usb_multi_register(struct f_multi_opts *opts)
{
+ int ret;
+
if (gadget_multi_opts) {
pr_err("USB multi gadget already registered\n");
return -EBUSY;
@@ -241,7 +244,13 @@ int usb_multi_register(struct f_multi_opts *opts)
gadget_multi_opts = opts;
- return usb_composite_probe(&multi_driver);
+ ret = usb_composite_probe(&multi_driver);
+ if (ret) {
+ usb_composite_unregister(&multi_driver);
+ gadget_multi_opts = NULL;
+ }
+
+ return ret;
}
void usb_multi_unregister(void)
diff --git a/include/bbu.h b/include/bbu.h
index 9d24ffc395..54434b03e0 100644
--- a/include/bbu.h
+++ b/include/bbu.h
@@ -42,6 +42,8 @@ bool barebox_update_handler_exists(struct bbu_data *);
void bbu_handlers_list(void);
+int bbu_handlers_iterate(int (*fn)(struct bbu_handler *, void *), void *);
+
#ifdef CONFIG_BAREBOX_UPDATE
int bbu_register_handler(struct bbu_handler *);
diff --git a/include/file-list.h b/include/file-list.h
index 608181ff8d..1e02539d4d 100644
--- a/include/file-list.h
+++ b/include/file-list.h
@@ -20,6 +20,11 @@ struct file_list {
struct file_list *file_list_parse(const char *str);
void file_list_free(struct file_list *);
+int file_list_add_entry(struct file_list *files, const char *name, const char *filename,
+ unsigned long flags);
+
+struct file_list_entry *file_list_entry_by_name(struct file_list *files, const char *name);
+
#define file_list_for_each_entry(files, entry) \
list_for_each_entry(entry, &files->list, list)
diff --git a/include/usb/fastboot.h b/include/usb/fastboot.h
index dab5a9a299..ced890c9ab 100644
--- a/include/usb/fastboot.h
+++ b/include/usb/fastboot.h
@@ -5,9 +5,16 @@
#include <file-list.h>
#include <usb/composite.h>
+/**
+ * struct f_fastboot_opts - options to configure the fastboot gadget
+ * @func_inst: The USB function instance to register on
+ * @files: A file_list containing the files (partitions) to export via fastboot
+ * @export_bbu: Automatically include the partitions provided by barebox update (bbu)
+ */
struct f_fastboot_opts {
struct usb_function_instance func_inst;
struct file_list *files;
+ bool export_bbu;
};
#endif /* _USB_FASTBOOT_H */