Commit b5f82b10 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda - Fix snd_hda_get_num_raw_conns() to return a correct value

In the connection list expansion in hda_codec.c and hda_proc.c, the
value returned from snd_hda_get_num_raw_conns() is used as the array
size to store the connection list.  However, the function returns
simply a raw value of the AC_PAR_CONNLIST_LEN parameter, and the
widget list with ranges isn't considered there.  Thus it may return a
smaller size than the actual list, which results in -ENOSPC in
snd_hda_get_raw_conections().

This patch fixes the bug by parsing the connection list correctly also
for snd_hda_get_num_raw_conns().
Reported-and-tested-by: default avatarDavid Henningsson <david.henningsson@canonical.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 281a6ac0
...@@ -494,7 +494,7 @@ static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid) ...@@ -494,7 +494,7 @@ static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid)
int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid) int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid)
{ {
return get_num_conns(codec, nid) & AC_CLIST_LENGTH; return snd_hda_get_raw_connections(codec, nid, NULL, 0);
} }
/** /**
...@@ -517,9 +517,6 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, ...@@ -517,9 +517,6 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
hda_nid_t prev_nid; hda_nid_t prev_nid;
int null_count = 0; int null_count = 0;
if (snd_BUG_ON(!conn_list || max_conns <= 0))
return -EINVAL;
parm = get_num_conns(codec, nid); parm = get_num_conns(codec, nid);
if (!parm) if (!parm)
return 0; return 0;
...@@ -545,7 +542,8 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, ...@@ -545,7 +542,8 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
AC_VERB_GET_CONNECT_LIST, 0); AC_VERB_GET_CONNECT_LIST, 0);
if (parm == -1 && codec->bus->rirb_error) if (parm == -1 && codec->bus->rirb_error)
return -EIO; return -EIO;
conn_list[0] = parm & mask; if (conn_list)
conn_list[0] = parm & mask;
return 1; return 1;
} }
...@@ -580,14 +578,20 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid, ...@@ -580,14 +578,20 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
continue; continue;
} }
for (n = prev_nid + 1; n <= val; n++) { for (n = prev_nid + 1; n <= val; n++) {
if (conn_list) {
if (conns >= max_conns)
return -ENOSPC;
conn_list[conns] = n;
}
conns++;
}
} else {
if (conn_list) {
if (conns >= max_conns) if (conns >= max_conns)
return -ENOSPC; return -ENOSPC;
conn_list[conns++] = n; conn_list[conns] = val;
} }
} else { conns++;
if (conns >= max_conns)
return -ENOSPC;
conn_list[conns++] = val;
} }
prev_nid = val; prev_nid = val;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment