blob: b1d865ad522bf0898e922b89331109990d7d274a [file] [log] [blame]
// Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <zlib.h>
#include "global.h"
#include "error.h"
#include "wimax.h"
#include "wm_ioctl.h"
#include "io.h"
#include "device.h"
#include "hci.h"
#include "log.h"
#include "fload.h"
typedef const char * ld_file_t;
typedef struct {
void *p;
int size;
} ld_buf_t;
typedef struct {
bool is_file;
union {
ld_file_t path;
ld_buf_t buf;
} u;
} ld_dst_t;
int bl_upload(int dev_idx, int type, void *buf, int size, void (*progress)(int bytes))
{
xprintf(SDK_ERR, "%s: not supported!\n", __func__);
return -1;
}
int bl_download(int dev_idx, int type, void *buf, int size, void (*progress)(int bytes))
{
xprintf(SDK_ERR, "%s: not supported!\n", __func__);
return -1;
}
static int do_read_file(int dev_idx, const char *target_file,
ld_dst_t *dst, void (*progress)(int bytes))
{
device_t *dev;
u8 send_buf[HCI_MAX_PACKET];
u8 recv_buf[HCI_MAX_PACKET];
hci_file_read_t *file = (hci_file_read_t *) send_buf;
hci_file_response_t *rsp;
u32 offset = 0;
int fd = 0;
int ret = -1, len, max_size = 0;
char *p = NULL;
u16 cmd;
void *param;
int plen;
if (!(dev = dm_get_dev(dev_idx)))
return -1;
xfunc_in("[%d]", dev_idx);
if (dst->is_file) {
if ((fd = open(dst->u.path, O_CREAT|O_WRONLY|O_TRUNC, 0644)) < 0) {
xprintf(SDK_STD_ERR, "open(%s) fail\n", dst->u.path);
goto out;
}
}
else {
if (!dst->u.buf.p || !dst->u.buf.size) {
xprintf(SDK_ERR, "buf=%p, size=%d\n", dst->u.buf.p, dst->u.buf.size);
goto out;
}
p = dst->u.buf.p;
max_size = dst->u.buf.size;
}
strcpy((char *)file->path, target_file);
cmd = WIMAX_READ_FILE;
param = file;
plen = sizeof(hci_file_read_t) + strlen((char *)file->path) + 1/*null*/;
pthread_mutex_lock(&dev->load_lock);
while (1) {
file->offset = DH2B(offset);
ret = hci_send_wait(dev_idx, cmd, param, plen,
WIMAX_FILE_RESULT, recv_buf, sizeof(recv_buf), 0, 0, 3);
if (ret < 0)
break;
rsp = (hci_file_response_t *) recv_buf;
if (!(len = DB2H(rsp->result))) {
ret = 0;
break;
}
if (len < 0) {
xprintf(SDK_ERR, "Read file failed(%d)\n", ret);
ret = -1;
break;
}
if (dst->is_file) {
ret = write(fd, file_response_data(rsp), len);
if (ret <= 0) {
xprintf(SDK_ERR, "Write fail %s(%d!=%d)\n", dst->u.path, ret, len);
ret = -1;
break;
}
}
else {
if (offset + len > max_size) {
xprintf(SDK_ERR, "buffer is too small(%d > %d)\n",
offset + len, max_size);
ret = -1;
break;
}
memcpy(p+offset, file_response_data(rsp), len);
}
offset += len;
if (progress)
progress(offset);
}
pthread_mutex_unlock(&dev->load_lock);
out:
if (fd > 0)
close(fd);
xprintf(SDK_INFO, "Read file size=%d\n", offset);
if (!ret) {
if (!offset)
ret = -ENOENT;
else
ret = offset;
}
xfunc_out("ret=%d", ret);
dm_put_dev(dev_idx);
return ret;
}
int fl_read_file(int dev_idx, const char *target_file,
const char *host_file, void (*progress)(int bytes))
{
ld_dst_t dst;
int ret;
dst.is_file = TRUE;
dst.u.path = host_file;
ret = do_read_file(dev_idx, target_file, &dst, progress);
return ret;
}