1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017 Oleksij Rempel <o.rempel@pengutronix.de>, Pengutronix
*/
#define pr_fmt(fmt) "usbgadget: " fmt
#include <common.h>
#include <command.h>
#include <errno.h>
#include <environment.h>
#include <malloc.h>
#include <getopt.h>
#include <fs.h>
#include <xfuncs.h>
#include <usb/usbserial.h>
#include <usb/dfu.h>
#include <usb/gadget-multi.h>
#include <globalvar.h>
#include <magicvar.h>
static int autostart;
static int acm;
static char *dfu_function;
static struct file_list *parse(const char *files)
{
struct file_list *list = file_list_parse(files);
if (IS_ERR(list)) {
pr_err("Parsing file list \"%s\" failed: %pe\n", files, list);
return NULL;
}
return list;
}
int usbgadget_register(bool dfu, const char *dfu_opts,
bool fastboot, const char *fastboot_opts,
bool acm, bool export_bbu)
{
int ret;
struct device_d *dev;
struct f_multi_opts *opts;
const char *fastboot_partitions = get_fastboot_partitions();
if (dfu && !dfu_opts && dfu_function && *dfu_function)
dfu_opts = dfu_function;
if (IS_ENABLED(CONFIG_FASTBOOT_BASE) && fastboot && !fastboot_opts &&
fastboot_partitions && *fastboot_partitions)
fastboot_opts = fastboot_partitions;
if (!dfu_opts && !fastboot_opts && !acm)
return COMMAND_ERROR_USAGE;
/*
* Creating a gadget with both DFU and Fastboot doesn't work.
* Both client tools seem to assume that the device only has
* a single configuration
*/
if (fastboot_opts && dfu_opts) {
pr_err("Only one of Fastboot and DFU allowed\n");
return -EINVAL;
}
opts = xzalloc(sizeof(*opts));
opts->release = usb_multi_opts_release;
if (fastboot_opts) {
opts->fastboot_opts.files = parse(fastboot_opts);
opts->fastboot_opts.export_bbu = export_bbu;
}
if (dfu_opts)
opts->dfu_opts.files = parse(dfu_opts);
if (!opts->dfu_opts.files && !opts->fastboot_opts.files && !acm) {
pr_warn("No functions to register\n");
free(opts);
return 0;
}
opts->create_acm = acm;
dev = get_device_by_name("otg");
if (dev)
dev_set_param(dev, "mode", "peripheral");
ret = usb_multi_register(opts);
if (ret)
usb_multi_opts_release(opts);
return ret;
}
static int usbgadget_autostart_set(struct param_d *param, void *ctx)
{
static bool started;
bool fastboot_bbu = get_fastboot_bbu();
int err;
if (!IS_ENABLED(CONFIG_USB_GADGET_AUTOSTART) || !autostart || started)
return 0;
err = usbgadget_register(true, NULL, true, NULL, acm, fastboot_bbu);
if (!err)
started = true;
return err;
}
static int usbgadget_globalvars_init(void)
{
if (IS_ENABLED(CONFIG_USB_GADGET_AUTOSTART)) {
globalvar_add_bool("usbgadget.autostart", usbgadget_autostart_set,
&autostart, NULL);
globalvar_add_simple_bool("usbgadget.acm", &acm);
}
globalvar_add_simple_string("usbgadget.dfu_function", &dfu_function);
return 0;
}
device_initcall(usbgadget_globalvars_init);
BAREBOX_MAGICVAR(global.usbgadget.autostart,
"usbgadget: Automatically start usbgadget on boot");
BAREBOX_MAGICVAR(global.usbgadget.acm,
"usbgadget: Create CDC ACM function");
BAREBOX_MAGICVAR(global.usbgadget.dfu_function,
"usbgadget: Create DFU function");
|