Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5f82b10 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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
Loading
Loading
Loading
Loading
+14 −10
Original line number Diff line number Diff line
@@ -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)
{
	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,
	hda_nid_t prev_nid;
	int null_count = 0;

	if (snd_BUG_ON(!conn_list || max_conns <= 0))
		return -EINVAL;

	parm = get_num_conns(codec, nid);
	if (!parm)
		return 0;
@@ -545,6 +542,7 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
					  AC_VERB_GET_CONNECT_LIST, 0);
		if (parm == -1 && codec->bus->rirb_error)
			return -EIO;
		if (conn_list)
			conn_list[0] = parm & mask;
		return 1;
	}
@@ -580,14 +578,20 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
				continue;
			}
			for (n = prev_nid + 1; n <= val; n++) {
				if (conn_list) {
					if (conns >= max_conns)
						return -ENOSPC;
				conn_list[conns++] = n;
					conn_list[conns] = n;
				}
				conns++;
			}
		} else {
			if (conn_list) {
				if (conns >= max_conns)
					return -ENOSPC;
			conn_list[conns++] = val;
				conn_list[conns] = val;
			}
			conns++;
		}
		prev_nid = val;
	}