chore: migrate project into clean repository

This commit is contained in:
yuuux
2026-08-13 16:50:52 +08:00
commit d1d25a09e7
27405 changed files with 9422808 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
if (DEFINED CONFIG_TUSB_APP_CLASS)
listenai_library_named(tinyusb-appclass)
listenai_library_sources(
tusb_appclass.c
)
listenai_add_subdirectory_ifdef(CONFIG_ADB adb)
listenai_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../modules/tinyusb/src/device)
endif()

View File

@@ -0,0 +1,12 @@
menu "tiny usb app class"
config TUSB_APP_CLASS
bool "tiny usb app class"
default n
depends on TINY_USB
if TUSB_APP_CLASS
rsource "adb/Kconfig"
endif
endmenu

View File

@@ -0,0 +1,22 @@
if (DEFINED CONFIG_ADB)
listenai_library_named(adb)
listenai_library_sources(
adb_device.c
adb.c
adb_services.c
)
listenai_library_sources_ifdef(
CONFIG_ADB_SHELL
adb_shell.c
)
listenai_library_sources_ifdef(
CONFIG_ADB_SYNC
adb_sync.c
adb_sync_ext_disk.c
)
listenai_include_directories(./)
endif()

View File

@@ -0,0 +1,38 @@
menu "adb"
config ADB
bool "adb"
default n
config ADB_MAX_PAYLOAD_SIZE
int "adb max payload size"
default 51200
range 1024 65536
config ADB_TASK_PRIORITY
int "adb task priority"
default 5
config ADB_SYNC
bool "adb sync"
default n
select ADB
select LSFS
config ADB_SHELL
bool "adb shell"
default n
select ADB
config ADB_SHELL_BUFFER_SIZE
int "adb shell buffer size"
default 4096
config ADB_PUSH_PULL_DEFAULT_ROOT
string "adb push/pull default root"
default "/RAM:/adb/"
depends on ADB_SYNC
endmenu

View File

