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*68c47f65SGarrett D'Amore * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2588447a05SGarrett D'Amore * Use is subject to license terms. 2688447a05SGarrett D'Amore */ 2788447a05SGarrett D'Amore /* 2888447a05SGarrett D'Amore * This program is a general purpose test facility for audio output. 2988447a05SGarrett D'Amore * It does not test record. 3088447a05SGarrett D'Amore * 3188447a05SGarrett D'Amore * The wavedata.c and wavedata.h files contain the actual samples compressed 3288447a05SGarrett D'Amore * using the MS ADPCM algorithm. 3388447a05SGarrett D'Amore */ 3488447a05SGarrett D'Amore 3588447a05SGarrett D'Amore #include <stdio.h> 3688447a05SGarrett D'Amore #include <stdlib.h> 3788447a05SGarrett D'Amore #include <unistd.h> 3888447a05SGarrett D'Amore #include <fcntl.h> 3988447a05SGarrett D'Amore #include <string.h> 4088447a05SGarrett D'Amore #include <errno.h> 4188447a05SGarrett D'Amore #include <unistd.h> 4288447a05SGarrett D'Amore #include <sys/time.h> 4388447a05SGarrett D'Amore #include <sys/ioctl.h> 4488447a05SGarrett D'Amore #include <sys/utsname.h> 4588447a05SGarrett D'Amore #include <sys/soundcard.h> 4688447a05SGarrett D'Amore #include <inttypes.h> 4788447a05SGarrett D'Amore #include <locale.h> 4888447a05SGarrett D'Amore 4988447a05SGarrett D'Amore #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 5088447a05SGarrett D'Amore #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 5188447a05SGarrett D'Amore #endif 5288447a05SGarrett D'Amore 5388447a05SGarrett D'Amore #define _(s) gettext(s) 5488447a05SGarrett D'Amore 5588447a05SGarrett D'Amore /* 5688447a05SGarrett D'Amore * Channel selectors 5788447a05SGarrett D'Amore */ 5888447a05SGarrett D'Amore #define CH_LEFT (1 << 0) 5988447a05SGarrett D'Amore #define CH_RIGHT (1 << 1) 6088447a05SGarrett D'Amore #define CH_LREAR4 (1 << 2) /* quadraphonic */ 6188447a05SGarrett D'Amore #define CH_RREAR4 (1 << 3) /* quadraphonic */ 6288447a05SGarrett D'Amore #define CH_CENTER (1 << 2) 6388447a05SGarrett D'Amore #define CH_LFE (1 << 3) 6488447a05SGarrett D'Amore #define CH_LSURR (1 << 4) 6588447a05SGarrett D'Amore #define CH_RSURR (1 << 5) 6688447a05SGarrett D'Amore #define CH_LREAR (1 << 6) 6788447a05SGarrett D'Amore #define CH_RREAR (1 << 7) 6888447a05SGarrett D'Amore #define CH_STEREO (CH_LEFT|CH_RIGHT) 6988447a05SGarrett D'Amore #define CH_4 (CH_STEREO | CH_LREAR4 | CH_RREAR4) 7088447a05SGarrett D'Amore #define CH_5 (CH_STEREO | CH_CENTER | CH_LSURR | CH_RSURR) 7188447a05SGarrett D'Amore #define CH_7 (CH_5 | CH_LREAR | CH_RREAR) 7288447a05SGarrett D'Amore 7388447a05SGarrett D'Amore typedef struct chancfg { 7488447a05SGarrett D'Amore int mask; 7588447a05SGarrett D'Amore const char *name; 7688447a05SGarrett D'Amore unsigned flags; 7788447a05SGarrett D'Amore int16_t *data; 7888447a05SGarrett D'Amore int len; 7988447a05SGarrett D'Amore } chancfg_t; 8088447a05SGarrett D'Amore 8188447a05SGarrett D'Amore typedef struct testcfg { 8288447a05SGarrett D'Amore int nchan; 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 = { 12788447a05SGarrett D'Amore 2, { &ch_left, &ch_right, &ch_stereo, NULL } 12888447a05SGarrett D'Amore }; 12988447a05SGarrett D'Amore 13088447a05SGarrett D'Amore testcfg_t test_quad = { 13188447a05SGarrett D'Amore 4, { &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 = { 13688447a05SGarrett D'Amore 6, { &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 = { 14188447a05SGarrett D'Amore 8, { &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; 17788447a05SGarrett D'Amore int i; 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; 19188447a05SGarrett D'Amore 19288447a05SGarrett D'Amore src = sample_buf; 19388447a05SGarrett D'Amore 19488447a05SGarrett D'Amore if (ccfg->flags != CFLAG_LFE) { 19588447a05SGarrett D'Amore ccfg->len = nsamples * tcfg->nchan * sizeof (int16_t); 19688447a05SGarrett D'Amore ccfg->data = malloc(ccfg->len); 19788447a05SGarrett D'Amore if ((dst = ccfg->data) == NULL) { 19888447a05SGarrett D'Amore perror("malloc"); 19988447a05SGarrett D'Amore exit(-1); 20088447a05SGarrett D'Amore } 20188447a05SGarrett D'Amore for (samp = 0; samp < nsamples; samp++) { 20288447a05SGarrett D'Amore for (ch = 0; ch < tcfg->nchan; ch++) { 20388447a05SGarrett D'Amore *dst = ((1U << ch) & ccfg->mask) ? 20488447a05SGarrett D'Amore *src : 0; 20588447a05SGarrett D'Amore dst++; 20688447a05SGarrett D'Amore } 20788447a05SGarrett D'Amore src += 2; 20888447a05SGarrett D'Amore } 20988447a05SGarrett D'Amore } else { 21088447a05SGarrett D'Amore /* Skip LFE for now */ 21188447a05SGarrett D'Amore ccfg->len = 0; 21288447a05SGarrett D'Amore } 21388447a05SGarrett D'Amore } 21488447a05SGarrett D'Amore } 21588447a05SGarrett D'Amore 21688447a05SGarrett D'Amore /* 21788447a05SGarrett D'Amore * The testdsp() routine checks the capabilities of a given audio device number 21888447a05SGarrett D'Amore * (parameter n) and decides if the test sound needs to be played. 21988447a05SGarrett D'Amore */ 22088447a05SGarrett D'Amore 22188447a05SGarrett D'Amore /*ARGSUSED*/ 22288447a05SGarrett D'Amore int 22388447a05SGarrett D'Amore testdsp(int hd, int flags, testcfg_t *tcfg) 22488447a05SGarrett D'Amore { 22588447a05SGarrett D'Amore float ratio; 22688447a05SGarrett D'Amore struct timeval t1, t2; 22788447a05SGarrett D'Amore unsigned long t; 22888447a05SGarrett D'Amore int sample_rate; 22988447a05SGarrett D'Amore int delay; 23088447a05SGarrett D'Amore long long total_bytes = 0; 23188447a05SGarrett D'Amore unsigned int tmp, caps; 23288447a05SGarrett D'Amore int i; 23388447a05SGarrett D'Amore chancfg_t *ccfg; 23488447a05SGarrett D'Amore 23588447a05SGarrett D'Amore caps = 0; 23688447a05SGarrett D'Amore if (ioctl(hd, SNDCTL_DSP_GETCAPS, &caps) == -1) { 23788447a05SGarrett D'Amore perror("SNDCTL_DSP_GETCAPS"); 23888447a05SGarrett D'Amore return (-1); 23988447a05SGarrett D'Amore } 24088447a05SGarrett D'Amore 24188447a05SGarrett D'Amore /* 24288447a05SGarrett D'Amore * Setup the sample format. Since OSS will support AFMT_S16_NE 24388447a05SGarrett D'Amore * regardless of the device we do not need to support any 24488447a05SGarrett D'Amore * other formats. 24588447a05SGarrett D'Amore */ 24688447a05SGarrett D'Amore 24788447a05SGarrett D'Amore tmp = AFMT_S16_NE; 24888447a05SGarrett D'Amore if (ioctl(hd, SNDCTL_DSP_SETFMT, &tmp) == -1 || tmp != AFMT_S16_NE) { 24988447a05SGarrett D'Amore (void) printf(_("Device doesn't support native 16-bit PCM\n")); 25088447a05SGarrett D'Amore return (-1); 25188447a05SGarrett D'Amore } 25288447a05SGarrett D'Amore 25388447a05SGarrett D'Amore /* 25488447a05SGarrett D'Amore * Setup the device for channels. Once again we can simply 25588447a05SGarrett D'Amore * assume that stereo will always work before OSS takes care 25688447a05SGarrett D'Amore * of this by emulation if necessary. 25788447a05SGarrett D'Amore */ 25888447a05SGarrett D'Amore tmp = tcfg->nchan; 25988447a05SGarrett D'Amore if (ioctl(hd, SNDCTL_DSP_CHANNELS, &tmp) == -1 || tmp != tcfg->nchan) { 26088447a05SGarrett D'Amore (void) printf(_("The device doesn't support %d channels\n"), 26188447a05SGarrett D'Amore tcfg->nchan); 26288447a05SGarrett D'Amore return (-2); 26388447a05SGarrett D'Amore } 26488447a05SGarrett D'Amore 26588447a05SGarrett D'Amore /* 26688447a05SGarrett D'Amore * Set up the sample rate. 26788447a05SGarrett D'Amore */ 26888447a05SGarrett D'Amore 26988447a05SGarrett D'Amore tmp = SAMPLE_RATE; 27088447a05SGarrett D'Amore if (ioctl(hd, SNDCTL_DSP_SPEED, &tmp) == -1) { 27188447a05SGarrett D'Amore perror("SNDCTL_DSP_SPEED"); 27288447a05SGarrett D'Amore return (-3); 27388447a05SGarrett D'Amore } 27488447a05SGarrett D'Amore 27588447a05SGarrett D'Amore sample_rate = tmp; 27688447a05SGarrett D'Amore if (sample_rate != SAMPLE_RATE) { 27788447a05SGarrett D'Amore (void) printf(_("The device doesn't support %d Hz\n"), 27888447a05SGarrett D'Amore SAMPLE_RATE); 27988447a05SGarrett D'Amore return (-3); 28088447a05SGarrett D'Amore } 28188447a05SGarrett D'Amore (void) printf("\n"); 28288447a05SGarrett D'Amore 28388447a05SGarrett D'Amore /* 28488447a05SGarrett D'Amore * This program will measure the real sampling rate by 28588447a05SGarrett D'Amore * computing the total time required to play the sample. 28688447a05SGarrett D'Amore * 28788447a05SGarrett D'Amore * This is not terribly presice with short test sounds but it 28888447a05SGarrett D'Amore * can be used to detect if the sampling rate badly 28988447a05SGarrett D'Amore * wrong. Errors of few percents is more likely to be caused 29088447a05SGarrett D'Amore * by poor accuracy of the system clock rather than problems 29188447a05SGarrett D'Amore * with the sampling rate. 29288447a05SGarrett D'Amore */ 29388447a05SGarrett D'Amore (void) gettimeofday(&t1, NULL); 29488447a05SGarrett D'Amore 29588447a05SGarrett D'Amore for (i = 0; (ccfg = tcfg->tests[i]) != NULL; i++) { 29688447a05SGarrett D'Amore (void) fputs(_(ccfg->name), stdout); 29788447a05SGarrett D'Amore (void) fflush(stdout); 29888447a05SGarrett D'Amore if (ccfg->flags & CFLAG_LFE) { 29988447a05SGarrett D'Amore (void) printf(_("SKIPPED\n")); 30088447a05SGarrett D'Amore continue; 30188447a05SGarrett D'Amore } 30288447a05SGarrett D'Amore 30388447a05SGarrett D'Amore if (write(hd, ccfg->data, ccfg->len) < 0) { 30488447a05SGarrett D'Amore (void) printf(_("ERROR: %s\n"), 30588447a05SGarrett D'Amore strerror(errno)); 30688447a05SGarrett D'Amore return (-3); 30788447a05SGarrett D'Amore } 30888447a05SGarrett D'Amore (void) printf(_("OK\n")); 30988447a05SGarrett D'Amore total_bytes += ccfg->len; 31088447a05SGarrett D'Amore } 31188447a05SGarrett D'Amore 31288447a05SGarrett D'Amore (void) gettimeofday(&t2, NULL); 31388447a05SGarrett D'Amore delay = 0; 31488447a05SGarrett D'Amore (void) ioctl(hd, SNDCTL_DSP_GETODELAY, &delay); /* Ignore errors */ 31588447a05SGarrett D'Amore 31688447a05SGarrett D'Amore /* 31788447a05SGarrett D'Amore * Perform the time computations using milliseconds. 31888447a05SGarrett D'Amore */ 31988447a05SGarrett D'Amore 32088447a05SGarrett D'Amore t = t2.tv_sec - t1.tv_sec; 32188447a05SGarrett D'Amore t *= 1000; 32288447a05SGarrett D'Amore 32388447a05SGarrett D'Amore t += t2.tv_usec / 1000; 32488447a05SGarrett D'Amore t -= t1.tv_usec / 1000; 32588447a05SGarrett D'Amore 32688447a05SGarrett D'Amore total_bytes -= delay; 32788447a05SGarrett D'Amore total_bytes *= 1000; 32888447a05SGarrett D'Amore 32988447a05SGarrett D'Amore total_bytes /= t; 33088447a05SGarrett D'Amore total_bytes /= (tcfg->nchan * sizeof (int16_t)); 33188447a05SGarrett D'Amore 33288447a05SGarrett D'Amore ratio = ((float)total_bytes / (float)sample_rate) * 100.0; 33388447a05SGarrett D'Amore (void) printf(_("\t<measured sample rate %8.2f Hz (%4.2f%%)>\n"), 33488447a05SGarrett D'Amore (float)sample_rate * ratio / 100.0, ratio - 100.0); 33588447a05SGarrett D'Amore num_devices_tested++; 33688447a05SGarrett D'Amore 33788447a05SGarrett D'Amore return (1); 33888447a05SGarrett D'Amore } 33988447a05SGarrett D'Amore 34088447a05SGarrett D'Amore static int 34188447a05SGarrett D'Amore find_num_devices(void) 34288447a05SGarrett D'Amore { 34388447a05SGarrett D'Amore oss_sysinfo info; 34488447a05SGarrett D'Amore struct utsname un; 34588447a05SGarrett D'Amore /* 34688447a05SGarrett D'Amore * Find out the number of available audio devices by calling 34788447a05SGarrett D'Amore * SNDCTL_SYSINFO. 34888447a05SGarrett D'Amore */ 34988447a05SGarrett D'Amore 35088447a05SGarrett D'Amore if (ioctl(mixerfd, SNDCTL_SYSINFO, &info) == -1) { 35188447a05SGarrett D'Amore if (errno == ENXIO) { 35288447a05SGarrett D'Amore (void) fprintf(stderr, 35388447a05SGarrett D'Amore _("No supported sound hardware detected.\n")); 35488447a05SGarrett D'Amore exit(-1); 35588447a05SGarrett D'Amore } else { 35688447a05SGarrett D'Amore perror("SNDCTL_SYSINFO"); 35788447a05SGarrett D'Amore (void) printf(_("Cannot get system information.\n")); 35888447a05SGarrett D'Amore exit(-1); 35988447a05SGarrett D'Amore } 36088447a05SGarrett D'Amore } 36188447a05SGarrett D'Amore (void) printf(_("Sound subsystem and version: %s %s (0x%08X)\n"), 36288447a05SGarrett D'Amore info.product, info.version, info.versionnum); 36388447a05SGarrett D'Amore 36488447a05SGarrett D'Amore if (uname(&un) != -1) 36588447a05SGarrett D'Amore (void) printf(_("Platform: %s %s %s %s\n"), 36688447a05SGarrett D'Amore un.sysname, un.release, un.version, un.machine); 36788447a05SGarrett D'Amore 36888447a05SGarrett D'Amore return (info.numaudios); 36988447a05SGarrett D'Amore } 37088447a05SGarrett D'Amore 37188447a05SGarrett D'Amore /* 37288447a05SGarrett D'Amore * The test_device() routine checks certain information about the device 37388447a05SGarrett D'Amore * and calls testdsp() to play the test sound. 37488447a05SGarrett D'Amore */ 37588447a05SGarrett D'Amore 37688447a05SGarrett D'Amore int 37788447a05SGarrett D'Amore test_device(char *dn, int flags, testcfg_t *tcfg) 37888447a05SGarrett D'Amore { 37988447a05SGarrett D'Amore oss_audioinfo ainfo; 38088447a05SGarrett D'Amore int code; 38188447a05SGarrett D'Amore int fd; 38288447a05SGarrett D'Amore 38388447a05SGarrett D'Amore fd = open(dn, O_WRONLY, 0); 38488447a05SGarrett D'Amore if (fd == -1) { 38588447a05SGarrett D'Amore int err = errno; 38688447a05SGarrett D'Amore perror(dn); 38788447a05SGarrett D'Amore errno = err; 38888447a05SGarrett D'Amore describe_error(errno); 389*68c47f65SGarrett D'Amore return (-1); 39088447a05SGarrett D'Amore } 39188447a05SGarrett D'Amore 39288447a05SGarrett D'Amore ainfo.dev = -1; 39388447a05SGarrett D'Amore if (ioctl(fd, SNDCTL_AUDIOINFO, &ainfo) == -1) { 39488447a05SGarrett D'Amore perror("SNDCTL_AUDIOINFO"); 39588447a05SGarrett D'Amore (void) close(fd); 396*68c47f65SGarrett D'Amore return (-1); 39788447a05SGarrett D'Amore } 39888447a05SGarrett D'Amore 39988447a05SGarrett D'Amore (void) printf(_("\n*** Scanning sound adapter #%d ***\n"), 40088447a05SGarrett D'Amore ainfo.card_number); 40188447a05SGarrett D'Amore 40288447a05SGarrett D'Amore (void) printf(_("%s (audio engine %d): %s\n"), ainfo.devnode, ainfo.dev, 40388447a05SGarrett D'Amore ainfo.name); 40488447a05SGarrett D'Amore 40588447a05SGarrett D'Amore if (!ainfo.enabled) { 40688447a05SGarrett D'Amore (void) printf(_(" - Device not present - Skipping\n")); 40788447a05SGarrett D'Amore (void) close(fd); 408*68c47f65SGarrett D'Amore return (0); 40988447a05SGarrett D'Amore } 41088447a05SGarrett D'Amore 41188447a05SGarrett D'Amore if (!(ainfo.caps & PCM_CAP_OUTPUT)) { 41288447a05SGarrett D'Amore (void) printf(_(" - Skipping input only device\n")); 41388447a05SGarrett D'Amore (void) close(fd); 414*68c47f65SGarrett D'Amore return (0); 41588447a05SGarrett D'Amore } 41688447a05SGarrett D'Amore 41788447a05SGarrett D'Amore (void) printf(_(" - Performing audio playback test... ")); 41888447a05SGarrett D'Amore (void) fflush(stdout); 41988447a05SGarrett D'Amore 42088447a05SGarrett D'Amore code = testdsp(fd, flags, tcfg); 42188447a05SGarrett D'Amore (void) close(fd); 422*68c47f65SGarrett D'Amore if (code < 0) { 423*68c47f65SGarrett D'Amore return (code); 424*68c47f65SGarrett D'Amore } 42588447a05SGarrett D'Amore 42688447a05SGarrett D'Amore return (code == 1); 42788447a05SGarrett D'Amore } 42888447a05SGarrett D'Amore 42988447a05SGarrett D'Amore void 43088447a05SGarrett D'Amore describe_error(int err) 43188447a05SGarrett D'Amore { 43288447a05SGarrett D'Amore switch (err) { 43388447a05SGarrett D'Amore case ENODEV: 43488447a05SGarrett D'Amore (void) fprintf(stderr, 43588447a05SGarrett D'Amore _("The device file was found in /dev but\n" 43688447a05SGarrett D'Amore "the driver was not loaded.\n")); 43788447a05SGarrett D'Amore break; 43888447a05SGarrett D'Amore 43988447a05SGarrett D'Amore case ENXIO: 44088447a05SGarrett D'Amore (void) fprintf(stderr, 44188447a05SGarrett D'Amore _("There are no sound devices available.\n" 44288447a05SGarrett D'Amore "The most likely reason is that the device you have\n" 44388447a05SGarrett D'Amore "is malfunctioning or it's not supported.\n" 44488447a05SGarrett D'Amore "It's also possible that you are trying to use the wrong " 44588447a05SGarrett D'Amore "device file.\n")); 44688447a05SGarrett D'Amore break; 44788447a05SGarrett D'Amore 44888447a05SGarrett D'Amore case ENOSPC: 44988447a05SGarrett D'Amore (void) fprintf(stderr, 45088447a05SGarrett D'Amore _("Your system cannot allocate memory for the device\n" 45188447a05SGarrett D'Amore "buffers. Reboot your machine and try again.\n")); 45288447a05SGarrett D'Amore break; 45388447a05SGarrett D'Amore 45488447a05SGarrett D'Amore case ENOENT: 45588447a05SGarrett D'Amore (void) fprintf(stderr, 45688447a05SGarrett D'Amore _("The device file is missing from /dev.\n")); 45788447a05SGarrett D'Amore break; 45888447a05SGarrett D'Amore 45988447a05SGarrett D'Amore 46088447a05SGarrett D'Amore case EBUSY: 46188447a05SGarrett D'Amore (void) fprintf(stderr, 46288447a05SGarrett D'Amore _("The device is busy. There is some other application\n" 46388447a05SGarrett D'Amore "using it.\n")); 46488447a05SGarrett D'Amore break; 46588447a05SGarrett D'Amore 46688447a05SGarrett D'Amore default: 46788447a05SGarrett D'Amore break; 46888447a05SGarrett D'Amore } 46988447a05SGarrett D'Amore } 47088447a05SGarrett D'Amore 47188447a05SGarrett D'Amore int 47288447a05SGarrett D'Amore main(int argc, char *argv[]) 47388447a05SGarrett D'Amore { 47488447a05SGarrett D'Amore int t, i; 47588447a05SGarrett D'Amore int maxdev; 47688447a05SGarrett D'Amore int flags = 0; 47788447a05SGarrett D'Amore int status = 0; 478*68c47f65SGarrett D'Amore int errors = 0; 47988447a05SGarrett D'Amore int numdev; 48088447a05SGarrett D'Amore extern int optind; 48188447a05SGarrett D'Amore testcfg_t *tcfg; 48288447a05SGarrett D'Amore 48388447a05SGarrett D'Amore (void) setlocale(LC_ALL, ""); 48488447a05SGarrett D'Amore (void) textdomain(TEXT_DOMAIN); 48588447a05SGarrett D'Amore 48688447a05SGarrett D'Amore tcfg = &test_stereo; 48788447a05SGarrett D'Amore 48888447a05SGarrett D'Amore /* 48988447a05SGarrett D'Amore * Simple command line switch handling. 49088447a05SGarrett D'Amore */ 49188447a05SGarrett D'Amore 49288447a05SGarrett D'Amore while ((i = getopt(argc, argv, "l2457")) != EOF) { 49388447a05SGarrett D'Amore switch (i) { 49488447a05SGarrett D'Amore case 'l': 49588447a05SGarrett D'Amore flags |= TF_LOOP; 49688447a05SGarrett D'Amore break; 49788447a05SGarrett D'Amore case '2': 49888447a05SGarrett D'Amore tcfg = &test_stereo; 49988447a05SGarrett D'Amore break; 50088447a05SGarrett D'Amore case '4': 50188447a05SGarrett D'Amore tcfg = &test_quad; 50288447a05SGarrett D'Amore break; 50388447a05SGarrett D'Amore case '5': 50488447a05SGarrett D'Amore tcfg = &test_51; 50588447a05SGarrett D'Amore break; 50688447a05SGarrett D'Amore case '7': 50788447a05SGarrett D'Amore tcfg = &test_71; 50888447a05SGarrett D'Amore break; 50988447a05SGarrett D'Amore default: 51088447a05SGarrett D'Amore (void) printf(_("Usage: %s [options...] [device]\n" 51188447a05SGarrett D'Amore " -2 Stereo test\n" 51288447a05SGarrett D'Amore " -4 Quadraphonic 4.0 test\n" 51388447a05SGarrett D'Amore " -5 Surround 5.1 test\n" 51488447a05SGarrett D'Amore " -7 Surround 7.1 test\n" 51588447a05SGarrett D'Amore " -l Loop test\n"), argv[0]); 51688447a05SGarrett D'Amore exit(-1); 51788447a05SGarrett D'Amore } 51888447a05SGarrett D'Amore } 51988447a05SGarrett D'Amore 52088447a05SGarrett D'Amore /* 52188447a05SGarrett D'Amore * Open the mixer device used for calling SNDCTL_SYSINFO and 52288447a05SGarrett D'Amore * SNDCTL_AUDIOINFO. 52388447a05SGarrett D'Amore */ 52488447a05SGarrett D'Amore if ((mixerfd = open("/dev/mixer", O_RDWR, 0)) == -1) { 52588447a05SGarrett D'Amore int err = errno; 52688447a05SGarrett D'Amore perror("/dev/mixer"); 52788447a05SGarrett D'Amore errno = err; 52888447a05SGarrett D'Amore describe_error(errno); 52988447a05SGarrett D'Amore exit(-1); 53088447a05SGarrett D'Amore } 53188447a05SGarrett D'Amore 53288447a05SGarrett D'Amore prepare(tcfg); /* Prepare the wave data */ 53388447a05SGarrett D'Amore 53488447a05SGarrett D'Amore /* 53588447a05SGarrett D'Amore * Enumerate all devices and play the test sounds. 53688447a05SGarrett D'Amore */ 53788447a05SGarrett D'Amore maxdev = find_num_devices(); 53888447a05SGarrett D'Amore if (maxdev < 1) { 53988447a05SGarrett D'Amore (void) printf(_("\n*** No audio hardware available ***\n")); 54088447a05SGarrett D'Amore exit(-1); 54188447a05SGarrett D'Amore } 54288447a05SGarrett D'Amore 54388447a05SGarrett D'Amore numdev = (argc - optind); 54488447a05SGarrett D'Amore do { 54588447a05SGarrett D'Amore char *dn; 54688447a05SGarrett D'Amore oss_audioinfo ainfo; 547*68c47f65SGarrett D'Amore int rv; 54888447a05SGarrett D'Amore 549*68c47f65SGarrett D'Amore status = 0; 55088447a05SGarrett D'Amore if (numdev > 0) { 55188447a05SGarrett D'Amore for (t = 0; t < numdev; t++) { 55288447a05SGarrett D'Amore dn = argv[optind + t]; 553*68c47f65SGarrett D'Amore rv = test_device(dn, flags, tcfg); 554*68c47f65SGarrett D'Amore if (rv < 0) { 555*68c47f65SGarrett D'Amore errors++; 556*68c47f65SGarrett D'Amore } else if (rv) { 55788447a05SGarrett D'Amore status++; 55888447a05SGarrett D'Amore } 559*68c47f65SGarrett D'Amore } 56088447a05SGarrett D'Amore } else { 56188447a05SGarrett D'Amore for (t = 0; t < maxdev; t++) { 56288447a05SGarrett D'Amore ainfo.dev = t; 56388447a05SGarrett D'Amore if (ioctl(mixerfd, SNDCTL_AUDIOINFO, 56488447a05SGarrett D'Amore &ainfo) == -1) { 56588447a05SGarrett D'Amore perror("SNDCTL_AUDIOINFO"); 56688447a05SGarrett D'Amore status++; 56788447a05SGarrett D'Amore continue; 56888447a05SGarrett D'Amore } 56988447a05SGarrett D'Amore dn = ainfo.devnode; 570*68c47f65SGarrett D'Amore rv = test_device(dn, flags, tcfg); 571*68c47f65SGarrett D'Amore if (rv < 0) { 572*68c47f65SGarrett D'Amore errors++; 573*68c47f65SGarrett D'Amore } else if (rv) { 57488447a05SGarrett D'Amore status++; 57588447a05SGarrett D'Amore } 57688447a05SGarrett D'Amore } 577*68c47f65SGarrett D'Amore } 57888447a05SGarrett D'Amore 579*68c47f65SGarrett D'Amore if (errors == 0) 58088447a05SGarrett D'Amore (void) printf(_("\n*** All tests completed OK ***\n")); 58188447a05SGarrett D'Amore else 58288447a05SGarrett D'Amore (void) printf(_("\n*** Errors were detected ***\n")); 58388447a05SGarrett D'Amore 584*68c47f65SGarrett D'Amore } while (status && (flags & TF_LOOP)); 58588447a05SGarrett D'Amore 58688447a05SGarrett D'Amore (void) close(mixerfd); 58788447a05SGarrett D'Amore 58888447a05SGarrett D'Amore return (status); 58988447a05SGarrett D'Amore } 590