314 lines
7.1 KiB
C
314 lines
7.1 KiB
C
#ifdef __USB_COMM__
|
|
#include "app_factory_cdc_comm.h"
|
|
#include "plat_types.h"
|
|
#include "stdbool.h"
|
|
#include "stdint.h"
|
|
#include "stdio.h"
|
|
#include "string.h"
|
|
#include "sys_api_cdc_comm.h"
|
|
#include "tool_msg.h"
|
|
|
|
static enum PARSE_STATE parse_state;
|
|
static struct message_t recv_msg;
|
|
static struct message_t send_msg = {
|
|
{
|
|
PREFIX_CHAR,
|
|
},
|
|
};
|
|
|
|
static unsigned char check_sum(unsigned char *buf, unsigned char len) {
|
|
int i;
|
|
unsigned char sum = 0;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
sum += buf[i];
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
int send_reply(const unsigned char *payload, unsigned int len) {
|
|
int ret = 0;
|
|
|
|
if (len + 1 > sizeof(send_msg.data)) {
|
|
TRACE(1, "Packet length too long: %u", len);
|
|
return -1;
|
|
}
|
|
|
|
send_msg.hdr.type = recv_msg.hdr.type;
|
|
send_msg.hdr.seq = recv_msg.hdr.seq;
|
|
send_msg.hdr.len = len;
|
|
memcpy(&send_msg.data[0], payload, len);
|
|
send_msg.data[len] =
|
|
~check_sum((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
|
|
|
|
ret = send_data((unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg));
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void reset_parse_state(unsigned char **buf, size_t *len) {
|
|
parse_state = PARSE_HEADER;
|
|
memset(&recv_msg.hdr, 0, sizeof(recv_msg.hdr));
|
|
|
|
*buf = (unsigned char *)&recv_msg.hdr;
|
|
*len = sizeof(recv_msg.hdr);
|
|
}
|
|
|
|
static enum ERR_CODE check_msg_hdr(void) {
|
|
enum ERR_CODE errcode = ERR_NONE;
|
|
|
|
switch (recv_msg.hdr.type) {
|
|
case TYPE_SYS:
|
|
if (recv_msg.hdr.len != 1 && recv_msg.hdr.len != 5) {
|
|
// TRACE(1,"SYS msg length error: %u", recv_msg.hdr.len);
|
|
errcode = ERR_LEN;
|
|
}
|
|
break;
|
|
case TYPE_READ:
|
|
if (recv_msg.hdr.len != 4) {
|
|
// TRACE(1,"READ msg length error: %u", recv_msg.hdr.len);
|
|
errcode = ERR_LEN;
|
|
}
|
|
break;
|
|
case TYPE_WRITE:
|
|
if (recv_msg.hdr.len <= 4 || recv_msg.hdr.len > 20) {
|
|
// TRACE(1,"WRITE msg length error: %u", recv_msg.hdr.len);
|
|
errcode = ERR_LEN;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (errcode == ERR_NONE && recv_msg.hdr.len + 1 > sizeof(recv_msg.data)) {
|
|
errcode = ERR_LEN;
|
|
}
|
|
|
|
return errcode;
|
|
}
|
|
|
|
static enum ERR_CODE handle_sys_cmd(enum SYS_CMD_TYPE cmd, unsigned char *param,
|
|
unsigned int len) {
|
|
unsigned char cret[5];
|
|
unsigned int bootmode;
|
|
|
|
cret[0] = ERR_NONE;
|
|
|
|
if (cmd == SYS_CMD_SET_BOOTMODE || cmd == SYS_CMD_CLR_BOOTMODE) {
|
|
if (len != 4) {
|
|
TRACE(2, "Invalid SYS CMD len %u for cmd: 0x%x", len, cmd);
|
|
return ERR_DATA_LEN;
|
|
}
|
|
} else {
|
|
if (len != 0) {
|
|
TRACE(2, "Invalid SYS CMD len %u for cmd: 0x%x", len, cmd);
|
|
return ERR_DATA_LEN;
|
|
}
|
|
}
|
|
|
|
switch (cmd) {
|
|
case SYS_CMD_REBOOT: {
|
|
TRACE(0, "--- Reboot---");
|
|
send_reply(cret, 1);
|
|
system_reboot();
|
|
break;
|
|
}
|
|
case SYS_CMD_SHUTDOWN: {
|
|
TRACE(0, "--- Shutdown ---");
|
|
send_reply(cret, 1);
|
|
system_shutdown();
|
|
break;
|
|
}
|
|
case SYS_CMD_SET_BOOTMODE: {
|
|
TRACE(0, "--- Set bootmode ---");
|
|
memcpy(&bootmode, param, 4);
|
|
system_set_bootmode(bootmode);
|
|
send_reply(cret, 1);
|
|
break;
|
|
}
|
|
case SYS_CMD_CLR_BOOTMODE: {
|
|
TRACE(0, "--- Clear bootmode ---");
|
|
memcpy(&bootmode, param, 4);
|
|
system_clear_bootmode(bootmode);
|
|
send_reply(cret, 1);
|
|
break;
|
|
}
|
|
case SYS_CMD_GET_BOOTMODE: {
|
|
TRACE(0, "--- Get bootmode ---");
|
|
bootmode = system_get_bootmode();
|
|
memcpy(&cret[1], &bootmode, 4);
|
|
send_reply(cret, 5);
|
|
break;
|
|
}
|
|
default: {
|
|
TRACE(1, "Invalid command: 0x%x", recv_msg.data[0]);
|
|
return ERR_SYS_CMD;
|
|
}
|
|
}
|
|
|
|
return ERR_NONE;
|
|
}
|
|
|
|
static enum ERR_CODE handle_data(unsigned char **buf, size_t *len, int *extra) {
|
|
enum ERR_CODE errcode = ERR_NONE;
|
|
#if 0
|
|
uint32_t rlen = 0;
|
|
#endif
|
|
*extra = 0;
|
|
|
|
// Checksum
|
|
if (check_sum((unsigned char *)&recv_msg, MSG_TOTAL_LEN(&recv_msg)) != 0xFF) {
|
|
TRACE(0, "Checksum error");
|
|
return ERR_CHECKSUM;
|
|
}
|
|
|
|
switch (recv_msg.hdr.type) {
|
|
case TYPE_SYS: {
|
|
TRACE_TIME(0, "------ SYS CMD ------");
|
|
errcode = handle_sys_cmd((enum SYS_CMD_TYPE)recv_msg.data[0],
|
|
&recv_msg.data[1], recv_msg.hdr.len - 1);
|
|
if (errcode != ERR_NONE) {
|
|
return errcode;
|
|
}
|
|
break;
|
|
}
|
|
case TYPE_READ: {
|
|
TRACE_TIME(0, "------ READ CMD ------");
|
|
#if 0
|
|
uint32_t addr = (recv_msg.data[0] << 16) | (recv_msg.data[1] << 8) | recv_msg.data[2];
|
|
uint8_t data[4] = {0};
|
|
rlen = read_reg(addr, data);
|
|
if(rlen == 0)
|
|
return ERR_LEN;
|
|
else {
|
|
send_reply(data, rlen);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
case TYPE_WRITE: {
|
|
TRACE_TIME(0, "------ WRITE CMD ------");
|
|
#if 0
|
|
uint32_t addr = (recv_msg.data[0] << 16) | (recv_msg.data[1] << 8) | recv_msg.data[2];
|
|
uint32_t wdata = (recv_msg.data[3] << 24) | (recv_msg.data[4] << 16) | (recv_msg.data[5] << 8) | recv_msg.data[6];
|
|
uint8_t data[1] = {0};
|
|
errcode = write_reg(addr, wdata);
|
|
if (errcode != ERR_NONE)
|
|
return errcode;
|
|
else
|
|
send_reply(data, 1);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return ERR_NONE;
|
|
}
|
|
|
|
static int parse_packet(unsigned char **buf, size_t *len) {
|
|
enum ERR_CODE errcode;
|
|
int rlen = *len;
|
|
unsigned char *data;
|
|
int i;
|
|
int extra;
|
|
unsigned char cret;
|
|
|
|
switch (parse_state) {
|
|
case PARSE_HEADER:
|
|
ASSERT(rlen > 0 && rlen <= sizeof(recv_msg.hdr), "Invalid rlen!");
|
|
|
|
if (recv_msg.hdr.prefix == PREFIX_CHAR) {
|
|
errcode = check_msg_hdr();
|
|
if (errcode != ERR_NONE) {
|
|
goto _err;
|
|
}
|
|
parse_state = PARSE_DATA;
|
|
*buf = &recv_msg.data[0];
|
|
*len = recv_msg.hdr.len + 1;
|
|
} else {
|
|
data = (unsigned char *)&recv_msg.hdr.prefix;
|
|
for (i = 1; i < rlen; i++) {
|
|
if (data[i] == PREFIX_CHAR) {
|
|
memmove(&recv_msg.hdr.prefix, &data[i], rlen - i);
|
|
break;
|
|
}
|
|
}
|
|
*buf = &data[rlen - i];
|
|
*len = sizeof(recv_msg.hdr) + i - rlen;
|
|
}
|
|
break;
|
|
case PARSE_DATA:
|
|
errcode = handle_data(buf, len, &extra);
|
|
if (errcode != ERR_NONE) {
|
|
goto _err;
|
|
}
|
|
// Receive next message
|
|
reset_parse_state(buf, len);
|
|
break;
|
|
default:
|
|
TRACE(1, "Invalid parse_state: %d", parse_state);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
_err:
|
|
cancel_input();
|
|
cret = (unsigned char)errcode;
|
|
send_reply(&cret, 1);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void comm_loop(void) {
|
|
int ret;
|
|
unsigned char *buf = NULL;
|
|
size_t len = 0;
|
|
size_t buf_len, rlen;
|
|
|
|
_sync:
|
|
reset_transport();
|
|
reset_parse_state(&buf, &len);
|
|
|
|
while (1) {
|
|
rlen = 0;
|
|
if (parse_state == PARSE_HEADER) {
|
|
set_recv_timeout(default_recv_timeout_idle);
|
|
} else {
|
|
set_recv_timeout(default_recv_timeout_short);
|
|
}
|
|
buf_len = 0;
|
|
|
|
ret = recv_data_ex(buf, buf_len, len, &rlen);
|
|
if (ret) {
|
|
TRACE(1, "Receiving data failed: %d", ret);
|
|
goto _err;
|
|
}
|
|
|
|
if (len != rlen) {
|
|
TRACE(2, "Receiving part of the data: expect=%u real=%u", len, rlen);
|
|
goto _err;
|
|
}
|
|
|
|
ret = parse_packet(&buf, &len);
|
|
if (ret) {
|
|
TRACE(0, "Parsing packet failed");
|
|
goto _err;
|
|
}
|
|
}
|
|
|
|
_err:
|
|
ret = handle_error();
|
|
if (ret == 0) {
|
|
TRACE(0, "retry ...");
|
|
goto _sync;
|
|
}
|
|
|
|
return;
|
|
}
|
|
#endif
|