@@ -0,0 +1,372 @@
#define LOG_TAG "adb.core"
#include "adb_device.h"
#include "adb.h"
#include "adb_services.h"
#include "adb_utils.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "queue.h"
#include <stdlib.h>
static SemaphoreHandle_t adb_msg_send_lock = NULL;
static SemaphoreHandle_t adb_recv_sem = NULL;
static QueueHandle_t adb_rx_queue = NULL;
static QueueHandle_t adb_tx_queue = NULL;
struct adb_recv_msg {
uint8_t *data;
uint32_t len;
};
static uint32_t adb_check_calc(const uint8_t *data, int len)
{
uint8_t *x = (uint8_t *)data;
uint32_t sum = 0;
while (len-- > 0) {
sum += *x++;
}
return sum;
}
static void adb_tx_queue_write(uint8_t *data, uint32_t len)
{
// struct adb_split sp = {0};
// sp.len = len;
// sp.spilt = ADB_MALLOC(sp.len);
// if (sp.spilt == NULL) {
// ADB_LOGE("ADB_MALLOC error\n");
// return;
// }
// memcpy(sp.spilt, data, len);
// xQueueSend(adb_tx_queue, &sp, portMAX_DELAY);
adb_dev_send(data, len);
}
static void adb_tx_msg(uint8_t *msg, uint32_t len)
{
#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
uint32_t n;
n = len / BULK_PACKET_SIZE;
while (n--) {
adb_tx_queue_write(msg, BULK_PACKET_SIZE);
msg += BULK_PACKET_SIZE;
}
n = len % BULK_PACKET_SIZE;
if (n) {
adb_tx_queue_write(msg, n);
}
}
static int adb_msg_send(struct message *msg, const uint8_t *payload, uint32_t payload_size)
{
msg->magic = (msg->command ^ 0xffffffff);
msg->data_length = payload_size;
if (msg->data_length) {
msg->data_check = adb_check_calc(payload, msg->data_length);
} else {
msg->data_check = 0;
}
uint8_t *cmd = (uint8_t *)&msg->command;
ADB_LOGD("adb msg send, cmd: %c%c%c%c, payload len:%d\n", cmd[0], cmd[1], cmd[2], cmd[3], msg->data_length);
xSemaphoreTake(adb_msg_send_lock, portMAX_DELAY);
adb_tx_msg((uint8_t *)msg, sizeof(struct message));
if (payload_size && payload) {
adb_tx_msg((uint8_t *)payload, payload_size);
}
xSemaphoreGive(adb_msg_send_lock);
ADB_LOGD("adb msg send done\n");
return 0;
}
static void adb_connect(void)
{
const uint8_t conn_payload[] = "device::"
"ro.product.name=mido;"
"ro.product.model=listenai;"
"ro.product.device=mido;"
"features=cmd,shell_v1";
struct message *msg = ADB_MALLOC(sizeof(struct message));
if (msg == NULL) {
ADB_LOGE("ADB_MALLOC error\n");
return;
}
memset(msg, 0, sizeof(struct message));
msg->command = A_CNXN;
msg->arg0 = A_VERSION;
msg->arg1 = MAX_PAYLOAD;
adb_msg_send(msg, conn_payload, sizeof(conn_payload));
ADB_FREE(msg);
}
static void adb_ready(uint32_t local_id, uint32_t remote_id)
{
struct message *msg = ADB_MALLOC(sizeof(struct message));
if (msg == NULL) {
ADB_LOGE("adb_ready, ADB_MALLOC error\n");
return;
}
msg->command = A_OKAY;
msg->arg0 = local_id;
msg->arg1 = remote_id;
msg->data_length = 0;
adb_msg_send(msg, NULL, 0);
ADB_FREE(msg);
}
void adb_close(uint32_t local_id, uint32_t remote_id)
{
struct message *msg = ADB_MALLOC(sizeof(struct message));
if (msg == NULL) {
ADB_LOGE("adb_close, ADB_MALLOC error\n");
return;
}
msg->command = A_CLSE;
msg->arg0 = local_id;
msg->arg1 = remote_id;
msg->data_length = 0;
adb_msg_send(msg, NULL, 0);
ADB_FREE(msg);
}
void adb_write(uint32_t local_id, uint32_t remote_id, uint8_t *data, uint32_t len)
{
struct message *msg = ADB_MALLOC(sizeof(struct message));
if (msg == NULL) {
ADB_LOGE("adb_write, ADB_MALLOC error\n");
return;
}
msg->command = A_WRTE;
msg->arg0 = local_id;
msg->arg1 = remote_id;
msg->data_length = len;
adb_msg_send(msg, data, len);
ADB_FREE(msg);
}
void adb_packet_free(adb_packet_t *p)
{
ADB_FREE(p);
}
static void adb_packet_received_cb(adb_packet_t *p)
{
if (p == NULL) {
return;
}
uint8_t *cmd = (uint8_t *)&p->msg.command;
ADB_LOGD("adb packet recv, cmd: %c%c%c%c, payload len:%d\n", cmd[0], cmd[1], cmd[2], cmd[3],
p->msg.data_length);
switch (p->msg.command) {
case A_CNXN: {
ADB_LOGI("adb connecting, remote info, version:%x, max payload:%d\n", p->msg.arg0,
p->msg.arg1);
adb_connect();
adb_packet_free(p);
} break;
case A_OPEN: {
uint32_t remote_id = p->msg.arg0;
uint8_t *name = p->data;
ADB_LOGI("adb open, remote_id:%d, name:%s\n", remote_id, name);
if (remote_id != 0) {
uint8_t *pos = strstr(name, ":");
if (pos == NULL) {
ADB_LOGE("invalid name:%s\n", name);
adb_close(0, remote_id);
adb_packet_free(p);
return;
}
*pos = '\0';
uint32_t local_id = adb_service_open(name, pos + 1, remote_id);
ADB_LOGI("adb open, local_id:%d\n", local_id);
if (local_id != 0) {
adb_ready(local_id, remote_id);
} else {
adb_close(0, remote_id);
}
}
adb_packet_free(p);
} break;
case A_OKAY:
adb_packet_free(p);
break;
case A_CLSE: {
uint32_t local_id = p->msg.arg1;
uint32_t remote_id = p->msg.arg0;
ADB_LOGI("adb close, local_id:%d, remote_id:%d\n", local_id, remote_id);
adb_service_close(local_id, remote_id);
adb_packet_free(p);
} break;
case A_WRTE: {
uint32_t local_id = p->msg.arg1;
uint32_t remote_id = p->msg.arg0;
if (local_id == 0 || remote_id == 0) {
adb_packet_free(p);
return;
}
if (adb_service_write(local_id, remote_id, p) != 0) {
adb_packet_free(p);
adb_close(local_id, remote_id);
} else {
/* adb packet will be freed in each adb service */
adb_ready(local_id, remote_id);
}
} break;
default:
adb_packet_free(p);
break;
}
}
static bool adb_msg_validate(struct message *m)
{
if (m == NULL) {
return false;
}
if (m->magic != (m->command ^ 0xffffffff)) {
ADB_LOGE("adb msg magic check failed, cmd:%x\n, calc magic:%x", m->command, (m->command ^ 0xffffffff));
return false;
}
if (m->data_length > MAX_PAYLOAD) {
ADB_LOGE("adb packet data length check failed, len: %d\n", m->data_length);
return false;
}
return true;
}
static bool adb_packet_validate(adb_packet_t *p)
{
if (p->msg.data_check != adb_check_calc(p->data, p->msg.data_length)) {
ADB_LOGE("adb packet check sum failed, cmd:%x\n,", p->msg.command);
return false;
}
return true;
}
static void adb_tx_task(void *arg)
{
struct adb_split sp = {0};
while (1) {
xQueueReceive(adb_tx_queue, &sp, portMAX_DELAY);
adb_dev_send(sp.spilt, sp.len);
}
}
static void adb_rx_task(void *arg)
{
struct adb_recv_msg msg;
uint32_t payload_recv_len = 0;
adb_packet_t *packet;
while (1) {
xQueueReceive(adb_rx_queue, &msg, portMAX_DELAY);
struct message *m = (struct message *)msg.data;
if (__builtin_expect(!adb_msg_validate(m), 0)) {
ADB_LOGE("adb msg validate failed\n");
ADB_FREE(msg.data);
continue;
}
packet = ADB_MALLOC(sizeof(adb_packet_t) + m->data_length);
if (packet == NULL) {
ADB_LOGE("malloc error\n");
ADB_FREE(msg.data);
continue;
}
memcpy(packet, m, sizeof(struct message));
ADB_FREE(msg.data);
payload_recv_len = 0;
if (__builtin_expect(packet->msg.data_length > 0, 1)) {
while (payload_recv_len < packet->msg.data_length) {
xQueueReceive(adb_rx_queue, &msg, portMAX_DELAY);
memcpy(packet->data + payload_recv_len, msg.data, msg.len);
payload_recv_len += msg.len;
ADB_FREE(msg.data);
}
}
if (__builtin_expect(adb_packet_validate(packet), 0)) {
adb_packet_received_cb(packet);
}
}
}
static void adb_recv_handle(uint8_t *buf, uint32_t len)
{
struct adb_recv_msg msg;
msg.data = ADB_MALLOC(len);
if (msg.data == NULL) {
ADB_LOGE("adb_recv_handle, malloc error\n");
return;
}
msg.len = len;
memcpy(msg.data, buf, len);
if (xQueueSend(adb_rx_queue, &msg, portMAX_DELAY) != pdPASS) {
ADB_LOGE("adb_recv_handle, queue send error\n");
ADB_FREE(msg.data);
}
}
void adb_init(void)
{
adb_dev_recv_cb_set(adb_recv_handle);
adb_rx_queue = xQueueCreate(50, sizeof(struct adb_recv_msg));
if (adb_rx_queue == NULL) {
ADB_LOGE("adb recv queue create failed\n");
return;
}
adb_tx_queue = xQueueCreate(10, sizeof(struct adb_split));
if (adb_tx_queue == NULL) {
ADB_LOGE("adb tx queue create failed\n");
return;
}
adb_msg_send_lock = xSemaphoreCreateMutex();
if (adb_msg_send_lock == NULL) {
ADB_LOGE("adb mutex create failed\n");
return;
}
if (xTaskCreate(adb_rx_task, "adb_rx", 1024 * 2, NULL, CONFIG_ADB_TASK_PRIORITY, NULL) != pdPASS) {
ADB_LOGE("adb task create failed\n");
return;
}
if (xTaskCreate(adb_tx_task, "adb_tx", 1024 * 2, NULL, CONFIG_ADB_TASK_PRIORITY, NULL) != pdPASS) {
ADB_LOGE("adb task create failed\n");
return;
}
}

