diff options
author | Andy Hung | 2014-03-26 20:29:07 -0500 |
---|---|---|
committer | Andy Hung | 2014-03-26 20:29:07 -0500 |
commit | 70530a69767a9a383c5bf546e6e803aac08a5a1e (patch) | |
tree | 71ae738911eb35f036d480145a96eb8ea411e4d6 | |
parent | a5b44d9bba0c5df52b37850bb929eb53817fb4a4 (diff) | |
download | platform-external-tinyalsa-70530a69767a9a383c5bf546e6e803aac08a5a1e.tar.gz platform-external-tinyalsa-70530a69767a9a383c5bf546e6e803aac08a5a1e.tar.xz platform-external-tinyalsa-70530a69767a9a383c5bf546e6e803aac08a5a1e.zip |
Add pcm_params string conversion and format checking
Change-Id: I93415bd1a88ff0feaf14af3daf48e00dd1990176
Signed-off-by: Andy Hung <hunga@google.com>
-rw-r--r-- | include/tinyalsa/asoundlib.h | 17 | ||||
-rw-r--r-- | pcm.c | 159 |
2 files changed, 175 insertions, 1 deletions
diff --git a/include/tinyalsa/asoundlib.h b/include/tinyalsa/asoundlib.h index 03e3c13..1083dba 100644 --- a/include/tinyalsa/asoundlib.h +++ b/include/tinyalsa/asoundlib.h | |||
@@ -158,12 +158,27 @@ struct pcm_params *pcm_params_get(unsigned int card, unsigned int device, | |||
158 | void pcm_params_free(struct pcm_params *pcm_params); | 158 | void pcm_params_free(struct pcm_params *pcm_params); |
159 | 159 | ||
160 | struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params, | 160 | struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params, |
161 | enum pcm_param param); | 161 | enum pcm_param param); |
162 | unsigned int pcm_params_get_min(struct pcm_params *pcm_params, | 162 | unsigned int pcm_params_get_min(struct pcm_params *pcm_params, |
163 | enum pcm_param param); | 163 | enum pcm_param param); |
164 | unsigned int pcm_params_get_max(struct pcm_params *pcm_params, | 164 | unsigned int pcm_params_get_max(struct pcm_params *pcm_params, |
165 | enum pcm_param param); | 165 | enum pcm_param param); |
166 | 166 | ||
167 | /* Converts the pcm parameters to a human readable string. | ||
168 | * The string parameter is a caller allocated buffer of size bytes, | ||
169 | * which is then filled up to size - 1 and null terminated, | ||
170 | * if size is greater than zero. | ||
171 | * The return value is the number of bytes copied to string | ||
172 | * (not including null termination) if less than size; otherwise, | ||
173 | * the number of bytes required for the buffer. | ||
174 | */ | ||
175 | int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size); | ||
176 | |||
177 | /* Returns 1 if the pcm_format is present (format bit set) in | ||
178 | * the pcm_params structure; 0 otherwise, or upon unrecognized format. | ||
179 | */ | ||
180 | int pcm_params_format_test(struct pcm_params *params, enum pcm_format format); | ||
181 | |||
167 | /* Set and get config */ | 182 | /* Set and get config */ |
168 | int pcm_get_config(struct pcm *pcm, struct pcm_config *config); | 183 | int pcm_get_config(struct pcm *pcm, struct pcm_config *config); |
169 | int pcm_set_config(struct pcm *pcm, struct pcm_config *config); | 184 | int pcm_set_config(struct pcm *pcm, struct pcm_config *config); |
@@ -51,6 +51,84 @@ | |||
51 | #define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL | 51 | #define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL |
52 | #define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) | 52 | #define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2) |
53 | 53 | ||
54 | /* Logs information into a string; follows snprintf() in that | ||
55 | * offset may be greater than size, and though no characters are copied | ||
56 | * into string, characters are still counted into offset. */ | ||
57 | #define STRLOG(string, offset, size, ...) \ | ||
58 | do { int temp, clipoffset = offset > size ? size : offset; \ | ||
59 | temp = snprintf(string + clipoffset, size - clipoffset, __VA_ARGS__); \ | ||
60 | if (temp > 0) offset += temp; } while (0) | ||
61 | |||
62 | #ifndef ARRAY_SIZE | ||
63 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) | ||
64 | #endif | ||
65 | |||
66 | /* refer to SNDRV_PCM_ACCESS_##index in sound/asound.h. */ | ||
67 | static const char * const access_lookup[] = { | ||
68 | "MMAP_INTERLEAVED", | ||
69 | "MMAP_NONINTERLEAVED", | ||
70 | "MMAP_COMPLEX", | ||
71 | "RW_INTERLEAVED", | ||
72 | "RW_NONINTERLEAVED", | ||
73 | }; | ||
74 | |||
75 | /* refer to SNDRV_PCM_FORMAT_##index in sound/asound.h. */ | ||
76 | static const char * const format_lookup[] = { | ||
77 | /*[0] =*/ "S8", | ||
78 | "U8", | ||
79 | "S16_LE", | ||
80 | "S16_BE", | ||
81 | "U16_LE", | ||
82 | "U16_BE", | ||
83 | "S24_LE", | ||
84 | "S24_BE", | ||
85 | "U24_LE", | ||
86 | "U24_BE", | ||
87 | "S32_LE", | ||
88 | "S32_BE", | ||
89 | "U32_LE", | ||
90 | "U32_BE", | ||
91 | "FLOAT_LE", | ||
92 | "FLOAT_BE", | ||
93 | "FLOAT64_LE", | ||
94 | "FLOAT64_BE", | ||
95 | "IEC958_SUBFRAME_LE", | ||
96 | "IEC958_SUBFRAME_BE", | ||
97 | "MU_LAW", | ||
98 | "A_LAW", | ||
99 | "IMA_ADPCM", | ||
100 | "MPEG", | ||
101 | /*[24] =*/ "GSM", | ||
102 | /* gap */ | ||
103 | [31] = "SPECIAL", | ||
104 | "S24_3LE", | ||
105 | "S24_3BE", | ||
106 | "U24_3LE", | ||
107 | "U24_3BE", | ||
108 | "S20_3LE", | ||
109 | "S20_3BE", | ||
110 | "U20_3LE", | ||
111 | "U20_3BE", | ||
112 | "S18_3LE", | ||
113 | "S18_3BE", | ||
114 | "U18_3LE", | ||
115 | /*[43] =*/ "U18_3BE", | ||
116 | #if 0 | ||
117 | /* recent additions, may not be present on local asound.h */ | ||
118 | "G723_24", | ||
119 | "G723_24_1B", | ||
120 | "G723_40", | ||
121 | "G723_40_1B", | ||
122 | "DSD_U8", | ||
123 | "DSD_U16_LE", | ||
124 | #endif | ||
125 | }; | ||
126 | |||
127 | /* refer to SNDRV_PCM_SUBFORMAT_##index in sound/asound.h. */ | ||
128 | static const char * const subformat_lookup[] = { | ||
129 | "STD", | ||
130 | }; | ||
131 | |||
54 | static inline int param_is_mask(int p) | 132 | static inline int param_is_mask(int p) |
55 | { | 133 | { |
56 | return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && | 134 | return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) && |
@@ -611,6 +689,87 @@ unsigned int pcm_params_get_max(struct pcm_params *pcm_params, | |||
611 | return param_get_max(params, p); | 689 | return param_get_max(params, p); |
612 | } | 690 | } |
613 | 691 | ||
692 | static int pcm_mask_test(struct pcm_mask *m, unsigned int index) | ||
693 | { | ||
694 | const unsigned int bitshift = 5; /* for 32 bit integer */ | ||
695 | const unsigned int bitmask = (1 << bitshift) - 1; | ||
696 | unsigned int element; | ||
697 | |||
698 | element = index >> bitshift; | ||
699 | if (element >= ARRAY_SIZE(m->bits)) | ||
700 | return 0; /* for safety, but should never occur */ | ||
701 | return (m->bits[element] >> (index & bitmask)) & 1; | ||
702 | } | ||
703 | |||
704 | static int pcm_mask_to_string(struct pcm_mask *m, char *string, unsigned int size, | ||
705 | char *mask_name, | ||
706 | const char * const *bit_array_name, size_t bit_array_size) | ||
707 | { | ||
708 | unsigned int i; | ||
709 | unsigned int offset = 0; | ||
710 | |||
711 | if (m == NULL) | ||
712 | return 0; | ||
713 | if (bit_array_size < 32) { | ||
714 | STRLOG(string, offset, size, "%12s:\t%#08x\n", mask_name, m->bits[0]); | ||
715 | } else { /* spans two or more bitfields, print with an array index */ | ||
716 | for (i = 0; i < (bit_array_size + 31) >> 5; ++i) { | ||
717 | STRLOG(string, offset, size, "%9s[%d]:\t%#08x\n", | ||
718 | mask_name, i, m->bits[i]); | ||
719 | } | ||
720 | } | ||
721 | for (i = 0; i < bit_array_size; ++i) { | ||
722 | if (pcm_mask_test(m, i)) { | ||
723 | STRLOG(string, offset, size, "%12s \t%s\n", "", bit_array_name[i]); | ||
724 | } | ||
725 | } | ||
726 | return offset; | ||
727 | } | ||
728 | |||
729 | int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size) | ||
730 | { | ||
731 | struct pcm_mask *m; | ||
732 | unsigned int min, max; | ||
733 | unsigned int clipoffset, offset; | ||
734 | |||
735 | m = pcm_params_get_mask(params, PCM_PARAM_ACCESS); | ||
736 | offset = pcm_mask_to_string(m, string, size, | ||
737 | "Access", access_lookup, ARRAY_SIZE(access_lookup)); | ||
738 | m = pcm_params_get_mask(params, PCM_PARAM_FORMAT); | ||
739 | clipoffset = offset > size ? size : offset; | ||
740 | offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset, | ||
741 | "Format", format_lookup, ARRAY_SIZE(format_lookup)); | ||
742 | m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT); | ||
743 | clipoffset = offset > size ? size : offset; | ||
744 | offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset, | ||
745 | "Subformat", subformat_lookup, ARRAY_SIZE(subformat_lookup)); | ||
746 | min = pcm_params_get_min(params, PCM_PARAM_RATE); | ||
747 | max = pcm_params_get_max(params, PCM_PARAM_RATE); | ||
748 | STRLOG(string, offset, size, " Rate:\tmin=%uHz\tmax=%uHz\n", min, max); | ||
749 | min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); | ||
750 | max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); | ||
751 | STRLOG(string, offset, size, " Channels:\tmin=%u\t\tmax=%u\n", min, max); | ||
752 | min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); | ||
753 | max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); | ||
754 | STRLOG(string, offset, size, " Sample bits:\tmin=%u\t\tmax=%u\n", min, max); | ||
755 | min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE); | ||
756 | max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE); | ||
757 | STRLOG(string, offset, size, " Period size:\tmin=%u\t\tmax=%u\n", min, max); | ||
758 | min = pcm_params_get_min(params, PCM_PARAM_PERIODS); | ||
759 | max = pcm_params_get_max(params, PCM_PARAM_PERIODS); | ||
760 | STRLOG(string, offset, size, "Period count:\tmin=%u\t\tmax=%u\n", min, max); | ||
761 | return offset; | ||
762 | } | ||
763 | |||
764 | int pcm_params_format_test(struct pcm_params *params, enum pcm_format format) | ||
765 | { | ||
766 | unsigned int alsa_format = pcm_format_to_alsa(format); | ||
767 | |||
768 | if (alsa_format == SNDRV_PCM_FORMAT_S16_LE && format != PCM_FORMAT_S16_LE) | ||
769 | return 0; /* caution: format not recognized is equivalent to S16_LE */ | ||
770 | return pcm_mask_test(pcm_params_get_mask(params, PCM_PARAM_FORMAT), alsa_format); | ||
771 | } | ||
772 | |||
614 | int pcm_close(struct pcm *pcm) | 773 | int pcm_close(struct pcm *pcm) |
615 | { | 774 | { |
616 | if (pcm == &bad_pcm) | 775 | if (pcm == &bad_pcm) |