946 lines
27 KiB
C
946 lines
27 KiB
C
#include "client.h"
|
||
#include "system/includes.h"
|
||
/* #include "os/os_compat.h" */
|
||
#include "btstack/avctp_user.h"
|
||
#include "server/audio_server.h"
|
||
#include "server/server_core.h"
|
||
#include "syscfg/syscfg_id.h"
|
||
|
||
#ifdef CONFIG_WIFIBOX_ENABLE
|
||
|
||
#ifdef WB_CLIENT_DEBUG_ENABLE
|
||
#define log_info(x, ...) printf("[WB_PRC][INFO] " x " ", ## __VA_ARGS__)
|
||
#define log_err(x, ...) printf("[WB_PRC][ERR] " x " ", ## __VA_ARGS__)
|
||
#else
|
||
#define log_info(...)
|
||
#define log_err(...)
|
||
#endif
|
||
|
||
MODULE_VERSION_EXPORT(wb_client, WB_CLIENT_VERSION);
|
||
|
||
|
||
typedef struct {
|
||
u8 serial[16];
|
||
u32 conn_fail;
|
||
u32 conn_cnt;
|
||
u32 finish_cnt;
|
||
} stat_data_type;
|
||
|
||
static stat_data_type stat_data = {0};
|
||
|
||
typedef struct {
|
||
struct server *dec_server; //解码服务
|
||
u8 dec_status; //解码器运行标志位
|
||
u8 *data_buf; //音频数据buffer
|
||
cbuffer_t data_cbuf; //音频数据cycle buffer
|
||
u32 total_size; //音频文件总长度
|
||
u32 recv_size; //已接收音频数据长度
|
||
u32 play_size; //当前播放进度
|
||
u8 dec_ready_flag; //解码器就绪标志位
|
||
OS_SEM audio_sem;
|
||
int init_data_len;
|
||
int init_tmp_len;
|
||
u8 *init_read_ptr;
|
||
} audio_hdl_type;
|
||
|
||
static audio_hdl_type audio_hdl = {0};
|
||
|
||
static struct {
|
||
u8 xosc[2];
|
||
test_option_type test_option;
|
||
u8 dut_reset_flag;
|
||
u8 freq_adj_flag;
|
||
u8 bt_freq_stat_flag;
|
||
u8 test_pass_flag;
|
||
OS_SEM conn_sem;
|
||
OS_SEM freq_sem;
|
||
FSM_T thradj_fsm;
|
||
FSM_T test_fsm;
|
||
u8 senthr_adj_flag;
|
||
u8 *remote_mac;
|
||
wbcp_operations_interface_type *wbcp_ops;
|
||
} client = {0};
|
||
|
||
#define __this (&client)
|
||
|
||
int bt_fre_offset_get();
|
||
|
||
static void exit_fsm_process(void);
|
||
static void bt_freq_test_before(void);
|
||
static void bt_freq_test_after(void);
|
||
static int wifibox_bt_connect_pend(int timeout);
|
||
static s32 wifibox_bt_freq_finish_pend(int timeout);
|
||
static s8 open_audio_dec(void);
|
||
/* static u32 wifibox_read_stat_data(stat_data_type *data); */
|
||
/* static s32 wifibox_write_stat_data(stat_data_type *data); */
|
||
|
||
static s8 pwrthr_adj_event_handler(void *priv);
|
||
static s8 senthr_adj_event_handler(void *priv);
|
||
static void thradj_fsm_err(void *priv);
|
||
|
||
static s8 pwr_test_event_handler(void *priv);
|
||
static s8 sen_test_event_handler(void *priv);
|
||
static s8 freq_test_event_handler(void *priv);
|
||
static s8 finish_test_event_handler(void *priv);
|
||
static void test_fsm_err(void *priv);
|
||
void __attribute__((weak)) wifibox_result_deal(u8 res);
|
||
|
||
static FsmTable_T thradj_fsm_tal[] = {
|
||
{PWRTHR_ADJ_EVENT, PWRTHR_ADJ_STATUS, pwrthr_adj_event_handler, SENTHR_ADJ_STATUS, 0},
|
||
{SENTHR_ADJ_EVENT, SENTHR_ADJ_STATUS, senthr_adj_event_handler, PWRTHR_ADJ_STATUS, 0},
|
||
};
|
||
|
||
static FsmTable_T test_fsm_tal[] = {
|
||
{PWR_TEST_EVENT, PWR_TEST_STATUS, pwr_test_event_handler, SEN_TEST_STATUS, 0},
|
||
{SEN_TEST_EVENT, SEN_TEST_STATUS, sen_test_event_handler, FREQ_TEST_STATUS, 0},
|
||
/* {FREQ_TEST_EVENT, FREQ_TEST_STATUS, freq_test_event_handler, PWR_TEST_STATUS, 0}, */
|
||
{FREQ_TEST_EVENT, FREQ_TEST_STATUS, freq_test_event_handler, FINISH_TEST_STATUS, 0},
|
||
{FINISH_TEST_EVENT, FINISH_TEST_STATUS, finish_test_event_handler, PWR_TEST_STATUS, 0},
|
||
};
|
||
|
||
|
||
static void fsm_tbl_init(void *priv)
|
||
{
|
||
wbcp_conn_params_type *conn_params = (wbcp_conn_params_type *)priv;
|
||
fsm_timeout_type *fsm_timeout = &conn_params->fsm_timeout;
|
||
test_option_type *test_option = &conn_params->test_option;
|
||
FsmTable_T fsm_tal[4] = {0};
|
||
static FsmTable_T init_fsm_tal[4] = {0};
|
||
u8 idx = 0;
|
||
static u8 init = 0;
|
||
|
||
if (!init) {
|
||
init = 1;
|
||
memcpy(&init_fsm_tal, &test_fsm_tal, sizeof(test_fsm_tal));
|
||
} else {
|
||
memcpy(&test_fsm_tal, &init_fsm_tal, sizeof(test_fsm_tal));
|
||
}
|
||
|
||
__this->dut_reset_flag = conn_params->dut_reset_flag;
|
||
__this->freq_adj_flag = conn_params->freq_adj_flag;
|
||
memcpy(&__this->test_option, test_option, sizeof(test_option_type));
|
||
|
||
thradj_fsm_tal[0].timeout = fsm_timeout->thradj_fsm[0];
|
||
thradj_fsm_tal[1].timeout = fsm_timeout->thradj_fsm[1];
|
||
|
||
for (u8 i = 0; i < ARRAY_SIZE(fsm_timeout->test_fsm); i++) {
|
||
test_fsm_tal[i].timeout = fsm_timeout->test_fsm[i];
|
||
}
|
||
|
||
if (__this->test_option.wifi_pwr_option) {
|
||
memcpy(&fsm_tal[idx], &test_fsm_tal[0], sizeof(FsmTable_T));
|
||
idx++;
|
||
}
|
||
|
||
if (__this->test_option.wifi_sen_option || __this->test_option.wifi_rx_rate_option) {
|
||
memcpy(&fsm_tal[idx], &test_fsm_tal[1], sizeof(FsmTable_T));
|
||
if (!__this->test_option.wifi_pwr_option) {
|
||
test_fsm_tal[ARRAY_SIZE(test_fsm_tal) - 1].NextState = test_fsm_tal[1].CurState;
|
||
}
|
||
idx++;
|
||
} else {
|
||
if (__this->test_option.wifi_pwr_option) {
|
||
fsm_tal[0].NextState = test_fsm_tal[1].NextState;
|
||
} else {
|
||
test_fsm_tal[ARRAY_SIZE(test_fsm_tal) - 1].NextState = test_fsm_tal[ARRAY_SIZE(test_fsm_tal) - 2].CurState;
|
||
}
|
||
}
|
||
memcpy(&fsm_tal[idx], &test_fsm_tal[2], sizeof(FsmTable_T) * 2);
|
||
memcpy(test_fsm_tal, fsm_tal, sizeof(test_fsm_tal));
|
||
|
||
FSM_Init(&__this->test_fsm, test_fsm_tal, idx + 2, test_fsm_tal[0].CurState, test_fsm_err);
|
||
}
|
||
|
||
|
||
static s8 pwrthr_adj_event_handler(void *priv)
|
||
{
|
||
log_info("==================== STATUS : PWRTHR_ADJ_STATUS ====================\n\n");
|
||
if (__this->wbcp_ops->start_send_test_data(__this->remote_mac, PWRTHR_SEND_TEST_DATA_PERIOD, 0) == 0) {
|
||
return FSM_NEXT_STATE;
|
||
}
|
||
return FSM_ERR;
|
||
}
|
||
|
||
|
||
static s8 senthr_adj_event_handler(void *priv)
|
||
{
|
||
log_info("==================== STATUS : SENTHR_ADJ_STATUS ====================\n\n");
|
||
stat_res_type *res = NULL;
|
||
event_data_type new_event = {0};
|
||
event_data_type *event_data = (event_data_type *)priv;
|
||
senthr_adj_event_params_type *params = &event_data->params.senthr_adj_event_params;
|
||
|
||
if (!__this->senthr_adj_flag) {
|
||
__this->senthr_adj_flag = 1;
|
||
__this->wbcp_ops->stop_send_test_data();
|
||
|
||
new_event.event = SENTHR_ADJ_EVENT;
|
||
if (__this->wbcp_ops->send_event_data(&new_event, __this->remote_mac, 1) != 0) {
|
||
log_err("SEND_FAIL : SENTHR_ADJ_EVENT");
|
||
goto _exit_;
|
||
}
|
||
return FSM_KEEP_STATE;
|
||
}
|
||
|
||
switch (params->stat) {
|
||
case 1 :
|
||
log_info("SENTHR_STEP : OPEN STAT");
|
||
__this->wbcp_ops->start_stat_prop(0, 0);
|
||
return FSM_KEEP_STATE;
|
||
|
||
case 2 :
|
||
res = __this->wbcp_ops->stop_stat_prop();
|
||
log_info("SENTHR_STEP : SEND RES, pcnt = %d, sen = %d.", res->pcnt, res->pwr);
|
||
new_event.event = SENTHR_ADJ_EVENT;
|
||
new_event.params.senthr_adj_event_params.pcnt = res->pcnt;
|
||
new_event.params.senthr_adj_event_params.sen = res->pwr;
|
||
if (__this->wbcp_ops->send_event_data(&new_event, __this->remote_mac, 1) != 0) {
|
||
log_err("SEND_FAIL : SENTHR_ADJ_EVENT");
|
||
goto _exit_;
|
||
}
|
||
return FSM_KEEP_STATE;
|
||
|
||
case 3 :
|
||
log_info("SENTHR_STEP : FINISH ADJUST");
|
||
cpu_reset();
|
||
/* return FSM_NEXT_STATE; */
|
||
|
||
default :
|
||
break;
|
||
}
|
||
|
||
_exit_:
|
||
__this->senthr_adj_flag = 0;
|
||
return FSM_ERR;
|
||
}
|
||
|
||
|
||
static void thradj_fsm_err(void *priv)
|
||
{
|
||
log_info("============================== THR_ADJ_FSM ERR =============================\n\n");
|
||
cpu_reset();
|
||
}
|
||
|
||
|
||
static s8 pwr_test_event_handler(void *priv)
|
||
{
|
||
log_info("==================== STATUS : PWR_TEST_STATUS =====================\n\n");
|
||
if (__this->wbcp_ops->start_send_test_data(__this->remote_mac, PWRTEST_SEND_TEST_DATA_PERIOD, 0) == 0) {
|
||
return FSM_NEXT_STATE;
|
||
}
|
||
return FSM_ERR;
|
||
}
|
||
|
||
|
||
static s8 sen_test_event_handler(void *priv)
|
||
{
|
||
log_info("==================== STATUS : SEN_TEST_STATUS =====================\n\n");
|
||
|
||
__this->wbcp_ops->stop_send_test_data();
|
||
__this->wbcp_ops->start_stat_prop(0, 0);
|
||
|
||
return FSM_NEXT_STATE;
|
||
}
|
||
|
||
|
||
static s8 freq_test_event_handler(void *priv)
|
||
{
|
||
log_info("==================== STATUS : FREQ_TEST_STATUS ====================\n\n");
|
||
|
||
event_data_type *event = (event_data_type *)priv;
|
||
freq_test_event_params_type *params = &event->params.freq_test_event_params;
|
||
event_data_type new_event = {0};
|
||
freq_test_event_params_type *new_params = &new_event.params.freq_test_event_params;
|
||
stat_res_type *res = NULL;
|
||
const u8 *bt_mac = NULL;
|
||
|
||
if (__this->test_option.wifi_pwr_option) {
|
||
__this->wbcp_ops->stop_send_test_data();
|
||
}
|
||
|
||
if (__this->test_option.wifi_sen_option || __this->test_option.wifi_rx_rate_option) {
|
||
res = __this->wbcp_ops->stop_stat_prop();
|
||
new_params->pcnt = res->pcnt;
|
||
new_params->sen = res->pwr;
|
||
log_info("SEN_RES : pcnt = %d, sen = %d.", res->pcnt, res->pwr);
|
||
}
|
||
|
||
if (__this->test_option.wifi_freq_option) {
|
||
const u8 *bt_get_mac_addr();
|
||
bt_mac = bt_get_mac_addr();
|
||
if (bt_mac == NULL) {
|
||
return FSM_ERR;
|
||
}
|
||
put_buf(bt_mac, MAC_ADDR_SIZE);
|
||
memcpy(&new_params->bt_mac, bt_mac, MAC_ADDR_SIZE);
|
||
}
|
||
|
||
new_event.event = FREQ_TEST_EVENT;
|
||
if (__this->wbcp_ops->send_event_data(&new_event, __this->remote_mac, 1) != 0) {
|
||
log_err("SEND_FAIL : FREQ_TEST_EVENT.");
|
||
return FSM_ERR;
|
||
}
|
||
|
||
if (__this->test_option.wifi_freq_option) {
|
||
/* wifi_off(); */
|
||
bt_freq_test_before();
|
||
/* if (wifibox_bt_connect_pend(BT_FREQ_CONN_TIMEOUT) != OS_NO_ERR) { */
|
||
/* log_err("BT CONN TIMEOUT.\n"); */
|
||
/* return FSM_ERR; */
|
||
/* } */
|
||
|
||
if (wifibox_bt_freq_finish_pend(BT_FREQ_STAT_TIMEOUT) != OS_NO_ERR) {
|
||
log_err("BT FREQ TEST TIMEOUT.\n");
|
||
return FSM_ERR;
|
||
}
|
||
bt_freq_test_after();
|
||
}
|
||
|
||
/* exit_fsm_process(); */
|
||
return FSM_NEXT_STATE;
|
||
}
|
||
|
||
|
||
static s8 finish_test_event_handler(void *priv)
|
||
{
|
||
log_info("=================== STATUS : FINISH_TEST_STATUS ===================\n\n");
|
||
|
||
s32 err = 0;
|
||
wifi_freq_offset_type wifi_offset = {0};
|
||
event_data_type *event = (event_data_type *)priv;
|
||
finish_test_event_params_type *params = &event->params.finish_test_event_params;
|
||
event_data_type new_event = {0};
|
||
|
||
wifibox_result_deal(params->result);
|
||
|
||
if (__this->freq_adj_flag) {
|
||
wifi_offset.offset = bt_fre_offset_get();
|
||
if (wifi_offset.offset < FREQ_ADJUST_LIMIT && \
|
||
wifi_offset.offset > -FREQ_ADJUST_LIMIT) {
|
||
wifi_get_xosc(wifi_offset.xosc);
|
||
wifi_offset.crc = CRC16(&wifi_offset.offset, sizeof(wifi_freq_offset_type) - sizeof(s16));
|
||
err = syscfg_write(CFG_WIFI_FRE_OFFSET, &wifi_offset, sizeof(wifi_freq_offset_type));
|
||
if (err == sizeof(wifi_freq_offset_type)) {
|
||
log_info("syscfg_write : fre = %d, osc = %d/%d\n", wifi_offset.offset, wifi_offset.xosc[0], wifi_offset.xosc[1]);
|
||
} else {
|
||
log_err("syscfg_write : err = %d\n", err);
|
||
}
|
||
} else {
|
||
log_info("freq = %d, out of FREQ_ADJUST_LIMIT\n", wifi_offset.offset);
|
||
}
|
||
}
|
||
|
||
#ifdef AUDIO_TRANSFER_ENABLE
|
||
if (!params->result) {
|
||
os_sem_set(&audio_hdl.audio_sem, 0);
|
||
if (os_sem_pend(&audio_hdl.audio_sem, AUDIO_RECV_TIMEOUT) != OS_NO_ERR) {
|
||
log_err("AUDIO RECV ERR");
|
||
return FSM_ERR;
|
||
}
|
||
log_info("AUDIO RECV COMPLETE");
|
||
__this->test_pass_flag = 1;
|
||
open_audio_dec();
|
||
}
|
||
#endif
|
||
stat_data.finish_cnt++;
|
||
os_time_dly(WBCP_WAIT_ACK_TIMEOUT);
|
||
exit_fsm_process();
|
||
return FSM_NEXT_STATE;
|
||
}
|
||
|
||
|
||
static void test_fsm_err(void *priv)
|
||
{
|
||
log_info("============================== FSM ERR =============================\n\n");
|
||
|
||
FSM_StateTransfer(&__this->test_fsm, __this->test_fsm.FsmTable[0].CurState);
|
||
exit_fsm_process();
|
||
}
|
||
|
||
|
||
static void exit_fsm_process(void)
|
||
{
|
||
log_info("======================== EXIT FSM PROCESS =========================\n\n");
|
||
/* wifibox_write_stat_data(&stat_data); */
|
||
if (__this->test_pass_flag) {
|
||
__this->wbcp_ops->rx_shield();
|
||
} else {
|
||
#ifdef WB_DUT_RESET_ENABLE
|
||
/* if (__this->dut_reset_flag) { */
|
||
cpu_reset();
|
||
/* } */
|
||
#endif
|
||
}
|
||
__this->senthr_adj_flag = 0;
|
||
__this->wbcp_ops->stop_send_test_data();
|
||
__this->wbcp_ops->stop_stat_prop();
|
||
bt_freq_test_after();
|
||
|
||
/* if (!wifi_is_on()) { */
|
||
/* wifi_on(); */
|
||
/* while (!wifi_is_on()); */
|
||
/* } */
|
||
__this->wbcp_ops->break_conn();
|
||
}
|
||
|
||
|
||
static void wbcp_event_handler(event_data_type *event_data)
|
||
{
|
||
switch (event_data->event) {
|
||
case PWRTHR_ADJ_EVENT :
|
||
case SENTHR_ADJ_EVENT :
|
||
case FINISH_ADJ_EVENT :
|
||
FSM_EventHandle(&__this->thradj_fsm, event_data->event, event_data);
|
||
break;
|
||
|
||
case PWR_TEST_EVENT :
|
||
case SEN_TEST_EVENT :
|
||
case FREQ_TEST_EVENT :
|
||
case FINISH_TEST_EVENT :
|
||
FSM_EventHandle(&__this->test_fsm, event_data->event, event_data);
|
||
break;
|
||
|
||
default :
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
static void wbcp_event_handle_task(void *priv)
|
||
{
|
||
s32 msg[32] = {0}, timer_id = 0;
|
||
event_data_type *event_data = NULL;
|
||
|
||
for (;;) {
|
||
if (os_taskq_pend(NULL, msg, ARRAY_SIZE(msg)) != OS_TASKQ) {
|
||
continue;
|
||
}
|
||
|
||
if (__this->test_pass_flag) {
|
||
continue;
|
||
}
|
||
|
||
switch (msg[0]) {
|
||
case ENTER_TEST_SUCC_MSG:
|
||
log_info("ENTER_TEST_SUCC_MSG");
|
||
__this->remote_mac = (u8 *)msg[1];
|
||
log_info("======================= ENTER TEST_MODE SUCC =======================\n\n");
|
||
put_buf(__this->remote_mac, MAC_ADDR_SIZE);
|
||
stat_data.conn_cnt++;
|
||
timer_id = sys_timeout_add(NULL, exit_fsm_process, RECV_EVENT_TIMEOUT);
|
||
fsm_tbl_init((u8 *)msg[2]);
|
||
break;
|
||
|
||
case ENTER_TEST_FAIL_MSG :
|
||
log_info("ENTER_TEST_FAIL_MSG");
|
||
log_info("======================= ENTER TEST_MODE FAIL=======================\n\n");
|
||
stat_data.conn_fail++;
|
||
/* wifibox_write_stat_data(&stat_data); */
|
||
#ifdef WB_DUT_RESET_ENABLE
|
||
/* if (msg[1]) { */
|
||
cpu_reset();
|
||
/* } */
|
||
#endif
|
||
__this->wbcp_ops->break_conn();
|
||
break;
|
||
|
||
case NEW_EVENT_MSG:
|
||
event_data = (event_data_type *)&msg[1];
|
||
log_info("NEW_EVENT_MSG : %d.\n", event_data->event);
|
||
if (timer_id && (event_data->event == test_fsm_tal[0].event || event_data->event == thradj_fsm_tal[0].event)) {
|
||
sys_timeout_del(timer_id);
|
||
timer_id = 0;
|
||
}
|
||
wbcp_event_handler(event_data);
|
||
break;
|
||
|
||
default :
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
static void wbcp_audio_data_handler(void *priv)
|
||
{
|
||
u32 wlen = 0, rlen = 0, temp_len = 0;
|
||
audio_data_type *audio_data = (audio_data_type *)priv;
|
||
|
||
audio_hdl.total_size = audio_data->total_size;
|
||
temp_len = audio_hdl.total_size - audio_hdl.recv_size;
|
||
rlen = (temp_len < AUDIO_DATA_SIZE) ? temp_len : AUDIO_DATA_SIZE;
|
||
|
||
wlen = cbuf_write(&audio_hdl.data_cbuf, audio_data->data, rlen);
|
||
if (wlen) {
|
||
putchar('(');
|
||
audio_hdl.recv_size += wlen;
|
||
log_info("AUDIO_RECV : %d / %d\n", audio_hdl.recv_size, audio_hdl.total_size);
|
||
|
||
//音频下载成功,打开解码器,开始播放
|
||
if (audio_hdl.recv_size >= audio_hdl.total_size && audio_hdl.dec_status == 0) {
|
||
os_sem_post(&audio_hdl.audio_sem);
|
||
//保存cycle buffer初始参数,用于循环播放音频
|
||
audio_hdl.init_data_len = audio_hdl.data_cbuf.data_len;
|
||
audio_hdl.init_tmp_len = audio_hdl.data_cbuf.tmp_len;
|
||
audio_hdl.init_read_ptr = audio_hdl.data_cbuf.read_ptr;
|
||
audio_hdl.dec_status = 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
static int audio_vfs_fread(void *priv, void *data, u32 len)
|
||
{
|
||
audio_hdl_type *hdl = (audio_hdl_type *)priv;
|
||
u32 rlen = 0;
|
||
|
||
if (hdl->dec_ready_flag) {
|
||
if (hdl->total_size - hdl->play_size < 512) {
|
||
len = hdl->total_size - hdl->play_size;
|
||
}
|
||
|
||
rlen = cbuf_read(&hdl->data_cbuf, data, len);
|
||
if (rlen) {
|
||
putchar(')');
|
||
hdl->play_size += rlen;
|
||
log_info("AUDIO_PLAY : %d / %d\n", hdl->play_size, hdl->total_size);
|
||
|
||
if (hdl->play_size >= hdl->total_size) {
|
||
hdl->dec_ready_flag = 0;
|
||
log_info("AUDIO_PLAY_COMPLETE\n");
|
||
}
|
||
}
|
||
}
|
||
|
||
return ((hdl->play_size >= hdl->total_size) ? 0 : len);
|
||
}
|
||
|
||
|
||
static int audio_vfs_flen(void *priv)
|
||
{
|
||
audio_hdl_type *hdl = (audio_hdl_type *)priv;
|
||
return hdl->total_size;
|
||
}
|
||
|
||
|
||
static int audio_vfs_seek(void *priv, u32 offset, int orig)
|
||
{
|
||
audio_hdl_type *hdl = (audio_hdl_type *)priv;
|
||
|
||
if (offset > 0) {
|
||
hdl->dec_ready_flag = 1; //解码器开始偏移数据后,再开始播放,避免音频播放开端吞字
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
static const struct audio_vfs_ops audio_vfs_ops = {
|
||
.fread = audio_vfs_fread,
|
||
.flen = audio_vfs_flen,
|
||
.fseek = audio_vfs_seek,
|
||
};
|
||
|
||
|
||
static s8 open_audio_dec(void)
|
||
{
|
||
union audio_req req = {0};
|
||
|
||
req.dec.cmd = AUDIO_DEC_OPEN;
|
||
req.dec.volume = 100;
|
||
req.dec.output_buf = NULL;
|
||
req.dec.output_buf_len = 12 * 1024;
|
||
req.dec.channel = 0;
|
||
req.dec.sample_rate = 0;
|
||
req.dec.priority = 1;
|
||
req.dec.vfs_ops = &audio_vfs_ops;
|
||
req.dec.file = (FILE *)&audio_hdl;
|
||
req.dec.dec_type = "mp3";
|
||
req.dec.sample_source = "dac";
|
||
|
||
//打开解码器
|
||
if (server_request(audio_hdl.dec_server, AUDIO_REQ_DEC, &req) != 0) {
|
||
return -1;
|
||
}
|
||
|
||
//开始解码
|
||
req.dec.cmd = AUDIO_DEC_START;
|
||
if (server_request(audio_hdl.dec_server, AUDIO_REQ_DEC, &req) != 0) {
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
static int close_audio_dec(void)
|
||
{
|
||
union audio_req req = {0};
|
||
|
||
req.dec.cmd = AUDIO_DEC_STOP;
|
||
if (audio_hdl.dec_server) {
|
||
|
||
//关闭解码器
|
||
log_info("stop dec.\n");
|
||
server_request(audio_hdl.dec_server, AUDIO_REQ_DEC, &req);
|
||
|
||
//关闭解码服务
|
||
/* log_info("close audio_server.\n"); */
|
||
/* server_close(audio_hdl.dec_server); */
|
||
/* audio_hdl.dec_server = NULL; */
|
||
|
||
audio_hdl.dec_status = 0;
|
||
audio_hdl.recv_size = 0;
|
||
audio_hdl.play_size = 0;
|
||
|
||
//循环播放音频, 恢复cycle buffer读指针
|
||
audio_hdl.data_cbuf.data_len = audio_hdl.init_data_len;
|
||
audio_hdl.data_cbuf.tmp_len = audio_hdl.init_tmp_len;
|
||
audio_hdl.data_cbuf.read_ptr = audio_hdl.init_read_ptr;
|
||
open_audio_dec();
|
||
|
||
//单次播放音频,清除cycle buffer
|
||
/* cbuf_clear(&audio_hdl.data_cbuf); */
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
static void dec_server_event_handler(void *priv, int argc, int *argv)
|
||
{
|
||
audio_hdl_type *hdl = (audio_hdl_type *)priv;
|
||
|
||
switch (argv[0]) {
|
||
case AUDIO_SERVER_EVENT_ERR:
|
||
log_info("AUDIO_SERVER_EVENT_ERR\n");
|
||
break;
|
||
|
||
case AUDIO_SERVER_EVENT_END:
|
||
log_info("AUDIO_SERVER_EVENT_END\n");
|
||
close_audio_dec();
|
||
break;
|
||
|
||
case AUDIO_SERVER_EVENT_CURR_TIME:
|
||
log_info("AUDIO_PLAY_TIME : %d\n", argv[1]);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
static s8 audio_play_init(void)
|
||
{
|
||
audio_hdl.data_buf = (char *)calloc(1, AUDIO_BUFFER_SIZE);
|
||
if (audio_hdl.data_buf == NULL) {
|
||
log_err("audio buffer malloc error.\n");
|
||
return -1;
|
||
}
|
||
|
||
cbuf_init(&audio_hdl.data_cbuf, audio_hdl.data_buf, AUDIO_BUFFER_SIZE);
|
||
|
||
audio_hdl.dec_server = server_open("audio_server", "dec");
|
||
if (!audio_hdl.dec_server) {
|
||
log_err("audio server open fail.\n");
|
||
return -1;
|
||
} else {
|
||
log_info("open success");
|
||
}
|
||
|
||
server_register_event_handler(audio_hdl.dec_server, &audio_hdl, dec_server_event_handler);
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
int wifibox_client_init(void)
|
||
{
|
||
static u8 init = 0;
|
||
|
||
#ifdef WB_ASSIST_ENABLE
|
||
u8 is_assist = 1;
|
||
#else
|
||
u8 is_assist = 0;
|
||
#endif
|
||
|
||
if (init) {
|
||
log_info("wifibox_client already init");
|
||
return 0;
|
||
}
|
||
|
||
FSM_Init(&__this->thradj_fsm, thradj_fsm_tal, ARRAY_SIZE(thradj_fsm_tal), PWRTHR_ADJ_STATUS, thradj_fsm_err);
|
||
/* FSM_Init(&__this->test_fsm, test_fsm_tal, ARRAY_SIZE(test_fsm_tal), PWR_TEST_STATUS, test_fsm_err); */
|
||
|
||
get_wbcp_operations_interface(&__this->wbcp_ops);
|
||
if (__this->wbcp_ops->init(WB_CLIENT_MODE, is_assist) != 0) {
|
||
log_err("wbcp init fail.\n");
|
||
}
|
||
|
||
os_sem_create(&__this->conn_sem, 0);
|
||
os_sem_create(&__this->freq_sem, 0);
|
||
os_sem_create(&audio_hdl.audio_sem, 0);
|
||
|
||
if (thread_fork("wbcp_event_handle_task", 14, 3 * 1024, 1024, NULL, wbcp_event_handle_task, NULL) != OS_NO_ERR) {
|
||
log_err("%s thread fork fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
#ifdef AUDIO_TRANSFER_ENABLE
|
||
audio_play_init();
|
||
__this->wbcp_ops->regist_audio_data_user_handler(wbcp_audio_data_handler);
|
||
#endif
|
||
|
||
__this->wbcp_ops->regist_usr_handler("wbcp_event_handle_task");
|
||
|
||
/* if (wifibox_read_stat_data(&stat_data) == 0) { */
|
||
/* stat_data.finish_cnt = 0; */
|
||
/* stat_data.conn_cnt = 0; */
|
||
/* stat_data.conn_fail = 0; */
|
||
/* } */
|
||
log_info("STAT_CNT : %d / %d, %d", stat_data.finish_cnt, stat_data.conn_cnt, stat_data.conn_fail);
|
||
|
||
init = 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
u32 user_send_cmd_prepare(USER_CMD_TYPE cmd, u16 param_len, u8 *param);
|
||
static void bt_freq_test_before(void)
|
||
{
|
||
if (__this->bt_freq_stat_flag == 0) {
|
||
log_info("bt_freq_test_before.\n");
|
||
__this->bt_freq_stat_flag = 1;
|
||
|
||
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL);
|
||
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL);
|
||
user_send_cmd_prepare(USER_CTRL_POWER_ON, 0, NULL);
|
||
}
|
||
}
|
||
|
||
|
||
static void bt_freq_test_after(void)
|
||
{
|
||
if (__this->bt_freq_stat_flag) {
|
||
log_info("bt_freq_test_after.\n");
|
||
__this->bt_freq_stat_flag = 0;
|
||
|
||
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL);
|
||
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL);
|
||
user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL);
|
||
user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL);
|
||
user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL);
|
||
}
|
||
}
|
||
|
||
|
||
int wifibox_bt_connect_post(void)
|
||
{
|
||
log_info("wifibox_bt_connect_post\n");
|
||
return os_sem_post(&__this->conn_sem);
|
||
}
|
||
|
||
|
||
static int wifibox_bt_connect_pend(int timeout)
|
||
{
|
||
log_info("wifibox_bt_connect_pend\n");
|
||
os_sem_set(&__this->conn_sem, 0);
|
||
return os_sem_pend(&__this->conn_sem, timeout);
|
||
}
|
||
|
||
|
||
int wifibox_bt_freq_finish_post(void)
|
||
{
|
||
log_info("wifibox_bt_freq_finish_post\n");
|
||
return os_sem_post(&__this->freq_sem);
|
||
}
|
||
|
||
|
||
static s32 wifibox_bt_freq_finish_pend(int timeout)
|
||
{
|
||
log_info("wifibox_bt_freq_finish_pend\n");
|
||
int ret = -1;
|
||
os_sem_set(&__this->freq_sem, 0);
|
||
ret = os_sem_pend(&__this->freq_sem, timeout);
|
||
log_info("bt_freq test finish.\n");
|
||
return ret;
|
||
}
|
||
|
||
|
||
void __attribute__((weak)) wifibox_result_deal(u8 res)
|
||
{
|
||
//测试结果处理回调,可添加非阻塞操作
|
||
if (!res) {
|
||
log_info("wifibox test pass");
|
||
} else {
|
||
log_info("wifibox test nopass");
|
||
}
|
||
}
|
||
|
||
|
||
static void wifi_set_xosc(u8 *xosc)
|
||
{
|
||
memcpy(__this->xosc, xosc, sizeof(__this->xosc));
|
||
}
|
||
|
||
|
||
static void fre_to_xosc(s8 fre, u8 *cur_osc, u8 *cal_osc)
|
||
{
|
||
u8 tmp = 0;
|
||
tmp = (((1000000 * (cur_osc[0] + cur_osc[1])) + (195863 * fre) - (466 * fre * fre)) / 1000000);
|
||
cal_osc[0] = tmp / 2;
|
||
cal_osc[1] = (tmp / 2) + ((tmp % 2) ? 1 : 0);
|
||
printf("tmp = %d, %d/%d\n", tmp, cal_osc[0], cal_osc[1]);
|
||
}
|
||
|
||
|
||
void __attribute__((weak)) wf_rf_pll_offset_adj(long foffet_khz, char en)
|
||
{
|
||
|
||
}
|
||
|
||
|
||
u8 wifi_freq_adjust(void)
|
||
{
|
||
u16 crc = 0;
|
||
s32 ret = 0;
|
||
u8 cal_xosc[2] = {0};
|
||
wifi_freq_offset_type wifi_offset = {0};
|
||
|
||
ret = syscfg_read(CFG_WIFI_FRE_OFFSET, &wifi_offset, sizeof(wifi_freq_offset_type));
|
||
crc = CRC16(&wifi_offset.offset, sizeof(wifi_freq_offset_type) - sizeof(s16));
|
||
if (ret == sizeof(wifi_freq_offset_type) && crc == wifi_offset.crc) {
|
||
log_info("^^^syscfg_read : fre = %d, osc = %d/%d\n", wifi_offset.offset, wifi_offset.xosc[0], wifi_offset.xosc[1]);
|
||
if (wifi_offset.offset) {
|
||
wf_rf_pll_offset_adj(-wifi_offset.offset, 0);
|
||
/* fre_to_xosc(wifi_offset.offset, wifi_offset.xosc, cal_xosc); */
|
||
/* wifi_set_xosc(cal_xosc); */
|
||
}
|
||
return 0;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
|
||
/* =============================================调试使用======================================== */
|
||
#if 0
|
||
|
||
#include "json_c/json_tokener.h"
|
||
#include "fs/fs.h"
|
||
#include "math.h"
|
||
#include <stdlib.h>
|
||
/* #include "hmc1122_attenuator.h" */
|
||
|
||
u8 dut_pa[7] = {0};
|
||
int dut_xosc_cls = 0;
|
||
int dut_xosc_crs = 0;
|
||
int dut_tx_attn = 0;
|
||
int dut_rx_attn = 0;
|
||
|
||
|
||
void wifi_get_xosc(u8 *xosc)
|
||
{
|
||
memcpy(xosc, __this->xosc, sizeof(__this->xosc));
|
||
}
|
||
|
||
|
||
static int wifibox_dut_read_config_info(void)
|
||
{
|
||
FILE *fd;
|
||
char *buf = NULL;
|
||
json_object *new_obj;
|
||
u32 cfg_pa = 0;
|
||
char *DUT_PA = NULL;
|
||
char *DUT_XOSC_CLS = NULL;
|
||
char *DUT_XOSC_CRS = NULL;
|
||
char *TX_ATTN = NULL;
|
||
char *RX_ATTN = NULL;
|
||
|
||
buf = malloc(1024 * 1);
|
||
if (!buf) {
|
||
log_err("malloc error: %d.\n", __LINE__);
|
||
}
|
||
|
||
fd = fopen("mnt/sdfile/res/cfg/dut_config.txt", "r");
|
||
if (!fd) {
|
||
log_err("wifibox config : open file error.\n");
|
||
return -1;
|
||
}
|
||
|
||
fread(buf, 1024, 1, fd);
|
||
fclose(fd);
|
||
|
||
new_obj = json_tokener_parse((const char *)buf);
|
||
if (!new_obj) {
|
||
log_err("wifibox config : json_tokener_parse error.\n");
|
||
return -1;
|
||
}
|
||
|
||
DUT_PA = json_object_get_string(json_object_object_get(new_obj, "PA"));
|
||
DUT_XOSC_CLS = json_object_get_string(json_object_object_get(new_obj, "XOSC_CLS"));
|
||
DUT_XOSC_CRS = json_object_get_string(json_object_object_get(new_obj, "XOSC_CRS"));
|
||
TX_ATTN = json_object_get_string(json_object_object_get(new_obj, "TX_ATTN"));
|
||
RX_ATTN = json_object_get_string(json_object_object_get(new_obj, "RX_ATTN"));
|
||
|
||
cfg_pa = atoi(DUT_PA);
|
||
for (int i = 0; i < ARRAY_SIZE(dut_pa); i++) {
|
||
dut_pa[i] = cfg_pa / ((int)pow(10, ARRAY_SIZE(dut_pa) - 1 - i)) % 10;
|
||
}
|
||
|
||
dut_xosc_cls = atoi(DUT_XOSC_CLS);
|
||
dut_xosc_crs = atoi(DUT_XOSC_CRS);
|
||
dut_tx_attn = atoi(TX_ATTN);
|
||
dut_rx_attn = atoi(RX_ATTN);
|
||
|
||
__this->xosc[0] = dut_xosc_cls;
|
||
__this->xosc[1] = dut_xosc_crs;
|
||
|
||
log_info("=====================DUT_CFG_INFO=====================");
|
||
put_buf(dut_pa, sizeof(dut_pa));
|
||
log_info("dut_xosc_cls = %d, dut_xosc_crs = %d.\n", dut_xosc_cls, dut_xosc_crs);
|
||
log_info("dut_tx_attn = %d, dut_rx_attn = %d.\n", dut_tx_attn, dut_rx_attn);
|
||
log_info("=====================DUT_CFG_INFO=====================");
|
||
|
||
json_object_put(new_obj);
|
||
|
||
if (buf) {
|
||
free(buf);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
void wifibox_dut_config(void)
|
||
{
|
||
if (wifibox_dut_read_config_info() == 0) {
|
||
log_info("DUT SET : PA = %d,%d,%d,%d,%d,%d,%d; XOSC_L = %d, XSOC_R = %d.\n", dut_pa[0], dut_pa[1], dut_pa[2], dut_pa[3], dut_pa[4], dut_pa[5], dut_pa[6], dut_xosc_cls, dut_xosc_crs);
|
||
//衰减器初始化
|
||
/* struct attenuator_operation_t *attn_hdl = NULL; */
|
||
/* get_attn_hdl(&attn_hdl); */
|
||
/* if (attn_hdl) { */
|
||
/* attn_hdl->init(); */
|
||
/* attn_hdl->set_tx_state(dut_tx_attn); */
|
||
/* attn_hdl->set_rx_state(dut_rx_attn); */
|
||
/* } */
|
||
} else {
|
||
log_err("wifibox_dut_config fail.\n");
|
||
}
|
||
}
|
||
|
||
|
||
int wifi_get_pa_trim_data(u8 *pa_data)
|
||
{
|
||
memcpy(pa_data, dut_pa, 7);
|
||
return 1;//不使用自动tune
|
||
}
|
||
|
||
|
||
#endif
|
||
|
||
#endif
|
||
|
||
|
||
|
||
|