View File

@@ -0,0 +1,44 @@
#ifndef __ADB_H__
#define __ADB_H__
#define A_SYNC 0x434e5953
#define A_CNXN 0x4e584e43
#define A_OPEN 0x4e45504f
#define A_OKAY 0x59414b4f
#define A_CLSE 0x45534c43
#define A_WRTE 0x45545257
#define A_VERSION 0x01000000
#ifdef CONFIG_ADB_MAX_PAYLOAD_SIZE
#define MAX_PAYLOAD CONFIG_ADB_MAX_PAYLOAD_SIZE
#else
#define MAX_PAYLOAD 4096
#endif
#include <stdint.h>
struct message {
uint32_t command; /* command identifier constant */
uint32_t arg0; /* first argument */
uint32_t arg1; /* second argument */
uint32_t data_length; /* length of payload (0 is allowed) */
uint32_t data_check; /* checksum of data payload */
uint32_t magic; /* command ^ 0xffffffff */
};
struct adb_split {
uint8_t *spilt;
uint32_t len;
};
typedef struct {
struct message msg;
uint8_t data[0];
} adb_packet_t;
void adb_init(void);
void adb_close(uint32_t local_id, uint32_t remote_id);
void adb_write(uint32_t local_id, uint32_t remote_id, uint8_t *data, uint32_t len);
void adb_packet_free(adb_packet_t *p);
#endif

View File

