生成了代码仓库

This commit is contained in:
2026-08-21 18:41:42 +08:00
commit 81bd2f724d
907 changed files with 215888 additions and 0 deletions
+96
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+39
View File
@@ -0,0 +1,39 @@
# AC701N Earphone SDK
## 基本信息
- 工程名称:AC701N Earphone SDK
- 版本号:V1.0.1
- 生成时间:2026-08-19 15:43:10
- 适用芯片:AC7016CBR28
## 目录说明
```
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 自动生成。*
+866
View File
@@ -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)
+180
View File
@@ -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
+26
View File
@@ -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_*/
+13
View File
@@ -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_*/
+79
View File
@@ -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
+450
View File
@@ -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;
}
+55
View File
@@ -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_*/
+140
View File
@@ -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*/
+126
View File
@@ -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");
}
+11
View File
@@ -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_*/
+112
View File
@@ -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*/
+61
View File
@@ -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_*/
+138
View File
@@ -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*/
+10
View File
@@ -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_*/
+28
View File
@@ -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];
}
}
+18
View File
@@ -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_*/
+707
View File
@@ -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
+325
View File
@@ -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*/
+410
View File
@@ -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;
}
+47
View File
@@ -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_*/
+20
View File
@@ -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__
+129
View File
@@ -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_DMAx = 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
+21
View File
@@ -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_*/
+246
View File
@@ -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
+150
View File
@@ -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
+121
View File
@@ -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;
}
+216
View File
@@ -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
+370
View File
@@ -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
+125
View File
@@ -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
+242
View File
@@ -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与小机使用到的CMDCMD包含在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,而擦除单元是 4K4096),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
+599
View File
@@ -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);
}
+63
View File
@@ -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
+68
View File
@@ -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
+93
View File
@@ -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__
+173
View File
@@ -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,
},
};
+21
View File
@@ -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__
+327
View File
@@ -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;
}
+10
View File
@@ -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__
+157
View File
@@ -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 */
+253
View File
@@ -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 */
+61
View File
@@ -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 */
+355
View File
@@ -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 */
+78
View File
@@ -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
+380
View File
@@ -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 */
+62
View File
@@ -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 */
+51
View File
@@ -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 */
+708
View File
@@ -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) */
+490
View File
@@ -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
+23
View File
@@ -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
+457
View File
@@ -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 */
+202
View File
@@ -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
+332
View File
@@ -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
+463
View File
@@ -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
+514
View File
@@ -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
+258
View File
@@ -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中断,intrusbeintrtxe
//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;
}
+223
View File
@@ -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
+459
View File
@@ -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
+73
View File
@@ -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*/
+115
View File
@@ -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
+232
View File
@@ -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
+20
View File
@@ -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*/
+8
View File
@@ -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
+820
View File
@@ -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
+56
View File
@@ -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
+111
View File
@@ -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
+657
View File
@@ -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
+83
View File
@@ -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
+353
View File
@@ -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
+834
View File
@@ -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
+145
View File
@@ -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
+168
View File
@@ -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
+354
View File
@@ -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;
}
+139
View File
@@ -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*/
+194
View File
@@ -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
+190
View File
@@ -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
+327
View File
@@ -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
}
+932
View File
@@ -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]:raddr = %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]:raddr = %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]:waddr = %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]:raddr = %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]:waddr = %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
+488
View File
@@ -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
+47
View File
@@ -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_*/
+371
View File
@@ -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;
}
+11
View File
@@ -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__
+503
View File
@@ -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*/
+306
View File
@@ -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
+189
View File
@@ -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