188447a05SGarrett D'Amore /* 288447a05SGarrett D'Amore * CDDL HEADER START 388447a05SGarrett D'Amore * 488447a05SGarrett D'Amore * The contents of this file are subject to the terms of the 588447a05SGarrett D'Amore * Common Development and Distribution License (the "License"). 688447a05SGarrett D'Amore * You may not use this file except in compliance with the License. 788447a05SGarrett D'Amore * 888447a05SGarrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 988447a05SGarrett D'Amore * or http://www.opensolaris.org/os/licensing. 1088447a05SGarrett D'Amore * See the License for the specific language governing permissions 1188447a05SGarrett D'Amore * and limitations under the License. 1288447a05SGarrett D'Amore * 1388447a05SGarrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each 1488447a05SGarrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1588447a05SGarrett D'Amore * If applicable, add the following below this CDDL HEADER, with the 1688447a05SGarrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying 1788447a05SGarrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner] 1888447a05SGarrett D'Amore * 1988447a05SGarrett D'Amore * CDDL HEADER END 2088447a05SGarrett D'Amore */ 2188447a05SGarrett D'Amore /* 2288447a05SGarrett D'Amore * Copyright (C) 4Front Technologies 1996-2008. 2388447a05SGarrett D'Amore * 24*a33ad26eSZhao Edgar Liu - Sun Microsystems * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 2588447a05SGarrett D'Amore */ 2688447a05SGarrett D'Amore /* 2788447a05SGarrett D'Amore * This program is a general purpose test facility for audio output. 2888447a05SGarrett D'Amore * It does not test record. 2988447a05SGarrett D'Amore * 3088447a05SGarrett D'Amore * The wavedata.c and wavedata.h files contain the actual samples compressed 3188447a05SGarrett D'Amore * using the MS ADPCM algorithm. 3288447a05SGarrett D'Amore */ 3388447a05SGarrett D'Amore 3488447a05SGarrett D'Amore #include <stdio.h> 3588447a05SGarrett D'Amore #include <stdlib.h> 3688447a05SGarrett D'Amore #include <unistd.h> 3788447a05SGarrett D'Amore #include <fcntl.h> 3888447a05SGarrett D'Amore #include <string.h> 3988447a05SGarrett D'Amore #include <errno.h> 4088447a05SGarrett D'Amore #include <unistd.h> 4188447a05SGarrett D'Amore #include <sys/time.h> 4288447a05SGarrett D'Amore #include <sys/ioctl.h> 4388447a05SGarrett D'Amore #include <sys/utsname.h> 4488447a05SGarrett D'Amore #include <sys/soundcard.h> 4588447a05SGarrett D'Amore #include <inttypes.h> 4688447a05SGarrett D'Amore #include <locale.h> 4788447a05SGarrett D'Amore 4888447a05SGarrett D'Amore #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 4988447a05SGarrett D'Amore #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 5088447a05SGarrett D'Amore #endif 5188447a05SGarrett D'Amore 5288447a05SGarrett D'Amore #define _(s) gettext(s) 5388447a05SGarrett D'Amore 5488447a05SGarrett D'Amore /* 5588447a05SGarrett D'Amore * Channel selectors 5688447a05SGarrett D'Amore */ 5788447a05SGarrett D'Amore #define CH_LEFT (1 << 0) 5888447a05SGarrett D'Amore #define CH_RIGHT (1 << 1) 5988447a05SGarrett D'Amore #define CH_LREAR4 (1 << 2) /* quadraphonic */ 6088447a05SGarrett D'Amore #define CH_RREAR4 (1 << 3) /* quadraphonic */ 6188447a05SGarrett D'Amore #define CH_CENTER (1 << 2) 6288447a05SGarrett D'Amore #define CH_LFE (1 << 3) 6388447a05SGarrett D'Amore #define CH_LSURR (1 << 4) 6488447a05SGarrett D'Amore #define CH_RSURR (1 << 5) 6588447a05SGarrett D'Amore #define CH_LREAR (1 << 6) 6688447a05SGarrett D'Amore #define CH_RREAR (1 << 7) 6788447a05SGarrett D'Amore #define CH_STEREO (CH_LEFT|CH_RIGHT) 6888447a05SGarrett D'Amore #define CH_4 (CH_STEREO | CH_LREAR4 | CH_RREAR4) 6988447a05SGarrett D'Amore #define CH_5 (CH_STEREO | CH_CENTER | CH_LSURR | CH_RSURR) 7088447a05SGarrett D'Amore #define CH_7 (CH_5 | CH_LREAR | CH_RREAR) 7188447a05SGarrett D'Amore 7288447a05SGarrett D'Amore typedef struct chancfg { 7388447a05SGarrett D'Amore int mask; 7488447a05SGarrett D'Amore const char *name; 7588447a05SGarrett D'Amore unsigned flags; 7688447a05SGarrett D'Amore int16_t *data; 7788447a05SGarrett D'Amore int len; 7888447a05SGarrett D'Amore } chancfg_t; 7988447a05SGarrett D'Amore 8088447a05SGarrett D'Amore typedef struct testcfg { 8188447a05SGarrett D'Amore int nchan; 82*a33ad26eSZhao Edgar Liu - Sun Microsystems uint32_t rate; 8388447a05SGarrett D'Amore chancfg_t *tests[16]; 8488447a05SGarrett D'Amore } testcfg_t; 8588447a05SGarrett D'Amore 8688447a05SGarrett D'Amore #define CFLAG_LFE 0x1 /* lfe channel - not full range */ 8788447a05SGarrett D'Amore 8888447a05SGarrett D'Amore /* 8988447a05SGarrett D'Amore * TRANSLATION_NOTE : The following strings are displayed during progress. 9088447a05SGarrett D'Amore * Its important for alignment that they have the same displayed length. 9188447a05SGarrett D'Amore */ 9288447a05SGarrett D'Amore #define NM_LEFT "\t<left> ................" 9388447a05SGarrett D'Amore #define NM_RIGHT "\t<right> ..............." 9488447a05SGarrett D'Amore #define NM_LREAR "\t<left rear> ..........." 9588447a05SGarrett D'Amore #define NM_RREAR "\t<right rear> .........." 9688447a05SGarrett D'Amore #define NM_LSIDE "\t<left side> ..........." 9788447a05SGarrett D'Amore #define NM_RSIDE "\t<right side> .........." 9888447a05SGarrett D'Amore #define NM_CENTER "\t<center> .............." 9988447a05SGarrett D'Amore #define NM_LFE "\t<lfe> ................." 10088447a05SGarrett D'Amore #define NM_STEREO "\t<stereo> .............." 10188447a05SGarrett D'Amore #define NM_40 "\t<4.0 surround> ........" 10288447a05SGarrett D'Amore #define NM_50 "\t<5.0 surround> ........" 10388447a05SGarrett D'Amore #define NM_70 "\t<7.0 surround> ........" 10488447a05SGarrett D'Amore 10588447a05SGarrett D'Amore chancfg_t ch_left = { CH_LEFT, NM_LEFT, 0 }; 10688447a05SGarrett D'Amore chancfg_t ch_right = { CH_RIGHT, NM_RIGHT, 0 }; 10788447a05SGarrett D'Amore chancfg_t ch_stereo = { CH_STEREO, NM_STEREO, 0 }; 10888447a05SGarrett D'Amore 10988447a05SGarrett D'Amore chancfg_t ch_center = { CH_CENTER, NM_CENTER, 0 }; 11088447a05SGarrett D'Amore chancfg_t ch_lfe = { CH_LFE, NM_LFE, CFLAG_LFE }; 11188447a05SGarrett D'Amore 11288447a05SGarrett D'Amore chancfg_t ch_lsurr_4 = { (1 << 2), NM_LREAR, 0 }; 11388447a05SGarrett D'Amore chancfg_t ch_rsurr_4 = { (1 << 3), NM_RREAR, 0 }; 11488447a05SGarrett D'Amore chancfg_t ch_4 = { CH_4, NM_40, 0 }; 11588447a05SGarrett D'Amore 11688447a05SGarrett D'Amore chancfg_t ch_lsurr_5 = { CH_LSURR, NM_LREAR, 0 }; 11788447a05SGarrett D'Amore chancfg_t ch_rsurr_5 = { CH_RSURR, NM_RREAR, 0 }; 11888447a05SGarrett D'Amore chancfg_t ch_5 = { CH_5, NM_50, 0 }; 11988447a05SGarrett D'Amore 12088447a05SGarrett D'Amore chancfg_t ch_lsurr_7 = { CH_LSURR, NM_LSIDE, 0 }; 12188447a05SGarrett D'Amore chancfg_t ch_rsurr_7 = { CH_RSURR, NM_RSIDE, 0 }; 12288447a05SGarrett D'Amore chancfg_t ch_lrear_7 = { CH_LREAR, NM_LREAR, 0 }; 12388447a05SGarrett D'Amore chancfg_t ch_rrear_7 = { CH_RREAR, NM_RREAR, 0 }; 12488447a05SGarrett D'Amore chancfg_t ch_7 = { CH_7, NM_70, 0 }; 12588447a05SGarrett D'Amore 12688447a05SGarrett D'Amore testcfg_t test_stereo = { 127*a33ad26eSZhao Edgar Liu - Sun Microsystems 2, 48000, { &ch_left, &ch_right, &ch_stereo, NULL } 12888447a05SGarrett D'Amore }; 12988447a05SGarrett D'Amore 13088447a05SGarrett D'Amore testcfg_t test_quad = { 131*a33ad26eSZhao Edgar Liu - Sun Microsystems 4, 48000, { &ch_left, &ch_right, &ch_stereo, 13288447a05SGarrett D'Amore &ch_lsurr_4, &ch_rsurr_4, &ch_4, NULL } 13388447a05SGarrett D'Amore }; 13488447a05SGarrett D'Amore 13588447a05SGarrett D'Amore testcfg_t test_51 = { 136*a33ad26eSZhao Edgar Liu - Sun Microsystems 6, 48000, { &ch_left, &ch_right, &ch_stereo, 13788447a05SGarrett D'Amore &ch_lsurr_5, &ch_rsurr_5, &ch_center, &ch_lfe, &ch_5, NULL } 13888447a05SGarrett D'Amore }; 13988447a05SGarrett D'Amore 14088447a05SGarrett D'Amore testcfg_t test_71 = { 141*a33ad26eSZhao Edgar Liu - Sun Microsystems 8, 48000, { &ch_left, &ch_right, &ch_stereo, 14288447a05SGarrett D'Amore &ch_lsurr_7, &ch_rsurr_7, &ch_lrear_7, &ch_rrear_7, 14388447a05SGarrett D'Amore &ch_center, &ch_lfe, &ch_7, NULL } 14488447a05SGarrett D'Amore }; 14588447a05SGarrett D'Amore 14688447a05SGarrett D'Amore /* 14788447a05SGarrett D'Amore * uncompress_wave() is defined in wavedata.c. It expands the audio 14888447a05SGarrett D'Amore * samples stored in wavedata.h and returns the lenghth of the 14988447a05SGarrett D'Amore * uncompressed version in bytes. 15088447a05SGarrett D'Amore * 15188447a05SGarrett D'Amore * The uncompressed wave data format is 16 bit (native) stereo 15288447a05SGarrett D'Amore * recorded at 48000 Hz. 15388447a05SGarrett D'Amore */ 15488447a05SGarrett D'Amore extern int uncompress_wave(short *outbuf); 15588447a05SGarrett D'Amore 15688447a05SGarrett D'Amore static int data_len; 15788447a05SGarrett D'Amore 15888447a05SGarrett D'Amore #define MAXDEVICE 64 15988447a05SGarrett D'Amore extern void describe_error(int); 16088447a05SGarrett D'Amore 16188447a05SGarrett D'Amore #define SAMPLE_RATE 48000 16288447a05SGarrett D'Amore 16388447a05SGarrett D'Amore /* 16488447a05SGarrett D'Amore * Operating mode flags (set from the command line). 16588447a05SGarrett D'Amore */ 16688447a05SGarrett D'Amore #define TF_LOOP 0x00000010 /* Loop until interrupted */ 16788447a05SGarrett D'Amore 16888447a05SGarrett D'Amore static int mixerfd; 16988447a05SGarrett D'Amore static int num_devices_tested = 0; 17088447a05SGarrett D'Amore 17188447a05SGarrett D'Amore static short *sample_buf; 17288447a05SGarrett D'Amore 17388447a05SGarrett D'Amore void 17488447a05SGarrett D'Amore prepare(testcfg_t *tcfg) 17588447a05SGarrett D'Amore { 17688447a05SGarrett D'Amore int nsamples; 177*a33ad26eSZhao Edgar Liu - Sun Microsystems int i, j; 17888447a05SGarrett D'Amore chancfg_t *ccfg; 17988447a05SGarrett D'Amore if ((sample_buf = malloc(2000000)) == NULL) { 18088447a05SGarrett D'Amore perror("malloc"); 18188447a05SGarrett D'Amore exit(-1); 18288447a05SGarrett D'Amore } 18388447a05SGarrett D'Amore 18488447a05SGarrett D'Amore data_len = uncompress_wave(sample_buf); 18588447a05SGarrett D'Amore nsamples = (data_len / sizeof (int16_t)) / 2; 18688447a05SGarrett D'Amore 18788447a05SGarrett D'Amore for (i = 0; (ccfg = tcfg->tests[i]) != NULL; i++) { 18888447a05SGarrett D'Amore int16_t *src, *dst; 18988447a05SGarrett D'Amore int ch; 19088447a05SGarrett D'Amore int samp; 191*a33ad26eSZhao Edgar Liu - Sun Microsystems int rate_multiple; 19288447a05SGarrett D'Amore 19388447a05SGarrett D'Amore src = sample_buf; 194*a33ad26eSZhao Edgar Liu - Sun Microsystems rate_multiple = tcfg->rate / 48000; 19588447a05SGarrett D'Amore 19688447a05SGarrett D'Amore if (ccfg->flags != CFLAG_LFE) { 197*a33ad26eSZhao Edgar Liu - Sun Microsystems ccfg->len = nsamples * tcfg->nchan * 198*a33ad26eSZhao Edgar Liu - Sun Microsystems sizeof (int16_t) * rate_multiple; 19988447a05SGarrett D'Amore ccfg->data = malloc(ccfg->len); 20088447a05SGarrett D'Amore if ((dst = ccfg->data) == NULL) { 20188447a05SGarrett D'Amore perror("malloc"); 20288447a05SGarrett D'Amore exit(-1); 20388447a05SGarrett D'Amore } 20488447a05SGarrett D'Amore for (samp = 0; samp < nsamples; samp++) { 20588447a05SGarrett D'Amore for (ch = 0; ch < tcfg->nchan; ch++) { 206*a33ad26eSZhao Edgar Liu - Sun Microsystems for (j = 0; j < rate_multiple; j++) { 207*a33ad26eSZhao Edgar Liu - Sun Microsystems *dst = ((1U << ch) & ccfg->mask) 208*a33ad26eSZhao Edgar Liu - Sun Microsystems ? *src : 0; 20988447a05SGarrett D'Amore dst++; 21088447a05SGarrett D'Amore } 211*a33ad26eSZhao Edgar Liu - Sun Microsystems } 21288447a05SGarrett D'Amore src += 2; 21388447a05SGarrett D'Amore } 21488447a05SGarrett D'Amore } else { 21588447a05SGarrett D'Amore /* Skip LFE for now */ 21688447a05SGarrett D'Amore ccfg->len = 0; 21788447a05SGarrett D'Amore } 21888447a05SGarrett D'Amore } 21988447a05SGarrett D'Amore } 22088447a05SGarrett D'Amore 22188447a05SGarrett D'Amore /* 22288447a05SGarrett D'Amore * The testdsp() routine checks the capabilities of a given audio device number 22388447a05SGarrett D'Amore * (parameter n) and decides if the test sound needs to be played. 22488447a05SGarrett D'Amore */ 22588447a05SGarrett D'Amore 22688447a05SGarrett D'Amore /*ARGSUSED*/ 22788447a05SGarrett D'Amore int 22888447a05SGarrett D'Amore testdsp(int hd, int flags, testcfg_t *tcfg) 22988447a05SGarrett D'Amore { 23088447a05SGarrett D'Amore float ratio; 23188447a05SGarrett D'Amore struct timeval t1, t2; 23288447a05SGarrett D'Amore unsigned long t; 23388447a05SGarrett D'Amore int sample_rate; 23488447a05SGarrett D'Amore int delay; 23588447a05SGarrett D'Amore long long total_bytes = 0; 23688447a05SGarrett D'Amore unsigned int tmp, caps; 23788447a05SGarrett D'Amore int i; 23888447a05SGarrett D'Amore chancfg_t *ccfg; 23988447a05SGarrett D'Amore 24088447a05SGarrett D'Amore caps = 0; 24188447a05SGarrett D'Amore if (ioctl(hd, SNDCTL_DSP_GETCAPS, &caps) == -1) { 24288447a05SGarrett D'Amore perror("SNDCTL_DSP_GETCAPS"); 24388447a05SGarrett D'Amore return (-1); 24488447a05SGarrett D'Amore } 24588447a05SGarrett D'Amore 24688447a05SGarrett D'Amore /* 24788447a05SGarrett D'Amore * Setup the sample format. Since OSS will support AFMT_S16_NE 24888447a05SGarrett D'Amore * regardless of the device we do not need to support any 24988447a05SGarrett D'Amore * other formats. 25088447a05SGarrett D'Amore */ 25188447a05SGarrett D'Amore tmp = AFMT_S16_NE; 25288447a05SGarrett D'Amore if (ioctl(hd, SNDCTL_DSP_SETFMT, &tmp) == -1 || tmp != AFMT_S16_NE) { 25388447a05SGarrett D'Amore (void) printf(_("Device doesn't support native 16-bit PCM\n")); 25488447a05SGarrett D'Amore return (-1); 25588447a05SGarrett D'Amore } 25688447a05SGarrett D'Amore 25788447a05SGarrett D'Amore /* 25888447a05SGarrett D'Amore * Setup the device for channels. Once again we can simply 25988447a05SGarrett D'Amore * assume that stereo will always work before OSS takes care 26088447a05SGarrett D'Amore * of this by emulation if necessary. 26188447a05SGarrett D'Amore */ 26288447a05SGarrett D'Amore tmp = tcfg->nchan; 26388447a05SGarrett D'Amore if (ioctl(hd, SNDCTL_DSP_CHANNELS, &tmp) == -1 || tmp != tcfg->nchan) { 26488447a05SGarrett D'Amore (void) printf(_("The device doesn't support %d channels\n"), 26588447a05SGarrett D'Amore tcfg->nchan); 26688447a05SGarrett D'Amore return (-2); 26788447a05SGarrett D'Amore } 26888447a05SGarrett D'Amore 26988447a05SGarrett D'Amore /* 27088447a05SGarrett D'Amore * Set up the sample rate. 27188447a05SGarrett D'Amore */ 272*a33ad26eSZhao Edgar Liu - Sun Microsystems tmp = tcfg->rate; 27388447a05SGarrett D'Amore if (ioctl(hd, SNDCTL_DSP_SPEED, &tmp) == -1) { 27488447a05SGarrett D'Amore perror("SNDCTL_DSP_SPEED"); 27588447a05SGarrett D'Amore return (-3); 27688447a05SGarrett D'Amore } 27788447a05SGarrett D'Amore 27888447a05SGarrett D'Amore sample_rate = tmp; 279*a33ad26eSZhao Edgar Liu - Sun Microsystems if (sample_rate != tcfg->rate) { 28088447a05SGarrett D'Amore (void) printf(_("The device doesn't support %d Hz\n"), 281*a33ad26eSZhao Edgar Liu - Sun Microsystems tcfg->rate); 28288447a05SGarrett D'Amore return (-3); 28388447a05SGarrett D'Amore } 28488447a05SGarrett D'Amore (void) printf("\n"); 28588447a05SGarrett D'Amore 28688447a05SGarrett D'Amore /* 28788447a05SGarrett D'Amore * This program will measure the real sampling rate by 28888447a05SGarrett D'Amore * computing the total time required to play the sample. 28988447a05SGarrett D'Amore * 29088447a05SGarrett D'Amore * This is not terribly presice with short test sounds but it 29188447a05SGarrett D'Amore * can be used to detect if the sampling rate badly 29288447a05SGarrett D'Amore * wrong. Errors of few percents is more likely to be caused 29388447a05SGarrett D'Amore * by poor accuracy of the system clock rather than problems 29488447a05SGarrett D'Amore * with the sampling rate. 29588447a05SGarrett D'Amore */ 29688447a05SGarrett D'Amore (void) gettimeofday(&t1, NULL); 29788447a05SGarrett D'Amore 29888447a05SGarrett D'Amore for (i = 0; (ccfg = tcfg->tests[i]) != NULL; i++) { 29988447a05SGarrett D'Amore (void) fputs(_(ccfg->name), stdout); 30088447a05SGarrett D'Amore (void) fflush(stdout); 30188447a05SGarrett D'Amore if (ccfg->flags & CFLAG_LFE) { 30288447a05SGarrett D'Amore (void) printf(_("SKIPPED\n")); 30388447a05SGarrett D'Amore continue; 30488447a05SGarrett D'Amore } 30588447a05SGarrett D'Amore 30688447a05SGarrett D'Amore if (write(hd, ccfg->data, ccfg->len) < 0) { 30788447a05SGarrett D'Amore (void) printf(_("ERROR: %s\n"), 30888447a05SGarrett D'Amore strerror(errno)); 30988447a05SGarrett D'Amore return (-3); 31088447a05SGarrett D'Amore } 31188447a05SGarrett D'Amore (void) printf(_("OK\n")); 31288447a05SGarrett D'Amore total_bytes += ccfg->len; 31388447a05SGarrett D'Amore } 31488447a05SGarrett D'Amore 31588447a05SGarrett D'Amore (void) gettimeofday(&t2, NULL); 31688447a05SGarrett D'Amore delay = 0; 31788447a05SGarrett D'Amore (void) ioctl(hd, SNDCTL_DSP_GETODELAY, &delay); /* Ignore errors */ 31888447a05SGarrett D'Amore 31988447a05SGarrett D'Amore /* 32088447a05SGarrett D'Amore * Perform the time computations using milliseconds. 32188447a05SGarrett D'Amore */ 32288447a05SGarrett D'Amore 32388447a05SGarrett D'Amore t = t2.tv_sec - t1.tv_sec; 32488447a05SGarrett D'Amore t *= 1000; 32588447a05SGarrett D'Amore 32688447a05SGarrett D'Amore t += t2.tv_usec / 1000; 32788447a05SGarrett D'Amore t -= t1.tv_usec / 1000; 32888447a05SGarrett D'Amore 32988447a05SGarrett D'Amore total_bytes -= delay; 33088447a05SGarrett D'Amore total_bytes *= 1000; 33188447a05SGarrett D'Amore 33288447a05SGarrett D'Amore total_bytes /= t; 33388447a05SGarrett D'Amore total_bytes /= (tcfg->nchan * sizeof (int16_t)); 33488447a05SGarrett D'Amore 33588447a05SGarrett D'Amore ratio = ((float)total_bytes / (float)sample_rate) * 100.0; 33688447a05SGarrett D'Amore (void) printf(_("\t<measured sample rate %8.2f Hz (%4.2f%%)>\n"), 33788447a05SGarrett D'Amore (float)sample_rate * ratio / 100.0, ratio - 100.0); 33888447a05SGarrett D'Amore num_devices_tested++; 33988447a05SGarrett D'Amore 34088447a05SGarrett D'Amore return (1); 34188447a05SGarrett D'Amore } 34288447a05SGarrett D'Amore 34388447a05SGarrett D'Amore static int 34488447a05SGarrett D'Amore find_num_devices(void) 34588447a05SGarrett D'Amore { 34688447a05SGarrett D'Amore oss_sysinfo info; 34788447a05SGarrett D'Amore struct utsname un; 34888447a05SGarrett D'Amore /* 34988447a05SGarrett D'Amore * Find out the number of available audio devices by calling 35088447a05SGarrett D'Amore * SNDCTL_SYSINFO. 35188447a05SGarrett D'Amore */ 35288447a05SGarrett D'Amore 35388447a05SGarrett D'Amore if (ioctl(mixerfd, SNDCTL_SYSINFO, &info) == -1) { 35488447a05SGarrett D'Amore if (errno == ENXIO) { 35588447a05SGarrett D'Amore (void) fprintf(stderr, 35688447a05SGarrett D'Amore _("No supported sound hardware detected.\n")); 35788447a05SGarrett D'Amore exit(-1); 35888447a05SGarrett D'Amore } else { 35988447a05SGarrett D'Amore perror("SNDCTL_SYSINFO"); 36088447a05SGarrett D'Amore (void) printf(_("Cannot get system information.\n")); 36188447a05SGarrett D'Amore exit(-1); 36288447a05SGarrett D'Amore } 36388447a05SGarrett D'Amore } 36488447a05SGarrett D'Amore (void) printf(_("Sound subsystem and version: %s %s (0x%08X)\n"), 36588447a05SGarrett D'Amore info.product, info.version, info.versionnum); 36688447a05SGarrett D'Amore 36788447a05SGarrett D'Amore if (uname(&un) != -1) 36888447a05SGarrett D'Amore (void) printf(_("Platform: %s %s %s %s\n"), 36988447a05SGarrett D'Amore un.sysname, un.release, un.version, un.machine); 37088447a05SGarrett D'Amore 37188447a05SGarrett D'Amore return (info.numaudios); 37288447a05SGarrett D'Amore } 37388447a05SGarrett D'Amore 37488447a05SGarrett D'Amore /* 37588447a05SGarrett D'Amore * The test_device() routine checks certain information about the device 37688447a05SGarrett D'Amore * and calls testdsp() to play the test sound. 37788447a05SGarrett D'Amore */ 37888447a05SGarrett D'Amore 37988447a05SGarrett D'Amore int 38088447a05SGarrett D'Amore test_device(char *dn, int flags, testcfg_t *tcfg) 38188447a05SGarrett D'Amore { 38288447a05SGarrett D'Amore oss_audioinfo ainfo; 38388447a05SGarrett D'Amore int code; 38488447a05SGarrett D'Amore int fd; 38588447a05SGarrett D'Amore 38688447a05SGarrett D'Amore fd = open(dn, O_WRONLY, 0); 38788447a05SGarrett D'Amore if (fd == -1) { 38888447a05SGarrett D'Amore int err = errno; 38988447a05SGarrett D'Amore perror(dn); 39088447a05SGarrett D'Amore errno = err; 39188447a05SGarrett D'Amore describe_error(errno); 39268c47f65SGarrett D'Amore return (-1); 39388447a05SGarrett D'Amore } 39488447a05SGarrett D'Amore 39588447a05SGarrett D'Amore ainfo.dev = -1; 39688447a05SGarrett D'Amore if (ioctl(fd, SNDCTL_AUDIOINFO, &ainfo) == -1) { 39788447a05SGarrett D'Amore perror("SNDCTL_AUDIOINFO"); 39888447a05SGarrett D'Amore (void) close(fd); 39968c47f65SGarrett D'Amore return (-1); 40088447a05SGarrett D'Amore } 40188447a05SGarrett D'Amore 40288447a05SGarrett D'Amore (void) printf(_("\n*** Scanning sound adapter #%d ***\n"), 40388447a05SGarrett D'Amore ainfo.card_number); 40488447a05SGarrett D'Amore 40588447a05SGarrett D'Amore (void) printf(_("%s (audio engine %d): %s\n"), ainfo.devnode, ainfo.dev, 40688447a05SGarrett D'Amore ainfo.name); 40788447a05SGarrett D'Amore 40888447a05SGarrett D'Amore if (!ainfo.enabled) { 40988447a05SGarrett D'Amore (void) printf(_(" - Device not present - Skipping\n")); 41088447a05SGarrett D'Amore (void) close(fd); 41168c47f65SGarrett D'Amore return (0); 41288447a05SGarrett D'Amore } 41388447a05SGarrett D'Amore 41488447a05SGarrett D'Amore if (!(ainfo.caps & PCM_CAP_OUTPUT)) { 41588447a05SGarrett D'Amore (void) printf(_(" - Skipping input only device\n")); 41688447a05SGarrett D'Amore (void) close(fd); 41768c47f65SGarrett D'Amore return (0); 41888447a05SGarrett D'Amore } 41988447a05SGarrett D'Amore 42088447a05SGarrett D'Amore (void) printf(_(" - Performing audio playback test... ")); 42188447a05SGarrett D'Amore (void) fflush(stdout); 42288447a05SGarrett D'Amore 42388447a05SGarrett D'Amore code = testdsp(fd, flags, tcfg); 42488447a05SGarrett D'Amore (void) close(fd); 42568c47f65SGarrett D'Amore if (code < 0) { 42668c47f65SGarrett D'Amore return (code); 42768c47f65SGarrett D'Amore } 42888447a05SGarrett D'Amore 42988447a05SGarrett D'Amore return (code == 1); 43088447a05SGarrett D'Amore } 43188447a05SGarrett D'Amore 43288447a05SGarrett D'Amore void 43388447a05SGarrett D'Amore describe_error(int err) 43488447a05SGarrett D'Amore { 43588447a05SGarrett D'Amore switch (err) { 43688447a05SGarrett D'Amore case ENODEV: 43788447a05SGarrett D'Amore (void) fprintf(stderr, 43888447a05SGarrett D'Amore _("The device file was found in /dev but\n" 43988447a05SGarrett D'Amore "the driver was not loaded.\n")); 44088447a05SGarrett D'Amore break; 44188447a05SGarrett D'Amore 44288447a05SGarrett D'Amore case ENXIO: 44388447a05SGarrett D'Amore (void) fprintf(stderr, 44488447a05SGarrett D'Amore _("There are no sound devices available.\n" 44588447a05SGarrett D'Amore "The most likely reason is that the device you have\n" 44688447a05SGarrett D'Amore "is malfunctioning or it's not supported.\n" 44788447a05SGarrett D'Amore "It's also possible that you are trying to use the wrong " 44888447a05SGarrett D'Amore "device file.\n")); 44988447a05SGarrett D'Amore break; 45088447a05SGarrett D'Amore 45188447a05SGarrett D'Amore case ENOSPC: 45288447a05SGarrett D'Amore (void) fprintf(stderr, 45388447a05SGarrett D'Amore _("Your system cannot allocate memory for the device\n" 45488447a05SGarrett D'Amore "buffers. Reboot your machine and try again.\n")); 45588447a05SGarrett D'Amore break; 45688447a05SGarrett D'Amore 45788447a05SGarrett D'Amore case ENOENT: 45888447a05SGarrett D'Amore (void) fprintf(stderr, 45988447a05SGarrett D'Amore _("The device file is missing from /dev.\n")); 46088447a05SGarrett D'Amore break; 46188447a05SGarrett D'Amore 46288447a05SGarrett D'Amore 46388447a05SGarrett D'Amore case EBUSY: 46488447a05SGarrett D'Amore (void) fprintf(stderr, 46588447a05SGarrett D'Amore _("The device is busy. There is some other application\n" 46688447a05SGarrett D'Amore "using it.\n")); 46788447a05SGarrett D'Amore break; 46888447a05SGarrett D'Amore 46988447a05SGarrett D'Amore default: 47088447a05SGarrett D'Amore break; 47188447a05SGarrett D'Amore } 47288447a05SGarrett D'Amore } 47388447a05SGarrett D'Amore 47488447a05SGarrett D'Amore int 47588447a05SGarrett D'Amore main(int argc, char *argv[]) 47688447a05SGarrett D'Amore { 47788447a05SGarrett D'Amore int t, i; 47888447a05SGarrett D'Amore int maxdev; 47988447a05SGarrett D'Amore int flags = 0; 48088447a05SGarrett D'Amore int status = 0; 48168c47f65SGarrett D'Amore int errors = 0; 48288447a05SGarrett D'Amore int numdev; 48388447a05SGarrett D'Amore extern int optind; 48488447a05SGarrett D'Amore testcfg_t *tcfg; 48588447a05SGarrett D'Amore 48688447a05SGarrett D'Amore (void) setlocale(LC_ALL, ""); 48788447a05SGarrett D'Amore (void) textdomain(TEXT_DOMAIN); 48888447a05SGarrett D'Amore 48988447a05SGarrett D'Amore tcfg = &test_stereo; 49088447a05SGarrett D'Amore 49188447a05SGarrett D'Amore /* 49288447a05SGarrett D'Amore * Simple command line switch handling. 49388447a05SGarrett D'Amore */ 49488447a05SGarrett D'Amore 495*a33ad26eSZhao Edgar Liu - Sun Microsystems while ((i = getopt(argc, argv, "l2457r:")) != EOF) { 49688447a05SGarrett D'Amore switch (i) { 49788447a05SGarrett D'Amore case 'l': 49888447a05SGarrett D'Amore flags |= TF_LOOP; 49988447a05SGarrett D'Amore break; 50088447a05SGarrett D'Amore case '2': 50188447a05SGarrett D'Amore tcfg = &test_stereo; 50288447a05SGarrett D'Amore break; 50388447a05SGarrett D'Amore case '4': 50488447a05SGarrett D'Amore tcfg = &test_quad; 50588447a05SGarrett D'Amore break; 50688447a05SGarrett D'Amore case '5': 50788447a05SGarrett D'Amore tcfg = &test_51; 50888447a05SGarrett D'Amore break; 50988447a05SGarrett D'Amore case '7': 51088447a05SGarrett D'Amore tcfg = &test_71; 51188447a05SGarrett D'Amore break; 512*a33ad26eSZhao Edgar Liu - Sun Microsystems case 'r': 513*a33ad26eSZhao Edgar Liu - Sun Microsystems tcfg->rate = atoi(optarg); 514*a33ad26eSZhao Edgar Liu - Sun Microsystems break; 51588447a05SGarrett D'Amore default: 51688447a05SGarrett D'Amore (void) printf(_("Usage: %s [options...] [device]\n" 51788447a05SGarrett D'Amore " -2 Stereo test\n" 51888447a05SGarrett D'Amore " -4 Quadraphonic 4.0 test\n" 51988447a05SGarrett D'Amore " -5 Surround 5.1 test\n" 52088447a05SGarrett D'Amore " -7 Surround 7.1 test\n" 521*a33ad26eSZhao Edgar Liu - Sun Microsystems " -r Sample Rate (48000|96000|192000)\n" 52288447a05SGarrett D'Amore " -l Loop test\n"), argv[0]); 52388447a05SGarrett D'Amore exit(-1); 52488447a05SGarrett D'Amore } 52588447a05SGarrett D'Amore } 52688447a05SGarrett D'Amore 52788447a05SGarrett D'Amore /* 52888447a05SGarrett D'Amore * Open the mixer device used for calling SNDCTL_SYSINFO and 52988447a05SGarrett D'Amore * SNDCTL_AUDIOINFO. 53088447a05SGarrett D'Amore */ 53188447a05SGarrett D'Amore if ((mixerfd = open("/dev/mixer", O_RDWR, 0)) == -1) { 53288447a05SGarrett D'Amore int err = errno; 53388447a05SGarrett D'Amore perror("/dev/mixer"); 53488447a05SGarrett D'Amore errno = err; 53588447a05SGarrett D'Amore describe_error(errno); 53688447a05SGarrett D'Amore exit(-1); 53788447a05SGarrett D'Amore } 53888447a05SGarrett D'Amore 53988447a05SGarrett D'Amore prepare(tcfg); /* Prepare the wave data */ 54088447a05SGarrett D'Amore 54188447a05SGarrett D'Amore /* 54288447a05SGarrett D'Amore * Enumerate all devices and play the test sounds. 54388447a05SGarrett D'Amore */ 54488447a05SGarrett D'Amore maxdev = find_num_devices(); 54588447a05SGarrett D'Amore if (maxdev < 1) { 54688447a05SGarrett D'Amore (void) printf(_("\n*** No audio hardware available ***\n")); 54788447a05SGarrett D'Amore exit(-1); 54888447a05SGarrett D'Amore } 54988447a05SGarrett D'Amore 55088447a05SGarrett D'Amore numdev = (argc - optind); 55188447a05SGarrett D'Amore do { 55288447a05SGarrett D'Amore char *dn; 55388447a05SGarrett D'Amore oss_audioinfo ainfo; 55468c47f65SGarrett D'Amore int rv; 55588447a05SGarrett D'Amore 55668c47f65SGarrett D'Amore status = 0; 55788447a05SGarrett D'Amore if (numdev > 0) { 55888447a05SGarrett D'Amore for (t = 0; t < numdev; t++) { 55988447a05SGarrett D'Amore dn = argv[optind + t]; 56068c47f65SGarrett D'Amore rv = test_device(dn, flags, tcfg); 56168c47f65SGarrett D'Amore if (rv < 0) { 56268c47f65SGarrett D'Amore errors++; 56368c47f65SGarrett D'Amore } else if (rv) { 56488447a05SGarrett D'Amore status++; 56588447a05SGarrett D'Amore } 56668c47f65SGarrett D'Amore } 56788447a05SGarrett D'Amore } else { 56888447a05SGarrett D'Amore for (t = 0; t < maxdev; t++) { 56988447a05SGarrett D'Amore ainfo.dev = t; 57088447a05SGarrett D'Amore if (ioctl(mixerfd, SNDCTL_AUDIOINFO, 57188447a05SGarrett D'Amore &ainfo) == -1) { 57288447a05SGarrett D'Amore perror("SNDCTL_AUDIOINFO"); 57388447a05SGarrett D'Amore status++; 57488447a05SGarrett D'Amore continue; 57588447a05SGarrett D'Amore } 57688447a05SGarrett D'Amore dn = ainfo.devnode; 57768c47f65SGarrett D'Amore rv = test_device(dn, flags, tcfg); 57868c47f65SGarrett D'Amore if (rv < 0) { 57968c47f65SGarrett D'Amore errors++; 58068c47f65SGarrett D'Amore } else if (rv) { 58188447a05SGarrett D'Amore status++; 58288447a05SGarrett D'Amore } 58388447a05SGarrett D'Amore } 58468c47f65SGarrett D'Amore } 58588447a05SGarrett D'Amore 58668c47f65SGarrett D'Amore if (errors == 0) 58788447a05SGarrett D'Amore (void) printf(_("\n*** All tests completed OK ***\n")); 58888447a05SGarrett D'Amore else 58988447a05SGarrett D'Amore (void) printf(_("\n*** Errors were detected ***\n")); 59088447a05SGarrett D'Amore 59168c47f65SGarrett D'Amore } while (status && (flags & TF_LOOP)); 59288447a05SGarrett D'Amore 59388447a05SGarrett D'Amore (void) close(mixerfd); 59488447a05SGarrett D'Amore 59588447a05SGarrett D'Amore return (status); 59688447a05SGarrett D'Amore } 597