pinebuds/apps/factory/sys_api_cdc_comm.c

195 lines
4.4 KiB
C

#ifdef __USB_COMM__
#include "sys_api_cdc_comm.h"
#include "app_factory_cdc_comm.h"
#include "hal_bootmode.h"
#include "hwtimer_list.h"
#include "pmu.h"
#ifdef CHIP_HAS_USB
#include "usb_cdc.h"
#endif
#define TIMEOUT_INFINITE ((uint32_t)-1)
const unsigned int default_recv_timeout_short = MS_TO_TICKS(500);
const unsigned int default_recv_timeout_idle =
TIMEOUT_INFINITE; // MS_TO_TICKS(10 * 60 * 1000);
const unsigned int default_recv_timeout_4k_data = MS_TO_TICKS(500);
const unsigned int default_send_timeout = MS_TO_TICKS(500);
static uint32_t send_timeout;
static uint32_t recv_timeout;
static volatile bool cancel_xfer = false;
static uint32_t xfer_err_time = 0;
static uint32_t xfer_err_cnt = 0;
static HWTIMER_ID xfer_timer;
static const struct USB_SERIAL_CFG_T cdc_cfg = {
.mode = USB_SERIAL_API_NONBLOCKING,
};
void reset_transport(void) {
cancel_xfer = false;
if (xfer_timer) {
hwtimer_stop(xfer_timer);
} else {
xfer_timer = hwtimer_alloc(NULL, NULL);
}
usb_serial_flush_recv_buffer();
usb_serial_init_xfer();
set_recv_timeout(default_recv_timeout_short);
set_send_timeout(default_send_timeout);
}
void set_recv_timeout(unsigned int timeout) { recv_timeout = timeout; }
void set_send_timeout(unsigned int timeout) { send_timeout = timeout; }
static void usb_send_timeout(void *param) { usb_serial_cancel_send(); }
static void usb_send_timer_start(void) {
if (send_timeout == TIMEOUT_INFINITE) {
return;
}
if (xfer_timer) {
hwtimer_update_then_start(xfer_timer, usb_send_timeout, NULL, send_timeout);
}
}
static void usb_send_timer_stop(void) {
if (xfer_timer) {
hwtimer_stop(xfer_timer);
}
}
static int usb_send_data(const unsigned char *buf, size_t len) {
int ret;
usb_send_timer_start();
ret = usb_serial_send(buf, len);
usb_send_timer_stop();
return ret;
}
int send_data(const unsigned char *buf, size_t len) {
if (cancel_xfer) {
return -1;
}
return usb_send_data(buf, len);
}
static void usb_recv_timeout(void *param) { usb_serial_cancel_recv(); }
static void usb_recv_timer_start(void) {
if (recv_timeout == TIMEOUT_INFINITE) {
return;
}
if (xfer_timer) {
hwtimer_update_then_start(xfer_timer, usb_recv_timeout, NULL, recv_timeout);
}
}
static void usb_recv_timer_stop(void) {
if (xfer_timer) {
hwtimer_stop(xfer_timer);
}
}
static int usb_recv_data(unsigned char *buf, size_t len, size_t *rlen) {
int ret;
usb_recv_timer_start();
ret = usb_serial_recv(buf, len);
usb_recv_timer_stop();
if (ret == 0) {
*rlen = len;
}
return ret;
}
int recv_data_ex(unsigned char *buf, size_t len, size_t expect, size_t *rlen) {
if (cancel_xfer) {
return -1;
}
return usb_recv_data(buf, expect, rlen);
}
static int usb_handle_error(void) {
int ret;
TRACE(0, "****** Send break ******");
// Send break signal, to tell the peer to reset the connection
ret = usb_serial_send_break();
if (ret) {
TRACE(1, "Sending break failed: %d", ret);
}
return ret;
}
int handle_error(void) {
int ret = 0;
uint32_t err_time;
hal_sys_timer_delay(MS_TO_TICKS(50));
if (!cancel_xfer) {
ret = usb_handle_error();
}
err_time = hal_sys_timer_get();
if (xfer_err_cnt == 0 || err_time - xfer_err_time > MS_TO_TICKS(5000)) {
xfer_err_cnt = 0;
xfer_err_time = err_time;
}
xfer_err_cnt++;
if (xfer_err_cnt < 3) {
hal_sys_timer_delay(MS_TO_TICKS(100));
} else if (xfer_err_cnt < 5) {
hal_sys_timer_delay(MS_TO_TICKS(500));
} else {
hal_sys_timer_delay(MS_TO_TICKS(2000));
}
return ret;
}
static int usb_cancel_input(void) { return usb_serial_flush_recv_buffer(); }
int cancel_input(void) { return usb_cancel_input(); }
void system_reboot(void) {
hal_sys_timer_delay(MS_TO_TICKS(10));
hal_cmu_sys_reboot();
}
void system_shutdown(void) {
#if 0
if (dld_transport == TRANSPORT_USB) {
// Avoid PC usb serial driver hanging
usb_serial_close();
}
#endif
hal_sys_timer_delay(MS_TO_TICKS(10));
pmu_shutdown();
}
void system_set_bootmode(unsigned int bootmode) {
bootmode &= ~(HAL_SW_BOOTMODE_READ_ENABLED | HAL_SW_BOOTMODE_WRITE_ENABLED);
hal_sw_bootmode_set(bootmode);
}
void system_clear_bootmode(unsigned int bootmode) {
bootmode &= ~(HAL_SW_BOOTMODE_READ_ENABLED | HAL_SW_BOOTMODE_WRITE_ENABLED);
hal_sw_bootmode_clear(bootmode);
}
unsigned int system_get_bootmode(void) { return hal_sw_bootmode_get(); }
#endif