生成了代码仓库
This commit is contained in:
+96
@@ -0,0 +1,96 @@
|
||||
# =============================================================================
|
||||
# AC701N (杰理 BR28) SDK - Git 忽略规则
|
||||
# =============================================================================
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 编译输出目录(CodeBlocks / Makefile 生成)
|
||||
# -----------------------------------------------------------------------------
|
||||
obj/
|
||||
**/obj/
|
||||
*.o
|
||||
*.d
|
||||
*.dep
|
||||
*.obj
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# CodeBlocks 工程临时文件(保留 AC701N.cbp)
|
||||
# -----------------------------------------------------------------------------
|
||||
*.depend
|
||||
*.layout
|
||||
*.cbTemp
|
||||
*.workspace
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 链接 / 编译中间产物(cpu/br28/tools 下生成)
|
||||
# -----------------------------------------------------------------------------
|
||||
cpu/*/tools/sdk.elf
|
||||
cpu/*/tools/sdk.elf.*
|
||||
cpu/*/tools/sdk.map
|
||||
cpu/*/tools/rom.lst
|
||||
cpu/*/tools/app.bin
|
||||
cpu/*/tools/data_code.bin
|
||||
cpu/*/tools/p11_code.bin
|
||||
cpu/*/tools/*.bc
|
||||
|
||||
# 打包下载目录中的固件产物(保留脚本 .bat / 密钥 .key)
|
||||
cpu/*/tools/download/**/*.bin
|
||||
cpu/*/tools/download/**/*.fw
|
||||
cpu/*/tools/download/**/*.ufw
|
||||
cpu/*/tools/download/**/*.hex
|
||||
|
||||
# 配置工具本地数据库
|
||||
cpu/*/tools/local.db
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# IDE / 编辑器
|
||||
# -----------------------------------------------------------------------------
|
||||
.vscode/
|
||||
.idea/
|
||||
*.user
|
||||
*.suo
|
||||
*.ncb
|
||||
*.aps
|
||||
*.opt
|
||||
*.plg
|
||||
*.clw
|
||||
*.pdb
|
||||
*.idb
|
||||
*.ilk
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 操作系统杂项
|
||||
# -----------------------------------------------------------------------------
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 临时 / 备份 / 日志
|
||||
# -----------------------------------------------------------------------------
|
||||
*~
|
||||
*.tmp
|
||||
*.temp
|
||||
*.bak
|
||||
*.swp
|
||||
*.swo
|
||||
*.log
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Release 交付产物(由 tools/package_release.py 生成,勿提交)
|
||||
# -----------------------------------------------------------------------------
|
||||
release/
|
||||
Release_Project_*/
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# 注意:以下内容请保留上传,不要忽略
|
||||
# - cpu/br28/liba/*.a SDK 预编译库
|
||||
# - AC701N.cbp / Makefile 工程文件
|
||||
# - cpu/br28/tools/*.exe 等 下载/打包工具
|
||||
# - include_lib/ / apps/ 头文件与应用源码
|
||||
# -----------------------------------------------------------------------------
|
||||
+1249
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
||||
# AC701N Earphone SDK
|
||||
|
||||
## 基本信息
|
||||
|
||||
- 工程名称:AC701N Earphone SDK
|
||||
- 版本号:V1.0.1
|
||||
- 生成时间:2026-08-19 15:43:10
|
||||
- 适用芯片:AC7016C(BR28)
|
||||
|
||||
## 目录说明
|
||||
|
||||
```
|
||||
JBao_JL7016_SOC_SDK_V1.0.1/
|
||||
├── apps/
|
||||
│ ├── common/ # SDK 公共模块
|
||||
│ ├── earphone/ # 耳机应用
|
||||
│ ├── usr_jb_proto/ # 应用协议层
|
||||
│ ├── usr_periph/ # 板级外设(RTC 等,源码开放)
|
||||
│ └── usr_le_code/ # BLE 协议库(库文件 + 公开头文件)
|
||||
├── cpu/ # 芯片相关代码与工具
|
||||
├── include_lib/ # SDK 头文件
|
||||
├── tools/ # 工程工具
|
||||
├── Makefile
|
||||
├── AC701N.cbp
|
||||
└── JBao_JL7016_SOC_SDK_README.md
|
||||
```
|
||||
|
||||
### 封装模块公开接口
|
||||
|
||||
**apps/usr_le_code**
|
||||
|
||||
- 静态库:`apps/usr_le_code/lib/`
|
||||
- 公开头文件:
|
||||
- `apps/usr_le_code/usr_le_api.h`
|
||||
- `apps/usr_le_code/usr_le_product.h`
|
||||
|
||||
---
|
||||
|
||||
*本文件由 tools/package_release.py 自动生成。*
|
||||
@@ -0,0 +1,866 @@
|
||||
|
||||
# make 编译并下载
|
||||
# make VERBOSE=1 显示编译详细过程
|
||||
# make clean 清除编译临时文件
|
||||
#
|
||||
# 注意: Linux 下编译方式:
|
||||
# 1. 从 http://pkgman.jieliapp.com/doc/all 处找到下载链接
|
||||
# 2. 下载后,解压到 /opt/jieli 目录下,保证
|
||||
# /opt/jieli/common/bin/clang 存在(注意目录层次)
|
||||
# 3. 确认 ulimit -n 的结果足够大(建议大于8096),否则链接可能会因为打开文件太多而失败
|
||||
# 可以通过 ulimit -n 8096 来设置一个较大的值
|
||||
#
|
||||
|
||||
# 工具路径设置
|
||||
ifeq ($(OS), Windows_NT)
|
||||
# Windows 下工具链位置
|
||||
TOOL_DIR := C:/JL/pi32/bin
|
||||
CC := clang.exe
|
||||
CXX := clang.exe
|
||||
LD := pi32v2-lto-wrapper.exe
|
||||
AR := llvm-ar.exe
|
||||
MKDIR := mkdir_win -p
|
||||
RM := rm -rf
|
||||
|
||||
SYS_LIB_DIR := C:/JL/pi32/pi32v2-lib/r3-large
|
||||
SYS_INC_DIR := C:/JL/pi32/pi32v2-include
|
||||
EXT_CFLAGS := # Windows 下不需要 -D__SHELL__
|
||||
export PATH:=$(TOOL_DIR);$(PATH)
|
||||
|
||||
## 后处理脚本
|
||||
FIXBAT := tools\utils\fixbat.exe # 用于处理 utf8->gbk 编码问题
|
||||
POST_SCRIPT := cpu/br28/tools/download.bat
|
||||
RUN_POST_SCRIPT := cpu\br28\tools\download.bat
|
||||
else
|
||||
# Linux 下工具链位置
|
||||
TOOL_DIR := /opt/jieli/pi32v2/bin
|
||||
CC := clang
|
||||
CXX := clang
|
||||
LD := lto-wrapper
|
||||
AR := lto-ar
|
||||
MKDIR := mkdir -p
|
||||
RM := rm -rf
|
||||
export OBJDUMP := $(TOOL_DIR)/objdump
|
||||
export OBJCOPY := $(TOOL_DIR)/objcopy
|
||||
export OBJSIZEDUMP := $(TOOL_DIR)/objsizedump
|
||||
|
||||
SYS_LIB_DIR := $(TOOL_DIR)/../lib/r3-large
|
||||
SYS_INC_DIR := $(TOOL_DIR)/../include
|
||||
EXT_CFLAGS := -D__SHELL__ # Linux 下需要这个保证正确处理 download.c
|
||||
export PATH:=$(TOOL_DIR):$(PATH)
|
||||
|
||||
## 后处理脚本
|
||||
FIXBAT := touch # Linux下不需要处理 bat 编码问题
|
||||
POST_SCRIPT := cpu/br28/tools/download.sh
|
||||
RUN_POST_SCRIPT := bash $(POST_SCRIPT)
|
||||
endif
|
||||
|
||||
CC := $(TOOL_DIR)/$(CC)
|
||||
CXX := $(TOOL_DIR)/$(CXX)
|
||||
LD := $(TOOL_DIR)/$(LD)
|
||||
AR := $(TOOL_DIR)/$(AR)
|
||||
# 输出文件设置
|
||||
OUT_ELF := cpu/br28/tools/sdk.elf
|
||||
OBJ_FILE := $(OUT_ELF).objs.txt
|
||||
# 编译路径设置
|
||||
BUILD_DIR := objs
|
||||
|
||||
# 编译参数设置
|
||||
CFLAGS := \
|
||||
-target pi32v2 \
|
||||
-mcpu=r3 \
|
||||
-integrated-as \
|
||||
-flto \
|
||||
-Wuninitialized \
|
||||
-Wno-invalid-noreturn \
|
||||
-fno-common \
|
||||
-integrated-as \
|
||||
-Oz \
|
||||
-g \
|
||||
-flto \
|
||||
-fallow-pointer-null \
|
||||
-fprefer-gnu-section \
|
||||
-Wno-shift-negative-value \
|
||||
-Wundef \
|
||||
-Wframe-larger-than=256 \
|
||||
-Wincompatible-pointer-types \
|
||||
-Wreturn-type \
|
||||
-Wimplicit-function-declaration \
|
||||
-mllvm -pi32v2-large-program=true \
|
||||
-fms-extensions \
|
||||
-fdiscrete-bitfield-abi \
|
||||
-w \
|
||||
|
||||
|
||||
# C++额外的编译参数
|
||||
CXXFLAGS :=
|
||||
|
||||
|
||||
# 宏定义
|
||||
DEFINES := \
|
||||
-DSUPPORT_MS_EXTENSIONS \
|
||||
-DCONFIG_RELEASE_ENABLE \
|
||||
-DCONFIG_CPU_BR28 \
|
||||
-DCONFIG_USB_SUPPORT_MRX_TX \
|
||||
-DCONFIG_PRINT_IN_MASK \
|
||||
-DCONFIG_NEW_BREDR_ENABLE \
|
||||
-DCONFIG_NEW_MODEM_ENABLE \
|
||||
-DCONFIG_NEW_TWS_FORWARD_ENABLE \
|
||||
-DCONFIG_UCOS_ENABLE \
|
||||
-DCONFIG_EQ_SUPPORT_ASYNC \
|
||||
-DEQ_CORE_V1 \
|
||||
-DCONFIG_AAC_CODEC_FFT_USE_MUTEX \
|
||||
-DCONFIG_DNS_ENABLE \
|
||||
-DCONFIG_DMS_MALLOC \
|
||||
-DCONFIG_MMU_ENABLE \
|
||||
-DCONFIG_SBC_CODEC_HW \
|
||||
-DCONFIG_MSBC_CODEC_HW \
|
||||
-DCONFIG_AEC_M=128 \
|
||||
-DCONFIG_SUPPORT_WIFI_DETECT \
|
||||
-DCONFIG_AUDIO_ONCHIP \
|
||||
-DCONFIG_MEDIA_NEW_ENABLE \
|
||||
-DCONFIG_SUPPORT_EX_TWS_ADJUST \
|
||||
-D__GCC_PI32V2__ \
|
||||
-DCONFIG_MAC_ADDR_GET_USED_SFC \
|
||||
-DTCFG_APP_BT_EN=1 \
|
||||
-DEVENT_HANDLER_NUM_CONFIG=2 \
|
||||
-DEVENT_TOUCH_ENABLE_CONFIG=0 \
|
||||
-DEVENT_POOL_SIZE_CONFIG=256 \
|
||||
-DCONFIG_EVENT_KEY_MAP_ENABLE=0 \
|
||||
-DTIMER_POOL_NUM_CONFIG=15 \
|
||||
-DAPP_ASYNC_POOL_NUM_CONFIG=0 \
|
||||
-DUSE_SDFILE_NEW=1 \
|
||||
-DSDFILE_STORAGE=0 \
|
||||
-DVFS_FILE_POOL_NUM_CONFIG=1 \
|
||||
-DFS_VERSION=0x020001 \
|
||||
-DFATFS_VERSION=0x020101 \
|
||||
-DSDFILE_VERSION=0x020000 \
|
||||
-DVFS_ENABLE=1 \
|
||||
-DVM_MAX_PAGE_ALIGN_SIZE_CONFIG=16*1024 \
|
||||
-DVM_MAX_SECTOR_ALIGN_SIZE_CONFIG=16*1024 \
|
||||
-DVM_ITEM_MAX_NUM=256 \
|
||||
-DCONFIG_TWS_ENABLE \
|
||||
-DCONFIG_EARPHONE_CASE_ENABLE \
|
||||
-DCONFIG_OS_AFFINITY_ENABLE \
|
||||
-DCONFIG_NEW_CFG_TOOL_ENABLE \
|
||||
-DCONFIG_LITE_AEC_ENABLE=0 \
|
||||
-DAUDIO_REC_LITE \
|
||||
-DAUDIO_DEC_LITE \
|
||||
-DAUDIO_REC_POOL_NUM=1 \
|
||||
-DAUDIO_DEC_POOL_NUM=3 \
|
||||
-DCONFIG_BTCTRLER_TASK_DEL_ENABLE \
|
||||
-DCONFIG_LINK_DISTURB_SCAN_ENABLE=0 \
|
||||
-DCONFIG_UPDATA_ENABLE \
|
||||
-DCONFIG_OTA_UPDATA_ENABLE \
|
||||
-DCONFIG_ITEM_FORMAT_VM \
|
||||
|
||||
|
||||
DEFINES += $(EXT_CFLAGS) # 额外的一些定义
|
||||
|
||||
# 头文件搜索路径
|
||||
INCLUDES := \
|
||||
-Iinclude_lib \
|
||||
-Iinclude_lib/driver \
|
||||
-Iinclude_lib/driver/device \
|
||||
-Iinclude_lib/driver/cpu/br28 \
|
||||
-Iinclude_lib/system \
|
||||
-Iinclude_lib/system/generic \
|
||||
-Iinclude_lib/system/device \
|
||||
-Iinclude_lib/system/fs \
|
||||
-Iinclude_lib/system/ui \
|
||||
-Iinclude_lib/btctrler \
|
||||
-Iinclude_lib/btctrler/port/br28 \
|
||||
-Iinclude_lib/update \
|
||||
-Iinclude_lib/agreement \
|
||||
-Iinclude_lib/btstack/third_party/common \
|
||||
-Iinclude_lib/btstack/third_party/rcsp \
|
||||
-Iinclude_lib/media/media_new \
|
||||
-Iinclude_lib/media/media_new/media \
|
||||
-Iinclude_lib/media/media_new/media/cpu/br28 \
|
||||
-Iinclude_lib/media/media_new/media/cpu/br28/asm \
|
||||
-Iapps/common \
|
||||
-Iapps/earphone/include \
|
||||
-Iapps/earphone/include/wireless_mic \
|
||||
-Iapps/common/icsd/anc \
|
||||
-Iapps/common/icsd/adt \
|
||||
-Iapps/common/power_manage \
|
||||
-Iapps/common/device \
|
||||
-Iapps/common/device/ntc \
|
||||
-Iapps/common/device/imu_sensor \
|
||||
-Iapps/common/audio \
|
||||
-Iapps/common/music \
|
||||
-Iapps/common/include \
|
||||
-Iapps/common/config/include \
|
||||
-Iapps/common/dev_manager \
|
||||
-Iapps/common/third_party_profile/common \
|
||||
-Iapps/common/third_party_profile/interface \
|
||||
-Iapps/common/third_party_profile/jieli \
|
||||
-Iapps/common/third_party_profile/jieli/trans_data_demo \
|
||||
-Iapps/common/third_party_profile/jieli/online_db \
|
||||
-Iapps/common/third_party_profile/jieli/JL_rcsp \
|
||||
-Iapps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting \
|
||||
-Iapps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data \
|
||||
-Iapps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol \
|
||||
-Iapps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata \
|
||||
-Iapps/earphone/board/br28 \
|
||||
-Icpu/br28 \
|
||||
-Icpu/br28/audio_dec \
|
||||
-Icpu/br28/spatial_effect \
|
||||
-Iapps/common/third_party_profile/Tecent_LL/include \
|
||||
-Iapps/common/third_party_profile/Tecent_LL/tecent_ll_demo \
|
||||
-Iapps/common/cJSON \
|
||||
-Iinclude_lib/media \
|
||||
-Iinclude_lib/btstack \
|
||||
-Iinclude_lib/driver/cpu/br28/asm/power \
|
||||
-Iapps/common/third_party_profile/tuya_protocol \
|
||||
-Iapps/common/third_party_profile/tuya_protocol/app/demo \
|
||||
-Iapps/common/third_party_profile/tuya_protocol/app/product_test \
|
||||
-Iapps/common/third_party_profile/tuya_protocol/app/uart_common \
|
||||
-Iapps/common/third_party_profile/tuya_protocol/extern_components/mbedtls \
|
||||
-Iapps/common/third_party_profile/tuya_protocol/port \
|
||||
-Iapps/common/third_party_profile/tuya_protocol/sdk/include \
|
||||
-Iapps/common/third_party_profile/tuya_protocol/sdk/lib \
|
||||
-Iapps/earphone/tuya \
|
||||
-Iapps/common/device/usb \
|
||||
-Iapps/common/device/usb/device \
|
||||
-Iapps/common/device/usb/host \
|
||||
-Iapps/earphone/wireless_mic/bt \
|
||||
-Iapps/earphone/wireless_mic/idev \
|
||||
-Iapps/earphone/wireless_mic/idev/idev_bt \
|
||||
-Iapps/earphone/wireless_mic/idev/idev_bt/include \
|
||||
-Iapps/earphone/wireless_mic/idev/idev_mic \
|
||||
-Iapps/earphone/wireless_mic/odev \
|
||||
-Iapps/earphone/wireless_mic/odev/odev_bt \
|
||||
-Iapps/earphone/wireless_mic/odev/odev_bt/odev_edr \
|
||||
-Iapps/earphone/wireless_mic/odev/odev_bt/odev_ble \
|
||||
-Iapps/earphone/wireless_mic/odev/odev_bt/include \
|
||||
-Iapps/earphone/wireless_mic/odev/odev_dac \
|
||||
-Iapps/earphone/wireless_mic/process \
|
||||
-Iapps/earphone/wireless_mic/audio \
|
||||
-Iapps/earphone/wireless_mic/audio/wireless \
|
||||
-Iapps/common/ezxml \
|
||||
-Icpu/br28/audio_dec/audio_dec_file.h \
|
||||
-Iinclude_lib/system/math/cpu/br28 \
|
||||
-Iinclude_lib/media/aispeech/asr/include \
|
||||
-Iinclude_lib/media/aispeech/enc/include \
|
||||
-Icpu/br28/audio_hearing \
|
||||
-Iinclude_lib/media/cvp \
|
||||
-Iapps/usr_le_code \
|
||||
-Iapps/usr_le_code/thirdpart \
|
||||
-Iapps/usr_le_code/thirdpart/mjson \
|
||||
-Iapps/usr_jb_proto/Protocol \
|
||||
-Iapps/usr_jb_proto/Utils \
|
||||
-Iapps/usr_periph \
|
||||
-I$(SYS_INC_DIR) \
|
||||
|
||||
|
||||
# 需要编译的 .c 文件
|
||||
c_SRC_FILES := \
|
||||
apps/common/audio/amplitude_statistic.c \
|
||||
apps/common/audio/audio_dvol.c \
|
||||
apps/common/audio/audio_export_demo.c \
|
||||
apps/common/audio/audio_noise_gate.c \
|
||||
apps/common/audio/audio_ns.c \
|
||||
apps/common/audio/audio_plc.c \
|
||||
apps/common/audio/audio_utils.c \
|
||||
apps/common/audio/decode/audio_key_tone.c \
|
||||
apps/common/audio/decode/decode.c \
|
||||
apps/common/audio/demo/audio_demo.c \
|
||||
apps/common/audio/online_debug/aud_data_export.c \
|
||||
apps/common/audio/online_debug/aud_mic_dut.c \
|
||||
apps/common/audio/online_debug/aud_spatial_effect_dut.c \
|
||||
apps/common/audio/online_debug/audio_online_debug.c \
|
||||
apps/common/audio/sine_make.c \
|
||||
apps/common/audio/uartPcmSender.c \
|
||||
apps/common/audio/wm8978/iic.c \
|
||||
apps/common/audio/wm8978/wm8978.c \
|
||||
apps/common/bt_common/bt_test_api.c \
|
||||
apps/common/cJSON/cJSON.c \
|
||||
apps/common/config/app_config.c \
|
||||
apps/common/config/bt_profile_config.c \
|
||||
apps/common/config/ci_transport_uart.c \
|
||||
apps/common/config/new_cfg_tool.c \
|
||||
apps/common/debug/debug.c \
|
||||
apps/common/debug/debug_lite.c \
|
||||
apps/common/dev_manager/dev_manager.c \
|
||||
apps/common/dev_manager/dev_reg.c \
|
||||
apps/common/dev_manager/dev_update.c \
|
||||
apps/common/device/gSensor/SC7A20.c \
|
||||
apps/common/device/gSensor/STK8321.c \
|
||||
apps/common/device/gSensor/da230.c \
|
||||
apps/common/device/gSensor/gSensor_manage.c \
|
||||
apps/common/device/gSensor/mpu6050.c \
|
||||
apps/common/device/gx8002_npu/gx8002_enc/gx8002_enc.c \
|
||||
apps/common/device/gx8002_npu/gx8002_npu.c \
|
||||
apps/common/device/gx8002_npu/gx8002_npu_event_deal.c \
|
||||
apps/common/device/gx8002_npu/gx8002_upgrade/app_upgrade/gx_uart_upgrade_app.c \
|
||||
apps/common/device/gx8002_npu/gx8002_upgrade/app_upgrade/gx_uart_upgrade_tws.c \
|
||||
apps/common/device/gx8002_npu/gx8002_upgrade/gx_uart_upgrade.c \
|
||||
apps/common/device/gx8002_npu/gx8002_upgrade/gx_uart_upgrade_porting.c \
|
||||
apps/common/device/gx8002_npu/gx8002_upgrade/sdfile_upgrade/gx_uart_upgrade_sdfile.c \
|
||||
apps/common/device/gx8002_npu/gx8002_upgrade/spp_upgrade/gx_fifo.c \
|
||||
apps/common/device/gx8002_npu/gx8002_upgrade/spp_upgrade/gx_uart_upgrade_spp.c \
|
||||
apps/common/device/imu_sensor/icm_42670p/icm_42670p.c \
|
||||
apps/common/device/imu_sensor/icm_42670p/inv_imu_apex.c \
|
||||
apps/common/device/imu_sensor/icm_42670p/inv_imu_driver.c \
|
||||
apps/common/device/imu_sensor/icm_42670p/inv_imu_transport.c \
|
||||
apps/common/device/imu_sensor/imuSensor_manage.c \
|
||||
apps/common/device/imu_sensor/lsm6dsl/lsm6dsl.c \
|
||||
apps/common/device/imu_sensor/mpu6887/mpu6887p.c \
|
||||
apps/common/device/imu_sensor/mpu9250/mpu9250.c \
|
||||
apps/common/device/imu_sensor/qmi8658/qmi8658c.c \
|
||||
apps/common/device/imu_sensor/sh3001/sh3001.c \
|
||||
apps/common/device/in_ear_detect/in_ear_detect.c \
|
||||
apps/common/device/in_ear_detect/in_ear_manage.c \
|
||||
apps/common/device/ir_sensor/ir_manage.c \
|
||||
apps/common/device/ir_sensor/jsa1221.c \
|
||||
apps/common/device/key/adkey.c \
|
||||
apps/common/device/key/adkey_rtcvdd.c \
|
||||
apps/common/device/key/ctmu_touch_key.c \
|
||||
apps/common/device/key/iokey.c \
|
||||
apps/common/device/key/irkey.c \
|
||||
apps/common/device/key/key_driver.c \
|
||||
apps/common/device/key/touch_key.c \
|
||||
apps/common/device/key/uart_key.c \
|
||||
apps/common/device/norflash/norflash_sfc.c \
|
||||
apps/common/device/ntc/ntc_det.c \
|
||||
apps/common/device/usb/device/cdc.c \
|
||||
apps/common/device/usb/device/descriptor.c \
|
||||
apps/common/device/usb/device/hid.c \
|
||||
apps/common/device/usb/device/msd.c \
|
||||
apps/common/device/usb/device/msd_upgrade.c \
|
||||
apps/common/device/usb/device/task_pc.c \
|
||||
apps/common/device/usb/device/uac1.c \
|
||||
apps/common/device/usb/device/uac_stream.c \
|
||||
apps/common/device/usb/device/usb_device.c \
|
||||
apps/common/device/usb/device/user_setup.c \
|
||||
apps/common/device/usb/host/adb.c \
|
||||
apps/common/device/usb/host/aoa.c \
|
||||
apps/common/device/usb/host/audio.c \
|
||||
apps/common/device/usb/host/audio_demo.c \
|
||||
apps/common/device/usb/host/hid.c \
|
||||
apps/common/device/usb/host/usb_bulk_transfer.c \
|
||||
apps/common/device/usb/host/usb_ctrl_transfer.c \
|
||||
apps/common/device/usb/host/usb_host.c \
|
||||
apps/common/device/usb/host/usb_storage.c \
|
||||
apps/common/device/usb/usb_config.c \
|
||||
apps/common/device/usb/usb_host_config.c \
|
||||
apps/common/ezxml/ezxml.c \
|
||||
apps/common/ezxml/ezxml_example.c \
|
||||
apps/common/fat_nor/cfg_private.c \
|
||||
apps/common/fat_nor/virfat_flash.c \
|
||||
apps/common/file_operate/file_bs_deal.c \
|
||||
apps/common/file_operate/file_manager.c \
|
||||
apps/common/icsd/adt/icsd_adt.c \
|
||||
apps/common/icsd/adt/icsd_adt_app.c \
|
||||
apps/common/icsd/anc/icsd_anc_app.c \
|
||||
apps/common/icsd/anc/icsd_anc_board.c \
|
||||
apps/common/icsd/anc/icsd_anc_data.c \
|
||||
apps/common/jl_kws/jl_kws_algo.c \
|
||||
apps/common/jl_kws/jl_kws_audio.c \
|
||||
apps/common/jl_kws/jl_kws_event.c \
|
||||
apps/common/jl_kws/jl_kws_main.c \
|
||||
apps/common/music/breakpoint.c \
|
||||
apps/common/music/music_decrypt.c \
|
||||
apps/common/music/music_id3.c \
|
||||
apps/common/music/music_player.c \
|
||||
apps/common/temp_trim/dtemp_pll_trim.c \
|
||||
apps/common/test/fs_test.c \
|
||||
apps/common/test/os_test.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_ll_demo/ll_demo.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_ll_demo/ll_task.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_import.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_llsync_data.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_llsync_device.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_llsync_event.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_llsync_ota.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_service.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_template.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_utils_base64.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_utils_crc.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_utils_hmac.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_utils_log.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_utils_md5.c \
|
||||
apps/common/third_party_profile/Tecent_LL/tecent_protocol/ble_qiot_utils_sha1.c \
|
||||
apps/common/third_party_profile/common/3th_profile_api.c \
|
||||
apps/common/third_party_profile/common/custom_cfg.c \
|
||||
apps/common/third_party_profile/common/mic_rec.c \
|
||||
apps/common/third_party_profile/interface/app_protocol_api.c \
|
||||
apps/common/third_party_profile/interface/app_protocol_common.c \
|
||||
apps/common/third_party_profile/interface/app_protocol_dma.c \
|
||||
apps/common/third_party_profile/interface/app_protocol_gfps.c \
|
||||
apps/common/third_party_profile/interface/app_protocol_gma.c \
|
||||
apps/common/third_party_profile/interface/app_protocol_mma.c \
|
||||
apps/common/third_party_profile/interface/app_protocol_ota.c \
|
||||
apps/common/third_party_profile/interface/app_protocol_tme.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_adaptive_noise_reduction.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_anc_voice.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_anc_voice_key.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_eq_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_hearing_aid_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_high_low_vol_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_music_info_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_bluetooth.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_customer_user.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/rcsp_adv_spp_user.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_ch_loader_download.c \
|
||||
apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_user_update.c \
|
||||
apps/common/third_party_profile/jieli/le_hogp.c \
|
||||
apps/common/third_party_profile/jieli/online_db/online_db_deal.c \
|
||||
apps/common/third_party_profile/jieli/online_db/spp_online_db.c \
|
||||
apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.c \
|
||||
apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.c \
|
||||
apps/common/third_party_profile/jieli/wireless_mic/le_wireless_mic_client.c \
|
||||
apps/common/third_party_profile/jieli/wireless_mic/le_wireless_mic_server.c \
|
||||
apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.c \
|
||||
apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.c \
|
||||
apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.c \
|
||||
apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.c \
|
||||
apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.c \
|
||||
apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.c \
|
||||
apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.c \
|
||||
apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.c \
|
||||
apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.c \
|
||||
apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.c \
|
||||
apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.c \
|
||||
apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_JL.c \
|
||||
apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_api.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_bulk_data.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_data_handler.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler_weak.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_feature_weather.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_gatt_send_queue.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_heap.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_main.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mem.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mutli_tsf_protocol.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_queue.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_storage.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_unix_time.c \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_utils.c \
|
||||
apps/common/ui/lcd_simple/lcd_simple_api.c \
|
||||
apps/common/ui/lcd_simple/ui.c \
|
||||
apps/common/ui/lcd_simple/ui_mainmenu.c \
|
||||
apps/common/update/testbox_update.c \
|
||||
apps/common/update/update.c \
|
||||
apps/common/update/update_tws.c \
|
||||
apps/common/update/update_tws_new.c \
|
||||
apps/earphone/aec/br28/audio_aec.c \
|
||||
apps/earphone/aec/br28/audio_aec_demo.c \
|
||||
apps/earphone/aec/br28/audio_aec_dms.c \
|
||||
apps/earphone/aec/br28/audio_aec_online.c \
|
||||
apps/earphone/aec/br28/audio_cvp_3mic.c \
|
||||
apps/earphone/aec/br28/audio_cvp_ais_3mic.c \
|
||||
apps/earphone/app_ancbox.c \
|
||||
apps/earphone/app_anctool.c \
|
||||
apps/earphone/app_main.c \
|
||||
apps/earphone/app_protocol_deal.c \
|
||||
apps/earphone/app_task_switch.c \
|
||||
apps/earphone/app_testbox.c \
|
||||
apps/earphone/audio_enc_mpt_cvp_ctr.c \
|
||||
apps/earphone/audio_enc_mpt_self.c \
|
||||
apps/earphone/ble_adv.c \
|
||||
apps/earphone/board/br28/board_jl7016g_hybrid.c \
|
||||
apps/earphone/board/br28/board_jl7018f_demo.c \
|
||||
apps/earphone/board/br28/board_jl701n_anc.c \
|
||||
apps/earphone/board/br28/board_jl701n_btemitter.c \
|
||||
apps/earphone/board/br28/board_jl701n_demo.c \
|
||||
apps/earphone/bt_auto_test.c \
|
||||
apps/earphone/bt_background.c \
|
||||
apps/earphone/bt_ble.c \
|
||||
apps/earphone/bt_ble_hid.c \
|
||||
apps/earphone/bt_emitter.c \
|
||||
apps/earphone/bt_tws.c \
|
||||
apps/earphone/default_event_handler.c \
|
||||
apps/earphone/dual_update_demo.c \
|
||||
apps/earphone/earphone.c \
|
||||
apps/earphone/eartch_event_deal.c \
|
||||
apps/earphone/font/fontinit.c \
|
||||
apps/earphone/idle.c \
|
||||
apps/earphone/key_event_deal.c \
|
||||
apps/earphone/kws_voice_event_deal.c \
|
||||
apps/earphone/linein/linein.c \
|
||||
apps/earphone/ll_sync_demo/ll_sync_demo.c \
|
||||
apps/earphone/log_config/app_config.c \
|
||||
apps/earphone/log_config/lib_btctrler_config.c \
|
||||
apps/earphone/log_config/lib_btstack_config.c \
|
||||
apps/earphone/log_config/lib_driver_config.c \
|
||||
apps/earphone/log_config/lib_media_config.c \
|
||||
apps/earphone/log_config/lib_system_config.c \
|
||||
apps/earphone/log_config/lib_update_config.c \
|
||||
apps/earphone/music/sd_music.c \
|
||||
apps/earphone/pbg_demo.c \
|
||||
apps/earphone/pc/pc.c \
|
||||
apps/earphone/power_manage/app_charge.c \
|
||||
apps/earphone/power_manage/app_chargestore.c \
|
||||
apps/earphone/power_manage/app_power_manage.c \
|
||||
apps/earphone/power_manage/app_umidigi_chargestore.c \
|
||||
apps/earphone/rcsp/jl_phone_app.c \
|
||||
apps/earphone/rcsp/rcsp_adv.c \
|
||||
apps/earphone/tone_table.c \
|
||||
apps/earphone/trans_data_demo/trans_data_demo.c \
|
||||
apps/earphone/tuya/tuya_app.c \
|
||||
apps/earphone/tuya/tuya_demo.c \
|
||||
apps/earphone/ui/lcd_simple/my_demo.c \
|
||||
apps/earphone/ui_manage.c \
|
||||
apps/earphone/user_cfg.c \
|
||||
apps/earphone/version.c \
|
||||
apps/earphone/vol_sync.c \
|
||||
apps/earphone/wireless_mic/app_main_wireless_mic.c \
|
||||
apps/earphone/wireless_mic/audio/adapter_adc.c \
|
||||
apps/earphone/wireless_mic/audio/adapter_media.c \
|
||||
apps/earphone/wireless_mic/audio/wireless/adapter_wireless_dec.c \
|
||||
apps/earphone/wireless_mic/audio/wireless/adapter_wireless_enc.c \
|
||||
apps/earphone/wireless_mic/bt/bt_edr_fun.c \
|
||||
apps/earphone/wireless_mic/bt/bt_status_event.c \
|
||||
apps/earphone/wireless_mic/idev/adapter_idev.c \
|
||||
apps/earphone/wireless_mic/idev/idev_bt/adapter_idev_bt.c \
|
||||
apps/earphone/wireless_mic/idev/idev_bt/idev_ble/adapter_idev_ble.c \
|
||||
apps/earphone/wireless_mic/idev/idev_mic/adapter_idev_mic.c \
|
||||
apps/earphone/wireless_mic/odev/adapter_odev.c \
|
||||
apps/earphone/wireless_mic/odev/odev_bt/adapter_odev_bt.c \
|
||||
apps/earphone/wireless_mic/odev/odev_bt/odev_ble/adapter_odev_ble.c \
|
||||
apps/earphone/wireless_mic/odev/odev_bt/odev_ble/odev_ble_wireless.c \
|
||||
apps/earphone/wireless_mic/odev/odev_bt/odev_edr/adapter_odev_edr.c \
|
||||
apps/earphone/wireless_mic/odev/odev_dac/adapter_odev_dac.c \
|
||||
apps/earphone/wireless_mic/process/adapter_process.c \
|
||||
cpu/br28/adc_api.c \
|
||||
cpu/br28/aec_tool.c \
|
||||
cpu/br28/app_audio.c \
|
||||
cpu/br28/audio_anc.c \
|
||||
cpu/br28/audio_anc_fade_ctr.c \
|
||||
cpu/br28/audio_anc_mult_scene.c \
|
||||
cpu/br28/audio_capture.c \
|
||||
cpu/br28/audio_codec_clock.c \
|
||||
cpu/br28/audio_common/audio_mic_codec.c \
|
||||
cpu/br28/audio_cvp_dut.c \
|
||||
cpu/br28/audio_cvp_sync.c \
|
||||
cpu/br28/audio_dec.c \
|
||||
cpu/br28/audio_dec/audio_dec_file.c \
|
||||
cpu/br28/audio_dec/audio_dec_iis.c \
|
||||
cpu/br28/audio_dec/audio_dec_pc.c \
|
||||
cpu/br28/audio_dec/audio_dec_pcm.c \
|
||||
cpu/br28/audio_dec/audio_usb_mic.c \
|
||||
cpu/br28/audio_dec_eff.c \
|
||||
cpu/br28/audio_demo/audio_adc_demo.c \
|
||||
cpu/br28/audio_demo/audio_dac_demo.c \
|
||||
cpu/br28/audio_demo/audio_fft_demo.c \
|
||||
cpu/br28/audio_demo/audio_matrix_demo.c \
|
||||
cpu/br28/audio_demo/audio_wind_detect_demo.c \
|
||||
cpu/br28/audio_effect_develop.c \
|
||||
cpu/br28/audio_enc.c \
|
||||
cpu/br28/audio_general.c \
|
||||
cpu/br28/audio_hearing/audio_hearing_aid.c \
|
||||
cpu/br28/audio_hearing/audio_hearing_aid_lp.c \
|
||||
cpu/br28/audio_hearing/audio_sidetone.c \
|
||||
cpu/br28/audio_link.c \
|
||||
cpu/br28/audio_sync.c \
|
||||
cpu/br28/charge.c \
|
||||
cpu/br28/chargestore.c \
|
||||
cpu/br28/clock_manager.c \
|
||||
cpu/br28/eq_config.c \
|
||||
cpu/br28/hw_fft.c \
|
||||
cpu/br28/icsd_anc_user.c \
|
||||
cpu/br28/iic_hw.c \
|
||||
cpu/br28/iic_soft.c \
|
||||
cpu/br28/irflt.c \
|
||||
cpu/br28/lp_touch_key.c \
|
||||
cpu/br28/lp_touch_key_alog.c \
|
||||
cpu/br28/lp_touch_key_tool.c \
|
||||
cpu/br28/lua_port_api.c \
|
||||
cpu/br28/mcpwm.c \
|
||||
cpu/br28/mic_dut_process.c \
|
||||
cpu/br28/overlay_code.c \
|
||||
cpu/br28/pdm_link.c \
|
||||
cpu/br28/plcnt.c \
|
||||
cpu/br28/power/power_app.c \
|
||||
cpu/br28/power/power_check.c \
|
||||
cpu/br28/power/power_port.c \
|
||||
cpu/br28/power/power_trim.c \
|
||||
cpu/br28/private_iis.c \
|
||||
cpu/br28/pwm_led.c \
|
||||
cpu/br28/rdec.c \
|
||||
cpu/br28/setup.c \
|
||||
cpu/br28/smart_voice/aispeech_asr.c \
|
||||
cpu/br28/smart_voice/jl_kws_platform.c \
|
||||
cpu/br28/smart_voice/kws_event.c \
|
||||
cpu/br28/smart_voice/nn_vad.c \
|
||||
cpu/br28/smart_voice/smart_voice_config.c \
|
||||
cpu/br28/smart_voice/smart_voice_core.c \
|
||||
cpu/br28/smart_voice/user_asr.c \
|
||||
cpu/br28/smart_voice/vad_clock_trim.c \
|
||||
cpu/br28/smart_voice/vad_mic.c \
|
||||
cpu/br28/smart_voice/voice_mic_data.c \
|
||||
cpu/br28/sound_device.c \
|
||||
cpu/br28/spatial_effect/spatial_effect.c \
|
||||
cpu/br28/spatial_effect/spatial_effect_imu.c \
|
||||
cpu/br28/spatial_effect/spatial_effect_test.c \
|
||||
cpu/br28/spatial_effect/spatial_effect_tws.c \
|
||||
cpu/br28/spatial_effect/spatial_imu_trim.c \
|
||||
cpu/br28/spi.c \
|
||||
cpu/br28/tone_player.c \
|
||||
cpu/br28/tws_audio.c \
|
||||
cpu/br28/uart_dev.c \
|
||||
cpu/br28/umidigi_chargestore.c \
|
||||
apps/usr_jb_proto/Protocol/jb_product.c \
|
||||
apps/usr_jb_proto/Protocol/jb_protocol.c \
|
||||
apps/usr_jb_proto/Utils/jb_common.c \
|
||||
apps/usr_jb_proto/Utils/jb_ringbuffer.c \
|
||||
apps/usr_jb_proto/usr_jb_main.c \
|
||||
apps/usr_periph/usr_rtc.c \
|
||||
|
||||
|
||||
# usr_le_code 预编译静态库(Release 不附带协议源码,禁止本地重建)
|
||||
USR_LE_LIB := apps/usr_le_code/lib/libusr_le_code.a
|
||||
|
||||
|
||||
|
||||
# 需要编译的 .S 文件
|
||||
S_SRC_FILES := \
|
||||
apps/earphone/sdk_version.z.S \
|
||||
|
||||
|
||||
# 需要编译的 .s 文件
|
||||
s_SRC_FILES :=
|
||||
|
||||
|
||||
# 需要编译的 .cpp 文件
|
||||
cpp_SRC_FILES :=
|
||||
|
||||
|
||||
# 需要编译的 .cc 文件
|
||||
cc_SRC_FILES :=
|
||||
|
||||
|
||||
# 需要编译的 .cxx 文件
|
||||
cxx_SRC_FILES :=
|
||||
|
||||
|
||||
# 链接参数
|
||||
LFLAGS := \
|
||||
--plugin-opt=-pi32v2-always-use-itblock=false \
|
||||
--plugin-opt=-enable-ipra=true \
|
||||
--plugin-opt=-pi32v2-merge-max-offset=4096 \
|
||||
--plugin-opt=-pi32v2-enable-simd=true \
|
||||
--plugin-opt=mcpu=r3 \
|
||||
--plugin-opt=-global-merge-on-const \
|
||||
--plugin-opt=-inline-threshold=5 \
|
||||
--plugin-opt=-inline-max-allocated-size=32 \
|
||||
--plugin-opt=-inline-normal-into-special-section=true \
|
||||
--plugin-opt=-dont-used-symbol-list=malloc,free,sprintf,printf,puts,putchar \
|
||||
--plugin-opt=save-temps \
|
||||
--plugin-opt=-pi32v2-enable-rep-memop \
|
||||
--plugin-opt=-warn-stack-size=256 \
|
||||
--sort-common \
|
||||
--plugin-opt=-used-symbol-file=cpu/br28/sdk_used_list.used \
|
||||
--plugin-opt=-pi32v2-large-program=true \
|
||||
--gc-sections \
|
||||
--start-group \
|
||||
cpu/br28/liba/cpu.a \
|
||||
cpu/br28/liba/system.a \
|
||||
cpu/br28/liba/btstack.a \
|
||||
cpu/br28/liba/rcsp_stack.a \
|
||||
cpu/br28/liba/tme_stack.a \
|
||||
cpu/br28/liba/google_fps.a \
|
||||
cpu/br28/liba/btctrler.a \
|
||||
cpu/br28/liba/aec.a \
|
||||
cpu/br28/liba/lib_icsd_anc.a \
|
||||
cpu/br28/liba/media.a \
|
||||
cpu/br28/liba/libepmotion.a \
|
||||
cpu/br28/liba/libAptFilt_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/libEchoSuppress_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/libNoiseSuppress_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/libSplittingFilter_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/libDelayEstimate_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/libDualMicSystem_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/libDualMicSystem_flexible_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/libAdaptiveEchoSuppress_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/libOpcore_maskrom_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/lib_esco_repair.a \
|
||||
cpu/br28/liba/noisegate.a \
|
||||
cpu/br28/liba/sbc_eng_lib.a \
|
||||
cpu/br28/liba/mp3_dec_lib.a \
|
||||
cpu/br28/liba/mp3_decstream_lib.a \
|
||||
cpu/br28/liba/mp3tsy_dec_lib.a \
|
||||
cpu/br28/liba/wav_dec_lib.a \
|
||||
cpu/br28/liba/flac_dec_lib.a \
|
||||
cpu/br28/liba/m4a_dec_lib.a \
|
||||
cpu/br28/liba/ape_dec_lib.a \
|
||||
cpu/br28/liba/wma_dec_lib.a \
|
||||
cpu/br28/liba/amr_dec_lib.a \
|
||||
cpu/br28/liba/dts_dec_lib.a \
|
||||
cpu/br28/liba/agreement.a \
|
||||
cpu/br28/liba/media_app.a \
|
||||
cpu/br28/liba/lc3_codec_lib.a \
|
||||
cpu/br28/liba/opus_dec_lib.a \
|
||||
cpu/br28/liba/speex_enc_lib.a \
|
||||
cpu/br28/liba/ldac_dec_lib.a \
|
||||
cpu/br28/liba/opus_enc_lib.a \
|
||||
cpu/br28/liba/bt_hash_enc.a \
|
||||
cpu/br28/liba/libjlsp.a \
|
||||
cpu/br28/liba/libjlsp_kws.a \
|
||||
cpu/br28/liba/lfaudio_plc_lib.a \
|
||||
cpu/br28/liba/drc.a \
|
||||
cpu/br28/liba/crossover_coff_old.a \
|
||||
cpu/br28/liba/lib_point360_td.a \
|
||||
cpu/br28/liba/lib_resample_cal.a \
|
||||
cpu/br28/liba/lib_resample_fast_cal.a \
|
||||
cpu/br28/liba/SpatialAudio.a \
|
||||
cpu/br28/liba/SensorCalib.a \
|
||||
cpu/br28/liba/lib_pitchshifter.a \
|
||||
cpu/br28/liba/VirtualBass.a \
|
||||
cpu/br28/liba/lib_sur_cal.a \
|
||||
cpu/br28/liba/limiter_noiseGate.a \
|
||||
cpu/br28/liba/howling.a \
|
||||
cpu/br28/liba/lib_howlings_phf.a \
|
||||
cpu/br28/liba/libllns.a \
|
||||
cpu/br28/liba/libkwscommon.a \
|
||||
apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a \
|
||||
apps/usr_le_code/lib/libusr_le_code.a \
|
||||
cpu/br28/liba/lib_icsd_adt.a \
|
||||
cpu/br28/liba/lib_diafx.a \
|
||||
cpu/br28/liba/libFFT_pi32v2_OnChip.a \
|
||||
cpu/br28/liba/wtg_dec_lib.a \
|
||||
cpu/br28/liba/bfilterfun_lib.a \
|
||||
cpu/br28/liba/aac_dec_lib.a \
|
||||
cpu/br28/liba/crypto_toolbox_Osize.a \
|
||||
cpu/br28/liba/lib_dns.a \
|
||||
cpu/br28/liba/update.a \
|
||||
cpu/br28/liba/compressor.a \
|
||||
cpu/br28/liba/limiter.a \
|
||||
--end-group \
|
||||
-Tcpu/br28/sdk.ld \
|
||||
-M=cpu/br28/tools/sdk.map \
|
||||
--plugin-opt=mcpu=r3 \
|
||||
--plugin-opt=-mattr=+fprev1 \
|
||||
|
||||
|
||||
LIBPATHS := \
|
||||
-L$(SYS_LIB_DIR) \
|
||||
|
||||
|
||||
LIBS := \
|
||||
$(SYS_LIB_DIR)/libm.a \
|
||||
$(SYS_LIB_DIR)/libc.a \
|
||||
$(SYS_LIB_DIR)/libm.a \
|
||||
$(SYS_LIB_DIR)/libcompiler-rt.a \
|
||||
|
||||
|
||||
|
||||
c_OBJS := $(c_SRC_FILES:%.c=%.c.o)
|
||||
S_OBJS := $(S_SRC_FILES:%.S=%.S.o)
|
||||
s_OBJS := $(s_SRC_FILES:%.s=%.s.o)
|
||||
cpp_OBJS := $(cpp_SRC_FILES:%.cpp=%.cpp.o)
|
||||
cxx_OBJS := $(cxx_SRC_FILES:%.cxx=%.cxx.o)
|
||||
cc_OBJS := $(cc_SRC_FILES:%.cc=%.cc.o)
|
||||
|
||||
OBJS := $(c_OBJS) $(S_OBJS) $(s_OBJS) $(cpp_OBJS) $(cxx_OBJS) $(cc_OBJS)
|
||||
DEP_FILES := $(OBJS:%.o=%.d)
|
||||
|
||||
|
||||
OBJS := $(addprefix $(BUILD_DIR)/, $(OBJS))
|
||||
DEP_FILES := $(addprefix $(BUILD_DIR)/, $(DEP_FILES))
|
||||
|
||||
|
||||
VERBOSE ?= 0
|
||||
ifeq ($(VERBOSE), 1)
|
||||
QUITE :=
|
||||
else
|
||||
QUITE := @
|
||||
endif
|
||||
|
||||
# 一些旧的 make 不支持 file 函数,需要 make 的时候指定 LINK_AT=0 make
|
||||
LINK_AT ?= 1
|
||||
|
||||
# 表示下面的不是一个文件的名字,无论是否存在 all, clean, pre_build 这样的文件
|
||||
# 还是要执行命令
|
||||
# see: https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html
|
||||
.PHONY: all clean pre_build
|
||||
|
||||
# 不要使用 make 预设置的规则
|
||||
# see: https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html
|
||||
.SUFFIXES:
|
||||
|
||||
all: pre_build $(USR_LE_LIB) $(OUT_ELF)
|
||||
$(info +POST-BUILD)
|
||||
$(QUITE) $(RUN_POST_SCRIPT) sdk
|
||||
|
||||
|
||||
pre_build:
|
||||
$(info +PRE-BUILD)
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br28/sdk_used_list.c -o cpu/br28/sdk_used_list.used
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br28/sdk_ld.c -o cpu/br28/sdk.ld
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br28/tools/download.c -o $(POST_SCRIPT)
|
||||
$(QUITE) $(FIXBAT) $(POST_SCRIPT)
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br28/tools/isd_config_rule.c -o cpu/br28/tools/isd_config.ini
|
||||
|
||||
clean:
|
||||
$(QUITE) $(RM) $(OUT_ELF)
|
||||
$(QUITE) $(RM) $(BUILD_DIR)
|
||||
|
||||
|
||||
|
||||
ifeq ($(LINK_AT), 1)
|
||||
$(OUT_ELF): $(OBJS) $(USR_LE_LIB)
|
||||
$(info +LINK $@)
|
||||
$(shell $(MKDIR) $(@D))
|
||||
$(file >$(OBJ_FILE), $(OBJS))
|
||||
$(QUITE) $(LD) -o $(OUT_ELF) @$(OBJ_FILE) $(LFLAGS) $(LIBPATHS) $(LIBS)
|
||||
else
|
||||
$(OUT_ELF): $(OBJS) $(USR_LE_LIB)
|
||||
$(info +LINK $@)
|
||||
$(shell $(MKDIR) $(@D))
|
||||
$(QUITE) $(LD) -o $(OUT_ELF) $(OBJS) $(LFLAGS) $(LIBPATHS) $(LIBS)
|
||||
endif
|
||||
|
||||
|
||||
$(BUILD_DIR)/%.c.o : %.c
|
||||
$(info +CC $<)
|
||||
$(QUITE) $(MKDIR) $(@D)
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d)
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.S.o : %.S
|
||||
$(info +AS $<)
|
||||
$(QUITE) $(MKDIR) $(@D)
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d)
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.s.o : %.s
|
||||
$(info +AS $<)
|
||||
$(QUITE) $(MKDIR) $(@D)
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d)
|
||||
$(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.cpp.o : %.cpp
|
||||
$(info +CXX $<)
|
||||
$(QUITE) $(MKDIR) $(@D)
|
||||
$(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d)
|
||||
$(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.cxx.o : %.cxx
|
||||
$(info +CXX $<)
|
||||
$(QUITE) $(MKDIR) $(@D)
|
||||
$(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d)
|
||||
$(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@
|
||||
|
||||
$(BUILD_DIR)/%.cc.o : %.cc
|
||||
$(info +CXX $<)
|
||||
$(QUITE) $(MKDIR) $(@D)
|
||||
$(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d)
|
||||
$(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@
|
||||
|
||||
-include $(DEP_FILES)
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
****************************************************************
|
||||
* Amplitude Statistics
|
||||
* 幅值统计模块
|
||||
* File : amplitude_statistic.c
|
||||
* By :
|
||||
* Notes :
|
||||
****************************************************************
|
||||
*/
|
||||
|
||||
#include "amplitude_statistic.h"
|
||||
|
||||
#if 0
|
||||
#define amplitude_log printf
|
||||
#else
|
||||
#define amplitude_log(...)
|
||||
#endif/*log_en*/
|
||||
|
||||
static const unsigned short am_va_tab[] = {
|
||||
32768, 29205, 26029, 23198, 20675, 18427, 16423, 14637, 13045, 11627, 10362, 9235, 8231, 7336, 6538, 5827,
|
||||
5193, 4629, 4125, 3677, 3277, 2920, 2603, 2320, 2068, 1843, 1642, 1464, 1305, 1163, 1036, 0
|
||||
};
|
||||
|
||||
static const int rms_va_tab[] = {
|
||||
134217728, 106612931, 84685661, 67268212, 53433040, 42443372, 33713969, 26779957, 21272076, 16897011,
|
||||
13421773, 10661293, 8468566, 6726821, 5343304, 4244337, 3371397, 2677996, 2127208, 1689701,
|
||||
1342177, 1066129, 846857, 672682, 534330, 424434, 337140, 267800, 212721, 168970,
|
||||
134218, 0
|
||||
};
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Loudness meter init
|
||||
* Description: 响度计算初始化
|
||||
* Arguments : loud_obj
|
||||
* sr
|
||||
* print_dest
|
||||
* index
|
||||
* Return : NULL
|
||||
* Note(s) : NULL
|
||||
*********************************************************************
|
||||
*/
|
||||
void loudness_meter_init(LOUDNESS_M_STRUCT *loud_obj, int sr, int print_dest, u8 index)
|
||||
{
|
||||
memset(loud_obj, 0, sizeof(LOUDNESS_M_STRUCT));
|
||||
loud_obj->countperiod = sr / 50;
|
||||
loud_obj->inv_counterpreiod = 16777216 / loud_obj->countperiod;
|
||||
loud_obj->print_dest = print_dest;
|
||||
loud_obj->index = index;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Loudness meter short
|
||||
* Description: 响度计算函数
|
||||
* Arguments : loud_obj
|
||||
* data
|
||||
* len
|
||||
* Return : NULL
|
||||
* Note(s) : NULL
|
||||
*********************************************************************
|
||||
*/
|
||||
void loudness_meter_short(LOUDNESS_M_STRUCT *loud_obj, short *data, int len)
|
||||
{
|
||||
int i;
|
||||
int loudness_val = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int tmp = data[i] * 256;
|
||||
loud_obj->dclevel = (loud_obj->dclevel * 511 + tmp) >> 9;
|
||||
|
||||
int xabs = (data[i] > 0) ? data[i] : (-data[i]);
|
||||
int xabs2 = (xabs * xabs) >> 10;
|
||||
loud_obj->rms += xabs2;
|
||||
loud_obj->maxval = (loud_obj->maxval > xabs) ? loud_obj->maxval : xabs;
|
||||
|
||||
if (xabs >= 32767) {
|
||||
loud_obj->errprintfcount0++;
|
||||
}
|
||||
|
||||
loud_obj->counti++;
|
||||
if (loud_obj->counti > loud_obj->countperiod) {
|
||||
if (loud_obj->maxval_print < loud_obj->maxval) {
|
||||
loud_obj->maxval_print = loud_obj->maxval;
|
||||
}
|
||||
|
||||
if (loud_obj->rms_print < loud_obj->rms) {
|
||||
loud_obj->rms_print = loud_obj->rms;
|
||||
}
|
||||
|
||||
loud_obj->counti = 0;
|
||||
loud_obj->maxval = 0;
|
||||
loud_obj->rms = 0;
|
||||
|
||||
if (loud_obj->errprintfcount0 > 2) {
|
||||
loud_obj->errprintfcount0 = 0;
|
||||
amplitude_log("[%d]overflow occur... \n", loud_obj->index);
|
||||
}
|
||||
|
||||
loud_obj->print_cnt++;
|
||||
|
||||
if (loud_obj->print_cnt >= loud_obj->print_dest) {
|
||||
|
||||
int rmsval = ((__int64)loud_obj->rms_print * (__int64)loud_obj->inv_counterpreiod) >> (24 - (10 - 3));
|
||||
|
||||
if (rmsval > 25837266) {
|
||||
amplitude_log("[%d]energy high... \n", loud_obj->index);
|
||||
}
|
||||
|
||||
{
|
||||
int compi = 0, found = 0;;
|
||||
while (compi < 31) {
|
||||
if (rmsval >= rms_va_tab[compi]) {
|
||||
// float upval = (0 - compi) * 0.5;
|
||||
// float dwonval = (0 - compi - 1) * 0.5;
|
||||
// amplitude_log("rms level: %f to %f dB\n", upval, dwonval);
|
||||
|
||||
int upval = (0 - compi);
|
||||
int dwonval = (0 - compi - 1);
|
||||
|
||||
amplitude_log("[%d]rms level: %d to %d dB\n", loud_obj->index, upval, dwonval);
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
compi++;
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
amplitude_log("[%d]rms level < -30dB \n", loud_obj->index);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int compi = 0, found = 0;;
|
||||
while (compi < 31) {
|
||||
if (loud_obj->maxval_print >= am_va_tab[compi]) {
|
||||
// float upval = (0 - compi) * 0.5;
|
||||
// float dwonval = (0 - compi - 1) * 0.5;
|
||||
// amplitude_log("peak level: %f to %f dB\n", upval, dwonval);
|
||||
int upval = (0 - compi);
|
||||
int dwonval = (0 - compi - 1);
|
||||
loud_obj->peak_val = dwonval;
|
||||
amplitude_log("[%d]peak level: %d to %d dB\n", loud_obj->index, upval, dwonval);
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
compi++;
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
loud_obj->peak_val = -31;
|
||||
amplitude_log("[%d]peak level < -30dB \n", loud_obj->index);
|
||||
}
|
||||
}
|
||||
|
||||
loud_obj->print_cnt = 0;
|
||||
loud_obj->maxval_print = 0;
|
||||
loud_obj->rms_print = 0;
|
||||
|
||||
if (loud_obj->dclevel > (255 * 256)) {
|
||||
amplitude_log("[%d] why ??? dc level : %d \n", loud_obj->index, loud_obj->dclevel >> 8);
|
||||
}
|
||||
amplitude_log("\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void loudness_meter_demo(void)
|
||||
{
|
||||
loudness_meter_init(&loudness_adc, 16000, 1);
|
||||
loudness_meter_short(&loudness_adc, datain, points);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef _AMPLITUDE_STATISTIC_H_
|
||||
#define _AMPLITUDE_STATISTIC_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
typedef struct _LOUDNESS_M_STRUCT_ {
|
||||
int mutecnt;
|
||||
int rms;
|
||||
int counti;
|
||||
int maxval;
|
||||
int countperiod;
|
||||
int inv_counterpreiod;
|
||||
int errprintfcount0;
|
||||
short print_cnt;
|
||||
short print_dest;
|
||||
int dclevel;
|
||||
int rms_print;
|
||||
int maxval_print;
|
||||
int peak_val;
|
||||
u8 index;
|
||||
} LOUDNESS_M_STRUCT;
|
||||
|
||||
void loudness_meter_init(LOUDNESS_M_STRUCT *loud_obj, int sr, int print_dest, u8 index);
|
||||
void loudness_meter_short(LOUDNESS_M_STRUCT *loud_obj, short *data, int len);
|
||||
|
||||
#endif /*_AMPLITUDE_STATISTIC_H_*/
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef _AUDIO_NOISE_GATE_H_
|
||||
#define _AUDIO_NOISE_GATE_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
|
||||
u8 *audio_noise_gate_open(int attack_time, int release_time, float thr, float gain, int sr, int ch);
|
||||
|
||||
void audio_noise_gate_run(u8 *runbuf, void *in, void *out, u16 len);
|
||||
|
||||
void audio_noise_gate_close(u8 *runbuf);
|
||||
|
||||
#endif/*_AUDIO_NOISE_GATE_H_*/
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef _AUDIO_DIGITAL_VOL_H_
|
||||
#define _AUDIO_DIGITAL_VOL_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "os/os_type.h"
|
||||
#include "os/os_api.h"
|
||||
#include "generic/list.h"
|
||||
|
||||
#define BG_DVOL_FADE_ENABLE 1 /*多路声音叠加,背景声音自动淡出小声*/
|
||||
|
||||
typedef struct {
|
||||
u8 toggle; /*数字音量开关*/
|
||||
u8 fade; /*淡入淡出标志*/
|
||||
u8 vol; /*淡入淡出当前音量(level)*/
|
||||
u8 vol_max; /*淡入淡出最大音量(level)*/
|
||||
s16 vol_fade; /*淡入淡出对应的起始音量*/
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
s16 vol_bk; /*后台自动淡出前音量值*/
|
||||
struct list_head entry;
|
||||
#endif
|
||||
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
|
||||
volatile u16 fade_step; /*淡入淡出的步进*/
|
||||
} dvol_handle;
|
||||
|
||||
|
||||
int audio_digital_vol_init(void);
|
||||
void audio_digital_vol_bg_fade(u8 fade_out);
|
||||
dvol_handle *audio_digital_vol_open(u8 vol, u8 vol_max, u16 fade_step);
|
||||
void audio_digital_vol_close(dvol_handle *dvol);
|
||||
void audio_digital_vol_set(dvol_handle *dvol, u8 vol);
|
||||
u8 audio_digital_vol_get(void);
|
||||
int audio_digital_vol_run(dvol_handle *dvol, void *data, u32 len);
|
||||
void audio_digital_vol_reset_fade(dvol_handle *dvol);
|
||||
|
||||
/*************************自定义支持重入的数字音量调节****************************/
|
||||
void *user_audio_digital_volume_open(u8 vol, u8 vol_max, u16 fade_step);
|
||||
int user_audio_digital_volume_close(void *_d_volume);
|
||||
u8 user_audio_digital_volume_get(void *_d_volume);
|
||||
int user_audio_digital_volume_set(void *_d_volume, u8 vol);
|
||||
int user_audio_digital_volume_reset_fade(void *_d_volume);
|
||||
int user_audio_digital_volume_run(void *_d_volume, void *data, u32 len, u8 ch_num);
|
||||
void user_audio_digital_handler_run(void *_d_volume, void *data, u32 len);
|
||||
void user_audio_digital_set_volume_tab(void *_d_volume, u16 *user_vol_tab, u8 user_vol_max);
|
||||
|
||||
void *user_audio_process_open(void *parm, void *priv, void (*handler)(void *priv, void *data, int len, u8 ch_num));
|
||||
int user_audio_process_close(void *_uparm_hdl);
|
||||
void user_audio_process_handler_run(void *_uparm_hdl, void *data, u32 len, u8 ch_num);
|
||||
|
||||
struct user_audio_digital_parm {
|
||||
u8 en;
|
||||
u8 vol;
|
||||
u8 vol_max;
|
||||
u16 fade_step;
|
||||
};
|
||||
|
||||
struct digital_volume {
|
||||
u8 toggle; /*数字音量开关*/
|
||||
u8 fade; /*淡入淡出标志*/
|
||||
u8 vol; /*淡入淡出当前音量*/
|
||||
u8 vol_max; /*淡入淡出最大音量*/
|
||||
s16 vol_fade; /*淡入淡出对应的起始音量*/
|
||||
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
|
||||
volatile u16 fade_step; /*淡入淡出的步进*/
|
||||
|
||||
OS_MUTEX mutex;
|
||||
u8 ch_num;
|
||||
void *priv;
|
||||
u8 user_vol_max; /*自定义音量表级数*/
|
||||
volatile s16 *user_vol_tab; /*自定义音量表*/
|
||||
|
||||
};
|
||||
|
||||
struct user_audio_parm {
|
||||
void *priv;
|
||||
void (*handler)(void *priv, void *data, int len, u8 ch_num);/*用户自定义回调处理*/
|
||||
struct digital_volume *dvol_hdl;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
****************************************************************
|
||||
* AUDIO DIGITAL VOLUME
|
||||
* File : audio_dvol.c
|
||||
* By :
|
||||
* Notes : 数字音量模块,支持多通道音量控制
|
||||
****************************************************************
|
||||
*/
|
||||
|
||||
#include "audio_dvol.h"
|
||||
|
||||
#if 0
|
||||
#define dvol_log y_printf
|
||||
#else
|
||||
#define dvol_log(...)
|
||||
#endif
|
||||
|
||||
#define DIGITAL_FADE_EN 1
|
||||
#define DIGITAL_FADE_STEP 4
|
||||
|
||||
#define BG_DVOL_MAX 14
|
||||
#define BG_DVOL_MID 10
|
||||
#define BG_DVOL_MIN 6
|
||||
#define BG_DVOL_MAX_FADE 13 /*>= BG_DVOL_MAX:自动淡出BG_DVOL_MAX_FADE*/
|
||||
#define BG_DVOL_MID_FADE 9 /*>= BG_DVOL_MID:自动淡出BG_DVOL_MID_FADE*/
|
||||
#define BG_DVOL_MIN_FADE 5 /*>= BG_DVOL_MIN:自动淡出BG_DVOL_MIN_FADE*/
|
||||
|
||||
#define ASM_ENABLE 1
|
||||
#define L_sat(b,a) __asm__ volatile("%0=sat16(%1)(s)":"=&r"(b) : "r"(a));
|
||||
#define L_sat32(b,a,n) __asm__ volatile("%0=%1>>%2(s)":"=&r"(b) : "r"(a),"r"(n));
|
||||
|
||||
typedef struct {
|
||||
u8 bg_dvol_fade_out;
|
||||
u8 start;
|
||||
OS_MUTEX mutex;
|
||||
struct list_head dvol_head;
|
||||
} dvol_t;
|
||||
static dvol_t dvol_attr;
|
||||
|
||||
/*
|
||||
*数字音量级数 DEFAULT_DIGITAL_VOL_MAX
|
||||
*数组长度 DEFAULT_DIGITAL_VOL_MAX + 1
|
||||
*/
|
||||
#define DEFAULT_DIGITAL_VOL_MAX (31)
|
||||
const u16 default_dig_vol_table[DEFAULT_DIGITAL_VOL_MAX + 1] = {
|
||||
0 , //0
|
||||
93 , //1
|
||||
111 , //2
|
||||
132 , //3
|
||||
158 , //4
|
||||
189 , //5
|
||||
226 , //6
|
||||
270 , //7
|
||||
323 , //8
|
||||
386 , //9
|
||||
462 , //10
|
||||
552 , //11
|
||||
660 , //12
|
||||
789 , //13
|
||||
943 , //14
|
||||
1127, //15
|
||||
1347, //16
|
||||
1610, //17
|
||||
1925, //18
|
||||
2301, //19
|
||||
2751, //20
|
||||
3288, //21
|
||||
3930, //22
|
||||
4698, //23
|
||||
5616, //24
|
||||
6713, //25
|
||||
8025, //26
|
||||
9592, //27
|
||||
11466,//28
|
||||
15200,//29
|
||||
16000,//30
|
||||
16384 //31
|
||||
};
|
||||
|
||||
static u16 digital_vol_max = DEFAULT_DIGITAL_VOL_MAX;
|
||||
static u16 *dig_vol_table = default_dig_vol_table;
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Init
|
||||
* Description: 数字音量模块初始化
|
||||
* Arguments : None.
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_digital_vol_init(u16 *vol_table, u16 vol_max)
|
||||
{
|
||||
memset(&dvol_attr, 0, sizeof(dvol_attr));
|
||||
INIT_LIST_HEAD(&dvol_attr.dvol_head);
|
||||
os_mutex_create(&dvol_attr.mutex);
|
||||
|
||||
if (vol_table != NULL) {
|
||||
dig_vol_table = vol_table;
|
||||
digital_vol_max = vol_max;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*背景音乐淡出使能*/
|
||||
void audio_digital_vol_bg_fade(u8 fade_out)
|
||||
{
|
||||
dvol_log("audio_digital_vol_bg_fade:%d", fade_out);
|
||||
dvol_attr.bg_dvol_fade_out = fade_out;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Open
|
||||
* Description: 数字音量模块打开
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* vol 当前数字音量等级
|
||||
* vol_max 最大数字音量等级
|
||||
* fade_step 淡入淡出步进
|
||||
* vol_limit 数字音量限制,即可以给vol_max等分的最大音量
|
||||
* Return : 数字音量通道句柄
|
||||
* Note(s) : fade_step一般不超过两级数字音量的最小差值
|
||||
* (1)通话如果用数字音量,一般步进小一点,音量调节的时候不会有杂音
|
||||
* (2)淡出的时候可以快一点,尽快淡出到0
|
||||
*********************************************************************
|
||||
*/
|
||||
dvol_handle *audio_digital_vol_open(u8 dvol_idx, u8 vol, u8 vol_max, u16 fade_step, char vol_limit)
|
||||
{
|
||||
dvol_log("dvol_open:%d-%d-%d-%d\n", vol, vol_max, fade_step, vol_limit);
|
||||
dvol_handle *dvol = NULL;
|
||||
dvol = zalloc(sizeof(dvol_handle));
|
||||
if (dvol) {
|
||||
u8 vol_level;
|
||||
dvol->fade = DIGITAL_FADE_EN;
|
||||
dvol->vol = (vol > vol_max) ? vol_max : vol;
|
||||
if (vol > vol_max) {
|
||||
printf("[warning]cur digital_vol(%d) > digital_vol_max(%d)!!", vol, vol_max);
|
||||
}
|
||||
dvol->vol_max = vol_max;
|
||||
if (vol_limit == -1) {
|
||||
dvol->vol_limit = digital_vol_max;
|
||||
} else {
|
||||
dvol->vol_limit = (vol_limit > digital_vol_max) ? digital_vol_max : vol_limit;
|
||||
}
|
||||
vol_level = dvol->vol * dvol->vol_limit / vol_max;
|
||||
dvol->vol_target = dig_vol_table[vol_level];
|
||||
dvol->vol_fade = dvol->vol_target;
|
||||
dvol->fade_step = fade_step;
|
||||
dvol->toggle = 1;
|
||||
dvol->idx = dvol_idx;
|
||||
local_irq_disable();
|
||||
list_add(&dvol->entry, &dvol_attr.dvol_head);
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
dvol->vol_bk = -1;
|
||||
if (dvol_attr.bg_dvol_fade_out) {
|
||||
dvol_handle *hdl;
|
||||
list_for_each_entry(hdl, &dvol_attr.dvol_head, entry) {
|
||||
if ((hdl != dvol) && (hdl->idx)) {
|
||||
hdl->vol_bk = hdl->vol;
|
||||
if (hdl->vol >= BG_DVOL_MAX) {
|
||||
hdl->vol -= BG_DVOL_MAX_FADE;
|
||||
} else if (hdl->vol >= BG_DVOL_MID) {
|
||||
hdl->vol -= BG_DVOL_MID_FADE;
|
||||
} else if (hdl->vol >= BG_DVOL_MIN) {
|
||||
hdl->vol -= BG_DVOL_MIN_FADE;
|
||||
} else {
|
||||
hdl->vol_bk = -1;
|
||||
continue;
|
||||
}
|
||||
u8 vol_level = hdl->vol * dvol->vol_limit / hdl->vol_max;
|
||||
hdl->vol_target = dig_vol_table[vol_level];
|
||||
//y_printf("bg_dvol fade_out:%x,vol_bk:%d,vol_set:%d,tartget:%d",hdl,hdl->vol_bk,hdl->vol,hdl->vol_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif/*BG_DVOL_FADE_ENABLE*/
|
||||
local_irq_enable();
|
||||
dvol_log("dvol_open[%x]:%x-%d-%d-%d\n", dvol_idx, dvol, dvol->vol, dvol->vol_max, fade_step);
|
||||
}
|
||||
return dvol;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Close
|
||||
* Description: 数字音量模块关闭
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_digital_vol_close(u8 dvol_idx)
|
||||
{
|
||||
dvol_log("dvol_close[%x]\n", dvol_idx);
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_log("dvol_close[%x]:%x", dvol_idx, dvol);
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dvol_valid == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dvol) {
|
||||
local_irq_disable();
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
dvol_handle *hdl;
|
||||
list_for_each_entry(hdl, &dvol_attr.dvol_head, entry) {
|
||||
if ((hdl != dvol) && (hdl->vol_bk >= 0)) {
|
||||
//y_printf("bg_dvol fade_in:%x,%d",hdl,hdl->vol_bk);
|
||||
hdl->vol = hdl->vol_bk;
|
||||
u8 vol_level = hdl->vol_bk * dvol->vol_limit / hdl->vol_max;
|
||||
hdl->vol_target = dig_vol_table[vol_level];
|
||||
hdl->vol_bk = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
list_del(&dvol->entry);
|
||||
free(dvol);
|
||||
dvol = NULL;
|
||||
local_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Get
|
||||
* Description: 数字音量获取
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* Return : 对应的数字音量通道的当前音量等级.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_digital_vol_get(u8 dvol_idx)
|
||||
{
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if (dvol && dvol_valid) {
|
||||
return dvol->vol;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Set
|
||||
* Description: 数字音量设置
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* vol 目标音量等级
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_digital_vol_set(u8 dvol_idx, u8 vol)
|
||||
{
|
||||
dvol_log("audio_digital_vol set:%d,%d\n", dvol_idx, vol);
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_log("dvol_set[%x]:%x", dvol_idx, dvol);
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if ((dvol == NULL) || (dvol_valid == 0)) {
|
||||
return;
|
||||
}
|
||||
if (dvol->toggle == 0) {
|
||||
return;
|
||||
}
|
||||
dvol->vol = (vol > dvol->vol_max) ? dvol->vol_max : vol;
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
if (dvol->vol_bk != -1) {
|
||||
dvol->vol_bk = vol;
|
||||
}
|
||||
#endif
|
||||
dvol->fade = DIGITAL_FADE_EN;
|
||||
u8 vol_level = dvol->vol * dvol->vol_limit / dvol->vol_max;
|
||||
dvol->vol_target = dig_vol_table[vol_level];
|
||||
dvol_log("digital_vol:%d-%d-%d-%d\n", vol, vol_level, dvol->vol_fade, dvol->vol_target);
|
||||
}
|
||||
/*********************************************************************
|
||||
* Audio Digital Volume Set
|
||||
* Description: 数字音量设置,设置数字音量的当前值,不用淡入淡出
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* vol 目标音量等级
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
|
||||
void audio_digital_vol_set_no_fade(u8 dvol_idx, u8 vol)
|
||||
{
|
||||
dvol_log("audio_digital_vol set:%d,%d\n", dvol_idx, vol);
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_log("dvol_set[%x]:%x", dvol_idx, dvol);
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if ((dvol == NULL) || (dvol_valid == 0)) {
|
||||
return;
|
||||
}
|
||||
if (dvol->toggle == 0) {
|
||||
return;
|
||||
}
|
||||
dvol->vol = (vol > dvol->vol_max) ? dvol->vol_max : vol;
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
if (dvol->vol_bk != -1) {
|
||||
dvol->vol_bk = vol;
|
||||
}
|
||||
#endif
|
||||
dvol->fade = DIGITAL_FADE_EN;
|
||||
u8 vol_level = dvol->vol * dvol->vol_limit / dvol->vol_max;
|
||||
dvol->vol_fade = dig_vol_table[vol_level];
|
||||
dvol_log("digital_vol:%d-%d-%d-%d\n", vol, vol_level, dvol->vol_fade, dvol->vol_target);
|
||||
}
|
||||
|
||||
void audio_digital_vol_reset_fade(u8 dvol_idx)
|
||||
{
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if (dvol && dvol_valid) {
|
||||
dvol->vol_fade = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Process
|
||||
* Description: 数字音量运算核心
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* data 待运算数据
|
||||
* len 待运算数据长度
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
/*rounding处理*/
|
||||
#define MUL32_PSHIFT(x,y,s) (((x) * (y) + (1 << ((s)-1))) >> (s))
|
||||
|
||||
int audio_digital_vol_run(u8 dvol_idx, void *data, u32 len)
|
||||
{
|
||||
s32 valuetemp;
|
||||
s16 *buf;
|
||||
|
||||
os_mutex_pend(&dvol_attr.mutex, 0);
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_valid = 1;
|
||||
#if 0
|
||||
static dvol_handle *last_dvol = NULL;
|
||||
if (last_dvol != dvol) {
|
||||
dvol_log("dvol_run[%x]:%x", dvol_idx, dvol);
|
||||
last_dvol = dvol;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
if ((dvol->toggle == 0) || (dvol_valid == 0)) {
|
||||
os_mutex_post(&dvol_attr.mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = data;
|
||||
len >>= 1; //byte to point
|
||||
|
||||
for (u32 i = 0; i < len; i += 2) {
|
||||
///left channel
|
||||
if (dvol->fade) {
|
||||
if (dvol->vol_fade > dvol->vol_target) {
|
||||
dvol->vol_fade -= dvol->fade_step;
|
||||
if (dvol->vol_fade < dvol->vol_target) {
|
||||
dvol->vol_fade = dvol->vol_target;
|
||||
}
|
||||
} else if (dvol->vol_fade < dvol->vol_target) {
|
||||
dvol->vol_fade += dvol->fade_step;
|
||||
if (dvol->vol_fade > dvol->vol_target) {
|
||||
dvol->vol_fade = dvol->vol_target;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dvol->vol_fade = dvol->vol_target;
|
||||
}
|
||||
|
||||
valuetemp = buf[i];
|
||||
if (valuetemp < 0) {
|
||||
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
|
||||
valuetemp = -valuetemp;
|
||||
/*rounding处理(加入0.5),减少小信号时候的误差和谐波幅值*/
|
||||
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
|
||||
valuetemp = -valuetemp;
|
||||
} else {
|
||||
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
|
||||
}
|
||||
/*饱和处理*/
|
||||
buf[i] = (s16)data_sat_s16(valuetemp);
|
||||
|
||||
///right channel
|
||||
valuetemp = buf[i + 1];
|
||||
if (valuetemp < 0) {
|
||||
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
|
||||
valuetemp = -valuetemp;
|
||||
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
|
||||
valuetemp = -valuetemp;
|
||||
} else {
|
||||
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
|
||||
}
|
||||
/*饱和处理*/
|
||||
buf[i + 1] = (s16)data_sat_s16(valuetemp);
|
||||
}
|
||||
os_mutex_post(&dvol_attr.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef _AUDIO_DVOL_H_
|
||||
#define _AUDIO_DVOL_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "os/os_type.h"
|
||||
#include "os/os_api.h"
|
||||
#include "generic/list.h"
|
||||
|
||||
#define BG_DVOL_FADE_ENABLE 1 /*多路声音叠加,背景声音自动淡出小声*/
|
||||
|
||||
/*Digital Volume Channel*/
|
||||
#define MUSIC_DVOL 0xA1
|
||||
#define CALL_DVOL 0xA2
|
||||
#define TONE_DVOL 0xA3
|
||||
#define HEARING_DVOL 0xA4
|
||||
|
||||
/*Digital Volume Fade Step*/
|
||||
#define MUSIC_DVOL_FS 2
|
||||
#define CALL_DVOL_FS 4
|
||||
#define TONE_DVOL_FS 30
|
||||
#define HEARING_DVOL_FS 2
|
||||
|
||||
/*Digital Volume Max Level*/
|
||||
#define MUSIC_DVOL_MAX 16
|
||||
#define CALL_DVOL_MAX 15
|
||||
#define TONE_DVOL_MAX 16
|
||||
#define HEARING_DVOL_MAX 16
|
||||
|
||||
typedef struct {
|
||||
u8 toggle; /*数字音量开关*/
|
||||
u8 fade; /*淡入淡出标志*/
|
||||
u8 vol; /*淡入淡出当前音量(level)*/
|
||||
u8 vol_max; /*淡入淡出最大音量(level)*/
|
||||
char vol_limit; /*最大数字音量限制*/
|
||||
u8 idx; /*数字音量通道索引*/
|
||||
s16 vol_fade; /*淡入淡出对应的起始音量*/
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
s16 vol_bk; /*后台自动淡出前音量值*/
|
||||
#endif/*BG_DVOL_FADE_ENABLE*/
|
||||
struct list_head entry;
|
||||
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
|
||||
volatile u16 fade_step; /*淡入淡出的步进*/
|
||||
} dvol_handle;
|
||||
|
||||
int audio_digital_vol_init(u16 *vol_table, u16 vol_max);
|
||||
void audio_digital_vol_bg_fade(u8 fade_out);
|
||||
dvol_handle *audio_digital_vol_open(u8 dvol_idx, u8 vol, u8 vol_max, u16 fade_step, char vol_limit);
|
||||
void audio_digital_vol_close(u8 dvol_idx);
|
||||
void audio_digital_vol_set(u8 dvol_idx, u8 vol);
|
||||
int audio_digital_vol_get(u8 dvol_idx);
|
||||
int audio_digital_vol_run(u8 dvol_idx, void *data, u32 len);
|
||||
void audio_digital_vol_reset_fade(u8 dvol_idx);
|
||||
void audio_digital_vol_set_no_fade(u8 dvol_idx, u8 vol);
|
||||
|
||||
#endif/*_AUDIO_DVOL_H_*/
|
||||
@@ -0,0 +1,140 @@
|
||||
#include "app_config.h"
|
||||
#ifdef AUDIO_PCM_DEBUG
|
||||
#include "uartPcmSender.h"
|
||||
|
||||
extern int aec_uart_init();
|
||||
extern int aec_uart_fill(u8 ch, void *buf, u16 size);
|
||||
extern void aec_uart_write(void);
|
||||
extern int aec_uart_close(void);
|
||||
|
||||
/*
|
||||
16k 正选波 pcm 数据
|
||||
*/
|
||||
static short const sin0_16k[16] = {
|
||||
0x0000, 0x30fd, 0x5a83, 0x7641, 0x7fff, 0x7642, 0x5a82, 0x30fc, 0x0000, 0xcf04, 0xa57d, 0x89be, 0x8000, 0x89be, 0xa57e, 0xcf05,
|
||||
};
|
||||
static u16 tx1_s_cnt = 0;
|
||||
static int get_sine0_data(u16 *s_cnt, s16 *data, u16 points, u8 ch)
|
||||
{
|
||||
while (points--) {
|
||||
if (*s_cnt >= 16) {
|
||||
*s_cnt = 0;
|
||||
}
|
||||
*data++ = sin0_16k[*s_cnt] / 2;
|
||||
if (ch == 2) {
|
||||
*data++ = sin0_16k[*s_cnt] / 2;
|
||||
}
|
||||
(*s_cnt)++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*************************************************************
|
||||
* uart data export 接口使用说明
|
||||
* 1、每个通道一次只能固定发送512byte数据,数据不够会被丢弃
|
||||
* 2、aec_uart_write()一次会发送3个通道的数据,没有填数的通道会发送空白数据
|
||||
* 3、UART DMA发送一次数据需要约8ms时间,两次发数间隔需 > 8ms
|
||||
* 4、发送波特率、发送引脚在 uartPcmSender.h 配置
|
||||
* 5、该接口的接收端需使用JL的串口导出工具接收数据
|
||||
*
|
||||
*************************************************************
|
||||
*/
|
||||
void audio_export_demo_task(void *param)
|
||||
{
|
||||
printf("audio_export_demo_task\n");
|
||||
s16 data[256];
|
||||
int len = 512;
|
||||
/*生成256个点的16k的正选波数据*/
|
||||
get_sine0_data(&tx1_s_cnt, data, len / 2, 1);
|
||||
|
||||
while (1) {
|
||||
putchar('.');
|
||||
|
||||
{
|
||||
/*run code*/
|
||||
}
|
||||
|
||||
aec_uart_fill(0, data, 512); //往通道0填数据
|
||||
|
||||
{
|
||||
/*run code*/
|
||||
}
|
||||
|
||||
aec_uart_fill(1, data, 512); //往通道1填数据
|
||||
|
||||
{
|
||||
/*run code*/
|
||||
}
|
||||
|
||||
aec_uart_fill(2, data, 512); //往通道2填数据
|
||||
aec_uart_write(); //一次把3路数据发送出去
|
||||
os_time_dly(2); //等待发送完成,发送一次要8ms,发完才可以进行下一次发数
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************
|
||||
* uart data export 接口使用示例
|
||||
*********************************************************
|
||||
*/
|
||||
int audio_export_demo_init()
|
||||
{
|
||||
printf("audio_export_demo_init\n");
|
||||
/* uartSendInit(); //串口初始化,已经在开机时调用初始化,这里不需调用 */
|
||||
aec_uart_init(); //uart export 初始化
|
||||
os_task_create(audio_export_demo_task, NULL, 1, 1024, 128, "audio_export_task");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*************************************************************
|
||||
* 通用 uart 发数接口(uartSendData())使用说明
|
||||
* 1、发数的数据长度可以根据需要修改
|
||||
* 2、一般发送512byte,DMA模式需要2.7ms
|
||||
* 3、发送波特率、发送引脚在 uartPcmSender.h 配置
|
||||
* 4、可以使用该接口自定义发数方式、协议等
|
||||
*
|
||||
*************************************************************
|
||||
*/
|
||||
void audio_uart_transmit_demo_task(void *param)
|
||||
{
|
||||
printf("audio_uart_transmit_demo_task\n");
|
||||
s16 data[256];
|
||||
int len = 512;
|
||||
/*生成256个点的16k的正选波数据*/
|
||||
get_sine0_data(&tx1_s_cnt, data, len / 2, 1);
|
||||
|
||||
while (1) {
|
||||
putchar('.');
|
||||
uartSendData(data, len); //uart 发送数据接口
|
||||
os_time_dly(1); //一般发送512byte,DMA模式需要2.7ms
|
||||
}
|
||||
}
|
||||
/*
|
||||
**********************************************************
|
||||
* 通用uart发数使用示例
|
||||
*********************************************************
|
||||
*/
|
||||
int audio_uart_transmit_demo_init()
|
||||
{
|
||||
printf("audio_uart_transmit_demo_init\n");
|
||||
/* uartSendInit(); //串口初始化,已经在开机时调用初始化,这里不需调用 */
|
||||
os_task_create(audio_uart_transmit_demo_task, NULL, 1, 1024, 128, "audio_uart_transmit_task");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 audio_export_demo_idle_query()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_LP_TARGET(audio_export_demo_lp_target) = {
|
||||
.name = "audio_export__demo",
|
||||
.is_idle = audio_export_demo_idle_query,
|
||||
};
|
||||
|
||||
#endif /*AUDIO_PCM_DEBUG*/
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
******************************************************************
|
||||
* Limiter_NoiseGate Module(限幅器/噪声门限模块)
|
||||
*1. Limiter:限制最大幅度
|
||||
*2. NoiseGate:
|
||||
*(1)启动时间
|
||||
*(2)释放时间
|
||||
*(3)噪声阈值
|
||||
*(4)噪声增益
|
||||
*3. Usage:
|
||||
*(1)LIMITER_THR:限幅器参数,限制信号的最大值
|
||||
*(2)LIMITER_NOISE_GATE:噪声门限的阈值,配合LIMITER_NOISE_GAIN使用
|
||||
*(3)LIMITER_NOISE_GAIN:当信号小于噪声门限LIMITER_NOISE_GATE的时候
|
||||
*信号增益为LIMITER_NOISE_GAIN,范围是0到1,增益0为静音,增益1为直通
|
||||
*效果。噪声门限用来优化声音的底噪
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
#include "system/includes.h"
|
||||
#include "os/os_api.h"
|
||||
#include "limiter_noiseGate_api.h"
|
||||
#include "audio_noise_gate.h"
|
||||
|
||||
|
||||
//#define NG_LOG_ENABLE
|
||||
#ifdef NG_LOG_ENABLE
|
||||
#define NG_LOG y_printf
|
||||
#else
|
||||
#define NG_LOG(...)
|
||||
#endif/*NG_LOG_ENABLE*/
|
||||
|
||||
/*限幅器上限*/
|
||||
#define LIMITER_THR -10000 /*-12000 = -12dB,放大1000倍,(-10000参考)*/
|
||||
/*小于CONST_NOISE_GATE的当成噪声处理,防止清0近端声音*/
|
||||
#define LIMITER_NOISE_GATE -40000 /*-12000 = -12dB,放大1000倍,(-40000参考)*/
|
||||
/*低于噪声门限阈值的增益 */
|
||||
#define LIMITER_NOISE_GAIN (0 << 30) /*(0~1)*2^30*/
|
||||
|
||||
enum {
|
||||
NG_STA_CLOSE = 0,
|
||||
NG_STA_OPEN,
|
||||
NG_STA_RUN,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u8 state;
|
||||
OS_MUTEX mutex;
|
||||
u8 *run_buf;
|
||||
} audio_noise_gate_t;
|
||||
audio_noise_gate_t NoiseGate;
|
||||
|
||||
int audio_noise_gate_open(u16 sample_rate, int limiter_thr, int noise_gate, int noise_gain)
|
||||
{
|
||||
NG_LOG("audio_noise_gate_open");
|
||||
NoiseGate.run_buf = malloc(need_limiter_noiseGate_buf(1));
|
||||
NG_LOG("Limiter_noisegate_buf size:%d\n", need_limiter_noiseGate_buf(1));
|
||||
if (NoiseGate.run_buf) {
|
||||
//限幅器启动因子 int32(exp(-0.65/(16000 * 0.005))*2^30) 16000为采样率 0.005 为启动时间(s)
|
||||
int limiter_attfactor = 1065053018;
|
||||
//限幅器释放因子 int32(exp(-0.15/(16000 * 0.1))*2^30) 16000为采样率 0.1 为释放时间(s)
|
||||
int limiter_relfactor = 1073641165;
|
||||
//限幅器阈值(mdb)
|
||||
//int limiter_threshold = CONST_LIMITER_THR;
|
||||
|
||||
//噪声门限启动因子 int32(exp(-1/(16000 * 0.1))*2^30) 16000为采样率 0.1 为启动时间(s)
|
||||
/*
|
||||
*import math
|
||||
*int(math.exp(-1.0/(16000*0.1))*2**30)
|
||||
*/
|
||||
int noiseGate_attfactor = 1073070945;
|
||||
//噪声门限释放因子 int32(exp(-1/(16000 * 0.005))*2^30) 16000为采样率 0.005 为释放时间(s)
|
||||
int noiseGate_relfactor = 1060403589;
|
||||
//噪声门限(mdb)
|
||||
//int noiseGate_threshold = -25000;
|
||||
//低于噪声门限阈值的增益 (0~1)*2^30
|
||||
//int noise
|
||||
//Gate_low_thr_gain = 0 << 30;
|
||||
|
||||
if (sample_rate == 8000) {
|
||||
limiter_attfactor = 1056434522;
|
||||
limiter_relfactor = 1073540516;
|
||||
noiseGate_attfactor = 1072400485;
|
||||
noiseGate_relfactor = 1047231044;
|
||||
}
|
||||
|
||||
limiter_noiseGate_init(NoiseGate.run_buf,
|
||||
limiter_attfactor,
|
||||
limiter_relfactor,
|
||||
noiseGate_attfactor,
|
||||
noiseGate_relfactor,
|
||||
limiter_thr,
|
||||
noise_gate,
|
||||
noise_gain,
|
||||
sample_rate, 1);
|
||||
os_mutex_create(&NoiseGate.mutex);
|
||||
NoiseGate.state = NG_STA_OPEN;
|
||||
NG_LOG("audio_noise_gate_open succ");
|
||||
return 0;
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void audio_noise_gate_run(void *in, void *out, u16 len)
|
||||
{
|
||||
if (NoiseGate.state == NG_STA_CLOSE) {
|
||||
return;
|
||||
}
|
||||
os_mutex_pend(&NoiseGate.mutex, 0);
|
||||
if (NoiseGate.run_buf) {
|
||||
limiter_noiseGate_run(NoiseGate.run_buf, in, out, len / 2);
|
||||
}
|
||||
os_mutex_post(&NoiseGate.mutex);
|
||||
}
|
||||
|
||||
void audio_noise_gate_close()
|
||||
{
|
||||
NG_LOG("audio_noise_gate_close");
|
||||
os_mutex_pend(&NoiseGate.mutex, 0);
|
||||
NoiseGate.state = NG_STA_CLOSE;
|
||||
if (NoiseGate.run_buf) {
|
||||
free(NoiseGate.run_buf);
|
||||
}
|
||||
os_mutex_post(&NoiseGate.mutex);
|
||||
NG_LOG("audio_noise_gate_close succ");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef _AUDIO_LIMITER_NOISE_GATE_H_
|
||||
#define _AUDIO_LIMITER_NOISE_GATE_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
|
||||
int audio_noise_gate_open(u16 sample_rate, int limiter_thr, int noise_gate, int noise_gain);
|
||||
void audio_noise_gate_run(void *in, void *out, u16 len);
|
||||
void audio_noise_gate_close();
|
||||
|
||||
#endif/*_AUDIO_NOISE_GATE_H_*/
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
******************************************************************
|
||||
* Noise Suppress Module(降噪模块)
|
||||
*Notes:
|
||||
*(1)支持降噪的数据采样率:8k/16k
|
||||
*(2)增加多5k左右代码
|
||||
*(3)内存消耗跟数据采样率有关,具体可通过以下接口查询:
|
||||
* int ns_mem_size = noise_suppress_mem_query(&ans->ns_para);
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
#include "audio_ns.h"
|
||||
|
||||
#ifdef CONFIG_MEDIA_NEW_ENABLE
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* NoiseSuppress Process
|
||||
* Description: 降噪处理主函数
|
||||
* Arguments : ns 降噪句柄
|
||||
* in 输入数据
|
||||
* out 输出数据
|
||||
* len 输入数据长度
|
||||
* Return : 降噪输出长度
|
||||
* Note(s) : 由于降噪是固定处理帧长的,所以如果输入数据长度不是降噪
|
||||
* 帧长整数倍,则某一次会输出0长度,即没有输出
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_ns_run(audio_ns_t *ns, short *in, short *out, u16 len)
|
||||
{
|
||||
if (ns == NULL) {
|
||||
return len;
|
||||
}
|
||||
#if 0
|
||||
int wlen = cbuf_write(&ns->cbuf, in, len);
|
||||
if (wlen != len) {
|
||||
printf("ns_cbuf full\n");
|
||||
}
|
||||
if (ns->cbuf.data_len >= NS_FRAME_SIZE) {
|
||||
cbuf_read(&ns->cbuf, out, NS_FRAME_SIZE);
|
||||
putchar('.');
|
||||
noise_suppress_run(out, out, NS_FRAME_POINTS);
|
||||
return NS_FRAME_SIZE;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
//putchar('.');
|
||||
int nOut = noise_suppress_run(in, out, (len / 2));
|
||||
return (nOut << 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Noise Suppress Open
|
||||
* Description: 初始化降噪模块
|
||||
* Arguments : sr 数据采样率
|
||||
* mode 降噪模式(0,1,2:越大越耗资源,效果越好)
|
||||
* NoiseLevel 初始噪声水平(评估初始噪声,加快收敛)
|
||||
* AggressFactor 降噪强度(越大越强:1~2)
|
||||
* MinSuppress 降噪最小压制(越小越强:0~1)
|
||||
* Return : 降噪模块句柄
|
||||
* Note(s) : (1)采样率只支持8k、16k
|
||||
* (2)如果内存不足,可以考虑wideband强制为0,即只做窄带降噪
|
||||
* ans-ns_para.wideband = 0;
|
||||
*********************************************************************
|
||||
*/
|
||||
audio_ns_t *audio_ns_open(u16 sr, u8 mode, float NoiseLevel, float AggressFactor, float MinSuppress)
|
||||
{
|
||||
audio_ns_t *ans = zalloc(sizeof(audio_ns_t));
|
||||
//cbuf_init(&ans->cbuf, ans->in, sizeof(ans->in));
|
||||
|
||||
ans->ns_para.wideband = (sr == 16000) ? 1 : 0;
|
||||
ans->ns_para.mode = mode;
|
||||
ans->ns_para.NoiseLevel = NoiseLevel;
|
||||
ans->ns_para.AggressFactor = AggressFactor;
|
||||
ans->ns_para.MinSuppress = MinSuppress;
|
||||
printf("ns wideband:%d\n", ans->ns_para.wideband);
|
||||
//int ns_mem_size = noise_suppress_mem_query(&ans->ns_para);
|
||||
//printf("ns mem_size:%d\n", ns_mem_size);
|
||||
noise_suppress_open(&ans->ns_para);
|
||||
float lowcut = -60.f;
|
||||
noise_suppress_config(NS_CMD_LOWCUTTHR, 0, &lowcut);
|
||||
float noise_floor = -60.f;
|
||||
noise_suppress_config(NS_CMD_NOISE_FLOOR, 0, &noise_floor);
|
||||
printf("audio_ns_open ok\n");
|
||||
return ans;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Noise Suppress Close
|
||||
* Description: 关闭降噪模块
|
||||
* Arguments : ns 降噪模块句柄
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_ns_close(audio_ns_t *ns)
|
||||
{
|
||||
noise_suppress_close();
|
||||
if (ns) {
|
||||
free(ns);
|
||||
ns = NULL;
|
||||
}
|
||||
printf("esco_ans_close ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /*CONFIG_MEDIA_NEW_ENABLE*/
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#ifndef _AUDIO_NOISE_SUPPRESS_H_
|
||||
#define _AUDIO_NOISE_SUPPRESS_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "generic/circular_buf.h"
|
||||
#include "commproc_ns.h"
|
||||
|
||||
/*降噪数据帧长(单位:点数)*/
|
||||
#define NS_FRAME_POINTS 160
|
||||
#define NS_FRAME_SIZE (NS_FRAME_POINTS << 1)
|
||||
/*降噪输出buf长度*/
|
||||
#define NS_OUT_POINTS_MAX (NS_FRAME_POINTS << 1)
|
||||
|
||||
typedef struct {
|
||||
//s16 in[512];
|
||||
//cbuffer_t cbuf;
|
||||
noise_suppress_param ns_para;
|
||||
} audio_ns_t;
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Noise Suppress Open
|
||||
* Description: 初始化降噪模块
|
||||
* Arguments : sr 数据采样率
|
||||
* mode 降噪模式(0,1,2:越大越耗资源,效果越好)
|
||||
* NoiseLevel 初始噪声水平(评估初始噪声,加快收敛)
|
||||
* AggressFactor 降噪强度(越大越强:1~2)
|
||||
* MinSuppress 降噪最小压制(越小越强:0~1)
|
||||
* Return : 降噪模块句柄
|
||||
* Note(s) : 采样率只支持8k、16k
|
||||
*********************************************************************
|
||||
*/
|
||||
audio_ns_t *audio_ns_open(u16 sr, u8 mode, float NoiseLevel, float AggressFactor, float MinSuppress);
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* NoiseSuppress Process
|
||||
* Description: 降噪处理主函数
|
||||
* Arguments : ns 降噪句柄
|
||||
* in 输入数据
|
||||
* out 输出数据
|
||||
* len 输入数据长度
|
||||
* Return : 降噪输出长度
|
||||
* Note(s) : 由于降噪是固定处理帧长的,所以如果输入数据长度不是降噪
|
||||
* 帧长整数倍,则某一次会输出0长度,即没有输出
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_ns_run(audio_ns_t *ns, short *in, short *out, u16 len);
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Noise Suppress Close
|
||||
* Description: 关闭降噪模块
|
||||
* Arguments : ns 降噪模块句柄
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_ns_close(audio_ns_t *ns);
|
||||
|
||||
#endif/*_AUDIO_NOISE_SUPPRESS_H_*/
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
************************************************************
|
||||
*/
|
||||
#include "system/includes.h"
|
||||
#include "PLC.h"
|
||||
#include "os/os_api.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
|
||||
#if TCFG_ESCO_PLC
|
||||
|
||||
//#define AUDIO_PLC_LOG_ENABLE
|
||||
#ifdef AUDIO_PLC_LOG_ENABLE
|
||||
#define PLC_LOG y_printf
|
||||
#else
|
||||
#define PLC_LOG(...)
|
||||
#endif/*AUDIO_PLC_LOG_ENABLE*/
|
||||
|
||||
enum {
|
||||
PLC_STA_CLOSE = 0,
|
||||
PLC_STA_OPEN,
|
||||
PLC_STA_RUN,
|
||||
};
|
||||
|
||||
|
||||
#define PLC_FRAME_LEN 120
|
||||
typedef struct {
|
||||
u8 state;
|
||||
u8 repair;
|
||||
u8 wideband;
|
||||
OS_MUTEX mutex;
|
||||
s16 *run_buf;
|
||||
} audio_plc_t;
|
||||
static audio_plc_t plc;
|
||||
|
||||
int audio_plc_open(u16 sr)
|
||||
{
|
||||
PLC_LOG("audio_plc_open:%d\n", sr);
|
||||
memset((u8 *)&plc, 0, sizeof(audio_plc_t));
|
||||
plc.run_buf = malloc(PLC_query()); /*buf_size:1040*/
|
||||
PLC_LOG("PLC_buf:%x,size:%d\n", plc.run_buf, PLC_query());
|
||||
if (plc.run_buf) {
|
||||
s8 err = PLC_init(plc.run_buf);
|
||||
if (err) {
|
||||
PLC_LOG("PLC_init err:%d", err);
|
||||
free(plc.run_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
os_mutex_create(&plc.mutex);
|
||||
if (sr == 16000) {
|
||||
plc.wideband = 1;
|
||||
}
|
||||
plc.state = PLC_STA_OPEN;
|
||||
}
|
||||
PLC_LOG("audio_plc_open succ\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_plc_run(s16 *data, u16 len, u8 repair)
|
||||
{
|
||||
u16 repair_point, tmp_point;
|
||||
s16 *p_in, *p_out;
|
||||
p_in = data;
|
||||
p_out = data;
|
||||
tmp_point = len / 2;
|
||||
u8 repair_flag = 0;
|
||||
|
||||
os_mutex_pend(&plc.mutex, 0);
|
||||
if (plc.state == PLC_STA_CLOSE) {
|
||||
os_mutex_post(&plc.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0 //debug
|
||||
static u16 repair_cnt = 0;
|
||||
if (repair) {
|
||||
repair_cnt++;
|
||||
y_printf("[E%d]", repair_cnt);
|
||||
} else {
|
||||
repair_cnt = 0;
|
||||
}
|
||||
//printf("[%d]",point);
|
||||
#endif/*debug*/
|
||||
|
||||
repair_flag = repair;
|
||||
if (plc.wideband) {
|
||||
/*
|
||||
*msbc plc deal
|
||||
*如果上一帧是错误,则当前帧也要修复
|
||||
*/
|
||||
if (plc.repair) {
|
||||
repair_flag = 1;
|
||||
}
|
||||
plc.repair = repair;
|
||||
}
|
||||
|
||||
while (tmp_point) {
|
||||
repair_point = (tmp_point > PLC_FRAME_LEN) ? PLC_FRAME_LEN : tmp_point;
|
||||
tmp_point = tmp_point - repair_point;
|
||||
PLC_run(p_in, p_out, repair_point, repair_flag);
|
||||
p_in += repair_point;
|
||||
p_out += repair_point;
|
||||
}
|
||||
os_mutex_post(&plc.mutex);
|
||||
}
|
||||
|
||||
int audio_plc_close(void)
|
||||
{
|
||||
PLC_LOG("audio_plc_close\n");
|
||||
os_mutex_pend(&plc.mutex, 0);
|
||||
plc.state = PLC_STA_CLOSE;
|
||||
if (plc.run_buf) {
|
||||
free(plc.run_buf);
|
||||
plc.run_buf = NULL;
|
||||
}
|
||||
os_mutex_post(&plc.mutex);
|
||||
PLC_LOG("audio_plc_close succ\n");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int audio_plc_open(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_plc_run(s16 *dat, u16 len, u8 repair_flag)
|
||||
{
|
||||
}
|
||||
|
||||
int audio_plc_close()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif/*TCFG_ESCO_PLC*/
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _AUDIO_PLC_H_
|
||||
#define _AUDIO_PLC_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
int audio_plc_open(u16 sr);
|
||||
void audio_plc_run(s16 *dat, u16 len, u8 repair_flag);
|
||||
int audio_plc_close(void);
|
||||
|
||||
#endif/*_AUDIO_PLC_H_*/
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
************************************************************
|
||||
* Audio Utils
|
||||
*Brief:数字信号处理常用模块合集
|
||||
*Notes:
|
||||
************************************************************
|
||||
*/
|
||||
|
||||
#include "audio_utils.h"
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Phase Inverter
|
||||
* Description: 数字反相器,用来反转数字音频信号的相位
|
||||
* Arguments : dat 数据buf地址
|
||||
* len 数据长度(unit:byte)
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void digital_phase_inverter_s16(s16 *dat, int len)
|
||||
{
|
||||
int data_size = len / 2;
|
||||
for (int i = 0; i < data_size; i++) {
|
||||
dat[i] = (dat[i] == -32768) ? 32767 : -dat[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef _AUDIO_UTILS_H_
|
||||
#define _AUDIO_UTILS_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Phase Inverter
|
||||
* Description: 数字反相器,用来反转数字音频信号的相位
|
||||
* Arguments : dat 数据buf地址
|
||||
* len 数据长度(unit:byte)
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void digital_phase_inverter_s16(s16 *dat, int len);
|
||||
|
||||
#endif/*_AUDIO_UTILS_H_*/
|
||||
@@ -0,0 +1,707 @@
|
||||
#include "asm/includes.h"
|
||||
#include "media/includes.h"
|
||||
#include "system/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
/* #include "audio_dec.h" */
|
||||
#include "application/audio_dec_app.h"
|
||||
#include "tone_player.h"
|
||||
#include "sine_make.h"
|
||||
|
||||
#if TCFG_KEY_TONE_EN
|
||||
|
||||
// 按键提示音任务名
|
||||
#define AUDIO_KEY_TONE_TASK_NAME "key_tone"
|
||||
|
||||
// 按键提示音数字音量控制
|
||||
#if (SYS_DIGVOL_GROUP_EN && defined(CONFIG_MEDIA_DEVELOP_ENABLE))
|
||||
#define AUDIO_KEY_TONE_DIGVOL_EN 0
|
||||
#define AUDIO_KEY_TONE_DIGVOL_NAME "key_tone"
|
||||
#else
|
||||
#define AUDIO_KEY_TONE_DIGVOL_EN 0
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* 使用audio_dec_app.h里面的接口,可以实现普通文件、正弦波文件、正弦波数组播放
|
||||
*/
|
||||
|
||||
// 参数
|
||||
struct __key_tone_play_info {
|
||||
const char *file_name; // 文件名
|
||||
struct audio_sin_param *sin; // 正弦波数组
|
||||
u8 sin_num; // 正弦波数组长度
|
||||
u8 preemption; // 1-抢占,0-叠加
|
||||
void (*evt_handler)(void *priv, int flag); // 事件回调
|
||||
void *evt_priv; // 事件回调私有句柄
|
||||
};
|
||||
|
||||
// 按键提示音
|
||||
struct __key_tone {
|
||||
volatile u8 busy; // 任务工作中
|
||||
volatile u8 start; // 运行标志
|
||||
volatile u8 play;
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
u8 volume; // 音量
|
||||
#endif
|
||||
struct __key_tone_play_info play_info; // 输入参数
|
||||
struct audio_dec_sine_app_hdl *dec_sin; // 文件播放句柄
|
||||
struct audio_dec_file_app_hdl *dec_file; // sine播放句柄
|
||||
void (*evt_handler)(void *priv, int flag); // 事件回调
|
||||
void *evt_priv; // 事件回调私有句柄
|
||||
const char *evt_owner; // 事件回调所在任务
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern struct audio_mixer mixer;
|
||||
|
||||
static struct __key_tone *key_tone = NULL;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Get File Ext Name
|
||||
* Description: 获取文件名后缀
|
||||
* Arguments : *name 文件名
|
||||
* Return : 后缀
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static char *get_file_ext_name(char *name)
|
||||
{
|
||||
int len = strlen(name);
|
||||
char *ext = (char *)name;
|
||||
|
||||
while (len--) {
|
||||
if (*ext++ == '.') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (len <= 0) {
|
||||
ext = name + (strlen(name) - 3);
|
||||
}
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Post Event
|
||||
* Description: 解码事件
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* end_flag 结束标志
|
||||
* Return : true 成功
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_dec_event_handler(struct __key_tone *ktone, u8 end_flag)
|
||||
{
|
||||
int argv[4];
|
||||
if (!ktone->evt_handler) {
|
||||
log_i("evt_handler null\n");
|
||||
return false;
|
||||
}
|
||||
argv[0] = (int)ktone->evt_handler;
|
||||
argv[1] = 2;
|
||||
argv[2] = (int)ktone->evt_priv;
|
||||
argv[3] = (int)end_flag; //0正常关闭,1被打断关闭
|
||||
|
||||
int ret = os_taskq_post_type(ktone->evt_owner, Q_CALLBACK, 4, argv);
|
||||
if (ret) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Reelease
|
||||
* Description: 提示音解码器释放
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void key_tone_dec_hdl_release(struct __key_tone *ktone)
|
||||
{
|
||||
if (ktone->dec_file) {
|
||||
audio_dec_file_app_close(ktone->dec_file);
|
||||
ktone->dec_file = NULL;
|
||||
}
|
||||
if (ktone->dec_sin) {
|
||||
audio_dec_sine_app_close(ktone->dec_sin);
|
||||
ktone->dec_sin = NULL;
|
||||
}
|
||||
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
|
||||
app_audio_state_exit(APP_AUDIO_STATE_WTONE);
|
||||
#endif
|
||||
/* clock_remove_set(DEC_TONE_CLK); */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Init OK
|
||||
* Description: 解码初始化完成
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void key_tone_dec_hdl_init_ok(struct __key_tone *ktone)
|
||||
{
|
||||
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
|
||||
if (audio_mixer_get_ch_num(&mixer) <= 1) {
|
||||
#ifdef TCFG_WTONT_ONCE_VOL
|
||||
extern u8 get_tone_once_vol(void);
|
||||
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_once_vol());
|
||||
#else
|
||||
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/* clock_add_set(DEC_TONE_CLK); */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Close
|
||||
* Description: 关闭提示音解码
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void key_tone_play_close(struct __key_tone *ktone)
|
||||
{
|
||||
/* log_i("ktone:0x%x, sin:0x%x, file:0x%x \n", ktone, ktone->dec_file, ktone->dec_file); */
|
||||
if (ktone->dec_file || ktone->dec_sin) {
|
||||
key_tone_dec_hdl_release(ktone);
|
||||
key_tone_dec_event_handler(ktone, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Event Callback
|
||||
* Description: 解码回调处理
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* event 事件
|
||||
* *param 事件参数
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_dec_app_evt_cb(struct __key_tone *ktone, enum audio_dec_app_event event, int *param)
|
||||
{
|
||||
switch (event) {
|
||||
case AUDIO_DEC_APP_EVENT_START_INIT_OK:
|
||||
log_i("key_tone start init ok\n");
|
||||
key_tone_dec_hdl_init_ok(ktone);
|
||||
break;
|
||||
case AUDIO_DEC_APP_EVENT_PLAY_END:
|
||||
log_i("key_tone play end\n");
|
||||
key_tone_dec_hdl_release(ktone);
|
||||
key_tone_dec_event_handler(ktone, 0);
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
|
||||
case AUDIO_DEC_APP_EVENT_STREAM_OPEN: {
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param;
|
||||
void *dvol_entry = NULL;
|
||||
audio_dig_vol_param temp_digvol_param = {
|
||||
.vol_start = ktone->volume,//get_max_sys_vol(),
|
||||
.vol_max = get_max_sys_vol(),
|
||||
.ch_total = audio_output_channel_num(),
|
||||
.fade_en = 0,
|
||||
.fade_points_step = 5,
|
||||
.fade_gain_step = 10,
|
||||
.vol_list = NULL,
|
||||
};
|
||||
dvol_entry = sys_digvol_group_ch_open(AUDIO_KEY_TONE_DIGVOL_NAME, -1, &temp_digvol_param);
|
||||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry;
|
||||
#endif // SYS_DIGVOL_GROUP_EN
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_DEC_APP_EVENT_STREAM_CLOSE: {
|
||||
}
|
||||
break;
|
||||
|
||||
#endif /*#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)*/
|
||||
|
||||
case AUDIO_DEC_APP_EVENT_DEC_CLOSE:
|
||||
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
sys_digvol_group_ch_close(AUDIO_KEY_TONE_DIGVOL_NAME);
|
||||
#endif // SYS_DIGVOL_GROUP_EN
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Sin Event Callback
|
||||
* Description: sine提示音解码回调
|
||||
* Arguments : *priv 私有句柄
|
||||
* event 事件
|
||||
* *param 事件参数
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_dec_sine_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
|
||||
{
|
||||
struct audio_dec_sine_app_hdl *sine_dec = priv;
|
||||
struct __key_tone *ktone = sine_dec->priv;
|
||||
switch (event) {
|
||||
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
|
||||
if (sine_dec->sin_maker) {
|
||||
break;
|
||||
}
|
||||
audio_dec_sine_app_probe(sine_dec);
|
||||
if (!sine_dec->sin_maker) {
|
||||
return -ENOENT;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
return key_tone_dec_app_evt_cb(ktone, event, param);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone File Event Callback
|
||||
* Description: file提示音解码回调
|
||||
* Arguments : *priv 私有句柄
|
||||
* event 事件
|
||||
* *param 事件参数
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_dec_file_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
|
||||
{
|
||||
struct audio_dec_file_app_hdl *file_dec = priv;
|
||||
struct __key_tone *ktone = file_dec->priv;
|
||||
switch (event) {
|
||||
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
|
||||
break;
|
||||
default :
|
||||
return key_tone_dec_app_evt_cb(ktone, event, param);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Run
|
||||
* Description: 按键提示音运行
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_play_run(struct __key_tone *ktone)
|
||||
{
|
||||
if (!ktone->start) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct __key_tone_play_info info = {0};
|
||||
local_irq_disable();
|
||||
if (!ktone->play) {
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
// 保存播放参数
|
||||
memcpy(&info, &ktone->play_info, sizeof(struct __key_tone_play_info));
|
||||
ktone->play = 0;
|
||||
local_irq_enable();
|
||||
|
||||
// 关闭现有play
|
||||
key_tone_play_close(ktone);
|
||||
|
||||
// 设置参数
|
||||
ktone->evt_handler = info.evt_handler;
|
||||
ktone->evt_priv = info.evt_priv;
|
||||
ktone->evt_owner = "app_core";
|
||||
|
||||
// 正弦波数组播放
|
||||
if (info.sin && info.sin_num) {
|
||||
ktone->dec_sin = audio_dec_sine_app_create_by_parm(info.sin, info.sin_num, !info.preemption);
|
||||
if (ktone->dec_sin == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb;
|
||||
ktone->dec_sin->priv = ktone;
|
||||
/* audio_dec_sine_app_open(ktone->dec_sin); */
|
||||
ktone->dec_sin->dec->wait.only_del = 1;
|
||||
audio_dec_app_start(ktone->dec_sin->dec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 判断文件名后缀
|
||||
u8 file_name[16];
|
||||
char *format = NULL;
|
||||
FILE *file = fopen(info.file_name, "r");
|
||||
if (!file) {
|
||||
return -1;
|
||||
}
|
||||
fget_name(file, file_name, 16);
|
||||
format = get_file_ext_name((char *)file_name);
|
||||
fclose(file);
|
||||
|
||||
// 正弦波文件播放
|
||||
if (ASCII_StrCmpNoCase(format, "sin", 3) == 0) {
|
||||
ktone->dec_sin = audio_dec_sine_app_create(info.file_name, !info.preemption);
|
||||
if (ktone->dec_sin == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb;
|
||||
ktone->dec_sin->priv = ktone;
|
||||
/* audio_dec_sine_app_open(ktone->dec_sin); */
|
||||
ktone->dec_sin->dec->wait.only_del = 1;
|
||||
audio_dec_app_start(ktone->dec_sin->dec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 普通文件播放
|
||||
ktone->dec_file = audio_dec_file_app_create(info.file_name, !info.preemption);
|
||||
if (ktone->dec_file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (ktone->dec_file->dec->dec_type == AUDIO_CODING_SBC) {
|
||||
audio_dec_app_set_frame_info(ktone->dec_file->dec, 0x4e, ktone->dec_file->dec->dec_type);
|
||||
}
|
||||
ktone->dec_file->dec->evt_cb = key_tone_dec_file_app_evt_cb;
|
||||
ktone->dec_file->priv = ktone;
|
||||
/* audio_dec_file_app_open(ktone->dec_file); */
|
||||
ktone->dec_file->dec->wait.only_del = 1;
|
||||
audio_dec_app_start(ktone->dec_file->dec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Task Run
|
||||
* Description: 按键提示音任务处理
|
||||
* Arguments : *p 按键提示音解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void key_tone_task_deal(void *p)
|
||||
{
|
||||
int res = 0;
|
||||
int msg[16];
|
||||
struct __key_tone *ktone = (struct __key_tone *)p;
|
||||
ktone->start = 1;
|
||||
ktone->busy = 1;
|
||||
while (1) {
|
||||
os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
|
||||
res = key_tone_play_run(ktone);
|
||||
if (res) {
|
||||
///等待删除线程
|
||||
key_tone_play_close(ktone);
|
||||
ktone->busy = 0;
|
||||
while (1) {
|
||||
os_time_dly(10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Destroy
|
||||
* Description: 注销按键提示音播放
|
||||
* Arguments : None.
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_key_tone_destroy(void)
|
||||
{
|
||||
if (!key_tone) {
|
||||
return ;
|
||||
}
|
||||
|
||||
key_tone->start = 0;
|
||||
|
||||
while (key_tone->busy) {
|
||||
os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0);
|
||||
os_time_dly(1);
|
||||
}
|
||||
|
||||
task_kill(AUDIO_KEY_TONE_TASK_NAME);
|
||||
|
||||
local_irq_disable();
|
||||
free(key_tone);
|
||||
key_tone = NULL;
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Init
|
||||
* Description: 按键提示音初始化
|
||||
* Arguments : None.
|
||||
* Return : true 成功
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
if (key_tone) {
|
||||
return true;
|
||||
}
|
||||
struct __key_tone *ktone = zalloc(sizeof(struct __key_tone));
|
||||
err = task_create(key_tone_task_deal, (void *)ktone, AUDIO_KEY_TONE_TASK_NAME);
|
||||
if (err != OS_NO_ERR) {
|
||||
log_e("%s creat fail %x\n", __FUNCTION__, err);
|
||||
free(ktone);
|
||||
return false;
|
||||
}
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
ktone->volume = get_max_sys_vol();
|
||||
#endif
|
||||
key_tone = ktone;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 正弦波序号
|
||||
#define KTONE_SINE_NORAML 0
|
||||
|
||||
// 按键提示音序号
|
||||
enum {
|
||||
KTONE_IDEX_NORAML = 0,
|
||||
KTONE_IDEX_NUM_0,
|
||||
KTONE_IDEX_NUM_1,
|
||||
|
||||
KTONE_IDEX_MAX,
|
||||
};
|
||||
|
||||
// 序号对应表
|
||||
static const char *const key_tone_index[] = {
|
||||
[KTONE_IDEX_NORAML] = DEFAULT_SINE_TONE(KTONE_SINE_NORAML),
|
||||
[KTONE_IDEX_NUM_0] = SDFILE_RES_ROOT_PATH"tone/0.*",
|
||||
[KTONE_IDEX_NUM_1] = SDFILE_RES_ROOT_PATH"tone/1.*",
|
||||
};
|
||||
|
||||
/*
|
||||
* 正弦波参数配置:
|
||||
* freq : 实际频率 * 512
|
||||
* points : 正弦波点数
|
||||
* win : 正弦窗
|
||||
* decay : 衰减系数(百分比), 正弦窗模式下为频率设置:频率*512
|
||||
*/
|
||||
static const struct sin_param sine_16k_normal[] = {
|
||||
/*{0, 1000, 0, 100},*/
|
||||
{200 << 9, 4000, 0, 100},
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Get Sine Param Data
|
||||
* Description: 获取正弦波数组
|
||||
* Arguments : id 正弦波序号
|
||||
* *num 正弦波数组长度
|
||||
* Return : 正弦波数组
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static const struct sin_param *get_sine_param_data(u8 id, u8 *num)
|
||||
{
|
||||
const struct sin_param *param_data = NULL;
|
||||
switch (id) {
|
||||
case KTONE_SINE_NORAML:
|
||||
param_data = sine_16k_normal;
|
||||
*num = ARRAY_SIZE(sine_16k_normal);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return param_data;
|
||||
};
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Open With Callback
|
||||
* Description: 打开文件播放
|
||||
* Arguments : *file_name 文件名
|
||||
* *sin 正弦波数组
|
||||
* sin_num 正弦波数组长度
|
||||
* preemption 1-抢断播放;0-叠加播放
|
||||
* evt_handler 事件回调
|
||||
* evt_priv 事件回调参数
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int ktone_play_open_with_callback_base(const char *file_name, struct audio_sin_param *sin, u8 sin_num, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv)
|
||||
{
|
||||
struct __key_tone *ktone = key_tone;
|
||||
if ((!ktone) || (!ktone->start)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct __key_tone_play_info info = {0};
|
||||
info.preemption = preemption;
|
||||
info.evt_handler = evt_handler;
|
||||
info.evt_priv = evt_priv;
|
||||
if (sin && sin_num) {
|
||||
info.sin = sin;
|
||||
info.sin_num = sin_num;
|
||||
} else {
|
||||
info.file_name = file_name;
|
||||
if (IS_DEFAULT_SINE(file_name)) {
|
||||
info.sin = get_sine_param_data(DEFAULT_SINE_ID(file_name), &info.sin_num);
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
memcpy(&ktone->play_info, &info, sizeof(struct __key_tone_play_info));
|
||||
ktone->play = 1;
|
||||
local_irq_enable();
|
||||
|
||||
os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Play Sine
|
||||
* Description: 播放正弦波数组
|
||||
* Arguments : *sin 正弦波数组
|
||||
* sin_num 正弦波数组长度
|
||||
* preemption 1-抢断播放;0-叠加播放
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_play_sin(struct audio_sin_param *sin, u8 sin_num, u8 preemption)
|
||||
{
|
||||
/* y_printf("n:0x%x \n", name); */
|
||||
return ktone_play_open_with_callback_base(NULL, sin, sin_num, preemption, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Play File
|
||||
* Description: 播放文件
|
||||
* Arguments : *name 文件名
|
||||
* preemption 1-抢断播放;0-叠加播放
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_play_name(const char *name, u8 preemption)
|
||||
{
|
||||
/* y_printf("n:0x%x \n", name); */
|
||||
return ktone_play_open_with_callback_base(name, NULL, 0, preemption, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Play Index
|
||||
* Description: 按序号播放文件
|
||||
* Arguments : index 序号
|
||||
* preemption 1-抢断播放;0-叠加播放
|
||||
* Return : 0 正常
|
||||
* Note(s) : 使用key_tone_index[]数组
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_play_index(u8 index, u8 preemption)
|
||||
{
|
||||
if (index >= KTONE_IDEX_MAX) {
|
||||
return -1;
|
||||
}
|
||||
return audio_key_tone_play_name(key_tone_index[index], preemption);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Play
|
||||
* Description: 按键提示音播放
|
||||
* Arguments : None.
|
||||
* Return : None.
|
||||
* Note(s) : 默认播放
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_key_tone_play(void)
|
||||
{
|
||||
audio_key_tone_play_index(KTONE_IDEX_NORAML, 0);
|
||||
/* audio_key_tone_play_index(KTONE_IDEX_NUM_0, 0); */
|
||||
/* audio_key_tone_play_sin(sine_16k_normal, ARRAY_SIZE(sine_16k_normal), 0); */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Check Play
|
||||
* Description: 检测按键提示音是否在播放
|
||||
* Arguments : None.
|
||||
* Return : true 正在播放
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_is_play(void)
|
||||
{
|
||||
if ((!key_tone) || (!key_tone->start)) {
|
||||
return false;
|
||||
}
|
||||
if (key_tone->dec_file || key_tone->dec_sin) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Set Digvol
|
||||
* Description: 设置按键提示音的音量
|
||||
* Arguments : volume 音量
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_key_tone_digvol_set(u8 volume)
|
||||
{
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
log_i("vol:%d \n", volume);
|
||||
if (!key_tone) {
|
||||
return ;
|
||||
}
|
||||
key_tone->volume = volume;
|
||||
void *vol_hdl = audio_dig_vol_group_hdl_get(sys_digvol_group, AUDIO_KEY_TONE_DIGVOL_NAME);
|
||||
if (vol_hdl == NULL) {
|
||||
return;
|
||||
}
|
||||
audio_dig_vol_set(vol_hdl, AUDIO_DIG_VOL_ALL_CH, volume);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
|
||||
#include "application/audio_dec_app.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
#include "app_main.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
extern struct audio_decoder_task decode_task;
|
||||
extern struct audio_mixer mixer;
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
#if AUDIO_DAC_MULTI_CHANNEL_ENABLE
|
||||
extern struct audio_dac_channel default_dac;
|
||||
#endif
|
||||
|
||||
extern const int audio_dec_app_mix_en;
|
||||
|
||||
extern u32 audio_output_channel_num(void);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
struct audio_dec_app_audio_state_hdl {
|
||||
struct audio_mixer *p_mixer;
|
||||
u32 dec_mix : 1; // 1:叠加模式
|
||||
u32 flag;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
const struct audio_dec_format_hdl decode_format_list[] = {
|
||||
{"wtg", AUDIO_CODING_G729},
|
||||
{"msbc", AUDIO_CODING_MSBC},
|
||||
{"msb", AUDIO_CODING_MSBC},
|
||||
{"sbc", AUDIO_CODING_SBC},
|
||||
{"mty", AUDIO_CODING_MTY},
|
||||
{"aac", AUDIO_CODING_AAC},
|
||||
{"mp3", AUDIO_CODING_MP3},
|
||||
{"wma", AUDIO_CODING_WMA},
|
||||
{"wav", AUDIO_CODING_WAV},
|
||||
#if (defined(TCFG_DEC_MIDI_ENABLE) && TCFG_DEC_MIDI_ENABLE)
|
||||
//midi 文件播放,需要对应音色文件配合
|
||||
{"midi", AUDIO_CODING_MIDI},
|
||||
{"mid", AUDIO_CODING_MIDI},
|
||||
#endif //TCFG_DEC_MIDI_ENABLE
|
||||
|
||||
#if TCFG_DEC_WTGV2_ENABLE
|
||||
{"wts", AUDIO_CODING_WTGV2},
|
||||
#endif
|
||||
{"speex", AUDIO_CODING_SPEEX},
|
||||
{"opus", AUDIO_CODING_OPUS},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
|
||||
static struct audio_stream_entry *audio_dec_app_entries[2] = {NULL};
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 解码创建参数初始化
|
||||
@param *dec: 解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_app_create_param_init(struct audio_dec_app_hdl *dec)
|
||||
{
|
||||
dec->p_decode_task = &decode_task;
|
||||
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
|
||||
if (!audio_dec_app_mix_en) {
|
||||
#if AUDIO_DAC_MULTI_CHANNEL_ENABLE
|
||||
audio_dec_app_entries[0] = &default_dac.entry;
|
||||
#else
|
||||
audio_dec_app_entries[0] = &dac_hdl.entry;
|
||||
#endif
|
||||
dec->entries = audio_dec_app_entries;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
dec->p_mixer = &mixer;
|
||||
}
|
||||
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
|
||||
u8 dac_connect_mode = app_audio_output_mode_get();
|
||||
if (dac_connect_mode == DAC_OUTPUT_FRONT_LR_REAR_LR) {
|
||||
dec->out_ch_num = 4;
|
||||
} else {
|
||||
dec->out_ch_num = audio_output_channel_num();
|
||||
}
|
||||
#else
|
||||
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
|
||||
switch (dac_connect_mode) {
|
||||
/* case DAC_OUTPUT_DUAL_LR_DIFF: */
|
||||
case DAC_OUTPUT_LR:
|
||||
dec->out_ch_num = 2;
|
||||
break;
|
||||
/* case DAC_OUTPUT_FRONT_LR_REAR_LR: */
|
||||
/* dec->out_ch_num = 4; */
|
||||
/* break; */
|
||||
default :
|
||||
dec->out_ch_num = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 文件解码创建参数初始化
|
||||
@param *file_dec: 文件解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_file_app_create_param_init(struct audio_dec_file_app_hdl *file_dec)
|
||||
{
|
||||
file_dec->format = (struct audio_dec_format_hdl *)decode_format_list;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 解码输出状态设置
|
||||
@param *dec: 解码句柄
|
||||
@param flag: 解码标签
|
||||
@return 0-正常
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_app_audio_state_switch(struct audio_dec_app_hdl *dec, u32 flag)
|
||||
{
|
||||
u8 need_set_audio = 1;
|
||||
/* if ((dec->dec_mix) && (audio_mixer_get_ch_num(dec->p_mixer) > 1)) { */
|
||||
/* need_set_audio = 0; */
|
||||
/* } */
|
||||
if (app_audio_get_state() == APP_AUDIO_STATE_IDLE) {
|
||||
need_set_audio = 1;
|
||||
}
|
||||
if (need_set_audio) {
|
||||
if (flag == AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC) {
|
||||
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
|
||||
} else {
|
||||
#ifdef TCFG_WTONT_ONCE_VOL
|
||||
extern u8 get_tone_once_vol(void);
|
||||
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_once_vol());
|
||||
#else
|
||||
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 解码输出状态退出
|
||||
@param *p_aud_state: 输出状态
|
||||
@return 0-正常
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_app_audio_state_exit(struct audio_dec_app_audio_state_hdl *p_aud_state)
|
||||
{
|
||||
u8 need_set_audio = 1;
|
||||
/* if ((p_aud_state->dec_mix) && (audio_mixer_get_ch_num(p_aud_state->p_mixer) > 1)) { */
|
||||
/* need_set_audio = 0; */
|
||||
/* } */
|
||||
/* if (app_audio_get_state() == APP_AUDIO_STATE_IDLE) { */
|
||||
/* need_set_audio = 1; */
|
||||
/* } */
|
||||
if (need_set_audio) {
|
||||
if (p_aud_state->flag == AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC) {
|
||||
app_audio_state_exit(APP_AUDIO_STATE_MUSIC);
|
||||
} else {
|
||||
app_audio_state_exit(APP_AUDIO_STATE_WTONE);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 文件解码初始化完成
|
||||
@param *file_dec: 文件解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_file_app_init_ok(struct audio_dec_file_app_hdl *file_dec)
|
||||
{
|
||||
audio_dec_app_audio_state_switch(file_dec->dec, file_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 文件解码结束
|
||||
@param *file_dec: 文件解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_file_app_play_end(struct audio_dec_file_app_hdl *file_dec)
|
||||
{
|
||||
struct audio_dec_app_audio_state_hdl aud_state = {0};
|
||||
aud_state.p_mixer = file_dec->dec->p_mixer;
|
||||
aud_state.dec_mix = file_dec->dec->dec_mix;
|
||||
aud_state.flag = file_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK;
|
||||
audio_dec_file_app_close(file_dec);
|
||||
audio_dec_app_audio_state_exit(&aud_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 正弦波解码初始化完成
|
||||
@param *sine_dec: 正弦波解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_sine_app_init_ok(struct audio_dec_sine_app_hdl *sine_dec)
|
||||
{
|
||||
audio_dec_app_audio_state_switch(sine_dec->dec, sine_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK);
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 正弦波解码结束
|
||||
@param *sine_dec: 正弦波解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_sine_app_play_end(struct audio_dec_sine_app_hdl *sine_dec)
|
||||
{
|
||||
struct audio_dec_app_audio_state_hdl aud_state = {0};
|
||||
aud_state.p_mixer = sine_dec->dec->p_mixer;
|
||||
aud_state.dec_mix = sine_dec->dec->dec_mix;
|
||||
aud_state.flag = sine_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK;
|
||||
audio_dec_sine_app_close(sine_dec);
|
||||
audio_dec_app_audio_state_exit(&aud_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
|
||||
void audio_dec_app_output_sr_set(struct audio_dec_app_hdl *dec)
|
||||
{
|
||||
/* #if defined(CONFIG_CPU_BR23) */
|
||||
/* extern u32 audio_output_rate(int input_rate); */
|
||||
/* dec->src_out_sr = audio_output_rate(dec->src_out_sr); */
|
||||
/* #endif */
|
||||
if (dec->src_out_sr == 0) {
|
||||
dec->src_out_sr = audio_dac_get_sample_rate(&dac_hdl);
|
||||
if (dec->src_out_sr == 0) {
|
||||
dec->src_out_sr = 16000;
|
||||
log_w("src out is zero \n");
|
||||
}
|
||||
}
|
||||
if (dec->sample_rate == 0) {
|
||||
dec->sample_rate = dec->src_out_sr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// test
|
||||
#if 0
|
||||
#include "tone_player.h"
|
||||
|
||||
void audio_dec_file_test(void)
|
||||
{
|
||||
struct audio_dec_file_app_hdl *hdl;
|
||||
hdl = audio_dec_file_app_create(TONE_POWER_ON, 1);
|
||||
if (hdl) {
|
||||
audio_dec_file_app_open(hdl);
|
||||
}
|
||||
os_time_dly(2);
|
||||
hdl = audio_dec_file_app_create(TONE_POWER_OFF, 1);
|
||||
if (hdl) {
|
||||
audio_dec_file_app_open(hdl);
|
||||
}
|
||||
os_time_dly(300);
|
||||
}
|
||||
|
||||
static const struct audio_sin_param sine_test[] = {
|
||||
/*{0, 1000, 0, 100},*/
|
||||
{200 << 9, 4000, 0, 100},
|
||||
};
|
||||
static const struct audio_sin_param sine_test1[] = {
|
||||
{450 << 9, 24960, 1, 16.667 * 512},
|
||||
{0, 16000, 0, 100},
|
||||
};
|
||||
void audio_dec_sine_test(void)
|
||||
{
|
||||
struct audio_dec_sine_app_hdl *hdl;
|
||||
/* hdl = audio_dec_sine_app_create(SDFILE_RES_ROOT_PATH"tone/vol_max.sin", 1); */
|
||||
hdl = audio_dec_sine_app_create_by_parm(sine_test1, ARRAY_SIZE(sine_test1), 1);
|
||||
if (hdl) {
|
||||
audio_dec_sine_app_open(hdl);
|
||||
}
|
||||
os_time_dly(2);
|
||||
hdl = audio_dec_sine_app_create_by_parm(sine_test, ARRAY_SIZE(sine_test), 1);
|
||||
if (hdl) {
|
||||
audio_dec_sine_app_open(hdl);
|
||||
}
|
||||
/* os_time_dly(300); */
|
||||
}
|
||||
|
||||
void audio_dec_usb_file_test(void)
|
||||
{
|
||||
tone_play_stop();
|
||||
clk_set("sys", 192 * 1000000L);
|
||||
|
||||
struct audio_dec_file_app_hdl *hdl;
|
||||
/* hdl = audio_dec_file_app_create("storage/udisk/C/1.mp3", 1); */
|
||||
hdl = audio_dec_file_app_create("storage/udisk/C/1.wav", 1);
|
||||
if (hdl) {
|
||||
audio_dec_file_app_open(hdl);
|
||||
}
|
||||
os_time_dly(2);
|
||||
/* hdl = audio_dec_file_app_create("storage/udisk/C/2.mp3", 1); */
|
||||
hdl = audio_dec_file_app_create("storage/udisk/C/2.wav", 1);
|
||||
if (hdl) {
|
||||
audio_dec_file_app_open(hdl);
|
||||
}
|
||||
os_time_dly(300);
|
||||
}
|
||||
|
||||
#endif /*test*/
|
||||
|
||||
|
||||
@@ -0,0 +1,410 @@
|
||||
/*****************************************************************
|
||||
>file name : apps/common/sine_make.c
|
||||
>author : lichao
|
||||
>create time : Sun 05 May 2019 08:37:35 PM CST
|
||||
*****************************************************************/
|
||||
#include "system/includes.h"
|
||||
#include "sine_make.h"
|
||||
|
||||
#define SINE_USE_MALLOC 1
|
||||
|
||||
struct audio_sin_maker {
|
||||
u8 open;
|
||||
u8 id;
|
||||
u8 sin_num;
|
||||
u8 channel;
|
||||
u8 repeat;
|
||||
u8 next_param;
|
||||
u16 fade_points;
|
||||
/*int sample_rate;*/
|
||||
int volume;
|
||||
int points;
|
||||
int sin_index;
|
||||
int win_sin_index;
|
||||
const struct sin_param *sin;
|
||||
};
|
||||
|
||||
#ifndef SINE_USE_MALLOC
|
||||
static struct audio_sin_maker sin_maker_handle;
|
||||
#endif
|
||||
|
||||
void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat)
|
||||
{
|
||||
if (!param || !num) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SINE_USE_MALLOC
|
||||
struct audio_sin_maker *sin = zalloc(sizeof(struct audio_sin_maker));
|
||||
#else
|
||||
struct audio_sin_maker *sin = &sin_maker_handle;
|
||||
#endif
|
||||
|
||||
if (!sin) {
|
||||
return NULL;
|
||||
}
|
||||
if (sin->open) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sin->sin = param;
|
||||
sin->sin_num = num;
|
||||
sin->open = 1;
|
||||
sin->points = param[0].points;
|
||||
sin->id = 0;
|
||||
sin->channel = channel;
|
||||
sin->repeat = repeat;
|
||||
#if (defined CONFIG_CPU_BR18 || \
|
||||
defined CONFIG_CPU_BR21)
|
||||
/*这里如果加多fade points,会导致结束的时候有噪声,不是在淡出尾部*/
|
||||
sin->fade_points = 0;
|
||||
#else
|
||||
sin->fade_points = 480;
|
||||
#endif
|
||||
sin->next_param = 1;
|
||||
|
||||
return (void *)sin;
|
||||
}
|
||||
#if !defined(SINE_MAKE_IN_MASK)
|
||||
const int sf_sin_tab1[513] = {
|
||||
0x00000000, 0x0000c910, 0x0001921f, 0x00025b2d, 0x0003243a, 0x0003ed45, 0x0004b64e, 0x00057f53,
|
||||
0x00064855, 0x00071154, 0x0007da4e, 0x0008a343, 0x00096c33, 0x000a351d, 0x000afe00, 0x000bc6dd,
|
||||
0x000c8fb3, 0x000d5881, 0x000e2147, 0x000eea03, 0x000fb2b7, 0x00107b61, 0x00114401, 0x00120c96,
|
||||
0x0012d521, 0x00139d9f, 0x00146611, 0x00152e77, 0x0015f6d0, 0x0016bf1b, 0x00178758, 0x00184f87,
|
||||
0x001917a7, 0x0019dfb7, 0x001aa7b7, 0x001b6fa7, 0x001c3786, 0x001cff53, 0x001dc70f, 0x001e8eb8,
|
||||
0x001f564e, 0x00201dd1, 0x0020e541, 0x0021ac9b, 0x002273e2, 0x00233b13, 0x0024022e, 0x0024c933,
|
||||
0x00259021, 0x002656f8, 0x00271db7, 0x0027e45f, 0x0028aaed, 0x00297163, 0x002a37bf, 0x002afe01,
|
||||
0x002bc429, 0x002c8a35, 0x002d5026, 0x002e15fb, 0x002edbb4, 0x002fa14f, 0x003066ce, 0x00312c2e,
|
||||
0x0031f170, 0x0032b694, 0x00337b98, 0x0034407c, 0x00350540, 0x0035c9e4, 0x00368e66, 0x003752c6,
|
||||
0x00381705, 0x0038db21, 0x00399f19, 0x003a62ef, 0x003b26a0, 0x003bea2c, 0x003cad94, 0x003d70d7,
|
||||
0x003e33f3, 0x003ef6e9, 0x003fb9b8, 0x00407c60, 0x00413ee0, 0x00420138, 0x0042c367, 0x0043856d,
|
||||
0x0044474a, 0x004508fc, 0x0045ca83, 0x00468be0, 0x00474d11, 0x00480e16, 0x0048ceef, 0x00498f9a,
|
||||
0x004a5019, 0x004b1069, 0x004bd08b, 0x004c907f, 0x004d5043, 0x004e0fd8, 0x004ecf3c, 0x004f8e70,
|
||||
0x00504d72, 0x00510c43, 0x0051cae3, 0x0052894f, 0x00534789, 0x0054058f, 0x0054c362, 0x00558100,
|
||||
0x00563e6a, 0x0056fb9e, 0x0057b89d, 0x00587565, 0x005931f7, 0x0059ee52, 0x005aaa76, 0x005b6662,
|
||||
0x005c2215, 0x005cdd8f, 0x005d98d0, 0x005e53d8, 0x005f0ea5, 0x005fc937, 0x0060838f, 0x00613dab,
|
||||
0x0061f78b, 0x0062b12e, 0x00636a95, 0x006423be, 0x0064dcaa, 0x00659557, 0x00664dc6, 0x006705f5,
|
||||
0x0067bde5, 0x00687595, 0x00692d05, 0x0069e433, 0x006a9b21, 0x006b51cc, 0x006c0836, 0x006cbe5c,
|
||||
0x006d7440, 0x006e29e0, 0x006edf3d, 0x006f9454, 0x00704927, 0x0070fdb5, 0x0071b1fd, 0x007265ff,
|
||||
0x007319ba, 0x0073cd2f, 0x0074805c, 0x00753341, 0x0075e5dd, 0x00769831, 0x00774a3c, 0x0077fbfe,
|
||||
0x0078ad75, 0x00795ea2, 0x007a0f84, 0x007ac01a, 0x007b7065, 0x007c2064, 0x007cd016, 0x007d7f7c,
|
||||
0x007e2e93, 0x007edd5d, 0x007f8bd9, 0x00803a06, 0x0080e7e4, 0x00819573, 0x008242b1, 0x0082ef9f,
|
||||
0x00839c3d, 0x00844889, 0x0084f484, 0x0085a02c, 0x00864b82, 0x0086f686, 0x0087a136, 0x00884b92,
|
||||
0x0088f59b, 0x00899f4e, 0x008a48ad, 0x008af1b7, 0x008b9a6b, 0x008c42c9, 0x008cead0, 0x008d9281,
|
||||
0x008e39da, 0x008ee0db, 0x008f8784, 0x00902dd5, 0x0090d3cd, 0x0091796b, 0x00921eb0, 0x0092c39a,
|
||||
0x0093682a, 0x00940c5f, 0x0094b039, 0x009553b7, 0x0095f6d9, 0x0096999f, 0x00973c07, 0x0097de12,
|
||||
0x00987fc0, 0x0099210f, 0x0099c200, 0x009a6293, 0x009b02c6, 0x009ba299, 0x009c420c, 0x009ce11f,
|
||||
0x009d7fd1, 0x009e1e22, 0x009ebc12, 0x009f599f, 0x009ff6cb, 0x00a09393, 0x00a12ff9, 0x00a1cbfb,
|
||||
0x00a26799, 0x00a302d3, 0x00a39da9, 0x00a4381a, 0x00a4d225, 0x00a56bcb, 0x00a6050a, 0x00a69de3,
|
||||
0x00a73656, 0x00a7ce61, 0x00a86605, 0x00a8fd41, 0x00a99415, 0x00aa2a80, 0x00aac082, 0x00ab561b,
|
||||
0x00abeb4a, 0x00ac800f, 0x00ad1469, 0x00ada859, 0x00ae3bde, 0x00aecef7, 0x00af61a5, 0x00aff3e6,
|
||||
0x00b085bb, 0x00b11722, 0x00b1a81d, 0x00b238aa, 0x00b2c8c9, 0x00b3587a, 0x00b3e7bc, 0x00b4768f,
|
||||
0x00b504f3, 0x00b592e7, 0x00b6206c, 0x00b6ad7f, 0x00b73a23, 0x00b7c655, 0x00b85216, 0x00b8dd65,
|
||||
0x00b96842, 0x00b9f2ac, 0x00ba7ca4, 0x00bb0629, 0x00bb8f3b, 0x00bc17d9, 0x00bca003, 0x00bd27b8,
|
||||
0x00bdaef9, 0x00be35c5, 0x00bebc1b, 0x00bf41fc, 0x00bfc767, 0x00c04c5c, 0x00c0d0da, 0x00c154e1,
|
||||
0x00c1d870, 0x00c25b89, 0x00c2de29, 0x00c36051, 0x00c3e200, 0x00c46337, 0x00c4e3f5, 0x00c56439,
|
||||
0x00c5e403, 0x00c66354, 0x00c6e22a, 0x00c76085, 0x00c7de65, 0x00c85bca, 0x00c8d8b3, 0x00c95521,
|
||||
0x00c9d112, 0x00ca4c87, 0x00cac77f, 0x00cb41fa, 0x00cbbbf8, 0x00cc3578, 0x00ccae79, 0x00cd26fd,
|
||||
0x00cd9f02, 0x00ce1689, 0x00ce8d90, 0x00cf0417, 0x00cf7a1f, 0x00cfefa8, 0x00d064af, 0x00d0d937,
|
||||
0x00d14d3d, 0x00d1c0c2, 0x00d233c6, 0x00d2a649, 0x00d31849, 0x00d389c7, 0x00d3fac3, 0x00d46b3b,
|
||||
0x00d4db31, 0x00d54aa4, 0x00d5b993, 0x00d627fe, 0x00d695e5, 0x00d70348, 0x00d77026, 0x00d7dc7f,
|
||||
0x00d84853, 0x00d8b3a1, 0x00d91e6a, 0x00d988ad, 0x00d9f26a, 0x00da5ba0, 0x00dac450, 0x00db2c79,
|
||||
0x00db941a, 0x00dbfb34, 0x00dc61c7, 0x00dcc7d1, 0x00dd2d53, 0x00dd924d, 0x00ddf6be, 0x00de5aa6,
|
||||
0x00debe05, 0x00df20db, 0x00df8327, 0x00dfe4e9, 0x00e04621, 0x00e0a6cf, 0x00e106f2, 0x00e1668a,
|
||||
0x00e1c598, 0x00e2241a, 0x00e28210, 0x00e2df7b, 0x00e33c5a, 0x00e398ac, 0x00e3f473, 0x00e44fac,
|
||||
0x00e4aa59, 0x00e50479, 0x00e55e0b, 0x00e5b710, 0x00e60f88, 0x00e66771, 0x00e6becc, 0x00e71599,
|
||||
0x00e76bd8, 0x00e7c187, 0x00e816a8, 0x00e86b39, 0x00e8bf3c, 0x00e912ae, 0x00e96591, 0x00e9b7e4,
|
||||
0x00ea09a7, 0x00ea5ad9, 0x00eaab7b, 0x00eafb8c, 0x00eb4b0c, 0x00eb99fb, 0x00ebe858, 0x00ec3624,
|
||||
0x00ec835e, 0x00ecd007, 0x00ed1c1d, 0x00ed67a1, 0x00edb293, 0x00edfcf2, 0x00ee46be, 0x00ee8ff8,
|
||||
0x00eed89e, 0x00ef20b0, 0x00ef6830, 0x00efaf1b, 0x00eff573, 0x00f03b37, 0x00f08066, 0x00f0c501,
|
||||
0x00f10908, 0x00f14c7a, 0x00f18f57, 0x00f1d19f, 0x00f21352, 0x00f25470, 0x00f294f8, 0x00f2d4eb,
|
||||
0x00f31447, 0x00f3530e, 0x00f3913f, 0x00f3ced9, 0x00f40bdd, 0x00f4484b, 0x00f48422, 0x00f4bf62,
|
||||
0x00f4fa0b, 0x00f5341d, 0x00f56d97, 0x00f5a67b, 0x00f5dec6, 0x00f6167a, 0x00f64d97, 0x00f6841b,
|
||||
0x00f6ba07, 0x00f6ef5b, 0x00f72417, 0x00f7583a, 0x00f78bc5, 0x00f7beb7, 0x00f7f110, 0x00f822d1,
|
||||
0x00f853f8, 0x00f88486, 0x00f8b47b, 0x00f8e3d6, 0x00f91298, 0x00f940c0, 0x00f96e4e, 0x00f99b43,
|
||||
0x00f9c79d, 0x00f9f35e, 0x00fa1e84, 0x00fa4910, 0x00fa7302, 0x00fa9c59, 0x00fac516, 0x00faed37,
|
||||
0x00fb14be, 0x00fb3bab, 0x00fb61fc, 0x00fb87b2, 0x00fbaccd, 0x00fbd14d, 0x00fbf531, 0x00fc187a,
|
||||
0x00fc3b28, 0x00fc5d3a, 0x00fc7eb0, 0x00fc9f8a, 0x00fcbfc9, 0x00fcdf6c, 0x00fcfe73, 0x00fd1cdd,
|
||||
0x00fd3aac, 0x00fd57de, 0x00fd7474, 0x00fd906e, 0x00fdabcc, 0x00fdc68c, 0x00fde0b1, 0x00fdfa38,
|
||||
0x00fe1324, 0x00fe2b72, 0x00fe4323, 0x00fe5a38, 0x00fe70b0, 0x00fe868b, 0x00fe9bc9, 0x00feb069,
|
||||
0x00fec46d, 0x00fed7d4, 0x00feea9d, 0x00fefcc9, 0x00ff0e58, 0x00ff1f49, 0x00ff2f9d, 0x00ff3f54,
|
||||
0x00ff4e6d, 0x00ff5ce9, 0x00ff6ac7, 0x00ff7808, 0x00ff84ab, 0x00ff90b1, 0x00ff9c18, 0x00ffa6e3,
|
||||
0x00ffb10f, 0x00ffba9e, 0x00ffc38f, 0x00ffcbe2, 0x00ffd397, 0x00ffdaaf, 0x00ffe129, 0x00ffe705,
|
||||
0x00ffec43, 0x00fff0e3, 0x00fff4e6, 0x00fff84a, 0x00fffb11, 0x00fffd39, 0x00fffec4, 0x00ffffb1,
|
||||
0x00ffffff,
|
||||
};
|
||||
#else
|
||||
extern const int sf_sin_tab1[513] ;
|
||||
#endif
|
||||
|
||||
|
||||
#define SINE_INT_ZOOM 16384
|
||||
#define SINE_INT_ZBIT 14
|
||||
#define __int64 long long
|
||||
/*软件索引实现sin生成*/
|
||||
static int get_sine_value(int mx_idx)
|
||||
{
|
||||
int ret = 0;
|
||||
int idx = 0;
|
||||
int tm_idx = mx_idx & 0x1FFFFFF; //2^25
|
||||
int phase = tm_idx & 0x3FFF;
|
||||
int tp_idx0 = tm_idx >> 14;
|
||||
int tp_idx1 = tp_idx0 + 1;
|
||||
int sign = 1, dt0, dt1;
|
||||
|
||||
if (tp_idx0 > 1024) {
|
||||
sign = -1;
|
||||
tp_idx0 = 2048 - tp_idx0;
|
||||
}
|
||||
if (tp_idx0 < 513) {
|
||||
dt0 = sf_sin_tab1[tp_idx0];
|
||||
} else {
|
||||
dt0 = sf_sin_tab1[1024 - tp_idx0];
|
||||
}
|
||||
|
||||
if (tp_idx1 > 1024) {
|
||||
sign = -1;
|
||||
tp_idx1 = 2048 - tp_idx1;
|
||||
}
|
||||
if (tp_idx1 < 513) {
|
||||
dt1 = sf_sin_tab1[tp_idx1];
|
||||
} else {
|
||||
dt1 = sf_sin_tab1[1024 - tp_idx1];
|
||||
}
|
||||
|
||||
ret = ((__int64)dt0 * (SINE_INT_ZOOM - phase) + (__int64)dt1 * phase) >> SINE_INT_ZBIT;
|
||||
|
||||
ret *= sign;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hw_sin_value(int a, int *sin_res, u8 precision)
|
||||
{
|
||||
u64 s64 = a;
|
||||
|
||||
*sin_res = __asm_sine(s64, precision);
|
||||
}
|
||||
|
||||
int sin_tone_make(void *_maker, void *data, int len)
|
||||
{
|
||||
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
|
||||
s16 *pcm = (s16 *)data;
|
||||
int sin_value = 0;
|
||||
int win_sin_value = 0;
|
||||
int add_idx = 0, sub_vol = 0, win_add_idx = 0;
|
||||
int offset = 0;
|
||||
u8 id = maker->id;
|
||||
u8 sin_num = maker->sin_num;
|
||||
u8 repeat = maker->repeat;
|
||||
u8 channel = maker->channel;
|
||||
int sin_index;
|
||||
int win_sin_index;
|
||||
int volume;
|
||||
u32 reamin_points = len / 2 / channel;
|
||||
|
||||
do {
|
||||
if (maker->next_param) {
|
||||
maker->volume = SINE_TOTAL_VOLUME;
|
||||
maker->sin_index = 0;
|
||||
maker->win_sin_index = 0;
|
||||
maker->next_param = 0;
|
||||
}
|
||||
|
||||
u8 win = maker->sin[id].win;
|
||||
add_idx = ((u64)(1 << 25) * maker->sin[id].freq / DEFAULT_SINE_SAMPLE_RATE) >> 9;
|
||||
if (win) {
|
||||
win_add_idx = ((u64)(1 << 25) * maker->sin[id].decay / DEFAULT_SINE_SAMPLE_RATE) >> 9;
|
||||
/*sub_vol = 0;*/
|
||||
} else {
|
||||
sub_vol = maker->sin[id].decay;
|
||||
}
|
||||
|
||||
sin_index = maker->sin_index;
|
||||
win_sin_index = maker->win_sin_index;
|
||||
volume = maker->volume;
|
||||
u32 points = 0;
|
||||
if (maker->fade_points) {
|
||||
points = maker->fade_points > reamin_points ? reamin_points : maker->fade_points;
|
||||
sub_vol = 0;
|
||||
maker->fade_points -= points;
|
||||
} else {
|
||||
points = maker->points > reamin_points ? reamin_points : maker->points;
|
||||
maker->points -= points;
|
||||
}
|
||||
reamin_points -= points;
|
||||
while (points--) {
|
||||
/*hw_sin_value(sin_index, &sin_value, 0);*/
|
||||
sin_value = __asm_sine((s64)sin_index, 2);
|
||||
if (win) {
|
||||
/*hw_sin_value(win_sin_index, &win_sin_value, 0);*/
|
||||
win_sin_value = __asm_sine((s64)win_sin_index, 2);
|
||||
#if ((defined CONFIG_CPU_BR36) || (defined CONFIG_CPU_BR28))
|
||||
sin_value = ((s64)sin_value * (s64)win_sin_value) >> 44;
|
||||
#else
|
||||
sin_value = ((s64)sin_value * (s64)win_sin_value) >> 34;
|
||||
#endif
|
||||
win_sin_index += win_add_idx;
|
||||
win_sin_index &= 0x1ffffff;
|
||||
} else {
|
||||
#if ((defined CONFIG_CPU_BR36) || (defined CONFIG_CPU_BR28))
|
||||
sin_value = ((s64)volume * sin_value) >> 39;
|
||||
#else
|
||||
sin_value = ((s64)volume * sin_value) >> 34;
|
||||
#endif
|
||||
}
|
||||
sin_index += add_idx;
|
||||
sin_index &= 0x1ffffff;
|
||||
|
||||
volume -= sub_vol;
|
||||
if (volume < 0) {
|
||||
volume = 0;
|
||||
}
|
||||
|
||||
*pcm++ = sin_value;
|
||||
if (channel == 2) {
|
||||
*pcm++ = sin_value;
|
||||
} else if (channel == 4) {
|
||||
*pcm++ = sin_value;
|
||||
*pcm++ = sin_value;
|
||||
*pcm++ = sin_value;
|
||||
}
|
||||
}
|
||||
|
||||
maker->volume = volume;
|
||||
maker->sin_index = sin_index;
|
||||
maker->win_sin_index = win_sin_index;
|
||||
if (!maker->points) {
|
||||
if (++id >= sin_num) {
|
||||
if (!repeat) {
|
||||
break;
|
||||
}
|
||||
id = 0;
|
||||
}
|
||||
maker->points = maker->sin[id].points;
|
||||
maker->id = id;
|
||||
maker->next_param = 1;
|
||||
}
|
||||
|
||||
if (!reamin_points) {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return len - (reamin_points * 2 * channel);
|
||||
}
|
||||
|
||||
int sin_tone_points(void *_maker)
|
||||
{
|
||||
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
|
||||
int points = 0;
|
||||
u8 i = 0;
|
||||
|
||||
for (i = 0; i < maker->sin_num; i++) {
|
||||
points += maker->sin[i].points;
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
void sin_tone_close(void *_maker)
|
||||
{
|
||||
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
|
||||
|
||||
#ifdef SINE_USE_MALLOC
|
||||
if (maker) {
|
||||
free(maker);
|
||||
}
|
||||
#else
|
||||
if (sin_maker_handle.open) {
|
||||
sin_maker_handle.open = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#include "asm/math_fast_function.h"
|
||||
|
||||
#ifndef DATA16
|
||||
#define DATA16 32767
|
||||
#endif
|
||||
|
||||
/*********************************
|
||||
* fc : 正弦波中心频率
|
||||
* fs : 采样频率
|
||||
* FrameSize :每次计算输出点数
|
||||
* idx :当前计算起始indix
|
||||
* rst :结果存放地址
|
||||
* *******************************/
|
||||
void SinWave_Generator(int fc, int fs, int FrameSize, int idx, short *rst)
|
||||
{
|
||||
float tmp0, tmp1, tmp2;
|
||||
tmp0 = (float)fc / fs;
|
||||
for (int i = 0; i < FrameSize; i++) {
|
||||
tmp1 = (i + idx) * tmp0 * 2;
|
||||
tmp2 = sin_float(tmp1);
|
||||
*rst = (short)(tmp2 * DATA16);
|
||||
rst++;
|
||||
}
|
||||
}
|
||||
/*********************************
|
||||
* fs : 采样频率
|
||||
* FrameSize :每次计算输出点数
|
||||
* idx :当前计算起始indix
|
||||
* ts :期望一次扫频所持续时间
|
||||
* rst :结果存放地址
|
||||
* *******************************/
|
||||
void SweepSin_Generator(int fs, int FrameSize, int idx, float ts, short *rst)
|
||||
{
|
||||
float fp, fc, tmp1, tmp2;
|
||||
int Ncnt, NPoint, DPoint;
|
||||
|
||||
NPoint = fs * ts;
|
||||
// fp = (fs/2)/(fs*ts);
|
||||
fp = 1 / (2 * 2 * ts);
|
||||
|
||||
for (int i = 0; i < FrameSize; i++) {
|
||||
Ncnt = (i + idx) / NPoint;
|
||||
DPoint = (i + idx) - Ncnt * NPoint;
|
||||
//printf("idx:%d \n",DPoint);
|
||||
tmp1 = ((DPoint * fp) / fs) * DPoint * 2;
|
||||
tmp2 = sin_float(tmp1);
|
||||
//printf("Sin[%d]:%d",i,(int)(tmp2*1000));
|
||||
*rst = (short)(tmp2 * DATA16);
|
||||
rst++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Description: 正弦信号生成
|
||||
* Arguments : fc 信号中心频率
|
||||
* fs 信号采样率
|
||||
* buf 数据输出地址
|
||||
* len 数据生成长度,单位是bytes
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int sin_idx = 0;
|
||||
void sin_pcm_fill(int fc, int fs, void *buf, u32 len)
|
||||
{
|
||||
SinWave_Generator(fc, fs, len / 2, sin_idx, buf);
|
||||
sin_idx += len / 2;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Description: 扫频信号生成
|
||||
* Arguments : fs 信号采样率
|
||||
* buf 数据输出地址
|
||||
* len 数据生成长度,单位是bytes
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int sweep_sin_idx = 0;
|
||||
void sweepsin_pcm_fill(int fs, void *buf, u32 len)
|
||||
{
|
||||
SweepSin_Generator(fs, len / 2, sweep_sin_idx, 25, buf);
|
||||
sweep_sin_idx += len / 2;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef __SINE_MAKE_H_
|
||||
#define __SINE_MAKE_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
#define DEFAULT_SINE_SAMPLE_RATE 16000
|
||||
#define SINE_TOTAL_VOLUME 26843546//16106128//20132660 //26843546
|
||||
|
||||
struct sin_param {
|
||||
//int idx_increment;
|
||||
int freq;
|
||||
int points;
|
||||
int win;
|
||||
int decay;
|
||||
};
|
||||
|
||||
int sin_tone_make(void *_maker, void *data, int len);
|
||||
void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat);
|
||||
int sin_tone_points(void *_maker);
|
||||
void sin_tone_close(void *_maker);
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Description: 正弦信号生成
|
||||
* Arguments : fc 信号中心频率
|
||||
* fs 信号采样率
|
||||
* buf 数据输出地址
|
||||
* len 数据生成长度,单位是bytes
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void sin_pcm_fill(int fc, int fs, void *buf, u32 len);
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Description: 扫频信号生成
|
||||
* Arguments : fs 信号采样率
|
||||
* buf 数据输出地址
|
||||
* len 数据生成长度,单位是bytes
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void sweepsin_pcm_fill(int fs, void *buf, u32 len);
|
||||
|
||||
#endif/*__SINE_MAKE_H_*/
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef __STREAM_ENTRY_H__
|
||||
#define __STREAM_ENTRY_H__
|
||||
|
||||
#include "system/includes.h"
|
||||
#include "media/includes.h"
|
||||
|
||||
// struct __stream_entry;
|
||||
struct __stream_entry {
|
||||
u8 is_end;
|
||||
void *data_priv;
|
||||
int (*data_callback)(void *priv, struct audio_data_frame *in);
|
||||
struct audio_stream_entry entry;
|
||||
};
|
||||
|
||||
struct __stream_entry *stream_entry_open(void *priv, int (*data_callback)(void *priv, struct audio_data_frame *in), u8 is_end);
|
||||
void stream_entry_close(struct __stream_entry **hdl);
|
||||
void stream_entry_resume(struct __stream_entry *hdl);
|
||||
|
||||
#endif// __STREAM_ENTRY_H__
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
#include "app_config.h"
|
||||
|
||||
#ifdef AUDIO_PCM_DEBUG
|
||||
#include "system/includes.h"
|
||||
#include "asm/uart_dev.h"
|
||||
#include "uartPcmSender.h"
|
||||
|
||||
static u8 uart_cbuf[32] __attribute__((aligned(4)));
|
||||
const uart_bus_t *uart_bus = NULL;
|
||||
|
||||
//设备事件响应demo
|
||||
void uart_event_handler(struct sys_event *e)
|
||||
{
|
||||
u8 uart_rxbuf[12] = {0};
|
||||
u8 uart_txbuf[12] = {0};
|
||||
const uart_bus_t *_uart_bus;
|
||||
u32 uart_rxcnt = 0;
|
||||
u8 i = 0;
|
||||
|
||||
if (0) {//!strcmp(e->arg, "uart_rx_overflow")) {
|
||||
if (e->u.dev.event == DEVICE_EVENT_CHANGE) {
|
||||
printf("uart event: %s\n", e->arg);
|
||||
_uart_bus = (const uart_bus_t *)e->u.dev.value;
|
||||
uart_rxcnt = _uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0);
|
||||
if (uart_rxcnt) {
|
||||
g_printf("rx:%s", uart_rxbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0) { //(!strcmp(e->arg, "uart_rx_outtime")) {
|
||||
if (e->u.dev.event == DEVICE_EVENT_CHANGE) {
|
||||
printf("uart event: %s\n", e->arg);
|
||||
_uart_bus = (const uart_bus_t *)e->u.dev.value;
|
||||
uart_rxcnt = _uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0);
|
||||
if (uart_rxcnt) {
|
||||
printf("get_buffer:\n");
|
||||
for (int i = 0; i < uart_rxcnt; i++) {
|
||||
putbyte(uart_rxbuf[i]);
|
||||
if (i % 16 == 15) {
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
if (uart_rxcnt % 16) {
|
||||
putchar('\n');
|
||||
}
|
||||
_uart_bus->write(uart_rxbuf, uart_rxcnt);
|
||||
}
|
||||
printf("uart out\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
SYS_EVENT_HANDLER(SYS_DEVICE_EVENT, uart_event_handler, 0);
|
||||
|
||||
void gpio_change(void *priv);
|
||||
static void uart_isr_hook(void *arg, u32 status)
|
||||
{
|
||||
const uart_bus_t *ubus = arg;
|
||||
struct sys_event e;
|
||||
|
||||
//当CONFIG_UARTx_ENABLE_TX_DMA(x = 0, 1)为1时,不要在中断里面调用ubus->write(),因为中断不能pend信号量
|
||||
if (status == UT_RX) {
|
||||
printf("uart_rx_isr\n");
|
||||
#if 1//(UART_DEV_USAGE_TEST_SEL == 1)
|
||||
e.type = SYS_DEVICE_EVENT;
|
||||
e.arg = "uart_rx_overflow";
|
||||
e.u.dev.event = DEVICE_EVENT_CHANGE;
|
||||
e.u.dev.value = (int)ubus;
|
||||
sys_event_notify(&e);
|
||||
#endif
|
||||
}
|
||||
if (status == UT_RX_OT) {
|
||||
printf("uart_rx_ot_isr\n");
|
||||
#if 1//(UART_DEV_USAGE_TEST_SEL == 1)
|
||||
e.type = SYS_DEVICE_EVENT;
|
||||
e.arg = "uart_rx_outtime";
|
||||
e.u.dev.event = DEVICE_EVENT_CHANGE;
|
||||
e.u.dev.value = (int)ubus;
|
||||
sys_event_notify(&e);
|
||||
#endif
|
||||
}
|
||||
if (status == UT_TX) {
|
||||
/* putchar('T'); */
|
||||
/* gpio_change(0); */
|
||||
}
|
||||
}
|
||||
|
||||
void uartSendData(void *buf, u16 len) //发送数据的接口。
|
||||
{
|
||||
if (uart_bus) {
|
||||
uart_bus->write(buf, len); //把数据写到DMA
|
||||
}
|
||||
}
|
||||
|
||||
/* char *TickPage = "uart online"; */
|
||||
/* void uartTickSend(void *priv){ */
|
||||
/* if(uartTickSendFlag){ */
|
||||
/* r_printf("sizeof:%d\n", sizeof(TickPage)); */
|
||||
/* uartSendData(TickPage, sizeof(TickPage)); */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
void uartSendInit()
|
||||
{
|
||||
struct uart_platform_data_t u_arg = {0};
|
||||
u_arg.tx_pin = PCM_UART1_TX_PORT;
|
||||
u_arg.rx_pin = PCM_UART1_RX_PORT;
|
||||
u_arg.rx_cbuf = uart_cbuf;
|
||||
u_arg.rx_cbuf_size = 32;
|
||||
u_arg.frame_length = 6;
|
||||
u_arg.rx_timeout = 100;
|
||||
u_arg.isr_cbfun = uart_isr_hook;
|
||||
u_arg.baud = PCM_UART1_BAUDRATE;
|
||||
u_arg.is_9bit = 0;
|
||||
|
||||
|
||||
r_printf("uart_dev_open() ...\n");
|
||||
uart_bus = uart_dev_open(&u_arg);
|
||||
r_printf("comming %s,%d\n", __func__, __LINE__);
|
||||
if (uart_bus != NULL) {
|
||||
r_printf("success\n");
|
||||
gpio_set_hd(PCM_UART1_TX_PORT, 1);
|
||||
gpio_set_hd0(PCM_UART1_TX_PORT, 1);
|
||||
//os_task_create(uart_u_task, (void *)uart_bus, 31, 512, 0, "uart_u_task");
|
||||
} else {
|
||||
r_printf("false\n");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _UARTPCMSENDER_H_
|
||||
#define _UARTPCMSENDER_H_
|
||||
#include "system/includes.h"
|
||||
#include "app_config.h"
|
||||
/*
|
||||
*串口导出数据配置
|
||||
*注意IO口设置不要和普通log输出uart冲突
|
||||
*/
|
||||
#define PCM_UART1_TX_PORT IO_PORT_DM /*数据导出发送IO*/
|
||||
#define PCM_UART1_RX_PORT -1
|
||||
#define PCM_UART1_BAUDRATE 2000000 /*数据导出波特率,不用修改,和接收端设置一直*/
|
||||
|
||||
#if ((TCFG_UART0_ENABLE == ENABLE_THIS_MOUDLE) && (PCM_UART1_TX_PORT == TCFG_UART0_TX_PORT))
|
||||
//IO口配置冲突,请检查修改
|
||||
#error "PCM_UART1_TX_PORT conflict with TCFG_UART0_TX_PORT"
|
||||
#endif/*PCM_UART1_TX_PORT*/
|
||||
|
||||
void uartSendInit(); //串口发数初始化
|
||||
void uartSendData(void *buf, u16 len); //发送数据的接口
|
||||
|
||||
#endif /*_UARTPCMSENDER_H_*/
|
||||
@@ -0,0 +1,246 @@
|
||||
|
||||
#include "typedef.h"
|
||||
#include "app_config.h"
|
||||
#include "task.h"
|
||||
#include "btctrler_task.h"
|
||||
#include "btcontroller_config.h"
|
||||
#include "system/includes.h"
|
||||
|
||||
#define LOG_TAG "[BT_DUT]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
//bredr test api
|
||||
extern void ble_enter_dut_tx_mode(void *param);
|
||||
extern void bt_ble_adv_enable(u8 enable);
|
||||
extern void bredr_fcc_init(u8 mode, u8 fre);
|
||||
|
||||
#if 0
|
||||
|
||||
static void bt_dut_api(void)
|
||||
{
|
||||
log_info("bt in dut \n");
|
||||
#if TCFG_AUTO_SHUT_DOWN_TIME
|
||||
extern void sys_auto_shut_down_disable(void);
|
||||
sys_auto_shut_down_disable();
|
||||
#endif
|
||||
|
||||
#if TCFG_USER_TWS_ENABLE
|
||||
extern void tws_cancle_all_noconn();
|
||||
tws_cancle_all_noconn() ;
|
||||
#else
|
||||
//sys_timer_del(app_var.auto_stop_page_scan_timer);
|
||||
extern void bredr_close_all_scan();
|
||||
bredr_close_all_scan();
|
||||
#endif
|
||||
|
||||
#if TCFG_USER_BLE_ENABLE
|
||||
#if (CONFIG_BT_MODE == BT_NORMAL)
|
||||
bt_ble_adv_enable(0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void bit_clr_ie(unsigned char index);
|
||||
/* !!!Notice:when this api is called and sleep mode should be sure to exit; */
|
||||
void bt_fix_fre_api(u8 fre)
|
||||
{
|
||||
bt_dut_api();
|
||||
|
||||
bit_clr_ie(IRQ_BREDR_IDX);
|
||||
bit_clr_ie(IRQ_BT_CLKN_IDX);
|
||||
|
||||
bredr_fcc_init(BT_FRE, fre);
|
||||
}
|
||||
#endif
|
||||
|
||||
//ble test api
|
||||
enum BLE_DUT_PAYLOAD_TYPE {
|
||||
PAYLOAD_TYPE_PRBS9 = 0,
|
||||
PAYLOAD_TYPE_11110000,
|
||||
PAYLOAD_TYPE_10101010,
|
||||
PAYLOAD_TYPE_PRBS15,
|
||||
PAYLOAD_TYPE_11111111,
|
||||
PAYLOAD_TYPE_00000000,
|
||||
PAYLOAD_TYPE_00001111,
|
||||
PAYLOAD_TYPE_01010101,
|
||||
|
||||
PAYLOAD_TYPE_SINGLE_CARRIER = 0xf0,
|
||||
};
|
||||
|
||||
enum BLE_DUT_PHY_TYPE {
|
||||
BLE_1M_UNCODED_PHY = 1,
|
||||
BLE_2M_UNCODED_PHY,
|
||||
BLE_1M_CODED_PHY_S8,
|
||||
BLE_1M_CODED_PHY_S2,
|
||||
};
|
||||
|
||||
struct ble_dut_param_set {
|
||||
u8 ch_index; //tx ch index;(0~39 -> 2402~2480)
|
||||
u8 payload_type; //tx payload type
|
||||
u8 payload_len; //payload_len(0~0xff) when continuous_tx = 0;
|
||||
u8 continuous_tx; //enable or disable continuous transmission mode(0/1)
|
||||
};
|
||||
|
||||
/* !!!Notice:when this api is called and sleep mode should be sure to exit; */
|
||||
void ble_fix_fre_api()
|
||||
{
|
||||
#if TCFG_USER_BLE_ENABLE
|
||||
#if (CONFIG_BT_MODE == BT_NORMAL)
|
||||
bt_ble_adv_enable(0);
|
||||
#endif
|
||||
os_time_dly(10);
|
||||
|
||||
struct ble_dut_param_set dut_param = {
|
||||
.ch_index = 0,
|
||||
.payload_type = PAYLOAD_TYPE_10101010,
|
||||
.payload_len = 0x20,
|
||||
.continuous_tx = 1,
|
||||
};
|
||||
ble_enter_dut_tx_mode(&dut_param);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *ble_dut_hdl = NULL;
|
||||
extern void ll_hci_destory(void);
|
||||
void ble_dut_mode_init(void)
|
||||
{
|
||||
if (!ble_dut_hdl) {
|
||||
ll_hci_destory();
|
||||
ble_dut_hdl = __ble_dut_ops->init();
|
||||
}
|
||||
}
|
||||
|
||||
void ble_dut_mode_exit(void)
|
||||
{
|
||||
if (ble_dut_hdl) {
|
||||
__ble_dut_ops->exit(ble_dut_hdl);
|
||||
ble_dut_hdl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ble_dut_tx_fre_api(u8 ch)
|
||||
{
|
||||
ble_dut_mode_init();
|
||||
struct ble_dut_tx_param_t tx_param = {
|
||||
.ch_index = ch,
|
||||
.payload_len = 0x20,
|
||||
.payload_type = PAYLOAD_TYPE_PRBS9,
|
||||
.phy_type = BLE_1M_UNCODED_PHY,
|
||||
};
|
||||
|
||||
log_info("BLE_DUT_TX-ch:%x\n", ch);
|
||||
__ble_dut_ops->ioctrl(BLE_DUT_SET_TX_MODE, &tx_param);
|
||||
|
||||
}
|
||||
|
||||
void ble_dut_rx_fre_api(u8 ch)
|
||||
{
|
||||
ble_dut_mode_init();
|
||||
struct ble_dut_rx_param_t rx_param = {
|
||||
.ch_index = ch,
|
||||
.phy_type = BLE_1M_UNCODED_PHY,
|
||||
};
|
||||
|
||||
log_info("BLE_DUT_RX-ch:%x \n", ch);
|
||||
__ble_dut_ops->ioctrl(BLE_DUT_SET_RX_MODE, &rx_param);
|
||||
|
||||
}
|
||||
|
||||
int ble_dut_test_end(void)
|
||||
{
|
||||
int pkt_valid_cnt = 0;
|
||||
int pkt_err_cnt = 0;
|
||||
if (ble_dut_hdl) {
|
||||
__ble_dut_ops->ioctrl(BLE_DUT_SET_TEST_END, &pkt_valid_cnt, NULL);
|
||||
|
||||
log_info("pkt_rx_cnt:%d pkt_err_cnt:%d\n", pkt_valid_cnt, pkt_err_cnt);
|
||||
} else {
|
||||
log_error("ble dut hdl not inited\n");
|
||||
}
|
||||
|
||||
return pkt_valid_cnt;
|
||||
}
|
||||
|
||||
static volatile u8 bt_test_status = 0;
|
||||
|
||||
void ble_bqb_test_thread_init(void);
|
||||
static hci_transport_config_uart_t config = {
|
||||
HCI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
0, // main baudrate
|
||||
0, // flow control
|
||||
NULL,
|
||||
};
|
||||
|
||||
extern void dut_hci_controller_init(const hci_transport_t *transport, const void *config);
|
||||
void ble_standard_dut_test_init(void)
|
||||
{
|
||||
log_info("%s\n", __FUNCTION__);
|
||||
bt_test_status = 1;
|
||||
ble_dut_mode_init();
|
||||
//ble_bqb_test_thread_init();
|
||||
dut_hci_controller_init((void *)hci_transport_uart_instance(), &config);
|
||||
}
|
||||
|
||||
void ble_standard_dut_test_close(void)
|
||||
{
|
||||
log_info("%s\n", __FUNCTION__);
|
||||
ble_dut_test_end();
|
||||
ble_dut_mode_exit();
|
||||
hci_transport_t *p_uart_trans = hci_transport_uart_instance();
|
||||
p_uart_trans->close();
|
||||
bt_test_status = 0;
|
||||
|
||||
}
|
||||
|
||||
void ble_dut_mode_key_handle(u8 type, u8 key_val)
|
||||
{
|
||||
static u8 rx_ch = 0;
|
||||
static u8 tx_ch = 0;
|
||||
switch (key_val) {
|
||||
case 3:
|
||||
ble_dut_tx_fre_api(tx_ch++);
|
||||
if (tx_ch > 39) {
|
||||
tx_ch = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ble_dut_rx_fre_api(rx_ch++);
|
||||
if (rx_ch > 39) {
|
||||
rx_ch = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ble_dut_test_end();
|
||||
break;
|
||||
|
||||
case 0:
|
||||
ble_standard_dut_test_init();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ble_standard_dut_test_close();
|
||||
break;
|
||||
|
||||
defualt:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 bt_test_idle_query(void)
|
||||
{
|
||||
return !bt_test_status;
|
||||
}
|
||||
|
||||
REGISTER_LP_TARGET(bt_test_lp_target) = {
|
||||
.name = "bt_test",
|
||||
.is_idle = bt_test_idle_query,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,150 @@
|
||||
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef cJSON__h
|
||||
#define cJSON__h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* cJSON Types: */
|
||||
#define cJSON_False 0
|
||||
#define cJSON_True 1
|
||||
#define cJSON_NULL 2
|
||||
#define cJSON_Number 3
|
||||
#define cJSON_String 4
|
||||
#define cJSON_Array 5
|
||||
#define cJSON_Object 6
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
#define cJSON_StringIsConst 512
|
||||
|
||||
/* The cJSON structure: */
|
||||
typedef struct cJSON {
|
||||
struct cJSON *next, *prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||
|
||||
int type; /* The type of the item, as above. */
|
||||
|
||||
char *valuestring; /* The item's string, if type==cJSON_String */
|
||||
int valueint; /* The item's number, if type==cJSON_Number */
|
||||
double valuedouble; /* The item's number, if type==cJSON_Number */
|
||||
|
||||
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||
} cJSON;
|
||||
|
||||
typedef struct cJSON_Hooks {
|
||||
void *(*malloc_fn)(size_t sz);
|
||||
void (*free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
extern void cJSON_InitHooks(cJSON_Hooks *hooks);
|
||||
|
||||
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
||||
extern cJSON *cJSON_Parse(const char *value);
|
||||
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
||||
extern char *cJSON_Print(cJSON *item);
|
||||
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
||||
extern char *cJSON_PrintUnformatted(cJSON *item);
|
||||
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
||||
extern char *cJSON_PrintBuffered(cJSON *item, int prebuffer, int fmt);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
extern void cJSON_Delete(cJSON *c);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
extern int cJSON_GetArraySize(cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
extern cJSON *cJSON_GetArrayItem(cJSON *array, int item);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
extern cJSON *cJSON_GetObjectItem(cJSON *object, const char *string);
|
||||
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||
extern const char *cJSON_GetErrorPtr(void);
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
extern cJSON *cJSON_CreateNull(void);
|
||||
extern cJSON *cJSON_CreateTrue(void);
|
||||
extern cJSON *cJSON_CreateFalse(void);
|
||||
extern cJSON *cJSON_CreateBool(int b);
|
||||
extern cJSON *cJSON_CreateNumber(double num);
|
||||
extern cJSON *cJSON_CreateString(const char *string);
|
||||
extern cJSON *cJSON_CreateArray(void);
|
||||
extern cJSON *cJSON_CreateObject(void);
|
||||
|
||||
/* These utilities create an Array of count items. */
|
||||
extern cJSON *cJSON_CreateIntArray(const int *numbers, int count);
|
||||
extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count);
|
||||
extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count);
|
||||
extern cJSON *cJSON_CreateStringArray(const char **strings, int count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
||||
extern void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */
|
||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||
|
||||
/* Remove/Detatch items from Arrays/Objects. */
|
||||
extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
|
||||
extern void cJSON_DeleteItemFromArray(cJSON *array, int which);
|
||||
extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
||||
extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
extern void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||
extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||
extern void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
extern cJSON *cJSON_Duplicate(cJSON *item, int recurse);
|
||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||
|
||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||
extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated);
|
||||
|
||||
extern void cJSON_Minify(char *json);
|
||||
|
||||
/* Macros for creating things quickly. */
|
||||
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
||||
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
|
||||
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
|
||||
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
|
||||
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
|
||||
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
|
||||
#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,121 @@
|
||||
#include "system/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "config/config_interface.h"
|
||||
|
||||
#define LOG_TAG "[APP-CONFIG]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
extern void dec_eq_test();
|
||||
static int sdfile_test(const char *name);
|
||||
int jl_cfg_dec_test(void);
|
||||
|
||||
ci_transport_config_uart_t config = {
|
||||
CI_TRANSPORT_CONFIG_UART,
|
||||
115200,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
};
|
||||
|
||||
#if (TCFG_ONLINE_ENABLE || TCFG_CFG_TOOL_ENABLE)
|
||||
#if TCFG_COMM_TYPE == TCFG_UART_COMM
|
||||
void config_online_init()
|
||||
{
|
||||
log_info("-------online Config Start-------");
|
||||
config_layer_init(ci_transport_uart_instance(), &config);
|
||||
}
|
||||
__initcall(config_online_init);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void config_test(void)
|
||||
{
|
||||
|
||||
#if 1
|
||||
log_info("-------EQ online Config Start-------");
|
||||
|
||||
sys_clk_set(SYS_48M);
|
||||
|
||||
//Setup dev input
|
||||
config_layer_init(ci_transport_uart_instance(), &config);
|
||||
|
||||
dec_eq_test();
|
||||
while (1) {
|
||||
extern void clr_wdt();
|
||||
clr_wdt();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
log_info("-------SDFile test Start------");
|
||||
|
||||
#ifdef SDFILE_DEV
|
||||
|
||||
#define SDFILE_NAME1 SDFILE_ROOT_PATH"xx.bin"
|
||||
|
||||
void *mnt = mount(SDFILE_DEV, SDFILE_MOUNT_PATH, "jlfs", 0, NULL);
|
||||
if (mnt == NULL) {
|
||||
log_error("mount jlfs failed");
|
||||
}
|
||||
|
||||
sdfile_test(SDFILE_NAME1);
|
||||
|
||||
#endif /*SDFILE_DEV*/
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
log_info("--------JL CFG test Start------");
|
||||
|
||||
jl_cfg_dec_test();
|
||||
#endif
|
||||
while (1);
|
||||
}
|
||||
|
||||
static int sdfile_test(const char *name)
|
||||
{
|
||||
log_d("SDFILE file path: %s", name);
|
||||
FILE *fp = NULL;
|
||||
u8 buf[16];
|
||||
u8 len;
|
||||
|
||||
fp = fopen(name, "r");
|
||||
if (!fp) {
|
||||
log_d("sdfile open file ERR!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = fread(fp, buf, sizeof(buf));
|
||||
|
||||
if (len != sizeof(buf)) {
|
||||
log_d("0-read file ERR!");
|
||||
goto _end;
|
||||
}
|
||||
|
||||
put_buf(buf, sizeof(buf));
|
||||
|
||||
fseek(fp, 16, SEEK_SET);
|
||||
|
||||
len = fread(fp, buf, sizeof(buf));
|
||||
|
||||
if (len != sizeof(buf)) {
|
||||
log_d("1-read file ERR!");
|
||||
goto _end;
|
||||
}
|
||||
|
||||
put_buf(buf, sizeof(buf));
|
||||
|
||||
log_d("SDFILE ok!");
|
||||
|
||||
_end:
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
#include "system/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "btcontroller_config.h"
|
||||
#include "btstack/bt_profile_config.h"
|
||||
#include "bt_common.h"
|
||||
|
||||
#define LOG_TAG "[BT-CFG]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#if TCFG_APP_BT_EN
|
||||
|
||||
typedef struct {
|
||||
// linked list - assert: first field
|
||||
void *offset_item;
|
||||
|
||||
// data is contained in same memory
|
||||
u32 service_record_handle;
|
||||
u8 *service_record;
|
||||
} service_record_item_t;
|
||||
|
||||
extern const u8 sdp_pnp_service_data[];
|
||||
extern const u8 sdp_a2dp_service_data[];
|
||||
extern const u8 sdp_avctp_ct_service_data[];
|
||||
extern const u8 sdp_avctp_ta_service_data[];
|
||||
extern const u8 sdp_hfp_service_data[];
|
||||
extern const u8 sdp_spp_service_data[];
|
||||
extern const u8 sdp_hid_service_data[];
|
||||
extern service_record_item_t sdp_record_item_begin[];
|
||||
extern service_record_item_t sdp_record_item_end[];
|
||||
|
||||
#define SDP_RECORD_HANDLER_REGISTER(handler) \
|
||||
const service_record_item_t handler \
|
||||
sec(.sdp_record_item)
|
||||
|
||||
#if TCFG_USER_BLE_ENABLE
|
||||
|
||||
#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV)
|
||||
const int config_stack_modules = (BT_BTSTACK_CLASSIC | BT_BTSTACK_LE_ADV);
|
||||
#else
|
||||
const int config_stack_modules = BT_BTSTACK_CLASSIC | BT_BTSTACK_LE;
|
||||
#endif
|
||||
|
||||
#else
|
||||
const int config_stack_modules = BT_BTSTACK_CLASSIC;
|
||||
#endif
|
||||
|
||||
#if (USER_SUPPORT_PROFILE_PNP==1)
|
||||
SDP_RECORD_HANDLER_REGISTER(pnp_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_pnp_service_data,
|
||||
.service_record_handle = 0x1000A,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (USER_SUPPORT_PROFILE_A2DP==1)
|
||||
u8 a2dp_profile_support = 1;
|
||||
SDP_RECORD_HANDLER_REGISTER(a2dp_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_a2dp_service_data,
|
||||
.service_record_handle = 0x00010001,
|
||||
};
|
||||
#endif
|
||||
#if (USER_SUPPORT_PROFILE_AVCTP==1)
|
||||
u8 acp_profile_support = 1;
|
||||
SDP_RECORD_HANDLER_REGISTER(arp_ct_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_avctp_ct_service_data,
|
||||
.service_record_handle = 0x00010002,
|
||||
};
|
||||
#if BT_SUPPORT_MUSIC_VOL_SYNC
|
||||
SDP_RECORD_HANDLER_REGISTER(arp_ta_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_avctp_ta_service_data,
|
||||
.service_record_handle = 0x00010005,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
#if (USER_SUPPORT_PROFILE_HFP==1)
|
||||
u8 hfp_profile_support = 1;
|
||||
SDP_RECORD_HANDLER_REGISTER(hfp_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_hfp_service_data,
|
||||
.service_record_handle = 0x00010003,
|
||||
};
|
||||
#endif
|
||||
#if (USER_SUPPORT_PROFILE_SPP==1)
|
||||
|
||||
u8 spp_up_profile_support = 1;
|
||||
//FE010000-1234-5678-ABCD-00805F9B34FB
|
||||
const u8 sdp_user_spp_service_data[96] = {
|
||||
0x36, 0x00, 0x5B, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x11, 0x09, 0x00, 0x01, 0x36, 0x00,
|
||||
0x11, 0x1C, 0xfe, 0x01, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xab, 0xcd, 0x00, 0x80, 0x5F, 0x9b,
|
||||
0x34, 0xfb, 0x09, 0x00, 0x04, 0x36, 0x00, 0x0E, 0x36, 0x00, 0x03, 0x19, 0x01, 0x00, 0x36, 0x00,
|
||||
0x05, 0x19, 0x00, 0x03, 0x08, 0x0a, 0x09, 0x00, 0x09, 0x36, 0x00, 0x17, 0x36, 0x00, 0x14, 0x1C,
|
||||
0xfe, 0x01, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xab, 0xcd, 0x00, 0x80, 0x5F, 0x9b, 0x34, 0xfb,
|
||||
0x09, 0x01, 0x00, 0x09, 0x01, 0x00, 0x25, 0x06, 0x4A, 0x4C, 0x5F, 0x53, 0x50, 0x50, 0x00, 0x00,
|
||||
};
|
||||
SDP_RECORD_HANDLER_REGISTER(spp_user_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_user_spp_service_data,
|
||||
.service_record_handle = 0x00010011,
|
||||
};
|
||||
|
||||
u8 spp_profile_support = 1;
|
||||
SDP_RECORD_HANDLER_REGISTER(spp_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_spp_service_data,
|
||||
.service_record_handle = 0x00010004,
|
||||
};
|
||||
|
||||
#endif
|
||||
#if (USER_SUPPORT_PROFILE_HID==1)
|
||||
u8 hid_profile_support = 1;
|
||||
SDP_RECORD_HANDLER_REGISTER(hid_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_hid_service_data,
|
||||
.service_record_handle = 0x00010006,
|
||||
};
|
||||
#endif
|
||||
#if (USER_SUPPORT_PROFILE_PBAP==1)
|
||||
extern const u8 sdp_pbap_service_data[];
|
||||
u8 pbap_profile_support = 1;
|
||||
SDP_RECORD_HANDLER_REGISTER(pbap_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_pbap_service_data,
|
||||
.service_record_handle = 0x00010008,
|
||||
};
|
||||
#endif
|
||||
#if (USER_SUPPORT_PROFILE_MAP==1)
|
||||
extern const u8 sdp_map_mce_service_data[];
|
||||
u8 map_profile_support = 1;
|
||||
SDP_RECORD_HANDLER_REGISTER(map_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_map_mce_service_data,
|
||||
.service_record_handle = 0x00010009,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*注意hid_conn_depend_on_dev_company置1之后,安卓手机会默认断开HID连接 */
|
||||
/*注意hid_conn_depend_on_dev_company置2之后,默认不断开HID连接 */
|
||||
const u8 hid_conn_depend_on_dev_company = 1;
|
||||
const u8 sdp_get_remote_pnp_info = 0;
|
||||
|
||||
#ifdef CONFIG_256K_FLASH
|
||||
const u8 pbg_support_enable = 0;
|
||||
const u8 adt_profile_support = 0;
|
||||
const u8 more_hfp_cmd_support = 0;
|
||||
#else
|
||||
|
||||
#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV)
|
||||
const u8 pbg_support_enable = 1;
|
||||
const u8 adt_profile_support = 1;
|
||||
#else
|
||||
const u8 pbg_support_enable = 0;
|
||||
const u8 adt_profile_support = 0;
|
||||
#endif
|
||||
|
||||
const u8 more_hfp_cmd_support = 1;
|
||||
|
||||
#endif
|
||||
|
||||
#if (TCFG_BD_NUM == 2)
|
||||
const u8 a2dp_mutual_support = 1;
|
||||
const u8 more_addr_reconnect_support = 1;
|
||||
#if USER_SUPPORT_DUAL_A2DP_SOURCE
|
||||
const u8 more_avctp_cmd_support = 0;
|
||||
#else
|
||||
const u8 more_avctp_cmd_support = 1;
|
||||
#endif
|
||||
#else
|
||||
const u8 a2dp_mutual_support = 0;
|
||||
const u8 more_addr_reconnect_support = 0;
|
||||
#if ((RCSP_ADV_EN || SMART_BOX_EN) && JL_EARPHONE_APP_EN)
|
||||
const u8 more_avctp_cmd_support = 1;
|
||||
#else
|
||||
const u8 more_avctp_cmd_support = 0;
|
||||
#endif
|
||||
#endif
|
||||
#if TCFG_USER_EMITTER_ENABLE
|
||||
const u8 hci_inquiry_support = 1;
|
||||
const u8 btstack_emitter_support = 1; /*定义用于优化代码编译*/
|
||||
|
||||
#if USER_SUPPORT_PROFILE_A2DP
|
||||
const u8 emitter_hfp_hf_support = 0; /*置1时做发射器连接手机时只支持hfp*/
|
||||
#else
|
||||
const u8 emitter_hfp_hf_support = 1; /*置1时做发射器连接手机时只支持hfp*/
|
||||
#endif
|
||||
|
||||
extern const u8 sdp_a2dp_source_service_data[];
|
||||
|
||||
#if (USER_SUPPORT_PROFILE_A2DP==0)
|
||||
u8 a2dp_profile_support = 2;
|
||||
#endif
|
||||
|
||||
SDP_RECORD_HANDLER_REGISTER(a2dp_src_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_a2dp_source_service_data,
|
||||
.service_record_handle = 0x0001000B,
|
||||
};
|
||||
#if (USER_SUPPORT_PROFILE_HFP_AG==1)
|
||||
extern const u8 sdp_hfp_ag_service_data[];
|
||||
u8 hfp_ag_profile_support = 1;
|
||||
SDP_RECORD_HANDLER_REGISTER(hfp_ag_sdp_record_item) = {
|
||||
.service_record = (u8 *)sdp_hfp_ag_service_data,
|
||||
.service_record_handle = 0x00010008,
|
||||
};
|
||||
#endif
|
||||
#else
|
||||
const u8 hci_inquiry_support = 0;
|
||||
const u8 btstack_emitter_support = 0; /*定义用于优化代码编译*/
|
||||
#endif
|
||||
/*u8 l2cap_debug_enable = 0xf0;
|
||||
u8 rfcomm_debug_enable = 0xf;
|
||||
u8 profile_debug_enable = 0xff;
|
||||
u8 ble_debug_enable = 0xff;
|
||||
u8 btstack_tws_debug_enable = 0xf;*/
|
||||
|
||||
#else
|
||||
const u8 btstack_emitter_support = 1; /*定义用于优化代码编译*/
|
||||
const u8 a2dp_mutual_support = 1;
|
||||
const u8 adt_profile_support = 0;
|
||||
const u8 pbg_support_enable = 0;
|
||||
#endif
|
||||
@@ -0,0 +1,370 @@
|
||||
#include "system/includes.h"
|
||||
#include "config/config_interface.h"
|
||||
#include "system/event.h"
|
||||
#include "app_online_cfg.h"
|
||||
#include "asm/uart_dev.h"
|
||||
#include "app_config.h"
|
||||
#include "asm/crc16.h"
|
||||
|
||||
#define LOG_TAG "[CI-UART]"
|
||||
/* #define LOG_ERROR_ENABLE */
|
||||
/* #define LOG_INFO_ENABLE */
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#include "debug.h"
|
||||
|
||||
#if (TCFG_ONLINE_ENABLE || TCFG_CFG_TOOL_ENABLE)
|
||||
struct config_uart {
|
||||
u32 baudrate;
|
||||
int flowcontrol;
|
||||
const char *dev_name;
|
||||
};
|
||||
|
||||
struct uart_hdl {
|
||||
|
||||
struct config_uart config;
|
||||
|
||||
uart_bus_t *udev;
|
||||
void *dbuf;
|
||||
|
||||
void *pRxBuffer;
|
||||
|
||||
u8 ucRxIndex;
|
||||
u8 rx_type;
|
||||
|
||||
u16 data_length;
|
||||
|
||||
void *pTxBuffer;
|
||||
|
||||
void (*packet_handler)(const u8 *packet, int size);
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
//head
|
||||
u16 preamble;
|
||||
u8 type;
|
||||
u16 length;
|
||||
u8 crc8;
|
||||
u16 crc16;
|
||||
u8 payload[0];
|
||||
} _GNU_PACKED_ uart_packet_t;
|
||||
|
||||
#define UART_FORMAT_HEAD sizeof(uart_packet_t)
|
||||
|
||||
typedef struct {
|
||||
//head
|
||||
u16 preamble0;
|
||||
u8 preamble1;
|
||||
u16 crc16;
|
||||
u8 length;
|
||||
u8 type;
|
||||
u8 sq;
|
||||
u8 payload[0];
|
||||
} _GNU_PACKED_ uart_tool_packet_t;
|
||||
|
||||
#define UART_TOOL_FORMAT_HEAD sizeof(uart_tool_packet_t)
|
||||
|
||||
static void dummy_handler(const u8 *packet, int size);
|
||||
|
||||
#define UART_PREAMBLE 0xBED6
|
||||
#define UART_NEW_TOOL_PREAMBLE0 0xAA5A
|
||||
#define UART_NEW_TOOL_PREAMBLE1 0xA5
|
||||
|
||||
#define UART_RX_SIZE 0x100
|
||||
#define UART_TX_SIZE 0x30
|
||||
#define UART_DB_SIZE 0x100
|
||||
#define UART_BAUD_RATE 115200
|
||||
|
||||
#ifdef HAVE_MALLOC
|
||||
static struct uart_hdl *hdl;
|
||||
#define __this (hdl)
|
||||
#else
|
||||
static struct uart_hdl hdl;
|
||||
#define __this (&hdl)
|
||||
|
||||
static u8 pRxBuffer_static[UART_RX_SIZE] __attribute__((aligned(4))); //rx memory
|
||||
static u8 pTxBuffer_static[UART_TX_SIZE] __attribute__((aligned(4))); //tx memory
|
||||
static u8 devBuffer_static[UART_DB_SIZE] __attribute__((aligned(4))); //dev DMA memory
|
||||
#endif
|
||||
|
||||
s16 get_ci_tx_size()
|
||||
{
|
||||
return UART_TX_SIZE;
|
||||
}
|
||||
static u8 procotol = 0;
|
||||
void ci_data_rx_handler(u8 type)
|
||||
{
|
||||
u16 crc16;
|
||||
uart_tool_packet_t *p_newtool;
|
||||
uart_packet_t *p;
|
||||
|
||||
__this->rx_type = type;
|
||||
|
||||
if (type == CI_UART && __this->udev) {
|
||||
__this->data_length += __this->udev->read(&__this->pRxBuffer[__this->data_length], (UART_RX_SIZE - __this->data_length), 0);//串口读取buf剩余空间的长度,实际长度比buf长,导致越界改写问题
|
||||
}
|
||||
|
||||
/* log_info("Rx : %d", __this->data_length); */
|
||||
/* log_info_hexdump(__this->pRxBuffer, __this->data_length); */
|
||||
if (__this->data_length > UART_RX_SIZE) {
|
||||
log_error("Wired");
|
||||
}
|
||||
|
||||
u8 *tmp_buf = NULL;
|
||||
tmp_buf = __this->pRxBuffer;
|
||||
if (__this->data_length >= 2) {
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < __this->data_length - 1; ++i) {
|
||||
if ((tmp_buf[i] == 0x5A) && (tmp_buf[i + 1] == 0xAA) && (tmp_buf[i + 2] == 0xA5)) {
|
||||
procotol = 1;
|
||||
break;
|
||||
} else if (tmp_buf[i] == 0xD6 && tmp_buf[i + 1] == 0xBE) {
|
||||
procotol = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != 0) {
|
||||
__this->data_length -= i;
|
||||
/* printf("__this->data_length %d i %d\n", __this->data_length, i); */
|
||||
if (__this->data_length > 0) {
|
||||
memmove(&__this->pRxBuffer[0], &tmp_buf[i], __this->data_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (procotol) {
|
||||
if (__this->data_length <= UART_TOOL_FORMAT_HEAD) {
|
||||
return;
|
||||
}
|
||||
p_newtool = __this->pRxBuffer;
|
||||
|
||||
if ((p_newtool->preamble0 != UART_NEW_TOOL_PREAMBLE0) || (p_newtool->preamble1 != UART_NEW_TOOL_PREAMBLE1)) {
|
||||
log_error("preamble err\n");
|
||||
log_info_hexdump(__this->pRxBuffer, __this->data_length);
|
||||
goto reset_buf;
|
||||
}
|
||||
|
||||
if (__this->data_length >= p_newtool->length + 6) {
|
||||
crc16 = crc_get_16bit(&p_newtool->length, p_newtool->length + 1);
|
||||
/* log_info("CRC16 0x%x / 0x%x", crc16, p_newtool->crc16); */
|
||||
if (p_newtool->crc16 != crc16) {
|
||||
log_error("crc16 err\n");
|
||||
goto reset_buf;
|
||||
}
|
||||
/* log_info_hexdump(p_newtool, p_newtool->length + 6); */
|
||||
online_cfg_tool_data_deal(p_newtool, p_newtool->length + 6);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (__this->data_length <= UART_FORMAT_HEAD) {
|
||||
return;
|
||||
}
|
||||
p = __this->pRxBuffer;
|
||||
|
||||
if (p->preamble != UART_PREAMBLE) {
|
||||
log_info("preamble err\n");
|
||||
log_info_hexdump(__this->pRxBuffer, __this->data_length);
|
||||
goto reset_buf;
|
||||
}
|
||||
|
||||
crc16 = crc_get_16bit(__this->pRxBuffer, UART_FORMAT_HEAD - 3);
|
||||
/* log_info("CRC8 0x%x / 0x%x", crc16, p->crc8); */
|
||||
if (p->crc8 != (crc16 & 0xff)) {
|
||||
log_info("crc8 err\n");
|
||||
goto reset_buf;
|
||||
}
|
||||
if (__this->data_length >= p->length + UART_FORMAT_HEAD) {
|
||||
/* log_info("Total length : 0x%x / Rx length : 0x%x", __this->data_length, p->length + CI_FORMAT_HEAD); */
|
||||
crc16 = crc_get_16bit(p->payload, p->length);
|
||||
/* log_info("CRC16 0x%x / 0x%x", crc16, p->crc16); */
|
||||
if (p->crc16 != crc16) {
|
||||
log_info("crc16 err\n");
|
||||
goto reset_buf;
|
||||
}
|
||||
__this->packet_handler(p->payload, p->length);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reset_buf:
|
||||
__this->data_length = 0;
|
||||
}
|
||||
|
||||
static void ci_uart_isr_cb(void *ut_bus, u32 status)
|
||||
{
|
||||
if (status == UT_TX) {
|
||||
return ;
|
||||
}
|
||||
struct sys_event e;
|
||||
e.type = SYS_DEVICE_EVENT;
|
||||
e.arg = (void *)DEVICE_EVENT_FROM_CI_UART;
|
||||
e.u.dev.event = 0;
|
||||
e.u.dev.value = 0;
|
||||
sys_event_notify(&e);
|
||||
}
|
||||
|
||||
static int ci_uart_init()
|
||||
{
|
||||
struct uart_platform_data_t ut = {0};
|
||||
ut.tx_pin = TCFG_ONLINE_TX_PORT;
|
||||
ut.rx_pin = TCFG_ONLINE_RX_PORT;
|
||||
ut.baud = __this->config.baudrate;
|
||||
ut.rx_timeout = 1;
|
||||
ut.isr_cbfun = ci_uart_isr_cb;
|
||||
ut.rx_cbuf = devBuffer_static;
|
||||
ut.rx_cbuf_size = UART_DB_SIZE;
|
||||
ut.frame_length = UART_DB_SIZE;
|
||||
/* JL_CLOCK->CLK_CON1 |= BIT(11); */
|
||||
/* JL_CLOCK->CLK_CON1 &= ~BIT(10); */
|
||||
__this->dbuf = devBuffer_static;
|
||||
__this->data_length = 0;
|
||||
__this->udev = (uart_bus_t *)uart_dev_open(&ut);
|
||||
if (__this->udev == NULL) {
|
||||
log_error("open uart dev err\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ci_uart_putbyte(char a)
|
||||
{
|
||||
if (__this->udev) {
|
||||
__this->udev->putbyte(a);
|
||||
}
|
||||
}
|
||||
|
||||
void ci_uart_write(char *buf, u16 len)
|
||||
{
|
||||
if (__this->udev) {
|
||||
__this->udev->write(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void dummy_handler(const u8 *packet, int size)
|
||||
{
|
||||
log_error("Dummy");
|
||||
}
|
||||
|
||||
static void clock_critical_enter(void)
|
||||
{
|
||||
|
||||
}
|
||||
static void clock_critical_exit(void)
|
||||
{
|
||||
if (__this->udev) {
|
||||
__this->udev->set_baud(__this->config.baudrate);
|
||||
}
|
||||
}
|
||||
CLOCK_CRITICAL_HANDLE_REG(ci, clock_critical_enter, clock_critical_exit)
|
||||
|
||||
static void ci_dev_init(const void *config)
|
||||
{
|
||||
#ifdef HAVE_MALLOC
|
||||
__this = malloc(sizeof(struct uart_hdl));
|
||||
ASSERT(__this, "Fatal error");
|
||||
|
||||
memset(__this, 0x0, sizeof(struct uart_hdl));
|
||||
|
||||
__this->pRxBuffer = malloc(UART_RX_SIZE);
|
||||
ASSERT(__this->pRxBuffer, "Fatal error");
|
||||
|
||||
__this->pTxBuffer = malloc(UART_TX_SIZE);
|
||||
ASSERT(__this->pTxBuffer, "Fatal error");
|
||||
#else
|
||||
log_info("Static");
|
||||
__this->pRxBuffer = pRxBuffer_static;
|
||||
__this->pTxBuffer = pTxBuffer_static;
|
||||
#endif
|
||||
|
||||
__this->packet_handler = dummy_handler;
|
||||
|
||||
ci_transport_config_uart_t *ci_config_uart = (ci_transport_config_uart_t *)config;
|
||||
|
||||
__this->config.baudrate = ci_config_uart->baudrate_init;
|
||||
__this->config.flowcontrol = ci_config_uart->flowcontrol;
|
||||
__this->config.dev_name = ci_config_uart->device_name;
|
||||
|
||||
log_info("baudrate : %d", __this->config.baudrate);
|
||||
log_info("flowcontrol: %d", __this->config.flowcontrol);
|
||||
}
|
||||
|
||||
static int ci_dev_open(void)
|
||||
{
|
||||
ci_uart_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ci_dev_close(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ci_dev_register_packet_handler(void (*handler)(const u8 *packet, int size))
|
||||
{
|
||||
__this->packet_handler = handler;
|
||||
}
|
||||
|
||||
static int ci_dev_send_packet(const u8 *packet, int size)
|
||||
{
|
||||
/* dev_stream_out(); */
|
||||
int i = 0;
|
||||
uart_packet_t *p = (uart_packet_t *)__this->pTxBuffer;
|
||||
|
||||
p->preamble = UART_PREAMBLE;
|
||||
p->type = 0;
|
||||
p->length = size;
|
||||
p->crc8 = CRC16(p, UART_FORMAT_HEAD - 3) & 0xff;
|
||||
p->crc16 = CRC16(packet, size);
|
||||
|
||||
size += UART_FORMAT_HEAD;
|
||||
/* ASSERT(size <= UART_TX_SIZE, "Fatal Error"); */
|
||||
if (size > UART_TX_SIZE) {
|
||||
log_e("Fatal Error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(p->payload, packet, size);
|
||||
|
||||
/* log_info("Tx : %d", size); */
|
||||
/* log_info_hexdump(p, size); */
|
||||
if (__this->rx_type == CI_UART) {
|
||||
#if 0
|
||||
while (size--) {
|
||||
ci_uart_putbyte(((char *)p)[i++]);
|
||||
}
|
||||
#else
|
||||
ci_uart_write(p, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ci_dev_can_send_packet_now(uint8_t packet_type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get dev api skeletons
|
||||
static const ci_transport_t ci_transport_uart = {
|
||||
/* const char * name; */ "CI_UART",
|
||||
/* void (*init) (const void *transport_config); */ &ci_dev_init,
|
||||
/* int (*open)(void); */ &ci_dev_open,
|
||||
/* int (*close)(void); */ &ci_dev_close,
|
||||
/* void (*register_packet_handler)(void (*handler)(...); */ &ci_dev_register_packet_handler,
|
||||
/* int (*can_send_packet_now)(uint8_t packet_type); */ &ci_dev_can_send_packet_now,
|
||||
/* int (*send_packet)(...); */ &ci_dev_send_packet,
|
||||
};
|
||||
|
||||
const ci_transport_t *ci_transport_uart_instance(void)
|
||||
{
|
||||
return &ci_transport_uart;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
|
||||
#ifndef _BT_PROFILE_CFG_H_
|
||||
#define _BT_PROFILE_CFG_H_
|
||||
|
||||
#include "app_config.h"
|
||||
#include "btcontroller_modules.h"
|
||||
|
||||
|
||||
#if (TRANS_DATA_EN || RCSP_BTMATE_EN || RCSP_ADV_EN || SMART_BOX_EN || ANCS_CLIENT_EN || LL_SYNC_EN || TUYA_DEMO_EN)
|
||||
#ifndef BT_FOR_APP_EN
|
||||
#define BT_FOR_APP_EN 1
|
||||
#endif
|
||||
#else
|
||||
#ifndef BT_FOR_APP_EN
|
||||
#define BT_FOR_APP_EN 0
|
||||
#endif
|
||||
#ifndef AI_APP_PROTOCOL
|
||||
#define AI_APP_PROTOCOL 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
///---sdp service record profile- 用户选择支持协议--///
|
||||
#if (BT_FOR_APP_EN || APP_ONLINE_DEBUG || AI_APP_PROTOCOL)
|
||||
#if (LL_SYNC_EN || TUYA_DEMO_EN)
|
||||
#undef USER_SUPPORT_PROFILE_SPP
|
||||
#define USER_SUPPORT_PROFILE_SPP 0
|
||||
#else
|
||||
#undef USER_SUPPORT_PROFILE_SPP
|
||||
#define USER_SUPPORT_PROFILE_SPP 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//ble demo的例子
|
||||
#define DEF_BLE_DEMO_NULL 0 //ble 没有使能
|
||||
#define DEF_BLE_DEMO_ADV 1 //only adv,can't connect
|
||||
#define DEF_BLE_DEMO_TRANS_DATA 2 //
|
||||
#define DEF_BLE_DEMO_RCSP_DEMO 4 //
|
||||
#define DEF_BLE_DEMO_ADV_RCSP 5
|
||||
#define DEF_BLE_DEMO_CLIENT 7 //
|
||||
#define DEF_BLE_ANCS_ADV 9
|
||||
#define DEF_BLE_DEMO_MULTI 11 //
|
||||
#define DEF_BLE_DEMO_LL_SYNC 13 //
|
||||
#define DEF_BLE_DEMO_WIRELESS_MIC_SERVER 14 //
|
||||
#define DEF_BLE_DEMO_WIRELESS_MIC_CLIENT 15 //
|
||||
#define DEF_BLE_DEMO_TUYA 16 //
|
||||
#define DEF_BLE_WL_MIC_1T1_TX 17
|
||||
#define DEF_BLE_WL_MIC_1T1_RX 18
|
||||
#define DEF_BLE_WL_MIC_1TN_TX 19
|
||||
#define DEF_BLE_WL_MIC_1TN_RX 20
|
||||
#define DEF_LE_AUDIO_CENTRAL 21
|
||||
#define DEF_LE_AUDIO_PERIPHERAL 22
|
||||
#define DEF_LE_AUDIO_BROADCASTER 23
|
||||
#define DEF_BLE_DEMO_HOGP 24
|
||||
|
||||
#define LE_AUDIO_EN 0 //DEF_LE_AUDIO_CENTRAL
|
||||
|
||||
//配置选择的demo
|
||||
#if TCFG_USER_BLE_ENABLE
|
||||
|
||||
#if (SMART_BOX_EN | RCSP_BTMATE_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_RCSP_DEMO
|
||||
|
||||
#elif TRANS_DATA_EN
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_TRANS_DATA
|
||||
|
||||
#elif LL_SYNC_EN
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_LL_SYNC
|
||||
|
||||
#elif TUYA_DEMO_EN
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_TUYA
|
||||
|
||||
#elif RCSP_ADV_EN
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_ADV_RCSP
|
||||
|
||||
#elif BLE_CLIENT_EN
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_CLIENT
|
||||
|
||||
#elif TRANS_MULTI_BLE_EN
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_MULTI
|
||||
|
||||
#elif ANCS_CLIENT_EN
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_ANCS_ADV
|
||||
|
||||
#elif AI_APP_PROTOCOL
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_NULL
|
||||
|
||||
#elif (BLE_WIRELESS_CLIENT_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_WIRELESS_MIC_CLIENT
|
||||
|
||||
#elif (BLE_WIRELESS_SERVER_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_WIRELESS_MIC_SERVER
|
||||
|
||||
#elif (BLE_WIRELESS_1T1_TX_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_WL_MIC_1T1_TX
|
||||
|
||||
#elif (BLE_WIRELESS_1T1_RX_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_WL_MIC_1T1_RX
|
||||
|
||||
#elif (BLE_WIRELESS_1TN_TX_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_WL_MIC_1TN_TX
|
||||
|
||||
#elif (BLE_WIRELESS_1TN_RX_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_WL_MIC_1TN_RX
|
||||
|
||||
#elif (LE_AUDIO_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT LE_AUDIO_EN
|
||||
|
||||
#elif (BLE_HID_EN)
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_HOGP
|
||||
|
||||
#else
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE5_DEMO
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_NULL//ble is closed
|
||||
#endif
|
||||
|
||||
//delete 2021-09-24;删除公共配置,放到各个profile自己配置
|
||||
// #define TCFG_BLE_SECURITY_EN 0 /*是否发请求加密命令*/
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,242 @@
|
||||
#ifndef _APP_SOUND_BOX_
|
||||
#define _APP_SOUND_BOX_
|
||||
|
||||
#include "typedef.h"
|
||||
#include "sdfile.h"
|
||||
#include "fs.h"
|
||||
#include "asm/sfc_norflash_api.h"
|
||||
#include "event.h"
|
||||
|
||||
/*
|
||||
* 波特率默认为 115200
|
||||
* 对于物理串口,且是异步形式的协议,封包方式如下
|
||||
*
|
||||
* CRC是 CRC16(L + T + SQ + DATA)
|
||||
* 其中,L是指(T+SQ+DATA)的长度
|
||||
* DATA包含CMD与具体的数据流
|
||||
*
|
||||
* +----+----+----+--+--+---+---+----+---....---+
|
||||
* | 5A | AA | A5 | CRC | L | T | SQ | DATA |
|
||||
* +----+----+----+--+--+---+---+----+---....---+
|
||||
*
|
||||
* T 表示包的类型,其中
|
||||
* 0x00 -- 表示回复,其中SQ是对应需要回应的包的序号
|
||||
* 无论哪种模式下,回复包都用该种类型
|
||||
* 0x12 -- 表示配置文件通道,是主动发送数据
|
||||
* 例如,在配置工具中,PC往小机或者小机往PC主动发都用这个
|
||||
*/
|
||||
|
||||
/*T 表示包的类型*/
|
||||
#define REPLY_STYLE 0x00 //无论哪种模式下,回复包都用该种类型
|
||||
#define INITIATIVE_STYLE 0x12 //主动发送数据的包用该类型
|
||||
#define SLAVE_ATIVE_SEND 0x01 //小机主动上发给PC
|
||||
#define EFF_CONFIG_ID 0x11 //调音
|
||||
/*
|
||||
*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
| VERSION |AT| X| X| X| X| X| X| X| X| X| X| X|
|
||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||
*/
|
||||
#define PROTOCOL_VER_AT_NEW 0x0001 //使用新模式
|
||||
#define PROTOCOL_VER_AT_OLD 0x0011 //使用旧模式
|
||||
|
||||
|
||||
/*该文件所属文件ID为0*/
|
||||
#define CFG_TOOL_FILEID 0x00000000
|
||||
|
||||
/*该文件所属文件ID为0*/
|
||||
#if ((defined CONFIG_NEW_CFG_TOOL_ENABLE) && ((defined CONFIG_SOUNDBOX) \
|
||||
|| (defined CONFIG_EARPHONE_CASE_ENABLE)))
|
||||
#define CFG_TOOL_FILE SDFILE_RES_ROOT_PATH"cfg_tool.bin"
|
||||
#else
|
||||
#define CFG_TOOL_FILE SDFILE_APP_ROOT_PATH"cfg_tool.bin"
|
||||
#endif
|
||||
|
||||
/*旧调音工具eq文件所属文件ID为1*/
|
||||
#define CFG_OLD_EQ_FILEID 0x00000001
|
||||
#define CFG_OLD_EQ_FILE SDFILE_RES_ROOT_PATH"eq_cfg_hw.bin"
|
||||
|
||||
/*旧调音工具混响文件所属文件ID为2*/
|
||||
#define CFG_OLD_EFFECT_FILEID 0x00000002
|
||||
#define CFG_OLD_EFFECT_FILE SDFILE_RES_ROOT_PATH"effects_cfg.bin"
|
||||
|
||||
/*新调音工具eq文件所属文件ID为3*/
|
||||
#define CFG_EQ_FILEID 0x00000003
|
||||
#define CFG_EQ_FILE SDFILE_RES_ROOT_PATH"eq_cfg_hw.bin"
|
||||
|
||||
/*****************************************************************/
|
||||
/****PC与小机使用到的CMD,CMD包含在DATA中,为DATA的第一个Byte*****/
|
||||
/*****************************************************************/
|
||||
|
||||
#define ONLINE_SUB_OP_QUERY_BASIC_INFO 0x00000023 //查询固件的基本信息
|
||||
#define ONLINE_SUB_OP_QUERY_FILE_SIZE 0x0000000B //查询文件大小
|
||||
#define ONLINE_SUB_OP_QUERY_FILE_CONTENT 0x0000000C //读取文件内容
|
||||
#define ONLINE_SUB_OP_PREPARE_WRITE_FILE 0x00000022 //准备写入文件
|
||||
#define ONLINE_SUB_OP_READ_ADDR_RANGE 0x00000027 //读取地址范围内容
|
||||
#define ONLINE_SUB_OP_ERASE_ADDR_RANGE 0x00000024 //擦除地址范围内容
|
||||
#define ONLINE_SUB_OP_WRITE_ADDR_RANGE 0x00000025 //写入地址范围内容
|
||||
#define ONLINE_SUB_OP_ENTER_UPGRADE_MODE 0x00000026 //进入升级模式
|
||||
|
||||
/*收到其他工具的数据*/
|
||||
#define DEFAULT_ACTION 0x000000FF //其他工具的数据
|
||||
|
||||
/*****************************************************************/
|
||||
/*****小机接收PC的DATA,具体携带的数据,依据命令不同而不同**********/
|
||||
/*****************************************************************/
|
||||
|
||||
//查询固件的基本信息
|
||||
typedef struct {
|
||||
uint32_t cmd_id; //命令号,为0x23
|
||||
} R_QUERY_BASIC_INFO;
|
||||
|
||||
//查询文件大小
|
||||
typedef struct {
|
||||
uint32_t cmd_id; //命令号,为0x0B
|
||||
uint32_t file_id; //查询的文件的ID,配置文件的ID为0
|
||||
} R_QUERY_FILE_SIZE;
|
||||
|
||||
//读取文件内容
|
||||
typedef struct {
|
||||
uint32_t cmd_id; //命令号,为0x0C
|
||||
uint32_t file_id; //文件ID
|
||||
uint32_t offset; //偏移
|
||||
uint32_t size;
|
||||
} R_QUERY_FILE_CONTENT;
|
||||
|
||||
//准备写入文件
|
||||
typedef struct {
|
||||
uint32_t cmd_id; //命令号,为0x22
|
||||
uint32_t file_id; //文件ID
|
||||
uint32_t size; //文件大小
|
||||
} R_PREPARE_WRITE_FILE;
|
||||
|
||||
//读取地址范围内容
|
||||
typedef struct {
|
||||
uint32_t cmd_id; //命令号,为0x23
|
||||
uint32_t addr; //flash的物理地址
|
||||
uint32_t size; //读取的范围大小
|
||||
} R_READ_ADDR_RANGE;
|
||||
|
||||
//擦除地址范围内容
|
||||
typedef struct {
|
||||
uint32_t cmd_id; //命令号,为0x24
|
||||
uint32_t addr; //起始地址
|
||||
uint32_t size; //擦除大小
|
||||
} R_ERASE_ADDR_RANGE;
|
||||
|
||||
//写入地址范围内容
|
||||
typedef struct {
|
||||
uint32_t cmd_id; //命令号,为0x25
|
||||
uint32_t addr; //物理地址
|
||||
uint32_t size; //内容大小
|
||||
/*uint8_t body[0];*/ //具体内容,大小为size
|
||||
} R_WRITE_ADDR_RANGE;
|
||||
|
||||
//进入升级模式
|
||||
typedef struct {
|
||||
uint32_t cmd_id; //命令号,为0x26
|
||||
} R_ENTER_UPGRADE_MODE;
|
||||
|
||||
/*****************************************************************/
|
||||
/*******小机返回PC发送的DATA,具体的内容,依据命令不同而不同********/
|
||||
/*****************************************************************/
|
||||
|
||||
//(1)查询固件的基本信息
|
||||
typedef struct {
|
||||
uint16_t protocolVer; //协议版本,目前为1
|
||||
char progCrc[32]; //固件的CRC,返回字符串,\0 结尾
|
||||
char sdkName[32]; //SDK名字,\0 结尾
|
||||
char pid[16]; //PID,\0 结尾(注意最长是16字节,16字节的时候,末尾不需要0)
|
||||
char vid[16]; //VID,\0 结尾
|
||||
} S_QUERY_BASIC_INFO;
|
||||
|
||||
//(2)查询文件大小
|
||||
typedef struct {
|
||||
uint32_t file_size; //文件大小
|
||||
} S_QUERY_FILE_SIZE;
|
||||
|
||||
//(3)读取文件内容
|
||||
/*
|
||||
* 返回:具体的文件内容,长度为命令中的size参数
|
||||
* 注:PC工具在获取配置文件的大小后,会自行决定拆分成几次命令读取
|
||||
*/
|
||||
|
||||
//(4)准备写入文件
|
||||
/*
|
||||
* 例如,cfg_tool.bin 本身的物理地址可能是 100,而擦除单元是 4K(4096),cfg_tool.bin 本身大小是 3999 字节,则
|
||||
* file_addr = 100, file_size = 3999, earse_unit = 4096。
|
||||
* 注意,接下来,PC 端会读取```[0, 8192)```这个范围的内容,修改掉```[100,4099]```的内容,然后再通过其他命令,
|
||||
* 把```[0,8192)```这范围的内容写回去。
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t file_addr; //配置文件真实物理地址
|
||||
uint32_t file_size; //配置文件(cfg_tool.bin)本身的大小
|
||||
uint32_t earse_unit; //flash 擦除单元(如 4K 的时候,填 4096)
|
||||
} S_PREPARE_WRITE_FILE;
|
||||
|
||||
|
||||
//(5)读取地址范围内容
|
||||
/*
|
||||
* 返回:具体的文件内容,长度为命令中的size参数
|
||||
* 注:PC工具在获取配置文件的大小后,会自行决定拆分成几次命令读取
|
||||
*/
|
||||
|
||||
//(6)擦除地址范围内容
|
||||
/*
|
||||
*返回两个字节的内容,"FA"或者"OK",表示失败或者成功
|
||||
*/
|
||||
|
||||
//(7)写入地址范围内容
|
||||
/*
|
||||
*返回两个字节的内容,"FA"或者"OK",表示失败或者成功
|
||||
*/
|
||||
|
||||
//(8)进入升级模式
|
||||
/*
|
||||
*小机收到命令后,进入升级模式
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief usb或者串口收到的数据流通过这个接口传入进行数据解析
|
||||
*
|
||||
* @param buf 存储普通串口/USB收到的数据包
|
||||
* @param len buf的长度(byte)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/* --------------------------------------------------------------------------*/
|
||||
void online_cfg_tool_data_deal(void *buf, u32 len);
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief 设备组装数据包并发送给PC工具,支持普通串口/USB串口/蓝牙SPP
|
||||
*
|
||||
* @param id 表示包的类型(不同的数据通道)
|
||||
* @param sq 对应需要回应的包的序号
|
||||
* @param buf 要发送的数据爆DATA部分
|
||||
* @param len buf的长度(byte)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/* --------------------------------------------------------------------------*/
|
||||
void all_assemble_package_send_to_pc(u8 id, u8 sq, u8 *buf, u32 len);
|
||||
|
||||
int app_cfg_tool_event_handler(struct cfg_tool_event *cfg_tool_dev);
|
||||
|
||||
struct tool_interface {
|
||||
u8 id;//通道
|
||||
void (*tool_message_deal)(u8 *buf, u32 len);//数据处理接口
|
||||
};
|
||||
|
||||
#define REGISTER_DETECT_TARGET(interface) \
|
||||
static struct tool_interface interface sec(.tool_interface)
|
||||
|
||||
extern struct tool_interface tool_interface_begin[];
|
||||
extern struct tool_interface tool_interface_end[];
|
||||
|
||||
#define list_for_each_tool_interface(p) \
|
||||
for (p = tool_interface_begin; p < tool_interface_end; p++)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,599 @@
|
||||
#include "cfg_tool.h"
|
||||
#include "event.h"
|
||||
#include "usb/device/cdc.h"
|
||||
#include "boot.h"
|
||||
#include "ioctl_cmds.h"
|
||||
#include "board_config.h"
|
||||
#include "app_online_cfg.h"
|
||||
#include "asm/crc16.h"
|
||||
#include "app_config.h"
|
||||
#include "config/config_target.h"
|
||||
#if APP_ONLINE_DEBUG
|
||||
#include "online_db_deal.h"
|
||||
#endif/*APP_ONLINE_DEBUG*/
|
||||
|
||||
/*
|
||||
*调音工具在线保存功能由协议接管,通道使用0x12,不分发给调音处理
|
||||
*配置工具通道为0x12,调音工具在线保存功能相关数据包通道必须设置为0x12
|
||||
*new_cfg_tool.c适用于新耳机/音箱配置工具和调音工具在线保存功能
|
||||
*支持异步协议和蓝牙SPP协议的数据解析与通信
|
||||
*/
|
||||
|
||||
#define LOG_TAG_CONST APP_CFG_TOOL
|
||||
#define LOG_TAG "[APP_CFG_TOOL]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
struct cfg_tool_info {
|
||||
/*PC往小机发送的DATA*/
|
||||
R_QUERY_BASIC_INFO r_basic_info;
|
||||
R_QUERY_FILE_SIZE r_file_size;
|
||||
R_QUERY_FILE_CONTENT r_file_content;
|
||||
R_PREPARE_WRITE_FILE r_prepare_write_file;
|
||||
R_READ_ADDR_RANGE r_read_addr_range;
|
||||
R_ERASE_ADDR_RANGE r_erase_addr_range;
|
||||
R_WRITE_ADDR_RANGE r_write_addr_range;
|
||||
R_ENTER_UPGRADE_MODE r_enter_upgrade_mode;
|
||||
|
||||
/*小机返回PC发送的DATA*/
|
||||
S_QUERY_BASIC_INFO s_basic_info;
|
||||
S_QUERY_FILE_SIZE s_file_size;
|
||||
S_PREPARE_WRITE_FILE s_prepare_write_file;
|
||||
};
|
||||
|
||||
static struct cfg_tool_info info = {
|
||||
.s_basic_info.protocolVer = PROTOCOL_VER_AT_OLD,
|
||||
};
|
||||
|
||||
#define TEMP_BUF_SIZE 256
|
||||
|
||||
extern const char *sdk_version_info_get(void);
|
||||
extern u8 *sdfile_get_burn_code(u8 *len);
|
||||
extern int norflash_erase(u32 cmd, u32 addr);
|
||||
|
||||
static u8 local_packet[TEMP_BUF_SIZE];
|
||||
const char error_return[] = "FA"; //表示失败
|
||||
const char ok_return[] = "OK"; //表示成功
|
||||
const char er_return[] = "ER"; //表示不能识别的命令
|
||||
static u32 size_total_write = 0;
|
||||
|
||||
extern void doe(u16 k, void *pBuf, u32 lenIn, u32 addr);
|
||||
extern int norflash_erase(u32 cmd, u32 addr);
|
||||
|
||||
#ifdef ALIGN
|
||||
#undef ALIGN
|
||||
#endif
|
||||
#define ALIGN(a, b) \
|
||||
({ \
|
||||
int m = (u32)(a) & ((b)-1); \
|
||||
int ret = (u32)(a) + (m?((b)-m):0); \
|
||||
ret;\
|
||||
})
|
||||
|
||||
static u32 cfg_tool_encode_data_by_user_key(u16 key, u8 *buff, u16 size, u32 dec_addr, u8 dec_len)
|
||||
{
|
||||
u16 key_addr;
|
||||
u16 r_len;
|
||||
|
||||
while (size) {
|
||||
r_len = (size > dec_len) ? dec_len : size;
|
||||
key_addr = (dec_addr >> 2)^key;
|
||||
doe(key_addr, buff, r_len, 0);
|
||||
buff += r_len;
|
||||
dec_addr += r_len;
|
||||
size -= r_len;
|
||||
}
|
||||
|
||||
return dec_addr;
|
||||
}
|
||||
|
||||
static u8 parse_seq = 0;
|
||||
static void ci_send_packet_new(u32 id, u8 *packet, int size)
|
||||
{
|
||||
#if APP_ONLINE_DEBUG
|
||||
app_online_db_ack(parse_seq, packet, size);
|
||||
#endif/*APP_ONLINE_DEBUG*/
|
||||
}
|
||||
|
||||
struct cfg_tool_event spp_packet;
|
||||
int cfg_tool_online_parse(u8 *buf, u32 len)
|
||||
{
|
||||
parse_seq = buf[2];
|
||||
u32 event = (buf[3] | (buf[4] << 8) | (buf[5] << 16) | (buf[6] << 24));
|
||||
spp_packet.event = event;
|
||||
spp_packet.packet = buf;
|
||||
spp_packet.size = len;
|
||||
return (app_cfg_tool_event_handler(&spp_packet));
|
||||
}
|
||||
|
||||
void all_assemble_package_send_to_pc(u8 id, u8 sq, u8 *buf, u32 len)
|
||||
{
|
||||
u8 *send_buf = NULL;
|
||||
u16 crc16_data;
|
||||
|
||||
send_buf = (u8 *)malloc(TEMP_BUF_SIZE);
|
||||
if (send_buf == NULL) {
|
||||
log_error("send_buf malloc err!");
|
||||
return;
|
||||
}
|
||||
|
||||
send_buf[0] = 0x5A;
|
||||
send_buf[1] = 0xAA;
|
||||
send_buf[2] = 0xA5;
|
||||
send_buf[5] = 2 + len;/*L*/
|
||||
send_buf[6] = id;/*T*/
|
||||
send_buf[7] = sq;/*SQ*/
|
||||
memcpy(send_buf + 8, buf, len);
|
||||
/*添加CRC16*/
|
||||
crc16_data = CRC16(&send_buf[5], len + 3);
|
||||
send_buf[3] = crc16_data & 0xff;
|
||||
send_buf[4] = (crc16_data >> 8) & 0xff;
|
||||
|
||||
/* printf_buf(send_buf, len + 8); */
|
||||
|
||||
#if (TCFG_CFG_TOOL_ENABLE || TCFG_ONLINE_ENABLE)
|
||||
#if (TCFG_COMM_TYPE == TCFG_SPP_COMM)
|
||||
ci_send_packet_new(INITIATIVE_STYLE, buf, len);
|
||||
#elif (TCFG_COMM_TYPE == TCFG_USB_COMM)
|
||||
cdc_write_data(0, send_buf, len + 8);
|
||||
#elif (TCFG_COMM_TYPE == TCFG_UART_COMM)
|
||||
ci_uart_write(send_buf, len + 8);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
free(send_buf);
|
||||
}
|
||||
|
||||
/*6个byte的校验码数组转为字符串*/
|
||||
void hex2text(u8 *buf, u8 *out)
|
||||
{
|
||||
sprintf(out, "%02x%02x-%02x%02x%02x%02x", buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
|
||||
}
|
||||
|
||||
u32 packet_combined(u8 *packet, u8 num)
|
||||
{
|
||||
u32 _packet = 0;
|
||||
_packet = (packet[num] | (packet[num + 1] << 8) | (packet[num + 2] << 16) | (packet[num + 3] << 24));
|
||||
return _packet;
|
||||
}
|
||||
|
||||
FILE *cfg_open_file(u32 file_id)
|
||||
{
|
||||
FILE *cfg_fp = NULL;
|
||||
if (file_id <= CFG_EQ_FILEID) {
|
||||
if ((file_id == CFG_TOOL_FILEID)) {
|
||||
cfg_fp = fopen(CFG_TOOL_FILE, "r");
|
||||
log_info("open cfg_tool.bin\n");
|
||||
} else if ((file_id == CFG_OLD_EQ_FILEID)) {
|
||||
cfg_fp = fopen(CFG_OLD_EQ_FILE, "r");
|
||||
log_info("open old eq_cfg_hw.bin\n");
|
||||
} else if ((file_id == CFG_OLD_EFFECT_FILEID)) {
|
||||
cfg_fp = fopen(CFG_OLD_EFFECT_FILE, "r");
|
||||
log_info("open effects_cfg.bin\n");
|
||||
} else if ((file_id == CFG_EQ_FILEID)) {
|
||||
cfg_fp = fopen(CFG_EQ_FILE, "r");
|
||||
log_info("open eq_cfg_hw.bin\n");
|
||||
}
|
||||
}
|
||||
return cfg_fp;
|
||||
}
|
||||
|
||||
extern void nvram_set_boot_state(u32 state);
|
||||
extern void hw_mmu_disable(void);
|
||||
extern void ram_protect_close(void);
|
||||
AT(.volatile_ram_code)
|
||||
void cfg_tool_go_mask_usb_updata()
|
||||
{
|
||||
local_irq_disable();
|
||||
ram_protect_close();
|
||||
hw_mmu_disable();
|
||||
nvram_set_boot_state(2);
|
||||
|
||||
JL_CLOCK->PWR_CON |= (1 << 4);
|
||||
/* chip_reset(); */
|
||||
/* cpu_reset(); */
|
||||
while (1);
|
||||
}
|
||||
|
||||
/*延时复位防止工具升级进度条显示错误*/
|
||||
static void delay_cpu_reset(void *priv)
|
||||
{
|
||||
extern void cpu_reset();
|
||||
cpu_reset();
|
||||
}
|
||||
|
||||
int app_cfg_tool_event_handler(struct cfg_tool_event *cfg_tool_dev)
|
||||
{
|
||||
u8 *buf = NULL;
|
||||
u8 *buf_temp = NULL;
|
||||
u8 *buf_temp_0 = NULL;
|
||||
u8 valid_cmd;
|
||||
u32 erase_cmd;
|
||||
int write_len;
|
||||
int send_len;
|
||||
u8 crc_temp_len, sdkname_temp_len;
|
||||
char proCrc_fw[32] = {0};
|
||||
char sdkName_fw[32] = {0};
|
||||
const struct tool_interface *p;
|
||||
struct vfs_attr attr;
|
||||
FILE *cfg_fp = NULL;
|
||||
|
||||
/* printf_buf(cfg_tool_dev->packet, cfg_tool_dev->size); */
|
||||
|
||||
buf = (u8 *)malloc(TEMP_BUF_SIZE);
|
||||
if (buf == NULL) {
|
||||
log_error("buf malloc err!");
|
||||
return 0;
|
||||
}
|
||||
buf_temp_0 = (u8 *)malloc(TEMP_BUF_SIZE);
|
||||
if (buf_temp_0 == NULL) {
|
||||
free(buf);
|
||||
log_error("buf_temp_0 malloc err!");
|
||||
return 0;
|
||||
}
|
||||
buf_temp_0 = (u8 *)ALIGN(buf_temp_0, 4);
|
||||
memset(buf_temp_0, 0, TEMP_BUF_SIZE);
|
||||
memcpy(buf_temp_0 + 1, cfg_tool_dev->packet, cfg_tool_dev->size);
|
||||
|
||||
/*数据进行处理*/
|
||||
list_for_each_tool_interface(p) {
|
||||
if (p->id == cfg_tool_dev->packet[1]) {
|
||||
p->tool_message_deal(buf_temp_0 + 2, cfg_tool_dev->size - 1);
|
||||
free(buf_temp_0);
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
memset(buf, 0, TEMP_BUF_SIZE);
|
||||
|
||||
switch (cfg_tool_dev->event) {
|
||||
case ONLINE_SUB_OP_QUERY_BASIC_INFO:
|
||||
valid_cmd = 1;
|
||||
/* log_info("event_ONLINE_SUB_OP_QUERY_BASIC_INFO\n"); */
|
||||
/*获取校验码*/
|
||||
u8 *p = sdfile_get_burn_code(&crc_temp_len);
|
||||
memcpy(info.s_basic_info.progCrc, p + 8, 6);
|
||||
/* printf_buf(info.s_basic_info.progCrc, 6); */
|
||||
hex2text(info.s_basic_info.progCrc, proCrc_fw);
|
||||
/* log_info("crc:%s\n", proCrc_fw); */
|
||||
|
||||
/*获取固件版本信息*/
|
||||
sdkname_temp_len = strlen(sdk_version_info_get());
|
||||
memcpy(info.s_basic_info.sdkName, sdk_version_info_get(), sdkname_temp_len);
|
||||
memcpy(sdkName_fw, info.s_basic_info.sdkName, sdkname_temp_len);
|
||||
/* log_info("version:%s\n", sdk_version_info_get()); */
|
||||
|
||||
struct flash_head flash_head_for_pid_vid;
|
||||
|
||||
for (u8 i = 0; i < 5; i++) {
|
||||
norflash_read(NULL, (u8 *)&flash_head_for_pid_vid, 32, 0x1000 * i);
|
||||
doe(0xffff, (u8 *)&flash_head_for_pid_vid, 32, 0);
|
||||
if (flash_head_for_pid_vid.crc == 0xffff) {
|
||||
continue;
|
||||
} else {
|
||||
log_info("flash head addr = 0x%x\n", 0x1000 * i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct flash_head _head;
|
||||
struct flash_head *temp_p = &_head;
|
||||
memcpy(temp_p, &flash_head_for_pid_vid, 32);
|
||||
|
||||
memset(info.s_basic_info.pid, 0, sizeof(info.s_basic_info.pid));
|
||||
memcpy(info.s_basic_info.pid, temp_p->pid, sizeof(info.s_basic_info.pid));
|
||||
for (u8 i = 0; i < sizeof(info.s_basic_info.pid); i++) {
|
||||
if (~info.s_basic_info.pid[i] == 0x00) {
|
||||
info.s_basic_info.pid[i] = 0x00;
|
||||
}
|
||||
}
|
||||
/* printf_buf(info.s_basic_info.pid, 16); */
|
||||
|
||||
memset(info.s_basic_info.vid, 0, sizeof(info.s_basic_info.vid));
|
||||
memcpy(info.s_basic_info.vid, temp_p->vid, 4);
|
||||
/* printf_buf(info.s_basic_info.vid, 16); */
|
||||
|
||||
send_len = sizeof(info.s_basic_info.protocolVer) + sizeof(proCrc_fw) + sizeof(sdkName_fw) + 32;
|
||||
buf[0] = info.s_basic_info.protocolVer & 0xff;
|
||||
buf[1] = (info.s_basic_info.protocolVer >> 8) & 0xff;
|
||||
memcpy(buf + 2, proCrc_fw, sizeof(proCrc_fw));
|
||||
memcpy(buf + 2 + sizeof(proCrc_fw), sdkName_fw, sizeof(sdkName_fw));
|
||||
memcpy(buf + 2 + sizeof(proCrc_fw) + sizeof(sdkName_fw), info.s_basic_info.pid, 16);
|
||||
memcpy(buf + 2 + sizeof(proCrc_fw) + sizeof(sdkName_fw) + 16, info.s_basic_info.vid, 16);
|
||||
break;
|
||||
case ONLINE_SUB_OP_QUERY_FILE_SIZE:
|
||||
valid_cmd = 1;
|
||||
/* log_info("event_ONLINE_SUB_OP_QUERY_FILE_SIZE\n"); */
|
||||
info.r_file_size.file_id = packet_combined(cfg_tool_dev->packet, 7);
|
||||
cfg_fp = cfg_open_file(info.r_file_size.file_id);
|
||||
|
||||
if (cfg_fp == NULL) {
|
||||
log_error("file open error!\n");
|
||||
goto _exit_;
|
||||
}
|
||||
fget_attrs(cfg_fp, &attr);
|
||||
|
||||
/* log_info("file addr:%x,file size:%d\n", attr.sclust, attr.fsize); */
|
||||
info.s_file_size.file_size = attr.fsize;
|
||||
|
||||
send_len = sizeof(info.s_file_size.file_size);//长度
|
||||
|
||||
/*小端格式*/
|
||||
buf[3] = (info.s_file_size.file_size >> 24) & 0xff;
|
||||
buf[2] = (info.s_file_size.file_size >> 16) & 0xff;
|
||||
buf[1] = (info.s_file_size.file_size >> 8) & 0xff;
|
||||
buf[0] = info.s_file_size.file_size & 0xff;
|
||||
|
||||
fclose(cfg_fp);
|
||||
break;
|
||||
case ONLINE_SUB_OP_QUERY_FILE_CONTENT:
|
||||
valid_cmd = 1;
|
||||
/* log_info("event_ONLINE_SUB_OP_QUERY_FILE_CONTENT\n"); */
|
||||
info.r_file_content.file_id = packet_combined(cfg_tool_dev->packet, 7);
|
||||
info.r_file_content.offset = packet_combined(cfg_tool_dev->packet, 11);
|
||||
info.r_file_content.size = packet_combined(cfg_tool_dev->packet, 15);
|
||||
|
||||
cfg_fp = cfg_open_file(info.r_file_content.file_id);
|
||||
|
||||
if (cfg_fp == NULL) {
|
||||
log_error("file open error!\n");
|
||||
goto _exit_;
|
||||
}
|
||||
fget_attrs(cfg_fp, &attr);
|
||||
|
||||
/* log_info("file addr:%x,file size:%d\n", attr.sclust, attr.fsize); */
|
||||
if (info.r_file_content.size > attr.fsize) {
|
||||
fclose(cfg_fp);
|
||||
log_error("reading size more than actual size!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/*逻辑地址转换成flash物理地址*/
|
||||
u32 flash_addr = sdfile_cpu_addr2flash_addr(attr.sclust);
|
||||
/* log_info("flash_addr:0x%x", flash_addr); */
|
||||
/*读取文件内容*/
|
||||
buf_temp = (char *)malloc(info.r_file_content.size);
|
||||
norflash_read(NULL, (void *)buf_temp, info.r_file_content.size, flash_addr + info.r_file_content.offset);
|
||||
/* printf_buf(buf_temp, info.r_file_content.size); */
|
||||
send_len = info.r_file_content.size;
|
||||
memcpy(buf, buf_temp, info.r_file_content.size);
|
||||
|
||||
if (buf_temp) {
|
||||
free(buf_temp);
|
||||
}
|
||||
fclose(cfg_fp);
|
||||
break;
|
||||
case ONLINE_SUB_OP_PREPARE_WRITE_FILE:
|
||||
valid_cmd = 1;
|
||||
/* log_info("event_ONLINE_SUB_OP_PREPARE_WRITE_FILE\n"); */
|
||||
info.r_prepare_write_file.file_id = packet_combined(cfg_tool_dev->packet, 7);
|
||||
info.r_prepare_write_file.size = packet_combined(cfg_tool_dev->packet, 11);
|
||||
|
||||
cfg_fp = cfg_open_file(info.r_prepare_write_file.file_id);
|
||||
if (cfg_fp == NULL) {
|
||||
log_error("file open error!\n");
|
||||
break;
|
||||
}
|
||||
fget_attrs(cfg_fp, &attr);
|
||||
|
||||
/* log_info("file addr:%x,file size:%d\n", attr.sclust, attr.fsize); */
|
||||
if (info.r_prepare_write_file.size > attr.fsize) {
|
||||
//fclose(cfg_fp);
|
||||
//log_error("preparing to write size more than actual size!\n");
|
||||
//break;
|
||||
}
|
||||
|
||||
info.s_prepare_write_file.file_size = attr.fsize;
|
||||
info.s_prepare_write_file.file_addr = sdfile_cpu_addr2flash_addr(attr.sclust);
|
||||
info.s_prepare_write_file.earse_unit = boot_info.vm.align * 256;
|
||||
|
||||
send_len = sizeof(info.s_prepare_write_file.file_size) * 3;
|
||||
|
||||
buf[3] = (info.s_prepare_write_file.file_addr >> 24) & 0xff;
|
||||
buf[2] = (info.s_prepare_write_file.file_addr >> 16) & 0xff;
|
||||
buf[1] = (info.s_prepare_write_file.file_addr >> 8) & 0xff;
|
||||
buf[0] = info.s_prepare_write_file.file_addr & 0xff;
|
||||
|
||||
buf[7] = (info.s_prepare_write_file.file_size >> 24) & 0xff;
|
||||
buf[6] = (info.s_prepare_write_file.file_size >> 16) & 0xff;
|
||||
buf[5] = (info.s_prepare_write_file.file_size >> 8) & 0xff;
|
||||
buf[4] = info.s_prepare_write_file.file_size & 0xff;
|
||||
|
||||
buf[11] = (info.s_prepare_write_file.earse_unit >> 24) & 0xff;
|
||||
buf[10] = (info.s_prepare_write_file.earse_unit >> 16) & 0xff;
|
||||
buf[9] = (info.s_prepare_write_file.earse_unit >> 8) & 0xff;
|
||||
buf[8] = info.s_prepare_write_file.earse_unit & 0xff;
|
||||
|
||||
fclose(cfg_fp);
|
||||
break;
|
||||
case ONLINE_SUB_OP_READ_ADDR_RANGE:
|
||||
valid_cmd = 1;
|
||||
/* log_info("event_ONLINE_SUB_OP_READ_ADDR_RANGE\n"); */
|
||||
info.r_read_addr_range.addr = packet_combined(cfg_tool_dev->packet, 7);
|
||||
/* log_info("reading flash addr:0x%x\n", info.r_read_addr_range.addr); */
|
||||
info.r_read_addr_range.size = packet_combined(cfg_tool_dev->packet, 11);
|
||||
/* log_info("reading size = %d\n", info.r_read_addr_range.size); */
|
||||
buf_temp = (char *)malloc(info.r_read_addr_range.size);
|
||||
norflash_read(NULL, (void *)buf_temp, info.r_read_addr_range.size, info.r_read_addr_range.addr);
|
||||
/* printf_buf(buf_temp, info.r_read_addr_range.size); */
|
||||
|
||||
send_len = info.r_read_addr_range.size;
|
||||
memcpy(buf, buf_temp, info.r_read_addr_range.size);
|
||||
|
||||
if (buf_temp) {
|
||||
free(buf_temp);
|
||||
}
|
||||
break;
|
||||
case ONLINE_SUB_OP_ERASE_ADDR_RANGE:
|
||||
valid_cmd = 1;
|
||||
/* log_info("event_ONLINE_SUB_OP_ERASE_ADDR_RANGE\n"); */
|
||||
info.r_erase_addr_range.addr = packet_combined(cfg_tool_dev->packet, 7);
|
||||
/* log_info("erasing flash start addr:0x%x\n", info.r_erase_addr_range.addr); */
|
||||
/*要擦除的大小,会保证按earse_unit对齐,即总是erase_unit的倍数*/
|
||||
info.r_erase_addr_range.size = packet_combined(cfg_tool_dev->packet, 11);
|
||||
/* log_info("erasing size = %d\n", info.r_erase_addr_range.size); */
|
||||
/* log_info("earse_unit = %d\n", info.s_prepare_write_file.earse_unit); */
|
||||
switch (info.s_prepare_write_file.earse_unit) {
|
||||
case 256:
|
||||
erase_cmd = IOCTL_ERASE_PAGE;
|
||||
break;
|
||||
case (4*1024):
|
||||
erase_cmd = IOCTL_ERASE_SECTOR;
|
||||
break;
|
||||
case (64*1024):
|
||||
erase_cmd = IOCTL_ERASE_BLOCK;
|
||||
break;
|
||||
defualt:
|
||||
memcpy(buf, error_return, sizeof(error_return));
|
||||
log_error("erase error!");
|
||||
break;
|
||||
}
|
||||
|
||||
for (u8 i = 0; i < (info.r_erase_addr_range.size / info.s_prepare_write_file.earse_unit); i ++) {
|
||||
u8 ret = norflash_erase(erase_cmd, info.r_erase_addr_range.addr + (i * info.s_prepare_write_file.earse_unit));
|
||||
if (ret) {
|
||||
memcpy(buf, error_return, sizeof(error_return));
|
||||
log_error("erase error!");
|
||||
} else {
|
||||
memcpy(buf, ok_return, sizeof(ok_return));
|
||||
log_info("erase success");
|
||||
}
|
||||
}
|
||||
|
||||
send_len = sizeof(error_return);
|
||||
break;
|
||||
case ONLINE_SUB_OP_WRITE_ADDR_RANGE:
|
||||
valid_cmd = 1;
|
||||
/* log_info("event_ONLINE_SUB_OP_WRITE_ADDR_RANGE\n"); */
|
||||
info.r_write_addr_range.addr = packet_combined(cfg_tool_dev->packet, 7);
|
||||
info.r_write_addr_range.size = packet_combined(cfg_tool_dev->packet, 11);
|
||||
/* log_info("writing flash start addr:0x%x\n", info.r_write_addr_range.addr); */
|
||||
/* log_info("writing size = %d\n", info.r_write_addr_range.size); */
|
||||
buf_temp = (char *)malloc(info.r_write_addr_range.size);
|
||||
memcpy(buf_temp, cfg_tool_dev->packet + 15, info.r_write_addr_range.size);
|
||||
/* printf_buf(buf_temp, info.r_write_addr_range.size); */
|
||||
|
||||
cfg_tool_encode_data_by_user_key(boot_info.chip_id, buf_temp, info.r_write_addr_range.size, info.r_write_addr_range.addr - boot_info.sfc.sfc_base_addr, 0x20);
|
||||
|
||||
write_len = norflash_write(NULL, buf_temp, info.r_write_addr_range.size, info.r_write_addr_range.addr);
|
||||
|
||||
/* norflash_read(NULL, buf_temp, info.r_write_addr_range.size, info.r_write_addr_range.addr); */
|
||||
/* printf_buf(buf_temp, info.r_write_addr_range.size); */
|
||||
|
||||
if (write_len != info.r_write_addr_range.size) {
|
||||
memcpy(buf, error_return, sizeof(error_return));
|
||||
log_error("write error!");
|
||||
} else {
|
||||
memcpy(buf, ok_return, sizeof(ok_return));
|
||||
}
|
||||
send_len = sizeof(error_return);
|
||||
|
||||
if (buf_temp) {
|
||||
free(buf_temp);
|
||||
}
|
||||
|
||||
if (info.r_prepare_write_file.file_id == CFG_TOOL_FILEID) {
|
||||
size_total_write += info.r_write_addr_range.size;
|
||||
/* log_info("size_total_write = %d\n", size_total_write); */
|
||||
/* log_info("erasing size = %d\n", info.r_erase_addr_range.size); */
|
||||
if (size_total_write >= info.r_erase_addr_range.size) {
|
||||
size_total_write = 0;
|
||||
log_info("cpu_reset\n");
|
||||
extern u16 sys_timeout_add(void *priv, void (*func)(void *priv), u32 msec);
|
||||
sys_timeout_add(NULL, delay_cpu_reset, 500);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ONLINE_SUB_OP_ENTER_UPGRADE_MODE:
|
||||
valid_cmd = 1;
|
||||
log_info("event_ONLINE_SUB_OP_ENTER_UPGRADE_MODE\n");
|
||||
cfg_tool_go_mask_usb_updata();
|
||||
break;
|
||||
default:
|
||||
valid_cmd = 0;
|
||||
log_error("invalid data\n");
|
||||
memcpy(buf, er_return, sizeof(er_return));//不认识的命令返回ER
|
||||
send_len = sizeof(er_return);
|
||||
break;
|
||||
_exit_:
|
||||
memcpy(buf, error_return, sizeof(error_return));//文件打开失败返回FA
|
||||
send_len = sizeof(error_return);
|
||||
break;
|
||||
}
|
||||
|
||||
all_assemble_package_send_to_pc(REPLY_STYLE, cfg_tool_dev->packet[2], buf, send_len);
|
||||
|
||||
free(buf_temp_0);
|
||||
free(buf);
|
||||
return (valid_cmd);
|
||||
}
|
||||
|
||||
void cfg_tool_event_to_user(u8 *packet, u32 type, u8 event, u8 size)
|
||||
{
|
||||
struct sys_event e;
|
||||
e.type = SYS_DEVICE_EVENT;
|
||||
if (packet != NULL) {
|
||||
if (size > sizeof(local_packet)) {
|
||||
return;
|
||||
}
|
||||
e.u.cfg_tool.packet = local_packet;
|
||||
memcpy(e.u.cfg_tool.packet, packet, size);
|
||||
}
|
||||
e.arg = (void *)type;
|
||||
e.u.cfg_tool.event = event;
|
||||
e.u.cfg_tool.size = size;
|
||||
sys_event_notify(&e);
|
||||
}
|
||||
|
||||
void app_cfg_tool_message_deal(u8 *buf, u32 len)
|
||||
{
|
||||
u8 cmd = buf[8];
|
||||
switch (cmd) {
|
||||
case ONLINE_SUB_OP_QUERY_BASIC_INFO:
|
||||
case ONLINE_SUB_OP_QUERY_FILE_SIZE:
|
||||
case ONLINE_SUB_OP_QUERY_FILE_CONTENT:
|
||||
case ONLINE_SUB_OP_PREPARE_WRITE_FILE:
|
||||
case ONLINE_SUB_OP_READ_ADDR_RANGE:
|
||||
case ONLINE_SUB_OP_ERASE_ADDR_RANGE:
|
||||
case ONLINE_SUB_OP_WRITE_ADDR_RANGE:
|
||||
case ONLINE_SUB_OP_ENTER_UPGRADE_MODE:
|
||||
cfg_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_CFG_TOOL, cmd, buf[5] + 1);
|
||||
break;
|
||||
default:
|
||||
cfg_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_CFG_TOOL, DEFAULT_ACTION, buf[5] + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void online_cfg_tool_data_deal(void *buf, u32 len)
|
||||
{
|
||||
u8 *data_buf = buf;
|
||||
u16 crc16_data;
|
||||
|
||||
/* printf_buf(buf, len); */
|
||||
|
||||
/*DATA前的固定字节包括 (5A AA A5 CRC L T SQ)共8个字节 */
|
||||
if (len < 8) {
|
||||
log_error("Data length is too short, receive an invalid message!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((data_buf[0] != 0x5a) || (data_buf[1] != 0xaa) || (data_buf[2] != 0xa5)) {
|
||||
log_error("Header check error, receive an invalid message!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*CRC16校验,CRC16校验码位于数据包的buf[3]和buf[4]*/
|
||||
crc16_data = (data_buf[4] << 8) | data_buf[3];
|
||||
if (crc16_data != CRC16(data_buf + 5, len - 5)) {
|
||||
log_error("CRC16 check error, receive an invalid message!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
app_cfg_tool_message_deal(buf, len);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "app_config.h"
|
||||
#include "typedef.h"
|
||||
|
||||
|
||||
|
||||
#ifndef CONFIG_DEBUG_ENABLE
|
||||
|
||||
int putchar(int a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
int puts(const char *out)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int printf(const char *format, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void put_buf(const u8 *buf, int len)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void put_u8hex(u8 dat)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void put_u16hex(u16 dat)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void put_u32hex(u32 dat)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void log_print(int level, const char *tag, const char *format, ...)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DEBUG_LITE_ENABLE
|
||||
void log_putbyte(char c)
|
||||
{
|
||||
|
||||
}
|
||||
#endif /* #ifndef CONFIG_DEBUG_LITE_ENABLE */
|
||||
|
||||
int assert_printf(const char *format, ...)
|
||||
{
|
||||
cpu_assert_debug();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,68 @@
|
||||
#include "app_config.h"
|
||||
#include "typedef.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_LITE_ENABLE
|
||||
|
||||
extern void putbyte(char a);
|
||||
|
||||
#define putbyte_lite putbyte
|
||||
|
||||
void log_putbyte(char c)
|
||||
{
|
||||
putbyte_lite(c);
|
||||
}
|
||||
|
||||
void puts_lite(const char *out)
|
||||
{
|
||||
while (*out != '\0') {
|
||||
putbyte_lite(*out);
|
||||
out++;
|
||||
}
|
||||
}
|
||||
|
||||
int printf_lite(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
return print(NULL, 0, format, args);
|
||||
}
|
||||
|
||||
void put_buf_lite(void *_buf, u32 len)
|
||||
{
|
||||
u8 *buf = (u8 *)_buf;
|
||||
printf_lite("\n0x%x\n", buf);
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (((i % 16) == 0) && (i != 0)) {
|
||||
putbyte_lite('\n');
|
||||
}
|
||||
printf_lite("%x", buf[i]);
|
||||
putbyte_lite(' ');
|
||||
}
|
||||
putbyte_lite('\n');
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
void puts_lite(const char *out)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void put_buf_lite(void *_buf, u32 len)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
int printf_lite(const char *format, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* #ifdef CONFIG_DEBUG_LITE_ENABLE */
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,93 @@
|
||||
#ifndef __DEV_MANAGER_H__
|
||||
#define __DEV_MANAGER_H__
|
||||
|
||||
#include "system/includes.h"
|
||||
#include "typedef.h"
|
||||
#include "system/fs/fs.h"
|
||||
|
||||
enum {
|
||||
DEV_MANAGER_ADD_OK = 0x0,
|
||||
DEV_MANAGER_ADD_IN_LIST_AREADY,
|
||||
DEV_MANAGER_ADD_ERR_PARM,
|
||||
DEV_MANAGER_ADD_ERR_NOMEM,
|
||||
DEV_MANAGER_ADD_ERR_NOT_FOUND,
|
||||
DEV_MANAGER_ADD_ERR_MOUNT_FAIL,
|
||||
};
|
||||
|
||||
|
||||
struct __dev;
|
||||
|
||||
struct __scan_callback {
|
||||
void (*enter)(struct __dev *dev);
|
||||
void (*exit)(struct __dev *dev);
|
||||
int (*scan_break)(void);
|
||||
};
|
||||
|
||||
//dev_manager增加设备节点
|
||||
int dev_manager_add(char *logo);
|
||||
//dev_manager删除设备节点
|
||||
int dev_manager_del(char *logo);
|
||||
//dev_manager获取设备总数
|
||||
u32 dev_manager_get_total(u8 valid);
|
||||
//dev_manager通过设备节点检查设备是否在设备链表中
|
||||
struct __dev *dev_manager_check(struct __dev *dev);
|
||||
//dev_manager通过逻辑盘符检查设备是否在设备链表中
|
||||
struct __dev *dev_manager_check_by_logo(char *logo);
|
||||
//dev_manager查找第一个设备
|
||||
struct __dev *dev_manager_find_first(u8 valid);
|
||||
//dev_manager查找最后一个设备
|
||||
struct __dev *dev_manager_find_last(u8 valid);
|
||||
//dev_manager查找参数设备的前一个设备
|
||||
struct __dev *dev_manager_find_prev(struct __dev *dev, u8 valid);
|
||||
//dev_manager查找参数设备的后一个设备
|
||||
struct __dev *dev_manager_find_next(struct __dev *dev, u8 valid);
|
||||
//dev_manager查找最后活动设备
|
||||
struct __dev *dev_manager_find_active(u8 valid);
|
||||
//dev_manager查找指定逻辑盘符对应的设备
|
||||
struct __dev *dev_manager_find_spec(char *logo, u8 valid);
|
||||
//dev_manager查找指定序号设备
|
||||
struct __dev *dev_manager_find_by_index(u32 index, u8 valid);
|
||||
//dev_manager扫盘句柄释放
|
||||
void dev_manager_scan_disk_release(struct vfscan *fsn);
|
||||
//dev_manager扫盘
|
||||
struct vfscan *dev_manager_scan_disk(struct __dev *dev, const char *path, const char *parm, u8 cycle_mode, struct __scan_callback *callback);
|
||||
//dev_manager设定指定设备节点设备有效
|
||||
void dev_manager_set_valid(struct __dev *dev, u8 flag);
|
||||
//dev_manager设定指定设备节点设备为最后活动设备
|
||||
void dev_manager_set_active(struct __dev *dev);
|
||||
//dev_manager设定指定逻辑盘符的设备有效
|
||||
void dev_manager_set_valid_by_logo(char *logo, u8 flag);
|
||||
//dev_manager设定指定逻辑盘符的设备为最后活动设备
|
||||
void dev_manager_set_active_by_logo(char *logo);
|
||||
//dev_manager获取指定设备节点的逻辑盘符
|
||||
char *dev_manager_get_logo(struct __dev *dev);
|
||||
//获取物理设备节点的逻辑盘符(去掉_rec后缀)
|
||||
char *dev_manager_get_phy_logo(struct __dev *dev);
|
||||
//获取录音文件夹设备节点的逻辑盘符(追加_rec后缀)
|
||||
char *dev_manager_get_rec_logo(struct __dev *dev);
|
||||
//dev_manager获取指定设备节点的文件系统根目录
|
||||
char *dev_manager_get_root_path(struct __dev *dev);
|
||||
//dev_manager获取指定逻辑盘符的设备的文件系统根目录
|
||||
char *dev_manager_get_root_path_by_logo(char *logo);
|
||||
//dev_manager通过设备节点获取设备mount信息
|
||||
struct imount *dev_manager_get_mount_hdl(struct __dev *dev);
|
||||
//dev_manager通过设备节点检查设备是否在线
|
||||
int dev_manager_online_check(struct __dev *dev, u8 valid);
|
||||
//dev_manager通过逻辑盘符检查设备是否在线
|
||||
int dev_manager_online_check_by_logo(char *logo, u8 valid);
|
||||
//通过逻辑盘符判断设备是否在设备链表中
|
||||
struct __dev *dev_manager_list_check_by_logo(char *logo);
|
||||
//检查链表中没有挂载的设备并重新挂载
|
||||
void dev_manager_list_check_mount(void);
|
||||
//设备挂载
|
||||
int dev_manager_mount(char *logo);
|
||||
//设备卸载
|
||||
int dev_manager_unmount(char *logo);
|
||||
|
||||
//dev_manager初始化
|
||||
void dev_manager_init(void);
|
||||
|
||||
void dev_manager_var_init();
|
||||
|
||||
#endif//__DEV_MANAGER_H__
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "dev_reg.h"
|
||||
#include "app_config.h"
|
||||
|
||||
//*----------------------------------------------------------------------------*/
|
||||
/**@brief 设备配置表
|
||||
@param 具体配置项请看struct __dev_reg结构体描述
|
||||
@return
|
||||
@note 注意:
|
||||
例如logo逻辑盘符sd0_rec/sd1_rec/udisk_rec是做录音文件夹区分使用的,
|
||||
在定义新的设备逻辑盘发的时候, 注意避开"_rec"后缀作为设备逻辑盘符
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
const struct __dev_reg dev_reg[] = {
|
||||
#if SDFILE_STORAGE && TCFG_CODE_FLASH_ENABLE
|
||||
//内置flash
|
||||
{
|
||||
/*logo*/ SDFILE_DEV,
|
||||
/*name*/ NULL,
|
||||
/*storage_path*/ SDFILE_MOUNT_PATH,
|
||||
/*root_path*/ SDFILE_RES_ROOT_PATH,
|
||||
/*fs_type*/ "sdfile",
|
||||
},
|
||||
#endif
|
||||
#if FLASH_INSIDE_REC_ENABLE
|
||||
//内置录音
|
||||
{
|
||||
/*logo*/ "rec_sdfile",
|
||||
/*name*/ NULL,
|
||||
/*storage_path*/ "mnt/rec_sdfile",
|
||||
/*root_path*/ "mnt/rec_sdfile/C/",
|
||||
/*fs_type*/ "rec_sdfile",
|
||||
},
|
||||
#endif
|
||||
#if (TCFG_SD0_ENABLE)
|
||||
//sd0
|
||||
{
|
||||
/*logo*/ "sd0",
|
||||
/*name*/ "sd0",
|
||||
/*storage_path*/ "storage/sd0",
|
||||
/*root_path*/ "storage/sd0/C/",
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
#if (TCFG_SD1_ENABLE)
|
||||
//sd1
|
||||
{
|
||||
/*logo*/ "sd1",
|
||||
/*name*/ "sd1",
|
||||
/*storage_path*/ "storage/sd1",
|
||||
/*root_path*/ "storage/sd1/C/",
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
#if (TCFG_UDISK_ENABLE)
|
||||
//u盘
|
||||
{
|
||||
/*logo*/ "udisk0",
|
||||
/*name*/ "udisk0",
|
||||
/*storage_path*/ "storage/udisk0",
|
||||
/*root_path*/ "storage/udisk0/C/",
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
#if (TCFG_SD0_ENABLE && TCFG_RECORD_FOLDER_DEV_ENABLE)
|
||||
//sd0录音文件夹分区
|
||||
{
|
||||
/*logo*/ "sd0_rec",
|
||||
/*name*/ "sd0",
|
||||
/*storage_path*/ "storage/sd0",
|
||||
/*root_path*/ "storage/sd0/C/"REC_FOLDER_NAME,
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
#if (TCFG_SD1_ENABLE && TCFG_RECORD_FOLDER_DEV_ENABLE)
|
||||
//sd1录音文件夹分区
|
||||
{
|
||||
/*logo*/ "sd1_rec",
|
||||
/*name*/ "sd1",
|
||||
/*storage_path*/ "storage/sd1",
|
||||
/*root_path*/ "storage/sd1/C/"REC_FOLDER_NAME,
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
#if (TCFG_UDISK_ENABLE && TCFG_RECORD_FOLDER_DEV_ENABLE)
|
||||
//u盘录音文件夹分区
|
||||
{
|
||||
/*logo*/ "udisk0_rec",
|
||||
/*name*/ "udisk0",
|
||||
/*storage_path*/ "storage/udisk0",
|
||||
/*root_path*/ "storage/udisk0/C/"REC_FOLDER_NAME,
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
#if TCFG_NOR_FAT
|
||||
//外挂fat分区
|
||||
{
|
||||
/*logo*/ "fat_nor",
|
||||
/*name*/ "fat_nor",
|
||||
/*storage_path*/ "storage/fat_nor",
|
||||
/*root_path*/ "storage/fat_nor/C/",
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
#if TCFG_NOR_FS
|
||||
//外挂flash资源分区
|
||||
{
|
||||
/*logo*/ "res_nor",
|
||||
/*name*/ "res_nor",
|
||||
/*storage_path*/ "storage/res_nor",
|
||||
/*root_path*/ "storage/res_nor/C/",
|
||||
/*fs_type*/ "nor_sdfile",
|
||||
},
|
||||
#endif
|
||||
#if TCFG_NOR_REC
|
||||
///外挂录音分区
|
||||
{
|
||||
/*logo*/ "rec_nor",
|
||||
/*name*/ "rec_nor",
|
||||
/*storage_path*/ "storage/rec_nor",
|
||||
/*root_path*/ "storage/rec_nor/C/",
|
||||
/*fs_type*/ "rec_fs",
|
||||
},
|
||||
#endif
|
||||
{
|
||||
/*logo*/ "nor_ui",
|
||||
/*name*/ "nor_ui",
|
||||
/*storage_path*/ "storage/nor_ui",
|
||||
/*root_path*/ "storage/nor_ui/C/",
|
||||
/*fs_type*/ "nor_sdfile",
|
||||
},
|
||||
#if TCFG_VIR_UDISK_ENABLE
|
||||
// 虚拟U盘
|
||||
{
|
||||
/*logo*/ "vir_udisk0",
|
||||
/*name*/ "vir_udisk0",
|
||||
/*storage_path*/ "storage/vir_udisk0",
|
||||
/*root_path*/ "storage/vir_udisk0/C/",
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
#if TCFG_VIRFAT_FLASH_ENABLE
|
||||
//flash 虚拟fat
|
||||
{
|
||||
/*logo*/ "virfat_flash",
|
||||
/*name*/ "virfat_flash",
|
||||
/*storage_path*/ "storage/virfat_flash",
|
||||
/*root_path*/ "storage/virfat_flash/C/",
|
||||
/*fs_type*/ "sdfile_fat",
|
||||
},
|
||||
#endif
|
||||
#if TCFG_NANDFLASH_DEV_ENABLE
|
||||
{
|
||||
/*logo*/ "nandflash_ftl",
|
||||
/*name*/ "nandflash_ftl",
|
||||
/*storage_path*/ "storage/nandflash_ftl",
|
||||
/*root_path*/ "storage/nandflash_ftl/C/",
|
||||
/*fs_type*/ "fat",
|
||||
},
|
||||
#endif
|
||||
//<新加设备参数请在reg end前添加!!
|
||||
//<reg end
|
||||
{
|
||||
/*logo*/ NULL,
|
||||
/*name*/ NULL,
|
||||
/*storage_path*/ NULL,
|
||||
/*root_path*/ NULL,
|
||||
/*fs_type*/ NULL,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef __DEV_REG_H__
|
||||
#define __DEV_REG_H__
|
||||
|
||||
#include "system/includes.h"
|
||||
#include "typedef.h"
|
||||
|
||||
///设备参数控制句柄
|
||||
struct __dev_reg {
|
||||
char *logo;//设备选择使用的逻辑盘符
|
||||
char *name;//设备名称,底层匹配设备节点使用
|
||||
char *storage_path;//设备路径,文件系统mount时使用
|
||||
char *root_path;//设备文件系统根目录
|
||||
char *fs_type;//文件系统类型,如:fat, sdfile
|
||||
};
|
||||
|
||||
|
||||
extern const struct __dev_reg dev_reg[];
|
||||
|
||||
#endif//__DEV_REG_H__
|
||||
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
#include "dev_update.h"
|
||||
#include "dev_manager.h"
|
||||
#include "update/update.h"
|
||||
#include "update/update_loader_download.h"
|
||||
#include "app_config.h"
|
||||
#include "btcontroller_modules.h"
|
||||
|
||||
#if defined(CONFIG_SD_UPDATE_ENABLE) || defined(CONFIG_USB_UPDATE_ENABLE)
|
||||
#define DEV_UPDATE_EN 1
|
||||
#else
|
||||
#define DEV_UPDATE_EN 0
|
||||
#endif
|
||||
|
||||
#ifdef DEV_UPDATE_SUPPORT_JUMP
|
||||
extern void __JUMP_TO_MASKROM();
|
||||
extern void save_spi_port();
|
||||
extern void update_close_hw(void *filter_name);
|
||||
extern void ram_protect_close(void);
|
||||
#endif //endif DEV_UPDATE_SUPPORT_JUMP
|
||||
|
||||
extern bool uart_update_send_update_ready(char *file_path);
|
||||
extern bool get_uart_update_sta(void);
|
||||
|
||||
static char update_path[48] = {0};
|
||||
extern const char updata_file_name[];
|
||||
|
||||
struct __update_dev_reg {
|
||||
char *logo;
|
||||
int type;
|
||||
union {
|
||||
UPDATA_SD sd;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
||||
#if TCFG_SD0_ENABLE
|
||||
static const struct __update_dev_reg sd0_update = {
|
||||
.logo = "sd0",
|
||||
.type = SD0_UPDATA,
|
||||
.u.sd.control_type = SD_CONTROLLER_0,
|
||||
#ifdef TCFG_SD0_PORT_CMD
|
||||
.u.sd.control_io_clk = TCFG_SD0_PORT_CLK,
|
||||
.u.sd.control_io_cmd = TCFG_SD0_PORT_CMD,
|
||||
.u.sd.control_io_dat = TCFG_SD0_PORT_DA0,
|
||||
#else
|
||||
#if (TCFG_SD0_PORTS=='A')
|
||||
.u.sd.control_io = SD0_IO_A,
|
||||
#elif (TCFG_SD0_PORTS=='B')
|
||||
.u.sd.control_io = SD0_IO_B,
|
||||
#elif (TCFG_SD0_PORTS=='C')
|
||||
.u.sd.control_io = SD0_IO_C,
|
||||
#elif (TCFG_SD0_PORTS=='D')
|
||||
.u.sd.control_io = SD0_IO_D,
|
||||
#elif (TCFG_SD0_PORTS=='E')
|
||||
.u.sd.control_io = SD0_IO_E,
|
||||
#elif (TCFG_SD0_PORTS=='F')
|
||||
.u.sd.control_io = SD0_IO_F,
|
||||
#endif
|
||||
#endif
|
||||
.u.sd.power = 1,
|
||||
};
|
||||
#endif//TCFG_SD0_ENABLE
|
||||
|
||||
#if TCFG_SD1_ENABLE
|
||||
static const struct __update_dev_reg sd1_update = {
|
||||
.logo = "sd1",
|
||||
.type = SD1_UPDATA,
|
||||
.u.sd.control_type = SD_CONTROLLER_1,
|
||||
#if (TCFG_SD1_PORTS=='A')
|
||||
.u.sd.control_io = SD1_IO_A,
|
||||
#else
|
||||
.u.sd.control_io = SD1_IO_B,
|
||||
#endif
|
||||
.u.sd.power = 1,
|
||||
|
||||
};
|
||||
#endif//TCFG_SD1_ENABLE
|
||||
|
||||
#if TCFG_UDISK_ENABLE
|
||||
static const struct __update_dev_reg udisk_update = {
|
||||
.logo = "udisk0",
|
||||
.type = USB_UPDATA,
|
||||
};
|
||||
#endif//TCFG_UDISK_ENABLE
|
||||
|
||||
|
||||
static const struct __update_dev_reg *update_dev_list[] = {
|
||||
#if TCFG_UDISK_ENABLE
|
||||
&udisk_update,
|
||||
#endif//TCFG_UDISK_ENABLE
|
||||
#if TCFG_SD0_ENABLE
|
||||
&sd0_update,
|
||||
#endif//
|
||||
#if TCFG_SD1_ENABLE
|
||||
&sd1_update,
|
||||
#endif//TCFG_SD1_ENABLE
|
||||
};
|
||||
|
||||
void *dev_update_get_parm(int type)
|
||||
{
|
||||
struct __update_dev_reg *parm = NULL;
|
||||
for (int i = 0; i < ARRAY_SIZE(update_dev_list); i++) {
|
||||
if (update_dev_list[i]->type == type) {
|
||||
parm = (struct __update_dev_reg *)update_dev_list[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (parm == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return (void *)&parm->u.sd;
|
||||
}
|
||||
|
||||
|
||||
struct strg_update {
|
||||
void *fd;
|
||||
char *update_path;
|
||||
};
|
||||
static struct strg_update strg_update = {0};
|
||||
#define __this (&strg_update)
|
||||
|
||||
static u16 strg_f_open(void)
|
||||
{
|
||||
if (!__this->update_path) {
|
||||
printf("file path err ");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (__this->fd) {
|
||||
return true;
|
||||
/* fclose(__this->fd);
|
||||
__this->fd = NULL; */
|
||||
}
|
||||
__this->fd = fopen(__this->update_path, "r");
|
||||
if (!__this->fd) {
|
||||
printf("file open err ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static u16 strg_f_read(void *fp, u8 *buff, u16 len)
|
||||
{
|
||||
if (!__this->fd) {
|
||||
return (u16) - 1;
|
||||
}
|
||||
|
||||
len = fread(__this->fd, buff, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int strg_f_seek(void *fp, u8 type, u32 offset)
|
||||
{
|
||||
if (!__this->fd) {
|
||||
return (int) - 1;
|
||||
}
|
||||
|
||||
int ret = fseek(__this->fd, offset, type);
|
||||
/* return 0; // 0k */
|
||||
return ret;
|
||||
}
|
||||
static u16 strg_f_stop(u8 err)
|
||||
{
|
||||
if (__this->fd) {
|
||||
fclose(__this->fd);
|
||||
__this->fd = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int strg_update_set_file_path_and_hdl(char *update_path, void *fd)
|
||||
{
|
||||
__this->update_path = update_path;
|
||||
__this->fd = fd;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const update_op_api_t strg_dev_update_op = {
|
||||
.f_open = strg_f_open,
|
||||
.f_read = strg_f_read,
|
||||
.f_seek = strg_f_seek,
|
||||
.f_stop = strg_f_stop,
|
||||
};
|
||||
|
||||
static void dev_update_param_private_handle(UPDATA_PARM *p)
|
||||
{
|
||||
u16 up_type = p->parm_type;
|
||||
|
||||
#ifdef CONFIG_SD_UPDATE_ENABLE
|
||||
if ((up_type == SD0_UPDATA) || (up_type == SD1_UPDATA)) {
|
||||
int sd_start = (u32)p->parm_priv;
|
||||
void *sd = NULL;
|
||||
sd = dev_update_get_parm(up_type);
|
||||
if (sd) {
|
||||
memcpy((void *)sd_start, sd, UPDATE_PRIV_PARAM_LEN);
|
||||
} else {
|
||||
memset((void *)sd_start, 0, UPDATE_PRIV_PARAM_LEN);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_UPDATE_ENABLE
|
||||
if (up_type == USB_UPDATA) {
|
||||
printf("usb updata ");
|
||||
int usb_start = (u32)p->parm_priv;
|
||||
memset((void *)usb_start, 0, UPDATE_PRIV_PARAM_LEN);
|
||||
}
|
||||
#endif
|
||||
memcpy(p->file_patch, updata_file_name, strlen(updata_file_name));
|
||||
}
|
||||
|
||||
|
||||
static void dev_update_before_jump_handle(u16 up_type)
|
||||
{
|
||||
#if (defined DEV_UPDATE_SUPPORT_JUMP) || (CONFIG_UPDATE_JUMP_TO_MASK)
|
||||
#if TCFG_BLUETOOTH_BACK_MODE //后台模式需要把蓝牙关掉
|
||||
if (BT_MODULES_IS_SUPPORT(BT_MODULE_LE)) {
|
||||
ll_hci_destory();
|
||||
}
|
||||
hci_controller_destory();
|
||||
#endif
|
||||
#if CONFIG_UPDATE_JUMP_TO_MASK
|
||||
y_printf(">>>[test]:latch reset update\n");
|
||||
latch_reset();
|
||||
|
||||
#if 0
|
||||
update_close_hw("null");
|
||||
ram_protect_close();
|
||||
save_spi_port();
|
||||
|
||||
extern void __BT_UPDATA_JUMP();
|
||||
y_printf("update jump to __BT_UPDATA ...\n");
|
||||
y_printf(">>>[test]:JL_IOMC = 0x%x\n", (JL_IOMAP->CON0 >> 16) & 0x3);
|
||||
/* clk_set("sys", 48 * 1000000L); */
|
||||
//跳转到uboot加载完,30ms左右(200410_yzb)
|
||||
__BT_UPDATA_JUMP();
|
||||
#endif
|
||||
#else
|
||||
printf("update jump to mask...\n");
|
||||
/* JL_UART0->CON0 = 0; */
|
||||
/* JL_UART1->CON0 = 0; */
|
||||
__JUMP_TO_MASKROM();
|
||||
#endif
|
||||
#else
|
||||
cpu_reset();
|
||||
#endif //DEV_UPDATE_SUPPORT_JUMP
|
||||
}
|
||||
|
||||
static void dev_update_state_cbk(int type, u32 state, void *priv)
|
||||
{
|
||||
update_ret_code_t *ret_code = (update_ret_code_t *)priv;
|
||||
|
||||
switch (state) {
|
||||
case UPDATE_CH_EXIT:
|
||||
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
|
||||
update_mode_api_v2(type,
|
||||
dev_update_param_private_handle,
|
||||
dev_update_before_jump_handle);
|
||||
} else {
|
||||
printf("update fail, cpu reset!!!\n");
|
||||
cpu_reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
u16 dev_update_check(char *logo)
|
||||
{
|
||||
if (update_success_boot_check() == true) {
|
||||
return UPDATA_NON;
|
||||
}
|
||||
struct __dev *dev = dev_manager_find_spec(logo, 0);
|
||||
if (dev) {
|
||||
#if DEV_UPDATE_EN
|
||||
//<查找设备升级配置
|
||||
struct __update_dev_reg *parm = NULL;
|
||||
for (int i = 0; i < ARRAY_SIZE(update_dev_list); i++) {
|
||||
if (0 == strcmp(update_dev_list[i]->logo, logo)) {
|
||||
parm = (struct __update_dev_reg *)update_dev_list[i];
|
||||
}
|
||||
}
|
||||
if (parm == NULL) {
|
||||
printf("dev update without parm err!!!\n");
|
||||
return UPDATA_PARM_ERR;
|
||||
}
|
||||
//<尝试按照路径打开升级文件
|
||||
char *updata_file = (char *)updata_file_name;
|
||||
if (*updata_file == '/') {
|
||||
updata_file ++;
|
||||
}
|
||||
memset(update_path, 0, sizeof(update_path));
|
||||
sprintf(update_path, "%s%s", dev_manager_get_root_path(dev), updata_file);
|
||||
printf("update_path: %s\n", update_path);
|
||||
FILE *fd = fopen(update_path, "r");
|
||||
if (!fd) {
|
||||
///没有升级文件, 继续跑其他解码相关的流程
|
||||
printf("open update file err!!!\n");
|
||||
return UPDATA_DEV_ERR;
|
||||
}
|
||||
|
||||
#if(USER_UART_UPDATE_ENABLE) && (UART_UPDATE_ROLE == UART_UPDATE_MASTER)
|
||||
uart_update_send_update_ready(update_path);
|
||||
while (get_uart_update_sta()) {
|
||||
os_time_dly(10);
|
||||
}
|
||||
#else
|
||||
///进行升级
|
||||
|
||||
strg_update_set_file_path_and_hdl(update_path, (void *)fd);
|
||||
|
||||
update_mode_info_t info = {
|
||||
.type = parm->type,
|
||||
.state_cbk = dev_update_state_cbk,
|
||||
.p_op_api = &strg_dev_update_op,
|
||||
.task_en = 0,
|
||||
};
|
||||
app_active_update_task_init(&info);
|
||||
|
||||
#endif// USER_UART_UPDATE_ENABLE
|
||||
|
||||
#endif//DEV_UPDATE_EN
|
||||
}
|
||||
return UPDATA_READY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef __DEV_UPDATE_H__
|
||||
#define __DEV_UPDATE_H__
|
||||
|
||||
#include "typedef.h"
|
||||
#include "system/includes.h"
|
||||
|
||||
void *dev_update_get_parm(int type);
|
||||
u16 dev_update_check(char *logo);
|
||||
|
||||
#endif//__DEV_UPDATE_H__
|
||||
@@ -0,0 +1,157 @@
|
||||
#include "key_driver.h"
|
||||
#include "adkey.h"
|
||||
#include "gpio.h"
|
||||
#include "system/event.h"
|
||||
#include "app_config.h"
|
||||
|
||||
|
||||
#if TCFG_ADKEY_ENABLE
|
||||
|
||||
static const struct adkey_platform_data *__this = NULL;
|
||||
|
||||
u8 ad_get_key_value(void);
|
||||
//按键驱动扫描参数列表
|
||||
struct key_driver_para adkey_scan_para = {
|
||||
.scan_time = 10, //按键扫描频率, 单位: ms
|
||||
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
|
||||
.filter_time = 2, //按键消抖延时;
|
||||
.long_time = 75, //按键判定长按数量
|
||||
.hold_time = (75 + 15), //按键判定HOLD数量
|
||||
.click_delay_time = 20, //按键被抬起后等待连击延时数量
|
||||
.key_type = KEY_DRIVER_TYPE_AD,
|
||||
.get_value = ad_get_key_value,
|
||||
};
|
||||
u8 ad_get_key_value(void)
|
||||
{
|
||||
u8 i;
|
||||
u16 ad_data;
|
||||
|
||||
if (!__this->enable) {
|
||||
return NO_KEY;
|
||||
}
|
||||
|
||||
/* ad_data = adc_get_voltage(__this->ad_channel); */
|
||||
ad_data = adc_get_value(__this->ad_channel);
|
||||
/* printf("ad_value = %d \n", ad_data); */
|
||||
for (i = 0; i < ADKEY_MAX_NUM; i++) {
|
||||
if ((ad_data <= __this->ad_value[i]) && (__this->ad_value[i] < 0x3ffL)) {
|
||||
return __this->key_value[i];
|
||||
}
|
||||
}
|
||||
return NO_KEY;
|
||||
}
|
||||
|
||||
int adkey_init(const struct adkey_platform_data *adkey_data)
|
||||
{
|
||||
__this = adkey_data;
|
||||
if (!__this) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!__this->enable) {
|
||||
return KEY_NOT_SUPPORT;
|
||||
}
|
||||
adc_add_sample_ch(__this->ad_channel); //注意:初始化AD_KEY之前,先初始化ADC
|
||||
#if (TCFG_ADKEY_LED_IO_REUSE || TCFG_ADKEY_IR_IO_REUSE || TCFG_ADKEY_LED_SPI_IO_REUSE)
|
||||
#else
|
||||
gpio_set_die(__this->adkey_pin, 0);
|
||||
gpio_set_direction(__this->adkey_pin, 1);
|
||||
gpio_set_pull_down(__this->adkey_pin, 0);
|
||||
if (__this->extern_up_en) {
|
||||
gpio_set_pull_up(__this->adkey_pin, 0);
|
||||
} else {
|
||||
gpio_set_pull_up(__this->adkey_pin, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (TCFG_ADKEY_LED_IO_REUSE || TCFG_ADKEY_IR_IO_REUSE || TCFG_ADKEY_LED_SPI_IO_REUSE)
|
||||
|
||||
#if TCFG_ADKEY_IR_IO_REUSE
|
||||
static u8 ir_io_sus = 0;
|
||||
extern u8 ir_io_suspend(void);
|
||||
extern u8 ir_io_resume(void);
|
||||
#endif
|
||||
#if TCFG_ADKEY_LED_IO_REUSE
|
||||
static u8 led_io_sus = 0;
|
||||
extern u8 led_io_suspend(void);
|
||||
extern u8 led_io_resume(void);
|
||||
#endif
|
||||
#if TCFG_ADKEY_LED_SPI_IO_REUSE
|
||||
static u8 led_spi_sus = 0;
|
||||
extern u8 led_spi_suspend(void);
|
||||
extern u8 led_spi_resume(void);
|
||||
#endif
|
||||
u8 adc_io_reuse_enter(u32 ch)
|
||||
{
|
||||
if (ch == __this->ad_channel) {
|
||||
#if TCFG_ADKEY_IR_IO_REUSE
|
||||
if (ir_io_suspend()) {
|
||||
return 1;
|
||||
} else {
|
||||
ir_io_sus = 1;
|
||||
}
|
||||
#endif
|
||||
#if TCFG_ADKEY_LED_IO_REUSE
|
||||
if (led_io_suspend()) {
|
||||
return 1;
|
||||
} else {
|
||||
led_io_sus = 1;
|
||||
}
|
||||
#endif
|
||||
#if TCFG_ADKEY_LED_SPI_IO_REUSE
|
||||
if (led_spi_suspend()) {
|
||||
return 1;
|
||||
} else {
|
||||
led_spi_sus = 1;
|
||||
}
|
||||
#endif
|
||||
gpio_set_die(__this->adkey_pin, 0);
|
||||
gpio_set_direction(__this->adkey_pin, 1);
|
||||
gpio_set_pull_down(__this->adkey_pin, 0);
|
||||
if (__this->extern_up_en) {
|
||||
gpio_set_pull_up(__this->adkey_pin, 0);
|
||||
} else {
|
||||
gpio_set_pull_up(__this->adkey_pin, 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 adc_io_reuse_exit(u32 ch)
|
||||
{
|
||||
if (ch == __this->ad_channel) {
|
||||
#if TCFG_ADKEY_IR_IO_REUSE
|
||||
if (ir_io_sus) {
|
||||
ir_io_sus = 0;
|
||||
ir_io_resume();
|
||||
}
|
||||
#endif
|
||||
#if TCFG_ADKEY_LED_IO_REUSE
|
||||
if (led_io_sus) {
|
||||
led_io_sus = 0;
|
||||
led_io_resume();
|
||||
}
|
||||
#endif
|
||||
#if TCFG_ADKEY_LED_SPI_IO_REUSE
|
||||
if (led_spi_sus) {
|
||||
led_spi_sus = 0;
|
||||
led_spi_resume();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif /* #if TCFG_ADKEY_ENABLE */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
#include "includes.h"
|
||||
#include "key_driver.h"
|
||||
#include "adkey.h"
|
||||
#include "gpio.h"
|
||||
#include "system/event.h"
|
||||
#include "app_config.h"
|
||||
#include "asm/power/p33.h"
|
||||
|
||||
#if TCFG_ADKEY_RTCVDD_ENABLE
|
||||
|
||||
#define ADKEY_RTCVDD_DEBUG 1
|
||||
#if ADKEY_RTCVDD_DEBUG
|
||||
#define adkey_rtcvdd_debug(fmt, ...) printf("[ADKEY_RTCVDD] "fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define adkey_rtcvdd_debug(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define ADC_KEY_NUMBER 10
|
||||
|
||||
#define FULL_ADC 0x3ffL
|
||||
|
||||
#define ADC_FULL(x) (x)
|
||||
#define ADC_VOLTAGE(x,y,z) ((x*y) / (y + z)) //x当前满幅电压,y分压电阻,z上拉电阻
|
||||
#define ADC_ZERRO(x) (0)
|
||||
|
||||
u16 ad_rtcvdd_key_table[ADC_KEY_NUMBER + 1] = {0};
|
||||
|
||||
#define FULL_AD_VOLTAGE 0x3FFF
|
||||
|
||||
volatile u8 adkey_lock_cnt = 0;
|
||||
static u8 rtcvdd_cnt = 10;
|
||||
static u8 rtcvdd_full_cnt = 0xff;
|
||||
u16 rtcvdd_full_value = FULL_AD_VOLTAGE;
|
||||
u16 max_value = 0;
|
||||
u16 min_value = 0xffff;
|
||||
u32 total_value = 0;
|
||||
static u8 check_rtcvdd_cnt = 0;
|
||||
|
||||
static const struct adkey_rtcvdd_platform_data *__this = NULL;
|
||||
|
||||
|
||||
u8 adkey_rtcvdd_get_key_value(void);
|
||||
//按键驱动扫描参数列表
|
||||
struct key_driver_para adkey_rtcvdd_scan_para = {
|
||||
.scan_time = 10, //按键扫描频率, 单位: ms
|
||||
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
|
||||
.filter_time = 2, //按键消抖延时;
|
||||
.long_time = 75, //按键判定长按数量
|
||||
.hold_time = (75 + 15), //按键判定HOLD数量
|
||||
.click_delay_time = 20, //按键被抬起后等待连击延时数量
|
||||
.key_type = KEY_DRIVER_TYPE_RTCVDD_AD,
|
||||
.get_value = adkey_rtcvdd_get_key_value,
|
||||
};
|
||||
|
||||
static void set_rtcvdd_table(u16 adc_rtcvdd)
|
||||
{
|
||||
u8 i;
|
||||
u32 extern_up_res_value = __this->extern_up_res_value;
|
||||
|
||||
if (extern_up_res_value == 0) { //使用内部上拉
|
||||
extern_up_res_value = 100;
|
||||
}
|
||||
|
||||
for (i = 0; i < __this->adkey_num; i++) {
|
||||
if (i == (__this->adkey_num - 1)) {
|
||||
ad_rtcvdd_key_table[i] = (ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i], extern_up_res_value) + ADC_FULL(adc_rtcvdd)) / 2;
|
||||
//adkey_rtcvdd_debug("recvdd = %d, res_value[%d] = %d", adc_rtcvdd, i, __this->res_value[i]);
|
||||
} else {
|
||||
ad_rtcvdd_key_table[i] = (ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i], extern_up_res_value) + ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i + 1], extern_up_res_value)) / 2;
|
||||
//adkey_rtcvdd_debug("res_value[%d] = %d, res_value[%d] = %d", i, __this->res_value[i], i + 1, __this->res_value[i+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SET_ADKEY_LOCK_CNT(u8 cnt)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
OS_ENTER_CRITICAL();
|
||||
|
||||
adkey_lock_cnt = cnt;
|
||||
|
||||
OS_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
static u8 GET_ADKEY_LOCK_CNT(void)
|
||||
{
|
||||
u8 val;
|
||||
CPU_SR_ALLOC();
|
||||
OS_ENTER_CRITICAL();
|
||||
|
||||
val = adkey_lock_cnt;
|
||||
|
||||
OS_EXIT_CRITICAL();
|
||||
return val;
|
||||
}
|
||||
|
||||
static void POST_ADKEY_LOCK_CNT(void)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
OS_ENTER_CRITICAL();
|
||||
|
||||
adkey_lock_cnt --;
|
||||
|
||||
OS_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief ad按键初始化
|
||||
@param void
|
||||
@param void
|
||||
@return void
|
||||
@note void ad_key0_init(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int adkey_rtcvdd_init(const struct adkey_rtcvdd_platform_data *adkey_data)
|
||||
{
|
||||
adkey_rtcvdd_debug("ad key init\n");
|
||||
|
||||
__this = adkey_data;
|
||||
if (!__this) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (__this->extern_up_res_value == 0) { //使用内部上拉
|
||||
gpio_set_pull_up(__this->adkey_pin, 1);
|
||||
} else {
|
||||
gpio_set_pull_up(__this->adkey_pin, 0);
|
||||
}
|
||||
gpio_set_direction(__this->adkey_pin, 1);
|
||||
gpio_set_pull_down(__this->adkey_pin, 0);
|
||||
gpio_set_die(__this->adkey_pin, 0);
|
||||
|
||||
adc_add_sample_ch(__this->ad_channel); //注意:初始化AD_KEY之前,先初始化ADC
|
||||
adc_add_sample_ch(AD_CH_RTCVDD);
|
||||
|
||||
set_rtcvdd_table(FULL_ADC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*把cnt个值里的最大值和最小值去掉,求剩余cnt-2个数的平均值*/
|
||||
static u16 rtcvdd_full_vaule_update(u16 value)
|
||||
{
|
||||
u16 full_value = FULL_ADC;
|
||||
if (rtcvdd_full_cnt == 0xff) {
|
||||
rtcvdd_full_cnt = 0;
|
||||
SET_ADKEY_LOCK_CNT(50);
|
||||
return value; //first time
|
||||
} else {
|
||||
rtcvdd_full_cnt ++;
|
||||
if (value > max_value) {
|
||||
max_value = value;
|
||||
}
|
||||
if (value < min_value) {
|
||||
min_value = value;
|
||||
}
|
||||
total_value += value;
|
||||
|
||||
if (rtcvdd_full_cnt > 10 - 1) { //算10个数
|
||||
full_value = (total_value - max_value - min_value) / (rtcvdd_full_cnt - 2);
|
||||
rtcvdd_full_cnt = 0;
|
||||
max_value = 0;
|
||||
min_value = 0xffff;
|
||||
total_value = 0;
|
||||
} else {
|
||||
return rtcvdd_full_value;
|
||||
}
|
||||
}
|
||||
return full_value;
|
||||
}
|
||||
|
||||
u8 get_rtcvdd_level(void)
|
||||
{
|
||||
u8 level = GET_RTCVDD_VOL();
|
||||
return level;
|
||||
}
|
||||
|
||||
void set_rtcvdd_level(u8 level)
|
||||
{
|
||||
if (level > 7 || level < 0) {
|
||||
return;
|
||||
}
|
||||
RTCVDD_VOL_SEL(level);
|
||||
}
|
||||
/*检测到RTCVDD 比 VDDIO 高的时候自动把RTCVDD降一档*/
|
||||
static u8 rtcvdd_auto_match_vddio_lev(u32 rtcvdd_value)
|
||||
{
|
||||
u8 rtcvdd_lev = 0;
|
||||
if (rtcvdd_value >= FULL_ADC) { //trim rtcvdd < vddio
|
||||
if (rtcvdd_cnt > 10) {
|
||||
rtcvdd_cnt = 0;
|
||||
rtcvdd_lev = get_rtcvdd_level();
|
||||
if (rtcvdd_lev < 8) {
|
||||
rtcvdd_lev++; //降一档
|
||||
/* rtcvdd_lev--; //降一档 */
|
||||
set_rtcvdd_level(rtcvdd_lev);
|
||||
SET_ADKEY_LOCK_CNT(50);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
rtcvdd_cnt ++;
|
||||
}
|
||||
} else {
|
||||
rtcvdd_cnt = 0;
|
||||
rtcvdd_full_value = rtcvdd_full_vaule_update(rtcvdd_value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 获取ad按键值
|
||||
@param void
|
||||
@param void
|
||||
@return key_number
|
||||
@note tu8 adkey_rtcvdd_get_key_value(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
u8 adkey_rtcvdd_get_key_value(void)
|
||||
{
|
||||
u8 key_number, i;
|
||||
u32 ad_value;
|
||||
u16 rtcvdd_value = 0;
|
||||
|
||||
rtcvdd_value = 2 * adc_get_value(AD_CH_RTCVDD);
|
||||
ad_value = adc_get_value(__this->ad_channel);
|
||||
|
||||
/* printf("rtcvdd_value = %d, ad_value = %d", rtcvdd_value, ad_value); */
|
||||
if (rtcvdd_auto_match_vddio_lev(rtcvdd_value)) {
|
||||
return NO_KEY;
|
||||
}
|
||||
|
||||
if (GET_ADKEY_LOCK_CNT()) {
|
||||
POST_ADKEY_LOCK_CNT();
|
||||
return NO_KEY;
|
||||
}
|
||||
|
||||
set_rtcvdd_table(rtcvdd_full_value);
|
||||
|
||||
for (i = 0; i < __this->adkey_num; i++) {
|
||||
if (ad_value <= ad_rtcvdd_key_table[i] && (ad_rtcvdd_key_table[i] < 0x3FFL)) {
|
||||
return __this->key_value[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NO_KEY;
|
||||
}
|
||||
|
||||
|
||||
#endif /* #if TCFG_ADKEY_RTCVDD_ENABLE */
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "key_driver.h"
|
||||
#include "app_config.h"
|
||||
|
||||
|
||||
|
||||
#if TCFG_CTMU_TOUCH_KEY_ENABLE
|
||||
#include "asm/ctmu.h"
|
||||
|
||||
#define LOG_TAG_CONST CTMU
|
||||
#define LOG_TAG "[ctmu]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
/* =========== 触摸键使用说明 ============= */
|
||||
//1. 使用ctmu模块作计数;
|
||||
|
||||
static const struct ctmu_touch_key_platform_data *__this = NULL;
|
||||
|
||||
static u8 ctmu_touch_key_get_value(void);
|
||||
//按键驱动扫描参数列表
|
||||
struct key_driver_para ctmu_touch_key_scan_para = {
|
||||
.scan_time = 10, //按键扫描频率, 单位: ms
|
||||
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
|
||||
.filter_time = 2, //按键消抖延时;
|
||||
.long_time = 55, //按键判定长按数量
|
||||
.hold_time = (55 + 15), //按键判定HOLD数量
|
||||
.click_delay_time = 40, //按键被抬起后等待连击延时数量
|
||||
.key_type = KEY_DRIVER_TYPE_CTMU_TOUCH,
|
||||
.get_value = ctmu_touch_key_get_value,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static u8 ctmu_touch_key_get_value(void)
|
||||
{
|
||||
u8 key = get_ctmu_value();
|
||||
|
||||
if (key != NO_KEY) {
|
||||
log_debug("key = %d %x", key, __this->port_list[key].key_value);
|
||||
return __this->port_list[key].key_value;
|
||||
}
|
||||
|
||||
return NO_KEY;
|
||||
}
|
||||
|
||||
|
||||
int ctmu_touch_key_init(const struct ctmu_touch_key_platform_data *ctmu_touch_key_data)
|
||||
{
|
||||
__this = ctmu_touch_key_data;
|
||||
log_info("ctmu touch_key_init >>>> ");
|
||||
|
||||
return ctmu_init((void *)ctmu_touch_key_data);
|
||||
}
|
||||
|
||||
|
||||
#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
#include "key_driver.h"
|
||||
#include "iokey.h"
|
||||
#include "gpio.h"
|
||||
#include "system/event.h"
|
||||
#include "app_config.h"
|
||||
#include "asm/clock.h"
|
||||
|
||||
#if TCFG_IOKEY_ENABLE
|
||||
|
||||
static const struct iokey_platform_data *__this = NULL;
|
||||
|
||||
u8 io_get_key_value(void);
|
||||
|
||||
#if MOUSE_KEY_SCAN_MODE
|
||||
struct key_driver_para iokey_scan_para = {
|
||||
.scan_time = 5, //按键扫描频率, 单位: ms
|
||||
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
|
||||
.filter_time = 2, //按键消抖延时;
|
||||
.long_time = 5, //按键判定长按数量
|
||||
.hold_time = (5 + 0), //按键判定HOLD数量
|
||||
.click_delay_time = 20, //按键被抬起后等待连击延时数量
|
||||
.key_type = KEY_DRIVER_TYPE_IO,
|
||||
.get_value = io_get_key_value,
|
||||
};
|
||||
#else
|
||||
//按键驱动扫描参数列表
|
||||
struct key_driver_para iokey_scan_para = {
|
||||
.scan_time = 10, //按键扫描频率, 单位: ms
|
||||
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
|
||||
.filter_time = 4, //按键消抖延时;
|
||||
.long_time = 75, //按键判定长按数量
|
||||
.hold_time = (75 + 15), //按键判定HOLD数量
|
||||
.click_delay_time = 20, //按键被抬起后等待连击延时数量
|
||||
.key_type = KEY_DRIVER_TYPE_IO,
|
||||
.get_value = io_get_key_value,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define MARK_BIT_VALUE(b, v) do {if ((v & (~BIT(7))) < 7) b |= BIT(v & (~BIT(7)));} while(0)
|
||||
|
||||
static void key_io_pull_down_input(u8 key_io)
|
||||
{
|
||||
gpio_direction_input(key_io);
|
||||
gpio_set_pull_down(key_io, 1);
|
||||
gpio_set_pull_up(key_io, 0);
|
||||
gpio_set_die(key_io, 1);
|
||||
}
|
||||
|
||||
|
||||
static void key_io_pull_up_input(u8 key_io)
|
||||
{
|
||||
gpio_direction_input(key_io);
|
||||
gpio_set_pull_down(key_io, 0);
|
||||
gpio_set_pull_up(key_io, 1);
|
||||
gpio_set_die(key_io, 1);
|
||||
}
|
||||
|
||||
static void key_io_output_high(u8 key_io)
|
||||
{
|
||||
gpio_set_pull_down(key_io, 0);
|
||||
gpio_set_pull_up(key_io, 0);
|
||||
gpio_direction_output(key_io, 1);
|
||||
}
|
||||
|
||||
static void key_io_output_low(u8 key_io)
|
||||
{
|
||||
gpio_set_pull_down(key_io, 0);
|
||||
gpio_set_pull_up(key_io, 0);
|
||||
gpio_direction_output(key_io, 0);
|
||||
}
|
||||
|
||||
static int get_io_key_value(u8 key_io)
|
||||
{
|
||||
return gpio_read(key_io);
|
||||
}
|
||||
|
||||
|
||||
static void key_io_reset(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < __this->num; i++) {
|
||||
switch (__this->port[i].connect_way) {
|
||||
case ONE_PORT_TO_HIGH:
|
||||
key_io_pull_down_input(__this->port[i].key_type.one_io.port);
|
||||
break;
|
||||
|
||||
case ONE_PORT_TO_LOW:
|
||||
#if (TCFG_IO_MULTIPLEX_WITH_SD == ENABLE)
|
||||
if (TCFG_MULTIPLEX_PORT != __this->port[i].key_type.one_io.port) {
|
||||
key_io_pull_up_input(__this->port[i].key_type.one_io.port);
|
||||
}
|
||||
#else
|
||||
|
||||
key_io_pull_up_input(__this->port[i].key_type.one_io.port);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DOUBLE_PORT_TO_IO:
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT(0, "IO KEY CONNECT ERR!!!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if MULT_KEY_ENABLE
|
||||
extern const struct key_remap_data iokey_remap_data;
|
||||
static u8 iokey_value_remap(u8 bit_mark)
|
||||
{
|
||||
for (int i = 0; i < iokey_remap_data.remap_num; i++) {
|
||||
if (iokey_remap_data.table[i].bit_value == bit_mark) {
|
||||
return iokey_remap_data.table[i].remap_value;
|
||||
}
|
||||
}
|
||||
|
||||
return NO_KEY;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if TCFG_IO_MULTIPLEX_WITH_SD == ENABLE
|
||||
static u8 mult_key_value = 1;
|
||||
static void udelay(u32 usec)
|
||||
{
|
||||
JL_TIMER0->CON = BIT(14);
|
||||
JL_TIMER0->CNT = 0;
|
||||
JL_TIMER0->PRD = clk_get("lsb") / 1000000L * usec;
|
||||
JL_TIMER0->CON = BIT(0); //lsb clk
|
||||
while ((JL_TIMER0->CON & BIT(15)) == 0);
|
||||
JL_TIMER0->CON = BIT(14);
|
||||
}
|
||||
extern u8 sd_io_suspend(u8 sdx, u8 sd_io);
|
||||
extern u8 sd_io_resume(u8 sdx, u8 sd_io);
|
||||
void sd_mult_io_detect(void *arg)
|
||||
{
|
||||
static u32 cnt = 0;
|
||||
if (sd_io_suspend(1, 1) == 0) {
|
||||
gpio_set_direction(TCFG_MULTIPLEX_PORT, 0);
|
||||
gpio_write(TCFG_MULTIPLEX_PORT, 0);
|
||||
udelay(10);
|
||||
gpio_set_die(TCFG_MULTIPLEX_PORT, 1);
|
||||
gpio_set_pull_down(TCFG_MULTIPLEX_PORT, 0);
|
||||
gpio_set_pull_up(TCFG_MULTIPLEX_PORT, 1);
|
||||
gpio_set_direction(TCFG_MULTIPLEX_PORT, 1);
|
||||
udelay(10);
|
||||
mult_key_value = gpio_read(TCFG_MULTIPLEX_PORT);
|
||||
sd_io_resume(1, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) u8 iokey_filter_hook(u8 io_state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 开机锁键剩余确认次数;非 0 时扫描一律返回 NO_KEY */
|
||||
static u8 s_boot_lock_cnt;
|
||||
|
||||
/**
|
||||
* @brief 启动/关闭开机锁键
|
||||
* @param release_cnt >0:松开后连续确认次数;0:关闭
|
||||
*/
|
||||
void iokey_boot_lock_start(u8 release_cnt)
|
||||
{
|
||||
#if TCFG_IOKEY_BOOT_LOCK_ENABLE
|
||||
s_boot_lock_cnt = release_cnt;
|
||||
#else
|
||||
(void)release_cnt;
|
||||
s_boot_lock_cnt = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 立即关闭开机锁键
|
||||
*/
|
||||
void iokey_boot_lock_stop(void)
|
||||
{
|
||||
s_boot_lock_cnt = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 扫描路径更新锁键:监视 port[0],松开则递减计数
|
||||
* @return 1=仍锁定(应返回 NO_KEY),0=已解锁可正常扫描
|
||||
*/
|
||||
static u8 iokey_boot_lock_update(void)
|
||||
{
|
||||
#if !TCFG_IOKEY_BOOT_LOCK_ENABLE
|
||||
return 0;
|
||||
#else
|
||||
u8 key_io;
|
||||
u8 io_level;
|
||||
u8 released;
|
||||
|
||||
if (!s_boot_lock_cnt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!__this || (__this->num == 0))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
key_io = __this->port[0].key_type.one_io.port;
|
||||
io_level = gpio_read(key_io);
|
||||
if (__this->port[0].connect_way == ONE_PORT_TO_LOW)
|
||||
{
|
||||
released = io_level; /* 上拉输入,松开为高 */
|
||||
}
|
||||
else
|
||||
{
|
||||
released = !io_level; /* 下拉输入,松开为低 */
|
||||
}
|
||||
|
||||
if (released)
|
||||
{
|
||||
s_boot_lock_cnt--;
|
||||
if (s_boot_lock_cnt == 0)
|
||||
{
|
||||
puts("iokey boot lock released\n");
|
||||
}
|
||||
}
|
||||
return 1; /* 本拍仍屏蔽;计数到 0 后下一拍才开放 */
|
||||
#endif
|
||||
}
|
||||
|
||||
u8 io_get_key_value(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
u8 press_value = 0;
|
||||
u8 read_value = 0;
|
||||
u8 read_io;
|
||||
u8 write_io;
|
||||
u8 connect_way;
|
||||
u8 ret_value = NO_KEY;
|
||||
u8 bit_mark = 0;
|
||||
|
||||
if (!__this->enable) {
|
||||
return NO_KEY;
|
||||
}
|
||||
if (iokey_boot_lock_update()) {
|
||||
return NO_KEY;
|
||||
}
|
||||
//先扫描单IO接按键方式
|
||||
for (i = 0; i < __this->num; i++) {
|
||||
connect_way = __this->port[i].connect_way;
|
||||
|
||||
if (connect_way == ONE_PORT_TO_HIGH) {
|
||||
press_value = 1;
|
||||
} else if (connect_way == ONE_PORT_TO_LOW) {
|
||||
press_value = 0;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
read_io = __this->port[i].key_type.one_io.port;
|
||||
|
||||
#if (TCFG_IO_MULTIPLEX_WITH_SD == ENABLE)
|
||||
if (read_io == TCFG_MULTIPLEX_PORT) {
|
||||
read_value = mult_key_value;
|
||||
} else {
|
||||
read_value = get_io_key_value(read_io);
|
||||
}
|
||||
#else
|
||||
read_value = get_io_key_value(read_io);
|
||||
#endif
|
||||
if (iokey_filter_hook(read_value)) {
|
||||
#ifdef TCFG_IOKEY_TIME_REDEFINE
|
||||
extern struct key_driver_para iokey_scan_user_para;
|
||||
iokey_scan_user_para.filter_cnt = 0;
|
||||
iokey_scan_user_para.press_cnt = 0;
|
||||
iokey_scan_user_para.click_cnt = 0;
|
||||
iokey_scan_user_para.click_delay_cnt = 0;
|
||||
iokey_scan_user_para.last_key = NO_KEY;
|
||||
#else
|
||||
iokey_scan_para.filter_cnt = 0;
|
||||
iokey_scan_para.press_cnt = 0;
|
||||
iokey_scan_para.click_cnt = 0;
|
||||
iokey_scan_para.click_delay_cnt = 0;
|
||||
iokey_scan_para.last_key = NO_KEY;
|
||||
#endif
|
||||
return NO_KEY;
|
||||
}
|
||||
if (read_value == press_value) {
|
||||
ret_value = __this->port[i].key_value;
|
||||
#if MULT_KEY_ENABLE
|
||||
MARK_BIT_VALUE(bit_mark, ret_value); //标记被按下的按键
|
||||
#else
|
||||
goto _iokey_get_value_end;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//再扫描两个IO接按键方式, in_port: 上拉输入, out_port: 输出低
|
||||
for (i = 0; i < __this->num; i++) {
|
||||
connect_way = __this->port[i].connect_way;
|
||||
if (connect_way == DOUBLE_PORT_TO_IO) {//标准双io
|
||||
press_value = 0;
|
||||
read_io = __this->port[i].key_type.two_io.in_port;
|
||||
key_io_output_low(__this->port[i].key_type.two_io.out_port); //输出低
|
||||
key_io_pull_up_input(read_io); //上拉
|
||||
read_value = get_io_key_value(read_io);
|
||||
key_io_reset(); //按键初始化为单IO检测状态
|
||||
if (read_value == press_value) {
|
||||
ret_value = __this->port[i].key_value;
|
||||
#if MULT_KEY_ENABLE
|
||||
MARK_BIT_VALUE(bit_mark, ret_value); //标记被按下的按键
|
||||
#else
|
||||
goto _iokey_get_value_end;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if MULT_KEY_ENABLE
|
||||
bit_mark = iokey_value_remap(bit_mark); //组合按键重新映射按键值
|
||||
ret_value = (bit_mark != NO_KEY) ? bit_mark : ret_value;
|
||||
#endif
|
||||
|
||||
_iokey_get_value_end:
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int iokey_init(const struct iokey_platform_data *iokey_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
__this = iokey_data;
|
||||
if (__this == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!__this->enable) {
|
||||
return KEY_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
/* 长按开机场景:等电源键(port[0])松开后再开放按键扫描 */
|
||||
#if TCFG_IOKEY_BOOT_LOCK_ENABLE
|
||||
iokey_boot_lock_start(IOKEY_BOOT_LOCK_DEFAULT_CNT);
|
||||
#else
|
||||
iokey_boot_lock_stop();
|
||||
#endif
|
||||
key_io_reset();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* #if TCFG_IOKEY_ENABLE */
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "key_driver.h"
|
||||
#include "irkey.h"
|
||||
#include "gpio.h"
|
||||
#include "asm/irflt.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#if TCFG_IRKEY_ENABLE
|
||||
|
||||
u8 ir_get_key_value(void);
|
||||
//按键驱动扫描参数列表
|
||||
struct key_driver_para irkey_scan_para = {
|
||||
.scan_time = 10, //按键扫描频率, 单位: ms
|
||||
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
|
||||
.filter_time = 2, //按键消抖延时;
|
||||
.long_time = 75, //按键判定长按数量
|
||||
.hold_time = (75 + 15), //按键判定HOLD数量
|
||||
.click_delay_time = 20, //按键被抬起后等待连击延时数量
|
||||
.key_type = KEY_DRIVER_TYPE_IR,
|
||||
.get_value = ir_get_key_value,
|
||||
};
|
||||
|
||||
|
||||
|
||||
const u8 IRTabFF00[] = {
|
||||
NKEY_00, NKEY_01, NKEY_02, NKEY_03, NKEY_04, NKEY_05, NKEY_06, IR_06, IR_15, IR_08, NKEY_0A, NKEY_0B, IR_12, IR_11, NKEY_0E, NKEY_0F,
|
||||
NKEY_10, NKEY_11, NKEY_12, NKEY_13, NKEY_14, IR_07, IR_09, NKEY_17, IR_13, IR_10, NKEY_1A, NKEY_1B, IR_16, NKEY_1D, NKEY_1E, NKEY_1F,
|
||||
NKEY_20, NKEY_21, NKEY_22, NKEY_23, NKEY_24, NKEY_25, NKEY_26, NKEY_27, NKEY_28, NKEY_29, NKEY_2A, NKEY_2B, NKEY_2C, NKEY_2D, NKEY_2E, NKEY_2F,
|
||||
NKEY_30, NKEY_31, NKEY_32, NKEY_33, NKEY_34, NKEY_35, NKEY_36, NKEY_37, NKEY_38, NKEY_39, NKEY_3A, NKEY_3B, NKEY_3C, NKEY_3D, NKEY_3E, NKEY_3F,
|
||||
IR_04, NKEY_41, IR_18, IR_05, IR_03, IR_00, IR_01, IR_02, NKEY_48, NKEY_49, IR_20, NKEY_4B, NKEY_4C, NKEY_4D, NKEY_4E, NKEY_4F,
|
||||
NKEY_50, NKEY_51, IR_19, NKEY_53, NKEY_54, NKEY_55, NKEY_56, NKEY_57, NKEY_58, NKEY_59, IR_17, NKEY_5B, NKEY_5C, NKEY_5D, IR_14, NKEY_5F,
|
||||
};
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 获取ir按键值
|
||||
@param void
|
||||
@param void
|
||||
@return void
|
||||
@note void get_irkey_value(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
u8 ir_get_key_value(void)
|
||||
{
|
||||
u8 tkey = 0xff;
|
||||
tkey = get_irflt_value();
|
||||
if (tkey == 0xff) {
|
||||
return tkey;
|
||||
}
|
||||
tkey = IRTabFF00[tkey];
|
||||
return tkey;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief ir按键初始化
|
||||
@param void
|
||||
@param void
|
||||
@return void
|
||||
@note void ir_key_init(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int irkey_init(const struct irkey_platform_data *irkey_data)
|
||||
{
|
||||
printf("irkey_init ");
|
||||
|
||||
ir_input_io_sel(irkey_data->port);
|
||||
|
||||
ir_output_timer_sel();
|
||||
|
||||
irflt_config();
|
||||
|
||||
ir_timeout_set();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
#include "device/key_driver.h"
|
||||
#include "system/event.h"
|
||||
#include "system/init.h"
|
||||
#include "iokey.h"
|
||||
#include "adkey.h"
|
||||
#include "slidekey.h"
|
||||
#include "irkey.h"
|
||||
#include "touch_key.h"
|
||||
#include "system/timer.h"
|
||||
#include "asm/power_interface.h"
|
||||
#include "app_config.h"
|
||||
#include "rdec_key.h"
|
||||
#include "tent600_key.h"
|
||||
#if TCFG_KEY_TONE_EN
|
||||
#include "tone_player.h"
|
||||
#endif
|
||||
|
||||
#if(TCFG_IRSENSOR_ENABLE == 1)
|
||||
#include "irSensor/ir_manage.h"
|
||||
#endif
|
||||
|
||||
#define LOG_TAG_CONST KEY
|
||||
#define LOG_TAG "[KEY]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
//#define LOG_DUMP_ENABLE
|
||||
//#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#define KEY_EVENT_CLICK_ONLY_SUPPORT 1 //是否支持某些按键只响应单击事件
|
||||
|
||||
|
||||
#if TCFG_SPI_LCD_ENABLE
|
||||
#ifndef ALL_KEY_EVENT_CLICK_ONLY
|
||||
#define ALL_KEY_EVENT_CLICK_ONLY 1 //是否全部按键只响应单击事件
|
||||
#endif
|
||||
#else
|
||||
#ifndef ALL_KEY_EVENT_CLICK_ONLY
|
||||
#define ALL_KEY_EVENT_CLICK_ONLY 0 //是否全部按键只响应单击事件
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static volatile u8 is_key_active = 0;
|
||||
static volatile u8 key_poweron_flag = 0;
|
||||
|
||||
extern u32 timer_get_ms(void);
|
||||
|
||||
//=======================================================//
|
||||
// 按键值重新映射函数:
|
||||
// 用户可以实现该函数把一些按键值重新映射, 可用于组合键的键值重新映射
|
||||
//=======================================================//
|
||||
int __attribute__((weak)) key_event_remap(struct sys_event *e)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//=======================================================//
|
||||
// 设置按键开机标志位
|
||||
//=======================================================//
|
||||
void set_key_poweron_flag(u8 flag)
|
||||
{
|
||||
key_poweron_flag = flag;
|
||||
}
|
||||
|
||||
//=======================================================//
|
||||
// 获取按键开机标志位
|
||||
//=======================================================//
|
||||
u8 get_key_poweron_flag(void)
|
||||
{
|
||||
return key_poweron_flag;
|
||||
}
|
||||
|
||||
//=======================================================//
|
||||
// 清除按键开机标志位
|
||||
//=======================================================//
|
||||
void clear_key_poweron_flag(void)
|
||||
{
|
||||
key_poweron_flag = 0;
|
||||
}
|
||||
|
||||
//=======================================================//
|
||||
// 按键扫描函数: 扫描所有注册的按键驱动
|
||||
//=======================================================//
|
||||
static void key_driver_scan(void *_scan_para)
|
||||
{
|
||||
struct key_driver_para *scan_para = (struct key_driver_para *)_scan_para;
|
||||
|
||||
u8 key_event = 0;
|
||||
u8 cur_key_value = NO_KEY;
|
||||
u8 key_value = 0;
|
||||
struct sys_event e;
|
||||
static u8 poweron_cnt = 0;
|
||||
|
||||
//为了滤掉adkey与mic连在一起时电容充放电导致的开机按键误判,一般用于type-c耳机
|
||||
/* if (poweron_cnt <= 250) { */
|
||||
/* poweron_cnt++; */
|
||||
/* return; */
|
||||
/* } */
|
||||
|
||||
cur_key_value = scan_para->get_value();
|
||||
/* if (cur_key_value != NO_KEY) { */
|
||||
/* printf(">>>cur_key_value: %d\n", cur_key_value); */
|
||||
/* } */
|
||||
|
||||
if (cur_key_value != NO_KEY) {
|
||||
is_key_active = 35; //35*10Ms
|
||||
} else if (is_key_active) {
|
||||
is_key_active --;
|
||||
}
|
||||
//===== 按键消抖处理
|
||||
if (cur_key_value != scan_para->filter_value && scan_para->filter_time) { //当前按键值与上一次按键值如果不相等, 重新消抖处理, 注意filter_time != 0;
|
||||
scan_para->filter_cnt = 0; //消抖次数清0, 重新开始消抖
|
||||
scan_para->filter_value = cur_key_value; //记录上一次的按键值
|
||||
return; //第一次检测, 返回不做处理
|
||||
} //当前按键值与上一次按键值相等, filter_cnt开始累加;
|
||||
if (scan_para->filter_cnt < scan_para->filter_time) {
|
||||
scan_para->filter_cnt++;
|
||||
return;
|
||||
}
|
||||
//为了滤掉adkey与mic连在一起时电容充放电导致的按键误判,一般用于type-c耳机
|
||||
/* if ((cur_key_value != scan_para->last_key) && (scan_para->last_key != NO_KEY) && (cur_key_value != NO_KEY)) { */
|
||||
/* return; */
|
||||
/* } */
|
||||
//===== 按键消抖结束, 开始判断按键类型(单击, 双击, 长按, 多击, HOLD, (长按/HOLD)抬起)
|
||||
if (cur_key_value != scan_para->last_key) {
|
||||
if (cur_key_value == NO_KEY) { //cur_key = NO_KEY; last_key = valid_key -> 按键被抬起
|
||||
|
||||
#if MOUSE_KEY_SCAN_MODE
|
||||
/* if (scan_para->press_cnt >= scan_para->long_time) { //长按/HOLD状态之后被按键抬起; */
|
||||
key_event = KEY_EVENT_UP;
|
||||
key_value = scan_para->last_key;
|
||||
goto _notify; //发送抬起消息
|
||||
/* } */
|
||||
#else
|
||||
if (scan_para->press_cnt >= scan_para->long_time) { //长按/HOLD状态之后被按键抬起;
|
||||
key_event = KEY_EVENT_UP;
|
||||
key_value = scan_para->last_key;
|
||||
goto _notify; //发送抬起消息
|
||||
}
|
||||
#endif
|
||||
|
||||
scan_para->click_delay_cnt = 1; //按键等待下次连击延时开始
|
||||
} else { //cur_key = valid_key, last_key = NO_KEY -> 按键被按下
|
||||
scan_para->press_cnt = 1; //用于判断long和hold事件的计数器重新开始计时;
|
||||
if (cur_key_value != scan_para->notify_value) { //第一次单击/连击时按下的是不同按键, 单击次数重新开始计数
|
||||
scan_para->click_cnt = 1;
|
||||
scan_para->notify_value = cur_key_value;
|
||||
} else {
|
||||
scan_para->click_cnt++; //单击次数累加
|
||||
}
|
||||
}
|
||||
goto _scan_end; //返回, 等待延时时间到
|
||||
} else { //cur_key = last_key -> 没有按键按下/按键长按(HOLD)
|
||||
if (cur_key_value == NO_KEY) { //last_key = NO_KEY; cur_key = NO_KEY -> 没有按键按下
|
||||
if (scan_para->click_cnt > 0) { //有按键需要消息需要处理
|
||||
|
||||
#if ALL_KEY_EVENT_CLICK_ONLY//彩屏方案支持单击
|
||||
key_event = KEY_EVENT_CLICK; //单击
|
||||
key_value = scan_para->notify_value;
|
||||
goto _notify;
|
||||
|
||||
#endif
|
||||
|
||||
#if KEY_EVENT_CLICK_ONLY_SUPPORT //是否支持某些按键只响应单击事件
|
||||
if (scan_para->notify_value & BIT(7)) { //BIT(7)按键特殊处理标志, 只发送单击事件, 也可以用于其它扩展
|
||||
key_event = KEY_EVENT_CLICK; //单击
|
||||
key_value = scan_para->notify_value;
|
||||
goto _notify;
|
||||
}
|
||||
#endif
|
||||
if (scan_para->click_delay_cnt > scan_para->click_delay_time) { //按键被抬起后延时到
|
||||
//TODO: 在此可以添加任意多击事件
|
||||
if (scan_para->click_cnt >= 5) {
|
||||
key_event = KEY_EVENT_FIRTH_CLICK; //五击
|
||||
} else if (scan_para->click_cnt >= 4) {
|
||||
key_event = KEY_EVENT_FOURTH_CLICK; //4击
|
||||
} else if (scan_para->click_cnt >= 3) {
|
||||
key_event = KEY_EVENT_TRIPLE_CLICK; //三击
|
||||
} else if (scan_para->click_cnt >= 2) {
|
||||
key_event = KEY_EVENT_DOUBLE_CLICK; //双击
|
||||
} else {
|
||||
key_event = KEY_EVENT_CLICK; //单击
|
||||
}
|
||||
key_value = scan_para->notify_value;
|
||||
goto _notify;
|
||||
} else { //按键抬起后等待下次延时时间未到
|
||||
scan_para->click_delay_cnt++;
|
||||
goto _scan_end; //按键抬起后延时时间未到, 返回
|
||||
}
|
||||
} else {
|
||||
goto _scan_end; //没有按键需要处理
|
||||
}
|
||||
} else { //last_key = valid_key; cur_key = valid_key, press_cnt累加用于判断long和hold
|
||||
scan_para->press_cnt++;
|
||||
if (scan_para->press_cnt == scan_para->long_time) {
|
||||
key_event = KEY_EVENT_LONG;
|
||||
} else if (scan_para->press_cnt == scan_para->hold_time) {
|
||||
key_event = KEY_EVENT_HOLD;
|
||||
scan_para->press_cnt = scan_para->long_time;
|
||||
} else {
|
||||
goto _scan_end; //press_cnt没到长按和HOLD次数, 返回
|
||||
}
|
||||
//press_cnt没到长按和HOLD次数, 发消息
|
||||
key_value = cur_key_value;
|
||||
goto _notify;
|
||||
}
|
||||
}
|
||||
|
||||
_notify:
|
||||
#if TCFG_IRSENSOR_ENABLE
|
||||
if (get_irSensor_event() == IR_SENSOR_EVENT_FAR) { //未佩戴的耳机不响应按键
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
key_value &= ~BIT(7); //BIT(7) 用作按键特殊处理的标志
|
||||
e.type = SYS_KEY_EVENT;
|
||||
e.u.key.init = 1;
|
||||
e.u.key.type = scan_para->key_type;//区分按键类型
|
||||
e.u.key.event = key_event;
|
||||
e.u.key.value = key_value;
|
||||
e.u.key.tmr = timer_get_ms();
|
||||
|
||||
|
||||
scan_para->click_cnt = 0; //单击次数清0
|
||||
scan_para->notify_value = NO_KEY;
|
||||
|
||||
e.arg = (void *)DEVICE_EVENT_FROM_KEY;
|
||||
/* printf("key_value: 0x%x, event: %d, key_poweron_flag: %d\n", key_value, key_event, key_poweron_flag); */
|
||||
if (key_poweron_flag) {
|
||||
if (key_event == KEY_EVENT_UP) {
|
||||
clear_key_poweron_flag();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (key_event_remap(&e)) {
|
||||
sys_event_notify(&e);
|
||||
#if TCFG_KEY_TONE_EN
|
||||
audio_key_tone_play();
|
||||
#endif
|
||||
}
|
||||
_scan_end:
|
||||
scan_para->last_key = cur_key_value;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//wakeup callback
|
||||
void key_active_set(u8 port)
|
||||
{
|
||||
is_key_active = 35; //35*10Ms
|
||||
}
|
||||
|
||||
//=======================================================//
|
||||
// 按键初始化函数: 初始化所有注册的按键驱动
|
||||
//=======================================================//
|
||||
int key_driver_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
#if TCFG_IOKEY_ENABLE
|
||||
extern const struct iokey_platform_data iokey_data;
|
||||
extern struct key_driver_para iokey_scan_para;
|
||||
err = iokey_init(&iokey_data);
|
||||
#ifdef TCFG_IOKEY_TIME_REDEFINE
|
||||
extern struct key_driver_para iokey_scan_user_para;
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&iokey_scan_user_para, key_driver_scan, iokey_scan_user_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#else
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&iokey_scan_para, key_driver_scan, iokey_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TCFG_ADKEY_ENABLE
|
||||
#ifdef CONFIG_ICRECORDER_CASE_ENABLE
|
||||
extern multi_adkey_init(const struct adkey_platform_data * multi_adkey_data);
|
||||
extern const struct adkey_platform_data multi_adkey_data[];
|
||||
extern struct key_driver_para multi_adkey_scan_para;
|
||||
err = multi_adkey_init(multi_adkey_data);
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&multi_adkey_scan_para, key_driver_scan, multi_adkey_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#else
|
||||
extern const struct adkey_platform_data adkey_data;
|
||||
extern struct key_driver_para adkey_scan_para;
|
||||
err = adkey_init(&adkey_data);
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&adkey_scan_para, key_driver_scan, adkey_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if TCFG_IRKEY_ENABLE
|
||||
extern const struct irkey_platform_data irkey_data;
|
||||
extern struct key_driver_para irkey_scan_para;
|
||||
err = irkey_init(&irkey_data);
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&irkey_scan_para, key_driver_scan, irkey_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TCFG_TOUCH_KEY_ENABLE
|
||||
extern const struct touch_key_platform_data touch_key_data;
|
||||
extern struct key_driver_para touch_key_scan_para;
|
||||
err = touch_key_init(&touch_key_data);
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&touch_key_scan_para, key_driver_scan, touch_key_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TCFG_ADKEY_RTCVDD_ENABLE
|
||||
extern const struct adkey_rtcvdd_platform_data adkey_rtcvdd_data;
|
||||
extern struct key_driver_para adkey_rtcvdd_scan_para;
|
||||
err = adkey_rtcvdd_init(&adkey_rtcvdd_data);
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&adkey_rtcvdd_scan_para, key_driver_scan, adkey_rtcvdd_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TCFG_RDEC_KEY_ENABLE
|
||||
extern const struct rdec_platform_data rdec_key_data;
|
||||
extern struct key_driver_para rdec_key_scan_para;
|
||||
err = rdec_key_init(&rdec_key_data);
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&rdec_key_scan_para, key_driver_scan, rdec_key_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TCFG_CTMU_TOUCH_KEY_ENABLE
|
||||
#include "asm/ctmu.h"
|
||||
extern const struct ctmu_touch_key_platform_data ctmu_touch_key_data;
|
||||
extern struct key_driver_para ctmu_touch_key_scan_para;
|
||||
extern int ctmu_touch_key_init(const struct ctmu_touch_key_platform_data * ctmu_touch_key_data);
|
||||
err = ctmu_touch_key_init(&ctmu_touch_key_data);
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&ctmu_touch_key_scan_para, key_driver_scan, ctmu_touch_key_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */
|
||||
|
||||
#if TCFG_SLIDE_KEY_ENABLE
|
||||
extern const struct slidekey_platform_data slidekey_data;
|
||||
extern int slidekey_init(const struct slidekey_platform_data * slidekey_data);
|
||||
err = slidekey_init(&slidekey_data);
|
||||
if (err == 0) {
|
||||
}
|
||||
#endif//TCFG_SLIDE_KEY_ENABLE
|
||||
|
||||
#if TCFG_6083_ADKEY_ENABLE
|
||||
extern int adkey_init_6083();
|
||||
err = adkey_init_6083();
|
||||
if (err == 0) {
|
||||
}
|
||||
#endif
|
||||
#if TCFG_TENT600_KEY_ENABLE
|
||||
extern const struct tent600_key_platform_data key_data ;
|
||||
extern struct key_driver_para tent600_key_scan_para;
|
||||
err = tent600_key_init(&key_data);
|
||||
if (err == 0) {
|
||||
sys_s_hi_timer_add((void *)&tent600_key_scan_para, key_driver_scan, tent600_key_scan_para.scan_time); //注册按键扫描定时器
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 key_idle_query(void)
|
||||
{
|
||||
return !is_key_active;
|
||||
}
|
||||
#if ((!TCFG_LP_TOUCH_KEY_ENABLE) && (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE))
|
||||
REGISTER_LP_TARGET(key_lp_target) = {
|
||||
.name = "key",
|
||||
.is_idle = key_idle_query,
|
||||
};
|
||||
#endif /* #if !TCFG_LP_TOUCH_KEY_ENABLE */
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "touch_key.h"
|
||||
#include "key_driver.h"
|
||||
#include "app_config.h"
|
||||
|
||||
|
||||
#if TCFG_TOUCH_KEY_ENABLE
|
||||
|
||||
|
||||
/* =========== 触摸键使用说明 ============= */
|
||||
//1. 使用plcnt模块作计数;
|
||||
//2. 配置参数时, 在配置好时钟后, 需要调试no_touch_cnt和touch_cnt的值;
|
||||
|
||||
static const struct touch_key_platform_data *__this = NULL;
|
||||
|
||||
//按键驱动扫描参数列表
|
||||
struct key_driver_para touch_key_scan_para = {
|
||||
.scan_time = 10, //按键扫描频率, 单位: ms
|
||||
.last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY;
|
||||
.filter_time = 1, //按键消抖延时;
|
||||
.long_time = 75, //按键判定长按数量
|
||||
.hold_time = (75 + 15), //按键判定HOLD数量
|
||||
.click_delay_time = 20, //按键被抬起后等待连击延时数量
|
||||
.key_type = KEY_DRIVER_TYPE_TOUCH,
|
||||
.get_value = touch_key_get_value,
|
||||
};
|
||||
|
||||
#define TOUCH_KEY_DEBUG 0
|
||||
|
||||
#if TOUCH_KEY_DEBUG
|
||||
#define touch_key_debug(fmt, ...) printf("[TOUCH] "fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define touch_key_debug(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
u8 touch_key_get_value(void)
|
||||
{
|
||||
u8 key = get_plcnt_value();
|
||||
|
||||
if (key != NO_KEY) {
|
||||
touch_key_debug("key = %d", key);
|
||||
return __this->port_list[key].key_value;
|
||||
}
|
||||
|
||||
return NO_KEY;
|
||||
}
|
||||
|
||||
|
||||
int touch_key_init(const struct touch_key_platform_data *touch_key_data)
|
||||
{
|
||||
__this = touch_key_data;
|
||||
printf("touch_key_init >>>> ");
|
||||
|
||||
return plcnt_init((void *)touch_key_data);
|
||||
}
|
||||
|
||||
|
||||
#endif /* #if TCFG_TOUCH_KEY_ENABLE */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "key_driver.h"
|
||||
#include "system/event.h"
|
||||
#include "asm/uart.h"
|
||||
#include "app_config.h"
|
||||
|
||||
extern int getbyte(char *c);
|
||||
|
||||
#if TCFG_UART_KEY_ENABLE
|
||||
|
||||
static int uart_key_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 uart_get_key_value(void)
|
||||
{
|
||||
char c;
|
||||
u8 key_value;
|
||||
|
||||
if (getbyte(&c) == 0) {
|
||||
return NO_KEY;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'm':
|
||||
key_value = KEY_MODE;
|
||||
break;
|
||||
case 'u':
|
||||
key_value = KEY_UP;
|
||||
break;
|
||||
case 'd':
|
||||
key_value = KEY_DOWN;
|
||||
break;
|
||||
case 'o':
|
||||
key_value = KEY_OK;
|
||||
break;
|
||||
case 'e':
|
||||
key_value = KEY_MENU;
|
||||
break;
|
||||
default:
|
||||
key_value = NO_KEY;
|
||||
break;
|
||||
}
|
||||
|
||||
return key_value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* #if TCFG_UART_KEY_ENABLE */
|
||||
|
||||
@@ -0,0 +1,708 @@
|
||||
#include "includes.h"
|
||||
#include "app_config.h"
|
||||
#include "norflash_sfc.h"
|
||||
|
||||
#if (defined(TCFG_NORFLASH_SFC_DEV_ENABLE) && TCFG_NORFLASH_SFC_DEV_ENABLE)
|
||||
|
||||
#undef LOG_TAG_CONST
|
||||
#define LOG_TAG "[FLASH_SFC]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#define MAX_NORFLASH_PART_NUM 4
|
||||
|
||||
struct norflash_partition {
|
||||
const char *name;
|
||||
u32 start_addr;
|
||||
u32 size;
|
||||
struct device device;
|
||||
};
|
||||
|
||||
static struct norflash_partition nor_part[MAX_NORFLASH_PART_NUM];
|
||||
|
||||
struct norflash_info {
|
||||
u32 flash_id;
|
||||
u32 flash_capacity;
|
||||
int spi_num;
|
||||
int spi_err;
|
||||
u8 spi_cs_io;
|
||||
u8 spi_r_width;
|
||||
u8 part_num;
|
||||
u8 open_cnt;
|
||||
struct norflash_partition *const part_list;
|
||||
OS_MUTEX mutex;
|
||||
u32 max_end_addr;
|
||||
};
|
||||
|
||||
static struct norflash_info _norflash = {
|
||||
.spi_num = (int) - 1,
|
||||
.part_list = nor_part,
|
||||
};
|
||||
|
||||
static int _norflash_read(u32 addr, u8 *buf, u32 len, u8 cache);
|
||||
static int _norflash_eraser(u8 eraser, u32 addr);
|
||||
static void _norflash_cache_sync_timer(void *priv);
|
||||
static int _norflash_write_pages(u32 addr, u8 *buf, u32 len);
|
||||
|
||||
static struct norflash_partition *norflash_find_part(const char *name)
|
||||
{
|
||||
struct norflash_partition *part = NULL;
|
||||
u32 idx;
|
||||
for (idx = 0; idx < MAX_NORFLASH_PART_NUM; idx++) {
|
||||
part = &_norflash.part_list[idx];
|
||||
if (part->name == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(part->name, name)) {
|
||||
return part;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct norflash_partition *norflash_new_part(const char *name, u32 addr, u32 size)
|
||||
{
|
||||
struct norflash_partition *part;
|
||||
u32 idx;
|
||||
for (idx = 0; idx < MAX_NORFLASH_PART_NUM; idx++) {
|
||||
part = &_norflash.part_list[idx];
|
||||
if (part->name == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (part->name != NULL) {
|
||||
log_error("create norflash part fail\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(part, 0, sizeof(*part));
|
||||
part->name = name;
|
||||
part->start_addr = addr;
|
||||
part->size = size;
|
||||
if (part->start_addr + part->size > _norflash.max_end_addr) {
|
||||
_norflash.max_end_addr = part->start_addr + part->size;
|
||||
}
|
||||
_norflash.part_num++;
|
||||
return part;
|
||||
}
|
||||
|
||||
static void norflash_delete_part(const char *name)
|
||||
{
|
||||
struct norflash_partition *part;
|
||||
u32 idx;
|
||||
for (idx = 0; idx < MAX_NORFLASH_PART_NUM; idx++) {
|
||||
part = &_norflash.part_list[idx];
|
||||
if (part->name == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(part->name, name)) {
|
||||
part->name = NULL;
|
||||
_norflash.part_num--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int norflash_verify_part(struct norflash_partition *p)
|
||||
{
|
||||
struct norflash_partition *part = NULL;
|
||||
u32 idx;
|
||||
for (idx = 0; idx < MAX_NORFLASH_PART_NUM; idx++) {
|
||||
part = &_norflash.part_list[idx];
|
||||
if (part->name == NULL) {
|
||||
continue;
|
||||
}
|
||||
if ((p->start_addr >= part->start_addr) && (p->start_addr < part->start_addr + part->size)) {
|
||||
if (strcmp(p->name, part->name) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define FLASH_CACHE_ENABLE 1
|
||||
|
||||
#if FLASH_CACHE_ENABLE
|
||||
static u32 flash_cache_addr;
|
||||
static u8 *flash_cache_buf = NULL; //缓存4K的数据,与flash里的数据一样。
|
||||
static u8 flash_cache_is_dirty;
|
||||
static u16 flash_cache_timer;
|
||||
|
||||
#define FLASH_CACHE_SYNC_T_INTERVAL 60
|
||||
|
||||
static int _check_0xff(u8 *buf, u32 len)
|
||||
{
|
||||
for (u32 i = 0; i < len; i ++) {
|
||||
if ((*(buf + i)) != 0xff) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static u32 _pow(u32 num, int n)
|
||||
{
|
||||
u32 powint = 1;
|
||||
int i;
|
||||
for (i = 1; i <= n; i++) {
|
||||
powint *= num;
|
||||
}
|
||||
return powint;
|
||||
}
|
||||
|
||||
static u32 _norflash_read_id()
|
||||
{
|
||||
return sfc_spi_read_id();
|
||||
}
|
||||
|
||||
static int _norflash_init(const char *name, struct norflash_sfc_dev_platform_data *pdata)
|
||||
{
|
||||
log_info("norflash_sfc_init >>>>");
|
||||
|
||||
struct norflash_partition *part;
|
||||
if (_norflash.spi_num == (int) - 1) {
|
||||
//_norflash.spi_num = pdata->spi_hw_num;
|
||||
_norflash.flash_id = 0;
|
||||
_norflash.flash_capacity = 0;
|
||||
os_mutex_create(&_norflash.mutex);
|
||||
_norflash.max_end_addr = 0;
|
||||
_norflash.part_num = 0;
|
||||
sfc_spi_init(pdata->sfc_spi_pdata);
|
||||
}
|
||||
|
||||
part = norflash_find_part(name);
|
||||
|
||||
if (!part) {
|
||||
part = norflash_new_part(name, pdata->start_addr, pdata->size);
|
||||
ASSERT(part, "not enough norflash partition memory in array\n");
|
||||
ASSERT(norflash_verify_part(part) == 0, "norflash partition %s overlaps\n", name);
|
||||
log_info("norflash new partition %s\n", part->name);
|
||||
} else {
|
||||
ASSERT(0, "norflash partition name already exists\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clock_critical_enter()
|
||||
{
|
||||
|
||||
}
|
||||
static void clock_critical_exit()
|
||||
{
|
||||
/* if (!(_norflash.flash_id == 0 || _norflash.flash_id == 0xffff)) { */
|
||||
/* spi_set_baud(_norflash.spi_num, spi_get_baud(_norflash.spi_num)); */
|
||||
/* } */
|
||||
}
|
||||
CLOCK_CRITICAL_HANDLE_REG(spi_norflash, clock_critical_enter, clock_critical_exit);
|
||||
|
||||
static int _norflash_open(void *arg)
|
||||
{
|
||||
int reg = 0;
|
||||
os_mutex_pend(&_norflash.mutex, 0);
|
||||
log_info("norflash open\n");
|
||||
if (!_norflash.open_cnt) {
|
||||
_norflash.flash_id = _norflash_read_id();
|
||||
|
||||
log_info("norflash_read_id: 0x%x\n", _norflash.flash_id);
|
||||
if ((_norflash.flash_id == 0) || (_norflash.flash_id == 0xffffff)) {
|
||||
log_error("read norflash id error !\n");
|
||||
reg = -ENODEV;
|
||||
goto __exit;
|
||||
}
|
||||
_norflash.flash_capacity = 64 * _pow(2, (_norflash.flash_id & 0xff) - 0x10) * 1024;
|
||||
log_info("norflash_capacity: 0x%x\n", _norflash.flash_capacity);
|
||||
|
||||
#if FLASH_CACHE_ENABLE
|
||||
flash_cache_buf = (u8 *)malloc(4096);
|
||||
ASSERT(flash_cache_buf, "flash_cache_buf is not ok\n");
|
||||
flash_cache_addr = 4096;//先给一个大于4096的数
|
||||
_norflash_read(0, flash_cache_buf, 4096, 1);
|
||||
flash_cache_addr = 0;
|
||||
#endif
|
||||
log_info("norflash open success !\n");
|
||||
}
|
||||
if (_norflash.flash_id == 0 || _norflash.flash_id == 0xffffff) {
|
||||
log_error("re-open norflash id error !\n");
|
||||
reg = -EFAULT;
|
||||
goto __exit;
|
||||
}
|
||||
ASSERT(_norflash.max_end_addr <= _norflash.flash_capacity, "max partition end address is greater than flash capacity\n");
|
||||
_norflash.open_cnt++;
|
||||
|
||||
__exit:
|
||||
os_mutex_post(&_norflash.mutex);
|
||||
return reg;
|
||||
}
|
||||
|
||||
int _norflash_close(void)
|
||||
{
|
||||
os_mutex_pend(&_norflash.mutex, 0);
|
||||
log_info("norflash close\n");
|
||||
if (_norflash.open_cnt) {
|
||||
_norflash.open_cnt--;
|
||||
}
|
||||
if (!_norflash.open_cnt) {
|
||||
#if FLASH_CACHE_ENABLE
|
||||
if (flash_cache_is_dirty) {
|
||||
flash_cache_is_dirty = 0;
|
||||
_norflash_eraser(IOCTL_ERASE_SECTOR, flash_cache_addr);
|
||||
_norflash_write_pages(flash_cache_addr, flash_cache_buf, 4096);
|
||||
}
|
||||
free(flash_cache_buf);
|
||||
flash_cache_buf = NULL;
|
||||
#endif
|
||||
log_info("norflash close done\n");
|
||||
}
|
||||
os_mutex_post(&_norflash.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _norflash_read(u32 addr, u8 *buf, u32 len, u8 cache)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = sfc_spi_read(addr, buf, len);
|
||||
if (ret != len) {
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _norflash_write_pages(u32 addr, u8 *buf, u32 len)
|
||||
{
|
||||
/* y_printf("flash write addr = %d, num = %d\n", addr, len); */
|
||||
int ret = 0;
|
||||
ret = sfc_spi_write_pages(addr, buf, len);
|
||||
if (ret != len) {
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if FLASH_CACHE_ENABLE
|
||||
static void _norflash_cache_sync_timer(void *priv)
|
||||
{
|
||||
int reg = 0;
|
||||
os_mutex_pend(&_norflash.mutex, 0);
|
||||
if (flash_cache_is_dirty) {
|
||||
flash_cache_is_dirty = 0;
|
||||
reg = _norflash_eraser(IOCTL_ERASE_SECTOR, flash_cache_addr);
|
||||
if (reg) {
|
||||
goto __exit;
|
||||
}
|
||||
reg = _norflash_write_pages(flash_cache_addr, flash_cache_buf, 4096);
|
||||
}
|
||||
if (flash_cache_timer) {
|
||||
sys_timeout_del(flash_cache_timer);
|
||||
flash_cache_timer = 0;
|
||||
}
|
||||
__exit:
|
||||
os_mutex_post(&_norflash.mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
int _norflash_write(u32 addr, void *buf, u32 len, u8 cache)
|
||||
{
|
||||
int reg = 0;
|
||||
os_mutex_pend(&_norflash.mutex, 0);
|
||||
|
||||
u8 *w_buf = (u8 *)buf;
|
||||
u32 w_len = len;
|
||||
|
||||
/* y_printf("flash write addr = %d, num = %d\n", addr, len); */
|
||||
#if FLASH_CACHE_ENABLE
|
||||
if (!cache) {
|
||||
reg = _norflash_write_pages(addr, w_buf, w_len);
|
||||
goto __exit;
|
||||
}
|
||||
u32 align_addr = addr / 4096 * 4096;
|
||||
u32 align_len = 4096 - (addr - align_addr);
|
||||
align_len = w_len > align_len ? align_len : w_len;
|
||||
if (align_addr != flash_cache_addr) {
|
||||
if (flash_cache_is_dirty) {
|
||||
flash_cache_is_dirty = 0;
|
||||
reg = _norflash_eraser(IOCTL_ERASE_SECTOR, flash_cache_addr);
|
||||
if (reg) {
|
||||
line_inf;
|
||||
goto __exit;
|
||||
}
|
||||
reg = _norflash_write_pages(flash_cache_addr, flash_cache_buf, 4096);
|
||||
if (reg) {
|
||||
line_inf;
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
_norflash_read(align_addr, flash_cache_buf, 4096, 0);
|
||||
flash_cache_addr = align_addr;
|
||||
}
|
||||
memcpy(flash_cache_buf + (addr - align_addr), w_buf, align_len);
|
||||
if ((addr + align_len) % 4096) {
|
||||
flash_cache_is_dirty = 1;
|
||||
if (flash_cache_timer) {
|
||||
sys_timer_re_run(flash_cache_timer);
|
||||
} else {
|
||||
flash_cache_timer = sys_timeout_add(0, _norflash_cache_sync_timer, FLASH_CACHE_SYNC_T_INTERVAL);
|
||||
}
|
||||
} else {
|
||||
flash_cache_is_dirty = 0;
|
||||
reg = _norflash_eraser(IOCTL_ERASE_SECTOR, align_addr);
|
||||
if (reg) {
|
||||
line_inf;
|
||||
goto __exit;
|
||||
}
|
||||
reg = _norflash_write_pages(align_addr, flash_cache_buf, 4096);
|
||||
if (reg) {
|
||||
line_inf;
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
addr += align_len;
|
||||
w_buf += align_len;
|
||||
w_len -= align_len;
|
||||
while (w_len) {
|
||||
u32 cnt = w_len > 4096 ? 4096 : w_len;
|
||||
_norflash_read(addr, flash_cache_buf, 4096, 0);
|
||||
flash_cache_addr = addr;
|
||||
memcpy(flash_cache_buf, w_buf, cnt);
|
||||
if ((addr + cnt) % 4096) {
|
||||
flash_cache_is_dirty = 1;
|
||||
if (flash_cache_timer) {
|
||||
sys_timer_re_run(flash_cache_timer);
|
||||
} else {
|
||||
flash_cache_timer = sys_timeout_add(0, _norflash_cache_sync_timer, FLASH_CACHE_SYNC_T_INTERVAL);
|
||||
}
|
||||
} else {
|
||||
flash_cache_is_dirty = 0;
|
||||
reg = _norflash_eraser(IOCTL_ERASE_SECTOR, addr);
|
||||
if (reg) {
|
||||
line_inf;
|
||||
goto __exit;
|
||||
}
|
||||
reg = _norflash_write_pages(addr, flash_cache_buf, 4096);
|
||||
if (reg) {
|
||||
line_inf;
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
addr += cnt;
|
||||
w_buf += cnt;
|
||||
w_len -= cnt;
|
||||
}
|
||||
#else
|
||||
reg = _norflash_write_pages(addr, w_buf, w_len);
|
||||
#endif
|
||||
__exit:
|
||||
os_mutex_post(&_norflash.mutex);
|
||||
return reg;
|
||||
}
|
||||
|
||||
static int _norflash_eraser(u8 eraser, u32 addr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = sfc_spi_eraser(eraser, addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _norflash_ioctl(u32 cmd, u32 arg, u32 unit, void *_part)
|
||||
{
|
||||
int reg = 0;
|
||||
struct norflash_partition *part = _part;
|
||||
os_mutex_pend(&_norflash.mutex, 0);
|
||||
switch (cmd) {
|
||||
case IOCTL_GET_STATUS:
|
||||
*(u32 *)arg = 1;
|
||||
break;
|
||||
case IOCTL_GET_ID:
|
||||
*((u32 *)arg) = _norflash.flash_id;
|
||||
break;
|
||||
case IOCTL_GET_CAPACITY:
|
||||
if (_norflash.flash_capacity == 0) {
|
||||
*(u32 *)arg = 0;
|
||||
} else if (_norflash.part_num == 1 && part->start_addr == 0) {
|
||||
*(u32 *)arg = _norflash.flash_capacity / unit;
|
||||
} else {
|
||||
*(u32 *)arg = part->size / unit;
|
||||
}
|
||||
break;
|
||||
case IOCTL_GET_BLOCK_SIZE:
|
||||
*(u32 *)arg = 512;
|
||||
break;
|
||||
case IOCTL_ERASE_PAGE:
|
||||
reg = _norflash_eraser(IOCTL_ERASE_PAGE, arg * unit + part->start_addr);
|
||||
break;
|
||||
case IOCTL_ERASE_SECTOR:
|
||||
reg = _norflash_eraser(IOCTL_ERASE_SECTOR, arg * unit + part->start_addr);
|
||||
break;
|
||||
case IOCTL_ERASE_BLOCK:
|
||||
reg = _norflash_eraser(IOCTL_ERASE_BLOCK, arg * unit + part->start_addr);
|
||||
break;
|
||||
case IOCTL_ERASE_CHIP:
|
||||
reg = _norflash_eraser(IOCTL_ERASE_CHIP, 0);
|
||||
break;
|
||||
case IOCTL_FLUSH:
|
||||
break;
|
||||
case IOCTL_CMD_RESUME:
|
||||
break;
|
||||
case IOCTL_CMD_SUSPEND:
|
||||
break;
|
||||
case IOCTL_GET_PART_INFO:
|
||||
u32 *info = (u32 *)arg;
|
||||
u32 *start_addr = &info[0];
|
||||
u32 *part_size = &info[1];
|
||||
*start_addr = part->start_addr;
|
||||
*part_size = part->size;
|
||||
break;
|
||||
default:
|
||||
reg = -EINVAL;
|
||||
break;
|
||||
}
|
||||
__exit:
|
||||
os_mutex_post(&_norflash.mutex);
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************************
|
||||
* 挂钩 device_api
|
||||
************************************************************************************/
|
||||
|
||||
static int norflash_sfc_dev_init(const struct dev_node *node, void *arg)
|
||||
{
|
||||
struct norflash_sfc_dev_platform_data *pdata = arg;
|
||||
|
||||
return _norflash_init(node->name, pdata);
|
||||
}
|
||||
|
||||
static int norflash_sfc_dev_open(const char *name, struct device **device, void *arg)
|
||||
{
|
||||
struct norflash_partition *part;
|
||||
part = norflash_find_part(name);
|
||||
if (!part) {
|
||||
log_error("no norflash partition is found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
*device = &part->device;
|
||||
(*device)->private_data = part;
|
||||
if (atomic_read(&part->device.ref)) {
|
||||
return 0;
|
||||
}
|
||||
return _norflash_open(arg);
|
||||
}
|
||||
static int norflash_sfc_dev_close(struct device *device)
|
||||
{
|
||||
return _norflash_close();
|
||||
}
|
||||
static int norflash_sfc_dev_read(struct device *device, void *buf, u32 len, u32 offset)
|
||||
{
|
||||
int reg;
|
||||
/* printf("flash read sector = %d, num = %d\n", offset, len); */
|
||||
offset = offset * 512;
|
||||
len = len * 512;
|
||||
struct norflash_partition *part;
|
||||
part = (struct norflash_partition *)device->private_data;
|
||||
if (!part) {
|
||||
log_error("norflash partition invalid\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
offset += part->start_addr;
|
||||
reg = _norflash_read(offset, buf, len, 1);
|
||||
if (reg) {
|
||||
r_printf(">>>[r error]:\n");
|
||||
len = 0;
|
||||
}
|
||||
|
||||
len = len / 512;
|
||||
return len;
|
||||
}
|
||||
static int norflash_sfc_dev_write(struct device *device, void *buf, u32 len, u32 offset)
|
||||
{
|
||||
/* printf("flash write sector = %d, num = %d\n", offset, len); */
|
||||
int reg = 0;
|
||||
offset = offset * 512;
|
||||
len = len * 512;
|
||||
struct norflash_partition *part = device->private_data;
|
||||
if (!part) {
|
||||
log_error("norflash partition invalid\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
offset += part->start_addr;
|
||||
reg = _norflash_write(offset, buf, len, 1);
|
||||
if (reg) {
|
||||
r_printf(">>>[w error]:\n");
|
||||
len = 0;
|
||||
}
|
||||
len = len / 512;
|
||||
return len;
|
||||
}
|
||||
static bool norflash_sfc_dev_online(const struct dev_node *node)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
static int norflash_sfc_dev_ioctl(struct device *device, u32 cmd, u32 arg)
|
||||
{
|
||||
struct norflash_partition *part = device->private_data;
|
||||
if (!part) {
|
||||
log_error("norflash partition invalid\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
return _norflash_ioctl(cmd, arg, 512, part);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. 外部调用时以512字节为单位的地址和长度,且需要驱动write自己处理擦除,
|
||||
* 请使用norflash_sfc_dev_ops接口,否则使用本文件内的其他ops
|
||||
*
|
||||
* 2. 如果不需要驱动自己处理擦除,可以把宏FLASH_CACHE_ENABLE清零,或者把
|
||||
* norflash_sfc_dev_read()里面调用的_norflash_read()的实参cache填0,
|
||||
* norflash_sfc_dev_write()同理
|
||||
*
|
||||
* 3. norflash_sfc_dev_ops可以被多个设备名注册,每个设备名被认为是不同分区,所以
|
||||
* 需要填不同的分区起始地址和大小,若分区地址有重叠或者最大分区结束地址大于
|
||||
* flash容量,会触发ASSERT()
|
||||
*
|
||||
* 4. 关于IOCTL_GET_CAPACITY,有多个分区注册时返回分区的大小,如果只注册了1
|
||||
* 个分区,分区起始地址 == 0时返回flash容量,起始地址 != 0时返回分区大小,
|
||||
* norflash_sfc_dev_ops返回的长度以512字节为单位
|
||||
*
|
||||
* 5. 本文件内的各个ops可以同时使用
|
||||
*/
|
||||
//按512字节单位读写
|
||||
const struct device_operations norflash_sfc_dev_ops = {
|
||||
.init = norflash_sfc_dev_init,
|
||||
.online = norflash_sfc_dev_online,
|
||||
.open = norflash_sfc_dev_open,
|
||||
.read = norflash_sfc_dev_read,
|
||||
.write = norflash_sfc_dev_write,
|
||||
.ioctl = norflash_sfc_dev_ioctl,
|
||||
.close = norflash_sfc_dev_close,
|
||||
};
|
||||
|
||||
|
||||
static int norflash_sfc_fs_dev_init(const struct dev_node *node, void *arg)
|
||||
{
|
||||
struct norflash_sfc_dev_platform_data *pdata = arg;
|
||||
|
||||
return _norflash_init(node->name, pdata);
|
||||
}
|
||||
|
||||
static int norflash_sfc_fs_dev_open(const char *name, struct device **device, void *arg)
|
||||
{
|
||||
struct norflash_partition *part;
|
||||
part = norflash_find_part(name);
|
||||
if (!part) {
|
||||
log_error("no norflash partition is found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
*device = &part->device;
|
||||
(*device)->private_data = part;
|
||||
if (atomic_read(&part->device.ref)) {
|
||||
return 0;
|
||||
}
|
||||
return _norflash_open(arg);
|
||||
}
|
||||
static int norflash_sfc_fs_dev_close(struct device *device)
|
||||
{
|
||||
return _norflash_close();
|
||||
}
|
||||
static int norflash_sfc_fs_dev_read(struct device *device, void *buf, u32 len, u32 offset)
|
||||
{
|
||||
int reg;
|
||||
/* printf("flash read sector = %d, num = %d\n", offset, len); */
|
||||
struct norflash_partition *part;
|
||||
part = (struct norflash_partition *)device->private_data;
|
||||
if (!part) {
|
||||
log_error("norflash partition invalid\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
offset += part->start_addr;
|
||||
reg = _norflash_read(offset, buf, len, 0);
|
||||
if (reg) {
|
||||
r_printf(">>>[r error]:\n");
|
||||
len = 0;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int norflash_sfc_fs_dev_write(struct device *device, void *buf, u32 len, u32 offset)
|
||||
{
|
||||
//printf("flash write addr = 0x%x, len = 0x%x\n", offset, len);
|
||||
int reg = 0;
|
||||
struct norflash_partition *part = device->private_data;
|
||||
if (!part) {
|
||||
log_error("norflash partition invalid\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
offset += part->start_addr;
|
||||
reg = _norflash_write(offset, buf, len, 0);
|
||||
if (reg) {
|
||||
r_printf(">>>[w error]:\n");
|
||||
len = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static bool norflash_sfc_fs_dev_online(const struct dev_node *node)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int norflash_sfc_fs_dev_ioctl(struct device *device, u32 cmd, u32 arg)
|
||||
{
|
||||
struct norflash_partition *part = device->private_data;
|
||||
if (!part) {
|
||||
log_error("norflash partition invalid\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
return _norflash_ioctl(cmd, arg, 1, part);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. 外部调用时以1字节为单位的地址和长度,且驱动write自己不处理擦除,
|
||||
* 请使用norflash_sfc_fs_dev_ops接口,否则使用本文件内的其他ops。注意:有些文件系
|
||||
* 统需要满足这个条件的驱动,如果期望修改成驱动内部处理擦除,需要测试所
|
||||
* 有关联的文件系统是否支持,或者新建一个符合需求的ops
|
||||
*
|
||||
* 2. 如果需要驱动自己处理擦除,需要把宏FLASH_CACHE_ENABLE置1,且
|
||||
* norflash_sfc_fs_dev_read()里面调用的_norflash_read()的实参cache填1,
|
||||
* norflash_sfc_fs_dev_write()同理
|
||||
*
|
||||
* 3. norflash_sfc_fs_dev_ops可以被多个设备名注册,每个设备名被认为是不同分区,所以
|
||||
* 需要填不同的分区起始地址和大小,若分区地址有重叠或者最大分区结束地址大于
|
||||
* flash容量,会触发ASSERT()
|
||||
*
|
||||
* 4. 关于IOCTL_GET_CAPACITY,有多个分区注册时返回分区的大小,如果只注册了1
|
||||
* 个分区,分区起始地址 == 0时返回flash容量,起始地址 != 0时返回分区大小
|
||||
* norflash_sfc_fs_dev_ops返回的长度以1字节为单位
|
||||
*
|
||||
* 5. 本文件内的各个ops可以同时使用
|
||||
*/
|
||||
//按1字节单位读写
|
||||
const struct device_operations norflash_sfc_fs_dev_ops = {
|
||||
.init = norflash_sfc_fs_dev_init,
|
||||
.online = norflash_sfc_fs_dev_online,
|
||||
.open = norflash_sfc_fs_dev_open,
|
||||
.read = norflash_sfc_fs_dev_read,
|
||||
.write = norflash_sfc_fs_dev_write,
|
||||
.ioctl = norflash_sfc_fs_dev_ioctl,
|
||||
.close = norflash_sfc_fs_dev_close,
|
||||
};
|
||||
|
||||
/*
|
||||
* 对ops的读写单位有另外需求,或者驱动内部是否支持擦除,可以参照上面的ops,
|
||||
* 不同条件自由组合,建立新的ops
|
||||
*/
|
||||
|
||||
#endif /* #if (defined(TCFG_NORFLASH_SFC_DEV_ENABLE) && TCFG_NORFLASH_SFC_DEV_ENABLE) */
|
||||
@@ -0,0 +1,490 @@
|
||||
#include "usb/device/usb_stack.h"
|
||||
#include "usb/usb_config.h"
|
||||
#include "usb/device/cdc.h"
|
||||
#include "app_config.h"
|
||||
#include "os/os_api.h"
|
||||
#include "cdc_defs.h" //need redefine __u8, __u16, __u32
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
|
||||
|
||||
struct usb_cdc_gadget {
|
||||
u8 *cdc_buffer;
|
||||
u8 *bulk_ep_out_buffer;
|
||||
u8 *bulk_ep_in_buffer;
|
||||
void *priv;
|
||||
int (*output)(void *priv, u8 *obuf, u32 olen);
|
||||
void (*wakeup_handler)(struct usb_device_t *usb_device);
|
||||
OS_MUTEX mutex_data;
|
||||
#if CDC_INTR_EP_ENABLE
|
||||
OS_MUTEX mutex_intr;
|
||||
u8 *intr_ep_in_buffer;
|
||||
#endif
|
||||
u8 bmTransceiver;
|
||||
u8 subtype_data[8];
|
||||
};
|
||||
|
||||
static struct usb_cdc_gadget *cdc_hdl;
|
||||
|
||||
#if USB_MALLOC_ENABLE
|
||||
|
||||
#else
|
||||
static u8 _cdc_buffer[MAXP_SIZE_CDC_BULKOUT] SEC(.cdc_var) __attribute__((aligned(4)));
|
||||
static struct usb_cdc_gadget _cdc_hdl SEC(.cdc_var);
|
||||
#endif
|
||||
|
||||
static const u8 cdc_virtual_comport_desc[] = {
|
||||
//IAD Descriptor
|
||||
0x08, //bLength
|
||||
0x0b, //bDescriptorType
|
||||
0x00, //bFirstInterface
|
||||
0x02, //bInterfaceCount
|
||||
0x02, //bFunctionClass, Comunication and CDC control
|
||||
0x02, //bFunctionSubClass
|
||||
0x01, //bFunctionProtocol
|
||||
0x00, //iFunction
|
||||
//Interface 0, Alt 0
|
||||
0x09, //Length
|
||||
0x04, //DescriptorType:Interface
|
||||
0x00, //InterfaceNum
|
||||
0x00, //AlternateSetting
|
||||
0x01, //NumEndpoint
|
||||
0x02, //InterfaceClass, Communation and CDC control
|
||||
0x02, //InterfaceSubClass, Abstract Control Model
|
||||
0x01, //InterfaceProtocol, AT commands defined by ITU-T V.250 etc
|
||||
0x00, //Interface String
|
||||
//CDC Interface Descriptor
|
||||
0x05, //bLength
|
||||
0x24, //bDescriptorType
|
||||
0x00, //bDescriptorSubType, Header Functional Desc
|
||||
0x10, 0x01, //bcdCDC, version 1.10
|
||||
//CDC Interface Descriptor
|
||||
0x05, //bLength
|
||||
0x24, //bDescriptorType
|
||||
0x01, //bDescriptorSubType, Call Management Functional Descriptor
|
||||
0x03, //bmCapabilities, D7..D2 reversed
|
||||
// D7..D2 reversed
|
||||
// D1 sends/receives call management information only over a Data Class interface
|
||||
// D0 handle call management itself
|
||||
0x01, //bDataInterface
|
||||
//CDC Interface Descriptor
|
||||
0x04, //bLength
|
||||
0x24, //bDescriptorType
|
||||
0x02, //bDescriptorSubType, Abstract Control Management Functional Descriptor
|
||||
0x02, //bmCapabilities, D7..D2 reversed
|
||||
// D7..D4 reversed
|
||||
// D3 supports the notification Network_Connection
|
||||
// D2 not supports the request Send_Break
|
||||
// D1 supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State
|
||||
// D0 supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature
|
||||
//CDC Interface Descriptor
|
||||
0x05, //bLength
|
||||
0x24, //bDescriptorType
|
||||
0x06, //bDescriptorSubType, Union Functional Descriptor
|
||||
0x00, //bControlInterface
|
||||
0x01, //bSubordinateInterface[0]
|
||||
//Endpoint In
|
||||
0x07, //bLength
|
||||
0x05, //bDescritorType
|
||||
0x82, //bEndpointAddr
|
||||
0x03, //bmAttributes, interrupt
|
||||
0x08, 0x00, //wMaxPacketSize
|
||||
0x01, //bInterval, 1ms
|
||||
//Interface 1, Alt 0
|
||||
0x09, //Length
|
||||
0x04, //DescriptorType:Interface
|
||||
0x01, //InterfaceNum
|
||||
0x00, //AlternateSetting
|
||||
0x02, //NumEndpoint
|
||||
0x0a, //InterfaceClass, CDC Data
|
||||
0x00, //InterfaceSubClass
|
||||
0x00, //InterfaceProtocol
|
||||
0x00, //Interface String
|
||||
//Endpoint Out
|
||||
0x07, //bLength
|
||||
0x05, //bDescriptor
|
||||
0x02, //bEndpointAddr
|
||||
0x02, //bmAttributes, bulk
|
||||
0x40, 0x00, //wMaxPacketSize
|
||||
0x00, //bInterval
|
||||
//Endpoint In
|
||||
0x07, //bLength
|
||||
0x05, //bDescritorType
|
||||
0x83, //bEndpointAddr
|
||||
0x02, //bmAttributes, bulk
|
||||
0x40, 0x00, //wMaxPacketSize
|
||||
0x00, //bInterval
|
||||
};
|
||||
|
||||
static void cdc_endpoint_init(struct usb_device_t *usb_device, u32 itf);
|
||||
static u32 cdc_setup_rx(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req);
|
||||
|
||||
static void usb_cdc_line_coding_init(struct usb_cdc_line_coding *lc)
|
||||
{
|
||||
lc->dwDTERate = 460800;
|
||||
lc->bCharFormat = USB_CDC_1_STOP_BITS;
|
||||
lc->bParityType = USB_CDC_NO_PARITY;
|
||||
lc->bDataBits = 8;
|
||||
}
|
||||
|
||||
static void dump_line_coding(struct usb_cdc_line_coding *lc)
|
||||
{
|
||||
log_debug("dtw rate : %d", lc->dwDTERate);
|
||||
log_debug("stop bits : %d", lc->bCharFormat);
|
||||
log_debug("verify bits : %d", lc->bParityType);
|
||||
log_debug("data bits : %d", lc->bDataBits);
|
||||
}
|
||||
|
||||
static u32 cdc_setup(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
int recip_type;
|
||||
u32 len;
|
||||
|
||||
recip_type = ctrl_req->bRequestType & USB_TYPE_MASK;
|
||||
|
||||
switch (recip_type) {
|
||||
case USB_TYPE_CLASS:
|
||||
switch (ctrl_req->bRequest) {
|
||||
case USB_CDC_REQ_SET_LINE_CODING:
|
||||
log_debug("set line coding");
|
||||
usb_set_setup_recv(usb_device, cdc_setup_rx);
|
||||
break;
|
||||
case USB_CDC_REQ_GET_LINE_CODING:
|
||||
log_debug("get line codling");
|
||||
len = ctrl_req->wLength < sizeof(struct usb_cdc_line_coding) ?
|
||||
ctrl_req->wLength : sizeof(struct usb_cdc_line_coding);
|
||||
if (cdc_hdl == NULL) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
break;
|
||||
}
|
||||
usb_set_data_payload(usb_device, ctrl_req, cdc_hdl->subtype_data, len);
|
||||
dump_line_coding((struct usb_cdc_line_coding *)cdc_hdl->subtype_data);
|
||||
break;
|
||||
case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
|
||||
log_debug("set control line state - %d", ctrl_req->wValue);
|
||||
if (cdc_hdl) {
|
||||
/* if (ctrl_req->wValue & BIT(0)) { //DTR */
|
||||
cdc_hdl->bmTransceiver |= BIT(0);
|
||||
/* } else { */
|
||||
/* usb_slave->cdc->bmTransceiver &= ~BIT(0); */
|
||||
/* } */
|
||||
/* if (ctrl_req->wValue & BIT(1)) { //RTS */
|
||||
cdc_hdl->bmTransceiver |= BIT(1);
|
||||
/* } else { */
|
||||
/* usb_slave->cdc->bmTransceiver &= ~BIT(1); */
|
||||
/* } */
|
||||
cdc_hdl->bmTransceiver |= BIT(4); //cfg done
|
||||
}
|
||||
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
|
||||
//cdc_endpoint_init(usb_device, (ctrl_req->wIndex & USB_RECIP_MASK));
|
||||
break;
|
||||
default:
|
||||
log_error("unsupported class req");
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error("unsupported req type");
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 cdc_setup_rx(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
int recip_type;
|
||||
struct usb_cdc_line_coding *lc = 0;
|
||||
u32 len;
|
||||
u8 read_ep[8];
|
||||
|
||||
len = ctrl_req->wLength;
|
||||
usb_read_ep0(usb_id, read_ep, len);
|
||||
recip_type = ctrl_req->bRequestType & USB_TYPE_MASK;
|
||||
switch (recip_type) {
|
||||
case USB_TYPE_CLASS:
|
||||
switch (ctrl_req->bRequest) {
|
||||
case USB_CDC_REQ_SET_LINE_CODING:
|
||||
log_debug("USB_CDC_REQ_SET_LINE_CODING");
|
||||
if (cdc_hdl == NULL) {
|
||||
break;
|
||||
}
|
||||
if (len > sizeof(struct usb_cdc_line_coding)) {
|
||||
len = sizeof(struct usb_cdc_line_coding);
|
||||
}
|
||||
memcpy(cdc_hdl->subtype_data, read_ep, len);
|
||||
lc = (struct usb_cdc_line_coding *)cdc_hdl->subtype_data;
|
||||
dump_line_coding(lc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return USB_EP0_STAGE_SETUP;
|
||||
}
|
||||
|
||||
static void cdc_reset(struct usb_device_t *usb_device, u32 itf)
|
||||
{
|
||||
log_error("%s()", __func__);
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
#if USB_ROOT2
|
||||
usb_disable_ep(usb_id, CDC_DATA_EP_IN);
|
||||
#if CDC_INTR_EP_ENABLE
|
||||
usb_disable_ep(usb_id, CDC_INTR_EP_IN);
|
||||
#endif
|
||||
#else
|
||||
cdc_endpoint_init(usb_device, itf);
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 cdc_desc_config(const usb_dev usb_id, u8 *ptr, u32 *itf)
|
||||
{
|
||||
u8 *tptr;
|
||||
|
||||
tptr = ptr;
|
||||
memcpy(tptr, cdc_virtual_comport_desc, sizeof(cdc_virtual_comport_desc));
|
||||
//iad interface number
|
||||
tptr[2] = *itf;
|
||||
//control interface number
|
||||
tptr[8 + 2] = *itf;
|
||||
tptr[8 + 9 + 5 + 4] = *itf + 1;
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 3] = *itf;
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 4] = *itf + 1;
|
||||
//interrupt in ep
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 2] = USB_DIR_IN | CDC_INTR_EP_IN;
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 4] = MAXP_SIZE_CDC_INTRIN & 0xff;
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 5] = (MAXP_SIZE_CDC_INTRIN >> 8) & 0xff;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 6] = 4; //high-speed mode, 125x2^(4-1)=1ms
|
||||
#endif
|
||||
//data interface number
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 2] = *itf + 1;
|
||||
//bulk out ep
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 2] = CDC_DATA_EP_OUT;
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 4] = MAXP_SIZE_CDC_BULKOUT & 0xff;
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 5] = (MAXP_SIZE_CDC_BULKOUT >> 8) & 0xff;
|
||||
//bulk in ep
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 2] = USB_DIR_IN | CDC_DATA_EP_IN;
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 4] = MAXP_SIZE_CDC_BULKIN & 0xff;
|
||||
tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 5] = (MAXP_SIZE_CDC_BULKIN >> 8) & 0xff;
|
||||
tptr += sizeof(cdc_virtual_comport_desc);
|
||||
|
||||
if (usb_set_interface_hander(usb_id, *itf, cdc_setup) != *itf) {
|
||||
ASSERT(0, "cdc set interface_hander fail");
|
||||
}
|
||||
if (usb_set_reset_hander(usb_id, *itf, cdc_reset) != *itf) {
|
||||
|
||||
}
|
||||
*itf += 2;
|
||||
return (u32)(tptr - ptr);
|
||||
}
|
||||
|
||||
void cdc_set_wakeup_handler(void (*handle)(struct usb_device_t *usb_device))
|
||||
{
|
||||
if (cdc_hdl) {
|
||||
cdc_hdl->wakeup_handler = handle;
|
||||
}
|
||||
}
|
||||
|
||||
static void cdc_wakeup_handler(struct usb_device_t *usb_device, u32 ep)
|
||||
{
|
||||
if (cdc_hdl && cdc_hdl->wakeup_handler) {
|
||||
cdc_hdl->wakeup_handler(usb_device);
|
||||
}
|
||||
}
|
||||
|
||||
void cdc_set_output_handle(void *priv, int (*output_handler)(void *priv, u8 *buf, u32 len))
|
||||
{
|
||||
if (cdc_hdl) {
|
||||
cdc_hdl->output = output_handler;
|
||||
cdc_hdl->priv = priv;
|
||||
}
|
||||
}
|
||||
|
||||
static void cdc_intrrx(struct usb_device_t *usb_device, u32 ep)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
if (cdc_hdl == NULL) {
|
||||
return;
|
||||
}
|
||||
u8 *cdc_rx_buf = cdc_hdl->cdc_buffer;
|
||||
//由于bulk传输使用双缓冲,无法用usb_get_ep_buffer()知道是哪一个buffer,需要外部buffer接收数据
|
||||
u32 len = usb_g_bulk_read(usb_id, CDC_DATA_EP_OUT, cdc_rx_buf, MAXP_SIZE_CDC_BULKOUT, 0);
|
||||
if (cdc_hdl->output) {
|
||||
cdc_hdl->output(cdc_hdl->priv, cdc_rx_buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void cdc_endpoint_init(struct usb_device_t *usb_device, u32 itf)
|
||||
{
|
||||
ASSERT(cdc_hdl, "cdc not register");
|
||||
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
|
||||
usb_g_ep_config(usb_id, CDC_DATA_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_BULK,
|
||||
0, cdc_hdl->bulk_ep_in_buffer, MAXP_SIZE_CDC_BULKIN);
|
||||
|
||||
usb_g_ep_config(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK,
|
||||
1, cdc_hdl->bulk_ep_out_buffer, MAXP_SIZE_CDC_BULKOUT);
|
||||
/* usb_g_set_intr_hander(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, cdc_intrrx); */
|
||||
usb_g_set_intr_hander(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, cdc_wakeup_handler);
|
||||
usb_enable_ep(usb_id, CDC_DATA_EP_IN);
|
||||
|
||||
#if CDC_INTR_EP_ENABLE
|
||||
usb_g_ep_config(usb_id, CDC_INTR_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_INT,
|
||||
0, cdc_hdl->intr_ep_in_buffer, MAXP_SIZE_CDC_INTRIN);
|
||||
usb_enable_ep(usb_id, CDC_INTR_EP_IN);
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 cdc_read_data(const usb_dev usb_id, u8 *buf, u32 len)
|
||||
{
|
||||
u32 rxlen;
|
||||
if (cdc_hdl == NULL) {
|
||||
return 0;
|
||||
}
|
||||
u8 *cdc_rx_buf = cdc_hdl->cdc_buffer;
|
||||
os_mutex_pend(&cdc_hdl->mutex_data, 0);
|
||||
//由于bulk传输使用双缓冲,无法用usb_get_ep_buffer()知道是哪一个buffer,需要外部buffer接收数据
|
||||
rxlen = usb_g_bulk_read(usb_id, CDC_DATA_EP_OUT, cdc_rx_buf, MAXP_SIZE_CDC_BULKOUT, 0);
|
||||
rxlen = rxlen > len ? len : rxlen;
|
||||
if (rxlen > 0) {
|
||||
memcpy(buf, cdc_rx_buf, rxlen);
|
||||
}
|
||||
os_mutex_post(&cdc_hdl->mutex_data);
|
||||
return rxlen;
|
||||
}
|
||||
|
||||
u32 cdc_write_data(const usb_dev usb_id, u8 *buf, u32 len)
|
||||
{
|
||||
u32 txlen, offset;
|
||||
if (cdc_hdl == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if ((cdc_hdl->bmTransceiver & (BIT(1) | BIT(4))) != (BIT(1) | BIT(4))) {
|
||||
return 0;
|
||||
}
|
||||
offset = 0;
|
||||
os_mutex_pend(&cdc_hdl->mutex_data, 0);
|
||||
while (offset < len) {
|
||||
txlen = len - offset > MAXP_SIZE_CDC_BULKIN ?
|
||||
MAXP_SIZE_CDC_BULKIN : len - offset;
|
||||
txlen = usb_g_bulk_write(usb_id, CDC_DATA_EP_IN, buf + offset, txlen);
|
||||
if (txlen == 0) {
|
||||
break;
|
||||
}
|
||||
if ((cdc_hdl->bmTransceiver & (BIT(1) | BIT(4))) != (BIT(1) | BIT(4))) {
|
||||
break;
|
||||
}
|
||||
offset += txlen;
|
||||
}
|
||||
//当最后一包的包长等于maxpktsize,需要发一个0长包表示结束
|
||||
if ((offset % MAXP_SIZE_CDC_BULKIN) == 0) {
|
||||
usb_g_bulk_write(usb_id, CDC_DATA_EP_IN, NULL, 0);
|
||||
}
|
||||
os_mutex_post(&cdc_hdl->mutex_data);
|
||||
return offset;
|
||||
}
|
||||
|
||||
u32 cdc_write_inir(const usb_dev usb_id, u8 *buf, u32 len)
|
||||
{
|
||||
#if CDC_INTR_EP_ENABLE
|
||||
u32 txlen, offset;
|
||||
if (cdc_hdl == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if ((cdc_hdl->bmTransceiver & BIT(4)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
offset = 0;
|
||||
os_mutex_pend(&cdc_hdl->mutex_intr, 0);
|
||||
while (offset < len) {
|
||||
txlen = len - offset > MAXP_SIZE_CDC_INTRIN ?
|
||||
MAXP_SIZE_CDC_INTRIN : len - offset;
|
||||
txlen = usb_g_intr_write(usb_id, CDC_INTR_EP_IN, buf + offset, txlen);
|
||||
if (txlen == 0) {
|
||||
break;
|
||||
}
|
||||
if ((cdc_hdl->bmTransceiver & BIT(4)) == 0) {
|
||||
break;
|
||||
}
|
||||
offset += txlen;
|
||||
}
|
||||
os_mutex_post(&cdc_hdl->mutex_intr);
|
||||
return offset;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cdc_register(const usb_dev usb_id)
|
||||
{
|
||||
struct usb_cdc_line_coding *lc;
|
||||
/* log_info("%s() %d", __func__, __LINE__); */
|
||||
if (!cdc_hdl) {
|
||||
#if USB_MALLOC_ENABLE
|
||||
cdc_hdl = zalloc(sizeof(struct usb_cdc_gadget));
|
||||
if (!cdc_hdl) {
|
||||
log_error("cdc_register err 1");
|
||||
return;
|
||||
}
|
||||
cdc_hdl->cdc_buffer = malloc(MAXP_SIZE_CDC_BULKOUT);
|
||||
if (!cdc_hdl->cdc_buffer) {
|
||||
log_error("cdc_register err 2");
|
||||
goto __exit_err;
|
||||
}
|
||||
#else
|
||||
memset(&_cdc_hdl, 0, sizeof(struct usb_cdc_gadget));
|
||||
cdc_hdl = &_cdc_hdl;
|
||||
cdc_hdl->cdc_buffer = _cdc_buffer;
|
||||
#endif
|
||||
lc = (struct usb_cdc_line_coding *)cdc_hdl->subtype_data;
|
||||
usb_cdc_line_coding_init(lc);
|
||||
os_mutex_create(&cdc_hdl->mutex_data);
|
||||
|
||||
cdc_hdl->bulk_ep_in_buffer = usb_alloc_ep_dmabuffer(usb_id, CDC_DATA_EP_IN | USB_DIR_IN, MAXP_SIZE_CDC_BULKIN + MAXP_SIZE_CDC_BULKOUT);
|
||||
cdc_hdl->bulk_ep_out_buffer = cdc_hdl->bulk_ep_in_buffer + MAXP_SIZE_CDC_BULKIN;
|
||||
|
||||
#if CDC_INTR_EP_ENABLE
|
||||
os_mutex_create(&cdc_hdl->mutex_intr);
|
||||
cdc_hdl->intr_ep_in_buffer = usb_alloc_ep_dmabuffer(usb_id, CDC_INTR_EP_IN | USB_DIR_IN, MAXP_SIZE_CDC_INTRIN);
|
||||
#endif
|
||||
|
||||
}
|
||||
return;
|
||||
__exit_err:
|
||||
#if USB_MALLOC_ENABLE
|
||||
if (cdc_hdl->cdc_buffer) {
|
||||
free(cdc_hdl->cdc_buffer);
|
||||
}
|
||||
if (cdc_hdl) {
|
||||
free(cdc_hdl);
|
||||
}
|
||||
#endif
|
||||
cdc_hdl = NULL;
|
||||
}
|
||||
|
||||
void cdc_release(const usb_dev usb_id)
|
||||
{
|
||||
/* log_info("%s() %d", __func__, __LINE__); */
|
||||
if (cdc_hdl) {
|
||||
#if USB_MALLOC_ENABLE
|
||||
free(cdc_hdl->cdc_buffer);
|
||||
free(cdc_hdl);
|
||||
#endif
|
||||
cdc_hdl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef __CDC_H__
|
||||
#define __CDC_H__
|
||||
|
||||
#include "usb/device/usb_stack.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
u32 cdc_desc_config(const usb_dev usb_id, u8 *ptr, u32 *itf);
|
||||
void cdc_set_wakeup_handler(void (*handle)(struct usb_device_t *usb_device));
|
||||
void cdc_set_output_handle(void *priv, int (*output_handler)(void *priv, u8 *buf, u32 len));
|
||||
u32 cdc_read_data(const usb_dev usb_id, u8 *buf, u32 len);
|
||||
u32 cdc_write_data(const usb_dev usb_id, u8 *buf, u32 len);
|
||||
u32 cdc_write_inir(const usb_dev usb_id, u8 *buf, u32 len);
|
||||
void cdc_register(const usb_dev usb_id);
|
||||
void cdc_release(const usb_dev usb_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,457 @@
|
||||
|
||||
/*
|
||||
* USB Communications Device Class (CDC) definitions
|
||||
*
|
||||
* CDC says how to talk to lots of different types of network adapters,
|
||||
* notably ethernet adapters and various modems. It's used mostly with
|
||||
* firmware based USB peripherals.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_CDC_H
|
||||
#define __LINUX_USB_CDC_H
|
||||
|
||||
#include "typedef.h" /* __u8 etc */
|
||||
|
||||
#ifdef __le16
|
||||
#undef __le16
|
||||
#endif
|
||||
typedef unsigned short __le16;
|
||||
#ifdef __le32
|
||||
#undef __le32
|
||||
#endif
|
||||
typedef unsigned int __le32;
|
||||
#ifdef __u8
|
||||
#undef __u8
|
||||
#endif
|
||||
typedef unsigned char __u8;
|
||||
#ifdef __u16
|
||||
#undef __u16
|
||||
#endif
|
||||
typedef unsigned short __u16;
|
||||
#ifdef __u32
|
||||
#undef __u32
|
||||
#endif
|
||||
typedef unsigned int __u32;
|
||||
|
||||
#define USB_CDC_SUBCLASS_ACM 0x02
|
||||
#define USB_CDC_SUBCLASS_ETHERNET 0x06
|
||||
#define USB_CDC_SUBCLASS_WHCM 0x08
|
||||
#define USB_CDC_SUBCLASS_DMM 0x09
|
||||
#define USB_CDC_SUBCLASS_MDLM 0x0a
|
||||
#define USB_CDC_SUBCLASS_OBEX 0x0b
|
||||
#define USB_CDC_SUBCLASS_EEM 0x0c
|
||||
#define USB_CDC_SUBCLASS_NCM 0x0d
|
||||
#define USB_CDC_SUBCLASS_MBIM 0x0e
|
||||
|
||||
#define USB_CDC_PROTO_NONE 0
|
||||
|
||||
#define USB_CDC_ACM_PROTO_AT_V25TER 1
|
||||
#define USB_CDC_ACM_PROTO_AT_PCCA101 2
|
||||
#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3
|
||||
#define USB_CDC_ACM_PROTO_AT_GSM 4
|
||||
#define USB_CDC_ACM_PROTO_AT_3G 5
|
||||
#define USB_CDC_ACM_PROTO_AT_CDMA 6
|
||||
#define USB_CDC_ACM_PROTO_VENDOR 0xff
|
||||
|
||||
#define USB_CDC_PROTO_EEM 7
|
||||
|
||||
#define USB_CDC_NCM_PROTO_NTB 1
|
||||
#define USB_CDC_MBIM_PROTO_NTB 2
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Class-Specific descriptors ... there are a couple dozen of them
|
||||
*/
|
||||
|
||||
#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */
|
||||
#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */
|
||||
#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */
|
||||
#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
|
||||
#define USB_CDC_COUNTRY_TYPE 0x07
|
||||
#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */
|
||||
#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
|
||||
#define USB_CDC_WHCM_TYPE 0x11
|
||||
#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */
|
||||
#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */
|
||||
#define USB_CDC_DMM_TYPE 0x14
|
||||
#define USB_CDC_OBEX_TYPE 0x15
|
||||
#define USB_CDC_NCM_TYPE 0x1a
|
||||
#define USB_CDC_MBIM_TYPE 0x1b
|
||||
|
||||
/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
|
||||
struct usb_cdc_header_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__le16 bcdCDC;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "Call Management Descriptor" from CDC spec 5.2.3.2 */
|
||||
struct usb_cdc_call_mgmt_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__u8 bmCapabilities;
|
||||
#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01
|
||||
#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02
|
||||
|
||||
__u8 bDataInterface;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */
|
||||
struct usb_cdc_acm_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__u8 bmCapabilities;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* capabilities from 5.2.3.3 */
|
||||
|
||||
#define USB_CDC_COMM_FEATURE 0x01
|
||||
#define USB_CDC_CAP_LINE 0x02
|
||||
#define USB_CDC_CAP_BRK 0x04
|
||||
#define USB_CDC_CAP_NOTIFY 0x08
|
||||
|
||||
/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
|
||||
struct usb_cdc_union_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__u8 bMasterInterface0;
|
||||
__u8 bSlaveInterface0;
|
||||
/* ... and there could be other slave interfaces */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "Country Selection Functional Descriptor" from CDC spec 5.2.3.9 */
|
||||
struct usb_cdc_country_functional_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__u8 iCountryCodeRelDate;
|
||||
__le16 wCountyCode0;
|
||||
/* ... and there can be a lot of country codes */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */
|
||||
struct usb_cdc_network_terminal_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__u8 bEntityId;
|
||||
__u8 iName;
|
||||
__u8 bChannelIndex;
|
||||
__u8 bPhysicalInterface;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
|
||||
struct usb_cdc_ether_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__u8 iMACAddress;
|
||||
__le32 bmEthernetStatistics;
|
||||
__le16 wMaxSegmentSize;
|
||||
__le16 wNumberMCFilters;
|
||||
__u8 bNumberPowerFilters;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "Telephone Control Model Functional Descriptor" from CDC WMC spec 6.3..3 */
|
||||
struct usb_cdc_dmm_desc {
|
||||
__u8 bFunctionLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubtype;
|
||||
__u16 bcdVersion;
|
||||
__le16 wMaxCommand;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
|
||||
struct usb_cdc_mdlm_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__le16 bcdVersion;
|
||||
__u8 bGUID[16];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
|
||||
struct usb_cdc_mdlm_detail_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
/* type is associated with mdlm_desc.bGUID */
|
||||
__u8 bGuidDescriptorType;
|
||||
__u8 bDetailData[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "OBEX Control Model Functional Descriptor" */
|
||||
struct usb_cdc_obex_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__le16 bcdVersion;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "NCM Control Model Functional Descriptor" */
|
||||
struct usb_cdc_ncm_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__le16 bcdNcmVersion;
|
||||
__u8 bmNetworkCapabilities;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* "MBIM Control Model Functional Descriptor" */
|
||||
struct usb_cdc_mbim_desc {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bDescriptorSubType;
|
||||
|
||||
__le16 bcdMBIMVersion;
|
||||
__le16 wMaxControlMessage;
|
||||
__u8 bNumberFilters;
|
||||
__u8 bMaxFilterSize;
|
||||
__le16 wMaxSegmentSize;
|
||||
__u8 bmNetworkCapabilities;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Class-Specific Control Requests (6.2)
|
||||
*
|
||||
* section 3.6.2.1 table 4 has the ACM profile, for modems.
|
||||
* section 3.8.2 table 10 has the ethernet profile.
|
||||
*
|
||||
* Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant,
|
||||
* heavily dependent on the encapsulated (proprietary) command mechanism.
|
||||
*/
|
||||
|
||||
#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00
|
||||
#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01
|
||||
#define USB_CDC_REQ_SET_LINE_CODING 0x20
|
||||
#define USB_CDC_REQ_GET_LINE_CODING 0x21
|
||||
#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22
|
||||
#define USB_CDC_REQ_SEND_BREAK 0x23
|
||||
#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
|
||||
#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41
|
||||
#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42
|
||||
#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43
|
||||
#define USB_CDC_GET_ETHERNET_STATISTIC 0x44
|
||||
#define USB_CDC_GET_NTB_PARAMETERS 0x80
|
||||
#define USB_CDC_GET_NET_ADDRESS 0x81
|
||||
#define USB_CDC_SET_NET_ADDRESS 0x82
|
||||
#define USB_CDC_GET_NTB_FORMAT 0x83
|
||||
#define USB_CDC_SET_NTB_FORMAT 0x84
|
||||
#define USB_CDC_GET_NTB_INPUT_SIZE 0x85
|
||||
#define USB_CDC_SET_NTB_INPUT_SIZE 0x86
|
||||
#define USB_CDC_GET_MAX_DATAGRAM_SIZE 0x87
|
||||
#define USB_CDC_SET_MAX_DATAGRAM_SIZE 0x88
|
||||
#define USB_CDC_GET_CRC_MODE 0x89
|
||||
#define USB_CDC_SET_CRC_MODE 0x8a
|
||||
|
||||
/* Line Coding Structure from CDC spec 6.2.13 */
|
||||
struct usb_cdc_line_coding {
|
||||
__le32 dwDTERate;
|
||||
__u8 bCharFormat;
|
||||
#define USB_CDC_1_STOP_BITS 0
|
||||
#define USB_CDC_1_5_STOP_BITS 1
|
||||
#define USB_CDC_2_STOP_BITS 2
|
||||
|
||||
__u8 bParityType;
|
||||
#define USB_CDC_NO_PARITY 0
|
||||
#define USB_CDC_ODD_PARITY 1
|
||||
#define USB_CDC_EVEN_PARITY 2
|
||||
#define USB_CDC_MARK_PARITY 3
|
||||
#define USB_CDC_SPACE_PARITY 4
|
||||
|
||||
__u8 bDataBits;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* table 62; bits in multicast filter */
|
||||
#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0)
|
||||
#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */
|
||||
#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2)
|
||||
#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3)
|
||||
#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Class-Specific Notifications (6.3) sent by interrupt transfers
|
||||
*
|
||||
* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
|
||||
* section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
|
||||
* RNDIS also defines its own bit-incompatible notifications
|
||||
*/
|
||||
|
||||
#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00
|
||||
#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01
|
||||
#define USB_CDC_NOTIFY_SERIAL_STATE 0x20
|
||||
#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a
|
||||
|
||||
struct usb_cdc_notification {
|
||||
__u8 bmRequestType;
|
||||
__u8 bNotificationType;
|
||||
__le16 wValue;
|
||||
__le16 wIndex;
|
||||
__le16 wLength;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_cdc_speed_change {
|
||||
__le32 DLBitRRate; /* contains the downlink bit rate (IN pipe) */
|
||||
__le32 ULBitRate; /* contains the uplink bit rate (OUT pipe) */
|
||||
} __attribute__((packed));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Class Specific structures and constants
|
||||
*
|
||||
* CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1
|
||||
*
|
||||
*/
|
||||
|
||||
struct usb_cdc_ncm_ntb_parameters {
|
||||
__le16 wLength;
|
||||
__le16 bmNtbFormatsSupported;
|
||||
__le32 dwNtbInMaxSize;
|
||||
__le16 wNdpInDivisor;
|
||||
__le16 wNdpInPayloadRemainder;
|
||||
__le16 wNdpInAlignment;
|
||||
__le16 wPadding1;
|
||||
__le32 dwNtbOutMaxSize;
|
||||
__le16 wNdpOutDivisor;
|
||||
__le16 wNdpOutPayloadRemainder;
|
||||
__le16 wNdpOutAlignment;
|
||||
__le16 wNtbOutMaxDatagrams;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* CDC NCM transfer headers, CDC NCM subclass 3.2
|
||||
*/
|
||||
|
||||
#define USB_CDC_NCM_NTH16_SIGN 0x484D434E /* NCMH */
|
||||
#define USB_CDC_NCM_NTH32_SIGN 0x686D636E /* ncmh */
|
||||
|
||||
struct usb_cdc_ncm_nth16 {
|
||||
__le32 dwSignature;
|
||||
__le16 wHeaderLength;
|
||||
__le16 wSequence;
|
||||
__le16 wBlockLength;
|
||||
__le16 wNdpIndex;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usb_cdc_ncm_nth32 {
|
||||
__le32 dwSignature;
|
||||
__le16 wHeaderLength;
|
||||
__le16 wSequence;
|
||||
__le32 dwBlockLength;
|
||||
__le32 dwNdpIndex;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* CDC NCM datagram pointers, CDC NCM subclass 3.3
|
||||
*/
|
||||
|
||||
#define USB_CDC_NCM_NDP16_CRC_SIGN 0x314D434E /* NCM1 */
|
||||
#define USB_CDC_NCM_NDP16_NOCRC_SIGN 0x304D434E /* NCM0 */
|
||||
#define USB_CDC_NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */
|
||||
#define USB_CDC_NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */
|
||||
|
||||
#define USB_CDC_MBIM_NDP16_IPS_SIGN 0x00535049 /* IPS<sessionID> : IPS0 for now */
|
||||
#define USB_CDC_MBIM_NDP32_IPS_SIGN 0x00737069 /* ips<sessionID> : ips0 for now */
|
||||
#define USB_CDC_MBIM_NDP16_DSS_SIGN 0x00535344 /* DSS<sessionID> */
|
||||
#define USB_CDC_MBIM_NDP32_DSS_SIGN 0x00737364 /* dss<sessionID> */
|
||||
|
||||
/* 16-bit NCM Datagram Pointer Entry */
|
||||
struct usb_cdc_ncm_dpe16 {
|
||||
__le16 wDatagramIndex;
|
||||
__le16 wDatagramLength;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* 16-bit NCM Datagram Pointer Table */
|
||||
struct usb_cdc_ncm_ndp16 {
|
||||
__le32 dwSignature;
|
||||
__le16 wLength;
|
||||
__le16 wNextNdpIndex;
|
||||
struct usb_cdc_ncm_dpe16 dpe16[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* 32-bit NCM Datagram Pointer Entry */
|
||||
struct usb_cdc_ncm_dpe32 {
|
||||
__le32 dwDatagramIndex;
|
||||
__le32 dwDatagramLength;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* 32-bit NCM Datagram Pointer Table */
|
||||
struct usb_cdc_ncm_ndp32 {
|
||||
__le32 dwSignature;
|
||||
__le16 wLength;
|
||||
__le16 wReserved6;
|
||||
__le32 dwNextNdpIndex;
|
||||
__le32 dwReserved12;
|
||||
struct usb_cdc_ncm_dpe32 dpe32[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* CDC NCM subclass 3.2.1 and 3.2.2 */
|
||||
#define USB_CDC_NCM_NDP16_INDEX_MIN 0x000C
|
||||
#define USB_CDC_NCM_NDP32_INDEX_MIN 0x0010
|
||||
|
||||
/* CDC NCM subclass 3.3.3 Datagram Formatting */
|
||||
#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC 0x30
|
||||
#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC 0X31
|
||||
|
||||
/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */
|
||||
#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS 0x00
|
||||
#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO 0xFE
|
||||
|
||||
/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */
|
||||
#define USB_CDC_NCM_NCAP_ETH_FILTER (1 << 0)
|
||||
#define USB_CDC_NCM_NCAP_NET_ADDRESS (1 << 1)
|
||||
#define USB_CDC_NCM_NCAP_ENCAP_COMMAND (1 << 2)
|
||||
#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE (1 << 3)
|
||||
#define USB_CDC_NCM_NCAP_CRC_MODE (1 << 4)
|
||||
#define USB_CDC_NCM_NCAP_NTB_INPUT_SIZE (1 << 5)
|
||||
|
||||
/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
|
||||
#define USB_CDC_NCM_NTB16_SUPPORTED (1 << 0)
|
||||
#define USB_CDC_NCM_NTB32_SUPPORTED (1 << 1)
|
||||
|
||||
/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
|
||||
#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE 0x04
|
||||
#define USB_CDC_NCM_NTB_MAX_LENGTH 0x1C
|
||||
|
||||
/* CDC NCM subclass 6.2.5 SetNtbFormat */
|
||||
#define USB_CDC_NCM_NTB16_FORMAT 0x00
|
||||
#define USB_CDC_NCM_NTB32_FORMAT 0x01
|
||||
|
||||
/* CDC NCM subclass 6.2.7 SetNtbInputSize */
|
||||
#define USB_CDC_NCM_NTB_MIN_IN_SIZE 2048
|
||||
#define USB_CDC_NCM_NTB_MIN_OUT_SIZE 2048
|
||||
|
||||
/* NTB Input Size Structure */
|
||||
struct usb_cdc_ncm_ndp_input_size {
|
||||
__le32 dwNtbInMaxSize;
|
||||
__le16 wNtbInMaxDatagrams;
|
||||
__le16 wReserved;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* CDC NCM subclass 6.2.11 SetCrcMode */
|
||||
#define USB_CDC_NCM_CRC_NOT_APPENDED 0x00
|
||||
#define USB_CDC_NCM_CRC_APPENDED 0x01
|
||||
|
||||
#endif /* __LINUX_USB_CDC_H */
|
||||
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @file descriptor.c
|
||||
* @brief overwrite usb device descriptor
|
||||
* @version 1.00
|
||||
* @date 2019-05-06
|
||||
*/
|
||||
|
||||
#include "usb/device/usb_stack.h"
|
||||
#include "usb/device/descriptor.h"
|
||||
#include "usb/device/uac_audio.h"
|
||||
|
||||
#include "app_config.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#if TCFG_USB_SLAVE_ENABLE
|
||||
|
||||
static const u8 sDeviceDescriptor[] = { //<Device Descriptor
|
||||
USB_DT_DEVICE_SIZE, // bLength: Size of descriptor
|
||||
USB_DT_DEVICE, // bDescriptorType: Device
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
0x10, 0x01, // bcdUSB: USB 1.1
|
||||
#elif defined(FUSB_MODE) && (FUSB_MODE ==0 )
|
||||
0x00, 0x02, // bcdUSB: USB 2.0
|
||||
#else
|
||||
#error "USB_SPEED_MODE not defined"
|
||||
#endif
|
||||
0x00, // bDeviceClass: none
|
||||
0x00, // bDeviceSubClass: none
|
||||
0x00, // bDeviceProtocol: none
|
||||
EP0_SETUP_LEN,//EP0_LEN, // bMaxPacketSize0: 8/64 bytes
|
||||
'J', 'L', // idVendor: 0x4a4c - JL
|
||||
'U', 'A', // idProduct: chip id
|
||||
0x00, 0x01, // bcdDevice: version 1.0
|
||||
0x01, // iManufacturer: Index to string descriptor that contains the string <Your Name> in Unicode
|
||||
0x02, // iProduct: Index to string descriptor that contains the string <Your Product Name> in Unicode
|
||||
0x03, // iSerialNumber: none
|
||||
0x01 // bNumConfigurations: 1
|
||||
};
|
||||
|
||||
static const u8 LANGUAGE_STR[] = {
|
||||
0x04, 0x03, 0x09, 0x04
|
||||
};
|
||||
|
||||
|
||||
static const u8 product_string[] = {
|
||||
42,
|
||||
0x03,
|
||||
'U', 0x00,
|
||||
'S', 0x00,
|
||||
'B', 0x00,
|
||||
' ', 0x00,
|
||||
'C', 0x00,
|
||||
'o', 0x00,
|
||||
'm', 0x00,
|
||||
'p', 0x00,
|
||||
'o', 0x00,
|
||||
's', 0x00,
|
||||
'i', 0x00,
|
||||
't', 0x00,
|
||||
'e', 0x00,
|
||||
' ', 0x00,
|
||||
'D', 0x00,
|
||||
'e', 0x00,
|
||||
'v', 0x00,
|
||||
'i', 0x00,
|
||||
'c', 0x00,
|
||||
'e', 0x00,
|
||||
};
|
||||
|
||||
static const u8 MANUFACTURE_STR[] = {
|
||||
34, //该描述符的长度为34字节
|
||||
0x03, //字符串描述符的类型编码为0x03
|
||||
0x4a, 0x00, //J
|
||||
0x69, 0x00, //i
|
||||
0x65, 0x00, //e
|
||||
0x6c, 0x00, //l
|
||||
0x69, 0x00, //i
|
||||
0x20, 0x00, //
|
||||
0x54, 0x00, //T
|
||||
0x65, 0x00, //e
|
||||
0x63, 0x00, //c
|
||||
0x68, 0x00, //h
|
||||
0x6e, 0x00, //n
|
||||
0x6f, 0x00, //o
|
||||
0x6c, 0x00, //l
|
||||
0x6f, 0x00, //o
|
||||
0x67, 0x00, //g
|
||||
0x79, 0x00, //y
|
||||
};
|
||||
|
||||
static const u8 sConfigDescriptor[] = { //<Config Descriptor
|
||||
//ConfiguraTIon
|
||||
USB_DT_CONFIG_SIZE, //bLength
|
||||
USB_DT_CONFIG, //DescriptorType : ConfigDescriptor
|
||||
0, 0, //TotalLength
|
||||
0,//bNumInterfaces: 在set_descriptor函数里面计算
|
||||
0x01, //bConfigurationValue - ID of this configuration
|
||||
0x00, //Unused
|
||||
#if USB_ROOT2 || USB_SUSPEND_RESUME || USB_SUSPEND_RESUME_SYSTEM_NO_SLEEP
|
||||
0xA0, //Attributes:Bus Power remotewakeup
|
||||
#else
|
||||
0x80, //Attributes:Bus Power
|
||||
#endif
|
||||
50, //MaxPower * 2ma
|
||||
};
|
||||
|
||||
static const u8 serial_string[] = {
|
||||
0x22, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x36, 0x00, 0x46, 0x00, 0x36, 0x00,
|
||||
0x34, 0x00, 0x30, 0x00, 0x39, 0x00, 0x36, 0x00, 0x42, 0x00, 0x32, 0x00, 0x32, 0x00, 0x45, 0x00,
|
||||
0x37, 0x00
|
||||
};
|
||||
|
||||
void get_device_descriptor(u8 *ptr)
|
||||
{
|
||||
memcpy(ptr, sDeviceDescriptor, USB_DT_DEVICE_SIZE);
|
||||
}
|
||||
|
||||
void get_language_str(u8 *ptr)
|
||||
{
|
||||
memcpy(ptr, LANGUAGE_STR, LANGUAGE_STR[0]);
|
||||
}
|
||||
|
||||
void get_manufacture_str(u8 *ptr)
|
||||
{
|
||||
memcpy(ptr, MANUFACTURE_STR, MANUFACTURE_STR[0]);
|
||||
}
|
||||
|
||||
void get_iserialnumber_str(u8 *ptr)
|
||||
{
|
||||
#if USB_ROOT2
|
||||
memcpy(ptr, serial_string, serial_string[0]);
|
||||
#else
|
||||
extern __attribute__((weak)) u8 *get_norflash_uuid(void);
|
||||
u8 flash_id[16] = {0};
|
||||
int i;
|
||||
u8 bcd;
|
||||
if (get_norflash_uuid && get_norflash_uuid()) {
|
||||
ptr[0] = 0x22;
|
||||
ptr[1] = 0x03;
|
||||
memset(&ptr[2], 0, 0x20);
|
||||
memcpy(flash_id, get_norflash_uuid(), 16);
|
||||
//take 8 bytes from flash uuid
|
||||
for (i = 0; i < 8; i++) {
|
||||
bcd = flash_id[i] >> 4;
|
||||
if (bcd > 9) {
|
||||
bcd = bcd - 0xa + 'A';
|
||||
} else {
|
||||
bcd = bcd + '0';
|
||||
}
|
||||
ptr[2 + i * 4] = bcd;
|
||||
bcd = flash_id[i] & 0xf;
|
||||
if (bcd > 9) {
|
||||
bcd = bcd - 0xa + 'A';
|
||||
} else {
|
||||
bcd = bcd + '0';
|
||||
}
|
||||
ptr[2 + i * 4 + 2] = bcd;
|
||||
}
|
||||
} else {
|
||||
memcpy(ptr, serial_string, serial_string[0]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USB_ROOT2
|
||||
static const u8 ee_string[] = {0x12, 0x03, 0x4D, 0x00, 0x53, 0x00, 0x46, 0x00, 0x54,
|
||||
0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x90, 0x00
|
||||
};
|
||||
void get_string_ee(u8 *ptr)
|
||||
{
|
||||
memcpy(ptr, ee_string, ee_string[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void get_product_str(u8 *ptr)
|
||||
{
|
||||
memcpy(ptr, product_string, product_string[0]);
|
||||
}
|
||||
|
||||
const u8 *usb_get_config_desc()
|
||||
{
|
||||
return sConfigDescriptor;
|
||||
}
|
||||
|
||||
const u8 *usb_get_string_desc(u32 id)
|
||||
{
|
||||
const u8 *pstr = uac_get_string(id);
|
||||
if (pstr != NULL) {
|
||||
return pstr;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,332 @@
|
||||
#include "os/os_api.h"
|
||||
#include "usb/device/usb_stack.h"
|
||||
#include "usb/device/hid.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
#include "app_config.h"
|
||||
|
||||
#if TCFG_USB_SLAVE_USER_HID
|
||||
#undef TCFG_USB_SLAVE_HID_ENABLE
|
||||
#define TCFG_USB_SLAVE_HID_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
static const u8 sHIDDescriptor[] = {
|
||||
//HID
|
||||
//InterfaceDeszcriptor:
|
||||
USB_DT_INTERFACE_SIZE, // Length
|
||||
USB_DT_INTERFACE, // DescriptorType
|
||||
/* 0x04, // bInterface number */
|
||||
0x00, // bInterface number
|
||||
0x00, // AlternateSetting
|
||||
0x01, // NumEndpoint
|
||||
/* 0x02, // NumEndpoint */
|
||||
USB_CLASS_HID, // Class = Human Interface Device
|
||||
0x00, // Subclass, 0 No subclass, 1 Boot Interface subclass
|
||||
0x00, // Procotol, 0 None, 1 Keyboard, 2 Mouse
|
||||
0x00, // Interface Name
|
||||
|
||||
//HIDDescriptor:
|
||||
0x09, // bLength
|
||||
USB_HID_DT_HID, // bDescriptorType, HID Descriptor
|
||||
0x00, 0x01, // bcdHID, HID Class Specification release NO.
|
||||
0x00, // bCuntryCode, Country localization (=none)
|
||||
0x01, // bNumDescriptors, Number of descriptors to follow
|
||||
0x22, // bDescriptorType, Report Desc. 0x22, Physical Desc. 0x23
|
||||
0,//LOW(ReportLength)
|
||||
0, //HIGH(ReportLength)
|
||||
|
||||
//EndpointDescriptor:
|
||||
USB_DT_ENDPOINT_SIZE, // bLength
|
||||
USB_DT_ENDPOINT, // bDescriptorType, Type
|
||||
USB_DIR_IN | HID_EP_IN, // bEndpointAddress
|
||||
USB_ENDPOINT_XFER_INT, // Interrupt
|
||||
LOBYTE(MAXP_SIZE_HIDIN), HIBYTE(MAXP_SIZE_HIDIN),// Maximum packet size
|
||||
HID_INTR_INTERVAL, // Poll every 10msec seconds
|
||||
|
||||
//@Endpoint Descriptor:
|
||||
/* USB_DT_ENDPOINT_SIZE, // bLength
|
||||
USB_DT_ENDPOINT, // bDescriptorType, Type
|
||||
USB_DIR_OUT | HID_EP_OUT, // bEndpointAddress
|
||||
USB_ENDPOINT_XFER_INT, // Interrupt
|
||||
LOBYTE(MAXP_SIZE_HIDOUT), HIBYTE(MAXP_SIZE_HIDOUT),// Maximum packet size
|
||||
HID_INTR_INTERVAL, // bInterval, for high speed 2^(n-1) * 125us, for full/low speed n * 1ms */
|
||||
};
|
||||
|
||||
static const u8 sHIDReportDesc[] = {
|
||||
USAGE_PAGE(1, CONSUMER_PAGE),
|
||||
USAGE(1, CONSUMER_CONTROL),
|
||||
COLLECTION(1, APPLICATION),
|
||||
|
||||
LOGICAL_MIN(1, 0x00),
|
||||
LOGICAL_MAX(1, 0x01),
|
||||
|
||||
USAGE(1, VOLUME_INC),
|
||||
USAGE(1, VOLUME_DEC),
|
||||
USAGE(1, MUTE),
|
||||
USAGE(1, PLAY_PAUSE),
|
||||
USAGE(1, SCAN_NEXT_TRACK),
|
||||
USAGE(1, SCAN_PREV_TRACK),
|
||||
USAGE(1, FAST_FORWARD),
|
||||
USAGE(1, STOP),
|
||||
|
||||
USAGE(1, TRACKING_INC),
|
||||
USAGE(1, TRACKING_DEC),
|
||||
USAGE(1, STOP_EJECT),
|
||||
USAGE(1, VOLUME),
|
||||
USAGE(2, BALANCE_LEFT),
|
||||
USAGE(2, BALANCE_RIGHT),
|
||||
USAGE(1, PLAY),
|
||||
USAGE(1, PAUSE),
|
||||
|
||||
REPORT_SIZE(1, 0x01),
|
||||
REPORT_COUNT(1, 0x10),
|
||||
INPUT(1, 0x42),
|
||||
END_COLLECTION,
|
||||
|
||||
};
|
||||
|
||||
static u32 get_hid_report_desc_len(u32 index)
|
||||
{
|
||||
u32 len = 0;
|
||||
len = sizeof(sHIDReportDesc);
|
||||
return len;
|
||||
}
|
||||
static void *get_hid_report_desc(u32 index)
|
||||
{
|
||||
u8 *ptr = NULL;
|
||||
ptr = (u8 *)sHIDReportDesc;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
static u8 *hid_ep_in_dma;
|
||||
/* static u8 *hid_ep_out_dma; */
|
||||
|
||||
static u32 hid_tx_data(struct usb_device_t *usb_device, const u8 *buffer, u32 len)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
return usb_g_intr_write(usb_id, HID_EP_IN, buffer, len);
|
||||
}
|
||||
static void hid_rx_data(struct usb_device_t *usb_device, u32 ep)
|
||||
{
|
||||
/* const usb_dev usb_id = usb_device2id(usb_device); */
|
||||
/* u32 rx_len = usb_g_intr_read(usb_id, ep, NULL, 64, 0); */
|
||||
/* hid_tx_data(usb_device, hid_ep_out_dma, rx_len); */
|
||||
}
|
||||
|
||||
static void hid_endpoint_init(struct usb_device_t *usb_device, u32 itf)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
usb_g_ep_config(usb_id, HID_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_INT, 0, hid_ep_in_dma, MAXP_SIZE_HIDIN);
|
||||
usb_enable_ep(usb_id, HID_EP_IN);
|
||||
|
||||
/* usb_g_set_intr_hander(usb_id, HID_EP_OUT, hid_rx_data); */
|
||||
/* usb_g_ep_config(usb_id, HID_EP_OUT, USB_ENDPOINT_XFER_INT, 1, ep_buffer, MAXP_SIZE_HIDOUT); */
|
||||
}
|
||||
u32 hid_register(const usb_dev usb_id)
|
||||
{
|
||||
hid_ep_in_dma = usb_alloc_ep_dmabuffer(usb_id, HID_EP_IN | USB_DIR_IN, MAXP_SIZE_HIDIN);
|
||||
|
||||
/* hid_ep_out_dma = hid_ep_in_dma + MAXP_SIZE_HIDIN; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hid_release(const usb_dev usb_id)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
static void hid_reset(struct usb_device_t *usb_device, u32 itf)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
log_debug("%s", __func__);
|
||||
#if USB_ROOT2
|
||||
usb_disable_ep(usb_id, HID_EP_IN);
|
||||
#else
|
||||
hid_endpoint_init(usb_device, itf);
|
||||
#endif
|
||||
}
|
||||
static u32 hid_recv_output_report(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
u32 ret = 0;
|
||||
u8 read_ep[8];
|
||||
u8 mute;
|
||||
u16 volume = 0;
|
||||
usb_read_ep0(usb_id, read_ep, MIN(sizeof(read_ep), setup->wLength));
|
||||
ret = USB_EP0_STAGE_SETUP;
|
||||
put_buf(read_ep, 8);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 hid_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
u32 tx_len;
|
||||
u8 *tx_payload = usb_get_setup_buffer(usb_device);
|
||||
u32 bRequestType = req->bRequestType & USB_TYPE_MASK;
|
||||
switch (bRequestType) {
|
||||
case USB_TYPE_STANDARD:
|
||||
switch (req->bRequest) {
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
switch (HIBYTE(req->wValue)) {
|
||||
case USB_HID_DT_HID:
|
||||
tx_payload = (u8 *)sHIDDescriptor + USB_DT_INTERFACE_SIZE;
|
||||
tx_len = 9;
|
||||
tx_payload = usb_set_data_payload(usb_device, req, tx_payload, tx_len);
|
||||
tx_payload[7] = LOBYTE(get_hid_report_desc_len(req->wIndex));
|
||||
tx_payload[8] = HIBYTE(get_hid_report_desc_len(req->wIndex));
|
||||
break;
|
||||
case USB_HID_DT_REPORT:
|
||||
hid_endpoint_init(usb_device, req->wIndex);
|
||||
tx_len = get_hid_report_desc_len(req->wIndex);
|
||||
tx_payload = get_hid_report_desc(req->wIndex);
|
||||
usb_set_data_payload(usb_device, req, tx_payload, tx_len);
|
||||
break;
|
||||
}// USB_REQ_GET_DESCRIPTOR
|
||||
break;
|
||||
case USB_REQ_SET_DESCRIPTOR:
|
||||
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
|
||||
break;
|
||||
case USB_REQ_SET_INTERFACE:
|
||||
if (usb_device->bDeviceStates == USB_DEFAULT) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
|
||||
//只有一个interface 没有Alternate
|
||||
if (req->wValue == 0) { //alt 0
|
||||
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
|
||||
} else {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case USB_REQ_GET_INTERFACE:
|
||||
if (req->wValue || (req->wLength != 1)) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
} else if (usb_device->bDeviceStates == USB_DEFAULT) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
} else if (usb_device->bDeviceStates == USB_CONFIGURED) {
|
||||
tx_len = 1;
|
||||
tx_payload[0] = 0x00;
|
||||
usb_set_data_payload(usb_device, req, tx_payload, tx_len);
|
||||
}
|
||||
break;
|
||||
case USB_REQ_GET_STATUS:
|
||||
if (usb_device->bDeviceStates == USB_DEFAULT) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
} else if (usb_device->bDeviceStates == USB_ADDRESS) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
} else {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
}
|
||||
break;
|
||||
}//bRequest @ USB_TYPE_STANDARD
|
||||
break;
|
||||
|
||||
case USB_TYPE_CLASS: {
|
||||
switch (req->bRequest) {
|
||||
case USB_REQ_SET_IDLE:
|
||||
usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP);
|
||||
break;
|
||||
case USB_REQ_GET_IDLE:
|
||||
tx_len = 1;
|
||||
tx_payload[0] = 0;
|
||||
usb_set_data_payload(usb_device, req, tx_payload, tx_len);
|
||||
break;
|
||||
case USB_REQ_SET_REPORT:
|
||||
usb_set_setup_recv(usb_device, hid_recv_output_report);
|
||||
break;
|
||||
}//bRequest @ USB_TYPE_CLASS
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 hid_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num)
|
||||
{
|
||||
log_debug("hid interface num:%d\n", *cur_itf_num);
|
||||
u8 *_ptr = ptr;
|
||||
memcpy(ptr, sHIDDescriptor, sizeof(sHIDDescriptor));
|
||||
ptr[2] = *cur_itf_num;
|
||||
if (usb_set_interface_hander(usb_id, *cur_itf_num, hid_itf_hander) != *cur_itf_num) {
|
||||
ASSERT(0, "hid set interface_hander fail");
|
||||
}
|
||||
if (usb_set_reset_hander(usb_id, *cur_itf_num, hid_reset) != *cur_itf_num) {
|
||||
ASSERT(0, "hid set interface_reset_hander fail");
|
||||
}
|
||||
|
||||
ptr[USB_DT_INTERFACE_SIZE + 7] = LOBYTE(get_hid_report_desc_len(0));
|
||||
ptr[USB_DT_INTERFACE_SIZE + 8] = HIBYTE(get_hid_report_desc_len(0));
|
||||
*cur_itf_num = *cur_itf_num + 1;
|
||||
return sizeof(sHIDDescriptor) ;
|
||||
}
|
||||
|
||||
void hid_key_handler(struct usb_device_t *usb_device, u32 hid_key)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
if (usb_get_ep_status(usb_id, HID_EP_IN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
u16 key_buf = hid_key;
|
||||
hid_tx_data(usb_device, (const u8 *)&key_buf, 2);
|
||||
os_time_dly(2);
|
||||
key_buf = 0;
|
||||
hid_tx_data(usb_device, (const u8 *)&key_buf, 2);
|
||||
}
|
||||
|
||||
void hid_key_handler_send_one_packet(struct usb_device_t *usb_device, u32 hid_key)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
u16 key_buf = hid_key;
|
||||
hid_tx_data(usb_device, (const u8 *)&key_buf, 2);
|
||||
}
|
||||
|
||||
struct hid_button {
|
||||
u8 report_id;
|
||||
u8 button1: 1;
|
||||
u8 button2: 1;
|
||||
u8 button3: 1;
|
||||
u8 no_button: 5;
|
||||
u8 X_axis;
|
||||
u8 Y_axis;
|
||||
};
|
||||
struct hid_button hid_key;
|
||||
void hid_test(struct usb_device_t *usb_device)
|
||||
{
|
||||
static u32 tx_count = 0;
|
||||
|
||||
hid_key_handler(usb_device, BIT(tx_count));
|
||||
tx_count ++;
|
||||
if (BIT(tx_count) > USB_AUDIO_PAUSE) {
|
||||
tx_count = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void hid_key_handler(struct usb_device_t *usb_device, u32 hid_key)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void hid_key_handler_for_one_packet(struct usb_device_t *usb_device, u32 hid_key)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
#include "system/includes.h"
|
||||
#include "usb/device/msd.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb_config.h"
|
||||
#include "app_config.h"
|
||||
#include "cpu.h"
|
||||
#include "asm/debug.h"
|
||||
|
||||
#define WRITE_FLASH 0xFB
|
||||
#define READ_FLASH 0xFD
|
||||
#define OTHER_CMD 0xFC
|
||||
typedef enum {
|
||||
UPGRADE_NULL = 0,
|
||||
UPGRADE_USB_HARD_KEY,
|
||||
UPGRADE_USB_SOFT_KEY,
|
||||
UPGRADE_UART_KEY,
|
||||
} UPGRADE_STATE;
|
||||
|
||||
extern void nvram_set_boot_state(u32 state);
|
||||
extern void hw_mmu_disable(void);
|
||||
extern void ram_protect_close(void);
|
||||
|
||||
AT(.volatile_ram_code)
|
||||
void go_mask_usb_updata()
|
||||
{
|
||||
#ifdef CONFIG_CPU_BR18
|
||||
gpio_set_die(IO_PORTD_02, 0);
|
||||
gpio_set_die(IO_PORTB_04, 0);
|
||||
cpu_reset();
|
||||
|
||||
#else
|
||||
local_irq_disable();
|
||||
ram_protect_close();
|
||||
//FIXME
|
||||
/* hw_mmu_disable(); */
|
||||
nvram_set_boot_state(UPGRADE_USB_SOFT_KEY);
|
||||
JL_CLOCK->PWR_CON |= (1 << 4);
|
||||
#endif
|
||||
|
||||
/* chip_reset(); */
|
||||
/* cpu_reset(); */
|
||||
while (1);
|
||||
}
|
||||
#if TCFG_PC_UPDATE
|
||||
|
||||
u32 _usb_bulk_rw_test(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw);
|
||||
|
||||
u32 private_scsi_cmd(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw)
|
||||
{
|
||||
/* if (_usb_bulk_rw_test(usb_device, cbw)) { */
|
||||
/* return TRUE; */
|
||||
/* } */
|
||||
|
||||
switch (cbw->operationCode) {
|
||||
//////////////////////Boot Loader Custom CMD
|
||||
case WRITE_FLASH:
|
||||
case READ_FLASH:
|
||||
case OTHER_CMD:
|
||||
log_d("goto mask pc mode\n");
|
||||
go_mask_usb_updata();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
u32 private_scsi_cmd(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,463 @@
|
||||
/**
|
||||
* @file task_pc.c
|
||||
* @brief 从机模式
|
||||
* @author chenrixin@zh-jieli.com
|
||||
* @version 1.0.0
|
||||
* @date 2020-02-29
|
||||
*/
|
||||
|
||||
#include "system/app_core.h"
|
||||
#include "system/includes.h"
|
||||
#include "server/server_core.h"
|
||||
#include "app_config.h"
|
||||
#include "app_action.h"
|
||||
#include "os/os_api.h"
|
||||
#include "device/sdmmc.h"
|
||||
|
||||
#include "app_charge.h"
|
||||
#include "asm/charge.h"
|
||||
|
||||
#if TCFG_USB_SLAVE_ENABLE
|
||||
#if USB_PC_NO_APP_MODE == 0
|
||||
#include "app_task.h"
|
||||
#endif
|
||||
#include "usb/usb_config.h"
|
||||
#include "usb/device/usb_stack.h"
|
||||
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
#include "usb/device/hid.h"
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
#include "usb/device/msd.h"
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
#include "usb/device/cdc.h"
|
||||
#endif
|
||||
|
||||
#if (TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0)
|
||||
#include "dev_multiplex_api.h"
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
#include "apple_dock/iAP.h"
|
||||
#endif
|
||||
|
||||
#if (TCFG_CFG_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE)
|
||||
#include "cfg_tool.h"
|
||||
#endif
|
||||
|
||||
#if ((TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE) \
|
||||
&& TCFG_CHARGESTORE_PORT == IO_PORT_DP)
|
||||
#include "asm/chargestore.h"
|
||||
#endif
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB_TASK]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#define USB_TASK_NAME "usb_msd"
|
||||
|
||||
#define USBSTACK_EVENT 0x80
|
||||
#define USBSTACK_MSD_RUN 0x81
|
||||
#define USBSTACK_MSD_RELASE 0x82
|
||||
#define USBSTACK_HID 0x83
|
||||
#define USBSTACK_MSD_RESET 0x84
|
||||
|
||||
extern int usb_audio_demo_init(void);
|
||||
extern void usb_audio_demo_exit(void);
|
||||
|
||||
static usb_dev usbfd = 0;//SEC(.usb_g_bss);
|
||||
static OS_MUTEX msd_mutex ;//SEC(.usb_g_bss);
|
||||
static u8 msd_in_task;
|
||||
static u8 msd_run_reset;
|
||||
|
||||
|
||||
static void usb_task(void *p)
|
||||
{
|
||||
int ret = 0;
|
||||
int msg[16];
|
||||
while (1) {
|
||||
ret = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
|
||||
if (ret != OS_TASKQ) {
|
||||
continue;
|
||||
}
|
||||
if (msg[0] != Q_MSG) {
|
||||
continue;
|
||||
}
|
||||
switch (msg[1]) {
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
case USBSTACK_MSD_RUN:
|
||||
os_mutex_pend(&msd_mutex, 0);
|
||||
msd_in_task = 1;
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
apple_mfi_link((void *)msg[2]);
|
||||
#else
|
||||
USB_MassStorage((void *)msg[2]);
|
||||
#endif
|
||||
if (msd_run_reset) {
|
||||
msd_reset((struct usb_device_t *)msg[2], 0);
|
||||
msd_run_reset = 0;
|
||||
}
|
||||
msd_in_task = 0;
|
||||
os_mutex_post(&msd_mutex);
|
||||
break;
|
||||
case USBSTACK_MSD_RELASE:
|
||||
os_sem_post((OS_SEM *)msg[2]);
|
||||
while (1) {
|
||||
os_time_dly(10000);
|
||||
}
|
||||
break;
|
||||
// case USBSTACK_MSD_RESET:
|
||||
// os_mutex_pend(&msd_mutex, 0);
|
||||
// msd_reset((struct usb_device_t *)msg[2], (u32)msg[3]);
|
||||
// os_mutex_post(&msd_mutex);
|
||||
// break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_msd_wakeup(struct usb_device_t *usb_device)
|
||||
{
|
||||
os_taskq_post_msg(USB_TASK_NAME, 2, USBSTACK_MSD_RUN, usb_device);
|
||||
}
|
||||
static void usb_msd_reset_wakeup(struct usb_device_t *usb_device, u32 itf_num)
|
||||
{
|
||||
/* os_taskq_post_msg(USB_TASK_NAME, 3, USBSTACK_MSD_RESET, usb_device, itf_num); */
|
||||
if (msd_in_task) {
|
||||
msd_run_reset = 1;
|
||||
} else {
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
msd_reset(usb_device, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
static void usb_msd_init()
|
||||
{
|
||||
r_printf("%s()", __func__);
|
||||
int err;
|
||||
os_mutex_create(&msd_mutex);
|
||||
err = task_create(usb_task, NULL, USB_TASK_NAME);
|
||||
if (err != OS_NO_ERR) {
|
||||
r_printf("usb_msd task creat fail %x\n", err);
|
||||
}
|
||||
}
|
||||
static void usb_msd_free()
|
||||
{
|
||||
r_printf("%s()", __func__);
|
||||
|
||||
os_mutex_del(&msd_mutex, 0);
|
||||
|
||||
int err;
|
||||
OS_SEM sem;
|
||||
os_sem_create(&sem, 0);
|
||||
os_taskq_post_msg(USB_TASK_NAME, 2, USBSTACK_MSD_RELASE, (int)&sem);
|
||||
os_sem_pend(&sem, 0);
|
||||
|
||||
|
||||
err = task_kill(USB_TASK_NAME);
|
||||
if (!err) {
|
||||
r_printf("usb_msd_uninit succ!!\n");
|
||||
} else {
|
||||
r_printf("usb_msd_uninit fail!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
static void usb_cdc_wakeup(struct usb_device_t *usb_device)
|
||||
{
|
||||
//回调函数在中断里,正式使用不要在这里加太多东西阻塞中断,
|
||||
//或者先post到任务,由任务调用cdc_read_data()读取再执行后续工作
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
u8 buf[64] = {0};
|
||||
static u8 buf_rx[256] = {0};
|
||||
static u8 rx_len_total = 0;
|
||||
u32 rlen;
|
||||
|
||||
log_debug("cdc rx hook");
|
||||
rlen = cdc_read_data(usb_id, buf, 64);
|
||||
|
||||
/* put_buf(buf, rlen);//固件三部测试使用 */
|
||||
/* cdc_write_data(usb_id, buf, rlen);//固件三部测试使用 */
|
||||
|
||||
if ((buf[0] == 0x5A) && (buf[1] == 0xAA) && (buf[2] == 0xA5)) {
|
||||
memset(buf_rx, 0, 256);
|
||||
memcpy(buf_rx, buf, rlen);
|
||||
/* log_info("need len = %d\n", buf_rx[5] + 6); */
|
||||
/* log_info("rx len = %d\n", rlen); */
|
||||
if ((buf_rx[5] + 6) == rlen) {
|
||||
rx_len_total = 0;
|
||||
#if TCFG_CFG_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE
|
||||
#if (TCFG_COMM_TYPE == TCFG_USB_COMM)
|
||||
/* put_buf(buf_rx, rlen); */
|
||||
online_cfg_tool_data_deal(buf_rx, rlen);
|
||||
#else
|
||||
put_buf(buf, rlen);
|
||||
cdc_write_data(usb_id, buf, rlen);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
rx_len_total += rlen;
|
||||
}
|
||||
} else {
|
||||
if ((rx_len_total + rlen) > 256) {
|
||||
memset(buf_rx, 0, 256);
|
||||
rx_len_total = 0;
|
||||
return;
|
||||
}
|
||||
memcpy(buf_rx + rx_len_total, buf, rlen);
|
||||
/* log_info("need len = %d\n", buf_rx[5] + 6); */
|
||||
/* log_info("rx len = %d\n", rx_len_total + rlen); */
|
||||
if ((buf_rx[5] + 6) == (rx_len_total + rlen)) {
|
||||
#if TCFG_CFG_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE
|
||||
#if (TCFG_COMM_TYPE == TCFG_USB_COMM)
|
||||
/* put_buf(buf_rx, rx_len_total + rlen); */
|
||||
online_cfg_tool_data_deal(buf_rx, rx_len_total + rlen);
|
||||
#else
|
||||
put_buf(buf, rlen);
|
||||
cdc_write_data(usb_id, buf, rlen);
|
||||
#endif
|
||||
#endif
|
||||
rx_len_total = 0;
|
||||
} else {
|
||||
rx_len_total += rlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void usb_start()
|
||||
{
|
||||
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
usb_audio_demo_init();
|
||||
#endif
|
||||
|
||||
#ifdef USB_DEVICE_CLASS_CONFIG
|
||||
g_printf("USB_DEVICE_CLASS_CONFIG:%x", USB_DEVICE_CLASS_CONFIG);
|
||||
#if TCFG_USB_CDC_BACKGROUND_RUN
|
||||
usb_device_mode(usbfd, USB_DEVICE_CLASS_CONFIG | CDC_CLASS);
|
||||
#else
|
||||
usb_device_mode(usbfd, USB_DEVICE_CLASS_CONFIG);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
//没有复用时候判断 sd开关
|
||||
//复用时候判断是否参与复用
|
||||
#if (!TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_SD0_ENABLE)\
|
||||
||(TCFG_SD0_ENABLE && TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_DM_MULTIPLEX_WITH_SD_PORT != 0)
|
||||
msd_register_disk("sd0", NULL);
|
||||
#endif
|
||||
|
||||
#if (!TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_SD1_ENABLE)\
|
||||
||(TCFG_SD1_ENABLE && TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_DM_MULTIPLEX_WITH_SD_PORT != 1)
|
||||
msd_register_disk("sd1", NULL);
|
||||
#endif
|
||||
|
||||
#if TCFG_NOR_FAT
|
||||
msd_register_disk("fat_nor", NULL);
|
||||
#endif
|
||||
|
||||
#if TCFG_VIR_UDISK_ENABLE
|
||||
msd_register_disk("vir_udisk0", NULL);
|
||||
#endif
|
||||
|
||||
msd_set_wakeup_handle(usb_msd_wakeup);
|
||||
msd_set_reset_wakeup_handle(usb_msd_reset_wakeup);
|
||||
usb_msd_init();
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
cdc_set_wakeup_handler(usb_cdc_wakeup);
|
||||
#endif
|
||||
}
|
||||
static void usb_remove_disk()
|
||||
{
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
os_mutex_pend(&msd_mutex, 0);
|
||||
msd_unregister_all();
|
||||
os_mutex_post(&msd_mutex);
|
||||
#endif
|
||||
}
|
||||
void usb_pause()
|
||||
{
|
||||
log_info("usb pause");
|
||||
|
||||
usb_sie_disable(usbfd);
|
||||
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
if (msd_set_wakeup_handle(NULL)) {
|
||||
usb_remove_disk();
|
||||
usb_msd_free();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
usb_audio_demo_exit();
|
||||
#endif
|
||||
|
||||
usb_device_mode(usbfd, 0);
|
||||
}
|
||||
|
||||
void usb_stop()
|
||||
{
|
||||
log_info("App Stop - usb");
|
||||
|
||||
usb_pause();
|
||||
|
||||
usb_sie_close(usbfd);
|
||||
}
|
||||
|
||||
#if TCFG_USB_CDC_BACKGROUND_RUN
|
||||
void usb_cdc_background_run()
|
||||
{
|
||||
g_printf("CDC is running in the background");
|
||||
usb_device_mode(0, CDC_CLASS);
|
||||
cdc_set_wakeup_handler(usb_cdc_wakeup);
|
||||
}
|
||||
#endif
|
||||
|
||||
int pc_device_event_handler(struct sys_event *event)
|
||||
{
|
||||
if ((int)event->arg != DEVICE_EVENT_FROM_OTG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int switch_app_case = false;
|
||||
const char *usb_msg = (const char *)event->u.dev.value;
|
||||
log_debug("usb event : %d DEVICE_EVENT_FROM_OTG %s", event->u.dev.event, usb_msg);
|
||||
|
||||
if (usb_msg[0] == 's') {
|
||||
if (event->u.dev.event == DEVICE_EVENT_IN) {
|
||||
log_info("usb %c online", usb_msg[2]);
|
||||
usbfd = usb_msg[2] - '0';
|
||||
#if USB_PC_NO_APP_MODE
|
||||
usb_start();
|
||||
#elif TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0
|
||||
|
||||
#if TCFG_USB_CDC_BACKGROUND_RUN
|
||||
mult_sdio_suspend();
|
||||
usb_cdc_background_run();
|
||||
switch_app_case = 0;
|
||||
#else
|
||||
usb_otg_suspend(0, OTG_KEEP_STATE);
|
||||
mult_sdio_suspend();
|
||||
usb_pause();
|
||||
mult_sdio_resume();
|
||||
switch_app_case = 0;
|
||||
#endif//TCFG_USB_CDC_BACKGROUND_RUN
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#if (TWFG_APP_POWERON_IGNORE_DEV && TCFG_USB_CDC_BACKGROUND_RUN && TCFG_PC_ENABLE)
|
||||
if (jiffies_to_msecs(jiffies) < TWFG_APP_POWERON_IGNORE_DEV) {
|
||||
usb_cdc_background_run();
|
||||
switch_app_case = 0;
|
||||
} else {
|
||||
usb_pause();
|
||||
switch_app_case = 1;
|
||||
}
|
||||
#elif (TCFG_USB_CDC_BACKGROUND_RUN)
|
||||
usb_cdc_background_run();
|
||||
switch_app_case = 0;
|
||||
|
||||
#elif (TWFG_APP_POWERON_IGNORE_DEV == 0)
|
||||
usb_pause();
|
||||
switch_app_case = 1;
|
||||
|
||||
#else
|
||||
usb_pause();
|
||||
switch_app_case = 1;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
} else if (event->u.dev.event == DEVICE_EVENT_OUT) {
|
||||
log_info("usb %c offline", usb_msg[2]);
|
||||
#if USB_PC_NO_APP_MODE
|
||||
usb_stop();
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_SOUNDBOX
|
||||
if (true == app_check_curr_task(APP_PC_TASK)) {
|
||||
#else
|
||||
if (app_get_curr_task() == APP_PC_TASK) {
|
||||
#endif
|
||||
switch_app_case = 2;
|
||||
} else {
|
||||
/* 此处的模式限制会在USB已连接,蓝牙播歌切换到蓝牙模式后再拔出USB的情况下,
|
||||
无法检测到再次插入USB */
|
||||
#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0
|
||||
mult_sdio_suspend();
|
||||
#endif
|
||||
usb_stop();
|
||||
#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0
|
||||
mult_sdio_resume();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return switch_app_case;
|
||||
}
|
||||
|
||||
#if USB_PC_NO_APP_MODE
|
||||
void usbstack_init()
|
||||
{
|
||||
register_sys_event_handler(SYS_DEVICE_EVENT, DEVICE_EVENT_FROM_OTG, 2,
|
||||
(void (*)(struct sys_event *))pc_device_event_handler);
|
||||
}
|
||||
|
||||
void usbstack_exit()
|
||||
{
|
||||
unregister_sys_event_handler((void (*)(struct sys_event *))pc_device_event_handler);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (TCFG_OTG_MODE & OTG_DET_DM_ONLY)
|
||||
static void otg_sof_check_before_hook()
|
||||
{
|
||||
log_debug("sof_check_before");
|
||||
#if ((TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE) \
|
||||
&& TCFG_CHARGESTORE_PORT == IO_PORT_DP)
|
||||
power_wakeup_index_enable(2, 0);
|
||||
chargestore_api_stop();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void otg_sof_check_after_hook()
|
||||
{
|
||||
log_debug("sof_check_after");
|
||||
#if ((TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE) \
|
||||
&& TCFG_CHARGESTORE_PORT == IO_PORT_DP)
|
||||
chargestore_api_restart();
|
||||
power_wakeup_index_enable(2, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int otg_sof_check_hook_register()
|
||||
{
|
||||
//需要在otg定时器启动之前(即devices_init()之前)注册钩子函数
|
||||
usb_otg_sof_check_register_hooks(otg_sof_check_before_hook,
|
||||
otg_sof_check_after_hook);
|
||||
return 0;
|
||||
}
|
||||
early_initcall(otg_sof_check_hook_register);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,514 @@
|
||||
#include "app_config.h"
|
||||
#include "system/includes.h"
|
||||
#include "printf.h"
|
||||
#include "usb/usb_config.h"
|
||||
#include "usb/device/usb_stack.h"
|
||||
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
#include "usb/device/uac_audio.h"
|
||||
#include "uac_stream.h"
|
||||
#include "audio_config.h"
|
||||
|
||||
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
|
||||
#include "audio_track.h"
|
||||
/* #endif */
|
||||
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[UAC]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#define UAC_DEBUG_ECHO_MODE 0
|
||||
|
||||
static volatile u8 speaker_stream_is_open = 0;
|
||||
struct uac_speaker_handle {
|
||||
cbuffer_t cbuf;
|
||||
volatile u8 need_resume;
|
||||
u8 channel;
|
||||
u8 alive;
|
||||
void *buffer;
|
||||
void *audio_track;
|
||||
//void (*rx_handler)(int, void *, int);
|
||||
};
|
||||
|
||||
static void (*uac_rx_handler)(int, void *, int) = NULL;
|
||||
|
||||
#if (SOUNDCARD_ENABLE)
|
||||
#define UAC_BUFFER_SIZE (4 * 1024)
|
||||
#else
|
||||
#define UAC_BUFFER_SIZE (1 * 1024)
|
||||
#endif
|
||||
|
||||
#define UAC_BUFFER_MAX (UAC_BUFFER_SIZE * 50 / 100)
|
||||
|
||||
static struct uac_speaker_handle *uac_speaker = NULL;
|
||||
|
||||
#if USB_MALLOC_ENABLE
|
||||
#else
|
||||
static struct uac_speaker_handle uac_speaker_handle SEC(.uac_var);
|
||||
static u8 uac_rx_buffer[UAC_BUFFER_SIZE] ALIGNED(4) SEC(.uac_rx);
|
||||
#endif
|
||||
u32 uac_speaker_stream_length()
|
||||
{
|
||||
return UAC_BUFFER_SIZE;
|
||||
}
|
||||
u32 uac_speaker_stream_size()
|
||||
{
|
||||
if (!speaker_stream_is_open) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uac_speaker) {
|
||||
return cbuf_get_data_size(&uac_speaker->cbuf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 uac_speaker_get_alive()
|
||||
{
|
||||
if (uac_speaker) {
|
||||
return uac_speaker->alive;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void uac_speaker_set_alive(u8 alive)
|
||||
{
|
||||
local_irq_disable();
|
||||
if (uac_speaker) {
|
||||
uac_speaker->alive = alive;
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
void uac_speaker_stream_buf_clear(void)
|
||||
{
|
||||
if (speaker_stream_is_open) {
|
||||
cbuf_clear(&uac_speaker->cbuf);
|
||||
}
|
||||
}
|
||||
|
||||
void set_uac_speaker_rx_handler(void *priv, void (*rx_handler)(int, void *, int))
|
||||
{
|
||||
uac_rx_handler = rx_handler;
|
||||
/* if (uac_speaker) { */
|
||||
/* uac_speaker->rx_handler = rx_handler; */
|
||||
/* } */
|
||||
}
|
||||
|
||||
int uac_speaker_stream_sample_rate(void)
|
||||
{
|
||||
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
|
||||
if (uac_speaker && uac_speaker->audio_track) {
|
||||
int sr = audio_local_sample_track_rate(uac_speaker->audio_track);
|
||||
if ((sr < (SPK_AUDIO_RATE + 100)) && (sr > (SPK_AUDIO_RATE - 100))) {
|
||||
return sr;
|
||||
}
|
||||
/* printf("uac audio_track reset \n"); */
|
||||
/* local_irq_disable(); */
|
||||
/* audio_local_sample_track_close(uac_speaker->audio_track); */
|
||||
/* uac_speaker->audio_track = audio_local_sample_track_open(SPK_CHANNEL, SPK_AUDIO_RATE, 1000); */
|
||||
/* local_irq_enable(); */
|
||||
}
|
||||
/* #endif */
|
||||
return SPK_AUDIO_RATE;
|
||||
}
|
||||
|
||||
void uac_speaker_stream_write(const u8 *obuf, u32 len)
|
||||
{
|
||||
if (speaker_stream_is_open) {
|
||||
//write dac
|
||||
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
|
||||
if (uac_speaker->audio_track) {
|
||||
audio_local_sample_track_in_period(uac_speaker->audio_track, (len >> 1) / uac_speaker->channel);
|
||||
}
|
||||
/* #endif */
|
||||
int wlen = cbuf_write(&uac_speaker->cbuf, (void *)obuf, len);
|
||||
if (wlen != len) {
|
||||
//putchar('W');
|
||||
}
|
||||
//if (uac_speaker->rx_handler) {
|
||||
if (uac_rx_handler) {
|
||||
/* if (uac_speaker->cbuf.data_len >= UAC_BUFFER_MAX) { */
|
||||
// 马上就要满了,赶紧取走
|
||||
uac_speaker->need_resume = 1; //2020-12-22注:无需唤醒
|
||||
/* } */
|
||||
if (uac_speaker->need_resume) {
|
||||
uac_speaker->need_resume = 0;
|
||||
uac_rx_handler(0, (void *)obuf, len);
|
||||
//uac_speaker->rx_handler(0, (void *)obuf, len);
|
||||
}
|
||||
}
|
||||
uac_speaker->alive = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int uac_speaker_read(void *priv, void *data, u32 len)
|
||||
{
|
||||
int r_len;
|
||||
int err = 0;
|
||||
|
||||
local_irq_disable();
|
||||
if (!speaker_stream_is_open) {
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
r_len = cbuf_get_data_size(&uac_speaker->cbuf);
|
||||
if (r_len) {
|
||||
r_len = r_len > len ? len : r_len;
|
||||
r_len = cbuf_read(&uac_speaker->cbuf, data, r_len);
|
||||
if (!r_len) {
|
||||
putchar('U');
|
||||
}
|
||||
}
|
||||
|
||||
if (r_len == 0) {
|
||||
uac_speaker->need_resume = 1;
|
||||
}
|
||||
local_irq_enable();
|
||||
return r_len;
|
||||
}
|
||||
|
||||
void uac_speaker_stream_open(u32 samplerate, u32 ch)
|
||||
{
|
||||
if (speaker_stream_is_open) {
|
||||
return;
|
||||
}
|
||||
log_info("%s", __func__);
|
||||
|
||||
if (!uac_speaker) {
|
||||
#if USB_MALLOC_ENABLE
|
||||
|
||||
uac_speaker = zalloc(sizeof(struct uac_speaker_handle));
|
||||
if (!uac_speaker) {
|
||||
return;
|
||||
}
|
||||
|
||||
uac_speaker->buffer = malloc(UAC_BUFFER_SIZE);
|
||||
if (!uac_speaker->buffer) {
|
||||
free(uac_speaker);
|
||||
uac_speaker = NULL;
|
||||
goto __err;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
uac_speaker = &uac_speaker_handle;
|
||||
|
||||
memset(uac_speaker, 0, sizeof(struct uac_speaker_handle));
|
||||
|
||||
uac_speaker->buffer = uac_rx_buffer;
|
||||
#endif
|
||||
uac_speaker->channel = ch;
|
||||
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
|
||||
uac_speaker->audio_track = audio_local_sample_track_open(ch, samplerate, 1000);
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
|
||||
//uac_speaker->rx_handler = NULL;
|
||||
|
||||
cbuf_init(&uac_speaker->cbuf, uac_speaker->buffer, UAC_BUFFER_SIZE);
|
||||
speaker_stream_is_open = 1;
|
||||
struct sys_event event;
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
|
||||
event.u.dev.event = USB_AUDIO_PLAY_OPEN;
|
||||
event.u.dev.value = (int)((ch << 24) | samplerate);
|
||||
|
||||
#if !UAC_DEBUG_ECHO_MODE
|
||||
sys_event_notify(&event);
|
||||
#endif
|
||||
|
||||
return;
|
||||
|
||||
__err:
|
||||
return;
|
||||
}
|
||||
|
||||
void uac_speaker_stream_close()
|
||||
{
|
||||
if (speaker_stream_is_open == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
log_info("%s", __func__);
|
||||
speaker_stream_is_open = 0;
|
||||
|
||||
if (uac_speaker) {
|
||||
/* #ifdef CONFIG_MEDIA_DEVELOP_ENABLE */
|
||||
audio_local_sample_track_close(uac_speaker->audio_track);
|
||||
/* #endif */
|
||||
uac_speaker->audio_track = NULL;
|
||||
#if USB_MALLOC_ENABLE
|
||||
if (uac_speaker->buffer) {
|
||||
free(uac_speaker->buffer);
|
||||
}
|
||||
free(uac_speaker);
|
||||
#endif
|
||||
uac_speaker = NULL;
|
||||
}
|
||||
struct sys_event event;
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
|
||||
event.u.dev.event = USB_AUDIO_PLAY_CLOSE;
|
||||
event.u.dev.value = (int)0;
|
||||
|
||||
#if !UAC_DEBUG_ECHO_MODE
|
||||
sys_event_notify(&event);
|
||||
#endif
|
||||
}
|
||||
|
||||
int uac_get_spk_vol()
|
||||
{
|
||||
int max_vol = get_max_sys_vol();
|
||||
int vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
|
||||
if (vol * 100 / max_vol < 100) {
|
||||
return vol * 100 / max_vol;
|
||||
} else {
|
||||
return 99;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static u8 flag_uac_event_enable = 1;
|
||||
void set_uac_event_flag(u8 en)
|
||||
{
|
||||
flag_uac_event_enable = en;
|
||||
}
|
||||
u8 get_uac_event_flag(void)
|
||||
{
|
||||
return flag_uac_event_enable;
|
||||
}
|
||||
static volatile u32 mic_stream_is_open;
|
||||
|
||||
u8 uac_get_mic_stream_status(void)
|
||||
{
|
||||
return mic_stream_is_open;
|
||||
}
|
||||
|
||||
void uac_mute_volume(u32 type, u32 l_vol, u32 r_vol)
|
||||
{
|
||||
struct sys_event event;
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
|
||||
|
||||
static u32 last_spk_l_vol = (u32) - 1, last_spk_r_vol = (u32) - 1;
|
||||
static u32 last_mic_vol = (u32) - 1;
|
||||
|
||||
if (!get_uac_event_flag()) {
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case MIC_FEATURE_UNIT_ID: //MIC
|
||||
if (mic_stream_is_open == 0) {
|
||||
return ;
|
||||
}
|
||||
if (l_vol == last_mic_vol) {
|
||||
return;
|
||||
}
|
||||
last_mic_vol = l_vol;
|
||||
event.u.dev.event = USB_AUDIO_SET_MIC_VOL;
|
||||
break;
|
||||
case SPK_FEATURE_UNIT_ID: //SPK
|
||||
if (speaker_stream_is_open == 0) {
|
||||
return;
|
||||
}
|
||||
if (l_vol == last_spk_l_vol && r_vol == last_spk_r_vol) {
|
||||
return;
|
||||
}
|
||||
last_spk_l_vol = l_vol;
|
||||
last_spk_r_vol = r_vol;
|
||||
event.u.dev.event = USB_AUDIO_SET_PLAY_VOL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
event.u.dev.value = (int)(r_vol << 16 | l_vol);
|
||||
#if !UAC_DEBUG_ECHO_MODE
|
||||
sys_event_notify(&event);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int (*mic_tx_handler)(int, void *, int) = NULL;
|
||||
int uac_mic_stream_read(u8 *buf, u32 len)
|
||||
{
|
||||
if (mic_stream_is_open == 0) {
|
||||
return 0;
|
||||
}
|
||||
#if 0//48K 1ksin
|
||||
const s16 sin_48k[] = {
|
||||
0, 2139, 4240, 6270, 8192, 9974, 11585, 12998,
|
||||
14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137,
|
||||
14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139,
|
||||
0, -2139, -4240, -6270, -8192, -9974, -11585, -12998,
|
||||
-14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137,
|
||||
-14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139
|
||||
};
|
||||
u16 *l_ch = (u16 *)buf;
|
||||
u16 *r_ch = (u16 *)buf;
|
||||
r_ch++;
|
||||
for (int i = 0; i < len / 2; i++) {
|
||||
*l_ch = sin_48k[i];
|
||||
*r_ch = sin_48k[i];
|
||||
l_ch += 1;
|
||||
r_ch += 1;
|
||||
}
|
||||
return len;
|
||||
#elif UAC_DEBUG_ECHO_MODE
|
||||
#if MIC_CHANNEL == 2
|
||||
uac_speaker_read(NULL, buf, len);
|
||||
const s16 sin_48k[] = {
|
||||
0, 2139, 4240, 6270, 8192, 9974, 11585, 12998,
|
||||
14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137,
|
||||
14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139,
|
||||
0, -2139, -4240, -6270, -8192, -9974, -11585, -12998,
|
||||
-14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137,
|
||||
-14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139
|
||||
};
|
||||
u16 *r_ch = (u16 *)buf;
|
||||
r_ch++;
|
||||
for (int i = 0; i < len / 4; i++) {
|
||||
*r_ch = sin_48k[i];
|
||||
r_ch += 2;
|
||||
}
|
||||
#else
|
||||
uac_speaker_read(NULL, buf, len * 2);
|
||||
u16 *r_ch = (u16 *)buf;
|
||||
for (int i = 0; i < len / 2; i++) {
|
||||
r_ch[i] = r_ch[i * 2];
|
||||
}
|
||||
|
||||
#endif
|
||||
return len;
|
||||
#else
|
||||
if (mic_tx_handler) {
|
||||
#if 1
|
||||
return mic_tx_handler(0, buf, len);
|
||||
#else
|
||||
//16bit ---> 24bit
|
||||
int rlen = mic_tx_handler(0, tmp_buf, len / 3 * 2);
|
||||
rlen /= 2; //sampe point
|
||||
for (int i = 0 ; i < rlen ; i++) {
|
||||
buf[i * 3] = 0;
|
||||
buf[i * 3 + 1] = tmp_buf[i * 2];
|
||||
buf[i * 3 + 2] = tmp_buf[i * 2 + 1];
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
//putchar('N');
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_uac_mic_tx_handler(void *priv, int (*tx_handler)(int, void *, int))
|
||||
{
|
||||
mic_tx_handler = tx_handler;
|
||||
}
|
||||
static u32 mic_close_tid = 0;
|
||||
static u8 mic_sw;
|
||||
u32 uac_mic_stream_open(u32 samplerate, u32 frame_len, u32 ch)
|
||||
{
|
||||
mic_sw = 1;
|
||||
if (mic_stream_is_open) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mic_tx_handler = NULL; */
|
||||
log_info("%s", __func__);
|
||||
|
||||
struct sys_event event;
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
|
||||
event.u.dev.event = USB_AUDIO_MIC_OPEN;
|
||||
event.u.dev.value = (int)((ch << 24) | samplerate);
|
||||
mic_stream_is_open = 1;
|
||||
|
||||
#if !UAC_DEBUG_ECHO_MODE
|
||||
sys_event_notify(&event);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uac_mic_stream_close_delay()
|
||||
{
|
||||
mic_close_tid = 0;
|
||||
if (!mic_sw) {
|
||||
|
||||
} else {
|
||||
return ;
|
||||
}
|
||||
log_info("%s", __func__);
|
||||
struct sys_event event;
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_UAC;
|
||||
event.u.dev.event = USB_AUDIO_MIC_CLOSE;
|
||||
event.u.dev.value = (int)0;
|
||||
mic_stream_is_open = 0;
|
||||
|
||||
#if !UAC_DEBUG_ECHO_MODE
|
||||
sys_event_notify(&event);
|
||||
#endif
|
||||
}
|
||||
void uac_mic_stream_close()
|
||||
{
|
||||
mic_sw = 0;
|
||||
if (mic_stream_is_open == 0) {
|
||||
return ;
|
||||
}
|
||||
//FIXME:
|
||||
//未知原因出现频繁开关mic,导致出现audio或者蓝牙工作异常,
|
||||
//收到mic关闭命令后延时1s再发消息通知audio模块执行关闭动作
|
||||
//如果在1s之内继续收到usb下发的关闭命令,则继续推迟1s。
|
||||
if (mic_close_tid == 0) {
|
||||
mic_close_tid = sys_hi_timeout_add(NULL, uac_mic_stream_close_delay, 1000);
|
||||
} else {
|
||||
sys_hi_timeout_modify(mic_close_tid, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
_WEAK_
|
||||
s8 app_audio_get_volume(u8 state)
|
||||
{
|
||||
return 88;
|
||||
}
|
||||
_WEAK_
|
||||
void usb_audio_demo_exit(void)
|
||||
{
|
||||
|
||||
}
|
||||
_WEAK_
|
||||
int usb_audio_demo_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
_WEAK_
|
||||
u8 get_max_sys_vol(void)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
_WEAK_
|
||||
void *audio_local_sample_track_open(u8 channel, int sample_rate, int period)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
_WEAK_
|
||||
int audio_local_sample_track_in_period(void *c, int samples)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
_WEAK_
|
||||
void audio_local_sample_track_close(void *c)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
/*****************************************************************
|
||||
>file name : usb_audio.h
|
||||
>author : lichao
|
||||
>create time : Wed 22 May 2019 10:39:35 AM CST
|
||||
*****************************************************************/
|
||||
#ifndef _UAC_STREAM_H_
|
||||
#define _UAC_STREAM_H_
|
||||
#include "typedef.h"
|
||||
|
||||
enum uac_event {
|
||||
USB_AUDIO_PLAY_OPEN = 0x0,
|
||||
USB_AUDIO_PLAY_CLOSE,
|
||||
USB_AUDIO_MIC_OPEN,
|
||||
USB_AUDIO_MIC_CLOSE,
|
||||
// USB_AUDIO_MUTE,
|
||||
USB_AUDIO_SET_PLAY_VOL,
|
||||
USB_AUDIO_SET_MIC_VOL,
|
||||
};
|
||||
|
||||
|
||||
void uac_speaker_stream_buf_clear(void);
|
||||
u32 uac_speaker_stream_length();
|
||||
u32 uac_speaker_stream_size();
|
||||
void set_uac_speaker_rx_handler(void *priv, void (*rx_handler)(int, void *, int));
|
||||
void set_uac_mic_tx_handler(void *priv, int (*tx_handler)(int, void *, int));
|
||||
int uac_speaker_stream_sample_rate(void);
|
||||
|
||||
int uac_speaker_read(void *priv, void *data, u32 len);
|
||||
u32 uac_speaker_get_alive();
|
||||
void uac_speaker_set_alive(u8 alive);
|
||||
#endif
|
||||
@@ -0,0 +1,258 @@
|
||||
#include "usb/device/usb_stack.h"
|
||||
#include "usb_config.h"
|
||||
#include "usb/device/msd.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb/device/hid.h"
|
||||
#include "usb/device/uac_audio.h"
|
||||
#include "usb/device/cdc.h"
|
||||
#include "irq.h"
|
||||
#include "init.h"
|
||||
#include "gpio.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#if TCFG_USB_SLAVE_ENABLE
|
||||
|
||||
static void usb_device_init(const usb_dev usb_id)
|
||||
{
|
||||
|
||||
usb_config(usb_id);
|
||||
usb_g_sie_init(usb_id);
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
usb_write_power(usb_id, 0x40);
|
||||
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
|
||||
usb_write_power(usb_id, 0x60);
|
||||
#endif
|
||||
usb_slave_init(usb_id);
|
||||
u8 *ep0_dma_buffer = usb_alloc_ep_dmabuffer(usb_id, 0, 64);
|
||||
|
||||
usb_set_dma_raddr(usb_id, 0, ep0_dma_buffer);
|
||||
usb_set_dma_raddr(usb_id, 1, ep0_dma_buffer);
|
||||
usb_set_dma_raddr(usb_id, 2, ep0_dma_buffer);
|
||||
usb_set_dma_raddr(usb_id, 3, ep0_dma_buffer);
|
||||
usb_set_dma_raddr(usb_id, 4, ep0_dma_buffer);
|
||||
|
||||
usb_write_intr_usbe(usb_id, INTRUSB_RESET_BABBLE | INTRUSB_SUSPEND);
|
||||
usb_clr_intr_txe(usb_id, -1);
|
||||
usb_clr_intr_rxe(usb_id, -1);
|
||||
usb_set_intr_txe(usb_id, 0);
|
||||
usb_set_intr_rxe(usb_id, 0);
|
||||
usb_g_isr_reg(usb_id, 3, 0);
|
||||
/* usb_sof_isr_reg(usb_id,3,0); */
|
||||
/* usb_sofie_enable(usb_id); */
|
||||
/* USB_DEBUG_PRINTF("ep0 addr %x %x\n", usb_get_dma_taddr(0), ep0_dma_buffer); */
|
||||
}
|
||||
static void usb_device_hold(const usb_dev usb_id)
|
||||
{
|
||||
|
||||
usb_g_hold(usb_id);
|
||||
usb_release(usb_id);
|
||||
}
|
||||
|
||||
|
||||
static int usb_ep_conflict_check(const usb_dev usb_id);
|
||||
int usb_device_mode(const usb_dev usb_id, const u32 class)
|
||||
{
|
||||
|
||||
/* usb_device_set_class(CLASS_CONFIG); */
|
||||
u8 class_index = 0;
|
||||
if (class == 0) {
|
||||
gpio_direction_input(IO_PORT_DM + 2 * usb_id);
|
||||
gpio_set_pull_up(IO_PORT_DM + 2 * usb_id, 0);
|
||||
gpio_set_pull_down(IO_PORT_DM + 2 * usb_id, 0);
|
||||
gpio_set_die(IO_PORT_DM + 2 * usb_id, 0);
|
||||
|
||||
gpio_direction_input(IO_PORT_DP + 2 * usb_id);
|
||||
gpio_set_pull_up(IO_PORT_DP + 2 * usb_id, 0);
|
||||
gpio_set_pull_down(IO_PORT_DP + 2 * usb_id, 0);
|
||||
gpio_set_die(IO_PORT_DP + 2 * usb_id, 0);
|
||||
|
||||
os_time_dly(15);
|
||||
|
||||
gpio_set_die(IO_PORT_DM + 2 * usb_id, 1);
|
||||
gpio_set_die(IO_PORT_DP + 2 * usb_id, 1);
|
||||
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
msd_release(usb_id);
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
uac_release(usb_id);
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
cdc_release(usb_id);
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
hid_release(usb_id);
|
||||
#endif
|
||||
usb_device_hold(usb_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* int ret = usb_ep_conflict_check(usb_id); */
|
||||
/* if (ret) { */
|
||||
/* return ret; */
|
||||
/* } */
|
||||
|
||||
usb_memory_init();
|
||||
|
||||
usb_add_desc_config(usb_id, MAX_INTERFACE_NUM, NULL);
|
||||
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
if ((class & MASSSTORAGE_CLASS) == MASSSTORAGE_CLASS) {
|
||||
log_info("add desc msd");
|
||||
usb_add_desc_config(usb_id, class_index++, msd_desc_config);
|
||||
msd_register(usb_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
if ((class & AUDIO_CLASS) == AUDIO_CLASS) {
|
||||
log_info("add audio desc");
|
||||
usb_add_desc_config(usb_id, class_index++, uac_audio_desc_config);
|
||||
uac_register(usb_id, AUDIO_CLASS);
|
||||
} else if ((class & SPEAKER_CLASS) == SPEAKER_CLASS) {
|
||||
log_info("add desc speaker");
|
||||
usb_add_desc_config(usb_id, class_index++, uac_spk_desc_config);
|
||||
uac_register(usb_id, SPEAKER_CLASS);
|
||||
} else if ((class & MIC_CLASS) == MIC_CLASS) {
|
||||
log_info("add desc mic");
|
||||
usb_add_desc_config(usb_id, class_index++, uac_mic_desc_config);
|
||||
uac_register(usb_id, MIC_CLASS);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
if ((class & HID_CLASS) == HID_CLASS) {
|
||||
log_info("add desc std hid");
|
||||
usb_add_desc_config(usb_id, class_index++, hid_desc_config);
|
||||
hid_register(usb_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
if ((class & CDC_CLASS) == CDC_CLASS) {
|
||||
log_info("add desc cdc");
|
||||
usb_add_desc_config(usb_id, class_index++, cdc_desc_config);
|
||||
cdc_register(usb_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_device_init(usb_id);
|
||||
user_setup_filter_install(usb_id2device(usb_id));
|
||||
return 0;
|
||||
}
|
||||
/* module_initcall(usb_device_mode); */
|
||||
|
||||
static int usb_ep_conflict_check(const usb_dev usb_id)
|
||||
{
|
||||
u8 usb_ep_tx_list[] = {
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
MSD_BULK_EP_IN,
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
HID_EP_IN,
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
MIC_ISO_EP_IN,
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
CDC_DATA_EP_IN,
|
||||
#if CDC_INTR_EP_ENABLE
|
||||
CDC_INTR_EP_IN,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
u8 usb_ep_rx_list[] = {
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
MSD_BULK_EP_OUT,
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
HID_EP_OUT,
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
SPK_ISO_EP_OUT,
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
CDC_DATA_EP_OUT,
|
||||
#endif
|
||||
};
|
||||
int ret = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < sizeof(usb_ep_tx_list) - 1; i++) {
|
||||
for (j = i + 1; j < sizeof(usb_ep_tx_list); j++) {
|
||||
if (usb_ep_tx_list[i] == usb_ep_tx_list[j]) {
|
||||
ret = -1;
|
||||
ASSERT(0, "ep%d conflict, dir in\n", usb_ep_tx_list[i]);
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < sizeof(usb_ep_rx_list) - 1; i++) {
|
||||
for (j = i + 1; j < sizeof(usb_ep_rx_list); j++) {
|
||||
if (usb_ep_rx_list[i] == usb_ep_rx_list[j]) {
|
||||
ret = -1;
|
||||
ASSERT(0, "ep%d conflict, dir out\n", usb_ep_rx_list[i]);
|
||||
goto __exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
__exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @brief otg检测中sof初始化,不要放在TCFG_USB_SLAVE_ENABLE里
|
||||
* @parm id usb设备号
|
||||
* @return 0 ,忽略sof检查,1 等待sof信号
|
||||
*/
|
||||
u32 usb_otg_sof_check_init(const usb_dev id)
|
||||
{
|
||||
/* return 0;// */
|
||||
u8 *ep0_dma_buffer = usb_alloc_ep_dmabuffer(id, 0, 64);
|
||||
|
||||
usb_g_sie_init(id);
|
||||
|
||||
#ifdef USB_HW_20
|
||||
//husb调用完usb_g_sie_init(),或者收到usb reset中断,intrusbe,intrtxe,
|
||||
//intrrxe会复位成默认值,不手动清零以及关中断,会收到usb reset中断,由于
|
||||
//空指针问题导致异常
|
||||
usb_write_intr_usbe(id, 0);
|
||||
usb_clr_intr_txe(id, -1);
|
||||
usb_clr_intr_rxe(id, -1);
|
||||
if (id == 0) {
|
||||
unrequest_irq(IRQ_USB_CTRL_IDX);
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
} else {
|
||||
unrequest_irq(IRQ_USB1_CTRL_IDX);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
usb_write_power(id, 0x40);
|
||||
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
|
||||
usb_write_power(id, 0x60);
|
||||
#endif
|
||||
|
||||
usb_set_dma_raddr(id, 0, ep0_dma_buffer);
|
||||
|
||||
for (int ep = 1; ep < USB_MAX_HW_EPNUM; ep++) {
|
||||
usb_disable_ep(id, ep);
|
||||
}
|
||||
usb_sof_clr_pnd(id);
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
#include "usb/device/usb_stack.h"
|
||||
#include "usb_config.h"
|
||||
#include "usb/device/msd.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb/device/hid.h"
|
||||
#include "usb/device/uac_audio.h"
|
||||
#include "irq.h"
|
||||
#include "init.h"
|
||||
#include "gpio.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
#include "apple_dock/iAP.h"
|
||||
#endif
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#if TCFG_USB_SLAVE_ENABLE
|
||||
|
||||
static const u8 user_stirng[] = {
|
||||
24,
|
||||
0x03,
|
||||
'U', 0x00,
|
||||
'S', 0x00,
|
||||
'B', 0x00,
|
||||
'A', 0x00,
|
||||
'u', 0x00,
|
||||
'd', 0x00,
|
||||
'i', 0x00,
|
||||
'o', 0x00,
|
||||
'1', 0x00,
|
||||
'.', 0x00,
|
||||
'0', 0x00,
|
||||
};
|
||||
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
static const u8 IAP_interface_string[] = {
|
||||
0x1c, 0x03,
|
||||
//iAP Interface
|
||||
0x69, 0x00, 0x41, 0x00, 0x50, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x74, 0x00,
|
||||
0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00
|
||||
};
|
||||
#endif
|
||||
|
||||
static u8 root2_testing;
|
||||
u32 usb_root2_testing()
|
||||
{
|
||||
#if USB_ROOT2
|
||||
return root2_testing;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
u32 check_ep_vaild(u32 ep)
|
||||
{
|
||||
u32 en = 0;
|
||||
switch (ep) {
|
||||
case 0:
|
||||
en = 1;
|
||||
break;
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
case 1:
|
||||
en = 1;
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
case 2:
|
||||
en = 1;
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
case 3:
|
||||
en = 1;
|
||||
break;
|
||||
#endif
|
||||
case 4:
|
||||
break;
|
||||
}
|
||||
return en;
|
||||
}
|
||||
static u32 setup_endpoint(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
u32 tx_len = 0;
|
||||
u8 *tx_payload = usb_get_setup_buffer(usb_device);
|
||||
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
if (uac_setup_endpoint(usb_device, req)) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
u32 ep = LOBYTE(req->wIndex) & 0x0f;
|
||||
if (check_ep_vaild(ep) == 0) {
|
||||
usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);
|
||||
return 1;// not zero user handle this request
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
static u32 setup_device(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
|
||||
{
|
||||
const usb_dev usb_id = usb_device2id(usb_device);
|
||||
u32 ret = 0;
|
||||
switch (req->bRequest) {
|
||||
case USB_REQ_GET_DESCRIPTOR:
|
||||
switch (HIBYTE(req->wValue)) {
|
||||
case USB_DT_STRING:
|
||||
switch (LOBYTE(req->wValue)) {
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
case SPEAKER_STR_INDEX:
|
||||
case MIC_STR_INDEX:
|
||||
if (usb_device->bDeviceStates == USB_DEFAULT) {
|
||||
ret = 0;
|
||||
} else {
|
||||
usb_set_data_payload(usb_device, req, user_stirng, sizeof(user_stirng));
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
case MSD_STR_INDEX:
|
||||
if (apple_mfi_chip_online_lib()) {
|
||||
y_printf("MSD_STR_INDEX \n");
|
||||
usb_set_data_payload(usb_device, req, IAP_interface_string, sizeof(IAP_interface_string));
|
||||
apple_mfi_pass_ready_set_api();
|
||||
extern void apple_usb_msd_wakeup(struct usb_device_t *usb_device);
|
||||
apple_usb_msd_wakeup(usb_device);
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USB_DT_DEVICE:
|
||||
#if USB_ROOT2
|
||||
if (req->wLength == 0xffff) {
|
||||
root2_testing = 1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case USB_REQ_SET_CONFIGURATION:
|
||||
break;
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
/* if(req->wLength || req->wIndex){ */
|
||||
/* ret = 1; */
|
||||
/* usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); */
|
||||
/* dump_setup_request(req); */
|
||||
/* log_debug_hexdump((u8 *)req, 8); */
|
||||
/* } */
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 setup_other(struct usb_device_t *usb_device, struct usb_ctrlrequest *req)
|
||||
{
|
||||
u32 ret = 0;
|
||||
u32 tx_len;
|
||||
u8 *tx_payload = usb_get_setup_buffer(usb_device);
|
||||
switch (req->bRequest) {
|
||||
case USB_REQ_GET_STATUS:
|
||||
#if TCFG_TYPEC_EARPHONE_TEST_FILTER
|
||||
tx_len = 1;
|
||||
tx_payload[0] = 0xfe;
|
||||
usb_set_data_payload(usb_device, req, tx_payload, tx_len);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ret = 1 ;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static u32 user_setup_filter(struct usb_device_t *usb_device, struct usb_ctrlrequest *request)
|
||||
{
|
||||
// dump_setup_request(request);
|
||||
// log_debug_hexdump((u8 *)request, 8);
|
||||
u32 ret = 0;
|
||||
u32 recip = request->bRequestType & USB_RECIP_MASK;
|
||||
switch (recip) {
|
||||
case USB_RECIP_DEVICE:
|
||||
ret = setup_device(usb_device, request);
|
||||
break;
|
||||
case USB_RECIP_INTERFACE:
|
||||
break;
|
||||
case USB_RECIP_ENDPOINT:
|
||||
ret = setup_endpoint(usb_device, request);
|
||||
break;
|
||||
case USB_RECIP_OTHER:
|
||||
ret = setup_other(usb_device, request);
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
const char *statas[] = {"USB_ATTACHED", "USB_POWERED", "USB_DEFAULT",
|
||||
"USB_ADDRESS", "USB_CONFIGURED", "USB_SUSPENDED"
|
||||
};
|
||||
|
||||
const char *phases[] = {"SETUP", "IN", "OUT",
|
||||
"STALL",
|
||||
};
|
||||
|
||||
printf("state:%s phase: %s", statas[usb_device->bDeviceStates],
|
||||
phases[usb_device->bsetup_phase]);
|
||||
#endif
|
||||
return ret;// not zero user handle this request
|
||||
}
|
||||
void user_setup_filter_install(struct usb_device_t *usb_device)
|
||||
{
|
||||
usb_set_setup_hook(usb_device, user_setup_filter);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,459 @@
|
||||
#include "includes.h"
|
||||
#include "asm/includes.h"
|
||||
#include "system/timer.h"
|
||||
#include "device/ioctl_cmds.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "device_drive.h"
|
||||
#include "adb.h"
|
||||
#include "usb_config.h"
|
||||
#include "app_config.h"
|
||||
#if TCFG_ADB_ENABLE
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[adb]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#include "adb_rsa_key.c"
|
||||
|
||||
struct adb_device_t adb;
|
||||
|
||||
struct device adb_device;
|
||||
void aoa_switch(struct usb_host_device *host_dev);
|
||||
|
||||
static int set_adb_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static int get_adb_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static const struct interface_ctrl adb_ops = {
|
||||
.interface_class = USB_CLASS_ADB,
|
||||
.set_power = set_adb_power,
|
||||
.get_power = get_adb_power,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
static const struct usb_interface_info adb_inf = {
|
||||
.ctrl = (struct interface_ctrl *) &adb_ops,
|
||||
.dev.adb = &adb,
|
||||
};
|
||||
|
||||
u32 usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
int len = 0;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
for (int i = 0; i < interface->bNumEndpoints; i++) {
|
||||
struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)pBuf;
|
||||
if (endpoint->bDescriptorType == USB_DT_ENDPOINT) {
|
||||
if (endpoint->bmAttributes == USB_ENDPOINT_XFER_BULK) {
|
||||
if (endpoint->bEndpointAddress & USB_DIR_IN) {
|
||||
adb.extr_in = endpoint->bEndpointAddress & 0xf;
|
||||
} else {
|
||||
adb.extr_out = endpoint->bEndpointAddress;
|
||||
}
|
||||
}
|
||||
pBuf += USB_DT_ENDPOINT_SIZE;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
printf("%s() %x %x\n", __func__, adb.extr_in, adb.extr_out);
|
||||
return pBuf - (u8 *)interface ;
|
||||
}
|
||||
|
||||
int usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
int len = 0;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
adb_device.private_data = host_dev;
|
||||
|
||||
host_dev->interface_info[interface_num] = &adb_inf;
|
||||
|
||||
for (int endnum = 0; endnum < interface->bNumEndpoints; endnum++) {
|
||||
struct usb_endpoint_descriptor *end_desc = (struct usb_endpoint_descriptor *)pBuf;
|
||||
|
||||
if (end_desc->bDescriptorType != USB_DT_ENDPOINT ||
|
||||
end_desc->bLength != USB_DT_ENDPOINT_SIZE) {
|
||||
log_error("ep bDescriptorType = %d bLength = %d", end_desc->bDescriptorType, end_desc->bLength);
|
||||
return -USB_DT_ENDPOINT;
|
||||
}
|
||||
|
||||
len += USB_DT_ENDPOINT_SIZE;
|
||||
pBuf += USB_DT_ENDPOINT_SIZE;
|
||||
|
||||
if ((end_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
|
||||
if (end_desc->bEndpointAddress & USB_DIR_IN) {
|
||||
adb.host_epin = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_BULK);
|
||||
adb.target_epin = end_desc->bEndpointAddress & 0x0f;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
adb.rxmaxp = end_desc->wMaxPacketSize;
|
||||
#endif
|
||||
log_debug("D(%d)->H(%d)", adb.target_epin, adb.host_epin);
|
||||
} else {
|
||||
adb.host_epout = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_BULK);
|
||||
adb.target_epout = end_desc->bEndpointAddress & 0x0f;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
adb.txmaxp = end_desc->wMaxPacketSize;
|
||||
#endif
|
||||
log_debug("H(%d)->D(%d)", adb.host_epout, adb.target_epout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 *ep_buffer = usb_h_get_ep_buffer(usb_id, adb.host_epin | USB_DIR_IN);
|
||||
usb_h_ep_config(usb_id, adb.host_epin | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64);
|
||||
|
||||
|
||||
ep_buffer = usb_h_get_ep_buffer(usb_id, adb.host_epout | USB_DIR_OUT);
|
||||
usb_h_ep_config(usb_id, adb.host_epout | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int adb_send_packet(struct amessage *msg, const u8 *data_ptr)
|
||||
{
|
||||
if (msg == NULL) {
|
||||
return usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, NULL, 0);
|
||||
}
|
||||
u32 cnt;
|
||||
u32 count = msg->data_length;
|
||||
|
||||
msg->magic = msg->command ^ 0xffffffff;
|
||||
const u8 *_data_ptr = data_ptr;
|
||||
msg->data_check = 0;
|
||||
while (count--) {
|
||||
msg->data_check += *_data_ptr++;
|
||||
}
|
||||
int ret = usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, (u8 *)msg, sizeof(*msg));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (data_ptr != NULL) {
|
||||
return usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, data_ptr, msg->data_length);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static int adb_recv(u8 *buffer, u32 len, u32 timeout)
|
||||
{
|
||||
return usb_bulk_only_receive(&adb_device, adb.host_epin, 64, adb.target_epin, buffer, len);
|
||||
}
|
||||
#define check_usb_status(ret) do{\
|
||||
if(ret < 0){\
|
||||
log_info("%s() @ %d %d\n", __func__, __LINE__, ret);\
|
||||
return ret;\
|
||||
}\
|
||||
}while(0);
|
||||
|
||||
static u8 adb_signatrue_data_index ;
|
||||
|
||||
u32 adb_auth()
|
||||
{
|
||||
log_info("%s() %d\n", __func__, __LINE__);
|
||||
struct amessage msg;
|
||||
int ret = 0;
|
||||
u8 *cmd_string;
|
||||
adb.local_id = 0x58525047;
|
||||
adb.remote_id = 0;
|
||||
msg.command = A_CNXN;
|
||||
msg.arg0 = A_VERSION;
|
||||
msg.arg1 = 0x00001000;
|
||||
cmd_string = (u8 *)"host::";
|
||||
msg.data_length = strlen((const char *)cmd_string) + 1;
|
||||
ret = adb_send_packet(&msg, cmd_string);
|
||||
check_usb_status(ret);
|
||||
memset(&msg, 0, 24);
|
||||
ret = adb_recv((u8 *)&msg, 24, 5);
|
||||
check_usb_status(ret);
|
||||
|
||||
if (msg.command == A_CNXN) {
|
||||
if (adb_recv(adb.buffer, msg.data_length, 1 * 100)) {
|
||||
log_error("auth error 0\n");
|
||||
return 0;
|
||||
}
|
||||
log_info("auth not send rsa pub key\n");
|
||||
return 0;
|
||||
} else if (msg.command == A_AUTH) {
|
||||
|
||||
} else {
|
||||
log_error("auth error 1\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
msg.command = A_AUTH;
|
||||
msg.arg0 = ADB_AUTH_SIGNATURE;
|
||||
msg.data_length = sizeof(adb_signatrue_data[0]);
|
||||
if (adb_signatrue_data_index > 2) {
|
||||
adb_signatrue_data_index = 0;
|
||||
}
|
||||
|
||||
adb_signatrue_data_index ++;
|
||||
cmd_string = (u8 *)&adb_signatrue_data[adb_signatrue_data_index][0];
|
||||
ret = adb_send_packet(&msg, cmd_string);
|
||||
check_usb_status(ret);
|
||||
|
||||
ret = adb_send_packet(NULL, NULL);//zero packet
|
||||
check_usb_status(ret);
|
||||
|
||||
memset(&msg, 0, 24);
|
||||
ret = adb_recv((u8 *)&msg, 24, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
if (msg.command != A_AUTH) {
|
||||
log_error("auth error 2\n");
|
||||
return 1;
|
||||
}
|
||||
ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
|
||||
|
||||
__RETRY:
|
||||
msg.command = A_AUTH;
|
||||
msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
|
||||
msg.arg1 = 0;
|
||||
msg.data_length = sizeof(adb_rsa_pub_key);
|
||||
ret = adb_send_packet(&msg, (u8 *)adb_rsa_pub_key);
|
||||
check_usb_status(ret);
|
||||
|
||||
ret = adb_recv((u8 *)&msg, 24, 30 * 100);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret == -DEV_ERR_TIMEOUT) {
|
||||
goto __RETRY;
|
||||
}
|
||||
check_usb_status(ret);
|
||||
}
|
||||
|
||||
ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);//最长等待30s,等手机点击确认授权adb
|
||||
if (ret < 0) {
|
||||
if (ret == -DEV_ERR_TIMEOUT) {
|
||||
goto __RETRY;
|
||||
}
|
||||
check_usb_status(ret);
|
||||
}
|
||||
|
||||
if (msg.command == A_AUTH) {
|
||||
goto __RETRY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 adb_shell_login()
|
||||
{
|
||||
log_info("%s() %d\n", __func__, __LINE__);
|
||||
struct amessage msg;
|
||||
u8 *cmd_string;
|
||||
/* __AUTH_SUCCESS: */
|
||||
|
||||
cmd_string = (u8 *)"shell:";
|
||||
msg.command = A_OPEN;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = 0;
|
||||
msg.data_length = strlen((char const *)cmd_string) + 1;
|
||||
int ret = adb_send_packet(&msg, cmd_string);
|
||||
check_usb_status(ret);
|
||||
|
||||
memset(&msg, 0, 24);
|
||||
ret = adb_recv((u8 *)&msg, 24, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
|
||||
if (msg.command != A_OKAY) {
|
||||
log_error("A_OKAY error\n");
|
||||
return 4;
|
||||
}
|
||||
|
||||
ret = adb_recv((u8 *)&msg, 24, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
if (msg.command != A_WRTE) {
|
||||
log_error("A_WRTE error\n");
|
||||
return 5;
|
||||
}
|
||||
adb.remote_id = msg.arg0;
|
||||
|
||||
ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);
|
||||
check_usb_status(ret);
|
||||
|
||||
msg.command = A_OKAY;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = adb.remote_id;
|
||||
msg.data_length = 0;
|
||||
ret = adb_send_packet(&msg, NULL);
|
||||
check_usb_status(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 adb_ex_cmd(const char *cmd_string, u8 *echo_buffer, u32 max_len)
|
||||
{
|
||||
log_info("%s\n", cmd_string);
|
||||
int ret;
|
||||
struct amessage msg;
|
||||
msg.command = A_WRTE;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = adb.remote_id;
|
||||
msg.data_length = strlen(cmd_string);
|
||||
ret = adb_send_packet(&msg, (u8 *)cmd_string);
|
||||
check_usb_status(ret);
|
||||
memset(&msg, 0, 24);
|
||||
memset(echo_buffer, 0, max_len);
|
||||
ret = adb_recv((u8 *)&msg, sizeof(msg), 3 * 100);
|
||||
check_usb_status(ret);
|
||||
|
||||
if (msg.command != A_OKAY) {
|
||||
return true;
|
||||
}
|
||||
u32 offset = 0;
|
||||
do {
|
||||
ret = adb_recv((u8 *)&msg, sizeof(msg), 3 * 100);
|
||||
check_usb_status(ret);
|
||||
if (msg.command != A_WRTE) {
|
||||
log_info("command %x\n", msg.command);
|
||||
return true;
|
||||
}
|
||||
if ((offset + msg.data_length) > max_len) {
|
||||
log_info("%s", echo_buffer);
|
||||
echo_buffer[offset] = 0;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
ret = adb_recv(&echo_buffer[offset], msg.data_length, 3 * 100);
|
||||
check_usb_status(ret);
|
||||
offset += msg.data_length;
|
||||
|
||||
if (msg.data_length == 0) {
|
||||
log_info("no data_length\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (offset >= max_len) {
|
||||
|
||||
}
|
||||
/* echo_buffer[offset] = '\n'; */
|
||||
echo_buffer[offset] = 0;
|
||||
|
||||
if (echo_buffer[offset - 2] == 0x24 && echo_buffer[offset - 1] == 0x20) {
|
||||
/* puts("end\n"); */
|
||||
break;
|
||||
} else if (echo_buffer[offset - 2] == 0x23 && echo_buffer[offset - 1] == 0x20) {
|
||||
/* puts("end 1\n"); */
|
||||
break;
|
||||
}
|
||||
msg.command = A_OKAY;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = adb.remote_id;
|
||||
msg.data_length = 0;
|
||||
ret = adb_send_packet(&msg, NULL);
|
||||
check_usb_status(ret);
|
||||
|
||||
} while (1);
|
||||
|
||||
msg.command = A_OKAY;
|
||||
msg.arg0 = adb.local_id;
|
||||
msg.arg1 = adb.remote_id;
|
||||
msg.data_length = 0;
|
||||
/* puts("exit\n"); */
|
||||
return adb_send_packet(&msg, NULL);
|
||||
|
||||
}
|
||||
#define APP_ACTIVITY_PATH "com.zh-jieli.gmaeCenter/com.zh-jieli.gameCenter.activity.guide.SplashActivity\n"
|
||||
#define APP_WEBSITE "http://www.zh-jieli.com\n"
|
||||
#define APP_BASH_IN_PATH "/sdcard/jilei/active.bash"
|
||||
#define APP_BASH_OUT_PATH "/data/local/tmp/active.bash"
|
||||
|
||||
u32 adb_game_active()
|
||||
{
|
||||
log_info("%s() %d\n", __func__, __LINE__);
|
||||
u32 max_len = adb.max_len;;
|
||||
u8 *adb_buffer = adb.buffer;
|
||||
//1,启动app
|
||||
adb_ex_cmd("am start -n " APP_ACTIVITY_PATH, adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
//查找Error字符串,如果找到跳转网页下载app,否则执行adb指令
|
||||
if (strstr((const char *)adb_buffer, "Error") != NULL) {
|
||||
adb_ex_cmd("am start -a android.intent.action.VIEW -d " APP_WEBSITE, adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
} else {
|
||||
adb_ex_cmd("dd if=" APP_BASH_IN_PATH " of=" APP_BASH_OUT_PATH "\n", adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
adb_ex_cmd("chown shell " APP_BASH_OUT_PATH";chmod 777 "APP_BASH_OUT_PATH "\n", adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
adb_ex_cmd("trap \"\" HUP;sh "APP_BASH_OUT_PATH "&\n", adb_buffer, max_len);
|
||||
puts((char *)adb_buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static void mtp_ptp_open_session(u32 is_mtp)
|
||||
{
|
||||
/* usbh_bulk_send_blocking(ADB_HOST_EP, adb_device.extr_out, (u8 *)_open_session, 16); */
|
||||
/* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 12, 3); */
|
||||
|
||||
/* usbh_bulk_send_blocking(ADB_HOST_EP, adb_device.extr_out, (u8 *)get_device_info, sizeof(get_device_info)); */
|
||||
/* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 512, 3); */
|
||||
|
||||
/* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 12, 3); */
|
||||
}
|
||||
|
||||
static void adb_open_session()
|
||||
{
|
||||
struct usb_host_device *host_dev = adb_device.private_data;
|
||||
if (adb.extr_in && adb.extr_out) {
|
||||
get_ms_extended_compat_id(host_dev, adb.buffer);
|
||||
get_device_status(host_dev);
|
||||
get_config_descriptor(host_dev, adb.buffer, 0xff);
|
||||
/* mtp_ptp_open_session(ac6921_data_buffer[0x12] == 0x4d); */
|
||||
}
|
||||
}
|
||||
u32 adb_process()
|
||||
{
|
||||
adb.max_len = 1024;
|
||||
adb.buffer = malloc(adb.max_len);
|
||||
os_time_dly(20);
|
||||
do {
|
||||
|
||||
adb_open_session();
|
||||
|
||||
if (adb_auth()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (adb_shell_login()) {
|
||||
break;
|
||||
}
|
||||
|
||||
adb_game_active();
|
||||
log_info("adb active succ");
|
||||
return 0;
|
||||
|
||||
} while (0);
|
||||
|
||||
free(adb.buffer);
|
||||
|
||||
|
||||
log_info("adb active error");
|
||||
return 1;
|
||||
}
|
||||
void adb_switch_aoa(u32 id)
|
||||
{
|
||||
struct usb_host_device *host_dev = adb_device.private_data;
|
||||
aoa_switch(host_dev);
|
||||
/* usb_host_remount(id, 3, 30, 50, 1); */
|
||||
}
|
||||
#endif //TCFG_ADB_ENABLE
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef __ADB_H__
|
||||
#define __ADB_H__
|
||||
|
||||
#include "system/task.h"
|
||||
#include "device/device.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
struct adb_device_t {
|
||||
u32 local_id;
|
||||
u32 remote_id;
|
||||
void *buffer;
|
||||
u32 max_len;
|
||||
|
||||
u8 target_epin;
|
||||
u8 target_epout;
|
||||
u8 host_epin;
|
||||
u8 host_epout;
|
||||
|
||||
u8 extr_in;
|
||||
u8 extr_out;
|
||||
};
|
||||
u32 usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
int usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
u32 adb_process();
|
||||
void adb_switch_aoa(u32 id);
|
||||
|
||||
#if 1
|
||||
#define A_SYNC 0x434e5953
|
||||
#define A_CNXN 0x4e584e43
|
||||
#define A_OPEN 0x4e45504f
|
||||
#define A_OKAY 0x59414b4f
|
||||
#define A_CLSE 0x45534c43
|
||||
#define A_WRTE 0x45545257
|
||||
#define A_AUTH 0x48545541
|
||||
//#define S_ID_LOCAL 0x00003456
|
||||
/* AUTH packets first argument */
|
||||
/* Request */
|
||||
#define ADB_AUTH_TOKEN 1
|
||||
/* Response */
|
||||
#define ADB_AUTH_SIGNATURE 2
|
||||
#define ADB_AUTH_RSAPUBLICKEY 3
|
||||
|
||||
#define A_VERSION 0x01000000 // ADB protocol version
|
||||
|
||||
#define ADB_VERSION_MAJOR 1 // Used for help/version information
|
||||
#define ADB_VERSION_MINOR 0 // Used for help/version information
|
||||
|
||||
#else
|
||||
#define A_SYNC 0x53594e43
|
||||
#define A_CNXN 0x434e584e
|
||||
#define A_OPEN 0x4f50454e
|
||||
#define A_OKAY 0x4f4b4159
|
||||
#define A_CLSE 0x434c5345
|
||||
#define A_WRTE 0x57525445
|
||||
|
||||
#define A_VERSION 0x00000001 // ADB protocol version
|
||||
|
||||
#define ADB_VERSION_MAJOR 1 // Used for help/version information
|
||||
#define ADB_VERSION_MINOR 0 // Used for help/version information
|
||||
|
||||
#endif
|
||||
|
||||
struct amessage {
|
||||
unsigned long int command; /* command identifier constant */
|
||||
unsigned long int arg0; /* first argument */
|
||||
unsigned long int arg1; /* second argument */
|
||||
unsigned long int data_length; /* length of payload (0 is allowed) */
|
||||
unsigned long int data_check; /* checksum of data payload */
|
||||
unsigned long int magic; /* command ^ 0xffffffff */
|
||||
};
|
||||
|
||||
#endif /*ADB_H*/
|
||||
@@ -0,0 +1,115 @@
|
||||
#include "typedef.h"
|
||||
#include "app_config.h"
|
||||
#if TCFG_ADB_ENABLE
|
||||
static const u8 _open_session[] = {
|
||||
0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
|
||||
};
|
||||
static const u8 get_device_info[] = {
|
||||
0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
|
||||
static const u8 adb_signatrue_data[][256] = {
|
||||
{
|
||||
0xFA, 0xA6, 0xE3, 0x50, 0x3C, 0xC4, 0x95, 0xFE, 0xBB, 0x46, 0xE0, 0x9F, 0xD9, 0x9A, 0x18, 0xC1,
|
||||
0x28, 0x67, 0xA9, 0x46, 0xF8, 0x20, 0xBF, 0xDB, 0xFE, 0x6B, 0xC8, 0xC4, 0x0A, 0x09, 0xFA, 0x9A,
|
||||
0xCD, 0x51, 0xE3, 0x67, 0xD1, 0xDF, 0xD2, 0x92, 0xD3, 0x9E, 0xFA, 0x17, 0x76, 0x01, 0xF5, 0xE2,
|
||||
0xBD, 0x64, 0x9C, 0x92, 0x82, 0x4B, 0xE4, 0x27, 0x21, 0x22, 0x1A, 0x70, 0x99, 0x8F, 0xC5, 0xD5,
|
||||
0xE2, 0x02, 0x2C, 0xA4, 0x13, 0x08, 0x1E, 0x42, 0x83, 0x5C, 0x7E, 0x3C, 0x1F, 0x97, 0x1B, 0xAF,
|
||||
0x6F, 0x7E, 0x4F, 0xAB, 0xDA, 0x6A, 0x61, 0x56, 0x03, 0x79, 0xB5, 0xF0, 0x97, 0xEE, 0xEC, 0x88,
|
||||
0x6F, 0x9E, 0x8D, 0x41, 0xE2, 0x13, 0x9B, 0x21, 0xEE, 0x6F, 0x09, 0x81, 0x62, 0xC1, 0xB5, 0xE7,
|
||||
0xC2, 0x5C, 0x4A, 0x8C, 0x39, 0xAA, 0x50, 0x08, 0x48, 0xB5, 0x1D, 0xF6, 0x7C, 0x67, 0xD6, 0x39,
|
||||
0x63, 0x7E, 0x5E, 0x49, 0x3D, 0x9B, 0x49, 0x4B, 0x67, 0x8E, 0x06, 0x31, 0x07, 0x4E, 0x56, 0x8A,
|
||||
0xC4, 0x9D, 0x84, 0xA9, 0xF4, 0xFC, 0xE3, 0x2D, 0x1D, 0x2A, 0x98, 0x52, 0x40, 0x49, 0x93, 0x71,
|
||||
0xA7, 0x43, 0x0D, 0x78, 0xEB, 0xFA, 0x49, 0x7A, 0x39, 0xBF, 0xE4, 0x06, 0x08, 0x1B, 0x20, 0x84,
|
||||
0xDC, 0x64, 0xBB, 0xDE, 0x1A, 0x5E, 0x4B, 0xF8, 0x57, 0xBF, 0x9C, 0x8C, 0xB9, 0x1D, 0xEE, 0xB3,
|
||||
0x90, 0x17, 0x03, 0x8B, 0x3E, 0x9F, 0x8A, 0x23, 0xEC, 0x30, 0xA7, 0x24, 0x5E, 0x5B, 0x58, 0xAA,
|
||||
0x5A, 0xAE, 0xE2, 0x14, 0xC1, 0xAE, 0xA3, 0xF9, 0xAF, 0x70, 0xE0, 0x14, 0x7D, 0x73, 0x3B, 0x6D,
|
||||
0x9B, 0x06, 0x2F, 0xAA, 0xFF, 0x7A, 0x2A, 0x56, 0x6F, 0x91, 0x70, 0x6D, 0x4A, 0x18, 0x35, 0x51,
|
||||
0xD5, 0x5D, 0xFB, 0xA1, 0x8B, 0x03, 0xF2, 0x0C, 0x56, 0xF0, 0x5A, 0x4A, 0x08, 0x89, 0xFE, 0x86
|
||||
},
|
||||
{
|
||||
0x60, 0xE6, 0x4A, 0x3D, 0x12, 0xD1, 0x48, 0x25, 0x7D, 0x6E, 0x8E, 0x03, 0xE2, 0xC8, 0xE7, 0x66,
|
||||
0x96, 0xD7, 0xD3, 0xBF, 0xE6, 0x97, 0x13, 0x3A, 0x2D, 0x2B, 0x85, 0xE7, 0xDA, 0x5C, 0x87, 0xD8,
|
||||
0xDC, 0x88, 0xAC, 0xF7, 0xC3, 0xF0, 0x5A, 0xE8, 0x95, 0x66, 0x19, 0xA1, 0xA8, 0x2A, 0xE1, 0x70,
|
||||
0x13, 0xF0, 0x05, 0x59, 0x3D, 0x89, 0x04, 0x65, 0x08, 0x03, 0x9C, 0xDC, 0x71, 0x24, 0xC5, 0x9E,
|
||||
0x4D, 0x82, 0xD8, 0x72, 0x07, 0xFD, 0x8F, 0xD3, 0x37, 0x56, 0x8C, 0xB6, 0x01, 0xDB, 0x08, 0x5B,
|
||||
0xA3, 0x42, 0x8F, 0xF0, 0xCA, 0xDC, 0x80, 0xEB, 0x32, 0xC4, 0x67, 0x1F, 0x73, 0xAF, 0xF0, 0x56,
|
||||
0xBC, 0x89, 0x72, 0xB1, 0x7D, 0xDA, 0xA4, 0x79, 0x7D, 0x02, 0x35, 0x38, 0xBA, 0xA0, 0x36, 0xFE,
|
||||
0x5A, 0x70, 0x93, 0xF5, 0x10, 0x7A, 0x92, 0xE9, 0xD4, 0xB0, 0xED, 0xF3, 0x00, 0xD0, 0x27, 0x79,
|
||||
0x51, 0x54, 0x38, 0x2D, 0x4C, 0xAA, 0x27, 0xEF, 0xA7, 0x8A, 0x34, 0x4E, 0x4B, 0x29, 0x90, 0xC4,
|
||||
0x3E, 0xA8, 0x8D, 0x3D, 0x00, 0xD6, 0x84, 0x11, 0x17, 0x32, 0xD6, 0xE9, 0x33, 0x02, 0xCD, 0x04,
|
||||
0x35, 0x3F, 0x1A, 0xC3, 0x05, 0xCF, 0x6F, 0xF4, 0x39, 0x65, 0xE5, 0x6B, 0x88, 0x1E, 0x25, 0xA1,
|
||||
0xD7, 0xC0, 0x30, 0xE4, 0x0B, 0x2A, 0x61, 0x6D, 0x61, 0xF1, 0x93, 0xAE, 0xC3, 0x42, 0xDC, 0x15,
|
||||
0x1D, 0x87, 0x60, 0x09, 0x92, 0x64, 0xC1, 0x63, 0xAD, 0xCA, 0x36, 0x63, 0x0E, 0x69, 0x51, 0x45,
|
||||
0xD0, 0x18, 0x5E, 0x10, 0x88, 0x7B, 0xD9, 0xDE, 0xA3, 0x12, 0x85, 0xF9, 0x30, 0x01, 0x0A, 0xE1,
|
||||
0x82, 0xD1, 0x49, 0x44, 0xD9, 0x97, 0xE4, 0xF1, 0x55, 0x2D, 0xE2, 0xF3, 0x32, 0xC8, 0xA0, 0xC8,
|
||||
0x81, 0xB9, 0x02, 0x87, 0x5C, 0x19, 0xB7, 0x21, 0x6A, 0xB9, 0xB0, 0x81, 0x61, 0x8C, 0x35, 0x78
|
||||
},
|
||||
{
|
||||
0x0C, 0x7E, 0xDC, 0x78, 0x60, 0x1A, 0xC8, 0x9B, 0x3A, 0x23, 0x0B, 0x1D, 0x6F, 0xAE, 0x71, 0x6D,
|
||||
0xD8, 0x3C, 0xE9, 0xA3, 0x51, 0x90, 0xAA, 0x7B, 0x7E, 0x2F, 0x2B, 0xBD, 0x34, 0xF4, 0x43, 0x3F,
|
||||
0x77, 0xC4, 0x0E, 0x41, 0x04, 0xD9, 0xD4, 0x9C, 0xB3, 0xD2, 0x6B, 0xE1, 0xC6, 0xA8, 0xEF, 0x50,
|
||||
0x00, 0x11, 0xE1, 0x08, 0x8B, 0xB4, 0xF1, 0xE3, 0x3D, 0x56, 0x83, 0x07, 0x7F, 0xB8, 0x47, 0xF2,
|
||||
0x84, 0xD2, 0xA1, 0x50, 0x64, 0x5A, 0x08, 0x42, 0x36, 0x23, 0x09, 0x31, 0x9A, 0x6B, 0x61, 0x6F,
|
||||
0x60, 0x2C, 0xF2, 0x75, 0x4E, 0x6B, 0xB9, 0x15, 0xEE, 0x3C, 0x5E, 0xA2, 0x7F, 0xA0, 0x41, 0xFE,
|
||||
0x00, 0x6A, 0x30, 0x49, 0x2C, 0xEC, 0x17, 0x8B, 0x04, 0x32, 0xE9, 0x7A, 0x68, 0xA0, 0xF4, 0xDF,
|
||||
0x34, 0xF7, 0x1E, 0x6F, 0x19, 0x09, 0x37, 0x87, 0x99, 0xAA, 0x81, 0x1A, 0xCD, 0xF3, 0x1F, 0x89,
|
||||
0x50, 0xB2, 0x17, 0x52, 0x6D, 0x8E, 0xA6, 0x02, 0xC4, 0x2A, 0xAB, 0x3E, 0x5B, 0x38, 0x0C, 0x3F,
|
||||
0x50, 0xAA, 0x5F, 0xFE, 0x47, 0x04, 0xED, 0xCD, 0xEE, 0x7C, 0xD5, 0xED, 0x5F, 0x0E, 0xC6, 0x9C,
|
||||
0x79, 0x10, 0x11, 0x6F, 0x65, 0x58, 0x37, 0x95, 0x54, 0x50, 0x59, 0x68, 0x4C, 0x8E, 0xE7, 0x35,
|
||||
0xF0, 0x96, 0x5A, 0x21, 0x48, 0xB4, 0x53, 0x52, 0xFC, 0xA4, 0x7C, 0x2B, 0xB1, 0xE1, 0x54, 0x2C,
|
||||
0x42, 0x3B, 0x68, 0xBF, 0xBB, 0x68, 0x0D, 0x62, 0x16, 0x2F, 0xF5, 0xC8, 0x5F, 0x95, 0x11, 0xF2,
|
||||
0xDF, 0x03, 0x1E, 0xCB, 0x7C, 0xD0, 0x9C, 0xE9, 0x89, 0x62, 0xEA, 0xC5, 0x4B, 0xA9, 0xD5, 0xCC,
|
||||
0xD2, 0x42, 0x33, 0xA8, 0x7B, 0x2C, 0x56, 0xCF, 0xCE, 0x0D, 0x09, 0x64, 0x62, 0x3F, 0x58, 0x41,
|
||||
0x71, 0x79, 0x5D, 0x1D, 0xDF, 0x08, 0x0B, 0x36, 0x97, 0x16, 0x24, 0x20, 0x76, 0x9C, 0x9E, 0xEA
|
||||
}
|
||||
};
|
||||
static const u8 adb_rsa_pub_key[] = {
|
||||
0x51, 0x41, 0x41, 0x41, 0x41, 0x46, 0x4F, 0x56, 0x4F, 0x6E, 0x49, 0x6C, 0x69, 0x51, 0x58, 0x44,
|
||||
0x73, 0x42, 0x43, 0x42, 0x31, 0x75, 0x6F, 0x68, 0x70, 0x2B, 0x52, 0x71, 0x6E, 0x6E, 0x59, 0x48,
|
||||
0x2F, 0x75, 0x45, 0x58, 0x34, 0x59, 0x6A, 0x50, 0x71, 0x52, 0x4D, 0x35, 0x4B, 0x75, 0x62, 0x56,
|
||||
0x50, 0x71, 0x66, 0x57, 0x35, 0x64, 0x56, 0x46, 0x33, 0x2B, 0x76, 0x57, 0x6B, 0x53, 0x4B, 0x71,
|
||||
0x35, 0x4C, 0x31, 0x42, 0x4F, 0x4E, 0x4D, 0x36, 0x4B, 0x4F, 0x31, 0x69, 0x31, 0x73, 0x69, 0x4F,
|
||||
0x54, 0x69, 0x34, 0x6C, 0x45, 0x30, 0x6F, 0x54, 0x6F, 0x74, 0x30, 0x41, 0x4B, 0x6E, 0x4D, 0x67,
|
||||
0x4E, 0x6A, 0x6F, 0x33, 0x45, 0x4D, 0x65, 0x72, 0x30, 0x6C, 0x57, 0x56, 0x54, 0x54, 0x43, 0x39,
|
||||
0x68, 0x52, 0x66, 0x67, 0x46, 0x65, 0x56, 0x73, 0x43, 0x32, 0x44, 0x74, 0x71, 0x62, 0x61, 0x6D,
|
||||
0x4A, 0x48, 0x63, 0x41, 0x66, 0x59, 0x77, 0x36, 0x54, 0x62, 0x4C, 0x44, 0x6C, 0x4B, 0x70, 0x6A,
|
||||
0x38, 0x34, 0x33, 0x63, 0x31, 0x59, 0x5A, 0x65, 0x59, 0x6D, 0x52, 0x56, 0x4D, 0x7A, 0x4D, 0x34,
|
||||
0x6E, 0x74, 0x49, 0x78, 0x64, 0x56, 0x33, 0x33, 0x76, 0x4B, 0x75, 0x39, 0x38, 0x34, 0x6A, 0x72,
|
||||
0x43, 0x41, 0x47, 0x68, 0x77, 0x4A, 0x41, 0x67, 0x4A, 0x46, 0x53, 0x41, 0x4B, 0x56, 0x59, 0x51,
|
||||
0x55, 0x33, 0x6A, 0x4C, 0x76, 0x41, 0x76, 0x57, 0x45, 0x6C, 0x59, 0x47, 0x37, 0x2F, 0x4B, 0x59,
|
||||
0x6D, 0x55, 0x34, 0x54, 0x71, 0x73, 0x70, 0x64, 0x76, 0x4C, 0x42, 0x6F, 0x65, 0x36, 0x68, 0x64,
|
||||
0x46, 0x44, 0x65, 0x76, 0x4D, 0x4D, 0x43, 0x63, 0x72, 0x6C, 0x44, 0x49, 0x66, 0x65, 0x45, 0x53,
|
||||
0x57, 0x68, 0x42, 0x56, 0x35, 0x67, 0x78, 0x6A, 0x57, 0x41, 0x70, 0x4D, 0x47, 0x67, 0x53, 0x71,
|
||||
0x53, 0x45, 0x6A, 0x70, 0x36, 0x79, 0x62, 0x6A, 0x33, 0x38, 0x50, 0x4C, 0x72, 0x76, 0x49, 0x51,
|
||||
0x48, 0x77, 0x2B, 0x66, 0x70, 0x6F, 0x51, 0x74, 0x6F, 0x4F, 0x4E, 0x65, 0x37, 0x6F, 0x68, 0x66,
|
||||
0x42, 0x77, 0x45, 0x66, 0x47, 0x46, 0x4E, 0x63, 0x33, 0x61, 0x70, 0x48, 0x50, 0x6E, 0x59, 0x53,
|
||||
0x47, 0x4F, 0x67, 0x70, 0x54, 0x78, 0x70, 0x57, 0x57, 0x75, 0x49, 0x42, 0x79, 0x2F, 0x67, 0x38,
|
||||
0x35, 0x2B, 0x65, 0x54, 0x30, 0x44, 0x61, 0x36, 0x53, 0x65, 0x71, 0x33, 0x67, 0x62, 0x4A, 0x59,
|
||||
0x64, 0x75, 0x52, 0x44, 0x65, 0x36, 0x5A, 0x39, 0x63, 0x4A, 0x77, 0x48, 0x79, 0x38, 0x43, 0x34,
|
||||
0x59, 0x79, 0x6B, 0x44, 0x56, 0x45, 0x4B, 0x6A, 0x39, 0x75, 0x52, 0x41, 0x41, 0x45, 0x59, 0x70,
|
||||
0x52, 0x6B, 0x74, 0x39, 0x66, 0x34, 0x79, 0x51, 0x4A, 0x31, 0x73, 0x4D, 0x48, 0x31, 0x5A, 0x75,
|
||||
0x4F, 0x55, 0x46, 0x4A, 0x46, 0x65, 0x74, 0x6B, 0x72, 0x67, 0x32, 0x44, 0x46, 0x61, 0x35, 0x30,
|
||||
0x50, 0x39, 0x48, 0x61, 0x78, 0x6F, 0x4D, 0x59, 0x30, 0x41, 0x79, 0x78, 0x7A, 0x51, 0x72, 0x53,
|
||||
0x77, 0x4D, 0x44, 0x79, 0x6E, 0x36, 0x64, 0x49, 0x65, 0x38, 0x65, 0x58, 0x46, 0x78, 0x51, 0x62,
|
||||
0x56, 0x4D, 0x4F, 0x6C, 0x4B, 0x36, 0x79, 0x33, 0x70, 0x6F, 0x2B, 0x4A, 0x4D, 0x42, 0x34, 0x79,
|
||||
0x4D, 0x42, 0x36, 0x51, 0x77, 0x30, 0x7A, 0x31, 0x35, 0x62, 0x6F, 0x58, 0x4C, 0x78, 0x4D, 0x4B,
|
||||
0x76, 0x4E, 0x59, 0x6E, 0x4B, 0x4E, 0x70, 0x69, 0x6F, 0x33, 0x67, 0x45, 0x78, 0x5A, 0x2B, 0x48,
|
||||
0x68, 0x57, 0x62, 0x43, 0x47, 0x69, 0x37, 0x64, 0x4A, 0x6C, 0x56, 0x47, 0x50, 0x6F, 0x74, 0x34,
|
||||
0x4D, 0x42, 0x45, 0x4C, 0x7A, 0x43, 0x38, 0x66, 0x4C, 0x55, 0x44, 0x69, 0x41, 0x43, 0x49, 0x54,
|
||||
0x37, 0x75, 0x31, 0x58, 0x31, 0x62, 0x68, 0x65, 0x71, 0x6C, 0x35, 0x59, 0x7A, 0x43, 0x30, 0x6C,
|
||||
0x67, 0x2F, 0x4B, 0x48, 0x5A, 0x7A, 0x62, 0x36, 0x6D, 0x63, 0x74, 0x4E, 0x2B, 0x34, 0x62, 0x52,
|
||||
0x74, 0x79, 0x4B, 0x35, 0x75, 0x52, 0x52, 0x4A, 0x70, 0x48, 0x45, 0x56, 0x63, 0x4B, 0x58, 0x57,
|
||||
0x50, 0x34, 0x30, 0x73, 0x31, 0x79, 0x38, 0x37, 0x75, 0x30, 0x6D, 0x49, 0x50, 0x4A, 0x6E, 0x73,
|
||||
0x39, 0x6D, 0x4F, 0x2F, 0x2F, 0x44, 0x41, 0x35, 0x4C, 0x32, 0x6D, 0x64, 0x77, 0x56, 0x79, 0x73,
|
||||
0x72, 0x74, 0x4B, 0x51, 0x69, 0x51, 0x37, 0x36, 0x57, 0x6A, 0x74, 0x59, 0x51, 0x63, 0x41, 0x73,
|
||||
0x46, 0x2B, 0x42, 0x54, 0x4E, 0x56, 0x48, 0x62, 0x41, 0x6E, 0x7A, 0x7A, 0x52, 0x75, 0x6C, 0x52,
|
||||
0x61, 0x43, 0x45, 0x78, 0x2B, 0x6E, 0x30, 0x49, 0x6A, 0x35, 0x34, 0x49, 0x45, 0x41, 0x4F, 0x75,
|
||||
0x55, 0x4B, 0x70, 0x6F, 0x61, 0x48, 0x71, 0x6F, 0x56, 0x4F, 0x33, 0x51, 0x42, 0x36, 0x52, 0x41,
|
||||
0x51, 0x7A, 0x4D, 0x67, 0x70, 0x44, 0x73, 0x41, 0x30, 0x58, 0x34, 0x4C, 0x6A, 0x4F, 0x32, 0x52,
|
||||
0x2B, 0x4D, 0x4B, 0x6F, 0x6D, 0x6F, 0x6C, 0x52, 0x5A, 0x6F, 0x32, 0x34, 0x57, 0x32, 0x41, 0x35,
|
||||
0x57, 0x2B, 0x30, 0x56, 0x4A, 0x77, 0x45, 0x41, 0x41, 0x51, 0x41, 0x3D, 0x20, 0x75, 0x6E, 0x6B,
|
||||
0x6E, 0x6F, 0x77, 0x6E, 0x40, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x00
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
* @file aoa.c
|
||||
* @brief https://source.android.com/devices/accessories/aoa
|
||||
* http://www.hackermi.com/2015-04/aoa-analyse/
|
||||
* Android 开放配件协议 1.0
|
||||
* @author chenrixin@zh-jieli.com
|
||||
* @version 1
|
||||
* @date 2020-03-25
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#include "usb_config.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb/usb_phy.h"
|
||||
#include "device_drive.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb_storage.h"
|
||||
#include "adb.h"
|
||||
#include "aoa.h"
|
||||
#include "usb_hid_keys.h"
|
||||
#if TCFG_AOA_ENABLE
|
||||
#include "gamebox.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[AOA]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
//0x2D00 有一个接口,该接口有两个批量端点,用于输入和输出通信。
|
||||
//0x2D01 有两个接口,每个接口有两个批量端点,用于输入和输出通信。
|
||||
//第一个接口处理标准通信,
|
||||
//第二个接口则处理 ADB 通信。
|
||||
//要使用接口,请找到第一个批量输入和输出端点,
|
||||
//使用 SET_CONFIGURATION (0x09) 设备请求将设备配置的值设为 1,然后使用端点进行通信
|
||||
//
|
||||
|
||||
|
||||
static void aoa_timer_handler(void *priv);
|
||||
static u32 aoa_timer_id;
|
||||
static struct aoa_device_t aoa;
|
||||
static struct device aoa_device;
|
||||
|
||||
static int set_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
if (aoa_timer_id) {
|
||||
usr_timer_del(aoa_timer_id);
|
||||
aoa_timer_id = 0;
|
||||
}
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static int get_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
static const struct interface_ctrl aoa_ctrl = {
|
||||
.interface_class = USB_CLASS_AOA,
|
||||
.set_power = set_power,
|
||||
.get_power = get_power,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
static const struct usb_interface_info aoa_inf = {
|
||||
.ctrl = (struct interface_ctrl *) &aoa_ctrl,
|
||||
.dev.aoa = &aoa,
|
||||
};
|
||||
|
||||
static const char *credetials[] = {"JieLiTec",
|
||||
"GameBox",
|
||||
"Android accessories devcie !",
|
||||
"1.0.0",
|
||||
"http://www.zh-jieli.com",
|
||||
"1234567890ABCDEF",
|
||||
};
|
||||
|
||||
void aoa_switch(struct usb_host_device *host_dev)
|
||||
{
|
||||
u16 version;
|
||||
log_info("aoa_switch");
|
||||
usb_get_aoa_version(host_dev, &version);
|
||||
log_info("AOA version: %x", version);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
log_info("send string [%d] %s", i, credetials[i]);
|
||||
int r = usb_set_credentials(host_dev, credetials[i], i);
|
||||
if (r < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
usb_switch2aoa(host_dev);
|
||||
}
|
||||
|
||||
int usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
int len = 0;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
aoa_device.private_data = host_dev;
|
||||
host_dev->interface_info[interface_num] = &aoa_inf;
|
||||
|
||||
for (int endnum = 0; endnum < interface->bNumEndpoints; endnum++) {
|
||||
struct usb_endpoint_descriptor *end_desc = (struct usb_endpoint_descriptor *)pBuf;
|
||||
|
||||
if (end_desc->bDescriptorType != USB_DT_ENDPOINT ||
|
||||
end_desc->bLength != USB_DT_ENDPOINT_SIZE) {
|
||||
log_error("ep bDescriptorType = %d bLength = %d", end_desc->bDescriptorType, end_desc->bLength);
|
||||
return -USB_DT_ENDPOINT;
|
||||
}
|
||||
|
||||
len += USB_DT_ENDPOINT_SIZE;
|
||||
pBuf += USB_DT_ENDPOINT_SIZE;
|
||||
|
||||
if ((end_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
|
||||
if (end_desc->bEndpointAddress & USB_DIR_IN) {
|
||||
aoa.target_epin = end_desc->bEndpointAddress & 0x0f;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
aoa.rxmaxp = end_desc->wMaxPacketSize;
|
||||
#endif
|
||||
} else {
|
||||
aoa.target_epout = end_desc->bEndpointAddress & 0x0f;
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
aoa.txmaxp = end_desc->wMaxPacketSize;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int aoa_tx_data(const u8 *pbuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = aoa_device.private_data;
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
g_printf("TX:");
|
||||
printf_buf(pbuf, len);
|
||||
return usb_h_ep_write_async(usb_id, aoa.host_epout, 64, aoa.target_epout, pbuf, len, USB_ENDPOINT_XFER_BULK, 1);
|
||||
}
|
||||
static void aoa_epin_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
u8 buffer[64] = {0};
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
u32 rx_len = usb_h_ep_read_async(usb_id, ep, aoa.target_epin, buffer, sizeof(buffer), USB_ENDPOINT_XFER_BULK, 0);
|
||||
g_printf("RX:");
|
||||
printf_buf(buffer, rx_len);
|
||||
|
||||
usb_h_ep_read_async(usb_id, ep, aoa.target_epin, NULL, 0, USB_ENDPOINT_XFER_BULK, 1);
|
||||
}
|
||||
|
||||
#define Accessory_assigned_ID 0x0001
|
||||
|
||||
u32 aoa_process(u32 mode, u32 id)
|
||||
{
|
||||
struct usb_host_device *host_dev = aoa_device.private_data;
|
||||
struct usb_device_descriptor device_desc;
|
||||
usb_get_device_descriptor(host_dev, &device_desc);
|
||||
|
||||
if ((device_desc.idVendor == 0x18d1) &&
|
||||
((device_desc.idProduct & 0x2d00) == 0x2d00)) {
|
||||
log_info("aoa mode ready idVendor:%x idProduct: %x",
|
||||
device_desc.idVendor, device_desc.idProduct);
|
||||
} else {
|
||||
log_info("aoa switch idVendor:%x idProduct: %x",
|
||||
device_desc.idVendor, device_desc.idProduct);
|
||||
|
||||
aoa_switch(host_dev);
|
||||
|
||||
usb_host_remount(id, 3, 30, 50, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
usb_aoa_register_hid(host_dev, Accessory_assigned_ID, sizeof(hid_report_desc));
|
||||
|
||||
u32 offset = 0;
|
||||
while (offset < sizeof(hid_report_desc)) {
|
||||
u32 cnt = min(sizeof(hid_report_desc) - offset, 63);
|
||||
usb_aoa_set_hid_report_desc(host_dev, Accessory_assigned_ID, offset, &hid_report_desc[offset], cnt);
|
||||
offset += cnt;
|
||||
}
|
||||
|
||||
aoa.host_epout = usb_get_ep_num(id, USB_DIR_OUT, USB_ENDPOINT_XFER_BULK);
|
||||
aoa.host_epin = usb_get_ep_num(id, USB_DIR_IN, USB_ENDPOINT_XFER_BULK);
|
||||
log_debug("D(%d)->H(%d)", aoa.target_epin, aoa.host_epin);
|
||||
log_debug("H(%d)->D(%d)", aoa.host_epout, aoa.target_epout);
|
||||
|
||||
usb_h_set_ep_isr(host_dev, aoa.host_epin | USB_DIR_IN, aoa_epin_isr, host_dev);
|
||||
u8 *ep_buffer = usb_h_get_ep_buffer(id, aoa.host_epin | USB_DIR_IN);
|
||||
usb_h_ep_config(id, aoa.host_epin | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 1, 0, ep_buffer, 64);
|
||||
int r = usb_h_ep_read_async(id, aoa.host_epin, aoa.target_epin, NULL, 0, USB_ENDPOINT_XFER_BULK, 1);
|
||||
|
||||
ep_buffer = usb_h_get_ep_buffer(id, aoa.host_epout | USB_DIR_OUT);
|
||||
usb_h_ep_config(id, aoa.host_epout | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64);
|
||||
|
||||
aoa_timer_id = usr_timer_add((void *)0, aoa_timer_handler, 4, 0);
|
||||
g_printf("aoa succ");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void aoa_timer_handler(void *priv)
|
||||
{
|
||||
struct usb_host_device *host_dev = aoa_device.private_data;
|
||||
|
||||
u8 tx_buffer[32];
|
||||
if (mouse_data_send == 1) {
|
||||
tx_buffer[0] = MOUSE_POINT_ID;
|
||||
memcpy(&tx_buffer[1], &mouse_data, sizeof(mouse_data));
|
||||
usb_aoa_send_hid_event(host_dev, Accessory_assigned_ID, tx_buffer, sizeof(mouse_data) + 1);
|
||||
memset(&mouse_data, 0, sizeof(mouse_data)) ;
|
||||
mouse_data_send = 0;
|
||||
}
|
||||
|
||||
tx_buffer[0] = TOUCH_SCREEN_ID;
|
||||
struct touch_screen_t t;
|
||||
memset(&t, 0, sizeof(t));
|
||||
if (point_list_pop(&t)) {
|
||||
memcpy(&tx_buffer[1], &t, sizeof(t));
|
||||
usb_aoa_send_hid_event(host_dev, Accessory_assigned_ID, tx_buffer, sizeof(t) + 1);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef __AOA_H__
|
||||
#define __AOA_H__
|
||||
|
||||
struct aoa_device_t {
|
||||
u16 version;
|
||||
|
||||
u8 target_epin;
|
||||
u8 target_epout;
|
||||
|
||||
u8 host_epin;
|
||||
u8 host_epout;
|
||||
|
||||
struct adb_device_t *adb;
|
||||
};
|
||||
u32 aoa_process(u32 mode, u32 id);
|
||||
int usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
|
||||
|
||||
#endif /*AOA_H*/
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef _APPLE_MFI_H_
|
||||
#define _APPLE_MFI_H_
|
||||
|
||||
int usb_apple_mfi_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,820 @@
|
||||
#include "includes.h"
|
||||
#include "asm/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "system/timer.h"
|
||||
#include "device/ioctl_cmds.h"
|
||||
#include "device_drive.h"
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "audio.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[AUDIO]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
/* #define USB_AUDIO_PLAY_TEST */
|
||||
|
||||
struct usb_audio_play {
|
||||
u32 sample_rate;
|
||||
u8 Cur_AlternateSetting;
|
||||
u8 src_channel;
|
||||
u8 play_state;
|
||||
u8 mute;
|
||||
u8 *send_buf;
|
||||
u8 *usb_audio_play_buf;
|
||||
u8 *usb_audio_play_buf2;
|
||||
cbuffer_t usb_audio_play_cbuf;
|
||||
u32 usb_audio_remain_len;
|
||||
OS_SEM sem;
|
||||
int (*put_buf)(void *ptr, u32 len);
|
||||
};
|
||||
struct usb_audio_mic {
|
||||
u8 Cur_AlternateSetting;
|
||||
u32 sample_rate;
|
||||
u8 record_state;
|
||||
u8 *usb_audio_record_buf;
|
||||
u8 *usb_audio_record_buf2;
|
||||
cbuffer_t usb_audio_record_cbuf;
|
||||
int *(*get_buf)(void *ptr, u32 len);
|
||||
};
|
||||
struct usb_audio_info {
|
||||
usb_dev usb_id;
|
||||
struct usb_audio_play player;
|
||||
struct usb_audio_mic microphone;
|
||||
};
|
||||
|
||||
enum {
|
||||
AUDIO_PLAY_IDLE = 0,
|
||||
AUDIO_PLAY_START,
|
||||
AUDIO_PLAY_STOP,
|
||||
AUDIO_PLAY_PAUSE,
|
||||
};
|
||||
enum {
|
||||
AUDIO_RECORD_IDLE = 0,
|
||||
AUDIO_RECORD_START,
|
||||
AUDIO_RECORD_STOP,
|
||||
AUDIO_RECORD_PAUSE,
|
||||
};
|
||||
|
||||
#define EP_MAX_PACKET_SIZE (192)
|
||||
|
||||
struct usb_audio_info _usb_audio_info = {0};
|
||||
#define __this (&_usb_audio_info)
|
||||
|
||||
struct audio_device_t audio_device[USB_MAX_HW_NUM][MAX_HOST_INTERFACE];
|
||||
|
||||
static u8 ep_in_dma_buf[256] __attribute__((aligned(4)));
|
||||
static u8 ep_out_dma_buf[256] __attribute__((aligned(4)));
|
||||
|
||||
static int set_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static int get_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static const struct interface_ctrl uac_ctrl = {
|
||||
.interface_class = USB_CLASS_AUDIO,
|
||||
.set_power = set_power,
|
||||
.get_power = get_power,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
static const struct usb_interface_info _uac_if[USB_MAX_HW_NUM][MAX_HOST_INTERFACE] = {
|
||||
{
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &uac_ctrl,
|
||||
.dev.audio = &audio_device[0][0],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &uac_ctrl,
|
||||
.dev.audio = &audio_device[0][1],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &uac_ctrl,
|
||||
.dev.audio = &audio_device[0][2],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &uac_ctrl,
|
||||
.dev.audio = &audio_device[0][3],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
int usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
const struct usb_interface_info *usb_if = &_uac_if[usb_id][interface_num];
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
memset(usb_if->dev.p, 0, sizeof(struct audio_device_t));
|
||||
host_dev->interface_info[interface_num] = usb_if;
|
||||
usb_if->dev.audio->parent = host_dev;
|
||||
|
||||
if (interface->bInterfaceSubClass == USB_SUBCLASS_AUDIOCONTROL) {
|
||||
log_info("audio control interface : %d\n", interface_num);
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
usb_if->dev.audio->subclass = interface->bInterfaceSubClass;
|
||||
usb_if->dev.audio->interface_num = interface_num;
|
||||
|
||||
return sizeof(struct usb_interface_descriptor);
|
||||
}
|
||||
|
||||
if (interface->bInterfaceSubClass == USB_SUBCLASS_AUDIOSTREAMING) {
|
||||
usb_if->dev.audio->subclass = interface->bInterfaceSubClass;
|
||||
usb_if->dev.audio->interface_num = interface_num;
|
||||
if (interface->bNumEndpoints == 0) {
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
do {
|
||||
struct usb_interface_descriptor *as_interface = (struct usb_interface_descriptor *)pBuf;
|
||||
if (as_interface->bNumEndpoints == 0 || as_interface->bInterfaceClass != USB_CLASS_AUDIO) {
|
||||
break;
|
||||
}
|
||||
log_info("audio streaming interface : %d ep_num:%d Altersetting:%d", interface_num, as_interface->bNumEndpoints, as_interface->bAlternateSetting);
|
||||
as_t = &usb_if->dev.audio->as[as_interface->bAlternateSetting - 1];
|
||||
as_t->bNumEndpoints = as_interface->bNumEndpoints;
|
||||
pBuf += (USB_DT_INTERFACE_SIZE + UAC_DT_AS_HEADER_SIZE);
|
||||
//解析format
|
||||
struct uac_format_type_i_discrete_descriptor *uac_format_desc = (struct uac_format_type_i_discrete_descriptor *)pBuf;
|
||||
if (uac_format_desc->bDescriptorSubtype == UAC_FORMAT_TYPE) {
|
||||
as_t->bFormatType = uac_format_desc->bFormatType;
|
||||
as_t->bNrChannels = uac_format_desc->bNrChannels;
|
||||
as_t->bSubframeSize = uac_format_desc->bSubframeSize;
|
||||
as_t->bBitResolution = uac_format_desc->bBitResolution;
|
||||
as_t->bSamFreqType = uac_format_desc->bSamFreqType;
|
||||
for (u8 i = 0; i < as_t->bSamFreqType; i++) {
|
||||
memcpy(&as_t->tSamFreq[i], &uac_format_desc->tSamFreq[i], 3);
|
||||
log_info("as bNrChannels:%d bBitResolution:%d tSamFreq : %d", as_t->bNrChannels, as_t->bBitResolution, as_t->tSamFreq[i]);
|
||||
}
|
||||
//Endpointdescriptor
|
||||
pBuf += uac_format_desc->bLength;
|
||||
/* for (int i = 0; i < as_t->bNumEndpoints; i++) { */
|
||||
struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)pBuf;
|
||||
if (endpoint->bDescriptorType == USB_DT_ENDPOINT) {
|
||||
as_t->ep_Interval = endpoint->bInterval;
|
||||
as_t->ep_max_packet_size = endpoint->wMaxPacketSize;
|
||||
if (endpoint->bEndpointAddress & USB_DIR_IN) {
|
||||
as_t->ep = endpoint->bEndpointAddress & 0xf;
|
||||
log_info("ep in : %x\n", as_t->ep);
|
||||
usb_if->dev.audio->support = MICROPHONE_SUPPORTED;
|
||||
} else {
|
||||
as_t->ep = endpoint->bEndpointAddress;
|
||||
log_info("ep out : %x\n", as_t->ep);
|
||||
usb_if->dev.audio->support = HEADPHONE_SUPPORTED;
|
||||
}
|
||||
pBuf += (USB_DT_ENDPOINT_AUDIO_SIZE + UAC_ISO_ENDPOINT_DESC_SIZE);
|
||||
}
|
||||
/* } */
|
||||
} else {
|
||||
log_error("uac_format_desc->bDescriptorSubtype err!!\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
} while (1);
|
||||
/* log_info("lennnn:%d\n",pBuf - (u8 *)interface); */
|
||||
return pBuf - (u8 *)interface ;
|
||||
} else {
|
||||
log_info("audio streaming interface : %d ep_num:%d Altersetting:%d\n", interface_num, interface->bNumEndpoints, interface->bAlternateSetting);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
__exit:
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
|
||||
}
|
||||
|
||||
static struct audio_device_t *__find_microphone_interface(const struct usb_host_device *host_dev)
|
||||
{
|
||||
struct audio_device_t *audio = NULL;
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
const struct usb_interface_info *usb_if = host_dev->interface_info[i];
|
||||
if (usb_if &&
|
||||
(usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) {
|
||||
audio = usb_if->dev.audio;
|
||||
if (audio->subclass == USB_SUBCLASS_AUDIOSTREAMING &&
|
||||
audio->support == MICROPHONE_SUPPORTED) {
|
||||
// find microphone
|
||||
return audio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
static struct audio_device_t *__find_headphone_interface(const struct usb_host_device *host_dev)
|
||||
{
|
||||
struct audio_device_t *audio = NULL;
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
const struct usb_interface_info *usb_if = host_dev->interface_info[i];
|
||||
if (usb_if &&
|
||||
(usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) {
|
||||
audio = usb_if->dev.audio;
|
||||
if (audio->subclass == USB_SUBCLASS_AUDIOSTREAMING &&
|
||||
audio->support == HEADPHONE_SUPPORTED) {
|
||||
// find headphone
|
||||
return audio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
static u32 play_vol_convert(u16 v)
|
||||
{
|
||||
//固定音量表,更换声卡需要修改音量表
|
||||
const u16 vol_table[] = {
|
||||
//0-100
|
||||
0xd300, //0
|
||||
0xd58f, 0xd7bf, 0xd9a8, 0xdb5b, 0xdce1, 0xde45, 0xdf8a, 0xe0b6, 0xe1cd, 0xe2d1,
|
||||
0xe3c5, 0xe4ab, 0xe583, 0xe651, 0xe714, 0xe7cd, 0xe87f, 0xe928, 0xe9ca, 0xea66,
|
||||
0xeafc, 0xeb8d, 0xec18, 0xec9e, 0xed20, 0xed9e, 0xee18, 0xee8e, 0xef00, 0xef6f,
|
||||
0xefdc, 0xf045, 0xf0ab, 0xf10f, 0xf171, 0xf1d0, 0xf22c, 0xf287, 0xf2e0, 0xf336,
|
||||
0xf38b, 0xf3de, 0xf42f, 0xf47e, 0xf4cc, 0xf518, 0xf563, 0xf5ad, 0xf5f5, 0xf63c,
|
||||
0xf681, 0xf6c6, 0xf709, 0xf74b, 0xf78c, 0xf7cb, 0xf80a, 0xf848, 0xf885, 0xf8c1,
|
||||
0xf8fc, 0xf936, 0xf96f, 0xf9a8, 0xf9df, 0xfa16, 0xfa4c, 0xfa81, 0xfab6, 0xfaea,
|
||||
0xfb1d, 0xfb50, 0xfb82, 0xfbb3, 0xfbe4, 0xfc14, 0xfc43, 0xfc72, 0xfca0, 0xfcce,
|
||||
0xfcfc, 0xfd28, 0xfd55, 0xfd80, 0xfdab, 0xfdd6, 0xfe01, 0xfe2a, 0xfe54, 0xfe7d,
|
||||
0xfea5, 0xfece, 0xfef5, 0xff1d, 0xff43, 0xff6a, 0xff90, 0xffb6, 0xffdb, 0x0000,
|
||||
};
|
||||
|
||||
if (v <= 100) {
|
||||
return vol_table[v];
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(vol_table) / 2; i++) {
|
||||
if (v <= vol_table[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_usb_audio_play_volume(u16 vol)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(__this->usb_id);
|
||||
u8 featureUnitID = 6;
|
||||
usb_audio_volume_control(host_dev, featureUnitID, 1, play_vol_convert(vol));
|
||||
usb_audio_volume_control(host_dev, featureUnitID, 2, play_vol_convert(vol));
|
||||
if (vol == 0) {
|
||||
__this->player.mute = 1;
|
||||
usb_audio_mute_control(host_dev, featureUnitID, __this->player.mute); //mute
|
||||
} else {
|
||||
if (__this->player.mute == 1) {
|
||||
__this->player.mute = 0;
|
||||
usb_audio_mute_control(host_dev, featureUnitID, __this->player.mute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USB_AUDIO_PLAY_TEST
|
||||
static const s16 sin_48k[] = {
|
||||
0, 2139, 4240, 6270, 8192, 9974, 11585, 12998,
|
||||
14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137,
|
||||
14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139,
|
||||
0, -2139, -4240, -6270, -8192, -9974, -11585, -12998,
|
||||
-14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137,
|
||||
-14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139
|
||||
};
|
||||
#endif
|
||||
static void usb_audio_tx_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
struct audio_device_t *audio = NULL;
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
u16 ep_max_packet_size = 0;
|
||||
u8 channel = 0;
|
||||
u32 rlen = 0;
|
||||
static u32 usb_audio_tx_len = 0;
|
||||
|
||||
if (__this->player.play_state != AUDIO_PLAY_START) {
|
||||
return;
|
||||
}
|
||||
|
||||
audio = __find_headphone_interface(host_dev);
|
||||
if (!audio) {
|
||||
log_error("no find headphone interface!");
|
||||
return;
|
||||
}
|
||||
|
||||
as_t = &audio->as[__this->player.Cur_AlternateSetting - 1];
|
||||
/* ep_max_packet_size = as_t->ep_max_packet_size; */
|
||||
ep_max_packet_size = EP_MAX_PACKET_SIZE;
|
||||
channel = as_t->bNrChannels;
|
||||
|
||||
//iso send
|
||||
#ifdef USB_AUDIO_PLAY_TEST
|
||||
//For Test
|
||||
int tx_len = 0;
|
||||
#if 1 // 单声道双声道输出
|
||||
s16 buf[240 / 2];
|
||||
for (u8 i = 0, j = 0; i < 240 / 2; i += 2) {
|
||||
buf[i] = sin_48k[j];
|
||||
buf[i + 1] = sin_48k[j];
|
||||
j++;
|
||||
if (j >= sizeof(sin_48k) / sizeof(sin_48k[0])) {
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
//单声道直接输出
|
||||
u8 buf[248];
|
||||
do {
|
||||
memcpy(&buf[tx_len], sin_48k, sizeof(sin_48k));
|
||||
tx_len += sizeof(sin_48k);
|
||||
} while (tx_len < ep_max_packet_size);
|
||||
#endif
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
|
||||
#else
|
||||
if (__this->player.usb_audio_remain_len == 0) {
|
||||
cbuf_read_alloc(&__this->player.usb_audio_play_cbuf, &__this->player.usb_audio_remain_len);
|
||||
usb_audio_tx_len = 0;
|
||||
}
|
||||
if (__this->player.usb_audio_remain_len) {
|
||||
if (usb_audio_tx_len == 0) {
|
||||
rlen = cbuf_read(&__this->player.usb_audio_play_cbuf, __this->player.usb_audio_play_buf2, __this->player.usb_audio_remain_len);
|
||||
if (!rlen) {
|
||||
__this->player.usb_audio_remain_len = 0;
|
||||
usb_audio_tx_len = 0;
|
||||
putchar('C');
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1);
|
||||
os_sem_post(&__this->player.sem);
|
||||
return;
|
||||
}
|
||||
os_sem_post(&__this->player.sem);
|
||||
|
||||
}
|
||||
u8 *send_buf = __this->player.send_buf;
|
||||
u8 *play_buf = __this->player.usb_audio_play_buf2;
|
||||
if (channel == 2) {
|
||||
if (__this->player.src_channel == 1) {
|
||||
//源数据是单声道数据,转双声道输出
|
||||
int j = 0;
|
||||
for (u8 i = 0; i < ep_max_packet_size; i += 4) {
|
||||
//left
|
||||
*(send_buf + i) = *(play_buf + (usb_audio_tx_len + j));
|
||||
*(send_buf + i + 1) = *(play_buf + (usb_audio_tx_len + j + 1));
|
||||
//right
|
||||
|
||||
*(send_buf + i + 2) = *(play_buf + (usb_audio_tx_len + j));
|
||||
*(send_buf + i + 3) = *(play_buf + (usb_audio_tx_len + j + 1));
|
||||
j += 2;
|
||||
}
|
||||
usb_audio_tx_len += j;
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, send_buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
|
||||
} else if (__this->player.src_channel == 2) {
|
||||
//源数据是双声道数据,直接双声道输出
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, play_buf + usb_audio_tx_len, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0);
|
||||
usb_audio_tx_len += ep_max_packet_size;
|
||||
}
|
||||
} else if (channel == 1) {
|
||||
}
|
||||
if (usb_audio_tx_len >= __this->player.usb_audio_remain_len) {
|
||||
__this->player.usb_audio_remain_len = 0;
|
||||
usb_audio_tx_len = 0;
|
||||
}
|
||||
} else {
|
||||
//audio buf null ,send null packet
|
||||
putchar('E');
|
||||
usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
void set_vol_test(void *p)
|
||||
{
|
||||
struct usb_host_device *host_dev = (struct usb_host_device *)p;
|
||||
static u16 vol = 100;
|
||||
set_usb_audio_play_volume(vol);
|
||||
/* static u8 f = 0; */
|
||||
/* void usb_audio_pause_play(void); */
|
||||
/* void usb_audio_resume_play(void); */
|
||||
/* if (!f) { */
|
||||
/* usb_audio_pause_play(); */
|
||||
/* } else { */
|
||||
/* usb_audio_resume_play(); */
|
||||
/* } */
|
||||
/* f = !f; */
|
||||
vol -= 10;
|
||||
}
|
||||
void audio_play_task(void *p)
|
||||
{
|
||||
log_info(">>> Enter usb audio play task");
|
||||
struct usb_host_device *host_dev = (struct usb_host_device *)p;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 *ptr = NULL;
|
||||
u32 wlen = 0;
|
||||
u32 ret = 0;
|
||||
struct audio_device_t *audio = NULL;
|
||||
audio = __find_headphone_interface(host_dev);
|
||||
struct audio_streaming_t *as_t = &audio->as[__this->player.Cur_AlternateSetting - 1];
|
||||
/* u32 ep_max_packet_size = as_t->ep_max_packet_size; */
|
||||
u32 ep_max_packet_size = EP_MAX_PACKET_SIZE;
|
||||
log_info("ep max packet : %d\n", ep_max_packet_size);
|
||||
if (__this->player.send_buf) {
|
||||
free(__this->player.send_buf);
|
||||
__this->player.send_buf = NULL;
|
||||
}
|
||||
__this->player.send_buf = zalloc(ep_max_packet_size);
|
||||
u32 usb_audio_buf_size = ep_max_packet_size * 5; //预留5个包的缓存
|
||||
|
||||
/* sys_timer_add(host_dev,set_vol_test,5000); */
|
||||
os_sem_create(&__this->player.sem, 0);
|
||||
u32 host_ep = as_t->host_ep;
|
||||
__this->player.play_state = AUDIO_PLAY_START;
|
||||
//分配双缓存
|
||||
// 一个缓存保存读卡的数据,一个用于usb发送
|
||||
if (!__this->player.usb_audio_play_buf) {
|
||||
__this->player.usb_audio_play_buf = zalloc(usb_audio_buf_size);
|
||||
cbuf_init(&__this->player.usb_audio_play_cbuf, __this->player.usb_audio_play_buf, usb_audio_buf_size);
|
||||
usb_h_ep_write_async(usb_id, host_ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); //启动iso传输
|
||||
}
|
||||
if (!__this->player.usb_audio_play_buf2) {
|
||||
__this->player.usb_audio_play_buf2 = zalloc(usb_audio_buf_size);
|
||||
}
|
||||
while (1) {
|
||||
if (__this->player.Cur_AlternateSetting == 0 || __this->player.play_state != AUDIO_PLAY_START) {
|
||||
putchar('C');
|
||||
os_time_dly(50);
|
||||
continue;
|
||||
}
|
||||
ptr = cbuf_write_alloc(&__this->player.usb_audio_play_cbuf, &wlen);
|
||||
if (wlen) {
|
||||
putchar('R');
|
||||
ret = __this->player.put_buf(ptr, wlen);
|
||||
if (ret != wlen) {
|
||||
__this->player.play_state = AUDIO_PLAY_STOP;
|
||||
goto __task_exit;
|
||||
|
||||
}
|
||||
cbuf_write_updata(&__this->player.usb_audio_play_cbuf, wlen);
|
||||
} else {
|
||||
log_w("usb audio play buf not enough!\n");
|
||||
}
|
||||
__task_exit:
|
||||
os_sem_pend(&__this->player.sem, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_audio_start_play(const usb_dev usb_id, u8 channel, u8 bit_reso, u32 sample_rate)
|
||||
{
|
||||
log_info(" usb audio play\n");
|
||||
const struct usb_host_device *host_dev = host_id2device(usb_id);
|
||||
struct audio_device_t *audio = NULL;
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
u8 *ep_buffer = ep_out_dma_buf;
|
||||
u8 find_alternatesetting = 0;
|
||||
audio = __find_headphone_interface(host_dev);
|
||||
if (!audio) {
|
||||
log_error("no find headphone interface!");
|
||||
return;
|
||||
}
|
||||
for (u8 i = 0; i < ARRAY_SIZE(audio->as); i++) {
|
||||
as_t = &audio->as[i];
|
||||
if (as_t->bBitResolution == bit_reso) {
|
||||
for (u8 j = 0; j < as_t->bSamFreqType; j++) {
|
||||
if (as_t->tSamFreq[j] == sample_rate) {
|
||||
find_alternatesetting = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!find_alternatesetting) {
|
||||
log_e("can not find Alternatesetting,please check bit_reso and sample_rate\n");
|
||||
return;
|
||||
}
|
||||
|
||||
__this->usb_id = usb_id;
|
||||
//端点分配
|
||||
u32 host_ep = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC);
|
||||
ASSERT(host_ep != -1, "ep not enough");
|
||||
|
||||
__this->player.Cur_AlternateSetting = find_alternatesetting; //选择Alternatesetting
|
||||
__this->player.sample_rate = sample_rate; //选择采样率
|
||||
__this->player.src_channel = channel;
|
||||
as_t = &audio->as[find_alternatesetting - 1];
|
||||
u8 target_ep = as_t->ep;
|
||||
u8 ep_interval = as_t->ep_Interval;
|
||||
as_t->host_ep = host_ep;
|
||||
|
||||
usb_set_interface(host_dev, audio->interface_num, find_alternatesetting); //interface Alternatesetting
|
||||
usb_audio_sampling_frequency_control(host_dev, target_ep, sample_rate);//设置采样率
|
||||
//设置音量
|
||||
/* usb_audio_volume_control(host_dev, 6, 1, vol_convert(5)); */
|
||||
/* usb_audio_volume_control(host_dev, 6, 2, vol_convert(5)); */
|
||||
|
||||
log_info("H2D ep: %x --> %x interval: %d", host_ep, target_ep, ep_interval);
|
||||
usb_h_set_ep_isr(host_dev, host_ep, usb_audio_tx_isr, host_dev);
|
||||
usb_h_ep_config(usb_id, host_ep, USB_ENDPOINT_XFER_ISOC, 1, ep_interval, ep_buffer, sizeof(ep_out_dma_buf));
|
||||
task_create(audio_play_task, host_dev, "uac_play");
|
||||
}
|
||||
|
||||
void usb_audio_stop_play(const usb_dev usb_id)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(usb_id);
|
||||
usb_h_set_ep_isr(NULL, 0, NULL, NULL);
|
||||
__this->player.put_buf(NULL, 0);
|
||||
__this->player.Cur_AlternateSetting = 0;
|
||||
__this->player.sample_rate = 0;
|
||||
__this->player.src_channel = 0;
|
||||
if (__this->player.usb_audio_play_buf) {
|
||||
free(__this->player.usb_audio_play_buf);
|
||||
__this->player.usb_audio_play_buf = NULL;
|
||||
}
|
||||
if (__this->player.usb_audio_play_buf2) {
|
||||
free(__this->player.usb_audio_play_buf2);
|
||||
__this->player.usb_audio_play_buf2 = NULL;
|
||||
}
|
||||
if (__this->player.send_buf) {
|
||||
free(__this->player.send_buf);
|
||||
__this->player.send_buf = NULL;
|
||||
}
|
||||
printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__);
|
||||
task_kill("uac_play");
|
||||
printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__);
|
||||
}
|
||||
void usb_audio_pause_play(void)
|
||||
{
|
||||
__this->player.play_state = AUDIO_PLAY_PAUSE;
|
||||
}
|
||||
void usb_audio_resume_play(void)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(__this->usb_id);
|
||||
struct audio_device_t *audio = __find_headphone_interface(host_dev);
|
||||
struct audio_streaming_t *as_t = &audio->as[__this->player.Cur_AlternateSetting - 1];
|
||||
__this->player.play_state = AUDIO_PLAY_START;
|
||||
usb_h_ep_write_async(__this->usb_id, as_t->host_ep, as_t->ep_max_packet_size, as_t->ep, NULL, as_t->ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); //重新启动传输
|
||||
}
|
||||
|
||||
|
||||
static u32 record_vol_convert(u16 v)
|
||||
{
|
||||
//固定音量表,更换声卡需要修改音量表
|
||||
const u16 vol_table[] = {
|
||||
//0-100
|
||||
0xf400,
|
||||
0xf479, 0xf4ee, 0xf560, 0xf5cf, 0xf63a, 0xf6a3, 0xf709, 0xf76c, 0xf7cd, 0xf82b,
|
||||
0xf887, 0xf8e1, 0xf939, 0xf98f, 0xf9e4, 0xfa36, 0xfa87, 0xfad6, 0xfb23, 0xfb6f,
|
||||
0xfbba, 0xfc03, 0xfc4b, 0xfc91, 0xfcd6, 0xfd1a, 0xfd5d, 0xfd9f, 0xfde0, 0xfe1f,
|
||||
0xfe5e, 0xfe9b, 0xfed8, 0xff14, 0xff4e, 0xff88, 0xffc1, 0xfff9, 0x0003, 0x0069,
|
||||
0x00a3, 0x00de, 0x0119, 0x0155, 0x0193, 0x01d1, 0x0210, 0x0251, 0x0292, 0x02d5,
|
||||
0x0318, 0x035d, 0x03a3, 0x03eb, 0x0434, 0x047e, 0x04c9, 0x0517, 0x0565, 0x05b5,
|
||||
0x0607, 0x065b, 0x06b1, 0x0708, 0x0762, 0x07bd, 0x081b, 0x087c, 0x08de, 0x0943,
|
||||
0x09ab, 0x0a16, 0x0a84, 0x0af4, 0x0b69, 0x0be1, 0x0c5c, 0x0cdc, 0x0d60, 0x0de9,
|
||||
0x0e77, 0x0f0a, 0x0fa2, 0x1041, 0x10e7, 0x1195, 0x124a, 0x1308, 0x13d0, 0x14a3,
|
||||
0x1582, 0x166e, 0x176a, 0x1877, 0x1998, 0x1ad0, 0x1c24, 0x1d98, 0x1f33, 0x2100,
|
||||
};
|
||||
|
||||
if (v <= 100) {
|
||||
return vol_table[v];
|
||||
}
|
||||
|
||||
for (int i = 0; i < sizeof(vol_table) / 2; i++) {
|
||||
if (v <= vol_table[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_usb_audio_record_volume(u16 vol)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(__this->usb_id);
|
||||
u8 featureUnitID = 5;
|
||||
usb_audio_volume_control(host_dev, featureUnitID, 0, record_vol_convert(vol));
|
||||
}
|
||||
|
||||
static u32 write_file_len = 0;
|
||||
static void usb_audio_rx_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
u8 buffer[192] = {0};
|
||||
u8 *ptr = NULL;
|
||||
int rlen, wlen = 0;
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
struct audio_device_t *audio = NULL;
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
audio = __find_microphone_interface(host_dev);
|
||||
if (!audio) {
|
||||
log_error("no find microphone interface!");
|
||||
return;
|
||||
}
|
||||
if (__this->microphone.record_state != AUDIO_RECORD_START) {
|
||||
return;
|
||||
}
|
||||
as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1];
|
||||
u8 channel = as_t->bNrChannels;
|
||||
|
||||
u32 rx_len = usb_h_ep_read_async(usb_id, ep, as_t->ep, buffer, sizeof(buffer), USB_ENDPOINT_XFER_ISOC, 0);
|
||||
/* g_printf("RX:%d\n",rx_len); */
|
||||
/* printf_buf(buffer, rx_len); */
|
||||
cbuf_write(&__this->microphone.usb_audio_record_cbuf, buffer, rx_len);
|
||||
cbuf_write_alloc(&__this->microphone.usb_audio_record_cbuf, &wlen);
|
||||
if (wlen == 0) {
|
||||
putchar('O');
|
||||
if (write_file_len) {
|
||||
log_w("write againnnnn\n");
|
||||
}
|
||||
/* [> printf("R:%d W:%d\n", rx_len,wlen); <] */
|
||||
cbuf_read_alloc(&__this->microphone.usb_audio_record_cbuf, &rlen);
|
||||
cbuf_read(&__this->microphone.usb_audio_record_cbuf, __this->microphone.usb_audio_record_buf2, rlen);
|
||||
write_file_len = rlen;
|
||||
os_taskq_post_msg("uac_record", 2, 0x01, rlen);
|
||||
/* return; */
|
||||
}
|
||||
|
||||
usb_h_ep_read_async(usb_id, ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //触发下一个接收中断
|
||||
}
|
||||
void audio_record_task(void *p)
|
||||
{
|
||||
log_info(">>> Enter usb audio record task");
|
||||
struct usb_host_device *host_dev = (struct usb_host_device *)p;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 *ptr = NULL;
|
||||
u32 rlen = 0;
|
||||
u32 ret = 0;
|
||||
int msg[16];
|
||||
struct audio_device_t *audio = NULL;
|
||||
audio = __find_microphone_interface(host_dev);
|
||||
struct audio_streaming_t *as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1];
|
||||
/* u32 ep_max_packet_size = as_t->ep_max_packet_size; */
|
||||
u32 ep_max_packet_size = EP_MAX_PACKET_SIZE;
|
||||
log_info("ep max packet : %d\n", ep_max_packet_size);
|
||||
u32 usb_audio_buf_size = ep_max_packet_size * 50;
|
||||
|
||||
u32 host_ep = as_t->host_ep;
|
||||
u8 target_ep = as_t->ep;
|
||||
//分配双缓存
|
||||
// 一个缓存写卡的数据,一个用于usb接收
|
||||
if (!__this->microphone.usb_audio_record_buf) {
|
||||
__this->microphone.usb_audio_record_buf = zalloc(usb_audio_buf_size);
|
||||
cbuf_init(&__this->microphone.usb_audio_record_cbuf, __this->microphone.usb_audio_record_buf, usb_audio_buf_size);
|
||||
|
||||
}
|
||||
if (!__this->microphone.usb_audio_record_buf2) {
|
||||
__this->microphone.usb_audio_record_buf2 = zalloc(usb_audio_buf_size);
|
||||
}
|
||||
|
||||
usb_h_ep_read_async(usb_id, host_ep, target_ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //启动iso
|
||||
while (1) {
|
||||
ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
|
||||
if (ret == OS_TASKQ) {
|
||||
switch (msg[1]) {
|
||||
case 0x01:
|
||||
ptr = __this->microphone.usb_audio_record_buf2;
|
||||
rlen = msg[2];
|
||||
putchar('W');
|
||||
__this->microphone.get_buf(ptr, rlen);
|
||||
write_file_len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void usb_audio_start_record(const usb_dev usb_id, u8 bit_reso, u32 sample_rate)
|
||||
{
|
||||
log_info(" usb audio record\n");
|
||||
const struct usb_host_device *host_dev = host_id2device(usb_id);
|
||||
struct audio_device_t *audio = NULL;
|
||||
struct audio_streaming_t *as_t = NULL;
|
||||
u8 *ep_buffer = ep_in_dma_buf;
|
||||
u8 find_alternatesetting = 0;
|
||||
audio = __find_microphone_interface(host_dev);
|
||||
if (!audio) {
|
||||
log_error("no find microphone interface!");
|
||||
return;
|
||||
}
|
||||
for (u8 i = 0; i < ARRAY_SIZE(audio->as); i++) {
|
||||
as_t = &audio->as[i];
|
||||
if (as_t->bBitResolution == bit_reso) {
|
||||
for (u8 j = 0; j < as_t->bSamFreqType; j++) {
|
||||
if (as_t->tSamFreq[j] == sample_rate) {
|
||||
find_alternatesetting = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!find_alternatesetting) {
|
||||
log_e("can not find Alternatesetting,please check bit_reso and sample_rate\n");
|
||||
return;
|
||||
}
|
||||
//端点分配
|
||||
u32 host_ep = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_ISOC);
|
||||
ASSERT(host_ep != -1, "ep not enough");
|
||||
__this->usb_id = usb_id;
|
||||
host_ep = host_ep | USB_DIR_IN;
|
||||
|
||||
__this->microphone.Cur_AlternateSetting = find_alternatesetting; //选择Alternatesetting
|
||||
__this->microphone.sample_rate = sample_rate; //选择采样率
|
||||
as_t = &audio->as[find_alternatesetting - 1];
|
||||
u8 target_ep = as_t->ep;
|
||||
u8 ep_interval = as_t->ep_Interval;
|
||||
as_t->host_ep = host_ep;
|
||||
|
||||
usb_set_interface(host_dev, audio->interface_num, find_alternatesetting); //interface 1 Alternatesetting 1
|
||||
usb_audio_sampling_frequency_control(host_dev, target_ep, sample_rate);//设置采样率
|
||||
//设置音量
|
||||
/* usb_audio_volume_control(host_dev, 6, 1, vol_convert(5)); */
|
||||
/* usb_audio_volume_control(host_dev, 6, 2, vol_convert(5)); */
|
||||
log_info("D2H ep: %x --> %x", target_ep, host_ep);
|
||||
usb_h_set_ep_isr(host_dev, host_ep, usb_audio_rx_isr, host_dev);
|
||||
usb_h_ep_config(usb_id, host_ep, USB_ENDPOINT_XFER_ISOC, 1, ep_interval, ep_buffer, sizeof(ep_in_dma_buf));
|
||||
task_create(audio_record_task, host_dev, "uac_record");
|
||||
__this->microphone.record_state = AUDIO_RECORD_START;
|
||||
}
|
||||
void usb_audio_stop_record(const usb_dev usb_id)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(usb_id);
|
||||
usb_h_set_ep_isr(NULL, 0, NULL, NULL);
|
||||
__this->microphone.get_buf(NULL, 0);
|
||||
__this->microphone.Cur_AlternateSetting = 0;
|
||||
__this->microphone.sample_rate = 0;
|
||||
if (__this->microphone.usb_audio_record_buf) {
|
||||
free(__this->microphone.usb_audio_record_buf);
|
||||
__this->microphone.usb_audio_record_buf = NULL;
|
||||
}
|
||||
if (__this->microphone.usb_audio_record_buf2) {
|
||||
free(__this->microphone.usb_audio_record_buf2);
|
||||
__this->microphone.usb_audio_record_buf2 = NULL;
|
||||
}
|
||||
printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__);
|
||||
task_kill("uac_record");
|
||||
printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__);
|
||||
}
|
||||
void usb_audio_pause_record(void)
|
||||
{
|
||||
__this->microphone.record_state = AUDIO_RECORD_PAUSE;
|
||||
}
|
||||
void usb_audio_resume_record(void)
|
||||
{
|
||||
const struct usb_host_device *host_dev = host_id2device(__this->usb_id);
|
||||
struct audio_device_t *audio = __find_microphone_interface(host_dev);
|
||||
struct audio_streaming_t *as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1];
|
||||
__this->microphone.record_state = AUDIO_RECORD_START;
|
||||
usb_h_ep_read_async(__this->usb_id, as_t->host_ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //重新启动接收
|
||||
}
|
||||
|
||||
void usb_audio_start_process(u32 id)
|
||||
{
|
||||
usb_audio_start_play(id, 1, 16, 48000); //开启headphone
|
||||
usb_audio_start_record(id, 16, 48000); //开启microphone
|
||||
}
|
||||
void usb_audio_stop_process(u32 id)
|
||||
{
|
||||
usb_audio_stop_play(id);
|
||||
usb_audio_stop_record(id);
|
||||
}
|
||||
|
||||
|
||||
static void usb_audio_event_handler(struct sys_event *event, void *priv)
|
||||
{
|
||||
const char *audio = NULL;
|
||||
switch (event->type) {
|
||||
case SYS_DEVICE_EVENT:
|
||||
if ((u32)event->arg == DEVICE_EVENT_FROM_USB_HOST) {
|
||||
if ((event->u.dev.event == DEVICE_EVENT_IN) ||
|
||||
(event->u.dev.event == DEVICE_EVENT_CHANGE)) {
|
||||
audio = (const char *)event->u.dev.value;
|
||||
usb_audio_start_process(audio[5] - '0');
|
||||
|
||||
} else if (event->u.dev.event == DEVICE_EVENT_OUT) {
|
||||
log_error("device out %x", event->u.dev.value);
|
||||
usb_audio_stop_process(audio[5] - '0');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void usb_host_audio_init(int (*put_buf)(void *ptr, u32 len), int *(*get_buf)(void *ptr, u32 len))
|
||||
{
|
||||
memset(__this, 0, sizeof(struct usb_audio_info));
|
||||
__this->player.put_buf = put_buf;
|
||||
__this->microphone.get_buf = get_buf;
|
||||
register_sys_event_handler(SYS_DEVICE_EVENT, DEVICE_EVENT_FROM_USB_HOST, 2,
|
||||
usb_audio_event_handler);
|
||||
}
|
||||
void usb_host_audio_exit()
|
||||
{
|
||||
unregister_sys_event_handler(usb_audio_event_handler);
|
||||
__this->player.put_buf = NULL;
|
||||
__this->microphone.get_buf = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef __AUDIO_H__
|
||||
#define __AUDIO_H__
|
||||
|
||||
#include "system/task.h"
|
||||
#include "device/device.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb/device/uac_audio.h"
|
||||
|
||||
|
||||
#define HEADPHONE_SUPPORTED 0x01
|
||||
#define MICROPHONE_SUPPORTED 0x02
|
||||
#define HEADSET_SUPPORTED 0x03
|
||||
|
||||
struct audio_streaming_t {
|
||||
u8 bNumEndpoints;
|
||||
u8 bFormatType; /** FORMAT_TYPE_1 */
|
||||
u8 bNrChannels; /** physical channels in the stream */
|
||||
u8 bSubframeSize;
|
||||
u8 bBitResolution;
|
||||
u8 bSamFreqType;
|
||||
u32 tSamFreq[8];
|
||||
u8 host_ep; //主机传输端点
|
||||
u8 ep; //从机端点(由描述符中指定)
|
||||
u8 ep_Interval;
|
||||
u16 ep_max_packet_size;
|
||||
};
|
||||
|
||||
struct audio_device_t {
|
||||
u8 interface_num; //接口号
|
||||
u8 subclass;
|
||||
u8 support;
|
||||
void *parent;
|
||||
struct audio_streaming_t as[8];
|
||||
};
|
||||
|
||||
int usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
// API
|
||||
int usb_audio_play_put_buf(void *ptr, u32 len);
|
||||
int usb_audio_record_get_buf(void *ptr, u32 len);
|
||||
|
||||
//headphone api
|
||||
void set_usb_audio_play_volume(u16 vol);
|
||||
void usb_audio_start_play(const usb_dev usb_id, u8 channel, u8 bit_reso, u32 sample_rate); //指定播放数据的声道数,位数,采样率
|
||||
void usb_audio_stop_play(const usb_dev usb_id);
|
||||
void usb_audio_pause_play(void);
|
||||
void usb_audio_resume_play(void);
|
||||
|
||||
//microphone api
|
||||
void set_usb_audio_record_volume(u16 vol);
|
||||
void usb_audio_start_record(const usb_dev usb_id, u8 bit_reso, u32 sample_rate); //指定录制数据的位数,采样率
|
||||
void usb_audio_stop_record(const usb_dev usb_id);
|
||||
void usb_audio_pause_record(void);
|
||||
void usb_audio_resume_record(void);
|
||||
#endif
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "includes.h"
|
||||
#include "asm/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "system/timer.h"
|
||||
#include "device/ioctl_cmds.h"
|
||||
#include "device_drive.h"
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "audio.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[AUDIO]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#define TEST_FILE_ENABLE (0) //从sd卡读数据; 录制数据至sd卡
|
||||
#if (TEST_FILE_ENABLE)
|
||||
static FILE *play_file = NULL;
|
||||
int usb_audio_play_put_buf(void *ptr, u32 len)
|
||||
{
|
||||
int ret = 0;
|
||||
if (ptr == NULL && len == 0) {
|
||||
//err
|
||||
if (play_file) {
|
||||
fclose(play_file);
|
||||
play_file = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!play_file) {
|
||||
play_file = fopen("storage/sd0/C/raw.pcm", "r"); //单声道
|
||||
/* play_file = fopen("storage/sd0/C/raw2.pcm", "r"); //双声道 */
|
||||
if (!play_file) {
|
||||
log_e("fopen play file faild!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//读sd卡数据到播放缓存中
|
||||
ret = fread(play_file, ptr, len);
|
||||
if (ret != len) {
|
||||
log_e(" file read buf err %d\n", ret);
|
||||
fclose(play_file);
|
||||
play_file = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
static FILE *record_file = NULL;
|
||||
int usb_audio_record_get_buf(void *ptr, u32 len)
|
||||
{
|
||||
#if (TEST_FILE_ENABLE)
|
||||
int ret = 0;
|
||||
static u32 cnt = 0;
|
||||
if (!record_file) {
|
||||
record_file = fopen("storage/sd0/C/record01.pcm", "w+");
|
||||
cnt = 0;
|
||||
if (!record_file) {
|
||||
log_e("fopen play file faild!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
putchar('W');
|
||||
ret = fwrite(record_file, ptr, len);
|
||||
if (ret != len) {
|
||||
log_e(" file write buf err %d\n", ret);
|
||||
fclose(record_file);
|
||||
record_file = NULL;
|
||||
return -1;
|
||||
}
|
||||
//test
|
||||
if (cnt++ >= 800) {
|
||||
cnt = 0;
|
||||
log_info("stop record....\n");
|
||||
fclose(record_file);
|
||||
record_file = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return len;
|
||||
}
|
||||
#else
|
||||
|
||||
//将数据传入usb
|
||||
//ptr:usb数据指针
|
||||
//len:需要传入的数据长度
|
||||
int usb_audio_play_put_buf(void *ptr, u32 len)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
//从usb读取数据
|
||||
//ptr:usb数据指针
|
||||
//len:读取的数据长度
|
||||
int usb_audio_record_get_buf(void *ptr, u32 len)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,657 @@
|
||||
#include "includes.h"
|
||||
#include "asm/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "system/timer.h"
|
||||
#include "device/ioctl_cmds.h"
|
||||
#include "device_drive.h"
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "hid.h"
|
||||
#include "usb_config.h"
|
||||
#include "usb_hid_keys.h"
|
||||
|
||||
#define MAIN_ITEM 0
|
||||
#define GLOBAL_ITEM 1
|
||||
#define LOCAL_ITEM 2
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[HID]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
struct hid_device_t hid_device[USB_MAX_HW_NUM][MAX_HOST_INTERFACE];
|
||||
|
||||
static int set_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
memset(hid_device[usb_id], 0, sizeof(hid_device[usb_id]));
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static int get_power(struct usb_host_device *host_dev, u32 value)
|
||||
{
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
static const struct interface_ctrl hid_ctrl = {
|
||||
.interface_class = USB_CLASS_HID,
|
||||
.set_power = set_power,
|
||||
.get_power = get_power,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
static const struct usb_interface_info _usb_if[USB_MAX_HW_NUM][MAX_HOST_INTERFACE] = {
|
||||
{
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[0][0],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[0][1],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[0][2],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[0][3],
|
||||
},
|
||||
},
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
{
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[1][0],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[1][1],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[1][2],
|
||||
},
|
||||
{
|
||||
.ctrl = (struct interface_ctrl *) &hid_ctrl,
|
||||
.dev.hid = &hid_device[1][3],
|
||||
},
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static u8 interval[USB_MAX_HW_NUM][16];
|
||||
|
||||
int usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
pBuf += sizeof(struct usb_interface_descriptor);
|
||||
int len = 0;
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
|
||||
pBuf += 9;//hid desc;
|
||||
|
||||
const struct usb_interface_info *usb_if = &_usb_if[usb_id][interface_num];
|
||||
|
||||
memset(usb_if->dev.p, 0, sizeof(struct hid_device_t));
|
||||
|
||||
host_dev->interface_info[interface_num] = usb_if;
|
||||
usb_if->dev.hid->parent = host_dev;
|
||||
|
||||
log_info("hid eps %d %d %x %x", interface->bNumEndpoints, interface_num, usb_if, usb_if->dev.p);
|
||||
|
||||
log_info("parent %x hid @ interface %d usb_if %x hid %x",
|
||||
host_dev, interface_num, usb_if, usb_if->dev.hid);
|
||||
|
||||
if ((interface->bInterfaceProtocol == 0x02) ||
|
||||
(interface->bInterfaceProtocol == 0x01)) { //mouse & keyboard
|
||||
|
||||
usb_if->dev.hid->bNumEndpoints = interface->bNumEndpoints;
|
||||
usb_if->dev.hid->report_list[0].usage = interface->bInterfaceProtocol;
|
||||
for (int i = 0 ; i < interface->bNumEndpoints; i++) {
|
||||
endpoint = (struct usb_endpoint_descriptor *)pBuf;
|
||||
if (USB_DIR_IN & endpoint->bEndpointAddress) {
|
||||
const u8 ep = endpoint->bEndpointAddress & 0x0f;
|
||||
usb_if->dev.hid->ep_pair[i] = ep;
|
||||
interval[usb_id][ep] = endpoint->bInterval;
|
||||
log_info("interfacenum = %d,endpoint = %x interval = %x",
|
||||
interface->bInterfaceNumber, endpoint->bEndpointAddress, endpoint->bInterval);
|
||||
}
|
||||
pBuf += endpoint->bLength;
|
||||
}
|
||||
} else {
|
||||
log_info("vendor");
|
||||
host_dev->interface_info[interface_num] = NULL; //???
|
||||
for (int i = 0 ; i < interface->bNumEndpoints; i++) {
|
||||
endpoint = (struct usb_endpoint_descriptor *)pBuf;
|
||||
if (USB_DIR_IN & endpoint->bEndpointAddress) {
|
||||
/* interface_endpoint[interface->bInterfaceNumber] = endpoint->bEndpointAddress & 0x0f; */
|
||||
log_info("interfacenum = %d,endpoint = %x interval = %x",
|
||||
interface->bInterfaceNumber, endpoint->bEndpointAddress, endpoint->bInterval);
|
||||
}
|
||||
pBuf += endpoint->bLength;
|
||||
}
|
||||
return sizeof(struct usb_interface_descriptor);
|
||||
}
|
||||
|
||||
return pBuf - (u8 *)interface;
|
||||
}
|
||||
|
||||
static u32 _hid_report_parse(struct hid_device_t *hid, const u8 *report, u32 len)
|
||||
{
|
||||
hid->report_count = 0;
|
||||
struct report_info_t null_rpt;
|
||||
struct report_info_t *const rpt = &null_rpt;
|
||||
|
||||
memset(rpt, 0, sizeof(*rpt));
|
||||
|
||||
unsigned char ops;
|
||||
int index = 0;
|
||||
u8 report_size = 0;
|
||||
u8 report_count = 0;
|
||||
u8 cur_ops_is_report_size_count = 0;
|
||||
u8 old_ops_is_report_size_count = 0;
|
||||
s8 cur_section_bit = 0;
|
||||
u8 input_bit_index = 0;
|
||||
u8 total_bits = 0;
|
||||
u8 output_bit_index = 0;
|
||||
u8 cur_usage = 0;
|
||||
u32 undef_type = 0;
|
||||
u8 undef_usage = 0;
|
||||
u8 collection_deep = 0;
|
||||
|
||||
while (index < len) {
|
||||
ops = (char)report[index++];
|
||||
char bSize = ops & 0x03;
|
||||
bSize = bSize == 3 ? 4 : bSize; // size is 4 when bSize is 3
|
||||
char bType = (ops >> 2) & 0x03;
|
||||
char bTag = (ops >> 4) & 0x0F;
|
||||
|
||||
cur_ops_is_report_size_count = 0;
|
||||
char bSizeActual = 0;
|
||||
int itemVal = 0;
|
||||
for (int j = 0; j < bSize; j++) {
|
||||
if (index + j < len) {
|
||||
itemVal += report[index + j] << (8 * j);
|
||||
bSizeActual++;
|
||||
}
|
||||
}
|
||||
if (undef_type) {
|
||||
undef_type ++;
|
||||
if (bTag == 0x0A) {
|
||||
undef_usage ++;
|
||||
} else if (bTag == 0x0C) {
|
||||
undef_usage --;
|
||||
}
|
||||
if (undef_usage == 0 && undef_type > 2) {
|
||||
undef_type = 0;
|
||||
}
|
||||
index += bSize;
|
||||
continue;
|
||||
}
|
||||
if (undef_type) {
|
||||
index += bSize;
|
||||
continue;
|
||||
}
|
||||
if (itemVal == 0xffb5) {
|
||||
undef_type = 1;
|
||||
index += bSize;
|
||||
continue;
|
||||
} else {
|
||||
undef_type = 0;
|
||||
}
|
||||
if (bType == MAIN_ITEM) {
|
||||
if (old_ops_is_report_size_count) {
|
||||
cur_section_bit += report_size * report_count;
|
||||
}
|
||||
if (bTag == 0x08) {
|
||||
/* log_info("input %X", itemVal); */
|
||||
/* log_info("\tusage %x", cur_usage); */
|
||||
/* log_info("\t\tcur_section_bit %d", cur_section_bit); */
|
||||
if (rpt->usage == 0x02) { //mouse
|
||||
if (cur_usage == 1) {
|
||||
if (rpt->btn_start_bit == 0) {
|
||||
rpt->btn_start_bit = total_bits ;
|
||||
}
|
||||
rpt->btn_width += cur_section_bit ;
|
||||
/* log_info("btn_width %d-%d", rpt->btn_start_bit, rpt->btn_width); */
|
||||
} else if ((cur_usage == 0x30) || (cur_usage == 0x31)) {
|
||||
|
||||
if (rpt->xy_start_bit == 0) {
|
||||
rpt->xy_start_bit = total_bits;
|
||||
}
|
||||
rpt->xy_width = cur_section_bit;
|
||||
/* log_info("xy_width %d-%d", rpt->xy_start_bit, rpt->xy_width); */
|
||||
} else if (cur_usage == 0x38) {
|
||||
if (rpt->wheel_start_bit == 0) {
|
||||
rpt->wheel_start_bit = total_bits;
|
||||
}
|
||||
if (rpt->xy_width || cur_section_bit < 24) {
|
||||
rpt->wheel_width = cur_section_bit;
|
||||
/* log_info("wheel_width %d-%d", rpt->wheel_start_bit, rpt->wheel_width); */
|
||||
} else {
|
||||
rpt->wheel_width = rpt->xy_width = cur_section_bit / 3;
|
||||
|
||||
rpt->xy_start_bit = total_bits;
|
||||
rpt->wheel_start_bit = rpt->xy_start_bit + rpt->xy_width * 2;
|
||||
/* log_info("wheel_width %d-%d", rpt->wheel_start_bit, rpt->wheel_width); */
|
||||
/* log_info("xy_width %d-%d", rpt->xy_start_bit, rpt->xy_width); */
|
||||
}
|
||||
} else if (cur_usage == 0xb8) {
|
||||
rpt->wheel_width = rpt->xy_width = cur_section_bit / 4;
|
||||
rpt->xy_start_bit = total_bits;
|
||||
rpt->wheel_start_bit = rpt->xy_start_bit + rpt->xy_width * 2;
|
||||
}
|
||||
}
|
||||
total_bits += cur_section_bit;
|
||||
/* input_bit[input_bit_index++] = cur_section_bit; */
|
||||
cur_section_bit = -1;
|
||||
} else if (bTag == 0x09) {
|
||||
/* log_info("OUTPUT %X", itemVal); */
|
||||
/* log_info("\tusage %x", cur_usage); */
|
||||
/* log_info("\t\tcur_section_bit %d", cur_section_bit); */
|
||||
/* output_bit[output_bit_index++] = cur_section_bit; */
|
||||
cur_section_bit = -1;
|
||||
} else if (bTag == 0x0B) {
|
||||
/* log_info("Feature %X", itemVal); */
|
||||
/* log_info("\tusage %x", cur_usage); */
|
||||
/* log_info("\t\tcur_section_bit %d", cur_section_bit); */
|
||||
/* output_bit[output_bit_index++] = cur_section_bit; */
|
||||
cur_section_bit = -1;
|
||||
} else if (bTag == 0x0A) {
|
||||
collection_deep ++ ;
|
||||
log_info("Collection %d %x", collection_deep, rpt->usage);
|
||||
} else if (bTag == 0x0C) {
|
||||
collection_deep --;
|
||||
log_info("End Collection %d %x", collection_deep, rpt->usage);
|
||||
if (collection_deep == 0) {
|
||||
if (rpt->usage == 0x02 ||
|
||||
rpt->usage == 0x06 ||
|
||||
rpt->usage == 0x07) {
|
||||
|
||||
memcpy(&hid->report_list[hid->report_count], rpt, sizeof(*rpt));
|
||||
memset(rpt, 0, sizeof(*rpt));
|
||||
|
||||
hid->report_count ++;
|
||||
}
|
||||
}
|
||||
if (index < len) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
log_info("MAIN_ITEM Unknown btag :%x", bTag);
|
||||
return 1;
|
||||
}
|
||||
} else if (bType == GLOBAL_ITEM) {
|
||||
/* log_info("GLOBAL_ITEM"); */
|
||||
if (bTag == 0x00) {
|
||||
/* log_info("Usage Page %x", itemVal); */
|
||||
|
||||
if (rpt->usage == 0x06) {
|
||||
if (itemVal == 0x07) {
|
||||
rpt->usage = 0x07;
|
||||
log_info("re set type %x", 0x07);
|
||||
}
|
||||
}
|
||||
if (itemVal == 0x02) {
|
||||
rpt->usage = 0x02;
|
||||
log_info("re set type %x", 0x02);
|
||||
}
|
||||
|
||||
} else if (bTag == 0x01) {
|
||||
//log_info("Logical Minimum %x", itemVal);
|
||||
} else if (bTag == 0x02) {
|
||||
//log_info("Logical Maximum %x", itemVal);
|
||||
} else if (bTag == 0x03) {
|
||||
/* log_info("Physical Minimum %x", itemVal); */
|
||||
} else if (bTag == 0x04) {
|
||||
/* log_info("Physical Maximum %x", itemVal); */
|
||||
} else if (bTag == 0x05) {
|
||||
/* log_info("Unit Exponent %x", itemVal); */
|
||||
} else if (bTag == 0x06) {
|
||||
/* log_info("Unit %x", itemVal); */
|
||||
} else if (bTag == 0x07) {
|
||||
/* log_info("Report Size %x", itemVal); */
|
||||
report_size = itemVal;
|
||||
cur_ops_is_report_size_count = 1;
|
||||
} else if (bTag == 0x08) {
|
||||
log_info("Report ID %x", itemVal, rpt->usage);
|
||||
rpt->report_id = itemVal;
|
||||
} else if (bTag == 0x09) {
|
||||
/* log_info("Report Count %x", itemVal); */
|
||||
report_count = itemVal;
|
||||
cur_ops_is_report_size_count = 1;
|
||||
} else if (bTag == 0x0A) {
|
||||
/* log_info("Push %x", bSizeActual); */
|
||||
} else if (bTag == 0x0B) {
|
||||
/* log_info("Pop %x", bSizeActual); */
|
||||
} else {
|
||||
log_info("GLOBAL_ITEM Unknown btag :%x", bTag);
|
||||
return 2;
|
||||
}
|
||||
} else if (bType == LOCAL_ITEM) {
|
||||
/* log_info("LOCAL_ITEM"); */
|
||||
if (bTag == 0x00) {
|
||||
if (rpt->usage == 0) {
|
||||
rpt->usage = itemVal;
|
||||
log_info("set type %x", rpt->usage);
|
||||
}
|
||||
if (itemVal == 0x30) { //X
|
||||
} else if (itemVal == 0x31) { //y
|
||||
} else if (itemVal == 0x38) { //wheel
|
||||
} else {
|
||||
}
|
||||
/* log_info("\t change usage %x -> %x", cur_usage, itemVal); */
|
||||
cur_usage = itemVal;
|
||||
if (!collection_deep) {
|
||||
if (itemVal == 0x06 || itemVal == 0x07 || itemVal == 0x02) {
|
||||
//仅限键盘和鼠标
|
||||
rpt->usage = itemVal;
|
||||
log_info("set typee %x", rpt->usage);
|
||||
}
|
||||
}
|
||||
/* type = itemVal; */
|
||||
} else if (bTag == 0x01) {
|
||||
// log_info("Usage Minimum %x", itemVal);
|
||||
} else if (bTag == 0x02) {
|
||||
// log_info("Usage Maximum %x", itemVal);
|
||||
} else if (bTag == 0x03) {
|
||||
/* log_info("Designator Index %x", itemVal); */
|
||||
} else if (bTag == 0x04) {
|
||||
/* log_info("Designator Minimum %x", itemVal); */
|
||||
} else if (bTag == 0x05) {
|
||||
/* log_info("Designator Maximum %x", itemVal); */
|
||||
} else if (bTag == 0x07) {
|
||||
/* log_info("String Index %x", itemVal); */
|
||||
} else if (bTag == 0x08) {
|
||||
/* log_info("String Minimum %x", itemVal); */
|
||||
} else if (bTag == 0x09) {
|
||||
/* log_info("String Maximum %x", itemVal); */
|
||||
} else if (bTag == 0x0A) {
|
||||
/* log_info("Delimiter %x", itemVal); */
|
||||
} else {
|
||||
log_info("LOCAL_ITEM Unknown btag :%x", bTag);
|
||||
return 3;
|
||||
}
|
||||
} else {
|
||||
log_info("OTHER Unknown btag :%x", bTag);
|
||||
return 4;
|
||||
}
|
||||
if (!cur_ops_is_report_size_count && old_ops_is_report_size_count) {
|
||||
if (cur_section_bit != -1) {
|
||||
cur_section_bit += report_size * report_count;
|
||||
} else {
|
||||
cur_section_bit = 0;
|
||||
}
|
||||
}
|
||||
if (cur_section_bit == -1) {
|
||||
cur_section_bit = 0;
|
||||
}
|
||||
old_ops_is_report_size_count = cur_ops_is_report_size_count;
|
||||
index += bSize;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static u32 hid_report_parse(struct hid_device_t *hid, const u8 *report, u32 len)
|
||||
{
|
||||
u8 type = _hid_report_parse(hid, report, len);
|
||||
for (int i = 0; i < hid->report_count; i++) {
|
||||
struct report_info_t *rpt = &hid->report_list[i];
|
||||
if (rpt->usage == 0x02) {
|
||||
if (rpt->report_id == 0) {
|
||||
rpt->report_id = 0xff;
|
||||
}
|
||||
rpt->btn_start_bit /= 8;
|
||||
rpt->btn_width /= 8;
|
||||
rpt->xy_start_bit /= 8;
|
||||
rpt->xy_width /= 8;
|
||||
rpt->wheel_start_bit /= 8;
|
||||
rpt->wheel_width /= 8;
|
||||
|
||||
log_info("mouse report_id %d",
|
||||
rpt->report_id);
|
||||
|
||||
log_info("btn_width %d-%d",
|
||||
rpt->btn_start_bit, rpt->btn_width);
|
||||
log_info("xy_width %d-%d",
|
||||
rpt->xy_start_bit, rpt->xy_width);
|
||||
log_info("wheel_width %d-%d",
|
||||
rpt->wheel_start_bit, rpt->wheel_width);
|
||||
|
||||
if (rpt->btn_width != 2) {
|
||||
rpt->btn_width = 1;
|
||||
}
|
||||
|
||||
log_info("btn_width %d-%d",
|
||||
rpt->btn_start_bit, rpt->btn_width);
|
||||
|
||||
} else if (rpt->usage == 6 || rpt->usage == 7) {
|
||||
if (rpt->report_id == 0) {
|
||||
rpt->report_id = 0xff;
|
||||
}
|
||||
log_info("keyboard report_id %d", rpt->report_id);
|
||||
} else {
|
||||
log_info("unknown usage %d", rpt->usage);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mouse_route(const struct mouse_data_t *p);
|
||||
/* __attribute__((weak)) void mouse_route(const struct mouse_data_t *p) */
|
||||
/* { */
|
||||
/* log_info("btn: %x x-y %d %d wheel %d ac_pan %d", */
|
||||
/* p->btn, p->x, p->y, p->wheel, p->ac_pan); */
|
||||
/* } */
|
||||
static void hid_convert_mouse(const struct report_info_t *mouse, const u8 *buffer)
|
||||
{
|
||||
struct mouse_data_t mouse_data;
|
||||
memset(&mouse_data, 0, sizeof(mouse_data));
|
||||
if (mouse->report_id != 0xff) {
|
||||
if (mouse->report_id != buffer[0]) {
|
||||
log_error("report_id = %x buffer[0] = %x", mouse->report_id, buffer[0]);
|
||||
return;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
const u8 *ptr;
|
||||
ptr = &buffer[mouse->btn_start_bit];
|
||||
if (mouse->btn_width == 2) {
|
||||
mouse_data.btn = ptr[0] | (ptr[1] << 8);
|
||||
} else {
|
||||
mouse_data.btn = ptr[0] ;
|
||||
}
|
||||
s16 tmp;
|
||||
ptr = &buffer[mouse->xy_start_bit];
|
||||
if (mouse->xy_width == 1 || mouse->xy_width == 2) {
|
||||
mouse_data.x = (char)ptr[0];
|
||||
mouse_data.y = (char)ptr[1];
|
||||
} else if (mouse->xy_width == 4) {
|
||||
mouse_data.x = ptr[0] | (ptr[1] << 8);
|
||||
ptr += 2;
|
||||
mouse_data.y = ptr[0] | (ptr[1] << 8);
|
||||
} else if (mouse->xy_width == 3) {
|
||||
tmp = (ptr[1] & 0xf) << 12 | ptr[0] << 4;
|
||||
tmp = tmp >> 4;
|
||||
mouse_data.x = tmp;
|
||||
|
||||
tmp = (ptr[2] << 8) | ((ptr[1] >> 4) << 4);
|
||||
tmp = tmp >> 4;
|
||||
mouse_data.y = tmp;
|
||||
} else {
|
||||
log_error("error mouse xy_width %d", mouse->xy_width);
|
||||
}
|
||||
|
||||
ptr = &buffer[mouse->wheel_start_bit];
|
||||
|
||||
if (mouse->wheel_width == 1) {
|
||||
mouse_data.wheel = (char)ptr[0];
|
||||
} else {
|
||||
mouse_data.wheel = ptr[0] | (ptr[1] << 8);
|
||||
}
|
||||
|
||||
mouse_route(&mouse_data);
|
||||
}
|
||||
__attribute__((weak)) void keyboard_route(const u8 *p)
|
||||
{
|
||||
log_info("keyboard_buffer:");
|
||||
printf_buf(p, 12);
|
||||
}
|
||||
void hid_convert_krbd(const struct report_info_t *kbd, u8 *buffer)
|
||||
{
|
||||
#if 0
|
||||
u8 keyboard_buffer[12];
|
||||
memset(keyboard_buffer, 0, sizeof(keyboard_buffer));
|
||||
if (kbd->report_id != 0xff) {
|
||||
if (kbd->report_id != buffer[0]) {
|
||||
log_error("report_id = %x buffer[0] = %x", kbd->report_id, buffer[0]);
|
||||
return;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
|
||||
u8 idx = 0;
|
||||
u8 index = 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (buffer[0] & BIT(i)) {
|
||||
keyboard_buffer[idx++] = 0xe0 + i;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer[1] == 0) {
|
||||
buffer += 2;
|
||||
}
|
||||
index = idx;
|
||||
for (; idx < 12; idx++) {
|
||||
if (*buffer) {
|
||||
keyboard_buffer[index] = *buffer;
|
||||
index++;
|
||||
}
|
||||
buffer ++;
|
||||
}
|
||||
keyboard_route(keyboard_buffer);
|
||||
#else
|
||||
if (kbd->report_id != 0xff) {
|
||||
if (kbd->report_id != buffer[0]) {
|
||||
log_error("report_id = %x buffer[0] = %x", kbd->report_id, buffer[0]);
|
||||
return;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
u8 keyboard_buffer[8];
|
||||
memset(keyboard_buffer, 0, sizeof(keyboard_buffer));
|
||||
|
||||
keyboard_buffer[0] = *buffer;
|
||||
buffer ++;
|
||||
|
||||
if (*buffer == 0) {
|
||||
buffer ++;
|
||||
}
|
||||
keyboard_buffer[1] = 0;
|
||||
|
||||
/* memcpy(&keyboard_buffer[2], buffer, 6); */
|
||||
u8 pos = 2;
|
||||
for (int i = pos; i < 8; i++) {
|
||||
if (*buffer) {
|
||||
keyboard_buffer[pos] = *buffer;
|
||||
pos++;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
keyboard_route(keyboard_buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void hid_route(const struct hid_device_t *hid, const u8 *buffer)
|
||||
{
|
||||
for (int i = 0; i < hid->report_count; i++) {
|
||||
if (hid->report_list[i].usage == 0x02) {
|
||||
hid_convert_mouse(&hid->report_list[i], buffer);
|
||||
} else if ((hid->report_list[i].usage == 0x06) ||
|
||||
(hid->report_list[i].usage == 0x07)) {
|
||||
hid_convert_krbd(&hid->report_list[i], buffer);
|
||||
} else {
|
||||
r_printf("usage %x", hid->report_list[i].usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void hid_isr(struct usb_interface_info *usb_if, u32 ep)
|
||||
{
|
||||
u8 buffer[64] = {0};
|
||||
struct usb_host_device *host_dev = usb_if->dev.hid->parent;
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
u32 target_ep = usb_if->dev.hid->ep_pair[ep];
|
||||
u32 rx_len = usb_h_ep_read_async(usb_id, ep, target_ep, buffer, 64, USB_ENDPOINT_XFER_INT, 0);
|
||||
|
||||
if (rx_len) {
|
||||
hid_route(usb_if->dev.hid, buffer);
|
||||
}
|
||||
/* printf_buf(buffer, rx_len); */
|
||||
|
||||
usb_h_ep_read_async(usb_id, ep, target_ep, buffer, 8, USB_ENDPOINT_XFER_INT, 1);
|
||||
}
|
||||
void hid_process(u32 id)
|
||||
{
|
||||
struct usb_host_device *host_dev = host_id2device(id);
|
||||
u8 report[256 + 2];
|
||||
u8 ep_pair[4];
|
||||
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
struct usb_interface_info *usb_if = host_dev->interface_info[i];
|
||||
log_info("parent %x hid @ interface %d usb_if %x hid %x",
|
||||
host_dev, i, usb_if, usb_if ? usb_if->dev.hid : 0);
|
||||
if (usb_if &&
|
||||
(usb_if->ctrl->interface_class == USB_CLASS_HID)) {
|
||||
hid_set_idle(host_dev, i);
|
||||
memset(report, 0, sizeof(report));
|
||||
hid_get_report(host_dev, report, i, 0xff);
|
||||
printf_buf(report, 256);
|
||||
hid_report_parse(usb_if->dev.hid, report, 256);
|
||||
memcpy(ep_pair, usb_if->dev.hid->ep_pair, 4);
|
||||
|
||||
if (usb_if->dev.hid->report_count == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < usb_if->dev.hid->bNumEndpoints; i++) {
|
||||
|
||||
u32 host_ep = usb_get_ep_num(id, USB_DIR_IN, USB_ENDPOINT_XFER_INT);
|
||||
|
||||
ASSERT(host_ep != -1, "ep not enough");
|
||||
|
||||
u32 target_ep = ep_pair[i];
|
||||
|
||||
usb_if->dev.hid->ep_pair[host_ep] = target_ep;
|
||||
|
||||
log_info("D2H ep: %x --> %x interval %d",
|
||||
target_ep, host_ep, interval[id][target_ep]);
|
||||
|
||||
usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, hid_isr, usb_if);
|
||||
|
||||
u8 *ep_buffer = usb_h_get_ep_buffer(id, host_ep | USB_DIR_OUT);
|
||||
usb_h_ep_config(id, host_ep | USB_DIR_IN, USB_ENDPOINT_XFER_INT, 1,
|
||||
interval[id][target_ep], ep_buffer, 64);
|
||||
int r = usb_h_ep_read_async(id, host_ep, target_ep, NULL, 0, USB_ENDPOINT_XFER_INT, 1);
|
||||
}
|
||||
} else {
|
||||
if (usb_if) {
|
||||
log_error("error hid class %x", usb_if->ctrl->interface_class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
/**@file hid.h
|
||||
* @brief hid驱动头文件(做主机)
|
||||
* @details 结构体声明,功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-9-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC632N
|
||||
* SDK版本:AC632N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-9-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __HID_H__
|
||||
#define __HID_H__
|
||||
|
||||
#include "system/task.h"
|
||||
#include "device/device.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
|
||||
/**@struct report_info_t
|
||||
* @brief 报告描述符包含的信息结构体\n
|
||||
* 自定义一些私有数据信息存储在该结构体中
|
||||
*/
|
||||
struct report_info_t {
|
||||
u8 report_id; ///<id号,不同hid设备对应不同id
|
||||
u8 usage; ///<描述该数据信息的用途
|
||||
|
||||
u8 btn_start_bit; ///<鼠标按键数据起始位
|
||||
u8 btn_width; ///<鼠标按键数据宽度
|
||||
|
||||
u8 xy_start_bit; ///<鼠标平移数据起始位
|
||||
u8 xy_width; ///<鼠标平移数据宽度
|
||||
|
||||
u8 wheel_start_bit; ///<鼠标滚轮数据起始位
|
||||
u8 wheel_width; ///<鼠标滚轮数据宽度
|
||||
};
|
||||
|
||||
#define MAX_REPORT_COUNT 4
|
||||
|
||||
/**@struct hid_device_t
|
||||
* @brief 报告描述符包含的信息结构体\n
|
||||
* 自定义一些私有数据信息存储在该结构体中
|
||||
*/
|
||||
struct hid_device_t {
|
||||
void *parent; ///<定义的parent指针,指向该hid的所属设备
|
||||
u8 ep_pair[4]; ///<端点对数组,数组下标存放主机端点,对应的元素存放目标端点
|
||||
u8 report_count; ///<报告描述符中item计数器
|
||||
u8 bNumEndpoints; ///<端点数量
|
||||
struct report_info_t report_list[MAX_REPORT_COUNT]; ///<报告描述符结构体
|
||||
};
|
||||
|
||||
/**@brief USB hid设备解析
|
||||
* @param[in] host_dev usb_host_device定义的结构体指针
|
||||
* @param[in] interface_num 接口号
|
||||
* @param[in] *pBuf 数据指针,指向数据存放的地址
|
||||
* @return 接口描述符长度
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_hid_parser(host_dev,interface_num,pBuf);
|
||||
* @encode
|
||||
*/
|
||||
int usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
/**@brief USB hid设备信息处理
|
||||
* @param[in] id usb设备id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* hid_process(id);
|
||||
* @encode
|
||||
*/
|
||||
void hid_process(u32 id);
|
||||
|
||||
#endif /*HID_H*/
|
||||
@@ -0,0 +1,319 @@
|
||||
/**
|
||||
* @file usb_bulk_transfer.c
|
||||
* @brief bulk transfer driver
|
||||
* @author chenrixin@zh-jieli.com
|
||||
* @version 1.00
|
||||
* @date 2017-02-09
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "jiffies.h"
|
||||
#include "usb_config.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_storage.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb/usb_phy.h"
|
||||
#include "app_config.h"
|
||||
#include "device_drive.h"
|
||||
|
||||
#if USB_HOST_ENABLE
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
struct usb_request_block {
|
||||
void *ptr;
|
||||
u32 len;
|
||||
u32 target_ep;
|
||||
u16 rxmap;
|
||||
u16 txmap;
|
||||
u32 msg;
|
||||
u32 async_mode;
|
||||
};
|
||||
static struct usb_request_block urb;
|
||||
|
||||
u8 get_async_mode(void)
|
||||
{
|
||||
u8 mode = BULK_ASYNC_MODE_EXIT ;
|
||||
#if UDISK_READ_512_ASYNC_ENABLE
|
||||
local_irq_disable();
|
||||
mode = urb.async_mode;
|
||||
local_irq_enable();
|
||||
#endif
|
||||
return mode;
|
||||
|
||||
}
|
||||
void set_async_mode(u8 mode)
|
||||
{
|
||||
#if UDISK_READ_512_ASYNC_ENABLE
|
||||
local_irq_disable();
|
||||
urb.async_mode = mode;
|
||||
local_irq_enable();
|
||||
#endif
|
||||
}
|
||||
static void usb_bulk_rx_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
int l = min(urb.len, urb.rxmap);
|
||||
|
||||
l = usb_h_ep_read_async(usb_id, ep, urb.target_ep, urb.ptr, l, USB_ENDPOINT_XFER_BULK, 0);
|
||||
/* g_printf("%s() %d %d", __func__, l, urb.len); */
|
||||
if (l > 0) {
|
||||
urb.len -= l;
|
||||
if (urb.ptr) {
|
||||
urb.ptr += l;
|
||||
}
|
||||
urb.msg = 0;
|
||||
} else {
|
||||
urb.msg = l;
|
||||
urb.len = 0;
|
||||
}
|
||||
|
||||
if (urb.len == 0) {
|
||||
u32 async_mode = get_async_mode();
|
||||
|
||||
if (async_mode == BULK_ASYNC_MODE_EXIT) {
|
||||
usb_sem_post(host_dev);
|
||||
} else if (async_mode == BULK_ASYNC_MODE_SEM_PEND) {
|
||||
if (urb.msg == 0) {
|
||||
usb_sem_post(host_dev);
|
||||
} else {
|
||||
r_printf("usb async error");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
usb_h_ep_read_async(usb_id, ep, urb.target_ep, urb.ptr, urb.len, USB_ENDPOINT_XFER_BULK, 1);
|
||||
}
|
||||
}
|
||||
s32 usb_bulk_only_receive_async(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 devnum = host_dev->private_data.devnum;
|
||||
|
||||
urb.ptr = pBuf;
|
||||
urb.len = len;
|
||||
urb.target_ep = target_ep;
|
||||
|
||||
#ifdef CONFIG_USB_SUPPORT_MRX_TX
|
||||
urb.rxmap = 1 * 1024;
|
||||
#else
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
urb.rxmap = rxmaxp;
|
||||
#else
|
||||
urb.rxmap = 0x40;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
urb.msg = -DEV_ERR_OFFLINE;
|
||||
|
||||
usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, usb_bulk_rx_isr, host_dev);
|
||||
usb_set_intr_rxe(usb_id, host_ep);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_rxfuncaddr(usb_id, host_ep, devnum);
|
||||
#endif
|
||||
|
||||
int ret = usb_h_ep_read_async(usb_id, host_ep, target_ep, urb.ptr, len, USB_ENDPOINT_XFER_BULK, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usb_sem_pend(host_dev, 300);
|
||||
|
||||
usb_clr_intr_rxe(usb_id, host_ep);
|
||||
usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, NULL, host_dev);
|
||||
if (ret) {
|
||||
return -DEV_ERR_TIMEOUT;
|
||||
}
|
||||
return urb.msg ? urb.msg : len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb_bulk_receive_async_no_wait 启动USB Bulk 异步预读
|
||||
* 不用等信号量,启动传输后返回
|
||||
* @param device 设备句柄
|
||||
* @param pBuf 读buffer缓冲区,芯片所有memory都可以
|
||||
* @param len 需要预读的长度
|
||||
*
|
||||
* @return 负数表示失败
|
||||
*/
|
||||
s32 usb_bulk_receive_async_no_wait(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 devnum = host_dev->private_data.devnum;
|
||||
|
||||
set_async_mode(BULK_ASYNC_MODE_SEM_PEND);
|
||||
urb.ptr = pBuf;
|
||||
urb.len = len;
|
||||
urb.target_ep = target_ep;
|
||||
|
||||
#ifdef CONFIG_USB_SUPPORT_MRX_TX
|
||||
urb.rxmap = 1 * 1024;
|
||||
#else
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
urb.rxmap = rxmaxp;
|
||||
#else
|
||||
urb.rxmap = 0x40;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
urb.msg = -DEV_ERR_OFFLINE;
|
||||
|
||||
usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, usb_bulk_rx_isr, host_dev);
|
||||
usb_set_intr_rxe(usb_id, host_ep);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_rxfuncaddr(usb_id, host_ep, devnum);
|
||||
#endif
|
||||
|
||||
int ret = usb_h_ep_read_async(usb_id, host_ep, target_ep, urb.ptr, len, USB_ENDPOINT_XFER_BULK, 1);
|
||||
if (ret < 0) {
|
||||
if (ret == -DEV_ERR_RXSTALL) {
|
||||
ret = usb_clear_feature(host_dev, target_ep | USB_DIR_IN);
|
||||
if (ret == 0) {
|
||||
return -DEV_ERR_RXSTALL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
static s32 _usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len)
|
||||
{
|
||||
#if 0
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
return usb_h_bulk_read(usb_id, host_ep, rxmaxp, target_ep, pBuf, len);
|
||||
#else
|
||||
return usb_bulk_only_receive_async(device, host_ep, rxmaxp, target_ep, pBuf, len);
|
||||
#endif
|
||||
}
|
||||
s32 usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len)
|
||||
{
|
||||
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
int ret = _usb_bulk_only_receive(device, host_ep, rxmaxp, target_ep, pBuf, len);
|
||||
if (ret == -DEV_ERR_RXSTALL) {
|
||||
ret = usb_clear_feature(host_dev, target_ep | USB_DIR_IN);
|
||||
if (ret == 0) {
|
||||
return -DEV_ERR_RXSTALL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static void usb_bulk_tx_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
int l = min(urb.len, urb.txmap);
|
||||
l = usb_h_ep_write_async(usb_id, ep, urb.txmap, urb.target_ep, urb.ptr, l, USB_ENDPOINT_XFER_BULK, 0);
|
||||
|
||||
if (l > 0) {
|
||||
urb.len -= l;
|
||||
urb.ptr += l;
|
||||
urb.msg = 0;
|
||||
} else {
|
||||
urb.msg = l;
|
||||
urb.len = 0;
|
||||
}
|
||||
|
||||
if (urb.len == 0) {
|
||||
if (urb.msg || l == 0) {
|
||||
usb_sem_post(host_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
s32 usb_bulk_only_send_async(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 devnum = host_dev->private_data.devnum;
|
||||
|
||||
urb.target_ep = target_ep;
|
||||
#ifdef CONFIG_USB_SUPPORT_MRX_TX
|
||||
urb.txmap = 8 * 1024;
|
||||
#else
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
urb.txmap = rxmaxp;
|
||||
#else
|
||||
urb.txmap = 0x40;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
urb.msg = -DEV_ERR_OFFLINE;
|
||||
urb.len = len - min(len, urb.txmap);
|
||||
urb.ptr = (u8 *)pBuf + min(len, urb.txmap);
|
||||
|
||||
|
||||
usb_h_set_ep_isr(host_dev, host_ep, usb_bulk_tx_isr, host_dev);
|
||||
usb_set_intr_txe(usb_id, host_ep);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_txfuncaddr(usb_id, host_ep, devnum);
|
||||
#endif
|
||||
|
||||
int ret = usb_h_ep_write_async(usb_id, host_ep, txmaxp, target_ep, pBuf, min(len, urb.txmap), USB_ENDPOINT_XFER_BULK, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = usb_sem_pend(host_dev, 250);
|
||||
|
||||
usb_clr_intr_txe(usb_id, host_ep);
|
||||
usb_h_set_ep_isr(host_dev, host_ep, NULL, host_dev);
|
||||
|
||||
if (ret) {
|
||||
r_printf("ret %d", ret);
|
||||
return -DEV_ERR_TIMEOUT;
|
||||
}
|
||||
/* g_printf("%s() %d %d", __func__, urb.len, urb.msg); */
|
||||
return urb.msg ? urb.msg : len;
|
||||
}
|
||||
/**
|
||||
* @brief usb_bulk_only_send
|
||||
*
|
||||
* @param device
|
||||
* @param host_ep 主机的端点号
|
||||
* @param target_ep 目标设备的端点号
|
||||
* @param pBuf
|
||||
* @param len
|
||||
*
|
||||
* @return 负数失败
|
||||
* 正数发送的字节数
|
||||
*/
|
||||
static s32 _usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len)
|
||||
{
|
||||
#if 0
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
return usb_h_bulk_write(usb_id, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
#elif 0
|
||||
if (len < 512) {
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
const usb_dev usb_id = host_device2id(host_dev);
|
||||
return usb_h_bulk_write(usb_id, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
} else {
|
||||
return usb_bulk_only_send_async(device, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
}
|
||||
#else
|
||||
return usb_bulk_only_send_async(device, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
#endif
|
||||
}
|
||||
s32 usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len)
|
||||
{
|
||||
struct usb_host_device *host_dev = device_to_usbdev(device);
|
||||
int ret = _usb_bulk_only_send(device, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
|
||||
if (ret == -DEV_ERR_TXSTALL) {
|
||||
ret = usb_clear_feature(host_dev, target_ep);
|
||||
if (ret == 0) {
|
||||
return -DEV_ERR_TXSTALL;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,120 @@
|
||||
/**@file usb_bulk_transfer.h
|
||||
* @brief usb_bulk_transfer批量传输头文件
|
||||
* @details 功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-8-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC695N
|
||||
* SDK版本:AC695N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-8-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __USB_BULK_TRANSFER_H__
|
||||
#define __USB_BULK_TRANSFER_H__
|
||||
#include "typedef.h"
|
||||
#include "device/device.h"
|
||||
|
||||
|
||||
/**@brief 批量传输只读取(异步模式)
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] host_ep 主机端点号
|
||||
* @param[in] rxmaxp 接收端点最大包长
|
||||
* @param[in] target_ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_receive_async(device, host_ep, rxmaxp, target_ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_only_receive_async(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len);
|
||||
|
||||
/**@brief 批量传输只读取(普通模式)
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] host_ep 主机端点号
|
||||
* @param[in] rxmaxp 接收端点最大包长
|
||||
* @param[in] ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_receive(device, host_ep, rxmaxp, ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 ep, u8 *pBuf, u32 len);
|
||||
|
||||
/**@brief 批量传输只发送(异步模式)
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] host_ep 主机端点号
|
||||
* @param[in] txmaxp 发送端点最大包长
|
||||
* @param[in] target_ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_send_async(device, host_ep, txmaxp, target_ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_only_send_async(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len);
|
||||
|
||||
/**@brief 批量传输只发送(普通模式)
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] ep 主机端点号
|
||||
* @param[in] txmaxp 发送端点最大包长
|
||||
* @param[in] ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_send(device, host_ep, txmaxp, ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 ep, const u8 *pBuf, u32 len);
|
||||
|
||||
/**@brief 获取异步模式当前状态
|
||||
* @param[in] 空
|
||||
* @return 当前状态
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_async_mode();
|
||||
* @encode
|
||||
*/
|
||||
u8 get_async_mode(void);
|
||||
|
||||
/**@brief 设置异步模式
|
||||
* @param[in] mode 需要设置的模式
|
||||
* @return 空
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_async_mode(BULK_ASYNC_MODE_EXIT);退出异步模式
|
||||
* @encode
|
||||
*/
|
||||
void set_async_mode(u8 mode);
|
||||
|
||||
/**@brief 批量传输异步模式读取并且不等待
|
||||
* @param[in] device定义的结构体指针
|
||||
* @param[in] ep 主机端点号
|
||||
* @param[in] rxmaxp 发送端点最大包长
|
||||
* @param[in] target_ep 目标端点号
|
||||
* @param[in] *pBuf BUFFER指针
|
||||
* @param[in] len 数据长度
|
||||
* @return
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_bulk_only_send(device, host_ep, rxmaxp, ep, pBuf, len);
|
||||
* @encode
|
||||
*/
|
||||
s32 usb_bulk_receive_async_no_wait(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len);
|
||||
#endif
|
||||
@@ -0,0 +1,637 @@
|
||||
/**
|
||||
* @file usb_ctrl_transfer.c
|
||||
* @brief usb 控制传输接口
|
||||
* @author chenrixin@zh-jieli.com
|
||||
* @version 1.00
|
||||
* @date 2017-02-09
|
||||
*/
|
||||
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "app_config.h"
|
||||
#include "device_drive.h"
|
||||
#include "gpio.h"
|
||||
#include "usb/scsi.h"
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#if USB_HOST_ENABLE
|
||||
|
||||
_WEAK_
|
||||
void usb_dis_ep0_txdly(const usb_dev id)
|
||||
{
|
||||
}
|
||||
static void ep0_h_isr(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
usb_sem_post(host_dev);
|
||||
}
|
||||
/**
|
||||
* @brief usb_ctlXfer
|
||||
*
|
||||
* @param host_dev
|
||||
* @param urb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static int usb_ctlXfer(struct usb_host_device *host_dev, struct ctlXfer *urb)
|
||||
{
|
||||
u32 ret = DEV_ERR_NONE;
|
||||
u8 reg = 0;
|
||||
u32 data_len;
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
u8 devnum = host_dev->private_data.devnum;
|
||||
u32 max_packet_size = host_dev->private_data.ep0_max_packet_size;
|
||||
|
||||
usb_write_faddr(usb_id, devnum);
|
||||
#ifdef USB_HW_20
|
||||
usb_write_txfuncaddr(usb_id, 0, devnum);
|
||||
#endif
|
||||
|
||||
switch (urb->stage) {
|
||||
case USB_PID_SETUP :
|
||||
usb_write_ep0(usb_id, (u8 *)&urb->setup, 8);
|
||||
reg = CSR0H_SetupPkt | CSR0H_TxPktRdy;
|
||||
break;
|
||||
case USB_PID_IN :
|
||||
if (urb->setup.wLength) {
|
||||
reg = CSR0H_ReqPkt;
|
||||
} else {
|
||||
reg = CSR0H_StatusPkt | CSR0H_ReqPkt;
|
||||
}
|
||||
break;
|
||||
case USB_PID_OUT:
|
||||
if (urb->setup.wLength) {
|
||||
data_len = min(urb->setup.wLength, max_packet_size);
|
||||
reg = CSR0H_TxPktRdy;
|
||||
usb_write_ep0(usb_id, urb->buffer, data_len);
|
||||
urb->setup.wLength -= data_len;
|
||||
urb->buffer += data_len;
|
||||
} else {
|
||||
reg = CSR0H_StatusPkt | CSR0H_TxPktRdy;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
#if USB_HOST_ASYNC
|
||||
//config ep0 callback fun
|
||||
usb_h_set_ep_isr(host_dev, 0, ep0_h_isr, host_dev);
|
||||
usb_set_intr_txe(usb_id, 0);
|
||||
#endif
|
||||
|
||||
#ifdef USB_HW_20
|
||||
usb_write_csr0(usb_id, reg | CSR0H_DISPING);
|
||||
#else
|
||||
usb_write_csr0(usb_id, reg);
|
||||
#endif
|
||||
|
||||
u32 st = 0;
|
||||
u32 ot = usb_get_jiffies() + 500;
|
||||
while (1) {
|
||||
if (usb_host_timeout(ot)) {
|
||||
log_error("time out %x\n", reg);
|
||||
ret = -DEV_ERR_TIMEOUT;
|
||||
goto __exit;
|
||||
}
|
||||
if (usb_h_dev_status(usb_id)) {
|
||||
st ++;
|
||||
} else {
|
||||
st = 0;
|
||||
}
|
||||
if (((usb_read_devctl(usb_id) & BIT(2)) == 0) || (st > 1000)) {
|
||||
log_error("usb%d_offline\n", usb_id);
|
||||
ret = -DEV_ERR_OFFLINE;
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
#if USB_HOST_ASYNC
|
||||
ret = usb_sem_pend(host_dev, 250); //wait isr
|
||||
if (ret) {
|
||||
log_error("usb%d_offline\n", usb_id);
|
||||
ret = -DEV_ERR_OFFLINE;
|
||||
goto __exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
reg = usb_read_csr0(usb_id);
|
||||
if (reg & CSR0H_RxStall) {
|
||||
log_error(" rxStall CSR0:0x%x", reg);
|
||||
ret = -DEV_ERR_CONTROL_STALL;
|
||||
goto __exit;
|
||||
}
|
||||
if (reg & CSR0H_Error) {
|
||||
log_error(" Error CSR0:0x%x", reg);
|
||||
usb_write_csr0(usb_id, 0);
|
||||
ret = -DEV_ERR_CONTROL;
|
||||
goto __exit;
|
||||
}
|
||||
if (USB_PID_IN == urb->stage) {
|
||||
|
||||
if (reg & CSR0H_RxPktRdy) {
|
||||
data_len = usb_read_count0(usb_id);
|
||||
data_len = min(data_len, urb->setup.wLength);
|
||||
usb_read_ep0(usb_id, urb->buffer, data_len);;
|
||||
urb->buffer += data_len;
|
||||
urb->setup.wLength -= data_len;
|
||||
if (data_len < max_packet_size) {
|
||||
urb->setup.wLength = 0;
|
||||
}
|
||||
if (urb->setup.wLength) {
|
||||
#ifdef USB_HW_20
|
||||
usb_write_csr0(usb_id, CSR0H_ReqPkt | CSR0H_DISPING);
|
||||
#else
|
||||
usb_write_csr0(usb_id, CSR0H_ReqPkt);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef USB_HW_20
|
||||
usb_write_csr0(usb_id, CSR0H_DISPING);
|
||||
#else
|
||||
usb_write_csr0(usb_id, 0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(reg & CSR0H_TxPktRdy)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
__exit:
|
||||
usb_clr_intr_txe(usb_id, 0);
|
||||
usb_dis_ep0_txdly(usb_id);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @brief usb_control_transfers
|
||||
*
|
||||
* @param struct host_dev
|
||||
* @param urb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static int usb_control_transfers(struct usb_host_device *host_dev, struct ctlXfer *urb)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
int res;
|
||||
/*SETUP*/
|
||||
|
||||
urb->stage = USB_PID_SETUP; //SETUP transaction
|
||||
|
||||
res = usb_ctlXfer(host_dev, urb);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/*IN or OUT*/
|
||||
urb->stage = USB_PID_IN;
|
||||
|
||||
|
||||
while (urb->setup.wLength) {
|
||||
if (urb->setup.bRequestType & USB_DIR_IN) { //Request Direction
|
||||
urb->stage = USB_PID_IN; //IN transaction
|
||||
|
||||
res = usb_ctlXfer(host_dev, urb);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
urb->stage = USB_PID_OUT;
|
||||
} else {
|
||||
urb->stage = USB_PID_OUT; //OUT transaction
|
||||
|
||||
res = usb_ctlXfer(host_dev, urb);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
urb->stage = USB_PID_IN;
|
||||
}
|
||||
}
|
||||
|
||||
res = usb_ctlXfer(host_dev, urb);
|
||||
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb_control_msg
|
||||
*
|
||||
* @param host_dev
|
||||
* @param request
|
||||
* @param requesttype
|
||||
* @param value
|
||||
* @param index
|
||||
* @param data
|
||||
* @param size
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int usb_control_msg(struct usb_host_device *host_dev,
|
||||
u8 request, u8 requesttype,
|
||||
u16 value, u16 index,
|
||||
void *data, u16 size)
|
||||
{
|
||||
struct ctlXfer urb;
|
||||
urb.setup.bRequestType = requesttype;
|
||||
urb.setup.bRequest = request;
|
||||
urb.setup.wValue = cpu_to_le16(value);
|
||||
urb.setup.wIndex = cpu_to_le16(index);
|
||||
urb.setup.wLength = cpu_to_le16(size);
|
||||
urb.buffer = data;
|
||||
|
||||
return usb_control_transfers(host_dev, &urb);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usb_clear_feature
|
||||
*
|
||||
* @param host_dev
|
||||
* @param ep
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int usb_clear_feature(struct usb_host_device *host_dev, u32 ep)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, ep, NULL, 0);
|
||||
}
|
||||
|
||||
int set_address(struct usb_host_device *host_dev, u8 devnum)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_SET_ADDRESS, 0, devnum, 0, NULL, 0);
|
||||
}
|
||||
|
||||
int usb_get_device_descriptor(struct usb_host_device *host_dev, struct usb_device_descriptor *desc)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_DEVICE << 8),
|
||||
0,
|
||||
desc,
|
||||
USB_DT_DEVICE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
int usb_get_string_descriptor(struct usb_host_device *host_dev, struct usb_device_descriptor *desc)
|
||||
{
|
||||
int ret = DEV_ERR_NONE;
|
||||
#if 0
|
||||
struct usb_private_data *private_data = host_dev->private_data ;
|
||||
/**********get string language*********/
|
||||
u8 buf[16];
|
||||
memset(buf, 0x0, sizeof(buf));
|
||||
ret = usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_STRING << 8),
|
||||
0,
|
||||
desc,
|
||||
sizeof(buf)
|
||||
);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(&private_data->language, buf + 2, sizeof(private_data->language));
|
||||
|
||||
/**********get manufacturer string**********/
|
||||
memset(private_data->manufacturer, 0x0, sizeof(private_data->manufacturer));
|
||||
if (desc->iManufacturer) {
|
||||
ret = usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_STRING << 8) | desc->iManufacturer,
|
||||
0,
|
||||
private_data->manufacturer,
|
||||
sizeof(private_data->manufacturer)
|
||||
);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
/**********get product string**********/
|
||||
memset(private_data->product, 0x0, sizeof(private_data->product));
|
||||
if (desc->iProduct) {
|
||||
ret = usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_STRING << 8) | desc->iProduct,
|
||||
0,
|
||||
private_data->product,
|
||||
sizeof(private_data->product)
|
||||
);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int set_configuration(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0);
|
||||
}
|
||||
int set_configuration_add_value(struct usb_host_device *host_dev, u16 value)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_SET_CONFIGURATION, 0, value, 0, NULL, 0);
|
||||
}
|
||||
int get_config_descriptor(struct usb_host_device *host_dev, void *cfg_desc, u32 len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_CONFIG << 8),
|
||||
0,
|
||||
cfg_desc,
|
||||
len);
|
||||
}
|
||||
|
||||
int get_config_descriptor_add_value_l(struct usb_host_device *host_dev, void *cfg_desc, u32 len, u8 value_l)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_CONFIG << 8) | value_l,
|
||||
0,
|
||||
cfg_desc,
|
||||
len);
|
||||
}
|
||||
|
||||
|
||||
int get_msd_max_lun(struct usb_host_device *host_dev, void *lun)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_MSD_MAX_LUN,
|
||||
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0,
|
||||
0,
|
||||
lun,
|
||||
1);
|
||||
}
|
||||
int set_msd_reset(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
0xff,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
int hid_set_idle(struct usb_host_device *host_dev, u32 id)
|
||||
{
|
||||
return usb_control_msg(host_dev, 0x0a, 0x21, 0, id << 8, NULL, 0);
|
||||
}
|
||||
int hid_get_report(struct usb_host_device *host_dev, u8 *report, u8 report_id, u16 report_len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN | USB_RECIP_INTERFACE,
|
||||
0x2200,
|
||||
report_id,
|
||||
report,
|
||||
report_len);
|
||||
}
|
||||
int hid_set_output_report(struct usb_host_device *host_dev, u8 *report, u8 report_id, u8 report_len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
0x09,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0x0201,
|
||||
report_id,
|
||||
report,
|
||||
report_len);
|
||||
}
|
||||
int usb_set_remote_wakeup(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev, USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
|
||||
USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0);
|
||||
}
|
||||
int get_device_status(struct usb_host_device *host_dev)
|
||||
{
|
||||
u16 status;
|
||||
return usb_control_msg(host_dev, USB_REQ_GET_STATUS, USB_DIR_IN, 0, 0, (u8 *)&status, 2);
|
||||
}
|
||||
int usb_get_device_qualifier(struct usb_host_device *host_dev, u8 *buffer)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_GET_DESCRIPTOR,
|
||||
USB_DIR_IN,
|
||||
(USB_DT_DEVICE_QUALIFIER << 8),
|
||||
0,
|
||||
buffer,
|
||||
0x0a);
|
||||
|
||||
}
|
||||
#define AOA_CMD51 0x33
|
||||
#define AOA_CMD52 0x34
|
||||
#define AOA_CMD53 0x35
|
||||
|
||||
|
||||
|
||||
|
||||
int usb_get_aoa_version(struct usb_host_device *host_dev, u16 *version)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
AOA_CMD51,
|
||||
USB_DIR_IN | USB_TYPE_VENDOR,
|
||||
0,
|
||||
0,
|
||||
version,
|
||||
2);
|
||||
}
|
||||
int usb_set_credentials(struct usb_host_device *host_dev, const char *string, int index)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
AOA_CMD52,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0,
|
||||
index,
|
||||
(u8 *)string,
|
||||
strlen(string));
|
||||
}
|
||||
int usb_switch2aoa(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
AOA_CMD53,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
int usb_switch2slave(struct usb_host_device *host_dev)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
0x51,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
/* Control request for registering a HID device.
|
||||
* Upon registering, a unique ID is sent by the accessory in the
|
||||
* value parameter. This ID will be used for future commands for
|
||||
* the device
|
||||
*
|
||||
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||||
* request: ACCESSORY_REGISTER_HID_DEVICE
|
||||
* value: Accessory assigned ID for the HID device
|
||||
* index: total length of the HID report descriptor
|
||||
* data none
|
||||
*/
|
||||
#define ACCESSORY_REGISTER_HID 54
|
||||
int usb_aoa_register_hid(struct usb_host_device *host_dev, u16 value, u16 index)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
ACCESSORY_REGISTER_HID,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
value,
|
||||
index,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
/* Control request for unregistering a HID device.
|
||||
*
|
||||
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||||
* request: ACCESSORY_REGISTER_HID
|
||||
* value: Accessory assigned ID for the HID device
|
||||
* index: 0
|
||||
* data none
|
||||
*/
|
||||
#define ACCESSORY_UNREGISTER_HID 55
|
||||
int usb_aoa_unregister_hid(struct usb_host_device *host_dev, u16 value)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
ACCESSORY_UNREGISTER_HID,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
value,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
/* Control request for sending the HID report descriptor.
|
||||
* If the HID descriptor is longer than the endpoint zero max packet size,
|
||||
* the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC
|
||||
* commands. The data for the descriptor must be sent sequentially
|
||||
* if multiple packets are needed.
|
||||
*
|
||||
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||||
* request: ACCESSORY_SET_HID_REPORT_DESC
|
||||
* value: Accessory assigned ID for the HID device
|
||||
* index: offset of data in descriptor
|
||||
* (needed when HID descriptor is too big for one packet)
|
||||
* data the HID report descriptor
|
||||
*/
|
||||
#define ACCESSORY_SET_HID_REPORT_DESC 56
|
||||
int usb_aoa_set_hid_report_desc(struct usb_host_device *host_dev, u16 value, u16 offset, const char *pbuf, u32 len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
ACCESSORY_SET_HID_REPORT_DESC,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
value,
|
||||
offset,
|
||||
(u8 *)pbuf,
|
||||
len);
|
||||
}
|
||||
|
||||
/* Control request for sending HID events.
|
||||
*
|
||||
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
|
||||
* request: ACCESSORY_SEND_HID_EVENT
|
||||
* value: Accessory assigned ID for the HID device
|
||||
* index: 0
|
||||
* data the HID report for the event
|
||||
*/
|
||||
#define ACCESSORY_SEND_HID_EVENT 57
|
||||
int usb_aoa_send_hid_event(struct usb_host_device *host_dev, u16 value, const u8 *pbuf, u32 len)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
ACCESSORY_SEND_HID_EVENT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
value,
|
||||
0,
|
||||
(u8 *)pbuf,
|
||||
len);
|
||||
}
|
||||
int get_ms_extended_compat_id(struct usb_host_device *host_dev, u8 *buffer)
|
||||
{
|
||||
return usb_control_msg(host_dev,
|
||||
0x01,
|
||||
USB_DIR_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR,
|
||||
0x0000,
|
||||
4,
|
||||
buffer,
|
||||
0x28);
|
||||
}
|
||||
|
||||
|
||||
int usb_set_interface(struct usb_host_device *host_dev, u8 interface, u8 alternateSetting)
|
||||
{
|
||||
log_info("%s Set Interface:%d AlternateSetting:%d", __func__, interface, alternateSetting);
|
||||
return usb_control_msg(host_dev,
|
||||
USB_REQ_SET_INTERFACE,
|
||||
USB_RECIP_INTERFACE,
|
||||
alternateSetting,
|
||||
interface,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
}
|
||||
|
||||
int usb_audio_sampling_frequency_control(struct usb_host_device *host_dev, u32 ep, u32 sampe_rate)
|
||||
{
|
||||
log_info("%s ep:%d sampe_rate:%d", __func__, ep, sampe_rate);
|
||||
return usb_control_msg(host_dev,
|
||||
1,
|
||||
USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
|
||||
0x0100,
|
||||
ep,
|
||||
&sampe_rate,
|
||||
3);
|
||||
}
|
||||
int usb_audio_volume_control(struct usb_host_device *host_dev, u8 feature_id, u8 channel_num, u16 volume)
|
||||
{
|
||||
log_info("%s featureID:%d vol:%x", __func__, feature_id, volume);
|
||||
return usb_control_msg(host_dev,
|
||||
1,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
(0x02 << 8) | channel_num,
|
||||
feature_id << 8,
|
||||
&volume,
|
||||
2);
|
||||
}
|
||||
int usb_audio_mute_control(struct usb_host_device *host_dev, u8 feature_id, u8 mute)
|
||||
{
|
||||
log_info("%s featureID:%d mute:%d", __func__, feature_id, mute);
|
||||
return usb_control_msg(host_dev,
|
||||
1,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
0x0100,
|
||||
feature_id << 8,
|
||||
&mute,
|
||||
1);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,384 @@
|
||||
/**@file usb_ctrl_transfer.h
|
||||
* @brief usb_ctrl_transfer控制传输头文件
|
||||
* @details 功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-8-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC695N
|
||||
* SDK版本:AC695N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-8-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __USB_CTRL_TRANSFER_H__
|
||||
#define __USB_CTRL_TRANSFER_H__
|
||||
|
||||
#include "usb/ch9.h"
|
||||
#include "usb/usb_phy.h"
|
||||
#include "device/device.h"
|
||||
#include "usb_config.h"
|
||||
|
||||
|
||||
/*
|
||||
* USB Packet IDs (PIDs)
|
||||
*/
|
||||
#define USB_PID_EXT 0xf0 /* USB 2.0 LPM ECN */
|
||||
#define USB_PID_OUT 0xe1
|
||||
#define USB_PID_ACK 0xd2
|
||||
#define USB_PID_DATA0 0xc3
|
||||
#define USB_PID_PING 0xb4 /* USB 2.0 */
|
||||
#define USB_PID_SOF 0xa5
|
||||
#define USB_PID_NYET 0x96 /* USB 2.0 */
|
||||
#define USB_PID_DATA2 0x87 /* USB 2.0 */
|
||||
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
|
||||
#define USB_PID_IN 0x69
|
||||
#define USB_PID_NAK 0x5a
|
||||
#define USB_PID_DATA1 0x4b
|
||||
#define USB_PID_PREAMBLE 0x3c /* Token mode */
|
||||
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
|
||||
#define USB_PID_SETUP 0x2d
|
||||
#define USB_PID_STALL 0x1e
|
||||
#define USB_PID_MDATA 0x0f /* USB 2.0 */
|
||||
|
||||
|
||||
|
||||
struct ctlXfer {
|
||||
struct usb_ctrlrequest setup; ///<控制请求
|
||||
void *buffer; ///<控制请求的data
|
||||
u8 stage; ///<当前状态
|
||||
};
|
||||
|
||||
int usb_control_msg(struct usb_host_device *host_dev,
|
||||
u8 request, u8 requesttype,
|
||||
u16 value, u16 index,
|
||||
void *data, u16 size);
|
||||
|
||||
/**@brief USB清除或禁用特定的特性
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] ep 端点号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_clear_feature(host_dev , ep);
|
||||
* @encode
|
||||
*/
|
||||
int usb_clear_feature(struct usb_host_device *usb_dev, u32 ep);
|
||||
|
||||
/**@brief USB设置地址
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] devnum 设备编号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_address(host_dev , ep);
|
||||
* @encode
|
||||
*/
|
||||
int set_address(struct usb_host_device *usb_dev, u8 devnum);
|
||||
|
||||
/**@brief USB获取设备描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] usb_device_descriptor定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_get_device_descriptor(host_dev , device_desc);
|
||||
* @encode
|
||||
*/
|
||||
int usb_get_device_descriptor(struct usb_host_device *usb_dev, struct usb_device_descriptor *desc);
|
||||
|
||||
/**@brief USB获取字符串描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] usb_device_descriptor定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_get_string_descriptor(host_dev , device_desc);
|
||||
* @encode
|
||||
*/
|
||||
int usb_get_string_descriptor(struct usb_host_device *usb_dev, struct usb_device_descriptor *desc);
|
||||
|
||||
/**@brief USB设置相关配置
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_configuration(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int set_configuration(struct usb_host_device *usb_dev);
|
||||
|
||||
/**@brief USB设置相关配置,添加相关参数
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] value 当前请求的参数
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_configuration_add_value(host_dev , value);
|
||||
* @encode
|
||||
*/
|
||||
int set_configuration_add_value(struct usb_host_device *host_dev, u16 value);
|
||||
|
||||
/**@brief USB获取配置描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] cfg_desc 自定义的配置描述符指针
|
||||
* @param[in] len 长度
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_config_descriptor(host_dev , cfg_desc , len);
|
||||
* @encode
|
||||
*/
|
||||
int get_config_descriptor(struct usb_host_device *usb_dev, void *cfg_desc, u32 len);
|
||||
|
||||
/**@brief USB获取配置描述符,添加相关参数
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] cfg_desc 自定义的配置描述符指针
|
||||
* @param[in] len 长度
|
||||
* @param[in] value_l 请求的参数
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_config_descriptor_add_value_l(host_dev , cfg_desc , len , value_l);
|
||||
* @encode
|
||||
*/
|
||||
int get_config_descriptor_add_value_l(struct usb_host_device *host_dev, void *cfg_desc, u32 len, u8 value_l);
|
||||
|
||||
/**@brief USB获取大容量存储设备的最大逻辑单元号
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] lun 逻辑单元号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_msd_max_lun(host_dev , lun);
|
||||
* @encode
|
||||
*/
|
||||
int get_msd_max_lun(struct usb_host_device *usb_dev, void *lun);
|
||||
|
||||
/**@brief USB设置大容量存储设备复位
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* set_msd_reset(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int set_msd_reset(struct usb_host_device *usb_dev);
|
||||
|
||||
/**@brief hid设置为空闲模式
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] id 指定接口或端点号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* hid_set_idle(host_dev , id);
|
||||
* @encode
|
||||
*/
|
||||
int hid_set_idle(struct usb_host_device *usb_dev, u32 id);
|
||||
|
||||
/**@brief hid获取报告描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] report 自定义报告指针,指向报告内容
|
||||
* @param[in] report_id 报告描述符id号
|
||||
* @param[in] report_len 报告描述符长度
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* hid_get_report(host_dev , report , report_id , report_len);
|
||||
* @encode
|
||||
*/
|
||||
int hid_get_report(struct usb_host_device *usb_dev, u8 *report, u8 report_id, u16 report_len);
|
||||
|
||||
/**@brief hid设置输出报告描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] report 自定义报告指针,指向报告内容
|
||||
* @param[in] report_id
|
||||
* @param[in] report_len
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* hid_set_output_report(host_dev , report , report_id , report_len);
|
||||
* @encode
|
||||
*/
|
||||
int hid_set_output_report(struct usb_host_device *usb_dev, u8 *report, u8 report_id, u8 report_len);
|
||||
|
||||
/**@brief USB设置远程唤醒
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_set_remote_wakeup(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int usb_set_remote_wakeup(struct usb_host_device *usb_dev);
|
||||
|
||||
/**@brief USB获取设备状态
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_device_status(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int get_device_status(struct usb_host_device *usb_dev);
|
||||
|
||||
/**@brief USB获取设备限定描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] BUFFER 自定义的指针,指向限定描述符内容
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_get_device_qualifier(host_dev , buffer);
|
||||
* @encode
|
||||
*/
|
||||
int usb_get_device_qualifier(struct usb_host_device *usb_dev, u8 *buffer);
|
||||
|
||||
/**@brief USB获取安卓aoa协议版本
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] version 自定义的指针,指向版本内容
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_get_aoa_version(host_dev , version);
|
||||
* @encode
|
||||
*/
|
||||
int usb_get_aoa_version(struct usb_host_device *host_dev, u16 *version);
|
||||
|
||||
/**@brief USB设置证书信息
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] string 字符串指针,指向证书内容
|
||||
* @param[in] index 传递的参数
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_set_credentials(host_dev , string , index);
|
||||
* @encode
|
||||
*/
|
||||
int usb_set_credentials(struct usb_host_device *host_dev, const char *string, int index);
|
||||
|
||||
/**@brief USB设置aoa开关
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_switch2aoa(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int usb_switch2aoa(struct usb_host_device *host_dev);
|
||||
|
||||
/**@brief USB设置从机模式开关
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_switch2slave(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int usb_switch2slave(struct usb_host_device *host_dev);
|
||||
|
||||
/**@brief USB hid设备注册
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] value 请求的参数
|
||||
* @param[in] index 传递的参数
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_aoa_register_hid(host_dev , value , index);
|
||||
* @encode
|
||||
*/
|
||||
int usb_aoa_register_hid(struct usb_host_device *host_dev, u16 value, u16 index);
|
||||
|
||||
/**@brief USB设置hid报告描述符
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] value 请求的参数
|
||||
* @param[in] offset 偏移量参数
|
||||
* @param[in] pbuf 存放数据的BUFFER指针
|
||||
* @param[in] len 长度
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_aoa_set_hid_report_desc(host_dev , value , offset , *pbuf , len);
|
||||
* @encode
|
||||
*/
|
||||
int usb_aoa_set_hid_report_desc(struct usb_host_device *host_dev, u16 value, u16 offset, const char *pbuf, u32 len);
|
||||
|
||||
/**@brief USB发送hid事件
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] value 请求的参数
|
||||
* @param[in] pbuf 存放数据的BUFFER指针
|
||||
* @param[in] len 长度
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_aoa_send_hid_event(host_dev , value , *pbuf , len);
|
||||
* @encode
|
||||
*/
|
||||
int usb_aoa_send_hid_event(struct usb_host_device *host_dev, u16 value, const u8 *pbuf, u32 len);
|
||||
|
||||
/**@brief 获取扩展的大容量存储设备(可兼容)id 号
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] BUFFER 存放数据的BUFFER
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* get_ms_extended_compat_id(host_dev , value , *pbuf , len);
|
||||
* @encode
|
||||
*/
|
||||
int get_ms_extended_compat_id(struct usb_host_device *host_dev, u8 *buffer);
|
||||
|
||||
/**@brief USB设置接口
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] interface 接口参数(请求的参数)
|
||||
* @param[in] alternateSetting 交替设置(传递的参数)
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_set_interface(host_dev , interface , alternateSetting);
|
||||
* @encode
|
||||
*/
|
||||
int usb_set_interface(struct usb_host_device *host_dev, u8 interface, u8 alternateSetting);
|
||||
|
||||
/**@brief USB音频采样频率控制
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] ep 端点号
|
||||
* @param[in] samp_rate 采样率
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_audio_sampling_frequency_control(host_dev , ep , sampe_rate);
|
||||
* @encode
|
||||
*/
|
||||
int usb_audio_sampling_frequency_control(struct usb_host_device *host_dev, u32 ep, u32 sampe_rate);
|
||||
|
||||
/**@brief USB音频音量控制
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] feature_id 特征值id号(端点或接口的id)(传递的参数)
|
||||
* @param[in] channel_num 通道编号(请求的参数)
|
||||
* @paeam[in] volume 音量
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_audio_volume_control(host_dev , feature_id , channel_num , volume);
|
||||
* @encode
|
||||
*/
|
||||
int usb_audio_volume_control(struct usb_host_device *host_dev, u8 feature_id, u8 channel_num, u16 volume);
|
||||
|
||||
/**@brief USB音频静音控制
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] feature_id 特征值id号(端点或接口的id)(传递的参数)
|
||||
* @param[in] mute 静音信号(静音标志)
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_audio_mute_control(host_dev , feature_id , channel_num , volume);
|
||||
* @encode
|
||||
*/
|
||||
int usb_audio_mute_control(struct usb_host_device *host_dev, u8 feature_id, u8 mute);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,353 @@
|
||||
/**
|
||||
* USB HID Keyboard scan codes as per USB spec 1.11
|
||||
* plus some additional codes
|
||||
*
|
||||
* Created by MightyPork, 2016
|
||||
* Public domain
|
||||
*
|
||||
* Adapted from:
|
||||
* https://source.android.com/devices/input/keyboard-devices.html
|
||||
*/
|
||||
|
||||
#ifndef USB_HID_KEYS
|
||||
#define USB_HID_KEYS
|
||||
|
||||
struct keyboard_data_t {
|
||||
u8 fun_key;
|
||||
u8 res;
|
||||
u8 Keypad[6];
|
||||
} _GNU_PACKED_ ;
|
||||
|
||||
struct mouse_data_t {
|
||||
u8 btn;
|
||||
s16 x;
|
||||
s16 y;
|
||||
s8 wheel;
|
||||
s8 ac_pan;
|
||||
} _GNU_PACKED_ ;
|
||||
struct point_t {
|
||||
u8 tip_switch: 2;
|
||||
/* u8 in_range: 1; */
|
||||
u8 res: 2;
|
||||
u8 cid: 4;
|
||||
s16 x;
|
||||
s16 y;
|
||||
} _GNU_PACKED_ ;
|
||||
|
||||
struct touch_screen_t {
|
||||
struct point_t p[3];
|
||||
} _GNU_PACKED_;
|
||||
|
||||
struct mouse_point_t {
|
||||
u8 btn;
|
||||
s8 x;
|
||||
s8 y;
|
||||
s8 wheel;
|
||||
} _GNU_PACKED_;
|
||||
/**
|
||||
* Modifier masks - used for the first byte in the HID report.
|
||||
* NOTE: The second byte in the report is reserved, 0x00
|
||||
*/
|
||||
#define _KEY_MOD_LCTRL 0x01
|
||||
#define _KEY_MOD_LSHIFT 0x02
|
||||
#define _KEY_MOD_LALT 0x04
|
||||
#define _KEY_MOD_LMETA 0x08
|
||||
#define _KEY_MOD_RCTRL 0x10
|
||||
#define _KEY_MOD_RSHIFT 0x20
|
||||
#define _KEY_MOD_RALT 0x40
|
||||
#define _KEY_MOD_RMETA 0x80
|
||||
|
||||
/**
|
||||
* Scan codes - last N slots in the HID report (usually 6).
|
||||
* 0x00 if no key pressed.
|
||||
*
|
||||
* If more than N keys are pressed, the HID reports
|
||||
* KEY_ERR_OVF in all slots to indicate this condition.
|
||||
*/
|
||||
|
||||
#define _KEY_NONE 0x00 // No key pressed
|
||||
#define _KEY_ERR_OVF 0x01 // Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key")
|
||||
// 0x02 // Keyboard POST Fail
|
||||
// 0x03 // Keyboard Error Undefined
|
||||
#define _KEY_A 0x04 // Keyboard a and A
|
||||
#define _KEY_B 0x05 // Keyboard b and B
|
||||
#define _KEY_C 0x06 // Keyboard c and C
|
||||
#define _KEY_D 0x07 // Keyboard d and D
|
||||
#define _KEY_E 0x08 // Keyboard e and E
|
||||
#define _KEY_F 0x09 // Keyboard f and F
|
||||
#define _KEY_G 0x0a // Keyboard g and G
|
||||
#define _KEY_H 0x0b // Keyboard h and H
|
||||
#define _KEY_I 0x0c // Keyboard i and I
|
||||
#define _KEY_J 0x0d // Keyboard j and J
|
||||
#define _KEY_K 0x0e // Keyboard k and K
|
||||
#define _KEY_L 0x0f // Keyboard l and L
|
||||
#define _KEY_M 0x10 // Keyboard m and M
|
||||
#define _KEY_N 0x11 // Keyboard n and N
|
||||
#define _KEY_O 0x12 // Keyboard o and O
|
||||
#define _KEY_P 0x13 // Keyboard p and P
|
||||
#define _KEY_Q 0x14 // Keyboard q and Q
|
||||
#define _KEY_R 0x15 // Keyboard r and R
|
||||
#define _KEY_S 0x16 // Keyboard s and S
|
||||
#define _KEY_T 0x17 // Keyboard t and T
|
||||
#define _KEY_U 0x18 // Keyboard u and U
|
||||
#define _KEY_V 0x19 // Keyboard v and V
|
||||
#define _KEY_W 0x1a // Keyboard w and W
|
||||
#define _KEY_X 0x1b // Keyboard x and X
|
||||
#define _KEY_Y 0x1c // Keyboard y and Y
|
||||
#define _KEY_Z 0x1d // Keyboard z and Z
|
||||
|
||||
#define _KEY_1 0x1e // Keyboard 1 and !
|
||||
#define _KEY_2 0x1f // Keyboard 2 and @
|
||||
#define _KEY_3 0x20 // Keyboard 3 and #
|
||||
#define _KEY_4 0x21 // Keyboard 4 and $
|
||||
#define _KEY_5 0x22 // Keyboard 5 and %
|
||||
#define _KEY_6 0x23 // Keyboard 6 and ^
|
||||
#define _KEY_7 0x24 // Keyboard 7 and &
|
||||
#define _KEY_8 0x25 // Keyboard 8 and *
|
||||
#define _KEY_9 0x26 // Keyboard 9 and (
|
||||
#define _KEY_0 0x27 // Keyboard 0 and )
|
||||
|
||||
#define _KEY_ENTER 0x28 // Keyboard Return (ENTER)
|
||||
#define _KEY_ESC 0x29 // Keyboard ESCAPE
|
||||
#define _KEY_BACKSPACE 0x2a // Keyboard DELETE (Backspace)
|
||||
#define _KEY_TAB 0x2b // Keyboard Tab
|
||||
#define _KEY_SPACE 0x2c // Keyboard Spacebar
|
||||
#define _KEY_MINUS 0x2d // Keyboard - and _
|
||||
#define _KEY_EQUAL 0x2e // Keyboard = and +
|
||||
#define _KEY_LEFTBRACE 0x2f // Keyboard [ and {
|
||||
#define _KEY_RIGHTBRACE 0x30 // Keyboard ] and }
|
||||
#define _KEY_BACKSLASH 0x31 // Keyboard \ and |
|
||||
#define _KEY_HASHTILDE 0x32 // Keyboard Non-US # and ~
|
||||
#define _KEY_SEMICOLON 0x33 // Keyboard ; and :
|
||||
#define _KEY_APOSTROPHE 0x34 // Keyboard ' and "
|
||||
#define _KEY_GRAVE 0x35 // Keyboard ` and ~
|
||||
#define _KEY_COMMA 0x36 // Keyboard , and <
|
||||
#define _KEY_DOT 0x37 // Keyboard . and >
|
||||
#define _KEY_SLASH 0x38 // Keyboard / and ?
|
||||
#define _KEY_CAPSLOCK 0x39 // Keyboard Caps Lock
|
||||
|
||||
#define _KEY_F1 0x3a // Keyboard F1
|
||||
#define _KEY_F2 0x3b // Keyboard F2
|
||||
#define _KEY_F3 0x3c // Keyboard F3
|
||||
#define _KEY_F4 0x3d // Keyboard F4
|
||||
#define _KEY_F5 0x3e // Keyboard F5
|
||||
#define _KEY_F6 0x3f // Keyboard F6
|
||||
#define _KEY_F7 0x40 // Keyboard F7
|
||||
#define _KEY_F8 0x41 // Keyboard F8
|
||||
#define _KEY_F9 0x42 // Keyboard F9
|
||||
#define _KEY_F10 0x43 // Keyboard F10
|
||||
#define _KEY_F11 0x44 // Keyboard F11
|
||||
#define _KEY_F12 0x45 // Keyboard F12
|
||||
|
||||
#define _KEY_SYSRQ 0x46 // Keyboard Print Screen
|
||||
#define _KEY_SCROLLLOCK 0x47 // Keyboard Scroll Lock
|
||||
#define _KEY_PAUSE 0x48 // Keyboard Pause
|
||||
#define _KEY_INSERT 0x49 // Keyboard Insert
|
||||
#define _KEY_HOME 0x4a // Keyboard Home
|
||||
#define _KEY_PAGEUP 0x4b // Keyboard Page Up
|
||||
#define _KEY_DELETE 0x4c // Keyboard Delete Forward
|
||||
#define _KEY_END 0x4d // Keyboard End
|
||||
#define _KEY_PAGEDOWN 0x4e // Keyboard Page Down
|
||||
#define _KEY_RIGHT 0x4f // Keyboard Right Arrow
|
||||
#define _KEY_LEFT 0x50 // Keyboard Left Arrow
|
||||
#define _KEY_DOWN 0x51 // Keyboard Down Arrow
|
||||
#define _KEY_UP 0x52 // Keyboard Up Arrow
|
||||
|
||||
#define _KEY_NUMLOCK 0x53 // Keyboard Num Lock and Clear
|
||||
#define _KEY_KPSLASH 0x54 // Keypad /
|
||||
#define _KEY_KPASTERISK 0x55 // Keypad *
|
||||
#define _KEY_KPMINUS 0x56 // Keypad -
|
||||
#define _KEY_KPPLUS 0x57 // Keypad +
|
||||
#define _KEY_KPENTER 0x58 // Keypad ENTER
|
||||
#define _KEY_KP1 0x59 // Keypad 1 and End
|
||||
#define _KEY_KP2 0x5a // Keypad 2 and Down Arrow
|
||||
#define _KEY_KP3 0x5b // Keypad 3 and PageDn
|
||||
#define _KEY_KP4 0x5c // Keypad 4 and Left Arrow
|
||||
#define _KEY_KP5 0x5d // Keypad 5
|
||||
#define _KEY_KP6 0x5e // Keypad 6 and Right Arrow
|
||||
#define _KEY_KP7 0x5f // Keypad 7 and Home
|
||||
#define _KEY_KP8 0x60 // Keypad 8 and Up Arrow
|
||||
#define _KEY_KP9 0x61 // Keypad 9 and Page Up
|
||||
#define _KEY_KP0 0x62 // Keypad 0 and Insert
|
||||
#define _KEY_KPDOT 0x63 // Keypad . and Delete
|
||||
|
||||
#define _KEY_102ND 0x64 // Keyboard Non-US \ and |
|
||||
#define _KEY_COMPOSE 0x65 // Keyboard Application
|
||||
#define _KEY_POWER 0x66 // Keyboard Power
|
||||
#define _KEY_KPEQUAL 0x67 // Keypad =
|
||||
|
||||
#define _KEY_F13 0x68 // Keyboard F13
|
||||
#define _KEY_F14 0x69 // Keyboard F14
|
||||
#define _KEY_F15 0x6a // Keyboard F15
|
||||
#define _KEY_F16 0x6b // Keyboard F16
|
||||
#define _KEY_F17 0x6c // Keyboard F17
|
||||
#define _KEY_F18 0x6d // Keyboard F18
|
||||
#define _KEY_F19 0x6e // Keyboard F19
|
||||
#define _KEY_F20 0x6f // Keyboard F20
|
||||
#define _KEY_F21 0x70 // Keyboard F21
|
||||
#define _KEY_F22 0x71 // Keyboard F22
|
||||
#define _KEY_F23 0x72 // Keyboard F23
|
||||
#define _KEY_F24 0x73 // Keyboard F24
|
||||
|
||||
#define _KEY_OPEN 0x74 // Keyboard Execute
|
||||
#define _KEY_HELP 0x75 // Keyboard Help
|
||||
#define _KEY_PROPS 0x76 // Keyboard Menu
|
||||
#define _KEY_FRONT 0x77 // Keyboard Select
|
||||
#define _KEY_STOP 0x78 // Keyboard Stop
|
||||
#define _KEY_AGAIN 0x79 // Keyboard Again
|
||||
#define _KEY_UNDO 0x7a // Keyboard Undo
|
||||
#define _KEY_CUT 0x7b // Keyboard Cut
|
||||
#define _KEY_COPY 0x7c // Keyboard Copy
|
||||
#define _KEY_PASTE 0x7d // Keyboard Paste
|
||||
#define _KEY_FIND 0x7e // Keyboard Find
|
||||
#define _KEY_MUTE 0x7f // Keyboard Mute
|
||||
#define _KEY_VOLUMEUP 0x80 // Keyboard Volume Up
|
||||
#define _KEY_VOLUMEDOWN 0x81 // Keyboard Volume Down
|
||||
// 0x82 Keyboard Locking Caps Lock
|
||||
// 0x83 Keyboard Locking Num Lock
|
||||
// 0x84 Keyboard Locking Scroll Lock
|
||||
#define _KEY_KPCOMMA 0x85 // Keypad Comma
|
||||
// 0x86 Keypad Equal Sign
|
||||
#define _KEY_RO 0x87 // Keyboard International1
|
||||
#define _KEY_KATAKANAHIRAGANA 0x88 // Keyboard International2
|
||||
#define _KEY_YEN 0x89 // Keyboard International3
|
||||
#define _KEY_HENKAN 0x8a // Keyboard International4
|
||||
#define _KEY_MUHENKAN 0x8b // Keyboard International5
|
||||
#define _KEY_KPJPCOMMA 0x8c // Keyboard International6
|
||||
// 0x8d Keyboard International7
|
||||
// 0x8e Keyboard International8
|
||||
// 0x8f Keyboard International9
|
||||
#define _KEY_HANGEUL 0x90 // Keyboard LANG1
|
||||
#define _KEY_HANJA 0x91 // Keyboard LANG2
|
||||
#define _KEY_KATAKANA 0x92 // Keyboard LANG3
|
||||
#define _KEY_HIRAGANA 0x93 // Keyboard LANG4
|
||||
#define _KEY_ZENKAKUHANKAKU 0x94 // Keyboard LANG5
|
||||
// 0x95 Keyboard LANG6
|
||||
// 0x96 Keyboard LANG7
|
||||
// 0x97 Keyboard LANG8
|
||||
// 0x98 Keyboard LANG9
|
||||
// 0x99 Keyboard Alternate Erase
|
||||
// 0x9a Keyboard SysReq/Attention
|
||||
// 0x9b Keyboard Cancel
|
||||
// 0x9c Keyboard Clear
|
||||
// 0x9d Keyboard Prior
|
||||
// 0x9e Keyboard Return
|
||||
// 0x9f Keyboard Separator
|
||||
// 0xa0 Keyboard Out
|
||||
// 0xa1 Keyboard Oper
|
||||
// 0xa2 Keyboard Clear/Again
|
||||
// 0xa3 Keyboard CrSel/Props
|
||||
// 0xa4 Keyboard ExSel
|
||||
|
||||
// 0xb0 Keypad 00
|
||||
// 0xb1 Keypad 000
|
||||
// 0xb2 Thousands Separator
|
||||
// 0xb3 Decimal Separator
|
||||
// 0xb4 Currency Unit
|
||||
// 0xb5 Currency Sub-unit
|
||||
#define _KEY_KPLEFTPAREN 0xb6 // Keypad (
|
||||
#define _KEY_KPRIGHTPAREN 0xb7 // Keypad )
|
||||
// 0xb8 Keypad {
|
||||
// 0xb9 Keypad }
|
||||
// 0xba Keypad Tab
|
||||
// 0xbb Keypad Backspace
|
||||
// 0xbc Keypad A
|
||||
// 0xbd Keypad B
|
||||
// 0xbe Keypad C
|
||||
// 0xbf Keypad D
|
||||
// 0xc0 Keypad E
|
||||
// 0xc1 Keypad F
|
||||
// 0xc2 Keypad XOR
|
||||
// 0xc3 Keypad ^
|
||||
// 0xc4 Keypad %
|
||||
// 0xc5 Keypad <
|
||||
// 0xc6 Keypad >
|
||||
// 0xc7 Keypad &
|
||||
// 0xc8 Keypad &&
|
||||
// 0xc9 Keypad |
|
||||
// 0xca Keypad ||
|
||||
// 0xcb Keypad :
|
||||
// 0xcc Keypad #
|
||||
// 0xcd Keypad Space
|
||||
// 0xce Keypad @
|
||||
// 0xcf Keypad !
|
||||
// 0xd0 Keypad Memory Store
|
||||
// 0xd1 Keypad Memory Recall
|
||||
// 0xd2 Keypad Memory Clear
|
||||
// 0xd3 Keypad Memory Add
|
||||
// 0xd4 Keypad Memory Subtract
|
||||
// 0xd5 Keypad Memory Multiply
|
||||
// 0xd6 Keypad Memory Divide
|
||||
// 0xd7 Keypad +/-
|
||||
// 0xd8 Keypad Clear
|
||||
// 0xd9 Keypad Clear Entry
|
||||
// 0xda Keypad Binary
|
||||
// 0xdb Keypad Octal
|
||||
// 0xdc Keypad Decimal
|
||||
// 0xdd Keypad Hexadecimal
|
||||
|
||||
#define _KEY_LEFTCTRL 0xe0 // Keyboard Left Control
|
||||
#define _KEY_LEFTSHIFT 0xe1 // Keyboard Left Shift
|
||||
#define _KEY_LEFTALT 0xe2 // Keyboard Left Alt
|
||||
#define _KEY_LEFTMETA 0xe3 // Keyboard Left GUI
|
||||
#define _KEY_RIGHTCTRL 0xe4 // Keyboard Right Control
|
||||
#define _KEY_RIGHTSHIFT 0xe5 // Keyboard Right Shift
|
||||
#define _KEY_RIGHTALT 0xe6 // Keyboard Right Alt
|
||||
#define _KEY_RIGHTMETA 0xe7 // Keyboard Right GUI
|
||||
|
||||
#define _KEY_MEDIA_PLAYPAUSE 0xe8
|
||||
#define _KEY_MEDIA_STOPCD 0xe9
|
||||
#define _KEY_MEDIA_PREVIOUSSONG 0xea
|
||||
#define _KEY_MEDIA_NEXTSONG 0xeb
|
||||
#define _KEY_MEDIA_EJECTCD 0xec
|
||||
#define _KEY_MEDIA_VOLUMEUP 0xed
|
||||
#define _KEY_MEDIA_VOLUMEDOWN 0xee
|
||||
#define _KEY_MEDIA_MUTE 0xef
|
||||
#define _KEY_MEDIA_WWW 0xf0
|
||||
#define _KEY_MEDIA_BACK 0xf1
|
||||
#define _KEY_MEDIA_FORWARD 0xf2
|
||||
#define _KEY_MEDIA_STOP 0xf3
|
||||
#define _KEY_MEDIA_FIND 0xf4
|
||||
#define _KEY_MEDIA_SCROLLUP 0xf5
|
||||
#define _KEY_MEDIA_SCROLLDOWN 0xf6
|
||||
#define _KEY_MEDIA_EDIT 0xf7
|
||||
#define _KEY_MEDIA_SLEEP 0xf8
|
||||
#define _KEY_MEDIA_COFFEE 0xf9
|
||||
#define _KEY_MEDIA_REFRESH 0xfa
|
||||
#define _KEY_MEDIA_CALC 0xfb
|
||||
|
||||
#define _KEY_CUSTOM_CTRL_VOL_UP 0x00e9
|
||||
#define _KEY_CUSTOM_CTRL_VOL_DOWN 0x00ea
|
||||
#define _KEY_CUSTOM_CTRL_MUTE 0x00e2
|
||||
#define _KEY_CUSTOM_CTRL_FORWARD 0x00b5
|
||||
#define _KEY_CUSTOM_CTRL_STOP 0x00cd
|
||||
#define _KEY_CUSTOM_CTRL_BACK 0x00b6
|
||||
#define _KEY_CUSTOM_CTRL_MUSIC 0x0183
|
||||
#define _KEY_CUSTOM_CTRL_CALCULATOR 0x0192
|
||||
#define _KEY_CUSTOM_CTRL_SEARCH 0x0221
|
||||
#define _KEY_CUSTOM_CTRL_EMAIL 0x018A
|
||||
#define _KEY_CUSTOM_CTRL_HOME 0x0223
|
||||
#define _KEY_BRIGHTNESS_INCREASE 0x006F
|
||||
#define _KEY_BRIGHTNESS_REDUCTION 0x0070
|
||||
#define _KEY_ZOOM_IN 0x022D
|
||||
#define _KEY_ZOOM_OUT 0x022E
|
||||
#define _KEY_CUSTOM_COPY 0x021B
|
||||
#define _KEY_CUSTOM_CUT 0x021C
|
||||
#define _KEY_CUSTOM_PASTE 0x021D
|
||||
#define _KEY_CUSTOM_SELECT_ALL 0x021E
|
||||
#define _KEY_CUSTOM_SPLIT_SCREEN 0x0196
|
||||
#define _KEY_CUSTOM_LOCK 0x0030
|
||||
#define _KEY_CUSTOM_ESC 0x0223
|
||||
#define _KEY_CUSTOM_CALENDAR 0x018e
|
||||
#define _KEY_CUSTOM_MESSAGE 0X018d
|
||||
|
||||
#define _KEY_CUSTOM_BROWER 0x0231
|
||||
#define _KEY_CUSTOM_PROCESS 0x023a
|
||||
|
||||
#define _KEY_CUSTOM_SET 0x029b
|
||||
|
||||
#define LED_NUM_LOCK 0x01
|
||||
#define LED_CAPS_LOCK 0x02
|
||||
#define LED_SCROLL_CLOCK 0x04
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,834 @@
|
||||
#include "includes.h"
|
||||
#include "app_config.h"
|
||||
#include "device_drive.h"
|
||||
/* #include "os/os_compat.h" */
|
||||
#if USB_HOST_ENABLE
|
||||
#include "usb_config.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
#include "usb/usb_phy.h"
|
||||
#include "usb_ctrl_transfer.h"
|
||||
#include "usb_storage.h"
|
||||
#include "adb.h"
|
||||
#include "aoa.h"
|
||||
#include "hid.h"
|
||||
#include "audio.h"
|
||||
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
#include "apple_dock/iAP.h"
|
||||
#include "apple_mfi.h"
|
||||
#endif
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[mount]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
static struct usb_host_device host_devices[USB_MAX_HW_NUM];// SEC(.usb_h_bss);
|
||||
|
||||
#define device_to_usbdev(device) ((struct usb_host_device *)((device)->private_data))
|
||||
|
||||
|
||||
int host_dev_status(const struct usb_host_device *host_dev)
|
||||
{
|
||||
return ((host_dev)->private_data.status);
|
||||
}
|
||||
|
||||
u32 host_device2id(const struct usb_host_device *host_dev)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
return ((host_dev)->private_data.usb_id);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
const struct usb_host_device *host_id2device(const usb_dev id)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
return &host_devices[id];
|
||||
#else
|
||||
return &host_devices[0];
|
||||
#endif
|
||||
}
|
||||
int usb_sem_init(struct usb_host_device *host_dev)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
usb_host_config(usb_id);
|
||||
|
||||
OS_SEM *sem = zalloc(sizeof(OS_SEM));
|
||||
ASSERT(sem, "usb alloc sem error");
|
||||
host_dev->sem = sem;
|
||||
g_printf("%s %x %x ", __func__, host_dev, sem);
|
||||
os_sem_create(host_dev->sem, 0);
|
||||
return 0;
|
||||
}
|
||||
int usb_sem_pend(struct usb_host_device *host_dev, u32 timeout)
|
||||
{
|
||||
if (host_dev->sem == NULL) {
|
||||
return 1;
|
||||
}
|
||||
int ret = os_sem_pend(host_dev->sem, timeout);
|
||||
if (ret) {
|
||||
r_printf("%s %d ", __func__, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int usb_sem_post(struct usb_host_device *host_dev)
|
||||
{
|
||||
if (host_dev->sem == NULL) {
|
||||
return 1;
|
||||
}
|
||||
int ret = os_sem_post(host_dev->sem);
|
||||
if (ret) {
|
||||
r_printf("%s %d ", __func__, ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int usb_sem_del(struct usb_host_device *host_dev)
|
||||
{
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
|
||||
r_printf("1");
|
||||
if (host_dev->sem == NULL) {
|
||||
return 0;
|
||||
}
|
||||
r_printf("2");
|
||||
r_printf("3");
|
||||
#if USB_HUB
|
||||
if (host_dev && host_dev->sem && host_dev->father == NULL) {
|
||||
os_sem_del(host_dev->sem, 0);
|
||||
}
|
||||
#else
|
||||
if (host_dev && host_dev->sem) {
|
||||
os_sem_del(host_dev->sem, 0);
|
||||
}
|
||||
#endif
|
||||
r_printf("4");
|
||||
g_printf("%s %x %x ", __func__, host_dev, host_dev->sem);
|
||||
free(host_dev->sem);
|
||||
r_printf("5");
|
||||
host_dev->sem = NULL;
|
||||
r_printf("6");
|
||||
usb_host_free(usb_id);
|
||||
r_printf("7");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find udisk @ interface %d", interface_num);
|
||||
#if TCFG_UDISK_ENABLE
|
||||
return usb_msd_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_apple_mfi_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find udisk @ interface %d", interface_num);
|
||||
#if TCFG_USB_APPLE_DOCK_EN
|
||||
return usb_apple_mfi_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find adb @ interface %d", interface_num);
|
||||
#if TCFG_ADB_ENABLE
|
||||
return usb_adb_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find aoa @ interface %d", interface_num);
|
||||
#if TCFG_AOA_ENABLE
|
||||
return usb_aoa_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
|
||||
}
|
||||
static int _usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find hid @ interface %d", interface_num);
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
return usb_hid_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find audio @ interface %d", interface_num);
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
return usb_audio_parser(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
static int _usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf)
|
||||
{
|
||||
log_info("find adbmtp @ interface %d", interface_num);
|
||||
#if TCFG_ADB_ENABLE
|
||||
return usb_adb_interface_ptp_mtp_parse(host_dev, interface_num, pBuf);
|
||||
#else
|
||||
return USB_DT_INTERFACE_SIZE;
|
||||
#endif
|
||||
}
|
||||
/**
|
||||
* @brief usb_descriptor_parser
|
||||
*
|
||||
* @param device
|
||||
* @param pBuf
|
||||
* @param total_len
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static int usb_descriptor_parser(struct usb_host_device *host_dev, const u8 *pBuf, u32 total_len, struct usb_device_descriptor *device_desc)
|
||||
{
|
||||
int len = 0;
|
||||
u8 interface_num = 0;
|
||||
struct usb_private_data *private_data = &host_dev->private_data;
|
||||
|
||||
struct usb_config_descriptor *cfg_desc = (struct usb_config_descriptor *)pBuf;
|
||||
|
||||
if (cfg_desc->bDescriptorType != USB_DT_CONFIG ||
|
||||
cfg_desc->bLength < USB_DT_CONFIG_SIZE) {
|
||||
log_error("invalid descriptor for config bDescriptorType = %d bLength= %d",
|
||||
cfg_desc->bDescriptorType, cfg_desc->bLength);
|
||||
return -USB_DT_CONFIG;
|
||||
}
|
||||
|
||||
log_info("idVendor %x idProduct %x", device_desc->idVendor, device_desc->idProduct);
|
||||
|
||||
len += USB_DT_CONFIG_SIZE;
|
||||
pBuf += USB_DT_CONFIG_SIZE;
|
||||
int i = 0;
|
||||
u32 have_find_valid_class = 0;
|
||||
while (len < total_len) {
|
||||
if (interface_num > MAX_HOST_INTERFACE) {
|
||||
log_error("interface_num too much");
|
||||
break;
|
||||
}
|
||||
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf;
|
||||
if (interface->bDescriptorType == USB_DT_INTERFACE) {
|
||||
|
||||
printf("inf class %x subclass %x ep %d",
|
||||
interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bNumEndpoints);
|
||||
|
||||
if (interface->bInterfaceClass == USB_CLASS_MASS_STORAGE) {
|
||||
i = _usb_msd_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if ((device_desc->idVendor == 0x05AC) &&
|
||||
((device_desc->idProduct & 0xff00) == 0x1200)) {
|
||||
i = _usb_apple_mfi_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if (interface->bInterfaceClass == USB_CLASS_AUDIO) {
|
||||
i = _usb_audio_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if ((interface->bInterfaceClass == 0xff) &&
|
||||
(interface->bInterfaceSubClass == USB_CLASS_ADB)) {
|
||||
i = _usb_adb_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if ((device_desc->idVendor == 0x18d1) &&
|
||||
((device_desc->idProduct & 0x2d00) == 0x2d00)) {
|
||||
i = _usb_aoa_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if (interface->bInterfaceClass == USB_CLASS_HID) {
|
||||
i = _usb_hid_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
have_find_valid_class = true;
|
||||
}
|
||||
} else if ((interface->bNumEndpoints == 3) &&
|
||||
(interface->bInterfaceClass == 0xff || interface->bInterfaceClass == 0x06)) {
|
||||
i = _usb_adb_interface_ptp_mtp_parse(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
}
|
||||
have_find_valid_class = true;
|
||||
} else if ((interface->bInterfaceClass == 0xff) &&
|
||||
(interface->bInterfaceSubClass == 0xff)) {
|
||||
i = _usb_aoa_parser(host_dev, interface_num, pBuf);
|
||||
if (i < 0) {
|
||||
log_error("---%s %d---", __func__, __LINE__);
|
||||
len = total_len;
|
||||
} else {
|
||||
interface_num++;
|
||||
len += i;
|
||||
pBuf += i;
|
||||
}
|
||||
have_find_valid_class = true;
|
||||
|
||||
} else {
|
||||
log_info("find unsupport [class %x subClass %x] @ interface %d",
|
||||
interface->bInterfaceClass,
|
||||
interface->bInterfaceSubClass,
|
||||
interface_num);
|
||||
|
||||
len += USB_DT_INTERFACE_SIZE;
|
||||
pBuf += USB_DT_INTERFACE_SIZE;
|
||||
}
|
||||
} else {
|
||||
/* log_error("unknown section %d %d", len, pBuf[0]); */
|
||||
if (pBuf[0]) {
|
||||
len += pBuf[0];
|
||||
pBuf += pBuf[0];
|
||||
} else {
|
||||
len = total_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log_debug("len %d total_len %d", len, total_len);
|
||||
return !have_find_valid_class;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief usb_host_suspend
|
||||
*
|
||||
* @param usb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/* --------------------------------------------------------------------------*/
|
||||
void usb_host_suspend(const usb_dev usb_id)
|
||||
{
|
||||
usb_h_entry_suspend(usb_id);
|
||||
}
|
||||
|
||||
void usb_host_resume(const usb_dev usb_id)
|
||||
{
|
||||
usb_h_resume(usb_id);
|
||||
}
|
||||
|
||||
static u32 _usb_host_mount(const usb_dev usb_id, u32 retry, u32 reset_delay, u32 mount_timeout)
|
||||
{
|
||||
u32 ret = DEV_ERR_NONE;
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
struct usb_private_data *private_data = &host_dev->private_data;
|
||||
|
||||
|
||||
for (int i = 0; i < retry; i++) {
|
||||
usb_h_sie_init(usb_id);
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
usb_write_power(usb_id, BIT(6)); //full-speed
|
||||
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
|
||||
usb_write_power(usb_id, BIT(5) | BIT(6)); //high-speed
|
||||
#else
|
||||
#error "USB_SPEED_MODE not defined"
|
||||
#endif
|
||||
ret = usb_host_init(usb_id, reset_delay, mount_timeout);
|
||||
if (ret) {
|
||||
reset_delay += 10;
|
||||
continue;
|
||||
}
|
||||
|
||||
void *const ep0_dma = usb_h_get_ep_buffer(usb_id, 0);
|
||||
usb_set_dma_taddr(usb_id, 0, ep0_dma);
|
||||
|
||||
usb_sie_enable(usb_id);//enable sie intr
|
||||
usb_mdelay(reset_delay);
|
||||
|
||||
/**********get device descriptor*********/
|
||||
struct usb_device_descriptor device_desc;
|
||||
private_data->usb_id = usb_id;
|
||||
private_data->status = 0;
|
||||
private_data->devnum = 0;
|
||||
private_data->ep0_max_packet_size = 8;
|
||||
ret = usb_get_device_descriptor(host_dev, &device_desc);
|
||||
|
||||
/**********set address*********/
|
||||
usb_mdelay(20);
|
||||
u8 devnum = rand32() % 16 + 1;
|
||||
ret = set_address(host_dev, devnum);
|
||||
check_usb_mount(ret);
|
||||
private_data->devnum = devnum ;
|
||||
|
||||
/**********get device descriptor*********/
|
||||
usb_mdelay(20);
|
||||
ret = usb_get_device_descriptor(host_dev, &device_desc);
|
||||
check_usb_mount(ret);
|
||||
private_data->ep0_max_packet_size = device_desc.bMaxPacketSize0;
|
||||
|
||||
/**********get config descriptor*********/
|
||||
struct usb_config_descriptor cfg_desc;
|
||||
ret = get_config_descriptor(host_dev, &cfg_desc, USB_DT_CONFIG_SIZE);
|
||||
check_usb_mount(ret);
|
||||
|
||||
#if USB_H_MALLOC_ENABLE
|
||||
u8 *desc_buf = zalloc(cfg_desc.wTotalLength + 16);
|
||||
ASSERT(desc_buf, "desc_buf");
|
||||
#else
|
||||
u8 desc_buf[128] = {0};
|
||||
cfg_desc.wTotalLength = min(sizeof(desc_buf), cfg_desc.wTotalLength);
|
||||
#endif
|
||||
|
||||
ret = get_config_descriptor(host_dev, desc_buf, cfg_desc.wTotalLength);
|
||||
check_usb_mount(ret);
|
||||
|
||||
/**********set configuration*********/
|
||||
ret = set_configuration(host_dev);
|
||||
/* printf_buf(desc_buf, cfg_desc.wTotalLength); */
|
||||
ret |= usb_descriptor_parser(host_dev, desc_buf, cfg_desc.wTotalLength, &device_desc);
|
||||
#if USB_H_MALLOC_ENABLE
|
||||
log_info("free:desc_buf= %x\n", desc_buf);
|
||||
free(desc_buf);
|
||||
#endif
|
||||
check_usb_mount(ret);
|
||||
|
||||
for (int itf = 0; itf < MAX_HOST_INTERFACE; itf++) {
|
||||
if (host_dev->interface_info[itf]) {
|
||||
host_dev->interface_info[itf]->ctrl->set_power(host_dev, 1);
|
||||
}
|
||||
}
|
||||
break;//succ
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
private_data->status = 1;
|
||||
return DEV_ERR_NONE;
|
||||
|
||||
__exit_fail:
|
||||
printf("usb_probe fail");
|
||||
private_data->status = 0;
|
||||
usb_sie_close(usb_id);
|
||||
return ret;
|
||||
}
|
||||
static int usb_event_notify(const struct usb_host_device *host_dev, u32 ev)
|
||||
{
|
||||
const usb_dev id = host_device2id(host_dev);
|
||||
struct sys_event event;
|
||||
static u32 bmUsbEvent[USB_MAX_HW_NUM];
|
||||
u8 have_post_event = 0;
|
||||
u8 no_send_event = 0;
|
||||
if (ev == 0) {
|
||||
event.u.dev.event = DEVICE_EVENT_IN;
|
||||
} else if (ev == 1) {
|
||||
event.u.dev.event = DEVICE_EVENT_CHANGE;
|
||||
} else {
|
||||
event.u.dev.event = DEVICE_EVENT_OUT;
|
||||
goto __usb_event_out;
|
||||
}
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
no_send_event = 0;
|
||||
event.u.dev.value = 0;
|
||||
if (host_dev->interface_info[i]) {
|
||||
switch (host_dev->interface_info[i]->ctrl->interface_class) {
|
||||
#if TCFG_UDISK_ENABLE
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
if (have_post_event & BIT(0)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(0);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"udisk0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"udisk1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(0);
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_ADB_ENABLE
|
||||
case USB_CLASS_ADB:
|
||||
if (have_post_event & BIT(1)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(1);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"adb0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"adb1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(1);
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_AOA_ENABLE
|
||||
case USB_CLASS_AOA:
|
||||
if (have_post_event & BIT(2)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(2);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"aoa0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"aoa1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(2);
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
case USB_CLASS_HID:
|
||||
if (have_post_event & BIT(3)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(3);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"hid0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"hid1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(3);
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
case USB_CLASS_AUDIO:
|
||||
if (have_post_event & BIT(4)) {
|
||||
no_send_event = 1;
|
||||
} else {
|
||||
have_post_event |= BIT(4);
|
||||
}
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"audio0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"audio1";
|
||||
}
|
||||
bmUsbEvent[id] |= BIT(4);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!no_send_event && event.u.dev.value) {
|
||||
log_info("event %x interface %x class %x %s",
|
||||
event.u.dev.event, i,
|
||||
host_dev->interface_info[i]->ctrl->interface_class,
|
||||
(const char *)event.u.dev.value);
|
||||
|
||||
/* printf("usb_host_mount notify >>>>>>>>>>>\n"); */
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_USB_HOST;
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
sys_event_notify(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__usb_event_out:
|
||||
if (event.u.dev.event == DEVICE_EVENT_OUT) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (bmUsbEvent[id] & BIT(i)) {
|
||||
switch (i) {
|
||||
#if TCFG_UDISK_ENABLE
|
||||
case 0:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"udisk0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"udisk1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_ADB_ENABLE
|
||||
case 1:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"adb0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"adb1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_AOA_ENABLE
|
||||
case 2:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"aoa0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"aoa1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
case 3:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"hid0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"hid1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if TCFG_HOST_AUDIO_ENABLE
|
||||
case 4:
|
||||
if (id == 0) {
|
||||
event.u.dev.value = (int)"audio0";
|
||||
} else {
|
||||
event.u.dev.value = (int)"audio1";
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
event.u.dev.value = 0;
|
||||
break;
|
||||
}
|
||||
bmUsbEvent[id] &= ~BIT(i);
|
||||
if (event.u.dev.value) {
|
||||
event.type = SYS_DEVICE_EVENT;
|
||||
event.arg = (void *)DEVICE_EVENT_FROM_USB_HOST;
|
||||
have_post_event = 1;
|
||||
sys_event_notify(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (have_post_event) {
|
||||
return DEV_ERR_NONE;
|
||||
} else {
|
||||
return DEV_ERR_UNKNOW_CLASS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const char *usb_host_valid_class_to_dev(const usb_dev id, u32 usbclass)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
const usb_dev usb_id = id;
|
||||
#else
|
||||
const usb_dev usb_id = 0;
|
||||
#endif
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
u32 itf_class;
|
||||
|
||||
for (int i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
if (host_dev->interface_info[i] &&
|
||||
host_dev->interface_info[i]->ctrl) {
|
||||
itf_class = host_dev->interface_info[i]->ctrl->interface_class;
|
||||
if (itf_class == usbclass) {
|
||||
switch (itf_class) {
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
if (usb_id == 0) {
|
||||
return "udisk0";
|
||||
} else if (usb_id == 1) {
|
||||
return "udisk1";
|
||||
}
|
||||
break;
|
||||
case USB_CLASS_ADB:
|
||||
if (usb_id == 0) {
|
||||
return "adb0";
|
||||
} else if (usb_id == 1) {
|
||||
return "adb1";
|
||||
}
|
||||
break;
|
||||
case USB_CLASS_AOA:
|
||||
if (usb_id == 0) {
|
||||
return "aoa0";
|
||||
} else if (usb_id == 1) {
|
||||
return "aoa1";
|
||||
}
|
||||
break;
|
||||
case USB_CLASS_HID:
|
||||
if (usb_id == 0) {
|
||||
return "hid0";
|
||||
} else if (usb_id == 1) {
|
||||
return "hid1";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief usb_host_mount
|
||||
*
|
||||
* @param usb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/* --------------------------------------------------------------------------*/
|
||||
u32 usb_host_mount(const usb_dev id, u32 retry, u32 reset_delay, u32 mount_timeout)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
const usb_dev usb_id = id;
|
||||
#else
|
||||
const usb_dev usb_id = 0;
|
||||
#endif
|
||||
|
||||
u32 ret;
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
memset(host_dev, 0, sizeof(*host_dev));
|
||||
|
||||
host_dev->private_data.usb_id = id;
|
||||
|
||||
usb_sem_init(host_dev);
|
||||
usb_h_isr_reg(usb_id, 1, 0);
|
||||
|
||||
|
||||
ret = _usb_host_mount(usb_id, retry, reset_delay, mount_timeout);
|
||||
usb_otg_resume(usb_id); //打开usb host之后恢复otg检测
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
return usb_event_notify(host_dev, 0);
|
||||
|
||||
__exit_fail:
|
||||
usb_sie_disable(usb_id);
|
||||
usb_sem_del(host_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 _usb_host_unmount(const usb_dev usb_id)
|
||||
{
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
|
||||
struct usb_private_data *private_data = &host_dev->private_data;
|
||||
private_data->status = 0;
|
||||
|
||||
usb_sem_post(host_dev);//拔掉设备时,让读写线程快速释放
|
||||
|
||||
for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) {
|
||||
if (host_dev->interface_info[i] && host_dev->interface_info[i]->ctrl->set_power) {
|
||||
host_dev->interface_info[i]->ctrl->set_power(host_dev, 0);
|
||||
host_dev->interface_info[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
usb_sie_close(usb_id);
|
||||
return DEV_ERR_NONE;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief usb_host_unmount
|
||||
*
|
||||
* @param usb
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/* u32 usb_host_unmount(const usb_dev usb_id, char *device_name) */
|
||||
u32 usb_host_unmount(const usb_dev id)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
const usb_dev usb_id = id;
|
||||
#else
|
||||
const usb_dev usb_id = 0;
|
||||
#endif
|
||||
u32 ret;
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
struct sys_event event;
|
||||
|
||||
#if (TCFG_UDISK_ENABLE && UDISK_READ_512_ASYNC_ENABLE)
|
||||
_usb_stor_async_wait_sem(host_dev);
|
||||
#endif
|
||||
ret = _usb_host_unmount(usb_id);
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
usb_sem_del(host_dev);
|
||||
|
||||
/* printf("usb_host_unmount notify >>>>>>>>>>>\n"); */
|
||||
usb_event_notify(host_dev, 2);
|
||||
return DEV_ERR_NONE;
|
||||
|
||||
__exit_fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 usb_host_remount(const usb_dev id, u32 retry, u32 delay, u32 ot, u8 notify)
|
||||
{
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
const usb_dev usb_id = id;
|
||||
#else
|
||||
const usb_dev usb_id = 0;
|
||||
#endif
|
||||
u32 ret;
|
||||
struct sys_event event;
|
||||
|
||||
ret = _usb_host_unmount(usb_id);
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
os_sem_set(host_dev->sem, 0);
|
||||
|
||||
ret = _usb_host_mount(usb_id, retry, delay, ot);
|
||||
if (ret) {
|
||||
goto __exit_fail;
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
struct usb_host_device *host_dev = &host_devices[usb_id];
|
||||
usb_event_notify(host_dev, 1);
|
||||
}
|
||||
return DEV_ERR_NONE;
|
||||
|
||||
__exit_fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usb_host_force_reset(const usb_dev usb_id)
|
||||
{
|
||||
//预留以后加上hub的处理
|
||||
usb_h_force_reset(usb_id);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,145 @@
|
||||
/**@file usb_storage.h
|
||||
* @brief usb_storage驱动头文件(做主机)
|
||||
* @details 结构体声明,功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-8-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC695N
|
||||
* SDK版本:AC695N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-8-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __USB_STORAGE_H__
|
||||
#define __USB_STORAGE_H__
|
||||
|
||||
#include "system/task.h"
|
||||
#include "device/device.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "usb_bulk_transfer.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
|
||||
/* u盘预读功能配置, 二选一
|
||||
* 当两种方式都不使能,则表示不开启预读 */
|
||||
#define UDISK_READ_BIGBLOCK_ASYNC_ENABLE 0 //使能大扇区预读方式(不需要额外buf,速度比512预读慢10%)
|
||||
#define UDISK_READ_512_ASYNC_ENABLE 0 //使能512Byte预读方式(需要额外的512byte buffer,速度比大扇区预读快10%)
|
||||
/****************************/
|
||||
|
||||
#define UDISK_READ_ASYNC_BLOCK_NUM (16) //预读扇区数
|
||||
|
||||
//****************************youning***********************************----->
|
||||
#define UDISK_READ_AHEAD_ENABLE 0 //使能U盘预读功能
|
||||
#define UDISK_READ_AHEAD_BLOCK_NUM 16 //U盘预读扇区数量
|
||||
#define check_usb_read_ahead(ret) \
|
||||
if(ret < 0) {\
|
||||
log_error("func:%s,line:%d,lba:%d,ret:%d\n", __func__, __LINE__, lba, ret);\
|
||||
goto __exit;\
|
||||
} //检查函数返回值,0:正确 非0:错误
|
||||
//****************************youning***********************************<-----
|
||||
|
||||
/**@enum usb_sta
|
||||
* @brief USB设备当前状态
|
||||
*/
|
||||
typedef enum usb_sta {
|
||||
DEV_IDLE = 0, ///<空闲状态
|
||||
DEV_INIT, ///<初始化
|
||||
DEV_OPEN, ///<开启
|
||||
DEV_READ, ///<读操作
|
||||
DEV_WRITE, ///<写操作
|
||||
DEV_CLOSE, ///<关闭
|
||||
DEV_SUSPEND, ///<挂起
|
||||
} USB_STA ;
|
||||
|
||||
/**@struct udisk_end_desc
|
||||
* @brief U盘端点描述结构体
|
||||
*
|
||||
*/
|
||||
struct udisk_end_desc {
|
||||
u8 host_epout; ///<主机端点输出
|
||||
u8 target_epout; ///<目标端点输出
|
||||
u8 host_epin; ///<主机端点输入
|
||||
u8 target_epin; ///<目标端点输入
|
||||
#if defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
u16 rxmaxp; ///<接收最大端点号
|
||||
u16 txmaxp; ///<发送最大端点号
|
||||
#endif
|
||||
};
|
||||
|
||||
#define ENABLE_DISK_HOTPLUG 0
|
||||
|
||||
/**@struct mass_storage
|
||||
* @brief mass_storage协议所使用的相关变量
|
||||
*/
|
||||
struct mass_storage {
|
||||
OS_MUTEX mutex; ///<互斥量
|
||||
|
||||
struct usb_scsi_cbw cbw; ///<CBW指令结构体
|
||||
struct usb_scsi_csw csw; ///<CSW状态结构体
|
||||
struct request_sense_data sense; ///<请求数据检查结构体
|
||||
|
||||
char *name; ///<设备名字
|
||||
struct read_capacity_data capacity[2]; ///<读取数据的能力,包含数据块的编号、大小
|
||||
u8 lun; ///<最大逻辑单元地址
|
||||
u8 curlun; ///<当前逻辑单元地址
|
||||
|
||||
u8 dev_status; ///<设备状态
|
||||
u8 suspend_cnt; ///<挂起状态计数器
|
||||
u8 read_only; ///<只读标志位
|
||||
|
||||
u32 remain_len; ///<剩余的包长度
|
||||
u32 prev_lba; ///<上一次扇区
|
||||
#if (UDISK_READ_BIGBLOCK_ASYNC_ENABLE || UDISK_READ_512_ASYNC_ENABLE)
|
||||
u8 async_en; ///<异步模式使能
|
||||
u8 need_send_csw; ///<需要发送csw标志位
|
||||
u8 *udisk_512_buf; ///<U盘512K大小BUFFER指针
|
||||
u32 async_prev_lba; ///<异步模式上一次地址
|
||||
#endif
|
||||
#if UDISK_READ_AHEAD_ENABLE
|
||||
u8 *udisk_read_ahead_buf; ///<U盘512byte大小BUFFER指针
|
||||
u32 udisk_read_ahead_lba_last; ///<异步模式上一次地址
|
||||
#endif
|
||||
#if ENABLE_DISK_HOTPLUG
|
||||
u8 media_sta_cur; ///<当前媒介状态 //for card reader, card removable
|
||||
u8 media_sta_prev; ///<上次媒介状态
|
||||
|
||||
int test_unit_ready_tick; ///<测试准备标记
|
||||
#endif
|
||||
};
|
||||
|
||||
enum usb_async_mode {
|
||||
BULK_ASYNC_MODE_EXIT = 0, ///<退出异步模式
|
||||
BULK_ASYNC_MODE_SEM_PEND, ///<异步预读等待信号量
|
||||
};
|
||||
|
||||
#define MASS_LBA_INIT (-2)
|
||||
|
||||
/**@brief 使用mass_storage协议,对大容量存储设备进行解析,端点配置
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @param[in] interface_num 接口号
|
||||
* @param[in] *pBuf 指向BUFFER的指针
|
||||
* @return len BUFFER的长度
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_msd_parser(host_dev,interface_num,pBuf);
|
||||
* @encode
|
||||
*/
|
||||
int usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf);
|
||||
|
||||
/**@brief 异步模式等待信号量
|
||||
* @param[in] usb_host_device定义的结构体指针
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* _usb_stor_async_wait_sem(host_dev);
|
||||
* @encode
|
||||
*/
|
||||
int _usb_stor_async_wait_sem(struct usb_host_device *host_dev);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,168 @@
|
||||
#ifndef __USB_COMMON_DEFINE_H__
|
||||
#define __USB_COMMON_DEFINE_H__
|
||||
|
||||
///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里
|
||||
///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里
|
||||
///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里
|
||||
//
|
||||
/**************************************************************************/
|
||||
/*
|
||||
CLASS BITMAP
|
||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
|
||||
HID AUDIO SPEAKER Mass Storage
|
||||
*/
|
||||
/**************************************************************************/
|
||||
#define MASSSTORAGE_CLASS 0x00000001
|
||||
#define SPEAKER_CLASS 0x00000002
|
||||
#define MIC_CLASS 0x00000004
|
||||
#define HID_CLASS 0x00000008
|
||||
#define CDC_CLASS 0x00000010
|
||||
|
||||
#define AUDIO_CLASS (SPEAKER_CLASS|MIC_CLASS)
|
||||
|
||||
|
||||
#define USB_ROOT2 0
|
||||
|
||||
/// board文件没有定义的宏,在这里定义,防止编译报warning
|
||||
#ifndef TCFG_PC_ENABLE
|
||||
#define TCFG_PC_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_UDISK_ENABLE
|
||||
#define TCFG_UDISK_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_HID_HOST_ENABLE
|
||||
#define TCFG_HID_HOST_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_AOA_ENABLE
|
||||
#define TCFG_AOA_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_ADB_ENABLE
|
||||
#define TCFG_ADB_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_APPLE_DOCK_EN
|
||||
#define TCFG_USB_APPLE_DOCK_EN 0
|
||||
#endif
|
||||
#ifndef TCFG_HOST_AUDIO_ENABLE
|
||||
#define TCFG_HOST_AUDIO_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_CHARGE_ENABLE
|
||||
#define TCFG_CHARGE_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_PORT_CHARGE
|
||||
#define TCFG_USB_PORT_CHARGE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_MIC_ECHO_ENABLE
|
||||
#define TCFG_USB_MIC_ECHO_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_MIC_DATA_FROM_MICEFFECT
|
||||
#define TCFG_USB_MIC_DATA_FROM_MICEFFECT 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0
|
||||
#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 0
|
||||
#endif
|
||||
#ifndef TCFG_ONLY_PC_ENABLE //只有pc模式
|
||||
#define TCFG_ONLY_PC_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_TYPE_C_ENABLE //应用于type-c场景
|
||||
#define TCFG_TYPE_C_ENABLE 0
|
||||
#endif
|
||||
#ifndef TCFG_USB_CDC_BACKGROUND_RUN
|
||||
#define TCFG_USB_CDC_BACKGROUND_RUN 0
|
||||
#endif
|
||||
|
||||
/********************************/
|
||||
|
||||
#if TCFG_UDISK_ENABLE || TCFG_HID_HOST_ENABLE || TCFG_AOA_ENABLE || TCFG_ADB_ENABLE || TCFG_HOST_AUDIO_ENABLE
|
||||
#define MOUNT_RETRY 3
|
||||
#define MOUNT_RESET 40
|
||||
#define MOUNT_TIMEOUT 50
|
||||
#define USB_HOST_ENABLE 1
|
||||
#else
|
||||
#define USB_HOST_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_CHARGE_ENABLE && TCFG_USB_PORT_CHARGE
|
||||
#define TCFG_OTG_MODE_CHARGE (OTG_CHARGE_MODE)
|
||||
#else
|
||||
#define TCFG_OTG_MODE_CHARGE 0
|
||||
#endif
|
||||
|
||||
#if (TCFG_PC_ENABLE)
|
||||
#define TCFG_PC_UPDATE 1
|
||||
#define TCFG_OTG_MODE_SLAVE (OTG_SLAVE_MODE)
|
||||
#else
|
||||
#define TCFG_PC_UPDATE 0
|
||||
#define TCFG_OTG_MODE_SLAVE 0
|
||||
#endif
|
||||
|
||||
#if (USB_HOST_ENABLE)
|
||||
#define TCFG_OTG_MODE_HOST (OTG_HOST_MODE)
|
||||
#else
|
||||
#define TCFG_OTG_MODE_HOST 0
|
||||
#endif
|
||||
|
||||
#if TCFG_PC_ENABLE
|
||||
#define TCFG_USB_SLAVE_ENABLE 1
|
||||
#if (USB_DEVICE_CLASS_CONFIG & MASSSTORAGE_CLASS)
|
||||
#define TCFG_USB_SLAVE_MSD_ENABLE 1
|
||||
#else
|
||||
#define TCFG_USB_SLAVE_MSD_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if (USB_DEVICE_CLASS_CONFIG & AUDIO_CLASS)
|
||||
#define TCFG_USB_SLAVE_AUDIO_ENABLE 1
|
||||
#else
|
||||
#define TCFG_USB_SLAVE_AUDIO_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if (USB_DEVICE_CLASS_CONFIG & HID_CLASS)
|
||||
#define TCFG_USB_SLAVE_HID_ENABLE 1
|
||||
#else
|
||||
#define TCFG_USB_SLAVE_HID_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if (USB_DEVICE_CLASS_CONFIG & CDC_CLASS)
|
||||
#define TCFG_USB_SLAVE_CDC_ENABLE 1
|
||||
#else
|
||||
#define TCFG_USB_SLAVE_CDC_ENABLE 0
|
||||
#endif
|
||||
|
||||
#else /* TCFG_PC_ENABLE == 0*/
|
||||
#define TCFG_USB_SLAVE_ENABLE 0
|
||||
#define TCFG_USB_SLAVE_MSD_ENABLE 0
|
||||
#define TCFG_USB_SLAVE_AUDIO_ENABLE 0
|
||||
#define TCFG_USB_SLAVE_HID_ENABLE 0
|
||||
#define TCFG_USB_SLAVE_CDC_ENABLE 0
|
||||
#endif
|
||||
|
||||
#define TCFG_OTG_SLAVE_ONLINE_CNT 3
|
||||
#define TCFG_OTG_SLAVE_OFFLINE_CNT 2
|
||||
|
||||
#define TCFG_OTG_HOST_ONLINE_CNT 2
|
||||
#define TCFG_OTG_HOST_OFFLINE_CNT 3
|
||||
|
||||
#ifndef TCFG_OTG_MODE
|
||||
#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE)
|
||||
#endif
|
||||
|
||||
#define TCFG_OTG_DET_INTERVAL 50
|
||||
|
||||
#if (TCFG_USB_CDC_BACKGROUND_RUN)
|
||||
|
||||
#if (USB_DEVICE_CLASS_CONFIG & CDC_CLASS)
|
||||
#error "CDC_CLASS and TCFG_COMM_TYPE==TCFG_USB_COMM 不能同时打开"
|
||||
#else
|
||||
#undef TCFG_USB_SLAVE_CDC_ENABLE
|
||||
#define TCFG_USB_SLAVE_CDC_ENABLE 1
|
||||
#endif
|
||||
#undef TCFG_USB_SLAVE_ENABLE
|
||||
#define TCFG_USB_SLAVE_ENABLE 1
|
||||
|
||||
#if (!TCFG_PC_ENABLE)
|
||||
#undef TCFG_OTG_MODE
|
||||
#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST | OTG_SLAVE_MODE | TCFG_OTG_MODE_CHARGE)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,354 @@
|
||||
#include "usb_config.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "irq.h"
|
||||
#include "init.h"
|
||||
#include "gpio.h"
|
||||
#include "timer.h"
|
||||
#include "app_config.h"
|
||||
#include "lbuf.h"
|
||||
|
||||
#ifdef CONFIG_ADAPTER_ENABLE
|
||||
#include "adapter_usb_hid.h"
|
||||
#endif//CONFIG_ADAPTER_ENABLE
|
||||
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#define SET_INTERRUPT ___interrupt
|
||||
|
||||
|
||||
#define MAX_EP_TX 5
|
||||
#define MAX_EP_RX 5
|
||||
|
||||
static usb_interrupt usb_interrupt_tx[USB_MAX_HW_NUM][MAX_EP_TX];// SEC(.usb_g_bss);
|
||||
static usb_interrupt usb_interrupt_rx[USB_MAX_HW_NUM][MAX_EP_RX];// SEC(.usb_h_bss);
|
||||
|
||||
static u8 ep0_dma_buffer[EP0_SETUP_LEN] __attribute__((aligned(4))) SEC(.usb_ep0) ;
|
||||
|
||||
#if TCFG_USB_SLAVE_MSD_ENABLE
|
||||
#define MSD_DMA_SIZE (MAXP_SIZE_BULKOUT + MAXP_SIZE_BULKIN)
|
||||
#else
|
||||
#define MSD_DMA_SIZE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_HID_ENABLE
|
||||
#define HID_DMA_SIZE 64
|
||||
#else
|
||||
#define HID_DMA_SIZE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_AUDIO_ENABLE
|
||||
#define AUDIO_DMA_SIZE 256+192
|
||||
#else
|
||||
#define AUDIO_DMA_SIZE 0
|
||||
#endif
|
||||
|
||||
#if TCFG_USB_SLAVE_CDC_ENABLE
|
||||
#if CDC_INTR_EP_ENABLE
|
||||
#define CDC_DMA_SIZE (64*3)
|
||||
#else
|
||||
#define CDC_DMA_SIZE (64*2)
|
||||
#endif
|
||||
#else
|
||||
#define CDC_DMA_SIZE 0
|
||||
#endif
|
||||
|
||||
struct usb_config_var_t {
|
||||
u8 usb_setup_buffer[USB_SETUP_SIZE];
|
||||
struct usb_ep_addr_t usb_ep_addr;
|
||||
struct usb_setup_t usb_setup;
|
||||
};
|
||||
static struct usb_config_var_t *usb_config_var = {NULL};
|
||||
|
||||
#if USB_MALLOC_ENABLE
|
||||
#else
|
||||
static struct usb_config_var_t _usb_config_var SEC(.usb_config_var);
|
||||
#endif
|
||||
|
||||
|
||||
#define USB_DMA_BUF_ALIGN (8)
|
||||
#ifndef USB_DMA_BUF_MAX_SIZE
|
||||
#define USB_DMA_BUF_MAX_SIZE (HID_DMA_SIZE +USB_DMA_BUF_ALIGN+ AUDIO_DMA_SIZE +USB_DMA_BUF_ALIGN+ MSD_DMA_SIZE*2 + USB_DMA_BUF_ALIGN+CDC_DMA_SIZE + USB_DMA_BUF_ALIGN + 100)
|
||||
#endif//USB_DMA_BUF_MAX_SIZE
|
||||
|
||||
static u8 usb_dma_buf[USB_DMA_BUF_MAX_SIZE] SEC(.usb_msd_dma) __attribute__((aligned(8)));
|
||||
struct lbuff_head *usb_dma_lbuf = NULL;
|
||||
void usb_memory_init()
|
||||
{
|
||||
usb_dma_lbuf = lbuf_init(usb_dma_buf, sizeof(usb_dma_buf), USB_DMA_BUF_ALIGN, 0);
|
||||
log_info("%s() total dma size %x @%x", __func__, sizeof(usb_dma_buf), usb_dma_buf);
|
||||
}
|
||||
|
||||
__attribute__((always_inline_when_const_args))
|
||||
void *usb_alloc_ep_dmabuffer(const usb_dev usb_id, u32 ep, u32 dma_size)
|
||||
{
|
||||
u8 *ep_buffer = NULL;
|
||||
u32 _ep = ep & 0xf;
|
||||
if (ep & USB_DIR_IN) {
|
||||
switch (_ep) {
|
||||
case 0:
|
||||
ep_buffer = ep0_dma_buffer;
|
||||
break;
|
||||
default :
|
||||
ep_buffer = lbuf_alloc(usb_dma_lbuf, dma_size);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (_ep) {
|
||||
case 0:
|
||||
ep_buffer = ep0_dma_buffer;
|
||||
break;
|
||||
default :
|
||||
ep_buffer = lbuf_alloc(usb_dma_lbuf, dma_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(ep_buffer, "usb_alloc_ep_dmabuffer ep_buffer = NULL!!!, _ep = %x, dma_size = %d\n", ep, dma_size);
|
||||
|
||||
log_info("ep_buffer = %x, ep = %x, dma_size = %d\n", ep_buffer, ep, dma_size);
|
||||
|
||||
return ep_buffer;
|
||||
}
|
||||
|
||||
|
||||
static u8 sleep_flag = 0;
|
||||
u8 get_sleep_flag()
|
||||
{
|
||||
return sleep_flag ;
|
||||
}
|
||||
|
||||
void set_sleep_flag(u8 sl_flag)
|
||||
{
|
||||
sleep_flag = sl_flag ;
|
||||
}
|
||||
|
||||
static void usb_resume_sign(void *priv)
|
||||
{
|
||||
usb_dev usb_id = usb_device2id(priv);
|
||||
u32 reg = usb_read_power(usb_id);
|
||||
usb_write_power(usb_id, reg | BIT(2));//send resume
|
||||
os_time_dly(2);//10ms~20ms
|
||||
usb_write_power(usb_id, reg);//clean resume
|
||||
}
|
||||
|
||||
void usb_remote_wakeup(const usb_dev usb_id)
|
||||
{
|
||||
struct usb_device_t *usb_device = usb_id2device(usb_id);
|
||||
if (usb_device->bRemoteWakup) {
|
||||
sys_timeout_add(usb_device, usb_resume_sign, 1);
|
||||
}
|
||||
}
|
||||
void usb_phy_resume(const usb_dev usb_id)
|
||||
{
|
||||
usb_iomode(0);
|
||||
|
||||
struct usb_device_t *usb_device = usb_id2device(usb_id);
|
||||
usb_write_faddr(usb_id, usb_device->baddr);
|
||||
|
||||
if (usb_device->baddr == 0) {
|
||||
usb_device->bDeviceStates = USB_DEFAULT;
|
||||
} else {
|
||||
usb_device->bDeviceStates = USB_CONFIGURED;
|
||||
}
|
||||
|
||||
usb_otg_resume(usb_id);
|
||||
}
|
||||
|
||||
void usb_phy_suspend(const usb_dev usb_id)
|
||||
{
|
||||
gpio_set_pull_up(IO_PORT_DP, 1);
|
||||
gpio_set_pull_down(IO_PORT_DP, 0);
|
||||
gpio_set_direction(IO_PORT_DP, 1);
|
||||
|
||||
usb_iomode(1);
|
||||
/* musb_read_usb(0, MUSB_INTRUSB); */
|
||||
|
||||
usb_otg_suspend(usb_id, OTG_KEEP_STATE);
|
||||
}
|
||||
void usb_isr(const usb_dev usb_id)
|
||||
{
|
||||
u32 intr_usb, intr_usbe;
|
||||
u32 intr_tx, intr_txe;
|
||||
u32 intr_rx, intr_rxe;
|
||||
|
||||
__asm__ volatile("ssync");
|
||||
usb_read_intr(usb_id, &intr_usb, &intr_tx, &intr_rx);
|
||||
usb_read_intre(usb_id, &intr_usbe, &intr_txe, &intr_rxe);
|
||||
struct usb_device_t *usb_device = usb_id2device(usb_id);
|
||||
|
||||
intr_usb &= intr_usbe;
|
||||
intr_tx &= intr_txe;
|
||||
intr_rx &= intr_rxe;
|
||||
|
||||
if (intr_usb & INTRUSB_SUSPEND) {
|
||||
log_error("usb suspend");
|
||||
set_sleep_flag(1);
|
||||
#if USB_SUSPEND_RESUME
|
||||
usb_phy_suspend(usb_id);
|
||||
#endif
|
||||
|
||||
#if USB_SUSPEND_RESUME_SYSTEM_NO_SLEEP
|
||||
printf("\n NULL \n");
|
||||
#endif
|
||||
}
|
||||
if (intr_usb & INTRUSB_RESET_BABBLE) {
|
||||
log_error("usb reset");
|
||||
usb_reset_interface(usb_device);
|
||||
|
||||
#if USB_SUSPEND_RESUME || USB_SUSPEND_RESUME_SYSTEM_NO_SLEEP
|
||||
u32 reg = usb_read_power(usb_id);
|
||||
usb_write_power(usb_id, (reg | INTRUSB_SUSPEND | INTRUSB_RESUME));//enable suspend resume
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intr_usb & INTRUSB_RESUME) {
|
||||
log_error("usb resume");
|
||||
#if USB_SUSPEND_RESUME
|
||||
usb_phy_resume(usb_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intr_tx & BIT(0)) {
|
||||
if (usb_interrupt_rx[usb_id][0]) {
|
||||
usb_interrupt_rx[usb_id][0](usb_device, 0);
|
||||
} else {
|
||||
usb_control_transfer(usb_device);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < MAX_EP_TX; i++) {
|
||||
if (intr_tx & BIT(i)) {
|
||||
if (usb_interrupt_tx[usb_id][i]) {
|
||||
usb_interrupt_tx[usb_id][i](usb_device, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < MAX_EP_RX; i++) {
|
||||
if (intr_rx & BIT(i)) {
|
||||
if (usb_interrupt_rx[usb_id][i]) {
|
||||
usb_interrupt_rx[usb_id][i](usb_device, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
__asm__ volatile("csync");
|
||||
}
|
||||
|
||||
void usb_sof_isr(const usb_dev usb_id)
|
||||
{
|
||||
usb_sof_clr_pnd(usb_id);
|
||||
static u32 sof_count = 0;
|
||||
if ((sof_count++ % 1000) == 0) {
|
||||
log_d("sof 1s isr frame:%d", usb_read_sofframe(usb_id));
|
||||
}
|
||||
}
|
||||
void usb_suspend_check(void *p)
|
||||
{
|
||||
usb_dev usb_id = (usb_dev)p;
|
||||
|
||||
static u16 sof_frame = 0;
|
||||
u16 frame = usb_read_sofframe(usb_id);// sof frame 不更新,则usb进入断开或者suspend状态
|
||||
if (frame == sof_frame) {
|
||||
usb_phy_suspend(usb_id);
|
||||
}
|
||||
sof_frame = frame;
|
||||
}
|
||||
|
||||
SET_INTERRUPT
|
||||
void usb0_g_isr()
|
||||
{
|
||||
usb_isr(0);
|
||||
}
|
||||
SET_INTERRUPT
|
||||
void usb0_sof_isr()
|
||||
{
|
||||
usb_sof_isr(0);
|
||||
}
|
||||
|
||||
#if USB_MAX_HW_NUM == 2
|
||||
SET_INTERRUPT
|
||||
void usb1_g_isr()
|
||||
{
|
||||
usb_isr(1);
|
||||
}
|
||||
SET_INTERRUPT
|
||||
void usb1_sof_isr()
|
||||
{
|
||||
usb_sof_isr(1);
|
||||
}
|
||||
#endif
|
||||
__attribute__((always_inline_when_const_args))
|
||||
u32 usb_g_set_intr_hander(const usb_dev usb_id, u32 ep, usb_interrupt hander)
|
||||
{
|
||||
if (ep & USB_DIR_IN) {
|
||||
usb_interrupt_tx[usb_id][ep & 0xf] = hander;
|
||||
} else {
|
||||
usb_interrupt_rx[usb_id][ep] = hander;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void usb_g_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id)
|
||||
{
|
||||
if (usb_id == 0) {
|
||||
request_irq(IRQ_USB_CTRL_IDX, priority, usb0_g_isr, cpu_id);
|
||||
} else {
|
||||
#if USB_MAX_HW_NUM == 2
|
||||
request_irq(IRQ_USB1_CTRL_IDX, priority, usb1_g_isr, cpu_id);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void usb_sof_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id)
|
||||
{
|
||||
if (usb_id == 0) {
|
||||
request_irq(IRQ_USB_SOF_IDX, priority, usb0_sof_isr, cpu_id);
|
||||
} else {
|
||||
#if USB_MAX_HW_NUM == 2
|
||||
request_irq(IRQ_USB1_SOF_IDX, priority, usb1_sof_isr, cpu_id);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
u32 usb_config(const usb_dev usb_id)
|
||||
{
|
||||
memset(usb_interrupt_rx[usb_id], 0, sizeof(usb_interrupt_rx[usb_id]));
|
||||
memset(usb_interrupt_tx[usb_id], 0, sizeof(usb_interrupt_tx[usb_id]));
|
||||
|
||||
if (!usb_config_var) {
|
||||
#if USB_MALLOC_ENABLE
|
||||
usb_config_var = (struct usb_config_var_t *)zalloc(sizeof(struct usb_config_var_t));
|
||||
if (!usb_config_var) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
memset(&_usb_config_var, 0, sizeof(_usb_config_var));
|
||||
usb_config_var = &_usb_config_var;
|
||||
#endif
|
||||
}
|
||||
log_debug("zalloc: usb_config_var = %x\n", usb_config_var);
|
||||
|
||||
usb_var_init(usb_id, &(usb_config_var->usb_ep_addr));
|
||||
usb_setup_init(usb_id, &(usb_config_var->usb_setup), usb_config_var->usb_setup_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 usb_release(const usb_dev usb_id)
|
||||
{
|
||||
log_debug("free zalloc: usb_config_var = %x\n", usb_id, usb_config_var);
|
||||
usb_var_init(usb_id, NULL);
|
||||
usb_setup_init(usb_id, NULL, NULL);
|
||||
#if USB_MALLOC_ENABLE
|
||||
if (usb_config_var) {
|
||||
log_debug("free: usb_config_var = %x\n", usb_config_var);
|
||||
free(usb_config_var);
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_config_var = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/**@file usb_config.h
|
||||
* @brief usb_config配置头文件
|
||||
* @details 功能函数声明
|
||||
* @author jieli
|
||||
* @date 2021-8-1
|
||||
* @version V1.0
|
||||
* @copyright Copyright(c)2010-2021 珠海市杰理科技股份有限公司
|
||||
*********************************************************
|
||||
* @attention
|
||||
* 硬件平台:AC695N
|
||||
* SDK版本:AC695N_V1.0.0_SDK
|
||||
* @修改日志:
|
||||
* <table>
|
||||
* <tr><th>Date <th>Version <th>Author <th>Description
|
||||
* <tr><td>2021-8-1 <td>1.0 <td>jieli <td>创建初始版本
|
||||
* </table>
|
||||
*
|
||||
*********************************************************
|
||||
*/
|
||||
#ifndef __USB_CONFIG_H__
|
||||
#define __USB_CONFIG_H__
|
||||
|
||||
#include "typedef.h"
|
||||
#include "asm/usb.h"
|
||||
#include "usb/device/usb_stack.h"
|
||||
#include "usb/host/usb_host.h"
|
||||
|
||||
/**@brief USB主机模式配置
|
||||
* @param[in] usb_id USB的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_host_config(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
void usb_host_config(usb_dev usb_id);
|
||||
|
||||
/**@brief USB主机模式释放
|
||||
* @param[in] usb_id USB的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_host_free(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
void usb_host_free(usb_dev usb_id);
|
||||
|
||||
/**@brief USB主机模式获取端点的BUFFER的地址
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] ep 端点号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_h_get_ep_bufeeer(usb_id , ep);
|
||||
* @encode
|
||||
*/
|
||||
void *usb_h_get_ep_buffer(const usb_dev usb_id, u32 ep);
|
||||
|
||||
/**@brief USB主机模式中断注册
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] priority 优先级
|
||||
* @param[in] cpu_id cpu的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_h_isr_reg(usb_id , ep);
|
||||
* @encode
|
||||
*/
|
||||
void usb_h_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id);
|
||||
|
||||
/**@brief USB从机模式中断注册
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] priority 优先级
|
||||
* @param[in] cpu_id cpu的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_g_isr_reg(usb_id , ep);
|
||||
* @encode
|
||||
*/
|
||||
void usb_g_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id);
|
||||
|
||||
|
||||
|
||||
/**@brief USB SOF中断注册
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] priority 优先级
|
||||
* @param[in] cpu_id cpu的id号
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_sof_isr_reg(usb_id , ep);
|
||||
* @encode
|
||||
*/
|
||||
void usb_sof_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id);
|
||||
|
||||
/**@brief 分配端点BUFFER的dma地址
|
||||
* @param[in] usb_id USB的id号
|
||||
* @param[in] ep 端点号
|
||||
* @param[in] dma_size 数据长度
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_alloc_ep_dmabuffer(usb_id , ep , size);
|
||||
* @encode
|
||||
*/
|
||||
void *usb_alloc_ep_dmabuffer(const usb_dev usb_id, u32 ep, u32 dma_size);
|
||||
|
||||
/**@brief USB从机初始化配置
|
||||
* @param[in] usb_id USB的id号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_config(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
u32 usb_config(const usb_dev usb_id);
|
||||
|
||||
/**@brief USB从机释放
|
||||
* @param[in] usb_id USB的id号
|
||||
* @return 0:成功
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_release(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
u32 usb_release(const usb_dev usb_id);
|
||||
|
||||
/**@brief USB内存空间初始化
|
||||
* @param[in] 无
|
||||
* @return 无
|
||||
* @par 示例:
|
||||
* @code
|
||||
* usb_memory_init(usb_id);
|
||||
* @encode
|
||||
*/
|
||||
void usb_memory_init();
|
||||
|
||||
#endif /*USB_CONFIG_H*/
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "usb_config.h"
|
||||
#include "usb/scsi.h"
|
||||
#include "irq.h"
|
||||
#include "init.h"
|
||||
#include "gpio.h"
|
||||
#include "app_config.h"
|
||||
#define LOG_TAG_CONST USB
|
||||
#define LOG_TAG "[USB]"
|
||||
#define LOG_ERROR_ENABLE
|
||||
#define LOG_DEBUG_ENABLE
|
||||
#define LOG_INFO_ENABLE
|
||||
/* #define LOG_DUMP_ENABLE */
|
||||
#define LOG_CLI_ENABLE
|
||||
#include "debug.h"
|
||||
|
||||
#define SET_INTERRUPT ___interrupt
|
||||
|
||||
#if TCFG_UDISK_ENABLE || TCFG_ADB_ENABLE ||TCFG_AOA_ENABLE || TCFG_HID_HOST_ENABLE || TCFG_HOST_AUDIO_ENABLE
|
||||
|
||||
#if TCFG_HID_HOST_ENABLE
|
||||
#define MAX_HOST_EP_RX 4
|
||||
#define MAX_HOST_EP_TX 4
|
||||
#else
|
||||
#define MAX_HOST_EP_RX 2
|
||||
#define MAX_HOST_EP_TX 2 //ep0 & ep1(msd)
|
||||
#endif
|
||||
|
||||
struct host_var_t {
|
||||
struct usb_ep_addr_t host_ep_addr ;
|
||||
usb_h_interrupt usb_h_interrupt_rx[MAX_HOST_EP_RX] ;
|
||||
usb_h_interrupt usb_h_interrupt_tx[MAX_HOST_EP_TX] ;
|
||||
struct usb_host_device *dev_at_ep[MAX_HOST_EP_RX];
|
||||
};
|
||||
static struct host_var_t *host_var[USB_MAX_HW_NUM];// SEC(.usb_h_bss);
|
||||
static struct host_var_t __host_var[USB_MAX_HW_NUM];
|
||||
#if TCFG_ADB_ENABLE && TCFG_AOA_ENABLE && TCFG_HID_HOST_ENABLE
|
||||
static u8 ep0_dma[USB_MAX_HW_NUM][64 + 4] __attribute__((aligned(4)));
|
||||
static u8 ep1_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4)));
|
||||
static u8 ep2_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4)));
|
||||
static u8 ep3_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4)));
|
||||
static u8 ep4_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4)));
|
||||
#else
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
static u8 msd_h_dma_buffer[2][64 + 4] __attribute__((aligned(4))) SEC(.usb_h_dma);
|
||||
#elif defined(FUSB_MODE) && (FUSB_MODE == 0)
|
||||
static u8 msd_h_dma_buffer[2][512] __attribute__((aligned(4))) SEC(.usb_h_dma);
|
||||
#else
|
||||
#error "USB_SPEED_MODE not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void usb_h_isr(const usb_dev usb_id)
|
||||
{
|
||||
u32 intr_usb, intr_usbe;
|
||||
u32 intr_tx, intr_txe;
|
||||
u32 intr_rx, intr_rxe;
|
||||
|
||||
__asm__ volatile("ssync");
|
||||
|
||||
usb_read_intr(usb_id, &intr_usb, &intr_tx, &intr_rx);
|
||||
usb_read_intre(usb_id, &intr_usbe, &intr_txe, &intr_rxe);
|
||||
struct usb_host_device *host_dev = NULL;
|
||||
|
||||
/* r_printf("usb_h_isr %x %x %x %x",host_dev,intr_usb,intr_tx,intr_rx); */
|
||||
intr_usb &= intr_usbe;
|
||||
intr_tx &= intr_txe;
|
||||
intr_rx &= intr_rxe;
|
||||
|
||||
if (intr_usb & INTRUSB_SUSPEND) {
|
||||
log_error("usb suspend");
|
||||
}
|
||||
if (intr_usb & INTRUSB_RESET_BABBLE) {
|
||||
log_error("usb reset");
|
||||
}
|
||||
if (intr_usb & INTRUSB_RESUME) {
|
||||
log_error("usb resume");
|
||||
}
|
||||
|
||||
if (intr_tx & BIT(0)) {
|
||||
if (host_var[usb_id]->usb_h_interrupt_tx[0]) {
|
||||
host_dev = host_var[usb_id]->dev_at_ep[0];
|
||||
host_var[usb_id]->usb_h_interrupt_tx[0](host_dev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < MAX_HOST_EP_TX; i++) {
|
||||
if (intr_tx & BIT(i)) {
|
||||
if (host_var[usb_id]->usb_h_interrupt_tx[i]) {
|
||||
host_dev = host_var[usb_id]->dev_at_ep[i];
|
||||
host_var[usb_id]->usb_h_interrupt_tx[i](host_dev, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i < MAX_HOST_EP_RX; i++) {
|
||||
if (intr_rx & BIT(i)) {
|
||||
if (host_var[usb_id]->usb_h_interrupt_rx[i]) {
|
||||
host_dev = host_var[usb_id]->dev_at_ep[i];
|
||||
host_var[usb_id]->usb_h_interrupt_rx[i](host_dev, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
__asm__ volatile("csync");
|
||||
}
|
||||
SET_INTERRUPT
|
||||
void usb0_h_isr()
|
||||
{
|
||||
usb_h_isr(0);
|
||||
}
|
||||
SET_INTERRUPT
|
||||
void usb1_h_isr()
|
||||
{
|
||||
usb_h_isr(1);
|
||||
}
|
||||
__attribute__((always_inline_when_const_args))
|
||||
u32 usb_h_set_intr_hander(const usb_dev usb_id, u32 ep, usb_h_interrupt hander)
|
||||
{
|
||||
if (ep & USB_DIR_IN) {
|
||||
host_var[usb_id]->usb_h_interrupt_rx[ep & 0xf] = hander;
|
||||
} else {
|
||||
host_var[usb_id]->usb_h_interrupt_tx[ep] = hander;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void usb_h_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id)
|
||||
{
|
||||
if (usb_id == 0) {
|
||||
request_irq(IRQ_USB_CTRL_IDX, priority, usb0_h_isr, cpu_id);
|
||||
#if USB_MAX_HW_NUM > 1
|
||||
} else if (usb_id == 1) {
|
||||
request_irq(IRQ_USB1_CTRL_IDX, priority, usb1_h_isr, cpu_id);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline_when_const_args))
|
||||
void *usb_h_get_ep_buffer(const usb_dev usb_id, u32 ep)
|
||||
{
|
||||
#if TCFG_ADB_ENABLE && TCFG_AOA_ENABLE && TCFG_HID_HOST_ENABLE
|
||||
u8 dir = !!(ep & USB_DIR_IN);
|
||||
u8 *p = NULL;
|
||||
switch (ep & 0xf) {
|
||||
case 0:
|
||||
p = &ep0_dma[usb_id][0];
|
||||
break;
|
||||
case 1:
|
||||
p = &ep1_dma[usb_id][dir * 64];
|
||||
break;
|
||||
case 2:
|
||||
p = &ep2_dma[usb_id][dir * 64];
|
||||
break;
|
||||
case 3:
|
||||
p = &ep3_dma[usb_id][dir * 64];
|
||||
break;
|
||||
case 4:
|
||||
p = &ep4_dma[usb_id][dir * 64];
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
#else
|
||||
return msd_h_dma_buffer;
|
||||
#endif
|
||||
}
|
||||
void usb_h_set_ep_isr(struct usb_host_device *host_dev, u32 ep, usb_h_interrupt hander, void *p)
|
||||
{
|
||||
if (host_dev) {
|
||||
usb_dev usb_id = host_device2id(host_dev);
|
||||
host_var[usb_id]->dev_at_ep[ep & 0xf] = p;
|
||||
usb_h_set_intr_hander(usb_id, ep, hander);
|
||||
}
|
||||
}
|
||||
void usb_host_config(usb_dev usb_id)
|
||||
{
|
||||
/* host_var[usb_id] = zalloc(sizeof(struct host_var_t)); */
|
||||
host_var[usb_id] = &__host_var[usb_id];
|
||||
|
||||
ASSERT(host_var[usb_id], "host_var_t");
|
||||
|
||||
g_printf("%s() %x %x", __func__, host_var[usb_id], &(host_var[usb_id]->host_ep_addr));
|
||||
usb_var_init(usb_id, &(host_var[usb_id]->host_ep_addr));
|
||||
}
|
||||
void usb_host_free(usb_dev usb_id)
|
||||
{
|
||||
g_printf("%s() %x", __func__, host_var[usb_id]);
|
||||
OS_ENTER_CRITICAL();
|
||||
/* free(host_var[usb_id]); */
|
||||
/* host_var[usb_id] = NULL; */
|
||||
if (host_var[usb_id]) {
|
||||
memset(host_var[usb_id]->usb_h_interrupt_rx, 0, sizeof(usb_h_interrupt) * MAX_HOST_EP_RX);
|
||||
memset(host_var[usb_id]->usb_h_interrupt_tx, 0, sizeof(usb_h_interrupt) * MAX_HOST_EP_TX);
|
||||
}
|
||||
OS_EXIT_CRITICAL();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,190 @@
|
||||
#ifndef __USB_STD_CLASS_DEF_H__
|
||||
#define __USB_STD_CLASS_DEF_H__
|
||||
|
||||
#ifndef USB_MALLOC_ENABLE
|
||||
#define USB_MALLOC_ENABLE 0
|
||||
#endif
|
||||
#ifndef USB_HOST_ASYNC
|
||||
#define USB_HOST_ASYNC 1
|
||||
#endif
|
||||
#ifndef USB_H_MALLOC_ENABLE
|
||||
#define USB_H_MALLOC_ENABLE 1
|
||||
#endif
|
||||
#ifndef USB_DEVICE_CLASS_CONFIG
|
||||
#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS|MASSSTORAGE_CLASS)
|
||||
#endif
|
||||
|
||||
///////////MassStorage Class
|
||||
#ifndef MSD_BULK_EP_OUT
|
||||
#define MSD_BULK_EP_OUT 1
|
||||
#endif
|
||||
#ifndef MSD_BULK_EP_IN
|
||||
#define MSD_BULK_EP_IN 1
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_BULKOUT
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
#define MAXP_SIZE_BULKOUT 64
|
||||
#elif defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
#define MAXP_SIZE_BULKOUT 512
|
||||
#endif
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_BULKIN
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
#define MAXP_SIZE_BULKIN 64
|
||||
#elif defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
#define MAXP_SIZE_BULKIN 512
|
||||
#endif
|
||||
#endif
|
||||
#ifndef MSD_STR_INDEX
|
||||
#define MSD_STR_INDEX 7
|
||||
#endif
|
||||
|
||||
///////////HID class
|
||||
#ifndef HID_EP_IN
|
||||
#define HID_EP_IN 2
|
||||
#endif
|
||||
#ifndef HID_EP_OUT
|
||||
#define HID_EP_OUT 2
|
||||
#endif
|
||||
#ifndef HID_EP_IN_2
|
||||
#define HID_EP_IN_2 3
|
||||
#endif
|
||||
#ifndef HID_EP_OUT_2
|
||||
#define HID_EP_OUT_2 3
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_HIDOUT
|
||||
#define MAXP_SIZE_HIDOUT 16
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_HIDIN
|
||||
#define MAXP_SIZE_HIDIN 16
|
||||
#endif
|
||||
#ifndef HID_INTR_INTERVAL
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
#define HID_INTR_INTERVAL 1
|
||||
#elif defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
#define HID_INTR_INTERVAL 4
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/////////////Audio Class
|
||||
#ifndef UAC_ISO_INTERVAL
|
||||
#if defined(FUSB_MODE) && FUSB_MODE
|
||||
#define UAC_ISO_INTERVAL 1
|
||||
#elif defined(FUSB_MODE) && FUSB_MODE == 0
|
||||
#define UAC_ISO_INTERVAL 4
|
||||
#endif
|
||||
#endif
|
||||
//speaker class
|
||||
#ifndef SPK_AUDIO_RATE
|
||||
#define SPK_AUDIO_RATE 48000
|
||||
#endif
|
||||
#ifndef SPK_AUDIO_RES
|
||||
#define SPK_AUDIO_RES 16
|
||||
#endif
|
||||
#ifndef SPK_CHANNEL
|
||||
#define SPK_CHANNEL 2
|
||||
#endif
|
||||
#ifndef SPK_FRAME_LEN
|
||||
#define SPK_FRAME_LEN (((SPK_AUDIO_RATE) * SPK_AUDIO_RES / 8 * SPK_CHANNEL)/1000+4)
|
||||
#endif
|
||||
#ifndef SPK_PCM_Type
|
||||
#define SPK_PCM_Type (SPK_AUDIO_RES >> 4) // 0=8 ,1=16
|
||||
#endif
|
||||
#ifndef SPK_AUDIO_TYPE
|
||||
#define SPK_AUDIO_TYPE (0x02 - SPK_PCM_Type) // TYPE1_PCM16
|
||||
#endif
|
||||
#ifndef SPK_ISO_EP_OUT
|
||||
#ifdef CONFIG_CPU_BR18
|
||||
#define SPK_ISO_EP_OUT 2
|
||||
#else
|
||||
#define SPK_ISO_EP_OUT 3
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SPEAKER_STR_INDEX
|
||||
#define SPEAKER_STR_INDEX 5
|
||||
#endif
|
||||
#ifndef SPK_INPUT_TERMINAL_ID
|
||||
#define SPK_INPUT_TERMINAL_ID 1
|
||||
#endif
|
||||
#ifndef SPK_FEATURE_UNIT_ID
|
||||
#define SPK_FEATURE_UNIT_ID 2
|
||||
#endif
|
||||
#ifndef SPK_OUTPUT_TERMINAL_ID
|
||||
#define SPK_OUTPUT_TERMINAL_ID 3
|
||||
#endif
|
||||
#ifndef SPK_SELECTOR_UNIT_ID
|
||||
#define SPK_SELECTOR_UNIT_ID 8
|
||||
#endif
|
||||
|
||||
/////////////Microphone Class
|
||||
#ifndef MIC_SamplingFrequency
|
||||
#define MIC_SamplingFrequency 1
|
||||
#endif
|
||||
|
||||
#if MIC_SamplingFrequency == 1
|
||||
#define MIC_AUDIO_RATE 48000
|
||||
#else
|
||||
#define MIC_AUDIO_RATE 192000
|
||||
#define MIC_AUDIO_RATE_1 44100
|
||||
#define MIC_AUDIO_RATE_2 48000
|
||||
#define MIC_AUDIO_RATE_4 96000
|
||||
#endif
|
||||
|
||||
#ifndef MIC_AUDIO_RES
|
||||
#define MIC_AUDIO_RES 16
|
||||
#endif
|
||||
#ifndef MIC_CHANNEL
|
||||
#define MIC_CHANNEL 1
|
||||
#endif
|
||||
#ifndef MIC_FRAME_LEN
|
||||
#define MIC_FRAME_LEN ((MIC_AUDIO_RATE * MIC_AUDIO_RES / 8 * MIC_CHANNEL)/1000)
|
||||
#endif
|
||||
#ifndef MIC_PCM_TYPE
|
||||
#define MIC_PCM_TYPE (MIC_AUDIO_RES >> 4) // 0=8 ,1=16
|
||||
#endif
|
||||
#ifndef MIC_AUDIO_TYPE
|
||||
#define MIC_AUDIO_TYPE (0x02 - MIC_PCM_TYPE)
|
||||
#endif
|
||||
#ifndef MIC_ISO_EP_IN
|
||||
#define MIC_ISO_EP_IN 3
|
||||
#endif
|
||||
#ifndef MIC_STR_INDEX
|
||||
#define MIC_STR_INDEX 6
|
||||
#endif
|
||||
#ifndef MIC_INPUT_TERMINAL_ID
|
||||
#define MIC_INPUT_TERMINAL_ID 4
|
||||
#endif
|
||||
#ifndef MIC_FEATURE_UNIT_ID
|
||||
#define MIC_FEATURE_UNIT_ID 5
|
||||
#endif
|
||||
#ifndef MIC_OUTPUT_TERMINAL_ID
|
||||
#define MIC_OUTPUT_TERMINAL_ID 6
|
||||
#endif
|
||||
#ifndef MIC_SELECTOR_UNIT_ID
|
||||
#define MIC_SELECTOR_UNIT_ID 7
|
||||
#endif
|
||||
|
||||
////////////CDC Class
|
||||
#ifndef CDC_DATA_EP_IN
|
||||
#define CDC_DATA_EP_IN 4
|
||||
#endif
|
||||
#ifndef CDC_DATA_EP_OUT
|
||||
#define CDC_DATA_EP_OUT 4
|
||||
#endif
|
||||
#ifndef CDC_INTR_EP_IN
|
||||
#define CDC_INTR_EP_IN 5
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_CDC_BULKIN
|
||||
#define MAXP_SIZE_CDC_BULKIN 64
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_CDC_BULKOUT
|
||||
#define MAXP_SIZE_CDC_BULKOUT 64
|
||||
#endif
|
||||
#ifndef MAXP_SIZE_CDC_INTRIN
|
||||
#define MAXP_SIZE_CDC_INTRIN 8
|
||||
#endif
|
||||
#ifndef CDC_INTR_EP_ENABLE
|
||||
#define CDC_INTR_EP_ENABLE 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,327 @@
|
||||
#include "includes.h"
|
||||
#include "boot.h"
|
||||
#include "asm/sfc_norflash_api.h"
|
||||
#include "cfg_private.h"
|
||||
/* #include "sdfile.h" */
|
||||
|
||||
#define CFG_PRIVATE_FILE_NUM 5
|
||||
SDFILE_FILE_HEAD head = {0};
|
||||
static u8 cfg_private_create_flag = 0;
|
||||
static u32 cfg_private_create_sclust = 0;
|
||||
|
||||
|
||||
static FILE *cfg_private_create(const char *path, const char *mode)
|
||||
{
|
||||
int i = 0;
|
||||
char *str = NULL;
|
||||
char *part_path = NULL;
|
||||
char *buf_temp = NULL;
|
||||
int file_head_len = 0;
|
||||
int align_size = 4096;
|
||||
if (boot_info.vm.align == 1) {
|
||||
align_size = 256;
|
||||
}
|
||||
|
||||
str = strrchr(path, '/');
|
||||
/* r_printf(">>>[test]:file name str = %s\n", str + 1); */
|
||||
part_path = (char *)zalloc(strlen(path));
|
||||
memcpy(part_path, path, strlen(path) - strlen(str));
|
||||
/* r_printf(">>>[test]:part_path = %s\n", part_path); */
|
||||
FILE *file = fopen(part_path, "r");
|
||||
if (!file) {
|
||||
r_printf(">>>[test]:no apply part!!!!!!!\n");
|
||||
goto __exit;
|
||||
}
|
||||
struct vfs_attr attrs = {0};
|
||||
fget_attrs(file, &attrs);
|
||||
attrs.sclust = sdfile_cpu_addr2flash_addr(attrs.sclust);
|
||||
if (attrs.sclust % align_size) {
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
r_printf(">>>[test]:part start addr is not alignment, sclust = %d, align_size = %d\n", attrs.sclust, align_size);
|
||||
goto __exit;
|
||||
}
|
||||
cfg_private_create_sclust = attrs.sclust;
|
||||
buf_temp = (char *)malloc(align_size);
|
||||
norflash_read(NULL, (void *)buf_temp, align_size, attrs.sclust);
|
||||
for (; i < CFG_PRIVATE_FILE_NUM; i++) {
|
||||
int addr = attrs.sclust + i * sizeof(SDFILE_FILE_HEAD);
|
||||
norflash_read(NULL, (void *)&head, sizeof(SDFILE_FILE_HEAD), addr);
|
||||
if (CRC16((u8 *)&head + 2, sizeof(SDFILE_FILE_HEAD) - 2) == head.head_crc) {
|
||||
file_head_len += head.len;
|
||||
continue;
|
||||
}
|
||||
memset(&head, 0, sizeof(SDFILE_FILE_HEAD));
|
||||
head.len = attrs.fsize - CFG_PRIVATE_FILE_NUM * sizeof(SDFILE_FILE_HEAD) - file_head_len;
|
||||
/* y_printf(">>>[test]:file len = %d\n", head.len); */
|
||||
head.addr = attrs.sclust + CFG_PRIVATE_FILE_NUM * sizeof(SDFILE_FILE_HEAD) + file_head_len;
|
||||
head.addr = sdfile_flash_addr2cpu_addr(head.addr);
|
||||
/* y_printf(">>>[test]:file addr = %d\n", head.addr); */
|
||||
memcpy(head.name, (char *)(str + 1), strlen(str + 1));
|
||||
head.attr = 0x02;
|
||||
head.head_crc = CRC16((u8 *)&head + 2, sizeof(SDFILE_FILE_HEAD) - 2);
|
||||
break;
|
||||
}
|
||||
if (i >= CFG_PRIVATE_FILE_NUM) {
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
r_printf(">>>[test]:file head is over\n");
|
||||
goto __exit;
|
||||
}
|
||||
cfg_private_erase(attrs.sclust, align_size);
|
||||
memcpy(buf_temp + i * sizeof(SDFILE_FILE_HEAD), &head, sizeof(SDFILE_FILE_HEAD));
|
||||
norflash_write(NULL, (void *)buf_temp, align_size, attrs.sclust);
|
||||
/* put_buf(buf_temp, align_size); */
|
||||
fclose(file);
|
||||
file = NULL;
|
||||
file = fopen(path, mode);
|
||||
|
||||
__exit:
|
||||
if (part_path) {
|
||||
free(part_path);
|
||||
}
|
||||
if (buf_temp) {
|
||||
free(buf_temp);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
FILE *cfg_private_open(const char *path, const char *mode)
|
||||
{
|
||||
int res;
|
||||
FILE *file = fopen(path, mode);
|
||||
if (!file) {
|
||||
if (mode[0] == 'w' && mode[1] == '+') {
|
||||
file = cfg_private_create(path, mode);
|
||||
if (file) {
|
||||
cfg_private_create_flag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
int cfg_private_read(FILE *file, void *buf, u32 len)
|
||||
{
|
||||
return fread(file, buf, len);
|
||||
}
|
||||
|
||||
void cfg_private_erase(u32 addr, u32 len)
|
||||
{
|
||||
/* r_printf(">>>[test]:addr = 0x%x, len = %d\n", addr, len); */
|
||||
u32 erase_total_size = len;
|
||||
u32 erase_addr = addr;
|
||||
u32 erase_size = 4096;
|
||||
u32 erase_cmd = IOCTL_ERASE_SECTOR;
|
||||
//flash不同支持的最小擦除单位不同(page/sector)
|
||||
//boot_info.vm.align == 1: 最小擦除单位page;
|
||||
//boot_info.vm.align != 1: 最小擦除单位sector;
|
||||
if (boot_info.vm.align == 1) {
|
||||
erase_size = 256;
|
||||
erase_cmd = IOCTL_ERASE_PAGE;
|
||||
}
|
||||
while (erase_total_size) {
|
||||
//擦除区域操作
|
||||
norflash_ioctl(NULL, erase_cmd, erase_addr);
|
||||
erase_addr += erase_size;
|
||||
erase_total_size -= erase_size;
|
||||
}
|
||||
}
|
||||
|
||||
int cfg_private_check(char *buf, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (buf[i] != 0xff) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int cfg_private_write(FILE *file, void *buf, u32 len)
|
||||
{
|
||||
int align_size = 4096;
|
||||
if (boot_info.vm.align == 1) {
|
||||
align_size = 256;
|
||||
}
|
||||
struct vfs_attr attrs = {0};
|
||||
fget_attrs(file, &attrs);
|
||||
/* r_printf(">>>[test]:attrs.sclust = 0x%x\n", attrs.sclust); */
|
||||
attrs.sclust = sdfile_cpu_addr2flash_addr(attrs.sclust);
|
||||
u32 fptr = fpos(file);
|
||||
/* r_printf(">>>[test]:addr = %d, fsize = %d, fptr = %d, w_len = %d\n", attrs.sclust, attrs.fsize, fptr, len); */
|
||||
if (len + fptr > attrs.fsize) {
|
||||
r_printf(">>>[test]:error, write over!!!!!!!!\n");
|
||||
return -1;
|
||||
}
|
||||
char *buf_temp = (char *)malloc(align_size);
|
||||
int res = len;
|
||||
|
||||
for (int wlen = 0; len > 0;) {
|
||||
u32 align_addr = (attrs.sclust + fptr) / align_size * align_size;
|
||||
u32 w_pos = attrs.sclust + fptr - align_addr;
|
||||
wlen = align_size - w_pos;
|
||||
/* y_printf(">>>[test]:wpos = %d, wlen = %d\n", w_pos, wlen); */
|
||||
if (wlen > len) {
|
||||
wlen = len;
|
||||
}
|
||||
norflash_read(NULL, (void *)buf_temp, align_size, align_addr);
|
||||
if (0 == cfg_private_check(buf_temp, align_size)) {
|
||||
cfg_private_erase(align_addr, align_size);
|
||||
}
|
||||
memcpy(buf_temp + w_pos, buf, wlen);
|
||||
/* put_buf(buf_temp, align_size); */
|
||||
norflash_write(NULL, (void *)buf_temp, align_size, align_addr);
|
||||
fptr += wlen;
|
||||
len -= wlen;
|
||||
}
|
||||
__exit:
|
||||
free(buf_temp);
|
||||
fseek(file, fptr, SEEK_SET);
|
||||
return res;
|
||||
}
|
||||
|
||||
int cfg_private_delete_file(FILE *file)
|
||||
{
|
||||
int align_size = 4096;
|
||||
if (boot_info.vm.align == 1) {
|
||||
align_size = 256;
|
||||
}
|
||||
struct vfs_attr attrs = {0};
|
||||
fget_attrs(file, &attrs);
|
||||
attrs.sclust = sdfile_cpu_addr2flash_addr(attrs.sclust);
|
||||
int len = attrs.fsize;
|
||||
char *buf_temp = (char *)malloc(align_size);
|
||||
u32 fptr = 0;
|
||||
|
||||
for (int wlen = 0; len > 0;) {
|
||||
u32 align_addr = (attrs.sclust + fptr) / align_size * align_size;
|
||||
u32 w_pos = attrs.sclust + fptr - align_addr;
|
||||
wlen = align_size - w_pos;
|
||||
if (wlen > len) {
|
||||
wlen = len;
|
||||
}
|
||||
norflash_read(NULL, (void *)buf_temp, align_size, align_addr);
|
||||
if (0 == cfg_private_check(buf_temp, align_size)) {
|
||||
cfg_private_erase(align_addr, align_size);
|
||||
}
|
||||
memset(buf_temp + w_pos, 0xff, wlen);
|
||||
norflash_write(NULL, (void *)buf_temp, align_size, align_addr);
|
||||
fptr += wlen;
|
||||
len -= wlen;
|
||||
}
|
||||
free(buf_temp);
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cfg_private_close(FILE *file)
|
||||
{
|
||||
if (cfg_private_create_flag) {
|
||||
int i = 0;
|
||||
int align_size = 4096;
|
||||
if (boot_info.vm.align == 1) {
|
||||
align_size = 256;
|
||||
}
|
||||
char name[SDFILE_NAME_LEN];
|
||||
fget_name(file, name, SDFILE_NAME_LEN);
|
||||
char *buf_temp = (char *)malloc(align_size);
|
||||
norflash_read(NULL, (void *)buf_temp, align_size, cfg_private_create_sclust);
|
||||
for (; i < CFG_PRIVATE_FILE_NUM; i++) {
|
||||
int addr = cfg_private_create_sclust + i * sizeof(SDFILE_FILE_HEAD);
|
||||
norflash_read(NULL, (void *)&head, sizeof(SDFILE_FILE_HEAD), addr);
|
||||
if (CRC16((u8 *)&head + 2, sizeof(SDFILE_FILE_HEAD) - 2) != head.head_crc) {
|
||||
continue;
|
||||
}
|
||||
if (0 == memcmp(head.name, name, SDFILE_NAME_LEN)) {
|
||||
head.len = fpos(file);
|
||||
y_printf(">>>[test]:real file len = %d\n", head.len);
|
||||
head.head_crc = CRC16((u8 *)&head + 2, sizeof(SDFILE_FILE_HEAD) - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cfg_private_create_flag = 0;
|
||||
if (i < CFG_PRIVATE_FILE_NUM) {
|
||||
cfg_private_erase(cfg_private_create_sclust, align_size);
|
||||
memcpy(buf_temp + i * sizeof(SDFILE_FILE_HEAD), &head, sizeof(SDFILE_FILE_HEAD));
|
||||
norflash_write(NULL, (void *)buf_temp, align_size, cfg_private_create_sclust);
|
||||
}
|
||||
if (buf_temp) {
|
||||
free(buf_temp);
|
||||
}
|
||||
}
|
||||
return fclose(file);
|
||||
}
|
||||
|
||||
int cfg_private_seek(FILE *file, int offset, int fromwhere)
|
||||
{
|
||||
return fseek(file, offset, fromwhere);
|
||||
}
|
||||
|
||||
void cfg_private_test_demo(void)
|
||||
{
|
||||
#if 0
|
||||
#define N 256
|
||||
char test_buf[N] = {0};
|
||||
char r_buf[512] = {0};
|
||||
for (int i = 0; i < N; i++) {
|
||||
test_buf[i] = i & 0xff;
|
||||
}
|
||||
|
||||
char path[64] = "mnt/sdfile/app/FATFSI/eq_cfg_hw.bin";
|
||||
char path2[64] = "mnt/sdfile/app/FATFSI/cfg_tool.bin";
|
||||
y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__);
|
||||
FILE *fp = cfg_private_open(path, "w+");
|
||||
if (!fp) {
|
||||
r_printf(">>>[test]:open fail!!!!!\n");
|
||||
while (1);
|
||||
}
|
||||
/* cfg_private_delete_file(fp); */
|
||||
/* fp = cfg_private_open(path, "w+"); */
|
||||
/* cfg_private_read(fp, r_buf, 512); */
|
||||
/* put_buf(r_buf, 512); */
|
||||
/* cfg_private_seek(fp, 0, SEEK_SET); */
|
||||
|
||||
cfg_private_write(fp, test_buf, N);
|
||||
|
||||
cfg_private_close(fp);
|
||||
fp = cfg_private_open(path, "r");
|
||||
cfg_private_read(fp, r_buf, 512);
|
||||
put_buf(r_buf, 512);
|
||||
fclose(fp);
|
||||
y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__);
|
||||
|
||||
fp = cfg_private_open(path2, "w+");
|
||||
if (!fp) {
|
||||
r_printf(">>>[test]:open fail!!!!!\n");
|
||||
while (1);
|
||||
}
|
||||
for (int i = 0; i < N; i++) {
|
||||
test_buf[i] = (N - 1 - i) & 0xff;
|
||||
}
|
||||
cfg_private_write(fp, test_buf, N);
|
||||
cfg_private_close(fp);
|
||||
fp = cfg_private_open(path2, "r");
|
||||
cfg_private_read(fp, r_buf, 512);
|
||||
put_buf(r_buf, 512);
|
||||
fclose(fp);
|
||||
|
||||
#if 0
|
||||
FILE *file = cfg_private_open("mnt/sdfile/app/FATFSI", "w+");
|
||||
if (!file) {
|
||||
r_printf(">>>[test]:open fail!!!!!\n");
|
||||
while (1);
|
||||
}
|
||||
struct vfs_attr attrs = {0};
|
||||
fget_attrs(file, &attrs);
|
||||
y_printf(">>>[test]:in part addr = %d, fsize = %d\n", attrs.sclust, attrs.fsize);
|
||||
char *part = zalloc(attrs.fsize);
|
||||
cfg_private_delete_file(file);
|
||||
file = cfg_private_open("mnt/sdfile/app/FATFSI", "w+");
|
||||
cfg_private_read(file, part, attrs.fsize);
|
||||
put_buf(part, attrs.fsize);
|
||||
free(part);
|
||||
#endif
|
||||
while (1);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,932 @@
|
||||
#include "system/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "fs/virfat_flash.h"
|
||||
#include "res/resfile.h"
|
||||
|
||||
#include "asm/sfc_norflash_api.h"
|
||||
#include "boot.h"
|
||||
#include "sdfile.h"
|
||||
|
||||
|
||||
#define OUTFLASH_FAT16_ENABLE 0 // 如果需要使用16M以上的flash需要修改download.bat文件与之对应
|
||||
|
||||
typedef struct _flash_private_info {
|
||||
char part_name[16];
|
||||
u32 flash_private_addr;
|
||||
u32 private_len;
|
||||
} FLASH_PRIVATE_INFO;
|
||||
|
||||
static virfat_flash_t virfat_flash;
|
||||
static u8 curr_file = 0xff;
|
||||
volatile char vir_file_type = 0;
|
||||
u32 change_flag = 0;
|
||||
static void *fd;
|
||||
|
||||
static OS_MUTEX virfat_flash_mutex;
|
||||
#define virfat_mutex_init() os_mutex_create(&virfat_flash_mutex)
|
||||
#define virfat_mutex_pend() os_mutex_pend(&virfat_flash_mutex, portMAX_DELAY)
|
||||
#define virfat_mutex_post() os_mutex_post(&virfat_flash_mutex)
|
||||
|
||||
#define FATFS_IN_FLASH_NAME "FATFSI"
|
||||
|
||||
static u32 virfat_flash_addr2cpu_addr(u32 offset)
|
||||
{
|
||||
return offset - boot_info.sfc.sfc_base_addr + boot_info.sfc.app_addr;
|
||||
}
|
||||
|
||||
static u32 virfat_cpu_addr2flash_addr(u32 offset)
|
||||
{
|
||||
return offset - boot_info.sfc.app_addr + boot_info.sfc.sfc_base_addr;
|
||||
}
|
||||
|
||||
static void virfat_get_cpu_fatfs_addr(char *name, u32 *addr, u32 *len)
|
||||
{
|
||||
u32 start_addr = boot_info.sfc.app_addr;
|
||||
/* y_printf(">>>[test]:base_addr = %d, app_addr = %d\n", boot_info.sfc.sfc_base_addr, boot_info.sfc.app_addr); */
|
||||
u32 offset = 0;
|
||||
struct sdfile_file_head head = {0};
|
||||
/* u16 local_flash_key = get_chip_id_in_phonefs(); */
|
||||
while (1) {
|
||||
/* extern int norflash_origin_read(u8 * buf, u32 offset, u32 len); */
|
||||
/* norflash_origin_read((u8 *)&head, start_addr, sizeof(head)); */
|
||||
memcpy(&head, (u8 *)start_addr, sizeof(head));
|
||||
/* put_buf(&head, 32); */
|
||||
/* decode_data_by_user_key_in_sdfile(local_flash_key, (u8 *)&head, sizeof(head), offset, sizeof(head)); */
|
||||
if (head.head_crc != CRC16((u8 *)&head.data_crc, sizeof(head) - sizeof(head.head_crc))) {
|
||||
y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__);
|
||||
return;
|
||||
}
|
||||
/* r_printf(">>>[test]:head.name = %s, name = %s\n", head.name, name); */
|
||||
if (0 == memcmp(head.name, name, strlen(name))) {
|
||||
break;
|
||||
}
|
||||
offset += sizeof(head);
|
||||
start_addr += sizeof(head);
|
||||
}
|
||||
*addr = head.addr;
|
||||
*len = head.len;
|
||||
r_printf(">>>[test]:######### start_addr = 0x%x, len = 0x%x\n", head.addr, head.len);
|
||||
}
|
||||
|
||||
#if TCFG_VIRFAT_FLASH_ENABLE
|
||||
void fat_copy(void *pDest, void *pSrc, u32 copyLen)
|
||||
{
|
||||
while (copyLen--) {
|
||||
((u8 *)pDest)[copyLen] = ((u8 *)pSrc)[copyLen];
|
||||
}
|
||||
}
|
||||
|
||||
static u16 ld_word(u8 *p)
|
||||
{
|
||||
return (u16)p[1] << 8 | p[0];
|
||||
}
|
||||
|
||||
static u32 ld_dword(u8 *p)
|
||||
{
|
||||
return (u32)p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
|
||||
}
|
||||
|
||||
//fat 备份4Kfat_table和4K目录项,保留扇区扩大8K ,8M
|
||||
#if 1
|
||||
/* static const unsigned char bpb_data[512] = { */
|
||||
static char bpb_data[512] = {
|
||||
0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x08, 0x18, 0x00,
|
||||
0x01, 0x80, 0x00, 0x00, 0x40, 0xF8, 0x08, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0xEE, 0x8D, 0xF2, 0x2C, 0x4E, 0x4F, 0x20, 0x4E, 0x41,
|
||||
0x4D, 0x45, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x33, 0xC9,
|
||||
0x8E, 0xD1, 0xBC, 0xF0, 0x7B, 0x8E, 0xD9, 0xB8, 0x00, 0x20, 0x8E, 0xC0, 0xFC, 0xBD, 0x00, 0x7C,
|
||||
0x38, 0x4E, 0x24, 0x7D, 0x24, 0x8B, 0xC1, 0x99, 0xE8, 0x3C, 0x01, 0x72, 0x1C, 0x83, 0xEB, 0x3A,
|
||||
0x66, 0xA1, 0x1C, 0x7C, 0x26, 0x66, 0x3B, 0x07, 0x26, 0x8A, 0x57, 0xFC, 0x75, 0x06, 0x80, 0xCA,
|
||||
0x02, 0x88, 0x56, 0x02, 0x80, 0xC3, 0x10, 0x73, 0xEB, 0x33, 0xC9, 0x8A, 0x46, 0x10, 0x98, 0xF7,
|
||||
0x66, 0x16, 0x03, 0x46, 0x1C, 0x13, 0x56, 0x1E, 0x03, 0x46, 0x0E, 0x13, 0xD1, 0x8B, 0x76, 0x11,
|
||||
0x60, 0x89, 0x46, 0xFC, 0x89, 0x56, 0xFE, 0xB8, 0x20, 0x00, 0xF7, 0xE6, 0x8B, 0x5E, 0x0B, 0x03,
|
||||
0xC3, 0x48, 0xF7, 0xF3, 0x01, 0x46, 0xFC, 0x11, 0x4E, 0xFE, 0x61, 0xBF, 0x00, 0x00, 0xE8, 0xE6,
|
||||
0x00, 0x72, 0x39, 0x26, 0x38, 0x2D, 0x74, 0x17, 0x60, 0xB1, 0x0B, 0xBE, 0xA1, 0x7D, 0xF3, 0xA6,
|
||||
0x61, 0x74, 0x32, 0x4E, 0x74, 0x09, 0x83, 0xC7, 0x20, 0x3B, 0xFB, 0x72, 0xE6, 0xEB, 0xDC, 0xA0,
|
||||
0xFB, 0x7D, 0xB4, 0x7D, 0x8B, 0xF0, 0xAC, 0x98, 0x40, 0x74, 0x0C, 0x48, 0x74, 0x13, 0xB4, 0x0E,
|
||||
0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xEF, 0xA0, 0xFD, 0x7D, 0xEB, 0xE6, 0xA0, 0xFC, 0x7D, 0xEB,
|
||||
0xE1, 0xCD, 0x16, 0xCD, 0x19, 0x26, 0x8B, 0x55, 0x1A, 0x52, 0xB0, 0x01, 0xBB, 0x00, 0x00, 0xE8,
|
||||
0x3B, 0x00, 0x72, 0xE8, 0x5B, 0x8A, 0x56, 0x24, 0xBE, 0x0B, 0x7C, 0x8B, 0xFC, 0xC7, 0x46, 0xF0,
|
||||
0x3D, 0x7D, 0xC7, 0x46, 0xF4, 0x29, 0x7D, 0x8C, 0xD9, 0x89, 0x4E, 0xF2, 0x89, 0x4E, 0xF6, 0xC6,
|
||||
0x06, 0x96, 0x7D, 0xCB, 0xEA, 0x03, 0x00, 0x00, 0x20, 0x0F, 0xB6, 0xC8, 0x66, 0x8B, 0x46, 0xF8,
|
||||
0x66, 0x03, 0x46, 0x1C, 0x66, 0x8B, 0xD0, 0x66, 0xC1, 0xEA, 0x10, 0xEB, 0x5E, 0x0F, 0xB6, 0xC8,
|
||||
0x4A, 0x4A, 0x8A, 0x46, 0x0D, 0x32, 0xE4, 0xF7, 0xE2, 0x03, 0x46, 0xFC, 0x13, 0x56, 0xFE, 0xEB,
|
||||
0x4A, 0x52, 0x50, 0x06, 0x53, 0x6A, 0x01, 0x6A, 0x10, 0x91, 0x8B, 0x46, 0x18, 0x96, 0x92, 0x33,
|
||||
0xD2, 0xF7, 0xF6, 0x91, 0xF7, 0xF6, 0x42, 0x87, 0xCA, 0xF7, 0x76, 0x1A, 0x8A, 0xF2, 0x8A, 0xE8,
|
||||
0xC0, 0xCC, 0x02, 0x0A, 0xCC, 0xB8, 0x01, 0x02, 0x80, 0x7E, 0x02, 0x0E, 0x75, 0x04, 0xB4, 0x42,
|
||||
0x8B, 0xF4, 0x8A, 0x56, 0x24, 0xCD, 0x13, 0x61, 0x61, 0x72, 0x0B, 0x40, 0x75, 0x01, 0x42, 0x03,
|
||||
0x5E, 0x0B, 0x49, 0x75, 0x06, 0xF8, 0xC3, 0x41, 0xBB, 0x00, 0x00, 0x60, 0x66, 0x6A, 0x00, 0xEB,
|
||||
0xB0, 0x42, 0x4F, 0x4F, 0x54, 0x4D, 0x47, 0x52, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x52, 0x65,
|
||||
0x6D, 0x6F, 0x76, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x73, 0x20, 0x6F, 0x72, 0x20, 0x6F, 0x74,
|
||||
0x68, 0x65, 0x72, 0x20, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x2E, 0xFF, 0x0D, 0x0A, 0x44, 0x69, 0x73,
|
||||
0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xFF, 0x0D, 0x0A, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20,
|
||||
0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61,
|
||||
0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xCB, 0xD8, 0x55, 0xAA
|
||||
};
|
||||
#else
|
||||
//fat 备份12Kfat_table和4K目录项,保留扇区扩大16K ,32M
|
||||
/* static const unsigned char bpb_data[512] = { */
|
||||
static char bpb_data[512] = {
|
||||
0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x08, 0x30, 0x00,
|
||||
0x01, 0x00, 0x01, 0x00, 0x00, 0xF8, 0x18, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x29, 0xEE, 0x8D, 0xF2, 0x2C, 0x4E, 0x4F, 0x20, 0x4E, 0x41,
|
||||
0x4D, 0x45, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x33, 0xC9,
|
||||
0x8E, 0xD1, 0xBC, 0xF0, 0x7B, 0x8E, 0xD9, 0xB8, 0x00, 0x20, 0x8E, 0xC0, 0xFC, 0xBD, 0x00, 0x7C,
|
||||
0x38, 0x4E, 0x24, 0x7D, 0x24, 0x8B, 0xC1, 0x99, 0xE8, 0x3C, 0x01, 0x72, 0x1C, 0x83, 0xEB, 0x3A,
|
||||
0x66, 0xA1, 0x1C, 0x7C, 0x26, 0x66, 0x3B, 0x07, 0x26, 0x8A, 0x57, 0xFC, 0x75, 0x06, 0x80, 0xCA,
|
||||
0x02, 0x88, 0x56, 0x02, 0x80, 0xC3, 0x10, 0x73, 0xEB, 0x33, 0xC9, 0x8A, 0x46, 0x10, 0x98, 0xF7,
|
||||
0x66, 0x16, 0x03, 0x46, 0x1C, 0x13, 0x56, 0x1E, 0x03, 0x46, 0x0E, 0x13, 0xD1, 0x8B, 0x76, 0x11,
|
||||
0x60, 0x89, 0x46, 0xFC, 0x89, 0x56, 0xFE, 0xB8, 0x20, 0x00, 0xF7, 0xE6, 0x8B, 0x5E, 0x0B, 0x03,
|
||||
0xC3, 0x48, 0xF7, 0xF3, 0x01, 0x46, 0xFC, 0x11, 0x4E, 0xFE, 0x61, 0xBF, 0x00, 0x00, 0xE8, 0xE6,
|
||||
0x00, 0x72, 0x39, 0x26, 0x38, 0x2D, 0x74, 0x17, 0x60, 0xB1, 0x0B, 0xBE, 0xA1, 0x7D, 0xF3, 0xA6,
|
||||
0x61, 0x74, 0x32, 0x4E, 0x74, 0x09, 0x83, 0xC7, 0x20, 0x3B, 0xFB, 0x72, 0xE6, 0xEB, 0xDC, 0xA0,
|
||||
0xFB, 0x7D, 0xB4, 0x7D, 0x8B, 0xF0, 0xAC, 0x98, 0x40, 0x74, 0x0C, 0x48, 0x74, 0x13, 0xB4, 0x0E,
|
||||
0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xEF, 0xA0, 0xFD, 0x7D, 0xEB, 0xE6, 0xA0, 0xFC, 0x7D, 0xEB,
|
||||
0xE1, 0xCD, 0x16, 0xCD, 0x19, 0x26, 0x8B, 0x55, 0x1A, 0x52, 0xB0, 0x01, 0xBB, 0x00, 0x00, 0xE8,
|
||||
0x3B, 0x00, 0x72, 0xE8, 0x5B, 0x8A, 0x56, 0x24, 0xBE, 0x0B, 0x7C, 0x8B, 0xFC, 0xC7, 0x46, 0xF0,
|
||||
0x3D, 0x7D, 0xC7, 0x46, 0xF4, 0x29, 0x7D, 0x8C, 0xD9, 0x89, 0x4E, 0xF2, 0x89, 0x4E, 0xF6, 0xC6,
|
||||
0x06, 0x96, 0x7D, 0xCB, 0xEA, 0x03, 0x00, 0x00, 0x20, 0x0F, 0xB6, 0xC8, 0x66, 0x8B, 0x46, 0xF8,
|
||||
0x66, 0x03, 0x46, 0x1C, 0x66, 0x8B, 0xD0, 0x66, 0xC1, 0xEA, 0x10, 0xEB, 0x5E, 0x0F, 0xB6, 0xC8,
|
||||
0x4A, 0x4A, 0x8A, 0x46, 0x0D, 0x32, 0xE4, 0xF7, 0xE2, 0x03, 0x46, 0xFC, 0x13, 0x56, 0xFE, 0xEB,
|
||||
0x4A, 0x52, 0x50, 0x06, 0x53, 0x6A, 0x01, 0x6A, 0x10, 0x91, 0x8B, 0x46, 0x18, 0x96, 0x92, 0x33,
|
||||
0xD2, 0xF7, 0xF6, 0x91, 0xF7, 0xF6, 0x42, 0x87, 0xCA, 0xF7, 0x76, 0x1A, 0x8A, 0xF2, 0x8A, 0xE8,
|
||||
0xC0, 0xCC, 0x02, 0x0A, 0xCC, 0xB8, 0x01, 0x02, 0x80, 0x7E, 0x02, 0x0E, 0x75, 0x04, 0xB4, 0x42,
|
||||
0x8B, 0xF4, 0x8A, 0x56, 0x24, 0xCD, 0x13, 0x61, 0x61, 0x72, 0x0B, 0x40, 0x75, 0x01, 0x42, 0x03,
|
||||
0x5E, 0x0B, 0x49, 0x75, 0x06, 0xF8, 0xC3, 0x41, 0xBB, 0x00, 0x00, 0x60, 0x66, 0x6A, 0x00, 0xEB,
|
||||
0xB0, 0x42, 0x4F, 0x4F, 0x54, 0x4D, 0x47, 0x52, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x52, 0x65,
|
||||
0x6D, 0x6F, 0x76, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x73, 0x20, 0x6F, 0x72, 0x20, 0x6F, 0x74,
|
||||
0x68, 0x65, 0x72, 0x20, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x2E, 0xFF, 0x0D, 0x0A, 0x44, 0x69, 0x73,
|
||||
0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xFF, 0x0D, 0x0A, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20,
|
||||
0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61,
|
||||
0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xCB, 0xD8, 0x55, 0xAA
|
||||
};
|
||||
#endif
|
||||
|
||||
static u32 get_first_one(u32 n)
|
||||
{
|
||||
u32 pos = 0;
|
||||
for (pos = 0; pos < 32; pos++) {
|
||||
if (n & BIT(pos)) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
return 0xff;
|
||||
|
||||
}
|
||||
|
||||
static bool virfat_flash_mount(virfat_flash_t *disk_handler, u8 *buf)
|
||||
{
|
||||
u32 fatsize;
|
||||
u32 maxclust;
|
||||
u32 sects_fat;
|
||||
u32 n_rootdir;
|
||||
|
||||
/*计算FAT表大小*/
|
||||
fatsize = ld_word(&buf[BPB_FATSz16]); /* Number of sectors per FAT */
|
||||
if (!fatsize) {
|
||||
fatsize = ld_dword(&buf[BPB_FATSz32]);
|
||||
}
|
||||
|
||||
disk_handler->fatsize = fatsize * 512; //fat表大小 byte.
|
||||
disk_handler->fatbase = ld_word(&buf[BPB_RsvdSecCnt]); /* FAT start sector (lba) */
|
||||
/* disk_handler->fatbase2 = disk_handler->fatbase + fatsize; */
|
||||
|
||||
fatsize *= buf[BPB_NumFATs];
|
||||
|
||||
disk_handler->csize = get_first_one(buf[BPB_SecPerClus]); /* Number of sectors per cluster */
|
||||
|
||||
n_rootdir = ld_word(&buf[BPB_RootEntCnt]); /* Nmuber of root directory entries */
|
||||
|
||||
disk_handler->database = (disk_handler->fatbase + fatsize + n_rootdir / 16); /* Data start sector (lba) */
|
||||
|
||||
|
||||
/*计算总容量*/
|
||||
disk_handler->capacity = ld_word(&buf[BPB_TotSec16]); /* Number of sectors on the file system */
|
||||
if (!disk_handler->capacity) {
|
||||
disk_handler->capacity = ld_dword(&buf[BPB_TotSec32]);
|
||||
}
|
||||
/* r_printf(">>>[test]:cap = 0x%x, csize = %d\n",disk_handler->capacity, disk_handler->csize); */
|
||||
maxclust = (disk_handler->capacity - ld_word(&buf[BPB_RsvdSecCnt]) - fatsize -
|
||||
n_rootdir / 16) >> disk_handler->csize;
|
||||
disk_handler->max_clust = maxclust + 2;
|
||||
/* r_printf(">>>[test]:maxclust = %d\n", maxclust); */
|
||||
|
||||
disk_handler->fs_type = (maxclust >= MIN_FAT32) ? FS_FAT32 : ((maxclust >= MIN_FAT16) ? FS_FAT16 : FS_FAT12);
|
||||
/* r_printf(">>>[test]:fs_type = 0x%x\n", disk_handler->fs_type); */
|
||||
|
||||
/* Root directory start cluster */
|
||||
if (disk_handler->fs_type == FS_FAT32) {
|
||||
disk_handler->dirbase = disk_handler->database;
|
||||
disk_handler->database += 1 << disk_handler->csize;
|
||||
} else {
|
||||
disk_handler->dirbase = disk_handler->fatbase + fatsize;
|
||||
}
|
||||
|
||||
disk_handler->clustSize = disk_handler->csize + 9;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void vir_read_reserved_area(u8 *buf, u32 len)
|
||||
{
|
||||
memset(buf, 0, len);
|
||||
}
|
||||
|
||||
|
||||
static void vir_read_BPB(u8 *buf, u32 offset, u32 len)
|
||||
{
|
||||
/* u8 bpb_jl_head[] = "JLBT_DISK"; */
|
||||
|
||||
/* memset(buf, 0, 512); */
|
||||
memcpy(buf, bpb_data + offset, len);
|
||||
|
||||
/* memcpy(buf + sizeof(bpb_data), bpb_jl_head, sizeof(bpb_jl_head)); */
|
||||
|
||||
/* buf[510] = 0x55; */
|
||||
/* buf[511] = 0xAA; */
|
||||
}
|
||||
|
||||
static int virfat_read(void *fd, void *buf, u32 addr, u32 len)
|
||||
{
|
||||
int rlen = -1;
|
||||
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
|
||||
u32 cpu_addr = virfat_flash_addr2cpu_addr(virfat_flash.flash_fatfs_addr + addr);
|
||||
/* r_printf(">>>[test]:cpu_addr = %d, addr = %d\n", cpu_addr, addr); */
|
||||
memcpy((u8 *)buf, (u8 *)cpu_addr, len);
|
||||
rlen = len;
|
||||
#else
|
||||
rlen = dev_bulk_read(fd, buf, addr, len);
|
||||
#endif
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static int virfat_write(void *fd, void *buf, u32 addr, u32 len)
|
||||
{
|
||||
int wlen = -1;
|
||||
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
|
||||
addr += virfat_flash.flash_fatfs_addr;
|
||||
wlen = norflash_write(NULL, buf, len, addr);
|
||||
#else
|
||||
wlen = dev_bulk_write(fd, buf, addr, len);
|
||||
#endif
|
||||
return wlen;
|
||||
}
|
||||
|
||||
static int virfat_ioctl(void *fd, u32 cmd, u32 arg)
|
||||
{
|
||||
int res = -1;
|
||||
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
|
||||
if ((cmd == IOCTL_ERASE_SECTOR) || (cmd == IOCTL_ERASE_PAGE) || (cmd == IOCTL_ERASE_BLOCK)) {
|
||||
arg += virfat_flash.flash_fatfs_addr;
|
||||
}
|
||||
res = norflash_ioctl(NULL, cmd, arg);
|
||||
#else
|
||||
res = dev_ioctl(fd, cmd, arg);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
AT_VOLATILE_RAM_CODE
|
||||
static u32 virfat_flash_read(void *buf, u32 addr_sec, u32 len)
|
||||
{
|
||||
/* y_printf("11111111111[r:%d],,", addr_sec); */
|
||||
u32 real_addrsec = 0;
|
||||
u32 rlen;
|
||||
if (addr_sec == 0) {
|
||||
vir_read_BPB(buf, 0, 512);
|
||||
y_printf("fatbase:%d \n", virfat_flash.fatbase);
|
||||
y_printf("dirbase:%d \n", virfat_flash.dirbase);
|
||||
y_printf("database:%d \n", virfat_flash.database);
|
||||
return len;
|
||||
} else if (addr_sec < 4096 / 512) {
|
||||
vir_read_reserved_area(buf, len);
|
||||
return len;
|
||||
} else {
|
||||
real_addrsec = addr_sec - 4096 / 512;
|
||||
}
|
||||
/* r_printf(">>>[test]111111:real-add= %d\n",real_addrsec); */
|
||||
|
||||
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
|
||||
rlen = virfat_read(fd, buf, real_addrsec * 512, len);
|
||||
#else
|
||||
rlen = _norflash_read_watch(buf, real_addrsec * 512, len, 1);
|
||||
if (rlen == 0) {
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
return rlen;
|
||||
}
|
||||
|
||||
|
||||
static u32 virfat_flash_write(void *buf, u32 addr_sec, u32 len)
|
||||
{
|
||||
/* r_printf("[w:%d],,", addr_sec); */
|
||||
u8 *buf_temp = (u8 *)malloc(4096);
|
||||
u32 wlen = 0;
|
||||
u32 real_addrsec = 0;
|
||||
if (addr_sec == 0) {
|
||||
return len;
|
||||
} else if (addr_sec < 4096 / 512) {
|
||||
return len;
|
||||
} else if (addr_sec < virfat_flash.fatbase) { //备份区不写
|
||||
real_addrsec = addr_sec - 4096 / 512 + 0; // 0为flash里面保留区域(备份fat表和目录项)实际位置。
|
||||
return len;
|
||||
} else if (addr_sec < virfat_flash.dirbase) {
|
||||
real_addrsec = addr_sec - 4096 / 512;
|
||||
/* real_addrsec = addr_sec - virfat_flash.fatbase + 8 * 1024 * UNIT / 512; // 8KxUNIT为flash里面fat表实际位置。 */
|
||||
int real_fatbase = virfat_flash.fatbase * 512 - 4096;
|
||||
if (virfat_flash.fatsize > 4096) {
|
||||
int a = (addr_sec - virfat_flash.fatbase) * 512 / 4096;
|
||||
real_fatbase += a * 4096;
|
||||
addr_sec -= a * 4096 / 512;
|
||||
}
|
||||
virfat_read(fd, buf_temp, real_fatbase, 4096);
|
||||
virfat_ioctl(fd, IOCTL_ERASE_SECTOR, real_fatbase);
|
||||
memcpy(buf_temp + (addr_sec - virfat_flash.fatbase) * 512, buf, len);
|
||||
wlen = virfat_write(fd, buf_temp, real_fatbase, 4096);
|
||||
if (wlen == 4096) {
|
||||
wlen = len;
|
||||
}
|
||||
} else if (addr_sec < virfat_flash.database) {
|
||||
real_addrsec = addr_sec - 4096 / 512;
|
||||
int real_dirbase = virfat_flash.dirbase * 512 - 4096;
|
||||
/* real_addrsec = addr_sec - virfat_flash.dirbase + 12 * 1024 * UNIT / 512; // 12KxUNIT为flash里面目录项实际位置。 */
|
||||
virfat_read(fd, buf_temp, real_dirbase, 4096);
|
||||
virfat_ioctl(fd, IOCTL_ERASE_SECTOR, real_dirbase);
|
||||
memcpy(buf_temp + (addr_sec - virfat_flash.dirbase) * 512, buf, len);
|
||||
wlen = virfat_write(fd, buf_temp, real_dirbase, 4096);
|
||||
if (wlen == 4096) {
|
||||
wlen = len;
|
||||
}
|
||||
} else {
|
||||
real_addrsec = addr_sec - 4096 / 512;
|
||||
/* real_addrsec = addr_sec - virfat_flash.database + 16 * 1024 * UNIT / 512; // 16KxUNIT为flash里面数据区实际位置。 */
|
||||
int align_addr = real_addrsec * 512 / 4096 * 4096;
|
||||
int offset = real_addrsec * 512 % 4096;
|
||||
virfat_read(fd, buf_temp, align_addr, 4096);
|
||||
virfat_ioctl(fd, IOCTL_ERASE_SECTOR, align_addr);
|
||||
memcpy(buf_temp + offset, buf, len);
|
||||
wlen = virfat_write(fd, buf_temp, align_addr, 4096);
|
||||
if (wlen == 4096) {
|
||||
wlen = len;
|
||||
}
|
||||
|
||||
/* wlen = virfat_write(fd, buf, real_addrsec * 512, len); */
|
||||
}
|
||||
free(buf_temp);
|
||||
buf_temp = NULL;
|
||||
if (wlen != len) {
|
||||
r_printf(">>>[test]:wlen = %d, len = %d\n", wlen, len);
|
||||
log_e("write error!!!!!!!!!!!!!");
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
AT_VOLATILE_RAM_CODE
|
||||
u32 virfat_flash_read_watch(void *buf, u32 addr_sec, u32 len)
|
||||
{
|
||||
/* y_printf("[r:%d],,", addr_sec); */
|
||||
u32 real_addrsec = 0;
|
||||
u32 rlen;
|
||||
/* if (addr_sec == 0) { */
|
||||
if (addr_sec < 512) {
|
||||
vir_read_BPB(buf, addr_sec, len);
|
||||
y_printf("fatbase:%d \n", virfat_flash.fatbase);
|
||||
y_printf("dirbase:%d \n", virfat_flash.dirbase);
|
||||
y_printf("database:%d \n", virfat_flash.database);
|
||||
return len;
|
||||
} else if (addr_sec < 4096) {
|
||||
vir_read_reserved_area(buf, len);
|
||||
return len;
|
||||
} else {
|
||||
real_addrsec = addr_sec - 4096 ;
|
||||
}
|
||||
/* r_printf(">>>[test]:real-add= %d\n",real_addrsec); */
|
||||
|
||||
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
|
||||
rlen = virfat_read(fd, buf, real_addrsec, len);
|
||||
#else
|
||||
rlen = _norflash_read_watch(buf, real_addrsec, len, 1);
|
||||
if (rlen == 0) {
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
return rlen;
|
||||
}
|
||||
|
||||
u32 virfat_flash_write_watch(void *buf, u32 addr_sec, u32 len)
|
||||
{
|
||||
u32 wlen;
|
||||
u32 real_addrsec = 0;
|
||||
if (addr_sec == 0) {
|
||||
return len;
|
||||
} else if (addr_sec < 4096) {
|
||||
return len;
|
||||
} else {
|
||||
real_addrsec = addr_sec - 4096;
|
||||
}
|
||||
wlen = virfat_write(fd, buf, real_addrsec, len);
|
||||
if (wlen != len) {
|
||||
r_printf(">>>[test]:wlen = %d, len = %d\n", wlen, len);
|
||||
log_e("write error!!!!!!!!!!!!!");
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
u32 virfat_flash_erase_watch(int cmd, u32 arg)
|
||||
{
|
||||
if (arg == 0) {
|
||||
return 0;
|
||||
} else if (arg < 4096) {
|
||||
return 0;
|
||||
} else {
|
||||
arg = arg - 4096;
|
||||
}
|
||||
return virfat_ioctl(fd, cmd, arg);
|
||||
}
|
||||
u32 virfat_flash_erase(int cmd, u32 arg)
|
||||
{
|
||||
return virfat_ioctl(fd, cmd, arg);
|
||||
}
|
||||
|
||||
u32 virfat_flash_capacity() //fat上容量
|
||||
{
|
||||
return virfat_flash.capacity * 512;
|
||||
}
|
||||
|
||||
u32 virfat_flash_get_real_capacity() //获取实际flash容量
|
||||
{
|
||||
static u32 jlfat_capacity = 0;
|
||||
if (jlfat_capacity == 0) {
|
||||
virfat_ioctl(fd, IOCTL_GET_CAPACITY, (u32)&jlfat_capacity);
|
||||
#if (OUTFLASH_FAT16_ENABLE == 0)
|
||||
int min_fat16_size = 10 * 1024 * 1024;
|
||||
if (jlfat_capacity > min_fat16_size) {
|
||||
return min_fat16_size;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
|
||||
jlfat_capacity = virfat_flash.fatfs_len;
|
||||
#endif
|
||||
return jlfat_capacity;
|
||||
}
|
||||
|
||||
#define BACKUPS_SPACE 8192
|
||||
void virfat_flash_backups_fat_dir_data()
|
||||
{
|
||||
u8 *buf = malloc(4096);
|
||||
ASSERT(buf);
|
||||
for (int offset = 0; offset < BACKUPS_SPACE; offset += 4096) {
|
||||
virfat_flash_read_watch(buf, 4096 + BACKUPS_SPACE + offset, 4096);
|
||||
virfat_flash_erase_watch(IOCTL_ERASE_SECTOR, 4096 + offset);
|
||||
virfat_flash_write_watch(buf, 4096 + offset, 4096);
|
||||
}
|
||||
if (buf) {
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void virfat_flash_resume_fat_dir_data()
|
||||
{
|
||||
u8 *buf = malloc(4096);
|
||||
ASSERT(buf);
|
||||
for (int offset = 0; offset < BACKUPS_SPACE; offset += 4096) {
|
||||
virfat_flash_read_watch(buf, 4096 + offset, 4096);
|
||||
virfat_flash_erase_watch(IOCTL_ERASE_SECTOR, 4096 + BACKUPS_SPACE + offset);
|
||||
virfat_flash_write_watch(buf, 4096 + BACKUPS_SPACE + offset, 4096);
|
||||
}
|
||||
if (buf) {
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief:
|
||||
@param:
|
||||
@return:
|
||||
@author:phewlee.
|
||||
@note: 外置flash jlaft文件系统,获取文件名。
|
||||
@date: 2021-05-19
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#define BUF_LEN 512
|
||||
void virfat_flash_get_dirinfo(void *file_buf, u32 *file_num)
|
||||
{
|
||||
u32 cnt = 0;
|
||||
u8 *buf = malloc(BUF_LEN);
|
||||
u8 name_buf[12] = {0};
|
||||
u32 dir_len = (virfat_flash.database - virfat_flash.dirbase) * 512;
|
||||
for (int k = 0; k < dir_len; k += BUF_LEN) {
|
||||
virfat_flash_read_watch(buf, virfat_flash.dirbase * 512 + k, BUF_LEN);
|
||||
for (int i = 0; i < BUF_LEN; i += 32) {
|
||||
memset(name_buf, 0, 12);
|
||||
memcpy(name_buf, buf + i, 12);
|
||||
/* put_buf(buf, 32); */
|
||||
if (name_buf[0] == 0xE5) {
|
||||
continue;
|
||||
}
|
||||
if ((name_buf[0] != 0) && (name_buf[1] != 0)) {
|
||||
if (file_buf) {
|
||||
memcpy(file_buf + cnt * 12, name_buf, 12);
|
||||
}
|
||||
cnt++;
|
||||
/* r_printf(">>>[test]:name = %s\n", name_buf); */
|
||||
} else {
|
||||
/* y_printf("\n >>>[test]:func = %s,line= %d\n",__FUNCTION__, __LINE__); */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*file_num = cnt;
|
||||
free(buf);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief:
|
||||
@param:
|
||||
@return:
|
||||
@author:phewlee.
|
||||
@note: 外置flash jlaft文件系统,获取文件信息。
|
||||
@date: 2021-05-19
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#if JLFAT_DIRINFO_ENABLE
|
||||
void virfat_flash_get_alldirinfo(JLFAT_DIRINFO *dir_info, u32 *file_num)
|
||||
{
|
||||
u32 cnt = 0;
|
||||
u8 *buf = malloc(BUF_LEN);
|
||||
u8 dir[32] = {0};
|
||||
u32 dir_len = (virfat_flash.database - virfat_flash.dirbase) * 512;
|
||||
for (int k = 0; k < dir_len; k += BUF_LEN) {
|
||||
virfat_flash_read_watch(buf, virfat_flash.dirbase * 512 + k, BUF_LEN);
|
||||
for (int i = 0; i < BUF_LEN; i += 32) {
|
||||
memset(dir, 0, 32);
|
||||
memcpy(dir, buf + i, 32);
|
||||
if (dir[0] == 0xE5) {
|
||||
continue;
|
||||
}
|
||||
if ((dir[0] != 0) && (dir[1] != 0)) {
|
||||
if (dir_info) {
|
||||
memcpy(dir_info[cnt].name, dir, 11);
|
||||
dir_info[cnt].name[11] = 0;
|
||||
dir_info[cnt].attr = buf[DIR_Attr] & (~AM_FCH);
|
||||
dir_info[cnt].fsize = ld_dword((u8 *)(&dir[DIR_FileSize]));
|
||||
dir_info[cnt].sclust = ((u32)ld_word(&dir[DIR_FstClusHI]) << 16) | ld_word(&dir[DIR_FstClusLO]);
|
||||
dir_info[cnt].fix_date = ld_word((u8 *)(&dir[DIR_WrtDate]));
|
||||
dir_info[cnt].fix_time = ld_word((u8 *)(&dir[DIR_WrtTime]));
|
||||
}
|
||||
cnt++;
|
||||
/* r_printf(">>>[test]:name = %s\n", dir_info[cnt].name); */
|
||||
} else {
|
||||
/* y_printf("\n >>>[test]:func = %s,line= %d\n",__FUNCTION__, __LINE__); */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
*file_num = cnt;
|
||||
free(buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static u32 virfat_flash_available()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
u8 virfat_flash_init(void)
|
||||
{
|
||||
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
|
||||
ASSERT(boot_info.vm.align >= 8, "virfat_flash erase sector < 4K is not support!!!!!!!!!");
|
||||
virfat_get_cpu_fatfs_addr(FATFS_IN_FLASH_NAME, &virfat_flash.flash_fatfs_addr, &virfat_flash.fatfs_len);
|
||||
#endif
|
||||
u32 a = 0;
|
||||
virfat_flash_mount(&virfat_flash, bpb_data);
|
||||
int real_capacity = virfat_flash_get_real_capacity();
|
||||
int min_fat32_size = ((MIN_FAT32 - 2) << (virfat_flash.csize + 9));
|
||||
ASSERT(real_capacity < min_fat32_size, "capacity > min_fat32_size, not surport fat32 flash");
|
||||
/* #if (OUTFLASH_FAT16_ENABLE == 0) */
|
||||
/* #<{(| int min_fat16_size = ((MIN_FAT16 - 2) << (virfat_flash.csize + 9)); |)}># */
|
||||
/* #<{(| r_printf(">>>[test]:min fat16 = %d\n", min_fat16_size); |)}># */
|
||||
/* int min_fat16_size = 10 * 1024 * 1024; */
|
||||
/* if (real_capacity > min_fat16_size) { */
|
||||
/* real_capacity = min_fat16_size; */
|
||||
/* } */
|
||||
/* #endif */
|
||||
r_printf(">>>[test]:real_capacity = 0x%x\n", real_capacity);
|
||||
real_capacity = real_capacity / 512;
|
||||
if (virfat_flash.capacity != real_capacity) {
|
||||
if (real_capacity >= 32 * 1024 * 1024 / 512) {
|
||||
fat_copy(&bpb_data[BPB_TotSec16], &a, 2);
|
||||
fat_copy(&bpb_data[BPB_TotSec32], &real_capacity, 4);
|
||||
} else {
|
||||
fat_copy(&bpb_data[BPB_TotSec16], &real_capacity, 2);
|
||||
}
|
||||
if (real_capacity >= 16 * 1024 * 1024 / 512) {
|
||||
int fatsize = (real_capacity * 512 / 4096 * 2 + 4097) / 4096 * 4096; //计算fat表大小,按fat16来,注意fat表前面占有F8FFFFFF.
|
||||
int fat_sector = fatsize / 512;
|
||||
int rsvdsec = fat_sector + 4096 / 512 + 4096 / 512; //目录项128 * 32 = 4096 不变,工具配置规则目录项没有扩大
|
||||
r_printf(">>>[test]:fat_sector = 0x%x, rsvdsec = 0x%x\n", fat_sector, rsvdsec);
|
||||
fat_copy(&bpb_data[BPB_FATSz16], &fat_sector, 2);
|
||||
fat_copy(&bpb_data[BPB_RsvdSecCnt], &rsvdsec, 2);
|
||||
}
|
||||
put_buf(bpb_data, 96);
|
||||
virfat_flash_mount(&virfat_flash, bpb_data);
|
||||
}
|
||||
|
||||
|
||||
/* y_printf("fatbase:%d \n", virfat_flash.fatbase); */
|
||||
/* y_printf("dirbase:%d \n", virfat_flash.dirbase); */
|
||||
/* y_printf("database:%d \n", virfat_flash.database); */
|
||||
/* y_printf("clustSize:%d \n", virfat_flash.clustSize); */
|
||||
|
||||
return 0;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////device api//////////////////////////////////////////////////////////
|
||||
|
||||
static struct device virfat_flash_dev;
|
||||
static int flash_virfat_init(const struct dev_node *node, void *arg)
|
||||
{
|
||||
/* r_printf(">>>[test]:init name = %s\n", virfat_flash.re_devname); */
|
||||
if (arg) {
|
||||
memcpy(&virfat_flash.re_devname, arg, strlen(arg));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flash_virfat_open(const char *name, struct device **device, void *arg)
|
||||
{
|
||||
/* y_printf(">>>[test]:dev_name = %s\n", virfat_flash.re_devname); */
|
||||
r_printf(">>>[test]:virfat_flash open!!!!!!\n");
|
||||
*device = &virfat_flash_dev;
|
||||
#if TCFG_VIRFAT_INSERT_FLASH_ENABLE
|
||||
virfat_flash_init();
|
||||
return 0;
|
||||
#endif
|
||||
fd = dev_open((const char *)&virfat_flash.re_devname, arg);
|
||||
virfat_flash_init();
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
AT_VOLATILE_RAM_CODE
|
||||
int flash_virfat_read(struct device *device, void *buf, u32 len, u32 addr)
|
||||
{
|
||||
/* y_printf(">>>[test]:r;addr = %d ,len = %d\n", addr, len); */
|
||||
virfat_flash_read_watch(buf, addr, len);
|
||||
return len;
|
||||
}
|
||||
#else
|
||||
AT_VOLATILE_RAM_CODE
|
||||
int flash_virfat_read(struct device *device, void *buf, u32 len, u32 addr)
|
||||
{
|
||||
/* y_printf(">>>[test]:r;addr = %d ,len = %d\n", addr, len); */
|
||||
void *_buf = buf;
|
||||
u32 _len = len;
|
||||
u32 _lba = addr;
|
||||
while (_len) {
|
||||
virfat_flash_read(_buf, _lba, 512);
|
||||
//printf_buf(_buf, 512);
|
||||
_len -= 1;
|
||||
_lba += 1;
|
||||
_buf += 512;
|
||||
}
|
||||
return len;
|
||||
|
||||
/* return virfat_flash_read(buf, addr, len); */
|
||||
}
|
||||
#endif
|
||||
|
||||
static int flash_virfat_write(struct device *device, void *buf, u32 len, u32 addr)
|
||||
{
|
||||
|
||||
/* r_printf(">>>[test]:w;addr = %d ,len = %d\n", addr, len); */
|
||||
/* return virfat_flash_write(buf, addr, len); */
|
||||
void *_buf = buf;
|
||||
u32 _len = len;
|
||||
u32 _lba = addr;
|
||||
while (_len) {
|
||||
virfat_flash_write(_buf, _lba, 512);
|
||||
//printf_buf(_buf, 512);
|
||||
_len -= 1;
|
||||
_lba += 1;
|
||||
_buf += 512;
|
||||
}
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
static bool flash_virfat_online(const struct dev_node *node)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int flash_virfat_close(struct device *device)
|
||||
{
|
||||
dev_close(device);
|
||||
return 0;
|
||||
}
|
||||
static int flash_virfat_ioctrl(struct device *device, u32 cmd, u32 arg)
|
||||
{
|
||||
int err = 0;
|
||||
switch (cmd) {
|
||||
case IOCTL_GET_STATUS:
|
||||
*(u32 *)arg = 1;
|
||||
break;
|
||||
case IOCTL_GET_ID:
|
||||
virfat_ioctl(device, IOCTL_GET_ID, arg);
|
||||
/* *((u32 *)arg) = 0x12345678; */
|
||||
break;
|
||||
case IOCTL_GET_CAPACITY:
|
||||
*((u32 *)arg) = virfat_flash_capacity();
|
||||
break;
|
||||
case IOCTL_GET_BLOCK_SIZE:
|
||||
*((u32 *)arg) = 512;
|
||||
break;
|
||||
case IOCTL_ERASE_PAGE:
|
||||
case IOCTL_ERASE_SECTOR:
|
||||
case IOCTL_ERASE_BLOCK:
|
||||
/* y_printf(">>>[test]:in flash_vir eraser addr = %d\n", arg); */
|
||||
err = virfat_flash_erase(cmd, arg);
|
||||
break;
|
||||
case IOCTL_FLUSH:
|
||||
break;
|
||||
case IOCTL_CMD_RESUME:
|
||||
break;
|
||||
case IOCTL_CMD_SUSPEND:
|
||||
break;
|
||||
case IOCTL_SET_ASYNC_MODE:
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct device_operations virfat_flash_dev_ops = {
|
||||
.init = flash_virfat_init,
|
||||
.online = flash_virfat_online,
|
||||
.open = flash_virfat_open,
|
||||
.read = flash_virfat_read,
|
||||
.write = flash_virfat_write,
|
||||
.ioctl = flash_virfat_ioctrl,
|
||||
.close = flash_virfat_close,
|
||||
};
|
||||
|
||||
static int _private_sfc_read(void *fd, void *buf, u32 addr, u32 len)
|
||||
{
|
||||
struct device *device = (struct device *)fd;
|
||||
FLASH_PRIVATE_INFO *flash_private_info = (FLASH_PRIVATE_INFO *)device->private_data;
|
||||
if (flash_private_info->private_len < (addr + len)) {
|
||||
return -1;
|
||||
}
|
||||
u32 cpu_addr = virfat_flash_addr2cpu_addr(flash_private_info->flash_private_addr + addr);
|
||||
/* r_printf(">>>[test]:cpu_addr = %d, addr = %d\n", cpu_addr, addr); */
|
||||
memcpy((u8 *)buf, (u8 *)cpu_addr, len);
|
||||
/* put_buf(buf, len); */
|
||||
return len;
|
||||
}
|
||||
|
||||
static int _private_sfc_write(void *fd, void *buf, u32 addr, u32 len)
|
||||
{
|
||||
struct device *device = (struct device *)fd;
|
||||
FLASH_PRIVATE_INFO *flash_private_info = (FLASH_PRIVATE_INFO *)device->private_data;
|
||||
if (flash_private_info->private_len < (addr + len)) {
|
||||
return -1;
|
||||
}
|
||||
u32 wlen = -1;
|
||||
addr += flash_private_info->flash_private_addr;
|
||||
/* r_printf(">>>[test]:addr = %d\n", addr); */
|
||||
/* put_buf(buf, len); */
|
||||
wlen = norflash_write(NULL, buf, len, addr);
|
||||
return wlen;
|
||||
}
|
||||
|
||||
static int _private_sfc_ioctl(void *fd, u32 cmd, u32 arg)
|
||||
{
|
||||
int res = -1;
|
||||
struct device *device = (struct device *)fd;
|
||||
FLASH_PRIVATE_INFO *flash_private_info = (FLASH_PRIVATE_INFO *)device->private_data;
|
||||
if ((cmd == IOCTL_ERASE_SECTOR) || (cmd == IOCTL_ERASE_PAGE) || (cmd == IOCTL_ERASE_BLOCK)) {
|
||||
if (flash_private_info->private_len <= arg) {
|
||||
return -1;
|
||||
}
|
||||
arg += flash_private_info->flash_private_addr;
|
||||
}
|
||||
res = norflash_ioctl(NULL, cmd, arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int private_sfc_init(const struct dev_node *node, void *arg)
|
||||
{
|
||||
virfat_mutex_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int private_sfc_open(const char *name, struct device **device, void *arg)
|
||||
{
|
||||
r_printf(">>>[test]:private_sfc open!!!!!!\n");
|
||||
virfat_mutex_pend();
|
||||
struct device *private_sfc_dev = (struct device *)zalloc(sizeof(struct device));
|
||||
FLASH_PRIVATE_INFO *flash_private_info = (FLASH_PRIVATE_INFO *)zalloc(sizeof(FLASH_PRIVATE_INFO));
|
||||
if (arg) {
|
||||
memcpy(flash_private_info->part_name, arg, strlen(arg));
|
||||
}
|
||||
ASSERT(boot_info.vm.align >= 8, "virfat_flash erase sector < 4K is not support!!!!!!!!!");
|
||||
virfat_get_cpu_fatfs_addr(flash_private_info->part_name, &flash_private_info->flash_private_addr, &flash_private_info->private_len);
|
||||
private_sfc_dev->private_data = flash_private_info;
|
||||
*device = private_sfc_dev;
|
||||
virfat_mutex_post();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int private_sfc_read(struct device *device, void *buf, u32 len, u32 addr)
|
||||
{
|
||||
/* y_printf(">>>[test]:r;addr = %d ,len = %d\n", addr, len); */
|
||||
virfat_mutex_pend();
|
||||
int rlen = _private_sfc_read(device, buf, addr, len);
|
||||
virfat_mutex_post();
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static int private_sfc_write(struct device *device, void *buf, u32 len, u32 addr)
|
||||
{
|
||||
|
||||
/* r_printf(">>>[test]:w;addr = %d ,len = %d\n", addr, len); */
|
||||
virfat_mutex_pend();
|
||||
int wlen = _private_sfc_write(device, buf, addr, len);
|
||||
virfat_mutex_post();
|
||||
return wlen;
|
||||
}
|
||||
|
||||
static bool private_sfc_online(const struct dev_node *node)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int private_sfc_close(struct device *device)
|
||||
{
|
||||
virfat_mutex_pend();
|
||||
dev_close(device);
|
||||
if (device->private_data) {
|
||||
free(device->private_data);
|
||||
}
|
||||
free(device);
|
||||
virfat_mutex_post();
|
||||
return 0;
|
||||
}
|
||||
static int private_sfc_ioctrl(struct device *device, u32 cmd, u32 arg)
|
||||
{
|
||||
virfat_mutex_pend();
|
||||
int err = 0;
|
||||
FLASH_PRIVATE_INFO *flash_private_info = (FLASH_PRIVATE_INFO *)device->private_data;
|
||||
switch (cmd) {
|
||||
case IOCTL_GET_STATUS:
|
||||
*(u32 *)arg = 1;
|
||||
break;
|
||||
case IOCTL_GET_ID:
|
||||
/* virfat_ioctl(device, IOCTL_GET_ID, arg); */
|
||||
/* *((u32 *)arg) = 0x12345678; */
|
||||
break;
|
||||
case IOCTL_GET_CAPACITY:
|
||||
*((u32 *)arg) = flash_private_info->private_len;
|
||||
break;
|
||||
case IOCTL_GET_BLOCK_SIZE:
|
||||
*((u32 *)arg) = 512;
|
||||
break;
|
||||
case IOCTL_ERASE_PAGE:
|
||||
case IOCTL_ERASE_SECTOR:
|
||||
case IOCTL_ERASE_BLOCK:
|
||||
/* y_printf(">>>[test]:in flash_vir eraser addr = %d\n", arg); */
|
||||
err = _private_sfc_ioctl(device, cmd, arg);
|
||||
break;
|
||||
case IOCTL_FLUSH:
|
||||
break;
|
||||
case IOCTL_CMD_RESUME:
|
||||
break;
|
||||
case IOCTL_CMD_SUSPEND:
|
||||
break;
|
||||
case IOCTL_SET_ASYNC_MODE:
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
virfat_mutex_post();
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct device_operations private_sfc_dev_ops = {
|
||||
.init = private_sfc_init,
|
||||
.online = private_sfc_online,
|
||||
.open = private_sfc_open,
|
||||
.read = private_sfc_read,
|
||||
.write = private_sfc_write,
|
||||
.ioctl = private_sfc_ioctrl,
|
||||
.close = private_sfc_close,
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* AC51
|
||||
* fs browser select
|
||||
* CODE
|
||||
*
|
||||
* (c) Copyright 2015-2016, ZHUHAI JIELI
|
||||
* All Rights Reserved
|
||||
*
|
||||
* File : *
|
||||
* By : jamin.li
|
||||
* DATE : 2015-10-15 build this file
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#include "file_bs_deal.h"
|
||||
#include "uart.h"
|
||||
#include "dev_manager.h"
|
||||
|
||||
#define FILE_BS_OPT_DBG
|
||||
#ifdef FILE_BS_OPT_DBG
|
||||
|
||||
#define file_bs_puts puts
|
||||
#define file_bs_printf printf
|
||||
|
||||
#else
|
||||
#define file_bs_puts(...)
|
||||
#define file_bs_printf(...)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 在指定数据中,搜索key(byte)的位置
|
||||
*
|
||||
* Arguments : buf - 指定数据起始地址, buf_len-长度, key-搜索的key,
|
||||
* find_type -搜索方向:0-从前往后搜索,1-从后往前搜索
|
||||
*
|
||||
* Returns : key的位置
|
||||
*
|
||||
* Note:
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
//查找byte的位置
|
||||
static int find_byte_pos(u8 *buf, u16 buf_len, u8 key, u8 find_type)
|
||||
{
|
||||
u8 *data = buf;
|
||||
|
||||
if (0 == find_type) {
|
||||
//从前往后找
|
||||
while (buf_len > 0) {
|
||||
if (*data == key) {
|
||||
return (int)(data - buf);
|
||||
}
|
||||
data++;
|
||||
buf_len--;
|
||||
}
|
||||
} else {
|
||||
//从后往前找
|
||||
data += (buf_len - 1);
|
||||
while (buf_len > 0) {
|
||||
if (*data == key) {
|
||||
return (int)(data - buf);
|
||||
}
|
||||
data--;
|
||||
buf_len--;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 转化路径格式
|
||||
*
|
||||
* Arguments :
|
||||
*
|
||||
* Returns : 0-为成功,其他值 失败
|
||||
*
|
||||
* Note:
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
int file_comm_change_file_path(char *dest, char *src)
|
||||
{
|
||||
u8 start_flag = 0, space_flag, val;
|
||||
|
||||
while (1) {
|
||||
val = *src;
|
||||
if (val == '\0') {
|
||||
*dest = '\0';
|
||||
break;
|
||||
}
|
||||
switch (val) {
|
||||
case '/':
|
||||
if (start_flag != 0) {
|
||||
space_flag = 0;
|
||||
}
|
||||
start_flag++;
|
||||
*dest = val;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
space_flag = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (space_flag != 0) {
|
||||
*dest = '.';
|
||||
dest++;
|
||||
space_flag = 0;
|
||||
}
|
||||
*dest = val;
|
||||
break;
|
||||
}
|
||||
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 修正从fs取等的长名
|
||||
*
|
||||
* Arguments : str,len
|
||||
*
|
||||
* Returns : 字节长度(不包含结束符)
|
||||
*
|
||||
* Note: 过滤0xffff值,自动填入结束符
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
int file_comm_long_name_fix(u8 *str, u16 len)
|
||||
{
|
||||
u8 *src = str;
|
||||
while (len > 1) {
|
||||
if ((*str == 0xff) && (*(str + 1) == 0xff)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((*str == 0x0) && (*(str + 1) == 0x0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
str += 2;
|
||||
len -= 2;
|
||||
}
|
||||
*str = 0x00;
|
||||
*(str + 1) = 0x00;
|
||||
return (int)(str - src);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 转换8+3名字显示
|
||||
*
|
||||
* Arguments : dest,src
|
||||
*
|
||||
* Returns : 转换后名字的长度(不包含结束符)
|
||||
*
|
||||
* Note: 转换后自动填入结束符
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
int file_comm_display_83name(u8 *dest, u8 *src)
|
||||
{
|
||||
u8 offset;
|
||||
|
||||
for (offset = 8; offset > 0; offset--) {
|
||||
if (src[offset - 1] != 0x20) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(dest, src, offset);
|
||||
|
||||
if (src[8] != 0x20) {
|
||||
dest[offset++] = '.';
|
||||
memcpy(dest + offset, src + 8, 3);
|
||||
offset += 3;
|
||||
}
|
||||
|
||||
dest[offset++] = '\0';
|
||||
|
||||
return offset; //name 's len
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 获取显示的文件夹或文件名字
|
||||
*
|
||||
* Arguments :tpath,disp_file_name,disp_dir_name
|
||||
*
|
||||
* Returns :
|
||||
*
|
||||
* Note: 转换后 lfn_cnt 为0为短名,lfn_cnt不为0 则是长名
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void file_comm_change_display_name(char *tpath, LONG_FILE_NAME *disp_file_name, LONG_FILE_NAME *disp_dir_name)
|
||||
{
|
||||
u16 len;
|
||||
int pos;
|
||||
|
||||
//取文件名字显示
|
||||
|
||||
if (disp_file_name != NULL) {
|
||||
if (disp_file_name->lfn_cnt != 0) {
|
||||
//long name
|
||||
file_bs_puts("file long name \n");
|
||||
//printf_buf(disp_file_name->lfn, 16);
|
||||
disp_file_name->lfn_cnt = file_comm_long_name_fix((void *)disp_file_name->lfn, disp_file_name->lfn_cnt); //增加结束符
|
||||
} else {
|
||||
//short name
|
||||
file_bs_puts("file short name\n");
|
||||
len = strlen((void *)tpath); //增加结束符
|
||||
pos = find_byte_pos((void *)tpath, len, 0x2f, 1); //
|
||||
if (pos == -1) {
|
||||
strcpy(disp_file_name->lfn, "----");
|
||||
} else {
|
||||
memcpy((void *)&disp_file_name->lfn[32], tpath + pos + 1, 11);
|
||||
file_comm_display_83name((void *)disp_file_name->lfn, (void *)&disp_file_name->lfn[32]);
|
||||
}
|
||||
|
||||
disp_file_name->lfn_cnt = 0;
|
||||
}
|
||||
|
||||
//printf_buf(disp_file_name->lfn, 32);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//取文件夹名字显示
|
||||
if (disp_dir_name != NULL) {
|
||||
if (disp_dir_name->lfn_cnt != 0) {
|
||||
//long name
|
||||
file_bs_puts("folder long name \n");
|
||||
//printf_buf(disp_dir_name->lfn, 16);
|
||||
disp_dir_name->lfn_cnt = file_comm_long_name_fix((void *)&disp_dir_name->lfn, disp_dir_name->lfn_cnt); //增加结束符
|
||||
} else {
|
||||
//short name
|
||||
file_bs_puts("folder short name \n");
|
||||
len = strlen((void *)tpath); //增加结束符
|
||||
pos = find_byte_pos((void *)tpath, len, 0x2f, 1); //
|
||||
|
||||
if (pos != -1) {
|
||||
pos = find_byte_pos((void *)tpath, pos, 0x2f, 1); //
|
||||
}
|
||||
|
||||
if (pos == -1) {
|
||||
strcpy(disp_dir_name->lfn, "ROOT");
|
||||
} else {
|
||||
memcpy(&disp_dir_name->lfn[32], tpath + pos + 1, 11);
|
||||
file_comm_display_83name((void *)disp_dir_name->lfn, (void *)&disp_dir_name->lfn[32]);
|
||||
}
|
||||
disp_dir_name->lfn_cnt = 0;
|
||||
}
|
||||
|
||||
//printf_buf(disp_dir_name->lfn, 32);
|
||||
}
|
||||
}
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 打开文件浏览器
|
||||
*
|
||||
* Arguments : fil_bs
|
||||
*
|
||||
* Returns : dir的总数
|
||||
*
|
||||
* Note:
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
//返回根目录dir总数
|
||||
u32 file_bs_open_handle(FILE_BS_DEAL *fil_bs, u8 *ext_name)
|
||||
{
|
||||
u32 total_dir;
|
||||
|
||||
if (fil_bs == NULL) {
|
||||
puts("*open hdl is null\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
file_bs_puts("open bs hdl\n");
|
||||
file_bs_printf("bs_mapi:0x%x\n", (int)fil_bs);
|
||||
|
||||
if (ext_name == NULL) {
|
||||
ext_name = "MP3";//"WAVWMAMP3FLA";
|
||||
}
|
||||
|
||||
printf("fil_bs->dev = %x\n", fil_bs->dev);
|
||||
printf("%s, %s, %s, %d\n]", dev_manager_get_root_path(fil_bs->dev), dev_manager_get_logo(fil_bs->dev), __FUNCTION__, __LINE__);
|
||||
fset_ext_type(dev_manager_get_root_path(fil_bs->dev), ext_name);
|
||||
printf("%s, %d\n]", __FUNCTION__, __LINE__);
|
||||
|
||||
total_dir = fopen_dir_info(dev_manager_get_root_path(fil_bs->dev), &fil_bs->file, 0);
|
||||
printf("%s, %d\n]", __FUNCTION__, __LINE__);
|
||||
if (fil_bs->file == 0) {
|
||||
file_bs_puts("open bs fail\n");
|
||||
return 0;
|
||||
}
|
||||
file_bs_printf("open bs hdl_out,root_dir = 0x%x\n", total_dir);
|
||||
return total_dir;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 关闭文件浏览器
|
||||
*
|
||||
* Arguments : fil_bs
|
||||
*
|
||||
* Returns :
|
||||
*
|
||||
* Note:
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
void file_bs_close_handle(FILE_BS_DEAL *fil_bs)
|
||||
{
|
||||
file_bs_puts("close bs hdl\n");
|
||||
if (fil_bs->file) {
|
||||
fclose(fil_bs->file);
|
||||
fil_bs->file = NULL;
|
||||
}
|
||||
file_bs_puts("close bs hdl_out\n");
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 进入文件夹目录
|
||||
*
|
||||
* Arguments : fil_bs,dir_info
|
||||
*
|
||||
* Returns : dir的总数
|
||||
*
|
||||
* Note:
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
u32 file_bs_entern_dir(FILE_BS_DEAL *fil_bs, FS_DIR_INFO *dir_info)
|
||||
{
|
||||
u32 total_dir;
|
||||
file_bs_printf("bs_enter dir\n");
|
||||
total_dir = fenter_dir_info(fil_bs->file, dir_info); //使用open获得的file,无需重新申请。
|
||||
file_bs_printf("bs_enter_out,t = 0x%x\n", total_dir);
|
||||
return total_dir;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 返回上传目录
|
||||
*
|
||||
* Arguments : fil_bs
|
||||
*
|
||||
* Returns : dir的总数
|
||||
*
|
||||
* Note:
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
u32 file_bs_exit_dir(FILE_BS_DEAL *fil_bs)
|
||||
{
|
||||
u32 total_dir;
|
||||
file_bs_printf("bs_exit dir\n");
|
||||
total_dir = fexit_dir_info(fil_bs->file);//
|
||||
file_bs_printf("bs_exit_out,total = 0x%x\n", total_dir);
|
||||
return total_dir;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
*
|
||||
* Description: 获取指定位置的dir信息
|
||||
*
|
||||
* Arguments : fil_bs,buf--被填入的buf,start_sn -获取的其实位置(从1开始),get_cnt--获取dir的个数
|
||||
*
|
||||
* Returns : 真正获取到的dir总数
|
||||
*
|
||||
* Note:
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
u32 file_bs_get_dir_info(FILE_BS_DEAL *fil_bs, FS_DIR_INFO *buf, u16 start_sn, u16 get_cnt)
|
||||
{
|
||||
u32 real_dir;
|
||||
/* file_bs_printf("bs_get dir_info\n"); */
|
||||
real_dir = fget_dir_info(fil_bs->file, start_sn, get_cnt, buf);
|
||||
/* file_bs_printf("bs_get_out,t = 0x%x\n", real_dir); */
|
||||
return real_dir;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// test
|
||||
|
||||
#if 0
|
||||
|
||||
#define BS_GET_DIR_NUM 3
|
||||
void file_bs_test(void)
|
||||
{
|
||||
printf("\n\n\n\n %s,%d, ", __func__, __LINE__);
|
||||
FS_DIR_INFO *dir_buf = zalloc(sizeof(FS_DIR_INFO) * BS_GET_DIR_NUM);
|
||||
FILE_BS_DEAL *fil_bs = zalloc(sizeof(FILE_BS_DEAL));
|
||||
if (!fil_bs || !dir_buf) {
|
||||
printf("%s,%d, ", __func__, __LINE__);
|
||||
printf("malloc err");
|
||||
while (1);
|
||||
}
|
||||
fil_bs->dev = storage_dev_last();
|
||||
if (!fil_bs->dev) {
|
||||
printf("%s,%d, ", __func__, __LINE__);
|
||||
printf("have no dev");
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* void *fmnt = mount(fil_bs->dev->dev_name, fil_bs->dev->storage_path, fil_bs->dev->fs_type, 3, NULL); */
|
||||
/* if (!fmnt) { */
|
||||
/* printf("%s,%d, ", __func__, __LINE__); */
|
||||
/* printf("mount err"); */
|
||||
/* while(1); */
|
||||
/* } */
|
||||
|
||||
int i, j, cnt, total;
|
||||
file_bs_open_handle(fil_bs, "MP3");//open完后需要close
|
||||
/* printf("\n root dir num: %d ", total); */
|
||||
/* if (!total) { */
|
||||
/* printf("%s,%d, ", __func__, __LINE__); */
|
||||
/* printf("total dir is zero"); */
|
||||
/* goto __exit; */
|
||||
/* } */
|
||||
|
||||
total = file_bs_entern_dir(fil_bs, dir_buf);
|
||||
/* printf("\n %s,%d, ", __func__, __LINE__); */
|
||||
/* printf("dir num: %d ", total); */
|
||||
if (!total) {
|
||||
printf("%s,%d, ", __func__, __LINE__);
|
||||
printf("total dir is zero");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
u8 flag = 0;
|
||||
for (i = 1; i <= total; i += BS_GET_DIR_NUM) {
|
||||
__again:
|
||||
cnt = file_bs_get_dir_info(fil_bs, dir_buf, i, BS_GET_DIR_NUM);
|
||||
/* printf("\n cnt:%d ", cnt); */
|
||||
for (j = 0; j < cnt; j++) {
|
||||
/* printf("j:%d, dirtype:%d, fntype:%d, sclust:0x%x ", i + j, dir_buf[j].dir_type, dir_buf[j].fn_type, dir_buf[j].sclust); */
|
||||
if (dir_buf[j].dir_type == BS_DIR_TYPE_FORLDER) {
|
||||
if (flag < 2) {
|
||||
flag ++;
|
||||
if (flag == 2) {
|
||||
int sub_i, sub_j, sub_cnt, sub_total;
|
||||
sub_total = file_bs_entern_dir(fil_bs, &dir_buf[j]);
|
||||
/* printf("\n %s,%d, ", __func__, __LINE__); */
|
||||
/* printf("dir num: %d ", sub_total); */
|
||||
if (sub_total) {
|
||||
for (sub_i = 1; sub_i <= sub_total; sub_i += BS_GET_DIR_NUM) {
|
||||
sub_cnt = file_bs_get_dir_info(fil_bs, dir_buf, sub_i, BS_GET_DIR_NUM);
|
||||
/* printf("sub_cnt:%d ", sub_cnt); */
|
||||
for (sub_j = 0; sub_j < sub_cnt; sub_j++) {
|
||||
/* printf("sub_j:%d, dirtype:%d, fntype:%d, sclust:0x%x ", sub_i + sub_j, dir_buf[sub_j].dir_type, dir_buf[sub_j].fn_type, dir_buf[sub_j].sclust); */
|
||||
}
|
||||
}
|
||||
}
|
||||
file_bs_exit_dir(fil_bs);
|
||||
goto __again;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__exit:
|
||||
/* printf("\n %s,%d, \n ", __func__, __LINE__); */
|
||||
|
||||
file_bs_close_handle(fil_bs);
|
||||
|
||||
/* unmount(fil_bs->dev->storage_path); */
|
||||
|
||||
free(dir_buf);
|
||||
free(fil_bs);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
*********************************************************************************************************
|
||||
* AC46
|
||||
* fs browser select
|
||||
* CODE
|
||||
*
|
||||
* (c) Copyright 2015-2016, ZHUHAI JIELI
|
||||
* All Rights Reserved
|
||||
*
|
||||
* File : *
|
||||
* By : jamin.li
|
||||
* DATE : 2015-10-15 build this file
|
||||
*********************************************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _FILE_BS_DEAL_H_
|
||||
#define _FILE_BS_DEAL_H_
|
||||
|
||||
#include "fs/fs.h"
|
||||
#include "storage_dev/storage_dev.h"
|
||||
|
||||
#define BS_DIR_TYPE_FORLDER 0
|
||||
#define BS_DIR_TYPE_FILE 1
|
||||
|
||||
#define BS_FNAME_TYPE_SHORT 0
|
||||
#define BS_FNAME_TYPE_LONG 1
|
||||
|
||||
typedef struct _FILE_BS_DEAL_ {
|
||||
struct __dev *dev;
|
||||
FILE *file;
|
||||
} FILE_BS_DEAL;
|
||||
|
||||
|
||||
extern int file_comm_change_file_path(char *dest, char *src);
|
||||
extern int file_comm_long_name_fix(u8 *str, u16 len);
|
||||
extern int file_comm_display_83name(u8 *dest, u8 *src);
|
||||
|
||||
extern u32 file_bs_open_handle(FILE_BS_DEAL *fil_bs, u8 *ext_name);
|
||||
extern void file_bs_close_handle(FILE_BS_DEAL *fil_bs);
|
||||
extern u32 file_bs_entern_dir(FILE_BS_DEAL *fil_bs, FS_DIR_INFO *dir_info);
|
||||
extern u32 file_bs_exit_dir(FILE_BS_DEAL *fil_bs);
|
||||
extern u32 file_bs_get_dir_info(FILE_BS_DEAL *fil_bs, FS_DIR_INFO *buf, u16 start_sn, u16 get_cnt);
|
||||
|
||||
extern void file_comm_change_display_name(char *tpath, LONG_FILE_NAME *disp_file_name, LONG_FILE_NAME *disp_dir_name);
|
||||
|
||||
#endif/*_FILE_BS_DEAL_H_*/
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
#include "file_manager.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#define MODE_FIX 0
|
||||
#if MODE_FIX
|
||||
static int file_manager_mode_deal(struct vfscan *fs, int sel_mode, int *arg)
|
||||
{
|
||||
|
||||
int err;
|
||||
int fnum = 0;
|
||||
int file_start = 1;
|
||||
int file_end = fs->file_number;
|
||||
|
||||
if (file_end == 0) {
|
||||
return -ENOENT;
|
||||
}
|
||||
struct ffolder folder = {0};
|
||||
fget_folder(fs, &folder);
|
||||
/* if ((scan->cycle_mode == FCYCLE_FOLDER) && (scan->ff_api.fileTotalInDir) */
|
||||
/* && ((scan->ff_api.fileTotalOutDir + scan->ff_api.fileTotalInDir) <= scan->ff_api.totalFileNumber) */
|
||||
/* ) { */
|
||||
|
||||
if ((fs->cycle_mode == FCYCLE_FOLDER) && (folder.fileTotal)
|
||||
&& ((folder.fileStart + folder.fileTotal - 1) <= file_end)
|
||||
) {
|
||||
file_start = folder.fileStart;
|
||||
file_end = folder.fileStart + folder.fileTotal - 1;
|
||||
}
|
||||
switch (sel_mode) {
|
||||
case FSEL_LAST_FILE:
|
||||
fnum = fs->file_number;
|
||||
break;
|
||||
case FSEL_FIRST_FILE:
|
||||
fnum = 1;
|
||||
break;
|
||||
case FSEL_AUTO_FILE:
|
||||
/* if (scan->ff_api.fileNumber == 0) { */
|
||||
/* return -EINVAL; */
|
||||
/* } */
|
||||
if (fs->cycle_mode == FCYCLE_ONE) {
|
||||
/* fnum = scan->ff_api.fileNumber; */
|
||||
fnum = fs->file_counter;
|
||||
break;
|
||||
}
|
||||
case FSEL_NEXT_FILE:
|
||||
/* if (scan->ff_api.fileNumber == 0) { */
|
||||
/* return -EINVAL; */
|
||||
/* } */
|
||||
if (fs->cycle_mode == FCYCLE_RANDOM) {
|
||||
fnum = rand32() % (file_end - file_start + 1) + file_start;
|
||||
if (fnum == fs->file_counter) {
|
||||
fnum = fs->file_counter + 1;
|
||||
}
|
||||
} else {
|
||||
fnum = fs->file_counter + 1;
|
||||
}
|
||||
/* if (fnum > scan->last_file_number) { */
|
||||
if (fnum > fs->file_number) {
|
||||
if (fs->cycle_mode == FCYCLE_LIST) {
|
||||
return -ENOENT;
|
||||
} else if (fs->cycle_mode == FCYCLE_FOLDER) {
|
||||
fnum = file_start;
|
||||
} else {
|
||||
fnum = 1;
|
||||
}
|
||||
}
|
||||
if (fnum > file_end) {
|
||||
fnum = file_start;
|
||||
} else if (fnum < file_start) {
|
||||
fnum = file_end;
|
||||
}
|
||||
break;
|
||||
case FSEL_PREV_FILE:
|
||||
/* if (scan->ff_api.fileNumber == 0) { */
|
||||
/* return -EINVAL; */
|
||||
/* } */
|
||||
if (fs->cycle_mode == FCYCLE_RANDOM) {
|
||||
fnum = rand32() % (file_end - file_start + 1) + file_start;
|
||||
if (fnum == fs->file_counter) {
|
||||
fnum = fs->file_counter + 1;
|
||||
}
|
||||
} else {
|
||||
fnum = fs->file_counter - 1;
|
||||
}
|
||||
/* if ((scan->ff_api.fileNumber | BIT(15)) != scan->cur_file_number) { */
|
||||
/* fnum -= scan->last_file_number - scan->ff_api.totalFileNumber; */
|
||||
/* } */
|
||||
/* scan->last_file_number = scan->ff_api.totalFileNumber; */
|
||||
if (fs->cycle_mode == FCYCLE_LIST) {
|
||||
break;
|
||||
}
|
||||
if (fnum > file_end) {
|
||||
fnum = file_start;
|
||||
} else if (fnum < file_start) {
|
||||
fnum = file_end;
|
||||
}
|
||||
break;
|
||||
|
||||
case FSEL_NEXT_FOLDER_FILE:
|
||||
/* fnum = scan->ff_api.fileTotalOutDir + scan->ff_api.fileTotalInDir + 1; */
|
||||
fnum = folder.fileStart + folder.fileTotal;
|
||||
if (fnum > fs->file_number) {
|
||||
fnum = 1;
|
||||
}
|
||||
break;
|
||||
case FSEL_PREV_FOLDER_FILE:
|
||||
/* if ((scan->ff_api.fileTotalOutDir + 1) > 1) { */
|
||||
if (folder.fileStart > 1) {
|
||||
fnum = folder.fileStart - 1;
|
||||
} else {
|
||||
fnum = fs->file_number;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((sel_mode != FSEL_NEXT_FOLDER_FILE) && (sel_mode != FSEL_PREV_FOLDER_FILE)) {
|
||||
if (fnum < file_start) {
|
||||
fnum = file_start;
|
||||
} else if (fnum > file_end) {
|
||||
fnum = file_end;
|
||||
}
|
||||
}
|
||||
*arg = fnum;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
FILE *file_manager_select(struct __dev *dev, struct vfscan *fs, int sel_mode, int arg, struct __scan_callback *callback)
|
||||
{
|
||||
FILE *_file = NULL;
|
||||
//clock_add_set(SCAN_DISK_CLK);
|
||||
if (callback && callback->enter) {
|
||||
callback->enter(dev);//扫描前处理, 可以在注册的回调里提高系统时钟等处理
|
||||
}
|
||||
#if MODE_FIX
|
||||
if ((sel_mode != FSEL_BY_SCLUST) && (sel_mode != FSEL_BY_PATH)) {
|
||||
if (file_manager_mode_deal(fs, sel_mode, &arg)) {
|
||||
return NULL;
|
||||
}
|
||||
sel_mode = FSEL_BY_NUMBER;
|
||||
}
|
||||
#endif
|
||||
_file = fselect(fs, sel_mode, arg);
|
||||
//clock_remove_set(SCAN_DISK_CLK);
|
||||
if (callback && callback->exit) {
|
||||
callback->exit(dev);//扫描后处理, 可以在注册的回调里还原到enter前的状态
|
||||
}
|
||||
return _file;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief 文件删除统一处理
|
||||
*
|
||||
* @param path 扫描路径名
|
||||
* @param param 配置参数
|
||||
* @param dir_flag 是否删除文件夹标志
|
||||
* @note 加速处理:(删除文件的时候使用)从前往后依次删除. 文件夹必须从后往前删。
|
||||
*
|
||||
* @return 0成功, 其他失败
|
||||
*/
|
||||
/* ----------------------------------------------------------------------------*/
|
||||
int file_manager_delete_deal(char *path, char *param, u8 dir_flag)
|
||||
{
|
||||
u16 folder_total_file = 0;
|
||||
int d_err = 0;
|
||||
struct vfscan *fsn = NULL;
|
||||
FILE *d_f = NULL;
|
||||
|
||||
fsn = fscan(path, param, 9);
|
||||
if (fsn == NULL) {
|
||||
r_printf(">>>[test]:err!!!!!! fsacn fsn fail\n");
|
||||
return 1;
|
||||
}
|
||||
folder_total_file = fsn->file_number;
|
||||
y_printf(">>>[test]:total = %d\n", folder_total_file);
|
||||
for (int i = folder_total_file; i >= 1; i--) {
|
||||
if (!dir_flag) {
|
||||
d_f = fselect(fsn, FSEL_BY_NUMBER, folder_total_file - i + 1); //加速处理,不用找到最后一个文件。
|
||||
} else {
|
||||
d_f = fselect(fsn, FSEL_BY_NUMBER, i);
|
||||
}
|
||||
if (d_f == NULL) {
|
||||
r_printf(">>>[test]:err!! select file err\n");
|
||||
return 1;
|
||||
}
|
||||
putchar('D');
|
||||
d_err = fdelete(d_f);
|
||||
if (d_err) {
|
||||
r_printf(">>>[test]:err!! delete file err\n");
|
||||
return 1;
|
||||
}
|
||||
d_f = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief:文件夹删除处理
|
||||
@param:dev_logo :设备logo folder:文件夹路径(短名) folder_len:文件夹路径长度
|
||||
@return:
|
||||
@author:phewlee
|
||||
@note:
|
||||
@date: 2021-05-21,10:16
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int file_manager_delete_dir(char *dev_logo, char *folder, u16 folder_len)
|
||||
{
|
||||
int err = 0;
|
||||
struct __dev *dev;
|
||||
char path[128] = {0};
|
||||
|
||||
static const u8 delete_file_param[] = "-t"
|
||||
"ALL"
|
||||
" -sn -r";
|
||||
|
||||
static const u8 delete_folder_param[] = "-t"
|
||||
"ALL"
|
||||
" -sn -d -r";
|
||||
|
||||
dev = dev_manager_find_spec(dev_logo, 0);
|
||||
if (dev == NULL) {
|
||||
r_printf(">>>[test]:errr!!!!!!!!! not find dev\n");
|
||||
return 1;
|
||||
}
|
||||
char *root_path = dev_manager_get_root_path(dev);
|
||||
memcpy(path, root_path, strlen(root_path));
|
||||
memcpy(path + strlen(root_path), folder, folder_len);
|
||||
r_printf(">>>[test]:path = %s\n", path);
|
||||
err = file_manager_delete_deal(path, delete_file_param, 0);
|
||||
if (err) {
|
||||
r_printf(">>>[test]:errr!!!!!!!!! delete file deal fail\n");
|
||||
return 1;
|
||||
}
|
||||
err = file_manager_delete_deal(path, delete_folder_param, 1);
|
||||
if (err) {
|
||||
r_printf(">>>[test]:errr!!!!!!!!! delete folder deal fail\n");
|
||||
return 1;
|
||||
}
|
||||
FILE *folder_f = fopen(path, "r");
|
||||
if (folder_f == NULL) {
|
||||
r_printf(">>>[test]:err open folder\n");
|
||||
return 1;
|
||||
}
|
||||
err = fdelete(folder_f);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief:文件插入处理
|
||||
@param:d_f: 源文件句柄, i_f:插入文件句柄,fptr:偏移量
|
||||
@return:
|
||||
@author:phewlee
|
||||
@note:
|
||||
@date: 2021-05-25,10:16
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int file_manager_insert_file(FILE *d_f, FILE *i_f, u32 fptr)
|
||||
{
|
||||
int err = finsert_file(d_f, i_f, fptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief:文件分割处理
|
||||
@param:f: 源文件句柄, dev_logo:设备logo , file_name : 文件名, name_len: 文件长度, fptr:偏移量, buf:头文件数据, buf_len:头文件数据长度, folder : 需要指定的路径,绝对路径,例如:/RECORD或者/1/2/3/4, 暂时只支持短名文件夹形式, folder 传NULL默认根目录。
|
||||
@return:
|
||||
@author:phewlee
|
||||
@note:
|
||||
@date: 2021-05-25,10:16
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int file_manager_division_file(FILE *f, char *dev_logo, char *file_name, u32 name_len, u32 fptr, char *buf, u32 buf_len, char *folder)
|
||||
{
|
||||
struct __dev *dev;
|
||||
char path[128] = {0};
|
||||
char tmp_name[64] = {0};
|
||||
if ((dev_logo == NULL) || (file_name == NULL) || (buf == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
dev = dev_manager_find_spec(dev_logo, 0);
|
||||
if (dev == NULL) {
|
||||
r_printf(">>>[test]:errr!!!!!!!!! not find dev\n");
|
||||
return -1;
|
||||
}
|
||||
char *root_path = dev_manager_get_root_path(dev);
|
||||
|
||||
/****************分割文件*********************/
|
||||
if (folder) {
|
||||
memcpy(tmp_name, folder, strlen(folder));
|
||||
}
|
||||
strcat(tmp_name, "/");
|
||||
strcat(tmp_name, "jl_test.tmp");
|
||||
if (fdicvision_file(f, tmp_name, fptr)) {
|
||||
r_printf(">>>[test]:file division fail\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
/****************打开分割出去的文件*********************/
|
||||
memcpy(path, root_path, strlen(root_path) - 1);
|
||||
memcpy(path + strlen(root_path) - 1, tmp_name, strlen(tmp_name));
|
||||
r_printf(">>>[test]:path1 = %s\n", path);
|
||||
FILE *i_f = fopen(path, "r");
|
||||
if (i_f == NULL) {
|
||||
r_printf(">>>[test]:open i_f fail\n");
|
||||
return -1;
|
||||
}
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
/****************创建新文件,写入头数据*********************/
|
||||
memset(path, 0, sizeof(path));
|
||||
memcpy(path, root_path, strlen(root_path));
|
||||
if (folder) {
|
||||
memcpy(path + strlen(path) - 1, folder, strlen(folder));
|
||||
strcat(path, "/");
|
||||
}
|
||||
memcpy(path + strlen(path), file_name, name_len);
|
||||
r_printf(">>>[test]:path1 = %s\n", path);
|
||||
FILE *d_f = fopen(path, "w+");
|
||||
if (d_f == NULL) {
|
||||
r_printf(">>>[test]:open d_f fail\n");
|
||||
fclose(i_f);
|
||||
i_f = NULL;
|
||||
goto __exit;
|
||||
}
|
||||
int wlen = fwrite(d_f, buf, buf_len);
|
||||
if (wlen != buf_len) {
|
||||
r_printf(">>>[test]:err write!!!!!!!!wlen = %d, buf_len = %d\n", wlen, buf_len);
|
||||
fclose(i_f);
|
||||
i_f = NULL;
|
||||
fclose(d_f);
|
||||
d_f = NULL;
|
||||
goto __exit;
|
||||
}
|
||||
fclose(d_f);
|
||||
d_f = NULL;
|
||||
d_f = fopen(path, "r");
|
||||
if (d_f == NULL) {
|
||||
r_printf(">>>[test]:open d_f fail\n");
|
||||
fclose(i_f);
|
||||
i_f = NULL;
|
||||
goto __exit;
|
||||
}
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
int fsize = flen(d_f);
|
||||
int err = finsert_file(d_f, i_f, fsize);
|
||||
fclose(i_f);
|
||||
i_f = NULL;
|
||||
fclose(d_f);
|
||||
d_f = NULL;
|
||||
return err;
|
||||
|
||||
__exit:
|
||||
memset(path, 0, sizeof(path));
|
||||
memcpy(path, root_path, strlen(root_path) - 1);
|
||||
memcpy(path + strlen(root_path) - 1, tmp_name, strlen(tmp_name));
|
||||
r_printf(">>>[test]:error process: path1 = %s\n", path);
|
||||
FILE *f_tmp = fopen(path, "r");
|
||||
if (f_tmp) {
|
||||
fdelete(f_tmp);
|
||||
f_tmp = NULL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef __FILE_MANAGER_H__
|
||||
#define __FILE_MANAGER_H__
|
||||
|
||||
#include "system/includes.h"
|
||||
#include "typedef.h"
|
||||
#include "system/fs/fs.h"
|
||||
#include "dev_manager.h"
|
||||
|
||||
FILE *file_manager_select(struct __dev *dev, struct vfscan *fs, int sel_mode, int arg, struct __scan_callback *callback);
|
||||
|
||||
#endif// __FILE_MANAGER_H__
|
||||
@@ -0,0 +1,503 @@
|
||||
#include "app_config.h"
|
||||
#if ((defined TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN) && TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN && \
|
||||
TCFG_AUDIO_ANC_ENABLE)
|
||||
#include "system/task.h"
|
||||
#include "icsd_adt.h"
|
||||
#include "icsd_adt_app.h"
|
||||
#include "classic/tws_api.h"
|
||||
#include "icsd_anc.h"
|
||||
#include "tone_player.h"
|
||||
#include "icsd_anc_user.h"
|
||||
|
||||
#define ICSD_ADT_TASK_NAME "icsd_adt"
|
||||
|
||||
const u8 VDT_TRAIN_EN = 0;
|
||||
|
||||
u8 adt_task = 0;
|
||||
u8 src_task = 0;
|
||||
int (*adt_printf)(const char *format, ...);
|
||||
int (*wat_printf)(const char *format, ...);
|
||||
int (*ein_printf)(const char *format, ...);
|
||||
int printf_off(const char *format, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ADT_DATA_DEBUG 0
|
||||
void icsd_adt_run_output(__adt_result *adt_result)
|
||||
{
|
||||
u8 voice_state = adt_result->voice_state;
|
||||
u8 wind_lvl = adt_result->wind_lvl;
|
||||
u8 wat_result = adt_result->wat_result;
|
||||
u8 ein_state = adt_result->ein_state;
|
||||
|
||||
#if ADT_DATA_DEBUG
|
||||
extern void icsd_adt_output_demo(__adt_result * adt_result);
|
||||
icsd_adt_output_demo(adt_result);
|
||||
#else
|
||||
void audio_acoustic_detector_output_hdl(u8 voice_state, u8 wind_lvl, u8 wat_result);
|
||||
audio_acoustic_detector_output_hdl(voice_state, wind_lvl, wat_result);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define AUDIO_ADC_CH0 BIT(0)
|
||||
#define AUDIO_ADC_CH1 BIT(1)
|
||||
#define AUDIO_ADC_CH2 BIT(2)
|
||||
#define AUDIO_ADC_CH3 BIT(3)
|
||||
void icsd_adt_mic_ch_analog_open(u32 ch)
|
||||
{
|
||||
if (ch & AUDIO_ADC_CH0) {
|
||||
/*close mic0 analog config*/
|
||||
SFR(JL_ADDA->ADA_CON4, 15, 1, 0); // AUDADC_MICA_BUFP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON4, 14, 1, 0); // AUDADC_MICA_BUFN_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON4, 4, 1, 1); // AUDADC_MICA_AMP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 8, 1, 1); // AUDADC_CHA_S2_RSTB_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 7, 1, 1); // AUDADC_CHA_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 6, 1, 1); // AUDADC_CHA_BIAS_EN_10v
|
||||
}
|
||||
if (ch & AUDIO_ADC_CH1) {
|
||||
/*close mic1 analog config*/
|
||||
SFR(JL_ADDA->ADA_CON5, 15, 1, 0); // AUDADC_MICB_BUFP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON5, 14, 1, 0); // AUDADC_MICB_BUFN_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON5, 4, 1, 1); // AUDADC_MICB_AMP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 11, 1, 1); // AUDADC_CHB_S2_RSTB_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 10, 1, 1); // AUDADC_CHB_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 9, 1, 1); // AUDADC_CHB_BIAS_EN_10v
|
||||
}
|
||||
if (ch & AUDIO_ADC_CH2) {
|
||||
/*close mic2 analog config*/
|
||||
SFR(JL_ADDA->ADA_CON6, 15, 1, 0); // AUDADC_MICC_BUFP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON6, 14, 1, 0); // AUDADC_MICC_BUFN_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON6, 4, 1, 1); // AUDADC_MICC_AMP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 14, 1, 1); // AUDADC_CHC_S2_RSTB_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 13, 1, 1); // AUDADC_CHC_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 12, 1, 1); // AUDADC_CHC_BIAS_EN_10v
|
||||
}
|
||||
if (ch & AUDIO_ADC_CH3) {
|
||||
/*close mic3 analog config*/
|
||||
SFR(JL_ADDA->ADA_CON7, 15, 1, 0); // AUDADC_MICD_BUFP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON7, 14, 1, 0); // AUDADC_MICD_BUFN_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON7, 4, 1, 1); // AUDADC_MICD_AMP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 17, 1, 1); // AUDADC_CHD_S2_RSTB_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 16, 1, 1); // AUDADC_CHD_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 15, 1, 1); // AUDADC_CHD_BIAS_EN_10v
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_adt_mic_ch_analog_close(u32 ch)
|
||||
{
|
||||
if (ch & AUDIO_ADC_CH0) {
|
||||
/*close mic0 analog config*/
|
||||
SFR(JL_ADDA->ADA_CON4, 15, 1, 0); // AUDADC_MICA_BUFP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON4, 14, 1, 0); // AUDADC_MICA_BUFN_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON4, 4, 1, 0); // AUDADC_MICA_AMP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 8, 1, 0); // AUDADC_CHA_S2_RSTB_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 7, 1, 0); // AUDADC_CHA_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 6, 1, 0); // AUDADC_CHA_BIAS_EN_10v
|
||||
}
|
||||
if (ch & AUDIO_ADC_CH1) {
|
||||
/*close mic1 analog config*/
|
||||
SFR(JL_ADDA->ADA_CON5, 15, 1, 0); // AUDADC_MICB_BUFP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON5, 14, 1, 0); // AUDADC_MICB_BUFN_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON5, 4, 1, 0); // AUDADC_MICB_AMP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 11, 1, 0); // AUDADC_CHB_S2_RSTB_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 10, 1, 0); // AUDADC_CHB_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 9, 1, 0); // AUDADC_CHB_BIAS_EN_10v
|
||||
}
|
||||
if (ch & AUDIO_ADC_CH2) {
|
||||
/*close mic2 analog config*/
|
||||
SFR(JL_ADDA->ADA_CON6, 15, 1, 0); // AUDADC_MICC_BUFP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON6, 14, 1, 0); // AUDADC_MICC_BUFN_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON6, 4, 1, 0); // AUDADC_MICC_AMP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 14, 1, 0); // AUDADC_CHC_S2_RSTB_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 13, 1, 0); // AUDADC_CHC_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 12, 1, 0); // AUDADC_CHC_BIAS_EN_10v
|
||||
}
|
||||
if (ch & AUDIO_ADC_CH3) {
|
||||
/*close mic3 analog config*/
|
||||
SFR(JL_ADDA->ADA_CON7, 15, 1, 0); // AUDADC_MICD_BUFP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON7, 14, 1, 0); // AUDADC_MICD_BUFN_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON7, 4, 1, 0); // AUDADC_MICD_AMP_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 17, 1, 0); // AUDADC_CHD_S2_RSTB_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 16, 1, 0); // AUDADC_CHD_EN_10v
|
||||
SFR(JL_ADDA->ADA_CON1, 15, 1, 0); // AUDADC_CHD_BIAS_EN_10v
|
||||
}
|
||||
}
|
||||
|
||||
u8 talk_mic_analog_close = 0;
|
||||
u8 audio_adt_talk_mic_analog_close()
|
||||
{
|
||||
if (talk_mic_analog_close == 0) {
|
||||
printf("-----------audio_adt_talk_mic_analog_close\n");
|
||||
u8 talk_mic_ch = icsd_get_talk_mic_ch();
|
||||
icsd_adt_mic_ch_analog_close(talk_mic_ch);
|
||||
talk_mic_analog_close = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u8 audio_adt_talk_mic_analog_open()
|
||||
{
|
||||
if (talk_mic_analog_close) {
|
||||
printf("-----------audio_adt_talk_mic_analog_open\n");
|
||||
u8 talk_mic_ch = icsd_get_talk_mic_ch();
|
||||
icsd_adt_mic_ch_analog_open(talk_mic_ch);
|
||||
talk_mic_analog_close = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float adt_pow10(float n)
|
||||
{
|
||||
float pow10n = exp_float((float)n / log10_float(exp_float((float)1.0)));
|
||||
return pow10n;
|
||||
}
|
||||
|
||||
u32 icsd_adt_get_role()
|
||||
{
|
||||
return tws_api_get_role();
|
||||
}
|
||||
|
||||
u32 icsd_adt_get_tws_state()
|
||||
{
|
||||
return tws_api_get_tws_state();
|
||||
}
|
||||
|
||||
#define TWS_FUNC_ID_SDADT_M2S TWS_FUNC_ID('A', 'D', 'T', 'M')
|
||||
REGISTER_TWS_FUNC_STUB(icsd_adt_m2s) = {
|
||||
.func_id = TWS_FUNC_ID_SDADT_M2S,
|
||||
.func = icsd_adt_m2s_cb,
|
||||
};
|
||||
#define TWS_FUNC_ID_SDADT_S2M TWS_FUNC_ID('A', 'D', 'T', 'S')
|
||||
REGISTER_TWS_FUNC_STUB(icsd_adt_s2m) = {
|
||||
.func_id = TWS_FUNC_ID_SDADT_S2M,
|
||||
.func = icsd_adt_s2m_cb,
|
||||
};
|
||||
|
||||
void icsd_adt_tws_m2s(u8 cmd)
|
||||
{
|
||||
local_irq_disable();
|
||||
s8 data[8];
|
||||
icsd_adt_m2s_packet(data, cmd);
|
||||
int ret = tws_api_send_data_to_sibling(data, 8, TWS_FUNC_ID_SDADT_M2S);
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
void icsd_adt_tws_s2m(u8 cmd)
|
||||
{
|
||||
local_irq_disable();
|
||||
s8 data[8];
|
||||
icsd_adt_s2m_packet(data, cmd);
|
||||
int ret = tws_api_send_data_to_sibling(data, 8, TWS_FUNC_ID_SDADT_S2M);
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
void icsd_adt_anc_dma_on(u8 out_sel, int *buf, int len)
|
||||
{
|
||||
anc_dma_on_double(out_sel, buf, len);
|
||||
}
|
||||
|
||||
void icsd_adt_dma_done()
|
||||
{
|
||||
icsd_acoustic_detector_ancdma_done();
|
||||
}
|
||||
|
||||
void icsd_adt_hw_suspend()
|
||||
{
|
||||
anc_core_dma_ie(0);
|
||||
anc_core_dma_stop();
|
||||
}
|
||||
|
||||
void icsd_adt_hw_resume()
|
||||
{
|
||||
audio_acoustic_detector_updata();
|
||||
icsd_adt_szout_init();
|
||||
}
|
||||
|
||||
void icsd_adt_FFT_radix256(int *in_cur, int *out)
|
||||
{
|
||||
u32 fft_config;
|
||||
fft_config = hw_fft_config(256, 8, 1, 0, 1);
|
||||
hw_fft_run(fft_config, in_cur, out);
|
||||
}
|
||||
|
||||
void icsd_adt_FFT_radix128(int *in_cur, int *out)
|
||||
{
|
||||
u32 fft_config;
|
||||
fft_config = hw_fft_config(128, 7, 1, 0, 1);
|
||||
hw_fft_run(fft_config, in_cur, out);
|
||||
}
|
||||
|
||||
void icsd_adt_FFT_radix64(int *in_cur, int *out)
|
||||
{
|
||||
u32 fft_config;
|
||||
fft_config = hw_fft_config(64, 6, 1, 0, 1);
|
||||
hw_fft_run(fft_config, in_cur, out);
|
||||
}
|
||||
|
||||
void icsd_post_anctask_msg(u8 cmd)
|
||||
{
|
||||
audio_anc_post_msg_adt(cmd);
|
||||
}
|
||||
|
||||
void icsd_post_adttask_msg(u8 cmd)
|
||||
{
|
||||
if (adt_task == 1) {
|
||||
os_taskq_post_msg("icsd_adt", 1, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_post_srctask_msg(u8 cmd)
|
||||
{
|
||||
if (src_task == 1) {
|
||||
os_taskq_post_msg("icsd_src", 1, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_adt_task(void *priv)
|
||||
{
|
||||
int res = 0;
|
||||
int msg[30];
|
||||
while (1) {
|
||||
res = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
|
||||
if (res == OS_TASKQ) {
|
||||
icsd_adt_task_handler(msg[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_adt_task_create()
|
||||
{
|
||||
if (adt_task == 0) {
|
||||
task_create(icsd_adt_task, NULL, ICSD_ADT_TASK_NAME);
|
||||
adt_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_adt_task_kill()
|
||||
{
|
||||
if (adt_task == 1) {
|
||||
task_kill(ICSD_ADT_TASK_NAME);
|
||||
adt_task = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_src_task(void *priv)
|
||||
{
|
||||
int res = 0;
|
||||
int msg[30];
|
||||
while (1) {
|
||||
res = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
|
||||
if (res == OS_TASKQ) {
|
||||
icsd_src_task_handler(msg[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_src_task_create()
|
||||
{
|
||||
if (src_task == 0) {
|
||||
task_create(icsd_src_task, NULL, "icsd_src");
|
||||
src_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_src_task_kill()
|
||||
{
|
||||
if (src_task == 1) {
|
||||
task_kill("icsd_src");
|
||||
src_task = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void icsd_adt_start()
|
||||
{
|
||||
adt_printf = _adt_printf;
|
||||
wat_printf = _wat_printf;
|
||||
ein_printf = _ein_printf;
|
||||
printf("icsd_adt_start====================================\n");
|
||||
}
|
||||
|
||||
void icsd_adt_szout_init()
|
||||
{
|
||||
#if ADT_USE_ADAPTIVE_SZ
|
||||
extern float icsd_anc_sz_data[120 + 40];
|
||||
extern float icsd_anc_pz_data[120 + 40];
|
||||
extern u8 sz_out_exist;//需要打开自适应ANC库中的 自适应SZ输出使能:ANC_SZ_OUT_EN
|
||||
icsd_adt_szout_set(icsd_anc_sz_data, icsd_anc_pz_data, sz_out_exist);
|
||||
#else
|
||||
icsd_adt_szout_set(0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
const u16 ADT_DEBUG_INF = 0;//ADT_INF_1;//state
|
||||
//state = 1, pwr = 7, dov = 8, angle_err = 7, angle_tlk = 3
|
||||
const u8 adt_errpxx_dB_thr = 80;//60;
|
||||
const u8 adt_err_zcv_thr = 10;//12;
|
||||
const u8 pwr_inside_even_flag0_thr = 5; //pwr
|
||||
const u8 angle_err_even_flag0_thr = 3;//4; //angle_err
|
||||
const u8 angle_talk_even_flag0_thr = 2; //angle_tlk
|
||||
const u16 f1f2_angsum_thr = 200;
|
||||
#ifndef ADT_CLIENT_BOARD
|
||||
const u8 final_speech_even_thr = 4; //dov
|
||||
|
||||
|
||||
const u8 ADT_TWS_MODE = 1;
|
||||
const u8 ADT_DET_VER = 6;
|
||||
const u8 ADT_PATH_CONFIG = ADT_PATH_DAC_SRC_EN | ADT_PATH_3M_EN;
|
||||
const u8 ADT_EIN_VER = ADT_EIN_TWS_V0;
|
||||
const float ref_gain_sel = 3;
|
||||
const float err_gain_sel = 3;
|
||||
u8 pnc_ref_pwr_thr = 160;
|
||||
u8 pnc_err_pwr_thr = 100;
|
||||
u8 tpc_ref_pwr_thr = 120;
|
||||
u8 tpc_err_pwr_thr = 100;
|
||||
u8 anc_ref_pwr_thr = 120;
|
||||
u8 anc_err_pwr_thr = 100;
|
||||
|
||||
const float wat_pn_gain = 0.22;
|
||||
const float wat_bypass_gain = 16;
|
||||
const float wat_anc_gain = 0.22;
|
||||
|
||||
const float wdac_senc = 0.7; //越小播音乐时灵敏度越高
|
||||
const float wdac[8] = { 0.35, 0.54, 0.57, 0.48, 0.37, 0.22, 0.38, 0.37};//播放音乐/100
|
||||
const float wref[8] = {1.62, 0.90, 0.71, 0.60, 0.54, 0.50, 0.47, 0.46};//播放外部噪声
|
||||
const float wref_tran[8] = {1.82, 1.80, 1.58, 1.30, 1.16, 1.12, 1.11, 1.12};
|
||||
const float wref_ancs[8] = {1.92, 0.48, 0.07, 0.03, 0.05, 0.06, 0.06, 0.04 };
|
||||
const float fdac[8] = {0.18, 0.051, 0.02, 0.02, 0.02, 0.02, 0.02, 0.05};//播放音乐/1000
|
||||
u8 icsd_get_ang_flag(float *_target_angle)
|
||||
{
|
||||
u8 af1 = _target_angle[1] > 15 || _target_angle[1] < -130;
|
||||
u8 af2 = _target_angle[2] > 15 || _target_angle[2] < -130;
|
||||
u8 af3 = _target_angle[3] > 15 || _target_angle[3] < -130;
|
||||
u8 ang_flag = af1 && af2 && af3;
|
||||
/* printf("get ang flag:%d\n", ang_flag); */
|
||||
return ang_flag;
|
||||
}
|
||||
|
||||
void icsd_adt_ein_parm_HT03(__icsd_adt_parm *_ADT_PARM)
|
||||
{
|
||||
_ADT_PARM->anc_in_pz_sum = -80;
|
||||
_ADT_PARM->anc_out_pz_sum = 0;
|
||||
_ADT_PARM->anc_in_sz_mean = 1;
|
||||
_ADT_PARM->anc_out_sz_mean = -12;
|
||||
_ADT_PARM->anc_in_fb_sum = 60;
|
||||
_ADT_PARM->anc_out_fb_sum = 30;
|
||||
|
||||
_ADT_PARM->pnc_in_pz_sum = -80;
|
||||
_ADT_PARM->pnc_out_pz_sum = 0;
|
||||
_ADT_PARM->pnc_in_sz_mean = 1;
|
||||
_ADT_PARM->pnc_out_sz_mean = -12;
|
||||
_ADT_PARM->pnc_in_fb_sum = 60;
|
||||
_ADT_PARM->pnc_out_fb_sum = 30;
|
||||
|
||||
_ADT_PARM->trans_in_pz_sum = 2;
|
||||
_ADT_PARM->trans_out_pz_sum = 26;
|
||||
_ADT_PARM->trans_in_sz_mean = 2;
|
||||
_ADT_PARM->trans_out_sz_mean = -7;
|
||||
_ADT_PARM->trans_in_fb_sum = 20;
|
||||
_ADT_PARM->trans_out_fb_sum = -20;
|
||||
}
|
||||
|
||||
void icsd_adt_voice_board_data()
|
||||
{
|
||||
__icsd_adt_parm *ADT_PARM;
|
||||
ADT_PARM = zalloc(sizeof(__icsd_adt_parm));
|
||||
|
||||
extern const float HT03_ADT_FLOAT_DATA[];
|
||||
extern const float HT03_sz_out_data[28];
|
||||
extern const float HT03_pz_out_data[28];
|
||||
ADT_PARM->adt_float_data = (void *)HT03_ADT_FLOAT_DATA;
|
||||
ADT_PARM->sz_inptr = (float *)HT03_sz_out_data;
|
||||
ADT_PARM->pz_inptr = (float *)HT03_pz_out_data;
|
||||
icsd_adt_ein_parm_HT03(ADT_PARM);
|
||||
|
||||
icsd_adt_parm_set(ADT_PARM);
|
||||
free(ADT_PARM);
|
||||
|
||||
icsd_adt_szout_init();
|
||||
}
|
||||
#else
|
||||
|
||||
#include "icsd_adt_client_board.c"
|
||||
|
||||
#endif/*ADC_CLIENT_BOARD*/
|
||||
|
||||
|
||||
//=======================================================================================================
|
||||
|
||||
#if ADT_DATA_DEBUG
|
||||
|
||||
void icsd_play_num0()
|
||||
{
|
||||
icsd_adt_tone_play(ICSD_ADT_TONE_NUM0);
|
||||
}
|
||||
void icsd_play_num1()
|
||||
{
|
||||
icsd_adt_tone_play(ICSD_ADT_TONE_NUM1);
|
||||
}
|
||||
void icsd_play_num2()
|
||||
{
|
||||
icsd_adt_tone_play(ICSD_ADT_TONE_NUM2);
|
||||
}
|
||||
void icsd_play_num3()
|
||||
{
|
||||
icsd_adt_tone_play(ICSD_ADT_TONE_NUM3);
|
||||
}
|
||||
void icsd_play_normal()
|
||||
{
|
||||
icsd_adt_tone_play(ICSD_ADT_TONE_NORMAL);
|
||||
}
|
||||
|
||||
void icsd_adt_output_demo(__adt_result *adt_result)
|
||||
{
|
||||
#if ADT_EAR_IN_EN
|
||||
static u8 hold = 0;
|
||||
static u8 hold_flg = 0;
|
||||
static int hold_time = 0;
|
||||
if (adt_result->ein_state == 0) {
|
||||
hold = 1;
|
||||
hold_flg = 1;
|
||||
hold_time = 0;
|
||||
printf("------------------------------------------------------------------ein state:0\n");
|
||||
} else {
|
||||
if (hold_flg) {
|
||||
hold_flg = 0;
|
||||
hold_time = jiffies;
|
||||
printf("set hold time:%d\n", hold_time);
|
||||
}
|
||||
if ((hold_time > 0) && (hold)) {
|
||||
if (jiffies > (hold_time + 100)) {
|
||||
printf("hold time out:%d\n", jiffies);
|
||||
hold = 0;
|
||||
}
|
||||
}
|
||||
printf("--------------------------------ein state:1\n");
|
||||
}
|
||||
if (hold) {
|
||||
//return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (adt_result->wind_lvl) {
|
||||
printf("------wind lvl:%d\n", adt_result->wind_lvl);
|
||||
}
|
||||
if (adt_result->voice_state) {
|
||||
icsd_play_normal();
|
||||
}
|
||||
switch (adt_result->wat_result) {
|
||||
case 2:
|
||||
icsd_play_num2();
|
||||
break;
|
||||
case 3:
|
||||
icsd_play_num3();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /*ADT_DATA_DEBUG*/
|
||||
|
||||
#endif /*(defined TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN) && TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
#ifndef _ICSD_ADT_H
|
||||
#define _ICSD_ADT_H
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "os/os_type.h"
|
||||
#include "os/os_api.h"
|
||||
#include "classic/tws_api.h"
|
||||
#include "math.h"
|
||||
|
||||
#if 0
|
||||
#define _adt_printf printf //打开智能免摘库打印信息
|
||||
#else
|
||||
extern int printf_off(const char *format, ...);
|
||||
#define _adt_printf printf_off
|
||||
#endif/*log_en*/
|
||||
|
||||
#if 0
|
||||
#define _wat_printf printf //打开广域点击库打印信息
|
||||
#else
|
||||
extern int printf_off(const char *format, ...);
|
||||
#define _wat_printf printf_off
|
||||
#endif/*log_en*/
|
||||
|
||||
#if 0
|
||||
#define _wind_printf printf //打开风噪检测库打印信息
|
||||
#else
|
||||
extern int printf_off(const char *format, ...);
|
||||
#define _wind_printf printf_off
|
||||
#endif/*log_en*/
|
||||
|
||||
#if 0
|
||||
#define _ein_printf printf //打开入耳检测库打印信息
|
||||
#else
|
||||
extern int printf_off(const char *format, ...);
|
||||
#define _ein_printf printf_off
|
||||
#endif/*log_en*/
|
||||
|
||||
#define ADT_CALIBRATION_EN 0
|
||||
#define ADT_USE_ADAPTIVE_SZ 0//使用自适应SZ
|
||||
#define ADT_EAR_IN_EN 0
|
||||
|
||||
#define ADT_VDT_EN BIT(0) //智能免摘
|
||||
#define ADT_WDT_EN BIT(1) //风噪检测
|
||||
#define ADT_WAT_EN BIT(2) //广域点击
|
||||
#define ADT_EIN_EN BIT(3) //入耳检测
|
||||
|
||||
#define ADT_PATH_VDT_ANCL_ON BIT(0) //智能免摘使用ancl通路数据
|
||||
#define ADT_PATH_WAT_EMIC_ON BIT(1) //广域点击使用errmic数据通路
|
||||
#define ADT_PATH_VAD_ON BIT(2) //通过VAD检测降低功耗
|
||||
#define ADT_PATH_DAC_SRC_EN BIT(3)
|
||||
#define ADT_PATH_3M_EN BIT(4)
|
||||
|
||||
|
||||
#define ADT_INF_1 BIT(0)
|
||||
#define ADT_INF_2 BIT(1)
|
||||
#define ADT_INF_3 BIT(2)
|
||||
|
||||
extern const u8 ADT_PATH_CONFIG;
|
||||
#define ICSD_TWS_STA_SIBLING_CONNECTED TWS_STA_SIBLING_CONNECTED//tws已连接
|
||||
|
||||
typedef struct {
|
||||
u8 voice_state;
|
||||
u8 wind_lvl;
|
||||
u8 wat_result;
|
||||
u8 ein_state;
|
||||
} __adt_result;
|
||||
|
||||
struct icsd_acoustic_detector_infmt {
|
||||
u16 sample_rate; //当前播放采样率
|
||||
u8 ff_gain;
|
||||
u8 fb_gain;
|
||||
u8 adt_mode; // TWS: 0 HEADSET: 1
|
||||
u8 dac_mode; //低压0 高压1
|
||||
u8 mic0_type; // MIC0 类型
|
||||
u8 mic1_type; // MIC1 类型
|
||||
u8 mic2_type; // MIC2 类型
|
||||
u8 mic3_type; // MIC3 类型
|
||||
u8 sensitivity; //智能免摘灵敏度设置
|
||||
void *lfb_coeff;
|
||||
void *lff_coeff;
|
||||
void *ltrans_coeff;
|
||||
void *ltransfb_coeff;
|
||||
float gains_l_fbgain;
|
||||
float gains_l_ffgain;
|
||||
float gains_l_transgain;
|
||||
float gains_l_transfbgain;
|
||||
u8 gain_sign;
|
||||
u8 lfb_yorder;
|
||||
u8 lff_yorder;
|
||||
u8 ltrans_yorder;
|
||||
u8 ltransfb_yorder;
|
||||
u32 trans_alogm;
|
||||
u32 alogm;
|
||||
|
||||
void *alloc_ptr; //外部申请的ram地址
|
||||
/*
|
||||
算法结果输出
|
||||
voice_state: 0 无讲话; 1 有讲话
|
||||
wind_lvl: 0-70 风噪等级
|
||||
*/
|
||||
void (*output_hdl)(u8 voice_state, u8 wind_lvl); //算法结果输出
|
||||
void (*anc_dma_post_msg)(void); //ANC task dma 抄数回调接口
|
||||
void (*anc_dma_output_callback); //ANC DMA下采样数据输出回调,用于写卡分析
|
||||
};
|
||||
|
||||
struct icsd_acoustic_detector_libfmt {
|
||||
int adc_isr_len; //ADC中断长度
|
||||
int adc_sr; //ADC 采样率
|
||||
int lib_alloc_size; //算法ram需求大小
|
||||
u8 mic_num; //需要打开的mic个数
|
||||
};
|
||||
|
||||
enum {
|
||||
ICSD_ANC_LFF_MIC = 0,
|
||||
ICSD_ANC_LFB_MIC = 1,
|
||||
ICSD_ANC_RFF_MIC = 2,
|
||||
ICSD_ANC_RFB_MIC = 3,
|
||||
ICSD_ANC_TALK_MIC = 4,
|
||||
ICSD_ANC_MIC_NULL = 0XFF, //对应的MIC没有数值,则表示这个MIC没有开启
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *adt_float_data;
|
||||
float *sz_inptr;
|
||||
float *pz_inptr;
|
||||
s16 anc_in_pz_sum;
|
||||
s16 anc_in_sz_mean;
|
||||
s16 anc_in_fb_sum;
|
||||
s16 anc_out_pz_sum;
|
||||
s16 anc_out_sz_mean;
|
||||
s16 anc_out_fb_sum;
|
||||
|
||||
s16 pnc_in_pz_sum;
|
||||
s16 pnc_in_sz_mean;
|
||||
s16 pnc_in_fb_sum;
|
||||
s16 pnc_out_pz_sum;
|
||||
s16 pnc_out_sz_mean;
|
||||
s16 pnc_out_fb_sum;
|
||||
|
||||
s16 trans_in_pz_sum;
|
||||
s16 trans_in_sz_mean;
|
||||
s16 trans_in_fb_sum;
|
||||
s16 trans_out_pz_sum;
|
||||
s16 trans_out_sz_mean;
|
||||
s16 trans_out_fb_sum;
|
||||
} __icsd_adt_parm;
|
||||
|
||||
enum {
|
||||
RESUME_ANCMODE = 0,
|
||||
RESUME_BYPASSMODE,
|
||||
};
|
||||
enum {
|
||||
ADT_DACMODE_LOW = 0,
|
||||
ADT_DACMODE_HIGH,
|
||||
};
|
||||
enum {
|
||||
ADT_TWS = 0,
|
||||
ADT_HEADSET,
|
||||
};
|
||||
enum {
|
||||
ADT_ANC_ON = 0,
|
||||
ADT_ANC_OFF,
|
||||
};
|
||||
enum {
|
||||
ADT_VOICE_WIND_MODE = 0, //智能免摘 + 风噪
|
||||
ADT_WAT_MODE, //广域点击
|
||||
ADT_VW_WAT_MODE, //智能免摘 + 风噪检测 + 广域点击
|
||||
};
|
||||
enum {
|
||||
ADT_EIN_UNSUPPORT = 0,
|
||||
ADT_EIN_TWS_V0,
|
||||
ADT_EIN_HEADSET_V0,
|
||||
};
|
||||
|
||||
extern const float wat_pn_gain;
|
||||
extern const float wat_anc_gain;
|
||||
extern const float wat_bypass_gain;
|
||||
extern const u8 final_speech_even_thr;
|
||||
extern const u8 VDT_TRAIN_EN;
|
||||
extern const float ref_gain_sel;
|
||||
extern const float err_gain_sel;
|
||||
extern u8 pnc_ref_pwr_thr;
|
||||
extern u8 pnc_err_pwr_thr;
|
||||
extern u8 tpc_ref_pwr_thr;
|
||||
extern u8 tpc_err_pwr_thr;
|
||||
extern u8 anc_ref_pwr_thr;
|
||||
extern u8 anc_err_pwr_thr;
|
||||
extern const float wref[8];
|
||||
extern const float wref_tran[8];
|
||||
extern const float wref_ancs[8];
|
||||
extern const float wdac_senc;
|
||||
extern const float wdac[8];
|
||||
extern const float fdac[8];
|
||||
extern const u8 ADT_DET_VER;
|
||||
extern const u8 ADT_TWS_MODE;
|
||||
extern const u8 ADT_EIN_VER;
|
||||
extern float anc_trans_lfb_gain;
|
||||
extern float anc_trans_rfb_gain;
|
||||
extern const double anc_trans_lfb_coeff[];
|
||||
extern const double anc_trans_rfb_coeff[];
|
||||
|
||||
extern int (*adt_printf)(const char *format, ...);
|
||||
extern int (*wat_printf)(const char *format, ...);
|
||||
extern int (*ein_printf)(const char *format, ...);
|
||||
|
||||
extern void icsd_adt_tws_m2s(u8 cmd);
|
||||
extern void icsd_adt_tws_s2m(u8 cmd);
|
||||
//LIB调用的算术函数
|
||||
extern float sin_float(float x);
|
||||
extern float cos_float(float x);
|
||||
extern float cos_hq(float x);
|
||||
extern float sin_hq(float x);
|
||||
extern float log10_float(float x);
|
||||
extern float exp_float(float x);
|
||||
extern float root_float(float x);
|
||||
//extern float pow10(float n);
|
||||
extern float adt_pow10(float n);
|
||||
extern float angle_float(float x, float y);
|
||||
//ADT调用的APP函数
|
||||
|
||||
extern int audio_dac_read_anc_reset(void);
|
||||
extern int audio_acoustic_detector_updata();
|
||||
extern void tws_tx_unsniff_req(void);
|
||||
extern int tws_api_get_role(void);
|
||||
extern int tws_api_get_tws_state();
|
||||
extern u8 anc_dma_done_ppflag();
|
||||
extern void anc_core_dma_ie(u8 en);
|
||||
extern void anc_core_dma_stop(void);
|
||||
extern int os_task_create(void (*task_func)(void *p_arg), void *p_arg, u8 prio, u32 stksize, int qsize, const char *name);
|
||||
extern int os_task_del(const char *name);
|
||||
extern int os_taskq_post_msg(const char *name, int argc, ...);
|
||||
extern int os_taskq_pend(const char *fmt, int *argv, int argc);
|
||||
extern void anc_dma_on_double(u8 out_sel, int *buf, int len);
|
||||
extern int audio_resample_hw_push_data_out(void *resample);
|
||||
extern void audio_resample_hw_close(void *resample);
|
||||
extern void *audio_resample_hw_open(u8 channel, int in_rate, int out_rate, u8 type);
|
||||
extern int audio_resample_hw_set_output_handler(void *resample, void *priv, int (*handler)(void *, void *, int));
|
||||
extern int audio_resample_hw_write(void *resample, void *data, int len);
|
||||
extern void audio_anc_post_msg_adt(u8 cmd);
|
||||
extern void hw_fft_run(unsigned int fft_config, const int *in, int *out);
|
||||
extern unsigned int hw_fft_config(int N, int log2N, int is_same_addr, int is_ifft, int is_real);
|
||||
//APP调用的ADT函数
|
||||
extern void icsd_adt_start();
|
||||
extern void icsd_adt_anctask_handle(u8 cmd);
|
||||
//APP调用的LIB函数
|
||||
extern void icsd_acoustic_detector_get_libfmt(struct icsd_acoustic_detector_libfmt *libfmt, u8 function);
|
||||
extern void icsd_acoustic_detector_set_infmt(struct icsd_acoustic_detector_infmt *fmt);
|
||||
extern void icsd_acoustic_detector_infmt_updata(struct icsd_acoustic_detector_infmt *fmt);
|
||||
extern void icsd_acoustic_detector_open(void);
|
||||
extern void icsd_acoustic_detector_close();
|
||||
extern void icsd_acoustic_detector_resume(u8 mode, u8 anc_onoff);
|
||||
extern void icsd_acoustic_detector_suspend();
|
||||
extern void icsd_acoustic_detector_ancdma_done();//ancdma done回调
|
||||
extern void icsd_acoustic_detector_mic_input_hdl(void *priv, s16 *buf, int len);
|
||||
extern void icsd_adt_set_audio_sample_rate(u16 sample_rate);
|
||||
//LIB调用的ADT函数
|
||||
extern void icsd_adt_FFT_radix256(int *in_cur, int *out);
|
||||
extern void icsd_adt_FFT_radix128(int *in_cur, int *out);
|
||||
extern void icsd_adt_FFT_radix64(int *in_cur, int *out);
|
||||
extern void icsd_adt_anc_dma_on(u8 out_sel, int *buf, int len);
|
||||
extern void icsd_adt_hw_suspend();
|
||||
extern void icsd_adt_hw_resume();
|
||||
extern void icsd_post_adttask_msg(u8 cmd);
|
||||
extern void icsd_post_srctask_msg(u8 cmd);
|
||||
extern void icsd_adt_src_close(void *resample);
|
||||
extern void *icsd_adt_src_init(int in_rate, int out_rate, int (*handler)(void *, void *, int));
|
||||
extern void icsd_adt_src_push(void *resample);
|
||||
extern void icsd_adt_src_write(void *data, int len, void *resample);
|
||||
extern void icsd_adt_run_output(__adt_result *adt_result);
|
||||
extern void icsd_post_anctask_msg(u8 cmd);
|
||||
extern void icsd_adt_voice_board_data();
|
||||
extern void icsd_adt_tx_unsniff_req();
|
||||
extern u32 icsd_adt_get_tws_state();
|
||||
extern u32 icsd_adt_get_role();
|
||||
extern u8 icsd_get_ang_flag(float *_target_angle);
|
||||
//ADT调用的LIB函数
|
||||
extern void icsd_adt_version();
|
||||
extern void icsd_adt_parm_set(__icsd_adt_parm *_ADT_PARM);
|
||||
extern void icsd_adt_szout_set(float *anc_sz_data, float *anc_pz_data, u8 sz_out_exist);
|
||||
extern void icsd_adt_task_handler(int msg);
|
||||
extern void icsd_src_task_handler(int msg);
|
||||
extern void icsd_adt_s2m_packet(s8 *data, u8 cmd);
|
||||
extern void icsd_adt_m2s_packet(s8 *data, u8 cmd);
|
||||
|
||||
extern void icsd_adt_szout_init();
|
||||
extern void icsd_adt_dma_done();
|
||||
extern void icsd_adt_task_create();
|
||||
extern void icsd_adt_task_kill();
|
||||
extern void icsd_src_task_create();
|
||||
extern void icsd_src_task_kill();
|
||||
extern void icsd_adt_m2s_cb(void *_data, u16 len, bool rx);
|
||||
extern void icsd_adt_s2m_cb(void *_data, u16 len, bool rx);
|
||||
|
||||
extern u8 audio_adt_talk_mic_analog_close();
|
||||
extern u8 audio_adt_talk_mic_analog_open();
|
||||
extern u8 talk_mic_analog_close;
|
||||
|
||||
extern u8 oral_function;
|
||||
extern const u8 adt_errpxx_dB_thr;
|
||||
extern const u8 adt_err_zcv_thr;
|
||||
extern const u8 pwr_inside_even_flag0_thr;
|
||||
extern const u8 angle_err_even_flag0_thr;
|
||||
extern const u8 angle_talk_even_flag0_thr;
|
||||
extern const u16 f1f2_angsum_thr;
|
||||
extern const u16 ADT_DEBUG_INF;
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,189 @@
|
||||
#ifndef __ICSD_ADT_APP_H_
|
||||
#define __ICSD_ADT_APP_H_
|
||||
|
||||
#include "typedef.h"
|
||||
#include "icsd_anc_user.h"
|
||||
// #include "icsd_adt_client_board.h"
|
||||
|
||||
#define SPEAK_TO_CHAT_TASK_NAME "speak_to_chat"
|
||||
|
||||
/*智能免摘检测到声音和退出通透是否播放提示音*/
|
||||
#define SPEAK_TO_CHAT_PLAY_TONE_EN 1
|
||||
|
||||
/*智能免摘每次检测到声音的测试提示音*/
|
||||
#define SPEAK_TO_CHAT_TEST_TONE_EN 0
|
||||
|
||||
/* 通过蓝牙spp发送风噪信息
|
||||
* 需要同时打开USER_SUPPORT_PROFILE_SPP和APP_ONLINE_DEBUG*/
|
||||
#define ICSD_ADT_WIND_INFO_SPP_DEBUG_EN 0
|
||||
|
||||
enum {
|
||||
AUDIO_ADT_CLOSE = 0, //关闭关闭
|
||||
AUDIO_ADT_OPEN, //打开状态
|
||||
AUDIO_ADT_CHAT, //免摘状态
|
||||
};
|
||||
|
||||
enum {
|
||||
ANC_WIND_NOISE_LVL0 = 1,
|
||||
ANC_WIND_NOISE_LVL1,
|
||||
ANC_WIND_NOISE_LVL2,
|
||||
ANC_WIND_NOISE_LVL3,
|
||||
ANC_WIND_NOISE_LVL4,
|
||||
ANC_WIND_NOISE_LVL5,
|
||||
};
|
||||
|
||||
enum {
|
||||
WIND_AREA_TAP_DOUBLE_CLICK = 2, //双击
|
||||
WIND_AREA_TAP_THIRD_CLICK, //三击
|
||||
WIND_AREA_TAP_MULTIPLE_CLICK, //大于3次多次连击
|
||||
};
|
||||
|
||||
enum {
|
||||
ADT_MODE_CLOSE = 0,
|
||||
ADT_SPEAK_TO_CHAT_MODE = BIT(0), //智能免摘
|
||||
ADT_WIND_NOISE_DET_MODE = BIT(1),//风噪检测
|
||||
ADT_WIDE_AREA_TAP_MODE = BIT(2), //广域点击
|
||||
};
|
||||
|
||||
enum {
|
||||
/*任务消息*/
|
||||
ICSD_ADT_VOICE_STATE = 1,
|
||||
ICSD_ADT_WIND_LVL,
|
||||
ICSD_ADT_WAT_RESULT,
|
||||
ICSD_ADT_TONE_PLAY,
|
||||
SPEAK_TO_CHAT_TASK_KILL,
|
||||
ICSD_ANC_MODE_SWITCH,
|
||||
ICSD_ADT_STATE_SYNC,
|
||||
|
||||
/*对耳信息同步*/
|
||||
SYNC_ICSD_ADT_VOICE_STATE,
|
||||
SYNC_ICSD_ADT_WIND_LVL_CMP,
|
||||
SYNC_ICSD_ADT_WAT_RESULT,
|
||||
SYNC_ICSD_ADT_WIND_LVL_RESULT,
|
||||
SYNC_ICSD_ADT_SUSPEND,
|
||||
SYNC_ICSD_ADT_OPEN,
|
||||
SYNC_ICSD_ADT_CLOSE,
|
||||
SYNC_ICSD_ADT_SET_ANC_FADE_GAIN,
|
||||
};
|
||||
|
||||
/*打开智能免摘*/
|
||||
int audio_speak_to_chat_open();
|
||||
|
||||
/*关闭智能免摘*/
|
||||
int audio_speak_to_chat_close();
|
||||
|
||||
void audio_speak_to_chat_demo();
|
||||
|
||||
/*设置免摘定时结束的时间,单位ms*/
|
||||
int audio_speak_to_char_end_time_set(u16 time);
|
||||
|
||||
/*设置智能免摘检测的灵敏度*/
|
||||
int audio_speak_to_chat_sensitivity_set(u8 sensitivity);
|
||||
|
||||
/*获取是否需要先开anc再开免摘的状态*/
|
||||
u8 get_adt_open_in_anc_state();
|
||||
|
||||
void audio_anc_mode_switch_in_adt(u8 anc_mode);
|
||||
|
||||
/*打开声音检测*/
|
||||
int audio_acoustic_detector_open();
|
||||
|
||||
/*关闭声音检测*/
|
||||
int audio_acoustic_detector_close();
|
||||
|
||||
int audio_speak_to_chat_open_in_anc_done();
|
||||
|
||||
void audio_icsd_adt_resume();
|
||||
void audio_icsd_adt_suspend();
|
||||
/*char 定时结束后从通透同步恢复anc on /anc off*/
|
||||
void audio_speak_to_char_suspend(void);
|
||||
void audio_speak_to_char_sync_suspend(void);
|
||||
|
||||
/*获取智能免摘是否打开*/
|
||||
u8 audio_speak_to_chat_is_running();
|
||||
|
||||
/*获取智能免摘状态*/
|
||||
u8 get_speak_to_chat_state();
|
||||
|
||||
/*获取adt的模式*/
|
||||
u8 get_icsd_adt_mode();
|
||||
|
||||
/*同步tws配对时,同步adt的状态*/
|
||||
void audio_anc_icsd_adt_state_sync(u8 *data);
|
||||
void audio_icsd_adt_state_sync_done(u8 adt_mode, u8 speak_to_chat_state);
|
||||
|
||||
/*检测到讲话状态同步*/
|
||||
void set_speak_to_chat_voice_state(u8 state);
|
||||
void audio_speak_to_chat_voice_state_sync(void);
|
||||
|
||||
int anc_adt_init();
|
||||
|
||||
int audio_icsd_adt_open(u8 adt_mode);
|
||||
int audio_icsd_adt_sync_open(u8 adt_mode);
|
||||
/*打开所有模块*/
|
||||
int audio_icsd_adt_open_all();
|
||||
|
||||
int audio_icsd_adt_sync_close(u8 adt_mode);
|
||||
int audio_icsd_adt_close(u8 adt_mode);
|
||||
int audio_icsd_adt_res_close(u8 adt_mode);
|
||||
/*关闭所有模块*/
|
||||
int audio_icsd_adt_close_all();
|
||||
|
||||
u8 audio_icsd_adt_is_running();
|
||||
|
||||
/*打开广域点击*/
|
||||
int audio_wat_click_open();
|
||||
|
||||
/*关闭广域点击*/
|
||||
int audio_wat_click_close();
|
||||
|
||||
/*设置是否忽略广域点击
|
||||
* ingore: 1 忽略点击,0 响应点击
|
||||
* 忽略点击的时间,单位ms*/
|
||||
int audio_wide_area_tap_ignore_flag_set(u8 ignore, u16 time);
|
||||
|
||||
/*广域点击开关demo*/
|
||||
void audio_wat_click_demo();
|
||||
|
||||
/*广域点击事件处理*/
|
||||
void audio_wat_area_tap_event_handle(u8 wat_result);
|
||||
|
||||
/*打开风噪检测*/
|
||||
int audio_icsd_wind_detect_open();
|
||||
|
||||
/*关闭风噪检测*/
|
||||
int audio_icsd_wind_detect_close();
|
||||
|
||||
/*获取风噪等级*/
|
||||
u8 get_audio_icsd_wind_lvl();
|
||||
|
||||
/*风噪检测开关demo*/
|
||||
void audio_icsd_wind_detect_demo();
|
||||
|
||||
/*风噪检测处理*/
|
||||
void audio_anc_wind_noise_process(u8 wind_lvl);
|
||||
|
||||
/*参数更新接口*/
|
||||
int audio_acoustic_detector_updata();
|
||||
void set_icsd_adt_param_updata();
|
||||
|
||||
/*获取免摘需要多少个mic*/
|
||||
u8 get_icsd_adt_mic_num();
|
||||
|
||||
extern void set_anc_adt_state(u8 state);
|
||||
extern void *get_anc_lfb_coeff();
|
||||
extern void *get_anc_lff_coeff();
|
||||
extern void *get_anc_ltrans_coeff();
|
||||
extern void *get_anc_ltrans_fb_coeff();
|
||||
extern float get_anc_gains_l_fbgain();
|
||||
extern float get_anc_gains_l_ffgain();
|
||||
extern float get_anc_gains_l_transgain();
|
||||
extern float get_anc_gains_lfb_transgain();
|
||||
extern u8 get_anc_l_fbyorder();
|
||||
extern u8 get_anc_l_ffyorder();
|
||||
extern u8 get_anc_l_transyorder();
|
||||
extern u8 get_anc_lfb_transyorder();
|
||||
extern u32 get_anc_gains_alogm();
|
||||
extern u32 get_anc_gains_trans_alogm();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,296 @@
|
||||
#if ADT_CLIENT_BOARD == HT03_HYBRID_6G
|
||||
const u8 ADT_TWS_MODE = 1;
|
||||
//const u8 ADT_DET_VER = 2;
|
||||
//const u8 ADT_PATH_CONFIG = 0;
|
||||
const u8 ADT_DET_VER = 4;
|
||||
const u8 ADT_PATH_CONFIG = ADT_PATH_DAC_SRC_EN;
|
||||
const u8 ADT_EIN_VER = ADT_EIN_TWS_V0;
|
||||
const float ref_gain_sel = 3;
|
||||
const float err_gain_sel = 3;
|
||||
u8 pnc_ref_pwr_thr = 160;
|
||||
u8 pnc_err_pwr_thr = 100;
|
||||
u8 tpc_ref_pwr_thr = 120;
|
||||
u8 tpc_err_pwr_thr = 100;
|
||||
u8 anc_ref_pwr_thr = 120;
|
||||
u8 anc_err_pwr_thr = 100;
|
||||
const float wat_pn_gain = 1;
|
||||
const float wat_bypass_gain = 16;
|
||||
const float wat_anc_gain = 1;
|
||||
const u8 final_speech_even_thr = 4;
|
||||
const float wdac_senc = 1;
|
||||
const float wdac[8] = {1, 1, 0.92, 0.80, 0.67, 0.62, 0.7, 0.7};//播放一笑江湖DJ /100
|
||||
const float wref[8] = {6.78, 3.66, 0.58, 0.37, 0.31, 0.29, 0.28, 0.27};//播放外部噪声
|
||||
const float wref_tran[8] = {1.26, 1.06, 1.06, 1.00, 1.00, 1.18, 1.16, 1.03 };
|
||||
const float wref_ancs[8] = {2.06, 2.00, 0.011, 0.006, 0.009, 0.012, 0.014, 0.018 };
|
||||
const float fdac[8] = {0.18, 0.051, 0.02, 0.02, 0.02, 0.02, 0.02, 0.05};//播放一笑江湖DJ /1000
|
||||
u8 icsd_get_ang_flag(float *_target_angle)
|
||||
{
|
||||
u8 af1 = _target_angle[1] > 15 || _target_angle[1] < -130;
|
||||
u8 af2 = _target_angle[2] > 15 || _target_angle[2] < -130;
|
||||
u8 af3 = _target_angle[3] > 15 || _target_angle[3] < -130;
|
||||
u8 ang_flag = af1 && af2 && af3;
|
||||
return ang_flag;
|
||||
}
|
||||
|
||||
#elif ADT_CLIENT_BOARD == G96_HYBRID
|
||||
const u8 ADT_TWS_MODE = 1;
|
||||
//const u8 ADT_DET_VER = 5;
|
||||
//const u8 ADT_PATH_CONFIG = 0;
|
||||
const u8 ADT_DET_VER = 4;
|
||||
const u8 ADT_PATH_CONFIG = ADT_PATH_DAC_SRC_EN;
|
||||
const u8 ADT_EIN_VER = ADT_EIN_TWS_V0;
|
||||
const float ref_gain_sel = 4;
|
||||
const float err_gain_sel = 1;
|
||||
u8 pnc_ref_pwr_thr = 160;
|
||||
u8 pnc_err_pwr_thr = 100;
|
||||
u8 tpc_ref_pwr_thr = 120;
|
||||
u8 tpc_err_pwr_thr = 100;
|
||||
u8 anc_ref_pwr_thr = 120;
|
||||
u8 anc_err_pwr_thr = 135;
|
||||
const float wat_pn_gain = 2.4;
|
||||
const float wat_bypass_gain = 16;
|
||||
const float wat_anc_gain = 2.5;
|
||||
const u8 final_speech_even_thr = 4;
|
||||
const float wdac_senc = 1;
|
||||
const float wdac[8] = {2.98, 2.29, 1.94, 1.95, 1.76, 1.54, 1.44, 1.29};
|
||||
const float wref[8] = {6.76, 1.98, 1.57, 1.50, 1.41, 1.32, 1.16, 1.02};
|
||||
const float wref_tran[8] = {4.26, 2.36, 2.36, 2.79, 3.00, 3.18, 3.16, 3.03 };
|
||||
const float wref_ancs[8] = {2.06, 2.00, 0.11, 0.06, 0.09, 0.12, 0.14, 0.18 };
|
||||
const float fdac[8] = {0.008, 0.008, 0.008, 0.008, 0.01, 0.01, 0.01, 0.01};
|
||||
u8 icsd_get_ang_flag(float *_target_angle)
|
||||
{
|
||||
u8 af1 = _target_angle[4] < 15 && _target_angle[4] > -150;
|
||||
u8 af2 = _target_angle[2] < 15 && _target_angle[2] > -150;
|
||||
u8 af3 = _target_angle[3] < 15 && _target_angle[3] > -150;
|
||||
u8 ang_flag = af1 && af2 && af3;
|
||||
return ang_flag;
|
||||
}
|
||||
|
||||
#elif ADT_CLIENT_BOARD == G97_HYBRID
|
||||
const u8 ADT_TWS_MODE = 1;
|
||||
const u8 ADT_DET_VER = 3;
|
||||
const u8 ADT_PATH_CONFIG = 0;
|
||||
//const u8 ADT_DET_VER = 4;
|
||||
//const u8 ADT_PATH_CONFIG = ADT_PATH_DAC_SRC_EN;
|
||||
const u8 ADT_EIN_VER = ADT_EIN_UNSUPPORT;
|
||||
const float ref_gain_sel = 2;
|
||||
const float err_gain_sel = 1;
|
||||
u8 pnc_ref_pwr_thr = 160;
|
||||
u8 pnc_err_pwr_thr = 100;
|
||||
u8 tpc_ref_pwr_thr = 120;
|
||||
u8 tpc_err_pwr_thr = 100;
|
||||
u8 anc_ref_pwr_thr = 120;
|
||||
u8 anc_err_pwr_thr = 135;
|
||||
const float wat_pn_gain = 2.88;
|
||||
const float wat_bypass_gain = 19.2;
|
||||
const float wat_anc_gain = 3;
|
||||
const u8 final_speech_even_thr = 4;
|
||||
const float wdac_senc = 1;
|
||||
const float wdac[8] = {10.43, 4.85, 1.36, 1.09, 0.87, 0.71, 0.63, 0.59};
|
||||
const float wref[8] = {7.31, 1.90, 0.43, 0.33, 0.28, 0.25, 0.22, 0.20};
|
||||
const float wref_tran[8] = {8.23, 3.33, 1.72, 1.64, 1.48, 1.30, 1.12, 1.04};
|
||||
const float wref_ancs[8] = {4.62, 1.32, 0.09, 0.06, 0.07, 0.10, 0.13, 0.15 };
|
||||
const float fdac[8] = {0.18, 0.051, 0.02, 0.02, 0.02, 0.02, 0.02, 0.05};
|
||||
u8 icsd_get_ang_flag(float *_target_angle)
|
||||
{
|
||||
u8 af1 = _target_angle[1] < -120 || _target_angle[1] > 20;
|
||||
u8 af2 = _target_angle[2] < -120 || _target_angle[2] > 20;
|
||||
u8 af3 = _target_angle[3] < -120 || _target_angle[3] > 20;
|
||||
u8 ang_flag = af1 && af2 && af3;
|
||||
|
||||
printf("ang:%d %d %d af:%d %d %d\n", (int)_target_angle[1], (int)_target_angle[2], (int)_target_angle[3], af1, af2, af3);
|
||||
return ang_flag;
|
||||
}
|
||||
|
||||
#elif ADT_CLIENT_BOARD == H3_HYBRID
|
||||
const u8 ADT_TWS_MODE = 0;
|
||||
const u8 ADT_DET_VER = 1;
|
||||
const u8 ADT_PATH_CONFIG = 0;
|
||||
const u8 ADT_EIN_VER = ADT_EIN_HEADSET_V0;
|
||||
const float ref_gain_sel = 3;
|
||||
const float err_gain_sel = 3;
|
||||
u8 pnc_ref_pwr_thr = 160;
|
||||
u8 pnc_err_pwr_thr = 100;
|
||||
u8 tpc_ref_pwr_thr = 120;
|
||||
u8 tpc_err_pwr_thr = 100;
|
||||
u8 anc_ref_pwr_thr = 120;
|
||||
u8 anc_err_pwr_thr = 135;
|
||||
const float wat_pn_gain = 1;
|
||||
const float wat_bypass_gain = 16;
|
||||
const float wat_anc_gain = 1;
|
||||
const u8 final_speech_even_thr = 4;
|
||||
const float wdac_senc = 1;
|
||||
const float wref[8] = {6.78, 3.66, 0.58, 0.37, 0.31, 0.29, 0.28, 0.27};
|
||||
const float wdac[8] = {1, 1, 0.92, 0.80, 0.67, 0.62, 0.7, 0.7};
|
||||
const float wref_tran[8] = {4.26, 2.36, 2.36, 2.79, 3.00, 3.18, 3.16, 3.03 };
|
||||
const float wref_ancs[8] = {2.06, 2.00, 0.011, 0.006, 0.009, 0.012, 0.014, 0.018 };
|
||||
const float fdac[8] = {0.18, 0.051, 0.02, 0.02, 0.02, 0.02, 0.02, 0.05};
|
||||
|
||||
#elif ADT_CLIENT_BOARD == ANC05_HYBRID
|
||||
const u8 ADT_TWS_MODE = 0;
|
||||
const u8 ADT_DET_VER = 1;
|
||||
const u8 ADT_PATH_CONFIG = 0;
|
||||
const u8 ADT_EIN_VER = ADT_EIN_UNSUPPORT;
|
||||
const float ref_gain_sel = 3;
|
||||
const float err_gain_sel = 3;
|
||||
u8 pnc_ref_pwr_thr = 160;
|
||||
u8 pnc_err_pwr_thr = 100;
|
||||
u8 tpc_ref_pwr_thr = 120;
|
||||
u8 tpc_err_pwr_thr = 100;
|
||||
u8 anc_ref_pwr_thr = 120;
|
||||
u8 anc_err_pwr_thr = 135;
|
||||
const float wat_pn_gain = 1;
|
||||
const float wat_bypass_gain = 16;
|
||||
const float wat_anc_gain = 1;
|
||||
const u8 final_speech_even_thr = 4;
|
||||
const float wdac_senc = 1;
|
||||
const float wref[8] = {6.78, 3.66, 0.58, 0.37, 0.31, 0.29, 0.28, 0.27};
|
||||
const float wdac[8] = {1, 1, 0.92, 0.80, 0.67, 0.62, 0.7, 0.7};
|
||||
const float wref_tran[8] = {4.26, 2.36, 2.36, 2.79, 3.00, 3.18, 3.16, 3.03 };
|
||||
const float wref_ancs[8] = {2.06, 2.00, 0.011, 0.006, 0.009, 0.012, 0.014, 0.018 };
|
||||
const float fdac[8] = {0.18, 0.051, 0.02, 0.02, 0.02, 0.02, 0.02, 0.05};
|
||||
|
||||
#else
|
||||
const float wdac_senc = 1;
|
||||
const u8 ADT_TWS_MODE = 1;
|
||||
const u8 ADT_DET_VER = 0;
|
||||
const u8 ADT_PATH_CONFIG = 0;
|
||||
const u8 ADT_EIN_VER = ADT_EIN_UNSUPPORT;
|
||||
const float ref_gain_sel = 3;
|
||||
const float err_gain_sel = 3;
|
||||
u8 pnc_ref_pwr_thr = 160;
|
||||
u8 pnc_err_pwr_thr = 100;
|
||||
u8 tpc_ref_pwr_thr = 120;
|
||||
u8 tpc_err_pwr_thr = 100;
|
||||
u8 anc_ref_pwr_thr = 120;
|
||||
u8 anc_err_pwr_thr = 135;
|
||||
const float wat_pn_gain = 1;
|
||||
const float wat_bypass_gain = 16;
|
||||
const float wat_anc_gain = 1;
|
||||
const u8 final_speech_even_thr = 4;
|
||||
const float wref[8] = {6.78, 3.66, 0.58, 0.37, 0.31, 0.29, 0.28, 0.27};
|
||||
const float wdac[8] = {1, 1, 0.92, 0.80, 0.67, 0.62, 0.7, 0.7};
|
||||
const float wref_tran[8] = {4.26, 2.36, 2.36, 2.79, 3.00, 3.18, 3.16, 3.03 };
|
||||
const float wref_ancs[8] = {2.06, 2.00, 0.011, 0.006, 0.009, 0.012, 0.014, 0.018 };
|
||||
const float fdac[8] = {0.18, 0.051, 0.02, 0.02, 0.02, 0.02, 0.02, 0.05};
|
||||
|
||||
#endif
|
||||
|
||||
void icsd_adt_ein_parm_HT03(__icsd_adt_parm *_ADT_PARM)
|
||||
{
|
||||
_ADT_PARM->anc_in_pz_sum = -80;
|
||||
_ADT_PARM->anc_out_pz_sum = 0;
|
||||
_ADT_PARM->anc_in_sz_mean = 1;
|
||||
_ADT_PARM->anc_out_sz_mean = -12;
|
||||
_ADT_PARM->anc_in_fb_sum = 60;
|
||||
_ADT_PARM->anc_out_fb_sum = 30;
|
||||
|
||||
_ADT_PARM->pnc_in_pz_sum = -80;
|
||||
_ADT_PARM->pnc_out_pz_sum = 0;
|
||||
_ADT_PARM->pnc_in_sz_mean = 1;
|
||||
_ADT_PARM->pnc_out_sz_mean = -12;
|
||||
_ADT_PARM->pnc_in_fb_sum = 60;
|
||||
_ADT_PARM->pnc_out_fb_sum = 30;
|
||||
|
||||
_ADT_PARM->trans_in_pz_sum = 2;
|
||||
_ADT_PARM->trans_out_pz_sum = 26;
|
||||
_ADT_PARM->trans_in_sz_mean = 2;
|
||||
_ADT_PARM->trans_out_sz_mean = -7;
|
||||
_ADT_PARM->trans_in_fb_sum = 20;
|
||||
_ADT_PARM->trans_out_fb_sum = -20;
|
||||
}
|
||||
|
||||
void icsd_adt_ein_parm(__icsd_adt_parm *_ADT_PARM)
|
||||
{
|
||||
_ADT_PARM->anc_in_pz_sum = -80;
|
||||
_ADT_PARM->anc_out_pz_sum = 0;
|
||||
_ADT_PARM->anc_in_sz_mean = 1;
|
||||
_ADT_PARM->anc_out_sz_mean = -12;
|
||||
_ADT_PARM->anc_in_fb_sum = 60;
|
||||
_ADT_PARM->anc_out_fb_sum = 30;
|
||||
|
||||
_ADT_PARM->pnc_in_pz_sum = -80;
|
||||
_ADT_PARM->pnc_out_pz_sum = 0;
|
||||
_ADT_PARM->pnc_in_sz_mean = 1;
|
||||
_ADT_PARM->pnc_out_sz_mean = -12;
|
||||
_ADT_PARM->pnc_in_fb_sum = 60;
|
||||
_ADT_PARM->pnc_out_fb_sum = 30;
|
||||
|
||||
_ADT_PARM->trans_in_pz_sum = 2;
|
||||
_ADT_PARM->trans_out_pz_sum = 26;
|
||||
_ADT_PARM->trans_in_sz_mean = 2;
|
||||
_ADT_PARM->trans_out_sz_mean = -7;
|
||||
_ADT_PARM->trans_in_fb_sum = 20;
|
||||
_ADT_PARM->trans_out_fb_sum = -20;
|
||||
}
|
||||
|
||||
void icsd_adt_voice_board_data()
|
||||
{
|
||||
__icsd_adt_parm *ADT_PARM;
|
||||
|
||||
ADT_PARM = zalloc(sizeof(__icsd_adt_parm));
|
||||
#if ADT_CLIENT_BOARD == HT03_HYBRID_6G
|
||||
adt_printf("ADT HT03\n");
|
||||
extern const float HT03_ADT_FLOAT_DATA[];
|
||||
extern const float HT03_sz_out_data[28];
|
||||
extern const float HT03_pz_out_data[28];
|
||||
ADT_PARM->adt_float_data = (void *)HT03_ADT_FLOAT_DATA;
|
||||
ADT_PARM->sz_inptr = (float *)HT03_sz_out_data;
|
||||
ADT_PARM->pz_inptr = (float *)HT03_pz_out_data;
|
||||
icsd_adt_ein_parm_HT03(ADT_PARM);
|
||||
|
||||
#elif ADT_CLIENT_BOARD == G96_HYBRID
|
||||
adt_printf("ADT G96\n");
|
||||
extern const float G96_ADT_FLOAT_DATA[];
|
||||
extern const float G96_sz_out_data[28];
|
||||
extern const float G96_pz_out_data[28];
|
||||
ADT_PARM->adt_float_data = (void *)G96_ADT_FLOAT_DATA;
|
||||
ADT_PARM->sz_inptr = (float *)G96_sz_out_data;
|
||||
ADT_PARM->pz_inptr = (float *)G96_pz_out_data;
|
||||
icsd_adt_ein_parm(ADT_PARM);
|
||||
|
||||
#elif ADT_CLIENT_BOARD == G97_HYBRID
|
||||
adt_printf("ADT G97\n");
|
||||
extern const float G97_ADT_FLOAT_DATA[];
|
||||
extern const float G97_sz_out_data[28];
|
||||
extern const float G97_pz_out_data[28];
|
||||
ADT_PARM->adt_float_data = (void *)G97_ADT_FLOAT_DATA;
|
||||
ADT_PARM->sz_inptr = (float *)G97_sz_out_data;
|
||||
ADT_PARM->pz_inptr = (float *)G97_pz_out_data;
|
||||
icsd_adt_ein_parm(ADT_PARM);
|
||||
|
||||
#elif ADT_CLIENT_BOARD == H3_HYBRID
|
||||
adt_printf("ADT H3\n");
|
||||
extern const float H3_ADT_FLOAT_DATA[];
|
||||
extern const float H3_sz_out_data[28];
|
||||
extern const float H3_pz_out_data[28];
|
||||
ADT_PARM->adt_float_data = (void *)H3_ADT_FLOAT_DATA;
|
||||
ADT_PARM->sz_inptr = (float *)H3_sz_out_data;
|
||||
ADT_PARM->pz_inptr = (float *)H3_pz_out_data;
|
||||
icsd_adt_ein_parm(ADT_PARM);
|
||||
|
||||
#elif ADT_CLIENT_BOARD == ANC05_HYBRID
|
||||
adt_printf("ADT ANC05\n");
|
||||
extern const float ANC05_ADT_FLOAT_DATA[];
|
||||
extern const float ANC05_sz_out_data[28];
|
||||
extern const float ANC05_pz_out_data[28];
|
||||
ADT_PARM->adt_float_data = (void *)ANC05_ADT_FLOAT_DATA;
|
||||
ADT_PARM->sz_inptr = (float *)ANC05_sz_out_data;
|
||||
ADT_PARM->pz_inptr = (float *)ANC05_pz_out_data;
|
||||
icsd_adt_ein_parm(ADT_PARM);
|
||||
|
||||
#else
|
||||
adt_printf("ADT XXX\n");
|
||||
#endif
|
||||
|
||||
icsd_adt_parm_set(ADT_PARM);
|
||||
free(ADT_PARM);
|
||||
|
||||
icsd_adt_szout_init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user