diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-09-08 08:30:49 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-09-08 08:46:49 -0400 |
commit | 9b151fec139d32ab3acce5da5761d868e205fadd (patch) | |
tree | 2793cabf9420d2a3b8f8026cab4cc1386f0f04b6 /sound/drivers/dummy.c | |
parent | 4f7454a9970fa0f3e9f1a68201520e3df1bb5224 (diff) |
ALSA: dummy - Add debug proc file
Added the debug proc file to see or change the snd_pcm_hardware fields
to emulate. The parameters can be changed by writing to a proc file like:
# echo periods_min 4 > /proc/asound/card1/dummy_pcm
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/drivers/dummy.c')
-rw-r--r-- | sound/drivers/dummy.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 2ee6c8ebe25a..ccfbdfa75511 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <sound/tlv.h> | 33 | #include <sound/tlv.h> |
34 | #include <sound/pcm.h> | 34 | #include <sound/pcm.h> |
35 | #include <sound/rawmidi.h> | 35 | #include <sound/rawmidi.h> |
36 | #include <sound/info.h> | ||
36 | #include <sound/initval.h> | 37 | #include <sound/initval.h> |
37 | 38 | ||
38 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 39 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
@@ -686,6 +687,10 @@ static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, | |||
686 | return 0; | 687 | return 0; |
687 | } | 688 | } |
688 | 689 | ||
690 | /* | ||
691 | * mixer interface | ||
692 | */ | ||
693 | |||
689 | #define DUMMY_VOLUME(xname, xindex, addr) \ | 694 | #define DUMMY_VOLUME(xname, xindex, addr) \ |
690 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 695 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
691 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ | 696 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ |
@@ -816,6 +821,131 @@ static int __devinit snd_card_dummy_new_mixer(struct snd_dummy *dummy) | |||
816 | return 0; | 821 | return 0; |
817 | } | 822 | } |
818 | 823 | ||
824 | #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_PROC_FS) | ||
825 | /* | ||
826 | * proc interface | ||
827 | */ | ||
828 | static void print_formats(struct snd_info_buffer *buffer) | ||
829 | { | ||
830 | int i; | ||
831 | |||
832 | for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) { | ||
833 | if (dummy_pcm_hardware.formats & (1ULL << i)) | ||
834 | snd_iprintf(buffer, " %s", snd_pcm_format_name(i)); | ||
835 | } | ||
836 | } | ||
837 | |||
838 | static void print_rates(struct snd_info_buffer *buffer) | ||
839 | { | ||
840 | static int rates[] = { | ||
841 | 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, | ||
842 | 64000, 88200, 96000, 176400, 192000, | ||
843 | }; | ||
844 | int i; | ||
845 | |||
846 | if (dummy_pcm_hardware.rates & SNDRV_PCM_RATE_CONTINUOUS) | ||
847 | snd_iprintf(buffer, " continuous"); | ||
848 | if (dummy_pcm_hardware.rates & SNDRV_PCM_RATE_KNOT) | ||
849 | snd_iprintf(buffer, " knot"); | ||
850 | for (i = 0; i < ARRAY_SIZE(rates); i++) | ||
851 | if (dummy_pcm_hardware.rates & (1 << i)) | ||
852 | snd_iprintf(buffer, " %d", rates[i]); | ||
853 | } | ||
854 | |||
855 | #define get_dummy_int_ptr(ofs) \ | ||
856 | (unsigned int *)((char *)&dummy_pcm_hardware + (ofs)) | ||
857 | #define get_dummy_ll_ptr(ofs) \ | ||
858 | (unsigned long long *)((char *)&dummy_pcm_hardware + (ofs)) | ||
859 | |||
860 | struct dummy_hw_field { | ||
861 | const char *name; | ||
862 | const char *format; | ||
863 | unsigned int offset; | ||
864 | unsigned int size; | ||
865 | }; | ||
866 | #define FIELD_ENTRY(item, fmt) { \ | ||
867 | .name = #item, \ | ||
868 | .format = fmt, \ | ||
869 | .offset = offsetof(struct snd_pcm_hardware, item), \ | ||
870 | .size = sizeof(dummy_pcm_hardware.item) } | ||
871 | |||
872 | static struct dummy_hw_field fields[] = { | ||
873 | FIELD_ENTRY(formats, "%#llx"), | ||
874 | FIELD_ENTRY(rates, "%#x"), | ||
875 | FIELD_ENTRY(rate_min, "%d"), | ||
876 | FIELD_ENTRY(rate_max, "%d"), | ||
877 | FIELD_ENTRY(channels_min, "%d"), | ||
878 | FIELD_ENTRY(channels_max, "%d"), | ||
879 | FIELD_ENTRY(buffer_bytes_max, "%ld"), | ||
880 | FIELD_ENTRY(period_bytes_min, "%ld"), | ||
881 | FIELD_ENTRY(period_bytes_max, "%ld"), | ||
882 | FIELD_ENTRY(periods_min, "%d"), | ||
883 | FIELD_ENTRY(periods_max, "%d"), | ||
884 | }; | ||
885 | |||
886 | static void dummy_proc_read(struct snd_info_entry *entry, | ||
887 | struct snd_info_buffer *buffer) | ||
888 | { | ||
889 | int i; | ||
890 | |||
891 | for (i = 0; i < ARRAY_SIZE(fields); i++) { | ||
892 | snd_iprintf(buffer, "%s ", fields[i].name); | ||
893 | if (fields[i].size == sizeof(int)) | ||
894 | snd_iprintf(buffer, fields[i].format, | ||
895 | *get_dummy_int_ptr(fields[i].offset)); | ||
896 | else | ||
897 | snd_iprintf(buffer, fields[i].format, | ||
898 | *get_dummy_ll_ptr(fields[i].offset)); | ||
899 | if (!strcmp(fields[i].name, "formats")) | ||
900 | print_formats(buffer); | ||
901 | else if (!strcmp(fields[i].name, "rates")) | ||
902 | print_rates(buffer); | ||
903 | snd_iprintf(buffer, "\n"); | ||
904 | } | ||
905 | } | ||
906 | |||
907 | static void dummy_proc_write(struct snd_info_entry *entry, | ||
908 | struct snd_info_buffer *buffer) | ||
909 | { | ||
910 | char line[64]; | ||
911 | |||
912 | while (!snd_info_get_line(buffer, line, sizeof(line))) { | ||
913 | char item[20]; | ||
914 | const char *ptr; | ||
915 | unsigned long long val; | ||
916 | int i; | ||
917 | |||
918 | ptr = snd_info_get_str(item, line, sizeof(item)); | ||
919 | for (i = 0; i < ARRAY_SIZE(fields); i++) { | ||
920 | if (!strcmp(item, fields[i].name)) | ||
921 | break; | ||
922 | } | ||
923 | if (i >= ARRAY_SIZE(fields)) | ||
924 | continue; | ||
925 | snd_info_get_str(item, ptr, sizeof(item)); | ||
926 | if (strict_strtoull(item, 0, &val)) | ||
927 | continue; | ||
928 | if (fields[i].size == sizeof(int)) | ||
929 | *get_dummy_int_ptr(fields[i].offset) = val; | ||
930 | else | ||
931 | *get_dummy_ll_ptr(fields[i].offset) = val; | ||
932 | } | ||
933 | } | ||
934 | |||
935 | static void __devinit dummy_proc_init(struct snd_dummy *chip) | ||
936 | { | ||
937 | struct snd_info_entry *entry; | ||
938 | |||
939 | if (!snd_card_proc_new(chip->card, "dummy_pcm", &entry)) { | ||
940 | snd_info_set_text_ops(entry, chip, dummy_proc_read); | ||
941 | entry->c.text.write = dummy_proc_write; | ||
942 | entry->mode |= S_IWUSR; | ||
943 | } | ||
944 | } | ||
945 | #else | ||
946 | #define dummy_proc_init(x) | ||
947 | #endif /* CONFIG_SND_DEBUG && CONFIG_PROC_FS */ | ||
948 | |||
819 | static int __devinit snd_dummy_probe(struct platform_device *devptr) | 949 | static int __devinit snd_dummy_probe(struct platform_device *devptr) |
820 | { | 950 | { |
821 | struct snd_card *card; | 951 | struct snd_card *card; |
@@ -845,6 +975,8 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr) | |||
845 | strcpy(card->shortname, "Dummy"); | 975 | strcpy(card->shortname, "Dummy"); |
846 | sprintf(card->longname, "Dummy %i", dev + 1); | 976 | sprintf(card->longname, "Dummy %i", dev + 1); |
847 | 977 | ||
978 | dummy_proc_init(dummy); | ||
979 | |||
848 | snd_card_set_dev(card, &devptr->dev); | 980 | snd_card_set_dev(card, &devptr->dev); |
849 | 981 | ||
850 | err = snd_card_register(card); | 982 | err = snd_card_register(card); |