111230Sgdamore@opensolaris.org /* 211230Sgdamore@opensolaris.org * CDDL HEADER START 311230Sgdamore@opensolaris.org * 411230Sgdamore@opensolaris.org * The contents of this file are subject to the terms of the 511230Sgdamore@opensolaris.org * Common Development and Distribution License (the "License"). 611230Sgdamore@opensolaris.org * You may not use this file except in compliance with the License. 711230Sgdamore@opensolaris.org * 811230Sgdamore@opensolaris.org * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 911230Sgdamore@opensolaris.org * or http://www.opensolaris.org/os/licensing. 1011230Sgdamore@opensolaris.org * See the License for the specific language governing permissions 1111230Sgdamore@opensolaris.org * and limitations under the License. 1211230Sgdamore@opensolaris.org * 1311230Sgdamore@opensolaris.org * When distributing Covered Code, include this CDDL HEADER in each 1411230Sgdamore@opensolaris.org * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1511230Sgdamore@opensolaris.org * If applicable, add the following below this CDDL HEADER, with the 1611230Sgdamore@opensolaris.org * fields enclosed by brackets "[]" replaced with your own identifying 1711230Sgdamore@opensolaris.org * information: Portions Copyright [yyyy] [name of copyright owner] 1811230Sgdamore@opensolaris.org * 1911230Sgdamore@opensolaris.org * CDDL HEADER END 2011230Sgdamore@opensolaris.org */ 2111230Sgdamore@opensolaris.org /* 2211230Sgdamore@opensolaris.org * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2311230Sgdamore@opensolaris.org * Use is subject to license terms. 2411230Sgdamore@opensolaris.org */ 2511230Sgdamore@opensolaris.org 2611230Sgdamore@opensolaris.org #include <stdio.h> 2711230Sgdamore@opensolaris.org #include <stdlib.h> 2811230Sgdamore@opensolaris.org #include <errno.h> 2911230Sgdamore@opensolaris.org #include <string.h> 3011230Sgdamore@opensolaris.org #include <strings.h> 3111230Sgdamore@opensolaris.org #include <locale.h> 3211230Sgdamore@opensolaris.org #include <libintl.h> 3311230Sgdamore@opensolaris.org #include <stdarg.h> 3411230Sgdamore@opensolaris.org #include <stddef.h> 3511230Sgdamore@opensolaris.org #include <sys/types.h> 3611230Sgdamore@opensolaris.org #include <sys/stat.h> 3711230Sgdamore@opensolaris.org #include <sys/mkdev.h> 3811230Sgdamore@opensolaris.org #include <fcntl.h> 3911230Sgdamore@opensolaris.org #include <unistd.h> 4011230Sgdamore@opensolaris.org #include <ctype.h> 4111230Sgdamore@opensolaris.org #include <sys/param.h> 4211230Sgdamore@opensolaris.org #include <sys/soundcard.h> 43*11253Sgdamore@opensolaris.org #include <libdevinfo.h> 4411230Sgdamore@opensolaris.org 4511230Sgdamore@opensolaris.org #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 4611230Sgdamore@opensolaris.org #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 4711230Sgdamore@opensolaris.org #endif 4811230Sgdamore@opensolaris.org 4911230Sgdamore@opensolaris.org #define _(s) gettext(s) 5011230Sgdamore@opensolaris.org 5111230Sgdamore@opensolaris.org #define MAXLINE 1024 5211230Sgdamore@opensolaris.org 5311230Sgdamore@opensolaris.org #define AUDIO_CTRL_STEREO_LEFT(v) ((uint8_t)((v) & 0xff)) 5411230Sgdamore@opensolaris.org #define AUDIO_CTRL_STEREO_RIGHT(v) ((uint8_t)(((v) >> 8) & 0xff)) 5511230Sgdamore@opensolaris.org #define AUDIO_CTRL_STEREO_VAL(l, r) (((l) & 0xff) | (((r) & 0xff) << 8)) 5611230Sgdamore@opensolaris.org 5711230Sgdamore@opensolaris.org /* 5811230Sgdamore@opensolaris.org * These are borrowed from sys/audio/audio_common.h, where the values 5911230Sgdamore@opensolaris.org * are protected by _KERNEL. 6011230Sgdamore@opensolaris.org */ 6111230Sgdamore@opensolaris.org #define AUDIO_MN_TYPE_NBITS (4) 6211230Sgdamore@opensolaris.org #define AUDIO_MN_TYPE_MASK ((1U << AUDIO_MN_TYPE_NBITS) - 1) 6311230Sgdamore@opensolaris.org #define AUDIO_MINOR_MIXER (0) 6411230Sgdamore@opensolaris.org 6511230Sgdamore@opensolaris.org 6611230Sgdamore@opensolaris.org /* 6711230Sgdamore@opensolaris.org * Column display information 6811230Sgdamore@opensolaris.org * All are related to the types enumerated in col_t and any change should be 6911230Sgdamore@opensolaris.org * reflected in the corresponding indices and offsets for all the variables 7011230Sgdamore@opensolaris.org * accordingly. Most tweaks to the display can be done by adjusting the 7111230Sgdamore@opensolaris.org * values here. 7211230Sgdamore@opensolaris.org */ 7311230Sgdamore@opensolaris.org 7411230Sgdamore@opensolaris.org /* types of columns displayed */ 7511230Sgdamore@opensolaris.org typedef enum { COL_DV = 0, COL_NM, COL_VAL, COL_SEL} col_t; 7611230Sgdamore@opensolaris.org 7711230Sgdamore@opensolaris.org /* corresponding sizes of columns; does not include trailing null */ 7811230Sgdamore@opensolaris.org #define COL_DV_SZ 16 7911230Sgdamore@opensolaris.org #define COL_NM_SZ 24 8011230Sgdamore@opensolaris.org #define COL_VAL_SZ 10 8111230Sgdamore@opensolaris.org #define COL_SEL_SZ 20 8211230Sgdamore@opensolaris.org #define COL_MAX_SZ 64 8311230Sgdamore@opensolaris.org 8411230Sgdamore@opensolaris.org /* corresponding sizes of columns, indexed by col_t value */ 8511230Sgdamore@opensolaris.org static int col_sz[] = { 8611230Sgdamore@opensolaris.org COL_DV_SZ, COL_NM_SZ, COL_VAL_SZ, COL_SEL_SZ 8711230Sgdamore@opensolaris.org }; 8811230Sgdamore@opensolaris.org 8911230Sgdamore@opensolaris.org /* used by callers of the printing function */ 9011230Sgdamore@opensolaris.org typedef struct col_prt { 9111230Sgdamore@opensolaris.org char *col_dv; 9211230Sgdamore@opensolaris.org char *col_nm; 9311230Sgdamore@opensolaris.org char *col_val; 9411230Sgdamore@opensolaris.org char *col_sel; 9511230Sgdamore@opensolaris.org } col_prt_t; 9611230Sgdamore@opensolaris.org 9711230Sgdamore@opensolaris.org /* columns displayed in order with vopt = 0 */ 9811230Sgdamore@opensolaris.org static int col_dpy[] = {COL_NM, COL_VAL}; 9911230Sgdamore@opensolaris.org static int col_dpy_len = sizeof (col_dpy) / sizeof (*col_dpy); 10011230Sgdamore@opensolaris.org 10111230Sgdamore@opensolaris.org /* tells the printing function what members to use; follows col_dpy[] */ 10211230Sgdamore@opensolaris.org static size_t col_dpy_prt[] = { 10311230Sgdamore@opensolaris.org offsetof(col_prt_t, col_nm), 10411230Sgdamore@opensolaris.org offsetof(col_prt_t, col_val), 10511230Sgdamore@opensolaris.org }; 10611230Sgdamore@opensolaris.org 10711230Sgdamore@opensolaris.org /* columns displayed in order with vopt = 1 */ 10811230Sgdamore@opensolaris.org static int col_dpy_vopt[] = { COL_DV, COL_NM, COL_VAL, COL_SEL}; 10911230Sgdamore@opensolaris.org static int col_dpy_vopt_len = sizeof (col_dpy_vopt) / sizeof (*col_dpy_vopt); 11011230Sgdamore@opensolaris.org 11111230Sgdamore@opensolaris.org /* tells the printing function what members to use; follows col_dpy_vopt[] */ 11211230Sgdamore@opensolaris.org static size_t col_dpy_prt_vopt[] = { 11311230Sgdamore@opensolaris.org offsetof(col_prt_t, col_dv), 11411230Sgdamore@opensolaris.org offsetof(col_prt_t, col_nm), 11511230Sgdamore@opensolaris.org offsetof(col_prt_t, col_val), 11611230Sgdamore@opensolaris.org offsetof(col_prt_t, col_sel) 11711230Sgdamore@opensolaris.org }; 11811230Sgdamore@opensolaris.org 11911230Sgdamore@opensolaris.org /* columns displayed in order with tofile = 1 */ 12011230Sgdamore@opensolaris.org static int col_dpy_tofile[] = { COL_NM, COL_VAL}; 12111230Sgdamore@opensolaris.org static int col_dpy_tofile_len = sizeof (col_dpy_tofile) / 12211230Sgdamore@opensolaris.org sizeof (*col_dpy_tofile); 12311230Sgdamore@opensolaris.org 12411230Sgdamore@opensolaris.org /* tells the printing function what members to use; follows col_dpy_tofile[] */ 12511230Sgdamore@opensolaris.org static size_t col_dpy_prt_tofile[] = { 12611230Sgdamore@opensolaris.org offsetof(col_prt_t, col_nm), 12711230Sgdamore@opensolaris.org offsetof(col_prt_t, col_val) 12811230Sgdamore@opensolaris.org }; 12911230Sgdamore@opensolaris.org 13011230Sgdamore@opensolaris.org 13111230Sgdamore@opensolaris.org /* 13211230Sgdamore@opensolaris.org * mixer and control accounting 13311230Sgdamore@opensolaris.org */ 13411230Sgdamore@opensolaris.org 13511230Sgdamore@opensolaris.org typedef struct cinfo { 13611230Sgdamore@opensolaris.org oss_mixext ci; 13711230Sgdamore@opensolaris.org oss_mixer_enuminfo *enump; 13811230Sgdamore@opensolaris.org } cinfo_t; 13911230Sgdamore@opensolaris.org 14011230Sgdamore@opensolaris.org typedef struct device { 14111230Sgdamore@opensolaris.org oss_card_info card; 14211230Sgdamore@opensolaris.org oss_mixerinfo mixer; 14311230Sgdamore@opensolaris.org 14411230Sgdamore@opensolaris.org int cmax; 14511230Sgdamore@opensolaris.org cinfo_t *controls; 14611230Sgdamore@opensolaris.org 14711230Sgdamore@opensolaris.org int mfd; 14811230Sgdamore@opensolaris.org dev_t devt; 14911230Sgdamore@opensolaris.org 15011230Sgdamore@opensolaris.org struct device *nextp; 15111230Sgdamore@opensolaris.org } device_t; 15211230Sgdamore@opensolaris.org 15311230Sgdamore@opensolaris.org static device_t *devices = NULL; 15411230Sgdamore@opensolaris.org 15511230Sgdamore@opensolaris.org /*PRINTFLIKE1*/ 15611230Sgdamore@opensolaris.org static void 15711230Sgdamore@opensolaris.org msg(char *fmt, ...) 15811230Sgdamore@opensolaris.org { 15911230Sgdamore@opensolaris.org va_list ap; 16011230Sgdamore@opensolaris.org 16111230Sgdamore@opensolaris.org va_start(ap, fmt); 16211230Sgdamore@opensolaris.org (void) vprintf(fmt, ap); 16311230Sgdamore@opensolaris.org va_end(ap); 16411230Sgdamore@opensolaris.org } 16511230Sgdamore@opensolaris.org 16611230Sgdamore@opensolaris.org /*PRINTFLIKE1*/ 16711230Sgdamore@opensolaris.org static void 16811230Sgdamore@opensolaris.org warn(char *fmt, ...) 16911230Sgdamore@opensolaris.org { 17011230Sgdamore@opensolaris.org va_list ap; 17111230Sgdamore@opensolaris.org 17211230Sgdamore@opensolaris.org va_start(ap, fmt); 17311230Sgdamore@opensolaris.org (void) vfprintf(stderr, fmt, ap); 17411230Sgdamore@opensolaris.org va_end(ap); 17511230Sgdamore@opensolaris.org } 17611230Sgdamore@opensolaris.org 17711230Sgdamore@opensolaris.org static void 17811230Sgdamore@opensolaris.org free_device(device_t *d) 17911230Sgdamore@opensolaris.org { 18011230Sgdamore@opensolaris.org int i; 18111230Sgdamore@opensolaris.org device_t **dpp; 18211230Sgdamore@opensolaris.org 18311230Sgdamore@opensolaris.org dpp = &devices; 18411230Sgdamore@opensolaris.org while ((*dpp) && ((*dpp) != d)) { 18511230Sgdamore@opensolaris.org dpp = &((*dpp)->nextp); 18611230Sgdamore@opensolaris.org } 18711230Sgdamore@opensolaris.org if (*dpp) { 18811230Sgdamore@opensolaris.org *dpp = d->nextp; 18911230Sgdamore@opensolaris.org } 19011230Sgdamore@opensolaris.org for (i = 0; i < d->cmax; i++) { 19111230Sgdamore@opensolaris.org if (d->controls[i].enump != NULL) 19211230Sgdamore@opensolaris.org free(d->controls[i].enump); 19311230Sgdamore@opensolaris.org } 19411230Sgdamore@opensolaris.org 19511230Sgdamore@opensolaris.org if (d->mfd >= 0) 19611230Sgdamore@opensolaris.org (void) close(d->mfd); 19711230Sgdamore@opensolaris.org 19811230Sgdamore@opensolaris.org free(d); 19911230Sgdamore@opensolaris.org } 20011230Sgdamore@opensolaris.org 20111230Sgdamore@opensolaris.org static void 20211230Sgdamore@opensolaris.org free_devices(void) 20311230Sgdamore@opensolaris.org { 20411230Sgdamore@opensolaris.org device_t *d = devices; 20511230Sgdamore@opensolaris.org 20611230Sgdamore@opensolaris.org while ((d = devices) != NULL) { 20711230Sgdamore@opensolaris.org free_device(d); 20811230Sgdamore@opensolaris.org } 20911230Sgdamore@opensolaris.org 21011230Sgdamore@opensolaris.org devices = NULL; 21111230Sgdamore@opensolaris.org } 21211230Sgdamore@opensolaris.org 21311230Sgdamore@opensolaris.org 21411230Sgdamore@opensolaris.org /* 21511230Sgdamore@opensolaris.org * adds to the end of global devices and returns a pointer to the new entry 21611230Sgdamore@opensolaris.org */ 21711230Sgdamore@opensolaris.org static device_t * 21811230Sgdamore@opensolaris.org alloc_device(void) 21911230Sgdamore@opensolaris.org { 22011230Sgdamore@opensolaris.org device_t *p; 22111230Sgdamore@opensolaris.org device_t *d = calloc(1, sizeof (*d)); 22211230Sgdamore@opensolaris.org 22311230Sgdamore@opensolaris.org d->card.card = -1; 22411230Sgdamore@opensolaris.org d->mixer.dev = -1; 22511230Sgdamore@opensolaris.org d->mfd = -1; 22611230Sgdamore@opensolaris.org 22711230Sgdamore@opensolaris.org if (devices == NULL) { 22811230Sgdamore@opensolaris.org devices = d; 22911230Sgdamore@opensolaris.org } else { 23011230Sgdamore@opensolaris.org for (p = devices; p->nextp != NULL; p = p->nextp) {} 23111230Sgdamore@opensolaris.org 23211230Sgdamore@opensolaris.org p->nextp = d; 23311230Sgdamore@opensolaris.org } 23411230Sgdamore@opensolaris.org return (d); 23511230Sgdamore@opensolaris.org } 23611230Sgdamore@opensolaris.org 23711230Sgdamore@opensolaris.org 23811230Sgdamore@opensolaris.org /* 23911230Sgdamore@opensolaris.org * cinfop->enump needs to be present 24011230Sgdamore@opensolaris.org * idx should be: >= 0 to < cinfop->ci.maxvalue 24111230Sgdamore@opensolaris.org */ 24211230Sgdamore@opensolaris.org static char * 24311230Sgdamore@opensolaris.org get_enum_str(cinfo_t *cinfop, int idx) 24411230Sgdamore@opensolaris.org { 24511230Sgdamore@opensolaris.org int sz = sizeof (*cinfop->ci.enum_present) * 8; 24611230Sgdamore@opensolaris.org 24711230Sgdamore@opensolaris.org if (cinfop->ci.enum_present[idx / sz] & (1 << (idx % sz))) 24811230Sgdamore@opensolaris.org return (cinfop->enump->strings + cinfop->enump->strindex[idx]); 24911230Sgdamore@opensolaris.org 25011230Sgdamore@opensolaris.org return (NULL); 25111230Sgdamore@opensolaris.org } 25211230Sgdamore@opensolaris.org 25311230Sgdamore@opensolaris.org 25411230Sgdamore@opensolaris.org /* 25511230Sgdamore@opensolaris.org * caller fills in d->mixer.devnode; func fills in the rest 25611230Sgdamore@opensolaris.org */ 25711230Sgdamore@opensolaris.org static int 25811230Sgdamore@opensolaris.org get_device_info(device_t *d) 25911230Sgdamore@opensolaris.org { 26011230Sgdamore@opensolaris.org int fd = -1; 26111230Sgdamore@opensolaris.org int i; 26211230Sgdamore@opensolaris.org cinfo_t *ci; 26311230Sgdamore@opensolaris.org 26411230Sgdamore@opensolaris.org if ((fd = open(d->mixer.devnode, O_RDWR)) < 0) { 26511230Sgdamore@opensolaris.org perror(_("Error opening device")); 26611230Sgdamore@opensolaris.org return (errno); 26711230Sgdamore@opensolaris.org } 26811230Sgdamore@opensolaris.org d->mfd = fd; 26911230Sgdamore@opensolaris.org 27011230Sgdamore@opensolaris.org d->cmax = -1; 27111230Sgdamore@opensolaris.org if (ioctl(fd, SNDCTL_MIX_NREXT, &d->cmax) < 0) { 27211230Sgdamore@opensolaris.org perror(_("Error getting control count")); 27311230Sgdamore@opensolaris.org return (errno); 27411230Sgdamore@opensolaris.org } 27511230Sgdamore@opensolaris.org 27611230Sgdamore@opensolaris.org d->controls = calloc(d->cmax, sizeof (*d->controls)); 27711230Sgdamore@opensolaris.org 27811230Sgdamore@opensolaris.org for (i = 0; i < d->cmax; i++) { 27911230Sgdamore@opensolaris.org ci = &d->controls[i]; 28011230Sgdamore@opensolaris.org 28111230Sgdamore@opensolaris.org ci->ci.dev = -1; 28211230Sgdamore@opensolaris.org ci->ci.ctrl = i; 28311230Sgdamore@opensolaris.org 28411230Sgdamore@opensolaris.org if (ioctl(fd, SNDCTL_MIX_EXTINFO, &ci->ci) < 0) { 28511230Sgdamore@opensolaris.org perror(_("Error getting control info")); 28611230Sgdamore@opensolaris.org return (errno); 28711230Sgdamore@opensolaris.org } 28811230Sgdamore@opensolaris.org 28911230Sgdamore@opensolaris.org if (ci->ci.type == MIXT_ENUM) { 29011230Sgdamore@opensolaris.org ci->enump = calloc(1, sizeof (*ci->enump)); 29111230Sgdamore@opensolaris.org ci->enump->dev = -1; 29211230Sgdamore@opensolaris.org ci->enump->ctrl = ci->ci.ctrl; 29311230Sgdamore@opensolaris.org 29411230Sgdamore@opensolaris.org if (ioctl(fd, SNDCTL_MIX_ENUMINFO, ci->enump) < 0) { 29511230Sgdamore@opensolaris.org perror(_("Error getting enum info")); 29611230Sgdamore@opensolaris.org return (errno); 29711230Sgdamore@opensolaris.org } 29811230Sgdamore@opensolaris.org } 29911230Sgdamore@opensolaris.org } 30011230Sgdamore@opensolaris.org 30111230Sgdamore@opensolaris.org return (0); 30211230Sgdamore@opensolaris.org } 30311230Sgdamore@opensolaris.org 30411230Sgdamore@opensolaris.org 30511230Sgdamore@opensolaris.org static int 30611230Sgdamore@opensolaris.org load_devices(void) 30711230Sgdamore@opensolaris.org { 30811230Sgdamore@opensolaris.org int rv = -1; 30911230Sgdamore@opensolaris.org int fd = -1; 31011230Sgdamore@opensolaris.org int i; 31111230Sgdamore@opensolaris.org oss_sysinfo si; 31211230Sgdamore@opensolaris.org device_t *d; 31311230Sgdamore@opensolaris.org 314*11253Sgdamore@opensolaris.org if (devices != NULL) { 315*11253Sgdamore@opensolaris.org /* already loaded */ 316*11253Sgdamore@opensolaris.org return (0); 317*11253Sgdamore@opensolaris.org } 318*11253Sgdamore@opensolaris.org 31911230Sgdamore@opensolaris.org if ((fd = open("/dev/mixer", O_RDWR)) < 0) { 32011230Sgdamore@opensolaris.org rv = errno; 32111230Sgdamore@opensolaris.org warn(_("Error opening mixer\n")); 32211230Sgdamore@opensolaris.org goto OUT; 32311230Sgdamore@opensolaris.org } 32411230Sgdamore@opensolaris.org 32511230Sgdamore@opensolaris.org if (ioctl(fd, SNDCTL_SYSINFO, &si) < 0) { 32611230Sgdamore@opensolaris.org rv = errno; 32711230Sgdamore@opensolaris.org perror(_("Error getting system information")); 32811230Sgdamore@opensolaris.org goto OUT; 32911230Sgdamore@opensolaris.org } 33011230Sgdamore@opensolaris.org 33111230Sgdamore@opensolaris.org for (i = 0; i < si.nummixers; i++) { 33211230Sgdamore@opensolaris.org 33311230Sgdamore@opensolaris.org struct stat sbuf; 33411230Sgdamore@opensolaris.org 33511230Sgdamore@opensolaris.org d = alloc_device(); 33611230Sgdamore@opensolaris.org d->mixer.dev = i; 33711230Sgdamore@opensolaris.org 33811230Sgdamore@opensolaris.org if (ioctl(fd, SNDCTL_MIXERINFO, &d->mixer) != 0) { 33911230Sgdamore@opensolaris.org continue; 34011230Sgdamore@opensolaris.org } 34111230Sgdamore@opensolaris.org 34211230Sgdamore@opensolaris.org d->card.card = d->mixer.card_number; 34311230Sgdamore@opensolaris.org 34411230Sgdamore@opensolaris.org if ((ioctl(fd, SNDCTL_CARDINFO, &d->card) != 0) || 34511230Sgdamore@opensolaris.org (stat(d->mixer.devnode, &sbuf) != 0) || 34611230Sgdamore@opensolaris.org ((sbuf.st_mode & S_IFCHR) == 0)) { 34711230Sgdamore@opensolaris.org warn(_("Device present: %s\n"), d->mixer.devnode); 34811230Sgdamore@opensolaris.org free_device(d); 34911230Sgdamore@opensolaris.org continue; 35011230Sgdamore@opensolaris.org } 35111230Sgdamore@opensolaris.org d->devt = makedev(major(sbuf.st_rdev), 35211230Sgdamore@opensolaris.org minor(sbuf.st_rdev) & ~(AUDIO_MN_TYPE_MASK)); 35311230Sgdamore@opensolaris.org 35411230Sgdamore@opensolaris.org if ((rv = get_device_info(d)) != 0) { 35511230Sgdamore@opensolaris.org free_device(d); 35611230Sgdamore@opensolaris.org goto OUT; 35711230Sgdamore@opensolaris.org } 35811230Sgdamore@opensolaris.org } 35911230Sgdamore@opensolaris.org 36011230Sgdamore@opensolaris.org rv = 0; 36111230Sgdamore@opensolaris.org 36211230Sgdamore@opensolaris.org OUT: 36311230Sgdamore@opensolaris.org if (fd >= 0) 36411230Sgdamore@opensolaris.org (void) close(fd); 36511230Sgdamore@opensolaris.org return (rv); 36611230Sgdamore@opensolaris.org } 36711230Sgdamore@opensolaris.org 36811230Sgdamore@opensolaris.org 36911230Sgdamore@opensolaris.org static int 37011230Sgdamore@opensolaris.org ctype_valid(int type) 37111230Sgdamore@opensolaris.org { 37211230Sgdamore@opensolaris.org switch (type) { 37311230Sgdamore@opensolaris.org case MIXT_ONOFF: 37411230Sgdamore@opensolaris.org case MIXT_ENUM: 37511230Sgdamore@opensolaris.org case MIXT_MONOSLIDER: 37611230Sgdamore@opensolaris.org case MIXT_STEREOSLIDER: 37711230Sgdamore@opensolaris.org return (1); 37811230Sgdamore@opensolaris.org default: 37911230Sgdamore@opensolaris.org return (0); 38011230Sgdamore@opensolaris.org } 38111230Sgdamore@opensolaris.org } 38211230Sgdamore@opensolaris.org 38311230Sgdamore@opensolaris.org 38411230Sgdamore@opensolaris.org static void 38511230Sgdamore@opensolaris.org print_control_line(FILE *sfp, col_prt_t *colp, int vopt) 38611230Sgdamore@opensolaris.org { 38711230Sgdamore@opensolaris.org int i; 38811230Sgdamore@opensolaris.org size_t *col_prtp; 38911230Sgdamore@opensolaris.org int *col_dpyp; 39011230Sgdamore@opensolaris.org int col_cnt; 39111230Sgdamore@opensolaris.org int col_type; 39211230Sgdamore@opensolaris.org int width; 39311230Sgdamore@opensolaris.org char *colstr; 39411230Sgdamore@opensolaris.org char cbuf[COL_MAX_SZ + 1]; 39511230Sgdamore@opensolaris.org char line[128]; 39611230Sgdamore@opensolaris.org char *colsep = " "; 39711230Sgdamore@opensolaris.org 39811230Sgdamore@opensolaris.org if (sfp != NULL) { 39911230Sgdamore@opensolaris.org col_prtp = col_dpy_prt_tofile; 40011230Sgdamore@opensolaris.org col_dpyp = col_dpy_tofile; 40111230Sgdamore@opensolaris.org col_cnt = col_dpy_tofile_len; 40211230Sgdamore@opensolaris.org } else if (vopt) { 40311230Sgdamore@opensolaris.org col_prtp = col_dpy_prt_vopt; 40411230Sgdamore@opensolaris.org col_dpyp = col_dpy_vopt; 40511230Sgdamore@opensolaris.org col_cnt = col_dpy_vopt_len; 40611230Sgdamore@opensolaris.org } else { 40711230Sgdamore@opensolaris.org col_prtp = col_dpy_prt; 40811230Sgdamore@opensolaris.org col_dpyp = col_dpy; 40911230Sgdamore@opensolaris.org col_cnt = col_dpy_len; 41011230Sgdamore@opensolaris.org } 41111230Sgdamore@opensolaris.org 41211230Sgdamore@opensolaris.org line[0] = '\0'; 41311230Sgdamore@opensolaris.org 41411230Sgdamore@opensolaris.org for (i = 0; i < col_cnt; i++) { 41511230Sgdamore@opensolaris.org col_type = col_dpyp[i]; 41611230Sgdamore@opensolaris.org width = col_sz[col_type]; 41711230Sgdamore@opensolaris.org colstr = *(char **)(((size_t)colp) + col_prtp[i]); 41811230Sgdamore@opensolaris.org 41911230Sgdamore@opensolaris.org (void) snprintf(cbuf, sizeof (cbuf), "%- *s", 42011230Sgdamore@opensolaris.org width > 0 ? width : 1, 42111230Sgdamore@opensolaris.org (colstr == NULL) ? "" : colstr); 42211230Sgdamore@opensolaris.org 42311230Sgdamore@opensolaris.org (void) strlcat(line, cbuf, sizeof (line)); 42411230Sgdamore@opensolaris.org if (i < col_cnt - 1) 42511230Sgdamore@opensolaris.org (void) strlcat(line, colsep, sizeof (line)); 42611230Sgdamore@opensolaris.org } 42711230Sgdamore@opensolaris.org 42811230Sgdamore@opensolaris.org (void) fprintf(sfp ? sfp : stdout, "%s\n", line); 42911230Sgdamore@opensolaris.org } 43011230Sgdamore@opensolaris.org 43111230Sgdamore@opensolaris.org 43211230Sgdamore@opensolaris.org static void 43311230Sgdamore@opensolaris.org print_header(FILE *sfp, int vopt) 43411230Sgdamore@opensolaris.org { 43511230Sgdamore@opensolaris.org col_prt_t col; 43611230Sgdamore@opensolaris.org 43711230Sgdamore@opensolaris.org if (sfp) { 43811230Sgdamore@opensolaris.org col.col_nm = _("#CONTROL"); 43911230Sgdamore@opensolaris.org col.col_val = _("VALUE"); 44011230Sgdamore@opensolaris.org } else { 44111230Sgdamore@opensolaris.org col.col_dv = _("DEVICE"); 44211230Sgdamore@opensolaris.org col.col_nm = _("CONTROL"); 44311230Sgdamore@opensolaris.org col.col_val = _("VALUE"); 44411230Sgdamore@opensolaris.org col.col_sel = _("POSSIBLE"); 44511230Sgdamore@opensolaris.org } 44611230Sgdamore@opensolaris.org print_control_line(sfp, &col, vopt); 44711230Sgdamore@opensolaris.org } 44811230Sgdamore@opensolaris.org 44911230Sgdamore@opensolaris.org 45011230Sgdamore@opensolaris.org static int 45111230Sgdamore@opensolaris.org print_control(FILE *sfp, device_t *d, cinfo_t *cinfop, int vopt) 45211230Sgdamore@opensolaris.org { 45311230Sgdamore@opensolaris.org int mfd = d->mfd; 45411230Sgdamore@opensolaris.org char *devnm = d->card.shortname; 45511230Sgdamore@opensolaris.org oss_mixer_value cval; 45611230Sgdamore@opensolaris.org char *str; 45711230Sgdamore@opensolaris.org int i; 45811230Sgdamore@opensolaris.org int idx = -1; 45911230Sgdamore@opensolaris.org int rv = -1; 46011230Sgdamore@opensolaris.org char valbuf[COL_VAL_SZ + 1]; 46111230Sgdamore@opensolaris.org char selbuf[COL_SEL_SZ + 1]; 46211230Sgdamore@opensolaris.org col_prt_t col; 46311230Sgdamore@opensolaris.org 46411230Sgdamore@opensolaris.org cval.dev = -1; 46511230Sgdamore@opensolaris.org cval.ctrl = cinfop->ci.ctrl; 46611230Sgdamore@opensolaris.org 46711230Sgdamore@opensolaris.org if (ctype_valid(cinfop->ci.type)) { 46811230Sgdamore@opensolaris.org if (ioctl(mfd, SNDCTL_MIX_READ, &cval) < 0) { 46911230Sgdamore@opensolaris.org rv = errno; 47011230Sgdamore@opensolaris.org perror(_("Error reading control\n")); 47111230Sgdamore@opensolaris.org return (rv); 47211230Sgdamore@opensolaris.org } 47311230Sgdamore@opensolaris.org } else { 47411230Sgdamore@opensolaris.org return (0); 47511230Sgdamore@opensolaris.org } 47611230Sgdamore@opensolaris.org 47711230Sgdamore@opensolaris.org /* 47811230Sgdamore@opensolaris.org * convert the control value into a string 47911230Sgdamore@opensolaris.org */ 48011230Sgdamore@opensolaris.org switch (cinfop->ci.type) { 48111230Sgdamore@opensolaris.org case MIXT_ONOFF: 48211230Sgdamore@opensolaris.org (void) snprintf(valbuf, sizeof (valbuf), "%s", 48311230Sgdamore@opensolaris.org cval.value ? _("on") : _("off")); 48411230Sgdamore@opensolaris.org break; 48511230Sgdamore@opensolaris.org 48611230Sgdamore@opensolaris.org case MIXT_MONOSLIDER: 48711230Sgdamore@opensolaris.org (void) snprintf(valbuf, sizeof (valbuf), "%d", 48811230Sgdamore@opensolaris.org cval.value & 0xff); 48911230Sgdamore@opensolaris.org break; 49011230Sgdamore@opensolaris.org 49111230Sgdamore@opensolaris.org case MIXT_STEREOSLIDER: 49211230Sgdamore@opensolaris.org (void) snprintf(valbuf, sizeof (valbuf), "%d:%d", 49311230Sgdamore@opensolaris.org (int)AUDIO_CTRL_STEREO_LEFT(cval.value), 49411230Sgdamore@opensolaris.org (int)AUDIO_CTRL_STEREO_RIGHT(cval.value)); 49511230Sgdamore@opensolaris.org break; 49611230Sgdamore@opensolaris.org 49711230Sgdamore@opensolaris.org case MIXT_ENUM: 49811230Sgdamore@opensolaris.org str = get_enum_str(cinfop, cval.value); 49911230Sgdamore@opensolaris.org if (str == NULL) { 50011230Sgdamore@opensolaris.org warn(_("Bad enum index %d for control '%s'\n"), 50111230Sgdamore@opensolaris.org cval.value, cinfop->ci.extname); 50211230Sgdamore@opensolaris.org return (EINVAL); 50311230Sgdamore@opensolaris.org } 50411230Sgdamore@opensolaris.org 50511230Sgdamore@opensolaris.org (void) snprintf(valbuf, sizeof (valbuf), "%s", str); 50611230Sgdamore@opensolaris.org break; 50711230Sgdamore@opensolaris.org 50811230Sgdamore@opensolaris.org default: 50911230Sgdamore@opensolaris.org return (0); 51011230Sgdamore@opensolaris.org } 51111230Sgdamore@opensolaris.org 51211230Sgdamore@opensolaris.org /* 51311230Sgdamore@opensolaris.org * possible control values (range/selection) 51411230Sgdamore@opensolaris.org */ 51511230Sgdamore@opensolaris.org switch (cinfop->ci.type) { 51611230Sgdamore@opensolaris.org case MIXT_ONOFF: 51711230Sgdamore@opensolaris.org (void) snprintf(selbuf, sizeof (selbuf), _("on,off")); 51811230Sgdamore@opensolaris.org break; 51911230Sgdamore@opensolaris.org 52011230Sgdamore@opensolaris.org case MIXT_MONOSLIDER: 52111230Sgdamore@opensolaris.org (void) snprintf(selbuf, sizeof (selbuf), "%d-%d", 52211230Sgdamore@opensolaris.org cinfop->ci.minvalue, cinfop->ci.maxvalue); 52311230Sgdamore@opensolaris.org break; 52411230Sgdamore@opensolaris.org case MIXT_STEREOSLIDER: 52511230Sgdamore@opensolaris.org (void) snprintf(selbuf, sizeof (selbuf), "%d-%d:%d-%d", 52611230Sgdamore@opensolaris.org cinfop->ci.minvalue, cinfop->ci.maxvalue, 52711230Sgdamore@opensolaris.org cinfop->ci.minvalue, cinfop->ci.maxvalue); 52811230Sgdamore@opensolaris.org break; 52911230Sgdamore@opensolaris.org 53011230Sgdamore@opensolaris.org case MIXT_ENUM: 53111230Sgdamore@opensolaris.org /* 53211230Sgdamore@opensolaris.org * display the first choice on the same line, then display 53311230Sgdamore@opensolaris.org * the rest on multiple lines 53411230Sgdamore@opensolaris.org */ 53511230Sgdamore@opensolaris.org selbuf[0] = 0; 53611230Sgdamore@opensolaris.org for (i = 0; i < cinfop->ci.maxvalue; i++) { 53711230Sgdamore@opensolaris.org str = get_enum_str(cinfop, i); 53811230Sgdamore@opensolaris.org if (str == NULL) 53911230Sgdamore@opensolaris.org continue; 54011230Sgdamore@opensolaris.org 54111230Sgdamore@opensolaris.org if ((strlen(str) + 1 + strlen(selbuf)) >= 54211230Sgdamore@opensolaris.org sizeof (selbuf)) { 54311230Sgdamore@opensolaris.org break; 54411230Sgdamore@opensolaris.org } 54511230Sgdamore@opensolaris.org if (strlen(selbuf)) { 54611230Sgdamore@opensolaris.org (void) strlcat(selbuf, ",", sizeof (selbuf)); 54711230Sgdamore@opensolaris.org } 54811230Sgdamore@opensolaris.org 54911230Sgdamore@opensolaris.org (void) strlcat(selbuf, str, sizeof (selbuf)); 55011230Sgdamore@opensolaris.org } 55111230Sgdamore@opensolaris.org idx = i; 55211230Sgdamore@opensolaris.org break; 55311230Sgdamore@opensolaris.org 55411230Sgdamore@opensolaris.org default: 55511230Sgdamore@opensolaris.org (void) snprintf(selbuf, sizeof (selbuf), "-"); 55611230Sgdamore@opensolaris.org } 55711230Sgdamore@opensolaris.org 55811230Sgdamore@opensolaris.org col.col_dv = devnm; 55911230Sgdamore@opensolaris.org col.col_nm = strlen(cinfop->ci.extname) ? 56011230Sgdamore@opensolaris.org cinfop->ci.extname : cinfop->ci.id; 56111230Sgdamore@opensolaris.org while (strchr(col.col_nm, '_') != NULL) { 56211230Sgdamore@opensolaris.org col.col_nm = strchr(col.col_nm, '_') + 1; 56311230Sgdamore@opensolaris.org } 56411230Sgdamore@opensolaris.org col.col_val = valbuf; 56511230Sgdamore@opensolaris.org col.col_sel = selbuf; 56611230Sgdamore@opensolaris.org print_control_line(sfp, &col, vopt); 56711230Sgdamore@opensolaris.org 56811230Sgdamore@opensolaris.org /* print leftover enum value selections */ 56911230Sgdamore@opensolaris.org while ((sfp == NULL) && (idx >= 0) && (idx < cinfop->ci.maxvalue)) { 57011230Sgdamore@opensolaris.org selbuf[0] = 0; 57111230Sgdamore@opensolaris.org for (i = idx; i < cinfop->ci.maxvalue; i++) { 57211230Sgdamore@opensolaris.org str = get_enum_str(cinfop, i); 57311230Sgdamore@opensolaris.org if (str == NULL) 57411230Sgdamore@opensolaris.org continue; 57511230Sgdamore@opensolaris.org 57611230Sgdamore@opensolaris.org if ((strlen(str) + 1 + strlen(selbuf)) >= 57711230Sgdamore@opensolaris.org sizeof (selbuf)) { 57811230Sgdamore@opensolaris.org break; 57911230Sgdamore@opensolaris.org } 58011230Sgdamore@opensolaris.org if (strlen(selbuf)) { 58111230Sgdamore@opensolaris.org (void) strlcat(selbuf, ",", sizeof (selbuf)); 58211230Sgdamore@opensolaris.org } 58311230Sgdamore@opensolaris.org 58411230Sgdamore@opensolaris.org (void) strlcat(selbuf, str, sizeof (selbuf)); 58511230Sgdamore@opensolaris.org } 58611230Sgdamore@opensolaris.org idx = i; 58711230Sgdamore@opensolaris.org col.col_dv = NULL; 58811230Sgdamore@opensolaris.org col.col_nm = NULL; 58911230Sgdamore@opensolaris.org col.col_val = NULL; 59011230Sgdamore@opensolaris.org col.col_sel = selbuf; 59111230Sgdamore@opensolaris.org print_control_line(sfp, &col, vopt); 59211230Sgdamore@opensolaris.org } 59311230Sgdamore@opensolaris.org 59411230Sgdamore@opensolaris.org return (0); 59511230Sgdamore@opensolaris.org } 59611230Sgdamore@opensolaris.org 59711230Sgdamore@opensolaris.org 59811230Sgdamore@opensolaris.org static int 59911230Sgdamore@opensolaris.org set_device_control(device_t *d, cinfo_t *cinfop, char *wstr, int vopt) 60011230Sgdamore@opensolaris.org { 60111230Sgdamore@opensolaris.org int mfd = d->mfd; 60211230Sgdamore@opensolaris.org oss_mixer_value cval; 60311230Sgdamore@opensolaris.org int wlen = strlen(wstr); 60411230Sgdamore@opensolaris.org int lval, rval; 60511230Sgdamore@opensolaris.org char *lstr, *rstr; 60611230Sgdamore@opensolaris.org char *str; 60711230Sgdamore@opensolaris.org int i; 60811230Sgdamore@opensolaris.org int rv = -1; 60911230Sgdamore@opensolaris.org 61011230Sgdamore@opensolaris.org cval.dev = -1; 61111230Sgdamore@opensolaris.org cval.ctrl = cinfop->ci.ctrl; 61211230Sgdamore@opensolaris.org cval.value = 0; 61311230Sgdamore@opensolaris.org 61411230Sgdamore@opensolaris.org switch (cinfop->ci.type) { 61511230Sgdamore@opensolaris.org case MIXT_ONOFF: 61611230Sgdamore@opensolaris.org cval.value = (strncmp(_("on"), wstr, wlen) == 0) ? 1 : 0; 61711230Sgdamore@opensolaris.org break; 61811230Sgdamore@opensolaris.org 61911230Sgdamore@opensolaris.org case MIXT_MONOSLIDER: 62011230Sgdamore@opensolaris.org cval.value = atoi(wstr); 62111230Sgdamore@opensolaris.org break; 62211230Sgdamore@opensolaris.org 62311230Sgdamore@opensolaris.org case MIXT_STEREOSLIDER: 62411230Sgdamore@opensolaris.org lstr = wstr; 62511230Sgdamore@opensolaris.org rstr = strchr(wstr, ':'); 62611230Sgdamore@opensolaris.org if (rstr != NULL) { 62711230Sgdamore@opensolaris.org *rstr = '\0'; 62811230Sgdamore@opensolaris.org rstr++; 62911230Sgdamore@opensolaris.org 63011230Sgdamore@opensolaris.org rval = atoi(rstr); 63111230Sgdamore@opensolaris.org lval = atoi(lstr); 63211230Sgdamore@opensolaris.org 63311230Sgdamore@opensolaris.org rstr--; 63411230Sgdamore@opensolaris.org *rstr = ':'; 63511230Sgdamore@opensolaris.org } else { 63611230Sgdamore@opensolaris.org lval = atoi(lstr); 63711230Sgdamore@opensolaris.org rval = lval; 63811230Sgdamore@opensolaris.org } 63911230Sgdamore@opensolaris.org 64011230Sgdamore@opensolaris.org cval.value = AUDIO_CTRL_STEREO_VAL(lval, rval); 64111230Sgdamore@opensolaris.org break; 64211230Sgdamore@opensolaris.org 64311230Sgdamore@opensolaris.org case MIXT_ENUM: 64411230Sgdamore@opensolaris.org for (i = 0; i < cinfop->ci.maxvalue; i++) { 64511230Sgdamore@opensolaris.org str = get_enum_str(cinfop, i); 64611230Sgdamore@opensolaris.org if (str == NULL) 64711230Sgdamore@opensolaris.org continue; 64811230Sgdamore@opensolaris.org 64911230Sgdamore@opensolaris.org if (strncmp(wstr, str, wlen) == 0) { 65011230Sgdamore@opensolaris.org cval.value = i; 65111230Sgdamore@opensolaris.org break; 65211230Sgdamore@opensolaris.org } 65311230Sgdamore@opensolaris.org } 65411230Sgdamore@opensolaris.org 65511230Sgdamore@opensolaris.org if (i >= cinfop->ci.maxvalue) { 65611230Sgdamore@opensolaris.org warn(_("Invalid enumeration value\n")); 65711230Sgdamore@opensolaris.org return (EINVAL); 65811230Sgdamore@opensolaris.org } 65911230Sgdamore@opensolaris.org break; 66011230Sgdamore@opensolaris.org 66111230Sgdamore@opensolaris.org default: 66211230Sgdamore@opensolaris.org warn(_("Unsupported control type: %d\n"), cinfop->ci.type); 66311230Sgdamore@opensolaris.org return (EINVAL); 66411230Sgdamore@opensolaris.org } 66511230Sgdamore@opensolaris.org 66611230Sgdamore@opensolaris.org if (vopt) { 66711230Sgdamore@opensolaris.org msg(_("%s: '%s' set to '%s'\n"), d->card.shortname, 66811230Sgdamore@opensolaris.org cinfop->ci.extname, wstr); 66911230Sgdamore@opensolaris.org } 67011230Sgdamore@opensolaris.org 67111230Sgdamore@opensolaris.org if (ioctl(mfd, SNDCTL_MIX_WRITE, &cval) < 0) { 67211230Sgdamore@opensolaris.org rv = errno; 67311230Sgdamore@opensolaris.org perror(_("Error writing control")); 67411230Sgdamore@opensolaris.org return (rv); 67511230Sgdamore@opensolaris.org } 67611230Sgdamore@opensolaris.org 67711230Sgdamore@opensolaris.org rv = 0; 67811230Sgdamore@opensolaris.org return (rv); 67911230Sgdamore@opensolaris.org } 68011230Sgdamore@opensolaris.org 68111230Sgdamore@opensolaris.org 68211230Sgdamore@opensolaris.org static void 68311230Sgdamore@opensolaris.org help(void) 68411230Sgdamore@opensolaris.org { 68511230Sgdamore@opensolaris.org #define HELP_STR _( \ 68611230Sgdamore@opensolaris.org "audioctl list-devices\n" \ 68711230Sgdamore@opensolaris.org " list all audio devices\n" \ 68811230Sgdamore@opensolaris.org "\n" \ 68911230Sgdamore@opensolaris.org "audioctl show-device [ -v ] [ -d <device> ]\n" \ 69011230Sgdamore@opensolaris.org " display information about an audio device\n" \ 69111230Sgdamore@opensolaris.org "\n" \ 69211230Sgdamore@opensolaris.org "audioctl show-control [ -v ] [ -d <device> ] [ <control> ... ]\n" \ 69311230Sgdamore@opensolaris.org " get the value of a specific control (all if not specified)\n" \ 69411230Sgdamore@opensolaris.org "\n" \ 69511230Sgdamore@opensolaris.org "audioctl set-control [ -v ] [ -d <device> ] <control> <value>\n" \ 69611230Sgdamore@opensolaris.org " set the value of a specific control\n" \ 69711230Sgdamore@opensolaris.org "\n" \ 69811230Sgdamore@opensolaris.org "audioctl save-controls [ -d <device> ] [ -f ] <file>\n" \ 69911230Sgdamore@opensolaris.org " save all control settings for the device to a file\n" \ 70011230Sgdamore@opensolaris.org "\n" \ 70111230Sgdamore@opensolaris.org "audioctl load-controls [ -d <device> ] <file>\n" \ 70211230Sgdamore@opensolaris.org " restore previously saved control settings to device\n" \ 70311230Sgdamore@opensolaris.org "\n" \ 70411230Sgdamore@opensolaris.org "audioctl help\n" \ 70511230Sgdamore@opensolaris.org " show this message.\n") 70611230Sgdamore@opensolaris.org 70711230Sgdamore@opensolaris.org (void) fprintf(stderr, HELP_STR); 70811230Sgdamore@opensolaris.org } 70911230Sgdamore@opensolaris.org 71011230Sgdamore@opensolaris.org dev_t 71111230Sgdamore@opensolaris.org device_devt(char *name) 71211230Sgdamore@opensolaris.org { 71311230Sgdamore@opensolaris.org struct stat sbuf; 71411230Sgdamore@opensolaris.org 71511230Sgdamore@opensolaris.org if ((stat(name, &sbuf) != 0) || 71611230Sgdamore@opensolaris.org ((sbuf.st_mode & S_IFCHR) == 0)) { 71711230Sgdamore@opensolaris.org /* Not a device node! */ 71811230Sgdamore@opensolaris.org return (0); 71911230Sgdamore@opensolaris.org } 72011230Sgdamore@opensolaris.org 72111230Sgdamore@opensolaris.org return (makedev(major(sbuf.st_rdev), 72211230Sgdamore@opensolaris.org minor(sbuf.st_rdev) & ~(AUDIO_MN_TYPE_MASK))); 72311230Sgdamore@opensolaris.org } 72411230Sgdamore@opensolaris.org 72511230Sgdamore@opensolaris.org static device_t * 72611230Sgdamore@opensolaris.org find_device(char *name) 72711230Sgdamore@opensolaris.org { 72811230Sgdamore@opensolaris.org dev_t devt; 72911230Sgdamore@opensolaris.org device_t *d; 73011230Sgdamore@opensolaris.org 73111230Sgdamore@opensolaris.org /* 73211230Sgdamore@opensolaris.org * User may have specified: 73311230Sgdamore@opensolaris.org * 73411230Sgdamore@opensolaris.org * /dev/dsp[<num>] 73511230Sgdamore@opensolaris.org * /dev/mixer[<num>] 73611230Sgdamore@opensolaris.org * /dev/audio[<num>9] 73711230Sgdamore@opensolaris.org * /dev/audioctl[<num>] 73811230Sgdamore@opensolaris.org * /dev/sound/<num>{,ctl,dsp,mixer} 73911230Sgdamore@opensolaris.org * /dev/sound/<driver>:<num>{,ctl,dsp,mixer} 74011230Sgdamore@opensolaris.org * 74111230Sgdamore@opensolaris.org * We can canonicalize these by looking at the dev_t though. 74211230Sgdamore@opensolaris.org */ 74311230Sgdamore@opensolaris.org 744*11253Sgdamore@opensolaris.org if (load_devices() != 0) { 745*11253Sgdamore@opensolaris.org return (NULL); 746*11253Sgdamore@opensolaris.org } 747*11253Sgdamore@opensolaris.org 74811230Sgdamore@opensolaris.org if (name == NULL) 74911230Sgdamore@opensolaris.org name = getenv("AUDIODEV"); 75011230Sgdamore@opensolaris.org 75111230Sgdamore@opensolaris.org if ((name == NULL) || 75211230Sgdamore@opensolaris.org (strcmp(name, "/dev/mixer") == 0)) { 75311230Sgdamore@opensolaris.org /* /dev/mixer node doesn't point to real hw */ 75411230Sgdamore@opensolaris.org name = "/dev/dsp"; 75511230Sgdamore@opensolaris.org } 75611230Sgdamore@opensolaris.org 75711230Sgdamore@opensolaris.org if (*name == '/') { 75811230Sgdamore@opensolaris.org /* if we have a full path, convert to the devt */ 75911230Sgdamore@opensolaris.org if ((devt = device_devt(name)) == 0) { 76011230Sgdamore@opensolaris.org warn(_("No such audio device.\n")); 76111230Sgdamore@opensolaris.org return (NULL); 76211230Sgdamore@opensolaris.org } 76311230Sgdamore@opensolaris.org name = NULL; 76411230Sgdamore@opensolaris.org } 76511230Sgdamore@opensolaris.org 76611230Sgdamore@opensolaris.org for (d = devices; d != NULL; d = d->nextp) { 76711230Sgdamore@opensolaris.org oss_card_info *card = &d->card; 76811230Sgdamore@opensolaris.org 76911230Sgdamore@opensolaris.org if ((name) && (strcmp(name, card->shortname) == 0)) { 77011230Sgdamore@opensolaris.org return (d); 77111230Sgdamore@opensolaris.org } 77211230Sgdamore@opensolaris.org if (devt == d->devt) { 77311230Sgdamore@opensolaris.org return (d); 77411230Sgdamore@opensolaris.org } 77511230Sgdamore@opensolaris.org } 77611230Sgdamore@opensolaris.org 77711230Sgdamore@opensolaris.org warn(_("No such audio device.\n")); 77811230Sgdamore@opensolaris.org return (NULL); 77911230Sgdamore@opensolaris.org } 78011230Sgdamore@opensolaris.org 78111230Sgdamore@opensolaris.org int 78211230Sgdamore@opensolaris.org do_list_devices(int argc, char **argv) 78311230Sgdamore@opensolaris.org { 78411230Sgdamore@opensolaris.org int optc; 78511230Sgdamore@opensolaris.org int verbose = 0; 78611230Sgdamore@opensolaris.org device_t *d; 78711230Sgdamore@opensolaris.org 78811230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "v")) != EOF) { 78911230Sgdamore@opensolaris.org switch (optc) { 79011230Sgdamore@opensolaris.org case 'v': 79111230Sgdamore@opensolaris.org verbose++; 79211230Sgdamore@opensolaris.org break; 79311230Sgdamore@opensolaris.org default: 79411230Sgdamore@opensolaris.org help(); 79511230Sgdamore@opensolaris.org return (-1); 79611230Sgdamore@opensolaris.org } 79711230Sgdamore@opensolaris.org } 79811230Sgdamore@opensolaris.org argc -= optind; 79911230Sgdamore@opensolaris.org argv += optind; 80011230Sgdamore@opensolaris.org if (argc != 0) { 80111230Sgdamore@opensolaris.org help(); 80211230Sgdamore@opensolaris.org return (-1); 80311230Sgdamore@opensolaris.org } 80411230Sgdamore@opensolaris.org 805*11253Sgdamore@opensolaris.org if (load_devices() != 0) { 806*11253Sgdamore@opensolaris.org return (-1); 807*11253Sgdamore@opensolaris.org } 808*11253Sgdamore@opensolaris.org 80911230Sgdamore@opensolaris.org for (d = devices; d != NULL; d = d->nextp) { 81011230Sgdamore@opensolaris.org 81111230Sgdamore@opensolaris.org if ((d->mixer.enabled == 0) && (!verbose)) 81211230Sgdamore@opensolaris.org continue; 81311230Sgdamore@opensolaris.org 81411230Sgdamore@opensolaris.org if (verbose) { 81511230Sgdamore@opensolaris.org msg(_("%s (%s)\n"), d->card.shortname, 81611230Sgdamore@opensolaris.org d->mixer.devnode); 81711230Sgdamore@opensolaris.org } else { 81811230Sgdamore@opensolaris.org msg(_("%s\n"), d->card.shortname); 81911230Sgdamore@opensolaris.org } 82011230Sgdamore@opensolaris.org } 82111230Sgdamore@opensolaris.org 82211230Sgdamore@opensolaris.org return (0); 82311230Sgdamore@opensolaris.org } 82411230Sgdamore@opensolaris.org 82511230Sgdamore@opensolaris.org int 82611230Sgdamore@opensolaris.org do_show_device(int argc, char **argv) 82711230Sgdamore@opensolaris.org { 82811230Sgdamore@opensolaris.org int optc; 82911230Sgdamore@opensolaris.org char *devname = NULL; 83011230Sgdamore@opensolaris.org device_t *d; 83111230Sgdamore@opensolaris.org 83211230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:v")) != EOF) { 83311230Sgdamore@opensolaris.org switch (optc) { 83411230Sgdamore@opensolaris.org case 'd': 83511230Sgdamore@opensolaris.org devname = optarg; 83611230Sgdamore@opensolaris.org break; 83711230Sgdamore@opensolaris.org case 'v': 83811230Sgdamore@opensolaris.org break; 83911230Sgdamore@opensolaris.org default: 84011230Sgdamore@opensolaris.org help(); 84111230Sgdamore@opensolaris.org return (-1); 84211230Sgdamore@opensolaris.org } 84311230Sgdamore@opensolaris.org } 84411230Sgdamore@opensolaris.org argc -= optind; 84511230Sgdamore@opensolaris.org argv += optind; 84611230Sgdamore@opensolaris.org if (argc != 0) { 84711230Sgdamore@opensolaris.org help(); 84811230Sgdamore@opensolaris.org return (-1); 84911230Sgdamore@opensolaris.org } 85011230Sgdamore@opensolaris.org 85111230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 85211230Sgdamore@opensolaris.org return (ENODEV); 85311230Sgdamore@opensolaris.org } 85411230Sgdamore@opensolaris.org 85511230Sgdamore@opensolaris.org msg(_("Device: %s\n"), d->mixer.devnode); 85611230Sgdamore@opensolaris.org msg(_(" Name = %s\n"), d->card.shortname); 85711230Sgdamore@opensolaris.org msg(_(" Config = %s\n"), d->card.longname); 85811230Sgdamore@opensolaris.org 85911230Sgdamore@opensolaris.org if (strlen(d->card.hw_info)) { 86011230Sgdamore@opensolaris.org msg(_(" HW Info = %s"), d->card.hw_info); 86111230Sgdamore@opensolaris.org } 86211230Sgdamore@opensolaris.org 86311230Sgdamore@opensolaris.org return (0); 86411230Sgdamore@opensolaris.org } 86511230Sgdamore@opensolaris.org 86611230Sgdamore@opensolaris.org int 86711230Sgdamore@opensolaris.org do_show_control(int argc, char **argv) 86811230Sgdamore@opensolaris.org { 86911230Sgdamore@opensolaris.org int optc; 87011230Sgdamore@opensolaris.org int rval = 0; 87111230Sgdamore@opensolaris.org int verbose = 0; 87211230Sgdamore@opensolaris.org device_t *d; 87311230Sgdamore@opensolaris.org char *devname = NULL; 87411230Sgdamore@opensolaris.org int i; 87511230Sgdamore@opensolaris.org int j; 87611230Sgdamore@opensolaris.org int rv; 87711230Sgdamore@opensolaris.org char *n; 87811230Sgdamore@opensolaris.org cinfo_t *cinfop; 87911230Sgdamore@opensolaris.org 88011230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:v")) != EOF) { 88111230Sgdamore@opensolaris.org switch (optc) { 88211230Sgdamore@opensolaris.org case 'd': 88311230Sgdamore@opensolaris.org devname = optarg; 88411230Sgdamore@opensolaris.org break; 88511230Sgdamore@opensolaris.org case 'v': 88611230Sgdamore@opensolaris.org verbose++; 88711230Sgdamore@opensolaris.org break; 88811230Sgdamore@opensolaris.org default: 88911230Sgdamore@opensolaris.org help(); 89011230Sgdamore@opensolaris.org return (-1); 89111230Sgdamore@opensolaris.org } 89211230Sgdamore@opensolaris.org } 89311230Sgdamore@opensolaris.org argc -= optind; 89411230Sgdamore@opensolaris.org argv += optind; 89511230Sgdamore@opensolaris.org 89611230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 89711230Sgdamore@opensolaris.org return (ENODEV); 89811230Sgdamore@opensolaris.org } 89911230Sgdamore@opensolaris.org 90011230Sgdamore@opensolaris.org print_header(NULL, verbose); 90111230Sgdamore@opensolaris.org if (argc == 0) { 90211230Sgdamore@opensolaris.org /* do them all! */ 90311230Sgdamore@opensolaris.org for (i = 0; i < d->cmax; i++) { 90411230Sgdamore@opensolaris.org 90511230Sgdamore@opensolaris.org cinfop = &d->controls[i]; 90611230Sgdamore@opensolaris.org rv = print_control(NULL, d, cinfop, verbose); 90711230Sgdamore@opensolaris.org rval = rval ? rval : rv; 90811230Sgdamore@opensolaris.org } 90911230Sgdamore@opensolaris.org return (rval); 91011230Sgdamore@opensolaris.org } 91111230Sgdamore@opensolaris.org 91211230Sgdamore@opensolaris.org for (i = 0; i < argc; i++) { 91311230Sgdamore@opensolaris.org for (j = 0; j < d->cmax; j++) { 91411230Sgdamore@opensolaris.org cinfop = &d->controls[j]; 91511230Sgdamore@opensolaris.org n = strrchr(cinfop->ci.extname, '_'); 91611230Sgdamore@opensolaris.org n = n ? n + 1 : cinfop->ci.extname; 91711230Sgdamore@opensolaris.org if (strcmp(argv[i], n) == 0) { 91811230Sgdamore@opensolaris.org rv = print_control(NULL, d, cinfop, verbose); 91911230Sgdamore@opensolaris.org rval = rval ? rval : rv; 92011230Sgdamore@opensolaris.org break; 92111230Sgdamore@opensolaris.org } 92211230Sgdamore@opensolaris.org } 92311230Sgdamore@opensolaris.org /* Didn't find requested control */ 92411230Sgdamore@opensolaris.org if (j == d->cmax) { 92511230Sgdamore@opensolaris.org warn(_("No such control: %s\n"), argv[i]); 92611230Sgdamore@opensolaris.org rval = rval ? rval : ENODEV; 92711230Sgdamore@opensolaris.org } 92811230Sgdamore@opensolaris.org } 92911230Sgdamore@opensolaris.org 93011230Sgdamore@opensolaris.org return (rval); 93111230Sgdamore@opensolaris.org } 93211230Sgdamore@opensolaris.org 93311230Sgdamore@opensolaris.org int 93411230Sgdamore@opensolaris.org do_set_control(int argc, char **argv) 93511230Sgdamore@opensolaris.org { 93611230Sgdamore@opensolaris.org int optc; 93711230Sgdamore@opensolaris.org int rval = 0; 93811230Sgdamore@opensolaris.org int verbose = 0; 93911230Sgdamore@opensolaris.org device_t *d; 94011230Sgdamore@opensolaris.org char *devname = NULL; 94111230Sgdamore@opensolaris.org char *cname; 94211230Sgdamore@opensolaris.org char *value; 94311230Sgdamore@opensolaris.org int i; 94411230Sgdamore@opensolaris.org int found; 94511230Sgdamore@opensolaris.org int rv; 94611230Sgdamore@opensolaris.org char *n; 94711230Sgdamore@opensolaris.org cinfo_t *cinfop; 94811230Sgdamore@opensolaris.org 94911230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:v")) != EOF) { 95011230Sgdamore@opensolaris.org switch (optc) { 95111230Sgdamore@opensolaris.org case 'd': 95211230Sgdamore@opensolaris.org devname = optarg; 95311230Sgdamore@opensolaris.org break; 95411230Sgdamore@opensolaris.org case 'v': 95511230Sgdamore@opensolaris.org verbose = 1; 95611230Sgdamore@opensolaris.org break; 95711230Sgdamore@opensolaris.org default: 95811230Sgdamore@opensolaris.org help(); 95911230Sgdamore@opensolaris.org return (-1); 96011230Sgdamore@opensolaris.org } 96111230Sgdamore@opensolaris.org } 96211230Sgdamore@opensolaris.org argc -= optind; 96311230Sgdamore@opensolaris.org argv += optind; 96411230Sgdamore@opensolaris.org 96511230Sgdamore@opensolaris.org if (argc != 2) { 96611230Sgdamore@opensolaris.org help(); 96711230Sgdamore@opensolaris.org return (-1); 96811230Sgdamore@opensolaris.org } 96911230Sgdamore@opensolaris.org cname = argv[0]; 97011230Sgdamore@opensolaris.org value = argv[1]; 97111230Sgdamore@opensolaris.org 97211230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 97311230Sgdamore@opensolaris.org return (ENODEV); 97411230Sgdamore@opensolaris.org } 97511230Sgdamore@opensolaris.org 97611230Sgdamore@opensolaris.org for (i = 0, found = 0; i < d->cmax; i++) { 97711230Sgdamore@opensolaris.org cinfop = &d->controls[i]; 97811230Sgdamore@opensolaris.org n = strrchr(cinfop->ci.extname, '_'); 97911230Sgdamore@opensolaris.org n = n ? n + 1 : cinfop->ci.extname; 98011230Sgdamore@opensolaris.org if (strcmp(cname, n) != 0) { 98111230Sgdamore@opensolaris.org continue; 98211230Sgdamore@opensolaris.org } 98311230Sgdamore@opensolaris.org found = 1; 98411230Sgdamore@opensolaris.org rv = set_device_control(d, cinfop, value, verbose); 98511230Sgdamore@opensolaris.org rval = rval ? rval : rv; 98611230Sgdamore@opensolaris.org } 98711230Sgdamore@opensolaris.org if (!found) { 98811230Sgdamore@opensolaris.org warn(_("No such control: %s\n"), cname); 98911230Sgdamore@opensolaris.org } 99011230Sgdamore@opensolaris.org 99111230Sgdamore@opensolaris.org return (rval); 99211230Sgdamore@opensolaris.org } 99311230Sgdamore@opensolaris.org 99411230Sgdamore@opensolaris.org int 99511230Sgdamore@opensolaris.org do_save_controls(int argc, char **argv) 99611230Sgdamore@opensolaris.org { 99711230Sgdamore@opensolaris.org int optc; 99811230Sgdamore@opensolaris.org int rval = 0; 99911230Sgdamore@opensolaris.org device_t *d; 100011230Sgdamore@opensolaris.org char *devname = NULL; 100111230Sgdamore@opensolaris.org char *fname; 100211230Sgdamore@opensolaris.org int i; 100311230Sgdamore@opensolaris.org int rv; 100411230Sgdamore@opensolaris.org cinfo_t *cinfop; 100511230Sgdamore@opensolaris.org FILE *fp; 100611230Sgdamore@opensolaris.org int fd; 100711230Sgdamore@opensolaris.org int mode; 100811230Sgdamore@opensolaris.org 100911230Sgdamore@opensolaris.org mode = O_WRONLY | O_CREAT | O_EXCL; 101011230Sgdamore@opensolaris.org 101111230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:f")) != EOF) { 101211230Sgdamore@opensolaris.org switch (optc) { 101311230Sgdamore@opensolaris.org case 'd': 101411230Sgdamore@opensolaris.org devname = optarg; 101511230Sgdamore@opensolaris.org break; 101611230Sgdamore@opensolaris.org case 'f': 101711230Sgdamore@opensolaris.org mode &= ~O_EXCL; 101811230Sgdamore@opensolaris.org mode |= O_TRUNC; 101911230Sgdamore@opensolaris.org break; 102011230Sgdamore@opensolaris.org default: 102111230Sgdamore@opensolaris.org help(); 102211230Sgdamore@opensolaris.org return (-1); 102311230Sgdamore@opensolaris.org } 102411230Sgdamore@opensolaris.org } 102511230Sgdamore@opensolaris.org argc -= optind; 102611230Sgdamore@opensolaris.org argv += optind; 102711230Sgdamore@opensolaris.org 102811230Sgdamore@opensolaris.org if (argc != 1) { 102911230Sgdamore@opensolaris.org help(); 103011230Sgdamore@opensolaris.org return (-1); 103111230Sgdamore@opensolaris.org } 103211230Sgdamore@opensolaris.org fname = argv[0]; 103311230Sgdamore@opensolaris.org 103411230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 103511230Sgdamore@opensolaris.org return (ENODEV); 103611230Sgdamore@opensolaris.org } 103711230Sgdamore@opensolaris.org 103811230Sgdamore@opensolaris.org if ((fd = open(fname, mode, 0666)) < 0) { 103911230Sgdamore@opensolaris.org perror(_("Failed to create file")); 104011230Sgdamore@opensolaris.org return (errno); 104111230Sgdamore@opensolaris.org } 104211230Sgdamore@opensolaris.org 104311230Sgdamore@opensolaris.org if ((fp = fdopen(fd, "w")) == NULL) { 104411230Sgdamore@opensolaris.org perror(_("Unable to open file\n")); 104511230Sgdamore@opensolaris.org (void) close(fd); 104611230Sgdamore@opensolaris.org (void) unlink(fname); 104711230Sgdamore@opensolaris.org return (errno); 104811230Sgdamore@opensolaris.org } 104911230Sgdamore@opensolaris.org 105011230Sgdamore@opensolaris.org (void) fprintf(fp, "# Device: %s\n", d->mixer.devnode); 105111230Sgdamore@opensolaris.org (void) fprintf(fp, "# Name = %s\n", d->card.shortname); 105211230Sgdamore@opensolaris.org (void) fprintf(fp, "# Config = %s\n", d->card.longname); 105311230Sgdamore@opensolaris.org 105411230Sgdamore@opensolaris.org if (strlen(d->card.hw_info)) { 105511230Sgdamore@opensolaris.org (void) fprintf(fp, "# HW Info = %s", d->card.hw_info); 105611230Sgdamore@opensolaris.org } 105711230Sgdamore@opensolaris.org (void) fprintf(fp, "#\n"); 105811230Sgdamore@opensolaris.org 105911230Sgdamore@opensolaris.org print_header(fp, 0); 106011230Sgdamore@opensolaris.org 106111230Sgdamore@opensolaris.org for (i = 0; i < d->cmax; i++) { 106211230Sgdamore@opensolaris.org cinfop = &d->controls[i]; 106311230Sgdamore@opensolaris.org rv = print_control(fp, d, cinfop, 0); 106411230Sgdamore@opensolaris.org rval = rval ? rval : rv; 106511230Sgdamore@opensolaris.org } 106611230Sgdamore@opensolaris.org 106711230Sgdamore@opensolaris.org (void) fclose(fp); 106811230Sgdamore@opensolaris.org 106911230Sgdamore@opensolaris.org return (rval); 107011230Sgdamore@opensolaris.org } 107111230Sgdamore@opensolaris.org 107211230Sgdamore@opensolaris.org int 107311230Sgdamore@opensolaris.org do_load_controls(int argc, char **argv) 107411230Sgdamore@opensolaris.org { 107511230Sgdamore@opensolaris.org int optc; 107611230Sgdamore@opensolaris.org int rval = 0; 107711230Sgdamore@opensolaris.org device_t *d; 107811230Sgdamore@opensolaris.org char *devname = NULL; 107911230Sgdamore@opensolaris.org char *fname; 108011230Sgdamore@opensolaris.org char *cname; 108111230Sgdamore@opensolaris.org char *value; 108211230Sgdamore@opensolaris.org int i; 108311230Sgdamore@opensolaris.org int rv; 108411230Sgdamore@opensolaris.org cinfo_t *cinfop; 108511230Sgdamore@opensolaris.org FILE *fp; 108611230Sgdamore@opensolaris.org char linebuf[MAXLINE]; 108711230Sgdamore@opensolaris.org int lineno = 0; 108811230Sgdamore@opensolaris.org int found; 108911230Sgdamore@opensolaris.org 109011230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:")) != EOF) { 109111230Sgdamore@opensolaris.org switch (optc) { 109211230Sgdamore@opensolaris.org case 'd': 109311230Sgdamore@opensolaris.org devname = optarg; 109411230Sgdamore@opensolaris.org break; 109511230Sgdamore@opensolaris.org default: 109611230Sgdamore@opensolaris.org help(); 109711230Sgdamore@opensolaris.org return (-1); 109811230Sgdamore@opensolaris.org } 109911230Sgdamore@opensolaris.org } 110011230Sgdamore@opensolaris.org argc -= optind; 110111230Sgdamore@opensolaris.org argv += optind; 110211230Sgdamore@opensolaris.org 110311230Sgdamore@opensolaris.org if (argc != 1) { 110411230Sgdamore@opensolaris.org help(); 110511230Sgdamore@opensolaris.org return (-1); 110611230Sgdamore@opensolaris.org } 110711230Sgdamore@opensolaris.org fname = argv[0]; 110811230Sgdamore@opensolaris.org 110911230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 111011230Sgdamore@opensolaris.org return (ENODEV); 111111230Sgdamore@opensolaris.org } 111211230Sgdamore@opensolaris.org 111311230Sgdamore@opensolaris.org if ((fp = fopen(fname, "r")) == NULL) { 111411230Sgdamore@opensolaris.org perror(_("Unable to open file")); 111511230Sgdamore@opensolaris.org return (errno); 111611230Sgdamore@opensolaris.org } 111711230Sgdamore@opensolaris.org 111811230Sgdamore@opensolaris.org while (fgets(linebuf, sizeof (linebuf), fp) != NULL) { 111911230Sgdamore@opensolaris.org lineno++; 112011230Sgdamore@opensolaris.org if (linebuf[strlen(linebuf) - 1] != '\n') { 112111230Sgdamore@opensolaris.org warn(_("Warning: line too long at line %d\n"), lineno); 112211230Sgdamore@opensolaris.org /* read in the rest of the line and discard it */ 112311230Sgdamore@opensolaris.org while (fgets(linebuf, sizeof (linebuf), fp) != NULL && 112411230Sgdamore@opensolaris.org (linebuf[strlen(linebuf) - 1] != '\n')) { 112511230Sgdamore@opensolaris.org continue; 112611230Sgdamore@opensolaris.org } 112711230Sgdamore@opensolaris.org continue; 112811230Sgdamore@opensolaris.org } 112911230Sgdamore@opensolaris.org 113011230Sgdamore@opensolaris.org /* we have a good line ... */ 113111230Sgdamore@opensolaris.org cname = strtok(linebuf, " \t\n"); 113211230Sgdamore@opensolaris.org /* skip comments and blank lines */ 113311230Sgdamore@opensolaris.org if ((cname == NULL) || (cname[0] == '#')) { 113411230Sgdamore@opensolaris.org continue; 113511230Sgdamore@opensolaris.org } 113611230Sgdamore@opensolaris.org value = strtok(NULL, " \t\n"); 113711230Sgdamore@opensolaris.org if ((value == NULL) || (*cname == 0)) { 113811230Sgdamore@opensolaris.org warn(_("Warning: missing value at line %d\n"), lineno); 113911230Sgdamore@opensolaris.org continue; 114011230Sgdamore@opensolaris.org } 114111230Sgdamore@opensolaris.org 114211230Sgdamore@opensolaris.org for (i = 0, found = 0; i < d->cmax; i++) { 114311230Sgdamore@opensolaris.org /* save and restore requires an exact match */ 114411230Sgdamore@opensolaris.org cinfop = &d->controls[i]; 114511230Sgdamore@opensolaris.org if (strcmp(cinfop->ci.extname, cname) != 0) { 114611230Sgdamore@opensolaris.org continue; 114711230Sgdamore@opensolaris.org } 114811230Sgdamore@opensolaris.org found = 1; 114911230Sgdamore@opensolaris.org rv = set_device_control(d, cinfop, value, 0); 115011230Sgdamore@opensolaris.org rval = rval ? rval : rv; 115111230Sgdamore@opensolaris.org } 115211230Sgdamore@opensolaris.org if (!found) { 115311230Sgdamore@opensolaris.org warn(_("No such control: %s\n"), cname); 115411230Sgdamore@opensolaris.org } 115511230Sgdamore@opensolaris.org } 115611230Sgdamore@opensolaris.org (void) fclose(fp); 115711230Sgdamore@opensolaris.org 115811230Sgdamore@opensolaris.org return (rval); 115911230Sgdamore@opensolaris.org } 116011230Sgdamore@opensolaris.org 116111230Sgdamore@opensolaris.org int 1162*11253Sgdamore@opensolaris.org mixer_walker(di_devlink_t dlink, void *arg) 1163*11253Sgdamore@opensolaris.org { 1164*11253Sgdamore@opensolaris.org const char *link; 1165*11253Sgdamore@opensolaris.org int num; 1166*11253Sgdamore@opensolaris.org int fd; 1167*11253Sgdamore@opensolaris.org int verbose = *(int *)arg; 1168*11253Sgdamore@opensolaris.org int num_offset; 1169*11253Sgdamore@opensolaris.org 1170*11253Sgdamore@opensolaris.org num_offset = sizeof ("/dev/mixer") - 1; 1171*11253Sgdamore@opensolaris.org 1172*11253Sgdamore@opensolaris.org link = di_devlink_path(dlink); 1173*11253Sgdamore@opensolaris.org 1174*11253Sgdamore@opensolaris.org if ((link == NULL) || 1175*11253Sgdamore@opensolaris.org (strncmp(link, "/dev/mixer", num_offset) != 0) || 1176*11253Sgdamore@opensolaris.org (!isdigit(link[num_offset]))) { 1177*11253Sgdamore@opensolaris.org return (DI_WALK_CONTINUE); 1178*11253Sgdamore@opensolaris.org } 1179*11253Sgdamore@opensolaris.org 1180*11253Sgdamore@opensolaris.org num = atoi(link + num_offset); 1181*11253Sgdamore@opensolaris.org if ((fd = open(link, O_RDWR)) < 0) { 1182*11253Sgdamore@opensolaris.org if (verbose) { 1183*11253Sgdamore@opensolaris.org if (errno == ENOENT) { 1184*11253Sgdamore@opensolaris.org msg(_("Device %s not present.\n"), link); 1185*11253Sgdamore@opensolaris.org } else { 1186*11253Sgdamore@opensolaris.org msg(_("Unable to open device %s: %s\n"), 1187*11253Sgdamore@opensolaris.org link, strerror(errno)); 1188*11253Sgdamore@opensolaris.org } 1189*11253Sgdamore@opensolaris.org } 1190*11253Sgdamore@opensolaris.org return (DI_WALK_CONTINUE); 1191*11253Sgdamore@opensolaris.org } 1192*11253Sgdamore@opensolaris.org 1193*11253Sgdamore@opensolaris.org if (verbose) { 1194*11253Sgdamore@opensolaris.org msg(_("Initializing link %s: "), link); 1195*11253Sgdamore@opensolaris.org } 1196*11253Sgdamore@opensolaris.org if (ioctl(fd, SNDCTL_SUN_SEND_NUMBER, &num) != 0) { 1197*11253Sgdamore@opensolaris.org if (verbose) { 1198*11253Sgdamore@opensolaris.org msg(_("failed: %s\n"), strerror(errno)); 1199*11253Sgdamore@opensolaris.org } 1200*11253Sgdamore@opensolaris.org } else { 1201*11253Sgdamore@opensolaris.org if (verbose) { 1202*11253Sgdamore@opensolaris.org msg(_("done.\n")); 1203*11253Sgdamore@opensolaris.org } 1204*11253Sgdamore@opensolaris.org } 1205*11253Sgdamore@opensolaris.org (void) close(fd); 1206*11253Sgdamore@opensolaris.org return (DI_WALK_CONTINUE); 1207*11253Sgdamore@opensolaris.org } 1208*11253Sgdamore@opensolaris.org 1209*11253Sgdamore@opensolaris.org int 1210*11253Sgdamore@opensolaris.org do_init_devices(int argc, char **argv) 1211*11253Sgdamore@opensolaris.org { 1212*11253Sgdamore@opensolaris.org int optc; 1213*11253Sgdamore@opensolaris.org di_devlink_handle_t dlh; 1214*11253Sgdamore@opensolaris.org int verbose = 0; 1215*11253Sgdamore@opensolaris.org 1216*11253Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "v")) != EOF) { 1217*11253Sgdamore@opensolaris.org switch (optc) { 1218*11253Sgdamore@opensolaris.org case 'v': 1219*11253Sgdamore@opensolaris.org verbose = 1; 1220*11253Sgdamore@opensolaris.org break; 1221*11253Sgdamore@opensolaris.org default: 1222*11253Sgdamore@opensolaris.org help(); 1223*11253Sgdamore@opensolaris.org return (-1); 1224*11253Sgdamore@opensolaris.org } 1225*11253Sgdamore@opensolaris.org } 1226*11253Sgdamore@opensolaris.org argc -= optind; 1227*11253Sgdamore@opensolaris.org argv += optind; 1228*11253Sgdamore@opensolaris.org 1229*11253Sgdamore@opensolaris.org if (argc != 0) { 1230*11253Sgdamore@opensolaris.org help(); 1231*11253Sgdamore@opensolaris.org return (-1); 1232*11253Sgdamore@opensolaris.org } 1233*11253Sgdamore@opensolaris.org 1234*11253Sgdamore@opensolaris.org dlh = di_devlink_init(NULL, 0); 1235*11253Sgdamore@opensolaris.org if (dlh == NULL) { 1236*11253Sgdamore@opensolaris.org perror(_("Unable to initialize devlink handle")); 1237*11253Sgdamore@opensolaris.org return (-1); 1238*11253Sgdamore@opensolaris.org } 1239*11253Sgdamore@opensolaris.org 1240*11253Sgdamore@opensolaris.org if (di_devlink_walk(dlh, "^mixer", NULL, 0, &verbose, 1241*11253Sgdamore@opensolaris.org mixer_walker) != 0) { 1242*11253Sgdamore@opensolaris.org perror(_("Unable to walk devlinks")); 1243*11253Sgdamore@opensolaris.org return (-1); 1244*11253Sgdamore@opensolaris.org } 1245*11253Sgdamore@opensolaris.org return (0); 1246*11253Sgdamore@opensolaris.org } 1247*11253Sgdamore@opensolaris.org 1248*11253Sgdamore@opensolaris.org int 124911230Sgdamore@opensolaris.org main(int argc, char **argv) 125011230Sgdamore@opensolaris.org { 125111230Sgdamore@opensolaris.org int rv = 0; 125211230Sgdamore@opensolaris.org int opt; 125311230Sgdamore@opensolaris.org 125411230Sgdamore@opensolaris.org (void) setlocale(LC_ALL, ""); 125511230Sgdamore@opensolaris.org (void) textdomain(TEXT_DOMAIN); 125611230Sgdamore@opensolaris.org 125711230Sgdamore@opensolaris.org while ((opt = getopt(argc, argv, "h")) != EOF) { 125811230Sgdamore@opensolaris.org switch (opt) { 125911230Sgdamore@opensolaris.org case 'h': 126011230Sgdamore@opensolaris.org help(); 126111230Sgdamore@opensolaris.org rv = 0; 126211230Sgdamore@opensolaris.org goto OUT; 126311230Sgdamore@opensolaris.org default: 126411230Sgdamore@opensolaris.org rv = EINVAL; 126511230Sgdamore@opensolaris.org break; 126611230Sgdamore@opensolaris.org } 126711230Sgdamore@opensolaris.org } 126811230Sgdamore@opensolaris.org 126911230Sgdamore@opensolaris.org if (rv) { 127011230Sgdamore@opensolaris.org goto OUT; 127111230Sgdamore@opensolaris.org } 127211230Sgdamore@opensolaris.org 127311230Sgdamore@opensolaris.org argc -= optind; 127411230Sgdamore@opensolaris.org argv += optind; 127511230Sgdamore@opensolaris.org 127611230Sgdamore@opensolaris.org if (argc < 1) { 127711230Sgdamore@opensolaris.org help(); 127811230Sgdamore@opensolaris.org rv = EINVAL; 127911230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "help") == 0) { 128011230Sgdamore@opensolaris.org help(); 128111230Sgdamore@opensolaris.org rv = 0; 128211230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "list-devices") == 0) { 128311230Sgdamore@opensolaris.org rv = do_list_devices(argc, argv); 128411230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "show-device") == 0) { 128511230Sgdamore@opensolaris.org rv = do_show_device(argc, argv); 128611230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "show-control") == 0) { 128711230Sgdamore@opensolaris.org rv = do_show_control(argc, argv); 128811230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "set-control") == 0) { 128911230Sgdamore@opensolaris.org rv = do_set_control(argc, argv); 129011230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "load-controls") == 0) { 129111230Sgdamore@opensolaris.org rv = do_load_controls(argc, argv); 129211230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "save-controls") == 0) { 129311230Sgdamore@opensolaris.org rv = do_save_controls(argc, argv); 1294*11253Sgdamore@opensolaris.org } else if (strcmp(argv[0], "init-devices") == 0) { 1295*11253Sgdamore@opensolaris.org rv = do_init_devices(argc, argv); 129611230Sgdamore@opensolaris.org } else { 129711230Sgdamore@opensolaris.org help(); 129811230Sgdamore@opensolaris.org rv = EINVAL; 129911230Sgdamore@opensolaris.org } 130011230Sgdamore@opensolaris.org 130111230Sgdamore@opensolaris.org OUT: 130211230Sgdamore@opensolaris.org free_devices(); 130311230Sgdamore@opensolaris.org return (rv); 130411230Sgdamore@opensolaris.org } 1305