@@ -0,0 +1,158 @@
#define LOG_TAG "adb.dev"
#include "adb_utils.h"
#include "adb_device.h"
#include "tusb.h"
#include "usbd_pvt.h"
#include <string.h>
#include <stdlib.h>
#define BULK_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
static adb_interface_t adb_itf = {0};
bool adb_dev_send(uint8_t *buf, uint32_t len)
{
xSemaphoreTake(adb_itf.tx_ready_sem, portMAX_DELAY);
if (!usbd_edpt_claim(0, adb_itf.ep_in)) {
return false;
}
return usbd_edpt_xfer(0, adb_itf.ep_in, buf, len);
}
void adb_dev_init(void)
{
memset(&adb_itf, 0, sizeof(adb_interface_t));
adb_itf.tx_ready_sem = xSemaphoreCreateBinary();
if (adb_itf.tx_ready_sem == NULL) {
ADB_LOGE("Failed to create ADB tx semaphore\n");
return;
}
/* give initial value */
xSemaphoreGive(adb_itf.tx_ready_sem);
}
bool adb_dev_deinit(void)
{
memset(&adb_itf, 0, sizeof(adb_interface_t));
return true;
}
void adb_dev_reset(uint8_t rhport)
{
/* give initial value */
xSemaphoreGive(adb_itf.tx_ready_sem);
}
uint16_t adb_dev_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
{
ADB_LOGI("Opening ADB interface, number: %d, endpoints: %d\n", itf_desc->bInterfaceNumber, itf_desc->bNumEndpoints);
TU_VERIFY(itf_desc->bInterfaceClass == TUSB_CLASS_VENDOR_SPECIFIC, 0);
adb_itf.itf_num = itf_desc->bInterfaceNumber;
uint8_t const *p_desc = tu_desc_next(itf_desc);
uint8_t const *desc_end = p_desc + max_len;
uint8_t found_ep = 0;
while (found_ep < itf_desc->bNumEndpoints) {
while ((TUSB_DESC_ENDPOINT != tu_desc_type(p_desc)) && (p_desc < desc_end)) {
p_desc = tu_desc_next(p_desc);
}
TU_VERIFY(p_desc < desc_end, 0);
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc;
TU_ASSERT(usbd_edpt_open(rhport, desc_ep));
found_ep++;
if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
adb_itf.ep_in = desc_ep->bEndpointAddress;
} else {
adb_itf.ep_out = desc_ep->bEndpointAddress;
}
p_desc = tu_desc_next(p_desc);
}
ADB_LOGI("Configured ADB interface: IN EP 0x%02x, OUT EP 0x%02x\n", adb_itf.ep_in, adb_itf.ep_out);
if (!usbd_edpt_xfer(rhport, adb_itf.ep_out, adb_itf.epout_buf, ADB_EP_BUFSIZE)) {
ADB_LOGE("Failed to xfer OUT EP 0x%02x\n", adb_itf.ep_out);
}
return (uint16_t)((uintptr_t)p_desc - (uintptr_t)itf_desc);
}
bool adb_dev_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request)
{
ADB_LOGI("adb_control_xfer_cb, stage: %d\n", stage);
adb_interface_t *adb = &adb_itf;
if ((request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD) &&
(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_ENDPOINT) &&
(request->bRequest == TUSB_REQ_CLEAR_FEATURE) && (request->wValue == TUSB_REQ_FEATURE_EDPT_HALT)) {
uint32_t ep_addr = (request->wIndex);
if (ep_addr == adb->ep_out) {
if (usbd_edpt_stalled(rhport, (uint8_t)ep_addr)) {
usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr);
}
} else if (ep_addr == adb->ep_in) {
if (usbd_edpt_stalled(rhport, (uint8_t)ep_addr)) {
usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr);
}
} else {
return false;
}
return true;
}
ADB_LOGE("Unhandled control transfer: type=0x%02x, request=0x%02x\n", request->bmRequestType, request->bRequest);
return false;
}
static void (*adb_dev_recv_cb)(uint8_t*, uint32_t) = NULL;
void adb_dev_recv_cb_set(void (*cb)(uint8_t*, uint32_t))
{
adb_dev_recv_cb = cb;
}
bool adb_dev_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
{
adb_interface_t *adb = &adb_itf;
int r;
if (ep_addr != adb->ep_in && ep_addr != adb->ep_out) {
return true;
}
if (result != XFER_RESULT_SUCCESS) {
ADB_LOGE("Transfer error on EP 0x%02x\n", ep_addr);
return true;
}
if (ep_addr == adb->ep_in) {
ADB_LOGD("TX completed: %d bytes\n", xferred_bytes);
xSemaphoreGive(adb->tx_ready_sem);
}
if (ep_addr == adb->ep_out) {
ADB_LOGD("RX completed: %d bytes\n", xferred_bytes);
if (adb_dev_recv_cb) {
adb_dev_recv_cb(adb->epout_buf, (uint16_t)xferred_bytes);
}
bool ret = usbd_edpt_xfer(rhport, adb->ep_out, adb->epout_buf, ADB_EP_BUFSIZE);
assert(ret);
}
return true;
}

View File

@@ -0,0 +1,36 @@
#ifndef __ADB_DEVICE_H__
#define __ADB_DEVICE_H__
#include "tusb.h"
#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
#define ADB_BUFFER_SIZE (1024 * 5)
#define ADB_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
typedef struct {
uint8_t itf_num;
uint8_t ep_in;
uint8_t ep_out;
CFG_TUSB_MEM_ALIGN uint8_t epout_buf[ADB_EP_BUFSIZE];
CFG_TUSB_MEM_ALIGN uint8_t epin_buf[ADB_EP_BUFSIZE];
SemaphoreHandle_t tx_ready_sem;
} adb_interface_t;
void adb_dev_init(void);
bool adb_dev_deinit(void);
void adb_dev_reset(uint8_t rhport);
uint16_t adb_dev_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
bool adb_dev_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request);
bool adb_dev_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
uint32_t adb_dev_write(void const *buffer, uint32_t bufsize);
void adb_dev_recv_cb_set(void (*cb)(uint8_t*, uint32_t));
bool adb_dev_send(uint8_t *buf, uint32_t len);
#endif

View File

