Home | History | Annotate | Download | only in alsa
      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