pinebuds/apps/factory/app_factory.cpp

685 lines
17 KiB
C++

/***************************************************************************
*
* Copyright 2015-2019 BES.
* All rights reserved. All unpublished rights reserved.
*
* No part of this work may be used or reproduced in any form or by any
* means, or stored in a database or retrieval system, without prior written
* permission of BES.
*
* Use of this work is governed by a license granted by BES.
* This work contains confidential and proprietary information of
* BES. which is protected by copyright, trade secret,
* trademark and other intellectual property rights.
*
****************************************************************************/
#include "app_factory.h"
#include "app_bt_stream.h"
#include "app_key.h"
#include "app_media_player.h"
#include "bluetooth.h"
#include "bt_drv_interface.h"
#include "bt_drv_reg_op.h"
#include "cmsis_os.h"
#include "hal_bootmode.h"
#include "hal_cmu.h"
#include "hal_sleep.h"
#include "hal_trace.h"
#include "list.h"
#include "nvrecord.h"
#include "nvrecord_dev.h"
#include "nvrecord_env.h"
#include "pmu.h"
#include "resources.h"
// for init
#include "app_battery.h"
#include "app_key.h"
#include "app_overlay.h"
#include "app_pwl.h"
#include "app_status_ind.h"
#include "app_thread.h"
#include "app_utils.h"
#include "apps.h"
// for bt
#include "app_bt.h"
#include "app_factory_bt.h"
#include "besbt.h"
// for audio
#include "app_audio.h"
#include "app_utils.h"
#include "audioflinger.h"
// for progress
#include "hal_uart.h"
#include "tool_msg.h"
#include "factory_section.h"
#ifdef __FACTORY_MODE_SUPPORT__
#define APP_FACTORYMODE_RETRY_LIMITED (2)
typedef enum APP_FACTORYMODE_STATUS_INDICATION_T {
APP_FACTORYMODE_STATUS_INDICATION_RUNNING = 0,
APP_FACTORYMODE_STATUS_INDICATION_PASS,
APP_FACTORYMODE_STATUS_INDICATION_FAILED,
APP_FACTORYMODE_STATUS_INDICATION_INVALID,
APP_FACTORYMODE_STATUS_INDICATION_NUM
} APP_FACTORYMODE_STATUS_INDICATION_T;
static void app_factorymode_timehandler(void const *param);
void app_bt_key_shutdown(APP_KEY_STATUS *status, void *param);
void app_factorymode_result_set(bool result);
static osThreadId app_factorymode_tid = NULL;
static struct message_t send_msg = {
{
PREFIX_CHAR,
},
};
static unsigned char send_seq = 0;
osTimerId app_factory_timer = NULL;
osTimerDef(APP_FACTORY_TIMER, app_factorymode_timehandler);
int app_factorymode_languageswitch_proc(void) {
#ifdef MEDIA_PLAYER_SUPPORT
int lan;
int new_lan;
struct nvrecord_env_t *nvrecord_env;
APP_FACTORY_TRACE(1, "%s", __func__);
lan = app_play_audio_get_lang();
new_lan = lan;
app_play_audio_set_lang(new_lan);
nv_record_env_get(&nvrecord_env);
nvrecord_env->media_language.language = new_lan;
nv_record_env_set(nvrecord_env);
APP_FACTORY_TRACE(2, "languages old:%d new:%d", lan, new_lan);
media_PlayAudio(AUD_ID_LANGUAGE_SWITCH, 0);
#endif
return 0;
}
void app_factorymode_languageswitch(APP_KEY_STATUS *status, void *param) {
app_factorymode_languageswitch_proc();
}
void app_factorymode_enter(void) {
APP_FACTORY_TRACE(1, "%s", __func__);
hal_sw_bootmode_set(HAL_SW_BOOTMODE_TEST_MODE |
HAL_SW_BOOTMODE_TEST_SIGNALINGMODE);
hal_cmu_sys_reboot();
}
extern "C" {
static bool isInFactoryMode = false;
bool app_factorymode_get(void) { return isInFactoryMode; }
void app_factorymode_set(bool set) { isInFactoryMode = set; }
}
#ifdef POWERKEY_I2C_SWITCH
void app_factorymode_i2c_switch(APP_KEY_STATUS *status, void *param) {
static int i = 0;
i++;
if (i & 1) {
TRACE(0, "set analog i2c mode !!!");
osDelay(100);
hal_iomux_set_analog_i2c();
} else {
hal_iomux_set_uart0();
osDelay(100);
TRACE(0, "hal_iomux_set_uart0 !!!");
}
}
#endif
#ifdef __IBRT_IBRT_TESTMODE__
void bt_drv_ibrt_test_key_click(APP_KEY_STATUS *status, void *param);
void bt_drv_ibrt_test_key_click(APP_KEY_STATUS *status, void *param) {
btdrv_connect_ibrt_device(bt_addr);
}
#endif
void app_factorymode_key_init(void) {
const APP_KEY_HANDLE app_factorymode_handle_cfg[] = {
#ifdef POWERKEY_I2C_SWITCH
{{APP_KEY_CODE_PWR, APP_KEY_EVENT_RAMPAGECLICK},
"bt i2c key",
app_factorymode_i2c_switch,
NULL},
#endif
#ifdef __POWERKEY_CTRL_ONOFF_ONLY__
{{APP_KEY_CODE_PWR, APP_KEY_EVENT_UP},
"bt function key",
app_bt_key_shutdown,
NULL},
#else
{{APP_KEY_CODE_PWR, APP_KEY_EVENT_LONGLONGPRESS},
"bt function key",
app_bt_key_shutdown,
NULL},
#endif
#ifdef __IBRT_IBRT_TESTMODE__
{{APP_KEY_CODE_PWR, APP_KEY_EVENT_CLICK},
"bt function key",
bt_drv_ibrt_test_key_click,
NULL},
#else
{{APP_KEY_CODE_PWR, APP_KEY_EVENT_CLICK},
"bt function key",
app_factorymode_languageswitch,
NULL},
#endif
{{APP_KEY_CODE_PWR, APP_KEY_EVENT_DOUBLECLICK},
"bt function key",
app_factorymode_bt_xtalcalib,
NULL},
{{APP_KEY_CODE_PWR, APP_KEY_EVENT_LONGPRESS},
"bt function key",
app_factorymode_bt_signalingtest,
NULL},
};
uint8_t i = 0;
APP_FACTORY_TRACE(1, "%s", __func__);
app_key_handle_clear();
for (i = 0; i < (sizeof(app_factorymode_handle_cfg) / sizeof(APP_KEY_HANDLE));
i++) {
app_key_handle_registration(&app_factorymode_handle_cfg[i]);
}
}
static void app_factorymode_audioloopswitch(APP_KEY_STATUS *status,
void *param) {
static bool onaudioloop = false;
onaudioloop = onaudioloop ? false : true;
if (onaudioloop)
app_audio_sendrequest(APP_FACTORYMODE_AUDIO_LOOP,
(uint8_t)APP_BT_SETTING_OPEN, 0);
else
app_audio_sendrequest(APP_FACTORYMODE_AUDIO_LOOP,
(uint8_t)APP_BT_SETTING_CLOSE, 0);
}
void app_factorymode_test_key_init(void) {
const APP_KEY_HANDLE app_factorymode_handle_cfg[] = {
{{APP_KEY_CODE_PWR, APP_KEY_EVENT_CLICK},
"bt function key",
app_factorymode_audioloopswitch,
NULL},
};
uint8_t i = 0;
APP_FACTORY_TRACE(1, "%s", __func__);
for (i = 0; i < (sizeof(app_factorymode_handle_cfg) / sizeof(APP_KEY_HANDLE));
i++) {
app_key_handle_registration(&app_factorymode_handle_cfg[i]);
}
}
void app_factorymode_result_clean(void) {
osSignalClear(app_factorymode_tid, 0x01);
osSignalClear(app_factorymode_tid, 0x02);
}
void app_factorymode_result_set(bool result) {
if (result)
osSignalSet(app_factorymode_tid, 0x01);
else
osSignalSet(app_factorymode_tid, 0x02);
}
bool app_factorymode_result_wait(void) {
bool nRet;
osEvent evt;
while (1) {
// wait any signal
evt = osSignalWait(0x0, osWaitForever);
// get role from signal value
if (evt.status == osEventSignal) {
if (evt.value.signals & 0x01) {
nRet = true;
break;
} else if (evt.value.signals & 0x02) {
nRet = false;
break;
}
}
}
return nRet;
}
static int app_factorymode_send_progress(uint8_t progress) {
APP_MESSAGE_BLOCK msg;
msg.mod_id = APP_MODUAL_OHTER;
msg.msg_body.message_id = 2;
msg.msg_body.message_Param0 = progress;
app_mailbox_put(&msg);
return 0;
}
static int app_factorymode_send_code(uint32_t progress) {
APP_MESSAGE_BLOCK msg;
msg.mod_id = APP_MODUAL_OHTER;
msg.msg_body.message_id = 3;
msg.msg_body.message_Param0 = progress;
app_mailbox_put(&msg);
return 0;
}
int app_factorymode_proc(void) {
uint8_t cnt = 0;
bool nRet;
app_factorymode_tid = osThreadGetId();
app_factorymode_send_progress(60);
app_factorymode_bt_init_connect();
do {
app_factorymode_result_clean();
app_factorymode_bt_create_connect();
nRet = app_factorymode_result_wait();
} while (!nRet && ++cnt < APP_FACTORYMODE_RETRY_LIMITED);
if (!nRet)
goto exit;
app_factorymode_send_progress(90);
app_factorymode_result_clean();
if (!nRet)
goto exit;
app_factorymode_send_progress(100);
osDelay(100);
exit:
app_factorymode_result_clean();
if (nRet) {
return 0;
} else {
return -1;
}
}
static unsigned char app_factorymode_msg_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;
}
static int app_factorymode_msg_uart_send(const unsigned char *buf, size_t len) {
uint32_t sent = 0;
while (sent < len) {
hal_uart_blocked_putc(HAL_UART_ID_0, buf[sent++]);
}
if (sent != len) {
return 1;
}
return 0;
}
static int app_factorymode_msg_send_ping(void) {
int ret;
send_msg.hdr.type = 0x88;
send_msg.hdr.seq = send_seq++;
send_msg.hdr.len = 2;
send_msg.data[0] = 0xaa;
send_msg.data[1] = 0x55;
send_msg.data[2] = ~app_factorymode_msg_check_sum(
(unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg,
MSG_TOTAL_LEN(&send_msg));
return ret;
}
static int app_factorymode_msg_send_progress(uint8_t progress) {
int ret;
send_msg.hdr.type = 0x88;
send_msg.hdr.seq = send_seq++;
send_msg.hdr.len = 2;
send_msg.data[0] = progress;
send_msg.data[1] = 100;
send_msg.data[2] = ~app_factorymode_msg_check_sum(
(unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg,
MSG_TOTAL_LEN(&send_msg));
return ret;
}
static int app_factorymode_msg_send_32bitcode(uint32_t code) {
int ret;
send_msg.hdr.type = 0x88;
send_msg.hdr.seq = send_seq++;
send_msg.hdr.len = 4;
send_msg.data[0] = 0xf2;
*(uint32_t *)&(send_msg.data[1]) = code;
send_msg.data[4] = ~app_factorymode_msg_check_sum(
(unsigned char *)&send_msg, MSG_TOTAL_LEN(&send_msg) - 1);
ret = app_factorymode_msg_uart_send((unsigned char *)&send_msg,
MSG_TOTAL_LEN(&send_msg));
return ret;
}
static int app_factorymode_process(APP_MESSAGE_BODY *msg_body) {
if (msg_body->message_id == 1) {
app_factorymode_msg_send_ping();
}
if (msg_body->message_id == 2) {
app_factorymode_msg_send_progress(msg_body->message_Param0);
}
if (msg_body->message_id == 3) {
app_factorymode_msg_send_32bitcode(msg_body->message_Param0);
}
return 0;
}
static int app_factorymode_uart_init(void) {
struct HAL_UART_CFG_T uart_cfg;
memset(&uart_cfg, 0, sizeof(struct HAL_UART_CFG_T));
uart_cfg.parity = HAL_UART_PARITY_NONE, uart_cfg.stop = HAL_UART_STOP_BITS_1,
uart_cfg.data = HAL_UART_DATA_BITS_8,
uart_cfg.flow = HAL_UART_FLOW_CONTROL_NONE, // HAL_UART_FLOW_CONTROL_RTSCTS,
uart_cfg.tx_level = HAL_UART_FIFO_LEVEL_1_2,
uart_cfg.rx_level = HAL_UART_FIFO_LEVEL_1_4, uart_cfg.baud = 921600,
uart_cfg.dma_rx = false, uart_cfg.dma_tx = false,
uart_cfg.dma_rx_stop_on_err = false;
hal_uart_close(HAL_UART_ID_0);
hal_uart_open(HAL_UART_ID_0, &uart_cfg);
return 0;
}
static void app_factorymode_timehandler(void const *param) {
APP_MESSAGE_BLOCK msg;
msg.mod_id = APP_MODUAL_OHTER;
msg.msg_body.message_id = 1;
app_mailbox_put(&msg);
}
static uint8_t app_factorymode_indication_init(void) {
struct APP_PWL_CFG_T cfg;
memset(&cfg, 0, sizeof(struct APP_PWL_CFG_T));
app_pwl_open();
app_pwl_setup(APP_PWL_ID_0, &cfg);
app_pwl_setup(APP_PWL_ID_1, &cfg);
return 0;
}
static uint8_t
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_T status) {
struct APP_PWL_CFG_T cfg0;
struct APP_PWL_CFG_T cfg1;
APP_FACTORY_TRACE(2, "%s %d", __func__, status);
memset(&cfg0, 0, sizeof(struct APP_PWL_CFG_T));
memset(&cfg1, 0, sizeof(struct APP_PWL_CFG_T));
app_pwl_stop(APP_PWL_ID_0);
app_pwl_stop(APP_PWL_ID_1);
switch (status) {
case APP_FACTORYMODE_STATUS_INDICATION_RUNNING:
cfg0.part[0].level = 0;
cfg0.part[0].time = (300);
cfg0.part[1].level = 1;
cfg0.part[1].time = (300);
cfg0.parttotal = 2;
cfg0.startlevel = 0;
cfg0.periodic = true;
cfg1.part[0].level = 1;
cfg1.part[0].time = (300);
cfg1.part[1].level = 0;
cfg1.part[1].time = (300);
cfg1.parttotal = 2;
cfg1.startlevel = 1;
cfg1.periodic = true;
app_pwl_setup(APP_PWL_ID_0, &cfg0);
app_pwl_start(APP_PWL_ID_0);
app_pwl_setup(APP_PWL_ID_1, &cfg1);
app_pwl_start(APP_PWL_ID_1);
break;
case APP_FACTORYMODE_STATUS_INDICATION_PASS:
cfg0.part[0].level = 1;
cfg0.part[0].time = (5000);
cfg0.parttotal = 1;
cfg0.startlevel = 1;
cfg0.periodic = false;
app_pwl_setup(APP_PWL_ID_0, &cfg0);
app_pwl_start(APP_PWL_ID_0);
break;
case APP_FACTORYMODE_STATUS_INDICATION_FAILED:
cfg1.part[0].level = 1;
cfg1.part[0].time = (5000);
cfg1.parttotal = 1;
cfg1.startlevel = 1;
cfg1.periodic = false;
app_pwl_setup(APP_PWL_ID_1, &cfg1);
app_pwl_start(APP_PWL_ID_1);
break;
default:
break;
}
return 0;
}
int app_factorymode_init(uint32_t factorymode) {
uint8_t cnt = 0;
int nRet = 0;
uint32_t capval = 0x00;
struct nvrecord_env_t *nvrecord_env;
APP_FACTORY_TRACE(1, "app_factorymode_init mode:%x\n", factorymode);
osThreadSetPriority(osThreadGetId(), osPriorityRealtime);
app_factorymode_uart_init();
#ifdef __WATCHER_DOG_RESET__
app_wdt_open(60);
#endif
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_52M);
list_init();
app_os_init();
app_factorymode_indication_init();
app_battery_open();
if (app_key_open(false)) {
nRet = -1;
goto exit;
}
app_set_threadhandle(APP_MODUAL_OHTER, app_factorymode_process);
app_factory_timer =
osTimerCreate(osTimer(APP_FACTORY_TIMER), osTimerPeriodic, NULL);
osTimerStart(app_factory_timer, 300);
app_factorymode_send_progress(10);
app_bt_init();
af_open();
app_audio_open();
app_overlay_open();
nv_record_env_init();
nvrec_dev_data_open();
nv_record_env_get(&nvrecord_env);
#ifdef MEDIA_PLAYER_SUPPORT
app_play_audio_set_lang(nvrecord_env->media_language.language);
app_voice_report(APP_STATUS_INDICATION_POWERON, 0);
#endif
app_status_indication_set(APP_STATUS_INDICATION_POWERON);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_RUNNING);
if (factorymode & HAL_SW_BOOTMODE_CALIB) {
btdrv_start_bt();
app_factorymode_send_progress(20);
do {
nRet = app_factorymode_bt_xtalcalib_proc();
} while (nRet && cnt++ < APP_FACTORYMODE_RETRY_LIMITED);
if (nRet)
goto err;
osDelay(200);
app_factorymode_send_progress(30);
}
nvrec_dev_get_xtal_fcap((unsigned int *)&capval);
app_factorymode_send_code(capval);
btdrv_start_bt();
bt_drv_reg_op_key_gen_after_reset(false);
app_factorymode_send_progress(40);
BesbtInit();
osDelay(600);
nRet = app_factorymode_proc();
if (nRet)
goto err;
app_factorymode_test_key_init();
// osTimerStop(app_factory_timer);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_PASS);
// wait forever
osSignalWait(0x01, osWaitForever);
goto exit;
err:
osTimerStop(app_factory_timer);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_FAILED);
app_factorymode_send_code(0xff);
osSignalWait(0x01, osWaitForever);
exit:
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
pmu_shutdown();
return nRet;
}
int app_factorymode_calib_only(void) {
uint8_t cnt = 0;
int nRet = 0;
uint32_t capval = 0x00;
app_factorymode_uart_init();
#ifdef __WATCHER_DOG_RESET__
app_wdt_reopen(60);
#endif
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_52M);
list_init();
app_os_init();
nv_record_env_init();
nvrec_dev_data_open();
factory_section_open();
app_factorymode_indication_init();
app_set_threadhandle(APP_MODUAL_OHTER, app_factorymode_process);
app_factory_timer =
osTimerCreate(osTimer(APP_FACTORY_TIMER), osTimerPeriodic, NULL);
osTimerStart(app_factory_timer, 300);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_RUNNING);
app_factorymode_send_progress(10);
btdrv_start_bt();
osDelay(20);
app_factorymode_send_progress(20);
do {
nRet = app_factorymode_bt_xtalcalib_proc();
} while (nRet && ++cnt < APP_FACTORYMODE_RETRY_LIMITED);
if (nRet)
goto err;
nvrec_dev_get_xtal_fcap((unsigned int *)&capval);
app_factorymode_send_code(capval);
app_factorymode_send_progress(50);
osDelay(200);
app_factorymode_send_progress(80);
osDelay(100);
app_factorymode_send_progress(100);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_PASS);
osSignalWait(0x01, osWaitForever);
goto exit;
err:
osTimerStop(app_factory_timer);
app_factorymode_status_indication(APP_FACTORYMODE_STATUS_INDICATION_FAILED);
app_factorymode_send_code(0xff);
osSignalWait(0x01, osWaitForever);
exit:
app_sysfreq_req(APP_SYSFREQ_USER_APP_0, APP_SYSFREQ_32K);
pmu_shutdown();
return nRet;
}
#ifdef __USB_COMM__
// for usb
#include "hal_timer.h"
#include "hwtimer_list.h"
#include "usb_cdc.h"
#include "app_factory_cdc_comm.h"
#include "hal_usb.h"
#include "sys_api_cdc_comm.h"
static const struct USB_SERIAL_CFG_T cdc_cfg = {
.mode = USB_SERIAL_API_NONBLOCKING,
};
static void usb_serial_recv_timeout(void *param) { usb_serial_cancel_recv(); }
int app_factorymode_cdc_comm(void) {
HWTIMER_ID timer;
pmu_usb_config(PMU_USB_CONFIG_TYPE_DEVICE);
usb_serial_open(&cdc_cfg);
osDelay(500);
hwtimer_init();
timer = hwtimer_alloc(usb_serial_recv_timeout, NULL);
ASSERT(timer, "Failed to alloc usb serial recv timer");
usb_serial_flush_recv_buffer();
usb_serial_init_xfer();
af_open();
comm_loop();
return 1;
}
#endif
#endif