struct card_data {
        snd_ctl_t *handle;
        int card;
+       snd_ctl_card_info_t *info;
+       const char *card_name;
        struct pollfd pollfd;
        int num_ctls;
        snd_ctl_elem_list_t *ctls;
                err = snd_card_get_longname(card, &card_longname);
                if (err != 0)
                        card_longname = "Unknown";
-               ksft_print_msg("Card %d - %s (%s)\n", card,
-                              card_name, card_longname);
+
+               err = snd_ctl_card_info_malloc(&card_data->info);
+               if (err != 0)
+                       ksft_exit_fail_msg("Failed to allocate card info: %d\n",
+                               err);
+
+               err = snd_ctl_card_info(card_data->handle, card_data->info);
+               if (err == 0) {
+                       card_data->card_name = snd_ctl_card_info_get_id(card_data->info);
+                       if (!card_data->card_name)
+                               ksft_print_msg("Failed to get card ID\n");
+               } else {
+                       ksft_print_msg("Failed to get card info: %d\n", err);
+               }
+
+               if (!card_data->card_name)
+                       card_data->card_name = "Unknown";
+
+               ksft_print_msg("Card %d/%s - %s (%s)\n", card,
+                              card_data->card_name, card_name, card_longname);
 
                /* Count controls */
                snd_ctl_elem_list_malloc(&card_data->ctls);
        /* If the control is turned off let's be polite */
        if (snd_ctl_elem_info_is_inactive(ctl->info)) {
                ksft_print_msg("%s is inactive\n", ctl->name);
-               ksft_test_result_skip("get_value.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("get_value.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
        /* Can't test reading on an unreadable control */
        if (!snd_ctl_elem_info_is_readable(ctl->info)) {
                ksft_print_msg("%s is not readable\n", ctl->name);
-               ksft_test_result_skip("get_value.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("get_value.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
                err = -EINVAL;
 
 out:
-       ksft_test_result(err >= 0, "get_value.%d.%d\n",
-                        ctl->card->card, ctl->elem);
+       ksft_test_result(err >= 0, "get_value.%s.%d\n",
+                        ctl->card->card_name, ctl->elem);
 }
 
 static bool strend(const char *haystack, const char *needle)
 {
        bool name_ok = true;
 
-       ksft_print_msg("%d.%d %s\n", ctl->card->card, ctl->elem,
+       ksft_print_msg("%s.%d %s\n", ctl->card->card_name, ctl->elem,
                       ctl->name);
 
        /* Only boolean controls should end in Switch */
                }
        }
 
-       ksft_test_result(name_ok, "name.%d.%d\n",
-                        ctl->card->card, ctl->elem);
+       ksft_test_result(name_ok, "name.%s.%d\n",
+                        ctl->card->card_name, ctl->elem);
 }
 
 static void show_values(struct ctl_data *ctl, snd_ctl_elem_value_t *orig_val,
        /* If the control is turned off let's be polite */
        if (snd_ctl_elem_info_is_inactive(ctl->info)) {
                ksft_print_msg("%s is inactive\n", ctl->name);
-               ksft_test_result_skip("write_default.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_default.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
        if (!snd_ctl_elem_info_is_writable(ctl->info)) {
                ksft_print_msg("%s is not writeable\n", ctl->name);
-               ksft_test_result_skip("write_default.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_default.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
        /* No idea what the default was for unreadable controls */
        if (!snd_ctl_elem_info_is_readable(ctl->info)) {
                ksft_print_msg("%s couldn't read default\n", ctl->name);
-               ksft_test_result_skip("write_default.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_default.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
        err = write_and_verify(ctl, ctl->def_val, NULL);
 
-       ksft_test_result(err >= 0, "write_default.%d.%d\n",
-                        ctl->card->card, ctl->elem);
+       ksft_test_result(err >= 0, "write_default.%s.%d\n",
+                        ctl->card->card_name, ctl->elem);
 }
 
 static bool test_ctl_write_valid_boolean(struct ctl_data *ctl)
        /* If the control is turned off let's be polite */
        if (snd_ctl_elem_info_is_inactive(ctl->info)) {
                ksft_print_msg("%s is inactive\n", ctl->name);
-               ksft_test_result_skip("write_valid.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_valid.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
        if (!snd_ctl_elem_info_is_writable(ctl->info)) {
                ksft_print_msg("%s is not writeable\n", ctl->name);
-               ksft_test_result_skip("write_valid.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_valid.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
 
        default:
                /* No tests for this yet */
-               ksft_test_result_skip("write_valid.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_valid.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
        /* Restore the default value to minimise disruption */
        write_and_verify(ctl, ctl->def_val, NULL);
 
-       ksft_test_result(pass, "write_valid.%d.%d\n",
-                        ctl->card->card, ctl->elem);
+       ksft_test_result(pass, "write_valid.%s.%d\n",
+                        ctl->card->card_name, ctl->elem);
 }
 
 static bool test_ctl_write_invalid_value(struct ctl_data *ctl,
        /* If the control is turned off let's be polite */
        if (snd_ctl_elem_info_is_inactive(ctl->info)) {
                ksft_print_msg("%s is inactive\n", ctl->name);
-               ksft_test_result_skip("write_invalid.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_invalid.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
        if (!snd_ctl_elem_info_is_writable(ctl->info)) {
                ksft_print_msg("%s is not writeable\n", ctl->name);
-               ksft_test_result_skip("write_invalid.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_invalid.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
 
        default:
                /* No tests for this yet */
-               ksft_test_result_skip("write_invalid.%d.%d\n",
-                                     ctl->card->card, ctl->elem);
+               ksft_test_result_skip("write_invalid.%s.%d\n",
+                                     ctl->card->card_name, ctl->elem);
                return;
        }
 
        /* Restore the default value to minimise disruption */
        write_and_verify(ctl, ctl->def_val, NULL);
 
-       ksft_test_result(pass, "write_invalid.%d.%d\n",
-                        ctl->card->card, ctl->elem);
+       ksft_test_result(pass, "write_invalid.%s.%d\n",
+                        ctl->card->card_name, ctl->elem);
 }
 
 static void test_ctl_event_missing(struct ctl_data *ctl)
 {
-       ksft_test_result(!ctl->event_missing, "event_missing.%d.%d\n",
-                        ctl->card->card, ctl->elem);
+       ksft_test_result(!ctl->event_missing, "event_missing.%s.%d\n",
+                        ctl->card->card_name, ctl->elem);
 }
 
 static void test_ctl_event_spurious(struct ctl_data *ctl)
 {
-       ksft_test_result(!ctl->event_spurious, "event_spurious.%d.%d\n",
-                        ctl->card->card, ctl->elem);
+       ksft_test_result(!ctl->event_spurious, "event_spurious.%s.%d\n",
+                        ctl->card->card_name, ctl->elem);
 }
 
 int main(void)
 
 
 struct card_data {
        int card;
+       snd_ctl_card_info_t *info;
+       const char *name;
        pthread_t thread;
        struct card_data *next;
 };
        int card;
        int device;
        int subdevice;
+       const char *card_name;
        snd_pcm_stream_t stream;
        snd_config_t *pcm_config;
        struct pcm_data *next;
        config = get_alsalib_config();
 
        while (card >= 0) {
+               card_data = calloc(1, sizeof(*card_data));
+               if (!card_data)
+                       ksft_exit_fail_msg("Out of memory\n");
+
                sprintf(name, "hw:%d", card);
 
                err = snd_ctl_open_lconf(&handle, name, 0, config);
                err = snd_card_get_longname(card, &card_longname);
                if (err != 0)
                        card_longname = "Unknown";
-               ksft_print_msg("Card %d - %s (%s)\n", card,
-                              card_name, card_longname);
+
+               err = snd_ctl_card_info_malloc(&card_data->info);
+               if (err != 0)
+                       ksft_exit_fail_msg("Failed to allocate card info: %d\n",
+                               err);
+
+               err = snd_ctl_card_info(handle, card_data->info);
+               if (err == 0) {
+                       card_data->name = snd_ctl_card_info_get_id(card_data->info);
+                       if (!card_data->name)
+                               ksft_print_msg("Failed to get card ID\n");
+               } else {
+                       ksft_print_msg("Failed to get card info: %d\n", err);
+               }
+
+               if (!card_data->name)
+                       card_data->name = "Unknown";
+
+               ksft_print_msg("Card %d/%s - %s (%s)\n", card,
+                              card_data->name, card_name, card_longname);
 
                card_config = conf_by_card(card);
 
-               card_data = calloc(1, sizeof(*card_data));
-               if (!card_data)
-                       ksft_exit_fail_msg("Out of memory\n");
                card_data->card = card;
                card_data->next = card_list;
                card_list = card_data;
                                        pcm_data->card = card;
                                        pcm_data->device = dev;
                                        pcm_data->subdevice = subdev;
+                                       pcm_data->card_name = card_data->name;
                                        pcm_data->stream = stream;
                                        pcm_data->pcm_config = conf_get_subtree(card_config, key, NULL);
                                        pcm_data->next = pcm_list;
 
        desc = conf_get_string(pcm_cfg, "description", NULL, NULL);
        if (desc)
-               ksft_print_msg("%s.%s.%d.%d.%d.%s - %s\n",
+               ksft_print_msg("%s.%s.%s.%d.%d.%s - %s\n",
                               test_class_name, test_name,
-                              data->card, data->device, data->subdevice,
+                              data->card_name, data->device, data->subdevice,
                               snd_pcm_stream_name(data->stream),
                               desc);
 
                        old_format = format;
                        format = snd_pcm_format_value(alt_formats[i]);
                        if (format != SND_PCM_FORMAT_UNKNOWN) {
-                               ksft_print_msg("%s.%d.%d.%d.%s.%s format %s -> %s\n",
+                               ksft_print_msg("%s.%s.%d.%d.%s.%s format %s -> %s\n",
                                                 test_name,
-                                                data->card, data->device, data->subdevice,
+                                                data->card_name, data->device, data->subdevice,
                                                 snd_pcm_stream_name(data->stream),
                                                 snd_pcm_access_name(access),
                                                 snd_pcm_format_name(old_format),
                goto __close;
        }
 
-       ksft_print_msg("%s.%s.%d.%d.%d.%s hw_params.%s.%s.%ld.%ld.%ld.%ld sw_params.%ld\n",
+       ksft_print_msg("%s.%s.%s.%d.%d.%s hw_params.%s.%s.%ld.%ld.%ld.%ld sw_params.%ld\n",
                         test_class_name, test_name,
-                        data->card, data->device, data->subdevice,
+                        data->card_name, data->device, data->subdevice,
                         snd_pcm_stream_name(data->stream),
                         snd_pcm_access_name(access),
                         snd_pcm_format_name(format),
                 * Anything specified as specific to this system
                 * should always be supported.
                 */
-               ksft_test_result(!skip, "%s.%s.%d.%d.%d.%s.params\n",
+               ksft_test_result(!skip, "%s.%s.%s.%d.%d.%s.params\n",
                                 test_class_name, test_name,
-                                data->card, data->device, data->subdevice,
+                                data->card_name, data->device,
+                                data->subdevice,
                                 snd_pcm_stream_name(data->stream));
                break;
        default:
        }
 
        if (!skip)
-               ksft_test_result(pass, "%s.%s.%d.%d.%d.%s\n",
+               ksft_test_result(pass, "%s.%s.%s.%d.%d.%s\n",
                                 test_class_name, test_name,
-                                data->card, data->device, data->subdevice,
+                                data->card_name, data->device,
+                                data->subdevice,
                                 snd_pcm_stream_name(data->stream));
        else
-               ksft_test_result_skip("%s.%s.%d.%d.%d.%s\n",
+               ksft_test_result_skip("%s.%s.%s.%d.%d.%s\n",
                                 test_class_name, test_name,
-                                data->card, data->device, data->subdevice,
+                                data->card_name, data->device,
+                                data->subdevice,
                                 snd_pcm_stream_name(data->stream));
 
        if (msg[0])
                                              conf->filename, conf->config_id);
 
        for (pcm = pcm_missing; pcm != NULL; pcm = pcm->next) {
-               ksft_test_result(false, "test.missing.%d.%d.%d.%s\n",
-                                pcm->card, pcm->device, pcm->subdevice,
+               ksft_test_result(false, "test.missing.%s.%d.%d.%s\n",
+                                pcm->card_name, pcm->device, pcm->subdevice,
                                 snd_pcm_stream_name(pcm->stream));
        }