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 56 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 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 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 166 TEST(pcmtest, CheckAudioDir) { 167 pcms = getPcmNodes(); 168 ASSERT_GT(pcms, 0); 169 } 170 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 178 TEST(pcmtest, CheckPcmSanity0) { 179 ASSERT_NE(0, pcms); 180 } 181 182 TEST(pcmtest, CheckPcmSanity1) { 183 EXPECT_NE(1, pcms % 2); 184 } 185 186 TEST(pcmtests, CheckMixerSanity) { 187 ASSERT_NE(0, mixers); 188 ASSERT_EQ(mixers, cards); 189 } 190 191 TEST(pcmtest, CheckTimesSanity0) { 192 ASSERT_NE(0, timers); 193 } 194 195 TEST(pcmtest, CheckTimesSanity1) { 196 EXPECT_EQ(1, timers); 197 } 198 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 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 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