@@ -0,0 +1,167 @@
#define LOG_TAG "adb.srv"
#include "adb_services.h"
#include "adb_shell.h"
#include "adb.h"
#include "adb_utils.h"
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
static struct adb_service adb_services[ADB_SERVICE_MAX_NUM] = {0};
static struct adb_service_handle const* adb_services_handle[ADB_SERVICE_HANDLE_MAX_NUM] = {0};
#define ADB_SERVICE_LOCAL_ID_DEFAULT 100
static uint32_t local_id_get(void)
{
static uint32_t local_id = ADB_SERVICE_LOCAL_ID_DEFAULT;
if (local_id == 0) {
local_id = ADB_SERVICE_LOCAL_ID_DEFAULT;
}
return local_id++;
}
static const struct adb_service_handle *adb_service_handle_find(const uint8_t *name)
{
int i;
for (i = 0; i < ADB_SERVICE_HANDLE_MAX_NUM; i++) {
if (adb_services_handle[i] == NULL) {
continue;
}
if (strcmp((char *)name, (char *)adb_services_handle[i]->name) == 0) {
return adb_services_handle[i];
}
}
return NULL;
}
static struct adb_service *adb_service_find(uint32_t local_id, uint32_t remote_id)
{
int i;
for (i = 0; i < sizeof(adb_services) / sizeof(adb_services[0]); i++) {
if (adb_services[i].used == 0) {
continue;
}
if (adb_services[i].local_id == local_id && adb_services[i].remote_id == remote_id) {
return &adb_services[i];
}
}
return NULL;
}
uint32_t adb_service_open(const uint8_t *name, const uint8_t *args, uint32_t remote_id)
{
uint32_t i;
const struct adb_service_handle *service_hd = adb_service_handle_find(name);
if (service_hd == NULL || service_hd->open == NULL) {
ADB_LOGE("service handle not found, name: %s\n", name);
return 0;
}
for (i = 0; i < sizeof(adb_services) / sizeof(adb_services[0]); i++) {
if (adb_services[i].used) {
continue;
}
adb_services[i].used = 1;
adb_services[i].local_id = local_id_get();
adb_services[i].remote_id = remote_id;
adb_services[i].hd = service_hd;
if (service_hd->open(&adb_services[i], args) != 0) {
ADB_LOGE("service handle open failed, name: %s\n", service_hd->name);
return 0;
}
ADB_LOGI("service open success, idx: %d, local_id: %d, remote_id: %d, handle: %s\n",
i, adb_services[i].local_id, remote_id, service_hd->name);
return adb_services[i].local_id;
}
ADB_LOGE("no available service slot\n");
return 0;
}
int adb_service_write(uint32_t local_id, uint32_t remote_id, adb_packet_t *p)
{
struct adb_service *s = adb_service_find(local_id, remote_id);
if (s == NULL) {
ADB_LOGE("service not found, local_id: %d, remote_id: %d\n", local_id, remote_id);
return -1;
}
if (s->hd == NULL || s->hd->write == NULL) {
ADB_LOGE("service handle invalid, %p, %p\n", s->hd, s->hd->write);
return -1;
}
if (s->hd->write(s, p) != 0) {
ADB_LOGE("service write failed, local_id: %d, remote_id: %d\n", local_id, remote_id);
adb_service_close(local_id, remote_id);
return -1;
}
return 0;
}
void adb_service_write_remote(struct adb_service *s, uint8_t *data, int len)
{
if (s && data && len > 0) {
adb_write(s->local_id, s->remote_id, data, len);
}
}
void adb_service_close(uint32_t local_id, uint32_t remote_id)
{
struct adb_service *s = adb_service_find(local_id, remote_id);
ADB_LOGI("adb service close, local_id: %d, remote_id: %d, %p\n", local_id, remote_id, s);
if (s) {
if (s->hd != NULL && s->hd->close != NULL) {
s->hd->close(s);
}
adb_close(local_id, remote_id);
ADB_LOGI("adb service close, %p, %p\n", s->hd, s->hd->write);
s->used = 0;
s->hd = NULL;
s->local_id = 0;
s->remote_id = 0;
s->data = NULL;
}
}
int adb_service_hd_register(const struct adb_service_handle *handle)
{
int i;
for (i = 0; i < ADB_SERVICE_HANDLE_MAX_NUM; i++) {
if (adb_services_handle[i] == NULL) {
ADB_LOGI("service handle register success, name: %s\n", handle->name);
adb_services_handle[i] = handle;
return 0;
}
}
ADB_LOGE("service handle register failed, name: %s\n", handle->name);
return -1;
}

View File

@@ -0,0 +1,32 @@
#ifndef __ADB_SERVICE_H__
#define __ADB_SERVICE_H__
#include <stdint.h>
#include "adb.h"
#define ADB_SERVICE_MAX_NUM 10
#define ADB_SERVICE_HANDLE_MAX_NUM 3
struct adb_service_handle;
struct adb_service {
uint8_t used;
uint32_t local_id;
uint32_t remote_id;
const struct adb_service_handle *hd;
void *data;
};
struct adb_service_handle {
uint8_t *name;
int (*open)(struct adb_service *, const uint8_t *);
int (*close)(struct adb_service *);
int (*write)(struct adb_service *, adb_packet_t *);
};
uint32_t adb_service_open(const uint8_t *name, const uint8_t *args, uint32_t remote_id);
int adb_service_write(uint32_t local_id, uint32_t remote_id, adb_packet_t *);
void adb_service_close(uint32_t local_id, uint32_t remote_id);
void adb_service_write_remote(struct adb_service *s, uint8_t *data, int len);
int adb_service_hd_register(const struct adb_service_handle const *handle);
#endif

View File

