TAILQ_HEAD(tailhead, dfu_frame) ioq;
int ioq_len;
+ uint64_t total_size;
+
char *dfu_entry_list[DFU_ENTRY_LIST_MAXLEN][DFU_INFO_MAX];
};
-void *dfu_get_buffer(unsigned long size)
+void *dfu_get_buffer(struct dfu_entry *e, unsigned long size)
{
int wait = 100000; /* 100ms */
void *buf;
wait *= 2;
}
+ e->buffer = buf;
+ e->buf_len = size;
+
return buf;
}
-void dfu_put_buffer(void *ptr)
+void dfu_put_buffer(struct dfu_entry *e)
{
- free(ptr);
+ if (!e || !e->buffer) {
+ fprintf(stderr, "Invalid free request\n");
+ return;
+ }
+
+ free(e->buffer);
+ e->buffer = NULL;
+ e->buf_len = 0;
}
static char **find_entry_match(struct dfu_context *ctx, const char *name)
return NULL;
}
-int dfu_request_io(struct dfu_entry *e, void *buffer, unsigned long len)
+int dfu_request_io(struct dfu_entry *e)
{
- struct dfu_context *ctx = e->ctx;
+ struct dfu_context *ctx;
struct dfu_frame *frame;
int notify = 0;
+ if (!e || !e->buffer || e->buf_len == 0)
+ return -EINVAL;
+
frame = malloc(sizeof(*frame));
if (!frame)
return -ENOMEM;
- frame->buf = buffer;
- frame->len = len;
+ frame->buf = e->buffer;
+ frame->len = e->buf_len;
+ ctx = e->ctx;
retry:
pthread_mutex_lock(&ctx->mutex);
if (notify)
pthread_cond_signal(&ctx->data_arrived);
+ /* buffer will be freed by dfu_thread_main() after write is finished */
+ e->buffer = NULL;
+ e->buf_len = 0;
+
return 0;
}
TAILQ_REMOVE(&ctx->ioq, frame, entry);
- dfu_put_buffer(frame->buf);
+ free(frame->buf);
free(frame);
}
fprintf(stdout, "#");
fflush(stdout);
- dfu_put_buffer(frame->buf);
+ free(frame->buf);
free(frame);
/* transfer finished */
e->entry = entry;
e->fd = fd;
e->file_size = size;
+ e->buffer = NULL;
+ e->buf_len = 0;
e->transfer_done = 0;
err:
return ret;
}
+void dfu_init_download(struct dfu_context *ctx, uint64_t size)
+{
+ ctx->total_size = size;
+
+ fprintf(stdout, "Start Download (Total: %.2lfMB)\n",
+ (double)size / (1024.0f * 1024.0f));
+}
+
struct dfu_entry *dfu_start(struct dfu_context *ctx,
uint64_t size, const char *filename)
{
ctx->thread = 0;
TAILQ_INIT(&ctx->ioq);
ctx->ioq_len = 0;
+ ctx->total_size = 0;
pthread_mutex_init(&ctx->mutex, NULL);
pthread_mutex_init(&ctx->sync_mutex, NULL);
struct dfu_context *ctx;
char **entry;
int fd;
- uint64_t file_size;
+ uint64_t file_size; /* size of a flashing file */
+ void *buffer; /* receive buffer for flashing */
+ unsigned long buf_len; /* filled size of buffer */
int transfer_done;
};
-void *dfu_get_buffer(unsigned long size);
-void dfu_put_buffer(void *ptr);
+void *dfu_get_buffer(struct dfu_entry *e, unsigned long size);
+void dfu_put_buffer(struct dfu_entry *e);
struct dfu_context *dfu_alloc_context(void);
void dfu_free_context(struct dfu_context *ctx);
int dfu_init_entry(struct dfu_context *ctx, const char *entry_file);
+void dfu_init_download(struct dfu_context *ctx, uint64_t size);
struct dfu_entry *dfu_start(struct dfu_context *ctx,
uint64_t size, const char *filename);
void dfu_sync(struct dfu_entry *e);
-int dfu_request_io(struct dfu_entry *e, void *buffer, unsigned long len);
+int dfu_request_io(struct dfu_entry *e);
#endif
struct tfm_interface *intf;
struct dfu_context *dfu;
struct dfu_entry *dfu_entry;
-
- void *buffer;
- uint64_t file_size;
- uint64_t remain;
};
static unsigned int _checkboard(void)
struct tfm_interface *intf = tctx->intf;
struct dfu_entry *e = tctx->dfu_entry;
uint64_t recv = 0;
- uint64_t total = tctx->file_size;
- void *buf;
+ uint64_t total = e->file_size;
+ void *buf, *curr;
int usb_pkt_cnt = 0, n;
int ret;
- tctx->buffer = buf = dfu_get_buffer(FLASH_UNIT_SIZE);
+ buf = curr = dfu_get_buffer(e, FLASH_UNIT_SIZE);
while (total - recv >= packet_size) {
- n = tfm_interface_recv(intf, buf, packet_size);
+ n = tfm_interface_recv(intf, curr, packet_size);
- if (n < packet_size)
- return -EIO;
+ if (n < packet_size) {
+ ret = -EIO;
+ goto err;
+ }
recv += n;
- buf += packet_size;
+ curr += packet_size;
if ((recv % FLASH_UNIT_SIZE) == 0) {
- ret = dfu_request_io(e, tctx->buffer, FLASH_UNIT_SIZE);
- if (ret < 0)
- return -EIO;
+ ret = dfu_request_io(e);
+ if (ret < 0) {
+ ret = -EIO;
+ goto err;
+ }
- tctx->buffer = buf = dfu_get_buffer(FLASH_UNIT_SIZE);
+ buf = curr = dfu_get_buffer(e, FLASH_UNIT_SIZE);
}
thor_send_data_rsp(tctx, 0, ++usb_pkt_cnt);
}
- tctx->remain = (total - recv) + (uint64_t)(buf - tctx->buffer);
+ e->buf_len = (total - recv) + (uint64_t)(curr - buf);
if ((total - recv) > 0) {
- n = tfm_interface_recv(intf, buf, packet_size);
- if (n < packet_size)
- return -EIO;
+ n = tfm_interface_recv(intf, curr, packet_size);
+ if (n < packet_size) {
+ ret = -EIO;
+ goto err;
+ }
recv += n;
thor_send_data_rsp(tctx, 0, ++usb_pkt_cnt);
}
return 0;
+
+err:
+ dfu_put_buffer(e);
+
+ return ret;
}
static int thor_download_tail(struct thor_context *tctx)
struct dfu_entry *e = tctx->dfu_entry;
int ret;
- if (tctx->remain) {
- ret = dfu_request_io(e, tctx->buffer, tctx->remain);
+ if (e->buf_len) {
+ ret = dfu_request_io(e);
if (ret < 0)
return -EIO;
} else {
/* if there is no remain, buffer should be freed */
- dfu_put_buffer(tctx->buffer);
+ dfu_put_buffer(e);
}
dfu_sync(e);
switch (rqt->sub_id) {
case RQT_DL_INIT:
- tctx->file_size = (uint64_t)rqt->int_data[0]
+ {
+ struct dfu_context *dfu = tctx->dfu;
+ uint64_t total_size;
+
+ total_size = (uint64_t)rqt->int_data[0]
+ ((uint64_t)rqt->int_data[1] << 32);
+
+ dfu_init_download(dfu, total_size);
break;
+ }
case RQT_DL_FILE_INFO:
{
struct dfu_context *dfu = tctx->dfu;
struct dfu_entry *e;
char f_name[FILE_NAME_MAXLEN + 1] = {0,};
+ uint64_t file_size;
int file_type;
file_type = rqt->int_data[0];
break;
}
- tctx->file_size = (uint64_t)rqt->int_data[1]
+ file_size = (uint64_t)rqt->int_data[1]
+ ((uint64_t)rqt->int_data[2] << 32);
memcpy(f_name, rqt->str_data[0], FILE_NAME_MAXLEN);
rsp.int_data[0] = DATA_PKT_SIZE;
- e = dfu_start(dfu, tctx->file_size, f_name);
+ e = dfu_start(dfu, file_size, f_name);
if (!e) {
fprintf(stderr, "failed to start dfu\n");
ret = -EINVAL;
ret = rsp.ack = -EINVAL;
break;
}
- ret = thor_download_head(tctx, DATA_PKT_SIZE);
- if (ret < 0)
- tctx->remain = 0;
-
- return ret;
+ return thor_download_head(tctx, DATA_PKT_SIZE);
case RQT_DL_FILE_END:
rsp.ack = thor_download_tail(tctx);
ret = rsp.ack;
- tctx->remain = 0;
- tctx->file_size = 0;
/*
* dfu_entry and buffer will be freed by dfu_thread_cleanup,
* so just make it NULL here.
*/
tctx->dfu_entry = NULL;
- tctx->buffer = NULL;
break;
case RQT_DL_EXIT:
break;