From accaf0f2da8c861450ce55992b2cd6cc6754c62c Mon Sep 17 00:00:00 2001 From: SnickerSun Date: Tue, 17 Dec 2024 17:40:55 +0800 Subject: [PATCH] =?utf8?q?=E7=A7=BB=E6=A4=8DGS21=20sdk=E6=BA=90=E7=A0=81U8?= =?utf8?q?=20=E4=B8=8Agnss=E5=8F=AF=E4=BB=A5=E5=B7=A5=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../config/target_config/brandy/config.py | 2 +- .../boards/brandy_evb/board_config/board_u8.h | 2 +- .../chips/brandy/porting/uart/uart_porting.c | 4 +- code/sdk/zhihui/gnss/CMakeLists.txt | 46 +- code/sdk/zhihui/gnss/driver/CMakeLists.txt | 73 ++ .../zhihui/gnss/driver/common/CMakeLists.txt | 20 + .../driver/common/controller/CMakeLists.txt | 11 + .../common/controller/tiot_controller.c | 157 +++ .../common/controller/tiot_controller.h | 152 +++ .../controller/tiot_controller_helper.h | 52 + .../common/controller/tiot_device_info.h | 78 ++ .../gnss/driver/common/fw_load/CMakeLists.txt | 46 + .../cfg_handle_priv/tiot_cfg_handle_priv.c | 170 ++++ .../cfg_handle_priv/tiot_cfg_handle_priv.h | 53 + .../driver/common/fw_load/tiot_firmware.c | 277 ++++++ .../driver/common/fw_load/tiot_firmware.h | 118 +++ .../common/fw_load/tiot_firmware_utils.h | 58 ++ .../driver/common/interface/CMakeLists.txt | 20 + .../board_internal/tiot_board.h | 61 ++ .../board_internal/tiot_board_log.h | 81 ++ .../board_internal/tiot_board_xmit.h | 64 ++ .../board_internal/tiot_board_xmit_ops.c | 62 ++ .../board_internal/tiot_board_xmit_ops.h | 87 ++ .../board_porting/gnss_board_port.h | 84 ++ .../board_porting/tiot_board_misc_port.h | 112 +++ .../board_porting/tiot_board_pin_port.h | 100 ++ .../board_porting/tiot_board_uart_port.h | 122 +++ .../board_interface/osal_porting/tiot_osal.h | 436 +++++++++ .../device_interface/tiot_service_interface.c | 248 +++++ .../device_interface/tiot_service_interface.h | 108 ++ .../tiot_service_interface_ext.h | 98 ++ .../gnss/driver/common/pm/CMakeLists.txt | 18 + .../common/pm/pm_default/CMakeLists.txt | 7 + .../common/pm/pm_default/tiot_pm_default.c | 288 ++++++ .../common/pm/pm_default/tiot_pm_default.h | 110 +++ .../driver/common/pm/pm_slave/CMakeLists.txt | 7 + .../driver/common/pm/pm_slave/tiot_pm_slave.c | 139 +++ .../driver/common/pm/pm_slave/tiot_pm_slave.h | 95 ++ .../zhihui/gnss/driver/common/pm/tiot_pm.c | 149 +++ .../zhihui/gnss/driver/common/pm/tiot_pm.h | 182 ++++ .../gnss/driver/common/pm/tiot_pm_wakelock.c | 72 ++ .../gnss/driver/common/pm/tiot_pm_wakelock.h | 74 ++ .../common/sys_msg_handler/CMakeLists.txt | 14 + .../sys_msg_handler/tiot_sys_msg_handle.c | 24 + .../sys_msg_handler/tiot_sys_msg_handle.h | 30 + .../tiot_sys_msg_slave_handle.c | 30 + .../sys_msg_handler/tiot_sys_msg_types.h | 139 +++ .../driver/common/transfer/CMakeLists.txt | 21 + .../packet_handle/tiot_packet/CMakeLists.txt | 8 + .../packet_handle/tiot_packet/tiot_packet.c | 919 ++++++++++++++++++ .../packet_handle/tiot_packet/tiot_packet.h | 205 ++++ .../tiot_packet/tiot_packet_manager.c | 90 ++ .../tiot_packet/tiot_packet_manager.h | 213 ++++ .../gnss/driver/common/transfer/tiot_xfer.c | 493 ++++++++++ .../gnss/driver/common/transfer/tiot_xfer.h | 248 +++++ .../driver/common/transfer/tiot_xfer_utils.c | 84 ++ .../driver/common/transfer/tiot_xfer_utils.h | 42 + .../gnss/driver/common/utils/CMakeLists.txt | 15 + .../common/utils/circ_buf/tiot_circ_buf.h | 207 ++++ .../common/utils/circ_queue/CMakeLists.txt | 11 + .../common/utils/circ_queue/tiot_circ_queue.c | 124 +++ .../common/utils/circ_queue/tiot_circ_queue.h | 105 ++ .../common/utils/fileops/CMakeLists.txt | 11 + .../common/utils/fileops/tiot_fileops.c | 93 ++ .../common/utils/fileops/tiot_fileops.h | 90 ++ .../gnss/driver/common/utils/list/tiot_list.h | 182 ++++ .../driver/common/utils/misc/CMakeLists.txt | 11 + .../gnss/driver/common/utils/misc/tiot_misc.c | 55 ++ .../gnss/driver/common/utils/misc/tiot_misc.h | 46 + .../gnss/driver/common/utils/tiot_types.h | 66 ++ .../gnss/driver/device/gnss/CMakeLists.txt | 31 + .../zhihui/gnss/driver/device/gnss/Makefile | 16 + .../driver/device/gnss/firmware/gnss_cfg.bin | 905 +++++++++++++++++ .../device/gnss/firmware/gnss_fw_file_array.c | 32 + .../device/gnss/firmware/gnss_fw_file_array.h | 29 + .../driver/device/gnss/gnss_device_info.c | 157 +++ .../driver/device/gnss/gnss_device_info.h | 42 + .../gnss/driver/device/gnss/gnss_service.c | 434 +++++++++ .../gnss/driver/device/gnss/gnss_service.h | 54 + .../driver/product_porting/CMakeLists.txt | 12 + .../product_porting/porting/CMakeLists.txt | 19 + .../product_porting/porting/gnss_board_port.c | 85 ++ .../porting/tiot_board_log_port.h | 46 + .../porting/tiot_board_misc_port.c | 45 + .../porting/tiot_board_pin_port.c | 112 +++ .../porting/tiot_board_uart_port.c | 193 ++++ .../gnss/driver/product_porting/readme.txt | 2 + .../driver/product_porting/tiot_autoconfig.h | 27 + .../driver/product_porting/tiot_defconfig | 101 ++ code/sdk/zhihui/gnss/{ => inc}/gnss_ctl.h | 0 code/sdk/zhihui/gnss/{ => inc}/uart_gnss.h | 0 .../gnss/sample/agnss_sample/CMakeLists.txt | 41 + .../gnss/sample/agnss_sample/agnss_encode.c | 252 +++++ .../gnss/sample/agnss_sample/agnss_encode.h | 15 + .../gnss/sample/agnss_sample/agnss_sample.c | 193 ++++ .../gnss/sample/agnss_sample/agnss_sample.h | 12 + .../gnss/sample/agnss_sample/gnss_datatypes.h | 76 ++ .../gnss/sample/gnss_sample/CMakeLists.txt | 41 + .../gnss/sample/gnss_sample/gnss_sample.c | 228 +++++ .../gnss/sample/gnss_sample/gnss_sample.h | 12 + .../zhihui/gnss/{ => src}/gnss_config_array.c | 0 code/sdk/zhihui/gnss/{ => src}/gnss_ctl.c | 0 code/sdk/zhihui/gnss/{ => src}/uart_gnss.c | 27 +- 103 files changed, 10935 insertions(+), 23 deletions(-) create mode 100644 code/sdk/zhihui/gnss/driver/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/controller/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/controller/tiot_controller.c create mode 100644 code/sdk/zhihui/gnss/driver/common/controller/tiot_controller.h create mode 100644 code/sdk/zhihui/gnss/driver/common/controller/tiot_controller_helper.h create mode 100644 code/sdk/zhihui/gnss/driver/common/controller/tiot_device_info.h create mode 100644 code/sdk/zhihui/gnss/driver/common/fw_load/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.c create mode 100644 code/sdk/zhihui/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.h create mode 100644 code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware.c create mode 100644 code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware.h create mode 100644 code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware_utils.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_log.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.c create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/gnss_board_port.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_misc_port.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_uart_port.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/board_interface/osal_porting/tiot_osal.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface.c create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface.h create mode 100644 code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface_ext.h create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/pm_default/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/pm_default/tiot_pm_default.c create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/pm_default/tiot_pm_default.h create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/pm_slave/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/pm_slave/tiot_pm_slave.c create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/pm_slave/tiot_pm_slave.h create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/tiot_pm.c create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/tiot_pm.h create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/tiot_pm_wakelock.c create mode 100644 code/sdk/zhihui/gnss/driver/common/pm/tiot_pm_wakelock.h create mode 100644 code/sdk/zhihui/gnss/driver/common/sys_msg_handler/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.c create mode 100644 code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.h create mode 100644 code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_slave_handle.c create mode 100644 code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_types.h create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.c create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.h create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.c create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.h create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer.c create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer.h create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer_utils.c create mode 100644 code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer_utils.h create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/circ_buf/tiot_circ_buf.h create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/circ_queue/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/circ_queue/tiot_circ_queue.c create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/circ_queue/tiot_circ_queue.h create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/fileops/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/fileops/tiot_fileops.c create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/fileops/tiot_fileops.h create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/list/tiot_list.h create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/misc/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/misc/tiot_misc.c create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/misc/tiot_misc.h create mode 100644 code/sdk/zhihui/gnss/driver/common/utils/tiot_types.h create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/Makefile create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_cfg.bin create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_fw_file_array.c create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_fw_file_array.h create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/gnss_device_info.c create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/gnss_device_info.h create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/gnss_service.c create mode 100644 code/sdk/zhihui/gnss/driver/device/gnss/gnss_service.h create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/porting/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/porting/gnss_board_port.c create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_log_port.h create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_misc_port.c create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_pin_port.c create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_uart_port.c create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/readme.txt create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/tiot_autoconfig.h create mode 100644 code/sdk/zhihui/gnss/driver/product_porting/tiot_defconfig rename code/sdk/zhihui/gnss/{ => inc}/gnss_ctl.h (100%) rename code/sdk/zhihui/gnss/{ => inc}/uart_gnss.h (100%) create mode 100644 code/sdk/zhihui/gnss/sample/agnss_sample/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/sample/agnss_sample/agnss_encode.c create mode 100644 code/sdk/zhihui/gnss/sample/agnss_sample/agnss_encode.h create mode 100644 code/sdk/zhihui/gnss/sample/agnss_sample/agnss_sample.c create mode 100644 code/sdk/zhihui/gnss/sample/agnss_sample/agnss_sample.h create mode 100644 code/sdk/zhihui/gnss/sample/agnss_sample/gnss_datatypes.h create mode 100644 code/sdk/zhihui/gnss/sample/gnss_sample/CMakeLists.txt create mode 100644 code/sdk/zhihui/gnss/sample/gnss_sample/gnss_sample.c create mode 100644 code/sdk/zhihui/gnss/sample/gnss_sample/gnss_sample.h rename code/sdk/zhihui/gnss/{ => src}/gnss_config_array.c (100%) rename code/sdk/zhihui/gnss/{ => src}/gnss_ctl.c (100%) rename code/sdk/zhihui/gnss/{ => src}/uart_gnss.c (91%) diff --git a/code/sdk/build/config/target_config/brandy/config.py b/code/sdk/build/config/target_config/brandy/config.py index 151b626d5..d63fbb390 100644 --- a/code/sdk/build/config/target_config/brandy/config.py +++ b/code/sdk/build/config/target_config/brandy/config.py @@ -373,7 +373,7 @@ target = { 'NANDFLASH_DS35X' ], #添加自定义应用 - 'ram_component': ['custom_cmd_service','gnss','custom_utils'] + 'ram_component': ['custom_cmd_service','gnss','gnss_sample','custom_utils'] }, 'brandy-native-js-u8-r': { 'base_target_name': 'brandy-native-js-r', diff --git a/code/sdk/drivers/boards/brandy_evb/board_config/board_u8.h b/code/sdk/drivers/boards/brandy_evb/board_config/board_u8.h index e7dbd2ea1..19195ce4e 100644 --- a/code/sdk/drivers/boards/brandy_evb/board_config/board_u8.h +++ b/code/sdk/drivers/boards/brandy_evb/board_config/board_u8.h @@ -266,7 +266,7 @@ const hal_gpio_config_t g_gpio_function_config[PIN_MAX_NUMBER] = { /***GPS Power*/ { S_AGPIO_L23, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL }, //GPS_BAT_ON { S_AGPIO_L28, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL }, //GPS_1V8 - { S_AGPIO_L30, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_HIGH, 0, NULL }, //S_AGPIO_L30 + { S_AGPIO_L30, HAL_GPIO_DIRECTION_OUTPUT, HAL_GPIO_LEVEL_LOW, 0, NULL }, //S_AGPIO_L30 // S_AGPIO_L17 HX3507_INT // { S_AGPIO_L17, HAL_GPIO_DIRECTION_INPUT, HAL_GPIO_LEVEL_LOW, 0, NULL }, diff --git a/code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c b/code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c index 543209b5a..62d53701a 100644 --- a/code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c +++ b/code/sdk/drivers/chips/brandy/porting/uart/uart_porting.c @@ -265,7 +265,7 @@ void log_factory_at_callback(const void *buffer, uint16_t length, bool remaining #if defined(GNSS_UART1) && defined(SUPPORT_GNSS_SERVER) if (is_gnss_on()) { - gnss_receive_handler((uint8_t *)buffer,length); + // gnss_receive_handler((uint8_t *)buffer,length); hal_uart_clear_pending(UART_BUS_1); }else{ #endif @@ -341,7 +341,7 @@ static void at_cmd_uart_rx_callback(const void *buf, uint16_t buf_len, bool rema at_cmd_msg_receive_handler((uint8_t *)buf, buf_len); #endif #if defined(GNSS_UART0) && defined(SUPPORT_GNSS_SERVER) - gnss_receive_handler((uint8_t *)buf,buf_len); + // gnss_receive_handler((uint8_t *)buf,buf_len); #endif hal_uart_clear_pending(SW_DEBUG_UART_BUS); } diff --git a/code/sdk/zhihui/gnss/CMakeLists.txt b/code/sdk/zhihui/gnss/CMakeLists.txt index 679cc2b87..9ae314493 100644 --- a/code/sdk/zhihui/gnss/CMakeLists.txt +++ b/code/sdk/zhihui/gnss/CMakeLists.txt @@ -2,20 +2,45 @@ # @brief cmake file # Copyright (c) @CompanyNameMagicTag 2023-2023. All rights reserved. #=============================================================================== + +add_subdirectory(driver) + set(COMPONENT_NAME "gnss") -set(SOURCES ${SOURCES} - ${CMAKE_CURRENT_SOURCE_DIR}/gnss_config_array.c - ${CMAKE_CURRENT_SOURCE_DIR}/uart_gnss.c - ${CMAKE_CURRENT_SOURCE_DIR}/gnss_ctl.c +# include(${CMAKE_CURRENT_SOURCE_DIR}/driver/CMakeLists.txt) +set(SOURCES + # ${CMAKE_CURRENT_SOURCE_DIR}/gnss_config_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/uart_gnss.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/gnss_ctl.c + ${TIOT_SRC_LIST} ) set(PUBLIC_HEADER -${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/inc ) set(PUBLIC_DEFINES -SUPPORT_GNSS_SERVER + SUPPORT_GNSS_SERVER + CONFIG_DEV_GNSS=1 + CONFIG_GNSS_DEV_NUM=1 + CONFIG_GNSS_WAKEUP_TYPE_UART=1 + CONFIG_GNSS_TCXO_FREQ_26M=1 + CONFIG_GNSS_UART_BAUDRATE=115200 + CONFIG_FILE_BY_ARRAY=1 + CONFIG_FIRMWARE_CFG_HANDLE_PRIV=1 + CONFIG_FIRMWARE_FILE_READ_BUF_LEN=1029 + CONFIG_PM_WAKEUP_BY_UART=1 + CONFIG_PM_MANAGE_LOWPOWER=1 + CONFIG_XMIT_WITH_UART=1 + CONFIG_UART_RX_MODE_BUFFED=1 + CONFIG_XFER_PACKET_TIOT=1 + CONFIG_XFER_DEFAULT_RX_BUFF=1 + CONFIG_XFER_RX_BUFF_SIZE=512 + CONFIG_OSAL_DEFINED=1 + CONFIG_LIBBOUNDSCHECK_IMPLEMENTED=1 + CONFIG_BOARD_DYNAMIC_ALLOC=1 + CONFIG_GNSS_PACKET_BUFF_MAX=10000 ) -set(PRIVATE_HEADER +set(PRIVATE_HEADER + ${TIOT_HEADER_LIST} ) set(PRIVATE_DEFINES @@ -28,6 +53,7 @@ set(COMPONENT_PUBLIC_CCFLAGS set(COMPONENT_CCFLAGS -Wno-incompatible-function-pointer-types -Wno-unused-function + # ${TIOT_CFLAGS} ) set(WHOLE_LINK @@ -38,5 +64,11 @@ set(MAIN_COMPONENT false ) +message("TIOT_HEADER_LIST" ${TIOT_HEADER_LIST}) +message("TIOT_SRC_LIST" ${TIOT_SRC_LIST}) + build_component() + + +add_subdirectory(sample/gnss_sample) diff --git a/code/sdk/zhihui/gnss/driver/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/CMakeLists.txt new file mode 100644 index 000000000..2db3bc64e --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/CMakeLists.txt @@ -0,0 +1,73 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +# 此处为TIoT驱动顶层CMake + +# CMake读取Kconfig配置 +# function(KCONFIG_GET_PARAMS KCONFIG_PATH) +# file(STRINGS ${KCONFIG_PATH} TIOT_CONFIG_LIST ENCODING "UTF-8") + +# foreach (CONFIG ${TIOT_CONFIG_LIST}) +# # CONFIG maybe: CONFIG_CC_STACKPROTECTOR_STRONG=y + +# # The first: variable name +# string(REGEX MATCH "[^=]+" CONFIG_VAR_NAME ${CONFIG}) + +# # The second: variable value +# string(REGEX MATCH "=(.+$)" CONFIG_VAR_VAL ${CONFIG}) +# set(CONFIG_VAR_VAL ${CMAKE_MATCH_1}) +# if(CONFIG_VAR_VAL MATCHES "^y$") +# set(${CONFIG_VAR_NAME} ${CONFIG_VAR_VAL} PARENT_SCOPE) +# endif() +# endforeach() +# endfunction() + +# macro(add_subdirectory_if_exist _path) +# if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_path}/CMakeLists.txt) +# add_subdirectory(${_path}) +# endif() +# endmacro() + +# macro(list_sub_dirs result curdir) +# file(GLOB children RELATIVE ${curdir} ${curdir}/*) +# set(dirlist "") +# foreach(child ${children}) +# if(IS_DIRECTORY ${curdir}/${child}) +# list(APPEND dirlist ${child}) +# endif() +# endforeach() +# set(${result} ${dirlist}) +# endmacro() + +if(NOT DEFINED TIOT_COMMON_DIR) + set(TIOT_COMMON_DIR "${CMAKE_CURRENT_SOURCE_DIR}/common") +endif() + +if(NOT DEFINED TIOT_PORTING_DIR) + set(TIOT_PORTING_DIR "${CMAKE_CURRENT_SOURCE_DIR}/product_porting") +endif() + +if(NOT DEFINED TIOT_PORTING_CONFIG_DIR) + set(TIOT_PORTING_CONFIG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/product_porting") +endif() + +# if(NOT DEFINED TIOT_DEVICE_LIST) +# list_sub_dirs(TIOT_DEVICE_LIST ${CMAKE_CURRENT_SOURCE_DIR}/device) +# endif() + +# 初始化CMake全局变量 +# set(TIOT_CFLAGS " -i ${TIOT_PORTING_CONFIG_DIR}/tiot_autoconfig.h" CACHE INTERNAL "tiot c flags" FORCE) +# all header and files listed here +set(TIOT_HEADER_LIST "${TIOT_PORTING_CONFIG_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "" CACHE INTERNAL "tiot src list" FORCE) + +# 获取Kconfig配置 +KCONFIG_GET_PARAMS(${TIOT_PORTING_CONFIG_DIR}/tiot_defconfig) + +add_subdirectory(device/gnss) + +# common +add_subdirectory("${TIOT_COMMON_DIR}" common.out) +# porting +add_subdirectory("${TIOT_PORTING_DIR}" porting.out) diff --git a/code/sdk/zhihui/gnss/driver/common/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/CMakeLists.txt new file mode 100644 index 000000000..a9f7cd340 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/CMakeLists.txt @@ -0,0 +1,20 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +add_subdirectory(controller) +add_subdirectory(fw_load) +add_subdirectory(interface) +add_subdirectory_if_exist(libboundscheck) +add_subdirectory(pm) +add_subdirectory(transfer) +add_subdirectory(sys_msg_handler) +add_subdirectory(utils) + +if(DEFINED CONFIG_COMMON_SUPPORT_DEBUG) +add_subdirectory_if_exist(debug) +endif() + +if(DEFINED CONFIG_COMMON_SUPPORT_DFR) +add_subdirectory_if_exist(dfr) +endif() diff --git a/code/sdk/zhihui/gnss/driver/common/controller/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/controller/CMakeLists.txt new file mode 100644 index 000000000..89ea3c576 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/controller/CMakeLists.txt @@ -0,0 +1,11 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +set( + tiot_controller_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_controller.c +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_controller_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller.c b/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller.c new file mode 100644 index 000000000..3fe85a052 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller.c @@ -0,0 +1,157 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT device controller. \n + * + * History: \n + * 2023-03-17, Create file. \n + */ + +#include +#include "tiot_device_info.h" +#include "tiot_controller.h" +#include "tiot_board_log.h" + +#define CTRL_OPEN_COUNT_MAX 0xFFFFFFFFU + +int32_t tiot_controller_init(tiot_controller *ctrl, tiot_controller_info *info) +{ + int32_t ret; + tiot_board_info *board_info = info->board_info; + const tiot_device_info *device_info = info->dev_info; + + if ((ctrl == NULL) || (ctrl->state == TIOT_CONTROLLER_INIT)) { + return -1; + } + + /***** 软件初始化 *****/ + /* 初始化open状态互斥锁. */ + ret = osal_mutex_init(&ctrl->open_mutex); + if (ret != 0) { + goto mutex_init_fail; + } + + /* 注册:1) PM状态机,如为NULL则使用默认状态机. + 2)板级PM管脚信息,依据产品不同而不同. */ + ret = tiot_pm_init(&ctrl->pm, board_info->hw_info.pm_info, + device_info->pm_event_map, device_info->pm_event_map_size); + if (ret != 0) { + goto pm_init_fail; + } + + /* 注册:1)固件加载回调,加载前 + 加载后,用于注册不同加载协议或设置波特率等,依据芯片不同而不同. */ + ret = tiot_firmware_init(&ctrl->firmware, &device_info->exec_cbs); + if (ret != 0) { + goto fw_init_fail; + } + + /* 注册:1) 接收回调 */ + ret = tiot_xfer_init(&ctrl->transfer, board_info->hw_info.xmit_id, &device_info->xfer_info); + if (ret != 0) { + goto xfer_init_fail; + } + + /* device info必须为静态分配变量. */ + ctrl->dev_info = device_info; + ctrl->state = TIOT_CONTROLLER_INIT; + ctrl->dev_cus = (uintptr_t)info->dev_cus; + + return 0; + +xfer_init_fail: + tiot_xfer_deinit(&ctrl->transfer); + memset_s((void *)&ctrl->transfer, sizeof(tiot_xfer_manager), 0, sizeof(tiot_xfer_manager)); +fw_init_fail: + memset_s((void *)&ctrl->firmware, sizeof(tiot_fw), 0, sizeof(tiot_fw)); +pm_init_fail: + memset_s((void *)&ctrl->pm, sizeof(tiot_pm), 0, sizeof(tiot_pm)); + osal_mutex_destroy(&ctrl->open_mutex); +mutex_init_fail: + return ret; +} + +int32_t tiot_controller_open(tiot_controller *ctrl, void *param) +{ + int32_t ret = 0; + if (ctrl == NULL) { + tiot_print_dbg("[TIoT]device is null.\n"); + return -1; + } + osal_mutex_lock(&ctrl->open_mutex); + if (ctrl->state == TIOT_CONTROLLER_UNINIT) { + tiot_print_err("[TIoT]dev state wrong %d.\r\n", ctrl->state); + ret = -1; + goto out; + } + if (ctrl->open_count == CTRL_OPEN_COUNT_MAX) { + tiot_print_err("[TIoT]reach max open count.\r\n"); + ret = -1; + goto out; + } + ctrl->open_count++; + if (ctrl->state == TIOT_CONTROLLER_OPEN) { + /* 重复调用open仅添加计数. */ + goto out; + } + ctrl->state = TIOT_CONTROLLER_OPENING; /* 中间状态,受mutex锁保护,不需要在open内判断. */ + if (ctrl->ops.open(ctrl, param) != 0) { + ctrl->open_count--; + ctrl->state = TIOT_CONTROLLER_INIT; + ret = -1; + goto out; + } + ctrl->state = TIOT_CONTROLLER_OPEN; +out: + osal_mutex_unlock(&ctrl->open_mutex); + return ret; +} + +bool tiot_controller_check_opened(tiot_controller *ctrl) +{ + bool ret = true; + if (ctrl == NULL) { + tiot_print_dbg("[TIoT]device is null.\n"); + return false; + } + osal_mutex_lock(&ctrl->open_mutex); + if (ctrl->state != TIOT_CONTROLLER_OPEN) { + tiot_print_dbg("[TIoT]device not opened.\n"); + ret = false; + } + osal_mutex_unlock(&ctrl->open_mutex); + return ret; +} + +void tiot_controller_close(tiot_controller *ctrl) +{ + if (ctrl == NULL) { + tiot_print_dbg("[TIoT]device is null.\n"); + return; + } + osal_mutex_lock(&ctrl->open_mutex); + if ((ctrl->state != TIOT_CONTROLLER_OPEN) && (ctrl->state != TIOT_CONTROLLER_OPENING)) { + tiot_print_dbg("[TIoT]device is not opening or not opened.\n"); + osal_mutex_unlock(&ctrl->open_mutex); + return; + } + /* 打开状态且open_count >=1时,减少open_count计数; 当open_count减少后变为0时,实际调用close操作. */ + ctrl->open_count--; + if (ctrl->open_count == 0) { + ctrl->ops.close(ctrl); + ctrl->state = TIOT_CONTROLLER_INIT; + } + osal_mutex_unlock(&ctrl->open_mutex); +} + +void tiot_controller_deinit(tiot_controller *ctrl) +{ + if ((ctrl == NULL) || (ctrl->state == TIOT_CONTROLLER_UNINIT)) { + return; + } + + tiot_xfer_deinit(&ctrl->transfer); + tiot_pm_deinit(&ctrl->pm); + osal_mutex_destroy(&ctrl->open_mutex); + (void)memset_s((void *)ctrl, sizeof(tiot_controller), 0, sizeof(tiot_controller)); + ctrl->state = TIOT_CONTROLLER_UNINIT; +} diff --git a/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller.h b/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller.h new file mode 100644 index 000000000..64a0dd3cb --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller.h @@ -0,0 +1,152 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT device controller header. \n + * + * History: \n + * 2023-03-17, Create file. \n + */ + +#ifndef TIOT_CONTROLLER_H +#define TIOT_CONTROLLER_H + +#ifndef __KERNEL__ +#include +#endif +#include "tiot_board.h" +#include "tiot_pm.h" +#include "tiot_firmware.h" +#include "tiot_xfer.h" +#include "tiot_device_info.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_controller Controller + * @ingroup tiot_common + * @{ + */ + +/** + * @brief TIoT controller state. + */ +typedef enum { + TIOT_CONTROLLER_UNINIT, + TIOT_CONTROLLER_INIT, + TIOT_CONTROLLER_OPENING, + TIOT_CONTROLLER_OPEN, +} tiot_controller_state; + +/** + * @brief TIoT controller info provided outside. + */ +typedef struct { + tiot_board_info *board_info; /*!< Board infomations. */ + const tiot_device_info *dev_info; /*!< Reserved device info, must be allocated staticly. */ + const tiot_dev_customize *dev_cus; /*!< Reserved device customize. */ +} tiot_controller_info; + +struct _tiot_controller; + +/** + * @brief TIoT controller ops. + */ +typedef struct { + int32_t (* open)(struct _tiot_controller *ctrl, void *param); + void (* close)(struct _tiot_controller *ctrl); + int32_t (* write)(struct _tiot_controller *ctrl, const uint8_t *data, + uint32_t len, const tiot_xfer_tx_param *param); + int32_t (* read)(struct _tiot_controller *ctrl, uint8_t *buff, uint32_t buff_len, const tiot_xfer_rx_param *param); + int32_t (* pm_ctrl)(struct _tiot_controller *ctrl, uint8_t cmd); +} tiot_controller_ops; + +/** + * @brief TIoT device controller. + */ +typedef struct _tiot_controller { + uint32_t state; /*!< Current state. */ + tiot_pm pm; /*!< Power Manangement module. */ + tiot_fw firmware; /*!< Firmware module. */ + tiot_xfer_manager transfer; /*!< Transfer manager modele. */ + const tiot_device_info *dev_info; /*!< Reserved device info, must be allocated staticly. */ + tiot_controller_ops ops; /*!< Controller ops, open, close, write, read. */ + volatile uint32_t open_count; /*!< open count. */ + osal_mutex open_mutex; /*!< open state mutex. */ + uintptr_t dev_cus; /*!< device customize. */ +} tiot_controller; + +/** + * @brief TIoT find controller by pin from controllers. + * @param [in] ctrls TIoT controller instances array. + * @param [in] ctrl_num TIoT controller instances num. + * @param [in] pin Pin number. + * @param [in] pin_type Pin type. + * @return if found controller, return controller pointer, else return NULL. + */ +static inline tiot_controller *tiot_find_controller_by_pin(tiot_controller *ctrls, uint8_t ctrl_num, + uint32_t pin, uint32_t pin_type) +{ + const uint32_t *pm_info; + uint8_t i; + for (i = 0; i < ctrl_num; i++) { + pm_info = ctrls[i].pm.pm_info; + if (pm_info[pin_type] == pin) { + return &ctrls[i]; + } + } + return NULL; +} + +/** + * @brief TIoT controller init. + * @param [in] ctrl TIoT controller instance. + * @param [in] info TIoT controller information. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_controller_init(tiot_controller *ctrl, tiot_controller_info *info); + +/** + * @brief TIoT controller open, if already opened, add open count only. + * @param [in] ctrl TIoT controller instance. + * @param [in] param TIoT controller open param. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_controller_open(tiot_controller *ctrl, void *param); + +/** + * @brief TIoT controller check opened or not, must be used after init. + * @param [in] ctrl TIoT controller instance. + * @return true if Opened; + * false if not opened. + */ +bool tiot_controller_check_opened(tiot_controller *ctrl); + +/** + * @brief TIoT controller close, if opened multiple times, only remove open count. + * @param [in] ctrl TIoT controller instance. + */ +void tiot_controller_close(tiot_controller *ctrl); + +/** + * @brief TIoT controller deinit. + * @param [in] ctrl TIoT controller instance. + */ +void tiot_controller_deinit(tiot_controller *ctrl); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller_helper.h b/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller_helper.h new file mode 100644 index 000000000..e0e02e1a1 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/controller/tiot_controller_helper.h @@ -0,0 +1,52 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: TIoT Controllrt helper. \n + * + * History: \n + * 2024-03-05, Create file. \n + */ +#ifndef TIOT_CONTROLLER_HELPER_H +#define TIOT_CONTROLLER_HELPER_H + +#include "tiot_board_pin_port.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_controller_helper Controller Helper + * @ingroup tiot_common_controllrt + * @{ + */ + +static inline void tiot_pin_int_request(uint32_t pin, tiot_pin_int_callback cb) +{ + if (pin != TIOT_PIN_NONE) { + (void)tiot_board_pin_register_int_callback(pin, cb); + (void)tiot_board_pin_enable_int(pin, TIOT_PIN_INT_ENABLE); + } +} + +static inline void tiot_pin_int_release(uint32_t pin) +{ + if (pin != TIOT_PIN_NONE) { + (void)tiot_board_pin_enable_int(pin, TIOT_PIN_INT_DISABLE); + (void)tiot_board_pin_register_int_callback(pin, NULL); + } +} + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/controller/tiot_device_info.h b/code/sdk/zhihui/gnss/driver/common/controller/tiot_device_info.h new file mode 100644 index 000000000..cd4f54f88 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/controller/tiot_device_info.h @@ -0,0 +1,78 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Device info header. \n + * + * History: \n + * 2023-03-25, Create file. \n + */ +#ifndef TIOT_DEVICE_INFO_H +#define TIOT_DEVICE_INFO_H + +#include "tiot_pm.h" +#include "tiot_firmware.h" +#include "tiot_xfer.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_device Device Interface + * @ingroup tiot_common_interface + * @{ + */ + +/** + * @brief Device common timing specs. + */ +typedef struct { + const uint32_t power_on_wait_ms; /*!< Before power on wait time. */ + const uint32_t boot_time_ms; /*!< Boot wait time. */ + const uint32_t init_time_ms; /*!< Init time wait time. */ + const uint32_t wakeup_pulse_ms; /*!< Wakeup pin pulse time. */ + const uint32_t wakeup_wait_ms; /*!< Wakeup wait time. */ + const uint32_t baud_change_wait_us; /*!< Baudrate change wait time. */ +} tiot_device_timings; + +struct _tiot_controller; + +/** + * @brief Device infomations to be registed in driver. + */ +typedef struct { + /*!< Power management event map, set NULL if use default event map. */ + tiot_pm_event_entry *pm_event_map; + uint8_t pm_event_map_size; + /*!< Firmware callback called before and after commands execute. */ + const tiot_fw_ops exec_cbs; + + /*!< Transfer */ + tiot_xfer_device_info xfer_info; + + /*!< Tiot packet sys msg handle. */ + void (*pkt_sys_msg_handle)(struct _tiot_controller *ctrl, uint8_t code); + + tiot_device_timings timings; +} tiot_device_info; + +typedef struct { + uintptr_t start_data; + uintptr_t curr_data; + uintptr_t end_data; + uint32_t unit_data_len; +} tiot_dev_customize; + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/fw_load/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/fw_load/CMakeLists.txt new file mode 100644 index 000000000..4f6793eed --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/fw_load/CMakeLists.txt @@ -0,0 +1,46 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +set( + tiot_firmware_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_firmware.c +) + +set( + tiot_firmware_header_list + ${CMAKE_CURRENT_SOURCE_DIR} +) + +if(CONFIG_FIRMWARE_CFG_HANDLE_PRIV) +list(APPEND + tiot_firmware_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_priv/tiot_cfg_handle_priv.c) + +list(APPEND + tiot_firmware_header_list + ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_priv) +endif() + +if(CONFIG_FIRMWARE_CFG_HANDLE_XCI) +list(APPEND + tiot_firmware_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_xci/tiot_cfg_handle_xci.c) + +list(APPEND + tiot_firmware_header_list + ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_xci) +endif() + +if(CONFIG_FIRMWARE_CFG_HANDLE_HIBURN) +list(APPEND + tiot_firmware_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_hiburn/tiot_cfg_handle_hiburn.c) + +list(APPEND + tiot_firmware_header_list + ${CMAKE_CURRENT_SOURCE_DIR}/cfg_handle_hiburn) +endif() + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${tiot_firmware_header_list}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_firmware_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.c b/code/sdk/zhihui/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.c new file mode 100644 index 000000000..b69bf1d85 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.c @@ -0,0 +1,170 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-12-05, Create file. \n + */ + +#include "tiot_misc.h" +#include "tiot_firmware.h" +#include "tiot_firmware_utils.h" +#include "tiot_board_log.h" +#include "tiot_cfg_handle_priv.h" + +#define TIOT_FW_FILE_STA 0x43 +#define TIOT_FW_FILE_ACK 0x06 +#define TIOT_FW_FILE_NAK 0x15 +#define TIOT_FW_PRIV_CMD_OK 'G' + +#define TIOT_FW_PRIV_ACK_MAX 128 +#define TIOT_FW_CUS_STR_LEN 12 + +typedef enum { + TIOT_FW_EXTCMD_ACK = 0x0, + TIOT_FW_EXTCMD_ACK_EXT = 0x1, + TIOT_FW_EXTCMD_CUSTOMIZE = 0x2, + TIOT_FW_EXTCMD_NUM +} tiot_fw_ext_cmd_priv; + +typedef int32_t (*priv_ext_cmd_handle_func)(tiot_fw *fw, const uint8_t *cmd, uint16_t len); +typedef int32_t (*pre_priv_ext_cmd_handle_func)(tiot_fw *fw, uint8_t *cmd, uint16_t *len); + +static int32_t tiot_fw_ack_handle_priv(tiot_fw *fw, const uint8_t *cmd, uint16_t len); +static int32_t tiot_fw_ack_ext_handle_priv(tiot_fw *fw, const uint8_t *cmd, uint16_t len); +static int32_t tiot_fw_customize_ext_cmd_handle_priv(tiot_fw *fw, uint8_t *cmd, uint16_t *len); + +static const priv_ext_cmd_handle_func tiot_fw_priv_ext_cmd_table[TIOT_FW_EXTCMD_NUM] = { + tiot_fw_ack_handle_priv, + tiot_fw_ack_ext_handle_priv, + tiot_fw_ack_handle_priv, +}; + +static const pre_priv_ext_cmd_handle_func tiot_fw_pre_priv_ext_cmd_table[TIOT_FW_EXTCMD_NUM] = { + NULL, + NULL, + tiot_fw_customize_ext_cmd_handle_priv, +}; + +static int32_t tiot_fw_customize_para_replace(uint8_t *cmd, uint16_t *len, uint32_t cus_data) +{ + char *tmp = NULL; + size_t str_len; + char cus_data_str[TIOT_FW_CUS_STR_LEN] = { 0 }; + + if (*len == 0 || (cmd[*len - 1] != ' ')) { + tiot_print_err("[TIoT:priv] customize cmd not space-terminated.\r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + + if (tiot_num_to_hex(cus_data, cus_data_str, TIOT_FW_CUS_STR_LEN) != TIOT_FW_LOAD_RET_OK) { + tiot_print_err("[TIoT:priv] tiot_num_to_hex failed.\r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + + // cmd如下格式"WRITEM 4 0x3ff08 0x1e8480 "; tmp指向子串"0x1e8480"的起始地址. + cmd[*len - 1] = '\0'; + tmp = strrchr((const char *)cmd, ' '); + if (tmp == NULL) { + tiot_print_err("[TIoT:priv] customize cmd string does not have space.\r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + tmp++; + + // 把tmp指向的字符串替换为tiot驱动配置的参数 + int ret = strcpy_s((char *)tmp, strlen(tmp) + 1, cus_data_str); + if (ret != 0) { + tiot_print_err("[TIoT:priv] customize para replace failed. \r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + + // cmd最后的'\0'替换为空格 + str_len = strlen((const char *)cmd); + cmd[str_len] = ' '; + + // 更新cmd的长度 + *len = str_len + 1; + return TIOT_FW_LOAD_RET_OK; +} + +static int32_t tiot_fw_ack_handle_priv(tiot_fw *fw, const uint8_t *cmd, uint16_t len) +{ + int32_t ret = 0; + uint8_t ack = 0; + const uint8_t quit_cmd[] = "QUIT "; + // QUIT命令特殊处理 + if ((len == (sizeof(quit_cmd) - 1)) && (memcmp(quit_cmd, cmd, len) == 0)) { + return 0; + } + ret = tiot_firmware_read(fw, &ack, sizeof(uint8_t)); + if (ret != sizeof(uint8_t)) { + return -1; + } + + tiot_print_dbg("[TIoT:priv]ack 0x%x\r\n", ack); + if ((ack == TIOT_FW_PRIV_CMD_OK) || (ack == TIOT_FW_FILE_STA) || (ack == TIOT_FW_FILE_ACK)) { + return TIOT_FW_LOAD_RET_OK; + } else if (ack == TIOT_FW_FILE_NAK) { + return TIOT_FW_LOAD_RET_RETRY; + } + return TIOT_FW_LOAD_RET_ERR; +} + +static int32_t tiot_fw_ack_ext_handle_priv(tiot_fw *fw, const uint8_t *cmd, uint16_t len) +{ + tiot_unused(cmd); + tiot_unused(len); + int32_t ret = 0; + uint8_t ack_buff[TIOT_FW_PRIV_ACK_MAX] = { 0 }; + ret = tiot_firmware_read(fw, ack_buff, sizeof(ack_buff)); + if ((ret <= 0) || ((uint32_t)ret > sizeof(ack_buff))) { + return TIOT_FW_LOAD_RET_ERR; + } + tiot_print_info("[TIoT:fw]ack ext: "); + for (uint32_t i = 0; i < (uint32_t)ret; i++) { + tiot_print_info("0x%x ", ack_buff[i]); + } + tiot_print_info("\r\n"); + return TIOT_FW_LOAD_RET_OK; +} + +static int32_t tiot_fw_customize_ext_cmd_handle_priv(tiot_fw *fw, uint8_t *cmd, uint16_t *len) +{ + uint32_t cus_data; + + tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware); + if (ctrl->dev_cus == 0) { + tiot_print_info("[TIoT:priv] customize is NULL.\r\n"); + return TIOT_FW_LOAD_RET_OK; + } + + if (tiot_firmware_customize_value_get(fw, &cus_data) != TIOT_FW_LOAD_RET_OK) { + return TIOT_FW_LOAD_RET_ERR; + } + + return tiot_fw_customize_para_replace(cmd, len, cus_data); +} + +int32_t tiot_fw_ext_cmd_handle_priv(tiot_fw *fw, uint16_t ext_cmd, const uint8_t *cmd, uint16_t len) +{ + if (ext_cmd >= TIOT_FW_EXTCMD_NUM) { + tiot_print_err("[TIoT:fw]priv ext cmd exceed max!\r\n"); + return -1; + } + return tiot_fw_priv_ext_cmd_table[ext_cmd](fw, cmd, len); +} + +int32_t tiot_fw_pre_ext_cmd_handle_priv(tiot_fw *fw, uint16_t ext_cmd, uint8_t *cmd, uint16_t *len) +{ + if (ext_cmd >= TIOT_FW_EXTCMD_NUM) { + tiot_print_err("[TIoT:fw]pre priv ext cmd exceed max!\r\n"); + return -1; + } + + if (tiot_fw_pre_priv_ext_cmd_table[ext_cmd] == NULL) { + return TIOT_FW_LOAD_RET_OK; + } + + return tiot_fw_pre_priv_ext_cmd_table[ext_cmd](fw, cmd, len); +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.h b/code/sdk/zhihui/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.h new file mode 100644 index 000000000..23a4069a5 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/fw_load/cfg_handle_priv/tiot_cfg_handle_priv.h @@ -0,0 +1,53 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT firmware load module private cfg handle. \n + * + * History: \n + * 2023-12-05, Create file. \n + */ +#ifndef TIOT_CFG_HANDLE_PRIV_H +#define TIOT_CFG_HANDLE_PRIV_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_firmware_cfg_handle_priv CFG HANDLE PRIVATE + * @ingroup tiot_common_firmware + * @{ + */ + +/** + * @brief TIoT firmware private extend command handle. + * @param [in] fw TIoT firmware object. + * @param [in] ext_cmd Extend command. + * @param [in] cmd Firmware Command. + * @param [in] len Firmware Command length. + * @return if OK, return 0, if need retry ,return 1, else return -1. + */ +int32_t tiot_fw_ext_cmd_handle_priv(tiot_fw *fw, uint16_t ext_cmd, const uint8_t *cmd, uint16_t len); + +/** + * @brief TIoT firmware before private extend command handle. + * @param [in] fw TIoT firmware object. + * @param [in] ext_cmd Extend command. + * @param [in] cmd Firmware Command. + * @param [in] len Firmware Command length. + * @return if OK, return 0, if need retry ,return 1, else return -1. + */ +int32_t tiot_fw_pre_ext_cmd_handle_priv(tiot_fw *fw, uint16_t ext_cmd, uint8_t *cmd, uint16_t *len); +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware.c b/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware.c new file mode 100644 index 000000000..0219376e6 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware.c @@ -0,0 +1,277 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT firmware load module. \n + * + * History: \n + * 2023-03-30, Create file. \n + */ +#include "tiot_firmware.h" +#include +#include "tiot_firmware_utils.h" +#include "securec.h" +#include "tiot_board_log.h" + +#define FW_LEN_PER_SEND 64 + +#define TIOT_FW_LOAD_FINISH 0 +#define TIOT_FW_LOAD_NEXT 1 + +#define TIOT_FW_LOAD_RETRY_CNT 3 + +#define TIOT_FW_EXT_VERSION1 0x1 + +static inline uint32_t little_endian_to_u32(const uint8_t *data) +{ + uint32_t val; + val = data[0x3]; + val <<= 0x8; + val |= data[0x2]; + val <<= 0x8; + val |= data[0x1]; + val <<= 0x8; + val |= data[0x0]; + return val; +} + +int32_t tiot_firmware_init(tiot_fw *fw, const tiot_fw_ops *ops) +{ + if ((fw == NULL) || (ops == NULL) || (ops->ext_cmd_handle == NULL)) { + tiot_print_dbg("[TIoT][fw]param invalid!\n"); + return -1; + } + fw->ops = ops; + fw->fw_file = NULL; + return 0; +} + +static int32_t tiot_firmware_pre_ext_cmd_write(tiot_fw *fw, uint16_t ext_cmd, uint8_t *cmd, uint16_t *cmd_len) +{ + int32_t ret = 0; + + if (fw->ops->pre_ext_cmd_handle != NULL) { + ret = fw->ops->pre_ext_cmd_handle(fw, ext_cmd, cmd, cmd_len); + } + return ret; +} + +static int32_t firmware_send_cmd(tiot_fw *fw, uint16_t ext_cmd, uint16_t cmd_len) +{ + uint16_t send_len; + uint16_t tmp_len; + // 加载时uart等接口每次最多发送64字节数据, 避免资源受限的场景申请大块内存 + uint8_t cmd[FW_LEN_PER_SEND] = { 0 }; + int32_t ret = 0; + uint16_t remain_len = cmd_len; + + // 一个完整的命令分多次发送,每次发送FW_LEN_PER_SEND字节 + do { + // 1, Get cmd data from file, maximum of 64 bytes each time. + send_len = (remain_len > FW_LEN_PER_SEND) ? FW_LEN_PER_SEND : remain_len; + ret = tiot_file_read(fw->fw_file, (char *)cmd, send_len, fw->cur_offset); + if (ret != send_len) { + tiot_print_err("[TIoT:fw]cmd content read fail\r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + fw->cur_offset += send_len; + + // 2, Callback function before sending data. + tmp_len = send_len; + // 要确保需要处理的扩展命令长度都小于FW_LEN_PER_SEND字节(customize当前已保证),否则需要调整当前的分包发送逻辑 + if (tiot_firmware_pre_ext_cmd_write(fw, ext_cmd, cmd, &tmp_len) != TIOT_FW_LOAD_RET_OK) { + tiot_print_err("[TIoT:fw]pre ext cmd handle failed.\r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + + // 3, send data + ret = tiot_firmware_write(fw, cmd, tmp_len); + if (ret != tmp_len) { + tiot_print_err("[TIoT:fw]cmd content send fail\r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + + remain_len -= send_len; + } while (remain_len > 0); + + // 4, after the whole cmd data send, handle the cmd ack (注意: ext_cmd_handle只能使用最后一包cmd) + ret = fw->ops->ext_cmd_handle(fw, ext_cmd, cmd, tmp_len); + if (ret == TIOT_FW_LOAD_RET_RETRY) { + // 如果命令要重试,需复位文件指针, 以及customize数据指针(当前不实现,customize对应的命令不会返回RETRY) + fw->cur_offset -= cmd_len; + } + + return ret; +} + +static int32_t tiot_firmware_send_cmd_retry(tiot_fw *fw, uint16_t ext_cmd, uint16_t cmd_len) +{ + uint8_t retry_cnt; + int32_t ret = -1; + + for (retry_cnt = 0; retry_cnt < TIOT_FW_LOAD_RETRY_CNT; retry_cnt++) { + ret = firmware_send_cmd(fw, ext_cmd, cmd_len); + if (ret != TIOT_FW_LOAD_RET_RETRY) { + break; + } + tiot_print_warning("[TIoT:fw]single cmd retry %d\r\n", retry_cnt); + } + + if (ret == TIOT_FW_LOAD_RET_QUIT) { + tiot_print_info("[TIoT:fw]version matches, no need to upgrade firmware.\r\n"); + } else if ((ret != TIOT_FW_LOAD_RET_OK) || (retry_cnt == TIOT_FW_LOAD_RETRY_CNT)) { + tiot_print_err("[TIoT:fw]cmd handle retry fail.\r\n"); + ret = -1; + } + + return ret; +} + +static int32_t tiot_firmware_customize_index_init(tiot_fw *fw) +{ + tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware); + if (ctrl->dev_cus == 0) { + tiot_print_info("[TIoT:fw]tiot firmware no customize. \r\n"); + return TIOT_FW_LOAD_RET_OK; + } + + tiot_dev_customize *cus_ptr = (tiot_dev_customize *)ctrl->dev_cus; + cus_ptr->curr_data = cus_ptr->start_data; + + return TIOT_FW_LOAD_RET_OK; +} + +static int32_t tiot_firmware_load_cmds(tiot_fw *fw) +{ + int32_t ret; + uint16_t cmd_len, ext_cmd; + + if (tiot_firmware_customize_index_init(fw) != TIOT_FW_LOAD_RET_OK) { + return -1; + } + + do { + ret = tiot_file_read(fw->fw_file, (char *)&cmd_len, sizeof(uint16_t), fw->cur_offset); + // 处于文件末尾,读文件结束 + if (ret == 0) { + break; + } + if (ret != sizeof(uint16_t)) { + tiot_print_err("[TIoT:fw]cmd len read fail\r\n"); + ret = -1; + break; + } + ext_cmd = cmd_len >> 12; // 拓展命令高4位, 右移12位 + cmd_len = cmd_len & 0xFFF; // 长度为低12位 + + // 更新offset + fw->cur_offset += sizeof(uint16_t); + + ret = tiot_firmware_send_cmd_retry(fw, ext_cmd, cmd_len); + if (ret != 0) { + break; + } + } while (true); + + return ret == TIOT_FW_LOAD_RET_QUIT ? 0 : ret; +} + +static inline int32_t firmware_read_u32(tiot_fw *fw, uint32_t *val) +{ + uint8_t data[4]; + int32_t ret = tiot_file_read(fw->fw_file, (char *)data, sizeof(uint32_t), fw->cur_offset); + if (ret != sizeof(uint32_t)) { + return -1; + } + fw->cur_offset += sizeof(uint32_t); + *val = little_endian_to_u32(data); + return 0; +} + +static int32_t firmware_load_ext_version1(tiot_fw *fw, tiot_fw_ext_version1 *ext) +{ + if (firmware_read_u32(fw, &ext->file_len) != 0) { + tiot_print_err("[TIoT:fw]read img file size fail.\n"); + return -1; + } + tiot_print_info("[TIoT:fw]img file size = %d\n", ext->file_len); + return 0; +} + +static int32_t tiot_firmware_load_file(tiot_fw *fw, const tiot_file_path *file_path, const char *file_name) +{ + uint32_t version; + int32_t ret = -1; + tiot_fw_ext_version1 ext = { 0 }; + + /* 初始化时保证cfg_path不为null */ + fw->fw_file = tiot_file_open(file_path, file_name, OSAL_O_RDONLY, 0); + if (fw->fw_file == NULL) { + tiot_print_err("open file %s fail\n", file_name); + return ret; + } + /* 读取镜像格式版本号 */ + fw->cur_offset = 0; /* 从偏移量为0开始读取镜像格式版本号 */ + if (firmware_read_u32(fw, &version) != 0) { + goto file_close; + } + tiot_print_info("[TIoT:fw]cfg img version: 0x%x\n", version); + if (version == TIOT_FW_EXT_VERSION1) { /* 存在拓展区 */ + if (firmware_load_ext_version1(fw, &ext) != 0) { + goto file_close; + } +#ifdef CONFIG_FILE_BY_ARRAY + fw->fw_file->len = ext.file_len; +#else + tiot_print_warning("[TIoT:fw]non file-array should not use ext version1.\n"); +#endif + } + // 读取发送命令 + ret = tiot_firmware_load_cmds(fw); +file_close: + tiot_file_close(fw->fw_file); + fw->fw_file = NULL; + return ret; +} + +int32_t tiot_firmware_load(tiot_fw *fw, const tiot_file_path *file_path, const char *file_name) +{ + if (fw == NULL || file_name == NULL) { + tiot_print_dbg("[TIoT][fw]fw object or file_name is NULL.\n"); + return -1; + } + if (fw->ops->pre_cmd_execute != NULL) { + tiot_print_info("[TIoT][fw]Pre command execute\n"); + fw->ops->pre_cmd_execute(fw); + } + /* 执行cfg镜像内命令 */ + if (tiot_firmware_load_file(fw, file_path, file_name) != 0) { + tiot_print_err("[TIoT][fw]command execute err!\n"); + return -1; + } + if (fw->ops->after_cmd_execute != NULL) { + tiot_print_info("[TIoT][fw]After command execute\n"); + fw->ops->after_cmd_execute(fw); + } + return 0; +} + +int32_t tiot_firmware_customize_value_get(tiot_fw *fw, uint32_t *cus_data) +{ + tiot_dev_customize *cus_ptr; + + tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware); + if (ctrl->dev_cus == 0) { + tiot_print_err("[TIoT:fw]customize dev_cus is NULL.\r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + + cus_ptr = (tiot_dev_customize *)ctrl->dev_cus; + if (cus_ptr->curr_data > cus_ptr->end_data) { + tiot_print_err("[TIoT:fw] firmware customize get overflow.\r\n"); + return TIOT_FW_LOAD_RET_ERR; + } + + *cus_data = *(uint32_t *)(cus_ptr->curr_data); + cus_ptr->curr_data += cus_ptr->unit_data_len; + return TIOT_FW_LOAD_RET_OK; +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware.h b/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware.h new file mode 100644 index 000000000..37d184d79 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware.h @@ -0,0 +1,118 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT firmware load module. \n + * + * History: \n + * 2023-12-05, Create file. \n + */ +#ifndef TIOT_FIRMWARE_H +#define TIOT_FIRMWARE_H + +#include "tiot_types.h" +#include "tiot_board.h" +#include "tiot_fileops.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_firmware_load Firmware Load + * @ingroup tiot_common + * @{ + */ + +#ifdef CONFIG_FILE_BY_ARRAY +#define TIOT_FW_FILE_ARRAY_CFG_NAME "cfg" +#endif + +typedef enum { + TIOT_FW_LOAD_RET_ERR = -1, + TIOT_FW_LOAD_RET_OK = 0, + TIOT_FW_LOAD_RET_RETRY = 1, + TIOT_FW_LOAD_RET_QUIT = 2, +} tiot_fw_ret; + +/* + 固件文件格式: + | Version | Extended Info | Command1 | Command2 | ... | CommandN | + |---------|---------------|----------|----------|-----|----------| + | 4bytes | -- | - | - | | - | + 单条命令格式: + | ext_cmd | cmd_len | cmd | + |---------|---------|--------| + | 2bytes | Nbytes | + | [12:15] | [0:11] | | +*/ + +/** + * @brief TIoT firmware extended infos. + */ +typedef struct { + uint32_t file_len; /*!< img file size */ +} tiot_fw_ext_version1; + +struct _tiot_fw; + +/** + * @brief TIoT firmware command execute callbacks. + */ +typedef struct { + void (* pre_cmd_execute)(struct _tiot_fw *fw); /*!< Before command execute. */ + void (* after_cmd_execute)(struct _tiot_fw *fw); /*!< After command execute. */ + /*!< After single command execute. */ + int32_t (* ext_cmd_handle)(struct _tiot_fw *fw, uint16_t ext_cmd, const uint8_t *cmd, uint16_t cmd_len); + /*!< Before single command execute. */ + int32_t (* pre_ext_cmd_handle)(struct _tiot_fw *fw, uint16_t ext_cmd, uint8_t *cmd, uint16_t *cmd_len); +} tiot_fw_ops; + +/** + * @brief TIoT firmware object. + */ +typedef struct _tiot_fw { + const tiot_fw_ops *ops; /*!< Firmware ops. */ + tiot_file *fw_file; /*!< Firmware file pointer. */ + uint32_t cur_offset; /*!< Firmware file offset. */ +} tiot_fw; + +/** + * @brief TIoT firmware object init. + * @param [in] fw TIoT firmware object. + * @param [in] ops Firmware command execute callbacks. + * @return if OK return 0, else return -1. + */ +int32_t tiot_firmware_init(tiot_fw *fw, const tiot_fw_ops *ops); + +/** + * @brief TIoT firmware start load process. + * @param [in] fw TIoT firmware object. + * @param [in] file_path TIoT firmware load file path. + * @param [in] file_name TIoT firmware load file name. + * @param [in/out] fw_cmd_info TIoT firmware load command info. + * @return if OK return 0, else return -1. + */ +int32_t tiot_firmware_load(tiot_fw *fw, const tiot_file_path *file_path, const char *file_name); + + +/** + * @brief TIoT firmware obtaining customized parameters. + * @param [in] fw TIoT firmware object. + * @param [out] cus_data customized parameter. + * @return if OK return 0, else return -1. + */ +int32_t tiot_firmware_customize_value_get(tiot_fw *fw, uint32_t *cus_data); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware_utils.h b/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware_utils.h new file mode 100644 index 000000000..a4b7e0f98 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/fw_load/tiot_firmware_utils.h @@ -0,0 +1,58 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT firmware load module utils. \n + * + * History: \n + * 2023-12-05, Create file. \n + */ +#ifndef TIOT_FIRMWARE_UTILS_H +#define TIOT_FIRMWARE_UTILS_H + +#include "tiot_firmware.h" +#include "tiot_controller.h" +#include "tiot_xfer.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_firmware_utils Firmware Utils + * @ingroup tiot_common_firmware + * @{ + */ + +static inline int32_t tiot_firmware_write(tiot_fw *fw, const uint8_t *data, uint32_t len) +{ + tiot_controller *controller = tiot_container_of(fw, tiot_controller, firmware); + return tiot_xfer_send(&controller->transfer, data, len, NULL); +} + +static inline int32_t tiot_firmware_read_timeout(tiot_fw *fw, uint8_t *data, uint32_t len, uint32_t timeout_ms) +{ + tiot_xfer_rx_param rx_param = { 0 }; + tiot_controller *controller = tiot_container_of(fw, tiot_controller, firmware); + rx_param.timeout = timeout_ms; + rx_param.subsys = 0; + return tiot_xfer_recv(&controller->transfer, data, len, &rx_param); +} + +static inline int32_t tiot_firmware_read(tiot_fw *fw, uint8_t *data, uint32_t len) +{ + return tiot_firmware_read_timeout(fw, data, len, TIOT_XFER_RECV_WAIT_FOREVER); +} + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/interface/CMakeLists.txt new file mode 100644 index 000000000..fc47d8935 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/CMakeLists.txt @@ -0,0 +1,20 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +set( + tiot_interface_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/board_interface/board_internal/tiot_board_xmit_ops.c + ${CMAKE_CURRENT_SOURCE_DIR}/device_interface/tiot_service_interface.c +) + +set( + interface_header_lists + "${CMAKE_CURRENT_SOURCE_DIR}/board_interface/board_internal" + "${CMAKE_CURRENT_SOURCE_DIR}/board_interface/board_porting" + "${CMAKE_CURRENT_SOURCE_DIR}/board_interface/osal_porting" + "${CMAKE_CURRENT_SOURCE_DIR}/device_interface" +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${interface_header_lists}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_interface_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board.h new file mode 100644 index 000000000..cae119bd4 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board.h @@ -0,0 +1,61 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-07-04, Create file. \n + */ +#ifndef TIOT_BOARD_H +#define TIOT_BOARD_H + +#include "tiot_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_board_internal_base Board + * @ingroup tiot_common_interface_board_internal + * @{ + */ + +/** + * @brief TIoT common board pins. + */ +typedef enum { + TIOT_PIN_POWER_CTRL, + TIOT_PIN_HOST_WAKEUP_DEVICE, + TIOT_PIN_DEVICE_WAKEUP_HOST, + TIOT_PIN_MAX +} tiot_board_pin; + +/** + * @brief Board hardware infomations. + */ +typedef struct { + uintptr_t xmit_id; /*!< Transmit(UART/I2C/SPI/...) port index. */ + const uint32_t *pm_info; /*!< Power manager related infomations. */ +} tiot_board_hw_info; + +/** + * @brief Board infomations, includes hardware infos and firmware info. + */ +typedef struct { + tiot_board_hw_info hw_info; /*!< Power manager related infomations. */ +} tiot_board_info; + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_log.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_log.h new file mode 100644 index 000000000..9de1f1fee --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_log.h @@ -0,0 +1,81 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board log header. \n + * + * History: \n + * 2023-03-24, Create file. \n + */ +#ifndef TIOT_BOARD_LOG_H +#define TIOT_BOARD_LOG_H + +#include "tiot_board_log_port.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_board_internal_log Board Log + * @ingroup tiot_common_interface_board_internal + * @{ + */ + +#define TIOT_LOG_ALERT 0 /*!< Log level alert. */ +#define TIOT_LOG_ERR 1 /*!< Log level error. */ +#define TIOT_LOG_WARNING 2 /*!< Log level warning. */ +#define TIOT_LOG_INFO 3 /*!< Log level info. */ +#define TIOT_LOG_DEBUG 4 /*!< Log level debug. */ + +#ifndef TIOT_BOARD_LOG_LEVEL +#define TIOT_BOARD_LOG_LEVEL TIOT_LOG_INFO +#endif + +/* 宏定义 */ +#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_DEBUG +#define TIOT_PRINT_FUNCTION_NAME BOARD_PRINT_FUNCTION_NAME +#define tiot_print_dbg(s, ...) board_print_dbg(s, ##__VA_ARGS__) +#else +#define TIOT_PRINT_FUNCTION_NAME +#define tiot_print_dbg(s, ...) +#endif + +#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_INFO +#define tiot_print_info(s, ...) board_print_info(s, ##__VA_ARGS__) +#define tiot_print_suc(s, ...) board_print_suc(s, ##__VA_ARGS__) +#else +#define tiot_print_info(s, ...) +#define tiot_print_suc(s, ...) +#endif + +#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_WARNING +#define tiot_print_warning(s, ...) board_print_warning(s, ##__VA_ARGS__) +#else +#define tiot_print_warning(s, ...) +#endif + +#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_ERR +#define tiot_print_err(s, ...) board_print_err(s, ##__VA_ARGS__) +#else +#define tiot_print_err(s, ...) +#endif + +#if TIOT_BOARD_LOG_LEVEL >= TIOT_LOG_ALERT +#define tiot_print_alert(s, ...) board_print_alter(s, ##__VA_ARGS__) +#else +#define tiot_print_alert(s, ...) +#endif + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit.h new file mode 100644 index 000000000..6a23acb3c --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit.h @@ -0,0 +1,64 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board transmit io common header. \n + * + * History: \n + * 2023-03-25, Create file. \n + */ +#ifndef TIOT_BOARD_XMIT_H +#define TIOT_BOARD_XMIT_H + +#include "tiot_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_board_internal_xmit Board Transmit + * @ingroup tiot_common_interface_board_internal + * @{ + */ + +/** + * @brief Transmit handle, compatible for board transmit handle. + */ +typedef void *tiot_xmit_handle; + +/** + * @brief Universal transmit config, compatible for all types of transmit io. + */ +struct tiot_xmit_config; + +/** + * @brief Transmit object. + */ +typedef struct { + uintptr_t id; /*!< Transmit io id. + If board io operations use index, set this id in port open interface. */ + tiot_xmit_handle handle; /*!< Transmit handle compatible for board io handle. + If board io operations use handle, set this handle in port open interface. */ +} tiot_xmit; + +/** + * @brief Transmit callbacks, registed in port open interface. + */ +typedef struct { + /*!< Rx data receive notify callback when use asynchronous board interface to read data. */ + void (*rx_notify)(tiot_xmit *xmit, uint8_t *data, uint32_t len); +} tiot_xmit_callbacks; + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.c b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.c new file mode 100644 index 000000000..32741b1a2 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.c @@ -0,0 +1,62 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board Transmit select. \n + * + * History: \n + * 2023-03-27, Create file. \n + */ +#include "tiot_board_xmit_ops.h" + +const tiot_xmit_ops g_tiot_xmit_ops_map[TIOT_XMIT_TYPE_BUTT] = { +#ifdef CONFIG_XMIT_WITH_UART + { + .open = tiot_board_uart_open, + .close = tiot_board_uart_close, + .write = tiot_board_uart_write, + .read = tiot_board_uart_read, + .set_config = tiot_board_uart_set_config, +#ifdef CONFIG_UART_RX_MODE_BUFFED + .rx_mode = TIOT_XMIT_RX_MODE_BUFFED, +#else + .rx_mode = TIOT_XMIT_RX_MODE_POLL, +#endif + }, +#endif +#ifdef CONFIG_XMIT_WITH_SPI + { + .open = tiot_board_spi_open, + .close = tiot_board_spi_close, + .write = tiot_board_spi_write, + .read = tiot_board_spi_read, + .set_config = tiot_board_spi_set_config, +#ifdef CONFIG_SPI_RX_MODE_BUFFED + .rx_mode = TIOT_XMIT_RX_MODE_BUFFED, +#else + .rx_mode = TIOT_XMIT_RX_MODE_POLL, +#endif + }, +#endif +#ifdef CONFIG_XMIT_WITH_I2C + { + .open = tiot_board_i2c_open, + .close = tiot_board_i2c_close, + .write = tiot_board_i2c_write, + .read = tiot_board_i2c_read, + .set_config = tiot_board_i2c_set_config, +#ifdef CONFIG_I2C_RX_MODE_BUFFED + .rx_mode = TIOT_XMIT_RX_MODE_BUFFED, +#else + .rx_mode = TIOT_XMIT_RX_MODE_POLL, +#endif + }, +#endif +}; + +const tiot_xmit_ops *tiot_xmit_get_ops(tiot_xmit_type type) +{ + if (type >= TIOT_XMIT_TYPE_BUTT) { + return NULL; + } + return &g_tiot_xmit_ops_map[type]; +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.h new file mode 100644 index 000000000..fa8bca9bf --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_internal/tiot_board_xmit_ops.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board transmit io common ops. \n + * + * History: \n + * 2023-06-13, Create file. \n + */ +#ifndef TIOT_BOARD_XMIT_OPS_H +#define TIOT_BOARD_XMIT_OPS_H + +#include "tiot_board_xmit.h" +#ifdef CONFIG_XMIT_WITH_UART +#include "tiot_board_uart_port.h" +#endif +#ifdef CONFIG_XMIT_WITH_SPI +#include "tiot_board_spi_port.h" +#endif +#ifdef CONFIG_XMIT_WITH_I2C +#include "tiot_board_i2c_port.h" +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_board_internal_xmit Board Transmit Ops + * @ingroup tiot_common_interface_board_internal + * @{ + */ + +/** + * @brief TIoT support transmit type. + */ +typedef enum { +#ifdef CONFIG_XMIT_WITH_UART + TIOT_XMIT_TYPE_UART, +#endif +#ifdef CONFIG_XMIT_WITH_SPI + TIOT_XMIT_TYPE_SPI, +#endif +#ifdef CONFIG_XMIT_WITH_I2C + TIOT_XMIT_TYPE_I2C, +#endif + TIOT_XMIT_TYPE_BUTT +} tiot_xmit_type; + +/** + * @brief TIoT Transmit rx mode. + */ +typedef enum { + TIOT_XMIT_RX_MODE_BUFFED, /* TIoT Transmit rx mode with circular buffer. */ + TIOT_XMIT_RX_MODE_POLL, /* TIoT Transmit rx mode without buffer, read data direct from io. */ +} tiot_xmit_rx_mode; + +/** + * @brief Transmit operations. + */ +typedef struct { + int32_t (*open)(tiot_xmit *xmit, tiot_xmit_callbacks *cbs); /*!< Port open interface. */ + void (*close)(tiot_xmit *xmit); /*!< Port close interface. */ + int32_t (*write)(tiot_xmit *xmit, const uint8_t *buff, uint32_t len); /*!< Port write interface. */ + int32_t (*read)(tiot_xmit *xmit, uint8_t *buff, uint32_t len); /*!< Port read interface. */ + int32_t (*set_config)(tiot_xmit *xmit, struct tiot_xmit_config *config); /*!< Port config interface. */ + const uint16_t rx_mode; +} tiot_xmit_ops; + +/** + * @brief Get selected transmit operations. + * @return const tiot_xmit_ops* Selected transmit operations. + */ +const tiot_xmit_ops *tiot_xmit_get_ops(tiot_xmit_type type); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/gnss_board_port.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/gnss_board_port.h new file mode 100644 index 000000000..3667f94e8 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/gnss_board_port.h @@ -0,0 +1,84 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: GNSS board port head. \n + * + * History: \n + * 2023-06-13, Create file. \n + */ +#ifndef GNSS_BOARD_PORT_H +#define GNSS_BOARD_PORT_H + +#include "tiot_types.h" +#include "tiot_board_pin_port.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_device_gnss_board_port GNSS Board Port + * @ingroup tiot_device_gnss + * @{ + */ + +/** + * @brief GNSS pm pins. + */ +typedef enum { + GNSS_PIN_POWER_CTRL, /*!< GNSS power control pin. */ + GNSS_PIN_HOST_WAKEUP_DEVICE, /*!< GNSS host wakeup device pin. */ + GNSS_PIN_DEVICE_WAKEUP_HOST, /*!< GNSS device wakeup host pin. */ + GNSS_PIN_NUM, /*!< GNSS pin max. */ + GNSS_PIN_NONE = TIOT_PIN_NONE /*!< GNSS pin none. */ +} gnss_pm_pins; + +/** + * @brief GNSS board hardware info. + */ +typedef struct { + uintptr_t xmit_id; + uint32_t pm_info[GNSS_PIN_NUM]; +} gnss_board_hw_info; + +/** + * @brief GNSS board info. + */ +typedef struct { + const char *cfg_path; /*!< cfg file path, NULL for file array. */ + gnss_board_hw_info *hw_infos; /*!< Pointer to array of GNSS hardware infos. */ +} gnss_board_info; + +/** + * @brief Board provides resource informations, including pin indexs, ids, file paths, etc. + * @return Provided resource information. + */ +const gnss_board_info *gnss_board_get_info(void); + +/** + * @brief Board porting init, request board resources, including hardware io, interrupt,etc. + * @param param user customsize parameters, like device num. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t gnss_board_init(void *param); + +/** + * @brief Board porting deinit, release board resources, including hardware io, interrupt,etc. + * @param param user customsize parameters, like device num. + */ +void gnss_board_deinit(void *param); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_misc_port.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_misc_port.h new file mode 100644 index 000000000..55f976cae --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_misc_port.h @@ -0,0 +1,112 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board misc porting header. \n + * + * History: \n + * 2023-03-24, Create file. \n + */ +#ifndef TIOT_BOARD_MISC_PORT_H +#define TIOT_BOARD_MISC_PORT_H + +#include "tiot_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_board_porting_misc Board Misc Port + * @ingroup tiot_common_interface_board_porting + * @{ + */ + +/** + * @if Eng + * @brief Board wake lock struct. + * @else + * @brief 板级唤醒锁结构体。 + * @endif + */ +typedef struct { + void *lock; +} tiot_board_wakelock; + +/** + * @if Eng + * @brief Board wake lock initialization interface. + * @param [out] lock wake lock to be initialized. + * @return if OK return 0, else return -1. + * @note if board has no sleep or just enter wfi, implement as empty function. + * @else + * @brief 板级唤醒锁初始化接口。 + * @param [out] lock 待初始化的唤醒锁。 + * @return 初始化成功返回0,否则返回-1。 + * @note 如果板级不睡眠或仅进入wfi,实现为空函数即可。 + * @endif + */ +int32_t tiot_board_wake_lock_init(tiot_board_wakelock *lock); + +/** + * @if Eng + * @brief Board wake lock interface. + * @param [in] lock wake lock to be locked. + * @note if board has no sleep or just enter wfi, implement as empty function. + * @else + * @brief 板级唤醒锁接口。 + * @param [in] lock 待上锁的唤醒锁。 + * @note 如果板级不睡眠或仅进入wfi,实现为空函数即可。 + * @endif + */ +void tiot_board_wake_lock(tiot_board_wakelock *lock); + +/** + * @if Eng + * @brief Board wake unlock interface. + * @param [in] lock wake lock to be unlocked. + * @note if board has no sleep or just enter wfi, implement as empty function. + * @else + * @brief 板级唤醒解锁接口。 + * @param [in] lock 待解锁的唤醒锁。 + * @note 如果板级不睡眠或仅进入wfi,实现为空函数即可。 + * @endif + */ +void tiot_board_wake_unlock(tiot_board_wakelock *lock); + +/** + * @if Eng + * @brief Board wake lock destroy interface. + * @param [in] lock wake lock to be destroyed. + * @note if board has no sleep or just enter wfi, implement as empty function. + * @else + * @brief 板级唤醒锁销毁接口。 + * @param [in] lock 待销毁的唤醒锁. + * @note 如果板级不睡眠或仅进入wfi,实现为空函数即可。 + * @endif + */ +void tiot_board_wake_lock_destroy(tiot_board_wakelock *lock); + +/** + * @if Eng + * @brief Board μs level delay. + * @param [in] us μs count. + * @else + * @brief 板级微秒级delay接口。 + * @param [in] us 微秒。 + * @endif + */ +void tiot_board_udelay(uint32_t us); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h new file mode 100644 index 000000000..e2a88b257 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_pin_port.h @@ -0,0 +1,100 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board pin porting header. \n + * + * History: \n + * 2023-03-24, Create file. \n + */ +#ifndef TIOT_BOARD_PIN_PORT_H +#define TIOT_BOARD_PIN_PORT_H + +#include "tiot_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_board_porting_pin Board Pin Port + * @ingroup tiot_common_interface_board_porting + * @{ + */ + +/** + * @brief Pin none, board port should use this macro if pin is not connected. + */ +#define TIOT_PIN_NONE 0xFFFFFFFFU +#define TIOT_PIN_UART_WAKEUP_NUM 0x80000000U /* 用于uart rx唤醒. */ + +/** + * @brief Pin level enum. + */ +typedef enum { + TIOT_PIN_LEVEL_LOW, /*!< 0: Pin level low. */ + TIOT_PIN_LEVEL_HIGH /*!< 1: Pin level high. */ +} tiot_pin_level; + +/** + * @brief Pin interrupt enable enum. + */ +typedef enum { + TIOT_PIN_INT_DISABLE, /*!< 0: Pin interrupt disable. */ + TIOT_PIN_INT_ENABLE /*!< 1: Pin interrupt enable. */ +} tiot_pin_int_enable; + +/** + * @brief Pin interrupt callback type, need input corresponding pin. + */ +typedef void (* tiot_pin_int_callback)(uint32_t pin); + +/** + * @brief Board set pin level interface. + * @param [in] pin Pin id. + * @param [in] level Pin level, see @ref tiot_pin_level. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_pin_set_level(uint32_t pin, uint8_t level); + +/** + * @brief Board get current pin level interface. + * @param [in] pin Pin id. + * @param [out] level Current pin level, see @ref tiot_pin_level. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_pin_get_level(uint32_t pin, uint8_t *level); + +/** + * @brief Board pin interrupt enable interface. + * @param [in] pin Pin id. + * @param [in] int_enable Interrupt enable or disable, see @ref tiot_pin_int_enable. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_pin_enable_int(uint32_t pin, uint8_t int_enable); + +/** + * @brief Board pin interrupt callback register interface. + * @note Porting should ensure this callback is called when enters pin irq if interrupt enabled. + * @param [in] pin Pin id. + * @param [in] int_cb Registed interrupt callback, see @ref tiot_pin_int_callback. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_pin_register_int_callback(uint32_t pin, tiot_pin_int_callback int_cb); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_uart_port.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_uart_port.h new file mode 100644 index 000000000..406cb485c --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/board_porting/tiot_board_uart_port.h @@ -0,0 +1,122 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board UART porting header. \n + * + * History: \n + * 2023-03-24, Create file. \n + */ +#ifndef TIOT_BOARD_UART_PORT_H +#define TIOT_BOARD_UART_PORT_H + +#include "tiot_board_xmit.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_board_porting_uart Board UART Port + * @ingroup tiot_common_interface_board_porting + * @{ + */ + +#define TIOT_UART_ATTR_DATABIT_8 0 /*!< UART word length is 8 data bits per frame. */ +#define TIOT_UART_ATTR_DATABIT_7 1 /*!< UART word length is 7 data bits per frame. */ +#define TIOT_UART_ATTR_DATABIT_6 2 /*!< UART word length is 6 data bits per frame. */ +#define TIOT_UART_ATTR_DATABIT_5 3 /*!< UART word length is 5 data bits per frame. */ +#define TIOT_UART_ATTR_DATABIT_BUTT 4 /*!< UART word length butt. */ + +#define TIOT_UART_ATTR_PARITY_NONE 0 /*!< no UART parity bit. */ +#define TIOT_UART_ATTR_PARITY_ODD 1 /*!< odd UART parity bit. */ +#define TIOT_UART_ATTR_PARITY_EVEN 2 /*!< even UART parity bit. */ +#define TIOT_UART_ATTR_PARITY_MARK 3 /*!< UART parity bit is always 1. */ +#define TIOT_UART_ATTR_PARITY_SPACE 4 /*!< UART parity bit is always 0. */ +#define TIOT_UART_ATTR_PARITY_BUTT 5 /*!< UART parity bit butt. */ + +#define TIOT_UART_ATTR_STOPBIT_1 0 /*!< UART has 1 stop bit. */ +#define TIOT_UART_ATTR_STOPBIT_1P5 1 /*!< UART has 1.5 stop bits. */ +#define TIOT_UART_ATTR_STOPBIT_2 2 /*!< UART has 2 stop bits. */ +#define TIOT_UART_ATTR_STOPBIT_BUTT 3 /*!< UART stop bits butt. */ + +#define TIOT_UART_ATTR_FLOW_CTRL_DISABLE 0 /*!< UART flow control is disabled. */ +#define TIOT_UART_ATTR_FLOW_CTRL_ENABLE 1 /*!< UART flow control enabled. */ + +/** + * @brief Uart attribute. + * + */ +typedef struct { + uint16_t data_bits : 4; + uint16_t parity : 4; + uint16_t stop_bits : 4; + uint16_t flow_ctrl : 4; + uint16_t reserved : 16; +} tiot_uart_attr; + +/** + * @brief Uart config. + * + */ +typedef struct tiot_xmit_config { + uint32_t baudrate; /*!< UART baudrate. */ + tiot_uart_attr attr; /*!< UART attribute. */ +} tiot_uart_config; + +/** + * @brief Board UART open interface. + * @param [in] xmit Transmit object. + * @param [in] cb Transmit callbacks. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_uart_open(tiot_xmit *xmit, tiot_xmit_callbacks *cb); + +/** + * @brief Board UART close interface. + * @param [in] xmit Transmit object. + */ +void tiot_board_uart_close(tiot_xmit *xmit); + +/** + * @brief Board UART write interface. + * @param [in] xmit Transmit object. + * @param [in] buff Data buff. + * @param [in] len Data length. + * @return zero or postive for writen OK length; + * negtive if write FAIL. + */ +int32_t tiot_board_uart_write(tiot_xmit *xmit, const uint8_t *buff, uint32_t len); + +/** + * @brief Board UART blocking read interface. + * @param [in] xmit Transmit object. + * @param [in] buff Read buff. + * @param [in] len Expected read length. + * @return zero or postive for read OK length; + * negtive if read FAIL or cannot implemented. + */ +int32_t tiot_board_uart_read(tiot_xmit *xmit, uint8_t *buff, uint32_t len); + +/** + * @brief Board UART config interface. + * @param [in] xmit Transmit object. + * @param [in] config UART config, see @ref tiot_uart_config. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_uart_set_config(tiot_xmit *xmit, tiot_uart_config *config); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/interface/board_interface/osal_porting/tiot_osal.h b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/osal_porting/tiot_osal.h new file mode 100644 index 000000000..0a78cb121 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/board_interface/osal_porting/tiot_osal.h @@ -0,0 +1,436 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT osal interface. \n + * + * History: \n + * 2023-05-31, Create file. \n + */ +#ifndef TIOT_OSAL_H +#define TIOT_OSAL_H + +#ifdef CONFIG_OSAL_DEFINED +#include "soc_osal.h" +#else +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_osal TIoT Osal Interface + * @ingroup tiot_common_interface + * @{ + */ + +#define OSAL_SUCCESS 0 +#define OSAL_FAILURE (-1) +#define OSAL_EOVERFLOW (-75) + +#define OSAL_WAIT_FOREVER 0xFFFFFFFF +#define OSAL_WAIT_CONDITION_TRUE 1 + +#define OSAL_GFP_ZERO (0x1) +#define OSAL_GFP_ATOMIC (0x1 << 1) +#define OSAL_GFP_DMA (0x1 << 2) +#define OSAL_GFP_KERNEL (0x1 << 3) + +#define OSAL_O_RDONLY 00000000 +#define OSAL_O_WRONLY 00000001 +#define OSAL_O_RDWR 00000002 +#define OSAL_O_ACCMODE 00000003 + +#define OSAL_O_CREAT 00000100 +#define OSAL_O_EXCL 00000200 +#define OSAL_O_TRUNC 00001000 +#define OSAL_O_APPEND 00002000 +#define OSAL_O_CLOEXEC 02000000 + +#define OSAL_SEEK_SET 0 +#define OSAL_SEEK_CUR 1 +#define OSAL_SEEK_END 2 + +/* Osal string. */ +#ifdef __KERNEL__ +#define osal_strtol(cp, endp, base) simple_strtol(cp, endp, base) +#else +#define osal_strtol(cp, endp, base) strtol(cp, endp, base) +#endif + +typedef struct { + void *lock; +} osal_spinlock; + +typedef struct { + void *mutex; +} osal_mutex; + +typedef struct { + void *wait; +} osal_wait; + +typedef struct { + void *task; +} osal_task; + +typedef int (*osal_kthread_handler)(void *data); + +/* return value is a bool type */ +typedef int (*osal_wait_condition_func)(const void *param); + +/** + * @ingroup osal_timer + * @brief sleep waiting for signals. + * + * @par Description: + * sleep waiting for signals. + * + * @param msecs [in] Time in milliseconds to sleep for. + * + * @return Returns 0 when the timer has expired otherwise the remaining time in ms will be returned. + * + * @par Support System: + * linux liteos freertos. + */ +unsigned long osal_msleep(unsigned int msecs); + +/** + * @ingroup osal_addr + * @brief Alloc dynamic memory. + * + * @par Description: + * This API is used to alloc a memory block of which the size is specified. + * + * @param size [in] How many bytes of memory are required. + * @param osal_gfp_flag [in] The type of memory to alloc. This parameter is not used in liteos and freertos. + * In linux, it must include one of the following access modes: OSAL_GFP_ATOMIC, OSAL_GFP_DMA, OSAL_GFP_KERNEL. + * OSAL_GFP_ZERO can be bitwise-or'd in flags, Then, the memory is set to zero. + * + * @par Support System: + * linux liteos freertos. + */ +void *osal_kmalloc(unsigned long size, unsigned int osal_gfp_flag); + +/** + * @ingroup osal_addr + * @brief Free dynamic memory. + * + * @par Description: + * This API is used to free specified dynamic memory that has been allocd and update module mem used. + * + * @param addr [in] Starting address of the memory block to be freed. + * + * @par Support System: + * linux liteos freertos. + */ +void osal_kfree(void *addr); + +/** + * @ingroup osal_spinlock + * @brief Initialize a spin lock. + * + * @par Description: + * This API is used to initialization of spin_lock. + * + * @param lock [out] the lock to be initialized. + * + * @attention + * must be free with osal_spin_lock_destroy, other wise will lead to memory leak; + * + * @return OSAL_SUCCESS/OSAL_FAILURE + * + * @par Support System: + * linux liteos. + */ +int osal_spin_lock_init(osal_spinlock *lock); + +/** + * @ingroup osal_spinlock + * @brief acquire the spin_lock. + * + * @par Description: + * Saves the current IRQ status of the CPU, obtains the specified spin_lock, and disables the interrupts of the CPU. + * + * @param lock [in] the lock to be acquired. + * + * @par Support System: + * linux liteos freertos. + */ +void osal_spin_lock_irqsave(osal_spinlock *lock, unsigned long *flags); + +/** + * @ingroup osal_spinlock + * @brief release the spin_lock. + * + * @par Description: + * Releases the specified spin_lock and restores the interrupt status of the CPU, and enables the interrupts of the CPU. + * + * @param lock [in] the lock to be released. + * + * @par Support System: + * linux liteos freertos. + */ +void osal_spin_unlock_irqrestore(osal_spinlock *lock, unsigned long *flags); + +/** + * @ingroup osal_spinlock + * @brief Destroy the spin_lock. + * + * @par Description: + * Destroy the spin_lock. + * + * @param lock [in] The lock to be destroyed. + * + * @attention + * must be called when kmod exit, other wise will lead to memory leak; + * this API will free memory, lock must be from osal_spin_lock_init returns + * + * @par Support System: + * linux liteos. + */ +void osal_spin_lock_destroy(osal_spinlock *lock); + +/** + * @ingroup osal_mutex + * @brief Initialize the mutex. + * + * @par Description: + * This API is used to initialize the mutex. + * + * @param mutex [in] the mutex to be initialized. + * + * @return OSAL_FAILURE/OSAL_SUCCESS + * + * @par Support System: + * linux liteos freertos. + */ +int osal_mutex_init(osal_mutex *mutex); + +/** + * @ingroup osal_mutex + * @brief Acquire the mutex. + * + * @par Description: + * Acquire the mutex. Lock the mutex exclusively for this task. + * If the mutex is not available right now, it will sleep until it can get it. + * + * @param mutex [in] the mutex to be initialized. + * + * @return OSAL_FAILURE/OSAL_SUCCESS + * + * @note + * The mutex must later on be released by the same task that acquired it. Recursive locking is not allowed. + * The task may not exit without first unlocking the mutex. + * Also, kernel memory where the mutex resides must not be freed with the mutex still locked. + * The mutex must first be initialized (or statically defined) before it can be locked. + * memset()-ing the mutex to 0 is not allowed. + * + * @par Support System: + * linux liteos freertos. + * @par System Differ: Only LiteOS supports the nested lock feature. + */ +int osal_mutex_lock(osal_mutex *mutex); + +/** + * @ingroup osal_mutex + * @brief Release the mutex. + * + * @par Description: + * Release the mutex. Unlock a mutex that has been locked by this task previously. + * This function must not be used in interrupt context. Unlocking of a not locked mutex is not allowed. + * + * @param mutex [in] the mutex to be released. + * + * @par Support System: + * linux liteos freertos. + */ +void osal_mutex_unlock(osal_mutex *mutex); + +/** + * @ingroup osal_mutex + * @brief Destroy the mutex. + * + * @par Description: + * This API is used to destroy the mutex. + * + * @param mutex [in] The mutex to be destroyed. + * + * @attention + * must be called when kmod exit, otherwise will lead to memory leak; osal_mutex_destroy will free memory, + * caller should clear pointer to be NULL after called. + * + * @par Support System: + * linux liteos freertos. + */ +void osal_mutex_destroy(osal_mutex *mutex); + +/** + * @ingroup osal_wait + * @brief Initialize a waiting queue. + * + * @par Description: + * This API is used to Initialize a waiting queue. + * + * @param wait [out] The wait queue to be initialized. + * + * @par Support System: + * linux liteos. + */ +int osal_wait_init(osal_wait *wait); + +/** + * @ingroup osal_wait + * @brief sleep until a condition gets true or a timeout elapses. + * + * @par Description: + * sleep until a condition gets true or a timeout elapses. + * The process is put to sleep (TASK_INTERRUPTIBLE) until the @func returned true or a signal is received. + * Return value of the @func is checked each time the waitqueue @wait is woken up. + * + * @param wait [in] the waitqueue to wait on. + * @param wait [in] a C expression for the event to wait for. + * @param wait [in] timeout, in ms. + * + * @par Support System: + * linux liteos. + */ +int osal_wait_timeout_interruptible(osal_wait *wait, osal_wait_condition_func func, const void *param, + unsigned long ms); + +/** + * @ingroup osal_wait + * @brief wake up threads blocked on a waitqueue. + * + * @par Description: + * Wake-up wait queue,pair to @wait_event_interruptible. + * + * @param wait [in] The wait to be wake up. + * + * @par Support System: + * linux liteos. + */ +void osal_wait_wakeup_interruptible(osal_wait *wait); // same as osal_wait_wakeup on liteos + +/** + * @ingroup osal_wait + * @brief to destroy the wait. + * + * @par Description: + * This API is used to destroy the wait. + * + * @param wait [in] The wait to be destroyed. + * + * @attention this api may free memory, wait should be from osal_complete_init. + * @par Support System: + * linux liteos. + */ +void osal_wait_destroy(osal_wait *wait); + +#ifdef CONFIG_XFER_TX_SUPPORT_TASK +/** + * @ingroup osal_task + * + * @brief Provides an interface for creating a thread and invokes kthread_run for creating a kernel thread. + * + * @par Description: + * Provides an interface for creating a thread and invokes kthread_run for creating a kernel thread. + * + * @param stack_size [in] Size of the stack space of the thread. 0 means default. + * @param handler [in] Functions to be processed by the thread + * @param data [in] Function handler data. + * @param name [in] Thread name displayed. + * + * @retval osal_task* If the thread is successfully created, the pointer of the thread is returned. + * @retval NULL If the thread fails to be created, NULL is returned. + * + * @par Support System: + * linux liteos freertos. + */ +osal_task *osal_kthread_create(osal_kthread_handler handler, void *data, const char *name, unsigned int stack_size); + +/** + * @ingroup osal_task + * + * @brief Used to destroy the threads you created. + * + * @par Description: + * Stops a specified kernel thread. + * + * @attention osal_kthread_destroy will free memory of task, caller should clear pointer to be NULL. + * Note that if you want to destroy a thread, the thread cannot end before calling this function, + * Or something terrible will happen. + * When you call the Kthread_stop function, the thread function cannot be finished, otherwise it will oops. + * @task may be free in api, @task should be from osal_kthread_create. + * + * @param task [in] Threads you want to destroy. + * @param stop_flag [in] Indicates whether the current thread exits. If the value of stop_flag is 0, + * The current thread does not exit. The stop flag is not 0. + * + * @par Support System: + * linux liteos freertos. + */ +void osal_kthread_destroy(osal_task *task, unsigned int stop_flag); +#endif + +#ifndef CONFIG_FILE_BY_ARRAY +/** + * @ingroup osal_fileops + * @brief open file and return file pointer. + * @param file [in] the filename of file + * @param flag [in] the opreation flag example: OSAL_O_CREAT + * @param mode [in] the mode example: OSAL_O_RDONLY + * @return void* / null + * + * @par Support System: + * linux liteos seliteos freertos. + */ +void *osal_klib_fopen(const char *file, int flags, int mode); + +/** + * @ingroup osal_fileops + * @brief close file. + * @param filp [in] the result of osal_klib_fopen + * @par Support System: + * linux liteos seliteos freertos. + */ +void osal_klib_fclose(void *filp); + +/** + * @ingroup osal_fileops + * @brief Kernel read function. + * @param buf [out] the buffer you want to read in + * @param size [in] the size of buffer + * @param filp [in] the result of osal_klib_fopen + * @return The length that has been read. + * + * @par Support System: + * linux liteos seliteos freertos. + */ +int osal_klib_fread(char *buf, unsigned long size, void *filp); + +/** + * @ingroup osal_fileops + * @brief Kernel file seek function. + * @param offset [in] the new position of file + * @param whence [in] the method of lseek,example:OSAL_SEEK_SET + * @param filp [in] the result of osal_klib_fopen + * @par Support System: + * linux liteos seliteos. + */ +int osal_klib_fseek(long long offset, int whence, void *filp); +#endif + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif /* CONFIG_OSAL_DEFINED */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface.c b/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface.c new file mode 100644 index 000000000..643b39aae --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface.c @@ -0,0 +1,248 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-10-28, Create file. \n + */ + +#include "tiot_service_interface.h" +#include "tiot_service_interface_ext.h" +#include "tiot_controller.h" +#include "tiot_pm_wakelock.h" +#include "tiot_board_log.h" +#ifdef CONFIG_DEV_GNSS +#include "gnss_service.h" +#endif +#ifdef CONFIG_DEV_W33 +#include "w33_service.h" +#endif +#ifdef CONFIG_DEV_CAXX +#include "caxx_service.h" +#endif +#ifdef CONFIG_DEV_BSXX +#include "bsxx_service.h" +#endif +#ifdef CONFIG_DEV_TIOT_SLAVE +#include "tiot_slave_service.h" +#endif + +typedef struct { + int32_t (* init)(void); + void (* deinit)(void); +} tiot_service_entry; + +typedef struct { + const char *name; + uint8_t dev_max; + uintptr_t (* get_ctrl)(uint8_t dev_id); +} tiot_service_desc; + +static const tiot_service_entry tiot_service_list[] = { +#ifdef CONFIG_DEV_GNSS + { gnss_service_init, gnss_service_deinit }, +#endif +#ifdef CONFIG_DEV_W33 + { w33_service_init, w33_service_deinit }, +#endif +#ifdef CONFIG_DEV_CAXX + { caxx_service_init, caxx_service_deinit }, +#endif +#ifdef CONFIG_DEV_BSXX + { bsxx_service_init, bsxx_service_deinit }, +#endif +#ifdef CONFIG_DEV_TIOT_SLAVE + { tiot_slave_service_init, tiot_slave_service_deinit }, +#endif +}; + +static const tiot_service_desc tiot_service_desc_list[] = { +#ifdef CONFIG_DEV_GNSS + { "gn71", CONFIG_GNSS_DEV_NUM, gnss_service_get_ctrl }, + { "gnss01", CONFIG_GNSS_DEV_NUM, gnss_service_get_ctrl }, +#endif +#ifdef CONFIG_DEV_W33 + { "w33", CONFIG_W33_DEV_NUM, w33_service_get_ctrl }, +#endif +#ifdef CONFIG_DEV_CAXX + { "ca01", CONFIG_CAXX_DEV_NUM, caxx_service_get_ctrl }, +#endif +#ifdef CONFIG_DEV_BSXX + { "bs21", CONFIG_BSXX_DEV_NUM, bsxx_service_get_ctrl }, + { "bs25", CONFIG_BSXX_DEV_NUM, bsxx_service_get_ctrl }, +#endif +#ifdef CONFIG_DEV_TIOT_SLAVE + { "tiot_slave", CONFIG_TIOT_SLAVE_DEV_NUM, tiot_slave_service_get_ctrl }, +#endif +}; + +static const tiot_service_desc *tiot_service_get_description(const char *device_name, uint8_t *dev_id) +{ + uint32_t i; + uint32_t len = strlen(device_name); + uint32_t name_len = 0; + for (i = 0; i < (sizeof(tiot_service_desc_list) / sizeof(tiot_service_desc)); i++) { + name_len = strlen(tiot_service_desc_list[i].name); + /* devcie_name长度小于描述名时不可能匹配,避免memcmp对device_name访问溢出. */ + if (len < name_len) { + continue; + } + if (memcmp(device_name, tiot_service_desc_list[i].name, name_len) == 0) { + break; + } + } + if (i == (sizeof(tiot_service_desc_list) / sizeof(tiot_service_desc))) { + tiot_print_err("[TIoT]invalid device_name string %s.\r\n", device_name); + return NULL; + } + /* device_name格式 */ + /* "xxxx" 其中xxxx为对应device名字, dev_id默认为0 */ + /* "xxxx,n" 其中n为单个数字字符,n < 10,dev_id设为n */ + if (len > name_len) { + if (len - name_len != 2) { // n为单个字符,加上分隔符,长度固定为2 + tiot_print_err("[TIoT]device_name length %d invalid.\r\n", len); + return NULL; + } + if (device_name[name_len] != ',') { + tiot_print_err("[TIoT]device_name seprator invalid %c.\r\n", device_name[name_len]); + return NULL; + } + if ((device_name[name_len + 1] < '0') || (device_name[name_len + 1] > '9')) { + tiot_print_err("[TIoT]dev id invalid %c.\r\n", device_name[name_len + 1]); + return NULL; + } + *dev_id = device_name[name_len + 1] - '0'; + } + if (*dev_id >= tiot_service_desc_list[i].dev_max) { + tiot_print_err("[TIoT]device_name dev id exceed max %c.\r\n", device_name[name_len + 1]); + return NULL; + } + return &tiot_service_desc_list[i]; +} + +int32_t tiot_service_init(void) +{ + int32_t ret; + uint32_t i; + uint32_t j; + if (tiot_pm_wake_lock_init() != 0) { + return -1; + } + for (i = 0; i < (sizeof(tiot_service_list) / sizeof(tiot_service_entry)); i++) { + ret = tiot_service_list[i].init(); + if (ret != 0) { + tiot_print_err("[TIoT]service init fail @%d\n", i); + goto fail; + } + } + return 0; +fail: + for (j = 0; j < i; j++) { + tiot_service_list[j].deinit(); + } + tiot_pm_wake_lock_destroy(); + return ret; +} + +void tiot_service_deinit(void) +{ + uint32_t i; + for (i = 0; i < (sizeof(tiot_service_list) / sizeof(tiot_service_entry)); i++) { + tiot_service_list[i].deinit(); + } + tiot_pm_wake_lock_destroy(); +} + +tiot_handle tiot_service_open(const char *device_name, void *param) +{ + tiot_controller *ctrl = NULL; + uint8_t dev_id = 0; + const tiot_service_desc *desc; + if (device_name == NULL) { + tiot_print_err("[TIoT]device_name is NULL.\r\n"); + return 0; + } + desc = tiot_service_get_description(device_name, &dev_id); + if (desc == NULL) { + return 0; + } + ctrl = (tiot_controller *)desc->get_ctrl(dev_id); + if (tiot_controller_open(ctrl, param) != 0) { + ctrl = NULL; + } + return (tiot_handle)ctrl; +} + +void tiot_service_close(tiot_handle handle) +{ + tiot_controller *ctrl = (tiot_controller *)handle; + tiot_controller_close(ctrl); +} + +int32_t tiot_service_write_ext(tiot_handle handle, const uint8_t *data, + uint32_t len, const tiot_service_tx_param *param) +{ + tiot_controller *ctrl = (tiot_controller *)handle; + if ((data == NULL) || (len == 0)) { + tiot_print_dbg("[TIoT]send data invalid.\n"); + return -1; + } + if (tiot_controller_check_opened(ctrl) != true) { + return -1; + } + return ctrl->ops.write(ctrl, data, len, (const tiot_xfer_tx_param *)param); +} + +int32_t tiot_service_write(tiot_handle handle, const uint8_t *data, uint32_t len) +{ + /* 默认发送subsys为0的数据 */ + const tiot_service_tx_param param = { 0 }; + return tiot_service_write_ext(handle, data, len, ¶m); +} + +int32_t tiot_service_read_ext(tiot_handle handle, uint8_t *buff, uint32_t buff_len, const tiot_service_rx_param *param) +{ + int32_t buff_invalid; + tiot_controller *ctrl = (tiot_controller *)handle; + if (param == NULL) { + tiot_print_dbg("[TIoT]rx param invalid.\n"); + return -1; + } + buff_invalid = (buff == NULL) || (buff_len == 0); +#ifdef __KERNEL__ + /* 用作poll接口时,buff & buff_len可以为空. */ + if (((param->filp == NULL) || (param->poll_wait == NULL)) && (buff_invalid != 0)) { +#else + if (buff_invalid != 0) { +#endif + tiot_print_dbg("[TIoT]read buff invalid.\n"); + return -1; + } + if (tiot_controller_check_opened(ctrl) != true) { + return -1; + } + return ctrl->ops.read(ctrl, buff, buff_len, (const tiot_xfer_rx_param *)param); +} + +int32_t tiot_service_read(tiot_handle handle, uint8_t *buff, uint32_t buff_len, uint32_t timeout_ms) +{ + /* 默认接收queueID为0的数据 */ + /* tiot_service_rx_para结构体有kernel编译宏区分, 不能列表初始化, 否则参数未知. */ + tiot_service_rx_param param = { 0 }; + param.timeout_ms = timeout_ms; + return tiot_service_read_ext(handle, buff, buff_len, ¶m); +} + +int32_t tiot_service_pm_ctrl(tiot_handle handle, tiot_service_pm_ctrl_cmd cmd) +{ + tiot_controller *ctrl = (tiot_controller *)handle; + if (tiot_controller_check_opened(ctrl) != true) { + return -1; + } + if (ctrl->ops.pm_ctrl == NULL) { + tiot_print_err("[TIoT]not support pm_ctrl.\n"); + return -1; + } + return ctrl->ops.pm_ctrl(ctrl, (uint8_t)cmd); +} diff --git a/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface.h b/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface.h new file mode 100644 index 000000000..506a0f54b --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface.h @@ -0,0 +1,108 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-10-24, Create file. \n + */ +#ifndef TIOT_SERVICE_INTERFACE_H +#define TIOT_SERVICE_INTERFACE_H + +#ifdef __KERNEL__ +#include +#include +#include +#else +#include +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_service Service Interface + * @ingroup tiot_common_interface + * @{ + */ + +#define TIOT_READ_TIMEOUT_FOREVER 0xFFFFFFFU /*!< Read wait timeout forever. */ + +typedef uintptr_t tiot_handle; + +typedef struct { + uint8_t *buff; /* 用户需要创建静态buff */ + uint32_t buff_len; + void (*rx_callback)(const uint8_t *buff, uint32_t len); + uint32_t flags; +} tiot_service_open_param; + +/** + * @brief TIoT Service Init interface. + * @return zero if OK; + * -1 if FAIL. + * @note Init for all driver and board. + */ +int32_t tiot_service_init(void); + +/** + * @brief TIoT Service Deinit interface. + * @note Deinit for all driver and board. + */ +void tiot_service_deinit(void); + +/** + * @brief TIoT Service Open interface. + * @param [in] device_name TIoT device compatible string. + * @param [in] param User/Service defined params. + * @return valid handle if OK; + * zero if FAIL. + * @note Must write/read after open. + */ +tiot_handle tiot_service_open(const char *device_name, void *param); + +/** + * @brief TIoT Service Close interface. + * @note Meaningless to return error. + */ +void tiot_service_close(tiot_handle handle); + +/** + * @brief TIoT Service Write Message interface. + * @param [in] data Data need to send. + * @param [in] len Data length. + * @return zero or postive for writen OK length; + * negtive if write FAIL. + * @note Will return after data is sent to board uart interface. + */ +int32_t tiot_service_write(tiot_handle handle, const uint8_t *data, uint32_t len); + +/** + * @brief TIoT Service Read Message interface. + * @param [in/out] buff User read buff. + * @param [in] buff_len User read buff size. + * @param [in] timeout_ms Wait timeout ms. + * @return if read wait timeout(nothing to read), return 0. + * if read fail, return -1. + * if support ASCII message, message type(2 bytes, ASCII or BINARY) and message will be copied to buff, + * else only message will be copied to buff, + * return read length. + * @note This interface will return only single complete message once, + * for continous message read, call this interface repeatly. + */ +int32_t tiot_service_read(tiot_handle handle, uint8_t *buff, uint32_t buff_len, uint32_t timeout_ms); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface_ext.h b/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface_ext.h new file mode 100644 index 000000000..37bcd4158 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/interface/device_interface/tiot_service_interface_ext.h @@ -0,0 +1,98 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: \n + * + * History: \n + * 2024-01-29, Create file. \n + */ +#ifndef TIOT_SERVICE_INTERFACE_EXT_H +#define TIOT_SERVICE_INTERFACE_EXT_H + +#include "tiot_service_interface.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_service_ext Service Interface Ext + * @ingroup tiot_common_interface + * @{ + */ + +/** + * @brief TIoT Tx param, for tiot_service_write_ext. + */ +typedef struct { + uint32_t subsys; /*!< Write for which sub system, varies for different device. */ +} tiot_service_tx_param; + +/** + * @brief TIoT Rx param, for tiot_service_read_ext. + */ +typedef struct { + uint32_t timeout_ms; /*!< Wait timeout ms. */ + uint32_t subsys; /*!< Read for which sub system, varies for different device. */ +#ifdef __KERNEL__ + struct file *filp; /*!< for poll */ + poll_table *poll_wait; /*!< for poll */ +#endif +} tiot_service_rx_param; + +typedef enum { + TIOT_PM_CTRL_SUSPEND_PREPARE, + TIOT_PM_CTRL_SUSPEND, + TIOT_PM_CTRL_RESUME_PREPARE, + TIOT_PM_CTRL_RESUME, + TIOT_PM_CTRL_BUTT +} tiot_service_pm_ctrl_cmd; + +/** + * @brief TIoT Service Write Message extende interface. + * @param [in] data Data need to send. + * @param [in] len Data length. + * @param [in] param Write Param, see @ref tiot_service_tx_param. + * @return zero or postive for writen OK length; + * negtive if write FAIL. + * @note Will return after data is sent to board uart interface. + */ +int32_t tiot_service_write_ext(tiot_handle handle, const uint8_t *data, + uint32_t len, const tiot_service_tx_param *param); + +/** + * @brief TIoT Service Read Message extended interface. + * @param [in/out] buff User read buff. + * @param [in] buff_len User read buff size. + * @param [in] param Read Param, see @ref tiot_service_rx_param. + * @return if read wait timeout(nothing to read), return 0. + * if read fail, return -1. + * if support ASCII message, message type(2 bytes, ASCII or BINARY) and message will be copied to buff, + * else only message will be copied to buff, + * return read length. + * @note This interface will return only single complete message once, + * for continous message read, call this interface repeatly. + */ +int32_t tiot_service_read_ext(tiot_handle handle, uint8_t *buff, uint32_t buff_len, const tiot_service_rx_param *param); + +/** + * @brief TIoT Service Pm Control interface. + * @param [in] handle Service instance handle, should be return by tiot_service_open. + * @param [in] cmd Service pm ctrl cmd. + * @return return 0 if success else return -1. + */ +int32_t tiot_service_pm_ctrl(tiot_handle handle, tiot_service_pm_ctrl_cmd cmd); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/pm/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/pm/CMakeLists.txt new file mode 100644 index 000000000..6d6660d58 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/CMakeLists.txt @@ -0,0 +1,18 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +set( + tiot_pm_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_pm.c + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_pm_wakelock.c +) + +add_subdirectory(pm_default) + +if(DEFINED CONFIG_DEV_TIOT_SLAVE) +add_subdirectory(pm_slave) +endif() + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_pm_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/pm/pm_default/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/pm/pm_default/CMakeLists.txt new file mode 100644 index 000000000..3f3d898cb --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/pm_default/CMakeLists.txt @@ -0,0 +1,7 @@ +set( + tiot_pm_default_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_pm_default.c +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_pm_default_src_list}" CACHE INTERNAL "tiot src list" FORCE) diff --git a/code/sdk/zhihui/gnss/driver/common/pm/pm_default/tiot_pm_default.c b/code/sdk/zhihui/gnss/driver/common/pm/pm_default/tiot_pm_default.c new file mode 100644 index 000000000..01a60ef2c --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/pm_default/tiot_pm_default.c @@ -0,0 +1,288 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT pm default. \n + * + * History: \n + * 2023-06-09, Create file. \n + */ + +#include "tiot_pm_default.h" +#include "tiot_pm_wakelock.h" +#include "tiot_board_pin_port.h" +#include "tiot_board_log.h" +#include "tiot_controller.h" +#include "tiot_xfer_utils.h" +#include "tiot_board.h" +#include "tiot_sys_msg_types.h" +#ifdef CONFIG_PM_WAKEUP_BY_UART +#include "tiot_board_uart_port.h" +#endif + +tiot_pm_retcode tiot_pm_default_power_off(tiot_pm *pm) +{ + if (tiot_board_pin_set_level(pm->pm_info[TIOT_PIN_POWER_CTRL], TIOT_PIN_LEVEL_LOW) != 0) { + return TIOT_PM_EVTRET_FAIL; + } + /* 下电时unlock。 */ + tiot_pm_wake_unlock(); + return TIOT_PM_EVTRET_NEXT_STATE; +} + +tiot_pm_retcode tiot_pm_default_power_on(tiot_pm *pm) +{ + tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm); + const tiot_device_timings *timings = &ctrl->dev_info->timings; + uint32_t power_ctrl_pin = pm->pm_info[TIOT_PIN_POWER_CTRL]; + int32_t ret = 0; + do { + ret = tiot_board_pin_set_level(power_ctrl_pin, TIOT_PIN_LEVEL_LOW); + if (ret != 0) { + tiot_print_err("[TIoT][pm]set pwr pin level low fail.\n"); + break; + } + osal_msleep(timings->power_on_wait_ms); + ret = tiot_board_pin_set_level(power_ctrl_pin, TIOT_PIN_LEVEL_HIGH); + if (ret != 0) { + tiot_print_err("[TIoT][pm]set pwr pin level high fail.\n"); + break; + } + osal_msleep(timings->boot_time_ms); + } while (0); + + if (ret != 0) { + tiot_print_err("[TIoT:pm]power on fail.\n"); + return TIOT_PM_EVTRET_FAIL; + } + /* 上电时lock。 */ + tiot_pm_wake_lock(); + return TIOT_PM_EVTRET_NEXT_STATE; +} + +/* 不可在中断环境下使用. */ +int32_t tiot_pm_check_sleeped(uint32_t wakein_pin, uint8_t check_times) +{ + int32_t ret; + uint8_t level; + uint8_t i; + const uint8_t sleep_check = check_times; /* 等待睡眠,重试check_times次. */ + const uint8_t sleep_wait_ms = 2; /* 等待睡眠,每次等待2ms. */ + /* 唤醒时,如果wakein_pin存在,检查wakein_pin拉低后再发送唤醒, 确保主机已休眠. */ + if (wakein_pin == TIOT_PIN_NONE) { + return 0; + } + for (i = 0; i < sleep_check; i++) { + ret = tiot_board_pin_get_level(wakein_pin, &level); + if (ret != 0) { + tiot_print_err("[TIoT:pm]wakein pin level get error.\n"); + return -1; + } + if (level == TIOT_PIN_LEVEL_LOW) { + return 0; + } + osal_msleep(sleep_wait_ms); + } + /* 此时device侧可能又重新拉高管脚通知有数据上报,保持状态即可, 响应event即转成work. */ + tiot_print_warning("[TIoT:pm]wakein pin level high after check (%d) times.\n", sleep_check); + return -1; +} + +#ifdef CONFIG_PM_WAKEUP_BY_UART +tiot_pm_retcode tiot_pm_default_wakeup_device_by_uart(tiot_pm *pm) +{ + tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm); + int32_t ret; + tiot_print_info("[TIoT][pm]wakeup device enter.\n"); + const uint32_t wakeup_baudrate = 115200; /* UART唤醒时设为115200波特率. */ + const uint8_t wakeup_cmd = 0x00; + const uint8_t check_times = 10; + tiot_xfer_manager *xfer = &ctrl->transfer; + ret = tiot_pm_check_sleeped(pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST], check_times); + if (ret != 0) { + return TIOT_PM_EVTRET_KEEP_STATE; + } + + tiot_uart_config old_config = { 0 }; + tiot_uart_config wakeup_config = { wakeup_baudrate, + { .data_bits = TIOT_UART_ATTR_DATABIT_8, .parity = TIOT_UART_ATTR_PARITY_NONE, + .stop_bits = TIOT_UART_ATTR_STOPBIT_1, .flow_ctrl = TIOT_UART_ATTR_FLOW_CTRL_DISABLE } }; + (void)tiot_xfer_get_config(xfer, &old_config); + (void)tiot_xfer_set_config(xfer, &wakeup_config); + ret = tiot_xfer_direct_send(xfer, &wakeup_cmd, sizeof(uint8_t)); + (void)tiot_xfer_set_config(xfer, &old_config); + if (ret != sizeof(uint8_t)) { + return TIOT_PM_EVTRET_FAIL; + } + return TIOT_PM_EVTRET_NEXT_STATE; +} +#endif + +tiot_pm_retcode tiot_pm_default_wakeup_device_by_gpio(tiot_pm *pm) +{ + int32_t ret; + tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm); + const tiot_device_timings *timings = &ctrl->dev_info->timings; + uint32_t wakeup_device_pin = pm->pm_info[TIOT_PIN_HOST_WAKEUP_DEVICE]; + const uint8_t check_times = 10; + + tiot_print_info("[TIoT][pm]wakeup device enter.\n"); + if (wakeup_device_pin == TIOT_PIN_NONE) { + tiot_print_err("[TIoT][pm]wakeup pin not set.\n"); + return TIOT_PM_EVTRET_FAIL; + } + + ret = tiot_pm_check_sleeped(pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST], check_times); + if (ret != 0) { + return TIOT_PM_EVTRET_KEEP_STATE; + } + + do { + ret = tiot_board_pin_set_level(wakeup_device_pin, TIOT_PIN_LEVEL_LOW); + if (ret != 0) { + tiot_print_err("[TIoT][pm]set wakeup pin level low fail.\n"); + break; + } + osal_msleep(timings->wakeup_pulse_ms); + ret = tiot_board_pin_set_level(wakeup_device_pin, TIOT_PIN_LEVEL_HIGH); + if (ret != 0) { + tiot_print_err("[TIoT][pm]set wakeup pin level high fail.\n"); + break; + } + osal_msleep(timings->wakeup_pulse_ms); + ret = tiot_board_pin_set_level(wakeup_device_pin, TIOT_PIN_LEVEL_LOW); + if (ret != 0) { + tiot_print_err("[TIoT][pm]set wakeup pin level low fail.\n"); + break; + } + } while (0); + + if (ret != 0) { + return TIOT_PM_EVTRET_FAIL; + } + return TIOT_PM_EVTRET_NEXT_STATE; +} + +#ifdef CONFIG_PM_MANAGE_LOWPOWER +tiot_pm_retcode tiot_pm_default_request_sleep_handle(tiot_pm *pm) +{ + const uint8_t allow_sleep_command[] = { 0x7e, 0x00, 0x06, 0x00, + SYS_PL_BFGNI_HOST_ASKTO_SLP, + 0x7e }; + int32_t ret; + tiot_controller *ctrl = NULL; + tiot_xfer_manager *xfer = NULL; + if (pm->work_vote == 1) { + return TIOT_PM_EVTRET_KEEP_STATE; + } + ctrl = tiot_container_of(pm, tiot_controller, pm); + xfer = &ctrl->transfer; + ret = xfer->xmit_ops->write(&xfer->xmit, allow_sleep_command, sizeof(allow_sleep_command)); + if (ret != sizeof(allow_sleep_command)) { + tiot_print_alert("[TIoT:fatal]send allow sleep msg fail.\r\n"); + return TIOT_PM_EVTRET_FAIL; + } + tiot_print_info("[TIoT][pm]allow device sleep.\n"); + return TIOT_PM_EVTRET_NEXT_STATE; +} + +tiot_pm_retcode tiot_pm_default_sleep_ack_handle(tiot_pm *pm) +{ + tiot_unused(pm); + /* device侧睡眠时可睡眠 */ + tiot_pm_wake_unlock(); + tiot_print_info("[TIoT][pm]goes to sleep.\n"); + return TIOT_PM_EVTRET_NEXT_STATE; +} + +/* + * 非S3状态,由于在中断中无法等待Sleep Ack(dev wkup host gpio拉低), + * 所以在下发allow sleep消息后,就立刻释放唤醒锁进入睡眠。 + */ +tiot_pm_retcode tiot_pm_default_request_sleep_ack_handle(tiot_pm *pm) +{ + tiot_pm_retcode ret = tiot_pm_default_request_sleep_handle(pm); + if (ret != TIOT_PM_EVTRET_NEXT_STATE) { + return ret; + } + return tiot_pm_default_sleep_ack_handle(pm); +} + +int32_t tiot_pm_send_disallow_sleep(tiot_xfer_manager *xfer) +{ + const uint8_t disallow_sleep_command[] = { 0x7e, 0x00, 0x06, 0x00, + SYS_PL_BFGNI_HOST_DISALLOW_DEVSLP, + 0x7e }; + int32_t ret; + ret = xfer->xmit_ops->write(&xfer->xmit, disallow_sleep_command, sizeof(disallow_sleep_command)); + if (ret != sizeof(disallow_sleep_command)) { + tiot_print_alert("[TIoT:fatal]send disallow msg fail.\r\n"); + return -1; + } + return 0; +} + +tiot_pm_retcode tiot_pm_default_wakeup_ack_handle(tiot_pm *pm) +{ + int32_t ret; + uint8_t input_level = TIOT_PIN_LEVEL_LOW; + uint16_t pre_state = pm->state; + tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm); + tiot_xfer_manager *xfer = &ctrl->transfer; + uint32_t wakeup_host_pin = pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST]; + + if (wakeup_host_pin == TIOT_PIN_NONE) { + tiot_print_err("[TIoT][pm]wakeup ack event called but dev_wk_host pin is none.\n"); + return TIOT_PM_EVTRET_KEEP_STATE; + } + + /* + * host上电后处于INIT状态时,此时接收到device拉高wakeup_host gpio,则不能下发disallow消息, + * 否则会多lock()一次,导致host后续无法睡下去。 + */ + if (pre_state == TIOT_PM_STATE_INIT) { + /* INIT -> WORK */ + return TIOT_PM_EVTRET_NEXT_STATE; + } + + /* 有数据上报时不睡眠 */ + /* 自唤醒流程: device_wake_out --> wake_lock -......-> request_sleep --> wake_unlock */ + /* 当前在唤醒中断内持锁,并直接回复disallow消息。 */ + + /* check wakeup_ack */ + ret = tiot_board_pin_get_level(wakeup_host_pin, &input_level); + if ((ret != 0) || (input_level == TIOT_PIN_LEVEL_LOW)) { + tiot_print_err("[TIoT][pm]get dev_wk_host pin level fail or false positive [state:0x%x].\n", pre_state); + return TIOT_PM_EVTRET_KEEP_STATE; + } + /* 使用临时flag区分suspend. */ + if (xfer->xmit_suspend & TIOT_XFER_SUSPEND) { + tiot_print_info("[TIoT:pm]delay disallow msg [state:0x%x].\n", pre_state); + xfer->xmit_suspend |= TIOT_XFER_DELAY_MSG; + } else { + tiot_print_info("[TIoT][pm]send disallow sleep msg [state:0x%x].\n", pre_state); + if (tiot_pm_send_disallow_sleep(xfer) != 0) { + return TIOT_PM_EVTRET_FAIL; + } + } + if ((pre_state == TIOT_PM_STATE_SLEEP) || (pre_state == TIOT_PM_STATE_WAKING)) { + tiot_pm_wake_lock(); + } + return TIOT_PM_EVTRET_NEXT_STATE; +} + +tiot_pm_retcode tiot_pm_default_work_vote_up(tiot_pm *pm) +{ + /* 发送时不睡眠 */ + tiot_pm_wake_lock(); + pm->work_vote = 1; + return TIOT_PM_EVTRET_KEEP_STATE; +} + +tiot_pm_retcode tiot_pm_default_work_vote_down(tiot_pm *pm) +{ + pm->work_vote = 0; + /* 发送结束后可睡眠 */ + tiot_pm_wake_unlock(); + return TIOT_PM_EVTRET_KEEP_STATE; +} +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/pm/pm_default/tiot_pm_default.h b/code/sdk/zhihui/gnss/driver/common/pm/pm_default/tiot_pm_default.h new file mode 100644 index 000000000..b9d4f9f61 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/pm_default/tiot_pm_default.h @@ -0,0 +1,110 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT pm default. \n + * + * History: \n + * 2023-06-09, Create file. \n + */ +#ifndef TIOT_PM_DEFAULT_H +#define TIOT_PM_DEFAULT_H + +#include "tiot_pm.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_pm_default PM Default Handlers + * @ingroup tiot_common_pm + * @{ + */ + +/** + * @brief Default power off handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_power_off(tiot_pm *pm); + +/** + * @brief Default power on handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_power_on(tiot_pm *pm); + +#ifdef CONFIG_PM_WAKEUP_BY_UART +/** + * @brief Default wakeup by uart handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_wakeup_device_by_uart(tiot_pm *pm); +#endif + +/** + * @brief Default wakeup by gpio handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_wakeup_device_by_gpio(tiot_pm *pm); + +#ifdef CONFIG_PM_MANAGE_LOWPOWER +/** + * @brief Default request sleep handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_request_sleep_handle(tiot_pm *pm); + +/** + * @brief Default sleep ack handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_sleep_ack_handle(tiot_pm *pm); + +/** + * @brief Default request sleep ack handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_request_sleep_ack_handle(tiot_pm *pm); + +/** + * @brief Default wakeup ack handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_wakeup_ack_handle(tiot_pm *pm); + +/** + * @brief Default work vote up handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_work_vote_up(tiot_pm *pm); + +/** + * @brief Default work vote down handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_default_work_vote_down(tiot_pm *pm); +#endif + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/CMakeLists.txt new file mode 100644 index 000000000..cdc63caba --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/CMakeLists.txt @@ -0,0 +1,7 @@ +set( + tiot_pm_slave_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_pm_slave.c +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_pm_slave_src_list}" CACHE INTERNAL "tiot src list" FORCE) diff --git a/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/tiot_pm_slave.c b/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/tiot_pm_slave.c new file mode 100644 index 000000000..7e8669b36 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/tiot_pm_slave.c @@ -0,0 +1,139 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: TIoT pm slave. \n + * + * History: \n + * 2024-02-28, Create file. \n + */ +#include "tiot_pm_slave.h" +#include "tiot_pm_wakelock.h" +#include "tiot_board_pin_port.h" +#include "tiot_board_log.h" +#include "tiot_controller.h" +#include "tiot_sys_msg_types.h" +#include "tiot_packet.h" +#include "tiot_board.h" + +tiot_pm_retcode tiot_pm_slave_power_off(tiot_pm *pm) +{ + tiot_unused(pm); + tiot_pm_wake_unlock(); + tiot_print_info("[TIoT][pm]power off.\r\n"); + return TIOT_PM_EVTRET_NEXT_STATE; +} + +tiot_pm_retcode tiot_pm_slave_power_on(tiot_pm *pm) +{ + tiot_unused(pm); + tiot_pm_wake_lock(); + tiot_print_info("[TIoT][pm]power on.\r\n"); + return TIOT_PM_EVTRET_NEXT_STATE; +} + +tiot_pm_retcode tiot_pm_slave_wakeup_handle(tiot_pm *pm) +{ + /* Only SLEEP -> WAKING */ + uint32_t wakeup_in_pin; + uint32_t wakeup_out_pin; + tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm); + const tiot_device_timings *timings = &ctrl->dev_info->timings; + + if (pm->state != TIOT_PM_STATE_SLEEP) { + return TIOT_PM_EVTRET_KEEP_STATE; + } + + tiot_pm_wake_lock(); + + wakeup_out_pin = pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST]; + if (wakeup_out_pin != TIOT_PIN_NONE) { + if (tiot_board_pin_set_level(wakeup_out_pin, TIOT_PIN_LEVEL_LOW) != 0) { + tiot_print_err("[TIoT:pm]wakeout pin set level low fail.\r\n"); + goto wakeout_fail; + } + osal_msleep(timings->wakeup_pulse_ms); + if (tiot_board_pin_set_level(wakeup_out_pin, TIOT_PIN_LEVEL_HIGH) != 0) { + tiot_print_err("[TIoT:pm]wakeout pin set level high fail.\r\n"); + goto wakeout_fail; + } + } else { + tiot_print_warning("[TIoT][pm]wakeout pin is invalid.\r\n"); + } + /* 唤醒host/唤醒ack后关闭唤醒源中断使能. */ + wakeup_in_pin = pm->pm_info[TIOT_PIN_HOST_WAKEUP_DEVICE]; + tiot_board_pin_enable_int(wakeup_in_pin, TIOT_PIN_INT_DISABLE); + return TIOT_PM_EVTRET_NEXT_STATE; +wakeout_fail: + tiot_pm_wake_unlock(); + return TIOT_PM_EVTRET_FAIL; +} + +#ifdef CONFIG_PM_MANAGE_LOWPOWER +/* 不允许在中断环境下调用 */ +tiot_pm_retcode tiot_pm_slave_request_sleep_handle(tiot_pm *pm) +{ + int32_t ret; + tiot_controller *ctrl = tiot_container_of(pm, tiot_controller, pm); + tiot_xfer_manager *xfer = &ctrl->transfer; + const uint8_t request_sleep_command = SYS_INF_REQUEST_SLEEP; + tiot_xfer_tx_param tx_param = { SUBSYS_SYS }; + + tiot_print_info("[TIoT][pm]request sleep enter.\n"); + + ret = tiot_xfer_send(xfer, &request_sleep_command, sizeof(request_sleep_command), &tx_param); + if (ret != sizeof(request_sleep_command)) { + tiot_print_err("[TIoT][pm]send request sleep msg fail.\r\n"); + return TIOT_PM_EVTRET_FAIL; + } + + return TIOT_PM_EVTRET_NEXT_STATE; +} + +tiot_pm_retcode tiot_pm_slave_sleep_ack_handle(tiot_pm *pm) +{ + uint32_t wakeup_in_pin; + uint32_t wakeup_out_pin; + /* When we reporting msg, ignore allow sleep msg. */ + if (pm->work_vote == 1) { + return TIOT_PM_EVTRET_KEEP_STATE; + } + + wakeup_out_pin = pm->pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST]; + /* 睡眠前,slave侧拉低唤醒主机管脚. */ + if (wakeup_out_pin != TIOT_PIN_NONE) { + if (tiot_board_pin_set_level(wakeup_out_pin, TIOT_PIN_LEVEL_LOW) != 0) { + tiot_print_err("[TIoT][pm]wakeup_out_pin set low fail.\r\n"); + return TIOT_PM_EVTRET_FAIL; + } + } + /* 进睡眠前 打开唤醒源中断使能. */ + wakeup_in_pin = pm->pm_info[TIOT_PIN_HOST_WAKEUP_DEVICE]; + tiot_board_pin_enable_int(wakeup_in_pin, TIOT_PIN_INT_ENABLE); + tiot_print_info("[TIoT][pm]goes to sleep.\r\n"); + /* 移除否决票 */ + tiot_pm_wake_unlock(); + return TIOT_PM_EVTRET_NEXT_STATE; +} + +tiot_pm_retcode tiot_pm_slave_wakeup_ack_handle(tiot_pm *pm) +{ + tiot_unused(pm); + tiot_print_info("[TIoT][pm]wakeup succ.\r\n"); + return TIOT_PM_EVTRET_NEXT_STATE; +} + +tiot_pm_retcode tiot_pm_slave_work_vote_up(tiot_pm *pm) +{ + /* Prevent sleeping while sending data. */ + tiot_pm_wake_lock(); + pm->work_vote = 1; + return TIOT_PM_EVTRET_KEEP_STATE; +} + +tiot_pm_retcode tiot_pm_slave_work_vote_down(tiot_pm *pm) +{ + pm->work_vote = 0; + tiot_pm_wake_unlock(); + return TIOT_PM_EVTRET_KEEP_STATE; +} +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/tiot_pm_slave.h b/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/tiot_pm_slave.h new file mode 100644 index 000000000..7c15a973f --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/pm_slave/tiot_pm_slave.h @@ -0,0 +1,95 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: TIoT pm slave. \n + * + * History: \n + * 2024-02-28, Create file. \n + */ +#ifndef TIOT_PM_SLAVE_H +#define TIOT_PM_SLAVE_H + +#include "tiot_pm.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_pm_slave PM Slave Handlers + * @ingroup tiot_common_pm + * @{ + */ + +/** + * @brief Slave power off handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_slave_power_off(tiot_pm *pm); + +/** + * @brief Slave power on handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_slave_power_on(tiot_pm *pm); + +/** + * @brief Slave wakeup by gpio handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_slave_wakeup_handle(tiot_pm *pm); + +#ifdef CONFIG_PM_MANAGE_LOWPOWER +/** + * @brief Slave request sleep handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_slave_request_sleep_handle(tiot_pm *pm); + +/** + * @brief Slave sleep ack handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_slave_sleep_ack_handle(tiot_pm *pm); + +/** + * @brief Slave wakeup ack handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_slave_wakeup_ack_handle(tiot_pm *pm); + +/** + * @brief Slave work vote up handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_slave_work_vote_up(tiot_pm *pm); + +/** + * @brief Slave work vote down handler. + * @param [in] pm PM control block. + * @return see@ref tiot_pm_retcode. + */ +tiot_pm_retcode tiot_pm_slave_work_vote_down(tiot_pm *pm); + +#endif + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm.c b/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm.c new file mode 100644 index 000000000..10a51fe9e --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm.c @@ -0,0 +1,149 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Power Manager module. \n + * + * History: \n + * 2023-03-27, Create file. \n + */ + +#include "tiot_pm.h" +#include "tiot_pm_wakelock.h" +#include "tiot_osal.h" +#include "securec.h" +#include "tiot_controller.h" +#include "tiot_board_log.h" + +typedef struct { + tiot_pm *pm; + uint16_t state; +} pm_wait_state; + +/* 传入的event_map必须为静态申请数组 */ +int32_t tiot_pm_init(tiot_pm *pm, const uint32_t *pm_info, + const tiot_pm_event_entry *event_map, uint8_t event_map_size) +{ + if ((pm == NULL) || (pm_info == NULL) || (event_map == NULL) || (event_map_size == 0)) { + tiot_print_dbg("[TIoT][pm]pm or pm info or event_map is NULL.\n"); + return -1; + } + if (osal_wait_init(&pm->state_wait) != OSAL_SUCCESS) { + tiot_print_err("[TIoT][pm]pm wait init fail.\n"); + return -1; + } + + /* 外部确保为静态变量 */ + pm->pm_info = pm_info; + pm->event_map = event_map; + pm->event_map_size = event_map_size; + + /* 此队列仅用于处理中断内产生pm事件情况,按产生顺序排序,预计不会同时在多个中断内产生pm事件,预留8个已经足够. */ + (void)memset_s(pm->event_queue_buff, TIOT_PM_EVENT_BUFF_MAX, 0, TIOT_PM_EVENT_BUFF_MAX); + tiot_circ_queue_init(&pm->event_queue, TIOT_PM_EVENT_BUFF_MAX, + sizeof(tiot_pm_event), (uintptr_t)pm->event_queue_buff); + pm->is_in_event = 0; + pm->work_vote = 0; + pm->state = TIOT_PM_STATE_POWEROFF; + return 0; +} + +static int32_t tiot_pm_handle_event(tiot_pm *pm, tiot_pm_event event) +{ + tiot_pm_retcode ret = TIOT_PM_EVTRET_NEXT_STATE; + /* 取对应事件的 [判断条件 - 执行处理 - 设置下个状态] 流程 */ + const tiot_pm_event_entry *entry = &pm->event_map[event]; + + /* 当前状态不符合tag mask条件, 不需要处理,直接返回OK */ + if ((pm->state & entry->condition_mask) == 0) { + tiot_print_dbg("[TIoT][pm]state %x not match condition %x, ignore event\n", pm->state, entry->condition_mask); + return 0; + } + + /* pm处理过程持唤醒锁,防止pm未转换完状态就直接进sleep。 */ + tiot_pm_wake_lock(); + + /* 当前状态符合tag mask条件,执行对应事件处理 */ + /* 约定:handler为空不需要处理,例如上报业务消息说明芯片处于WORK状态,只需要切换状态即可 */ + if (entry->handler != NULL) { + ret = entry->handler(pm); + } + + if (ret == TIOT_PM_EVTRET_NEXT_STATE) { + /* 处理成功,设为下一个状态 */ + tiot_print_dbg("[TIoT][pm]evt:%x, st:%x, next_st: %x.\n", event, pm->state, entry->next_state); + pm->state = entry->next_state; + /* 切换状态时保证设置event. */ + osal_wait_wakeup_interruptible(&pm->state_wait); + } else if (ret == TIOT_PM_EVTRET_FAIL) { + /* 处理失败,返回false. */ + tiot_print_dbg("[TIoT][pm]evt:%x, st:%x, event fail.\n", event, pm->state); + tiot_pm_wake_unlock(); + return -1; + } else { /* ret == TIOT_PM_EVTRET_KEEP_STATE */ + /* 处理成功,保持当前状态 */ + tiot_print_dbg("[TIoT][pm]evt:%x, st:%x, keep state.\n", event, pm->state); + } + tiot_pm_wake_unlock(); + + return 0; +} + +int32_t tiot_pm_set_event(tiot_pm *pm, tiot_pm_event event) +{ + int32_t ret; + tiot_pm_event *event_node; + + if ((pm == NULL) || (event >= TIOT_PM_EVENT_MAX) || (event >= pm->event_map_size)) { + tiot_print_dbg("[TIoT][pm]pm is NULL or illegal event.\n"); + return -1; + } + + tiot_circ_queue_enqueue(&pm->event_queue, (uintptr_t)&event); + /* 依靠队列防止pm事件处理嵌套,此处不使用互斥锁(可能在中断内产生事件),也不使用自旋锁(不能保证提供自旋锁) */ + if (pm->is_in_event == 1) { + return 0; + } + + do { + event_node = (tiot_pm_event *)tiot_circ_queue_dequeue(&pm->event_queue); + if (event_node == NULL) { + return 0; + } + pm->is_in_event = 1; + ret = tiot_pm_handle_event(pm, *event_node); + pm->is_in_event = 0; + if (ret != 0) { + tiot_circ_queue_clear(&pm->event_queue); + break; + } + } while (event_node != NULL); + + return ret; +} + +static int pm_wait_state_condition(const void *param) +{ + pm_wait_state *wait_state = (pm_wait_state *)param; + return (wait_state->pm->state == wait_state->state); +} + +int32_t tiot_pm_wait_state(tiot_pm *pm, uint16_t state, uint32_t wait_timeout) +{ + pm_wait_state wait_state = { 0 }; + if (state == TIOT_PM_STATE_INVALID) { + return -1; + } + wait_state.pm = pm; + wait_state.state = state; + return osal_wait_timeout_interruptible(&pm->state_wait, pm_wait_state_condition, &wait_state, wait_timeout); +} + +void tiot_pm_deinit(tiot_pm *pm) +{ + tiot_circ_queue_clear(&pm->event_queue); + osal_spin_lock_destroy(&pm->event_queue.lock); + osal_wait_destroy(&pm->state_wait); + (void)memset_s(pm->event_queue_buff, TIOT_PM_EVENT_BUFF_MAX, 0, TIOT_PM_EVENT_BUFF_MAX); + pm->state = TIOT_PM_STATE_INVALID; + pm->work_vote = 0; +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm.h b/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm.h new file mode 100644 index 000000000..587d6c714 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm.h @@ -0,0 +1,182 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Power Manager module header. \n + * + * History: \n + * 2023-03-27, Create file. \n + */ +#ifndef TIOT_PM_H +#define TIOT_PM_H + +#include "tiot_types.h" +#include "tiot_circ_queue.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_pm Power Manager + * @ingroup tiot_common + * @{ + */ + +#define TIOT_PM_EVENT_BUFF_MAX 8 + +/** + * @brief TIoT PM tags. + */ +typedef enum { + TIOT_PM_TAG_INVALID = 0, /*!< Invalid PM tag. */ + TIOT_PM_TAG_POWEROFF = ((uint16_t)1 << 0), /*!< Power off tag. */ + TIOT_PM_TAG_POWERON = ((uint16_t)1 << 1), /*!< Power on tag. */ + /* Low power tags. */ + TIOT_PM_TAG_CAN_WORK = ((uint16_t)1 << 2), /*!< Low power can work tag. */ + TIOT_PM_TAG_CAN_SLEEP = ((uint16_t)1 << 3), /*!< Low power can sleep tag. */ + TIOT_PM_TAG_CAN_WAKEUP = ((uint16_t)1 << 4), /*!< Low power can wakeup tag. */ + TIOT_PM_TAG_CAN_ALLOW_SLEEP = ((uint16_t)1 << 5), /*!< Low power can allow sleep tag. */ + TIOT_PM_TAG_MAX = (uint16_t)0xFFFF /* PM tag max. */ +} tiot_pm_tag; + +/** + * @brief TIoT PM states. + */ +typedef enum { + TIOT_PM_STATE_INVALID = 0, /*!< Invalid PM state. */ + TIOT_PM_STATE_POWEROFF = TIOT_PM_TAG_POWEROFF, /*!< Power off state. */ + TIOT_PM_STATE_POWERON = TIOT_PM_TAG_POWERON, /*!< Power on state. */ + /* Low power states */ + /*!< Low power init state, can work, can sleep. */ + TIOT_PM_STATE_INIT = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_WORK | TIOT_PM_TAG_CAN_SLEEP, + /*!< Low power work state, can sleep, can allow sleep. */ + /*!< Host: WORK -> SLEEPING -> SLEEP (正常睡眠流程,等待sleep ack) + WORK -> SLEEP (非S3状态,不等待sleep ack) + Device: WORK -> SLEEPING -> SLEEP (Device主动请求睡眠) + WORK -> SLEEP (S3状态,Host强制要求睡眠) */ + TIOT_PM_STATE_WORK = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_SLEEP | TIOT_PM_TAG_CAN_ALLOW_SLEEP, + /*!< Low power sleep state, can work, can be waked up. */ + TIOT_PM_STATE_SLEEP = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_WORK | TIOT_PM_TAG_CAN_WAKEUP, + /*!< Low power waking state, can be waked up. */ + TIOT_PM_STATE_WAKING = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_WAKEUP, + /*!< Low power sleeping state, can allow sleep. */ + TIOT_PM_STATE_SLEEPING = TIOT_PM_TAG_POWERON | TIOT_PM_TAG_CAN_SLEEP +} tiot_pm_state; + +/** + * @brief Tiot PM event types. + */ +typedef enum { + /* OUTPUT */ + TIOT_PM_EVENT_POWEROFF, /*!< Power off. */ + TIOT_PM_EVENT_POWERON, /*!< Power on. */ + TIOT_PM_EVENT_WAKEUP, /*!< Host: wakeup device. + Device: wakeup host(pull up dev_wkup_host gpio). */ + /* INPUT,for host to manage device lowpower */ + TIOT_PM_EVENT_WAKEUP_ACK, /*!< Host: send disallow sleep cmd to ack(device wakeup host). + Device: handle the ack of disallow sleep cmd. */ + TIOT_PM_EVENT_REQUEST_SLEEP, /*!< Host: send allow sleep cmd. + Device: send request sleep cmd to request sleep. */ + TIOT_PM_EVENT_SLEEP_ACK, /*!< Host: handle the ack of allow sleep cmd. + Device: pull down dev_wkup_host gpio to ack (host allow sleep cmd). */ + TIOT_PM_EVENT_REQUEST_SLEEP_ACK, /*!< Combine TIOT_PM_EVENT_REQUEST_SLEEP and TIOT_PM_EVENT_SLEEP_ACK */ + TIOT_PM_EVENT_REPORT_WORK, /*!< Device transmit port report message. */ + /* Vote */ + TIOT_PM_EVENT_WORK_VOTE_UP, /*!< Host keep device at work state. */ + TIOT_PM_EVENT_WORK_VOTE_DOWN, /*!< Host not keep device at work state. */ + TIOT_PM_EVENT_MAX +} tiot_pm_event; + +/** + * @brief Tiot PM event retcode. + */ +typedef enum { + TIOT_PM_EVTRET_FAIL = -1, /* Event handle failed. */ + TIOT_PM_EVTRET_NEXT_STATE = 0, /* Change to next state. */ + TIOT_PM_EVTRET_KEEP_STATE = 1, /* Keep current state. */ +} tiot_pm_retcode; + +struct _tiot_pm; + +/** + * @brief Tiot PM event handler. + */ +typedef tiot_pm_retcode (* tiot_pm_event_handler)(struct _tiot_pm *pm); + +/** + * @brief Tiot PM event handle entry. + */ +typedef struct { + uint16_t condition_mask; /*!< Enter event condition, could be combination of PM tags. */ + uint16_t next_state; /*!< Next PM state. */ + tiot_pm_event_handler handler; /*!< PM event handler, NULL mean this event don't need operation. */ +} tiot_pm_event_entry; + +/** + * @brief Tiot PM control block. + */ +typedef struct _tiot_pm { + uint16_t state; /*!< Current PM state. */ + uint16_t work_vote; /*!< Host require device work vote. */ + const uint32_t *pm_info; /*!< PM board info, pin indexs. */ + osal_wait state_wait; /*!< PM state wait, used for wait some state. */ + tiot_circ_queue_t event_queue; /*!< PM event queue for syncing events. */ + /*!< PM event queue buffer. */ + tiot_pm_event event_queue_buff[TIOT_PM_EVENT_BUFF_MAX]; + volatile uint8_t is_in_event; /*!< PM event processing. */ + uint8_t event_map_size; /*!< PM event handle map size. */ + /*!< PM event handle map, must point to static allocated array. */ + const tiot_pm_event_entry *event_map; +} tiot_pm; + +/** + * @brief PM control block init. + * @param [in] pm PM control block. + * @param [in] pm_info Pointer to board PM info, static allocated, from device saved board info. + * @param [in] event_map Registed PM event handle map, static allocated, from *_device_info.c. + * @param [in] event_map_size Registed PM event handle map size. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_pm_init(tiot_pm *pm, const uint32_t *pm_info, + const tiot_pm_event_entry *event_map, uint8_t event_map_size); + +/** + * @brief Set event to PM control block. + * @param [in] pm PM control block. + * @param [in] event PM event. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_pm_set_event(tiot_pm *pm, tiot_pm_event event); + +/** + * @brief PM control block wait for state. + * @param [in] pm PM control block. + * @param [in] state PM state,caller must ensure state is valid. + * @param [in] wait_timeout Wait timeout, shound not be too long. + * @return negative if wait state fail; + * zero if wait state timeout; + * postive if wait state OK. + */ +int32_t tiot_pm_wait_state(tiot_pm *pm, uint16_t state, uint32_t wait_timeout); + +/** + * @brief PM control block deinit. + * @param [in] pm PM control block. + */ +void tiot_pm_deinit(tiot_pm *pm); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm_wakelock.c b/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm_wakelock.c new file mode 100644 index 000000000..1101a77af --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm_wakelock.c @@ -0,0 +1,72 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: \n + * + * History: \n + * 2024-03-01, Create file. \n + */ +#include "tiot_pm_wakelock.h" +#include "tiot_board_misc_port.h" +#include "tiot_board_log.h" +#include "tiot_osal.h" + +/* 所有controller共享同一个wakelock, 只有所有controller未持锁时才允许睡眠. */ +static tiot_board_wakelock g_top_wakelock; +static osal_spinlock g_top_wakelock_spinlock; +static uint16_t g_top_lock_count; + +int32_t tiot_pm_wake_lock_init(void) +{ + if (tiot_board_wake_lock_init(&g_top_wakelock) != 0) { + return -1; + } + if (osal_spin_lock_init(&g_top_wakelock_spinlock) != OSAL_SUCCESS) { + tiot_board_wake_lock_destroy(&g_top_wakelock); + return -1; + } + g_top_lock_count = 0; + return 0; +} + +void tiot_pm_wake_lock(void) +{ + unsigned long flags; + osal_spin_lock_irqsave(&g_top_wakelock_spinlock, &flags); + if (g_top_lock_count == 0) { + tiot_board_wake_lock(&g_top_wakelock); + } + g_top_lock_count++; + osal_spin_unlock_irqrestore(&g_top_wakelock_spinlock, &flags); +} + +void tiot_pm_wake_unlock(void) +{ + unsigned long flags; + osal_spin_lock_irqsave(&g_top_wakelock_spinlock, &flags); + if (g_top_lock_count > 0) { + g_top_lock_count--; + /* 防止count为0时多次调用unlock接口。 */ + if (g_top_lock_count == 0) { + tiot_board_wake_unlock(&g_top_wakelock); + } + } + osal_spin_unlock_irqrestore(&g_top_wakelock_spinlock, &flags); +} + +void tiot_pm_wake_lock_destroy(void) +{ + /* 确保destroy时一定释放。 */ + unsigned long flags; + osal_spin_lock_irqsave(&g_top_wakelock_spinlock, &flags); + if (g_top_lock_count > 0) { + tiot_print_err("[TIoT][wakelock]g_top_lock_count should be 0, but is %d\n", g_top_lock_count); + g_top_lock_count = 0; + tiot_board_wake_unlock(&g_top_wakelock); + } + osal_spin_unlock_irqrestore(&g_top_wakelock_spinlock, &flags); + + tiot_board_wake_lock_destroy(&g_top_wakelock); + osal_spin_lock_destroy(&g_top_wakelock_spinlock); +} + diff --git a/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm_wakelock.h b/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm_wakelock.h new file mode 100644 index 000000000..f29b86a0c --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/pm/tiot_pm_wakelock.h @@ -0,0 +1,74 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: \n + * + * History: \n + * 2024-03-01, Create file. \n + */ +#ifndef TIOT_PM_WAKELOCK_H +#define TIOT_PM_WAKELOCK_H + +#include "tiot_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_pm_wakelock PM Wake Lock + * @ingroup tiot_common_pm + * @{ + */ + +/** + * @if Eng + * @brief PM wake lock initialization interface. + * @return if OK return 0, else return -1. + * @else + * @brief PM唤醒锁初始化接口。 + * @return 初始化成功返回0,否则返回-1。 + * @endif + */ +int32_t tiot_pm_wake_lock_init(void); + +/** + * @if Eng + * @brief PM wake lock interface, support nested, pair with unlock. + * @else + * @brief PM唤醒锁接口,支持嵌套使用,需要和unlock配对。 + * @endif + */ +void tiot_pm_wake_lock(void); + +/** + * @if Eng + * @brief PM wake unlock interface, support nested, pair with unlock. + * @else + * @brief PM唤醒解锁接口,支持嵌套使用,需要和lock配对。 + * @endif + */ +void tiot_pm_wake_unlock(void); + +/** + * @if Eng + * @brief PM wake lock destroy interface. + * @else + * @brief PM唤醒锁销毁接口。 + * @endif + */ +void tiot_pm_wake_lock_destroy(void); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/CMakeLists.txt new file mode 100644 index 000000000..9631fb6f9 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/CMakeLists.txt @@ -0,0 +1,14 @@ +set( + tiot_sys_msg_handler_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_sys_msg_handle.c +) + +if(DEFINED CONFIG_DEV_TIOT_SLAVE) +list( + APPEND tiot_sys_msg_handler_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_sys_msg_slave_handle.c +) +endif() + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_sys_msg_handler_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.c b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.c new file mode 100644 index 000000000..f72d88c2f --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.c @@ -0,0 +1,24 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-02-29, Create file. \n + */ +#include "tiot_sys_msg_handle.h" +#include "tiot_sys_msg_types.h" +#include "tiot_pm.h" +#include "tiot_board_log.h" + +void tiot_pkt_sys_msg_handle(tiot_controller *ctrl, uint8_t code) +{ + if ((code == SYS_INF_GNSS_INIT) || (code == SYS_INF_GNSS_LPPE_INIT)) { + tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_REPORT_WORK); + } else if (code == SYS_INF_REQUEST_SLEEP) { + tiot_print_info("[TIoT:pkt]recv request sleep\n"); + tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_REQUEST_SLEEP_ACK); + } else { + tiot_print_warning("[TIoT:pkt]recv unknown sys msg:0x%x\n", code); + } +} diff --git a/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.h b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.h new file mode 100644 index 000000000..154645ab4 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_handle.h @@ -0,0 +1,30 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-02-29, Create file. \n + */ +#ifndef TIOT_SYS_MSG_HANDLE_H +#define TIOT_SYS_MSG_HANDLE_H + +#include "tiot_controller.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +void tiot_pkt_sys_msg_handle(tiot_controller *ctrl, uint8_t code); + +void tiot_pkt_sys_msg_slave_handle(tiot_controller *ctrl, uint8_t code); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_slave_handle.c b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_slave_handle.c new file mode 100644 index 000000000..7b359ff6f --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_slave_handle.c @@ -0,0 +1,30 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-02-29, Create file. \n + */ +#include "tiot_sys_msg_handle.h" +#include "tiot_sys_msg_types.h" +#include "tiot_slave_board_port.h" +#include "tiot_pm_slave.h" +#include "tiot_board_log.h" + +void tiot_pkt_sys_msg_slave_handle(tiot_controller *ctrl, uint8_t code) +{ + switch (code) { + case SYS_PL_BFGNI_HOST_ASKTO_SLP: + tiot_print_info("[TIoT:pkt]recv allow sleep.\n"); + tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_SLEEP_ACK); + break; + case SYS_PL_BFGNI_HOST_DISALLOW_DEVSLP: + tiot_print_info("[TIoT:pkt]recv disallow sleep.\n"); + tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_WAKEUP_ACK); + break; + default: + tiot_print_warning("[TIoT:pkt]recv unknown sys msg:0x%x\n", code); + break; + } +} diff --git a/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_types.h b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_types.h new file mode 100644 index 000000000..7c5cb36d3 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/sys_msg_handler/tiot_sys_msg_types.h @@ -0,0 +1,139 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: TIoT sys msg types. \n + * + * History: \n + * 2024-03-11, Create file. \n + */ +#ifndef TIOT_SYS_MSG_TYPES_H +#define TIOT_SYS_MSG_TYPES_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_types TIoT sys msg types. + * @ingroup tiot_common_interface + * @{ + */ +enum SYS_INF_MSG_VALUE_ENUM { + SYS_INF_PF_INIT = 0x00, /* 平台软件初始化完成 */ + SYS_INF_BT_INIT = 0x01, /* BT软件初始化完成 */ + SYS_INF_GNSS_INIT = 0x02, /* GNSS软件初始化完成 */ + SYS_INF_FM_INIT = 0x03, /* FM软件初始化完成 */ + SYS_INF_BT_DISABLE = 0x04, /* BT禁能 */ + SYS_INF_GNSS_DISABLE = 0x05, /* GNSS禁能 */ + SYS_INF_FM_DISABLE = 0x06, /* FM禁能 */ + SYS_INF_BT_EXIT = 0x07, /* BT退出 */ + SYS_INF_GNSS_EXIT = 0x08, /* GNSS退出 */ + SYS_INF_FM_EXIT = 0x09, /* FM退出 */ + SYS_INF_GNSS_WAIT_DOWNLOAD = 0x0A, /* 等待GNSS代码下载 */ + SYS_INF_GNSS_DOWNLOAD_COMPLETE = 0x0B, /* GNSS代码下载完毕 */ + SYS_INF_BFG_HEART_BEAT = 0x0C, /* 心跳信号 */ + SYS_INF_DEV_AGREE_HOST_SLP = 0x0D, /* device回复host可睡 */ + SYS_INF_DEV_NOAGREE_HOST_SLP = 0x0E, /* device回复host不可睡 */ + SYS_INF_WIFI_OPEN = 0x0F, /* WCPU上电完成 */ + SYS_INF_IR_INIT = 0x10, /* IR软件初始化完成 */ + SYS_INF_IR_EXIT = 0x11, /* IR退出 */ + SYS_INF_NFC_INIT = 0x12, /* NFC软件初始化完成 */ + SYS_INF_NFC_EXIT = 0x13, /* NFC退出 */ + SYS_INF_WIFI_CLOSE = 0x14, /* WCPU下电完成 */ + SYS_INF_RF_TEMP_NORMAL = 0x15, /* RF温度正常 */ + SYS_INF_RF_TEMP_OVERHEAT = 0x16, /* RF温度过热 */ + SYS_INF_MEM_DUMP_COMPLETE = 0x17, /* bfgx异常时,MEM DUMP已完成 */ + SYS_INF_WIFI_MEM_DUMP_COMPLETE = 0X18, /* bfgx异常时,MEM DUMP已完成 */ + SYS_INF_UART_HALT_WCPU = 0x19, /* uart halt wcpu ok */ + SYS_INF_UART_LOOP_SET_DONE = 0x1a, /* device 设置uart环回ok */ + SYS_INF_CHR_ERRNO_REPORT = 0x1b, /* device向host上报CHR异常码 */ + + SYS_INF_FAKE_CLOSE_BT = 0x1c, /* FAKE CLOSE BT的ACK */ + SYS_INF_RSV1 = 0x1d, /* rsv */ + SYS_INF_RSV2 = 0x1e, /* rsv */ + + SYS_INF_GNSS_LPPE_INIT = 0x1F, /* MP13 GNSS 新增的线程初始化完成 */ + SYS_INF_GNSS_LPPE_EXIT = 0x20, /* MP13 GNSS 新增的线程退出 */ + SYS_INF_GNSS_TRICKLE_SLEEP = 0x21, /* MP13 GNSS_TRICKLE_SLEEP */ + SYS_INF_ENABLE_GPIO_WKUP_BFG_RSP = 0x22, /* 配置uart or gpio唤醒 */ + SYS_INF_BOOT_UP_ACK = 0x23, /* device启动时通过消息回复ack的场景(通常是通过GPIO回复ack) */ + SYS_INF_WAKE_UP_ACK = 0x24, /* device被唤醒时通过消息回复ack的场景(通常是通过GPIO回复ack) */ + SYS_INF_SLE_INIT = 0x25, /* SLE软件初始化完成 */ + SYS_INF_SLE_EXIT = 0x26, /* SLE退出 */ + SYS_INF_REQUEST_SLEEP = 0x27, /* device请求睡眠 */ + + SYS_INF_BUTT /* 枚举定义最大不能超过127,因为128~255被用来当做心跳的时间戳 */ +}; + +enum SYS_PL_MSG_VALUE_ENUM { + SYS_PL_OPEN_BT = 0x0, + SYS_PL_CLOSE_BT = 0x1, + SYS_PL_OPEN_GNSS = 0x2, + SYS_PL_CLOSE_GNSS = 0x3, + SYS_PL_OPEN_FM = 0x4, + SYS_PL_CLOSE_FM = 0x5, + SYS_PL_OPEN_NFC = 0x6, + SYS_PL_CLOSE_NFC = 0x7, + SYS_PL_OPEN_IR = 0x8, + SYS_PL_CLOSE_IR = 0x9, + SYS_PL_OPEN_WIFI = 0xa, /* host通过uart打开WCPU */ + SYS_PL_CLOSE_WIFI = 0xb, /* host通过uart关闭WCPU */ + + SYS_PL_READ_STACK = 0xc, /* host通过uart读栈,心跳超时时使用 */ + SYS_PL_QUERY_RF_TEMP = 0xd, /* host通过uart查询rf温度 */ + + SYS_PL_BFGNI_HOST_ASKTO_SLP = 0xe, /* host allow device sleep */ + SYS_PL_BFGNI_HOST_DISALLOW_DEVSLP = 0xf, /* host disallow device sleep */ + + SYS_PL_BFGNI_SHUTDOWN = 0x10, + SYS_PL_ENABLE_PM = 0x11, /* enable plat dev lowpower feature */ + SYS_PL_DISABLE_PM = 0x12, /* disable plat dev lowpower feature */ + SYS_PL_BT_ENABLE_PM = 0x13, /* enable BT dev lowpower feature */ + SYS_PL_BT_DISABLE_PM = 0x14, /* disable BT dev lowpower feature */ + SYS_PL_GNSS_ENABLE_PM = 0x15, /* enable GNSS dev lowpower feature */ + SYS_PL_GNSS_DISABLE_PM = 0x16, /* disable GNSS dev lowpower feature */ + SYS_PL_NFC_ENABLE_PM = 0x17, /* enable NFC dev lowpower feature */ + SYS_PL_NFC_DISABLE_PM = 0x18, /* disable NFC dev lowpower feature */ + + SYS_PL_TEST_CAUSE_PANIC = 0x19, /* HOST发命令,触发device进入exception */ + SYS_PL_DUMP_RESET_WCPU = 0x1a, /* host通过uart不掉电复位WCPU */ + + SYS_PL_HALT_WCPU = 0x1b, /* halt WCPU */ + SYS_PL_READ_WLAN_PUB_REG = 0x1c, /* 读取wcpu的公共寄存器 */ + SYS_PL_READ_WLAN_PRIV_REG = 0x1d, /* 读取wcpu的私有寄存器 */ + SYS_PL_READ_WLAN_MEM = 0x1e, /* 读取wcpu的mem */ + + SYS_PL_EXCEP_RESET_WCPU = 0x1f, /* wifi DFR WCPU复位 */ + + SYS_PL_SET_UART_LOOP_HANDLER = 0x20, /* 设置deviceä¾§uart环回处理函数 */ + SYS_PL_SET_UART_LOOP_FINISH = 0x21, /* UART环回test ok,恢复gnss消息处理函数 */ + + SYS_PL_PM_DEBUG = 0x22, /* 低功耗维测开关 */ + SYS_PL_BAUT_CHG_REQ_ACK = 0x23, /* 波特率切换请求ACK */ + SYS_PL_BAUT_CHG_COMPLETE = 0x24, /* 波特率切换完成 */ + + SYS_PL_WIFI_OPEN_NOTIFY = 0x25, /* wifi open 通知 */ + SYS_PL_WIFI_CLOSE_NOTIFY = 0x26, /* wifi close 通知 */ + + SYS_PL_CFG_OPEN_GLE = 0x28, /* host通过uart打开GLE */ + SYS_PL_CFG_CLOSE_GLE = 0x29, /* host通过uart打开GLE */ + + SYS_PL_PM_SET_WAKEUP_HOST_VALID = 0x30, /* 根据板级连接配置device可以唤醒host */ + SYS_PL_PM_SET_WAKEUP_HOST_INVALID = 0x31, /* 根据板级连接配置device不需要唤醒host */ + + SYS_PL_BUTT +}; + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/transfer/CMakeLists.txt new file mode 100644 index 000000000..7ca327843 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/CMakeLists.txt @@ -0,0 +1,21 @@ +set( + tiot_transfer_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_xfer.c + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_xfer_utils.c +) + +set( + tiot_transfer_header_list + ${CMAKE_CURRENT_SOURCE_DIR} +) + +if(DEFINED CONFIG_XFER_PACKET_TIOT) +add_subdirectory(packet_handle/tiot_packet) +endif() + +if(DEFINED CONFIG_XFER_PACKET_NCI) +add_subdirectory(packet_handle/nci_packet) +endif() + +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_transfer_src_list}" CACHE INTERNAL "tiot src list" FORCE) +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${tiot_transfer_header_list}" CACHE INTERNAL "tiot header list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/CMakeLists.txt new file mode 100644 index 000000000..5ec32712b --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/CMakeLists.txt @@ -0,0 +1,8 @@ +set( + tiot_packet_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_packet_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_packet.c +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_packet_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.c b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.c new file mode 100644 index 000000000..746933fae --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.c @@ -0,0 +1,919 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-08-03, Create file. \n + */ + +#include "tiot_packet.h" +#include "tiot_sys_msg_handle.h" +#include "tiot_controller.h" +#include "tiot_board_log.h" +#include "tiot_board_pin_port.h" +#include "tiot_xfer_utils.h" +#include "securec.h" + +typedef enum { + TIOT_PKT_FRAME_IDLE, + TIOT_PKT_FRAME_HEAD, + TIOT_PKT_FRAME_PAYLOAD, + TIOT_PKT_FRAME_TAIL +} tiot_pkt_rx_frame; + +typedef enum { + TIOT_PKT_RX_SEPERATE_START, + TIOT_PKT_RX_SEPERATE_COMMON, + TIOT_PKT_RX_SEPERATE_LAST, + TIOT_PKT_RX_COMPLETE, +} tiot_pkt_rx_sep_tag; + +typedef void (* tiot_pkt_msg_handler)(tiot_packet_context *ctx); + +static void tiot_packet_sys_func(tiot_packet_context *ctx); +static void tiot_packet_recv_not_seperated_data(tiot_packet_context *ctx); +static void tiot_packet_recv_seperated_data(tiot_packet_context *ctx); +static int32_t tiot_packet_copy_from_queue(tiot_packet_context *ctx, tiot_packet_queue *queue, + uint8_t *buff, uint32_t buff_len); + +static tiot_pkt_msg_handler g_tiot_pkt_msg_handle[MSG_BUTT] = { + [SYS_MSG] = tiot_packet_sys_func, // SYS_MSG = 0x00, 系统串口消息 + [GNSS_FIRST_MSG] = tiot_packet_recv_seperated_data, // GNSS_FIRST_MSG = 0x02, GNSS串口消息,第一个分段消息 + [GNSS_COMMON_MSG] = tiot_packet_recv_seperated_data, // GNSS_COMMON_MSG = 0x03, GNSS串口消息,中间分段消息 + [GNSS_LAST_MSG] = tiot_packet_recv_seperated_data, // GNSS_LAST_MSG = 0x04, GNSS串口消息,最后一个分段消息 + [OML_MSG] = tiot_packet_recv_not_seperated_data, // OML_MSG = 0x0e, OML串口消息 + [SLE_MSG] = tiot_packet_recv_not_seperated_data, // SLE_MSG = 0x15, SLE串口消息 +}; + +static const tiot_packet_subsys_info g_tiot_pkt_subsys_info[SUBSYS_BUTT] = { + { PKG_SEPRETED, GNSS_FIRST_MSG, GNSS_COMMON_MSG, GNSS_LAST_MSG }, + { PKG_NOT_SEPRETED, OML_MSG, OML_MSG, OML_MSG }, + { PKG_NOT_SEPRETED, SYS_MSG, SYS_MSG, SYS_MSG } +}; + +/* 将旧packet节点推入队列,若队列已满,则丢包. */ +static inline void tiot_cur_packet_to_queue(tiot_packet_context *ctx) +{ + tiot_packet_manager_enqueue_packet(&ctx->rx_manager, ctx->rx_queue_id); + ctx->frame_cnt = 0; + ctx->packet = NULL; +} + +/* 丢包时释放packet节点,重置当前packet节点为空,收到新数据时重新获取对应节点. */ +static inline void tiot_cur_packet_discard(tiot_packet_context *ctx) +{ +#ifndef CONFIG_BOARD_DYNAMIC_ALLOC + if (ctx->packet != NULL) { + circ_buf_update_read_pos(&(ctx->rx_buff.buf), ctx->packet->len); + } +#endif + tiot_packet_manager_discard_packet(&ctx->rx_manager, ctx->rx_queue_id); + ctx->frame_cnt = 0; + ctx->packet = NULL; +} + +/* 按照subsys code更新当前packet节点. */ +static inline void tiot_cur_packet_update(tiot_packet_context *ctx, uint8_t subsys_code) +{ + uint16_t queue_id = ctx->rx_manager.match(subsys_code); + if ((ctx->packet == NULL) || (queue_id != ctx->rx_queue_id)) { + ctx->rx_queue_id = queue_id; + ctx->packet = tiot_packet_manager_get_packet(&ctx->rx_manager, queue_id); + } +} + +static inline void packet_frame_error(tiot_packet_context *ctx) +{ + ctx->frame_error = 1; + ctx->pos = NULL; +} + +static void tiot_packet_report_work(tiot_packet_context *ctx) +{ + tiot_controller *ctrl; + tiot_xfer_manager *xfer; + uint32_t wakein_pin; + if (ctx == NULL) { + return; + } + xfer = ctx->xfer; + if (xfer == NULL) { + return; + } + ctrl = tiot_container_of(xfer, tiot_controller, transfer); + wakein_pin = ctrl->pm.pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST]; + if (wakein_pin == TIOT_PIN_NONE) { + /* 没有dev_wkup_host管脚时,host不休眠(只是PM状态切换),通过上报消息来判断device状态 */ + tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_REPORT_WORK); + } +} + +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC +static inline tiot_packet_rx_node *tiot_packet_rx_node_malloc(uint32_t len) +{ + tiot_packet_rx_node *node = (tiot_packet_rx_node *)osal_kmalloc(sizeof(tiot_packet_rx_node) + len, OSAL_GFP_KERNEL); + if (node == NULL) { + tiot_print_err("[TIoT]pkt rx node malloc fail."); + return NULL; + } + node->data = (uint8_t *)node + sizeof(tiot_packet_rx_node); + node->len = len; + return node; +} +#endif + +int32_t tiot_packet_init(tiot_packet_context *ctx, tiot_xfer_manager *xfer, const tiot_packet_context_param *param) +{ + tiot_packet_buffer *buff; + if ((ctx == NULL) || (xfer == NULL) || (xfer->pkt_context != 0) || (param == NULL)) { + return -1; + } + + /* 接收状态机初始状态均为0,只需要memset为0即可. */ + (void)memset_s((void *)ctx, sizeof(tiot_packet_context), 0, sizeof(tiot_packet_context)); + (void)memcpy_s((void *)&ctx->rx_manager, sizeof(tiot_packet_manager), + ¶m->rx_manager_info, sizeof(tiot_packet_manager)); + + if (osal_mutex_init(&ctx->tx_packet_mutex) != OSAL_SUCCESS) { + tiot_print_err("[TIoT][pkt]tx packet mutex init failed.\n"); + return -1; + } + + if (tiot_packet_manager_init(&ctx->rx_manager) != 0) { + osal_mutex_destroy(&ctx->tx_packet_mutex); + return -1; + } +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + tiot_unused(buff); +#else + buff = param->buff; + (void)memset_s(buff->start, buff->size, 0, buff->size); + circ_buf_init(&(ctx->rx_buff.buf), &(ctx->rx_buff.buff_write), &(ctx->rx_buff.buff_read), buff->start, buff->size); +#endif + ctx->flags = param->flags; + ctx->xfer = xfer; + /* 调用tiot_xfer_install_packet后才注册到xfer内. */ + return 0; +} + +void tiot_packet_deinit(tiot_packet_context *ctx) +{ + if (ctx == NULL) { + return; + } + ctx->xfer = NULL; + ctx->packet = NULL; + tiot_packet_manager_deinit(&ctx->rx_manager); + osal_mutex_destroy(&ctx->tx_packet_mutex); +} + +static void tiot_packet_sys_func(tiot_packet_context *ctx) +{ + uint8_t syschar = ctx->sys_msg; + tiot_xfer_manager *xfer = ctx->xfer; + tiot_controller *ctrl = tiot_container_of(xfer, tiot_controller, transfer); + + if (ctrl->dev_info->pkt_sys_msg_handle != NULL) { + ctrl->dev_info->pkt_sys_msg_handle(ctrl, syschar); + } else { + tiot_print_warning("[TIoT][pkt]pkt_sys_msg_handle is NULL.\r\n"); + } +} + +static void tiot_packet_cums_recv_handle(tiot_packet_context *ctx) +{ + int32_t copy_len; + tiot_packet_queue *queue; + tiot_xfer_cbk_param rx_cbk_param = ctx->xfer->rx_cbk_param; + + /* 直接使用上一次的rx_queue_id. */ + queue = tiot_packet_manager_find_queue(&ctx->rx_manager, ctx->rx_queue_id); + if (queue == NULL) { + tiot_print_err("[TIoT:pkt]can't find subsys queue(%d).\r\n", ctx->rx_queue_id); + return; + } + + if (rx_cbk_param.rx_callback != NULL) { + /* 用户注册了rx callback,直接就地处理 */ + copy_len = tiot_packet_copy_from_queue(ctx, queue, rx_cbk_param.buff, rx_cbk_param.buff_len); + rx_cbk_param.rx_callback(rx_cbk_param.buff, copy_len); + } else { + /* 唤醒等待的reader */ + osal_wait_wakeup_interruptible(&queue->rx_wait); + } +} + +static void tiot_packet_recv_not_seperated_data(tiot_packet_context *ctx) +{ + /* 处理之前的包错误, 释放当前包 */ + if (ctx->frame_error == 1) { + tiot_cur_packet_discard(ctx); + ctx->frame_error = 0; + return; + } + /* 正常完整包. */ + ctx->packet->tag = TIOT_PKT_TAG_BINARY; + tiot_cur_packet_to_queue(ctx); + tiot_packet_cums_recv_handle(ctx); +} + +static void tiot_packet_recv_seperated_data(tiot_packet_context *ctx) +{ + uint8_t subsys_code = ctx->head.subsys_code; + /* 包顺序检测 */ + if (subsys_code == GNSS_FIRST_MSG) { + /* First 包必须为第一个包 */ + if (ctx->frame_cnt != 1) { + tiot_print_err("[TIoT:pkt]parse error: expect first packet.\r\n"); + packet_frame_error(ctx); + } + return; + } + if (subsys_code == GNSS_COMMON_MSG) { + /* 必须先有fisrt包再有common包,所以收到common包时frame_cnt最小为2 */ + if (ctx->frame_cnt < 2) { + tiot_print_err("[TIoT:pkt]parse error: expect first-common packet.\r\n"); + packet_frame_error(ctx); + } + return; + } + /* 收完Last包数据才处理之前的包序错误, 确保完整包被释放 */ + if ((subsys_code == GNSS_LAST_MSG) && (ctx->frame_error == 1)) { + tiot_print_err("[TIoT:pkt]packet order error, discard the whole packet.\r\n"); + tiot_cur_packet_discard(ctx); + ctx->frame_error = 0; + return; + } + /* 正常完整包. */ + ctx->packet->tag = TIOT_PKT_TAG_BINARY; + tiot_cur_packet_to_queue(ctx); + tiot_packet_cums_recv_handle(ctx); +} + +static int32_t tiot_packet_head_check(tiot_packet_head *head) +{ + /* 包头错误!!! */ + if (head->head != TIOT_PKT_HEAD) { + tiot_print_err("[TIoT:pkt]head error: 0x%x\r\n", head->head); + return -1; + } + /* 子系统错误 */ + if (head->subsys_code >= MSG_BUTT) { + tiot_print_err("[TIoT:pkt]subsys error: 0x%x\r\n", head->subsys_code); + return -1; + } + /* 系统消息特殊判断, 长度必须为0x6. */ + if ((head->subsys_code == SYS_MSG) && (head->len != (TIOT_PKT_PKG_SIZE + sizeof(uint8_t)))) { + tiot_print_err("[TIoT:pkt]sys msg len error: 0x%x\r\n", head->len); + return -1; + } + /* payload大小 小于0 或大于最大包大小 */ + if ((head->len <= TIOT_PKT_PKG_SIZE) || + (head->len > (TIOT_PKT_PAYLOAD_MAX_SIZE + TIOT_PKT_PKG_SIZE))) { + tiot_print_err("[TIoT:pkt]payload error: 0x%x\r\n", head->len); + return -1; + } + return 0; +} + +static int32_t tiot_packet_head_try_recovery(tiot_packet_context *ctx) +{ + uint8_t i; + uint8_t *head_data; + errno_t err; + head_data = (uint8_t *)&ctx->head; + /* 出现问题时,先把上一个起始标志位丢弃. */ + for (i = 1; i < sizeof(tiot_packet_head); i++) { + /* 头部出现其他pkt_head时,可以尝试恢复. */ + if (head_data[i] == TIOT_PKT_HEAD) { + break; + } + } + if (i == sizeof(tiot_packet_head)) { + return -1; + } + tiot_print_dbg("[TIoT][pkt]head: [%x %x %x %x].\r\n", + head_data[0], head_data[1], head_data[2], head_data[3]); /* 打印恢复前head数据. */ + tiot_print_warning("[TIoT][pkt]head recovery.\r\n"); + err = memmove_s((void *)&ctx->head, sizeof(tiot_packet_head), &head_data[i], sizeof(tiot_packet_head) - i); + if (err != EOK) { + tiot_print_err("[TIoT][pkt]memmove_s error.\r\n"); + return -1; + } + /* 更新需要读取的个数 & 位置. */ + ctx->frame_need_read = i; + ctx->pos = &head_data[sizeof(tiot_packet_head) - i]; + return 0; +} + +static void tiot_packet_head_done(tiot_packet_context *ctx) +{ + tiot_packet_head *head = &ctx->head; + uint16_t payload_len = head->len - TIOT_PKT_PKG_SIZE; +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + tiot_packet_rx_node *node = NULL; +#endif + if (tiot_packet_head_check(head) != 0) { + if (tiot_packet_head_try_recovery(ctx) == 0) { + /* 恢复成功,继续处理. */ + return; + } + goto discard; + } + /* 消息头校验OK时,认为work. */ + tiot_packet_report_work(ctx); + /* 系统消息不分包特殊处理,避免申请内存. */ + if (head->subsys_code == SYS_MSG) { + ctx->frame_need_read = sizeof(uint8_t); + ctx->pos = &ctx->sys_msg; + ctx->current_frame = TIOT_PKT_FRAME_PAYLOAD; + return; + } + + tiot_cur_packet_update(ctx, head->subsys_code); +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + if (ctx->packet != NULL) { + node = tiot_packet_rx_node_malloc(payload_len); + if (node == NULL) { + packet_frame_error(ctx); + } else { + tiot_list_add_tail(&(node->node), ctx->packet->head); + ctx->pos = node->data; + } + } else { + tiot_print_err("[TIoT:rx]circ queue no space.\n"); + packet_frame_error(ctx); + } +#else + if ((ctx->packet == NULL) || (circ_buf_query_free(&(ctx->rx_buff.buf)) <= payload_len)) { + tiot_print_err("[TIoT:rx]circ queue or rx buff no space.\n"); + packet_frame_error(ctx); + } + if (ctx->packet != NULL) { + ctx->packet->len += payload_len; + } +#endif + ctx->frame_need_read = payload_len; + ctx->frame_cnt++; + ctx->current_frame = TIOT_PKT_FRAME_PAYLOAD; + return; + +discard: + tiot_cur_packet_discard(ctx); + ctx->current_frame = TIOT_PKT_FRAME_IDLE; +} + +static void tiot_packet_payload_done(tiot_packet_context *ctx) +{ + ctx->current_frame = TIOT_PKT_FRAME_TAIL; + ctx->frame_need_read = TIOT_PKT_TAIL_SIZE; + ctx->pos = &ctx->tail; +} + +static void tiot_packet_tail_done(tiot_packet_context *ctx) +{ + uint8_t tail = ctx->tail; + uint8_t subsys_code; + if (tail != TIOT_PKT_TAIL) { + tiot_cur_packet_discard(ctx); + ctx->current_frame = TIOT_PKT_FRAME_IDLE; + ctx->frame_error = 0; + return; + } + + /* 在head done内已经确保subsys_code正确 */ + subsys_code = ctx->head.subsys_code; + if (g_tiot_pkt_msg_handle[subsys_code] != NULL) { + g_tiot_pkt_msg_handle[subsys_code](ctx); + } + ctx->current_frame = TIOT_PKT_FRAME_IDLE; +} + +uint32_t tiot_packet_handle(tiot_packet_context *ctx, uint8_t *data, uint32_t data_len) +{ + uint16_t packet_len = (uint16_t)(data_len & 0xFFFF); /* 取低16位,包格式只需要16位大小. */ + uint32_t handle_len = packet_len < ctx->frame_need_read ? packet_len : ctx->frame_need_read; + ctx->frame_need_read -= handle_len; + +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + if (ctx->pos != NULL) { + (void)memcpy_s(ctx->pos, handle_len, data, handle_len); + ctx->pos += handle_len; + } else { + tiot_print_dbg("[TIoT][rx]packet buff pos is NULL.\n"); + } +#else + /* 系统消息直接拷贝;buffer放不下时丢包处理,使用frame_error标识. */ + if ((ctx->current_frame == TIOT_PKT_FRAME_PAYLOAD) && + (ctx->head.subsys_code != SYS_MSG)) { + circ_buf_write_data(&(ctx->rx_buff.buf), data, handle_len, ctx->rx_buff.buff_write); + circ_buf_update_write_pos(&(ctx->rx_buff.buf), handle_len); + } else { + if (ctx->pos != NULL) { + (void)memcpy_s(ctx->pos, handle_len, data, handle_len); + ctx->pos += handle_len; + } else { + tiot_print_dbg("[TIoT][rx]packet buff pos is NULL.\n"); + } + } +#endif + + if (ctx->frame_need_read != 0) { + return handle_len; + } + + /* 完成一帧数据 */ + switch (ctx->current_frame) { + case TIOT_PKT_FRAME_HEAD: + tiot_packet_head_done(ctx); + break; + case TIOT_PKT_FRAME_PAYLOAD: + tiot_packet_payload_done(ctx); + break; + case TIOT_PKT_FRAME_TAIL: + tiot_packet_tail_done(ctx); + break; + default: + tiot_print_dbg("[TIoT][rx]err frame: %d\n", ctx->current_frame); + break; + } + return handle_len; +} + +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC +static inline void tiot_packet_ascii_line_store(tiot_packet_context *ctx, uint8_t *line_start, uint32_t line_len) +{ + tiot_packet_rx_node *node = tiot_packet_rx_node_malloc(line_len); + if (node == NULL) { + /* discard */ + return; + } + (void)memcpy_s(node->data, line_len, line_start, line_len); + tiot_list_add_tail(&(node->node), ctx->packet->head); +} +#else +static inline void tiot_packet_ascii_line_store(tiot_packet_context *ctx, uint8_t *line_start, uint32_t line_len) +{ + if (circ_buf_query_free(&(ctx->rx_buff.buf)) <= line_len) { + tiot_print_err("[TIoT][rx]rx buffer no space for data."); + return; + } + circ_buf_write(&(ctx->rx_buff.buf), line_start, line_len); + ctx->packet->len += line_len; +} +#endif + +static void tiot_packet_ascii_line_handle(tiot_packet_context *ctx, uint8_t *data, uint32_t handle_len) +{ + uint8_t *left = data; + uint8_t *right = data; + uint32_t line_len = 0; + while (right < (data + handle_len)) { + if (*right != '\n') { + right++; + continue; + } + /* 找到行尾. */ + line_len = right - left + 1; /* 当前字符也复制 '\n'. */ + tiot_cur_packet_update(ctx, MSG_BUTT); /* ASCII消息使用MSG_BUTT,避免重复. */ + if (ctx->packet != NULL) { + tiot_packet_ascii_line_store(ctx, left, line_len); + ctx->packet->tag = TIOT_PKT_TAG_ASCII; + tiot_cur_packet_to_queue(ctx); + tiot_packet_cums_recv_handle(ctx); + } else { + tiot_print_err("[TIoT:rx]circ queue no space, discard: 0x%x\r\n", line_len); + } + left = right + 1; /* 下一行起始 */ + right = left; + } + /* 最后一段没有结尾的情况 */ + line_len = (data + handle_len) - left; + if (line_len == 0) { + return; + } + tiot_cur_packet_update(ctx, MSG_BUTT); /* ASCII消息使用MSG_BUTT,避免重复. */ + if (ctx->packet != NULL) { + tiot_packet_ascii_line_store(ctx, left, line_len); + /* ASCII字符串结束判断. */ + if (ctx->current_frame == TIOT_PKT_FRAME_HEAD) { + ctx->packet->tag = TIOT_PKT_TAG_ASCII; + tiot_cur_packet_to_queue(ctx); + tiot_packet_cums_recv_handle(ctx); + } + } else { + tiot_print_err("[TIoT:rx]circ queue no space, discard: 0x%x\r\n", line_len); + } +} + +uint32_t tiot_packet_ascii_handle(tiot_packet_context *ctx, uint8_t *data, uint32_t data_len) +{ + /* ascii字符串处理 */ + uint32_t handle_len = 0; + uint8_t *tmp = data; + /* 寻找包头起始 */ + while (handle_len < data_len) { + if (*tmp == 0x7e) { + break; + } + tmp++; + handle_len++; + } + + if (handle_len < data_len) { + /* 找到包头 */ + ctx->current_frame = TIOT_PKT_FRAME_HEAD; + ctx->frame_need_read = TIOT_PKT_HEAD_SIZE; + ctx->pos = (uint8_t *)&ctx->head; + } + + if ((handle_len == 0) || !(ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII)) { + /* 1. 第一个字节即0x7e, 不需要处理. */ + /* 2. 不支持上报ascii数据,直接丢包处理. */ + goto discard; + } + /* 支持上报ascii数据时,有数据认为work. */ + tiot_packet_report_work(ctx); + tiot_packet_ascii_line_handle(ctx, data, handle_len); +discard: + return handle_len; +} + +void tiot_packet_rx_data_parse(tiot_packet_context *ctx, uint8_t *data, uint32_t len) +{ + uint8_t *buff = data; + uint32_t handle_len = 0; + uint32_t total_len = len; + + while (total_len) { + if (ctx->current_frame == TIOT_PKT_FRAME_IDLE) { + handle_len = tiot_packet_ascii_handle(ctx, buff, total_len); + } else { + handle_len = tiot_packet_handle(ctx, buff, total_len); + } + buff += handle_len; + total_len -= handle_len; + } +} + +void tiot_packet_rx_data_store(tiot_xfer_manager *xfer, uint8_t *data, uint32_t len) +{ + tiot_packet_context *ctx = NULL; + /* 入参已在调用处判空 */ + ctx = (tiot_packet_context *)xfer->pkt_context; + tiot_packet_rx_data_parse(ctx, data, len); +} + +static int tiot_packet_read_out_check(const void *param) +{ + int check; + tiot_packet_manager_query *query = (tiot_packet_manager_query *)param; + tiot_xfer_manager *xfer = query->xfer; + tiot_packet_context *ctx = (tiot_packet_context *)xfer->pkt_context; + if (ctx == NULL) { + tiot_print_warning("[TIoT][rx]read out check: pkt_context is NULL\n"); + return 1; + } + check = (xfer->rx_wait_func(xfer) != 0) || + (tiot_packet_manager_has_data(&ctx->rx_manager, query->queue_id)); + return check; +} + +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC +static int32_t tiot_packet_is_valid(tiot_packet *packet) +{ + uint16_t frame_cnt = 0; + tiot_packet_rx_node *pos; + if (packet->head == NULL) { + return -1; + } + tiot_list_for_each_entry(pos, packet->head, node, tiot_packet_rx_node) { + if ((pos->data == NULL) || (pos->len == 0)) { + return -1; + } + frame_cnt++; + } + if (frame_cnt == 0) { + return -1; + } + return 0; +} + +static int32_t tiot_packet_copy_from_queue(tiot_packet_context *ctx, tiot_packet_queue *queue, + uint8_t *buff, uint32_t buff_len) +{ + tiot_packet *packet = NULL; + uint8_t *tmp_buff = buff; + uint32_t copy_len; + tiot_packet_rx_node *pos; + + do { + copy_len = 0; + packet = (tiot_packet *)tiot_circ_queue_dequeue(&queue->queue); + if (packet == NULL) { + tiot_print_info("[TIoT][rx]packet queue is empty.\n"); + break; + } + if (tiot_packet_is_valid(packet) != 0) { + tiot_print_err("[TIoT][rx]invalid packet."); + tiot_packet_free_packet(packet); + continue; + } + + tiot_list_for_each_entry(pos, packet->head, node, tiot_packet_rx_node) { + copy_len += pos->len; + } + if (ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII) { + copy_len += sizeof(uint16_t); + } + if (copy_len > buff_len) { + tiot_print_info("[TIoT][rx]not enough buff len:%d for this packet: %d.", buff_len, copy_len); + tiot_packet_free_packet(packet); + continue; + } + /* 完整包正常, 复制一包到用户buffer后退出. */ + if (ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII) { + (void)memcpy_s((void *)tmp_buff, sizeof(uint16_t), (void *)&packet->tag, sizeof(uint16_t)); + tmp_buff += sizeof(uint16_t); + } + tiot_list_for_each_entry(pos, packet->head, node, tiot_packet_rx_node) { + (void)memcpy_s((void *)tmp_buff, pos->len, (void *)pos->data, pos->len); + tmp_buff += pos->len; + } + tiot_packet_free_packet(packet); + break; + } while (packet != NULL); + + return copy_len; +} +#else +static int32_t tiot_packet_copy_from_queue(tiot_packet_context *ctx, tiot_packet_queue *queue, + uint8_t *buff, uint32_t buff_len) +{ + uint32_t copy_len; + uint8_t *tmp_buff = buff; + tiot_packet *packet; + do { + copy_len = 0; + packet = (tiot_packet *)tiot_circ_queue_dequeue(&queue->queue); + if (packet == NULL) { + tiot_print_info("[TIoT][rx]packet queue is empty."); + break; + } + copy_len = packet->len; + if (ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII) { + copy_len += sizeof(uint16_t); + } + if (copy_len > buff_len) { + tiot_print_info("[TIoT][rx]not enough buff len:%d for this packet: %d.", buff_len, copy_len); + (void)circ_buf_update_read_pos(&(ctx->rx_buff.buf), packet->len); + continue; + } + /* 完整包正常, 复制一包到用户buffer后退出. */ + if (ctx->flags & TIOT_PKT_FLAGS_SUPPORT_ASCII) { + (void)memcpy_s((void *)tmp_buff, sizeof(uint16_t), (void *)&packet->tag, sizeof(uint16_t)); + tmp_buff += sizeof(uint16_t); + } + /* 按顺序读即可,不需要记录起始. */ + (void)circ_buf_read(&(ctx->rx_buff.buf), tmp_buff, packet->len); + break; + } while (packet != NULL); + return copy_len; +} +#endif + +#ifdef __KERNEL__ +static int32_t packet_poll(tiot_packet_manager_query *query, tiot_packet_queue *queue, const tiot_xfer_rx_param *param) +{ + if (tiot_packet_read_out_check(query) != 0) { + return 1; + } + + poll_wait(param->filp, (wait_queue_head_t *)(queue->rx_wait.wait), param->poll_wait); + + if (tiot_packet_read_out_check(query) != 0) { + return 1; + } + return 0; +} +#endif + +int32_t tiot_packet_read_out(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, const tiot_xfer_rx_param *param) +{ + int32_t read_ret; + tiot_packet_queue *queue; + tiot_packet_manager_query query; + tiot_packet_context *ctx = (tiot_packet_context *)xfer->pkt_context; + if (ctx == NULL) { + return -1; + } + queue = tiot_packet_manager_find_queue(&ctx->rx_manager, param->subsys); /* 对应queue_id */ + if (queue == NULL) { + return -1; + } + query.xfer = xfer; + query.queue_id = param->subsys; /* 对应queue_id. */ + +#ifdef __KERNEL__ + if (param->filp != NULL && param->poll_wait != NULL) { /* poll mode */ + return packet_poll(&query, queue, param); + } +#endif + + if (param->timeout == 0) { /* 非阻塞. */ + /* 没有数据直接返回. */ + if (tiot_packet_read_out_check(&query) == 0) { + tiot_print_dbg("[TIoT:pkt][%d]no data to read.\r\n", param->subsys); + return 0; + } + } else { /* 阻塞. */ + if (queue->flags & TIOT_PACKET_QUEUE_RX_WAITING) { + tiot_print_err("[TIoT:pkt][%d]there's already a thread blocking read().\r\n", param->subsys); + return -1; + } + queue->flags |= TIOT_PACKET_QUEUE_RX_WAITING; + /* 等待接收到一个完整包. */ + read_ret = osal_wait_timeout_interruptible(&queue->rx_wait, tiot_packet_read_out_check, &query, param->timeout); + if (xfer->pkt_context == 0) { + read_ret = 0; + } + queue->flags &= ~TIOT_PACKET_QUEUE_RX_WAITING; + if (read_ret <= 0) { + tiot_print_warning("[TIoT:pkt][%d]osal_wait timeout.\r\n", param->subsys); + return read_ret; + } + } + + return tiot_packet_copy_from_queue(ctx, queue, buff, len); +} + +#ifdef CONFIG_XFER_SUPPORT_TX_TASK +static int32_t tiot_tx_packet_fill(uint8_t *dest, uint8_t *payload, uint16_t payload_len, uint8_t subsys_code) +{ + uint16_t packet_len = payload_len + TIOT_PKT_PKG_SIZE; + uint8_t *packet_buff = dest; + + tiot_packet_head *head = (tiot_packet_head *)packet_buff; + head->head = TIOT_PKT_HEAD; + head->subsys_code = subsys_code; + head->len = packet_len; + + if (memcpy_s(&packet_buff[TIOT_PKT_HEAD_SIZE], payload_len, payload, payload_len) != EOK) { + tiot_print_err("[TIoT][tx]packet memcpy err.\r\n"); + return -1; + } + packet_buff[packet_len - 1] = TIOT_PKT_TAIL; + return 0; +} + +int32_t tiot_packet_tx_push(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len, + const tiot_xfer_tx_param *param) +{ + int32_t ret; + uint16_t payload_len; + uint32_t total_len; + const uint8_t *buff; + uint8_t packet_count; + const tiot_packet_subsys_info *subsys_info; + tiot_xfer_tx_data new_data; + + /* data外部已验证 */ + if ((param == NULL) || (len == 0)) { + tiot_print_err("[TIoT:pkt]tx param is NULL or len is 0.\r\n"); + return -1; + } + + total_len = len; + subsys_info = &g_tiot_pkt_subsys_info[param->subsys]; + /* 分包个数: tx_len / 4095 + (tx_len % 4095 ? 1 : 0) ==> (tx_len + (4095 - 1)) / 4095。 */ + packet_count = (total_len + TIOT_PKT_PAYLOAD_MAX_SIZE - 1) / TIOT_PKT_PAYLOAD_MAX_SIZE; + /* 预先申请 */ + packet_buff = osal_kmalloc(total_len + packet_count * (TIOT_PKT_PKG_SIZE)); + if (packet_buff == NULL) { + return -1; + } + tmp = packet_buff; + + for (i = 0; i < packet_count - 1; i++) { + payload_len = TIOT_PKT_PAYLOAD_MAX_SIZE; + if (i == 0) { + ret = tiot_tx_packet_fill(tmp, buff, payload_len, subsys_info->common); + } else { + ret = tiot_tx_packet_fill(tmp, buff, payload_len, subsys_info->first); + } + if (ret != 0) { + /* 复制数据出错,释放buffer */ + osal_kfree(packet_buff); + return -1; + } + tmp += payload_len + TIOT_PKT_PKG_SIZE; + buff += payload_len; + } + + payload_len = total_len - (packet_count - 1) * TIOT_PKT_PAYLOAD_MAX_SIZE; + ret = tiot_tx_packet_fill(tmp, buff, payload_len, subsys_info->last); + if (ret != 0) { + /* 复制数据出错,释放buffer */ + osal_kfree(packet_buff); + return -1; + } + + new_data.data = packet_buff; + new_data.len = total_len + packet_count * (TIOT_PKT_PKG_SIZE); + if (tiot_circ_queue_enqueue(&xfer->tx_queue, (uintptr_t)&new_data) != 0) { + osal_kfree(packet_buff); + return -1; + } + return (ret >= 0) ? total_len : (-1); +} +#else +static int32_t tiot_tx_packet_push(tiot_xfer_manager *xfer, const uint8_t *payload, + uint16_t payload_len, uint8_t subsys_code) +{ + int32_t ret = 0; + uint16_t packet_len = payload_len + TIOT_PKT_PKG_SIZE; + const uint8_t tail = TIOT_PKT_TAIL; + tiot_packet_head head = { TIOT_PKT_HEAD, subsys_code, packet_len }; + + do { + ret = tiot_xfer_direct_send(xfer, (uint8_t *)&head, sizeof(tiot_packet_head)); + if (ret != sizeof(tiot_packet_head)) { + ret = -1; + break; + } + ret = tiot_xfer_direct_send(xfer, payload, payload_len); + if (ret != payload_len) { + ret = -1; + break; + } + ret = tiot_xfer_direct_send(xfer, &tail, sizeof(uint8_t)); + if (ret != sizeof(uint8_t)) { + ret = -1; + break; + } + } while (0); + + return (ret >= 0) ? (int32_t)packet_len : (-1); +} + +int32_t tiot_packet_tx_push(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len, + const tiot_xfer_tx_param *param) +{ + int32_t ret; + uint16_t payload_len; + uint32_t total_len; + const uint8_t *buff; + uint8_t packet_count; + uint8_t i; + const tiot_packet_subsys_info *subsys_info; + tiot_packet_context *pkt_ctx; + + /* data外部已验证 */ + if ((param == NULL) || (len == 0)) { + tiot_print_err("[TIoT:pkt]tx param is NULL or len is 0.\r\n"); + return -1; + } + + pkt_ctx = (tiot_packet_context*)(xfer->pkt_context); + if (pkt_ctx == NULL) { + tiot_print_err("[TIoT][pkt]packet context is NULL.\r\n"); + return -1; + } + + total_len = len; + buff = data; + /* 分包个数: tx_len / 4095 + (tx_len % 4095 ? 1 : 0) ==> (tx_len + (4095 - 1)) / 4095。 */ + packet_count = (total_len + TIOT_PKT_PAYLOAD_MAX_SIZE - 1) / TIOT_PKT_PAYLOAD_MAX_SIZE; + subsys_info = &g_tiot_pkt_subsys_info[param->subsys]; + + /* + * 多线程并发情况下,必须保证每个线程完整地发完整个packet,中间不能插入同类型的其他packet + * thread1: gnss-first gnss-last + * thread2: gnss-first + * 像如上情况就会出现first-first-last,导致解包出现错误 + */ + osal_mutex_lock(&pkt_ctx->tx_packet_mutex); + + for (i = 0; i < packet_count - 1; i++) { + payload_len = TIOT_PKT_PAYLOAD_MAX_SIZE; + if (i == 0) { + ret = tiot_tx_packet_push(xfer, buff, payload_len, subsys_info->first); + } else { + ret = tiot_tx_packet_push(xfer, buff, payload_len, subsys_info->common); + } + + if (ret == -1) { + osal_mutex_unlock(&pkt_ctx->tx_packet_mutex); + return -1; + } + buff += payload_len; + } + payload_len = total_len - (packet_count - 1) * TIOT_PKT_PAYLOAD_MAX_SIZE; + ret = tiot_tx_packet_push(xfer, buff, payload_len, subsys_info->last); + + osal_mutex_unlock(&pkt_ctx->tx_packet_mutex); + + return (ret >= 0) ? (int32_t)total_len : (-1); +} +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.h b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.h new file mode 100644 index 000000000..9fa18d770 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet.h @@ -0,0 +1,205 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-07-21, Create file. \n + */ +#ifndef TIOT_PACKET_H +#define TIOT_PACKET_H + +#include "tiot_types.h" +#include "tiot_xfer.h" +#include "tiot_list.h" +#include "tiot_packet_manager.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_transfer_packet_handle_tiot_packet Packet Handle + * @ingroup tiot_common_transfer_packet_handle + * @{ + */ + +#define TIOT_PKT_FLAGS_SUPPORT_ASCII 0x1U + +#define TIOT_PKT_PAYLOAD_MAX_SIZE 4095U +#define TIOT_PKT_HEAD_SIZE 4 +#define TIOT_PKT_TAIL_SIZE 1 +#define TIOT_PKT_PKG_SIZE (TIOT_PKT_HEAD_SIZE + TIOT_PKT_TAIL_SIZE) + +#define TIOT_PKT_HEAD 0x7e +#define TIOT_PKT_TAIL 0x7e + +/* 重新定义, 暂时只需要这些 */ +typedef enum { + SUBSYS_GNSS = 0x00, + SUBSYS_OM = 0x01, + SUBSYS_SYS = 0x02, + SUBSYS_BUTT +} subsys_type_enum; + +typedef enum { + TIOT_PKT_TAG_BINARY, + TIOT_PKT_TAG_ASCII +} tiot_pkt_rx_tag; + +typedef enum { + PKG_NOT_SEPRETED = 0, + PKG_SEPRETED = 1, +} pkg_sepreted_state; + +enum TIOT_PKT_DATA_MSG_TYPE_ENUM { + SYS_MSG = 0x00, /* 系统串口消息 */ + BT_MSG = 0x01, /* BT串口消息 */ + GNSS_FIRST_MSG = 0x02, /* GNSS串口消息,第一个分段消息 */ + GNSS_COMMON_MSG = 0x03, /* GNSS串口消息,中间分段消息 */ + GNSS_LAST_MSG = 0x04, /* GNSS串口消息,最后一个分段消息 */ + FM_FIRST_MSG = 0x05, /* FM串口消息,第一个分段消息 */ + FM_COMMON_MSG = 0x06, /* FM串口消息,中间分段消息 */ + FM_LAST_MSG = 0x07, /* FM串口消息,最后一个分段消息 */ + IR_FIRST_MSG = 0x08, /* 红外串口消息,第一个分段消息 */ + IR_COMMON_MSG = 0x09, /* 红外串口消息,中间分段消息 */ + IR_LAST_MSG = 0x0A, /* 红外串口消息,最后一个分段消息 */ + NFC_FIRST_MSG = 0x0B, /* NFC串口消息,第一个分段消息 */ + NFC_COMMON_MSG = 0x0C, /* NFC串口消息,中间分段消息 */ + NFC_LAST_MSG = 0x0D, /* NFC串口消息,最后一个分段消息 */ + OML_MSG = 0x0E, /* 可维可测消息 */ + MEM_DUMP_SIZE = 0x0f, /* bfgx异常时,要dump的mem长度消息 */ + MEM_DUMP = 0x10, /* bfgx异常时,内存dump消息 */ + WIFI_MEM_DUMP = 0x11, /* UART READ WIFI MEM,内存dump消息 */ + BFGX_CALI_MSG = 0x12, /* BFGX 校准数据上报 */ + + /* GF_CPU消息 */ + GF_SYS_MSG = 0x13, /* GF系统串口消息 */ + GF_OML_MSG = 0x14, /* GF可维可测消息 */ + + SLE_MSG = 0x15, /* SLE串口消息 */ + + MSG_BUTT, +}; + +typedef struct { + uint8_t seperated; + uint8_t first; + uint8_t common; + uint8_t last; +} tiot_packet_subsys_info; + +typedef struct { + uint8_t head; + uint8_t subsys_code; + uint16_t len; +} tiot_packet_head; + +typedef struct { + uint8_t *start; + uint32_t size; + uint32_t recv_cnt; +} tiot_packet_buffer; + +#ifndef CONFIG_BOARD_DYNAMIC_ALLOC +typedef struct { + tiot_circ_buf buf; + uint32_t buff_write; + uint32_t buff_read; +} tiot_packet_circ_buffer; +#endif + +typedef struct { + uint32_t flags; /*!< Control behave. */ + tiot_packet_manager rx_manager_info; + tiot_packet_buffer *buff; +} tiot_packet_context_param; + +/** + * @brief Packet parser context. + */ +typedef struct { + tiot_packet_manager rx_manager; + tiot_packet *packet; + uint32_t flags; /*!< Control behave. */ + osal_mutex tx_packet_mutex; +#ifndef CONFIG_BOARD_DYNAMIC_ALLOC + tiot_packet_circ_buffer rx_buff; +#endif + /* Rx State machine. */ + uint8_t *pos; + tiot_packet_head head; + uint8_t tail; + uint8_t sys_msg; + uint8_t frame_error; + uint16_t frame_cnt; + uint16_t current_frame; + uint16_t frame_need_read; + uint16_t rx_queue_id; + + tiot_xfer_manager *xfer; /*!< Connect transfer manager. */ +} tiot_packet_context; + +typedef struct { + tiot_xfer_tx_data data; + uint16_t subsys; +} tiot_packet_tx_data; + +/** + * @brief Packet context init. + * @param [in] ctx packet context. + * @param [in] xfer Transfer manager. + * @param [in] flags control flags. + * @return if OK, return 0, else return -1. + */ +int32_t tiot_packet_init(tiot_packet_context *ctx, tiot_xfer_manager *xfer, const tiot_packet_context_param *param); + +/** + * @brief Packet context deinit. + * @param [in] ctx packet context. + */ +void tiot_packet_deinit(tiot_packet_context *ctx); + +/** + * @brief tx packet push. + * @param [in] xfer Transfer manager. + * @param [out] data Caller send data. + * @param [in] len Caller data len. + * @param [in] param Caller send param, must. + * @return if OK, return sent data, else return -1. + */ +int32_t tiot_packet_tx_push(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len, + const tiot_xfer_tx_param *param); + +/** + * @brief rx data store. + * @param [in] xfer Transfer manager. + * @param [in] data Received data. + * @param [in] len Received data length. + */ +void tiot_packet_rx_data_store(tiot_xfer_manager *xfer, uint8_t *data, uint32_t len); + +/** + * @brief rx data read out, copy uint16_t data_tag and single complete packet into user buffer. + * @param [in] xfer Transfer manager. + * @param [out] buff User buffer. + * @param [in] len Max read length. + * @param [in] param Caller receive param. + * @return int32_t if OK, return readout length;if wait timeout, return 0; if err, return -1. + * @note First two bytes copyed to buff indicate data type, ASCII or BINARY. + */ +int32_t tiot_packet_read_out(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, const tiot_xfer_rx_param *param); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.c b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.c new file mode 100644 index 000000000..9f11492ae --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.c @@ -0,0 +1,90 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: \n + * + * History: \n + * 2024-01-27, Create file. \n + */ + +#include "tiot_packet_manager.h" +#include "tiot_osal.h" + +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC +void tiot_packet_free_packet(tiot_packet *packet) +{ + tiot_packet_rx_node *pos, *next; + tiot_list_head_create(tmp_head); + if ((packet == NULL) || (packet->head == NULL)) { + return; + } + tiot_list_replace(packet->head, &tmp_head); + /* 使用临时节点遍历删除. */ + tiot_list_for_each_entry_safe(pos, next, &tmp_head, node, tiot_packet_rx_node, tiot_packet_rx_node) { + if (pos != NULL) { + tiot___list_del_entry(&pos->node); + osal_kfree(pos); + } + } + osal_kfree(packet->head); +} +#endif + +void tiot_packet_queue_deinit(tiot_packet_queue *queue) +{ + /* 唤醒并等待可能的blocking-read()线程正常退出 */ + osal_wait_wakeup_interruptible(&queue->rx_wait); + while (queue->flags & TIOT_PACKET_QUEUE_RX_WAITING) { + osal_msleep(1); + } +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + /* 动态申请buffer时才需要清除. */ + /* 释放所有未处理缓存数据. */ + tiot_packet *packet = NULL; + tiot_packet_free_packet(&queue->active_node); + do { + packet = (tiot_packet *)tiot_circ_queue_dequeue(&queue->queue); + if (packet == NULL) { + break; + } + tiot_packet_free_packet(packet); + } while (packet != NULL); +#endif + osal_spin_lock_destroy(&queue->queue.lock); + osal_wait_destroy(&queue->rx_wait); +} + +tiot_packet *tiot_packet_manager_get_packet(tiot_packet_manager *manager, uint16_t queue_id) +{ + tiot_packet_queue *queue = tiot_packet_manager_find_queue(manager, queue_id); + if (queue == NULL) { + return NULL; + } +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + if (queue->active_node.head == NULL) { + queue->active_node.head = (struct tiot_list_head *)osal_kmalloc(sizeof(struct tiot_list_head), OSAL_GFP_KERNEL); + if (queue->active_node.head == NULL) { + return NULL; + } + tiot_init_list_head(queue->active_node.head); + } +#endif + return &queue->active_node; +} + +int32_t tiot_packet_manager_init(tiot_packet_manager *manager) +{ + uint16_t i, j; + if (manager->match == NULL) { + return -1; + } + for (i = 0; i < manager->queue_num; i++) { + if (tiot_packet_queue_init((tiot_packet_queue *)&(manager->queues[i])) != 0) { + for (j = 0; j < i; j++) { /* 释放之前已初始化的queue */ + tiot_packet_queue_deinit((tiot_packet_queue *)&manager->queues[j]); + } + return -1; + } + } + return 0; +} diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.h b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.h new file mode 100644 index 000000000..29605bbed --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/packet_handle/tiot_packet/tiot_packet_manager.h @@ -0,0 +1,213 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * + * Description: TIoT Packet Manager. \n + * + * History: \n + * 2024-01-13, Create file. \n + */ +#ifndef TIOT_PACKET_MANAGER_H +#define TIOT_PACKET_MANAGER_H + +#include "tiot_types.h" +#include "tiot_xfer.h" +#include "tiot_circ_queue.h" +#include "tiot_list.h" +#include "tiot_board_log.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_transfer_packet_handle_tiot_packet_manager Packet Manager + * @ingroup tiot_common_transfer_packet_handle_tiot_packet + * @{ + */ + +#define TIOT_PACKET_QUEUE_RX_WAITING 0x1 + +/** + * @brief TIOT Complete Packet, simple replace for skb_queue. + */ +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC +typedef struct { + struct tiot_list_head *head; /* Dynamic Allocated. */ + uint16_t tag; /* BINARY | ASCII. */ +} tiot_packet; + +typedef struct { + struct tiot_list_head node; + uint8_t *data; + uint32_t len; +} tiot_packet_rx_node; +#else +typedef struct { + uint32_t len; + uint16_t tag; /* BINARY | ASCII. */ +} tiot_packet; +#endif + +typedef struct { + tiot_circ_queue_t queue; + const tiot_packet *queue_nodes; + uint16_t queue_size; + uint8_t flags; + tiot_packet active_node; + osal_wait rx_wait; +} tiot_packet_queue; + +typedef uint16_t (* tiot_packet_match_func)(uint32_t msg_type); + +typedef struct { + const tiot_packet_queue *queues; + uint16_t queue_num; + tiot_packet_match_func match; +} tiot_packet_manager; + +typedef struct { + tiot_xfer_manager *xfer; + uint16_t queue_id; +} tiot_packet_manager_query; + +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC +/** + * @if Eng + * @brief Free TIoT packlet. + * @param packet Pointer to TIoT packet. + * @else + * @brief 释放TIoT消息包。 + * @param packet TIoT消息包指针。 + * @endif + */ +void tiot_packet_free_packet(tiot_packet *packet); +#endif + +/** + * @if Eng + * @brief Deinit packet queue. + * @param queue Pointer to TIoT packet queue. + * @else + * @brief 去初始化包格式队列。 + * @param queue 包格式队列指针。 + * @endif + */ +void tiot_packet_queue_deinit(tiot_packet_queue *queue); + +/** + * @if Eng + * @brief Get packet pointer for queue_id, from packet manager. + * @param manager Packet manager. + * @param queue_id The index of queue in packet manager. + * @return Return packet pointer for queue_id,if no such queue or malloc fail, return NULL. + * @else + * @brief 从包管理器中获取指定队列ID的包。 + * @param manager 包管理器。 + * @param queue_id 包管理器内队列ID。 + * @return 返回指定队列ID的包的指针,如果没有对应队列,或内存申请失败则返回NULL。 + * @endif + */ +tiot_packet *tiot_packet_manager_get_packet(tiot_packet_manager *manager, uint16_t queue_id); + +/** + * @if Eng + * @brief init packet manager. + * @param manager Packet manager. + * @else + * @brief 初始化包包管理器。 + * @param manager 包管理器。 + * @endif + */ +int32_t tiot_packet_manager_init(tiot_packet_manager *manager); + +static inline int32_t tiot_packet_queue_init(tiot_packet_queue *queue) +{ + const uint32_t queue_mem_size = queue->queue_size * sizeof(tiot_packet); + tiot_circ_queue_init(&queue->queue, queue->queue_size, sizeof(tiot_packet), (uintptr_t)queue->queue_nodes); + (void)memset_s((void *)queue->queue_nodes, queue_mem_size, 0, queue_mem_size); + (void)memset_s((void *)&queue->active_node, sizeof(tiot_packet), 0, sizeof(tiot_packet)); + queue->flags = 0; + if (osal_wait_init(&queue->rx_wait) != OSAL_SUCCESS) { + return -1; + } + return 0; +} + +static inline void tiot_packet_manager_deinit(tiot_packet_manager *manager) +{ + uint16_t i; + for (i = 0; i < manager->queue_num; i++) { + tiot_packet_queue_deinit((tiot_packet_queue *)&manager->queues[i]); + } +} + +static inline tiot_packet_queue *tiot_packet_manager_find_queue(tiot_packet_manager *manager, uint16_t queue_id) +{ + tiot_packet_queue *queue = NULL; + if (manager == NULL) { + return queue; + } + if (queue_id < manager->queue_num) { + queue = (tiot_packet_queue *)&manager->queues[queue_id]; + } + return queue; +} + +static inline void tiot_packet_manager_enqueue_packet(tiot_packet_manager *manager, uint16_t queue_id) +{ + tiot_packet_queue *queue = tiot_packet_manager_find_queue(manager, queue_id); + if (queue == NULL) { + return; + } + if (tiot_circ_queue_enqueue(&queue->queue, (uintptr_t)&queue->active_node) != 0) { + tiot_print_err("[TIoT:rx]circ queue [%d] no space.\r\n", queue_id); +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + tiot_packet_free_packet(&queue->active_node); +#endif + } +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + /* 指针转移至循环队列内或已释放. */ + queue->active_node.head = NULL; +#else + queue->active_node.len = 0; +#endif +} + +static inline void tiot_packet_manager_discard_packet(tiot_packet_manager *manager, uint16_t queue_id) +{ + tiot_packet_queue *queue = tiot_packet_manager_find_queue(manager, queue_id); + if (queue == NULL) { + return; + } +#ifdef CONFIG_BOARD_DYNAMIC_ALLOC + tiot_packet_free_packet(&queue->active_node); + /* 指针已释放. */ + queue->active_node.head = NULL; +#else + queue->active_node.len = 0; +#endif +} + +static inline int32_t tiot_packet_manager_has_data(tiot_packet_manager *manager, uint16_t queue_id) +{ + tiot_packet_queue *queue; + queue = tiot_packet_manager_find_queue(manager, queue_id); + if (queue == NULL) { + return 0; + } + return (tiot_circ_queue_empty(&queue->queue) == 0); +} + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer.c b/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer.c new file mode 100644 index 000000000..1b82ac89f --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer.c @@ -0,0 +1,493 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT transfer module. \n + * + * History: \n + * 2023-04-18, Create file. \n + */ +#include "tiot_xfer.h" +#include "tiot_xfer_utils.h" +#include "tiot_board_log.h" + +#ifdef CONFIG_XFER_TX_SUPPORT_TASK +#define TIOT_XFER_MANAGER_MAX 16 + +typedef enum { + TIOT_XFER_TASK_UNINIT, + TIOT_XFER_TASK_INIT, + TIOT_XFER_TASK_ABORT, +} tiot_xfer_task_state; + +typedef struct { + osal_task *task; + tiot_xfer_manager *xfer_list[TIOT_XFER_MANAGER_MAX]; + volatile uint16_t xfer_count; + volatile uint16_t state; + osal_wait tx_wait; +} tiot_xfer_send_task; + +/* 单线程 */ +static tiot_xfer_send_task g_tiot_xfer_send_task = { 0 }; + +static int32_t tiot_xfer_send_task_init(tiot_xfer_manager *xfer); +static void tiot_xfer_send_task_quit(tiot_xfer_manager *xfer); + +static int32_t tiot_xfer_send_task_queue_init(tiot_xfer_manager *xfer) +{ + /* 仅单一发送队列 */ + const uint32_t tx_queue_node_num = CONFIG_XFER_TX_NODE_NUM; + uint32_t tx_queue_mem_size = sizeof(tiot_xfer_tx_data) * tx_queue_node_num; + xfer->tx_queue_mem = (uintptr_t)osal_kmalloc(tx_queue_mem_size, OSAL_GFP_KERNEL); + if (xfer->tx_queue_mem == 0) { + tiot_print_err("[TIoT][xfer]tx queue malloc failed.\n"); + return -1; + } + (void)memset_s((void *)xfer->tx_queue_mem, tx_queue_mem_size, 0, tx_queue_mem_size); + tiot_circ_queue_init(&xfer->tx_queue, tx_queue_node_num, sizeof(tiot_xfer_tx_data), xfer->tx_queue_mem); + return 0; +} + +static void tiot_xfer_send_task_queue_deinit(tiot_xfer_manager *xfer) +{ + if (xfer->tx_queue_mem != 0) { + osal_kfree((void *)xfer->tx_queue_mem); + xfer->tx_queue_mem = 0; + } +} +#endif + +static inline int32_t tiot_xfer_default_rx_buff_init(tiot_xfer_manager *xfer) +{ +#ifdef CONFIG_XFER_DEFAULT_RX_BUFF + (void)memset_s((void *)xfer->rx_buff_mem, CONFIG_XFER_RX_BUFF_SIZE, 0, CONFIG_XFER_RX_BUFF_SIZE); + circ_buf_init(&xfer->rx_buff, &xfer->rx_buff_write, &xfer->rx_buff_read, + (void *)xfer->rx_buff_mem, CONFIG_XFER_RX_BUFF_SIZE); + return 0; +#else + tiot_unused(xfer); + tiot_print_err("[TIoT][xfer]no rx buff, check tiot_autoconfig.h.\n"); + return -1; +#endif +} + +int32_t tiot_xfer_init(tiot_xfer_manager *xfer, uintptr_t xmit_id, const tiot_xfer_device_info *dev_info) +{ + int32_t ret = 0; + const tiot_xmit_ops *xmit_ops; + /* 等待函数必须不为空,否则osal_wait_timeout_interruptible不能正常工作. */ + if ((xfer == NULL) || (dev_info == NULL) || (dev_info->rx_wait_func == NULL)) { + return -1; + } + xmit_ops = tiot_xmit_get_ops(dev_info->xmit_type); + if (xmit_ops == NULL) { + tiot_print_dbg("[TIoT][xfer]transmit type invalid.\n"); + return -1; + } + xfer->tx_queue_mem = 0; +#ifdef CONFIG_XFER_TX_SUPPORT_TASK + /* 仅单一发送队列 */ + ret = tiot_xfer_send_task_init(xfer); + if (ret != 0) { + goto rx_wait_err; + } +#endif + if ((xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) && (tiot_xfer_default_rx_buff_init(xfer) != 0)) { + goto rx_wait_err; + } + if (osal_wait_init(&xfer->rx_wait) != OSAL_SUCCESS) { + tiot_print_err("[TIoT][xfer]rx wait init failed.\n"); + goto rx_wait_err; + } + if (osal_mutex_init(&xfer->dev_mutex) != OSAL_SUCCESS) { + tiot_print_err("[TIoT][xfer]device mutex init failed.\n"); + goto dev_mutex_err; + } + if (osal_mutex_init(&xfer->read_mutex) != OSAL_SUCCESS) { + tiot_print_err("[TIoT][xfer]read mutex init failed.\n"); + goto read_mutex_err; + } + + /* Transmit实例初始化. */ + xfer->xmit_ops = xmit_ops; + xfer->xmit.id = xmit_id; + xfer->xmit_state = TIOT_XMIT_STATE_CLOSE; + /* 接收初始化 */ + xfer->rx_wait_func = dev_info->rx_wait_func; + (void)memset_s(&xfer->config, sizeof(struct tiot_xmit_config), 0, sizeof(struct tiot_xmit_config)); + /* 包格式处理初始化 */ + (void)memset_s(&xfer->pkt_ops, sizeof(tiot_xfer_packet_ops), 0, sizeof(tiot_xfer_packet_ops)); + tiot_print_suc("[TIoT][xfer]transfer manager init succ.\n"); + return ret; +read_mutex_err: + osal_mutex_destroy(&xfer->dev_mutex); +dev_mutex_err: + osal_wait_destroy(&xfer->rx_wait); +rx_wait_err: +#ifdef CONFIG_XFER_TX_SUPPORT_TASK + tiot_xfer_send_task_quit(xfer); +#endif + return -1; +} + +void tiot_xfer_deinit(tiot_xfer_manager *xfer) +{ + if (xfer == NULL) { + tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n"); + return; + } + + tiot_print_info("[TIoT][xfer]transfer manager deinit.\n"); + /* 先关闭xfer保证硬件不再发送接收 */ + tiot_xfer_close(xfer); + + /* Transmit实例去初始化. */ + (void)memset_s(&xfer->xmit, sizeof(tiot_xmit), 0, sizeof(tiot_xmit)); + (void)memset_s(&xfer->config, sizeof(struct tiot_xmit_config), 0, sizeof(struct tiot_xmit_config)); + xfer->xmit_ops = NULL; + + tiot_xfer_uninstall_packet(xfer); + +#ifdef CONFIG_XFER_TX_SUPPORT_TASK + tiot_xfer_send_task_quit(xfer); +#endif + osal_wait_destroy(&xfer->rx_wait); + + /* 互斥锁初始化 */ + osal_mutex_destroy(&xfer->dev_mutex); + osal_mutex_destroy(&xfer->read_mutex); +} + +int32_t tiot_xfer_install_packet(tiot_xfer_manager *xfer, tiot_xfer_packet_ops *pkt_ops, uintptr_t pkt_context) +{ + if (xfer == NULL) { + tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n"); + return -1; + } + + osal_mutex_lock(&xfer->dev_mutex); + (void)memcpy_s(&xfer->pkt_ops, sizeof(tiot_xfer_packet_ops), pkt_ops, sizeof(tiot_xfer_packet_ops)); + xfer->pkt_context = pkt_context; + osal_mutex_unlock(&xfer->dev_mutex); + return 0; +} + +void tiot_xfer_uninstall_packet(tiot_xfer_manager *xfer) +{ + if (xfer == NULL) { + tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n"); + return; + } + + osal_mutex_lock(&xfer->dev_mutex); + xfer->pkt_context = 0; + memset_s(&xfer->pkt_ops, sizeof(tiot_xfer_packet_ops), 0, sizeof(tiot_xfer_packet_ops)); + osal_mutex_unlock(&xfer->dev_mutex); +} + +int32_t tiot_xfer_open(tiot_xfer_manager *xfer, tiot_xfer_open_param *param) +{ + int32_t ret; + tiot_xmit_callbacks cbs = { tiot_xfer_rx_notify }; + if (xfer == NULL) { + tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n"); + return -1; + } + + osal_mutex_lock(&xfer->dev_mutex); + if (xfer->xmit_state != TIOT_XMIT_STATE_CLOSE) { + osal_mutex_unlock(&xfer->dev_mutex); + tiot_print_err("[TIoT][xfer]transmit state already opened.\n"); + return -1; + } + ret = xfer->xmit_ops->open(&xfer->xmit, &cbs); + if (ret != 0) { + osal_mutex_unlock(&xfer->dev_mutex); + tiot_print_err("[TIoT][xfer]transmit open failed.\n"); + return ret; + } + + if ((xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) && (param != NULL)) { + (void)memcpy_s(&xfer->rx_cbk_param, sizeof(tiot_xfer_cbk_param), + ¶m->rx_cbk_param, sizeof(tiot_xfer_cbk_param)); + } else { + xfer->rx_cbk_param.rx_callback = NULL; + } + + xfer->xmit_state = TIOT_XMIT_STATE_OPEN; + + osal_mutex_unlock(&xfer->dev_mutex); + return ret; +} + +int32_t tiot_xfer_set_config(tiot_xfer_manager *xfer, struct tiot_xmit_config *config) +{ + int32_t ret; + if ((xfer == NULL) || (config == NULL)) { + tiot_print_dbg("[TIoT][xfer]transfer manager or config is NULL.\n"); + return -1; + } + (void)osal_mutex_lock(&xfer->dev_mutex); + if (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE) { + tiot_print_dbg("[TIoT][xfer]transmit state closed, cannot set config.\n"); + (void)osal_mutex_unlock(&xfer->dev_mutex); + return -1; + } + ret = xfer->xmit_ops->set_config(&xfer->xmit, config); + if (ret == 0) { + (void)memcpy_s(&xfer->config, sizeof(struct tiot_xmit_config), config, sizeof(struct tiot_xmit_config)); + } + (void)osal_mutex_unlock(&xfer->dev_mutex); + return ret; +} + +int32_t tiot_xfer_get_config(tiot_xfer_manager *xfer, struct tiot_xmit_config *config) +{ + if ((xfer == NULL) || (config == NULL)) { + tiot_print_dbg("[TIoT][xfer]transfer manager or config is NULL.\n"); + return -1; + } + + (void)memcpy_s(config, sizeof(struct tiot_xmit_config), &xfer->config, sizeof(struct tiot_xmit_config)); + return 0; +} + +void tiot_xfer_close(tiot_xfer_manager *xfer) +{ + if (xfer == NULL) { + tiot_print_dbg("[TIoT][xfer]transfer manager is NULL.\n"); + return; + } + + (void)osal_mutex_lock(&xfer->dev_mutex); + if (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE) { + (void)osal_mutex_unlock(&xfer->dev_mutex); + tiot_print_dbg("[TIoT][xfer]transmit state already closed.\n"); + return; + } + + xfer->xmit_ops->close(&xfer->xmit); + (void)memset_s(&xfer->rx_cbk_param, sizeof(tiot_xfer_cbk_param), 0, sizeof(tiot_xfer_cbk_param)); + + xfer->xmit_state = TIOT_XMIT_STATE_CLOSE; +#ifdef CONFIG_XFER_DEFAULT_RX_BUFF + (void)memset_s((void *)xfer->rx_buff_mem, CONFIG_XFER_RX_BUFF_SIZE, 0, CONFIG_XFER_RX_BUFF_SIZE); + circ_buf_flush(&xfer->rx_buff); +#endif + (void)osal_mutex_unlock(&xfer->dev_mutex); + return; +} + +#ifdef CONFIG_XFER_TX_SUPPORT_TASK +static int tiot_xfer_send_task_wait_condition(void *param) +{ + tiot_xfer_send_task *send_task = &g_tiot_xfer_send_task; + if (send_task->state == TIOT_XFER_TASK_ABORT) { + return OSAL_WAIT_CONDITION_TRUE; + } + + uint16_t xfer_count = g_tiot_xfer_send_task.xfer_count; + for (uint16_t i = 0; i < xfer_count; i++) { + if (tiot_circ_queue_empty(&xfer_list[i]->tx_queue) == 0) { + return OSAL_WAIT_CONDITION_TRUE; + } + } + return 0; +} + +static void tiot_xfer_send_schedule(tiot_xfer_manager *xfer) +{ + if ((xfer == NULL) || (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE)) { + tiot_print_info("[TIoT][xfer]xfer is null or xmit close."); + return; + } + tiot_xfer_tx_data *node = NULL; + do { + node = (tiot_xfer_tx_data *)tiot_circ_queue_dequeue(&xfer->tx_queue); + if (node != NULL) { + tiot_xfer_direct_send(xfer, node->data, node->len); + } else { + tiot_print_info("[TIoT][xfer]tx queue is empty."); + } + } while (node != NULL); +} + +static void tiot_xfer_send_task_handle(void *param) +{ + (void)param; + tiot_xfer_manager **xfer_list = g_tiot_xfer_send_task.xfer_list; + uint16_t xfer_count; + for (;;) { + /* 等待某个transfer manager有数据或退出 */ + osal_wait_timeout_interruptible(&g_tiot_xfer_send_task.tx_wait, tiot_xfer_send_task_wait_condition, + NULL, OSAL_WAIT_FOREVER); + if (g_tiot_xfer_send_task.state == TIOT_XFER_TASK_ABORT) { + break; + } + xfer_count = g_tiot_xfer_send_task.xfer_count; + for (uint16_t i = 0; i < xfer_count; i++) { + tiot_xfer_send_schedule(xfer_list[i]); + } + } + + /* 退出流程. */ + g_tiot_xfer_send_task.state = TIOT_XFER_TASK_UNINIT; + osal_wait_wakeup(&g_tiot_xfer_send_task.tx_wait); +} + +static int32_t tiot_xfer_send_task_init(tiot_xfer_manager *xfer) +{ + const uint32_t stack_size = 2048; + tiot_xfer_send_task *send_task = &g_tiot_xfer_send_task; + if (send_task->xfer_count == 0) { + if (osal_wait_init(&send_task->tx_wait) != OSAL_SUCCESS) { + tiot_print_err("[TIoT][xfer]send task wait init failed.\n"); + return -1; + } + send_task->task = osal_kthread_create(tiot_xfer_send_task_handle, NULL, "tiot_tx", stack_size); + if (send_task->task == NULL) { + osal_wait_destroy(&send_task->tx_wait); + tiot_print_err("[TIoT][xfer]send task init failed.\n"); + return -1; + } + } + if (tiot_xfer_send_task_queue_init(xfer) != 0) { + return -1; + } + send_task->xfer_count++; + send_task->xfer_list[send_task->xfer_count] = xfer; + return 0; +} + +static int tiot_xfer_send_task_quit_wait_condition(void *param) +{ + if (g_tiot_xfer_send_task.state == TIOT_XFER_TASK_UNINIT) { + return OSAL_WAIT_CONDITION_TRUE; + } + return 0; +} + +/* Transfer manager去初始化时调用 */ +static void tiot_xfer_send_task_quit(tiot_xfer_manager *xfer) +{ + tiot_xfer_send_task *send_task = &g_tiot_xfer_send_task; + uint16_t xfer_count = send_task->xfer_count; + uint16_t i = 0; + for (; i < xfer_count; i++) { + if (send_task->xfer_list[i] == xfer) { + send_task->xfer_list[i] = NULL; + break; + } + } + tiot_xfer_send_task_queue_deinit(xfer); + if (i == xfer_count) { + /* 未注册 */ + return; + } + send_task->xfer_count--; + /* 当所有transfer manager均去初始化时,释放task */ + if (send_task->xfer_count == 0) { + g_tiot_xfer_send_task.state = TIOT_XFER_TASK_ABORT; + osal_wait_wakeup(&g_tiot_xfer_send_task.tx_wait); + /* 等待任务退出 */ + osal_wait_timeout_interruptible(&g_tiot_xfer_send_task.tx_wait, + tiot_xfer_send_task_quit_wait_condition, NULL, OSAL_WAIT_FOREVER); + osal_kthread_destroy(g_tiot_xfer_send_task.task, 0); + g_tiot_xfer_send_task.task = NULL; + (void)memset_s(&g_tiot_xfer_send_task, sizeof(tiot_xfer_send_task), 0, sizeof(tiot_xfer_send_task)); + } +} +#endif + +int32_t tiot_xfer_send(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len, const tiot_xfer_tx_param *param) +{ + int32_t ret; +#ifdef CONFIG_XFER_TX_SUPPORT_TASK + tiot_xfer_tx_data node = { data, len }; +#endif + if ((xfer == NULL) || (data == NULL)) { + tiot_print_err("[TIoT][xfer]transfer manager is NULL or input data is NULL."); + return -1; + } + + if (xfer->pkt_ops.tx_push != NULL) { + ret = xfer->pkt_ops.tx_push(xfer, data, len, param); + } else { +#ifdef CONFIG_XFER_TX_SUPPORT_TASK + ret = tiot_circ_queue_enqueue(&xfer->tx_queue, (uintptr_t)&node); +#else + ret = tiot_xfer_direct_send(xfer, data, len); +#endif + } + +#ifdef CONFIG_XFER_TX_SUPPORT_TASK + tiot_xfer_send_task *send_task = &g_tiot_xfer_send_task; + if (ret == 0) { + osal_wait_wakeup(&send_task->tx_wait); + } +#endif + return ret; +} + +void tiot_xfer_rx_notify(tiot_xmit *xmit, uint8_t *data, uint32_t len) +{ + int32_t ret = 0; + tiot_xfer_manager *xfer = (tiot_xfer_manager *)xmit; + if (xfer == NULL) { + tiot_print_err("[TIoT][rx]notified transmit is NULL.\n"); + return; + } + + /* 可能中断内被调用 */ + if (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE) { + tiot_print_dbg("[TIoT][rx]transmit state closed.\n"); + return; + } + + if (xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) { + if ((data == NULL) || (len == 0)) { + tiot_print_err("[TIoT][rx]notified data is NULL or len is 0.\n"); + return; + } + if (xfer->pkt_ops.rx_data_store != NULL) { + /* 由包格式决定什么时候唤醒rx_wait */ + xfer->pkt_ops.rx_data_store(xfer, data, len); + return; + } else { + /* 存入默认buffer */ + ret = tiot_xfer_read_store(&xfer->rx_buff, data, len); + } + } + + if (ret == 0) { + osal_wait_wakeup_interruptible(&xfer->rx_wait); + } else { + tiot_print_err("[TIoT][rx]circ buff not stored.\n"); + } +} + +int32_t tiot_xfer_recv(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, const tiot_xfer_rx_param *param) +{ + int32_t ret; + if ((xfer == NULL) || (param == NULL)) { + tiot_print_dbg("[TIoT][rx]transfer manager is NULL or param is NULL.\n"); + return -1; + } + + osal_mutex_lock(&xfer->dev_mutex); + if (xfer->xmit_state == TIOT_XMIT_STATE_CLOSE) { + osal_mutex_unlock(&xfer->dev_mutex); + tiot_print_dbg("[TIoT][rx]transmit state closed.\n"); + return -1; + } + osal_mutex_unlock(&xfer->dev_mutex); + + if (xfer->pkt_ops.read_out != NULL) { + ret = xfer->pkt_ops.read_out(xfer, buff, len, param); + } else { + /* 默认读取路径,固件加载时使用. */ + ret = tiot_xfer_read_out(xfer, buff, len, param->timeout); + } + + return ret; +} diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer.h b/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer.h new file mode 100644 index 000000000..d9866bf94 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer.h @@ -0,0 +1,248 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT transfer module. \n + * + * History: \n + * 2023-04-18, Create file. \n + */ +#ifndef TIOT_XFER_H +#define TIOT_XFER_H + +#include "tiot_board_xmit.h" +#include "tiot_board_xmit_ops.h" +#include "tiot_circ_queue.h" +#include "tiot_circ_buf.h" +#include "tiot_osal.h" +#include "tiot_board_uart_port.h" + +#ifdef __KERNEL__ +#include +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_transfer Transfer + * @ingroup tiot_common + * @{ + */ + +/* 临时flags, 用于拆分低功耗持锁 & disallow消息. */ +#define TIOT_XFER_RESUME 0U +#define TIOT_XFER_SUSPEND ((uint16_t)1 << 1) +#define TIOT_XFER_DELAY_MSG ((uint16_t)1 << 2) + +#define TIOT_XFER_RECV_NO_WAIT ((uint32_t)0) +#define TIOT_XFER_RECV_WAIT_FOREVER ((uint32_t)0xFFFFFFF) + +/** + * @brief TIoT Transmit port state. + */ +typedef enum { + TIOT_XMIT_STATE_CLOSE, /* TIoT Transmit state close. */ + TIOT_XMIT_STATE_OPEN, /* TIoT Transmit state open. */ + TIOT_XMIT_STATE_BUSY /* TIoT Transmit state busy for reading or writing. */ +} tiot_xmit_state; + +/** + * @brief TIoT Transfer send node, cound be exetend by packet ops with other attributes. + */ +typedef struct { + const uint8_t *data; /* Pointer to send buff. */ + uint32_t len; /* Send len. */ +} tiot_xfer_tx_data; + +/** + * @brief TIoT Transfer send param, cound be exetend by packet ops with other attributes. + */ +typedef struct { + uint32_t subsys; /* subsys info. */ +} tiot_xfer_tx_param; + +/** + * @brief TIoT Transfer receive param, cound be exetend by packet ops with other attributes. + */ +typedef struct { + uint32_t timeout; /* Read timeout by ms, 0 timeout means no wait. */ + uint32_t subsys; /* subsys info. */ +#ifdef __KERNEL__ + struct file *filp; + poll_table *poll_wait; +#endif +} tiot_xfer_rx_param; + +struct _tiot_xfer_manager; +struct _tiot_xfer_packet; + +/** + * @brief TIoT Transfer packet operations. + */ +typedef struct { + /*!< Packet parse tx node, and push to transmit or tx queue. */ + int32_t (* tx_push)(struct _tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len, + const tiot_xfer_tx_param *param); + /*!< Read data out to caller buffer, same as tiot_xfer_recv. */ + int32_t (* read_out)(struct _tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, const tiot_xfer_rx_param *param); + /*!< For async read, store data from board transmit isr. */ + void (* rx_data_store)(struct _tiot_xfer_manager *xfer, uint8_t *data, uint32_t len); +} tiot_xfer_packet_ops; + +/** + * @brief TIoT Transfer device info. + */ +typedef struct { + tiot_xmit_type xmit_type; + osal_wait_condition_func rx_wait_func; /*!< Device related read wait func, could be gpio level. */ +} tiot_xfer_device_info; + +typedef struct { + uint8_t *buff; + uint32_t buff_len; + void (*rx_callback)(const uint8_t *buff, uint32_t len); +} tiot_xfer_cbk_param; + +typedef struct { + tiot_xfer_cbk_param rx_cbk_param; +} tiot_xfer_open_param; + +/** + * @brief TIoT Transfer manager. + */ +typedef struct _tiot_xfer_manager { + /* Board transmit infos. */ + tiot_xmit xmit; /*!< Board transmit instance. */ + const tiot_xmit_ops *xmit_ops; /*!< Board transmit operations. */ + struct tiot_xmit_config config; /*!< Board transmit config saved. */ + uint16_t xmit_state; /*!< Board transmit state, close or open. */ + uint16_t xmit_suspend; /*!< Tmp flag for suspend, will merge to state. */ + + /* Mutexes */ + osal_mutex dev_mutex; /*!< Transmit device mutex. */ + osal_mutex read_mutex; /*!< Transmit read mutex. */ + + /* Send */ + tiot_circ_queue_t tx_queue; /*!< Tx circular queue, with tiot_xfer_tx_node as node. */ + uintptr_t tx_queue_mem; /*!< Tx circular queue allocated memory. */ + + /* Recieve */ + osal_wait rx_wait; + osal_wait_condition_func rx_wait_func; /*!< Registed read wait func, could be gpio level. */ + + tiot_circ_buf rx_buff; /*!< Rx circular buff. */ + uint32_t rx_buff_write; /*!< Rx circular buff write index. */ + uint32_t rx_buff_read; /*!< Rx circular buff read index. */ +#ifdef CONFIG_XFER_DEFAULT_RX_BUFF + /*!< Rx circular buff memory. */ + uint8_t rx_buff_mem[CONFIG_XFER_RX_BUFF_SIZE]; +#endif + + /* Packet */ + tiot_xfer_packet_ops pkt_ops; /*!< Packet operation, tx & rx data packet parse. */ + uintptr_t pkt_context; /*!< Packet operation used context. */ + + tiot_xfer_cbk_param rx_cbk_param; +} tiot_xfer_manager; + +/** + * @brief TIoT Transfer manager init. + * @param [in] xfer Transfer manager. + * @param [in] xmit_id Board Transmit id. + * @param [in] dev_info Device Transfer related info. + * @return if OK return 0, else return -1. + */ +int32_t tiot_xfer_init(tiot_xfer_manager *xfer, uintptr_t xmit_id, const tiot_xfer_device_info *dev_info); + +/** + * @brief TIoT Transfer manager deinit. + * @param [in] xfer Transfer manager. + */ +void tiot_xfer_deinit(tiot_xfer_manager *xfer); + +/** + * @brief TIoT Transfer manager install packet. + * @param [in] xfer Transfer manager. + * @param [in] pkt_ops Transfer packet ops. + * @param [in] pkt_context Transfer packet context. + * @return if OK return 0, else return -1. + */ +int32_t tiot_xfer_install_packet(tiot_xfer_manager *xfer, tiot_xfer_packet_ops *pkt_ops, uintptr_t pkt_context); + +/** + * @brief TIoT Transfer manager uninstall packet. + * @param [in] xfer Transfer manager. + */ +void tiot_xfer_uninstall_packet(tiot_xfer_manager *xfer); + +/** + * @brief TIoT Transfer manager open, with packet installed. + * @param [in] xfer Transfer manager. + * @return if OK return 0, else return -1. + */ +int32_t tiot_xfer_open(tiot_xfer_manager *xfer, tiot_xfer_open_param *param); + +/** + * @brief TIoT Transfer manager close. + * @param [in] xfer Transfer manager. + */ +void tiot_xfer_close(tiot_xfer_manager *xfer); + +/** + * @brief TIoT Transfer manager set config. + * @param [in] xfer Transfer manager. + * @param [in] config New config to be set. + * @return if OK return 0, else return -1. + */ +int32_t tiot_xfer_set_config(tiot_xfer_manager *xfer, struct tiot_xmit_config *config); + +/** + * @brief TIoT Transfer manager get config. + * @param [in] xfer Transfer manager. + * @param [out] config copy old transmit config to caller. + * @return if OK return 0, else return -1. + */ +int32_t tiot_xfer_get_config(tiot_xfer_manager *xfer, struct tiot_xmit_config *config); + +/** + * @brief TIoT Transfer manager send. + * @param [in] xfer Transfer manager. + * @param [out] data Caller send data. + * @param [in] len Caller data len. + * @param [in] param Caller send param, optional. + * @return if Send OK return actual send len, else return -1. + */ +int32_t tiot_xfer_send(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len, const tiot_xfer_tx_param *param); + +/** + * @brief TIoT Transfer RX read notify. + * @param [in] xmit Transmit instance, will be extend to Transfer manager instance. + * @param [in] data RX data need to read, could be NULL for sync read. + * @param [in] len Rx data len need to read, 0 indicates sync read. + */ +void tiot_xfer_rx_notify(tiot_xmit *xmit, uint8_t *data, uint32_t len); + +/** + * @brief TIoT Transfer receive. + * @param [in] xfer Transfer manager. + * @param [out] data Caller read buff. + * @param [in] len Caller expected read len. + * @param [in] param Caller receive param. + * @return if Read OK return actual read len, if timeout, return 0, else return -1. + */ +int32_t tiot_xfer_recv(tiot_xfer_manager *xfer, uint8_t *data, uint32_t len, const tiot_xfer_rx_param *param); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer_utils.c b/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer_utils.c new file mode 100644 index 000000000..03937754c --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer_utils.c @@ -0,0 +1,84 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-04-26, Create file. \n + */ + +#include "tiot_xfer_utils.h" + +int32_t tiot_xfer_direct_send(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len) +{ + int32_t ret; + const uint8_t *buff = data; + uint32_t remain_len = len; + while (remain_len) { + /* 板级接口可能有单次发送限制. */ + (void)osal_mutex_lock(&xfer->dev_mutex); + if (xfer->xmit_state != TIOT_XMIT_STATE_OPEN) { + ret = -1; + } else { + ret = xfer->xmit_ops->write(&xfer->xmit, buff, remain_len); + } + (void)osal_mutex_unlock(&xfer->dev_mutex); + /* 阻塞式接口,发送结果为0情况时继续发送 */ + if (ret < 0) { + return -1; + } + + remain_len -= ret; + buff += ret; + } + return len; +} + +int32_t tiot_xfer_read_store(tiot_circ_buf *cb, uint8_t *data, uint32_t len) +{ + int32_t ret; + if ((cb == NULL) || (circ_buf_query_free(cb) < len)) { + return -1; + } + ret = circ_buf_write(cb, data, len); + if (ret == 0) { + return -1; + } + return 0; +} + +static int tiot_xfer_read_out_check(const void *param) +{ + tiot_xfer_manager *xfer = (tiot_xfer_manager *)param; + if ((xfer->rx_wait_func(xfer) != 0) || + ((xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) && (circ_buf_query_busy(&xfer->rx_buff) != 0))) { + return 1; + } + return 0; +} + +int32_t tiot_xfer_read_out(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, uint32_t timeout_ms) +{ + int32_t read_len; + int32_t timeout = osal_wait_timeout_interruptible(&xfer->rx_wait, tiot_xfer_read_out_check, + (const void *)xfer, timeout_ms); + /* 超时返回 0, 失败返回-1 */ + if (timeout <= 0) { + return timeout; + } + osal_mutex_lock(&xfer->dev_mutex); + + if (xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) { + uint32_t buff_data_len = circ_buf_query_busy(&xfer->rx_buff); + read_len = buff_data_len < len ? buff_data_len : len; + read_len = circ_buf_read(&xfer->rx_buff, buff, read_len); + if (read_len == 0) { + read_len = -1; + } + } else { + read_len = xfer->xmit_ops->read(&xfer->xmit, buff, len); + } + + osal_mutex_unlock(&xfer->dev_mutex); + return read_len; +} diff --git a/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer_utils.h b/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer_utils.h new file mode 100644 index 000000000..748e53f37 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/transfer/tiot_xfer_utils.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-04-26, Create file. \n + */ +#ifndef TIOT_XFER_UTILS_H +#define TIOT_XFER_UTILS_H + +#include "tiot_xfer.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_transfer_utils Transfer Utils + * @ingroup tiot_common_transfer + * @{ + */ + +int32_t tiot_xfer_direct_send(tiot_xfer_manager *xfer, const uint8_t *data, uint32_t len); + +int32_t tiot_xfer_read_store(tiot_circ_buf *cb, uint8_t *data, uint32_t len); + +int32_t tiot_xfer_read_out(tiot_xfer_manager *xfer, uint8_t *buff, uint32_t len, uint32_t timeout_ms); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/utils/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/utils/CMakeLists.txt new file mode 100644 index 000000000..7f5d5bcf3 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/CMakeLists.txt @@ -0,0 +1,15 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +set( + utils_header_lists + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/circ_buf" + "${CMAKE_CURRENT_SOURCE_DIR}/list" +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${utils_header_lists}" CACHE INTERNAL "tiot header list" FORCE) +add_subdirectory(circ_queue) +add_subdirectory(fileops) +add_subdirectory(misc) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/utils/circ_buf/tiot_circ_buf.h b/code/sdk/zhihui/gnss/driver/common/utils/circ_buf/tiot_circ_buf.h new file mode 100644 index 000000000..d1e538dd9 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/circ_buf/tiot_circ_buf.h @@ -0,0 +1,207 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd.. 2019-2024. All rights reserved. + * Description: audio circle buffer function + * Author: audio + * Create: 2019-05-30 + */ + +#ifndef TIOT_CIRC_BUF_H +#define TIOT_CIRC_BUF_H + +#include "securec.h" +#include "tiot_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +typedef struct { + volatile uint32_t *write; /* circle buffer write pointer */ + volatile uint32_t *read; /* circle buffer read pointer */ + uint8_t *data; /* circle buffer data virtual address */ + uint32_t size; /* circle buffer size */ +} tiot_circ_buf; + +static inline uint32_t circ_buf_min(uint32_t x, uint32_t y) +{ + return (x <= y) ? x : y; +} + +static inline uint32_t saturate_add(uint32_t x, uint32_t y, uint32_t saturation) +{ + /* add x and y, saturate to saturation */ + uint32_t x_temp = x + y; + + return (x_temp >= saturation) ? (x_temp - saturation) : x_temp; +} + +static inline void circ_buf_init(tiot_circ_buf *cb, uint32_t *write, uint32_t *read, void *data, uint32_t len) +{ + cb->write = write; + cb->read = read; + cb->data = (uint8_t*)data; + cb->size = len; + + *cb->write = 0; + *cb->read = 0; +} + +static inline void circ_buf_flush(tiot_circ_buf *cb) +{ + *cb->read = 0; + *cb->write = 0; +} + +static inline uint32_t circ_buf_data_size(uint32_t write, uint32_t read, uint32_t size) +{ + return (write >= read) ? (write - read) : (size - read + write); +} + +static inline uint32_t circ_buf_free_size(uint32_t write, uint32_t read, uint32_t size) +{ + return size - circ_buf_data_size(write, read, size); +} + +static inline uint32_t __circ_buf_read_data(const tiot_circ_buf *cb, uint8_t *to, uint32_t len, uint32_t off) +{ + if ((len == 0) || (memcpy_s(to, len * sizeof(uint8_t), cb->data + off, len) != EOK)) { + return 0; + } + + return len; +} + +/* read data from circle buffer */ +static inline uint32_t circ_buf_read_data(const tiot_circ_buf *cb, uint8_t *to, uint32_t len, uint32_t off) +{ + uint32_t l = circ_buf_min(len, cb->size - off); + + if (to == NULL) { + /* dump data in circle buffer */ + return len; + } + + return __circ_buf_read_data(cb, to, l, off) + __circ_buf_read_data(cb, to + l, len - l, 0); +} + +static inline uint32_t __circ_buf_write_zero(tiot_circ_buf *cb, const uint8_t *from, uint32_t len, uint32_t off) +{ + if ((len == 0) || (memset_s(cb->data + off, len, 0, len) != EOK)) { + return 0; + } + (void)from; + return len; +} + +static inline uint32_t __circ_buf_write_data(tiot_circ_buf *cb, const uint8_t *from, uint32_t len, uint32_t off) +{ + if ((len == 0) || (memcpy_s(cb->data + off, cb->size - off, from, len) != EOK)) { + return 0; + } + + return len; +} + +/* + * circ_buf_write_data - puts some data from kernel space into the circle buffer + * @cb: address of the circle buffer to be used + * @from: pointer to the data to be added + * @len: the length of the data to be added + * @off: data write offset in circle buffer + * + * Note: Check free space in circle buffer before calling this function + */ +static inline uint32_t circ_buf_write_data(tiot_circ_buf *cb, const uint8_t *from, uint32_t len, uint32_t off) +{ + uint32_t l = circ_buf_min(len, cb->size - off); + + /* generate mute data if input buffer is NULL */ + uint32_t (*action)(tiot_circ_buf *, const uint8_t *, uint32_t, uint32_t) = + (from == NULL) ? __circ_buf_write_zero : __circ_buf_write_data; + + return action(cb, from, l, off) + action(cb, from + l, len - l, 0); +} + +static inline uint32_t circ_buf_query_busy(const tiot_circ_buf *cb) +{ + return circ_buf_data_size(*cb->write, *cb->read, cb->size); +} + +static inline uint32_t circ_buf_query_free(const tiot_circ_buf *cb) +{ + return circ_buf_free_size(*cb->write, *cb->read, cb->size); +} + +/* read data from circle buffer */ +static inline uint32_t circ_buf_read(tiot_circ_buf *cb, uint8_t *to, uint32_t len) +{ + uint32_t read = *cb->read; + + if ((len == 0) || (circ_buf_data_size(*cb->write, read, cb->size) < len) || + (circ_buf_read_data(cb, to, len, read) != len)) { + return 0; + } + + *cb->read = saturate_add(read, len, cb->size); + return len; +} + +/* write data into circle buffer */ +static inline uint32_t circ_buf_write(tiot_circ_buf *cb, const uint8_t *from, uint32_t len) +{ + uint32_t write = *cb->write; + + if ((len == 0) || (circ_buf_write_data(cb, from, len, write) != len)) { + return 0; + } + + *cb->write = saturate_add(write, len, cb->size); + return len; +} + +static inline uint32_t circ_buf_update_read_pos(tiot_circ_buf *cb, uint32_t len) +{ + *cb->read = saturate_add(*cb->read, len, cb->size); + return len; +} + +static inline uint32_t circ_buf_update_write_pos(tiot_circ_buf *cb, uint32_t len) +{ + *cb->write = saturate_add(*cb->write, len, cb->size); + return len; +} + +static inline uint32_t circ_buf_cast_read(const tiot_circ_buf *cb, uint32_t *data_offset, uint32_t len) +{ + uint32_t read = *cb->read; + + if (circ_buf_data_size(*cb->write, read, cb->size) < len) { + *data_offset = 0; + return 0; + } + + *data_offset = read; + return len; +} + +static inline uint32_t circ_buf_cast_relese(tiot_circ_buf *cb, uint32_t len) +{ + uint32_t read = *cb->read; + uint32_t data_size = circ_buf_data_size(*cb->write, read, cb->size); + uint32_t len_temp; + + len_temp = circ_buf_min(data_size, len); + *cb->read = saturate_add(read, len_temp, cb->size); + + return len_temp; +} + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/CMakeLists.txt new file mode 100644 index 000000000..4b0bdb438 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/CMakeLists.txt @@ -0,0 +1,11 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +set( + tiot_circ_queue_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_circ_queue.c +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_circ_queue_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/tiot_circ_queue.c b/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/tiot_circ_queue.c new file mode 100644 index 000000000..f56f4a64c --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/tiot_circ_queue.c @@ -0,0 +1,124 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Tiot Circular queue header. \n + * + * History: \n + * 2023-04-18, Create file. \n + */ +#include "tiot_circ_queue.h" +#ifdef __KERNEL__ +#include +#endif +#include "securec.h" + +#ifndef __KERNEL__ +#if (defined(__GNUC__)) +#define likely(_expr) __builtin_expect(!!(_expr), 1) +#define unlikely(_expr) __builtin_expect(!!(_expr), 0) +#else +#define likely(_expr) (_expr) +#define unlikely(_expr) (_expr) +#endif +#endif + +static inline uint16_t tiot_circ_queue_mask(const tiot_circ_queue_t *queue) +{ + return (queue->size - 1); +} + +static inline uintptr_t tiot_circ_queue_node(const tiot_circ_queue_t *queue, uint16_t idx) +{ + return (queue->mem_addr + ((idx & tiot_circ_queue_mask(queue)) * queue->node_bytes)); +} + +static inline uint16_t _tiot_circ_queue_space(tiot_circ_queue_t *queue) +{ + return ((queue->tail - (queue->head + 1)) & tiot_circ_queue_mask(queue)); +} + +void tiot_circ_queue_init(tiot_circ_queue_t *queue, uint16_t size, uint16_t node_bytes, uintptr_t mem_addr) +{ + if (unlikely((queue == NULL) || (size == 0) || (node_bytes == 0) || (mem_addr == 0))) { + return; + } + + /* 队列大小应为2的幂次方 */ + if ((size & (size - 1)) != 0) { + return; + } + + osal_spin_lock_init(&queue->lock); + + queue->head = 0; + queue->tail = 0; + queue->size = size; + queue->node_bytes = node_bytes; + queue->mem_addr = mem_addr; +} + +/* + * 功能描述: 入队列一个节点 + */ +int32_t tiot_circ_queue_enqueue(tiot_circ_queue_t *queue, uintptr_t src_node) +{ + uintptr_t dis_node; + unsigned long flags; + + osal_spin_lock_irqsave(&queue->lock, &flags); + + // 检查队列是否已满 + if (_tiot_circ_queue_space(queue) == 0) { + osal_spin_unlock_irqrestore(&queue->lock, &flags); + return -1; + } + + // 保存节点内容 + dis_node = tiot_circ_queue_node(queue, queue->head); + if (memcpy_s((void *)dis_node, queue->node_bytes, (void *)src_node, queue->node_bytes) != EOK) { + osal_spin_unlock_irqrestore(&queue->lock, &flags); + return -1; + } + + // 索引更新到下一位置 + queue->head = (queue->head + 1) & tiot_circ_queue_mask(queue); + + osal_spin_unlock_irqrestore(&queue->lock, &flags); + return 0; +} + +/* + * 功能描述: 从循环队列中,取出最早入队列的节点 + */ +uintptr_t tiot_circ_queue_dequeue(tiot_circ_queue_t *queue) +{ + uintptr_t node; + unsigned long flags; + + osal_spin_lock_irqsave(&queue->lock, &flags); + + // 检查是否为空 + if (queue->head == queue->tail) { + osal_spin_unlock_irqrestore(&queue->lock, &flags); + return 0; + } + + node = tiot_circ_queue_node(queue, queue->tail); + + // 索引更新到下一位置 + queue->tail = (queue->tail + 1) & tiot_circ_queue_mask(queue); + + osal_spin_unlock_irqrestore(&queue->lock, &flags); + return node; +} + +uint16_t tiot_circ_queue_space(tiot_circ_queue_t *queue) +{ + uint16_t space; + unsigned long flags; + + osal_spin_lock_irqsave(&queue->lock, &flags); + space = _tiot_circ_queue_space(queue); + osal_spin_unlock_irqrestore(&queue->lock, &flags); + return space; +} diff --git a/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/tiot_circ_queue.h b/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/tiot_circ_queue.h new file mode 100644 index 000000000..5d2d668a6 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/circ_queue/tiot_circ_queue.h @@ -0,0 +1,105 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Tiot Circular queue header. \n + * + * History: \n + * 2023-04-18, Create file. \n + */ +#ifndef TIOT_CIRC_QUEUE_H +#define TIOT_CIRC_QUEUE_H + +#include "tiot_types.h" +#include "tiot_osal.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_util_tiot_circ_queue Circular Queue + * @ingroup tiot_common_util + * @{ + */ + +typedef struct { + uint16_t head; // 队列头索引,入队索引 + uint16_t tail; // 队列尾索引,出队索引 + uint16_t size; // 队列总大小,深度 + uint16_t node_bytes; // 每个节点的长度 + uintptr_t mem_addr; // 队列管理的内存空间(size * node_bytes)起始地址 + osal_spinlock lock; +} tiot_circ_queue_t; + +/** + * @brief TIoT circ queue empty or not. + * @param [in] queue Circular queue. + * @return if empty return 1, else return 0. + */ +static inline int32_t tiot_circ_queue_empty(tiot_circ_queue_t *queue) +{ + int32_t ret; + unsigned long flags; + osal_spin_lock_irqsave(&queue->lock, &flags); + ret = (queue->head == queue->tail); + osal_spin_unlock_irqrestore(&queue->lock, &flags); + return ret; +} + +/** + * @brief TIoT circ queue clear. + * @param queue Circular queue. + */ +static inline void tiot_circ_queue_clear(tiot_circ_queue_t *queue) +{ + unsigned long flags; + osal_spin_lock_irqsave(&queue->lock, &flags); + queue->head = 0; + queue->tail = 0; + osal_spin_unlock_irqrestore(&queue->lock, &flags); +} + +/** + * @brief TIoT circ queue init. + * @param [in] queue Circular queue. + * @param [in] size Queue size, nodes number max is size - 1, must be power of 2. + * @param [in] node_bytes Fixed node size. + * @param [in] mem_addr Queue memory start address, ensure has init outside, length should be size * node_bytes. + */ +void tiot_circ_queue_init(tiot_circ_queue_t *queue, uint16_t size, uint16_t node_bytes, uintptr_t mem_addr); + +/** + * @brief TIoT circ queue enqueue. + * @param [in] queue Circular queue. + * @param [in] src_node Node to be enqueued, will be copyed in queue memory. + * @return if OK return 0, else return -1. + */ +int32_t tiot_circ_queue_enqueue(tiot_circ_queue_t *queue, uintptr_t src_node); + +/** + * @brief TIoT circ queue dequeue. + * @param [in] queue Circular queue. + * @return Pointer to deequeued node. + */ +uintptr_t tiot_circ_queue_dequeue(tiot_circ_queue_t *queue); + +/** + * @brief TIoT circ queue space. + * @param [in] queue Circular queue. + * @return Circ queue avalible space for nodes. + */ +uint16_t tiot_circ_queue_space(tiot_circ_queue_t *queue); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/utils/fileops/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/utils/fileops/CMakeLists.txt new file mode 100644 index 000000000..40434cf17 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/fileops/CMakeLists.txt @@ -0,0 +1,11 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +set( + tiot_fileops_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_fileops.c +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_fileops_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/utils/fileops/tiot_fileops.c b/code/sdk/zhihui/gnss/driver/common/utils/fileops/tiot_fileops.c new file mode 100644 index 000000000..c2179c1a0 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/fileops/tiot_fileops.c @@ -0,0 +1,93 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT file ops. \n + * + * History: \n + * 2023-04-13, Create file. \n + */ + +#include "tiot_fileops.h" +#include "tiot_board_log.h" +#include "tiot_osal.h" +#include "securec.h" +#include "tiot_types.h" + +#ifdef CONFIG_FILE_BY_ARRAY +tiot_file *tiot_file_open(const tiot_file_path *path, const char *file_name, int flags, int mode) +{ + unsigned int i; + const tiot_file *file_list; + /* 非只读文件 */ + tiot_unused(mode); + if (flags != OSAL_O_RDONLY) { + tiot_print_dbg("[TIoT][file]rw file\n"); + return NULL; + } + if (path == NULL) { + tiot_print_dbg("[TIoT][file]array file path is NULL\n"); + return NULL; + } + + file_list = path->file_list; /* 文件数组生成保证不为NULL. */ + for (i = 0; i < path->file_num; i++) { + if (strcmp(file_list->name, file_name) == 0) { + return (tiot_file *)file_list; + } + file_list++; + } + return NULL; +} + +int tiot_file_read(tiot_file *filp, char *buf, unsigned long size, int offset) +{ + uint32_t remain_size; + uint32_t copy_size; + int ret; + if (buf == NULL) { + return -1; + } + /* 偏移值需在文件数据范围内. */ + if ((offset < 0) || (offset > filp->len)) { + tiot_print_err("[TIoT][file]exceed file range!\n"); + return -1; + } + + remain_size = filp->len - offset; + copy_size = size > remain_size ? remain_size : size; + if (copy_size == 0) { + /* 处于文件末尾 */ + return 0; + } + ret = memcpy_s(buf, copy_size, &filp->data[offset], copy_size); + if (ret != EOK) { + return -1; + } + return copy_size; +} +#else +tiot_file *tiot_file_open(const tiot_file_path *path, const char *file_name, int flags, int mode) +{ + (void)path; + return (tiot_file *)osal_klib_fopen(file_name, flags, mode); +} + +void tiot_file_close(tiot_file *filp) +{ + osal_klib_fclose((void *)filp); +} + +int tiot_file_read(tiot_file *filp, char *buf, unsigned long size, int offset) +{ + if (buf == NULL) { + tiot_print_err("[TIoT][file]read buff is NULL!\n"); + return -1; + } + if (osal_klib_fseek(offset, OSAL_SEEK_SET, (void *)filp) < 0) { + tiot_print_err("[TIoT][file]fseek error!\n"); + return -1; + } + return osal_klib_fread(buf, size, (void *)filp); +} +#endif + diff --git a/code/sdk/zhihui/gnss/driver/common/utils/fileops/tiot_fileops.h b/code/sdk/zhihui/gnss/driver/common/utils/fileops/tiot_fileops.h new file mode 100644 index 000000000..131269cc6 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/fileops/tiot_fileops.h @@ -0,0 +1,90 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Tiot file types. \n + * + * History: \n + * 2023-04-12, Create file. \n + */ +#ifndef TIOT_FILEOPS_H +#define TIOT_FILEOPS_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_utils_file_ops File Ops + * @ingroup tiot_common_utils + * @{ + */ + +#ifdef CONFIG_FILE_BY_ARRAY +#define TIOT_FILE_NAME_MAX 16 + +/** + * @brief TIoT file struct for file array, read only. + */ +typedef struct { + const char name[TIOT_FILE_NAME_MAX]; + int len; + const char *data; +} tiot_file; + +/** + * @brief TIoT file search path, set for search file array, read only. + */ +typedef struct { + const tiot_file *file_list; /* A list of file array, read only. */ + const unsigned int file_num; /* File array num, read only. */ +} tiot_file_path; +#else +typedef void *tiot_file; /*!< Dummy type for filp when board has file system. */ +typedef char tiot_file_path; /*!< Dummy type for path when board has file system. */ +#endif + +#ifdef CONFIG_FILE_BY_ARRAY +#define tiot_file_close(filp) /*!< No need to close for file array. */ +#else +/** + * @brief TIoT file open, redirect to osal_klib_fclose. + * @param [in] filp File handle. + */ +void tiot_file_close(tiot_file *filp); +#endif + +/** + * @brief TIoT file open, for file system see @ref osal_klib_fopen, path is ignored. + * for file array, search in file name in the tiot_file_path. + * @param [in] path File array path, ignore for file system. + * @param [in] file_name File name. + * @param [in] flags File flags, like: OSAL_O_RDONLY. + * @param [in] mode File rwx mode, like: 0644. + * @return if OK return file handle, else return NULL. + */ +tiot_file *tiot_file_open(const tiot_file_path *path, const char *file_name, int flags, int mode); + +/** + * @brief TIoT file read, for file system read to buf->buff. + * for file array, only move the buff pointer to offset. + * @param [in] filp TIoT file handle. + * @param [in] buf TIoT file readbuf. + * @param [in] size Required read size. + * @param [in] offset Read offset of file. + * @return The length that has been read, could less than required size, or -1 if fail. + */ +int tiot_file_read(tiot_file *filp, char *buf, unsigned long size, int offset); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/common/utils/list/tiot_list.h b/code/sdk/zhihui/gnss/driver/common/utils/list/tiot_list.h new file mode 100644 index 000000000..717b5bad3 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/list/tiot_list.h @@ -0,0 +1,182 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT list. \n + * + * History: \n + * 2023-08-03, Create file. \n + */ +#ifndef TIOT_LIST_H +#define TIOT_LIST_H + +#include "tiot_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_util_tiot_list List + * @ingroup tiot_common_util + * @{ + */ + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct tiot_list_head { + struct tiot_list_head *next, *prev; +}; + +#define tiot_list_head_init(name) \ + { \ + &(name), &(name) \ + } + +#define tiot_list_head_create(name) \ + struct tiot_list_head name = tiot_list_head_init(name) + +static inline void tiot_init_list_head(struct tiot_list_head *list) +{ + if (list == NULL) { + return; + } + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void tiot___list_add(struct tiot_list_head *_new, + struct tiot_list_head *prev, + struct tiot_list_head *next) +{ + if (_new == NULL || prev == NULL || next == NULL) { + return; + } + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void tiot_list_add_tail(struct tiot_list_head *cur, struct tiot_list_head *head) +{ + tiot___list_add(cur, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void tiot___list_del(struct tiot_list_head *prev, struct tiot_list_head *next) +{ + if (prev == NULL || next == NULL) { + return; + } + + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void tiot___list_del_entry(struct tiot_list_head *entry) +{ + if (entry == NULL) { + return; + } + tiot___list_del(entry->prev, entry->next); +} + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void tiot_list_replace(struct tiot_list_head *old, + struct tiot_list_head *_new) +{ + _new->next = old->next; + _new->next->prev = _new; + _new->prev = old->prev; + _new->prev->next = _new; +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define tiot_list_entry(ptr, type, member) \ + tiot_container_of(ptr, type, member) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * @pos_type: type of the struct which the list_node in. + */ +#define tiot_list_for_each_entry(pos, head, member, pos_type) \ + for ((pos) = tiot_list_entry((head)->next, pos_type, member); \ + &(pos)->member != (head); \ + (pos) = tiot_list_entry((pos)->member.next, pos_type, member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * @pos_type: type of pos. + * @n_type: type of n. + */ +#define tiot_list_for_each_entry_safe(pos, n, head, member, pos_type, n_type) \ + for ((pos) = tiot_list_entry((head)->next, pos_type, member), \ + (n) = tiot_list_entry((pos)->member.next, pos_type, member); \ + &(pos)->member != (head); \ + (pos) = (n), (n) = tiot_list_entry((n)->member.next, n_type, member)) + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/utils/misc/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/common/utils/misc/CMakeLists.txt new file mode 100644 index 000000000..d20f3a5af --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/misc/CMakeLists.txt @@ -0,0 +1,11 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. +#=============================================================================== +set( + tiot_misc_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_misc.c +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_misc_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/utils/misc/tiot_misc.c b/code/sdk/zhihui/gnss/driver/common/utils/misc/tiot_misc.c new file mode 100644 index 000000000..2e2c61f49 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/misc/tiot_misc.c @@ -0,0 +1,55 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. \n + * + * Description: TIoT miscellaneous file. \n + * + * History: \n + * 2024-06-20, Create file. \n + */ + +#include "tiot_misc.h" + +#define TIOT_HEX_RADIX 16 +#define TIOT_CONVERT_BASIC_LEN 1 +#define TIOT_CONVERT_STR_MIN_LEN 4 + +// For example, if 3200 is entered, 0xC80 is displayed. +int32_t tiot_num_to_hex(uint32_t num, char* str_buff, uint32_t str_buff_len) +{ + int right = 0; + int str_num = 0; + uint32_t number = num; + int left = 2; // 跳过前两个字符"0x". + const char map[] = "0123456789ABCDEF"; + + if (str_buff == NULL || str_buff_len < TIOT_CONVERT_STR_MIN_LEN) { + return -1; + } + + str_buff[str_num++] = '0'; + str_buff[str_num++] = 'x'; + + // Conversion part. + do { + str_buff[str_num++] = map[number % TIOT_HEX_RADIX]; + number /= TIOT_HEX_RADIX; + + // 确保有空间存放结束符'\0'. + if ((uint32_t)(str_num + TIOT_CONVERT_BASIC_LEN) > str_buff_len) { + str_buff[0] = '\0'; + return -1; + } + } while (number); + + // Inverting Data + right = str_num - TIOT_CONVERT_BASIC_LEN; + while (right > left) { + char tmp = str_buff[left]; + str_buff[left] = str_buff[right]; + str_buff[right] = tmp; + left++; + right--; + } + str_buff[str_num++] = '\0'; + return 0; +} diff --git a/code/sdk/zhihui/gnss/driver/common/utils/misc/tiot_misc.h b/code/sdk/zhihui/gnss/driver/common/utils/misc/tiot_misc.h new file mode 100644 index 000000000..4f7e441c2 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/misc/tiot_misc.h @@ -0,0 +1,46 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. \n + * + * Description: Tiot miscellaneous header file. \n + * + * History: \n + * 2024-06-20, Create file. \n + */ +#ifndef TIOT_MISC_H +#define TIOT_MISC_H + +#include "tiot_types.h" +#include "tiot_osal.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_utils_tiot_misc TIOT miscellaneous function + * @ingroup tiot_common_utils + * @{ + */ + +/** + * @brief TIoT converts a non-negative integer to a hexadecimal string. + * @param [in] num Nonnegative integer. + * @param [in] str_buff String after conversion num. + * @param [in] str_buff_len Length of str_buff. + * @return 0 is returned if Conversion succeeded. Otherwise, -1 is returned. + */ +int32_t tiot_num_to_hex(uint32_t num, char* str_buff, uint32_t str_buff_len); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/common/utils/tiot_types.h b/code/sdk/zhihui/gnss/driver/common/utils/tiot_types.h new file mode 100644 index 000000000..4854c71c8 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/common/utils/tiot_types.h @@ -0,0 +1,66 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: TIoT types. \n + * + * History: \n + * 2023-06-01, Create file. \n + */ +#ifndef TIOT_TYPES_H +#define TIOT_TYPES_H + +#ifdef __KERNEL__ +/* 内核类型可能与编译器stdint.h冲突. */ +#include +#include +#else +#include +#endif + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_common_interface_types TIoT types. + * @ingroup tiot_common_interface + * @{ + */ +#ifndef NULL +#define NULL ((void*)0) +#endif + +/* container */ +#undef tiot_offsetof +#ifdef __compiler_offsetof +#define tiot_offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER) +#else +#define tiot_offsetof(TYPE, MEMBER) ((int)(unsigned long)&((TYPE *)0)->MEMBER) +#endif + +#ifdef _MSC_VER +#define tiot_container_of(ptr, type, member) ((type *)((char *)(const void *){ptr} - tiot_offsetof(type, member))) +#else +#define tiot_container_of(ptr, type, member) ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)((char *)__mptr - tiot_offsetof(type, member)); }) +#endif + +#define tiot_unused(var) \ + do { \ + (void)(var); \ + } while (0) + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/device/gnss/CMakeLists.txt new file mode 100644 index 000000000..adbe7fb4e --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/CMakeLists.txt @@ -0,0 +1,31 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +if(DEFINED CONFIG_DEV_GNSS) +set( + device_include_list + "${CMAKE_CURRENT_SOURCE_DIR}" +) + +set( + device_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/gnss_device_info.c + ${CMAKE_CURRENT_SOURCE_DIR}/gnss_service.c +) + +if(DEFINED CONFIG_FILE_BY_ARRAY) +list( + APPEND device_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/firmware/gnss_fw_file_array.c +) + +list( + APPEND device_include_list + "${CMAKE_CURRENT_SOURCE_DIR}/firmware" +) +endif() + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${device_include_list}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${device_src_list}" CACHE INTERNAL "tiot src list" FORCE) +endif() diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/Makefile b/code/sdk/zhihui/gnss/driver/device/gnss/Makefile new file mode 100644 index 000000000..fc031188b --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/Makefile @@ -0,0 +1,16 @@ +# GNSS Makefile +ifeq ($(CONFIG_DEV_GNSS), y) +tiot-gnss-objs += gnss_device_info.o gnss_service.o + +ifeq ($(CONFIG_FILE_BY_ARRAY), y) +ifneq (,$(wildcard $(TIOT_DRIVER_PATH)/device/gnss/firmware/gnss_fw_file_array.c)) +tiot-gnss-objs += firmware/gnss_fw_file_array.o +TIOT_HEADER_LIST += -I$(TIOT_DRIVER_PATH)/device/gnss/firmware +endif +endif + +tiot-gnss-objs := $(addprefix device/gnss/,$(tiot-gnss-objs)) +tiot_driver-objs += $(tiot-gnss-objs) + +TIOT_HEADER_LIST += -I$(TIOT_DRIVER_PATH)/device/gnss +endif diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_cfg.bin b/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_cfg.bin new file mode 100644 index 000000000..e11d8f281 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_cfg.bin @@ -0,0 +1,905 @@ +0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x20, 0x30, 0x78, 0x30, 0x30, +0x30, 0x39, 0x38, 0x30, 0x30, 0x30, 0x20, 0x05, 0x04, 0x01, 0x01, 0xfe, 0xef, 0xb2, 0x48, 0x6a, +0xae, 0x84, 0x2a, 0x84, 0xef, 0x02, 0xd9, 0x0d, 0x40, 0x99, 0x2a, 0x84, 0xef, 0x82, 0x54, 0x4a, +0x08, 0x00, 0x93, 0x05, 0x00, 0x00, 0x00, 0x00, 0xef, 0x12, 0x92, 0x18, 0xef, 0x42, 0x42, 0x16, +0x01, 0x8a, 0x13, 0x01, 0x82, 0x80, 0x00, 0x00, 0xef, 0x02, 0xd4, 0x69, 0x70, 0x6e, 0x00, 0x00, +0xef, 0xa2, 0x11, 0x53, 0xef, 0x82, 0x44, 0x3c, 0x22, 0x2c, 0x31, 0xcd, 0x82, 0x80, 0x00, 0x00, +0xef, 0x72, 0xd5, 0x68, 0xef, 0x92, 0x56, 0x10, 0x03, 0x45, 0xc5, 0xd9, 0xef, 0x92, 0xd6, 0x10, +0x03, 0x45, 0xc5, 0xd9, 0xef, 0x32, 0xd5, 0x24, 0x53, 0x15, 0x05, 0xc2, 0x3c, 0x99, 0x00, 0x00, +0xef, 0x12, 0x56, 0x57, 0xef, 0x22, 0x06, 0x02, 0xef, 0xe0, 0x40, 0x37, 0xef, 0xf2, 0x92, 0x35, +0x03, 0x06, 0xa6, 0xb4, 0xa0, 0x99, 0x00, 0x00, 0xef, 0xf2, 0x01, 0x57, 0x20, 0x99, 0x00, 0x00, +0xef, 0xf2, 0x01, 0x50, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf2, 0xc1, 0x3e, 0x20, 0x99, 0x00, 0x00, +0xef, 0xf2, 0xc1, 0x33, 0xef, 0xa2, 0x41, 0x4c, 0x13, 0xb6, 0x16, 0x00, 0xef, 0xa2, 0x01, 0x2a, +0x01, 0xdb, 0x27, 0x30, 0x20, 0x99, 0x00, 0x00, 0xef, 0x92, 0x51, 0x48, 0xef, 0xb2, 0xc1, 0x40, +0xae, 0x84, 0x2a, 0x89, 0xef, 0x22, 0x93, 0x5d, 0xb5, 0x00, 0x03, 0x26, 0x82, 0x80, 0x00, 0x00, +0xef, 0xb2, 0xd2, 0x1f, 0xef, 0xb2, 0x52, 0x04, 0x2e, 0x86, 0x2a, 0x84, 0xa4, 0x99, 0x00, 0x00, +0xef, 0xb2, 0xd2, 0x21, 0x82, 0x80, 0x00, 0x00, 0xef, 0x72, 0xc6, 0x47, 0xef, 0x42, 0x06, 0x5f, +0x8b, 0xdb, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xef, 0x42, 0xc6, 0x42, 0x3f, 0xf9, 0x00, 0x00, +0xef, 0xe2, 0x45, 0x09, 0xef, 0xe2, 0x05, 0x63, 0x8b, 0x84, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, +0xef, 0xe2, 0x85, 0x7b, 0xef, 0xe2, 0x45, 0x7a, 0x23, 0x10, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, +0xef, 0xd2, 0xd5, 0x7c, 0xef, 0xe2, 0x55, 0x19, 0x05, 0x07, 0x2e, 0x85, 0x00, 0x00, 0x00, 0x00, +0xef, 0x42, 0xd6, 0x2a, 0xef, 0x52, 0xc6, 0x4d, 0x37, 0xc5, 0x08, 0x00, 0x82, 0x80, 0x00, 0x00, +0xef, 0xc2, 0xd3, 0x53, 0x82, 0x80, 0x00, 0x00, 0xef, 0xc2, 0x13, 0x51, 0xef, 0x82, 0x13, 0x5e, +0x04, 0x20, 0x13, 0x04, 0xef, 0xe2, 0xc8, 0x07, 0x7f, 0x9f, 0x13, 0x84, 0xef, 0x12, 0x15, 0x69, +0xb0, 0x42, 0x11, 0xc1, 0xef, 0xa2, 0xd6, 0x18, 0x2a, 0x89, 0x37, 0x44, 0xef, 0x62, 0x44, 0x32, +0x15, 0x02, 0x2a, 0x86, 0xef, 0x52, 0x94, 0x43, 0xef, 0xd0, 0xcf, 0x90, 0xef, 0x42, 0x84, 0x70, +0xef, 0x50, 0xd2, 0x44, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf2, 0x54, 0x46, 0x00, 0x00, 0x00, 0x00, +0xef, 0x22, 0xc1, 0x61, 0xef, 0x62, 0x50, 0x4c, 0x37, 0x35, 0x09, 0x00, 0x82, 0x80, 0x00, 0x00, +0xef, 0xe2, 0xc5, 0x37, 0xef, 0xe2, 0xd6, 0x01, 0xaa, 0x84, 0xef, 0xe0, 0xef, 0x72, 0x86, 0x71, +0x05, 0x44, 0xef, 0xd0, 0xef, 0x32, 0xd6, 0x69, 0x37, 0xd5, 0x08, 0x00, 0xef, 0x22, 0x43, 0x55, +0x83, 0xd6, 0x86, 0xb2, 0xa0, 0x98, 0x00, 0x00, 0xef, 0x62, 0x94, 0x29, 0x00, 0x00, 0x00, 0x00, +0xef, 0xd2, 0x51, 0x16, 0xef, 0xe2, 0xd2, 0x75, 0x26, 0xa0, 0x2a, 0x84, 0xef, 0xf2, 0x52, 0x0b, +0x32, 0x89, 0x8b, 0x87, 0xef, 0x22, 0x54, 0x2a, 0x2a, 0x86, 0x0d, 0x45, 0x00, 0x00, 0x00, 0x00, +0xef, 0xf2, 0xc7, 0x6b, 0xef, 0x92, 0x11, 0x65, 0x04, 0x20, 0x07, 0x30, 0xef, 0xa2, 0xc3, 0x76, +0xb7, 0xb5, 0x04, 0x20, 0x20, 0x98, 0x00, 0x00, 0xef, 0x62, 0x54, 0x48, 0xef, 0x72, 0x03, 0x6c, +0xef, 0xe0, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xef, 0x72, 0x88, 0x07, 0xef, 0x82, 0x98, 0x32, +0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x31, 0x05, 0x04, +0x01, 0x02, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x09, 0x00, 0x43, 0x00, 0x00, 0x00, 0x09, +0xd0, 0x00, 0x00, 0x31, 0x7d, 0x00, 0x00, 0xe9, 0x09, 0x05, 0x00, 0x79, 0x8e, 0x07, 0x00, 0xe1, +0x65, 0x07, 0x00, 0xa9, 0x8d, 0x05, 0x00, 0x99, 0x01, 0x08, 0x00, 0xd1, 0x13, 0x05, 0x00, 0x09, +0x16, 0x04, 0x00, 0xd1, 0xf0, 0x02, 0x00, 0x21, 0xf1, 0x02, 0x00, 0xd1, 0x5a, 0x04, 0x00, 0x39, +0x72, 0x03, 0x00, 0x09, 0x70, 0x03, 0x00, 0xe9, 0xa5, 0x06, 0x00, 0x91, 0xb4, 0x07, 0x00, 0x71, +0xb5, 0x07, 0x00, 0xf1, 0xb6, 0x07, 0x00, 0x11, 0xb8, 0x07, 0x00, 0x91, 0x07, 0x08, 0x00, 0xa9, +0x0a, 0x08, 0x00, 0x71, 0x14, 0x08, 0x00, 0x71, 0xfb, 0x07, 0x00, 0x59, 0x71, 0x06, 0x00, 0xc9, +0xec, 0x06, 0x00, 0x61, 0xeb, 0x06, 0x00, 0xf1, 0xeb, 0x06, 0x00, 0x31, 0x16, 0x03, 0x00, 0x29, +0x46, 0x03, 0x00, 0x41, 0x48, 0x03, 0x00, 0x99, 0xb0, 0x03, 0x00, 0xd1, 0xab, 0x03, 0x00, 0x41, +0xa9, 0x03, 0x00, 0x31, 0xa9, 0x03, 0x00, 0x81, 0xb2, 0x03, 0x00, 0x59, 0xa9, 0x03, 0x00, 0x79, +0x42, 0x03, 0x00, 0xe9, 0x39, 0x03, 0x00, 0xe9, 0xcf, 0x05, 0x00, 0x79, 0xd0, 0x05, 0x00, 0xb1, +0x10, 0x06, 0x00, 0x09, 0xa6, 0x00, 0x00, 0x09, 0x77, 0x04, 0x00, 0x31, 0xdf, 0x02, 0x00, 0xe1, +0x34, 0x05, 0x00, 0x49, 0x3c, 0x05, 0x00, 0x61, 0x53, 0x05, 0x00, 0x39, 0x99, 0x04, 0x00, 0xd1, +0x8b, 0x08, 0x00, 0x09, 0x27, 0x09, 0x00, 0x99, 0xaf, 0x03, 0x00, 0x29, 0x9f, 0x02, 0x00, 0xc9, +0x13, 0x03, 0x00, 0x61, 0x50, 0x03, 0x00, 0x61, 0x7a, 0x06, 0x00, 0x21, 0x2e, 0x05, 0x00, 0xb9, +0xd2, 0x07, 0x00, 0xd1, 0xb2, 0x06, 0x00, 0x01, 0xa9, 0x06, 0x00, 0xa1, 0x70, 0x05, 0x00, 0x11, +0x90, 0x01, 0x00, 0x71, 0x13, 0x08, 0x00, 0x81, 0x0a, 0x06, 0x00, 0xd9, 0x2c, 0x05, 0x00, 0x09, +0x28, 0x06, 0x00, 0xe1, 0x15, 0x01, 0x00, 0x49, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, +0x98, 0xef, 0xf0, 0x66, 0xee, 0xb7, 0x25, 0x00, 0x40, 0x03, 0xd5, 0xc5, 0x54, 0x13, 0x76, 0x15, +0x00, 0x13, 0x85, 0x01, 0x24, 0x01, 0xc6, 0x23, 0x9a, 0x05, 0x60, 0x7a, 0x1d, 0x19, 0x46, 0x23, +0xa0, 0xc1, 0x3c, 0x93, 0x85, 0x81, 0xf7, 0x85, 0x46, 0x23, 0x93, 0xd5, 0x00, 0x23, 0x97, 0xd5, +0x00, 0x23, 0x9b, 0xc5, 0x00, 0x93, 0x85, 0x81, 0x05, 0xf2, 0x15, 0xe2, 0x19, 0xf2, 0x1d, 0xe6, +0x11, 0xc1, 0x65, 0x93, 0x85, 0x15, 0x9c, 0x6c, 0xc1, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0x7b, +0xe8, 0x00, 0x70, 0x37, 0x25, 0x00, 0x40, 0x85, 0x45, 0x23, 0x10, 0xb5, 0x20, 0x82, 0x80, 0x00, +0x00, 0x00, 0x00, 0xc0, 0x98, 0x2a, 0x84, 0xef, 0x40, 0x57, 0x84, 0x7b, 0xe8, 0xa0, 0x70, 0xfb, +0xca, 0x81, 0x9e, 0xa0, 0x98, 0x00, 0x00, 0xc0, 0x98, 0xef, 0x10, 0xb7, 0xf7, 0x2a, 0x84, 0xef, +0xf0, 0x56, 0x97, 0x03, 0x55, 0x44, 0x01, 0x0c, 0x48, 0x10, 0x4c, 0x2e, 0x95, 0x08, 0xc8, 0x02, +0x96, 0xef, 0xf0, 0xf6, 0x93, 0x5c, 0x4c, 0x22, 0x85, 0x80, 0x98, 0x82, 0x87, 0x00, 0x00, 0xc0, +0x99, 0x32, 0x89, 0xae, 0x84, 0x2a, 0x84, 0xef, 0xf0, 0xd6, 0x94, 0x22, 0x85, 0xa6, 0x85, 0x4a, +0x86, 0xef, 0x30, 0xb7, 0xdd, 0x2a, 0x84, 0xef, 0xf0, 0x96, 0x91, 0x22, 0x85, 0xa0, 0x99, 0x00, +0x00, 0x00, 0x00, 0xc4, 0x99, 0x83, 0x44, 0xc5, 0x01, 0x2e, 0x84, 0x01, 0x46, 0xd4, 0x4d, 0xa9, +0x45, 0xb3, 0xf5, 0xb4, 0x02, 0x13, 0x07, 0xc0, 0x17, 0xb3, 0x37, 0xd7, 0x00, 0x13, 0xb7, 0x15, +0x00, 0xf9, 0x8f, 0x9d, 0x90, 0xa9, 0xe7, 0x03, 0x46, 0x05, 0x00, 0x93, 0x07, 0xc0, 0x12, 0xb3, +0xb6, 0xd7, 0x00, 0x64, 0x9f, 0xf9, 0x8e, 0x79, 0x16, 0x33, 0x36, 0xc0, 0x00, 0x55, 0x8e, 0x1d, +0xe6, 0x03, 0x49, 0x15, 0x00, 0x2e, 0x85, 0xef, 0x10, 0x08, 0xd6, 0x0d, 0xc1, 0x13, 0x05, 0xf1, +0x00, 0xef, 0x10, 0xe8, 0xbb, 0x01, 0xcd, 0x03, 0x46, 0xf1, 0x00, 0x26, 0x85, 0xa2, 0x85, 0xca, +0x86, 0xef, 0x10, 0xa8, 0xa9, 0x7d, 0x15, 0x13, 0x36, 0x15, 0x00, 0x11, 0xa0, 0x01, 0x46, 0x32, +0x85, 0xa4, 0x99, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x9a, 0x39, 0xcd, 0xaa, 0x84, 0xef, 0x00, 0xa9, +0x99, 0x2a, 0x84, 0x13, 0x86, 0x44, 0x00, 0x0a, 0x85, 0x91, 0x45, 0xa2, 0x86, 0xef, 0x50, 0xe7, +0xb5, 0xfb, 0x25, 0x00, 0x81, 0x2a, 0x86, 0x13, 0x35, 0x15, 0x00, 0x93, 0xb5, 0x15, 0x00, 0x4d, +0x8d, 0x19, 0xe9, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x24, 0x93, +0x85, 0x25, 0x64, 0xef, 0x60, 0x97, 0xa2, 0xb7, 0xf9, 0x01, 0x20, 0x03, 0xc5, 0x89, 0xad, 0x05, +0x4a, 0x93, 0x84, 0x89, 0xad, 0x05, 0xc9, 0x8b, 0x18, 0x15, 0x01, 0x03, 0x45, 0x11, 0x00, 0xcc, +0x50, 0x4d, 0x8d, 0x39, 0xe9, 0xb1, 0xa8, 0x7b, 0x25, 0x00, 0x81, 0x19, 0xc9, 0x37, 0x05, 0x23, +0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x18, 0x93, 0x85, 0x25, 0x64, 0xef, 0x60, 0xb7, +0x99, 0x01, 0x44, 0xd5, 0xa8, 0x03, 0x45, 0x01, 0x00, 0x0b, 0x1c, 0x05, 0x01, 0x7b, 0x25, 0x00, +0x81, 0xa3, 0x83, 0x44, 0x01, 0x0b, 0x49, 0x05, 0x03, 0x7b, 0x26, 0x09, 0xf6, 0x37, 0x05, 0x23, +0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x28, 0x93, 0x85, 0x25, 0x6c, 0xef, 0x60, 0xf7, +0x9b, 0x03, 0xc5, 0x89, 0xad, 0x8b, 0x09, 0xe5, 0x01, 0x03, 0xc5, 0x84, 0x00, 0x8b, 0x1b, 0x05, +0x03, 0xef, 0x70, 0xf3, 0xc0, 0x05, 0x04, 0x01, 0x03, 0xfc, 0x69, 0xe2, 0x7b, 0x25, 0x00, 0x81, +0x0b, 0x48, 0x05, 0x03, 0x03, 0xc6, 0x84, 0x00, 0xfb, 0x26, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, +0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x32, 0x93, 0x85, 0x25, 0x6c, 0xef, 0x60, 0xf7, 0x9d, +0x92, 0x10, 0x83, 0x46, 0x01, 0x00, 0x03, 0x05, 0x11, 0x00, 0x03, 0x56, 0x21, 0x00, 0x23, 0x8c, +0xd9, 0xac, 0x23, 0x85, 0xa4, 0x00, 0x8b, 0x49, 0x06, 0x04, 0x7b, 0x25, 0x00, 0x81, 0x09, 0xcd, +0x7b, 0x27, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x39, +0x93, 0x85, 0x25, 0x64, 0xef, 0x60, 0x37, 0xa0, 0x01, 0x46, 0x29, 0x90, 0x83, 0xa5, 0x41, 0x7a, +0x81, 0xc5, 0x32, 0x85, 0x82, 0x95, 0x19, 0xa0, 0x13, 0x05, 0x60, 0x22, 0xef, 0x60, 0xe9, 0xdf, +0x26, 0x85, 0xef, 0x20, 0x89, 0xe3, 0x7b, 0x25, 0x00, 0x81, 0xa3, 0x8c, 0x49, 0xad, 0x0b, 0x4c, +0x05, 0x03, 0x03, 0xc6, 0x89, 0xad, 0xfb, 0x25, 0x09, 0xf6, 0xfb, 0x26, 0x0f, 0x26, 0x7b, 0x27, +0x09, 0xf6, 0x83, 0x57, 0x21, 0x00, 0xb3, 0x86, 0xd5, 0x40, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, +0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x49, 0x93, 0x85, 0x25, 0x6c, 0xef, 0x60, 0xd7, 0xa0, 0x22, 0x85, +0xa0, 0x9a, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x9a, 0xae, 0x89, 0x2a, 0x89, 0x37, 0x44, 0x02, 0x40, +0x13, 0x05, 0x44, 0x20, 0x89, 0x45, 0xef, 0x50, 0x89, 0xe1, 0x13, 0x05, 0x44, 0x23, 0xc1, 0x45, +0xef, 0x50, 0xe9, 0xe0, 0x13, 0x04, 0x04, 0x20, 0x93, 0x05, 0x00, 0x0a, 0x22, 0x85, 0xef, 0x50, +0x09, 0xe1, 0x93, 0x05, 0x00, 0x0a, 0x22, 0x85, 0xef, 0x50, 0x69, 0xdf, 0x37, 0x45, 0x10, 0x40, +0x4c, 0x55, 0x41, 0x66, 0xd1, 0x8d, 0x4c, 0xd5, 0x37, 0x6a, 0x02, 0x40, 0x13, 0x04, 0x4a, 0x20, +0x93, 0x05, 0x00, 0x20, 0x22, 0x85, 0xef, 0x50, 0x89, 0xde, 0x93, 0x04, 0x0a, 0x12, 0x93, 0x05, +0x00, 0x10, 0x26, 0x85, 0xef, 0x50, 0xa9, 0xdd, 0x83, 0xd5, 0x41, 0x56, 0x26, 0x85, 0xef, 0x50, +0x09, 0xdc, 0x93, 0x05, 0x00, 0x10, 0x26, 0x85, 0xef, 0x50, 0x69, 0xdb, 0x93, 0x75, 0xf9, 0x03, +0x13, 0x05, 0x0a, 0x20, 0xef, 0x50, 0x29, 0xda, 0x8d, 0x45, 0x22, 0x85, 0xef, 0x50, 0x29, 0xdb, +0x93, 0x95, 0x09, 0x01, 0xc1, 0x81, 0x13, 0x05, 0x8a, 0x20, 0xef, 0x50, 0xc9, 0xd8, 0x93, 0xd5, +0x09, 0x01, 0x13, 0x05, 0xca, 0x20, 0xef, 0x50, 0x09, 0xd8, 0x83, 0xd5, 0x81, 0x56, 0x13, 0x05, +0x0a, 0x21, 0xef, 0x50, 0x49, 0xd7, 0x83, 0xd5, 0xa1, 0x56, 0x13, 0x05, 0x4a, 0x21, 0xef, 0x50, +0x89, 0xd6, 0x83, 0xd5, 0xc1, 0x56, 0x13, 0x05, 0x8a, 0x21, 0xef, 0x50, 0xc9, 0xd5, 0x83, 0xd5, +0xe1, 0x56, 0x13, 0x05, 0xca, 0x21, 0xef, 0x50, 0x09, 0xd5, 0x93, 0x05, 0x00, 0x08, 0x22, 0x85, +0xef, 0x50, 0xe9, 0xd4, 0x93, 0x05, 0x00, 0x20, 0x22, 0x85, 0xef, 0x50, 0x49, 0xd4, 0x93, 0x05, +0x00, 0x10, 0x22, 0x85, 0xef, 0x50, 0xa9, 0xd3, 0x7b, 0x25, 0x00, 0x81, 0x19, 0xcd, 0x83, 0x56, +0x4a, 0x20, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0x49, 0x93, 0x85, +0x25, 0x54, 0x22, 0x86, 0x80, 0x9a, 0x6f, 0x60, 0x57, 0x83, 0xa0, 0x9a, 0x00, 0x00, 0x37, 0x55, +0x03, 0x20, 0x03, 0x45, 0xc5, 0xd9, 0xb7, 0xb5, 0x09, 0x00, 0x83, 0xc5, 0x45, 0x70, 0x4d, 0x8d, +0x11, 0xcd, 0x7b, 0x25, 0x00, 0x81, 0x0b, 0x4f, 0x05, 0x03, 0x7b, 0x26, 0x09, 0xf6, 0x37, 0x05, +0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x16, 0x05, 0xa0, 0x7b, 0x25, 0x00, 0x81, +0x09, 0x46, 0x7b, 0x66, 0xcf, 0x2e, 0x0b, 0x47, 0x05, 0x03, 0x7b, 0x26, 0x09, 0xf6, 0x37, 0x05, +0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x14, 0x93, 0x85, 0x25, 0x4c, 0x6f, 0x60, +0x47, 0xf8, 0x82, 0x80, 0x00, 0x00, 0x37, 0x55, 0x03, 0x20, 0x03, 0x45, 0xc5, 0xd9, 0xb7, 0xb5, +0x09, 0x00, 0x83, 0xc5, 0x45, 0x70, 0x7d, 0x15, 0x33, 0x35, 0xa0, 0x00, 0xfd, 0x15, 0xb3, 0x35, +0xb0, 0x00, 0x6d, 0x8d, 0x0d, 0xed, 0x37, 0xf5, 0x01, 0x20, 0x93, 0x05, 0x85, 0xad, 0x03, 0x85, +0x65, 0x00, 0x7b, 0x26, 0x00, 0x81, 0x85, 0x46, 0xd4, 0xc9, 0x05, 0x05, 0x23, 0x83, 0xa5, 0x00, +0x0b, 0x41, 0x16, 0x03, 0x08, 0x92, 0xfb, 0x26, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, +0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x20, 0x93, 0x85, 0x25, 0x4c, 0x6f, 0x60, 0x07, 0xf8, 0x7b, 0x25, +0x00, 0x81, 0x09, 0x46, 0x7b, 0x66, 0xcf, 0x2e, 0x0b, 0x47, 0x05, 0x03, 0x7b, 0x26, 0x09, 0xf6, +0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x23, 0x93, 0x85, 0x25, 0x4c, +0x6f, 0x60, 0x27, 0xf0, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x15, 0x08, 0x91, 0x8b, 0x54, +0x05, 0x02, 0x03, 0x45, 0x86, 0x00, 0x0b, 0x15, 0x05, 0x01, 0x33, 0x35, 0xb0, 0x00, 0x82, 0x80, +0xa3, 0x15, 0x06, 0x00, 0x93, 0x05, 0xd6, 0x00, 0x21, 0xa0, 0x1a, 0x12, 0x93, 0x05, 0xb6, 0x00, +0x05, 0x45, 0x82, 0x11, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x9b, 0xaa, 0x84, 0x05, 0x44, +0xef, 0x60, 0xa9, 0xbf, 0x01, 0xe5, 0x03, 0xc5, 0x24, 0x00, 0x19, 0xc1, 0x22, 0x85, 0xa8, 0x9b, +0x03, 0x95, 0x04, 0x00, 0x2c, 0x08, 0x10, 0x08, 0x34, 0x00, 0x13, 0x07, 0xf1, 0x01, 0xef, 0x80, +0x49, 0xa1, 0x2a, 0x89, 0x32, 0x45, 0xa2, 0x45, 0x92, 0x1c, 0x13, 0x06, 0x09, 0xfe, 0x05, 0x44, +0x0b, 0x23, 0x06, 0x00, 0x81, 0x4a, 0x33, 0x1a, 0xc4, 0x00, 0x21, 0xa0, 0x01, 0x4a, 0xb3, 0x1a, +0x24, 0x01, 0xb3, 0xf5, 0x55, 0x01, 0x33, 0x75, 0x45, 0x01, 0x4d, 0x8d, 0x61, 0xd1, 0x37, 0x55, +0x00, 0x20, 0x13, 0x05, 0x85, 0x88, 0x54, 0x51, 0x10, 0x51, 0x7b, 0x25, 0x09, 0xf6, 0xe2, 0x47, +0x1d, 0x8d, 0x93, 0x05, 0xc0, 0x44, 0x63, 0x4c, 0xb5, 0x06, 0x7b, 0x25, 0x00, 0x81, 0xb7, 0x45, +0x01, 0x20, 0x93, 0x84, 0x05, 0xa3, 0x8b, 0x4a, 0x05, 0x03, 0x03, 0x45, 0xf1, 0x01, 0x2b, 0x85, +0xa4, 0x06, 0x18, 0x41, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x00, 0x57, +0x93, 0x85, 0x25, 0x7c, 0x01, 0x46, 0xca, 0x86, 0xef, 0x60, 0xe7, 0xf3, 0x7b, 0x25, 0x00, 0x81, +0x83, 0x45, 0xf1, 0x01, 0xab, 0x85, 0xb4, 0x06, 0xd0, 0x41, 0x94, 0x41, 0x13, 0xc7, 0xfa, 0xff, +0x93, 0x47, 0xfa, 0xff, 0x7d, 0x8e, 0x75, 0x8f, 0x98, 0xc1, 0xd0, 0xc1, 0x0b, 0x44, 0xd5, 0x03, +0xfb, 0x27, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x00, 0x5a, +0x93, 0x85, 0x25, 0x7c, 0x01, 0x46, 0xca, 0x86, 0xef, 0x60, 0xe7, 0xef, 0x05, 0xbf, 0xd2, 0x45, +0x42, 0x45, 0x33, 0xc8, 0xb6, 0x00, 0xb3, 0x37, 0xa6, 0x00, 0xe4, 0x9f, 0x33, 0xb7, 0xb6, 0x00, +0x64, 0x9f, 0x2b, 0xe7, 0x07, 0x21, 0x0d, 0xe7, 0x7b, 0x25, 0x00, 0x81, 0x0b, 0x44, 0xc5, 0x02, +0x83, 0x96, 0x04, 0x00, 0x7b, 0x27, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, +0xb7, 0xb5, 0x00, 0x60, 0x93, 0x85, 0x25, 0x78, 0x01, 0x46, 0x02, 0x72, 0x05, 0x04, 0x01, 0x04, +0xfb, 0xef, 0x60, 0xc7, 0xe5, 0xfd, 0xb5, 0x26, 0x87, 0xef, 0x80, 0x49, 0xef, 0x7d, 0x15, 0x13, +0x34, 0x15, 0x00, 0xc5, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x83, 0x45, 0x25, 0x00, 0x8b, 0xdc, 0x05, +0x06, 0x05, 0x46, 0xb3, 0x15, 0xb6, 0x00, 0x93, 0xf5, 0x55, 0x02, 0x95, 0xc1, 0x83, 0x05, 0x05, +0x07, 0xfd, 0x15, 0x8c, 0x91, 0x8b, 0xd4, 0x05, 0x02, 0x83, 0x45, 0xd5, 0x03, 0x13, 0xf6, 0x35, +0x00, 0x19, 0xce, 0x5e, 0x1d, 0x39, 0xa0, 0x3e, 0x1d, 0xa3, 0x1e, 0x05, 0x02, 0x39, 0xa0, 0x83, +0x45, 0xd5, 0x03, 0x93, 0xf5, 0x75, 0x0e, 0xa3, 0x0e, 0xb5, 0x02, 0x01, 0x45, 0x82, 0x80, 0x83, +0x45, 0xc5, 0x03, 0xe5, 0xfd, 0x03, 0x45, 0xb5, 0x03, 0x13, 0x35, 0x15, 0x00, 0x82, 0x80, 0x00, +0x00, 0x40, 0x99, 0x2a, 0x84, 0x83, 0x44, 0x25, 0x00, 0xef, 0xb0, 0x59, 0xb8, 0x0b, 0x0a, 0x15, +0x01, 0x03, 0x25, 0x44, 0x09, 0x83, 0x25, 0x44, 0x08, 0x83, 0x06, 0x04, 0x07, 0xa3, 0x0c, 0x04, +0x06, 0x13, 0x06, 0x15, 0x00, 0x03, 0x25, 0x04, 0x0b, 0xfd, 0x16, 0x94, 0x92, 0x23, 0x2a, 0xc4, +0x08, 0x8b, 0xdf, 0x06, 0x02, 0x2b, 0x86, 0xb5, 0xbe, 0xab, 0x35, 0xb6, 0xbe, 0x15, 0x46, 0xef, +0xb0, 0xf9, 0xeb, 0xb7, 0xb5, 0x09, 0x00, 0x93, 0x85, 0xc5, 0x20, 0xab, 0x85, 0x95, 0x04, 0x8c, +0x41, 0x23, 0x28, 0xa4, 0x0a, 0x63, 0x60, 0xb5, 0x02, 0x23, 0x08, 0x04, 0x06, 0x0d, 0x45, 0xa3, +0x0c, 0xa4, 0x06, 0x23, 0x28, 0x04, 0x0a, 0x23, 0x2a, 0x04, 0x08, 0x3a, 0x1c, 0x20, 0x99, 0x01, +0xc5, 0x23, 0x28, 0x04, 0x0a, 0x20, 0x99, 0x8b, 0x4e, 0x06, 0x32, 0x22, 0x85, 0xef, 0xb0, 0x99, +0xc0, 0x75, 0xf9, 0x09, 0x45, 0x23, 0x08, 0xa4, 0x06, 0x37, 0xb5, 0x09, 0x00, 0x13, 0x05, 0xc5, +0x20, 0x2b, 0x05, 0x95, 0x04, 0x08, 0x41, 0x85, 0x45, 0x03, 0x06, 0xd4, 0x03, 0xa3, 0x0c, 0xb4, +0x06, 0x05, 0x81, 0x23, 0x28, 0xa4, 0x0a, 0x13, 0x65, 0x06, 0x02, 0xa3, 0x0e, 0xa4, 0x02, 0x20, +0x99, 0x23, 0x08, 0x04, 0x06, 0x20, 0x99, 0x00, 0x00, 0x40, 0x99, 0xae, 0x84, 0x2a, 0x84, 0x13, +0x05, 0x00, 0x20, 0x2a, 0xc0, 0x0a, 0x85, 0xef, 0xb0, 0x29, 0xd3, 0x03, 0x45, 0x04, 0x07, 0x8b, +0x03, 0x15, 0x02, 0x0b, 0x12, 0x35, 0x01, 0x82, 0x45, 0x13, 0x05, 0x90, 0x6c, 0x2e, 0x86, 0x83, +0x26, 0x84, 0x09, 0x77, 0x96, 0xa4, 0xc4, 0x13, 0x07, 0x00, 0x40, 0x33, 0x45, 0xe6, 0x02, 0x36, +0x95, 0x05, 0x66, 0x13, 0x06, 0xd6, 0x24, 0xae, 0x86, 0xf7, 0x96, 0xc4, 0xc4, 0x03, 0x26, 0xc4, +0x09, 0x23, 0x2c, 0xa4, 0x08, 0xb3, 0xc6, 0xe6, 0x02, 0x36, 0x95, 0x32, 0x95, 0x23, 0x2e, 0xa4, +0x08, 0x19, 0x66, 0x13, 0x06, 0x66, 0x1e, 0xf7, 0x95, 0xc4, 0xc4, 0xa1, 0xa8, 0x82, 0x45, 0x13, +0x05, 0x90, 0x6c, 0x2e, 0x86, 0x77, 0x96, 0xa4, 0xc4, 0x03, 0x25, 0x84, 0x09, 0x85, 0x66, 0x13, +0x87, 0x06, 0xa0, 0x33, 0x46, 0xe6, 0x02, 0x32, 0x95, 0x23, 0x2c, 0xa4, 0x08, 0x13, 0x86, 0xd6, +0x24, 0xae, 0x86, 0xf7, 0x96, 0xc4, 0xc4, 0x13, 0x06, 0x00, 0x40, 0xb3, 0xc6, 0xc6, 0x02, 0x36, +0x95, 0x83, 0x26, 0xc4, 0x09, 0x0a, 0x05, 0x29, 0x47, 0x33, 0x45, 0xe5, 0x02, 0x36, 0x95, 0x23, +0x2e, 0xa4, 0x08, 0x99, 0x66, 0x93, 0x86, 0x66, 0x1e, 0xf7, 0x95, 0xd4, 0xc4, 0xb3, 0xc5, 0xc5, +0x02, 0x8a, 0x05, 0xb3, 0xc5, 0xe5, 0x02, 0x50, 0x48, 0x2e, 0x95, 0x93, 0x55, 0xf6, 0x41, 0xc2, +0x05, 0xab, 0xa5, 0xc5, 0x60, 0x93, 0x16, 0x06, 0x01, 0xab, 0x85, 0xa5, 0xbe, 0x2b, 0x05, 0xc5, +0x20, 0x33, 0x36, 0xd5, 0x00, 0xb2, 0x95, 0x08, 0xcc, 0x4c, 0xcc, 0x20, 0x99, 0x00, 0x00, 0x00, +0x00, 0x5c, 0x98, 0x79, 0x71, 0xef, 0x10, 0x50, 0x5e, 0xfb, 0x05, 0x2f, 0x2e, 0x64, 0x9d, 0xfd, +0x15, 0xb3, 0x35, 0xb0, 0x00, 0x4d, 0x8d, 0x29, 0xe5, 0x37, 0xb5, 0x09, 0x00, 0x93, 0x05, 0x85, +0x22, 0x28, 0x00, 0x13, 0x06, 0x20, 0x0a, 0xef, 0x80, 0xe6, 0xed, 0x37, 0x65, 0x02, 0x20, 0x13, +0x05, 0x85, 0xd9, 0x93, 0x05, 0x20, 0x0a, 0x30, 0x00, 0x93, 0x06, 0x20, 0x0a, 0xef, 0x40, 0xd7, +0xc6, 0xfb, 0x25, 0x00, 0x81, 0x2a, 0x86, 0x13, 0x35, 0x15, 0x00, 0x93, 0xb5, 0x15, 0x00, 0x4d, +0x8d, 0x39, 0xed, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0xf2, 0xa1, +0xa0, 0x37, 0xb5, 0x09, 0x00, 0x93, 0x05, 0xa5, 0x2c, 0x28, 0x00, 0x13, 0x06, 0x20, 0x0a, 0xef, +0x80, 0x66, 0xe9, 0x37, 0x65, 0x02, 0x20, 0x13, 0x05, 0x85, 0xd9, 0x93, 0x05, 0x20, 0x0a, 0x30, +0x00, 0x93, 0x06, 0x20, 0x0a, 0xef, 0x40, 0x57, 0xc2, 0xfb, 0x25, 0x00, 0x81, 0x2a, 0x86, 0x13, +0x35, 0x15, 0x00, 0x93, 0xb5, 0x15, 0x00, 0x4d, 0x8d, 0x19, 0xe9, 0x37, 0x05, 0x23, 0x00, 0x13, +0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x05, 0x1d, 0x93, 0x85, 0x25, 0x64, 0xef, 0x60, 0xe7, 0xae, 0x45, +0x61, 0x3c, 0x98, 0x00, 0x00, 0x5c, 0x98, 0x79, 0x71, 0x37, 0xb5, 0x09, 0x00, 0x93, 0x05, 0xc5, +0x36, 0x28, 0x00, 0x13, 0x06, 0x20, 0x0a, 0xef, 0x80, 0xe6, 0xe3, 0x37, 0x65, 0x02, 0x20, 0x13, +0x05, 0xa5, 0xe3, 0x93, 0x05, 0x20, 0x0a, 0x30, 0x00, 0x93, 0x06, 0x20, 0x0a, 0xef, 0x40, 0xd7, +0xbc, 0x05, 0x37, 0x01, 0x45, 0xef, 0xf0, 0x98, 0x9d, 0x45, 0x61, 0x3c, 0x98, 0x5c, 0x98, 0x79, +0x71, 0xef, 0x10, 0x90, 0x4f, 0xfb, 0x05, 0x2f, 0x2e, 0x64, 0x9d, 0xfd, 0x15, 0xb3, 0x35, 0xb0, +0x00, 0x4d, 0x8d, 0x29, 0xe5, 0x37, 0xb5, 0x09, 0x00, 0x93, 0x05, 0xe5, 0x40, 0x28, 0x00, 0x13, +0x06, 0x20, 0x0a, 0xef, 0x80, 0x26, 0xdf, 0x37, 0x65, 0x02, 0x20, 0x13, 0x05, 0xc5, 0xed, 0x93, +0x05, 0x20, 0x0a, 0x30, 0x00, 0x93, 0x06, 0x20, 0x0a, 0xef, 0x40, 0x17, 0xb8, 0xfb, 0x25, 0x00, +0x81, 0x2a, 0x86, 0x13, 0x35, 0x15, 0x00, 0x93, 0xb5, 0x15, 0x00, 0x4d, 0x8d, 0x39, 0xed, 0x37, +0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x00, 0x42, 0xa1, 0xa0, 0x37, 0xb5, 0x09, +0x00, 0x93, 0x05, 0x05, 0x4b, 0x28, 0x00, 0x13, 0x06, 0x20, 0x0a, 0xef, 0x80, 0xa6, 0xda, 0x37, +0x65, 0x02, 0x20, 0x13, 0x05, 0xc5, 0xed, 0x93, 0x05, 0x20, 0x0a, 0x30, 0x00, 0x93, 0x06, 0x20, +0x0a, 0xef, 0x40, 0x97, 0xb3, 0xfb, 0x25, 0x00, 0x81, 0x2a, 0x86, 0x13, 0x35, 0x15, 0x00, 0x93, +0xb5, 0x15, 0x00, 0x4d, 0x8d, 0x19, 0xe9, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, +0xb5, 0x00, 0x6d, 0x93, 0x85, 0x25, 0x64, 0xef, 0x60, 0x27, 0xa0, 0x45, 0x61, 0x3c, 0x98, 0x00, +0x00, 0xc0, 0x98, 0x37, 0x54, 0x03, 0x20, 0x03, 0x45, 0xc4, 0xd9, 0x8b, 0x18, 0x15, 0x01, 0xef, +0xa0, 0xba, 0x84, 0x37, 0x05, 0x03, 0x20, 0x83, 0x45, 0x05, 0x24, 0x8b, 0x91, 0x15, 0x01, 0x23, +0x00, 0x05, 0x24, 0x13, 0x06, 0x05, 0x24, 0x37, 0x05, 0x03, 0x20, 0x13, 0x05, 0x05, 0x2a, 0x93, +0x05, 0x00, 0x06, 0x93, 0x06, 0x00, 0x06, 0xef, 0x40, 0x37, 0xad, 0xfb, 0x25, 0x00, 0x81, 0x2a, +0x86, 0x13, 0x35, 0x15, 0x00, 0x93, 0xb5, 0x15, 0x00, 0x4d, 0x8d, 0x19, 0xe9, 0x37, 0x05, 0x23, +0x00, 0xec, 0x7d, 0x05, 0x04, 0x01, 0x05, 0xfa, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x03, 0x2d, +0x93, 0x85, 0x25, 0x44, 0xef, 0x60, 0xc7, 0x99, 0x23, 0x0e, 0x04, 0xd8, 0x37, 0xb5, 0x09, 0x00, +0x23, 0x02, 0x05, 0x70, 0x37, 0x55, 0x03, 0x20, 0xa3, 0x0e, 0x05, 0xd8, 0xa0, 0x98, 0x00, 0x00, +0x44, 0x99, 0x37, 0xb5, 0x09, 0x00, 0x85, 0x45, 0x23, 0x02, 0xb5, 0x70, 0x08, 0x08, 0xef, 0xc0, +0xaa, 0xb4, 0xef, 0xd0, 0xb9, 0xd4, 0xef, 0xe0, 0x69, 0x86, 0xef, 0xd0, 0x79, 0xcf, 0x37, 0x54, +0x03, 0x20, 0x03, 0x26, 0x44, 0xdb, 0xb7, 0x54, 0x03, 0x20, 0x03, 0xa5, 0xc4, 0xdb, 0x83, 0x25, +0x44, 0xdb, 0x63, 0x64, 0xc5, 0x00, 0x0d, 0x8d, 0x19, 0xa0, 0x33, 0x85, 0xa5, 0x40, 0x93, 0x05, +0x00, 0x10, 0x63, 0x6a, 0xb5, 0x02, 0x37, 0x55, 0x03, 0x20, 0x03, 0x25, 0x85, 0xdb, 0x03, 0x26, +0x44, 0xdb, 0x83, 0x25, 0x44, 0xdb, 0x63, 0x67, 0xa6, 0x00, 0x33, 0x85, 0xa5, 0x40, 0x0b, 0x53, +0x05, 0x3c, 0x11, 0xa8, 0x0d, 0x8d, 0x0b, 0x44, 0x05, 0x3c, 0xef, 0x20, 0x29, 0x83, 0x03, 0x25, +0x44, 0xdb, 0x23, 0xae, 0xa4, 0xda, 0xef, 0xd0, 0x79, 0xef, 0x68, 0x00, 0xef, 0xc0, 0xca, 0xad, +0x42, 0x45, 0xb2, 0x45, 0xef, 0xc0, 0x0a, 0xb2, 0xb7, 0x55, 0x03, 0x20, 0x93, 0x85, 0x85, 0xe0, +0x90, 0x4d, 0x63, 0x73, 0xa6, 0x00, 0x88, 0xcd, 0xb7, 0x55, 0x03, 0x20, 0x03, 0xa6, 0x85, 0xdf, +0x32, 0x95, 0x23, 0xac, 0xa5, 0xde, 0x24, 0x99, 0x00, 0x00, 0x00, 0x00, 0x40, 0x99, 0x2e, 0x84, +0xaa, 0x84, 0xef, 0x30, 0xbc, 0xc6, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x05, 0x60, 0x0e, 0x13, 0x06, +0x30, 0x11, 0x2b, 0xe6, 0xa5, 0x20, 0x23, 0x90, 0xc4, 0x00, 0x09, 0x45, 0x23, 0x10, 0xa4, 0x00, +0x20, 0x99, 0x00, 0x00, 0xc0, 0x99, 0x2e, 0x89, 0xaa, 0x84, 0xef, 0x10, 0x70, 0x2f, 0x93, 0x05, +0x20, 0x1c, 0x13, 0x04, 0x00, 0x14, 0x2b, 0xe4, 0xa5, 0x22, 0xef, 0x30, 0x3c, 0xc3, 0x03, 0x45, +0xc5, 0x0e, 0x93, 0x05, 0x60, 0x0e, 0x2b, 0xe4, 0xa5, 0x20, 0x23, 0x90, 0x84, 0x00, 0x0d, 0x45, +0x23, 0x10, 0xa9, 0x00, 0xa0, 0x99, 0x00, 0x00, 0x40, 0x9a, 0x69, 0xc5, 0x2a, 0x84, 0xef, 0x10, +0x30, 0x2c, 0x83, 0x05, 0x04, 0x07, 0xaa, 0x89, 0x03, 0x29, 0xc4, 0x2a, 0x13, 0x85, 0xf5, 0xff, +0x88, 0x91, 0x13, 0x05, 0xf0, 0x0f, 0x8b, 0xcd, 0x05, 0x02, 0x83, 0x44, 0xa4, 0x03, 0xef, 0x30, +0xfc, 0xbe, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x35, 0x15, 0x00, 0x8b, 0x93, 0x04, 0x01, 0x13, 0x06, +0x60, 0x0e, 0x13, 0x05, 0x30, 0x11, 0x09, 0xa8, 0x13, 0x06, 0x20, 0x1c, 0x13, 0x05, 0x00, 0x14, +0x2b, 0x65, 0x36, 0x23, 0x13, 0x06, 0x60, 0x0e, 0x2b, 0x65, 0xb6, 0x22, 0x83, 0x55, 0x44, 0x27, +0x63, 0x6c, 0xb5, 0x02, 0x03, 0x45, 0x14, 0x03, 0x0b, 0x1c, 0x05, 0x01, 0x03, 0x45, 0x04, 0x2a, +0x0b, 0x1a, 0x05, 0x01, 0x03, 0x45, 0x14, 0x2a, 0x05, 0xe1, 0x03, 0x25, 0x44, 0x08, 0xab, 0x05, +0xa5, 0xbe, 0x2b, 0xb5, 0xa5, 0xbe, 0x95, 0x65, 0x93, 0x85, 0x65, 0x55, 0x23, 0x20, 0x04, 0x0a, +0x63, 0x64, 0xb5, 0x00, 0x23, 0x22, 0x04, 0x08, 0x03, 0x45, 0xc4, 0x07, 0x0b, 0x19, 0x05, 0x01, +0x09, 0x45, 0x23, 0x0e, 0xa4, 0x06, 0x23, 0x20, 0x04, 0x08, 0x23, 0x22, 0x04, 0x08, 0x13, 0x05, +0x44, 0x23, 0x93, 0x05, 0x40, 0x03, 0x93, 0x06, 0x40, 0x03, 0x01, 0x46, 0xef, 0x40, 0xd7, 0xee, +0x63, 0x0a, 0x09, 0x00, 0x03, 0x45, 0x39, 0x00, 0x0b, 0x13, 0x05, 0x05, 0x23, 0x20, 0x04, 0x08, +0x23, 0x22, 0x04, 0x08, 0x20, 0x9a, 0x00, 0x00, 0xc0, 0x9a, 0x32, 0x8a, 0x2e, 0x89, 0xaa, 0x84, +0xef, 0x10, 0x10, 0x1f, 0x13, 0x04, 0x40, 0x15, 0x93, 0x09, 0xa0, 0x0f, 0x0b, 0x87, 0x04, 0x03, +0x93, 0x05, 0x40, 0x1f, 0x13, 0x04, 0xe0, 0x15, 0x2b, 0xe4, 0xa5, 0x22, 0xef, 0x30, 0x1c, 0xb2, +0x03, 0x45, 0xc5, 0x0e, 0x2b, 0xe4, 0xa9, 0x20, 0x23, 0x10, 0x8a, 0x00, 0x0b, 0x16, 0x09, 0x01, +0xef, 0x30, 0xdc, 0xb0, 0x03, 0x45, 0xc5, 0x0e, 0x93, 0x05, 0xb0, 0x12, 0xab, 0xe5, 0xa9, 0x20, +0x23, 0x10, 0xba, 0x00, 0xa0, 0x9a, 0x00, 0x00, 0x40, 0x9a, 0x49, 0xc5, 0xae, 0x89, 0x2a, 0x84, +0xef, 0x10, 0x10, 0x1a, 0x93, 0x05, 0x20, 0x1c, 0x03, 0x29, 0x44, 0x02, 0x93, 0x04, 0x00, 0x14, +0xab, 0xe4, 0xa5, 0x22, 0xa3, 0x0c, 0x34, 0x03, 0xef, 0x30, 0x5c, 0xad, 0x03, 0x45, 0xc5, 0x0e, +0x93, 0x05, 0x60, 0x0e, 0xab, 0xe4, 0xa5, 0x20, 0x63, 0x77, 0x99, 0x02, 0x09, 0x45, 0xa3, 0x08, +0xa4, 0x02, 0x8b, 0x59, 0x09, 0xfb, 0x93, 0x05, 0x04, 0x03, 0x11, 0x45, 0xa3, 0x08, 0xa4, 0x02, +0x8b, 0x81, 0x19, 0x02, 0x0b, 0x93, 0x09, 0x01, 0x2e, 0x85, 0xca, 0x85, 0xef, 0x10, 0x5a, 0xfb, +0xef, 0x50, 0xd9, 0xc5, 0x25, 0xa0, 0x22, 0x1c, 0xef, 0x50, 0x59, 0xc5, 0x64, 0x9d, 0x93, 0x85, +0xe9, 0xff, 0xb3, 0x35, 0xb0, 0x00, 0x4d, 0x8d, 0x11, 0xe9, 0x03, 0x45, 0x14, 0x03, 0x0b, 0x02, +0x05, 0x04, 0x8b, 0x12, 0x05, 0x02, 0x05, 0x05, 0xa3, 0x08, 0xa4, 0x02, 0xef, 0x10, 0x19, 0xfe, +0x11, 0xc1, 0x22, 0x1c, 0x20, 0x9a, 0x22, 0x85, 0x4a, 0x86, 0xef, 0x10, 0x7a, 0xf8, 0xe9, 0xb7, +0x00, 0x00, 0x00, 0x00, 0xaa, 0x86, 0x03, 0x05, 0x05, 0x07, 0x7d, 0x15, 0x08, 0x93, 0x2e, 0x85, +0x8b, 0x52, 0x07, 0x02, 0xb2, 0x85, 0x6f, 0x10, 0xea, 0xe1, 0x83, 0xc5, 0xa6, 0x03, 0x8b, 0x92, +0x05, 0x01, 0xb2, 0x85, 0x6f, 0x10, 0x4a, 0xe2, 0xb2, 0x85, 0x6f, 0x10, 0x2a, 0xe3, 0x00, 0x00, +0x40, 0x9a, 0xb6, 0x84, 0xb2, 0x89, 0x2e, 0x89, 0x2a, 0x84, 0xef, 0x50, 0xf9, 0xbb, 0x4d, 0xc1, +0x8b, 0x9b, 0x04, 0x01, 0x0b, 0x47, 0x24, 0x03, 0xef, 0x70, 0x19, 0x9d, 0x7b, 0x06, 0x2f, 0x2e, +0x93, 0x05, 0xc0, 0x12, 0x0b, 0x05, 0x06, 0x01, 0x13, 0x45, 0xc5, 0x2b, 0x13, 0x06, 0x40, 0x06, +0x93, 0x05, 0x80, 0x0c, 0xab, 0x65, 0xa6, 0x20, 0x23, 0x10, 0xb9, 0x00, 0x20, 0x9a, 0xef, 0x70, +0xb9, 0x9a, 0x13, 0x05, 0x45, 0xd4, 0x33, 0x35, 0xa0, 0x00, 0x93, 0x35, 0x34, 0x00, 0x4d, 0x8d, +0x11, 0xe5, 0x8b, 0x11, 0x14, 0x03, 0x13, 0x05, 0x00, 0x05, 0x89, 0xa0, 0xef, 0x70, 0xd9, 0x98, +0x13, 0x45, 0x65, 0x22, 0x93, 0x45, 0x34, 0x00, 0x4d, 0x8d, 0x1d, 0xe9, 0x83, 0xd5, 0xa9, 0x00, +0x13, 0x06, 0x20, 0x12, 0x09, 0x45, 0x63, 0x65, 0xb6, 0x00, 0x05, 0x45, 0x0b, 0xc4, 0x05, 0xf1, +0x83, 0x55, 0x09, 0x00, 0x33, 0xd5, 0xa5, 0x00, 0x23, 0x10, 0xa9, 0x00, 0xef, 0x10, 0x50, 0x05, +0x01, 0xc9, 0x13, 0x05, 0x00, 0x14, 0x19, 0xa0, 0x13, 0x05, 0x00, 0x0a, 0x23, 0x10, 0xa9, 0x00, +0x7b, 0x05, 0x2f, 0x2e, 0x0b, 0x13, 0x05, 0x01, 0x13, 0x05, 0x00, 0x14, 0x23, 0x10, 0xa9, 0x00, +0x20, 0x9a, 0x00, 0x00, 0xc0, 0x99, 0x01, 0x44, 0x37, 0x35, 0x09, 0x00, 0x13, 0x09, 0x05, 0xa7, +0x37, 0x86, 0x02, 0x40, 0xb7, 0x84, 0x02, 0x40, 0x03, 0x25, 0x09, 0x00, 0x5b, 0xa2, 0xa4, 0xc0, +0xdb, 0x26, 0x49, 0x80, 0x01, 0x45, 0xa2, 0x85, 0xef, 0x50, 0x0a, 0xa9, 0x05, 0x04, 0x26, 0x86, +0x0b, 0x1a, 0xf4, 0x46, 0x37, 0x85, 0x02, 0x40, 0x18, 0x99, 0x05, 0x04, 0x01, 0x06, 0xf9, 0x93, +0x05, 0x10, 0x10, 0x23, 0x28, 0xb5, 0x0e, 0x85, 0x65, 0x93, 0x85, 0xa5, 0xa0, 0x23, 0x2a, 0xb5, +0x0e, 0xa0, 0x99, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x98, 0x2a, 0x84, 0x03, 0x45, 0x65, 0x00, 0x8b, +0x1e, 0x05, 0x02, 0x03, 0x47, 0x44, 0x00, 0xa3, 0x01, 0xe4, 0x00, 0x10, 0x5c, 0x54, 0x5c, 0x7b, +0x25, 0x00, 0x81, 0x10, 0xd8, 0x54, 0xd8, 0x72, 0x1c, 0x7a, 0x1c, 0x0b, 0x47, 0x05, 0x04, 0xfb, +0x27, 0x09, 0xf6, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0x25, 0x93, +0x85, 0x25, 0x4c, 0xef, 0x50, 0x97, 0xe6, 0x0e, 0x10, 0xa0, 0x98, 0x00, 0x00, 0x00, 0x00, 0x03, +0x47, 0x45, 0x00, 0xa3, 0x01, 0xe5, 0x00, 0x10, 0x5d, 0x54, 0x5d, 0xfb, 0x25, 0x00, 0x81, 0x10, +0xd9, 0x54, 0xd9, 0x72, 0x1d, 0x7a, 0x1d, 0x0b, 0xc7, 0x05, 0x03, 0xfb, 0x27, 0x09, 0xf6, 0x37, +0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0x34, 0x93, 0x85, 0x25, 0x4c, 0x6f, +0x50, 0xd7, 0xe2, 0x82, 0x80, 0x00, 0x00, 0xc0, 0x99, 0x37, 0x05, 0x00, 0x04, 0xb7, 0x45, 0x10, +0x40, 0xec, 0x55, 0x37, 0x16, 0x03, 0x20, 0x13, 0x04, 0x06, 0xb1, 0x50, 0x54, 0x13, 0x09, 0xf5, +0xff, 0x2b, 0xe5, 0x05, 0x74, 0x48, 0xd0, 0xb3, 0x24, 0xc5, 0x00, 0x22, 0x85, 0xa9, 0x3f, 0x03, +0x45, 0x64, 0x00, 0x0b, 0x16, 0x05, 0x01, 0x03, 0x45, 0x54, 0x00, 0x13, 0x35, 0x15, 0x00, 0x65, +0x8d, 0x93, 0x15, 0x15, 0x00, 0xa9, 0x8c, 0x23, 0x03, 0xb4, 0x00, 0x48, 0x50, 0x2a, 0x10, 0x48, +0xd4, 0x37, 0x86, 0x12, 0x40, 0x03, 0x25, 0x06, 0x0b, 0x83, 0x25, 0x46, 0x0b, 0x03, 0x26, 0xc6, +0x0b, 0x69, 0x82, 0xb3, 0xe6, 0xa5, 0x00, 0xb3, 0xf6, 0x26, 0x01, 0x23, 0x02, 0xc4, 0x00, 0x99, +0xc6, 0xb3, 0xf5, 0x25, 0x01, 0x33, 0x75, 0x25, 0x01, 0x08, 0xdc, 0x4c, 0xdc, 0x81, 0xc4, 0x22, +0x85, 0x80, 0x99, 0xb1, 0xb7, 0xa0, 0x99, 0x00, 0x00, 0x00, 0x00, 0x40, 0x98, 0x22, 0xa0, 0x53, +0x15, 0x05, 0xc2, 0x53, 0x00, 0x05, 0xd2, 0x53, 0x74, 0x05, 0x0a, 0xef, 0x30, 0x8e, 0xb0, 0x31, +0xc1, 0xef, 0x30, 0x2e, 0xb0, 0x13, 0x45, 0x45, 0x00, 0x93, 0x05, 0x40, 0x06, 0x13, 0x06, 0x80, +0x0c, 0x2b, 0xe6, 0xa5, 0x20, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x85, 0x5a, 0x53, 0x15, 0x04, +0xc2, 0xd3, 0x00, 0x05, 0xd2, 0xd3, 0x70, 0x14, 0x0a, 0xd3, 0xf0, 0x00, 0x12, 0x53, 0x95, 0x00, +0xc2, 0xb3, 0x65, 0xc5, 0x02, 0x0d, 0x8d, 0x53, 0x01, 0x05, 0xd2, 0xd3, 0xf0, 0x20, 0x0a, 0x53, +0xf4, 0x00, 0x1a, 0xef, 0xf0, 0x5d, 0xd5, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x85, 0x55, 0x53, +0x15, 0x85, 0xa2, 0x43, 0x70, 0x05, 0x42, 0x2b, 0x64, 0xa0, 0x3a, 0x53, 0x05, 0x84, 0x22, 0x02, +0x24, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xd0, 0x8a, 0xea, 0x00, 0x00, 0x00, 0x00, 0xcc, +0x9a, 0x22, 0xb8, 0x26, 0xb4, 0x36, 0x89, 0x32, 0x84, 0x53, 0x84, 0xb5, 0x22, 0xae, 0x89, 0xd3, +0x04, 0xa5, 0x22, 0xaa, 0x84, 0xef, 0xe0, 0xea, 0xb0, 0x2a, 0x8a, 0x03, 0x55, 0x05, 0x0d, 0x69, +0xc1, 0x13, 0x06, 0x84, 0x07, 0x93, 0x06, 0x94, 0x07, 0xa4, 0x91, 0x0d, 0x45, 0xef, 0xd0, 0xeb, +0xe6, 0x02, 0xd2, 0x02, 0xd0, 0x08, 0x10, 0x53, 0x85, 0x94, 0x22, 0xef, 0xe0, 0x9e, 0xe5, 0x26, +0x85, 0xef, 0x30, 0xec, 0xf6, 0x02, 0x35, 0x8b, 0x13, 0x05, 0x01, 0x52, 0x85, 0xa2, 0x85, 0xef, +0xe0, 0xda, 0xa4, 0x29, 0xa0, 0x52, 0x85, 0xa2, 0x85, 0xef, 0xe0, 0xba, 0x9c, 0x07, 0x30, 0x84, +0x01, 0x82, 0x30, 0x53, 0xf0, 0x00, 0x0a, 0x02, 0xb0, 0x53, 0x05, 0x84, 0x22, 0x22, 0x85, 0xce, +0x85, 0x4a, 0x86, 0xef, 0x00, 0x0b, 0x94, 0x13, 0x05, 0x84, 0x03, 0x13, 0x06, 0xc4, 0x02, 0x93, +0x06, 0x84, 0x02, 0xce, 0x85, 0xef, 0x80, 0xfe, 0xa6, 0x08, 0xa0, 0xef, 0xa0, 0x0c, 0xf8, 0x48, +0x74, 0x0c, 0x74, 0x02, 0x36, 0x53, 0x05, 0x05, 0x42, 0xd3, 0x85, 0x05, 0x42, 0xce, 0x85, 0xef, +0x80, 0x4e, 0xf6, 0x53, 0x04, 0xa5, 0x22, 0x0a, 0x85, 0x93, 0x05, 0x00, 0x02, 0x93, 0x06, 0x00, +0x02, 0x01, 0x46, 0xef, 0x40, 0xd7, 0xa7, 0x8a, 0x85, 0x4e, 0x85, 0xef, 0x50, 0x1b, 0xc0, 0x08, +0x74, 0xc2, 0x25, 0x53, 0x05, 0x05, 0x42, 0xef, 0x80, 0x5e, 0x9b, 0xd3, 0x05, 0xa5, 0x22, 0x37, +0xb5, 0x09, 0x00, 0x07, 0x36, 0x05, 0x56, 0x22, 0x85, 0x53, 0x05, 0x84, 0x22, 0xef, 0x00, 0x2b, +0x8a, 0xa2, 0x34, 0x42, 0x34, 0xac, 0x9a, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x99, 0x37, 0xb5, 0x09, +0x00, 0x93, 0x05, 0x85, 0x56, 0x13, 0x05, 0x51, 0x02, 0x6d, 0x46, 0x13, 0x04, 0x51, 0x02, 0xef, +0x70, 0x56, 0xe7, 0x37, 0xb5, 0x09, 0x00, 0x93, 0x05, 0x35, 0x58, 0x13, 0x05, 0xa1, 0x00, 0x6d, +0x46, 0x93, 0x04, 0xa1, 0x00, 0xef, 0x70, 0xf6, 0xe5, 0xef, 0x30, 0xbc, 0x97, 0xab, 0x64, 0xa4, +0x20, 0x37, 0xb5, 0x00, 0x20, 0x13, 0x04, 0x05, 0xf2, 0x93, 0x05, 0x40, 0x02, 0x93, 0x06, 0x40, +0x02, 0x13, 0x09, 0x40, 0x02, 0x22, 0x85, 0x01, 0x46, 0xef, 0x40, 0x77, 0x9f, 0x26, 0x85, 0xef, +0x80, 0x46, 0xb9, 0xaa, 0x86, 0x93, 0x05, 0x40, 0x02, 0x22, 0x85, 0x26, 0x86, 0xef, 0x40, 0xa7, +0xbc, 0x19, 0xcd, 0x7b, 0x25, 0x00, 0x81, 0x41, 0xcd, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, +0x17, 0xb7, 0xb5, 0x01, 0x38, 0x93, 0x85, 0x25, 0x34, 0xef, 0x50, 0xb7, 0xa4, 0xb0, 0x99, 0x26, +0x85, 0xef, 0x80, 0x26, 0xb6, 0xaa, 0x84, 0x8b, 0x28, 0x05, 0x1f, 0x7b, 0x25, 0x00, 0x81, 0x25, +0xc9, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0x3d, 0x93, 0x85, 0x25, +0x34, 0x26, 0x86, 0xef, 0x50, 0x57, 0xa7, 0xb0, 0x99, 0xef, 0x80, 0x67, 0xa4, 0xaa, 0x86, 0x33, +0x85, 0x84, 0x00, 0xb3, 0x05, 0x99, 0x40, 0x37, 0xb6, 0x09, 0x00, 0x13, 0x06, 0xe6, 0x59, 0xef, +0x10, 0x57, 0xb3, 0x0b, 0x22, 0x05, 0x00, 0xaa, 0x94, 0x31, 0xa8, 0x7b, 0x25, 0x00, 0x81, 0x19, +0xc9, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x01, 0x44, 0x93, 0x85, 0x25, +0x34, 0xef, 0x50, 0x37, 0x9e, 0x13, 0x06, 0x40, 0x02, 0x22, 0x85, 0xa6, 0x85, 0xef, 0x70, 0x7e, +0x87, 0x93, 0x85, 0x34, 0x00, 0x13, 0x06, 0x40, 0x02, 0x22, 0x85, 0xef, 0x70, 0x1e, 0x8f, 0xb0, +0x99, 0x00, 0x00, 0xc0, 0x98, 0xef, 0x20, 0xfe, 0xef, 0x3d, 0xc1, 0x2a, 0x84, 0x37, 0xb5, 0x00, +0x20, 0x03, 0x15, 0x85, 0x6a, 0x85, 0x65, 0x95, 0x05, 0x23, 0x10, 0xb4, 0x00, 0x93, 0x05, 0x85, +0x00, 0x23, 0x13, 0xb4, 0x00, 0x13, 0x05, 0x84, 0x00, 0xac, 0x91, 0xef, 0xf0, 0xdd, 0xae, 0x23, +0x11, 0xa4, 0x00, 0xef, 0xf0, 0x9d, 0x91, 0xfb, 0x25, 0x00, 0x81, 0x23, 0x12, 0xa4, 0x00, 0x0b, +0xc8, 0x05, 0x03, 0x03, 0x56, 0x64, 0x00, 0x83, 0x56, 0x24, 0x00, 0x37, 0x05, 0x23, 0x00, 0x13, +0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x00, 0x25, 0x93, 0x85, 0x25, 0x4c, 0xef, 0x50, 0x57, 0xa1, 0x03, +0x55, 0x64, 0x00, 0x93, 0x05, 0x85, 0x00, 0x22, 0x85, 0x80, 0x98, 0x6f, 0xf0, 0xdd, 0x96, 0x9f, +0x1f, 0x05, 0x04, 0x01, 0x07, 0xf8, 0xa0, 0x98, 0x00, 0x00, 0x40, 0x98, 0x0b, 0x94, 0x15, 0x01, +0x2a, 0x86, 0x13, 0x05, 0xb1, 0x00, 0x85, 0x45, 0x85, 0x46, 0xef, 0x40, 0x47, 0xaa, 0x03, 0x46, +0xb1, 0x00, 0x8b, 0x1f, 0x06, 0x01, 0x37, 0x55, 0x00, 0x20, 0x13, 0x05, 0x85, 0x88, 0x0c, 0x51, +0x48, 0x51, 0xfb, 0x26, 0x00, 0x81, 0x37, 0xb7, 0x09, 0x00, 0x23, 0x26, 0xa7, 0x70, 0x23, 0x24, +0xb7, 0x70, 0x0b, 0xc6, 0x06, 0x03, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, +0x02, 0x30, 0x93, 0x85, 0x25, 0x5c, 0xef, 0x50, 0x97, 0x95, 0x20, 0x98, 0x85, 0x45, 0x39, 0xa8, +0x7b, 0x25, 0x00, 0x81, 0x19, 0xc9, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, +0x02, 0x2b, 0x93, 0x85, 0x25, 0x54, 0xef, 0x50, 0x97, 0x93, 0x89, 0x45, 0x7b, 0x6e, 0xb5, 0x6c, +0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x98, 0x2a, 0x84, 0xef, 0x70, 0x4b, 0xcd, 0xaa, 0x85, +0x05, 0x45, 0x85, 0xc5, 0x0b, 0x54, 0x04, 0x0a, 0x85, 0x45, 0xb3, 0x95, 0x85, 0x00, 0x93, 0xf5, +0x85, 0x23, 0x81, 0xed, 0xfd, 0x75, 0xfd, 0x15, 0xa2, 0x95, 0x8b, 0xd4, 0x05, 0x09, 0x05, 0x46, +0xb3, 0x15, 0xb6, 0x00, 0x93, 0xf5, 0x15, 0x14, 0x91, 0xc1, 0xa0, 0x98, 0x01, 0x45, 0xa0, 0x98, +0x00, 0x00, 0xc0, 0x98, 0x8b, 0x9f, 0x05, 0x02, 0x2a, 0x86, 0x0a, 0x85, 0x89, 0x45, 0x89, 0x46, +0x09, 0x44, 0xef, 0x40, 0xc7, 0x9e, 0x03, 0x46, 0x01, 0x00, 0x0b, 0x4c, 0x06, 0x02, 0x7b, 0x25, +0x00, 0x81, 0x09, 0xcd, 0x83, 0x46, 0x11, 0x00, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, +0xb7, 0xb5, 0x02, 0x4b, 0x93, 0x85, 0x25, 0x54, 0xef, 0x50, 0xf7, 0x90, 0x7b, 0x6e, 0x85, 0x6c, +0xa0, 0x98, 0x85, 0x45, 0x7b, 0x6e, 0xb5, 0x6c, 0xa0, 0x98, 0xef, 0x30, 0x0c, 0xc4, 0x2a, 0x84, +0x83, 0x45, 0x01, 0x00, 0x03, 0x25, 0x45, 0x11, 0x2c, 0xc8, 0x0b, 0x97, 0x05, 0x01, 0x13, 0x65, +0x05, 0x04, 0x23, 0x2a, 0xa4, 0x10, 0xef, 0x30, 0x4c, 0xf1, 0x13, 0x35, 0x15, 0x00, 0x05, 0x05, +0x23, 0x0a, 0xa4, 0x04, 0x29, 0xa0, 0x13, 0x75, 0xf5, 0xfb, 0x23, 0x2a, 0xa4, 0x10, 0x7b, 0x25, +0x00, 0x81, 0x0b, 0x48, 0x05, 0x03, 0x03, 0x46, 0x01, 0x00, 0x83, 0x46, 0x11, 0x00, 0x37, 0x05, +0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x02, 0x5a, 0x93, 0x85, 0x25, 0x5c, 0xef, 0x50, +0x97, 0x8a, 0xa0, 0x98, 0x00, 0x00, 0x4c, 0x98, 0x0b, 0x92, 0x25, 0x1c, 0x2a, 0x86, 0x08, 0x10, +0xf1, 0x45, 0xf1, 0x46, 0xef, 0x40, 0xa7, 0x94, 0x83, 0x46, 0x01, 0x02, 0x37, 0xb5, 0x09, 0x00, +0x83, 0x05, 0x15, 0x6d, 0x36, 0x86, 0x2b, 0xe6, 0xd5, 0x20, 0xa3, 0x08, 0xc5, 0x6c, 0x03, 0x47, +0x11, 0x02, 0x83, 0x47, 0x21, 0x02, 0x7b, 0x25, 0x00, 0x81, 0xb7, 0xb5, 0x09, 0x00, 0x23, 0x88, +0xe5, 0x70, 0x93, 0x85, 0x05, 0x71, 0xa3, 0x80, 0xf5, 0x00, 0x0b, 0x41, 0x15, 0x03, 0x03, 0x48, +0x31, 0x02, 0x83, 0x58, 0x41, 0x02, 0x83, 0x52, 0x61, 0x02, 0x03, 0x53, 0x81, 0x02, 0x83, 0x53, +0xa1, 0x02, 0x32, 0x5e, 0x42, 0x55, 0xd2, 0x55, 0x62, 0x56, 0x32, 0xcc, 0x2e, 0xca, 0x2a, 0xc8, +0x72, 0xc6, 0x1e, 0xc4, 0x1a, 0xc2, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, +0x02, 0x73, 0x93, 0x85, 0x25, 0x5c, 0x31, 0x46, 0x16, 0xc0, 0xef, 0x50, 0xd7, 0x93, 0x2c, 0x98, +0x85, 0x45, 0x7b, 0x6e, 0xb5, 0x6c, 0x2c, 0x98, 0x00, 0x00, 0x40, 0x98, 0x22, 0xa0, 0x33, 0xc8, +0xb6, 0x00, 0xb3, 0x38, 0xc5, 0x00, 0x33, 0xb7, 0xd5, 0x00, 0x2b, 0xe7, 0x08, 0x21, 0x33, 0x38, +0xa6, 0x00, 0xb3, 0x87, 0xb6, 0x40, 0xb3, 0x87, 0x07, 0x41, 0x33, 0x08, 0xa6, 0x40, 0x95, 0x8d, +0xb3, 0x85, 0x15, 0x41, 0x11, 0x8d, 0xab, 0xe5, 0xe7, 0x22, 0x2b, 0x65, 0xe8, 0x22, 0x41, 0x81, +0x2b, 0x26, 0xb5, 0x20, 0x93, 0xd6, 0x05, 0x01, 0x33, 0x35, 0xc0, 0x00, 0x2b, 0x05, 0xb5, 0x60, +0xe8, 0x8d, 0x70, 0x8d, 0x2b, 0x65, 0xe6, 0x22, 0xab, 0xe5, 0xe6, 0x22, 0xef, 0xd0, 0xa6, 0xbf, +0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x85, 0x5a, 0x53, 0x74, 0x05, 0x12, 0xef, 0x50, 0xeb, 0xe5, +0xef, 0xd0, 0x66, 0xbe, 0x53, 0x75, 0xa4, 0x1a, 0x02, 0x24, 0x20, 0x98, 0x00, 0x00, 0xc0, 0x98, +0xef, 0x10, 0x6e, 0xd4, 0x2a, 0x84, 0xef, 0x50, 0x5e, 0xc4, 0x37, 0xb6, 0x09, 0x00, 0x83, 0x25, +0xc6, 0x70, 0x03, 0x27, 0x86, 0x70, 0x33, 0x66, 0xb7, 0x00, 0x01, 0xca, 0x74, 0x49, 0x30, 0x49, +0x3a, 0x85, 0xa5, 0x37, 0x53, 0x15, 0x15, 0xc2, 0x11, 0xa0, 0x01, 0x45, 0x08, 0xc0, 0xef, 0xb0, +0x4e, 0xd5, 0x23, 0x02, 0xa4, 0x00, 0xef, 0x50, 0x4e, 0xbc, 0xb7, 0xc5, 0x04, 0x20, 0x93, 0x85, +0x85, 0xf6, 0x07, 0xb0, 0x05, 0x73, 0x53, 0x75, 0x10, 0x40, 0x53, 0x06, 0x05, 0xe0, 0xa3, 0x28, +0xc4, 0x00, 0x07, 0xb0, 0x05, 0x14, 0x53, 0x75, 0x10, 0x40, 0x53, 0x06, 0x05, 0xe0, 0xa3, 0x26, +0xc4, 0x00, 0x03, 0xa6, 0x85, 0x71, 0x83, 0xa5, 0x05, 0x1d, 0x23, 0x03, 0xa4, 0x00, 0xa3, 0x13, +0xc4, 0x00, 0xa3, 0x24, 0xb4, 0x00, 0xef, 0x10, 0x4e, 0xcc, 0x2a, 0x84, 0x05, 0x65, 0x2d, 0x05, +0x23, 0x10, 0xa4, 0x00, 0x55, 0x45, 0x23, 0x13, 0xa4, 0x00, 0xef, 0xf0, 0x8d, 0xde, 0x83, 0x55, +0x64, 0x00, 0x23, 0x12, 0xa4, 0x00, 0x13, 0x05, 0x84, 0x00, 0xef, 0xf0, 0x4d, 0xfa, 0x2a, 0x87, +0x23, 0x11, 0xa4, 0x00, 0x7b, 0x25, 0x00, 0x81, 0x0b, 0x48, 0x05, 0x03, 0x03, 0x56, 0x04, 0x00, +0x83, 0x56, 0x64, 0x00, 0x37, 0x05, 0x23, 0x00, 0x13, 0x05, 0xe5, 0x17, 0xb7, 0xb5, 0x03, 0x45, +0x93, 0x85, 0x25, 0x5c, 0xef, 0x50, 0xe7, 0xf2, 0x03, 0x55, 0x64, 0x00, 0x93, 0x05, 0x85, 0x00, +0x22, 0x85, 0x80, 0x98, 0x6f, 0xf0, 0xad, 0xe2, 0x00, 0x00, 0x40, 0x99, 0x03, 0xc6, 0xb5, 0x00, +0x2a, 0x84, 0x0d, 0x45, 0x0b, 0x03, 0x16, 0x01, 0x83, 0xc4, 0x95, 0x00, 0x33, 0x85, 0xb4, 0x00, +0x03, 0x45, 0x25, 0x00, 0x0b, 0xcf, 0x04, 0x03, 0x0b, 0x0e, 0x05, 0x02, 0x0b, 0x0d, 0x05, 0x04, +0xef, 0x10, 0xe0, 0x08, 0x4c, 0x44, 0x53, 0x80, 0x05, 0xd2, 0xd3, 0x80, 0x14, 0xd2, 0x11, 0xc5, +0x37, 0xb5, 0x09, 0x00, 0x07, 0x31, 0x85, 0x5b, 0x29, 0xa0, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x31, +0x05, 0x5b, 0xd3, 0xf0, 0x20, 0x12, 0xd3, 0x85, 0x00, 0xa2, 0x15, 0x45, 0x91, 0xe1, 0x11, 0x45, +0x20, 0x99, 0x00, 0x00, 0x00, 0x00, 0x83, 0x45, 0xf5, 0x02, 0x13, 0xf6, 0x05, 0x02, 0x53, 0x05, +0x00, 0xd2, 0x59, 0xca, 0x54, 0x45, 0x18, 0x45, 0x37, 0xb6, 0x09, 0x00, 0x07, 0x30, 0x06, 0x5c, +0x03, 0x46, 0x15, 0x02, 0xd3, 0x80, 0x16, 0xd2, 0x53, 0x01, 0x17, 0xd2, 0x43, 0x70, 0x01, 0x0a, +0x0b, 0x53, 0x16, 0x06, 0x85, 0x46, 0xb3, 0x96, 0xc6, 0x00, 0x93, 0xf6, 0x96, 0x02, 0x9d, 0xce, +0xab, 0xe6, 0x35, 0x44, 0x11, 0xca, 0x03, 0x05, 0x05, 0x02, 0x0b, 0x17, 0x06, 0x03, 0x37, 0x07, +0x04, 0x20, 0x13, 0x07, 0x07, 0xde, 0x21, 0xa8, 0x03, 0x05, 0x05, 0x02, 0x37, 0x57, 0x04, 0x20, +0x13, 0x07, 0x07, 0xcf, 0x29, 0xa0, 0xdf, 0xbc, 0x05, 0x04, 0x01, 0x08, 0xf7, 0x37, 0x57, 0x04, +0x20, 0x13, 0x07, 0x07, 0xcc, 0x3a, 0x95, 0x89, 0xca, 0x03, 0x45, 0x05, 0x00, 0x11, 0xc5, 0x63, +0x82, 0xa6, 0x02, 0x53, 0x05, 0x00, 0x22, 0x82, 0x80, 0x01, 0x45, 0x13, 0x36, 0x16, 0x00, 0x8d, +0x89, 0x93, 0xc6, 0x35, 0x00, 0xab, 0x65, 0xd0, 0x20, 0x2b, 0xe5, 0xc5, 0x22, 0x09, 0xc9, 0x0b, +0x19, 0xf5, 0x01, 0x37, 0xb5, 0x09, 0x00, 0x87, 0x30, 0x85, 0x5c, 0x53, 0x75, 0x10, 0x02, 0x82, +0x80, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x99, 0x2a, 0x84, 0x03, 0x06, 0x05, 0x02, 0x03, 0x45, 0x15, +0x02, 0xae, 0x84, 0x23, 0x90, 0xc5, 0x02, 0xa3, 0x86, 0xa5, 0x02, 0xb2, 0x85, 0xef, 0x90, 0xce, +0xe6, 0x83, 0xd5, 0x04, 0x02, 0x03, 0xc6, 0xd4, 0x02, 0x23, 0x91, 0xa4, 0x02, 0x2e, 0x89, 0x8b, +0x15, 0x06, 0x01, 0x37, 0x15, 0x00, 0x20, 0x13, 0x05, 0x85, 0x01, 0x2b, 0x05, 0xb5, 0x04, 0x08, +0x41, 0x13, 0x09, 0x75, 0x00, 0x03, 0x05, 0x04, 0x03, 0x23, 0x88, 0xa4, 0x02, 0xec, 0x91, 0x32, +0x85, 0xef, 0xf0, 0x1e, 0xdf, 0xa3, 0x89, 0xa4, 0x02, 0x03, 0xc5, 0xd4, 0x02, 0x02, 0xc4, 0x02, +0xc2, 0x02, 0xc0, 0x93, 0x15, 0x09, 0x01, 0xc1, 0x81, 0x0a, 0x86, 0xef, 0x80, 0x3e, 0xa4, 0x02, +0x45, 0x83, 0x05, 0x44, 0x02, 0x03, 0x06, 0xb4, 0x02, 0x23, 0x83, 0xa4, 0x02, 0x23, 0x86, 0xb4, +0x02, 0xa3, 0x82, 0xc4, 0x02, 0x03, 0x05, 0xe4, 0x01, 0x83, 0x05, 0x34, 0x02, 0x03, 0x06, 0x74, +0x02, 0x83, 0x06, 0x24, 0x02, 0x23, 0x82, 0xa4, 0x02, 0xa3, 0x83, 0xb4, 0x02, 0xa3, 0x88, 0xc4, +0x02, 0x13, 0x85, 0xd6, 0xff, 0x88, 0x91, 0x93, 0xb5, 0xa5, 0x00, 0x13, 0x06, 0x10, 0x21, 0x33, +0x55, 0xa6, 0x00, 0x6d, 0x8d, 0x4c, 0x44, 0x10, 0x44, 0xb7, 0xb6, 0x09, 0x00, 0x07, 0xb0, 0x06, +0x5c, 0x23, 0x8a, 0xa4, 0x02, 0xd3, 0x80, 0x05, 0xd2, 0x53, 0x01, 0x16, 0xd2, 0x43, 0x70, 0x01, +0x0a, 0x27, 0xb8, 0x04, 0x00, 0x22, 0x85, 0x59, 0x35, 0x03, 0x05, 0xf4, 0x02, 0x88, 0xa8, 0x23, +0x87, 0xa4, 0x02, 0xa4, 0x99, 0x40, 0x99, 0xef, 0x30, 0xac, 0x81, 0x2a, 0x84, 0x13, 0x05, 0xf0, +0x0f, 0x23, 0x12, 0xa4, 0x00, 0xef, 0x30, 0xcc, 0xaf, 0x93, 0x05, 0x10, 0x24, 0x93, 0x04, 0x10, +0x20, 0x13, 0x06, 0x10, 0x20, 0x2b, 0xe6, 0xa5, 0x20, 0x23, 0x2a, 0xc4, 0x10, 0xef, 0x30, 0x4c, +0xae, 0x83, 0x25, 0x44, 0x11, 0x13, 0x35, 0x15, 0x00, 0x05, 0x05, 0x13, 0xf6, 0x05, 0x04, 0xa3, +0x0a, 0xa4, 0x04, 0x09, 0xc6, 0x05, 0x46, 0x30, 0xc8, 0x23, 0x0a, 0xa4, 0x04, 0x13, 0xf5, 0x05, +0x20, 0x23, 0x0b, 0x04, 0x04, 0x11, 0xc5, 0xef, 0x30, 0xac, 0xab, 0x19, 0xe1, 0x23, 0x1c, 0x94, +0x04, 0x23, 0x01, 0x04, 0x14, 0x20, 0x99, 0x00, 0x00, 0x40, 0x98, 0xef, 0x20, 0x7c, 0xfb, 0x89, +0x45, 0x23, 0x05, 0xb5, 0x00, 0xb7, 0xd5, 0x4c, 0x3f, 0x93, 0x85, 0xd5, 0xcc, 0x23, 0x26, 0xb5, +0x12, 0x20, 0x98, 0x00, 0x00, 0xc0, 0x98, 0xef, 0x50, 0x2d, 0xbb, 0x79, 0xed, 0x37, 0xb5, 0x04, +0x20, 0x93, 0x05, 0x05, 0x6b, 0xc8, 0x49, 0x09, 0xc9, 0x07, 0xb0, 0x85, 0x00, 0x05, 0x05, 0xd3, +0x00, 0x15, 0xd2, 0x53, 0x15, 0x10, 0xa2, 0x69, 0xe1, 0xef, 0x50, 0xce, 0x81, 0xb7, 0xc5, 0x04, +0x20, 0x13, 0x84, 0x85, 0xf6, 0x83, 0x25, 0x04, 0x16, 0x13, 0x35, 0x15, 0x00, 0x93, 0xb5, 0x15, +0x00, 0x4d, 0x8d, 0x5d, 0xe1, 0xef, 0x20, 0xdc, 0xf5, 0x03, 0x45, 0xc5, 0x0e, 0x0b, 0x17, 0x25, +0x01, 0xef, 0x50, 0x0e, 0x87, 0x07, 0x30, 0x84, 0x12, 0xb7, 0xb5, 0x09, 0x00, 0x87, 0xb0, 0x05, +0x66, 0xd3, 0x95, 0x00, 0xa2, 0x37, 0xb6, 0x09, 0x00, 0x13, 0x06, 0x86, 0x5d, 0xab, 0x05, 0xb6, +0x06, 0x07, 0xb0, 0x05, 0x00, 0xb7, 0xb5, 0x09, 0x00, 0x87, 0xb0, 0x05, 0x5d, 0xb7, 0xb5, 0x09, +0x00, 0x83, 0xc5, 0x05, 0x71, 0x13, 0x35, 0x15, 0x00, 0x2b, 0xe0, 0xa0, 0x3a, 0x07, 0x25, 0x04, +0x1d, 0x13, 0xb5, 0x15, 0x00, 0xd3, 0x80, 0x15, 0xd2, 0xab, 0x60, 0xa0, 0x3a, 0x53, 0x00, 0x05, +0x42, 0x53, 0x95, 0x00, 0xa2, 0x05, 0xc9, 0x23, 0x20, 0x04, 0x16, 0x23, 0x20, 0x04, 0x18, 0x13, +0x05, 0x84, 0x1f, 0x93, 0x05, 0x00, 0x29, 0x93, 0x06, 0x00, 0x29, 0x01, 0x46, 0xef, 0x40, 0x07, +0xa7, 0x13, 0x05, 0x84, 0x48, 0x93, 0x05, 0x00, 0x29, 0x93, 0x06, 0x00, 0x29, 0x01, 0x46, 0x80, +0x98, 0x6f, 0x40, 0xc7, 0xa5, 0x03, 0x45, 0x14, 0x72, 0x0b, 0x14, 0x05, 0x02, 0xef, 0x40, 0x5e, +0xfe, 0x79, 0xd1, 0xef, 0x40, 0xbd, 0xa3, 0x61, 0xd1, 0xa0, 0x98, 0x00, 0x00, 0xc0, 0x98, 0x37, +0x24, 0x04, 0x20, 0x83, 0x25, 0x44, 0xe3, 0x37, 0xb5, 0x09, 0x00, 0x03, 0x45, 0x15, 0x6d, 0xb3, +0x35, 0xb0, 0x00, 0x13, 0x06, 0xd5, 0xfd, 0x13, 0x36, 0x16, 0x00, 0xd1, 0x8d, 0x99, 0xe5, 0xef, +0x20, 0x3c, 0xd2, 0x13, 0x05, 0x44, 0xe3, 0x85, 0x45, 0x0c, 0xc1, 0xed, 0x35, 0x80, 0x98, 0x6f, +0x00, 0x30, 0x54, 0x00, 0x00, 0x40, 0x99, 0x2a, 0x84, 0xef, 0x60, 0x1d, 0xbc, 0xaa, 0x84, 0xef, +0x40, 0x7e, 0xf3, 0x05, 0xc1, 0x37, 0xb5, 0x09, 0x00, 0x03, 0x45, 0x15, 0x71, 0x93, 0x75, 0x05, +0x08, 0x91, 0xe5, 0x13, 0x75, 0x05, 0x04, 0x11, 0xc5, 0x09, 0x45, 0x11, 0xa0, 0x05, 0x45, 0x23, +0x8c, 0xa4, 0x00, 0x03, 0xc5, 0x84, 0x01, 0x93, 0x65, 0x25, 0x00, 0x8b, 0x93, 0x05, 0x02, 0x22, +0x85, 0xef, 0x70, 0x0d, 0xc5, 0x03, 0xc5, 0x84, 0x01, 0x8b, 0x14, 0x05, 0x01, 0x09, 0x45, 0x23, +0x8c, 0xa4, 0x00, 0x22, 0x85, 0xef, 0x70, 0xcd, 0xc3, 0x11, 0xc1, 0x20, 0x99, 0x05, 0x45, 0x23, +0x8c, 0xa4, 0x00, 0x22, 0x85, 0x00, 0x99, 0x6f, 0x70, 0xad, 0xc2, 0x00, 0x00, 0x40, 0x99, 0x2a, +0x84, 0x05, 0x65, 0xb3, 0x05, 0xa4, 0x00, 0x83, 0xa5, 0x85, 0xb0, 0x13, 0x05, 0x05, 0xb0, 0x0b, +0x98, 0x05, 0x01, 0xb7, 0xd5, 0x4c, 0x3f, 0x93, 0x85, 0xd5, 0xcc, 0x23, 0x26, 0xb4, 0x0e, 0xb7, +0x05, 0x40, 0x40, 0x23, 0x28, 0xb4, 0x0e, 0xb7, 0x05, 0x00, 0x40, 0x23, 0x24, 0xb4, 0x0e, 0xb3, +0x04, 0xa4, 0x00, 0xef, 0x20, 0xfc, 0xdd, 0x03, 0x45, 0xc5, 0x0e, 0x15, 0xcd, 0xef, 0x20, 0x5c, +0xdd, 0x03, 0x45, 0xc5, 0x0e, 0x0d, 0xe1, 0x07, 0x30, 0x84, 0x05, 0x37, 0xb5, 0x09, 0x00, 0x87, +0x30, 0x85, 0x5e, 0x53, 0x15, 0x10, 0xa2, 0x01, 0xc9, 0x37, 0x05, 0x00, 0x40, 0x23, 0x26, 0xa4, +0x0e, 0x37, 0x05, 0x80, 0x3f, 0x31, 0xa0, 0x88, 0x40, 0x0b, 0x15, 0x05, 0x01, 0x37, 0x05, 0x80, +0x40, 0x23, 0x28, 0xa4, 0x0e, 0x21, 0xa0, 0x03, 0xc5, 0x84, 0x01, 0x69, 0xd1, 0x20, 0x99, 0x00, +0x00, 0x50, 0x9e, 0xa2, 0xa0, 0x26, 0xbc, 0x4a, 0xb8, 0x4e, 0xb4, 0x52, 0xb0, 0x56, 0xac, 0x5a, +0xa8, 0x5e, 0xa4, 0x32, 0x84, 0xae, 0x89, 0x2a, 0xc2, 0xef, 0x00, 0xd0, 0x42, 0x64, 0x9d, 0x93, +0x25, 0x14, 0x00, 0x4d, 0x8d, 0x63, 0x19, 0x05, 0x14, 0x81, 0x44, 0x09, 0x65, 0x13, 0x05, 0x05, +0x86, 0xb3, 0x8a, 0xa9, 0x00, 0x05, 0x65, 0x13, 0x0b, 0x85, 0xc6, 0xb3, 0x8b, 0x69, 0x01, 0x13, +0x8c, 0x89, 0x12, 0xb7, 0xb5, 0x09, 0x00, 0x07, 0xa4, 0x05, 0x5f, 0xb7, 0xb5, 0x78, 0x80, 0x05, +0x04, 0x01, 0x09, 0xf6, 0x09, 0x00, 0x87, 0xa4, 0x45, 0x5f, 0xb7, 0xb5, 0x09, 0x00, 0x07, 0xb9, +0x05, 0x6a, 0xb7, 0xb5, 0x09, 0x00, 0x87, 0xb9, 0x85, 0x60, 0xb7, 0xb5, 0x09, 0x00, 0x07, 0xaa, +0x85, 0x5f, 0xb7, 0xb5, 0x09, 0x00, 0x87, 0xaa, 0xc5, 0x5f, 0xb7, 0xb5, 0x09, 0x00, 0x07, 0xbb, +0x05, 0x60, 0x93, 0x0c, 0x05, 0xc6, 0x13, 0x0d, 0x45, 0xc6, 0xd3, 0x0b, 0x00, 0xf0, 0xab, 0x8d, +0x99, 0x04, 0x13, 0x8a, 0x8d, 0x2a, 0x52, 0x85, 0x53, 0x05, 0x84, 0x20, 0xef, 0x40, 0x5d, 0xdd, +0x13, 0x85, 0x8d, 0x36, 0x53, 0x85, 0x94, 0x20, 0xef, 0x40, 0x9d, 0xdc, 0x81, 0x45, 0x01, 0x45, +0x01, 0x49, 0x2b, 0x86, 0x99, 0x0a, 0x33, 0x08, 0x96, 0x01, 0xb3, 0x08, 0xa6, 0x01, 0x33, 0x07, +0x66, 0x01, 0xe2, 0x87, 0x5e, 0x86, 0x53, 0x05, 0x00, 0xf0, 0x63, 0x87, 0xb4, 0x04, 0xb3, 0x86, +0xba, 0x00, 0x83, 0xc6, 0x06, 0x00, 0xa9, 0xc2, 0x87, 0x25, 0x08, 0x00, 0x07, 0x26, 0x86, 0xff, +0x87, 0xa6, 0x08, 0x00, 0x07, 0x27, 0xc6, 0xff, 0x1c, 0x63, 0x07, 0x28, 0x06, 0x00, 0xd3, 0xf6, +0xe6, 0x10, 0xc3, 0xf5, 0xc5, 0x68, 0xc3, 0xf5, 0x07, 0x59, 0x53, 0x80, 0x05, 0x42, 0xd3, 0x06, +0x0b, 0xa2, 0x99, 0xc6, 0x90, 0x63, 0x05, 0x05, 0x53, 0x76, 0xb6, 0x18, 0x53, 0x75, 0xc5, 0x00, +0xd3, 0x86, 0x75, 0xa1, 0x91, 0xc2, 0x05, 0x09, 0x85, 0x05, 0x13, 0x06, 0x06, 0x02, 0x91, 0x07, +0xe3, 0x15, 0xb4, 0xfa, 0x1d, 0xc1, 0x87, 0xa5, 0x8d, 0x12, 0x53, 0x76, 0x05, 0xd0, 0x53, 0x75, +0xc5, 0x18, 0x53, 0x75, 0x45, 0x01, 0x53, 0x15, 0xb5, 0xa0, 0x01, 0xc9, 0x53, 0xf5, 0xb5, 0x10, +0x53, 0x75, 0x55, 0x11, 0x52, 0x85, 0xef, 0x40, 0xbd, 0xd2, 0x8b, 0x3b, 0x09, 0x03, 0x12, 0x45, +0x2b, 0x75, 0x95, 0x58, 0x48, 0x75, 0x53, 0x00, 0x05, 0x42, 0x53, 0x70, 0x20, 0x13, 0x53, 0x15, +0x30, 0xa3, 0x19, 0xc9, 0x07, 0xa5, 0x8d, 0x12, 0x53, 0x15, 0xaa, 0xa0, 0x11, 0xc5, 0x53, 0x75, +0xa5, 0x10, 0x52, 0x85, 0xef, 0x40, 0xdd, 0xcf, 0x85, 0x04, 0xe3, 0x9a, 0x84, 0xf0, 0xa2, 0x2b, +0x42, 0x2b, 0xe2, 0x2a, 0x02, 0x3a, 0xa2, 0x39, 0x42, 0x39, 0xe2, 0x34, 0x06, 0x24, 0x30, 0x9e, +0x00, 0x00, 0x00, 0x00, 0x40, 0x99, 0x2e, 0x84, 0xaa, 0x84, 0xef, 0x20, 0xfc, 0xbf, 0x03, 0x45, +0xc5, 0x0e, 0x25, 0xc1, 0x05, 0x65, 0x26, 0x95, 0x03, 0x05, 0xa5, 0xb4, 0x75, 0x15, 0x08, 0x91, +0x8b, 0x54, 0x15, 0x02, 0x8b, 0x23, 0x14, 0x01, 0x01, 0x46, 0xb3, 0x25, 0x80, 0x00, 0x09, 0x65, +0x93, 0x06, 0x05, 0x86, 0xa6, 0x96, 0x22, 0x87, 0x83, 0xc7, 0x06, 0x00, 0x81, 0xc7, 0x83, 0xc7, +0x06, 0x03, 0x3e, 0x96, 0x7d, 0x17, 0x85, 0x06, 0x65, 0xfb, 0x13, 0x26, 0x86, 0x00, 0xe4, 0x9d, +0xd1, 0x8d, 0x85, 0xe1, 0x13, 0x05, 0x05, 0x89, 0x26, 0x95, 0x83, 0x45, 0x05, 0xfd, 0x81, 0xc5, +0x83, 0x45, 0x05, 0x00, 0x81, 0xe5, 0x23, 0x08, 0x05, 0xfc, 0x02, 0x11, 0x7d, 0x14, 0x05, 0x05, +0x6d, 0xf4, 0x20, 0x99, 0x00, 0x00, 0x00, 0x00, 0x44, 0x9a, 0x22, 0xa8, 0x26, 0xa4, 0xb2, 0x89, +0x8b, 0x86, 0x06, 0x02, 0x8b, 0x98, 0x16, 0x01, 0x89, 0x65, 0x93, 0x85, 0x05, 0x89, 0xb3, 0x04, +0xb5, 0x00, 0x13, 0x04, 0x85, 0x1e, 0x21, 0x05, 0x01, 0xa8, 0x89, 0x65, 0x93, 0x85, 0x05, 0x86, +0xb3, 0x04, 0xb5, 0x00, 0x13, 0x04, 0x85, 0x12, 0x00, 0x21, 0xef, 0x00, 0x30, 0x21, 0x0b, 0xae, +0x09, 0x01, 0x2a, 0x89, 0xd3, 0x04, 0x00, 0xf0, 0x03, 0xc5, 0x04, 0x00, 0x05, 0xc1, 0x08, 0x60, +0x53, 0x05, 0x05, 0x42, 0xef, 0x90, 0xa6, 0x80, 0x53, 0x15, 0xa4, 0xa2, 0x63, 0x06, 0x09, 0x00, +0x11, 0xc5, 0x08, 0x60, 0x53, 0x95, 0xa4, 0xa0, 0x11, 0xc1, 0x82, 0x10, 0xfd, 0x19, 0x11, 0x04, +0x85, 0x04, 0xe3, 0x9b, 0x09, 0xfc, 0xa2, 0x24, 0x42, 0x24, 0x24, 0x9a, 0x00, 0x00, 0x00, 0x00, +0xc8, 0x99, 0x22, 0xac, 0x26, 0xa8, 0x4a, 0xa4, 0x2a, 0x84, 0x05, 0x65, 0x13, 0x05, 0xa5, 0xb2, +0xb3, 0x04, 0xa4, 0x00, 0x07, 0xb0, 0x64, 0x0b, 0x87, 0xb0, 0xe4, 0x0a, 0x09, 0x65, 0x53, 0x75, +0x10, 0x40, 0xd3, 0xf5, 0x10, 0x40, 0xb7, 0xb5, 0x09, 0x00, 0x07, 0xb0, 0x05, 0x61, 0xb7, 0xb5, +0x09, 0x00, 0x87, 0xb0, 0x85, 0x61, 0x83, 0xd5, 0x04, 0x00, 0x53, 0x81, 0x05, 0x42, 0x53, 0x71, +0x01, 0x12, 0xd3, 0x01, 0x05, 0x42, 0x53, 0x82, 0x15, 0xd2, 0x53, 0x72, 0x12, 0x12, 0x43, 0xf0, +0x01, 0x22, 0xb7, 0xb5, 0x09, 0x00, 0x07, 0xa5, 0x85, 0x62, 0x87, 0x31, 0x04, 0x0a, 0x13, 0x05, +0xd5, 0x8c, 0x53, 0x74, 0x10, 0x40, 0xd3, 0x05, 0x85, 0xa0, 0x43, 0xf0, 0x11, 0x12, 0x8d, 0xe9, +0xb7, 0xb5, 0x09, 0x00, 0x07, 0xa5, 0xc5, 0x62, 0x53, 0x06, 0xa4, 0xa0, 0xb7, 0xb5, 0x09, 0x00, +0x0d, 0xe6, 0x37, 0xb6, 0x09, 0x00, 0x07, 0x25, 0x46, 0x63, 0x87, 0xa5, 0x05, 0x63, 0xb7, 0xb5, +0x09, 0x00, 0x07, 0xa6, 0x85, 0x63, 0x53, 0x75, 0xa4, 0x00, 0x43, 0x75, 0xc5, 0x58, 0x01, 0xa8, +0xb7, 0xb5, 0x09, 0x00, 0x07, 0xa5, 0xc5, 0x67, 0x19, 0xa0, 0x07, 0xa5, 0x05, 0x63, 0x83, 0x85, +0x04, 0x02, 0xd3, 0x74, 0x10, 0x40, 0xf5, 0x15, 0x8c, 0x91, 0x33, 0x09, 0xa4, 0x00, 0x8b, 0xc8, +0x05, 0x02, 0x53, 0x79, 0x95, 0x10, 0xef, 0x00, 0x70, 0x10, 0x0d, 0xc1, 0x28, 0x34, 0xef, 0x80, +0x16, 0xf1, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x05, 0x62, 0x53, 0x15, 0x05, 0xa2, 0x19, 0xc5, +0xef, 0x30, 0x5d, 0x8b, 0x07, 0x30, 0x05, 0x46, 0x53, 0x79, 0x10, 0x40, 0x37, 0xb5, 0x09, 0x00, +0x07, 0x25, 0xc5, 0x63, 0x03, 0x45, 0x09, 0x00, 0xd3, 0x15, 0xa9, 0xa0, 0x37, 0xb6, 0x09, 0x00, +0x07, 0x30, 0x86, 0x66, 0x13, 0x35, 0x65, 0x00, 0x6d, 0x8d, 0xd3, 0x00, 0x09, 0x42, 0xab, 0x60, +0xa0, 0x3a, 0x27, 0x38, 0x14, 0x04, 0x53, 0x00, 0x04, 0x42, 0x27, 0xbb, 0x04, 0x0a, 0x27, 0xb3, +0x14, 0x0a, 0x53, 0x80, 0x04, 0x42, 0x27, 0xb7, 0x04, 0x0a, 0xef, 0x40, 0xad, 0xd2, 0xaa, 0x84, +0x48, 0x71, 0x0c, 0x61, 0x30, 0x65, 0x53, 0x75, 0xa5, 0x10, 0x43, 0xf5, 0xb5, 0x50, 0x43, 0x75, +0xc6, 0x50, 0x53, 0x05, 0x05, 0x42, 0xef, 0xa0, 0x76, 0xac, 0x87, 0xa5, 0x84, 0x0d, 0x07, 0xa6, +0x44, 0x0b, 0x87, 0xa6, 0xc4, 0x0f, 0x08, 0xb4, 0x53, 0xf5, 0xb5, 0x10, 0x43, 0x75, 0xc6, 0x50, +0x43, 0xf5, 0xd6, 0x50, 0x53, 0x05, 0x05, 0x42, 0xef, 0xa0, 0x56, 0xaa, 0x08, 0xb0, 0x22, 0x29, +0xc2, 0x24, 0x62, 0x24, 0xa8, 0x99, 0x00, 0x00, 0xc0, 0x99, 0x2e, 0x86, 0x2a, 0x84, 0x05, 0x65, +0x07, 0x30, 0x84, 0x05, 0xb7, 0xb5, 0x09, 0x00, 0x87, 0xb0, 0x05, 0x64, 0xb3, 0x05, 0xa4, 0x00, +0x83, 0xc5, 0x85, 0xb1, 0x13, 0x05, 0x85, 0xb0, 0xd3, 0x96, 0x00, 0xa2, 0xb3, 0x04, 0xa4, 0x00, +0x81, 0xc6, 0x99, 0xc1, 0x81, 0x45, 0x82, 0x14, 0x32, 0x85, 0xef, 0x40, 0xad, 0xee, 0xcc, 0x44, +0x05, 0x49, 0x8b, 0x81, 0x05, 0x01, 0x2a, 0x89, 0x07, 0x30, 0x84, 0x05, 0x37, 0xb5, 0x09, 0x00, +0x87, 0x30, 0x85, 0x65, 0x53, 0x15, 0x10, 0xa2, 0x01, 0xcd, 0xef, 0x20, 0xad, 0x93, 0x8b, 0x14, +0x05, 0x01, 0xef, 0x40, 0x3d, 0xde, 0x05, 0x04, 0x01, 0x0a, 0xf5, 0x7d, 0xd7, 0x8b, 0x02, 0x05, +0x02, 0x05, 0x49, 0x23, 0x88, 0x24, 0x01, 0x22, 0x85, 0xef, 0x40, 0xad, 0xef, 0xaa, 0x85, 0x01, +0x45, 0x8b, 0x81, 0x05, 0x01, 0x4a, 0x85, 0x8c, 0x40, 0x0b, 0x96, 0x05, 0x01, 0x83, 0xc5, 0x24, +0x04, 0x0b, 0x84, 0x05, 0x02, 0xef, 0x40, 0x3d, 0x86, 0x8b, 0x12, 0x05, 0x01, 0x01, 0x45, 0x82, +0x14, 0xa0, 0x99, 0x01, 0x45, 0xa0, 0x99, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x99, 0x22, 0xac, 0x26, +0xa8, 0x4a, 0xa4, 0x32, 0x84, 0x08, 0x22, 0x2e, 0x89, 0xaa, 0x84, 0xef, 0x80, 0x66, 0x9d, 0x07, +0x30, 0x04, 0x00, 0x53, 0x04, 0xa5, 0x22, 0x53, 0x05, 0x00, 0x22, 0xef, 0x80, 0x86, 0x82, 0x07, +0x30, 0x84, 0x00, 0xd3, 0x04, 0xa5, 0x22, 0x53, 0x05, 0x00, 0x22, 0xef, 0x80, 0x66, 0x9b, 0x07, +0x30, 0x84, 0x00, 0x53, 0x09, 0xa5, 0x22, 0x53, 0x05, 0x00, 0x22, 0xef, 0x80, 0x86, 0x80, 0x07, +0xb0, 0x84, 0x00, 0x87, 0xb0, 0x04, 0x00, 0x53, 0x11, 0x84, 0x22, 0x87, 0xb1, 0x04, 0x01, 0x53, +0x70, 0x20, 0x12, 0xd3, 0x70, 0x19, 0x12, 0xc7, 0x70, 0x05, 0x0a, 0x53, 0xf1, 0x34, 0x12, 0xc3, +0x70, 0x25, 0x0a, 0x27, 0x30, 0x19, 0x00, 0x87, 0xb0, 0x04, 0x00, 0xd3, 0x70, 0x15, 0x12, 0x43, +0x70, 0x09, 0x0a, 0x43, 0x70, 0x29, 0x02, 0x27, 0x34, 0x09, 0x00, 0x07, 0xb0, 0x84, 0x00, 0x88, +0x4c, 0x53, 0xf0, 0x04, 0x12, 0x43, 0x70, 0x34, 0x02, 0x27, 0x38, 0x09, 0x00, 0x23, 0x2c, 0xa9, +0x00, 0x22, 0x29, 0xc2, 0x24, 0x62, 0x24, 0xa8, 0x99, 0x00, 0x00, 0xdc, 0x99, 0x59, 0x71, 0xa2, +0xad, 0xa6, 0xa9, 0x2a, 0x84, 0x07, 0x30, 0x05, 0x00, 0x87, 0x30, 0x85, 0x00, 0x07, 0x31, 0x05, +0x01, 0x53, 0x84, 0xb5, 0x22, 0xd3, 0x04, 0xa5, 0x22, 0xae, 0x84, 0x02, 0xb9, 0x06, 0xbd, 0x8a, +0xa1, 0x05, 0x49, 0xca, 0xc5, 0x08, 0x19, 0x8c, 0x18, 0xef, 0x40, 0xfb, 0xd4, 0x07, 0x30, 0x84, +0x02, 0x87, 0x30, 0x04, 0x03, 0x07, 0x31, 0x84, 0x03, 0x02, 0xa9, 0x06, 0xad, 0x0a, 0xb1, 0x4a, +0xd5, 0x28, 0x10, 0x0c, 0x09, 0x13, 0x06, 0x00, 0x02, 0xef, 0x60, 0x76, 0xfe, 0x28, 0x00, 0x8c, +0x18, 0x13, 0x06, 0x00, 0x02, 0xef, 0x60, 0xb6, 0xfd, 0x28, 0x10, 0x2c, 0x00, 0x90, 0x08, 0xb4, +0x00, 0xef, 0x40, 0x7b, 0xee, 0x46, 0x20, 0xe6, 0x20, 0x53, 0x70, 0x90, 0x12, 0x82, 0xa8, 0x53, +0xf0, 0x90, 0x12, 0x82, 0xac, 0x88, 0x08, 0x0c, 0x09, 0x90, 0x18, 0xc5, 0x35, 0x4a, 0x20, 0xea, +0x20, 0x0a, 0x31, 0x27, 0x34, 0x04, 0x02, 0x27, 0x38, 0x14, 0x02, 0x27, 0x3c, 0x24, 0x02, 0x07, +0x30, 0x04, 0x00, 0x87, 0xb0, 0x04, 0x00, 0x53, 0x70, 0x10, 0x0a, 0x87, 0x30, 0x84, 0x00, 0x07, +0xb1, 0x84, 0x00, 0x87, 0x31, 0x04, 0x01, 0x07, 0xb2, 0x04, 0x01, 0x02, 0xa9, 0x53, 0xf0, 0x20, +0x0a, 0x02, 0xad, 0x53, 0xf0, 0x41, 0x0a, 0x02, 0xb1, 0x4a, 0xd5, 0x28, 0x10, 0x0c, 0x09, 0x13, +0x06, 0x00, 0x02, 0xef, 0x60, 0xd6, 0xf6, 0x28, 0x00, 0x8c, 0x18, 0x13, 0x06, 0x00, 0x02, 0xef, +0x60, 0x16, 0xf6, 0x28, 0x10, 0x2c, 0x00, 0x90, 0x08, 0xb4, 0x00, 0xef, 0x40, 0xdb, 0xe6, 0x46, +0x20, 0xe6, 0x20, 0x53, 0x70, 0x80, 0x12, 0x82, 0xa8, 0x53, 0xf0, 0x80, 0x12, 0x82, 0xac, 0x88, +0x08, 0x0c, 0x09, 0x90, 0x18, 0x9d, 0x35, 0x07, 0xb0, 0x04, 0x00, 0xca, 0x20, 0x53, 0x70, 0x10, +0x02, 0x27, 0x30, 0x04, 0x00, 0x07, 0xb0, 0x84, 0x00, 0xea, 0x20, 0x53, 0x70, 0x10, 0x02, 0x27, +0x34, 0x04, 0x00, 0x07, 0xb0, 0x04, 0x01, 0x8a, 0x30, 0x53, 0x70, 0x10, 0x02, 0x27, 0x38, 0x04, +0x00, 0xce, 0x24, 0x6e, 0x24, 0x65, 0x61, 0xbc, 0x99, 0x00, 0x00, 0x40, 0x9b, 0x2e, 0x8a, 0xaa, +0x84, 0x05, 0x64, 0x13, 0x05, 0x04, 0xb1, 0xb3, 0x89, 0xa4, 0x00, 0xef, 0x20, 0x4c, 0xf2, 0x83, +0x2a, 0x85, 0x0e, 0xef, 0x30, 0x8d, 0xd9, 0xaa, 0x85, 0x26, 0x85, 0x95, 0x3b, 0xb3, 0x85, 0x84, +0x00, 0x83, 0xa5, 0x85, 0xb3, 0x25, 0x46, 0xb3, 0x35, 0xb6, 0x00, 0x33, 0x35, 0xa0, 0x00, 0x6d, +0x8d, 0x15, 0xe1, 0x13, 0x05, 0x84, 0xb7, 0x26, 0x95, 0xb7, 0xb5, 0x09, 0x00, 0x07, 0xb5, 0x05, +0x65, 0xd2, 0x85, 0xef, 0x40, 0x4d, 0xfd, 0x23, 0xa0, 0x09, 0x00, 0x37, 0x55, 0x04, 0x20, 0x23, +0x2e, 0x05, 0x72, 0x20, 0x9b, 0x13, 0x05, 0x84, 0xb7, 0x33, 0x89, 0xa4, 0x00, 0x63, 0x8a, 0x0a, +0x00, 0x53, 0x05, 0x00, 0xd2, 0x52, 0x85, 0xca, 0x85, 0xef, 0x40, 0xed, 0xfa, 0x05, 0x45, 0x2d, +0xa0, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x35, 0x85, 0x5c, 0x37, 0xb5, 0x09, 0x00, 0x87, 0x35, 0x85, +0x64, 0x52, 0x85, 0xca, 0x85, 0x99, 0x35, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x35, 0x05, 0x65, 0x4a, +0x85, 0xd2, 0x85, 0xef, 0x40, 0x4d, 0xf8, 0x01, 0x45, 0x23, 0xa0, 0xa9, 0x00, 0xb7, 0x55, 0x04, +0x20, 0x23, 0xae, 0xa5, 0x72, 0x52, 0x85, 0xa6, 0x85, 0x00, 0x9b, 0x6f, 0xf0, 0x1c, 0x92, 0x00, +0x00, 0x00, 0x00, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x05, 0x65, 0x53, 0x95, 0x05, 0xa2, 0x11, +0xc5, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x85, 0x65, 0xb9, 0xa8, 0x53, 0x15, 0x05, 0xa2, 0x01, +0xc9, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x85, 0x5c, 0x53, 0x70, 0x05, 0x02, 0xa9, 0xa0, 0x37, +0xb5, 0x09, 0x00, 0x07, 0x30, 0x05, 0x66, 0x53, 0x15, 0x05, 0xa2, 0x01, 0xcd, 0x37, 0xb5, 0x09, +0x00, 0x07, 0x30, 0x85, 0x5c, 0x37, 0xb5, 0x09, 0x00, 0x87, 0x30, 0x85, 0x5e, 0x43, 0x70, 0x15, +0x02, 0x1d, 0xa0, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x85, 0x66, 0x53, 0x15, 0x05, 0xa2, 0x01, +0xc9, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x30, 0x85, 0x5c, 0x53, 0x70, 0x05, 0x12, 0x29, 0xa0, 0x37, +0xb5, 0x09, 0x00, 0x07, 0x30, 0x05, 0x67, 0x53, 0x75, 0xc0, 0x12, 0x82, 0x80, 0x00, 0x00, 0xc0, +0x9b, 0x37, 0xbb, 0x09, 0x00, 0x93, 0x04, 0x4b, 0x6d, 0xdc, 0x40, 0xba, 0x89, 0x36, 0x89, 0x32, +0x8a, 0x2e, 0x84, 0xaa, 0x8a, 0x05, 0x65, 0x93, 0x05, 0x05, 0xa0, 0x3e, 0x85, 0x01, 0x46, 0xae, +0x86, 0xef, 0x30, 0xb7, 0x96, 0x03, 0x25, 0x4b, 0x6d, 0x93, 0x05, 0x80, 0x2d, 0x93, 0x06, 0x80, +0x2d, 0x01, 0x46, 0xef, 0x30, 0x97, 0x95, 0x22, 0x85, 0xef, 0xb0, 0xbd, 0xe1, 0x83, 0x26, 0x4b, +0x6d, 0xd8, 0x40, 0x05, 0x45, 0xd6, 0x85, 0x22, 0x86, 0xef, 0x90, 0x2d, 0xd5, 0x05, 0xc5, 0x03, +0x25, 0x4b, 0x6d, 0x93, 0x95, 0x29, 0x00, 0x13, 0x06, 0x05, 0x1e, 0x93, 0x06, 0x40, 0x0c, 0x52, +0x85, 0xef, 0x30, 0x27, 0xb1, 0xd0, 0x40, 0x22, 0x85, 0xd2, 0x85, 0xca, 0x86, 0xef, 0x80, 0xbd, +0xdd, 0x33, 0x35, 0xa0, 0x00, 0xa0, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x2f, 0x05, 0x01, 0x81, +0x48, 0x33, 0x28, 0xb0, 0x00, 0x13, 0x13, 0x25, 0x00, 0x93, 0x92, 0x25, 0x00, 0x63, 0x01, 0x08, +0x02, 0xb2, 0x83, 0x36, 0x8e, 0xba, 0x8e, 0xae, 0x87, 0x5b, 0xa5, 0x43, 0xa0, 0xdb, 0x25, 0x4e, +0xa0, 0x53, 0x75, 0xb5, 0x10, 0x27, 0xa0, 0xae, 0x00, 0xfd, 0x17, 0x9a, 0x9e, 0xf5, 0xf7, 0x85, +0x08, 0x11, 0x07, 0x16, 0x96, 0xe3, 0x9c, 0xa8, 0xfc, 0x82, 0x80, 0x7e, 0x95, 0x05, 0x04, 0x01, +0x0b, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x48, 0x9e, 0x22, 0xb0, 0x26, 0xac, 0x80, 0x10, 0x83, 0x2a, +0x44, 0x00, 0x83, 0x2d, 0x04, 0x00, 0x2a, 0x89, 0x37, 0xb5, 0x09, 0x00, 0x63, 0xd5, 0xba, 0x01, +0x07, 0x24, 0x85, 0x67, 0xa1, 0xaa, 0xc6, 0x89, 0xbe, 0x84, 0x36, 0x8c, 0x2e, 0x8b, 0x23, 0x24, +0xe4, 0xfa, 0x23, 0x26, 0x04, 0xfb, 0x23, 0x28, 0xc4, 0xfa, 0x23, 0x2a, 0x24, 0xfa, 0x3d, 0x45, +0xab, 0x05, 0x55, 0x05, 0xc1, 0x99, 0x33, 0x0a, 0xb1, 0x40, 0x52, 0x81, 0xb3, 0x85, 0xba, 0x03, +0xab, 0x05, 0xb5, 0x04, 0xc1, 0x99, 0x33, 0x0d, 0xb1, 0x40, 0x6a, 0x81, 0xb3, 0x0c, 0xb1, 0x40, +0x66, 0x81, 0xab, 0x05, 0xb5, 0x05, 0xc1, 0x99, 0xb3, 0x05, 0xb1, 0x40, 0x23, 0x22, 0xb4, 0xfa, +0x2e, 0x81, 0xb3, 0x85, 0xbd, 0x03, 0x2b, 0x05, 0xb5, 0x04, 0x41, 0x99, 0xb3, 0x0b, 0xa1, 0x40, +0x5e, 0x81, 0x93, 0x95, 0x2a, 0x00, 0x52, 0x85, 0x01, 0x46, 0xae, 0x86, 0xef, 0x30, 0x77, 0x84, +0x6a, 0x85, 0xe2, 0x85, 0x56, 0x86, 0xee, 0x86, 0x5a, 0x87, 0xef, 0xe0, 0xcd, 0x95, 0x0b, 0xa9, +0x0a, 0x01, 0x13, 0x05, 0xf9, 0xff, 0x13, 0x35, 0x15, 0x00, 0xd6, 0x85, 0x52, 0x86, 0x5b, 0xa5, +0x44, 0xa0, 0xd3, 0x75, 0xa5, 0x10, 0xab, 0x65, 0xa5, 0x38, 0xfd, 0x15, 0x5b, 0x22, 0xb6, 0xe0, +0xfd, 0xf5, 0x6e, 0x85, 0xd6, 0x85, 0x6a, 0x86, 0xd2, 0x86, 0x66, 0x87, 0xdd, 0x3d, 0x37, 0xb5, +0x09, 0x00, 0x87, 0x24, 0xc5, 0x67, 0xd3, 0x05, 0x00, 0xf0, 0x53, 0x04, 0x00, 0xf0, 0x01, 0x45, +0xee, 0x85, 0x6e, 0x86, 0xd6, 0x86, 0x53, 0x85, 0x94, 0x20, 0x66, 0x87, 0xea, 0x87, 0x5e, 0x88, +0xef, 0xe0, 0xed, 0x8a, 0x5e, 0x85, 0xee, 0x85, 0xef, 0xe0, 0xad, 0xca, 0x11, 0xc5, 0x37, 0xb5, +0x09, 0x00, 0x07, 0x24, 0x85, 0x67, 0xb1, 0xa8, 0x8b, 0xa7, 0x0d, 0x01, 0x11, 0x45, 0x2b, 0x05, +0xb5, 0x05, 0x53, 0x04, 0x00, 0xf0, 0xde, 0x85, 0x6e, 0x86, 0x88, 0x61, 0x53, 0x74, 0xa4, 0x00, +0x7d, 0x16, 0xaa, 0x95, 0x7d, 0xfa, 0x05, 0x46, 0xd3, 0x05, 0x00, 0xf0, 0x01, 0x45, 0xee, 0x85, +0xd6, 0x86, 0x53, 0x85, 0x94, 0x20, 0x66, 0x87, 0x83, 0x27, 0x84, 0xfa, 0x83, 0x24, 0x44, 0xfa, +0x26, 0x88, 0xef, 0xe0, 0xcd, 0x85, 0x05, 0x46, 0xd3, 0x05, 0x00, 0xf0, 0x01, 0x45, 0xee, 0x85, +0xee, 0x86, 0x53, 0x85, 0x94, 0x20, 0x5e, 0x87, 0xa6, 0x87, 0x03, 0x28, 0xc4, 0xfa, 0xef, 0xe0, +0x0d, 0x84, 0x83, 0x24, 0x44, 0xfb, 0x63, 0x8a, 0x09, 0x00, 0x5e, 0x85, 0xce, 0x85, 0x6e, 0x86, +0xee, 0x86, 0x03, 0x27, 0x04, 0xfb, 0xef, 0xe0, 0x8d, 0x8b, 0x26, 0x81, 0x53, 0x05, 0x84, 0x20, +0x13, 0x01, 0x04, 0xfa, 0xe2, 0x24, 0x02, 0x34, 0x28, 0x9e, 0xc0, 0x98, 0x2a, 0x84, 0xef, 0x20, +0x8c, 0xbb, 0x81, 0x45, 0x37, 0xb6, 0x09, 0x00, 0x13, 0x06, 0xc6, 0x6d, 0xb3, 0x86, 0xc5, 0x00, +0x83, 0xc6, 0x06, 0x00, 0x63, 0x86, 0x86, 0x00, 0xa1, 0x05, 0x8b, 0x9c, 0xf5, 0x28, 0x01, 0xa8, +0x08, 0x41, 0xb2, 0x95, 0xcc, 0x41, 0xe9, 0x8d, 0x05, 0x45, 0x91, 0xc1, 0xa0, 0x98, 0x01, 0x45, +0xa0, 0x98, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x99, 0x2e, 0x84, 0xaa, 0x84, 0xef, 0xc0, 0x2b, 0x87, +0x15, 0xc5, 0xef, 0x40, 0x0e, 0xae, 0x37, 0xb5, 0x09, 0x00, 0x87, 0x25, 0x05, 0x68, 0x53, 0x85, +0xa5, 0xa0, 0x05, 0x49, 0x09, 0xed, 0xe0, 0x91, 0x26, 0x85, 0xef, 0x70, 0x9e, 0x9e, 0x37, 0xb5, +0x09, 0x00, 0x07, 0x30, 0x85, 0x68, 0x53, 0x15, 0x05, 0xa2, 0x11, 0xc1, 0x01, 0x49, 0x4a, 0x85, +0xa0, 0x99, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x9b, 0x0b, 0xc9, 0x15, 0xe4, 0xae, 0x89, 0x2a, 0x89, +0x01, 0x45, 0xa5, 0x3f, 0x21, 0xcd, 0x31, 0x4a, 0x05, 0x44, 0x13, 0x0b, 0x40, 0x0e, 0xa0, 0x90, +0x26, 0x85, 0xef, 0x90, 0xdc, 0xb2, 0xaa, 0x8a, 0x01, 0x45, 0xa6, 0x85, 0x69, 0x3f, 0x0b, 0x16, +0x05, 0x01, 0x33, 0x05, 0x49, 0x01, 0xb3, 0x85, 0x49, 0x41, 0x93, 0x06, 0x80, 0x0d, 0x56, 0x86, +0xef, 0x30, 0xa7, 0x87, 0x5a, 0x8a, 0x13, 0x35, 0x04, 0x02, 0x05, 0x04, 0x13, 0x0b, 0x8a, 0x0d, +0xb3, 0xb5, 0x69, 0x01, 0xe4, 0x9d, 0x6d, 0x8d, 0x79, 0xf1, 0x93, 0x05, 0x4a, 0xff, 0x0d, 0x45, +0x05, 0x46, 0xca, 0x86, 0x4e, 0x87, 0xef, 0x00, 0x9e, 0x95, 0x11, 0xa0, 0x01, 0x4a, 0x52, 0x85, +0xa0, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9b, 0x8b, 0xc8, 0x15, 0xe4, 0xae, 0x89, 0x2a, 0x89, +0x0d, 0x45, 0x21, 0x37, 0x39, 0xc9, 0x31, 0x4a, 0x85, 0x44, 0x13, 0x04, 0x40, 0x0e, 0x64, 0x91, +0xef, 0xc0, 0x7a, 0xe3, 0xaa, 0x8a, 0xa4, 0x91, 0x0d, 0x45, 0x35, 0x37, 0x0b, 0x16, 0x05, 0x01, +0x33, 0x05, 0x49, 0x01, 0xb3, 0x85, 0x49, 0x41, 0x93, 0x06, 0x80, 0x0d, 0x56, 0x86, 0xef, 0x30, +0xc7, 0x80, 0x22, 0x8a, 0x13, 0xb5, 0x24, 0x03, 0x85, 0x04, 0x13, 0x04, 0x8a, 0x0d, 0xb3, 0xb5, +0x89, 0x00, 0xe4, 0x9d, 0x6d, 0x8d, 0x61, 0xf5, 0x93, 0x05, 0x4a, 0xff, 0x1d, 0x45, 0x05, 0x46, +0xca, 0x86, 0x4e, 0x87, 0xef, 0x00, 0xbe, 0x8e, 0x11, 0xa0, 0x01, 0x4a, 0x52, 0x85, 0x20, 0x9b, +0x00, 0x00, 0xc0, 0x9b, 0x0b, 0xc9, 0x15, 0xd4, 0xae, 0x89, 0x2a, 0x89, 0x19, 0x45, 0x71, 0x3d, +0x21, 0xcd, 0x31, 0x4a, 0x05, 0x44, 0x13, 0x0b, 0x40, 0x0d, 0xa0, 0x90, 0x26, 0x85, 0xef, 0xd0, +0x9b, 0xa5, 0xaa, 0x8a, 0x19, 0x45, 0xa6, 0x85, 0x7d, 0x3d, 0x0b, 0x16, 0x05, 0x01, 0x33, 0x05, +0x49, 0x01, 0xb3, 0x85, 0x49, 0x41, 0x93, 0x06, 0x80, 0x0c, 0x56, 0x86, 0xef, 0x20, 0xf7, 0xf9, +0x5a, 0x8a, 0x13, 0x35, 0x44, 0x02, 0x05, 0x04, 0x13, 0x0b, 0x8a, 0x0c, 0xb3, 0xb5, 0x69, 0x01, +0xe4, 0x9d, 0x6d, 0x8d, 0x79, 0xf1, 0x93, 0x05, 0x4a, 0xff, 0x39, 0x45, 0x05, 0x46, 0xca, 0x86, +0x4e, 0x87, 0xef, 0x00, 0xde, 0x87, 0x11, 0xa0, 0x01, 0x4a, 0x52, 0x85, 0xa0, 0x9b, 0x00, 0x00, +0x00, 0x00, 0xc0, 0x9b, 0x0b, 0xca, 0x15, 0xbc, 0xae, 0x89, 0x2a, 0x89, 0x05, 0x45, 0x05, 0x44, +0x2d, 0x35, 0x29, 0xcd, 0x31, 0x4a, 0x13, 0x0b, 0xc0, 0x0b, 0xa0, 0x90, 0x26, 0x85, 0xef, 0xf0, +0x0b, 0xdb, 0xaa, 0x8a, 0x05, 0x45, 0xa6, 0x85, 0xb9, 0x35, 0x0b, 0x17, 0x05, 0x01, 0x23, 0x96, +0x8a, 0x0a, 0x33, 0x05, 0x49, 0x01, 0xb3, 0x85, 0x49, 0x41, 0x93, 0x06, 0x00, 0x0b, 0x56, 0x86, +0xef, 0x20, 0xb7, 0xf2, 0x5a, 0x8a, 0x13, 0x35, 0x84, 0x01, 0x05, 0x04, 0x13, 0x0b, 0x0a, 0x0b, +0xb3, 0xb5, 0x69, 0x01, 0xe4, 0x9d, 0x6d, 0x8d, 0x69, 0xf1, 0x93, 0x05, 0x4a, 0xff, 0x55, 0x45, +0x05, 0x46, 0xca, 0x86, 0x4e, 0x87, 0xef, 0x00, 0x9e, 0x80, 0x11, 0xa0, 0x01, 0x4a, 0x52, 0x85, +0xa0, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x37, 0xc5, 0x04, 0x20, 0x13, 0x05, 0x85, 0xf6, 0x83, 0x25, +0x05, 0x16, 0x07, 0x30, 0x85, 0x12, 0x37, 0xb5, 0x09, 0x00, 0x87, 0x30, 0x85, 0x5c, 0x37, 0xb5, +0x09, 0x00, 0x07, 0x31, 0x05, 0x69, 0x33, 0x35, 0xb0, 0x00, 0xd3, 0x85, 0x00, 0xa2, 0x6d, 0x8d, +0xd3, 0x05, 0x20, 0xa2, 0x6d, 0x8d, 0x82, 0x80, 0x00, 0x00, 0x37, 0xb5, 0x09, 0x00, 0x03, 0x45, +0x25, 0x71, 0x3a, 0x36, 0x05, 0x04, 0x01, 0x0c, 0xf3, 0x82, 0x80, 0x00, 0x00, 0xc0, 0x98, 0xef, +0x20, 0xec, 0xc2, 0x01, 0xe5, 0x05, 0x44, 0x5d, 0x3f, 0x11, 0xe1, 0x01, 0x44, 0x37, 0xb5, 0x09, +0x00, 0x23, 0x09, 0x85, 0x70, 0xa0, 0x98, 0x00, 0x00, 0x40, 0x98, 0x37, 0xb5, 0x09, 0x00, 0x03, +0x45, 0x25, 0x71, 0x0d, 0xc1, 0xef, 0xe0, 0x1e, 0xf9, 0x85, 0x45, 0xa3, 0x00, 0xb5, 0x00, 0xef, +0x20, 0xae, 0x90, 0xaa, 0x85, 0x35, 0x45, 0x0b, 0x84, 0x05, 0x01, 0xef, 0xe0, 0xbe, 0xf7, 0x8d, +0x45, 0x23, 0x11, 0xb5, 0x00, 0x05, 0x45, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x9d, 0x13, +0x01, 0x01, 0xdd, 0x27, 0x3c, 0x81, 0x28, 0x36, 0x84, 0xb2, 0x89, 0x2e, 0x89, 0x28, 0x00, 0x93, +0x05, 0x00, 0x29, 0x7d, 0x56, 0x93, 0x06, 0x00, 0x29, 0x13, 0x0a, 0x81, 0x00, 0xef, 0x30, 0xc7, +0xc5, 0x28, 0x00, 0x93, 0x05, 0x40, 0x0a, 0xef, 0x50, 0x7e, 0xd5, 0x37, 0x15, 0x09, 0x00, 0x13, +0x05, 0x05, 0x98, 0xab, 0x05, 0x84, 0x04, 0x33, 0x86, 0xa5, 0x00, 0x83, 0x0a, 0x06, 0x00, 0x13, +0xa6, 0x1a, 0x00, 0x93, 0xb6, 0x19, 0x00, 0x01, 0x4b, 0x55, 0x8e, 0x51, 0xea, 0x2e, 0x95, 0x93, +0x0b, 0x15, 0x00, 0x37, 0xb5, 0x09, 0x00, 0x07, 0x34, 0x85, 0x69, 0x05, 0x4c, 0x37, 0x15, 0x09, +0x00, 0x93, 0x0c, 0x45, 0x9a, 0x81, 0x44, 0x33, 0x85, 0x9b, 0x00, 0x03, 0x44, 0x05, 0x00, 0x13, +0x1d, 0x0c, 0x01, 0x13, 0x5d, 0x0d, 0x41, 0x0b, 0x5f, 0x04, 0x1b, 0x22, 0x85, 0xea, 0x85, 0xef, +0x80, 0x6e, 0xdf, 0x0d, 0xc5, 0xab, 0x85, 0x8c, 0x04, 0x03, 0x94, 0x25, 0x00, 0x63, 0x40, 0x04, +0x02, 0xab, 0x05, 0xaa, 0x04, 0x8c, 0x41, 0x8b, 0x85, 0x05, 0xff, 0xef, 0x70, 0x2e, 0xe7, 0x19, +0xc5, 0x28, 0x69, 0x53, 0x00, 0x05, 0x42, 0x53, 0x05, 0x80, 0xa2, 0x19, 0xcd, 0x85, 0x04, 0x0b, +0x9e, 0xe4, 0x04, 0x33, 0x25, 0x5d, 0x01, 0x93, 0x15, 0x0b, 0x01, 0xc1, 0x81, 0xb3, 0xb5, 0x35, +0x01, 0x6d, 0x8d, 0x05, 0x0c, 0x45, 0xf1, 0x21, 0xa8, 0x33, 0x05, 0x84, 0x01, 0x93, 0x15, 0x0b, +0x01, 0xc1, 0x81, 0x05, 0x0b, 0xab, 0x05, 0xb9, 0x02, 0x23, 0x90, 0xa5, 0x00, 0xd9, 0xbf, 0x13, +0x15, 0x0b, 0x01, 0x41, 0x81, 0x07, 0x34, 0x81, 0x29, 0x13, 0x01, 0x01, 0x23, 0xbc, 0x9d, 0x00, +0x00, 0x5c, 0x9e, 0x13, 0x01, 0x01, 0xdc, 0x27, 0x38, 0x81, 0x2a, 0x27, 0x34, 0x91, 0x2a, 0x27, +0x30, 0x21, 0x2b, 0x2a, 0xc6, 0x63, 0x0d, 0x05, 0x14, 0x2e, 0x84, 0x01, 0x45, 0x93, 0x09, 0x01, +0x01, 0xfd, 0x55, 0x13, 0x06, 0x00, 0x29, 0xb3, 0x86, 0xa9, 0x00, 0x11, 0x05, 0x8c, 0xc2, 0xe3, +0x1c, 0xc5, 0xfe, 0x08, 0x08, 0x93, 0x05, 0x40, 0x0a, 0xef, 0x50, 0x5e, 0xc5, 0x13, 0x7a, 0xf4, +0x0f, 0x63, 0x07, 0x0a, 0x12, 0x01, 0x45, 0x81, 0x4a, 0xb7, 0xb5, 0x09, 0x00, 0x07, 0xb4, 0x85, +0x69, 0xb7, 0xb5, 0x09, 0x00, 0x87, 0xb4, 0x05, 0x6a, 0xb7, 0x15, 0x09, 0x00, 0x13, 0x8b, 0x45, +0x9a, 0x53, 0x09, 0x00, 0xd2, 0xab, 0x05, 0xab, 0x04, 0x83, 0x9b, 0x05, 0x00, 0x0b, 0xae, 0x3b, +0x01, 0x32, 0x46, 0x2b, 0x0c, 0xa6, 0x10, 0x93, 0x8c, 0x25, 0x00, 0x85, 0x44, 0x13, 0xf5, 0xfa, +0x0f, 0xe4, 0x91, 0xef, 0x80, 0x2e, 0xd0, 0x2a, 0x84, 0x7d, 0x15, 0x28, 0x91, 0x8b, 0x53, 0x35, +0xa3, 0x22, 0x85, 0xef, 0x70, 0xae, 0xd8, 0x83, 0x4d, 0x0c, 0x00, 0x0b, 0xd0, 0x3d, 0x24, 0x83, +0x95, 0x0c, 0x00, 0x63, 0xcc, 0x05, 0x0a, 0x2a, 0x8d, 0x1d, 0xc1, 0x07, 0x25, 0x0d, 0x05, 0x53, +0x00, 0x05, 0x42, 0x53, 0x05, 0x80, 0xa2, 0x55, 0xe1, 0x2b, 0x85, 0x89, 0x04, 0x08, 0x41, 0xa6, +0x95, 0x2b, 0x06, 0xbc, 0x03, 0x23, 0x12, 0xb6, 0x00, 0x8b, 0x16, 0x05, 0xff, 0x15, 0xa8, 0x2b, +0x85, 0x89, 0x04, 0x08, 0x41, 0x8b, 0x01, 0x25, 0xff, 0xa6, 0x95, 0x2b, 0x06, 0xbc, 0x03, 0x23, +0x12, 0xb6, 0x00, 0x13, 0x34, 0x1d, 0x00, 0x33, 0x09, 0xbc, 0x01, 0x23, 0x0e, 0x09, 0x0c, 0xef, +0x50, 0x3e, 0xc5, 0x93, 0x05, 0x15, 0x00, 0xab, 0x65, 0xa0, 0x20, 0x23, 0x0e, 0xb9, 0x0c, 0x0d, +0xec, 0x07, 0x25, 0x0d, 0x05, 0x53, 0x00, 0x05, 0x42, 0x53, 0x15, 0x04, 0xa2, 0x53, 0x70, 0x90, +0x12, 0xd3, 0x00, 0x29, 0x23, 0xab, 0x60, 0xa0, 0x3a, 0xd3, 0x95, 0x00, 0xc2, 0x2b, 0x06, 0xbc, +0x03, 0x23, 0x16, 0xb6, 0x04, 0x53, 0x00, 0x29, 0x23, 0x11, 0xcd, 0x07, 0x25, 0x4d, 0x05, 0x53, +0x00, 0x05, 0x42, 0x53, 0x70, 0x90, 0x12, 0x39, 0xa0, 0x2b, 0x05, 0xbc, 0x03, 0x23, 0x16, 0x05, +0x04, 0x53, 0x00, 0x29, 0x23, 0x53, 0x15, 0x00, 0xc2, 0xab, 0x05, 0xbc, 0x03, 0x23, 0x9a, 0xa5, +0x08, 0x03, 0x05, 0x0c, 0x00, 0x05, 0x05, 0x23, 0x00, 0xac, 0x00, 0x13, 0x85, 0x14, 0x00, 0xe8, +0x90, 0xe3, 0xde, 0x9b, 0xf0, 0x85, 0x0a, 0x13, 0xf5, 0xfa, 0x0f, 0xe3, 0x6d, 0x45, 0xef, 0x07, +0x39, 0x01, 0x2a, 0x87, 0x34, 0x81, 0x2a, 0x07, 0x34, 0x01, 0x2b, 0x13, 0x01, 0x01, 0x24, 0x3c, +0x9e, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x99, 0x2e, 0x89, 0xaa, 0x84, 0x93, 0x06, 0xc5, 0x10, 0x37, +0xb5, 0x09, 0x00, 0x13, 0x06, 0x85, 0x6a, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0xef, 0x00, 0x07, +0xba, 0x63, 0x45, 0x05, 0x06, 0x13, 0x84, 0x04, 0x0d, 0x22, 0x85, 0xef, 0x60, 0x36, 0xb8, 0xaa, +0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x22, 0x86, 0xef, 0x70, 0x97, 0x9e, 0x39, 0xe5, 0x93, +0x84, 0x04, 0x0f, 0x26, 0x85, 0xef, 0x60, 0x96, 0xb6, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, +0x85, 0x26, 0x86, 0xef, 0x70, 0xf7, 0x9c, 0x15, 0xe9, 0x26, 0x85, 0xef, 0x60, 0x36, 0xb5, 0x8b, +0x13, 0x05, 0x01, 0x37, 0xb5, 0x09, 0x00, 0x13, 0x04, 0xf5, 0x6a, 0x29, 0xa0, 0x37, 0xb5, 0x09, +0x00, 0x13, 0x04, 0x15, 0x6b, 0x22, 0x85, 0xef, 0x60, 0x76, 0xb3, 0xaa, 0x86, 0x93, 0x05, 0x00, +0x08, 0x4a, 0x85, 0x22, 0x86, 0xef, 0x70, 0xd7, 0x99, 0x11, 0xc1, 0xa0, 0x99, 0x4a, 0x85, 0xef, +0x60, 0xf6, 0xb1, 0xaa, 0x85, 0x13, 0x06, 0x00, 0x08, 0x4a, 0x85, 0xef, 0x60, 0x2e, 0x89, 0x4a, +0x85, 0xef, 0x60, 0xd6, 0xb0, 0x13, 0x06, 0x00, 0x08, 0xaa, 0x85, 0x4a, 0x85, 0x80, 0x99, 0x6f, +0x60, 0x6e, 0x90, 0x00, 0x00, 0x40, 0x9a, 0x32, 0x89, 0xae, 0x89, 0x01, 0x45, 0x01, 0x44, 0x93, +0x85, 0xa5, 0x1b, 0x33, 0x86, 0xa5, 0x00, 0x03, 0x16, 0x06, 0x00, 0x63, 0x43, 0xc0, 0x00, 0x01, +0x46, 0x30, 0x92, 0x09, 0x05, 0x32, 0x94, 0x0b, 0x1b, 0xf5, 0x0c, 0x93, 0x86, 0xc9, 0x10, 0x37, +0xb5, 0x09, 0x00, 0x13, 0x06, 0x85, 0x6b, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0xef, 0x00, 0x07, +0xad, 0x63, 0x47, 0x05, 0x0a, 0x93, 0x84, 0x09, 0x0d, 0x26, 0x85, 0xef, 0x60, 0x36, 0xab, 0xaa, +0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x26, 0x86, 0xef, 0x70, 0x97, 0x91, 0x49, 0xe9, 0x93, +0x84, 0x09, 0x03, 0x26, 0x85, 0xef, 0x60, 0x96, 0xa9, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, +0x85, 0x26, 0x86, 0xef, 0x70, 0xf7, 0x8f, 0x25, 0xed, 0x93, 0x84, 0x09, 0x10, 0x26, 0x85, 0xef, +0x60, 0xf6, 0xa7, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x85, 0x27, 0x05, 0x04, 0x01, 0x0d, 0xf2, +0x4a, 0x85, 0x26, 0x86, 0xef, 0x70, 0x57, 0x8e, 0x39, 0xed, 0x93, 0x06, 0x00, 0x08, 0x22, 0x85, +0x81, 0x45, 0x4a, 0x86, 0xef, 0x50, 0xde, 0xf1, 0x4e, 0x85, 0xef, 0x60, 0xb6, 0xa5, 0xaa, 0x86, +0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x4e, 0x86, 0xef, 0x70, 0x17, 0x8c, 0x0d, 0xed, 0x13, 0x84, +0x09, 0x05, 0x22, 0x85, 0xef, 0x60, 0x16, 0xa4, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, +0x22, 0x86, 0xef, 0x70, 0x77, 0x8a, 0x05, 0xe1, 0x37, 0xb5, 0x09, 0x00, 0x13, 0x04, 0xf5, 0x6b, +0x22, 0x85, 0xef, 0x60, 0x36, 0xa2, 0xaa, 0x86, 0x93, 0x05, 0x00, 0x08, 0x4a, 0x85, 0x22, 0x86, +0xef, 0x70, 0x97, 0x88, 0x11, 0xc1, 0x20, 0x9a, 0x4a, 0x85, 0xef, 0x60, 0xb6, 0xa0, 0xaa, 0x85, +0x13, 0x06, 0x00, 0x08, 0x4a, 0x85, 0xef, 0x50, 0xfe, 0xf7, 0x4a, 0x85, 0xef, 0x60, 0x96, 0x9f, +0x13, 0x06, 0x00, 0x08, 0xaa, 0x85, 0x4a, 0x85, 0x00, 0x9a, 0x6f, 0x50, 0x3e, 0xff, 0x00, 0x00, +0x40, 0x98, 0xef, 0x10, 0xae, 0xec, 0xb7, 0xc5, 0x04, 0x20, 0x03, 0xa6, 0x85, 0x0c, 0x81, 0x45, +0x01, 0xe6, 0x85, 0x45, 0x0b, 0x52, 0x05, 0x05, 0x2e, 0x85, 0x20, 0x98, 0xef, 0xb0, 0x5b, 0xb0, +0x13, 0x25, 0x55, 0x00, 0x8d, 0x45, 0x33, 0x85, 0xa5, 0x40, 0x20, 0x98, 0x00, 0x00, 0x00, 0x00, +0xc0, 0x99, 0x2a, 0x84, 0xf1, 0x37, 0xaa, 0x84, 0xef, 0xb0, 0x9b, 0xae, 0x2a, 0x89, 0x84, 0x92, +0x37, 0xb5, 0x09, 0x00, 0x93, 0x04, 0xe5, 0x59, 0x91, 0x45, 0x22, 0x85, 0x26, 0x86, 0xef, 0x00, +0x67, 0x9a, 0x63, 0x4a, 0x05, 0x00, 0x13, 0x05, 0x44, 0x00, 0xc1, 0x45, 0x26, 0x86, 0xca, 0x86, +0x80, 0x99, 0x6f, 0x00, 0x27, 0x99, 0xa0, 0x99, 0xdc, 0x99, 0x7d, 0x71, 0x2e, 0x89, 0xaa, 0x84, +0x08, 0x10, 0x93, 0x05, 0x00, 0x06, 0x93, 0x06, 0x00, 0x06, 0x01, 0x46, 0xef, 0x20, 0x57, 0xfc, +0x28, 0x00, 0xd1, 0x45, 0xd1, 0x46, 0x01, 0x46, 0xef, 0x20, 0x97, 0xfb, 0x37, 0x05, 0x05, 0x20, +0x13, 0x04, 0x85, 0xc3, 0x22, 0x85, 0xef, 0x60, 0x2e, 0xaf, 0x08, 0x10, 0xa2, 0x85, 0xef, 0x60, +0x2e, 0xab, 0x28, 0x00, 0x71, 0x37, 0x37, 0xb5, 0x09, 0x00, 0x13, 0x06, 0x25, 0x6c, 0x26, 0x85, +0xca, 0x85, 0xef, 0x70, 0xa7, 0xbc, 0x3d, 0xe9, 0x10, 0x10, 0x26, 0x85, 0xca, 0x85, 0xef, 0x70, +0xe7, 0xbb, 0x2d, 0xe5, 0x10, 0x18, 0x26, 0x85, 0xca, 0x85, 0xef, 0x70, 0x27, 0xbb, 0x39, 0xed, +0x90, 0x00, 0x26, 0x85, 0xca, 0x85, 0xef, 0x70, 0x67, 0xba, 0x29, 0xe9, 0x90, 0x08, 0x26, 0x85, +0xca, 0x85, 0xef, 0x70, 0xa7, 0xb9, 0x39, 0xe1, 0x30, 0x00, 0x26, 0x85, 0xca, 0x85, 0xef, 0x70, +0xe7, 0xb8, 0x0d, 0xed, 0x90, 0x10, 0x26, 0x85, 0xca, 0x85, 0xef, 0x70, 0x27, 0xb8, 0x1d, 0xe5, +0x70, 0x00, 0x26, 0x85, 0xca, 0x85, 0xef, 0x70, 0x67, 0xb7, 0x0d, 0xe1, 0x26, 0x85, 0xef, 0x60, +0x76, 0x8d, 0xaa, 0x85, 0x26, 0x85, 0x4a, 0x86, 0xef, 0x50, 0xde, 0xe4, 0x26, 0x85, 0xef, 0x60, +0x76, 0x8c, 0xaa, 0x85, 0x26, 0x85, 0x4a, 0x86, 0xef, 0x50, 0x5e, 0xec, 0x41, 0x61, 0xbc, 0x99, +0x7d, 0x71, 0x37, 0xc6, 0x04, 0x20, 0x07, 0x25, 0x86, 0x13, 0xc8, 0xe5, 0x13, 0x05, 0x05, 0x03, +0x53, 0x00, 0x05, 0x42, 0x02, 0xa4, 0x22, 0x47, 0xb2, 0x47, 0xb7, 0xb5, 0x09, 0x00, 0x13, 0x86, +0xb5, 0x6c, 0xc1, 0x45, 0x41, 0x61, 0x6f, 0x00, 0xe7, 0x89, 0x00, 0x00, 0x82, 0x80, 0x00, 0x00, +0x37, 0x45, 0x05, 0x20, 0x23, 0x2a, 0x05, 0x8c, 0x23, 0x28, 0x05, 0x8c, 0x37, 0xb5, 0x09, 0x00, +0x23, 0x26, 0x05, 0x70, 0x23, 0x24, 0x05, 0x70, 0x82, 0x80, 0x00, 0x00, 0x49, 0x1f, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x49, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x49, 0x1f, 0x00, 0x00, 0xc7, 0x31, 0x00, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, +0x47, 0x03, 0x08, 0x00, 0x87, 0x40, 0x04, 0x01, 0x04, 0x00, 0x73, 0x4c, 0x6b, 0x0b, 0x06, 0x00, +0x87, 0x40, 0x08, 0x02, 0x03, 0x00, 0x88, 0x41, 0x64, 0x08, 0x06, 0x00, 0x88, 0x41, 0x32, 0x04, +0x07, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x07, 0x00, 0x43, 0x44, 0x1a, 0x09, 0x06, 0x00, 0x63, 0x65, +0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x47, 0x03, 0x08, 0x00, 0xfd, 0x78, 0xc9, 0x01, 0x05, 0x00, +0x73, 0x4c, 0x6b, 0x0b, 0x06, 0x00, 0x47, 0x6e, 0xcd, 0x03, 0x05, 0x00, 0x88, 0x41, 0x64, 0x08, +0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x07, 0x00, 0x43, 0x44, +0x1a, 0x09, 0x06, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x47, 0x03, 0x08, 0x00, +0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x1c, 0x0d, 0x06, 0x00, 0xaa, 0x79, 0x28, 0x01, +0x05, 0x00, 0xde, 0x7a, 0xbf, 0x0e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, +0x8d, 0x04, 0x07, 0x00, 0x43, 0x44, 0x1a, 0x09, 0x06, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, +0xe9, 0x51, 0x47, 0x03, 0x08, 0x00, 0xd3, 0x64, 0xed, 0x09, 0x02, 0x00, 0x43, 0x44, 0x35, 0x12, +0x05, 0x00, 0x87, 0x40, 0x08, 0x02, 0x03, 0x00, 0xde, 0x7a, 0x7f, 0x1d, 0x06, 0x00, 0x88, 0x41, +0x32, 0x04, 0x07, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x07, 0x00, 0x43, 0x44, 0x1a, 0x09, 0x06, 0x00, +0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x47, 0x03, 0x08, 0x00, 0xfd, 0x78, 0xc9, 0x01, +0x05, 0x00, 0x43, 0x44, 0x35, 0x12, 0x05, 0x00, 0x47, 0x6e, 0xcd, 0x03, 0x05, 0x00, 0x88, 0x41, +0x64, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x07, 0x00, +0x43, 0x44, 0x1a, 0x09, 0x06, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x47, 0x03, +0x08, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x1c, 0x0d, 0x06, 0x00, 0xaa, 0x79, +0x28, 0x01, 0x05, 0x00, 0xde, 0x7a, 0xbf, 0x0e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x43, 0x44, 0x8d, 0x04, 0x07, 0x00, 0x43, 0x44, 0x1a, 0x09, 0x06, 0x00, 0x63, 0x65, 0xce, 0x00, +0x05, 0x00, 0xe9, 0x51, 0x1c, 0x0d, 0x06, 0x00, 0x87, 0x40, 0x04, 0x01, 0x04, 0x00, 0x73, 0x4c, +0x6b, 0x0b, 0x06, 0x00, 0x87, 0x40, 0x08, 0x02, 0x03, 0x00, 0x88, 0x41, 0x64, 0x08, 0x06, 0x00, +0x88, 0x41, 0x32, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x1c, 0x0d, 0x06, 0x00, 0xfd, 0x78, +0xc9, 0x01, 0x05, 0x00, 0x73, 0x4c, 0x6b, 0x0b, 0x06, 0x00, 0x47, 0x6e, 0xcd, 0x03, 0x05, 0x00, +0x88, 0x41, 0x64, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, +0x1c, 0x0d, 0x06, 0x00, 0x63, 0x65, 0xce, 0x00, 0x05, 0x00, 0xe9, 0x51, 0x1c, 0x0d, 0x06, 0x00, +0xaa, 0x79, 0x28, 0x01, 0x05, 0x00, 0xde, 0x7a, 0xbf, 0x0e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, +0x93, 0x71, 0x05, 0x04, 0x01, 0x0e, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x57, 0x61, 0x00, 0x0e, 0x00, 0x53, 0x55, 0x23, 0x01, 0x12, +0x00, 0xcd, 0x4f, 0x29, 0x00, 0x10, 0x00, 0x43, 0x44, 0xea, 0x02, 0x14, 0x00, 0x60, 0x52, 0xae, +0x00, 0x11, 0x00, 0x43, 0x44, 0xea, 0x02, 0x14, 0x00, 0x43, 0x44, 0x2f, 0x02, 0x15, 0x00, 0x43, +0x44, 0x47, 0x02, 0x14, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x14, 0x00, 0x21, 0x57, 0x61, 0x00, 0x0e, +0x00, 0x53, 0x55, 0x23, 0x01, 0x12, 0x00, 0xcd, 0x4f, 0x29, 0x00, 0x10, 0x00, 0x43, 0x44, 0xea, +0x02, 0x14, 0x00, 0x60, 0x52, 0xae, 0x00, 0x11, 0x00, 0x43, 0x44, 0xea, 0x02, 0x14, 0x00, 0x43, +0x44, 0x2f, 0x02, 0x15, 0x00, 0x43, 0x44, 0x47, 0x02, 0x14, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x14, +0x00, 0x21, 0x57, 0x61, 0x00, 0x0e, 0x00, 0x53, 0x55, 0x23, 0x01, 0x12, 0x00, 0x25, 0x66, 0x2a, +0x00, 0x11, 0x00, 0x43, 0x44, 0x76, 0x05, 0x13, 0x00, 0x60, 0x52, 0xa3, 0x00, 0x11, 0x00, 0x43, +0x44, 0xbb, 0x02, 0x14, 0x00, 0x43, 0x44, 0x2f, 0x02, 0x15, 0x00, 0x43, 0x44, 0x02, 0x06, 0x13, +0x00, 0x43, 0x44, 0x35, 0x12, 0x13, 0x00, 0x0d, 0x5f, 0x3a, 0x00, 0x0f, 0x00, 0x43, 0x44, 0x5d, +0x00, 0x13, 0x00, 0xcd, 0x4f, 0x7f, 0x00, 0x10, 0x00, 0x43, 0x44, 0x1a, 0x09, 0x14, 0x00, 0x60, +0x52, 0x1f, 0x02, 0x11, 0x00, 0x43, 0x44, 0x1a, 0x09, 0x14, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x15, +0x00, 0x43, 0x44, 0x47, 0x02, 0x14, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x14, 0x00, 0x0d, 0x5f, 0x3a, +0x00, 0x0f, 0x00, 0x43, 0x44, 0x5d, 0x00, 0x13, 0x00, 0xcd, 0x4f, 0x7f, 0x00, 0x10, 0x00, 0x43, +0x44, 0x1a, 0x09, 0x14, 0x00, 0x60, 0x52, 0x1f, 0x02, 0x11, 0x00, 0x43, 0x44, 0x1a, 0x09, 0x14, +0x00, 0x43, 0x44, 0x8d, 0x04, 0x15, 0x00, 0x43, 0x44, 0x47, 0x02, 0x14, 0x00, 0x43, 0x44, 0x8d, +0x04, 0x14, 0x00, 0x21, 0x57, 0x61, 0x00, 0x0e, 0x00, 0x53, 0x55, 0x23, 0x01, 0x12, 0x00, 0x25, +0x66, 0xd1, 0x00, 0x11, 0x00, 0x43, 0x44, 0x35, 0x12, 0x13, 0x00, 0x60, 0x52, 0x1f, 0x02, 0x11, +0x00, 0x43, 0x44, 0x1a, 0x09, 0x14, 0x00, 0x43, 0x44, 0x8d, 0x04, 0x15, 0x00, 0x43, 0x44, 0xe9, +0x00, 0x14, 0x00, 0x43, 0x44, 0xd2, 0x01, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc4, 0x1d, 0x43, 0xd7, 0x41, 0x24, +0x41, 0x63, 0x68, 0x69, 0x6c, 0x6c, 0x65, 0x73, 0x2c, 0x48, 0x37, 0x53, 0x31, 0x2c, 0x51, 0x33, +0x35, 0x2c, 0x46, 0x31, 0x50, 0x32, 0x36, 0x2e, 0x30, 0x00, 0x24, 0x41, 0x63, 0x68, 0x69, 0x6c, +0x6c, 0x65, 0x73, 0x2c, 0x48, 0x37, 0x53, 0x31, 0x2c, 0x51, 0x35, 0x30, 0x2c, 0x46, 0x31, 0x50, +0x32, 0x36, 0x2e, 0x30, 0x00, 0x2c, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x40, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xe3, 0x3f, 0x9a, +0x99, 0x99, 0x99, 0x99, 0x99, 0xd9, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x3e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xa0, 0x41, 0x0a, 0xd7, 0x23, 0x3d, 0x00, +0x00, 0xa0, 0x40, 0x00, 0x00, 0x40, 0x40, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xeb, 0x3f, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x40, 0xe8, 0x6a, 0x2b, 0xf6, 0x97, 0xdd, 0xed, 0x3f, 0xc0, +0xa8, 0xa4, 0x4e, 0x40, 0x13, 0xb1, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, +0x00, 0xf0, 0x41, 0x00, 0x00, 0xc8, 0x41, 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0xc8, 0xc1, 0x9a, +0x99, 0x99, 0xbe, 0x00, 0x00, 0xa0, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x9a, +0x99, 0x99, 0x99, 0x99, 0x99, 0xb9, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x33, +0x33, 0x33, 0x33, 0x33, 0x33, 0xd3, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, +0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x50, 0xc3, 0x47, 0x00, 0x00, 0x00, 0x00, 0x87, +0x44, 0xe7, 0x4a, 0x18, 0x57, 0xc6, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x55, +0x94, 0xe7, 0x4a, 0x18, 0x57, 0xb6, 0x3f, 0xf8, 0xc1, 0x63, 0x1a, 0xdc, 0xa5, 0x4c, 0x40, 0x24, +0x25, 0x73, 0x5a, 0x44, 0x41, 0x00, 0x2c, 0x2c, 0x2c, 0x30, 0x30, 0x2c, 0x30, 0x30, 0x00, 0x24, +0x25, 0x73, 0x47, 0x47, 0x41, 0x00, 0x2c, 0x2c, 0x00, 0x24, 0x50, 0x4e, 0x54, 0x48, 0x30, 0x30, +0x31, 0x00, 0x2c, 0x25, 0x2e, 0x32, 0x66, 0x00, 0x23, 0x00, 0x00, 0x00, 0x70, 0x05, 0x20, 0xd8, +0x72, 0x05, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, +0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, +0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x1b, 0x01, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, +0x51, 0x55, 0x49, 0x54, 0x20 diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_fw_file_array.c b/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_fw_file_array.c new file mode 100644 index 000000000..38f9a485c --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_fw_file_array.c @@ -0,0 +1,32 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: gnss firmware dummy file arrays. + * + * History: + * 2023-11-01, Create file. + */ +#include "gnss_fw_file_array.h" +#include "tiot_types.h" + +/* 仅用于SDK,无文件系统使用文件数组时,替换此目录下文件. */ + +#define GNSS_FW_ATTR + +#define GNSS_CFG_BIN "gnss_cfg.bin" +GNSS_FW_ATTR const char g_gnss_cfg_file[] = { +#include GNSS_CFG_BIN +}; + +const tiot_file g_gnss_fw_files[] = { + { "cfg", sizeof(g_gnss_cfg_file), g_gnss_cfg_file }, +}; + +const tiot_file_path g_gnss_fw_file_path = { + g_gnss_fw_files, sizeof(g_gnss_fw_files) / sizeof(tiot_file) +}; + +const tiot_file_path *gnss_fw_file_path_get(void) +{ + return &g_gnss_fw_file_path; +} diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_fw_file_array.h b/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_fw_file_array.h new file mode 100644 index 000000000..36312d908 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/firmware/gnss_fw_file_array.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: gnss firmware file arrays. + * + * History: + * 2023-11-01, Create file. + */ + +#ifndef GNSS_FW_FILE_ARRAY_H +#define GNSS_FW_FILE_ARRAY_H + +#include "tiot_fileops.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +const tiot_file_path *gnss_fw_file_path_get(void); + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/gnss_device_info.c b/code/sdk/zhihui/gnss/driver/device/gnss/gnss_device_info.c new file mode 100644 index 000000000..38578d924 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/gnss_device_info.c @@ -0,0 +1,157 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: GNSS device info. \n + * + * History: \n + * 2023-03-25, Create file. \n + */ + +#include "gnss_device_info.h" +#include "tiot_pm_default.h" +#include "tiot_board_uart_port.h" +#include "tiot_board_log.h" +#include "tiot_controller.h" +#include "tiot_board_pin_port.h" +#include "tiot_cfg_handle_priv.h" +#include "tiot_sys_msg_handle.h" +#ifdef CONFIG_FILE_BY_ARRAY +#include "gnss_fw_file_array.h" +#endif + +#define GNSS_POWERON_WAIT_MS 1 /* Wait time before power on. */ +#define GNSS_BOOT_TIME_MS 200 /* Power on ==> Boot time. */ +#define GNSS_INIT_TIME_MS 600 /* Boot ==> Init time. */ +#define GNSS_WAKEUP_PULSE_MS 1 /* GPIO wake up pulse. */ +#define GNSS_WAKEUP_WAIT_MS 50 /* Wake up wait ms. */ +#define GNSS_BAUD_CHANGE_WAIT_US 11000 /* Baudrate change wait μs. */ + +#ifdef CONFIG_GNSS_TCXO_FREQ_38P4M +#define GNSS_WAKEUP_PIN_INIT_LEVEL TIOT_PIN_LEVEL_LOW +#else +#define GNSS_WAKEUP_PIN_INIT_LEVEL TIOT_PIN_LEVEL_HIGH +#endif + +#ifdef CONFIG_GNSS_UART_WITH_FLOWCTRL +#define GNSS_UART_ATTR_FLOW_CTRL TIOT_UART_ATTR_FLOW_CTRL_ENABLE +#else +#define GNSS_UART_ATTR_FLOW_CTRL TIOT_UART_ATTR_FLOW_CTRL_DISABLE +#endif + +#define GNSS_DEFAULT_UART_CONFIG \ +{ \ + 115200, \ + { .data_bits = TIOT_UART_ATTR_DATABIT_8, \ + .parity = TIOT_UART_ATTR_PARITY_NONE, \ + .stop_bits = TIOT_UART_ATTR_STOPBIT_1, \ + .flow_ctrl = GNSS_UART_ATTR_FLOW_CTRL \ + } \ +} + +static inline int32_t gnss_pin_set_level_if_exist(uint32_t pin, uint32_t pin_level) +{ + if (pin != TIOT_PIN_NONE) { + return tiot_board_pin_set_level(pin, pin_level); + } + return 0; +} + +static tiot_pm_retcode gnss_pm_power_on(tiot_pm *pm) +{ + uint32_t wakeup_device_pin = pm->pm_info[TIOT_PIN_HOST_WAKEUP_DEVICE]; + /* GNSS板级连接唤醒管脚时,上拉或下拉 */ + if (gnss_pin_set_level_if_exist(wakeup_device_pin, GNSS_WAKEUP_PIN_INIT_LEVEL) != 0) { + tiot_print_err("[TIoT][pm]set wkup pin level %d fail.\n", GNSS_WAKEUP_PIN_INIT_LEVEL); + return TIOT_PM_EVTRET_FAIL; + } + if (tiot_pm_default_power_on(pm) == TIOT_PM_EVTRET_FAIL) { + return TIOT_PM_EVTRET_FAIL; + } + if (gnss_pin_set_level_if_exist(wakeup_device_pin, TIOT_PIN_LEVEL_LOW) != 0) { + tiot_print_err("[TIoT][pm]set wkup pin level low fail.\n"); + return TIOT_PM_EVTRET_FAIL; + } + return TIOT_PM_EVTRET_NEXT_STATE; +} + +static const tiot_pm_event_entry g_gnss_pm_event_map[TIOT_PM_EVENT_MAX] = { + { TIOT_PM_TAG_POWERON, TIOT_PM_STATE_POWEROFF, tiot_pm_default_power_off }, + /* 上电后等待init消息或业务消息才说明进入work状态 */ + /* GNSS板级连接唤醒管脚时,上电特殊处理 */ + { TIOT_PM_TAG_POWEROFF, TIOT_PM_STATE_INIT, gnss_pm_power_on }, +#ifdef CONFIG_GNSS_WAKEUP_TYPE_UART + /* 只有sleep态才需要唤醒 */ + { TIOT_PM_TAG_CAN_WAKEUP, TIOT_PM_STATE_WAKING, tiot_pm_default_wakeup_device_by_uart }, +#else + /* 只有sleep态才需要唤醒 */ + { TIOT_PM_TAG_CAN_WAKEUP, TIOT_PM_STATE_WAKING, tiot_pm_default_wakeup_device_by_gpio }, +#endif + /* 有device wakeup host管脚时,通过此管脚说明已唤醒,且需要下发disallow消息 */ + { TIOT_PM_TAG_POWERON, TIOT_PM_STATE_WORK, tiot_pm_default_wakeup_ack_handle }, + /* 接收到request sleep消息,下发allow sleep消息 */ + { TIOT_PM_TAG_CAN_ALLOW_SLEEP, TIOT_PM_STATE_SLEEPING, tiot_pm_default_request_sleep_handle }, + /* 接收到dev wkup host gpio拉低,需要释放唤醒锁 */ + { TIOT_PM_TAG_CAN_SLEEP, TIOT_PM_STATE_SLEEP, tiot_pm_default_sleep_ack_handle }, + /* 非S3状态,下发allow sleep并释放唤醒锁 */ + { TIOT_PM_TAG_CAN_ALLOW_SLEEP, TIOT_PM_STATE_SLEEP, tiot_pm_default_request_sleep_ack_handle }, + /* 上报init消息或业务消息说明唤醒成功 */ + { TIOT_PM_TAG_CAN_WORK, TIOT_PM_STATE_WORK, NULL }, + { TIOT_PM_TAG_POWERON, TIOT_PM_STATE_INVALID, tiot_pm_default_work_vote_up }, + { TIOT_PM_TAG_POWERON, TIOT_PM_STATE_INVALID, tiot_pm_default_work_vote_down } +}; + +static void gnss_firmware_before_load(tiot_fw *fw) +{ + /* 加载前设置为固件加载默认波特率 */ + tiot_uart_config gnss_firmware_load_config = GNSS_DEFAULT_UART_CONFIG; + tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware); + tiot_xfer_manager *xfer = &ctrl->transfer; + if (tiot_xfer_set_config(xfer, &gnss_firmware_load_config) != 0) { + tiot_print_dbg("[TIoT:fw]config before load fail.\r\n"); + } + /* 加载前先清掉rx_buff */ +#ifdef CONFIG_XFER_DEFAULT_RX_BUFF + if (xfer->xmit_ops->rx_mode == TIOT_XMIT_RX_MODE_BUFFED) { + circ_buf_flush(&xfer->rx_buff); + } +#endif +} + +static void gnss_firmware_after_load(tiot_fw *fw) +{ + /* 加载过程中可能切换波特率,加载后设置为业务默认波特率 */ + tiot_uart_config gnss_transfer_config = GNSS_DEFAULT_UART_CONFIG; + tiot_controller *ctrl = tiot_container_of(fw, tiot_controller, firmware); + tiot_xfer_manager *xfer = &ctrl->transfer; + if (tiot_xfer_set_config(xfer, &gnss_transfer_config) != 0) { + tiot_print_dbg("[TIoT:fw]config after load fail.\r\n"); + } +} + +static int gnss_rx_wait_func(const void *param) +{ + (void)param; + /* GNSS通过UART上报数据,不需要拉高管脚来通知读取 */ + return 0; +} + +static const tiot_device_info g_gnss_device_info = { + .pm_event_map = (tiot_pm_event_entry *)g_gnss_pm_event_map, + .pm_event_map_size = sizeof(g_gnss_pm_event_map) / sizeof(tiot_pm_event_entry), + .exec_cbs = { gnss_firmware_before_load, gnss_firmware_after_load, tiot_fw_ext_cmd_handle_priv, NULL }, + .xfer_info = { TIOT_XMIT_TYPE_UART, gnss_rx_wait_func }, + .pkt_sys_msg_handle = tiot_pkt_sys_msg_handle, + .timings = { + .power_on_wait_ms = GNSS_POWERON_WAIT_MS, + .boot_time_ms = GNSS_BOOT_TIME_MS, + .init_time_ms = GNSS_INIT_TIME_MS, + .wakeup_pulse_ms = GNSS_WAKEUP_PULSE_MS, + .wakeup_wait_ms = GNSS_WAKEUP_WAIT_MS, + .baud_change_wait_us = GNSS_BAUD_CHANGE_WAIT_US, + } +}; + +const tiot_device_info *gnss_device_get_info(void) +{ + return &g_gnss_device_info; +} diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/gnss_device_info.h b/code/sdk/zhihui/gnss/driver/device/gnss/gnss_device_info.h new file mode 100644 index 000000000..5356fbda1 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/gnss_device_info.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: GNSS device info header. \n + * + * History: \n + * 2023-06-13, Create file. \n + */ +#ifndef GNSS_DEVICE_INFO_H +#define GNSS_DEVICE_INFO_H + +#include "tiot_device_info.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_device_gnss_device_info GNSS Device Info + * @ingroup tiot_device_gnss + * @{ + */ + +/** + * @brief GNSS device get info, same for all GNSS devices. + * @return GNSS device info. + */ +const tiot_device_info *gnss_device_get_info(void); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/gnss_service.c b/code/sdk/zhihui/gnss/driver/device/gnss/gnss_service.c new file mode 100644 index 000000000..6a570e531 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/gnss_service.c @@ -0,0 +1,434 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-03-31, Create file. \n + */ +#include "gnss_service.h" +#include "gnss_device_info.h" +#include "gnss_board_port.h" +#include "tiot_board_log.h" +#include "tiot_controller.h" +#include "tiot_controller_helper.h" +#include "tiot_packet.h" +#include "tiot_sys_msg_types.h" +#include "tiot_board_pin_port.h" +#include "tiot_board_uart_port.h" +#include "tiot_board_misc_port.h" +#include "tiot_board.h" +#include "tiot_service_interface.h" + +#ifndef CONFIG_BOARD_DYNAMIC_ALLOC +/* 加载 & 数据收发复用buffer,不同时使用 */ +/* 数据收发需求 ~10K用于缓存数据. */ +/* 固件加载时 ~3K用于保存解析后命令, ~128字节用于加载回复接收. */ +#define GNSS_FW_LOAD_REUSE_BUFF_START 0U +#define GNSS_FW_LOAD_RX_BUFF_START GNSS_FW_LOAD_REUSE_BUFF_START +#define GNSS_FW_LOAD_RX_BUFF_SIZE 128U + +#define GNSS_FW_LOAD_REUSE_BUFF_END (GNSS_FW_LOAD_RX_BUFF_START + GNSS_FW_LOAD_RX_BUFF_SIZE) + +#define GNSS_COMMON_BUFF_MAX ((CONFIG_GNSS_PACKET_BUFF_MAX > GNSS_FW_LOAD_REUSE_BUFF_END) ? \ + CONFIG_GNSS_PACKET_BUFF_MAX : GNSS_FW_LOAD_REUSE_BUFF_END) +#endif + +#define GNSS_PACKET_QUEUE_NODES 8 + +typedef enum { + GNSS_RX_SUBSYS_0 = 0, + GNSS_RX_SUBSYS_MAX +} gnss_rx_subsys_id; + +typedef enum { + GNSS_PLT_SWITCH_GUART_BPS = 0, + GNSS_PLT_SWITCH_DBGUART_BPS, + GNSS_PLT_SWITCH_UART_SELECT, + GNSS_PLT_SWITCH_HSO_OR_SDT, + GNSS_PLT_SWITCH_DBGUART_SKIP, + GNSS_PLT_CMD_MAXSIZE +} gnss_plt_cmd; + +typedef struct { + uint32_t bps; + uint32_t cr_crg; +} tiot_plt_guart_para; + +typedef struct { + uint8_t frame_start; + uint8_t func_type; + uint8_t prime_id; + uint8_t reserved; + uint16_t frame_len; + uint16_t sn; +} tiot_plt_om_header; + +typedef struct { + uint16_t cmd; + uint16_t para_len; +} tiot_plt_cmd_header; + +#pragma pack(push, 1) +typedef struct { + tiot_plt_om_header om_header; + tiot_plt_cmd_header cmd_header; + tiot_plt_guart_para para; + uint8_t tail; +} tiot_plt_guart_cmd; +#pragma pack(pop) + +#define tiot_plat_guart_baud_cmd(bps, flow_ctrl) \ +{ \ + .om_header = { 0x7e, 0x0c, 0x00, 0x00, 0x15, 0x00 }, \ + .cmd_header = { GNSS_PLT_SWITCH_GUART_BPS, sizeof(tiot_plt_guart_para) }, \ + .para = { (bps), \ + ((flow_ctrl) == TIOT_UART_ATTR_FLOW_CTRL_ENABLE) ? 0xC301 : 0x301 \ + }, \ + .tail = 0x7e \ +} + +static tiot_controller g_gnss_controllers[CONFIG_GNSS_DEV_NUM] = { 0 }; +static tiot_packet_context g_gnss_pkt_ctx[CONFIG_GNSS_DEV_NUM]; +static tiot_packet g_gnss_pkt_queue_nodes[CONFIG_GNSS_DEV_NUM][GNSS_PACKET_QUEUE_NODES]; +static tiot_packet_queue g_gnss_pkt_queues[CONFIG_GNSS_DEV_NUM][GNSS_RX_SUBSYS_MAX]; + +#ifndef CONFIG_BOARD_DYNAMIC_ALLOC +static uint8_t g_gnss_common_buff_mem[CONFIG_GNSS_DEV_NUM][GNSS_COMMON_BUFF_MAX]; +#endif + +static uint16_t gnss_packet_manager_match_func(uint32_t subsys_code) +{ + if ((subsys_code == GNSS_FIRST_MSG) || (subsys_code == GNSS_COMMON_MSG) || + (subsys_code == GNSS_LAST_MSG) || (subsys_code == MSG_BUTT)) { + return GNSS_RX_SUBSYS_0; + } + return GNSS_RX_SUBSYS_MAX; +} + +static void gnss_device_wakeup_host_cb(uint32_t pin) +{ + (void)tiot_board_pin_enable_int(pin, TIOT_PIN_INT_DISABLE); + tiot_controller *cur_ctrl = tiot_find_controller_by_pin(g_gnss_controllers, CONFIG_GNSS_DEV_NUM, + pin, GNSS_PIN_DEVICE_WAKEUP_HOST); + if (cur_ctrl != NULL) { + tiot_pm_set_event(&cur_ctrl->pm, TIOT_PM_EVENT_WAKEUP_ACK); + } + (void)tiot_board_pin_enable_int(pin, TIOT_PIN_INT_ENABLE); +} + +static int32_t gnss_change_uart_config(tiot_xfer_manager *xfer, tiot_uart_config *uart_cfg) +{ + tiot_plt_guart_cmd uart_cmd = tiot_plat_guart_baud_cmd(uart_cfg->baudrate, uart_cfg->attr.flow_ctrl); + tiot_xfer_tx_param param = { SUBSYS_OM }; + int32_t ret = tiot_xfer_send(xfer, (const uint8_t *)&uart_cmd, sizeof(tiot_plt_guart_cmd), ¶m); + if (ret != sizeof(tiot_plt_guart_cmd)) { + tiot_print_err("[TIOT]set user baudrate cmd fail.\r\n"); + return -1; + } + ret = tiot_xfer_set_config(xfer, uart_cfg); + if (ret != 0) { + tiot_print_err("[TIOT]set user baudrate fail.\r\n"); + return -1; + } + return 0; +} + +static inline int32_t gnss_send_host_need_wakeup(tiot_controller *ctrl) +{ + int32_t ret; + const uint8_t host_need_wakeup_cmd = SYS_PL_PM_SET_WAKEUP_HOST_VALID; + const tiot_xfer_tx_param param = { SUBSYS_SYS }; + ret = tiot_xfer_send(&ctrl->transfer, &host_need_wakeup_cmd, sizeof(uint8_t), ¶m); + if (ret != sizeof(uint8_t)) { + tiot_print_err("[TIOT]set host need wakeup cmd fail.\r\n"); + return -1; + } + return 0; +} + +static int32_t gnss_send_change_buadrate(tiot_controller *ctrl, uint32_t new_buadrate) +{ + const tiot_device_timings *timings = &ctrl->dev_info->timings; + tiot_uart_config uart_config = { 0 }; + (void)tiot_xfer_get_config(&ctrl->transfer, &uart_config); + /* 配置用户波特率 */ + if (uart_config.baudrate == new_buadrate) { + return 0; + } + uart_config.baudrate = new_buadrate; + if (gnss_change_uart_config(&ctrl->transfer, &uart_config) != 0) { + tiot_print_err("[TIoT]send change buadrate fail\n"); + return -1; + } + /* 切换波特率后等待波特率稳定,device或host? */ + tiot_board_udelay(timings->baud_change_wait_us); + return 0; +} + +static int32_t gnss_service_packet_init(tiot_controller *ctrl, uint8_t dev_id) +{ + int32_t ret; +#ifndef CONFIG_BOARD_DYNAMIC_ALLOC + tiot_packet_buffer pkt_buff = { g_gnss_common_buff_mem[dev_id], CONFIG_GNSS_PACKET_BUFF_MAX, 0 }; +#endif + tiot_packet_context_param param = { + .flags = TIOT_PKT_FLAGS_SUPPORT_ASCII, + .rx_manager_info = { g_gnss_pkt_queues[dev_id], GNSS_RX_SUBSYS_MAX, gnss_packet_manager_match_func }, + .buff = NULL + }; +#ifndef CONFIG_BOARD_DYNAMIC_ALLOC + param.buff = &pkt_buff; +#endif + g_gnss_pkt_queues[dev_id][GNSS_RX_SUBSYS_0].queue_nodes = g_gnss_pkt_queue_nodes[dev_id]; + g_gnss_pkt_queues[dev_id][GNSS_RX_SUBSYS_0].queue_size = GNSS_PACKET_QUEUE_NODES; + tiot_packet_context *pkt_ctx = &g_gnss_pkt_ctx[dev_id]; + ret = tiot_packet_init(pkt_ctx, &ctrl->transfer, ¶m); + if (ret != 0) { + tiot_print_err("[TIOT]packet init fail.\r\n"); + } + return ret; +} + +static int32_t gnss_service_install_packet(tiot_controller *ctrl, uint8_t dev_id) +{ + tiot_xfer_packet_ops gnss_packet_ops = { + .read_out = tiot_packet_read_out, + .rx_data_store = tiot_packet_rx_data_store, + .tx_push = tiot_packet_tx_push, + }; + const tiot_device_timings *timings = &ctrl->dev_info->timings; + /* 收发模块注册包格式 */ + if (tiot_xfer_install_packet(&ctrl->transfer, (tiot_xfer_packet_ops *)&gnss_packet_ops, + (uintptr_t)&g_gnss_pkt_ctx[dev_id]) != 0) { + tiot_print_err("[TIOT]packet install fail.\r\n"); + return -1; + } + /* 必须等待device UART初始化后才能接收消息, 待确认时间. */ + osal_msleep(timings->init_time_ms); + tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_REPORT_WORK); + return 0; +} + +static inline int32_t gnss_service_custom_msg_send(tiot_controller *ctrl, uint32_t dev_wkup_host_pin, + uint32_t custom_buadrate) +{ + /* 通过管脚有无判断host是否需要唤醒 */ + if (dev_wkup_host_pin != TIOT_PIN_NONE) { + if (gnss_send_host_need_wakeup(ctrl) != 0) { + return -1; + } + } + /* 切换波特率 */ + if (gnss_send_change_buadrate(ctrl, custom_buadrate) != 0) { + return -1; + } + return 0; +} + +static inline int32_t gnss_get_dev_id(tiot_controller *ctrl, uint8_t *dev_id) +{ + uint8_t i; + for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) { + if (ctrl == &g_gnss_controllers[i]) { + *dev_id = i; + return 0; + } + } + tiot_print_err("[TIoT]invalid device\n"); + return -1; +} + +static inline void gnss_set_open_param(tiot_xfer_open_param *xfer_open_param, tiot_service_open_param *param) +{ + if (param == NULL) { + return; + } + xfer_open_param->rx_cbk_param.buff = param->buff; + xfer_open_param->rx_cbk_param.buff_len = param->buff_len; + xfer_open_param->rx_cbk_param.rx_callback = param->rx_callback; +} + +static inline int32_t gnss_firmware_load(tiot_fw *firmware) +{ + int ret = -1; +#ifdef CONFIG_FILE_BY_ARRAY + ret = tiot_firmware_load(firmware, gnss_fw_file_path_get(), TIOT_FW_FILE_ARRAY_CFG_NAME); +#else + ret = tiot_firmware_load(firmware, NULL, gnss_board_get_info()->cfg_path); +#endif + if (ret != 0) { + tiot_print_err("[TIoT]Gnss firmware load fail.\n"); + } + return ret; +} + +static int32_t gnss_service_open(tiot_controller *ctrl, void *param) +{ + int ret = -1; + uint8_t dev_id; + uint32_t dev_wkup_host_pin; + tiot_xfer_open_param xfer_open_param = { 0 }; + if (gnss_get_dev_id(ctrl, &dev_id) != 0) { + return -1; + } + gnss_set_open_param(&xfer_open_param, param); + /* 传输启动 */ + if (tiot_xfer_open(&ctrl->transfer, &xfer_open_param) != 0) { + /* 通信接口打开失败 */ + tiot_print_err("[TIoT]Transfer port open fail\n"); + goto xfer_open_fail; + } + /* 上电 */ + if (tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_POWERON) != 0) { + /* 上电失败 */ + tiot_print_err("[TIoT]Power on fail\n"); + goto power_on_fail; + } + /* 加载固件 */ + ret = gnss_firmware_load(&ctrl->firmware); + if (ret != 0) { + goto fw_load_fail; + } + /* 使能中断 */ + dev_wkup_host_pin = ctrl->pm.pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST]; + tiot_pin_int_request(dev_wkup_host_pin, gnss_device_wakeup_host_cb); + + ret = gnss_service_packet_init(ctrl, dev_id); + if (ret != 0) { + goto pkt_init_fail; + } + ret = gnss_service_install_packet(ctrl, dev_id); + if (ret != 0) { + goto pkt_install_fail; + } + ret = gnss_service_custom_msg_send(ctrl, dev_wkup_host_pin, CONFIG_GNSS_UART_BAUDRATE); + if (ret != 0) { + goto pkt_install_fail; + } + /* 打开OK */ + tiot_print_suc("[TIoT]Controller open succ.\n"); + return 0; + +pkt_install_fail: + tiot_packet_deinit(&g_gnss_pkt_ctx[dev_id]); +pkt_init_fail: + tiot_pin_int_release(dev_wkup_host_pin); +fw_load_fail: + (void)tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_POWEROFF); +power_on_fail: + tiot_xfer_close(&ctrl->transfer); +xfer_open_fail: + return ret; +} + +static void gnss_service_close(tiot_controller *ctrl) +{ + uint8_t dev_id; + uint32_t dev_wkup_host_pin; + if (gnss_get_dev_id(ctrl, &dev_id) != 0) { + return; + } + dev_wkup_host_pin = ctrl->pm.pm_info[TIOT_PIN_DEVICE_WAKEUP_HOST]; + (void)tiot_pm_set_event(&ctrl->pm, TIOT_PM_EVENT_POWEROFF); + tiot_pin_int_release(dev_wkup_host_pin); + tiot_xfer_close(&ctrl->transfer); + tiot_xfer_uninstall_packet(&ctrl->transfer); + tiot_packet_deinit(&g_gnss_pkt_ctx[dev_id]); +} + +static int32_t gnss_service_write(tiot_controller *ctrl, const uint8_t *data, + uint32_t len, const tiot_xfer_tx_param *param) +{ + tiot_unused(param); + uint8_t dev_id; + if (gnss_get_dev_id(ctrl, &dev_id) != 0) { + return -1; + } + const tiot_xfer_tx_param tx_param = { SUBSYS_GNSS }; + tiot_pm *pm = &ctrl->pm; + (void)tiot_pm_set_event(pm, TIOT_PM_EVENT_WORK_VOTE_UP); + /* 尝试唤醒device */ + int32_t ret = tiot_pm_set_event(pm, TIOT_PM_EVENT_WAKEUP); + if (ret != 0) { + tiot_print_err("[TIoT]wake up error\n"); + goto vote_down; + } + /* 等待成功唤醒device */ + ret = tiot_pm_wait_state(&ctrl->pm, TIOT_PM_STATE_WORK, ctrl->dev_info->timings.wakeup_wait_ms); + if (ret <= 0) { + tiot_print_warning("[TIoT]wakeup device fail, pm state is 0x%x.\n", pm->state); + } + ret = tiot_xfer_send(&ctrl->transfer, data, len, &tx_param); +vote_down: + (void)tiot_pm_set_event(pm, TIOT_PM_EVENT_WORK_VOTE_DOWN); + return ret; +} + +static int32_t gnss_service_read(tiot_controller *ctrl, uint8_t *buff, uint32_t buff_len, + const tiot_xfer_rx_param *param) +{ + uint8_t dev_id; + if (gnss_get_dev_id(ctrl, &dev_id) != 0) { + return -1; + } + return tiot_xfer_recv(&ctrl->transfer, buff, buff_len, param); +} + +int32_t gnss_service_init(void) +{ + uint8_t i; + int32_t ret; + tiot_board_info per_board_info; + tiot_controller_info ctrl_info; + for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) { + if (gnss_board_init(&i) != 0) { + tiot_print_err("[TIoT]board init fail\n"); + return -1; + } + } + const gnss_board_info *board_info = gnss_board_get_info(); + if (board_info == NULL) { + tiot_print_err("[TIoT]no board info.\n"); + goto deinit; + } + for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) { + per_board_info.hw_info.xmit_id = board_info->hw_infos[i].xmit_id; + per_board_info.hw_info.pm_info = board_info->hw_infos[i].pm_info; + ctrl_info.board_info = &per_board_info; + ctrl_info.dev_info = gnss_device_get_info(); + ctrl_info.dev_cus = 0; + ret = tiot_controller_init(&g_gnss_controllers[i], &ctrl_info); + if (ret != 0) { + tiot_print_err("[TIoT]controller init fail\n"); + goto deinit; + } + } + for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) { + g_gnss_controllers[i].ops.open = gnss_service_open; + g_gnss_controllers[i].ops.close = gnss_service_close; + g_gnss_controllers[i].ops.write = gnss_service_write; + g_gnss_controllers[i].ops.read = gnss_service_read; + g_gnss_controllers[i].ops.pm_ctrl = NULL; + } + return 0; +deinit: + gnss_service_deinit(); + return -1; +} + +void gnss_service_deinit(void) +{ + uint8_t i; + for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) { + tiot_controller_deinit(&g_gnss_controllers[i]); + } + for (i = 0; i < CONFIG_GNSS_DEV_NUM; i++) { + gnss_board_deinit(&i); + } +} + +uintptr_t gnss_service_get_ctrl(uint8_t dev_id) +{ + return (uintptr_t)&g_gnss_controllers[dev_id]; +} diff --git a/code/sdk/zhihui/gnss/driver/device/gnss/gnss_service.h b/code/sdk/zhihui/gnss/driver/device/gnss/gnss_service.h new file mode 100644 index 000000000..3d37a81e1 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/device/gnss/gnss_service.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: GNSS service interface. \n + * + * History: \n + * 2023-06-13, Create file. \n + */ +#ifndef GNSS_SERVICE_H +#define GNSS_SERVICE_H + +#include "tiot_types.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_device_gnss_service_if GNSS Service Interface + * @ingroup tiot_device_gnss + * @{ + */ + +/** + * @brief GNSS service init. + * @return zero if OK, -1 if failed. + */ +int32_t gnss_service_init(void); + +/** + * @brief GNSS service deinit. + */ +void gnss_service_deinit(void); + +/** + * @brief GNSS service get ctrl. + * @param dev_id Device id. + * @return Tiot controller instace. + */ +uintptr_t gnss_service_get_ctrl(uint8_t dev_id); + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/product_porting/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/product_porting/CMakeLists.txt new file mode 100644 index 000000000..7149394a0 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/CMakeLists.txt @@ -0,0 +1,12 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +add_subdirectory(porting) # 替换成对应porting目录 + +set( + tiot_product_header_list + ${CMAKE_CURRENT_SOURCE_DIR} +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${tiot_product_header_list}" CACHE INTERNAL "tiot header list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/product_porting/porting/CMakeLists.txt b/code/sdk/zhihui/gnss/driver/product_porting/porting/CMakeLists.txt new file mode 100644 index 000000000..b5e118505 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/porting/CMakeLists.txt @@ -0,0 +1,19 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. +#=============================================================================== +set( + tiot_product_src_list + ${CMAKE_CURRENT_SOURCE_DIR}/gnss_board_port.c + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_board_uart_port.c + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_board_pin_port.c + ${CMAKE_CURRENT_SOURCE_DIR}/tiot_board_misc_port.c +) + +set( + tiot_product_header_list + ${CMAKE_CURRENT_SOURCE_DIR} +) + +set(TIOT_HEADER_LIST "${TIOT_HEADER_LIST}" "${tiot_product_header_list}" CACHE INTERNAL "tiot header list" FORCE) +set(TIOT_SRC_LIST "${TIOT_SRC_LIST}" "${tiot_product_src_list}" CACHE INTERNAL "tiot src list" FORCE) \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/product_porting/porting/gnss_board_port.c b/code/sdk/zhihui/gnss/driver/product_porting/porting/gnss_board_port.c new file mode 100644 index 000000000..63927a756 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/porting/gnss_board_port.c @@ -0,0 +1,85 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: \n + * + * History: \n + * 2023-06-13, Create file. \n + */ + +#include "gnss_board_port.h" +#include "tiot_board_pin_port.h" +#include "gpio.h" +#include "uart.h" +#include "pinctrl.h" +#include "soc_osal.h" + +/* 根据板级MCU与gnss两个芯片的硬件连接修改适配 */ +/* 1. MCU芯片连接到gnss芯片的UART bus编号, 如UART_BUS_0. */ +/* 2. MCU芯片连接到gnss芯片PWREN管脚号, 。必须. +U8 GPS_1V8 S_AGPIO_L28 High 默认一直拉高 + GPS_BAT_ON S_AGPIO_L23 High 默认一直拉高 + PWREN S_AGPIO_L30 High 只需要控制PWREN +*/ +/* 3. MCU芯片连接到gnss芯片GPIO9(host唤醒gnss)管脚号, + U8 当下悬空。 + 可选,如果板级未连接此管脚,必须设为TIOT_PIN_NONE宏. + */ +/* 4. MCU芯片连接到gnss芯片GPIO7(gnss唤醒host)管脚号, + U8 S_AGPIO_L31。 + 可选,如果板级未连接此管脚,必须设为TIOT_PIN_NONE宏. + */ +static const gnss_board_hw_info g_gnss_board_hw_info = { UART_BUS_0, { S_AGPIO_L30, TIOT_PIN_NONE, TIOT_PIN_NONE } }; +static const gnss_board_info g_gnss_board_info = { + .cfg_path = NULL, /* 如果使用文件系统,此处填写固件cfg文件完整路径, + 例如 .cfg_path = "user/gnss_firmware/gnss_fw_cfg"; + 否则, 填写NULL,并替换源码目录tiot_driver/device/gnss/firmware下的固件数组文件。 */ + .hw_infos = (gnss_board_hw_info *)&g_gnss_board_hw_info +}; + +int32_t gnss_board_init(void *param) +{ + tiot_unused(param); + const uint32_t *gnss_pins = g_gnss_board_hw_info.pm_info; + /* power en */ + uint32_t power_ctrl_pin = gnss_pins[GNSS_PIN_POWER_CTRL]; + (void)uapi_pin_set_mode((pin_t)power_ctrl_pin, (pin_mode_t)HAL_PIO_FUNC_GPIO); + (void)uapi_pin_set_pull((pin_t)power_ctrl_pin, PIN_PULL_DOWN); + (void)uapi_gpio_set_val((pin_t)power_ctrl_pin, GPIO_LEVEL_LOW); + (void)uapi_gpio_set_dir((pin_t)power_ctrl_pin, GPIO_DIRECTION_OUTPUT); + (void)uapi_pin_set_ds((pin_t)power_ctrl_pin, (pin_drive_strength_t)(PIN_DS_MAX - 1)); + + /* host wakeup dev */ + uint32_t host_wakeup_device_pin = gnss_pins[GNSS_PIN_HOST_WAKEUP_DEVICE]; + if (host_wakeup_device_pin != TIOT_PIN_NONE) { + (void)uapi_pin_set_mode((pin_t)host_wakeup_device_pin, (pin_mode_t)HAL_PIO_FUNC_GPIO); + (void)uapi_pin_set_ds((pin_t)host_wakeup_device_pin, (pin_drive_strength_t)(PIN_DS_MAX - 1)); + (void)uapi_pin_set_pull((pin_t)host_wakeup_device_pin, PIN_PULL_DOWN); + (void)uapi_gpio_set_val((pin_t)host_wakeup_device_pin, GPIO_LEVEL_LOW); + (void)uapi_gpio_set_dir((pin_t)host_wakeup_device_pin, GPIO_DIRECTION_OUTPUT); + } + + /* device wakeup host */ + uint32_t device_wakeup_host_pin = gnss_pins[GNSS_PIN_DEVICE_WAKEUP_HOST]; + if (device_wakeup_host_pin != TIOT_PIN_NONE) { + (void)uapi_pin_set_mode((pin_t)device_wakeup_host_pin, (pin_mode_t)HAL_PIO_FUNC_GPIO); + (void)uapi_pin_set_pull((pin_t)device_wakeup_host_pin, PIN_PULL_DOWN); + (void)uapi_gpio_set_val((pin_t)device_wakeup_host_pin, GPIO_LEVEL_LOW); + (void)uapi_gpio_set_dir((pin_t)device_wakeup_host_pin, GPIO_DIRECTION_INPUT); + } + /* UART1 pinmux已经在板级完成初始化, 或在UART open时进行初始化。 */ + return 0; +} + +void gnss_board_deinit(void *param) +{ + tiot_unused(param); + const uint32_t *gnss_pins = g_gnss_board_hw_info.pm_info; + /* 确保PWREN管脚下拉 */ + (void)uapi_gpio_set_val((pin_t)gnss_pins[GNSS_PIN_POWER_CTRL], GPIO_LEVEL_LOW); +} + +const gnss_board_info *gnss_board_get_info(void) +{ + return &g_gnss_board_info; +} diff --git a/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_log_port.h b/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_log_port.h new file mode 100644 index 000000000..8a87996b1 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_log_port.h @@ -0,0 +1,46 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board log port. \n + * + * History: \n + * 2023-05-06, Create file. \n + */ +#ifndef BOARD_LOG_PORT_H +#define BOARD_LOG_PORT_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * @defgroup tiot_board_port_log LOG port + * @ingroup tiot_board_port + * @{ + */ + +/* 通过printf直接打印,不需要日志时需要注释掉define后半部分. */ +#define BOARD_PRINT_FUNCTION_NAME printf("%s\r\n", __func__) +#define board_print_dbg(s, args...) printf(s, ##args) +#define board_print_info(s, args...) printf(s, ##args) +#define board_print_info(s, args...) printf(s, ##args) +#define board_print_suc(s, args...) printf(s, ##args) +#define board_print_warning(s, args...) printf(s, ##args) +#define board_print_err(s, args...) printf(s, ##args) +#define board_print_alter(s, args...) printf(s, ##args) + +/** + * @} + */ + +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#endif diff --git a/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_misc_port.c b/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_misc_port.c new file mode 100644 index 000000000..a7a6e4324 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_misc_port.c @@ -0,0 +1,45 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board Misc port. \n + * + * History: \n + * 2023-12-04, Create file. \n + */ +#include "tiot_board_misc_port.h" +#include "soc_osal.h" +#include "pm_veto.h" + +#define TIOT_WAKEUP_LOCK_ID PM_ID_SYS + +int32_t tiot_board_wake_lock_init(tiot_board_wakelock *lock) +{ + tiot_unused(lock); + return 0; +} + +void tiot_board_wake_lock(tiot_board_wakelock *lock) +{ + tiot_unused(lock); +#if ENABLE_LOW_POWER == YES + (void)uapi_pm_add_sleep_veto(TIOT_WAKEUP_LOCK_ID); +#endif +} + +void tiot_board_wake_unlock(tiot_board_wakelock *lock) +{ + tiot_unused(lock); +#if ENABLE_LOW_POWER == YES + (void)uapi_pm_remove_sleep_veto(TIOT_WAKEUP_LOCK_ID); +#endif +} + +void tiot_board_wake_lock_destroy(tiot_board_wakelock *lock) +{ + tiot_unused(lock); +} + +void tiot_board_udelay(uint32_t us) +{ + osal_udelay(us); +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_pin_port.c b/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_pin_port.c new file mode 100644 index 000000000..aebb1c2a1 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_pin_port.c @@ -0,0 +1,112 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board PIN port. \n + * + * History: \n + * 2023-04-20, Create file. \n + */ +#include "tiot_board_pin_port.h" +#include "gpio.h" + +#define uapi_err2ret(errcode) (((errcode) == ERRCODE_SUCC) ? 0 : -1) + +/* TIoT驱动使用中断管脚个数,需要按实际板级情况适配修改。 */ +#define TIOT_INT_PIN_NUMBER 1 +typedef struct { + uint32_t pin; + tiot_pin_int_callback callback; +} tiot_int_pin_map; +/* TIoT驱动使用中断管脚配置,需要按实际使用的中断管脚适配修改。 */ +static tiot_int_pin_map g_tiot_int_pin_map[TIOT_INT_PIN_NUMBER] = { + /* 例如使用XXX唤醒MCU管脚,对应GPIO ID为S_AGPIO_R0. */ + { S_AGPIO_R0, NULL } +}; + +/** + * @brief Board set pin level interface. + * @param [in] pin Pin id. + * @param [in] level Pin level, see @ref tiot_pin_level. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_pin_set_level(uint32_t pin, uint8_t level) +{ + errcode_t errcode; + gpio_level_t gpio_level = (level == TIOT_PIN_LEVEL_LOW) ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH; + errcode = uapi_gpio_set_val((pin_t)pin, gpio_level); + return uapi_err2ret(errcode); +} + +/** + * @brief Board get current pin level interface. + * @param [in] pin Pin id. + * @param [out] level Current pin level, see @ref tiot_pin_level. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_pin_get_level(uint32_t pin, uint8_t *level) +{ + gpio_level_t gpio_level = uapi_gpio_get_val((pin_t)pin); + *level = (gpio_level == GPIO_LEVEL_LOW) ? TIOT_PIN_LEVEL_LOW : TIOT_PIN_LEVEL_HIGH; + return 0; +} + +/** + * @brief Board pin interrupt enable interface. + * @param [in] pin Pin id. + * @param [in] int_enable Interrupt enable or disable, see @ref tiot_pin_int_enable. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_pin_enable_int(uint32_t pin, uint8_t int_enable) +{ + errcode_t errcode; + if (int_enable == TIOT_PIN_INT_ENABLE) { + errcode = uapi_gpio_enable_interrupt((pin_t)pin); + } else { + errcode = uapi_gpio_disable_interrupt((pin_t)pin); + } + return uapi_err2ret(errcode); +} + + +static void tiot_board_gpio_callback(pin_t pin, uintptr_t param) +{ + (void)param; + uapi_gpio_clear_interrupt(pin); + for (uint8_t index = 0; index < TIOT_INT_PIN_NUMBER; index++) { + if ((pin == g_tiot_int_pin_map[index].pin) && (g_tiot_int_pin_map[index].callback != NULL)) { + g_tiot_int_pin_map[index].callback(pin); + break; + } + } +} + +/** + * @brief Board pin interrupt callback register interface. + * @note Porting should ensure this callback is called when enters pin irq if interrupt enabled. + * @param [in] pin Pin id. + * @param [in] int_cb Registed interrupt callback, see @ref tiot_pin_int_callback. + * @return zero if OK; + * non-zero if FAIL. + */ +int32_t tiot_board_pin_register_int_callback(uint32_t pin, tiot_pin_int_callback int_cb) +{ + errcode_t errcode; + if (int_cb != NULL) { + errcode = uapi_gpio_register_isr_func((pin_t)pin, GPIO_INTERRUPT_RISING_EDGE, tiot_board_gpio_callback); + } else { + errcode = uapi_gpio_unregister_isr_func((pin_t)pin); + } + if (errcode != ERRCODE_SUCC) { + return -1; + } + for (uint8_t index = 0; index < TIOT_INT_PIN_NUMBER; index++) { + if (pin == g_tiot_int_pin_map[index].pin) { + g_tiot_int_pin_map[index].callback = int_cb; + break; + } + } + return 0; +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_uart_port.c b/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_uart_port.c new file mode 100644 index 000000000..36dd877a6 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/porting/tiot_board_uart_port.c @@ -0,0 +1,193 @@ +/** + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2023. All rights reserved. + * + * Description: Board UART port\n + * + * History: \n + * 2023-03-25, Create file. \n + */ +#include "tiot_board_uart_port.h" +#include "tiot_board_log.h" + +#include "uart.h" +#include "uart_porting.h" +#include "pinctrl.h" +#include "pinctrl_porting.h" + +#define TIOT_UAPI_RW_TIMEOUT 0xFFFFFFFF +#define UART_RX_BUFFER_SIZE 56 + +#define TIOT_UAPI_UART_RX_MAX 1024 + +/* TIoT驱动使用MCU UART个数. */ +enum tiot_uart_port { + TIOT_UART_PORT0, + TIOT_UART_NUM, + TIOT_UART_NONE = TIOT_UART_NUM +}; + +enum tiot_uart_pin_type { + UART_PIN_TYPE_TX, + UART_PIN_TYPE_RX, + UART_PIN_TYPE_CTS, + UART_PIN_TYPE_RTS, + UART_PIN_TYPE_NUM +}; + +typedef struct { + tiot_xmit *xmit; + uint8_t flow_ctrl_bk; + uint8_t rx_buff[UART_RX_BUFFER_SIZE]; + const uart_pin_config_t pin_config_orig; + uart_pin_config_t pin_config; + hal_pio_func_t pinmux[UART_PIN_TYPE_NUM]; + uart_rx_callback_t rx_callback; +} tiot_board_uart_port; + +static tiot_xmit_callbacks g_tiot_xmit_cbs; + +/* MCU UART管脚接收回调,按TIoT驱动使用UART个数适配增加 */ +static void tiot_board_rx_callback0(const void *buff, uint16_t length, bool error); +/* TIoT驱动使用的UART初始信息,需要按实际板级情况适配。 */ +static tiot_board_uart_port g_tiot_board_uart_port[TIOT_UART_NUM] = { + /* TIOT_UART_PORT0. */ + { + .flow_ctrl_bk = TIOT_UART_ATTR_FLOW_CTRL_ENABLE, /* MCU UART默认是否开启流控。 */ + .rx_buff = { 0 }, + .pin_config_orig = { S_MGPIO19, S_MGPIO20, S_MGPIO21, S_MGPIO22 }, /* MCU UART管脚,按实际板级情况适配。 */ + /* MCU UART管脚pinmux,按实际板级情况适配。 */ + .pinmux = { + HAL_PIO_FUNC_UART1, HAL_PIO_FUNC_UART1, + HAL_PIO_FUNC_UART1, HAL_PIO_FUNC_UART1 + }, + .rx_callback = tiot_board_rx_callback0 /* MCU UART管脚接收回调,按TIoT驱动使用UART个数适配增加。 */ + } + /* TIOT_UART_PORTx... */ +}; + +/* MCU UART bus号与TIoT驱动使用的UART 对应关系,需要按实际情况适配。 */ +static inline enum tiot_uart_port tiot_board_uart_bus_convert_port(uart_bus_t bus) +{ + /* 例如 UART_BUS_0 对应 TIoT驱动使用的第一个UART。 */ + if (bus == UART_BUS_0) { + return TIOT_UART_PORT0; + } + return TIOT_UART_NONE; +} + +static inline void tiot_board_rx_callback_common(tiot_board_uart_port *port, const void *buff, uint16_t length) +{ + g_tiot_xmit_cbs.rx_notify(port->xmit, (uint8_t *)buff, length); +} + +/* MCU UART管脚接收回调,按TIoT驱动使用UART个数适配增加 */ +static void tiot_board_rx_callback0(const void *buff, uint16_t length, bool error) +{ + if (error == false) { + tiot_board_rx_callback_common(&g_tiot_board_uart_port[TIOT_UART_PORT0], buff, length); + } else { + tiot_print_err("[TIoT]uart port0 receive error.\r\n"); + } +} + +static void tiot_board_uart_txrx_pinmux_init(tiot_board_uart_port *port) +{ + /* 防止板级未初始化. */ + uapi_pin_set_mode(port->pin_config.tx_pin, (pin_mode_t)port->pinmux[UART_PIN_TYPE_TX]); + uapi_pin_set_mode(port->pin_config.rx_pin, (pin_mode_t)port->pinmux[UART_PIN_TYPE_RX]); +} + +static void tiot_board_uart_switch_flowctrl(tiot_board_uart_port *port) +{ + /* 板级uart初始化不会初始化ctsrts pinmux... */ + if (port->flow_ctrl_bk == TIOT_UART_ATTR_FLOW_CTRL_ENABLE) { + port->pin_config.cts_pin = port->pin_config_orig.cts_pin; + port->pin_config.rts_pin = port->pin_config_orig.rts_pin; + uapi_pin_set_mode(port->pin_config.cts_pin, (pin_mode_t)port->pinmux[UART_PIN_TYPE_CTS]); + uapi_pin_set_mode(port->pin_config.rts_pin, (pin_mode_t)port->pinmux[UART_PIN_TYPE_RTS]); + } else { + port->pin_config.cts_pin = PIN_NONE; + port->pin_config.rts_pin = PIN_NONE; + } +} + +static int32_t tiot_board_uart_reopen(uart_bus_t bus, tiot_board_uart_port *port, const uart_attr_t *attr) +{ + uart_buffer_config_t buff_cfg = { (uint8_t *)port->rx_buff, UART_RX_BUFFER_SIZE }; + (void)uapi_uart_deinit(bus); + tiot_board_uart_txrx_pinmux_init(port); + tiot_board_uart_switch_flowctrl(port); + errcode_t ret = uapi_uart_init(bus, &(port->pin_config), attr, NULL, &buff_cfg); + if (ret != ERRCODE_SUCC) { + return -1; + } + uapi_uart_register_rx_callback(bus, UART_RX_CONDITION_FULL_OR_SUFFICIENT_DATA_OR_IDLE, + TIOT_UAPI_UART_RX_MAX, port->rx_callback); + return 0; +} + +int32_t tiot_board_uart_open(tiot_xmit *xmit, tiot_xmit_callbacks *cbs) +{ + enum tiot_uart_port port_type = tiot_board_uart_bus_convert_port((uart_bus_t)xmit->id); + if (port_type == TIOT_UART_NONE) { + return -1; + } + tiot_board_uart_port *port = &g_tiot_board_uart_port[port_type]; + const uart_attr_t init_attr = { 115200, UART_DATA_BIT_8, UART_STOP_BIT_1, UART_PARITY_NONE, + ((port->flow_ctrl_bk == TIOT_UART_ATTR_FLOW_CTRL_ENABLE) ? + UART_FLOW_CTRL_RTS_CTS : UART_FLOW_CTRL_NONE) }; + port->pin_config.tx_pin = port->pin_config_orig.tx_pin; + port->pin_config.rx_pin = port->pin_config_orig.rx_pin; + if (tiot_board_uart_reopen((uart_bus_t)xmit->id, port, &init_attr) != 0) { + return -1; + } + g_tiot_xmit_cbs = *cbs; + port->xmit = xmit; + xmit->handle = port; + return 0; +} + +void tiot_board_uart_close(tiot_xmit *xmit) +{ + uapi_uart_unregister_rx_callback(xmit->id); + (void)uapi_uart_deinit(xmit->id); +} + +int32_t tiot_board_uart_write(tiot_xmit *xmit, const uint8_t *buff, uint32_t len) +{ + return uapi_uart_write(xmit->id, buff, len, TIOT_UAPI_RW_TIMEOUT); +} + +int32_t tiot_board_uart_read(tiot_xmit *xmit, uint8_t *buff, uint32_t len) +{ + return uapi_uart_read(xmit->id, buff, len, TIOT_UAPI_RW_TIMEOUT); +} + +int32_t tiot_board_uart_set_config(tiot_xmit *xmit, tiot_uart_config *config) +{ + errcode_t ret; + tiot_board_uart_port *port = xmit->handle; + if ((config == NULL) || (config->attr.data_bits >= TIOT_UART_ATTR_DATABIT_BUTT) || + (config->attr.stop_bits >= TIOT_UART_ATTR_STOPBIT_BUTT) || + (config->attr.parity >= TIOT_UART_ATTR_PARITY_BUTT)) { + return -1; + } + if (port == NULL) { + return -1; + } + /* 确保当前无数据正在FIFO内传输,才能修改配置. */ + while (uapi_uart_has_pending_transmissions(xmit->id) == true) {;} + + const uart_attr_t attr = { config->baudrate, UART_DATA_BIT_8, UART_STOP_BIT_1, UART_PARITY_NONE, + ((config->attr.flow_ctrl == TIOT_UART_ATTR_FLOW_CTRL_ENABLE) ? + UART_FLOW_CTRL_RTS_CTS : UART_FLOW_CTRL_NONE) }; + /* 调整流控需要重新init. */ + if (config->attr.flow_ctrl != port->flow_ctrl_bk) { + port->flow_ctrl_bk = config->attr.flow_ctrl; + if (tiot_board_uart_reopen((uart_bus_t)xmit->id, port, &attr) != 0) { + return -1; + } + } + ret = uapi_uart_set_attr(xmit->id, &attr); + return (ret == ERRCODE_SUCC) ? 0 : -1; +} diff --git a/code/sdk/zhihui/gnss/driver/product_porting/readme.txt b/code/sdk/zhihui/gnss/driver/product_porting/readme.txt new file mode 100644 index 000000000..53939afab --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/readme.txt @@ -0,0 +1,2 @@ +TCXO时钟26M + 硬件流控连接 +TCXO时钟26M + 硬件流控悬空 + 无文件系统及动态内存 \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/product_porting/tiot_autoconfig.h b/code/sdk/zhihui/gnss/driver/product_porting/tiot_autoconfig.h new file mode 100644 index 000000000..fc27814a9 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/tiot_autoconfig.h @@ -0,0 +1,27 @@ +/* Config 0/2 Common */ +#define CONFIG_DEV_GNSS 1 +#define CONFIG_GNSS_DEV_NUM 1 +#define CONFIG_GNSS_WAKEUP_TYPE_UART 1 +#define CONFIG_GNSS_TCXO_FREQ_26M 1 +#define CONFIG_GNSS_UART_BAUDRATE 115200 +#define CONFIG_FILE_BY_ARRAY 1 +#define CONFIG_FIRMWARE_CFG_HANDLE_PRIV 1 +#define CONFIG_FIRMWARE_FILE_READ_BUF_LEN 1029 +#define CONFIG_PM_WAKEUP_BY_UART 1 +#define CONFIG_PM_MANAGE_LOWPOWER 1 +#define CONFIG_XMIT_WITH_UART 1 +#define CONFIG_UART_RX_MODE_BUFFED 1 +#define CONFIG_XFER_PACKET_TIOT 1 +#define CONFIG_XFER_DEFAULT_RX_BUFF 1 +#define CONFIG_XFER_RX_BUFF_SIZE 512 + + +/**Config2 OSAL 已有, 安全应用已经实现, 动态申请内存*/ +#define CONFIG_OSAL_DEFINED 1 +#define CONFIG_LIBBOUNDSCHECK_IMPLEMENTED 1 +#define CONFIG_BOARD_DYNAMIC_ALLOC 1 + +/* Config0 */ +#if (CONFIG_BOARD_DYNAMIC_ALLOC != 1) +#define CONFIG_GNSS_PACKET_BUFF_MAX 10000 +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/driver/product_porting/tiot_defconfig b/code/sdk/zhihui/gnss/driver/product_porting/tiot_defconfig new file mode 100644 index 000000000..a84e7eaa1 --- /dev/null +++ b/code/sdk/zhihui/gnss/driver/product_porting/tiot_defconfig @@ -0,0 +1,101 @@ +# Generated by HiCFBB Kconfig Tool. +# Note: !!!This file can not be modify manually!!! + +# +# Devices +# + +# +# Config the devices. +# +CONFIG_DEV_GNSS=y +CONFIG_GNSS_DEV_NUM=1 +CONFIG_GNSS_WAKEUP_TYPE_UART=y +# CONFIG_GNSS_WAKEUP_TYPE_GPIO is not set +CONFIG_GNSS_TCXO_FREQ_26M=y +# CONFIG_GNSS_TCXO_FREQ_38P4M is not set +CONFIG_GNSS_UART_BAUDRATE=115200 +# CONFIG_GNSS_UART_WITH_FLOWCTRL is not set +CONFIG_GNSS_PACKET_BUFF_MAX=10000 +# CONFIG_DEV_W33 is not set +# CONFIG_DEV_CA01 is not set +# end of Devices + +# +# Common +# + +# +# Config common modules. +# + +# +# Misc +# +CONFIG_FILE_BY_ARRAY=y +CONFIG_OSAL_DEFINED=y +CONFIG_LIBBOUNDSCHECK_IMPLEMENTED=y +CONFIG_BOARD_DYNAMIC_ALLOC=y +# end of Misc + +# +# Firmware Load +# + +# +# Firmware load module. +# +CONFIG_FIRMWARE_CFG_HANDLE_PRIV=y +# CONFIG_FIRMWARE_CFG_HANDLE_XCI is not set +CONFIG_FIRMWARE_FILE_READ_BUF_LEN=1029 +# end of Firmware Load + +# +# Power Management +# + +# +# Power management module. +# +CONFIG_PM_WAKEUP_BY_UART=y +CONFIG_PM_MANAGE_LOWPOWER=y +# end of Power Management + +# +# Transfer +# + +# +# Transfer module. +# + +# +# Transmit Type Support +# + +# +# Transmit type support. +# +CONFIG_XMIT_WITH_UART=y +# CONFIG_XMIT_WITH_SPI is not set +# CONFIG_XMIT_WITH_I2C is not set +CONFIG_UART_RX_MODE_BUFFED=y +# CONFIG_UART_RX_MODE_BLOCK is not set +# end of Transmit Type Support + +# +# Packet Handle Support +# + +# +# Pakcet handle support. +# +CONFIG_XFER_PACKET_TIOT=y +# CONFIG_XFER_PACKET_NCI is not set +# end of Packet Handle Support + +CONFIG_XFER_DEFAULT_RX_BUFF=y +CONFIG_XFER_RX_BUFF_SIZE=512 +# CONFIG_XFER_TX_SUPPORT_TASK is not set +# end of Transfer +# end of Common diff --git a/code/sdk/zhihui/gnss/gnss_ctl.h b/code/sdk/zhihui/gnss/inc/gnss_ctl.h similarity index 100% rename from code/sdk/zhihui/gnss/gnss_ctl.h rename to code/sdk/zhihui/gnss/inc/gnss_ctl.h diff --git a/code/sdk/zhihui/gnss/uart_gnss.h b/code/sdk/zhihui/gnss/inc/uart_gnss.h similarity index 100% rename from code/sdk/zhihui/gnss/uart_gnss.h rename to code/sdk/zhihui/gnss/inc/uart_gnss.h diff --git a/code/sdk/zhihui/gnss/sample/agnss_sample/CMakeLists.txt b/code/sdk/zhihui/gnss/sample/agnss_sample/CMakeLists.txt new file mode 100644 index 000000000..5b80af730 --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/agnss_sample/CMakeLists.txt @@ -0,0 +1,41 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. +#=============================================================================== +set(COMPONENT_NAME "agnss_sample") + +set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/agnss_sample.c + ${CMAKE_CURRENT_SOURCE_DIR}/agnss_encode.c +) + +set(PRIVATE_HEADER +) + +set(PUBLIC_HEADER + ${CMAKE_CURRENT_SOURCE_DIR} +) + +set(PRIVATE_DEFINES +) + +set(PUBLIC_DEFINES +CONFIG_AGNSS_SAMPLE +) + +set(COMPONENT_CCFLAGS + -Wno-implicit-function-declaration +) + +set(WHOLE_LINK +true +) + +set(BUILD_AS_OBJ +false +) + +set(MAIN_COMPONENT +false +) +build_component() diff --git a/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_encode.c b/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_encode.c new file mode 100644 index 000000000..9309437b0 --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_encode.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * Description: agnss encode + * Author: + * Create: + */ +#include "agnss_encode.h" +#include +#include +#include +#include "securec.h" +#include "gnss_datatypes.h" +#include "tiot_service_interface.h" + +#define GNSS_ENCODE_BUFF_MAX_LEN 9300 +#define FILE_PATH_LEN 1024 +#define INJECT_SLEEP_MS_TIME 500 +#define REPORT_MAX_BYTES 10000 +#define LISTEN_TIME_THR 1000 +#define AGNSS_FILE_MAX_SIZE 1024000 +#define AGNSS_DATA_PATH "/user/xgnss/AGNSS.dat" // 可自行配置路径 + +// 监听消息 +static uint8_t g_ackBuff[REPORT_MAX_BYTES] = { 0 }; + +/* 计算命令内容校准和 */ +static uint16_t CalcChecksum(uint8_t *buff, uint16_t len) +{ + uint16_t checksum = 0; + uint16_t i = 0; + while (i++ < len) { + checksum += *buff; + buff++; + } + return checksum; +} + +/* AGNSS计算内容校准和, 校验和模256,与芯片侧的命令校验和计算不可混用 */ +uint8_t CalcAgnssCheckSum(uint8_t *data, uint16_t len) +{ + uint8_t sum = 0; + for (uint16_t i = 0; i < len; i++) { + sum += data[i]; + } + return sum; +} + +int32_t AgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime) +{ + uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN); + if (buff == NULL) { + printf("\nerror: malloc failed in AgnssInjectUtcTime\n"); + return 0; + } + memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN); + + GnssMsg *hdr = (GnssMsg *)buff; + hdr->cmd = CMD_XGNSS_INJECT_UTC_TIME; + hdr->sequence = 0; + errno_t copyRet = memcpy_s(hdr->data, (GNSS_ENCODE_BUFF_MAX_LEN - sizeof(GnssMsg)), utcTime, sizeof(GnssUtcTime)); + if (copyRet != EOK) { + printf("\nmemcpy UtcTime failed! Errno is %d\n", copyRet); + free(buff); + return 0; + } + hdr->dataLength = sizeof(GnssUtcTime); + hdr->checkSum = CalcChecksum(hdr->data, hdr->dataLength); + int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + hdr->dataLength)); + if (ret < 0) { + printf("\nerror: AgnssInjectUtcTime error: %d\n", ret); + free(buff); + return 0; + } + + free(buff); + return 1; +} + +static uint16_t FillGnssMessageData(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen) +{ + errno_t ret = memcpy_s(outBuff, outLen, inBuff, inLen); + if (ret != EOK) { + printf("memcpy XgnssData failed! Errno is %d", ret); + return 0; + } + + return inLen; +} + +static int32_t EncodeGnssMsg(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen) +{ + uint16_t len = FillGnssMessageData(inBuff, inLen, outBuff, outLen); + if (len > 0) { + return 1; + } + return 0; +} + +static void ListenAck(tiot_handle handle) +{ + int32_t i = 0; + for (;;) { + // 监听 + int32_t ret = tiot_service_read(handle, g_ackBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR); + if (ret > 0) { + uint16_t *type = (uint16_t *)g_ackBuff; + // 二进制消息类型 + if (type[0] == 0) { + g_ackBuff[ret] = '\0'; + printf("%s\n", (char *)&g_ackBuff[MSG_CONTENT_IDX]); + } + i++; + } + if (i >= 1) { + printf("\ncnt enough\n"); + break; + } + } +} + +static int32_t EncodeAndInjectCmd(tiot_handle handle, GnssCmdType cmdType, uint8_t* inBuff, uint32_t inLen) +{ + // 获取GNSS业务消息头 + int32_t len = 0; + uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN); + if (buff == NULL) { + printf("\nerror: malloc failed in EncodeAndInjectCmd\n"); + return 0; + } + memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN); + + GnssMsg *gnssHdr = (GnssMsg *)buff; + len += sizeof(GnssMsg); + + gnssHdr->sequence = 0; + + int32_t retLen = EncodeGnssMsg(inBuff, inLen, buff + len, (GNSS_ENCODE_BUFF_MAX_LEN - len)); + if (retLen != 1) { + printf("\nerror: Encode Cmd failed: %d\n", cmdType); + free(buff); + return retLen; + } + gnssHdr->cmd = cmdType; + gnssHdr->dataLength = inLen; + gnssHdr->checkSum = CalcChecksum(gnssHdr->data, gnssHdr->dataLength); + int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + gnssHdr->dataLength)); + if (ret < 0) { + printf("\nerror: Inject Cmd failed: %d\n", cmdType); + free(buff); + return 0; + } + ListenAck(handle); + printf("\nInject Cmd SUCCESS: %x\n", cmdType); + free(buff); + return 1; +} + +void ProcAndInjectAgnssCmd(tiot_handle handle, uint16_t dataType, uint8_t *data, uint16_t dataLen) +{ + /* 1.根据AGNSS dataType类型,转换为芯片侧消息类型 */ + const struct { + AgnssDataType agnssDataType; // AGNSS type类型, + GnssCmdType innerType; // 芯片侧消息类型 + } table[] = { + {AGNSS_GPS_INJECT_EPH, CMD_AGNSS_INJECT_NAV}, + {AGNSS_GPS_INJECT_UTC, CMD_AGNSS_INJECT_UTC}, + {AGNSS_GPS_INJECT_ION, CMD_AGNSS_INJECT_IONO}, + {AGNSS_GPS_INJECT_RTI, CMD_AGNSS_INJECT_RTI}, + {AGNSS_GLO_INJECT_EPH, CMD_AGNSS_INJECT_GANSS_NAV}, + {AGNSS_GLO_INJECT_RTI, CMD_AGNSS_INJECT_GANSS_RTI}, + {AGNSS_GLO_INJECT_AUX, CMD_AGNSS_INJECT_GANSS_AUXI}, + {AGNSS_BDS_INJECT_EPH, CMD_AGNSS_INJECT_GANSS_NAV}, + {AGNSS_BDS_INJECT_ION, CMD_AGNSS_INJECT_GANSS_ADDL_IONO}, + {AGNSS_BDS_INJECT_RTI, CMD_AGNSS_INJECT_GANSS_RTI}, + {AGNSS_GAL_INJECT_EPH, CMD_AGNSS_INJECT_GANSS_NAV}, + {AGNSS_GAL_INJECT_RTI, CMD_AGNSS_INJECT_GANSS_RTI} + }; + uint16_t cmdType = 0; + // 2.遍历对应关系表 + for (int i = 0; i < sizeof(table) / sizeof(table[0]); i++) { + if (dataType == table[i].agnssDataType) { + cmdType = (uint16_t)table[i].innerType; + // 3.找到对应芯片侧消息类型,并下发消息 + EncodeAndInjectCmd(handle, cmdType, data, dataLen); + break; + } + } + osal_msleep(INJECT_SLEEP_MS_TIME); +} + +void AgnssInjectAllContent(tiot_handle handle, uint8_t *buff, int32_t len) +{ + int32_t remainLen = len; + // tlv + while ((uint32_t)remainLen >= sizeof(AgnssDataHeader) + sizeof(AgnssDataTail)) { + AgnssDataHeader *header = (AgnssDataHeader *)buff; + uint16_t dataLen = header->len; + if ((uint32_t)remainLen < sizeof(AgnssDataHeader) + sizeof(AgnssDataTail) + dataLen) { + printf("AgnssInjectAllContent: remainLen %d and dataLen %d not match\n", remainLen, dataLen); + return; + } + uint8_t localCheckSum = CalcAgnssCheckSum((uint8_t *)header, (header->data - (uint8_t *)header) + dataLen); + uint8_t checkSum = ((AgnssDataTail *)(header->data + dataLen))->checkSum; + if (localCheckSum != checkSum) { + printf("AgnssInjectAllContent: local CheckSum %d and CheckSum %d not match\n", localCheckSum, checkSum); + return; + } + ProcAndInjectAgnssCmd(handle, header->dataType, header->data, dataLen); + buff += sizeof(AgnssDataHeader) + sizeof(AgnssDataTail) + dataLen; + remainLen -= sizeof(AgnssDataHeader) + sizeof(AgnssDataTail) + dataLen; + } +} + +void ProcAgnssFileContent(tiot_handle handle) +{ + char fileName[] = AGNSS_DATA_PATH; + FILE *fp = fopen(fileName, "rb"); + if (fp == NULL) { + printf("\nerror: open file failed: %s\n", fileName); + return; + } + fseek(fp, 0, SEEK_END); + int32_t len = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (len < 0 || len > AGNSS_FILE_MAX_SIZE) { + fclose(fp); + printf("\nerror: get file len failed: %s\n", fileName); + return; + } + uint8_t *buff = (uint8_t *)malloc(len); + if (buff == NULL) { + fclose(fp); + printf("\nerror: malloc file len failed: %s\n", fileName); + return; + } + int32_t dataSize = fread(buff, len, 1, fp); + if (dataSize < 0) { + fclose(fp); + printf("\nerror: read file failed: %s\n", fileName); + free(buff); + return; + } + fclose(fp); + AgnssInjectAllContent(handle, buff, len); + free(buff); +} + +void AgnssInject(tiot_handle handle) +{ + // 处理AGNSS文件,向芯片注入Agnss辅助数据 + ProcAgnssFileContent(handle); +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_encode.h b/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_encode.h new file mode 100644 index 000000000..bbef15353 --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_encode.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * Description: agnss encode + * Author: + * Create: + */ +#ifndef AGNSS_ENCODE_H +#define AGNSS_ENCODE_H + +#include "gnss_datatypes.h" +#include "tiot_service_interface.h" + +int32_t AgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime); +void AgnssInject(tiot_handle handle); +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_sample.c b/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_sample.c new file mode 100644 index 000000000..537608d5c --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_sample.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * Description: agnss sample + * Author: + * Create: + */ +#include "agnss_sample.h" +#include +#include "securec.h" +#include "tiot_service_interface.h" +#include "pm_definition.h" +#include "gnss_datatypes.h" +#include "agnss_encode.h" + +#define AGNSS_FIXMODEALL_NMEADEF_SAMPLE 0 + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif + +#define MSG_TYPE_BINRY 0 +#define MSG_TYPE_ASCII 1 +#define LISTEN_DATA_MAX_LINES 1000 +#define REPORT_MAX_BYTES 10000 + +static FILE* g_gnssLogFp = NULL; +static uint8_t g_gnssServiceBuff[REPORT_MAX_BYTES] = { 0 }; + +typedef int32_t (*GnssCfgFunc)(tiot_handle handle); + +typedef struct { + uint16_t sampleId; + GnssCfgFunc cfgHandle; +} GnssSamplesCfgTable; + +static int32_t QryVersion(tiot_handle handle) +{ + const uint8_t qryVersion[] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; + // 查询版本号 + int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion)); + if (ret < 0) { + printf("error: QryVersion error: %d\n", ret); + return 0; + } + return 1; +} + +// 注入AGNSS,使用默认配置启动 +int32_t InjectAgnss(tiot_handle handle) +{ + const uint8_t cfgLogLevelInfo[] = {0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x10, 0x01, 0x00, 0x03}; + + // 配置log级别:info级别。 + int32_t ret = tiot_service_write(handle, cfgLogLevelInfo, sizeof(cfgLogLevelInfo)); + if (ret < 0) { + printf("error: cfgLogLevelInfo error: %d\n", ret); + return 0; + } + + // 注入UTC时间, 注入Agnss辅助数据前必须先注入参考时间 + GnssUtcTime utcTime = {2024, 3, 22, 10, 0, 0, 0, 1}; // 需要用当前的UTC时间替换 + ret = AgnssInjectUtcTime(handle, &utcTime); + if (ret == 0) { + printf("error: AgnssInjectUtcTime failed!\n"); + return 0; + } + printf("AgnssInjectUtcTime success!\n"); + + // AGNSS注入 + // 注意,默认AGNSS文件存放在/user/xgnss/目录中,如修改目录,请全局搜索替换 + AgnssInject(handle); + + return 1; +} + +static const GnssSamplesCfgTable g_gnssSamplesCfg[] = { + {AGNSS_FIXMODEALL_NMEADEF_SAMPLE, InjectAgnss}, +}; + +static int32_t StartGnss(tiot_handle handle) +{ + const uint8_t startCmd[] = {0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + // 启动GNSS + int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd)); + if (ret < 0) { + printf("error: start gnss error: %d\n", ret); + return 0; + } + printf("start gnss\n"); + return 1; +} + +static int32_t StopGnss(tiot_handle handle) +{ + const uint8_t stopCmd[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + // 停止GNSS + int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd)); + if (ret < 0) { + printf("error: stop gnss error: %d\n", ret); + return 0; + } + printf("stop gnss\n"); + return 1; +} + +static void ListenGnssData(tiot_handle handle) +{ + int32_t i = 0; + // 写日志 + for (;;) { // 写日志条件 + // 监听 + int32_t ret = tiot_service_read(handle, g_gnssServiceBuff, REPORT_MAX_BYTES, 1000); + if (ret > 0) { + uint16_t *type = (uint16_t *)g_gnssServiceBuff; + if (type[0] == MSG_TYPE_ASCII) { + g_gnssServiceBuff[ret] = '\0'; + printf("%s\n", (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]); + fprintf(g_gnssLogFp, "%s\n", (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]); + } + i++; + } + if (i >= LISTEN_DATA_MAX_LINES) { + printf("cnt enough\n"); + break; + } + } +} + +void AgnssExecuteSamples(void) +{ + uapi_pm_add_sleep_veto(PM_ID_SYS); + printf("enter gnss samples\n"); + // Step1: init + int32_t ret = tiot_service_init(); + if (ret != 0) { + printf("tiot service init fail\n"); + } + + // 打开日志文件 + g_gnssLogFp = fopen("/user/gnss.log", "w"); + if (g_gnssLogFp == NULL) { + printf("error: open log file error\n"); + return; + } + printf("before open tiot service\n"); + + // Step2: power on gnss + tiot_handle handle = tiot_service_open("gn71", NULL); + if (handle == 0) { + printf("open tiot service fail\n"); + return; + } + printf("open tiot service success\n"); + + int32_t cfgRet; + // ---- loop ---------- + for (uint16_t i = 0; i < ARRAY_SIZE(g_gnssSamplesCfg); i++) { + cfgRet = 0; + if (g_gnssSamplesCfg[i].sampleId == i) { + // Step3: config gnss + if (g_gnssSamplesCfg[i].cfgHandle != NULL) { + cfgRet = g_gnssSamplesCfg[i].cfgHandle(handle); + } + if (cfgRet == 0) { + continue; + } + printf("cfg sample id:%u\n", g_gnssSamplesCfg[i].sampleId); + QryVersion(handle); + + // Step4: start gnss + if (StartGnss(handle) == 0) { + continue; + } + // Step5: listening gnss data + ListenGnssData(handle); + // Step6: stop gnss + if (StopGnss(handle) == 0) { + continue; + } + } + } + // --------------------- + // Step7: power off gnss + tiot_service_close(handle); + // 关日志文件 + fclose(g_gnssLogFp); + g_gnssLogFp = NULL; + // Step8: deinit + tiot_service_deinit(); + uapi_pm_remove_sleep_veto(PM_ID_SYS); + printf("finish gnss samples\n"); +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_sample.h b/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_sample.h new file mode 100644 index 000000000..8c8823b90 --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/agnss_sample/agnss_sample.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * Description: agnss sample + * Author: + * Create: + */ +#ifndef AGNSS_SAMPLE_H +#define AGNSS_SAMPLE_H + +void AgnssExecuteSamples(void); + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/sample/agnss_sample/gnss_datatypes.h b/code/sdk/zhihui/gnss/sample/agnss_sample/gnss_datatypes.h new file mode 100644 index 000000000..97607f9c7 --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/agnss_sample/gnss_datatypes.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * Description: gnss datatypes + * Author: + * Create: + */ +#ifndef GNSS_DATATYPES_H +#define GNSS_DATATYPES_H + +#include + +#define MSG_CONTENT_IDX 2 + +// 消息类型 +typedef enum { + CMD_AGNSS_INJECT_REF_LOC = 0x0302, // 位置预测注入 + CMD_AGNSS_INJECT_NAV = 0x0303, // 星历数据注入 + CMD_AGNSS_INJECT_IONO = 0x0304, // 电离层参数注入 + CMD_AGNSS_INJECT_UTC = 0x0305, // UTC时间注入 + CMD_AGNSS_INJECT_RTI = 0x0306, // 完好性信息注入 + CMD_AGNSS_INJECT_GANSS_ADDL_IONO = 0x0308, // 非GPS电离层参数注入 + CMD_AGNSS_INJECT_GANSS_NAV = 0x0309, // 非GPS星历数据注入 + CMD_AGNSS_INJECT_GANSS_RTI = 0x030A, // 非GPS完好性信息注入 + CMD_AGNSS_INJECT_GANSS_AUXI = 0x030C, // 频点对应关系注入,GLONASS + CMD_XGNSS_INJECT_UTC_TIME = 0x0404, // 最开始注入的UTC时间 + CMD_BUTT, +} GnssCmdType; + +typedef enum { + AGNSS_GPS_INJECT_EPH = 0x0002, + AGNSS_GPS_INJECT_UTC = 0x0003, + AGNSS_GPS_INJECT_ION = 0x0004, + AGNSS_GPS_INJECT_RTI = 0x0005, + AGNSS_GLO_INJECT_EPH = 0x0022, + AGNSS_GLO_INJECT_RTI = 0x0025, + AGNSS_GLO_INJECT_AUX = 0x0026, + AGNSS_BDS_INJECT_EPH = 0x0042, + AGNSS_BDS_INJECT_ION = 0x0044, + AGNSS_BDS_INJECT_RTI = 0x0045, + AGNSS_GAL_INJECT_EPH = 0x0062, + AGNSS_GAL_INJECT_RTI = 0x0065 +} AgnssDataType; + +#pragma pack(1) +typedef struct { + uint16_t cmd; // 消息类型 + uint16_t checkSum; // 校验和,只计算实际数据部分,不包含头 + uint16_t sequence; // 序列号,host下发 + uint16_t dataLength; // 数据长度,实际数据的长度,不包含头 + uint8_t data[0]; +} GnssMsg; + +typedef struct { + uint16_t year; // YYYY + uint8_t month; // MM, 1~12 + uint8_t day; // DD, 1~31 + uint8_t hour; // hh, 0~23 + uint8_t minute; // mm, 0~59 + uint8_t second; // ss, 0~59 + uint16_t ms; // ms, 0~999 + uint8_t valid; // 0: invalid, 1: valid +} GnssUtcTime; + +typedef struct { + uint16_t dataType; + uint16_t len; + uint8_t data[0]; +} AgnssDataHeader; + +typedef struct { + uint8_t checkSum; +} AgnssDataTail; + +#pragma pack() + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/sample/gnss_sample/CMakeLists.txt b/code/sdk/zhihui/gnss/sample/gnss_sample/CMakeLists.txt new file mode 100644 index 000000000..780a541cf --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/gnss_sample/CMakeLists.txt @@ -0,0 +1,41 @@ +#=============================================================================== +# @brief cmake make file +# Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. +#=============================================================================== +set(COMPONENT_NAME "gnss_sample") + +set(SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/gnss_sample.c +) + +set(PRIVATE_HEADER + ${TIOT_HEADER_LIST} +) + +set(PUBLIC_HEADER + ${CMAKE_CURRENT_SOURCE_DIR} +) + +set(PRIVATE_DEFINES +) + +set(PUBLIC_DEFINES +CONFIG_GNSS_SAMPLE +) + +set(COMPONENT_CCFLAGS + -Wno-implicit-function-declaration +) + +set(WHOLE_LINK +true +) + +set(BUILD_AS_OBJ +false +) + +set(MAIN_COMPONENT +false +) +build_component() diff --git a/code/sdk/zhihui/gnss/sample/gnss_sample/gnss_sample.c b/code/sdk/zhihui/gnss/sample/gnss_sample/gnss_sample.c new file mode 100644 index 000000000..18e1d8a71 --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/gnss_sample/gnss_sample.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: gnss sample + * Author: + * Create: + */ +#include "gnss_sample.h" +#include +#include "securec.h" +#include "tiot_service_interface.h" +#include "pm_definition.h" + +#define COLDSTART_FIXMODEGPS_NMEAALL_SAMPLE 0 +#define AUTOSTART_FIXMODEALL_NMEADEF_SAMPLE 1 + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif +#define MSG_CONTENT_IDX 2 +#define MSG_TYPE_BINRY 0 +#define MSG_TYPE_ASCII 1 +#define LISTEN_DATA_MAX_LINES 1000 +#define REPORT_MAX_BYTES 10000 +#define LISTEN_TIME_THR 1000 + +static FILE* g_gnssLogFp = NULL; +static uint8_t g_gnssServiceBuff[REPORT_MAX_BYTES] = { 0 }; + +typedef int32_t (*GnssCfgFunc)(tiot_handle handle); + +typedef struct { + uint16_t sampleId; + GnssCfgFunc cfgHandle; +} GnssSamplesCfgTable; + +int32_t CfgColdStartFixModeGpsNmeaAll(tiot_handle handle) +{ + const uint8_t cfgColdStartCmd[] = {0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; + const uint8_t cfgFixModeGpsCmd[] = {0x03, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, + 0x00, 0x00, 0x00}; + const uint8_t cfgNmeaAllCmd[] = {0x03, 0x00, 0x04, 0x01, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0xff, + 0x00}; + // 配置启动模式:冷启动模式。 + int32_t ret = tiot_service_write(handle, cfgColdStartCmd, sizeof(cfgColdStartCmd)); + if (ret < 0) { + printf("\nerror: cfgColdStartCmd error: %d\n", ret); + return 0; + } + + // 配置使能的GNSS星座:GPS。 + ret = tiot_service_write(handle, cfgFixModeGpsCmd, sizeof(cfgFixModeGpsCmd)); + if (ret < 0) { + printf("\nerror: cfgFixModeGpsCmd error: %d\n", ret); + return 0; + } + + // 配置上报NMEA类型:PNT/ZDA/VTG/RMC/GSV/GSA/GLL/GGA。 + ret = tiot_service_write(handle, cfgNmeaAllCmd, sizeof(cfgNmeaAllCmd)); + if (ret < 0) { + printf("\nerror: cfgNmeaAllCmd error: %d\n", ret); + return 0; + } + return 1; +} + +// 如果有历史信息,自动模式启动会切换到热启动模式,如果无历史信息,则自动模式启动仍然为冷启动 +int32_t CfgAutoStartFixModeAllNmeaDefault(tiot_handle handle) +{ + const uint8_t cfgFixModeAllCmd[] = {0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1f, + 0x00, 0x00, 0x00}; + const uint8_t cfgAutoStartCmd[] = {0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00}; + const uint8_t cfgNmeaDefaultCmd[] = {0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0x11, + 0x00}; + + // 配置启动模式:自动模式。 + int32_t ret = tiot_service_write(handle, cfgAutoStartCmd, sizeof(cfgAutoStartCmd)); + if (ret < 0) { + printf("\nerror: cfgAutoStartCmd error: %d\n", ret); + return 0; + } + + // 配置使能的GNSS星座:QZSS/GAL/BDS/GLO/GPS。 + ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd)); + if (ret < 0) { + printf("\nerror: cfgFixModeAllCmd error: %d\n", ret); + return 0; + } + + // 配置上报NMEA类型:RMC/GGA。 + ret = tiot_service_write(handle, cfgNmeaDefaultCmd, sizeof(cfgNmeaDefaultCmd)); + if (ret < 0) { + printf("\nerror: cfgNmeaDefaultCmd error: %d\n", ret); + return 0; + } + return 1; +} + +static int32_t QryVersion(tiot_handle handle) +{ + const uint8_t qryVersion[] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; + // 查询版本号 + int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion)); + if (ret < 0) { + printf("\nerror: QryVersion error: %d\n", ret); + return 0; + } + return 1; +} + +static const GnssSamplesCfgTable g_gnssSamplesCfg[] = { + {COLDSTART_FIXMODEGPS_NMEAALL_SAMPLE, CfgColdStartFixModeGpsNmeaAll}, + {AUTOSTART_FIXMODEALL_NMEADEF_SAMPLE, CfgAutoStartFixModeAllNmeaDefault} +}; + +static int32_t StartGnss(tiot_handle handle) +{ + const uint8_t startCmd[] = {0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + // 启动GNSS + int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd)); + if (ret < 0) { + printf("\nerror: start gnss error: %d\n", ret); + return 0; + } + printf("\nstart gnss\n"); + return 1; +} + +static int32_t StopGnss(tiot_handle handle) +{ + const uint8_t stopCmd[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + // 停止GNSS + int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd)); + if (ret < 0) { + printf("\nerror: stop gnss error: %d\n", ret); + return 0; + } + printf("\nstop gnss\n"); + return 1; +} + +static void ListenGnssData(tiot_handle handle) +{ + int32_t i = 0; + // 写日志 + for (;;) { // 写日志条件 + // 监听 + int32_t ret = tiot_service_read(handle, g_gnssServiceBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR); + if (ret > 0) { + uint16_t *type = (uint16_t *)g_gnssServiceBuff; + if (type[0] == MSG_TYPE_ASCII) { + g_gnssServiceBuff[ret] = '\0'; + printf("%s\n", (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]); + fprintf(g_gnssLogFp, "%s\n", (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]); + } + i++; + } + if (i >= LISTEN_DATA_MAX_LINES) { + printf("\ncnt enough\n"); + break; + } + } +} + +void GnssExecuteSamples(void) +{ + uapi_pm_add_sleep_veto(PM_ID_SYS); + printf("\nenter gnss samples\n"); + // Step1: init + int32_t ret = tiot_service_init(); + if (ret != 0) { + printf("\ntiot service init fail\n"); + } + + // 打开日志文件 + g_gnssLogFp = fopen("/user/gnss.log", "w"); + if (g_gnssLogFp == NULL) { + printf("\nerror: open log file error\n"); + return; + } + printf("\nbefore open tiot service\n"); + + // Step2: power on gnss + tiot_handle handle = tiot_service_open("gn71", NULL); + if (handle == 0) { + printf("\nopen tiot service fail\n"); + return; + } + printf("\nopen tiot service success\n"); + + int32_t cfgRet; + // ---- loop ---------- + for (uint16_t i = 0; i < ARRAY_SIZE(g_gnssSamplesCfg); i++) { + cfgRet = 0; + if (g_gnssSamplesCfg[i].sampleId == i) { + // Step3: config gnss + if (g_gnssSamplesCfg[i].cfgHandle != NULL) { + cfgRet = g_gnssSamplesCfg[i].cfgHandle(handle); + } + if (cfgRet == 0) { + continue; + } + printf("\ncfg sample id:%u\n", g_gnssSamplesCfg[i].sampleId); + QryVersion(handle); + + // Step4: start gnss + if (StartGnss(handle) == 0) { + continue; + } + // Step5: listening gnss data + ListenGnssData(handle); + // Step6: stop gnss + if (StopGnss(handle) == 0) { + continue; + } + } + } + // --------------------- + // Step7: power off gnss + tiot_service_close(handle); + // 关日志文件 + fclose(g_gnssLogFp); + g_gnssLogFp = NULL; + // Step8: deinit + tiot_service_deinit(); + uapi_pm_remove_sleep_veto(PM_ID_SYS); + printf("\nfinish gnss samples\n"); +} \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/sample/gnss_sample/gnss_sample.h b/code/sdk/zhihui/gnss/sample/gnss_sample/gnss_sample.h new file mode 100644 index 000000000..9d3d27544 --- /dev/null +++ b/code/sdk/zhihui/gnss/sample/gnss_sample/gnss_sample.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: gnss sample + * Author: + * Create: + */ +#ifndef GNSS_SAMPLE_H +#define GNSS_SAMPLE_H + +void GnssExecuteSamples(void); + +#endif \ No newline at end of file diff --git a/code/sdk/zhihui/gnss/gnss_config_array.c b/code/sdk/zhihui/gnss/src/gnss_config_array.c similarity index 100% rename from code/sdk/zhihui/gnss/gnss_config_array.c rename to code/sdk/zhihui/gnss/src/gnss_config_array.c diff --git a/code/sdk/zhihui/gnss/gnss_ctl.c b/code/sdk/zhihui/gnss/src/gnss_ctl.c similarity index 100% rename from code/sdk/zhihui/gnss/gnss_ctl.c rename to code/sdk/zhihui/gnss/src/gnss_ctl.c diff --git a/code/sdk/zhihui/gnss/uart_gnss.c b/code/sdk/zhihui/gnss/src/uart_gnss.c similarity index 91% rename from code/sdk/zhihui/gnss/uart_gnss.c rename to code/sdk/zhihui/gnss/src/uart_gnss.c index f6ad3ac2e..64f288e8a 100644 --- a/code/sdk/zhihui/gnss/uart_gnss.c +++ b/code/sdk/zhihui/gnss/src/uart_gnss.c @@ -29,11 +29,11 @@ #include "custom_utils.h" #include "uart_gnss.h" #include "gnss_ctl.h" -errcode_t gnss_get_next_cmd(uint8_t cmd_index,uint8_t** cmdbuf,int *cmdlen); -errcode_t gnss_get_current_cmd(uint8_t cmd_index,uint8_t** cmdbuf,int *cmdlen); -errcode_t gnss_get_nmea_cfg_cmd(uint8_t** cmdbuf,int *cmdlen); -errcode_t gnss_get_stop_cmd(uint8_t** cmdbuf,int *cmdlen); -errcode_t gnss_get_start_cmd(uint8_t** cmdbuf,int *cmdlen); +// errcode_t gnss_get_next_cmd(uint8_t cmd_index,uint8_t** cmdbuf,int *cmdlen); +// errcode_t gnss_get_current_cmd(uint8_t cmd_index,uint8_t** cmdbuf,int *cmdlen); +// errcode_t gnss_get_nmea_cfg_cmd(uint8_t** cmdbuf,int *cmdlen); +// errcode_t gnss_get_stop_cmd(uint8_t** cmdbuf,int *cmdlen); +// errcode_t gnss_get_start_cmd(uint8_t** cmdbuf,int *cmdlen); static unsigned long g_gnss_cmd_queue= 0xFFFFFFFF; #define MAX_BUFFER_SIZE (256) typedef struct { @@ -155,11 +155,13 @@ static void uart_event_task(void const *arg) uint32_t wlen=0; uint8_t *buf=NULL; uint16_t len=0; - if (gnss_get_current_cmd(last_cfg_cmd_index,&buf,&len)==0) + // if (gnss_get_current_cmd(last_cfg_cmd_index,&buf,&len)==0) { WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"write next cmd[%d] size=%d! %s \r\n",last_cfg_cmd_index,len); wlen=gnss_write_cmd(buf,len); - }else{ + } + // else + { WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"no next cmd, stopped! \r\n"); last_cfg_cmd_index = 0xFF; //last_cfg_cmd_index=0xFF 代表结束写入 } @@ -177,7 +179,7 @@ static void uart_event_task(void const *arg) WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"last_cfg_cmd_index %d \r\n",last_cfg_cmd_index); if (last_cfg_cmd_index == 0xFF) //第一次写 { - if (gnss_get_current_cmd(0,&buf,&len)==0) + // if (gnss_get_current_cmd(0,&buf,&len)==0) { WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"last_cfg_cmd_index %d \r\n",last_cfg_cmd_index); last_cfg_cmd_index = 0; @@ -185,15 +187,16 @@ static void uart_event_task(void const *arg) } break; case GNSS_CMD_NMEA_CFG: - gnss_get_nmea_cfg_cmd(&buf,&len); + // gnss_get_nmea_cfg_cmd(&buf,&len); last_cfg_cmd_index = 0xFF; //last_cfg_cmd_index=0xFF 代表cfg结束写入,开始检测其他指令 break; case GNSS_CMD_START: - gnss_get_start_cmd(&buf,&len); + // gnss_get_start_cmd(&buf,&len); + GnssExecuteSamples(); last_cfg_cmd_index = 0xFF; //last_cfg_cmd_index=0xFF 代表cfg结束写入,开始检测其他指令 break; case GNSS_CMD_STOP: - gnss_get_stop_cmd(&buf,&len); + // gnss_get_stop_cmd(&buf,&len); last_cfg_cmd_index = 0xFF; //last_cfg_cmd_index=0xFF 代表cfg结束写入,开始检测其他指令 break; default: @@ -203,7 +206,7 @@ static void uart_event_task(void const *arg) } if (buf!=NULL) { - wlen=gnss_write_cmd(buf,len); + // wlen=gnss_write_cmd(buf,len); WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"GNSS_CMD_WRITEDATA cmdtype %d, written len %d\r\n",mail.cmd_type,wlen); }else{ WEARABLE_LOGW(WEARABLE_LOG_MODULE_MAIN_SERVICE,"GNSS_CMD_WRITEDATA cmdtype %d failed \r\n",mail.cmd_type); -- 2.17.1