815 lines
18 KiB
C
815 lines
18 KiB
C
#define LOG_TAG "adb.sync"
|
|
|
|
#include "adb_services.h"
|
|
#include "adb.h"
|
|
#include "adb_utils.h"
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
#include "queue.h"
|
|
#include "lsfs.h"
|
|
|
|
#include "tusb.h"
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
#include "adb_sync_ext_disk.h"
|
|
|
|
#ifndef CONFIG_ADB_PUSH_PULL_DEFAULT_ROOT
|
|
#define CONFIG_ADB_PUSH_PULL_DEFAULT_ROOT "/RAM:/adb/"
|
|
#endif
|
|
|
|
#define ADB_SYNC_FS_ROOT CONFIG_ADB_PUSH_PULL_DEFAULT_ROOT
|
|
|
|
#define SYNC_ID(a, b, c, d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
|
|
|
|
#define ADB_SYNC_ID_LIST SYNC_ID('L', 'I', 'S', 'T')
|
|
#define ADB_SYNC_ID_RECV SYNC_ID('R', 'E', 'C', 'V')
|
|
#define ADB_SYNC_ID_SEND SYNC_ID('S', 'E', 'N', 'D')
|
|
#define ADB_SYNC_ID_STAT SYNC_ID('S', 'T', 'A', 'T')
|
|
#define ADB_SYNC_ID_FAIL SYNC_ID('F', 'A', 'I', 'L')
|
|
#define ADB_SYNC_ID_DATA SYNC_ID('D', 'A', 'T', 'A')
|
|
#define ADB_SYNC_ID_DONE SYNC_ID('D', 'O', 'N', 'E')
|
|
#define ADB_SYNC_ID_OKAY SYNC_ID('O', 'K', 'A', 'Y')
|
|
#define ADB_SYNC_ID_QUIT SYNC_ID('Q', 'U', 'I', 'T')
|
|
#define ADB_SYNC_ID_DENT SYNC_ID('D', 'E', 'N', 'T')
|
|
|
|
|
|
struct adb_sync_req {
|
|
uint32_t id;
|
|
uint32_t len;
|
|
};
|
|
|
|
struct adb_sync_rsp_data {
|
|
uint32_t id;
|
|
uint32_t len;
|
|
};
|
|
|
|
struct adb_sync_rsp_stat {
|
|
uint32_t id;
|
|
uint32_t mode;
|
|
uint32_t size;
|
|
uint32_t time;
|
|
};
|
|
|
|
struct adb_sync_send_data {
|
|
uint32_t id;
|
|
uint32_t chunk_size;
|
|
};
|
|
|
|
struct adb_sync_done_data {
|
|
uint32_t id;
|
|
uint32_t time;
|
|
};
|
|
|
|
struct adb_sync_dent_data {
|
|
uint32_t id;
|
|
uint32_t mode;
|
|
uint32_t size;
|
|
uint32_t time;
|
|
uint32_t namelen;
|
|
};
|
|
|
|
struct adb_sync_ctx {
|
|
QueueHandle_t rx_queue;
|
|
struct adb_service *s;
|
|
uint32_t rd_pos;
|
|
adb_packet_t *curr_pkt;
|
|
};
|
|
|
|
static inline uint32_t adb_sync_buffer_claim(struct adb_sync_ctx *ctx, uint8_t **data, uint32_t size)
|
|
{
|
|
uint32_t len;
|
|
|
|
if (ctx->curr_pkt == NULL) {
|
|
adb_packet_t *p = NULL;
|
|
if (xQueueReceive(ctx->rx_queue, &p, portMAX_DELAY) != pdTRUE) {
|
|
ADB_LOGE("sync buffer read timeout\n");
|
|
return -1;
|
|
}
|
|
ctx->rd_pos = 0;
|
|
ctx->curr_pkt = p;
|
|
}
|
|
|
|
if ((ctx->rd_pos + size) > ctx->curr_pkt->msg.data_length) {
|
|
len = ctx->curr_pkt->msg.data_length - ctx->rd_pos;
|
|
} else {
|
|
len = size;
|
|
}
|
|
|
|
*data = ctx->curr_pkt->data + ctx->rd_pos;
|
|
|
|
return len;
|
|
}
|
|
|
|
static inline void adb_sync_buffer_commit(struct adb_sync_ctx *ctx, uint32_t size)
|
|
{
|
|
ctx->rd_pos += size;
|
|
|
|
if (ctx->rd_pos >= ctx->curr_pkt->msg.data_length) {
|
|
adb_packet_free(ctx->curr_pkt);
|
|
ctx->curr_pkt = NULL;
|
|
ctx->rd_pos = 0;
|
|
}
|
|
}
|
|
|
|
static inline int adb_sync_buffer_read(struct adb_sync_ctx *ctx, uint8_t *data, uint32_t size)
|
|
{
|
|
int len;
|
|
|
|
while (size) {
|
|
uint8_t *p = NULL;
|
|
len = adb_sync_buffer_claim(ctx, &p, size);
|
|
memcpy(data, p, len);
|
|
adb_sync_buffer_commit(ctx, len);
|
|
data += len;
|
|
size -= len;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static uint8_t *adb_get_full_path(const char *file_name)
|
|
{
|
|
uint8_t *full_path = NULL;
|
|
uint32_t len;
|
|
if (file_name[0] != '/') {
|
|
len = strlen(ADB_SYNC_FS_ROOT) + strlen(file_name) + 1;
|
|
} else {
|
|
len = strlen(file_name) + 1;
|
|
}
|
|
|
|
full_path = ADB_MALLOC(len);
|
|
|
|
if (full_path == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memset(full_path, 0, len);
|
|
if (file_name[0] != '/') {
|
|
strcat(full_path, ADB_SYNC_FS_ROOT);
|
|
}
|
|
|
|
strcat(full_path, file_name);
|
|
|
|
return full_path;
|
|
}
|
|
|
|
static uint8_t *adb_get_dir_path(const char *file_name)
|
|
{
|
|
uint32_t idx = strlen(file_name) - 1;
|
|
|
|
while (idx >= 0) {
|
|
if (file_name[idx] == '/') {
|
|
break;
|
|
}
|
|
idx--;
|
|
}
|
|
|
|
if (idx < 0) {
|
|
return NULL;
|
|
}
|
|
|
|
uint32_t len = idx + 1;
|
|
|
|
uint8_t *dir_path = (uint8_t *)malloc(len + 1);
|
|
if (dir_path == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(dir_path, file_name, len);
|
|
dir_path[len] = '\0';
|
|
|
|
return dir_path;
|
|
}
|
|
|
|
static void adb_sync_rsp_okay(struct adb_service *s)
|
|
{
|
|
struct adb_sync_rsp_data okay_data = {
|
|
.id = ADB_SYNC_ID_OKAY,
|
|
.len = 0,
|
|
};
|
|
|
|
adb_service_write_remote(s, (uint8_t *)&okay_data, sizeof(struct adb_sync_rsp_data));
|
|
}
|
|
|
|
static void adb_sync_rsp_fail(struct adb_service *s)
|
|
{
|
|
struct adb_sync_rsp_data fail_data = {
|
|
.id = ADB_SYNC_ID_FAIL,
|
|
.len = 0,
|
|
};
|
|
|
|
adb_service_write_remote(s, (uint8_t *)&fail_data, sizeof(fail_data));
|
|
}
|
|
|
|
static void adb_sync_rsp_stat(struct adb_service *s, struct adb_sync_rsp_stat *stat)
|
|
{
|
|
adb_service_write_remote(s, (uint8_t *)stat, sizeof(struct adb_sync_rsp_stat));
|
|
}
|
|
|
|
static void *adb_file_open_create(const char *name)
|
|
{
|
|
struct lsfs_file_t *f = ADB_MALLOC(sizeof(struct lsfs_file_t));
|
|
uint8_t *file_path = NULL;
|
|
|
|
if (f == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (name[0] != '/') {
|
|
file_path = ADB_MALLOC(strlen(ADB_SYNC_FS_ROOT) + strlen(name) + 1);
|
|
if (file_path == NULL) {
|
|
ADB_LOGE("adb file open failed, malloc error");
|
|
ADB_FREE(f);
|
|
return NULL;
|
|
}
|
|
strcat(file_path, ADB_SYNC_FS_ROOT);
|
|
} else {
|
|
file_path = ADB_MALLOC(strlen(name) + 1);
|
|
if (file_path == NULL) {
|
|
ADB_LOGE("adb file open failed, malloc error");
|
|
ADB_FREE(f);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
memset(f, 0, sizeof(struct lsfs_file_t));
|
|
strcat(file_path, name);
|
|
|
|
int r = lsfs_open(f, file_path, LSFS_O_CREATE | LSFS_O_TRUNC | LSFS_O_WRITE);
|
|
if (r != 0) {
|
|
ADB_FREE(f);
|
|
ADB_FREE(file_path);
|
|
ADB_LOGE("adb file open failed, %d\n", r);
|
|
return NULL;
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
static void adb_file_close(void *f)
|
|
{
|
|
int r = lsfs_close((struct lsfs_file_t *)f);
|
|
|
|
if (r != 0) {
|
|
ADB_LOGE("adb file close failed, %d\n", r);
|
|
}
|
|
}
|
|
|
|
static void do_stat(struct adb_service *s, struct adb_sync_req *req)
|
|
{
|
|
struct adb_sync_ctx *ctx = s->data;
|
|
uint8_t *file_name = ADB_MALLOC(req->len + 1);
|
|
int r;
|
|
uint8_t *full_path = NULL;
|
|
|
|
if (file_name == NULL) {
|
|
ADB_LOGE("do stat,file_name ADB_MALLOC error\n");
|
|
adb_sync_rsp_fail(s);
|
|
return;
|
|
}
|
|
file_name[req->len] = '\0';
|
|
adb_sync_buffer_read(ctx, file_name, req->len);
|
|
|
|
struct lsfs_dirent *ls_stat = ADB_MALLOC(sizeof(struct lsfs_dirent));
|
|
if (ls_stat == NULL) {
|
|
ADB_LOGE("do stat, ls_stat ADB_MALLOC error\n");
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
|
|
full_path = adb_get_full_path(file_name);
|
|
if (full_path == NULL) {
|
|
ADB_LOGE("do stat, adb_get_full_path error\n");
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
ADB_LOGI("sync stat, stat file name: %s, full path: %s\n", file_name, full_path);
|
|
memset(ls_stat, 0, sizeof(struct lsfs_dirent));
|
|
struct adb_sync_rsp_stat stat = {0};
|
|
stat.id = ADB_SYNC_ID_STAT;
|
|
|
|
if (adb_sync_is_ext_disk_access(full_path)) {
|
|
char *disk_name = NULL;
|
|
uint32_t start_addr = 0;
|
|
uint32_t size = 0;
|
|
r = adb_sync_ext_disk_get_info_by_path(full_path, &disk_name, &start_addr, &size);
|
|
if (r == 0) {
|
|
stat.mode = 33188;
|
|
stat.size = size;
|
|
stat.time = 0;
|
|
}
|
|
} else {
|
|
r = lsfs_stat(full_path, ls_stat);
|
|
if (r == 0) {
|
|
/* normal file, 0o100644 */
|
|
stat.mode = ls_stat->type == 0 ? 33188 : 16877;
|
|
stat.size = ls_stat->size;
|
|
|
|
/* TOTO: time */
|
|
stat.time = 0;
|
|
ADB_LOGI("file details: name=%s, size=%d, type=%d\n", ls_stat->name, ls_stat->size,
|
|
ls_stat->type);
|
|
} else {
|
|
ADB_LOGE("Failed to get file stat, name:%s, error:%d\n", file_name, r);
|
|
}
|
|
}
|
|
|
|
adb_sync_rsp_stat(s, &stat);
|
|
failed:
|
|
ADB_FREE(file_name);
|
|
ADB_FREE(ls_stat);
|
|
ADB_FREE(full_path);
|
|
}
|
|
|
|
static void do_send(struct adb_service *s, struct adb_sync_req *req)
|
|
{
|
|
struct adb_sync_ctx *ctx = s->data;
|
|
uint32_t total_size = 0;
|
|
|
|
uint8_t *file_name = ADB_MALLOC(req->len + 1);
|
|
uint8_t *buff = NULL;
|
|
const int buff_size = MAX_PAYLOAD;
|
|
int r;
|
|
|
|
if (file_name == NULL) {
|
|
ADB_LOGE("do_send, file_name ADB_MALLOC error\n");
|
|
goto failed;
|
|
}
|
|
file_name[req->len] = '\0';
|
|
buff = ADB_MALLOC(buff_size);
|
|
if (buff == NULL) {
|
|
ADB_LOGE("do_send, buff ADB_MALLOC error\n");
|
|
goto failed;
|
|
}
|
|
|
|
adb_sync_buffer_read(ctx, file_name, req->len);
|
|
|
|
/* format: filename,mode */
|
|
for (int i = 0; i < req->len; i++) {
|
|
if (file_name[i] == ',') {
|
|
file_name[i] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint8_t *full_path = adb_get_full_path(file_name);
|
|
if (full_path == NULL) {
|
|
ADB_LOGE("do_send, adb_get_full_path error\n");
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
|
|
ADB_LOGI("sync send, file name: %s, full path: %s\n", file_name, full_path);
|
|
|
|
if (adb_sync_is_ext_disk_access(full_path)) {
|
|
char *disk_name = NULL;
|
|
uint32_t start_addr = 0;
|
|
uint32_t size = 0;
|
|
adb_sync_ext_disk_get_info_by_path(full_path, &disk_name, &start_addr, &size);
|
|
ADB_LOGI("do_send, ext disk access, disk_name:%s, start_addr:0x%x, size:0x%x\n", disk_name, start_addr, size);
|
|
struct adb_sync_ext_disk_ctx *disk_ctx = adb_sync_ext_disk_ctx_init(disk_name, start_addr);
|
|
if (disk_ctx == NULL) {
|
|
ADB_LOGE("do send, ext disk init error\n");
|
|
goto failed;
|
|
}
|
|
while (1) {
|
|
struct adb_sync_send_data req;
|
|
adb_sync_buffer_read(ctx, (uint8_t *)&req, sizeof(struct adb_sync_send_data));
|
|
|
|
if (req.id != ADB_SYNC_ID_DATA) {
|
|
if (req.id == ADB_SYNC_ID_DONE) {
|
|
ADB_LOGI("do_send, done, timestamp:%d\n", req.chunk_size);
|
|
adb_sync_rsp_okay(s);
|
|
adb_sync_ext_disk_ctx_free(disk_ctx);
|
|
goto done;
|
|
} else {
|
|
ADB_LOGE("do_send, unknown req id:%x\n", req.id);
|
|
adb_sync_ext_disk_ctx_free(disk_ctx);
|
|
goto failed;
|
|
}
|
|
}
|
|
if (req.chunk_size > 65536) {
|
|
ADB_LOGE("do_send, invalid chunksize: %d\n", req.chunk_size);
|
|
adb_sync_ext_disk_ctx_free(disk_ctx);
|
|
goto failed;
|
|
}
|
|
while (req.chunk_size) {
|
|
uint8_t *p = NULL;
|
|
int n = 0;
|
|
n = adb_sync_buffer_claim(ctx, &p, req.chunk_size);
|
|
req.chunk_size -= n;
|
|
r = adb_sync_ext_disk_write(disk_ctx, p, n);
|
|
adb_sync_buffer_commit(ctx, n);
|
|
if (r) {
|
|
ADB_LOGE("do_send, ext disk write error: %d\n", r);
|
|
adb_sync_ext_disk_ctx_free(disk_ctx);
|
|
goto failed;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct lsfs_file_t fp = {0};
|
|
|
|
uint8_t *dir_path = adb_get_dir_path(full_path);
|
|
ADB_LOGI("sync send, dir path: %s\n", dir_path);
|
|
if (dir_path == NULL) {
|
|
ADB_LOGE("do_send, adb_get_dir_path error\n");
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
|
|
struct lsfs_dir_t dir;
|
|
uint8_t *p = dir_path + 1;
|
|
for (; *p; p++) {
|
|
if (*p == '/') {
|
|
*p = '\0';
|
|
ADB_LOGI("sync send, mkdir dir path: %s\n", dir_path);
|
|
lsfs_dir_t_init(&dir);
|
|
r = lsfs_opendir(&dir, dir_path);
|
|
if (r) {
|
|
r = lsfs_mkdir(dir_path);
|
|
if (r) {
|
|
ADB_LOGE("lsfs_mkdir error: %d\n", r);
|
|
lsfs_closedir(&dir);
|
|
adb_sync_rsp_fail(s);
|
|
ADB_FREE(dir_path);
|
|
goto failed;
|
|
}
|
|
} else {
|
|
lsfs_closedir(&dir);
|
|
}
|
|
*p = '/';
|
|
}
|
|
}
|
|
ADB_FREE(dir_path);
|
|
|
|
r = lsfs_open(&fp, full_path, LSFS_O_WRITE | LSFS_O_CREATE | LSFS_O_TRUNC);
|
|
if (r != 0) {
|
|
ADB_LOGE("open file error: %d\n", r);
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
|
|
/**
|
|
* DATA(4) CHUNK_SIZE(4) DATAS(CHUNK_SIZE)
|
|
* DATA(4) CHUNK_SIZE(4) DATAS(CHUNK_SIZE)
|
|
* DATA(4) CHUNK_SIZE(4) DATAS(CHUNK_SIZE)
|
|
* ....
|
|
* DONE(4) TIME(4)
|
|
*/
|
|
uint32_t total_recv_size = 0;
|
|
while (1) {
|
|
struct adb_sync_send_data req;
|
|
adb_sync_buffer_read(ctx, (uint8_t *)&req, sizeof(struct adb_sync_send_data));
|
|
uint8_t *cmd = (uint8_t *)&req.id;
|
|
|
|
if (req.id != ADB_SYNC_ID_DATA) {
|
|
if (req.id == ADB_SYNC_ID_DONE) {
|
|
ADB_LOGI("do_send, done, timestamp:%d\n", req.chunk_size);
|
|
adb_sync_rsp_okay(s);
|
|
goto done;
|
|
} else {
|
|
ADB_LOGE("do_send, unknown req id:%x\n", req.id);
|
|
goto failed;
|
|
}
|
|
}
|
|
|
|
if (req.chunk_size > 65536) {
|
|
ADB_LOGE("do_send, invalid chunksize: %d\n", req.chunk_size);
|
|
goto failed;
|
|
}
|
|
|
|
while (req.chunk_size) {
|
|
uint8_t *p = NULL;
|
|
int n = 0;
|
|
n = adb_sync_buffer_claim(ctx, &p, req.chunk_size);
|
|
req.chunk_size -= n;
|
|
r = lsfs_write(&fp, p, n);
|
|
adb_sync_buffer_commit(ctx, n);
|
|
total_size += r;
|
|
ADB_LOGD("do_send, file saved %d bytes", total_size);
|
|
if (r != n) {
|
|
ADB_LOGE("lsfs write error: %d\n", r);
|
|
goto failed;
|
|
}
|
|
}
|
|
}
|
|
|
|
failed:
|
|
adb_sync_rsp_fail(s);
|
|
|
|
done:
|
|
ADB_FREE(file_name);
|
|
ADB_FREE(buff);
|
|
ADB_FREE(full_path);
|
|
|
|
adb_file_close(&fp);
|
|
}
|
|
|
|
static void do_recv(struct adb_service *s, struct adb_sync_req *req)
|
|
{
|
|
uint8_t *full_path = NULL;
|
|
uint8_t *path = NULL;
|
|
uint8_t *read_buf = NULL;
|
|
int r;
|
|
const uint32_t chunk_size = MAX_PAYLOAD;
|
|
struct adb_sync_ctx *ctx = s->data;
|
|
|
|
read_buf = ADB_MALLOC(chunk_size);
|
|
if (read_buf == NULL) {
|
|
ADB_LOGE("do recv, read buff malloc error\n");
|
|
adb_sync_rsp_fail(s);
|
|
return;
|
|
}
|
|
|
|
path = ADB_MALLOC(req->len + 1);
|
|
if (path == NULL) {
|
|
ADB_LOGE("do recv, path ADB_MALLOC error\n");
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
path[req->len] = '\0';
|
|
adb_sync_buffer_read(ctx, path, req->len);
|
|
|
|
full_path = adb_get_full_path(path);
|
|
if (full_path == NULL) {
|
|
ADB_LOGE("do recv, get full path error\n");
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
|
|
ADB_LOGI("sync recv, path: %s, full path: %s\n", path, full_path);
|
|
struct adb_sync_send_data sd = {0};
|
|
sd.id = ADB_SYNC_ID_DATA;
|
|
|
|
if (adb_sync_is_ext_disk_access(full_path)) {
|
|
char *disk_name = NULL;
|
|
uint32_t start_addr = 0;
|
|
uint32_t size = 0;
|
|
|
|
adb_sync_ext_disk_get_info_by_path(full_path, &disk_name, &start_addr, &size);
|
|
ADB_LOGI("do_recv, ext disk access, disk_name:%s, start_addr:0x%x, size:0x%x\n", disk_name, start_addr, size);
|
|
struct adb_sync_ext_disk_ctx *disk_ctx = adb_sync_ext_disk_ctx_init(disk_name, start_addr);
|
|
if (disk_ctx == NULL) {
|
|
ADB_LOGE("do recv, ext disk init error\n");
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
uint32_t read_size = chunk_size / disk_ctx->sec_size * disk_ctx->sec_size;
|
|
|
|
while (1) {
|
|
r = adb_sync_ext_disk_read(disk_ctx, read_buf, size > read_size ? read_size : size);
|
|
if (r < 0) {
|
|
ADB_LOGE("do recv, ext disk read error: %d\n", r);
|
|
adb_sync_rsp_fail(s);
|
|
adb_sync_ext_disk_ctx_free(disk_ctx);
|
|
goto failed;
|
|
}
|
|
|
|
sd.id = ADB_SYNC_ID_DATA;
|
|
sd.chunk_size = r;
|
|
adb_service_write_remote(s, (uint8_t *)&sd,
|
|
sizeof(struct adb_sync_send_data));
|
|
adb_service_write_remote(s, (uint8_t *)read_buf, r);
|
|
size -= r;
|
|
|
|
if (size == 0) {
|
|
ADB_LOGI("do recv, ext disk read done\n");
|
|
sd.id = ADB_SYNC_ID_DONE;
|
|
sd.chunk_size = 0;
|
|
|
|
adb_service_write_remote(s, (uint8_t *)&sd,
|
|
sizeof(struct adb_sync_send_data));
|
|
adb_sync_ext_disk_ctx_free(disk_ctx);
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct lsfs_file_t fp = {0};
|
|
r = lsfs_open(&fp, full_path, LSFS_O_READ | LSFS_O_RDWR);
|
|
if (r) {
|
|
adb_sync_rsp_fail(s);
|
|
ADB_LOGE("do recv, lsfs open error: %d\n", r);
|
|
goto failed;
|
|
}
|
|
|
|
while (1) {
|
|
r = lsfs_read(&fp, read_buf, chunk_size);
|
|
if (r < 0) {
|
|
ADB_LOGE("do recv, lsfs read error: %d\n", r);
|
|
adb_sync_rsp_fail(s);
|
|
lsfs_close(&fp);
|
|
goto failed;
|
|
} else if (r == 0) {
|
|
ADB_LOGI("do recv, lsfs read done\n");
|
|
lsfs_close(&fp);
|
|
sd.id = ADB_SYNC_ID_DONE;
|
|
sd.chunk_size = 0;
|
|
|
|
adb_service_write_remote(s, (uint8_t *)&sd,
|
|
sizeof(struct adb_sync_send_data));
|
|
break;
|
|
} else {
|
|
sd.id = ADB_SYNC_ID_DATA;
|
|
sd.chunk_size = r;
|
|
adb_service_write_remote(s, (uint8_t *)&sd,
|
|
sizeof(struct adb_sync_send_data));
|
|
adb_service_write_remote(s, (uint8_t *)read_buf, r);
|
|
}
|
|
}
|
|
|
|
failed:
|
|
done:
|
|
ADB_FREE(full_path);
|
|
ADB_FREE(path);
|
|
ADB_FREE(read_buf);
|
|
}
|
|
|
|
static void do_list(struct adb_service *s, struct adb_sync_req *req)
|
|
{
|
|
uint8_t *path = ADB_MALLOC(req->len + 1);
|
|
struct lsfs_dir_t dir;
|
|
struct lsfs_dirent entry;
|
|
struct adb_sync_ctx *ctx = s->data;
|
|
|
|
if (path == NULL) {
|
|
ADB_LOGE("ADB_MALLOC error\n");
|
|
adb_sync_rsp_fail(s);
|
|
goto failed;
|
|
}
|
|
|
|
ADB_LOGI("sync list, req len: %d\n", req->len);
|
|
adb_sync_buffer_read(ctx, path, req->len);
|
|
path[req->len] = '\0';
|
|
|
|
ADB_LOGI("sync list, path: %s\n", path);
|
|
|
|
lsfs_dir_t_init(&dir);
|
|
|
|
struct adb_sync_dent_data dent = {0};
|
|
|
|
dent.id = ADB_SYNC_ID_DENT;
|
|
|
|
int r = lsfs_opendir(&dir, path);
|
|
if (r == 0) {
|
|
while (1) {
|
|
r = lsfs_readdir(&dir, &entry);
|
|
if (r != 0 || entry.name[0] == 0) {
|
|
break;
|
|
}
|
|
|
|
dent.namelen = strlen(entry.name);
|
|
dent.size = entry.size;
|
|
dent.mode = entry.type == 0 ? 33188 : 16877;
|
|
ADB_LOGI("list, name:%s, size:%d, type:%d\n", entry.name, entry.size,
|
|
entry.type);
|
|
adb_service_write_remote(s, (uint8_t *)&dent,
|
|
sizeof(struct adb_sync_dent_data));
|
|
adb_service_write_remote(s, (uint8_t *)entry.name, dent.namelen);
|
|
}
|
|
} else {
|
|
ADB_LOGE("lsfs opendir error: %d\n", r);
|
|
}
|
|
lsfs_closedir(&dir);
|
|
failed:
|
|
memset(&dent, 0, sizeof(struct adb_sync_dent_data));
|
|
dent.id = ADB_SYNC_ID_DONE;
|
|
adb_service_write_remote(s, (uint8_t *)&dent, sizeof(struct adb_sync_dent_data));
|
|
|
|
if (path) {
|
|
ADB_FREE(path);
|
|
}
|
|
}
|
|
|
|
static void adb_sync_task(void *arg)
|
|
{
|
|
struct adb_sync_ctx *ctx = arg;
|
|
struct adb_service *s = ctx->s;
|
|
|
|
assert(s);
|
|
assert(ctx);
|
|
|
|
uint8_t quit = 0;
|
|
while (!quit) {
|
|
struct adb_sync_req req;
|
|
adb_sync_buffer_read(ctx, (uint8_t *)&req, sizeof(struct adb_sync_req));
|
|
uint8_t *cmd = (uint8_t *)&req.id;
|
|
ADB_LOGI("adb sync, cmd: %c%c%c%c\n", cmd[0], cmd[1], cmd[2], cmd[3]);
|
|
switch (req.id) {
|
|
case ADB_SYNC_ID_LIST:
|
|
do_list(s, &req);
|
|
break;
|
|
case ADB_SYNC_ID_RECV:
|
|
do_recv(s, &req);
|
|
break;
|
|
case ADB_SYNC_ID_SEND:
|
|
do_send(s, &req);
|
|
break;
|
|
case ADB_SYNC_ID_STAT:
|
|
do_stat(s, &req);
|
|
break;
|
|
case ADB_SYNC_ID_QUIT:
|
|
quit = 1;
|
|
break;
|
|
default:
|
|
ADB_LOGE("adb sync, unknown req id:%x\n", req.id);
|
|
quit = 1;
|
|
break;
|
|
}
|
|
}
|
|
ADB_LOGI("adb sync, quit\n");
|
|
adb_close(s->local_id, s->remote_id);
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
static int adb_sync_open(struct adb_service *s, const uint8_t *args)
|
|
{
|
|
struct adb_sync_ctx *ctx = ADB_MALLOC(sizeof(struct adb_sync_ctx));
|
|
|
|
if (ctx == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
memset(ctx, 0, sizeof(struct adb_sync_ctx));
|
|
|
|
ADB_LOGI("adb sync open, local_id:%d, remote_id:%d\n", s->local_id, s->remote_id);
|
|
|
|
ctx->rx_queue = xQueueCreate(20, sizeof(adb_packet_t *));
|
|
|
|
if (ctx->rx_queue == NULL) {
|
|
ADB_FREE(ctx);
|
|
ADB_LOGE("sync queue create failed\n");
|
|
return -1;
|
|
}
|
|
|
|
ctx->s = s;
|
|
s->data = ctx;
|
|
|
|
BaseType_t xReturn = xTaskCreate(adb_sync_task, "sync_task", 1024 * 2, ctx, CONFIG_ADB_TASK_PRIORITY - 1, NULL);
|
|
if (xReturn != pdPASS) {
|
|
vQueueDelete(ctx->rx_queue);
|
|
ADB_FREE(ctx);
|
|
ADB_LOGE("sync task create failed\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int adb_write_file(const char *path, uint8_t *data, uint32_t len)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int adb_sync_write(struct adb_service *s, adb_packet_t *p)
|
|
{
|
|
struct adb_sync_ctx *ctx = s->data;
|
|
|
|
if (ctx && ctx->rx_queue) {
|
|
xQueueSend(ctx->rx_queue, &p, portMAX_DELAY);
|
|
} else {
|
|
ADB_LOGE("sync write failed\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int adb_sync_close(struct adb_service *s)
|
|
{
|
|
if (s == NULL || s->data == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
struct adb_sync_ctx *ctx = s->data;
|
|
if (ctx->curr_pkt) {
|
|
adb_packet_free(ctx->curr_pkt);
|
|
ctx->curr_pkt = NULL;
|
|
}
|
|
|
|
if (ctx->rx_queue) {
|
|
vQueueDelete(ctx->rx_queue);
|
|
ctx->rx_queue = NULL;
|
|
}
|
|
|
|
ADB_FREE(ctx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct adb_service_handle adb_sync_handle = {
|
|
.name = "sync",
|
|
.open = adb_sync_open,
|
|
.close = adb_sync_close,
|
|
.write = adb_sync_write,
|
|
};
|
|
|
|
int adb_sync_init(void)
|
|
{
|
|
return adb_service_hd_register(&adb_sync_handle);
|
|
}
|