Add function to parse a string in dfu format
The dfu command parses a string which contains a list of devices and flags. This format is useful for other users aswell, so add common helper functions to parse it and let the dfu command use this format. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
55ebc38493
commit
057a57448d
|
@ -24,71 +24,7 @@
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <xfuncs.h>
|
#include <xfuncs.h>
|
||||||
#include <usb/dfu.h>
|
#include <usb/dfu.h>
|
||||||
|
#include <linux/err.h>
|
||||||
#define PARSE_DEVICE 0
|
|
||||||
#define PARSE_NAME 1
|
|
||||||
#define PARSE_FLAGS 2
|
|
||||||
|
|
||||||
static int dfu_do_parse_one(char *partstr, char **endstr, struct usb_dfu_dev *dfu)
|
|
||||||
{
|
|
||||||
int i = 0, state = PARSE_DEVICE;
|
|
||||||
char device[PATH_MAX];
|
|
||||||
char name[PATH_MAX];
|
|
||||||
|
|
||||||
memset(device, 0, sizeof(device));
|
|
||||||
memset(name, 0, sizeof(name));
|
|
||||||
dfu->flags = 0;
|
|
||||||
|
|
||||||
while (*partstr && *partstr != ',') {
|
|
||||||
switch (state) {
|
|
||||||
case PARSE_DEVICE:
|
|
||||||
if (*partstr == '(') {
|
|
||||||
state = PARSE_NAME;
|
|
||||||
i = 0;
|
|
||||||
} else {
|
|
||||||
device[i++] = *partstr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PARSE_NAME:
|
|
||||||
if (*partstr == ')') {
|
|
||||||
state = PARSE_FLAGS;
|
|
||||||
i = 0;
|
|
||||||
} else {
|
|
||||||
name[i++] = *partstr;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PARSE_FLAGS:
|
|
||||||
switch (*partstr) {
|
|
||||||
case 's':
|
|
||||||
dfu->flags |= DFU_FLAG_SAFE;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
dfu->flags |= DFU_FLAG_READBACK;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
dfu->flags |= DFU_FLAG_CREATE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
partstr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state != PARSE_FLAGS)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
dfu->name = xstrdup(name);
|
|
||||||
dfu->dev = xstrdup(device);
|
|
||||||
if (*partstr == ',')
|
|
||||||
partstr++;
|
|
||||||
*endstr = partstr;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dfu /dev/self0(bootloader)sr,/dev/nand0.root.bb(root)
|
/* dfu /dev/self0(bootloader)sr,/dev/nand0.root.bb(root)
|
||||||
*
|
*
|
||||||
|
@ -97,9 +33,8 @@ static int dfu_do_parse_one(char *partstr, char **endstr, struct usb_dfu_dev *df
|
||||||
*/
|
*/
|
||||||
static int do_dfu(int argc, char *argv[])
|
static int do_dfu(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int n = 0;
|
|
||||||
struct usb_dfu_pdata pdata;
|
struct usb_dfu_pdata pdata;
|
||||||
char *endptr, *argstr;
|
char *argstr;
|
||||||
struct usb_dfu_dev *dfu_alts = NULL;
|
struct usb_dfu_dev *dfu_alts = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -108,27 +43,16 @@ static int do_dfu(int argc, char *argv[])
|
||||||
|
|
||||||
argstr = argv[optind];
|
argstr = argv[optind];
|
||||||
|
|
||||||
for (n = 0; *argstr; n++) {
|
pdata.files = file_list_parse(argstr);
|
||||||
dfu_alts = xrealloc(dfu_alts, sizeof(*dfu_alts) * (n + 1));
|
if (IS_ERR(pdata.files)) {
|
||||||
if (dfu_do_parse_one(argstr, &endptr, &dfu_alts[n])) {
|
ret = PTR_ERR(pdata.files);
|
||||||
printf("parse error\n");
|
goto out;
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
argstr = endptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pdata.alts = dfu_alts;
|
|
||||||
pdata.num_alts = n;
|
|
||||||
|
|
||||||
ret = usb_dfu_register(&pdata);
|
ret = usb_dfu_register(&pdata);
|
||||||
|
|
||||||
|
file_list_free(pdata.files);
|
||||||
out:
|
out:
|
||||||
while (n) {
|
|
||||||
n--;
|
|
||||||
free(dfu_alts[n].name);
|
|
||||||
free(dfu_alts[n].dev);
|
|
||||||
};
|
|
||||||
|
|
||||||
free(dfu_alts);
|
free(dfu_alts);
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,9 @@ config MENUTREE
|
||||||
select GLOB
|
select GLOB
|
||||||
select GLOB_SORT
|
select GLOB_SORT
|
||||||
|
|
||||||
|
config FILE_LIST
|
||||||
|
bool
|
||||||
|
|
||||||
menu "General Settings"
|
menu "General Settings"
|
||||||
|
|
||||||
config LOCALVERSION
|
config LOCALVERSION
|
||||||
|
|
|
@ -44,6 +44,7 @@ obj-$(CONFIG_SHELL_HUSH) += hush.o
|
||||||
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
|
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
|
||||||
obj-$(CONFIG_UIMAGE) += image.o uimage.o
|
obj-$(CONFIG_UIMAGE) += image.o uimage.o
|
||||||
obj-$(CONFIG_MENUTREE) += menutree.o
|
obj-$(CONFIG_MENUTREE) += menutree.o
|
||||||
|
obj-$(CONFIG_FILE_LIST) += file-list.o
|
||||||
|
|
||||||
quiet_cmd_pwd_h = PWDH $@
|
quiet_cmd_pwd_h = PWDH $@
|
||||||
ifdef CONFIG_PASSWORD
|
ifdef CONFIG_PASSWORD
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
#include <common.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <fs.h>
|
||||||
|
#include <file-list.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
|
||||||
|
#define PARSE_DEVICE 0
|
||||||
|
#define PARSE_NAME 1
|
||||||
|
#define PARSE_FLAGS 2
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
memset(filename, 0, sizeof(filename));
|
||||||
|
memset(name, 0, sizeof(name));
|
||||||
|
|
||||||
|
while (*partstr && *partstr != ',') {
|
||||||
|
switch (state) {
|
||||||
|
case PARSE_DEVICE:
|
||||||
|
if (*partstr == '(') {
|
||||||
|
state = PARSE_NAME;
|
||||||
|
i = 0;
|
||||||
|
} else {
|
||||||
|
filename[i++] = *partstr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PARSE_NAME:
|
||||||
|
if (*partstr == ')') {
|
||||||
|
state = PARSE_FLAGS;
|
||||||
|
i = 0;
|
||||||
|
} else {
|
||||||
|
name[i++] = *partstr;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PARSE_FLAGS:
|
||||||
|
switch (*partstr) {
|
||||||
|
case 's':
|
||||||
|
entry->flags |= FILE_LIST_FLAG_SAFE;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
entry->flags |= FILE_LIST_FLAG_READBACK;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
entry->flags |= FILE_LIST_FLAG_CREATE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
partstr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state != PARSE_FLAGS)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
entry->name = xstrdup(name);
|
||||||
|
entry->filename = xstrdup(filename);
|
||||||
|
if (*partstr == ',')
|
||||||
|
partstr++;
|
||||||
|
*endstr = partstr;
|
||||||
|
|
||||||
|
list_add_tail(&entry->list, &files->list);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct file_list *file_list_parse(const char *str)
|
||||||
|
{
|
||||||
|
struct file_list *files;
|
||||||
|
int ret;
|
||||||
|
const char *endptr;
|
||||||
|
|
||||||
|
files = xzalloc(sizeof(*files));
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&files->list);
|
||||||
|
|
||||||
|
while (*str) {
|
||||||
|
if (file_list_parse_one(files, str, &endptr)) {
|
||||||
|
printf("parse error\n");
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
str = endptr;
|
||||||
|
|
||||||
|
files->num_entries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
out:
|
||||||
|
free(files);
|
||||||
|
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
void file_list_free(struct file_list *files)
|
||||||
|
{
|
||||||
|
struct file_list_entry *entry, *tmp;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(entry, tmp, &files->list, list) {
|
||||||
|
free(entry->name);
|
||||||
|
free(entry->filename);
|
||||||
|
free(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(files);
|
||||||
|
}
|
|
@ -41,6 +41,7 @@ comment "USB Gadget drivers"
|
||||||
|
|
||||||
config USB_GADGET_DFU
|
config USB_GADGET_DFU
|
||||||
bool
|
bool
|
||||||
|
select FILE_LIST
|
||||||
prompt "Device Firmware Update Gadget"
|
prompt "Device Firmware Update Gadget"
|
||||||
|
|
||||||
config USB_GADGET_SERIAL
|
config USB_GADGET_SERIAL
|
||||||
|
|
|
@ -126,10 +126,9 @@ enum dfu_state {
|
||||||
#define CONFIG_USBD_DFU_XFER_SIZE 4096
|
#define CONFIG_USBD_DFU_XFER_SIZE 4096
|
||||||
#define DFU_TEMPFILE "/dfu_temp"
|
#define DFU_TEMPFILE "/dfu_temp"
|
||||||
|
|
||||||
static int dfualt;
|
struct file_list_entry *dfu_file_entry;
|
||||||
static int dfufd = -EINVAL;
|
static int dfufd = -EINVAL;
|
||||||
static struct usb_dfu_dev *dfu_devs;
|
static struct file_list *dfu_files;
|
||||||
static int dfu_num_alt;
|
|
||||||
static int dfudetach;
|
static int dfudetach;
|
||||||
|
|
||||||
/* USB DFU functional descriptor */
|
/* USB DFU functional descriptor */
|
||||||
|
@ -174,6 +173,7 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
struct usb_composite_dev *cdev = c->cdev;
|
struct usb_composite_dev *cdev = c->cdev;
|
||||||
struct usb_descriptor_header **header;
|
struct usb_descriptor_header **header;
|
||||||
struct usb_interface_descriptor *desc;
|
struct usb_interface_descriptor *desc;
|
||||||
|
struct file_list_entry *fentry;
|
||||||
int i;
|
int i;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
@ -182,9 +182,9 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
header = xzalloc(sizeof(void *) * (dfu_num_alt + 2));
|
header = xzalloc(sizeof(void *) * (dfu_files->num_entries + 2));
|
||||||
desc = xzalloc(sizeof(struct usb_interface_descriptor) * dfu_num_alt);
|
desc = xzalloc(sizeof(struct usb_interface_descriptor) * dfu_files->num_entries);
|
||||||
for (i = 0; i < dfu_num_alt; i++) {
|
for (i = 0; i < dfu_files->num_entries; i++) {
|
||||||
desc[i].bLength = USB_DT_INTERFACE_SIZE;
|
desc[i].bLength = USB_DT_INTERFACE_SIZE;
|
||||||
desc[i].bDescriptorType = USB_DT_INTERFACE;
|
desc[i].bDescriptorType = USB_DT_INTERFACE;
|
||||||
desc[i].bNumEndpoints = 0;
|
desc[i].bNumEndpoints = 0;
|
||||||
|
@ -206,9 +206,14 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
if (status)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (i = 0; i < dfu_num_alt; i++)
|
i = 0;
|
||||||
|
file_list_for_each_entry(dfu_files, fentry) {
|
||||||
printf("dfu: register alt%d(%s) with device %s\n",
|
printf("dfu: register alt%d(%s) with device %s\n",
|
||||||
i, dfu_devs[i].name, dfu_devs[i].dev);
|
i, fentry->name, fentry->filename);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
out:
|
out:
|
||||||
free(desc);
|
free(desc);
|
||||||
free(header);
|
free(header);
|
||||||
|
@ -233,9 +238,19 @@ dfu_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||||
|
|
||||||
static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
||||||
{
|
{
|
||||||
dfualt = alt;
|
struct file_list_entry *fentry;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
return 0;
|
file_list_for_each_entry(dfu_files, fentry) {
|
||||||
|
if (i == alt) {
|
||||||
|
dfu_file_entry = fentry;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dfu_status(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
static int dfu_status(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
||||||
|
@ -290,14 +305,14 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c
|
||||||
|
|
||||||
if (w_length == 0) {
|
if (w_length == 0) {
|
||||||
dfu->dfu_state = DFU_STATE_dfuIDLE;
|
dfu->dfu_state = DFU_STATE_dfuIDLE;
|
||||||
if (dfu_devs[dfualt].flags & DFU_FLAG_SAFE) {
|
if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
|
||||||
int fd;
|
int fd;
|
||||||
unsigned flags = O_WRONLY;
|
unsigned flags = O_WRONLY;
|
||||||
|
|
||||||
if (dfu_devs[dfualt].flags & DFU_FLAG_CREATE)
|
if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
|
||||||
flags |= O_CREAT | O_TRUNC;
|
flags |= O_CREAT | O_TRUNC;
|
||||||
|
|
||||||
fd = open(dfu_devs[dfualt].dev, flags);
|
fd = open(dfu_file_entry->filename, flags);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("open");
|
perror("open");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -310,7 +325,7 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
ret = copy_file(DFU_TEMPFILE, dfu_devs[dfualt].dev, 0);
|
ret = copy_file(DFU_TEMPFILE, dfu_file_entry->filename, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("copy file failed\n");
|
printf("copy file failed\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -425,16 +440,16 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
||||||
value = -EINVAL;
|
value = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
debug("dfu: starting download to %s\n", dfu_devs[dfualt].dev);
|
debug("dfu: starting download to %s\n", dfu_file_entry->filename);
|
||||||
if (dfu_devs[dfualt].flags & DFU_FLAG_SAFE) {
|
if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
|
||||||
dfufd = open(DFU_TEMPFILE, O_WRONLY | O_CREAT);
|
dfufd = open(DFU_TEMPFILE, O_WRONLY | O_CREAT);
|
||||||
} else {
|
} else {
|
||||||
unsigned flags = O_WRONLY;
|
unsigned flags = O_WRONLY;
|
||||||
|
|
||||||
if (dfu_devs[dfualt].flags & DFU_FLAG_CREATE)
|
if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
|
||||||
flags |= O_CREAT | O_TRUNC;
|
flags |= O_CREAT | O_TRUNC;
|
||||||
|
|
||||||
dfufd = open(dfu_devs[dfualt].dev, flags);
|
dfufd = open(dfu_file_entry->filename, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dfufd < 0) {
|
if (dfufd < 0) {
|
||||||
|
@ -456,12 +471,12 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
|
||||||
break;
|
break;
|
||||||
case USB_REQ_DFU_UPLOAD:
|
case USB_REQ_DFU_UPLOAD:
|
||||||
dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
|
dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
|
||||||
debug("dfu: starting upload from %s\n", dfu_devs[dfualt].dev);
|
debug("dfu: starting upload from %s\n", dfu_file_entry->filename);
|
||||||
if (!(dfu_devs[dfualt].flags & DFU_FLAG_READBACK)) {
|
if (!(dfu_file_entry->flags & FILE_LIST_FLAG_READBACK)) {
|
||||||
dfu->dfu_state = DFU_STATE_dfuERROR;
|
dfu->dfu_state = DFU_STATE_dfuERROR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
dfufd = open(dfu_devs[dfualt].dev, O_RDONLY);
|
dfufd = open(dfu_file_entry->filename, O_RDONLY);
|
||||||
if (dfufd < 0) {
|
if (dfufd < 0) {
|
||||||
dfu->dfu_state = DFU_STATE_dfuERROR;
|
dfu->dfu_state = DFU_STATE_dfuERROR;
|
||||||
perror("open");
|
perror("open");
|
||||||
|
@ -609,6 +624,7 @@ static int dfu_bind_config(struct usb_configuration *c)
|
||||||
{
|
{
|
||||||
struct f_dfu *dfu;
|
struct f_dfu *dfu;
|
||||||
struct usb_function *func;
|
struct usb_function *func;
|
||||||
|
struct file_list_entry *fentry;
|
||||||
int status;
|
int status;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -628,15 +644,17 @@ static int dfu_bind_config(struct usb_configuration *c)
|
||||||
dfu->dfu_state = DFU_STATE_appIDLE;
|
dfu->dfu_state = DFU_STATE_appIDLE;
|
||||||
dfu->dfu_status = DFU_STATUS_OK;
|
dfu->dfu_status = DFU_STATUS_OK;
|
||||||
|
|
||||||
dfu_string_defs = xzalloc(sizeof(struct usb_string) * (dfu_num_alt + 2));
|
dfu_string_defs = xzalloc(sizeof(struct usb_string) * (dfu_files->num_entries + 2));
|
||||||
dfu_string_defs[0].s = "Generic DFU";
|
dfu_string_defs[0].s = "Generic DFU";
|
||||||
dfu_string_defs[0].id = status;
|
dfu_string_defs[0].id = status;
|
||||||
for (i = 0; i < dfu_num_alt; i++) {
|
i = 0;
|
||||||
dfu_string_defs[i + 1].s = dfu_devs[i].name;
|
file_list_for_each_entry(dfu_files, fentry) {
|
||||||
|
dfu_string_defs[i + 1].s = fentry->name;
|
||||||
status = usb_string_id(c->cdev);
|
status = usb_string_id(c->cdev);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
goto out;
|
goto out;
|
||||||
dfu_string_defs[i + 1].id = status;
|
dfu_string_defs[i + 1].id = status;
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
dfu_string_defs[i + 1].s = NULL;
|
dfu_string_defs[i + 1].s = NULL;
|
||||||
dfu_string_table.strings = dfu_string_defs;
|
dfu_string_table.strings = dfu_string_defs;
|
||||||
|
@ -752,8 +770,7 @@ int usb_dfu_register(struct usb_dfu_pdata *pdata)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dfu_devs = pdata->alts;
|
dfu_files = pdata->files;
|
||||||
dfu_num_alt = pdata->num_alts;
|
|
||||||
|
|
||||||
ret = usb_composite_probe(&dfu_driver);
|
ret = usb_composite_probe(&dfu_driver);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef __FILE_LIST
|
||||||
|
#define __FILE_LIST
|
||||||
|
|
||||||
|
#define FILE_LIST_FLAG_SAFE (1 << 0)
|
||||||
|
#define FILE_LIST_FLAG_READBACK (1 << 1)
|
||||||
|
#define FILE_LIST_FLAG_CREATE (1 << 2)
|
||||||
|
|
||||||
|
struct file_list_entry {
|
||||||
|
char *name;
|
||||||
|
char *filename;
|
||||||
|
unsigned long flags;
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct file_list {
|
||||||
|
struct list_head list;
|
||||||
|
int num_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct file_list *file_list_parse(const char *str);
|
||||||
|
void file_list_free(struct file_list *);
|
||||||
|
|
||||||
|
#define file_list_for_each_entry(files, entry) \
|
||||||
|
list_for_each_entry(entry, &files->list, list)
|
||||||
|
|
||||||
|
#endif /* __FILE_LIST */
|
|
@ -21,20 +21,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <file-list.h>
|
||||||
#define DFU_FLAG_SAFE (1 << 0)
|
|
||||||
#define DFU_FLAG_READBACK (1 << 1)
|
|
||||||
#define DFU_FLAG_CREATE (1 << 2)
|
|
||||||
|
|
||||||
struct usb_dfu_dev {
|
|
||||||
char *name;
|
|
||||||
char *dev;
|
|
||||||
unsigned long flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct usb_dfu_pdata {
|
struct usb_dfu_pdata {
|
||||||
struct usb_dfu_dev *alts;
|
struct file_list *files;
|
||||||
int num_alts;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int usb_dfu_register(struct usb_dfu_pdata *);
|
int usb_dfu_register(struct usb_dfu_pdata *);
|
||||||
|
|
Loading…
Reference in New Issue