@@ -0,0 +1,261 @@
#include "adb_services.h"
#include "adb.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "shell.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "stream_buffer.h"
#include <stdio.h>
#include <string.h>
#define LOG_TAG "adb.sh"
#include "adb_utils.h"
#include "lisa_log.h"
#define ETX 0x03 /* ctrl+c */
static struct adb_service *curr_service = NULL;
struct adb_shell_context {
Shell sh;
uint8_t buf[CONFIG_ADB_SHELL_BUFFER_SIZE] __attribute__((aligned(8)));
StreamBufferHandle_t rx_stream;
StreamBufferHandle_t tx_stream;
struct adb_service *s;
TaskHandle_t task;
};
static void adb_shell_log_output(const uint8_t *log, uint32_t len, void *data)
{
if (curr_service == NULL || curr_service->data == NULL) {
return;
}
struct adb_shell_context *ctx = curr_service->data;
shellWriteEndLine(&ctx->sh, (char *)log, len);
}
static signed short shell_write(char *data, unsigned short size)
{
if (curr_service == NULL || data == NULL || size == 0) {
return 0;
}
struct adb_shell_context *ctx = curr_service->data;
xStreamBufferSend(ctx->tx_stream, data, size, 0);
return size;
}
static void shell_task(void *arg)
{
struct adb_shell_context *ctx = arg;
vTaskDelay(50 / portTICK_PERIOD_MS);
ADB_LOGI("adb shell task start, arg:%p\n", arg);
ctx->sh.read = NULL;
ctx->sh.write = shell_write;
shellInit(&ctx->sh, ctx->buf, CONFIG_ADB_SHELL_BUFFER_SIZE);
ADB_LOGD("shell init done\n");
lisa_log_backend_add("adb_shell", adb_shell_log_output, NULL);
uint8_t ch;
while (1) {
if (xStreamBufferReceive(ctx->rx_stream, &ch, 1, 50) == 1) {
if (ch == ETX) {
adb_close(ctx->s->local_id, ctx->s->remote_id);
} else {
shellHandler(&ctx->sh, ch);
}
}
size_t len = xStreamBufferBytesAvailable(ctx->tx_stream);
if (len > 0) {
uint8_t *data = ADB_MALLOC(len);
if (data != NULL) {
size_t received = xStreamBufferReceive(ctx->tx_stream, data, len, 0);
if (received > 0) {
adb_service_write_remote(ctx->s, data, received);
}
ADB_FREE(data);
}
}
}
}
static int adb_shell_close(struct adb_service *s)
{
ADB_LOGI("adb shell close, %p\n", s);
if (s != NULL && s->data != NULL) {
struct adb_shell_context *ctx = s->data;
lisa_log_backend_remove("adb_shell");
vTaskSuspend(ctx->task);
vTaskDelete(ctx->task);
vStreamBufferDelete(ctx->rx_stream);
vStreamBufferDelete(ctx->tx_stream);
shellRemove(&ctx->sh);
ADB_FREE(ctx);
curr_service = NULL;
s->data = NULL;
}
return 0;
}
static int adb_shell_open(struct adb_service *s, const uint8_t *args)
{
if (s == NULL) {
return -1;
}
if (curr_service != NULL) {
ADB_LOGE("adb shell already open, close and reopen\n");
adb_shell_close(curr_service);
}
struct adb_shell_context *ctx = ADB_MALLOC(sizeof(struct adb_shell_context));
if (ctx == NULL) {
return -1;
}
memset(ctx, 0, sizeof(struct adb_shell_context));
ADB_LOGI("adb shell open, local_id:%d, remote_id:%d\n", s->local_id, s->remote_id);
ctx->s = s;
s->data = ctx;
curr_service = s;
ctx->rx_stream = xStreamBufferCreate(CONFIG_ADB_SHELL_BUFFER_SIZE, 1);
if (ctx->rx_stream == NULL) {
ADB_FREE(ctx);
ADB_LOGE("shell rx stream create failed\n");
curr_service = NULL;
return -1;
}
ctx->tx_stream = xStreamBufferCreate(CONFIG_ADB_SHELL_BUFFER_SIZE, 1);
if (ctx->tx_stream == NULL) {
vStreamBufferDelete(ctx->rx_stream);
ADB_FREE(ctx);
ADB_LOGE("shell tx stream create failed\n");
curr_service = NULL;
return -1;
}
BaseType_t xReturn = xTaskCreate(shell_task, "shell_task", 1024 * 1, ctx, CONFIG_ADB_TASK_PRIORITY - 1, &ctx->task);
if (xReturn != pdPASS) {
vStreamBufferDelete(ctx->rx_stream);
vStreamBufferDelete(ctx->tx_stream);
ADB_FREE(ctx);
ADB_LOGE("shell task create failed\n");
curr_service = NULL;
return -1;
}
if (args) {
int len = strlen((char *)args);
ADB_LOGI("shell args: %s, len: %d\n", args, len);
if (len) {
char *token;
char *saveptr;
char *cmd = ADB_MALLOC(len + 1);
if (cmd == NULL) {
vTaskDelete(ctx->task);
vStreamBufferDelete(ctx->rx_stream);
vStreamBufferDelete(ctx->tx_stream);
ADB_FREE(ctx);
curr_service = NULL;
ADB_LOGE("shell cmd alloc failed\n");
return -1;
}
memcpy(cmd, args, len);
cmd[len] = '\0';
token = strtok_r(cmd, ";", &saveptr);
uint8_t c;
while (token != NULL) {
ADB_LOGI("shell cmd: %s\n", token);
size_t token_len = strlen(token);
xStreamBufferSend(ctx->rx_stream, token, token_len, portMAX_DELAY);
c = '\r';
xStreamBufferSend(ctx->rx_stream, &c, 1, portMAX_DELAY);
token = strtok_r(NULL, ";", &saveptr);
}
ADB_FREE(cmd);
c = ETX;
xStreamBufferSend(ctx->rx_stream, &c, 1, portMAX_DELAY);
}
}
return 0;
}
static void adb_shell_write_remote(struct adb_service *s, uint8_t *data, int len)
{
adb_service_write_remote(s, data, len);
}
static int adb_shell_write_datas(const char *data, int size)
{
if (curr_service == NULL || data == NULL || size == 0) {
return 0;
}
struct adb_shell_context *ctx = curr_service->data;
for (int i = 0; i < size; i++) {
if (data[i] == '\n') {
uint8_t c = '\r';
xStreamBufferSend(ctx->tx_stream, &c, 1, 0);
}
xStreamBufferSend(ctx->tx_stream, &data[i], 1, 0);
}
return size;
}
static int adb_shell_write(struct adb_service *s, adb_packet_t *p)
{
struct adb_shell_context *ctx = s->data;
uint32_t len = p->msg.data_length;
uint8_t *data = p->data;
for (uint32_t i = 0; i < len; i++) {
if (data[i] == ETX) {
adb_service_close(s->local_id, s->remote_id);
break;
}
xStreamBufferSend(ctx->rx_stream, &data[i], 1, portMAX_DELAY);
}
adb_packet_free(p);
return 0;
}
static const struct adb_service_handle adb_shell_handle = {
.name = "shell",
.open = adb_shell_open,
.close = adb_shell_close,
.write = adb_shell_write,
};
void adb_shell_init(void)
{
adb_service_hd_register(&adb_shell_handle);
}

