alsa_conformance_test: Print the name of the card

Print the name of the card which the device belongs to.

BUG=b:155008270
TEST=Run alsa_conformance_test and check the result

Change-Id: Ie0dda76323a4bb8baf0e8a7e8b88eae592d3c422
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/audiotest/+/2166865
Reviewed-by: Cheng-Yi Chiang <cychiang@chromium.org>
Tested-by: Yu-Hsuan Hsu <yuhsuan@chromium.org>
Commit-Queue: Yu-Hsuan Hsu <yuhsuan@chromium.org>
diff --git a/alsa_conformance_test.md b/alsa_conformance_test.md
index 9e4170a..d501faf 100644
--- a/alsa_conformance_test.md
+++ b/alsa_conformance_test.md
@@ -119,6 +119,8 @@
 ```
 ---------PRINT PARAMS---------
 PCM name: hw:0,0
+card: acpd7219m98357 [acpd7219m98357]
+device: Playback da7219-hifi-0 []
 stream: PLAYBACK
 access type: MMAP_INTERLEAVED
 format: S16_LE
@@ -364,6 +366,7 @@
 11 passed, 0 failed
 Device Information
         Name: hw:0,0
+        Card: sof-glkda7219max
         Stream: PLAYBACK
         Format: ['S16_LE', 'S32_LE']
         Channels: [2]
diff --git a/alsa_conformance_test/alsa_conformance_helper.c b/alsa_conformance_test/alsa_conformance_helper.c
index 325ec53..45cfbdb 100644
--- a/alsa_conformance_test/alsa_conformance_helper.c
+++ b/alsa_conformance_test/alsa_conformance_helper.c
@@ -10,23 +10,74 @@
 #include "alsa_conformance_helper.h"
 #include "alsa_conformance_timer.h"
 
-/* Print device information before setting params */
+void print_card_information(snd_pcm_info_t *pcm_info,
+			    snd_ctl_card_info_t *card_info)
+{
+	printf("card: %s [%s]\n", snd_ctl_card_info_get_id(card_info),
+	       snd_ctl_card_info_get_name(card_info));
+	printf("device: %s [%s]\n", snd_pcm_info_get_id(pcm_info),
+	       snd_pcm_info_get_name(pcm_info));
+}
+
+int alsa_helper_get_card_info(snd_pcm_t *handle, snd_pcm_info_t *pcm_info,
+			      snd_ctl_card_info_t *card_info)
+{
+	int card_idx;
+	char name[32];
+	snd_ctl_t *ctl_handle = NULL;
+	int rc;
+
+	assert(pcm_info);
+	assert(card_info);
+	rc = snd_pcm_info(handle, pcm_info);
+	if (rc < 0) {
+		fprintf(stderr, "snd_pcm_info: %s\n", snd_strerror(rc));
+		return rc;
+	}
+
+	card_idx = snd_pcm_info_get_card(pcm_info);
+	sprintf(name, "hw:%d", card_idx);
+
+	rc = snd_ctl_open(&ctl_handle, name, 0);
+	if (rc < 0) {
+		fprintf(stderr, "snd_ctl_open: %s\n", snd_strerror(rc));
+		return rc;
+	}
+
+	rc = snd_ctl_card_info(ctl_handle, card_info);
+	if (rc < 0) {
+		fprintf(stderr, "snd_ctl_card_info: %s\n", snd_strerror(rc));
+		return rc;
+	}
+
+	return 0;
+}
+
 int print_device_information(snd_pcm_t *handle, snd_pcm_hw_params_t *params)
 {
 	unsigned int min;
 	unsigned int max;
 	unsigned int i;
 	/* The min2 and max2 are for period size and buffer size. The type of
-     * snd_pcm_uframes_t is unsigned long.*/
+	 * snd_pcm_uframes_t is unsigned long.*/
 	snd_pcm_uframes_t min2;
 	snd_pcm_uframes_t max2;
 	int dir;
 	int rc;
+	snd_pcm_info_t *pcm_info;
+	snd_ctl_card_info_t *card_info;
 
 	printf("PCM handle name: %s\n", snd_pcm_name(handle));
 
 	printf("PCM type: %s\n", snd_pcm_type_name(snd_pcm_type(handle)));
 
+	snd_pcm_info_malloc(&pcm_info);
+	snd_ctl_card_info_malloc(&card_info);
+	alsa_helper_get_card_info(handle, pcm_info, card_info);
+	print_card_information(pcm_info, card_info);
+	snd_ctl_card_info_free(card_info);
+	snd_pcm_info_free(pcm_info);
+
 	printf("stream: %s\n", snd_pcm_stream_name(snd_pcm_stream(handle)));
 
 	rc = snd_pcm_hw_params_get_channels_min(params, &min);
diff --git a/alsa_conformance_test/alsa_conformance_helper.h b/alsa_conformance_test/alsa_conformance_helper.h
index 4f91231..ba7ca55 100644
--- a/alsa_conformance_test/alsa_conformance_helper.h
+++ b/alsa_conformance_test/alsa_conformance_helper.h
@@ -10,6 +10,29 @@
 #include <alsa/asoundlib.h>
 #include "alsa_conformance_timer.h"
 
+/*
+ * Print card information.
+ * Args:
+ *    pcm_info - The pointer storing pcm information.
+ *    card_info - The pointer storing card information.
+ * Prints to stdout:
+ *    card name - The name of the card.
+ */
+void print_card_information(snd_pcm_info_t *pcm_info,
+			    snd_ctl_card_info_t *card_info);
+
+/*
+ * Get card information from the device.
+ * Args:
+ *    handle - The open PCM to configure.
+ *    pcm_info - The allocated pointer to store the pcm information.
+ *    card_info - The allocated pointer to store the card information.
+ * Returns:
+ *    0 on success, negative error on failure.
+ */
+int alsa_helper_get_card_info(snd_pcm_t *handle, snd_pcm_info_t *pcm_info,
+			      snd_ctl_card_info_t *card_info);
+
 /* Print device information.
  * Args:
  *    handle - The open PCM to configure.
diff --git a/alsa_conformance_test/alsa_conformance_thread.c b/alsa_conformance_test/alsa_conformance_thread.c
index 4805dd5..79bef76 100644
--- a/alsa_conformance_test/alsa_conformance_thread.c
+++ b/alsa_conformance_test/alsa_conformance_thread.c
@@ -23,6 +23,8 @@
 	snd_pcm_t *handle;
 	snd_pcm_hw_params_t *params;
 	snd_pcm_hw_params_t *params_record;
+	snd_pcm_info_t *pcm_info;
+	snd_ctl_card_info_t *card_info;
 
 	char *dev_name;
 	snd_pcm_stream_t stream;
@@ -60,6 +62,8 @@
 	thread->handle = NULL;
 	thread->params = NULL;
 	thread->params_record = NULL;
+	thread->pcm_info = NULL;
+	thread->card_info = NULL;
 	thread->dev_name = NULL;
 	thread->underrun_count = 0;
 	thread->overrun_count = 0;
@@ -77,6 +81,8 @@
 void dev_thread_destroy(struct dev_thread *thread)
 {
 	snd_pcm_hw_params_free(thread->params_record);
+	snd_pcm_info_free(thread->pcm_info);
+	snd_ctl_card_info_free(thread->card_info);
 	conformance_timer_destroy(thread->timer);
 	recorder_list_destroy(thread->recorder_list);
 	free(thread->dev_name);
@@ -157,6 +163,14 @@
 			      thread->dev_name, thread->stream);
 	if (rc < 0)
 		exit(EXIT_FAILURE);
+
+	/* Records pcm_info and card_info to show it on the result. */
+	if (thread->pcm_info == NULL)
+		snd_pcm_info_malloc(&thread->pcm_info);
+	if (thread->card_info == NULL)
+		snd_ctl_card_info_malloc(&thread->card_info);
+	alsa_helper_get_card_info(thread->handle, thread->pcm_info,
+				  thread->card_info);
 }
 
 /* Close device. */
@@ -566,6 +580,7 @@
 	int rc;
 	assert(thread->params_record);
 	printf("PCM name: %s\n", thread->dev_name);
+	print_card_information(thread->pcm_info, thread->card_info);
 	printf("stream: %s\n", snd_pcm_stream_name(thread->stream));
 	printf("merge_threshold_t: %lf\n", thread->merge_threshold_t);
 	printf("merge_threshold_sz: %ld\n", thread->merge_threshold_sz);
diff --git a/script/alsa_conformance_test.py b/script/alsa_conformance_test.py
index f95dee6..b4d62fc 100755
--- a/script/alsa_conformance_test.py
+++ b/script/alsa_conformance_test.py
@@ -18,8 +18,8 @@
 Range = collections.namedtuple('Range', ['lower', 'upper'])
 
 DataDevInfo = collections.namedtuple('DataDevInfo', [
-    'name', 'stream', 'valid_formats', 'valid_rates', 'valid_channels',
-    'period_size_range', 'buffer_size_range'
+    'name', 'card', 'device', 'stream', 'valid_formats', 'valid_rates',
+    'valid_channels', 'period_size_range', 'buffer_size_range'
 ])
 
 DataParams = collections.namedtuple('DataParams', [
@@ -195,6 +195,8 @@
           ------DEVICE INFORMATION------
           PCM handle name: hw:0,0
           PCM type: HW
+          card: CardID [CardName]
+          device: DeviceID [DeviceName]
           stream: PLAYBACK
           available range: 1, 2
           available formats: S16_LE S32_LE
@@ -207,6 +209,7 @@
       Result
           DataDevInfo(
               name='hw:0,0',
+              card='soundcard',
               stream='PLAYBACK',
               valid_formats=['S16_LE', 'S32_LE'],
               valid_channels=['1', '2'],
@@ -225,6 +228,8 @@
 
     return DataDevInfo(
         self._get_value('PCM handle name'),
+        self._get_value('card'),
+        self._get_value('device'),
         self._get_value('stream'),
         self._get_list('available formats'),
         list(map(int, self._get_list('available rates'))),
@@ -407,6 +412,8 @@
     """Prints device information."""
     print('Device Information')
     print('\tName:', self.dev_info.name)
+    print('\tCard:', self.dev_info.card)
+    print('\tDevice:', self.dev_info.device)
     print('\tStream:', self.dev_info.stream)
     print('\tFormat:', self.dev_info.valid_formats)
     print('\tChannels:', self.dev_info.valid_channels)