#define DFU_INFO_MODE_PARTITION 'p'
#define DFU_INFO_MODE_FILE 'f'
+#define DFU_INFO_PART_A "a"
+#define DFU_INFO_PART_B "b"
#define DFU_IOQ_MAXLEN 5
DFU_INFO_PARTITION,
DFU_INFO_NAME,
DFU_INFO_PATH,
+ DFU_INFO_AB,
DFU_INFO_MAX,
};
state = DFU_THREAD_STATE_ERROR;
}
+ if (e->fd_b > 0) {
+ ret = write(e->fd_b, frame->buf, frame->len);
+ if (ret < frame->len) {
+ fprintf(stderr, "Error occurs while flashing\n");
+ state = DFU_THREAD_STATE_ERROR;
+ }
+ }
+
+
progress += frame->len;
fsync(e->fd);
+ if (e->fd_b > 0)
+ fsync(e->fd_b);
pthread_mutex_lock(&ctx->mutex);
TAILQ_REMOVE(&ctx->ioq, frame, entry);
return NULL;
}
+static int find_slot_b(struct dfu_context *ctx, char *name) {
+ int fd = -1;
+ char *file = NULL;
+ int i, ret = 0;
+
+ for (i = 0; i < DFU_ENTRY_LIST_MAXLEN; i++) {
+ char *entry_name = ctx->dfu_entry_list[i][DFU_INFO_NAME];
+ char *entry_ab = ctx->dfu_entry_list[i][DFU_INFO_AB];
+
+ if (entry_ab && strncmp(entry_ab, DFU_INFO_PART_B, strlen(entry_ab)) == 0) {
+ if (entry_name && !strncmp(entry_name, name, strlen(entry_name))) {
+ char **entry = ctx->dfu_entry_list[i];
+ switch (*entry[DFU_INFO_MODE]) {
+ case DFU_INFO_MODE_PARTITION:
+ file = strdup(entry[DFU_INFO_PARTITION]);
+ break;
+ case DFU_INFO_MODE_FILE:
+ {
+ int path_prefix = strlen(DFU_MOUNT_PATH);
+ int path_suffix = strlen(entry[DFU_INFO_PATH]);
+ int path_name = strlen(entry[DFU_INFO_NAME]);
+
+ ret = mount_dev(entry[DFU_INFO_PARTITION]);
+ if (ret < 0)
+ return -EINVAL;
+
+ file = malloc(path_prefix + path_suffix + path_name + 1);
+ if (!file) {
+ umount_dev();
+ return -ENOMEM;
+ }
+
+ strncpy(file, DFU_MOUNT_PATH, path_prefix + 1);
+ strncat(file, entry[DFU_INFO_PATH], path_suffix + 1);
+ strncat(file, entry[DFU_INFO_NAME], path_name + 1);
+ break;
+ }
+ default:
+ fprintf(stderr,
+ "flash entry '%s' has wrong mode\n",
+ entry_name);
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (file)
+ break;
+ }
+
+ if (!file)
+ return -EINVAL;
+
+ fd = open(file, O_WRONLY);
+ if (fd < 0) {
+ fprintf(stderr,
+ "cannot open target: %s\n", name);
+ fd = -EIO;
+ }
+
+ free(file);
+
+ return fd;
+}
+
+/* Set entry values for dfu */
static int dfu_start_entry(struct dfu_entry *e, char **entry, uint64_t size)
{
char *file;
e->buf_len = 0;
e->transfer_done = 0;
+ /* Check if there is the slot B */
+ e->fd_b = find_slot_b(e->ctx, entry[DFU_INFO_NAME]);
err:
free(file);
if (!e)
return NULL;
+ e->ctx = ctx;
+
ret = dfu_start_entry(e, entry, size);
if (ret < 0) {
fprintf(stderr, "Cannot start download: %s\n", filename);
else
fprintf(stdout, "\n%s", filename);
- e->ctx = ctx;
pthread_create(&ctx->thread, NULL, dfu_thread_main, e);
return e;
pthread_mutex_unlock(&ctx->sync_mutex);
close(e->fd);
+ close(e->fd_b);
if (*info[DFU_INFO_MODE] == DFU_INFO_MODE_FILE)
umount_dev();