156746Sroberto/* 256746Sroberto * audio.c - audio interface for reference clock audio drivers 356746Sroberto */ 456746Sroberto#ifdef HAVE_CONFIG_H 5132451Sroberto# include <config.h> 656746Sroberto#endif 756746Sroberto 8132451Sroberto#if defined(HAVE_SYS_AUDIOIO_H) || defined(HAVE_SUN_AUDIOIO_H) || \ 9132451Sroberto defined(HAVE_SYS_SOUNDCARD_H) || defined(HAVE_MACHINE_SOUNDCARD_H) 1082498Sroberto 1156746Sroberto#include "audio.h" 1282498Sroberto#include "ntp_stdlib.h" 1382498Sroberto#include "ntp_syslog.h" 1482498Sroberto#ifdef HAVE_UNISTD_H 1582498Sroberto# include <unistd.h> 1682498Sroberto#endif 1756746Sroberto#include <stdio.h> 1882498Sroberto#include "ntp_string.h" 1956746Sroberto 2056746Sroberto#ifdef HAVE_SYS_AUDIOIO_H 21132451Sroberto# include <sys/audioio.h> 2256746Sroberto#endif /* HAVE_SYS_AUDIOIO_H */ 2382498Sroberto 2456746Sroberto#ifdef HAVE_SUN_AUDIOIO_H 25132451Sroberto# include <sys/ioccom.h> 26132451Sroberto# include <sun/audioio.h> 2756746Sroberto#endif /* HAVE_SUN_AUDIOIO_H */ 2882498Sroberto 2956746Sroberto#ifdef HAVE_SYS_IOCTL_H 30132451Sroberto# include <sys/ioctl.h> 3156746Sroberto#endif /* HAVE_SYS_IOCTL_H */ 3256746Sroberto 3356746Sroberto#include <fcntl.h> 3456746Sroberto 35132451Sroberto#ifdef HAVE_MACHINE_SOUNDCARD_H 36132451Sroberto# include <machine/soundcard.h> 37132451Sroberto# define PCM_STYLE_SOUND 38132451Sroberto#else 39132451Sroberto# ifdef HAVE_SYS_SOUNDCARD_H 40132451Sroberto# include <sys/soundcard.h> 41132451Sroberto# define PCM_STYLE_SOUND 42132451Sroberto# endif 43132451Sroberto#endif 44132451Sroberto 45132451Sroberto#ifdef PCM_STYLE_SOUND 46132451Sroberto# include <ctype.h> 47132451Sroberto#endif 48132451Sroberto 49316069Sdelphij 50316069Sdelphij/* 51316069Sdelphij * 4.4BSD-Lite switched to an unsigned long ioctl arg. Detect common 52316069Sdelphij * derivatives here, and apply that type. To make the following code 53316069Sdelphij * less verbose we make a proper typedef. 54316069Sdelphij * The joy of IOCTL programming... 55316069Sdelphij */ 56316069Sdelphij# if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__) || defined __OpenBSD__ 57316069Sdelphijtypedef unsigned long ioctl_arg_T; 58316069Sdelphij#else 59316069Sdelphijtypedef int ioctl_arg_T; 60316069Sdelphij#endif 61316069Sdelphij 6256746Sroberto/* 6356746Sroberto * Global variables 6456746Sroberto */ 6556746Sroberto#ifdef HAVE_SYS_AUDIOIO_H 6656746Srobertostatic struct audio_device device; /* audio device ident */ 6782498Sroberto#endif /* HAVE_SYS_AUDIOIO_H */ 68132451Sroberto#ifdef PCM_STYLE_SOUND 69132451Sroberto# define INIT_FILE "/etc/ntp.audio" 70132451Sroberto 71316069Sdelphijstatic ioctl_arg_T agc = SOUND_MIXER_WRITE_RECLEV; /* or IGAIN or LINE */ 72316069Sdelphijstatic ioctl_arg_T audiomonitor = SOUND_MIXER_WRITE_VOLUME; /* or OGAIN */ 73316069Sdelphijstatic int devmask = 0; 74316069Sdelphijstatic int recmask = 0; 75316069Sdelphijstatic char cf_c_dev[100], cf_i_dev[100], cf_agc[100], cf_monitor[100]; 76316069Sdelphij 77316069Sdelphijstatic const char *m_names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 78132451Sroberto#else /* not PCM_STYLE_SOUND */ 7956746Srobertostatic struct audio_info info; /* audio device info */ 80132451Sroberto#endif /* not PCM_STYLE_SOUND */ 8156746Srobertostatic int ctl_fd; /* audio control file descriptor */ 8256746Sroberto 83132451Sroberto#ifdef PCM_STYLE_SOUND 84285612Sdelphijstatic void audio_config_read (int, const char **, const char **); 85285612Sdelphijstatic int mixer_name (const char *, int); 8656746Sroberto 87132451Sroberto 88132451Srobertoint 89132451Srobertomixer_name( 90132451Sroberto const char *m_name, 91132451Sroberto int m_mask 92132451Sroberto ) 93132451Sroberto{ 94132451Sroberto int i; 95132451Sroberto 96132451Sroberto for (i = 0; i < SOUND_MIXER_NRDEVICES; ++i) 97132451Sroberto if (((1 << i) & m_mask) 98132451Sroberto && !strcmp(m_names[i], m_name)) 99132451Sroberto break; 100132451Sroberto 101132451Sroberto return (SOUND_MIXER_NRDEVICES == i) 102132451Sroberto ? -1 103132451Sroberto : i 104132451Sroberto ; 105132451Sroberto} 106132451Sroberto 107132451Sroberto 10856746Sroberto/* 109132451Sroberto * Check: 110132451Sroberto * 111132451Sroberto * /etc/ntp.audio# where # is the unit number 112132451Sroberto * /etc/ntp.audio.# where # is the unit number 113132451Sroberto * /etc/ntp.audio 114132451Sroberto * 115132451Sroberto * for contents of the form: 116132451Sroberto * 117132451Sroberto * idev /dev/input_device 118132451Sroberto * cdev /dev/control_device 119132451Sroberto * agc pcm_input_device {igain,line,line1,...} 120132451Sroberto * monitor pcm_monitor_device {ogain,...} 121132451Sroberto * 122132451Sroberto * The device names for the "agc" and "monitor" keywords 123132451Sroberto * can be found by running either the "mixer" program or the 124132451Sroberto * util/audio-pcm program. 125132451Sroberto * 126132451Sroberto * Great hunks of this subroutine were swiped from refclock_oncore.c 127132451Sroberto */ 128132451Srobertostatic void 129132451Srobertoaudio_config_read( 130132451Sroberto int unit, 131285612Sdelphij const char **c_dev, /* Control device */ 132285612Sdelphij const char **i_dev /* input device */ 133132451Sroberto ) 134132451Sroberto{ 135132451Sroberto FILE *fd; 136132451Sroberto char device[20], line[100], ab[100]; 137132451Sroberto 138285612Sdelphij snprintf(device, sizeof(device), "%s%d", INIT_FILE, unit); 139132451Sroberto if ((fd = fopen(device, "r")) == NULL) { 140132451Sroberto printf("audio_config_read: <%s> NO\n", device); 141285612Sdelphij snprintf(device, sizeof(device), "%s.%d", INIT_FILE, 142285612Sdelphij unit); 143132451Sroberto if ((fd = fopen(device, "r")) == NULL) { 144132451Sroberto printf("audio_config_read: <%s> NO\n", device); 145285612Sdelphij snprintf(device, sizeof(device), "%s", 146285612Sdelphij INIT_FILE); 147132451Sroberto if ((fd = fopen(device, "r")) == NULL) { 148285612Sdelphij printf("audio_config_read: <%s> NO\n", 149285612Sdelphij device); 150132451Sroberto return; 151132451Sroberto } 152132451Sroberto } 153132451Sroberto } 154132451Sroberto printf("audio_config_read: reading <%s>\n", device); 155132451Sroberto while (fgets(line, sizeof line, fd)) { 156132451Sroberto char *cp, *cc, *ca; 157132451Sroberto int i; 158132451Sroberto 159132451Sroberto /* Remove comments */ 160132451Sroberto if ((cp = strchr(line, '#'))) 161132451Sroberto *cp = '\0'; 162132451Sroberto 163132451Sroberto /* Remove any trailing spaces */ 164132451Sroberto for (i = strlen(line); 165285612Sdelphij i > 0 && isascii((unsigned char)line[i - 1]) && isspace((unsigned char)line[i - 1]); 166132451Sroberto ) 167132451Sroberto line[--i] = '\0'; 168132451Sroberto 169132451Sroberto /* Remove leading space */ 170285612Sdelphij for (cc = line; *cc && isascii((unsigned char)*cc) && isspace((unsigned char)*cc); cc++) 171132451Sroberto continue; 172132451Sroberto 173132451Sroberto /* Stop if nothing left */ 174132451Sroberto if (!*cc) 175132451Sroberto continue; 176132451Sroberto 177132451Sroberto /* Uppercase the command and find the arg */ 178132451Sroberto for (ca = cc; *ca; ca++) { 179285612Sdelphij if (isascii((unsigned char)*ca)) { 180285612Sdelphij if (islower((unsigned char)*ca)) { 181285612Sdelphij *ca = toupper((unsigned char)*ca); 182285612Sdelphij } else if (isspace((unsigned char)*ca) || (*ca == '=')) 183132451Sroberto break; 184132451Sroberto } 185132451Sroberto } 186132451Sroberto 187132451Sroberto /* Remove space (and possible =) leading the arg */ 188285612Sdelphij for (; *ca && isascii((unsigned char)*ca) && (isspace((unsigned char)*ca) || (*ca == '=')); ca++) 189132451Sroberto continue; 190132451Sroberto 191285612Sdelphij if (!strncmp(cc, "IDEV", 4) && 192285612Sdelphij 1 == sscanf(ca, "%99s", ab)) { 193285612Sdelphij strlcpy(cf_i_dev, ab, sizeof(cf_i_dev)); 194132451Sroberto printf("idev <%s>\n", ab); 195285612Sdelphij } else if (!strncmp(cc, "CDEV", 4) && 196285612Sdelphij 1 == sscanf(ca, "%99s", ab)) { 197285612Sdelphij strlcpy(cf_c_dev, ab, sizeof(cf_c_dev)); 198132451Sroberto printf("cdev <%s>\n", ab); 199285612Sdelphij } else if (!strncmp(cc, "AGC", 3) && 200285612Sdelphij 1 == sscanf(ca, "%99s", ab)) { 201285612Sdelphij strlcpy(cf_agc, ab, sizeof(cf_agc)); 202132451Sroberto printf("agc <%s> %d\n", ab, i); 203285612Sdelphij } else if (!strncmp(cc, "MONITOR", 7) && 204285612Sdelphij 1 == sscanf(ca, "%99s", ab)) { 205285612Sdelphij strlcpy(cf_monitor, ab, sizeof(cf_monitor)); 206132451Sroberto printf("monitor <%s> %d\n", ab, mixer_name(ab, -1)); 207132451Sroberto } 208132451Sroberto } 209132451Sroberto fclose(fd); 210132451Sroberto return; 211132451Sroberto} 212132451Sroberto#endif /* PCM_STYLE_SOUND */ 213132451Sroberto 214132451Sroberto/* 21556746Sroberto * audio_init - open and initialize audio device 21656746Sroberto * 217132451Sroberto * This code works with SunOS 4.x, Solaris 2.x, and PCM; however, it is 21856746Sroberto * believed generic and applicable to other systems with a minor twid 21956746Sroberto * or two. All it does is open the device, set the buffer size (Solaris 22056746Sroberto * only), preset the gain and set the input port. It assumes that the 22156746Sroberto * codec sample rate (8000 Hz), precision (8 bits), number of channels 22256746Sroberto * (1) and encoding (ITU-T G.711 mu-law companded) have been set by 22356746Sroberto * default. 22456746Sroberto */ 22556746Srobertoint 22682498Srobertoaudio_init( 227285612Sdelphij const char *dname, /* device name */ 228132451Sroberto int bufsiz, /* buffer size */ 229132451Sroberto int unit /* device unit (0-3) */ 23082498Sroberto ) 23156746Sroberto{ 232132451Sroberto#ifdef PCM_STYLE_SOUND 233132451Sroberto# define ACTL_DEV "/dev/mixer%d" 234132451Sroberto char actl_dev[30]; 235132451Sroberto# ifdef HAVE_STRUCT_SND_SIZE 236132451Sroberto struct snd_size s_size; 237132451Sroberto# endif 238132451Sroberto# ifdef AIOGFMT 239132451Sroberto snd_chan_param s_c_p; 240132451Sroberto# endif 241132451Sroberto#endif 24256746Sroberto int fd; 24356746Sroberto int rval; 244285612Sdelphij const char *actl = 245132451Sroberto#ifdef PCM_STYLE_SOUND 246132451Sroberto actl_dev 247132451Sroberto#else 248132451Sroberto "/dev/audioctl" 249132451Sroberto#endif 250132451Sroberto ; 25156746Sroberto 252132451Sroberto#ifdef PCM_STYLE_SOUND 253285612Sdelphij snprintf(actl_dev, sizeof(actl_dev), ACTL_DEV, unit); 254132451Sroberto 255132451Sroberto audio_config_read(unit, &actl, &dname); 256132451Sroberto /* If we have values for cf_c_dev or cf_i_dev, use them. */ 257132451Sroberto if (*cf_c_dev) 258182007Sroberto actl = cf_c_dev; 259132451Sroberto if (*cf_i_dev) 260182007Sroberto dname = cf_i_dev; 261132451Sroberto#endif 262132451Sroberto 26356746Sroberto /* 264285612Sdelphij * Open audio device 26556746Sroberto */ 26682498Sroberto fd = open(dname, O_RDWR | O_NONBLOCK, 0777); 267285612Sdelphij if (fd < 0) { 268285612Sdelphij msyslog(LOG_ERR, "audio_init: %s %m", dname); 26956746Sroberto return (fd); 270285612Sdelphij } 27156746Sroberto 27256746Sroberto /* 27382498Sroberto * Open audio control device. 27456746Sroberto */ 275132451Sroberto ctl_fd = open(actl, O_RDWR); 27656746Sroberto if (ctl_fd < 0) { 277285612Sdelphij msyslog(LOG_ERR, "audio_init: invalid control device <%s>", 278285612Sdelphij actl); 27956746Sroberto close(fd); 28056746Sroberto return(ctl_fd); 28156746Sroberto } 28256746Sroberto 28356746Sroberto /* 28456746Sroberto * Set audio device parameters. 28556746Sroberto */ 286132451Sroberto#ifdef PCM_STYLE_SOUND 287132451Sroberto printf("audio_init: <%s> bufsiz %d\n", dname, bufsiz); 288132451Sroberto rval = fd; 289132451Sroberto 290132451Sroberto# ifdef HAVE_STRUCT_SND_SIZE 291132451Sroberto if (ioctl(fd, AIOGSIZE, &s_size) == -1) 292132451Sroberto printf("audio_init: AIOGSIZE: %s\n", strerror(errno)); 293132451Sroberto else 294132451Sroberto printf("audio_init: orig: play_size %d, rec_size %d\n", 295132451Sroberto s_size.play_size, s_size.rec_size); 296132451Sroberto 297132451Sroberto s_size.play_size = s_size.rec_size = bufsiz; 298132451Sroberto printf("audio_init: want: play_size %d, rec_size %d\n", 299132451Sroberto s_size.play_size, s_size.rec_size); 300132451Sroberto 301132451Sroberto if (ioctl(fd, AIOSSIZE, &s_size) == -1) 302132451Sroberto printf("audio_init: AIOSSIZE: %s\n", strerror(errno)); 303132451Sroberto else 304132451Sroberto printf("audio_init: set: play_size %d, rec_size %d\n", 305132451Sroberto s_size.play_size, s_size.rec_size); 306132451Sroberto# endif /* HAVE_STRUCT_SND_SIZE */ 307132451Sroberto 308182007Sroberto# ifdef SNDCTL_DSP_SETFRAGMENT 309182007Sroberto { 310182007Sroberto int tmp = (16 << 16) + 6; /* 16 fragments, each 2^6 bytes */ 311182007Sroberto if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1) 312182007Sroberto printf("audio_init: SNDCTL_DSP_SETFRAGMENT: %s\n", 313182007Sroberto strerror(errno)); 314182007Sroberto } 315182007Sroberto# endif /* SNDCTL_DSP_SETFRAGMENT */ 316182007Sroberto 317132451Sroberto# ifdef AIOGFMT 318132451Sroberto if (ioctl(fd, AIOGFMT, &s_c_p) == -1) 319132451Sroberto printf("audio_init: AIOGFMT: %s\n", strerror(errno)); 320132451Sroberto else 321132451Sroberto printf("audio_init: play_rate %lu, rec_rate %lu, play_format %#lx, rec_format %#lx\n", 322132451Sroberto s_c_p.play_rate, s_c_p.rec_rate, s_c_p.play_format, s_c_p.rec_format); 323132451Sroberto# endif 324132451Sroberto 325132451Sroberto /* Grab the device and record masks */ 326132451Sroberto 327132451Sroberto if (ioctl(ctl_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 328132451Sroberto printf("SOUND_MIXER_READ_DEVMASK: %s\n", strerror(errno)); 329132451Sroberto if (ioctl(ctl_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 330132451Sroberto printf("SOUND_MIXER_READ_RECMASK: %s\n", strerror(errno)); 331132451Sroberto 332132451Sroberto /* validate and set any specified config file stuff */ 333285612Sdelphij if (cf_agc[0] != '\0') { 334132451Sroberto int i; 335132451Sroberto 336285612Sdelphij /* recmask */ 337285612Sdelphij i = mixer_name(cf_agc, recmask); 338132451Sroberto if (i >= 0) 339132451Sroberto agc = MIXER_WRITE(i); 340132451Sroberto else 341132451Sroberto printf("input %s not in recmask %#x\n", 342132451Sroberto cf_agc, recmask); 343132451Sroberto } 344132451Sroberto 345285612Sdelphij if (cf_monitor[0] != '\0') { 346132451Sroberto int i; 347132451Sroberto 348132451Sroberto /* devmask */ 349132451Sroberto i = mixer_name(cf_monitor, devmask); 350132451Sroberto if (i >= 0) 351309008Sdelphij audiomonitor = MIXER_WRITE(i); 352132451Sroberto else 353132451Sroberto printf("monitor %s not in devmask %#x\n", 354132451Sroberto cf_monitor, devmask); 355132451Sroberto } 356132451Sroberto 357132451Sroberto#else /* not PCM_STYLE_SOUND */ 358132451Sroberto AUDIO_INITINFO(&info); 359132451Sroberto info.play.gain = AUDIO_MAX_GAIN; 360132451Sroberto info.play.port = AUDIO_SPEAKER; 361132451Sroberto# ifdef HAVE_SYS_AUDIOIO_H 362132451Sroberto info.record.buffer_size = bufsiz; 363132451Sroberto# endif /* HAVE_SYS_AUDIOIO_H */ 364316069Sdelphij rval = ioctl(ctl_fd, AUDIO_SETINFO, (char *)&info); 36556746Sroberto if (rval < 0) { 366285612Sdelphij msyslog(LOG_ERR, "audio: invalid control device parameters"); 36756746Sroberto close(ctl_fd); 36856746Sroberto close(fd); 36956746Sroberto return(rval); 37056746Sroberto } 371132451Sroberto rval = fd; 372132451Sroberto#endif /* not PCM_STYLE_SOUND */ 373132451Sroberto return (rval); 37456746Sroberto} 37556746Sroberto 37656746Sroberto 37756746Sroberto/* 378132451Sroberto * audio_gain - adjust codec gains and port 37956746Sroberto */ 38056746Srobertoint 38156746Srobertoaudio_gain( 382132451Sroberto int gain, /* volume level (gain) 0-255 */ 383132451Sroberto int mongain, /* input to output mix (monitor gain) 0-255 */ 384132451Sroberto int port /* selected I/O port: 1 mic/2 line in */ 38556746Sroberto ) 38656746Sroberto{ 38756746Sroberto int rval; 388132451Sroberto static int o_mongain = -1; 389132451Sroberto static int o_port = -1; 39056746Sroberto 391132451Sroberto#ifdef PCM_STYLE_SOUND 392132451Sroberto int l, r; 393132451Sroberto 394289997Sglebius# ifdef GCC 395289997Sglebius rval = 0; /* GCC thinks rval is used uninitialized */ 396289997Sglebius# endif 397132451Sroberto 398132451Sroberto r = l = 100 * gain / 255; /* Normalize to 0-100 */ 399132451Sroberto# ifdef DEBUG 400132451Sroberto if (debug > 1) 401132451Sroberto printf("audio_gain: gain %d/%d\n", gain, l); 402132451Sroberto# endif 403285612Sdelphij#if 0 /* not a good idea to do this; connector wiring dependency */ 404132451Sroberto /* figure out what channel(s) to use. just nuke right for now. */ 405132451Sroberto r = 0 ; /* setting to zero nicely mutes the channel */ 406285612Sdelphij#endif 407132451Sroberto l |= r << 8; 408285612Sdelphij if (cf_agc[0] != '\0') 409285612Sdelphij rval = ioctl(ctl_fd, agc, &l); 410285612Sdelphij else 411289997Sglebius rval = ioctl(ctl_fd 412289997Sglebius , (2 == port) 413289997Sglebius ? SOUND_MIXER_WRITE_LINE 414289997Sglebius : SOUND_MIXER_WRITE_MIC 415289997Sglebius , &l); 416285612Sdelphij if (-1 == rval) { 417132451Sroberto printf("audio_gain: agc write: %s\n", strerror(errno)); 418285612Sdelphij return rval; 419132451Sroberto } 420132451Sroberto 421132451Sroberto if (o_mongain != mongain) { 422132451Sroberto r = l = 100 * mongain / 255; /* Normalize to 0-100 */ 423132451Sroberto# ifdef DEBUG 424132451Sroberto if (debug > 1) 425132451Sroberto printf("audio_gain: mongain %d/%d\n", mongain, l); 426132451Sroberto# endif 427132451Sroberto l |= r << 8; 428285612Sdelphij if (cf_monitor[0] != '\0') 429309008Sdelphij rval = ioctl(ctl_fd, audiomonitor, &l ); 430285612Sdelphij else 431285612Sdelphij rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_VOLUME, 432285612Sdelphij &l); 433285612Sdelphij if (-1 == rval) { 434132451Sroberto printf("audio_gain: mongain write: %s\n", 435132451Sroberto strerror(errno)); 436132451Sroberto return (rval); 437132451Sroberto } 438132451Sroberto o_mongain = mongain; 439132451Sroberto } 440132451Sroberto 441132451Sroberto if (o_port != port) { 442132451Sroberto# ifdef DEBUG 443132451Sroberto if (debug > 1) 444132451Sroberto printf("audio_gain: port %d\n", port); 445132451Sroberto# endif 446132451Sroberto l = (1 << ((port == 2) ? SOUND_MIXER_LINE : SOUND_MIXER_MIC)); 447132451Sroberto rval = ioctl(ctl_fd, SOUND_MIXER_WRITE_RECSRC, &l); 448132451Sroberto if (rval == -1) { 449132451Sroberto printf("SOUND_MIXER_WRITE_RECSRC: %s\n", 450132451Sroberto strerror(errno)); 451132451Sroberto return (rval); 452132451Sroberto } 453132451Sroberto# ifdef DEBUG 454132451Sroberto if (debug > 1) { 455132451Sroberto if (ioctl(ctl_fd, SOUND_MIXER_READ_RECSRC, &l) == -1) 456132451Sroberto printf("SOUND_MIXER_WRITE_RECSRC: %s\n", 457132451Sroberto strerror(errno)); 458132451Sroberto else 459132451Sroberto printf("audio_gain: recsrc is %d\n", l); 460132451Sroberto } 461132451Sroberto# endif 462132451Sroberto o_port = port; 463132451Sroberto } 464132451Sroberto#else /* not PCM_STYLE_SOUND */ 465316069Sdelphij ioctl(ctl_fd, AUDIO_GETINFO, (char *)&info); 466132451Sroberto info.record.encoding = AUDIO_ENCODING_ULAW; 467132451Sroberto info.record.error = 0; 46856746Sroberto info.record.gain = gain; 469132451Sroberto if (o_mongain != mongain) 470132451Sroberto o_mongain = info.monitor_gain = mongain; 471132451Sroberto if (o_port != port) 472132451Sroberto o_port = info.record.port = port; 473316069Sdelphij rval = ioctl(ctl_fd, AUDIO_SETINFO, (char *)&info); 47456746Sroberto if (rval < 0) { 47582498Sroberto msyslog(LOG_ERR, "audio_gain: %m"); 47656746Sroberto return (rval); 47756746Sroberto } 478132451Sroberto rval = info.record.error; 479132451Sroberto#endif /* not PCM_STYLE_SOUND */ 480132451Sroberto return (rval); 48156746Sroberto} 48256746Sroberto 48356746Sroberto 48456746Sroberto/* 48556746Sroberto * audio_show - display audio parameters 48656746Sroberto * 48756746Sroberto * This code doesn't really do anything, except satisfy curiousity and 48856746Sroberto * verify the ioctl's work. 48956746Sroberto */ 49056746Srobertovoid 49156746Srobertoaudio_show(void) 49256746Sroberto{ 493132451Sroberto#ifdef PCM_STYLE_SOUND 494132451Sroberto int recsrc = 0; 495132451Sroberto 496132451Sroberto printf("audio_show: ctl_fd %d\n", ctl_fd); 497132451Sroberto if (ioctl(ctl_fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 498132451Sroberto printf("SOUND_MIXER_READ_RECSRC: %s\n", strerror(errno)); 499132451Sroberto 500132451Sroberto#else /* not PCM_STYLE_SOUND */ 501132451Sroberto# ifdef HAVE_SYS_AUDIOIO_H 502316069Sdelphij ioctl(ctl_fd, AUDIO_GETDEV, &device); 50356746Sroberto printf("audio: name %s, version %s, config %s\n", 50456746Sroberto device.name, device.version, device.config); 505132451Sroberto# endif /* HAVE_SYS_AUDIOIO_H */ 506316069Sdelphij ioctl(ctl_fd, AUDIO_GETINFO, (char *)&info); 50756746Sroberto printf( 508132451Sroberto "audio: rate %d, chan %d, prec %d, code %d, gain %d, mon %d, port %d\n", 50956746Sroberto info.record.sample_rate, info.record.channels, 51082498Sroberto info.record.precision, info.record.encoding, 511132451Sroberto info.record.gain, info.monitor_gain, info.record.port); 51256746Sroberto printf( 51356746Sroberto "audio: samples %d, eof %d, pause %d, error %d, waiting %d, balance %d\n", 51456746Sroberto info.record.samples, info.record.eof, 51556746Sroberto info.record.pause, info.record.error, 51656746Sroberto info.record.waiting, info.record.balance); 517132451Sroberto#endif /* not PCM_STYLE_SOUND */ 51856746Sroberto} 51982498Sroberto#else 52082498Srobertoint audio_bs; 521132451Sroberto#endif /* HAVE_{SYS_AUDIOIO,SUN_AUDIOIO,MACHINE_SOUNDCARD,SYS_SOUNDCARD}_H */ 522