1 /*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless requied by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include <assert.h>
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <gtest/gtest.h>
25 #include <linux/ioctl.h>
26 #define __force
27 #define __bitwise
28 #define __user
29 #include <sound/asound.h>
30 #include <sys/types.h>
31 #include <tinyalsa/asoundlib.h>
32
33 #define LOG_TAG "pcmtest"
34 #include <utils/Log.h>
35 #include <testUtil.h>
36
37 #define PCM_PREFIX "pcm"
38 #define MIXER_PREFIX "control"
39 #define TIMER_PREFIX "timer"
40
41 const char kSoundDir[] = "/dev/snd";
42
43 typedef struct PCM_NODE {
44 unsigned int card;
45 unsigned int device;
46 unsigned int flags;
47 } pcm_node_t;
48
49 static pcm_node_t *pcmnodes;
50
51 static unsigned int pcms;
52 static unsigned int cards;
53 static unsigned int mixers;
54 static unsigned int timers;
55
getPcmNodes(void)56 unsigned int getPcmNodes(void)
57 {
58 DIR *d;
59 struct dirent *de;
60 unsigned int pcount = 0;
61
62 d = opendir(kSoundDir);
63 if (d == 0)
64 return 0;
65 while ((de = readdir(d)) != NULL) {
66 if (de->d_name[0] == '.')
67 continue;
68 if (strstr(de->d_name, PCM_PREFIX))
69 pcount++;
70 }
71 closedir(d);
72 return pcount;
73 }
74
getSndDev(unsigned int pcmdevs)75 int getSndDev(unsigned int pcmdevs)
76 {
77 DIR *d;
78 struct dirent *de;
79 unsigned int prevcard = -1;
80
81 d = opendir(kSoundDir);
82 if (d == 0)
83 return -ENXIO;
84 pcmnodes = (pcm_node_t *)malloc(pcmdevs * sizeof(pcm_node_t));
85 if (!pcmnodes)
86 return -ENOMEM;
87 pcms = 0;
88 while ((de = readdir(d)) != NULL) {
89 if (de->d_name[0] == '.')
90 continue;
91 /* printf("%s\n", de->d_name); */
92 if (strstr(de->d_name, PCM_PREFIX)) {
93 char flags;
94
95 EXPECT_LE(pcms, pcmdevs) << "Too many PCMs";
96 if (pcms >= pcmdevs)
97 continue;
98 sscanf(de->d_name, PCM_PREFIX "C%uD%u", &(pcmnodes[pcms].card),
99 &(pcmnodes[pcms].device));
100 flags = de->d_name[strlen(de->d_name)-1];
101 if (flags == 'c') {
102 pcmnodes[pcms].flags = PCM_IN;
103 } else if(flags == 'p') {
104 pcmnodes[pcms].flags = PCM_OUT;
105 } else {
106 pcmnodes[pcms].flags = -1;
107 testPrintI("Unknown PCM type = %c", flags);
108 }
109 if (prevcard != pcmnodes[pcms].card)
110 cards++;
111 prevcard = pcmnodes[pcms].card;
112 pcms++;
113 continue;
114 }
115 if (strstr(de->d_name, MIXER_PREFIX)) {
116 unsigned int mixer = -1;
117 sscanf(de->d_name, MIXER_PREFIX "C%u", &mixer);
118 mixers++;
119 continue;
120 }
121 if (strstr(de->d_name, TIMER_PREFIX)) {
122 timers++;
123 continue;
124 }
125 }
126 closedir(d);
127 return 0;
128 }
129
getPcmParams(unsigned int i)130 int getPcmParams(unsigned int i)
131 {
132 struct pcm_params *params;
133 unsigned int min;
134 unsigned int max;
135
136 params = pcm_params_get(pcmnodes[i].card, pcmnodes[i].device,
137 pcmnodes[i].flags);
138 if (params == NULL)
139 return -ENODEV;
140
141 min = pcm_params_get_min(params, PCM_PARAM_RATE);
142 max = pcm_params_get_max(params, PCM_PARAM_RATE);
143 EXPECT_LE(min, max);
144 /* printf(" Rate:\tmin=%uHz\tmax=%uHz\n", min, max); */
145 min = pcm_params_get_min(params, PCM_PARAM_CHANNELS);
146 max = pcm_params_get_max(params, PCM_PARAM_CHANNELS);
147 EXPECT_LE(min, max);
148 /* printf(" Channels:\tmin=%u\t\tmax=%u\n", min, max); */
149 min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS);
150 max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS);
151 EXPECT_LE(min, max);
152 /* printf(" Sample bits:\tmin=%u\t\tmax=%u\n", min, max); */
153 min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE);
154 max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE);
155 EXPECT_LE(min, max);
156 /* printf(" Period size:\tmin=%u\t\tmax=%u\n", min, max); */
157 min = pcm_params_get_min(params, PCM_PARAM_PERIODS);
158 max = pcm_params_get_max(params, PCM_PARAM_PERIODS);
159 EXPECT_LE(min, max);
160 /* printf("Period count:\tmin=%u\t\tmax=%u\n", min, max); */
161
162 pcm_params_free(params);
163 return 0;
164 }
165
TEST(pcmtest,CheckAudioDir)166 TEST(pcmtest, CheckAudioDir) {
167 pcms = getPcmNodes();
168 ASSERT_GT(pcms, 0U);
169 }
170
TEST(pcmtest,GetSoundDevs)171 TEST(pcmtest, GetSoundDevs) {
172 int err = getSndDev(pcms);
173 testPrintI(" DEVICES = PCMS:%u CARDS:%u MIXERS:%u TIMERS:%u",
174 pcms, cards, mixers, timers);
175 ASSERT_EQ(0, err);
176 }
177
TEST(pcmtest,CheckPcmSanity0)178 TEST(pcmtest, CheckPcmSanity0) {
179 ASSERT_NE(0U, pcms);
180 }
181
TEST(pcmtest,CheckPcmSanity1)182 TEST(pcmtest, CheckPcmSanity1) {
183 EXPECT_NE(1U, pcms % 2);
184 }
185
TEST(pcmtests,CheckMixerSanity)186 TEST(pcmtests, CheckMixerSanity) {
187 ASSERT_NE(0U, mixers);
188 ASSERT_EQ(mixers, cards);
189 }
190
TEST(pcmtest,CheckTimesSanity0)191 TEST(pcmtest, CheckTimesSanity0) {
192 ASSERT_NE(0U, timers);
193 }
194
TEST(pcmtest,CheckTimesSanity1)195 TEST(pcmtest, CheckTimesSanity1) {
196 EXPECT_EQ(1U, timers);
197 }
198
TEST(pcmtest,CheckPcmDevices)199 TEST(pcmtest, CheckPcmDevices) {
200 for (unsigned int i = 0; i < pcms; i++) {
201 EXPECT_EQ(0, getPcmParams(i));
202 }
203 free(pcmnodes);
204 }
205
TEST(pcmtest,CheckMixerDevices)206 TEST(pcmtest, CheckMixerDevices) {
207 struct mixer *mixer;
208 for (unsigned int i = 0; i < mixers; i++) {
209 mixer = mixer_open(i);
210 EXPECT_TRUE(mixer != NULL);
211 if (mixer)
212 mixer_close(mixer);
213 }
214 }
215
TEST(pcmtest,CheckTimer)216 TEST(pcmtest, CheckTimer) {
217 int ver = 0;
218 int fd = open("/dev/snd/timer", O_RDWR | O_NONBLOCK);
219 ASSERT_GE(fd, 0);
220 int ret = ioctl(fd, SNDRV_TIMER_IOCTL_PVERSION, &ver);
221 EXPECT_EQ(0, ret);
222 testPrintI(" Timer Version = 0x%x", ver);
223 close(fd);
224 }
225