1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * audio_clean - Clear any residual data that may be residing in the in the 31 * audio device driver or chip. 32 * 33 * Usage: audio_clean [-Iisf] device_name 34 * 35 * Note: The same operation is performed for any of the "ifs" flags. 36 * The "I" flag is a silent form of "i". Support for the flags 37 * is provided so that the framework is place if added 38 * functionality is required. 39 * 40 * Note: The AUDIO_SETINFO ioctl is used instead of the low level 41 * AUDIOSETREG command which is used to perform low level 42 * operations on the device. If a process had previously used 43 * AUDIOSETREG to monkey with the device, then the driver would 44 * have reset the chip when the process performed a close, 45 * so this can just clear the info structure. 46 */ 47 48 #include <ctype.h> 49 #include <errno.h> 50 #include <fcntl.h> 51 #include <libintl.h> 52 #include <locale.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <strings.h> 57 #include <stropts.h> 58 #include <unistd.h> 59 #include <bsm/devices.h> 60 #include <sys/audioio.h> 61 #include <sys/file.h> 62 #include <sys/ioctl.h> 63 #include <sys/param.h> 64 #include <sys/stat.h> 65 #include <sys/types.h> 66 67 #ifndef TEXT_DOMAIN 68 #define TEXT_DOMAIN "SUNW_OST_OSCMD" 69 #endif 70 71 #ifdef DEBUG 72 static void print_info(audio_info_t *); 73 static void print_prinfo(audio_prinfo_t *); 74 #endif /* DEBUG */ 75 76 static void 77 usage(char *prog) 78 { 79 (void) fprintf(stderr, "%s%s", prog, 80 gettext(" : usage:[-I|-s|-f|-i] device\n")); 81 } 82 83 int 84 main(int argc, char **argv) 85 { 86 int err = 0; 87 int Audio_fd; 88 int forced = 0; /* Command line options */ 89 int initial = 0; 90 int standard = 0; 91 int verbose = 1; /* default is to be verbose */ 92 int c; 93 char *prog, *devname, *devpath; 94 devmap_t *dm; 95 struct stat st; 96 audio_info_t info; 97 98 (void) setlocale(LC_ALL, ""); 99 (void) textdomain(TEXT_DOMAIN); 100 101 prog = argv[0]; /* save program initiation name */ 102 103 /* 104 * Parse arguments. Currently i, s and f all do the 105 * the same thing. 106 */ 107 108 while ((c = getopt(argc, argv, "Iifs")) != -1) { 109 switch (c) { 110 case 'I': 111 verbose = 0; 112 initial++; 113 if (standard || forced) 114 err++; 115 break; 116 case 'i': 117 initial++; 118 if (standard || forced) 119 err++; 120 break; 121 case 's': 122 standard++; 123 if (initial || forced) 124 err++; 125 break; 126 case 'f': 127 forced++; 128 if (initial || standard) 129 err++; 130 break; 131 case '?': 132 err++; 133 break; 134 default: 135 err++; 136 break; 137 } 138 if (err) { 139 if (verbose) 140 usage(prog); 141 exit(1); 142 } 143 } 144 145 if ((argc - optind) != 1) { 146 if (verbose) 147 usage(prog); 148 exit(1); 149 } else { 150 devname = argv[optind]; 151 } 152 153 setdmapent(); 154 if ((dm = getdmapnam(devname)) == NULL) { 155 enddmapent(); 156 if (verbose) 157 (void) fprintf(stderr, "%s%s", 158 devname, 159 gettext(" : No such allocatable device\n")); 160 exit(1); 161 } 162 enddmapent(); 163 if (dm->dmap_devarray == NULL || dm->dmap_devarray[0] == NULL) { 164 if (verbose) 165 (void) fprintf(stderr, "%s%s", 166 devname, 167 gettext(" : No such allocatable device\n")); 168 exit(1); 169 } 170 devpath = strdup(dm->dmap_devarray[0]); 171 freedmapent(dm); 172 173 /* 174 * Validate and open the audio device 175 */ 176 err = stat(devpath, &st); 177 178 if (err < 0) { 179 if (verbose) { 180 (void) fprintf(stderr, gettext("%s: cannot stat "), 181 prog); 182 perror("audio_clean"); 183 } 184 exit(1); 185 } 186 if (!S_ISCHR(st.st_mode)) { 187 if (verbose) 188 (void) fprintf(stderr, 189 gettext("%s: %s is not an audio device\n"), prog, 190 devpath); 191 exit(1); 192 } 193 194 /* 195 * Since the device /dev/audio can suspend if someone else is 196 * using it we check to see if we're going to hang before we 197 * do anything. 198 */ 199 Audio_fd = open(devpath, O_WRONLY | O_NDELAY); 200 201 if ((Audio_fd < 0) && (errno == EBUSY)) { 202 if (verbose) 203 (void) fprintf(stderr, gettext("%s: waiting for %s..."), 204 prog, devpath); 205 exit(0); 206 } else if (Audio_fd < 0) { 207 if (verbose) { 208 (void) fprintf(stderr, gettext("%s: error opening "), 209 prog); 210 perror(devpath); 211 } 212 exit(1); 213 } 214 215 #ifdef DEBUG 216 /* 217 * Read the audio_info structure. 218 */ 219 220 if (ioctl(Audio_fd, AUDIO_GETINFO, &info) != 0) { 221 perror("Ioctl AUDIO_GETINFO error"); 222 (void) close(Audio_fd); 223 exit(1); 224 } 225 226 print_info(&info); 227 #endif /* DEBUG */ 228 229 /* LINTED */ 230 AUDIO_INITINFO(&info); /* clear audit info structure */ 231 232 if (ioctl(Audio_fd, AUDIO_SETINFO, &info) != 0) { 233 if (verbose) 234 perror(gettext("Ioctl AUDIO_SETINFO error")); 235 (void) close(Audio_fd); 236 exit(1); 237 } 238 239 #ifdef DEBUG 240 if (ioctl(Audio_fd, AUDIO_GETINFO, &info) != 0) { 241 perror("Ioctl AUDIO_GETINFO-2 error"); 242 (void) close(Audio_fd); 243 exit(1); 244 } 245 246 print_info(&info); 247 #endif /* DEBUG */ 248 249 return (0); 250 } 251 252 253 #ifdef DEBUG 254 void 255 print_info(audio_info_t *info) 256 { 257 print_prinfo(&info->play); 258 print_prinfo(&info->record); 259 (void) printf("monitor_gain %d\n", info->monitor_gain); 260 (void) fflush(stdout); 261 } 262 263 264 void 265 print_prinfo(audio_prinfo_t *prinfo) 266 { 267 /* The following values decribe audio data encoding: */ 268 (void) printf("sample_rate %d\n", prinfo->sample_rate); 269 (void) printf("channels %d\n", prinfo->channels); 270 (void) printf("precision %d\n", prinfo->precision); 271 (void) printf("encoding %d\n", prinfo->encoding); 272 273 /* The following values control audio device configuration */ 274 (void) printf("gain %d\n", prinfo->gain); 275 (void) printf("port %d\n", prinfo->port); 276 (void) printf("avail_ports %d\n", prinfo->avail_ports); 277 (void) printf("mod_ports %d\n", prinfo->mod_ports); 278 279 /* These are Reserved for future use, but we clear them */ 280 (void) printf("_xxx %d\n", prinfo->_xxx); 281 282 (void) printf("buffer_size %d\n", prinfo->buffer_size); 283 284 /* The following values describe driver state */ 285 (void) printf("samples %d\n", prinfo->samples); 286 (void) printf("eof %d\n", prinfo->eof); 287 (void) printf("pause %d\n", prinfo->pause); 288 (void) printf("error %d\n", prinfo->error); 289 (void) printf("waiting %d\n", prinfo->waiting); 290 (void) printf("balance %d\n", prinfo->balance); 291 292 /* The following values are read-only state flags */ 293 (void) printf("open %d\n", prinfo->open); 294 (void) printf("active %d\n", prinfo->active); 295 } 296 #endif /* DEBUG */ 297