View File

@@ -0,0 +1,10 @@
#ifndef __ADB_SHELL_H__
#define __ADB_SHELL_H__
#include <stdint.h>
void adb_shell_init(void);
int adb_shell_write_datas(const char *data, int size);
int adb_printf(const char *format, ...);
#endif

View File

@@ -0,0 +1,814 @@
#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);
}

View File

@@ -0,0 +1,6 @@
#ifndef __ADB_SYNC_H__
#define __ADB_SYNC_H__
int adb_sync_init(void);
#endif

View File

@@ -0,0 +1,192 @@
#include "disk/disk_access.h"
#include "adb_utils.h"
#include "adb_sync_ext_disk.h"
#include "stdint.h"
#include "string.h"
#include "stdlib.h"
struct adb_sync_ext_disk_ctx *adb_sync_ext_disk_ctx_init(const char *name, uint32_t start_addr)
{
int r;
if (name == NULL) {
return NULL;
}
struct adb_sync_ext_disk_ctx *ctx = ADB_MALLOC(sizeof(struct adb_sync_ext_disk_ctx));
if (ctx == NULL) {
ADB_LOGE("adb sync ext disk context malloc error");
return NULL;
}
ctx->name = name;
r = disk_access_ioctl(ctx->name, DISK_IOCTL_GET_SECTOR_SIZE, &ctx->sec_size);
if (r) {
ADB_LOGE("get disk sector size error, disk name:%s\n", ctx->name);
ADB_FREE(ctx);
return NULL;
}
if (start_addr % ctx->sec_size != 0) {
ADB_LOGE("start_addr is not align with sec_size, start_addr:0x%x, sec_size:%d\n", start_addr, ctx->sec_size);
ADB_FREE(ctx);
return NULL;
}
ctx->buf = ADB_MALLOC(ctx->sec_size);
if (ctx->buf == NULL) {
ADB_LOGE("adb sync ext disk buffer malloc error");
ADB_FREE(ctx);
return NULL;
}
ctx->buf_idx = 0;
ctx->curr_sec = start_addr / ctx->sec_size;
ADB_LOGI("adb sync ext disk init, name:%s, sec_size:%d, start_sec:%d\n", name, ctx->sec_size, ctx->curr_sec);
return ctx;
}
static int adb_sync_ext_disk_flush(struct adb_sync_ext_disk_ctx *ctx)
{
int r;
if (ctx->buf_idx == 0) {
return 0;
}
r = disk_access_write(ctx->name, ctx->buf, ctx->curr_sec, 1);
if (r) {
return r;
}
if (ctx->buf_idx == ctx->sec_size) {
ctx->curr_sec += 1;
}
ctx->buf_idx = 0;
return 0;
}
void adb_sync_ext_disk_ctx_free(struct adb_sync_ext_disk_ctx *ctx)
{
if (ctx) {
adb_sync_ext_disk_flush(ctx);
ADB_FREE(ctx->buf);
ADB_FREE(ctx);
}
}
static int adb_sync_ext_disk_write_align_start_sector(struct adb_sync_ext_disk_ctx *ctx, const uint8_t *data, uint32_t len)
{
int r;
int n;
n = len / ctx->sec_size;
if (n) {
r = disk_access_write(ctx->name, data, ctx->curr_sec, n);
if (r) {
return r;
}
ctx->curr_sec += n;
data += n * ctx->sec_size;
}
n = len % ctx->sec_size;
if (n) {
memcpy(ctx->buf, data, n);
ctx->buf_idx = n;
}
return 0;
}
int adb_sync_ext_disk_write(struct adb_sync_ext_disk_ctx *ctx, const uint8_t *data, uint32_t len)
{
int r;
int n;
if (ctx == NULL || data == NULL || len == 0) {
return -1;
}
if (ctx->buf_idx == 0) {
adb_sync_ext_disk_write_align_start_sector(ctx, data, len);
} else {
if (ctx->buf_idx == ctx->sec_size) {
adb_sync_ext_disk_flush(ctx);
}
int cpy_len = len <= ctx->sec_size - ctx->buf_idx ? len : ctx->sec_size - ctx->buf_idx;
memcpy(ctx->buf + ctx->buf_idx, data, cpy_len);
ctx->buf_idx += cpy_len;
if (ctx->buf_idx == ctx->sec_size) {
adb_sync_ext_disk_flush(ctx);
}
adb_sync_ext_disk_write_align_start_sector(ctx, data + cpy_len, len - cpy_len);
}
return 0;
}
int adb_sync_ext_disk_read(struct adb_sync_ext_disk_ctx *ctx, uint8_t *data, uint32_t len)
{
int r;
int cnt;
if (ctx == NULL || data == NULL || len == 0) {
return -1;
}
cnt = (len / ctx->sec_size) + ((len % ctx->sec_size) ? 1 : 0);
r = disk_access_read(ctx->name, data, ctx->curr_sec, cnt);
if (r) {
return r;
}
ctx->curr_sec += cnt;
return len;
}
bool adb_sync_is_ext_disk_access(const char *path)
{
return strncmp(path, ADB_SYNC_EXT_MOUNT_POINT, strlen(ADB_SYNC_EXT_MOUNT_POINT)) == 0;
}
int adb_sync_ext_disk_get_info_by_path(char *path, char **name, uint32_t *addr, uint32_t *size)
{
/* /RAW/name/addr/size */
char *p = strstr(path, ADB_SYNC_EXT_MOUNT_POINT);
char *token;
char *saveptr;
if (p != path) {
return -1;
}
p += strlen(ADB_SYNC_EXT_MOUNT_POINT);
*size = 0;
*addr = 0;
token = strtok_r(p, "/", &saveptr);
if (token == NULL) {
return -1;
}
*name = token;
token = strtok_r(NULL, "/", &saveptr);
if (token == NULL) {
return -1;
}
*addr = strtol(token, NULL, 16);
token = strtok_r(NULL, "/", &saveptr);
if (token == NULL) {
return -1;
}
*size = strtol(token, NULL, 16);
return 0;
}

