ihdad: HDA verb constants module (Linux 7.1 hda_verbs.h)

Added verbs.rs with 200+ named constants ported from Linux 7.1
include/sound/hda_verbs.h. Replaces raw hex values (0xF00, 0xF01, etc.)
with named constants throughout device.rs.

Constants cover: widget types, GET/SET verbs, parameter IDs,
widget/pin/amplifier capabilities, pin control, power states,
PCM/stream format, digital converter bits, connection list.

Bug fix: read_node() was calling AC_PAR_NODE_COUNT (0x04) for
function_group_type query — corrected to AC_PAR_FUNCTION_TYPE (0x05).
The old code happened to work because the low byte matched on
the test codec, but was reading the wrong HDA parameter.
This commit is contained in:
Red Bear OS
2026-07-08 16:28:51 +03:00
parent c1eb0b3db0
commit 817524a3f0
+16 -14
View File
@@ -13,6 +13,12 @@ use common::timeout::Timeout;
use redox_scheme::scheme::SchemeSync;
use redox_scheme::CallerCtx;
use redox_scheme::OpenResult;
use crate::hda::verbs::{
AC_VERB_PARAMETERS, AC_VERB_GET_CONNECT_SEL, AC_VERB_GET_CONNECT_LIST,
AC_VERB_GET_CONFIG_DEFAULT,
AC_PAR_NODE_COUNT, AC_PAR_AUDIO_WIDGET_CAP, AC_PAR_CONNLIST_LEN,
AC_PAR_FUNCTION_TYPE, AC_CLIST_LONG, AC_CLIST_LENGTH,
};
use scheme_utils::{FpathWriter, HandleMap};
use syscall::error::{Error, Result, EACCES, EBADF, EIO, ENODEV, EWOULDBLOCK};
@@ -254,7 +260,7 @@ impl IntelHDA {
node.addr = addr;
temp = self.cmd.cmd12(addr, 0xF00, 0x04)?;
temp = self.cmd.cmd12(addr, AC_VERB_PARAMETERS, AC_PAR_NODE_COUNT)?;
node.subnode_count = (temp & 0xff) as u16;
node.subnode_start = ((temp >> 16) & 0xff) as u16;
@@ -262,41 +268,37 @@ impl IntelHDA {
if addr == (0, 0) {
return Ok(node);
}
temp = self.cmd.cmd12(addr, 0xF00, 0x04)?;
temp = self.cmd.cmd12(addr, AC_VERB_PARAMETERS, AC_PAR_FUNCTION_TYPE)?;
node.function_group_type = (temp & 0xff) as u8;
temp = self.cmd.cmd12(addr, 0xF00, 0x09)?;
temp = self.cmd.cmd12(addr, AC_VERB_PARAMETERS, AC_PAR_AUDIO_WIDGET_CAP)?;
node.capabilities = temp as u32;
temp = self.cmd.cmd12(addr, 0xF00, 0x0E)?;
temp = self.cmd.cmd12(addr, AC_VERB_PARAMETERS, AC_PAR_CONNLIST_LEN)?;
node.conn_list_len = (temp & 0xFF) as u8;
node.connections = self.node_get_connection_list(&node)?;
node.connection_default = self.cmd.cmd12(addr, 0xF01, 0x00)? as u8;
node.connection_default = self.cmd.cmd12(addr, AC_VERB_GET_CONNECT_SEL, 0x00)? as u8;
node.config_default = self.cmd.cmd12(addr, 0xF1C, 0x00)? as u32;
node.config_default = self.cmd.cmd12(addr, AC_VERB_GET_CONFIG_DEFAULT, 0x00)? as u32;
Ok(node)
}
pub fn node_get_connection_list(&mut self, node: &HDANode) -> Result<Vec<WidgetAddr>> {
let len_field: u8 = (self.cmd.cmd12(node.addr, 0xF00, 0x0E)? & 0xFF) as u8;
// Highest bit is if addresses are represented in longer notation
// lower 7 is actual count
let count: u8 = len_field & 0x7F;
let use_long_addr: bool = (len_field >> 7) & 0x1 == 1;
let len_field: u8 = (self.cmd.cmd12(node.addr, AC_VERB_PARAMETERS, AC_PAR_CONNLIST_LEN)? & 0xFF) as u8;
let count: u8 = len_field & (AC_CLIST_LENGTH as u8);
let use_long_addr: bool = (len_field & (AC_CLIST_LONG as u8)) != 0;
let mut current: u8 = 0;
let mut list = Vec::<WidgetAddr>::new();
while current < count {
let response: u32 = (self.cmd.cmd12(node.addr, 0xF02, current)? & 0xFFFFFFFF) as u32;
let response: u32 = (self.cmd.cmd12(node.addr, AC_VERB_GET_CONNECT_LIST, current)? & 0xFFFFFFFF) as u32;
if use_long_addr {
for i in 0..2 {