add ex3d hid commands

This commit is contained in:
Steven Dan
2025-12-31 10:06:49 +08:00
parent 51f453cd78
commit c90853ec94
5 changed files with 1502 additions and 2 deletions

View File

@@ -1,3 +1,4 @@
#define DEBUG_PRINT_ENABLE 1
#include <platform.h>
#include <xs1.h>
#include <stdlib.h>

View File

@@ -48,6 +48,15 @@ static struct {
bool is_get_uac_mode_info_request; // GET_UAC_MODE_INFO请求标志
bool is_get_current_uac_mode_request; // GET_CURRENT_UAC_MODE请求标志
} uac_request = {0};
static struct {
bool is_set_ex3d_cmd_request; // SET_EX3D_CMD请求标志
bool is_get_ex3d_cmd_request; // GET_EX3D_CMD请求标志
uint32_t ex3d_command_code; // EX3D命令码
uint8_t ex3d_params[56]; // EX3D参数数据最多14个uint3256字节
uint8_t ex3d_params_len; // EX3D参数长度
uint8_t ex3d_response[56]; // EX3D响应数据
uint8_t ex3d_response_len; // EX3D响应长度
} ex3d_request = {0};
#if EQ_EN
@@ -1115,6 +1124,10 @@ void get_device_info(unsigned char *response) {
void program_key(unsigned char *, signed int);
// 改动原因声明外部EX3D命令处理函数该函数在dsp.c中定义
#if (USE_EX3D == 1) && (HID_CONTROLS == 1)
extern void hid_receive_task_in_c(unsigned char * RcvData, unsigned * SendData);
#endif
unsigned char process_send_params(uint8_t data[], uint16_t len) {
#if 0
for (int i = 0; i < len; i++) {
@@ -1716,6 +1729,50 @@ unsigned char process_send_params(uint8_t data[], uint16_t len) {
return true;
}
// 处理发送EX3D命令 (0xB0) - SET_EX3D_CMD
// 改动原因添加EX3D命令封装将EQ协议格式转换为EX3D协议格式并处理
if (data[1] == 0xB0) {
debug_printf("Received set EX3D command (SET_EX3D_CMD)\n");
#if (USE_EX3D == 1) && (HID_CONTROLS == 1)
// 提取EX3D命令码4字节小端序
uint32_t ex3d_cmd = (uint32_t)data[2] | ((uint32_t)data[3] << 8) |
((uint32_t)data[4] << 16) | ((uint32_t)data[5] << 24);
debug_printf("EX3D command code: 0x%08X\n", ex3d_cmd);
// 提取参数从data[6]开始最多56字节
ex3d_request.ex3d_command_code = ex3d_cmd;
ex3d_request.ex3d_params_len = (len > 62) ? 56 : (len - 6);
memcpy(ex3d_request.ex3d_params, &data[6], ex3d_request.ex3d_params_len);
ex3d_request.is_set_ex3d_cmd_request = true;
return true;
#else
debug_printf("EX3D support not enabled\n");
return false;
#endif
}
// 处理读取EX3D命令 (0xB1) - GET_EX3D_CMD
// 改动原因添加EX3D读取命令封装将EQ协议格式转换为EX3D协议格式并处理
if (data[1] == 0xB1) {
debug_printf("Received get EX3D command (GET_EX3D_CMD)\n");
#if (USE_EX3D == 1) && (HID_CONTROLS == 1)
// 提取EX3D命令码4字节小端序
uint32_t ex3d_cmd = (uint32_t)data[2] | ((uint32_t)data[3] << 8) |
((uint32_t)data[4] << 16) | ((uint32_t)data[5] << 24);
debug_printf("EX3D command code: 0x%08X\n", ex3d_cmd);
// 提取参数从data[6]开始最多56字节
ex3d_request.ex3d_command_code = ex3d_cmd;
ex3d_request.ex3d_params_len = (len > 62) ? 56 : (len - 6);
memcpy(ex3d_request.ex3d_params, &data[6], ex3d_request.ex3d_params_len);
ex3d_request.is_get_ex3d_cmd_request = true;
return true;
#else
debug_printf("EX3D support not enabled\n");
return false;
#endif
}
if (data[1] == 0x8d)
{
debug_printf("Received set EQ filter parameters command (SET_EQ_PARAMS)\n");
@@ -3072,6 +3129,148 @@ unsigned char process_read_params(uint8_t response[]) {
return true;
}
// 处理发送EX3D命令响应 (0xB0) - SET_EX3D_CMD
// 改动原因添加EX3D SET命令响应处理调用hid_receive_task_in_c处理命令并返回结果
if (ex3d_request.is_set_ex3d_cmd_request == true) {
debug_printf("Building 0xB0 response data (SET_EX3D_CMD):\n");
response[0] = 0x77; // Sync header 1
response[1] = 0xB0; // Sync header 2
#if (USE_EX3D == 1) && (HID_CONTROLS == 1)
// 构建hid_receive_task_in_c需要的输入格式
// RcvData格式: [0-3: 保留] [4开始: 32位对齐的数据]
unsigned char rcv_data[64] = {0};
unsigned send_data[16] = {0}; // hid_receive_task_in_c的输出缓冲区
// 设置Report IDhid_receive_task_in_c期望从RcvData[4]开始)
rcv_data[0] = 0x01; // Report ID
// 从RcvData[4]开始放置数据即pRcvBuf[0]
unsigned *pRcvBuf = (unsigned *)(rcv_data + 4);
pRcvBuf[0] = ex3d_request.ex3d_command_code; // EX3D命令码
// 复制参数最多14个uint32
for (int i = 0; i < ex3d_request.ex3d_params_len / 4 && i < 14; i++) {
pRcvBuf[i + 1] = (uint32_t)ex3d_request.ex3d_params[i * 4] |
((uint32_t)ex3d_request.ex3d_params[i * 4 + 1] << 8) |
((uint32_t)ex3d_request.ex3d_params[i * 4 + 2] << 16) |
((uint32_t)ex3d_request.ex3d_params[i * 4 + 3] << 24);
}
// 调用EX3D命令处理函数
hid_receive_task_in_c(rcv_data, send_data);
// 状态码检查send_data[1]是否有错误返回值0xFFFFFFFF表示参数错误
uint8_t status = 0x00; // 默认成功
if (send_data[1] == 0xFFFFFFFF) {
status = 0x01; // 失败
debug_printf("EX3D command returned error (0xFFFFFFFF)\n");
}
response[2] = status;
// 回显命令码4字节
response[3] = (uint8_t)(ex3d_request.ex3d_command_code & 0xFF);
response[4] = (uint8_t)((ex3d_request.ex3d_command_code >> 8) & 0xFF);
response[5] = (uint8_t)((ex3d_request.ex3d_command_code >> 16) & 0xFF);
response[6] = (uint8_t)((ex3d_request.ex3d_command_code >> 24) & 0xFF);
// 返回send_data中的返回值如果有
if (send_data[1] != 0xFFFFFFFF) {
// 某些SET命令可能返回数据将send_data[1]开始的数据复制到响应
response[7] = (uint8_t)(send_data[1] & 0xFF);
response[8] = (uint8_t)((send_data[1] >> 8) & 0xFF);
response[9] = (uint8_t)((send_data[1] >> 16) & 0xFF);
response[10] = (uint8_t)((send_data[1] >> 24) & 0xFF);
} else {
// 错误时返回0xFFFFFFFF
response[7] = 0xFF;
response[8] = 0xFF;
response[9] = 0xFF;
response[10] = 0xFF;
}
// 其余字节填充为0
for (int i = 11; i < 63; i++) {
response[i] = 0x00;
}
#else
response[2] = 0x01; // 失败EX3D支持未启用
// 其余字节填充为0
for (int i = 3; i < 63; i++) {
response[i] = 0x00;
}
#endif
ex3d_request.is_set_ex3d_cmd_request = false; // Clear request flag
return true;
}
// 处理读取EX3D命令响应 (0xB1) - GET_EX3D_CMD
// 改动原因添加EX3D GET命令响应处理调用hid_receive_task_in_c处理命令并返回结果
if (ex3d_request.is_get_ex3d_cmd_request == true) {
debug_printf("Building 0xB1 response data (GET_EX3D_CMD):\n");
response[0] = 0x77; // Sync header 1
response[1] = 0xB1; // Sync header 2
#if (USE_EX3D == 1) && (HID_CONTROLS == 1)
// 构建hid_receive_task_in_c需要的输入格式
unsigned char rcv_data[64] = {0};
unsigned send_data[16] = {0}; // hid_receive_task_in_c的输出缓冲区
// 设置Report ID
rcv_data[0] = 0x01; // Report ID
// 从RcvData[4]开始放置数据即pRcvBuf[0]
unsigned *pRcvBuf = (unsigned *)(rcv_data + 4);
pRcvBuf[0] = ex3d_request.ex3d_command_code; // EX3D命令码
// 复制参数最多14个uint32
for (int i = 0; i < ex3d_request.ex3d_params_len / 4 && i < 14; i++) {
pRcvBuf[i + 1] = (uint32_t)ex3d_request.ex3d_params[i * 4] |
((uint32_t)ex3d_request.ex3d_params[i * 4 + 1] << 8) |
((uint32_t)ex3d_request.ex3d_params[i * 4 + 2] << 16) |
((uint32_t)ex3d_request.ex3d_params[i * 4 + 3] << 24);
}
// 调用EX3D命令处理函数
hid_receive_task_in_c(rcv_data, send_data);
// 回显命令码4字节
response[2] = (uint8_t)(ex3d_request.ex3d_command_code & 0xFF);
response[3] = (uint8_t)((ex3d_request.ex3d_command_code >> 8) & 0xFF);
response[4] = (uint8_t)((ex3d_request.ex3d_command_code >> 16) & 0xFF);
response[5] = (uint8_t)((ex3d_request.ex3d_command_code >> 24) & 0xFF);
// 复制返回值从send_data[1]开始最多14个uint32值
int response_idx = 6;
for (int i = 1; i < 16 && response_idx < 63; i++) {
if (response_idx + 3 < 63) {
response[response_idx++] = (uint8_t)(send_data[i] & 0xFF);
response[response_idx++] = (uint8_t)((send_data[i] >> 8) & 0xFF);
response[response_idx++] = (uint8_t)((send_data[i] >> 16) & 0xFF);
response[response_idx++] = (uint8_t)((send_data[i] >> 24) & 0xFF);
}
}
// 其余字节填充为0
while (response_idx < 63) {
response[response_idx++] = 0x00;
}
#else
// EX3D支持未启用返回错误
response[2] = 0xFF;
response[3] = 0xFF;
response[4] = 0xFF;
response[5] = 0xFF;
// 其余字节填充为0
for (int i = 6; i < 63; i++) {
response[i] = 0x00;
}
#endif
ex3d_request.is_get_ex3d_cmd_request = false; // Clear request flag
return true;
}
if (read_request.is_read_request == true) {
debug_printf("Read request information:\n");

View File

@@ -843,6 +843,70 @@ class EQDesigner(QMainWindow):
left_content_layout.addWidget(eq_enable_group)
# 添加EX3D控制组
ex3d_group = QGroupBox("EX3D控制")
self.ui_groups['ex3d'] = ex3d_group # 保存引用
ex3d_layout = QVBoxLayout(ex3d_group)
# EX3D命令码选择
ex3d_cmd_layout = QHBoxLayout()
ex3d_cmd_layout.addWidget(QLabel("EX3D命令码:"))
self.ex3d_cmd_combo = QComboBox()
# 添加SET命令选项清除第9位
self.ex3d_cmd_combo.addItem("CMD_OPEN (0x81)", 0x81)
self.ex3d_cmd_combo.addItem("CMD_ONOFF (0x82)", 0x82)
self.ex3d_cmd_combo.addItem("CMD_ANGLE (0x83)", 0x83)
self.ex3d_cmd_combo.addItem("CMD_SOUND_FIELD (0x84)", 0x84)
self.ex3d_cmd_combo.addItem("CMD_MUTE (0x85)", 0x85)
self.ex3d_cmd_combo.addItem("CMD_ON_GAIN (0x86)", 0x86)
self.ex3d_cmd_combo.addItem("CMD_LMT_THRESHOLD (0x87)", 0x87)
self.ex3d_cmd_combo.addItem("CMD_UPMIX (0x88)", 0x88)
self.ex3d_cmd_combo.addItem("CMD_LFE (0x89)", 0x89)
self.ex3d_cmd_combo.addItem("CMD_OFF_GAIN (0x8A)", 0x8A)
self.ex3d_cmd_combo.addItem("CMD_LMT_ATTACKK_TIME (0x8E)", 0x8E)
self.ex3d_cmd_combo.addItem("CMD_LMT_RELEASE_TIME (0x8F)", 0x8F)
self.ex3d_cmd_combo.addItem("CMD_EXPAND_GAIN (0x93)", 0x93)
self.ex3d_cmd_combo.addItem("CMD_REDUCE_GAIN (0x94)", 0x94)
ex3d_cmd_layout.addWidget(self.ex3d_cmd_combo)
ex3d_layout.addLayout(ex3d_cmd_layout)
# EX3D命令类型选择SET或GET
ex3d_type_layout = QHBoxLayout()
ex3d_type_layout.addWidget(QLabel("命令类型:"))
self.ex3d_cmd_type_combo = QComboBox()
self.ex3d_cmd_type_combo.addItem("SET (设置)", "SET")
self.ex3d_cmd_type_combo.addItem("GET (读取)", "GET")
ex3d_type_layout.addWidget(self.ex3d_cmd_type_combo)
ex3d_layout.addLayout(ex3d_type_layout)
# EX3D参数输入最多3个参数
ex3d_params_layout = QFormLayout()
self.ex3d_param1 = QSpinBox()
self.ex3d_param1.setRange(-2147483648, 2147483647)
self.ex3d_param1.setValue(0)
ex3d_params_layout.addRow("参数1 (int32):", self.ex3d_param1)
self.ex3d_param2 = QSpinBox()
self.ex3d_param2.setRange(-2147483648, 2147483647)
self.ex3d_param2.setValue(0)
ex3d_params_layout.addRow("参数2 (int32):", self.ex3d_param2)
self.ex3d_param3 = QSpinBox()
self.ex3d_param3.setRange(-2147483648, 2147483647)
self.ex3d_param3.setValue(0)
ex3d_params_layout.addRow("参数3 (int32):", self.ex3d_param3)
ex3d_layout.addLayout(ex3d_params_layout)
# EX3D命令按钮
ex3d_btn_layout = QHBoxLayout()
self.send_ex3d_btn = QPushButton("发送EX3D命令")
self.send_ex3d_btn.clicked.connect(self.on_send_ex3d_cmd)
self.get_ex3d_btn = QPushButton("读取EX3D参数")
self.get_ex3d_btn.clicked.connect(self.on_get_ex3d_cmd)
ex3d_btn_layout.addWidget(self.send_ex3d_btn)
ex3d_btn_layout.addWidget(self.get_ex3d_btn)
ex3d_layout.addLayout(ex3d_btn_layout)
left_content_layout.addWidget(ex3d_group)
# EQ后增益补偿
post_gain_layout = QHBoxLayout()
post_gain_label = QLabel("EQ整体增益 (dB):")
@@ -926,7 +990,8 @@ class EQDesigner(QMainWindow):
'device_mode': '设备模式控制',
'led': 'LED控制',
'uac': 'UAC模式控制',
'eq_enable': 'EQ使能控制'
'eq_enable': 'EQ使能控制',
'ex3d': 'EX3D控制'
}
# 为每组创建切换可见性的动作
@@ -954,7 +1019,8 @@ class EQDesigner(QMainWindow):
'device_mode': '设备模式控制',
'led': 'LED控制',
'uac': 'UAC模式控制',
'eq_enable': 'EQ使能控制'
'eq_enable': 'EQ使能控制',
'ex3d': 'EX3D控制'
}
name = group_names.get(group_key, group_key)
self.view_actions[group_key].setText(f"{'显示' if visible else '隐藏'} {name}")
@@ -3366,6 +3432,201 @@ eq_mode_data_t sEQ_data_{int(fs)}HZ[NUM_EQ_MODES][NUM_EQ_CHANS] = {{
except Exception as e:
log_message(LOG_LEVEL_ERROR, f"读取固件版本时出错: {str(e)}", self.log_level)
def on_send_ex3d_cmd(self):
"""发送EX3D SET命令0xB0命令"""
if self.device_combo.currentData() is None:
log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level)
return
try:
# 获取命令码和类型
base_cmd = self.ex3d_cmd_combo.currentData()
cmd_type = self.ex3d_cmd_type_combo.currentData()
# 构建EX3D命令码SET命令清除第9位GET命令设置第9位
if cmd_type == "SET":
ex3d_cmd = base_cmd & ~0x0100 # 清除第9位
else:
ex3d_cmd = base_cmd | 0x0100 # 设置第9位
# GET命令应该使用读取函数
self.on_get_ex3d_cmd()
return
device_info = self.device_combo.currentData()
h = hid.device()
h.open(device_info['vendor_id'], device_info['product_id'])
h.set_nonblocking(1)
# 构建0xB0数据包
data = bytearray(63) # 63字节数据包
data[0] = 0x77 # 同步头1
data[1] = 0xB0 # 命令码 (SET_EX3D_CMD)
# EX3D命令码 (4字节小端序)
data[2] = (ex3d_cmd >> 0) & 0xFF
data[3] = (ex3d_cmd >> 8) & 0xFF
data[4] = (ex3d_cmd >> 16) & 0xFF
data[5] = (ex3d_cmd >> 24) & 0xFF
# 参数最多14个uint32这里使用前3个
param1 = self.ex3d_param1.value()
param2 = self.ex3d_param2.value()
param3 = self.ex3d_param3.value()
# 参数1 (4字节小端序)
data[6] = (param1 >> 0) & 0xFF
data[7] = (param1 >> 8) & 0xFF
data[8] = (param1 >> 16) & 0xFF
data[9] = (param1 >> 24) & 0xFF
# 参数2 (4字节小端序)
data[10] = (param2 >> 0) & 0xFF
data[11] = (param2 >> 8) & 0xFF
data[12] = (param2 >> 16) & 0xFF
data[13] = (param2 >> 24) & 0xFF
# 参数3 (4字节小端序)
data[14] = (param3 >> 0) & 0xFF
data[15] = (param3 >> 8) & 0xFF
data[16] = (param3 >> 16) & 0xFF
data[17] = (param3 >> 24) & 0xFF
# 发送请求
log_message(LOG_LEVEL_INFO, f"正在发送EX3D SET命令: 0x{ex3d_cmd:04X}...", self.log_level)
h.write([0x01] + list(data))
# 读取响应
import time
time.sleep(0.05) # 等待设备响应
reply = h.get_input_report(0x1, 64) # 64字节响应
if reply and len(reply) == 64:
# 检查Report ID和同步头
if reply[0] == 0x01 and reply[1] == 0x77 and reply[2] == 0xB0:
# 解析状态码
status = reply[3]
# 解析回显的命令码
echo_cmd = reply[4] | (reply[5] << 8) | (reply[6] << 16) | (reply[7] << 24)
# 解析返回值
return_value = reply[8] | (reply[9] << 8) | (reply[10] << 16) | (reply[11] << 24)
if status == 0x00:
log_message(LOG_LEVEL_INFO, f"EX3D SET命令执行成功: 0x{echo_cmd:04X}, 返回值: 0x{return_value:08X}", self.log_level)
QMessageBox.information(
self,
"成功",
f"EX3D SET命令执行成功\n\n"
f"命令码: 0x{echo_cmd:04X}\n"
f"返回值: 0x{return_value:08X}"
)
else:
log_message(LOG_LEVEL_ERROR, f"EX3D SET命令执行失败: 0x{echo_cmd:04X}, 返回值: 0x{return_value:08X}", self.log_level)
QMessageBox.warning(
self,
"失败",
f"EX3D SET命令执行失败\n\n"
f"命令码: 0x{echo_cmd:04X}\n"
f"返回值: 0x{return_value:08X}"
)
else:
log_message(LOG_LEVEL_ERROR, f"无效的0xB0响应同步头: 0x{reply[1]:02x} 0x{reply[2]:02x}", self.log_level)
else:
log_message(LOG_LEVEL_ERROR, "未收到0xB0响应数据", self.log_level)
h.close()
except Exception as e:
log_message(LOG_LEVEL_ERROR, f"发送EX3D SET命令时出错: {str(e)}", self.log_level)
def on_get_ex3d_cmd(self):
"""读取EX3D GET命令0xB1命令"""
if self.device_combo.currentData() is None:
log_message(LOG_LEVEL_ERROR, "请先选择设备", self.log_level)
return
try:
# 获取命令码
base_cmd = self.ex3d_cmd_combo.currentData()
cmd_type = self.ex3d_cmd_type_combo.currentData()
# 构建EX3D命令码GET命令设置第9位
if cmd_type == "GET":
ex3d_cmd = base_cmd | 0x0100 # 设置第9位
else:
# SET命令应该使用发送函数但这里允许GET模式下读取
ex3d_cmd = base_cmd | 0x0100
device_info = self.device_combo.currentData()
h = hid.device()
h.open(device_info['vendor_id'], device_info['product_id'])
h.set_nonblocking(1)
# 构建0xB1数据包
data = bytearray(63) # 63字节数据包
data[0] = 0x77 # 同步头1
data[1] = 0xB1 # 命令码 (GET_EX3D_CMD)
# EX3D命令码 (4字节小端序)
data[2] = (ex3d_cmd >> 0) & 0xFF
data[3] = (ex3d_cmd >> 8) & 0xFF
data[4] = (ex3d_cmd >> 16) & 0xFF
data[5] = (ex3d_cmd >> 24) & 0xFF
# 参数某些GET命令需要参数如通道号、索引等
param1 = self.ex3d_param1.value()
# 参数1 (4字节小端序)
data[6] = (param1 >> 0) & 0xFF
data[7] = (param1 >> 8) & 0xFF
data[8] = (param1 >> 16) & 0xFF
data[9] = (param1 >> 24) & 0xFF
# 发送请求
log_message(LOG_LEVEL_INFO, f"正在读取EX3D GET命令: 0x{ex3d_cmd:04X}...", self.log_level)
h.write([0x01] + list(data))
# 读取响应
import time
time.sleep(0.05) # 等待设备响应
reply = h.get_input_report(0x1, 64) # 64字节响应
if reply and len(reply) == 64:
# 检查Report ID和同步头
if reply[0] == 0x01 and reply[1] == 0x77 and reply[2] == 0xB1:
# 解析回显的命令码位置3-64字节小端序
echo_cmd = reply[3] | (reply[4] << 8) | (reply[5] << 16) | (reply[6] << 24)
# 解析返回值从reply[7]开始最多14个uint32值
return_values = []
for i in range(0, 56, 4): # 最多14个uint32值
idx = 7 + i
if idx + 3 < 64:
val = reply[idx] | (reply[idx + 1] << 8) | (reply[idx + 2] << 16) | (reply[idx + 3] << 24)
return_values.append(val)
if val == 0 and i > 16: # 遇到连续0值可能表示数据结束
break
log_message(LOG_LEVEL_INFO, f"EX3D GET命令响应: 0x{echo_cmd:04X}, 返回值: {return_values}", self.log_level)
# 格式化返回值显示
values_str = ", ".join([f"0x{val:08X}" for val in return_values[:4]]) # 只显示前4个值
if len(return_values) > 4:
values_str += f" ... (共{len(return_values)}个值)"
QMessageBox.information(
self,
"EX3D GET命令响应",
f"命令码: 0x{echo_cmd:04X}\n\n"
f"返回值:\n{values_str}"
)
else:
log_message(LOG_LEVEL_ERROR, f"无效的0xB1响应同步头: 0x{reply[1]:02x} 0x{reply[2]:02x}", self.log_level)
else:
log_message(LOG_LEVEL_ERROR, "未收到0xB1响应数据", self.log_level)
h.close()
except Exception as e:
log_message(LOG_LEVEL_ERROR, f"读取EX3D GET命令时出错: {str(e)}", self.log_level)
if __name__ == "__main__":
app = QApplication([])
window = EQDesigner()

View File

@@ -37,6 +37,8 @@
| 0xA4 | SET_GAME_MODE | 设置游戏模式 | 主机→设备 | 设置游戏模式0=无音效1=FPS2=虚拟7.1 |
| 0xA5 | GET_GAME_MODE | 获取游戏模式 | 主机→设备 | 读取当前游戏模式0-2 |
| 0xA6 | GET_FIRMWARE_VERSION | 获取固件版本 | 主机→设备 | 读取设备固件版本号BCD格式主版本.次版本.修订版本) |
| 0xB0 | SET_EX3D_CMD | 发送EX3D命令 | 主机→设备 | 发送EX3D设置命令封装所有EX3D SET命令 |
| 0xB1 | GET_EX3D_CMD | 读取EX3D命令 | 主机→设备 | 读取EX3D参数封装所有EX3D GET命令 |
### 1.3 数据包格式
- **Report ID**: 0x01 (HID报告ID)
@@ -841,6 +843,134 @@
- 3个字节分别表示主版本号、次版本号、修订版本号
- 例如0x01 0x00 0x0C 表示版本 1.0.12
### 2.30 0xB0 - SET_EX3D_CMD (发送EX3D命令)
**功能**: 发送EX3D设置命令封装所有EX3D SET命令
**方向**: 主机→设备
**数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x77 | 同步头1
1 | 1 | 0xB0 | 命令码
2-5 | 4 | uint32 | EX3D命令码包含SET标志参考ex3d_protocol.md
6-9 | 4 | uint32 | 参数1根据EX3D命令不同而不同
10-13 | 4 | uint32 | 参数2根据EX3D命令不同而不同
14-17 | 4 | uint32 | 参数3根据EX3D命令不同而不同
18-62 | 45 | 0x00 | 保留字节或扩展参数
```
**EX3D命令码说明**:
- 基础命令码范围: 0x80-0x94
- SET命令格式: `基础命令码 & ~0x0100`清除第9位
- 支持的SET命令
- 0x81: CMD_OPEN打开EX3D
- 0x82: CMD_ONOFF设置EX3D开关
- 0x83: CMD_ANGLE设置角度
- 0x84: CMD_SOUND_FIELD设置声场模式
- 0x85: CMD_MUTE设置静音
- 0x86: CMD_ON_GAIN设置开启增益
- 0x87: CMD_LMT_THRESHOLD设置限制器阈值
- 0x88: CMD_UPMIX设置上混
- 0x89: CMD_LFE设置LFE增益
- 0x8A: CMD_OFF_GAIN设置关闭增益
- 0x8E: CMD_LMT_ATTACKK_TIME设置限制器攻击时间
- 0x8F: CMD_LMT_RELEASE_TIME设置限制器释放时间
- 0x90: CMD_TEST_CANCEL取消测试
- 0x91: CMD_TEST_STEP测试步骤
- 0x92: CMD_TEST_ROTATE测试旋转
- 0x93: CMD_EXPAND_GAIN设置扩展增益
- 0x94: CMD_REDUCE_GAIN设置减少增益
**设备端处理**:
- 解析EX3D命令码提取基础命令码和参数
- 调用相应的EX3D处理函数hid_receive_task_in_c
- 根据命令类型执行相应的设置操作
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1 | 1 | 0x77 | 同步头1
2 | 1 | 0xB0 | 同步头2
3 | 1 | uint8 | 状态码 (0x00=成功, 0x01=失败)
4-7 | 4 | uint32 | EX3D命令码回显
8-11 | 4 | uint32 | 返回值某些命令返回0xFFFFFFFF表示参数错误
12-62 | 51 | 0x00 | 保留字节
```
**使用说明**:
- 该命令用于统一封装所有EX3D设置命令
- 参数格式与原始EX3D协议保持一致
- 详细的EX3D命令说明请参考ex3d_protocol.md文档
### 2.31 0xB1 - GET_EX3D_CMD (读取EX3D命令)
**功能**: 读取EX3D参数封装所有EX3D GET命令
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x77 | 同步头1
1 | 1 | 0xB1 | 命令码
2-5 | 4 | uint32 | EX3D命令码包含GET标志参考ex3d_protocol.md
6-9 | 4 | uint32 | 参数1根据EX3D命令不同而不同如通道号、索引等
10-62 | 53 | 0x00 | 保留字节或扩展参数
```
**EX3D命令码说明**:
- 基础命令码范围: 0x80-0x94
- GET命令格式: `基础命令码 | 0x0100`设置第9位
- 支持的GET命令
- 0x180: CMD_CH_NUM获取通道数量
- 0x182: CMD_ONOFF获取EX3D开关
- 0x183: CMD_ANGLE获取角度
- 0x184: CMD_SOUND_FIELD获取声场模式
- 0x185: CMD_MUTE获取静音
- 0x186: CMD_ON_GAIN获取开启增益
- 0x187: CMD_LMT_THRESHOLD获取限制器阈值
- 0x188: CMD_UPMIX获取上混
- 0x189: CMD_LFE获取LFE增益
- 0x18A: CMD_OFF_GAIN获取关闭增益
- 0x18B: CMD_SOUND_FIELD_NUM获取声场模式数量
- 0x18C: CMD_SOUND_FIELD_NAME获取声场模式名称
- 0x18D: CMD_LEVEL获取电平
- 0x18E: CMD_LMT_ATTACKK_TIME获取限制器攻击时间
- 0x18F: CMD_LMT_RELEASE_TIME获取限制器释放时间
- 0x193: CMD_EXPAND_GAIN获取扩展增益
- 0x194: CMD_REDUCE_GAIN获取减少增益
**设备端处理**:
- 解析EX3D命令码提取基础命令码和参数
- 调用相应的EX3D处理函数hid_receive_task_in_c
- 返回当前参数值
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1 | 1 | 0x77 | 同步头1
2 | 1 | 0xB1 | 同步头2
3-6 | 4 | uint32 | EX3D命令码回显
7-10 | 4 | uint32 | 返回值1根据命令不同而不同
11-14 | 4 | uint32 | 返回值2某些命令需要多个返回值如角度、多通道数据等
15-18 | 4 | uint32 | 返回值3扩展返回值如多通道数据
... | ... | ... | 其他返回值最多可返回14个uint32值总长度不超过63字节
```
**返回值说明**:
- 返回值数量和格式取决于具体的EX3D命令
- 单值命令返回1个uint32值
- 多值命令如角度、多通道数据返回多个uint32值
- 字符串命令(如声场名称):先返回长度(uint32),然后返回字符串数据
- 详细的返回值格式请参考ex3d_protocol.md文档
**使用说明**:
- 该命令用于统一封装所有EX3D读取命令
- 参数格式与原始EX3D协议保持一致
- 详细的EX3D命令说明请参考ex3d_protocol.md文档
## 5. 关键特性

View File

@@ -0,0 +1,909 @@
# EX3D HID通信协议详细文档
## 1. 总体框架
### 1.1 协议概述
该协议使用HID (Human Interface Device) 协议进行主机与设备之间的通信。协议支持EX3D3D音频扩展参数设置、读取等功能。
### 1.2 命令格式说明
EX3D命令使用特殊的命令格式
- **基础命令码**: 0x80-0x94 (定义在PlbkCmdCode枚举中)
- **命令修饰符**:
- `CMD_SET(cmd)`: 清除第9位(0x0100),用于设置命令
- `CMD_GET(cmd)`: 设置第9位(0x0100),用于读取命令
- `CMD_MASK`: 提取基础命令码的掩码(~0x0F00)
- **命令结构**:
- 设置命令: `基础命令码 & ~0x0100` (例如: CMD_ONOFF = 0x82, SET命令 = 0x82)
- 读取命令: `基础命令码 | 0x0100` (例如: CMD_ONOFF = 0x82, GET命令 = 0x182)
### 1.3 数据包格式
- **数据包大小**: 最大64字节 (1字节Report ID + 63字节数据)
- **数据对齐**: 使用32位(unsigned)对齐数据从RcvData[4]开始即pRcvBuf[0]开始
- **字节序**: 小端序 (Little Endian)
## 2. 详细命令说明
### 2.1 命令列表
| 基础命令码 | 命令名称 | SET命令码 | GET命令码 | 功能 | 方向 |
|-----------|----------|-----------|-----------|------|------|
| 0x80 | CMD_CH_NUM | - | 0x180 | 获取通道数量 | 主机→设备 |
| 0x81 | CMD_OPEN | 0x81 | - | 打开EX3D | 主机→设备 |
| 0x82 | CMD_ONOFF | 0x82 | 0x182 | 设置/获取EX3D开关 | 主机↔设备 |
| 0x83 | CMD_ANGLE | 0x83 | 0x183 | 设置/获取角度 | 主机↔设备 |
| 0x84 | CMD_SOUND_FIELD | 0x84 | 0x184 | 设置/获取声场模式 | 主机↔设备 |
| 0x85 | CMD_MUTE | 0x85 | 0x185 | 设置/获取静音 | 主机↔设备 |
| 0x86 | CMD_ON_GAIN | 0x86 | 0x186 | 设置/获取开启增益 | 主机↔设备 |
| 0x87 | CMD_LMT_THRESHOLD | 0x87 | 0x187 | 设置/获取限制器阈值 | 主机↔设备 |
| 0x88 | CMD_UPMIX | 0x88 | 0x188 | 设置/获取上混 | 主机↔设备 |
| 0x89 | CMD_LFE | 0x89 | 0x189 | 设置/获取LFE增益 | 主机↔设备 |
| 0x8A | CMD_OFF_GAIN | 0x8A | 0x18A | 设置/获取关闭增益 | 主机↔设备 |
| 0x8B | CMD_SOUND_FIELD_NUM | - | 0x18B | 获取声场模式数量 | 主机→设备 |
| 0x8C | CMD_SOUND_FIELD_NAME | - | 0x18C | 获取声场模式名称 | 主机→设备 |
| 0x8D | CMD_LEVEL | - | 0x18D | 获取电平 | 主机→设备 |
| 0x8E | CMD_LMT_ATTACKK_TIME | 0x8E | 0x18E | 设置/获取限制器攻击时间 | 主机↔设备 |
| 0x8F | CMD_LMT_RELEASE_TIME | 0x8F | 0x18F | 设置/获取限制器释放时间 | 主机↔设备 |
| 0x90 | CMD_TEST_CANCEL | 0x90 | - | 取消测试 | 主机→设备 |
| 0x91 | CMD_TEST_STEP | 0x91 | - | 测试步骤 | 主机→设备 |
| 0x92 | CMD_TEST_ROTATE | 0x92 | - | 测试旋转 | 主机→设备 |
| 0x93 | CMD_EXPAND_GAIN | 0x93 | 0x193 | 设置/获取扩展增益 | 主机↔设备 |
| 0x94 | CMD_REDUCE_GAIN | 0x94 | 0x194 | 设置/获取减少增益 | 主机↔设备 |
### 2.2 数据包结构
#### 通用请求数据包格式
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 保留 | 保留字节(跳过)
4-7 | 4 | uint32 | 命令码 (包含SET/GET标志)
8-11 | 4 | uint32 | 参数1 (根据命令不同而不同)
12-15 | 4 | uint32 | 参数2 (根据命令不同而不同)
... | ... | ... | 其他参数
```
#### 通用响应数据包格式
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 保留 | 保留字节(跳过)
4-7 | 4 | uint32 | 命令码 (回显)
8-11 | 4 | uint32 | 返回值/参数1
12-15 | 4 | uint32 | 返回值/参数2
... | ... | ... | 其他返回值
```
### 2.3 详细命令说明
#### 2.3.1 CMD_CH_NUM (0x80) - 获取通道数量
**功能**: 获取USB音频输出通道数量
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x180 = CMD_GET(CMD_CH_NUM))
8-63 | 56 | 0x00 | 保留字节
```
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x180回显)
8-11 | 4 | uint32 | 通道数量 (NUM_USB_CHAN_OUT)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.2 CMD_OPEN (0x81) - 打开EX3D
**功能**: 打开EX3D系统
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x81 = CMD_SET(CMD_OPEN))
8-63 | 56 | 0x00 | 保留字节
```
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x81回显)
8-63 | 56 | 0x00 | 保留字节(无返回值)
```
#### 2.3.3 CMD_ONOFF (0x82) - 设置/获取EX3D开关
**功能**: 设置或获取EX3D开关状态
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x82):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x82 = CMD_SET(CMD_ONOFF))
8-11 | 4 | uint32 | 开关值 (0=关闭, 1=开启)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x82回显)
8-63 | 56 | 0x00 | 保留字节(无返回值)
```
**GET命令请求数据包格式** (0x182):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x182 = CMD_GET(CMD_ONOFF))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x182回显)
8-11 | 4 | uint32 | 当前开关状态 (0=关闭, 1=开启)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.4 CMD_ANGLE (0x83) - 设置/获取角度
**功能**: 设置或获取通道的角度(垂直角度和水平角度)
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x83):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x83 = CMD_SET(CMD_ANGLE))
8-11 | 4 | uint32 | 通道号 (如果 >= NUM_USB_CHAN_OUT表示设置所有通道)
12-15 | 4 | uint32 | 角度值1 (单通道) 或 角度值[0] (多通道)
16-19 | 4 | uint32 | 角度值2 (多通道,可选)
... | ... | ... | 其他通道角度值最多NUM_USB_CHAN_OUT个
```
**角度值格式**: `(VAngle << 16) | HAngle`
- VAngle: 垂直角度 (0-180度高16位)
- HAngle: 水平角度 (0-359度低16位)
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x83回显)
8-63 | 56 | 0x00 | 保留字节(无返回值)
```
**GET命令请求数据包格式** (0x183):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x183 = CMD_GET(CMD_ANGLE))
8-11 | 4 | uint32 | 通道号 (如果 >= NUM_USB_CHAN_OUT表示获取所有通道)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x183回显)
8-11 | 4 | uint32 | 角度值 (单通道) 或 角度值[0] (多通道)
12-15 | 4 | uint32 | 角度值[1] (多通道,可选)
... | ... | ... | 其他通道角度值最多NUM_USB_CHAN_OUT个
```
**角度值格式**: `(VAngle << 16) | HAngle`
#### 2.3.5 CMD_SOUND_FIELD (0x84) - 设置/获取声场模式
**功能**: 设置或获取当前声场模式
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x84):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x84 = CMD_SET(CMD_SOUND_FIELD))
8-11 | 4 | uint32 | 声场模式索引 (0到EX3D_SF_NUM-1)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x84回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=索引无效, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x184):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x184 = CMD_GET(CMD_SOUND_FIELD))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x184回显)
8-11 | 4 | uint32 | 当前声场模式索引 (或0)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.6 CMD_MUTE (0x85) - 设置/获取静音
**功能**: 设置或获取通道的静音状态
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x85):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x85 = CMD_SET(CMD_MUTE))
8-11 | 4 | uint32 | 通道号 (如果 >= NUM_USB_CHAN_OUT表示设置所有通道)
12-15 | 4 | uint32 | 静音值1 (单通道) 或 静音值[0] (多通道0=不静音, 1=静音)
16-19 | 4 | uint32 | 静音值2 (多通道,可选)
... | ... | ... | 其他通道静音值最多NUM_USB_CHAN_OUT个
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x85回显)
8-63 | 56 | 0x00 | 保留字节(无返回值)
```
**GET命令请求数据包格式** (0x185):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x185 = CMD_GET(CMD_MUTE))
8-11 | 4 | uint32 | 通道号 (如果 >= NUM_USB_CHAN_OUT表示获取所有通道)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x185回显)
8-11 | 4 | uint32 | 静音值 (单通道) 或 静音值[0] (多通道)
12-15 | 4 | uint32 | 静音值[1] (多通道,可选)
... | ... | ... | 其他通道静音值最多NUM_USB_CHAN_OUT个
```
#### 2.3.7 CMD_ON_GAIN (0x86) - 设置/获取开启增益
**功能**: 设置或获取EX3D开启时的增益值
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x86):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x86 = CMD_SET(CMD_ON_GAIN))
8-11 | 4 | int32 | 增益值 (范围-100到0 dB小端序)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x86回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x186):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x186 = CMD_GET(CMD_ON_GAIN))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x186回显)
8-11 | 4 | int32 | 当前开启增益值 (范围-100到0 dB小端序)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.8 CMD_LMT_THRESHOLD (0x87) - 设置/获取限制器阈值
**功能**: 设置或获取限制器阈值
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x87):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x87 = CMD_SET(CMD_LMT_THRESHOLD))
8-11 | 4 | int32 | 阈值 (范围-35到0 dB小端序)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x87回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x187):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x187 = CMD_GET(CMD_LMT_THRESHOLD))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x187回显)
8-11 | 4 | int32 | 当前限制器阈值 (范围-35到0 dB小端序)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.9 CMD_UPMIX (0x88) - 设置/获取上混
**功能**: 设置或获取上混状态
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x88):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x88 = CMD_SET(CMD_UPMIX))
8-11 | 4 | uint32 | 上混值 (0=关闭, 1=开启)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x88回显)
8-63 | 56 | 0x00 | 保留字节(无返回值)
```
**GET命令请求数据包格式** (0x188):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x188 = CMD_GET(CMD_UPMIX))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x188回显)
8-11 | 4 | uint32 | 当前上混状态 (0=关闭, 1=开启)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.10 CMD_LFE (0x89) - 设置/获取LFE增益
**功能**: 设置或获取LFE低频效果增益
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x89):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x89 = CMD_SET(CMD_LFE))
8-11 | 4 | int32 | 增益值 (范围-100到0 dB小端序)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x89回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x189):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x189 = CMD_GET(CMD_LFE))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x189回显)
8-11 | 4 | int32 | 当前LFE增益值 (范围-100到0 dB小端序)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.11 CMD_OFF_GAIN (0x8A) - 设置/获取关闭增益
**功能**: 设置或获取EX3D关闭时的增益值
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x8A):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x8A = CMD_SET(CMD_OFF_GAIN))
8-11 | 4 | int32 | 增益值 (范围-100到0 dB小端序)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x8A回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x18A):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18A = CMD_GET(CMD_OFF_GAIN))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18A回显)
8-11 | 4 | int32 | 当前关闭增益值 (范围-100到0 dB小端序)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.12 CMD_SOUND_FIELD_NUM (0x8B) - 获取声场模式数量
**功能**: 获取可用的声场模式数量
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18B = CMD_GET(CMD_SOUND_FIELD_NUM))
8-63 | 56 | 0x00 | 保留字节
```
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18B回显)
8-11 | 4 | uint32 | 声场模式数量 (EX3D_SF_NUM)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.13 CMD_SOUND_FIELD_NAME (0x8C) - 获取声场模式名称
**功能**: 获取指定声场模式的名称
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18C = CMD_GET(CMD_SOUND_FIELD_NAME))
8-11 | 4 | uint32 | 声场模式索引
12-63 | 52 | 0x00 | 保留字节
```
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18C回显)
8-11 | 4 | uint32 | 名称长度 (如果索引无效则为0xFFFFFFFF)
12-15 | 4 | char | 名称字符[0-3] (UTF-8编码如果索引有效)
16-19 | 4 | char | 名称字符[4-7] (UTF-8编码可选)
... | ... | ... | 其他名称字符最多16字节
```
**注意**: 如果索引无效位置8-11返回0xFFFFFFFF后续字节为0x00
#### 2.3.14 CMD_LEVEL (0x8D) - 获取电平
**功能**: 获取通道的电平值
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18D = CMD_GET(CMD_LEVEL))
8-11 | 4 | uint32 | 通道数量
12-63 | 52 | 0x00 | 保留字节
```
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18D回显)
8-11 | 4 | float | 电平值[0] (通道0的电平值IEEE 754格式小端序)
12-15 | 4 | float | 电平值[1] (通道1的电平值可选)
... | ... | ... | 其他通道电平值最多NUM_USB_CHAN_OUT个每个4字节float
```
#### 2.3.15 CMD_LMT_ATTACKK_TIME (0x8E) - 设置/获取限制器攻击时间
**功能**: 设置或获取限制器攻击时间
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x8E):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x8E = CMD_SET(CMD_LMT_ATTACKK_TIME))
8-11 | 4 | uint32 | 攻击时间 (范围0到10小端序)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x8E回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x18E):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18E = CMD_GET(CMD_LMT_ATTACKK_TIME))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18E回显)
8-11 | 4 | uint32 | 当前限制器攻击时间 (范围0到10小端序)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.16 CMD_LMT_RELEASE_TIME (0x8F) - 设置/获取限制器释放时间
**功能**: 设置或获取限制器释放时间
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x8F):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x8F = CMD_SET(CMD_LMT_RELEASE_TIME))
8-11 | 4 | uint32 | 释放时间 (范围0到100小端序)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x8F回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x18F):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18F = CMD_GET(CMD_LMT_RELEASE_TIME))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x18F回显)
8-11 | 4 | uint32 | 当前限制器释放时间 (范围0到100小端序)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.17 CMD_EXPAND_GAIN (0x93) - 设置/获取扩展增益
**功能**: 设置或获取扩展增益值
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x93):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x93 = CMD_SET(CMD_EXPAND_GAIN))
8-11 | 4 | int32 | 增益值 (范围0到20小端序)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x93回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x193):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x193 = CMD_GET(CMD_EXPAND_GAIN))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x193回显)
8-11 | 4 | int32 | 当前扩展增益值 (范围0到20小端序)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.18 CMD_REDUCE_GAIN (0x94) - 设置/获取减少增益
**功能**: 设置或获取减少增益值
**方向**: 主机↔设备
**SET命令请求数据包格式** (0x94):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x94 = CMD_SET(CMD_REDUCE_GAIN))
8-11 | 4 | int32 | 增益值 (范围-20到0小端序)
12-63 | 52 | 0x00 | 保留字节
```
**SET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x94回显)
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
12-63 | 52 | 0x00 | 保留字节
```
**GET命令请求数据包格式** (0x194):
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x194 = CMD_GET(CMD_REDUCE_GAIN))
8-63 | 56 | 0x00 | 保留字节
```
**GET命令响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x194回显)
8-11 | 4 | int32 | 当前减少增益值 (范围-20到0小端序)
12-63 | 52 | 0x00 | 保留字节
```
#### 2.3.19 CMD_TEST_CANCEL (0x90) - 取消测试
**功能**: 取消EX3D测试
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x90 = CMD_SET(CMD_TEST_CANCEL))
8-63 | 56 | 0x00 | 保留字节
```
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x90回显)
8-63 | 56 | 0x00 | 保留字节(无返回值)
```
#### 2.3.20 CMD_TEST_STEP (0x91) - 测试步骤
**功能**: 执行EX3D测试步骤
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x91 = CMD_SET(CMD_TEST_STEP))
8-63 | 56 | 0x00 | 保留字节
```
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x91回显)
8-63 | 56 | 0x00 | 保留字节(无返回值)
```
#### 2.3.21 CMD_TEST_ROTATE (0x92) - 测试旋转
**功能**: 执行EX3D测试旋转
**方向**: 主机→设备
**请求数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x92 = CMD_SET(CMD_TEST_ROTATE))
8-63 | 56 | 0x00 | 保留字节
```
**响应数据包格式**:
```
字节位置 | 长度 | 内容 | 描述
---------|------|------|------
0 | 1 | 0x01 | Report ID
1-3 | 3 | 0x00 | 保留字节
4-7 | 4 | uint32 | 命令码 (0x92回显)
8-63 | 56 | 0x00 | 保留字节(无返回值)
```
## 3. 注意事项
1. **数据对齐**: 所有数据使用32位(unsigned)对齐从RcvData[4]开始
2. **命令码格式**: SET命令清除第9位GET命令设置第9位
3. **错误处理**: 当参数超出范围时返回0xFFFFFFFF表示错误
4. **多通道处理**: ANGLE和MUTE命令支持单通道或多通道批量设置
5. **字节序**: 所有多字节数据使用小端序
6. **字符串编码**: 字符串使用UTF-8编码
## 4. 实现参考
参考文件: `sw_usb_audio/app_usb_aud_phaten_golden/src/extensions/dsp.c`
- 函数: `hid_receive_task_in_c()`
- 行号: 269-598