View File

@@ -0,0 +1,24 @@
#ifndef __ADB_SYNC_EXT_DISK_H__
#define __ADB_SYNC_EXT_DISK_H__
#include "stdint.h"
#ifndef ADB_SYNC_EXT_MOUNT_POINT
#define ADB_SYNC_EXT_MOUNT_POINT "/RAW/"
#endif
struct adb_sync_ext_disk_ctx {
const char *name;
uint32_t curr_sec;
uint32_t sec_size;
uint32_t buf_idx;
uint8_t *buf;
};
struct adb_sync_ext_disk_ctx *adb_sync_ext_disk_ctx_init(const char *name, uint32_t start_addr);
void adb_sync_ext_disk_ctx_free(struct adb_sync_ext_disk_ctx *ctx);
int adb_sync_ext_disk_write(struct adb_sync_ext_disk_ctx *ctx, const uint8_t *data, uint32_t len);
bool adb_sync_is_ext_disk_access(const char *path);
int adb_sync_ext_disk_get_info_by_path(char *path, char **name, uint32_t *addr, uint32_t *size);
int adb_sync_ext_disk_read(struct adb_sync_ext_disk_ctx *ctx, uint8_t *data, uint32_t len);
#endif

View File

@@ -0,0 +1,41 @@
#ifndef __ADB_UTILS_H__
#define __ADB_UTILS_H__
#if CONFIG_LOG
#include "elog.h"
#define ADB_LOGE(fmt, args...) log_e(fmt, ##args)
#define ADB_LOGW(fmt, args...) log_w(fmt, ##args)
#define ADB_LOGI(fmt, args...) log_i(fmt, ##args)
#define ADB_LOGD(fmt, args...) log_d(fmt, ##args)
#else
#define ADB_LOGE(fmt, args...) printk(fmt, ##args)
#define ADB_LOGW(fmt, args...) printk(fmt, ##args)
#define ADB_LOGI(fmt, args...) printk(fmt, ##args)
#define ADB_LOGD(fmt, args...) printk(fmt, ##args)
#endif
#include "sysheap.h"
#define ADB_MEM_TRACE 0
#if ADB_MEM_TRACE
static inline void* adb_malloc_trace(uint32_t size)
{
void *ptr = exram_malloc(4, size);
ADB_LOGI("adb malloc, size:%d, ptr:%p, caller:%p\n", size, ptr, __builtin_return_address(0));
return ptr;
}
static inline void adb_free_trace(void *ptr)
{
ADB_LOGI("adb free, ptr:%p, caller:%p\n", ptr, __builtin_return_address(0));
exram_free(ptr);
}
#define ADB_MALLOC(size) adb_malloc_trace(size)
#define ADB_FREE(ptr) adb_free_trace(ptr)
#else
#define ADB_MALLOC(size) exram_malloc(4, size)
#define ADB_FREE(ptr) exram_free(ptr)
#endif
#endif

View File

@@ -0,0 +1,30 @@
#include "tusb.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "usbd_pvt.h"
#if CONFIG_ADB
#include "adb_device.h"
#endif
static const usbd_class_driver_t _usbd_app_driver[] = {
#if CONFIG_ADB
{
.name = "adb",
.init = adb_dev_init,
.deinit = adb_dev_deinit,
.reset = adb_dev_reset,
.open = adb_dev_open,
.control_xfer_cb = adb_dev_control_xfer_cb,
.xfer_cb = adb_dev_xfer_cb,
.sof = NULL,
},
#endif
};
usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count)
{
*driver_count = sizeof(_usbd_app_driver) / sizeof(usbd_class_driver_t);
return &_usbd_app_driver[0];
}