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 /* 22*11423Sgdamore@opensolaris.org * Copyright 2010 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> 4311253Sgdamore@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 31411253Sgdamore@opensolaris.org if (devices != NULL) { 31511253Sgdamore@opensolaris.org /* already loaded */ 31611253Sgdamore@opensolaris.org return (0); 31711253Sgdamore@opensolaris.org } 31811253Sgdamore@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 568*11423Sgdamore@opensolaris.org /* non-verbose mode prints don't display the enum values */ 569*11423Sgdamore@opensolaris.org if ((!vopt) || (sfp != NULL)) { 570*11423Sgdamore@opensolaris.org return (0); 571*11423Sgdamore@opensolaris.org } 572*11423Sgdamore@opensolaris.org 57311230Sgdamore@opensolaris.org /* print leftover enum value selections */ 574*11423Sgdamore@opensolaris.org while ((idx >= 0) && (idx < cinfop->ci.maxvalue)) { 57511230Sgdamore@opensolaris.org selbuf[0] = 0; 57611230Sgdamore@opensolaris.org for (i = idx; i < cinfop->ci.maxvalue; i++) { 57711230Sgdamore@opensolaris.org str = get_enum_str(cinfop, i); 57811230Sgdamore@opensolaris.org if (str == NULL) 57911230Sgdamore@opensolaris.org continue; 58011230Sgdamore@opensolaris.org 58111230Sgdamore@opensolaris.org if ((strlen(str) + 1 + strlen(selbuf)) >= 58211230Sgdamore@opensolaris.org sizeof (selbuf)) { 58311230Sgdamore@opensolaris.org break; 58411230Sgdamore@opensolaris.org } 58511230Sgdamore@opensolaris.org if (strlen(selbuf)) { 58611230Sgdamore@opensolaris.org (void) strlcat(selbuf, ",", sizeof (selbuf)); 58711230Sgdamore@opensolaris.org } 58811230Sgdamore@opensolaris.org 58911230Sgdamore@opensolaris.org (void) strlcat(selbuf, str, sizeof (selbuf)); 59011230Sgdamore@opensolaris.org } 59111230Sgdamore@opensolaris.org idx = i; 59211230Sgdamore@opensolaris.org col.col_dv = NULL; 59311230Sgdamore@opensolaris.org col.col_nm = NULL; 59411230Sgdamore@opensolaris.org col.col_val = NULL; 59511230Sgdamore@opensolaris.org col.col_sel = selbuf; 59611230Sgdamore@opensolaris.org print_control_line(sfp, &col, vopt); 59711230Sgdamore@opensolaris.org } 59811230Sgdamore@opensolaris.org 59911230Sgdamore@opensolaris.org return (0); 60011230Sgdamore@opensolaris.org } 60111230Sgdamore@opensolaris.org 60211230Sgdamore@opensolaris.org 60311230Sgdamore@opensolaris.org static int 60411230Sgdamore@opensolaris.org set_device_control(device_t *d, cinfo_t *cinfop, char *wstr, int vopt) 60511230Sgdamore@opensolaris.org { 60611230Sgdamore@opensolaris.org int mfd = d->mfd; 60711230Sgdamore@opensolaris.org oss_mixer_value cval; 60811230Sgdamore@opensolaris.org int wlen = strlen(wstr); 60911230Sgdamore@opensolaris.org int lval, rval; 61011230Sgdamore@opensolaris.org char *lstr, *rstr; 61111230Sgdamore@opensolaris.org char *str; 61211230Sgdamore@opensolaris.org int i; 61311230Sgdamore@opensolaris.org int rv = -1; 61411230Sgdamore@opensolaris.org 61511230Sgdamore@opensolaris.org cval.dev = -1; 61611230Sgdamore@opensolaris.org cval.ctrl = cinfop->ci.ctrl; 61711230Sgdamore@opensolaris.org cval.value = 0; 61811230Sgdamore@opensolaris.org 61911230Sgdamore@opensolaris.org switch (cinfop->ci.type) { 62011230Sgdamore@opensolaris.org case MIXT_ONOFF: 62111230Sgdamore@opensolaris.org cval.value = (strncmp(_("on"), wstr, wlen) == 0) ? 1 : 0; 62211230Sgdamore@opensolaris.org break; 62311230Sgdamore@opensolaris.org 62411230Sgdamore@opensolaris.org case MIXT_MONOSLIDER: 62511230Sgdamore@opensolaris.org cval.value = atoi(wstr); 62611230Sgdamore@opensolaris.org break; 62711230Sgdamore@opensolaris.org 62811230Sgdamore@opensolaris.org case MIXT_STEREOSLIDER: 62911230Sgdamore@opensolaris.org lstr = wstr; 63011230Sgdamore@opensolaris.org rstr = strchr(wstr, ':'); 63111230Sgdamore@opensolaris.org if (rstr != NULL) { 63211230Sgdamore@opensolaris.org *rstr = '\0'; 63311230Sgdamore@opensolaris.org rstr++; 63411230Sgdamore@opensolaris.org 63511230Sgdamore@opensolaris.org rval = atoi(rstr); 63611230Sgdamore@opensolaris.org lval = atoi(lstr); 63711230Sgdamore@opensolaris.org 63811230Sgdamore@opensolaris.org rstr--; 63911230Sgdamore@opensolaris.org *rstr = ':'; 64011230Sgdamore@opensolaris.org } else { 64111230Sgdamore@opensolaris.org lval = atoi(lstr); 64211230Sgdamore@opensolaris.org rval = lval; 64311230Sgdamore@opensolaris.org } 64411230Sgdamore@opensolaris.org 64511230Sgdamore@opensolaris.org cval.value = AUDIO_CTRL_STEREO_VAL(lval, rval); 64611230Sgdamore@opensolaris.org break; 64711230Sgdamore@opensolaris.org 64811230Sgdamore@opensolaris.org case MIXT_ENUM: 64911230Sgdamore@opensolaris.org for (i = 0; i < cinfop->ci.maxvalue; i++) { 65011230Sgdamore@opensolaris.org str = get_enum_str(cinfop, i); 65111230Sgdamore@opensolaris.org if (str == NULL) 65211230Sgdamore@opensolaris.org continue; 65311230Sgdamore@opensolaris.org 65411230Sgdamore@opensolaris.org if (strncmp(wstr, str, wlen) == 0) { 65511230Sgdamore@opensolaris.org cval.value = i; 65611230Sgdamore@opensolaris.org break; 65711230Sgdamore@opensolaris.org } 65811230Sgdamore@opensolaris.org } 65911230Sgdamore@opensolaris.org 66011230Sgdamore@opensolaris.org if (i >= cinfop->ci.maxvalue) { 66111230Sgdamore@opensolaris.org warn(_("Invalid enumeration value\n")); 66211230Sgdamore@opensolaris.org return (EINVAL); 66311230Sgdamore@opensolaris.org } 66411230Sgdamore@opensolaris.org break; 66511230Sgdamore@opensolaris.org 66611230Sgdamore@opensolaris.org default: 66711230Sgdamore@opensolaris.org warn(_("Unsupported control type: %d\n"), cinfop->ci.type); 66811230Sgdamore@opensolaris.org return (EINVAL); 66911230Sgdamore@opensolaris.org } 67011230Sgdamore@opensolaris.org 67111230Sgdamore@opensolaris.org if (vopt) { 67211230Sgdamore@opensolaris.org msg(_("%s: '%s' set to '%s'\n"), d->card.shortname, 67311230Sgdamore@opensolaris.org cinfop->ci.extname, wstr); 67411230Sgdamore@opensolaris.org } 67511230Sgdamore@opensolaris.org 67611230Sgdamore@opensolaris.org if (ioctl(mfd, SNDCTL_MIX_WRITE, &cval) < 0) { 67711230Sgdamore@opensolaris.org rv = errno; 67811230Sgdamore@opensolaris.org perror(_("Error writing control")); 67911230Sgdamore@opensolaris.org return (rv); 68011230Sgdamore@opensolaris.org } 68111230Sgdamore@opensolaris.org 68211230Sgdamore@opensolaris.org rv = 0; 68311230Sgdamore@opensolaris.org return (rv); 68411230Sgdamore@opensolaris.org } 68511230Sgdamore@opensolaris.org 68611230Sgdamore@opensolaris.org 68711230Sgdamore@opensolaris.org static void 68811230Sgdamore@opensolaris.org help(void) 68911230Sgdamore@opensolaris.org { 69011230Sgdamore@opensolaris.org #define HELP_STR _( \ 69111230Sgdamore@opensolaris.org "audioctl list-devices\n" \ 69211230Sgdamore@opensolaris.org " list all audio devices\n" \ 69311230Sgdamore@opensolaris.org "\n" \ 69411230Sgdamore@opensolaris.org "audioctl show-device [ -v ] [ -d <device> ]\n" \ 69511230Sgdamore@opensolaris.org " display information about an audio device\n" \ 69611230Sgdamore@opensolaris.org "\n" \ 69711230Sgdamore@opensolaris.org "audioctl show-control [ -v ] [ -d <device> ] [ <control> ... ]\n" \ 69811230Sgdamore@opensolaris.org " get the value of a specific control (all if not specified)\n" \ 69911230Sgdamore@opensolaris.org "\n" \ 70011230Sgdamore@opensolaris.org "audioctl set-control [ -v ] [ -d <device> ] <control> <value>\n" \ 70111230Sgdamore@opensolaris.org " set the value of a specific control\n" \ 70211230Sgdamore@opensolaris.org "\n" \ 70311230Sgdamore@opensolaris.org "audioctl save-controls [ -d <device> ] [ -f ] <file>\n" \ 70411230Sgdamore@opensolaris.org " save all control settings for the device to a file\n" \ 70511230Sgdamore@opensolaris.org "\n" \ 70611230Sgdamore@opensolaris.org "audioctl load-controls [ -d <device> ] <file>\n" \ 70711230Sgdamore@opensolaris.org " restore previously saved control settings to device\n" \ 70811230Sgdamore@opensolaris.org "\n" \ 70911230Sgdamore@opensolaris.org "audioctl help\n" \ 71011230Sgdamore@opensolaris.org " show this message.\n") 71111230Sgdamore@opensolaris.org 71211230Sgdamore@opensolaris.org (void) fprintf(stderr, HELP_STR); 71311230Sgdamore@opensolaris.org } 71411230Sgdamore@opensolaris.org 71511230Sgdamore@opensolaris.org dev_t 71611230Sgdamore@opensolaris.org device_devt(char *name) 71711230Sgdamore@opensolaris.org { 71811230Sgdamore@opensolaris.org struct stat sbuf; 71911230Sgdamore@opensolaris.org 72011230Sgdamore@opensolaris.org if ((stat(name, &sbuf) != 0) || 72111230Sgdamore@opensolaris.org ((sbuf.st_mode & S_IFCHR) == 0)) { 72211230Sgdamore@opensolaris.org /* Not a device node! */ 72311230Sgdamore@opensolaris.org return (0); 72411230Sgdamore@opensolaris.org } 72511230Sgdamore@opensolaris.org 72611230Sgdamore@opensolaris.org return (makedev(major(sbuf.st_rdev), 72711230Sgdamore@opensolaris.org minor(sbuf.st_rdev) & ~(AUDIO_MN_TYPE_MASK))); 72811230Sgdamore@opensolaris.org } 72911230Sgdamore@opensolaris.org 73011230Sgdamore@opensolaris.org static device_t * 73111230Sgdamore@opensolaris.org find_device(char *name) 73211230Sgdamore@opensolaris.org { 73311230Sgdamore@opensolaris.org dev_t devt; 73411230Sgdamore@opensolaris.org device_t *d; 73511230Sgdamore@opensolaris.org 73611230Sgdamore@opensolaris.org /* 73711230Sgdamore@opensolaris.org * User may have specified: 73811230Sgdamore@opensolaris.org * 73911230Sgdamore@opensolaris.org * /dev/dsp[<num>] 74011230Sgdamore@opensolaris.org * /dev/mixer[<num>] 74111230Sgdamore@opensolaris.org * /dev/audio[<num>9] 74211230Sgdamore@opensolaris.org * /dev/audioctl[<num>] 74311230Sgdamore@opensolaris.org * /dev/sound/<num>{,ctl,dsp,mixer} 74411230Sgdamore@opensolaris.org * /dev/sound/<driver>:<num>{,ctl,dsp,mixer} 74511230Sgdamore@opensolaris.org * 74611230Sgdamore@opensolaris.org * We can canonicalize these by looking at the dev_t though. 74711230Sgdamore@opensolaris.org */ 74811230Sgdamore@opensolaris.org 74911253Sgdamore@opensolaris.org if (load_devices() != 0) { 75011253Sgdamore@opensolaris.org return (NULL); 75111253Sgdamore@opensolaris.org } 75211253Sgdamore@opensolaris.org 75311230Sgdamore@opensolaris.org if (name == NULL) 75411230Sgdamore@opensolaris.org name = getenv("AUDIODEV"); 75511230Sgdamore@opensolaris.org 75611230Sgdamore@opensolaris.org if ((name == NULL) || 75711230Sgdamore@opensolaris.org (strcmp(name, "/dev/mixer") == 0)) { 75811230Sgdamore@opensolaris.org /* /dev/mixer node doesn't point to real hw */ 75911230Sgdamore@opensolaris.org name = "/dev/dsp"; 76011230Sgdamore@opensolaris.org } 76111230Sgdamore@opensolaris.org 76211230Sgdamore@opensolaris.org if (*name == '/') { 76311230Sgdamore@opensolaris.org /* if we have a full path, convert to the devt */ 76411230Sgdamore@opensolaris.org if ((devt = device_devt(name)) == 0) { 76511230Sgdamore@opensolaris.org warn(_("No such audio device.\n")); 76611230Sgdamore@opensolaris.org return (NULL); 76711230Sgdamore@opensolaris.org } 76811230Sgdamore@opensolaris.org name = NULL; 76911230Sgdamore@opensolaris.org } 77011230Sgdamore@opensolaris.org 77111230Sgdamore@opensolaris.org for (d = devices; d != NULL; d = d->nextp) { 77211230Sgdamore@opensolaris.org oss_card_info *card = &d->card; 77311230Sgdamore@opensolaris.org 77411230Sgdamore@opensolaris.org if ((name) && (strcmp(name, card->shortname) == 0)) { 77511230Sgdamore@opensolaris.org return (d); 77611230Sgdamore@opensolaris.org } 77711230Sgdamore@opensolaris.org if (devt == d->devt) { 77811230Sgdamore@opensolaris.org return (d); 77911230Sgdamore@opensolaris.org } 78011230Sgdamore@opensolaris.org } 78111230Sgdamore@opensolaris.org 78211230Sgdamore@opensolaris.org warn(_("No such audio device.\n")); 78311230Sgdamore@opensolaris.org return (NULL); 78411230Sgdamore@opensolaris.org } 78511230Sgdamore@opensolaris.org 78611230Sgdamore@opensolaris.org int 78711230Sgdamore@opensolaris.org do_list_devices(int argc, char **argv) 78811230Sgdamore@opensolaris.org { 78911230Sgdamore@opensolaris.org int optc; 79011230Sgdamore@opensolaris.org int verbose = 0; 79111230Sgdamore@opensolaris.org device_t *d; 79211230Sgdamore@opensolaris.org 79311230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "v")) != EOF) { 79411230Sgdamore@opensolaris.org switch (optc) { 79511230Sgdamore@opensolaris.org case 'v': 79611230Sgdamore@opensolaris.org verbose++; 79711230Sgdamore@opensolaris.org break; 79811230Sgdamore@opensolaris.org default: 79911230Sgdamore@opensolaris.org help(); 80011230Sgdamore@opensolaris.org return (-1); 80111230Sgdamore@opensolaris.org } 80211230Sgdamore@opensolaris.org } 80311230Sgdamore@opensolaris.org argc -= optind; 80411230Sgdamore@opensolaris.org argv += optind; 80511230Sgdamore@opensolaris.org if (argc != 0) { 80611230Sgdamore@opensolaris.org help(); 80711230Sgdamore@opensolaris.org return (-1); 80811230Sgdamore@opensolaris.org } 80911230Sgdamore@opensolaris.org 81011253Sgdamore@opensolaris.org if (load_devices() != 0) { 81111253Sgdamore@opensolaris.org return (-1); 81211253Sgdamore@opensolaris.org } 81311253Sgdamore@opensolaris.org 81411230Sgdamore@opensolaris.org for (d = devices; d != NULL; d = d->nextp) { 81511230Sgdamore@opensolaris.org 81611230Sgdamore@opensolaris.org if ((d->mixer.enabled == 0) && (!verbose)) 81711230Sgdamore@opensolaris.org continue; 81811230Sgdamore@opensolaris.org 81911230Sgdamore@opensolaris.org if (verbose) { 82011230Sgdamore@opensolaris.org msg(_("%s (%s)\n"), d->card.shortname, 82111230Sgdamore@opensolaris.org d->mixer.devnode); 82211230Sgdamore@opensolaris.org } else { 82311230Sgdamore@opensolaris.org msg(_("%s\n"), d->card.shortname); 82411230Sgdamore@opensolaris.org } 82511230Sgdamore@opensolaris.org } 82611230Sgdamore@opensolaris.org 82711230Sgdamore@opensolaris.org return (0); 82811230Sgdamore@opensolaris.org } 82911230Sgdamore@opensolaris.org 83011230Sgdamore@opensolaris.org int 83111230Sgdamore@opensolaris.org do_show_device(int argc, char **argv) 83211230Sgdamore@opensolaris.org { 83311230Sgdamore@opensolaris.org int optc; 83411230Sgdamore@opensolaris.org char *devname = NULL; 83511230Sgdamore@opensolaris.org device_t *d; 83611230Sgdamore@opensolaris.org 83711230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:v")) != EOF) { 83811230Sgdamore@opensolaris.org switch (optc) { 83911230Sgdamore@opensolaris.org case 'd': 84011230Sgdamore@opensolaris.org devname = optarg; 84111230Sgdamore@opensolaris.org break; 84211230Sgdamore@opensolaris.org case 'v': 84311230Sgdamore@opensolaris.org break; 84411230Sgdamore@opensolaris.org default: 84511230Sgdamore@opensolaris.org help(); 84611230Sgdamore@opensolaris.org return (-1); 84711230Sgdamore@opensolaris.org } 84811230Sgdamore@opensolaris.org } 84911230Sgdamore@opensolaris.org argc -= optind; 85011230Sgdamore@opensolaris.org argv += optind; 85111230Sgdamore@opensolaris.org if (argc != 0) { 85211230Sgdamore@opensolaris.org help(); 85311230Sgdamore@opensolaris.org return (-1); 85411230Sgdamore@opensolaris.org } 85511230Sgdamore@opensolaris.org 85611230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 85711230Sgdamore@opensolaris.org return (ENODEV); 85811230Sgdamore@opensolaris.org } 85911230Sgdamore@opensolaris.org 86011230Sgdamore@opensolaris.org msg(_("Device: %s\n"), d->mixer.devnode); 86111230Sgdamore@opensolaris.org msg(_(" Name = %s\n"), d->card.shortname); 86211230Sgdamore@opensolaris.org msg(_(" Config = %s\n"), d->card.longname); 86311230Sgdamore@opensolaris.org 86411230Sgdamore@opensolaris.org if (strlen(d->card.hw_info)) { 86511230Sgdamore@opensolaris.org msg(_(" HW Info = %s"), d->card.hw_info); 86611230Sgdamore@opensolaris.org } 86711230Sgdamore@opensolaris.org 86811230Sgdamore@opensolaris.org return (0); 86911230Sgdamore@opensolaris.org } 87011230Sgdamore@opensolaris.org 87111230Sgdamore@opensolaris.org int 87211230Sgdamore@opensolaris.org do_show_control(int argc, char **argv) 87311230Sgdamore@opensolaris.org { 87411230Sgdamore@opensolaris.org int optc; 87511230Sgdamore@opensolaris.org int rval = 0; 87611230Sgdamore@opensolaris.org int verbose = 0; 87711230Sgdamore@opensolaris.org device_t *d; 87811230Sgdamore@opensolaris.org char *devname = NULL; 87911230Sgdamore@opensolaris.org int i; 88011230Sgdamore@opensolaris.org int j; 88111230Sgdamore@opensolaris.org int rv; 88211230Sgdamore@opensolaris.org char *n; 88311230Sgdamore@opensolaris.org cinfo_t *cinfop; 88411230Sgdamore@opensolaris.org 88511230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:v")) != EOF) { 88611230Sgdamore@opensolaris.org switch (optc) { 88711230Sgdamore@opensolaris.org case 'd': 88811230Sgdamore@opensolaris.org devname = optarg; 88911230Sgdamore@opensolaris.org break; 89011230Sgdamore@opensolaris.org case 'v': 89111230Sgdamore@opensolaris.org verbose++; 89211230Sgdamore@opensolaris.org break; 89311230Sgdamore@opensolaris.org default: 89411230Sgdamore@opensolaris.org help(); 89511230Sgdamore@opensolaris.org return (-1); 89611230Sgdamore@opensolaris.org } 89711230Sgdamore@opensolaris.org } 89811230Sgdamore@opensolaris.org argc -= optind; 89911230Sgdamore@opensolaris.org argv += optind; 90011230Sgdamore@opensolaris.org 90111230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 90211230Sgdamore@opensolaris.org return (ENODEV); 90311230Sgdamore@opensolaris.org } 90411230Sgdamore@opensolaris.org 90511230Sgdamore@opensolaris.org print_header(NULL, verbose); 90611230Sgdamore@opensolaris.org if (argc == 0) { 90711230Sgdamore@opensolaris.org /* do them all! */ 90811230Sgdamore@opensolaris.org for (i = 0; i < d->cmax; i++) { 90911230Sgdamore@opensolaris.org 91011230Sgdamore@opensolaris.org cinfop = &d->controls[i]; 91111230Sgdamore@opensolaris.org rv = print_control(NULL, d, cinfop, verbose); 91211230Sgdamore@opensolaris.org rval = rval ? rval : rv; 91311230Sgdamore@opensolaris.org } 91411230Sgdamore@opensolaris.org return (rval); 91511230Sgdamore@opensolaris.org } 91611230Sgdamore@opensolaris.org 91711230Sgdamore@opensolaris.org for (i = 0; i < argc; i++) { 91811230Sgdamore@opensolaris.org for (j = 0; j < d->cmax; j++) { 91911230Sgdamore@opensolaris.org cinfop = &d->controls[j]; 92011230Sgdamore@opensolaris.org n = strrchr(cinfop->ci.extname, '_'); 92111230Sgdamore@opensolaris.org n = n ? n + 1 : cinfop->ci.extname; 92211230Sgdamore@opensolaris.org if (strcmp(argv[i], n) == 0) { 92311230Sgdamore@opensolaris.org rv = print_control(NULL, d, cinfop, verbose); 92411230Sgdamore@opensolaris.org rval = rval ? rval : rv; 92511230Sgdamore@opensolaris.org break; 92611230Sgdamore@opensolaris.org } 92711230Sgdamore@opensolaris.org } 92811230Sgdamore@opensolaris.org /* Didn't find requested control */ 92911230Sgdamore@opensolaris.org if (j == d->cmax) { 93011230Sgdamore@opensolaris.org warn(_("No such control: %s\n"), argv[i]); 93111230Sgdamore@opensolaris.org rval = rval ? rval : ENODEV; 93211230Sgdamore@opensolaris.org } 93311230Sgdamore@opensolaris.org } 93411230Sgdamore@opensolaris.org 93511230Sgdamore@opensolaris.org return (rval); 93611230Sgdamore@opensolaris.org } 93711230Sgdamore@opensolaris.org 93811230Sgdamore@opensolaris.org int 93911230Sgdamore@opensolaris.org do_set_control(int argc, char **argv) 94011230Sgdamore@opensolaris.org { 94111230Sgdamore@opensolaris.org int optc; 94211230Sgdamore@opensolaris.org int rval = 0; 94311230Sgdamore@opensolaris.org int verbose = 0; 94411230Sgdamore@opensolaris.org device_t *d; 94511230Sgdamore@opensolaris.org char *devname = NULL; 94611230Sgdamore@opensolaris.org char *cname; 94711230Sgdamore@opensolaris.org char *value; 94811230Sgdamore@opensolaris.org int i; 94911230Sgdamore@opensolaris.org int found; 95011230Sgdamore@opensolaris.org int rv; 95111230Sgdamore@opensolaris.org char *n; 95211230Sgdamore@opensolaris.org cinfo_t *cinfop; 95311230Sgdamore@opensolaris.org 95411230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:v")) != EOF) { 95511230Sgdamore@opensolaris.org switch (optc) { 95611230Sgdamore@opensolaris.org case 'd': 95711230Sgdamore@opensolaris.org devname = optarg; 95811230Sgdamore@opensolaris.org break; 95911230Sgdamore@opensolaris.org case 'v': 96011230Sgdamore@opensolaris.org verbose = 1; 96111230Sgdamore@opensolaris.org break; 96211230Sgdamore@opensolaris.org default: 96311230Sgdamore@opensolaris.org help(); 96411230Sgdamore@opensolaris.org return (-1); 96511230Sgdamore@opensolaris.org } 96611230Sgdamore@opensolaris.org } 96711230Sgdamore@opensolaris.org argc -= optind; 96811230Sgdamore@opensolaris.org argv += optind; 96911230Sgdamore@opensolaris.org 97011230Sgdamore@opensolaris.org if (argc != 2) { 97111230Sgdamore@opensolaris.org help(); 97211230Sgdamore@opensolaris.org return (-1); 97311230Sgdamore@opensolaris.org } 97411230Sgdamore@opensolaris.org cname = argv[0]; 97511230Sgdamore@opensolaris.org value = argv[1]; 97611230Sgdamore@opensolaris.org 97711230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 97811230Sgdamore@opensolaris.org return (ENODEV); 97911230Sgdamore@opensolaris.org } 98011230Sgdamore@opensolaris.org 98111230Sgdamore@opensolaris.org for (i = 0, found = 0; i < d->cmax; i++) { 98211230Sgdamore@opensolaris.org cinfop = &d->controls[i]; 98311230Sgdamore@opensolaris.org n = strrchr(cinfop->ci.extname, '_'); 98411230Sgdamore@opensolaris.org n = n ? n + 1 : cinfop->ci.extname; 98511230Sgdamore@opensolaris.org if (strcmp(cname, n) != 0) { 98611230Sgdamore@opensolaris.org continue; 98711230Sgdamore@opensolaris.org } 98811230Sgdamore@opensolaris.org found = 1; 98911230Sgdamore@opensolaris.org rv = set_device_control(d, cinfop, value, verbose); 99011230Sgdamore@opensolaris.org rval = rval ? rval : rv; 99111230Sgdamore@opensolaris.org } 99211230Sgdamore@opensolaris.org if (!found) { 99311230Sgdamore@opensolaris.org warn(_("No such control: %s\n"), cname); 99411230Sgdamore@opensolaris.org } 99511230Sgdamore@opensolaris.org 99611230Sgdamore@opensolaris.org return (rval); 99711230Sgdamore@opensolaris.org } 99811230Sgdamore@opensolaris.org 99911230Sgdamore@opensolaris.org int 100011230Sgdamore@opensolaris.org do_save_controls(int argc, char **argv) 100111230Sgdamore@opensolaris.org { 100211230Sgdamore@opensolaris.org int optc; 100311230Sgdamore@opensolaris.org int rval = 0; 100411230Sgdamore@opensolaris.org device_t *d; 100511230Sgdamore@opensolaris.org char *devname = NULL; 100611230Sgdamore@opensolaris.org char *fname; 100711230Sgdamore@opensolaris.org int i; 100811230Sgdamore@opensolaris.org int rv; 100911230Sgdamore@opensolaris.org cinfo_t *cinfop; 101011230Sgdamore@opensolaris.org FILE *fp; 101111230Sgdamore@opensolaris.org int fd; 101211230Sgdamore@opensolaris.org int mode; 101311230Sgdamore@opensolaris.org 101411230Sgdamore@opensolaris.org mode = O_WRONLY | O_CREAT | O_EXCL; 101511230Sgdamore@opensolaris.org 101611230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:f")) != EOF) { 101711230Sgdamore@opensolaris.org switch (optc) { 101811230Sgdamore@opensolaris.org case 'd': 101911230Sgdamore@opensolaris.org devname = optarg; 102011230Sgdamore@opensolaris.org break; 102111230Sgdamore@opensolaris.org case 'f': 102211230Sgdamore@opensolaris.org mode &= ~O_EXCL; 102311230Sgdamore@opensolaris.org mode |= O_TRUNC; 102411230Sgdamore@opensolaris.org break; 102511230Sgdamore@opensolaris.org default: 102611230Sgdamore@opensolaris.org help(); 102711230Sgdamore@opensolaris.org return (-1); 102811230Sgdamore@opensolaris.org } 102911230Sgdamore@opensolaris.org } 103011230Sgdamore@opensolaris.org argc -= optind; 103111230Sgdamore@opensolaris.org argv += optind; 103211230Sgdamore@opensolaris.org 103311230Sgdamore@opensolaris.org if (argc != 1) { 103411230Sgdamore@opensolaris.org help(); 103511230Sgdamore@opensolaris.org return (-1); 103611230Sgdamore@opensolaris.org } 103711230Sgdamore@opensolaris.org fname = argv[0]; 103811230Sgdamore@opensolaris.org 103911230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 104011230Sgdamore@opensolaris.org return (ENODEV); 104111230Sgdamore@opensolaris.org } 104211230Sgdamore@opensolaris.org 104311230Sgdamore@opensolaris.org if ((fd = open(fname, mode, 0666)) < 0) { 104411230Sgdamore@opensolaris.org perror(_("Failed to create file")); 104511230Sgdamore@opensolaris.org return (errno); 104611230Sgdamore@opensolaris.org } 104711230Sgdamore@opensolaris.org 104811230Sgdamore@opensolaris.org if ((fp = fdopen(fd, "w")) == NULL) { 104911230Sgdamore@opensolaris.org perror(_("Unable to open file\n")); 105011230Sgdamore@opensolaris.org (void) close(fd); 105111230Sgdamore@opensolaris.org (void) unlink(fname); 105211230Sgdamore@opensolaris.org return (errno); 105311230Sgdamore@opensolaris.org } 105411230Sgdamore@opensolaris.org 105511230Sgdamore@opensolaris.org (void) fprintf(fp, "# Device: %s\n", d->mixer.devnode); 105611230Sgdamore@opensolaris.org (void) fprintf(fp, "# Name = %s\n", d->card.shortname); 105711230Sgdamore@opensolaris.org (void) fprintf(fp, "# Config = %s\n", d->card.longname); 105811230Sgdamore@opensolaris.org 105911230Sgdamore@opensolaris.org if (strlen(d->card.hw_info)) { 106011230Sgdamore@opensolaris.org (void) fprintf(fp, "# HW Info = %s", d->card.hw_info); 106111230Sgdamore@opensolaris.org } 106211230Sgdamore@opensolaris.org (void) fprintf(fp, "#\n"); 106311230Sgdamore@opensolaris.org 106411230Sgdamore@opensolaris.org print_header(fp, 0); 106511230Sgdamore@opensolaris.org 106611230Sgdamore@opensolaris.org for (i = 0; i < d->cmax; i++) { 106711230Sgdamore@opensolaris.org cinfop = &d->controls[i]; 106811230Sgdamore@opensolaris.org rv = print_control(fp, d, cinfop, 0); 106911230Sgdamore@opensolaris.org rval = rval ? rval : rv; 107011230Sgdamore@opensolaris.org } 107111230Sgdamore@opensolaris.org 107211230Sgdamore@opensolaris.org (void) fclose(fp); 107311230Sgdamore@opensolaris.org 107411230Sgdamore@opensolaris.org return (rval); 107511230Sgdamore@opensolaris.org } 107611230Sgdamore@opensolaris.org 107711230Sgdamore@opensolaris.org int 107811230Sgdamore@opensolaris.org do_load_controls(int argc, char **argv) 107911230Sgdamore@opensolaris.org { 108011230Sgdamore@opensolaris.org int optc; 108111230Sgdamore@opensolaris.org int rval = 0; 108211230Sgdamore@opensolaris.org device_t *d; 108311230Sgdamore@opensolaris.org char *devname = NULL; 108411230Sgdamore@opensolaris.org char *fname; 108511230Sgdamore@opensolaris.org char *cname; 108611230Sgdamore@opensolaris.org char *value; 108711230Sgdamore@opensolaris.org int i; 108811230Sgdamore@opensolaris.org int rv; 108911230Sgdamore@opensolaris.org cinfo_t *cinfop; 109011230Sgdamore@opensolaris.org FILE *fp; 109111230Sgdamore@opensolaris.org char linebuf[MAXLINE]; 109211230Sgdamore@opensolaris.org int lineno = 0; 109311230Sgdamore@opensolaris.org int found; 109411230Sgdamore@opensolaris.org 109511230Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "d:")) != EOF) { 109611230Sgdamore@opensolaris.org switch (optc) { 109711230Sgdamore@opensolaris.org case 'd': 109811230Sgdamore@opensolaris.org devname = optarg; 109911230Sgdamore@opensolaris.org break; 110011230Sgdamore@opensolaris.org default: 110111230Sgdamore@opensolaris.org help(); 110211230Sgdamore@opensolaris.org return (-1); 110311230Sgdamore@opensolaris.org } 110411230Sgdamore@opensolaris.org } 110511230Sgdamore@opensolaris.org argc -= optind; 110611230Sgdamore@opensolaris.org argv += optind; 110711230Sgdamore@opensolaris.org 110811230Sgdamore@opensolaris.org if (argc != 1) { 110911230Sgdamore@opensolaris.org help(); 111011230Sgdamore@opensolaris.org return (-1); 111111230Sgdamore@opensolaris.org } 111211230Sgdamore@opensolaris.org fname = argv[0]; 111311230Sgdamore@opensolaris.org 111411230Sgdamore@opensolaris.org if ((d = find_device(devname)) == NULL) { 111511230Sgdamore@opensolaris.org return (ENODEV); 111611230Sgdamore@opensolaris.org } 111711230Sgdamore@opensolaris.org 111811230Sgdamore@opensolaris.org if ((fp = fopen(fname, "r")) == NULL) { 111911230Sgdamore@opensolaris.org perror(_("Unable to open file")); 112011230Sgdamore@opensolaris.org return (errno); 112111230Sgdamore@opensolaris.org } 112211230Sgdamore@opensolaris.org 112311230Sgdamore@opensolaris.org while (fgets(linebuf, sizeof (linebuf), fp) != NULL) { 112411230Sgdamore@opensolaris.org lineno++; 112511230Sgdamore@opensolaris.org if (linebuf[strlen(linebuf) - 1] != '\n') { 112611230Sgdamore@opensolaris.org warn(_("Warning: line too long at line %d\n"), lineno); 112711230Sgdamore@opensolaris.org /* read in the rest of the line and discard it */ 112811230Sgdamore@opensolaris.org while (fgets(linebuf, sizeof (linebuf), fp) != NULL && 112911230Sgdamore@opensolaris.org (linebuf[strlen(linebuf) - 1] != '\n')) { 113011230Sgdamore@opensolaris.org continue; 113111230Sgdamore@opensolaris.org } 113211230Sgdamore@opensolaris.org continue; 113311230Sgdamore@opensolaris.org } 113411230Sgdamore@opensolaris.org 113511230Sgdamore@opensolaris.org /* we have a good line ... */ 113611230Sgdamore@opensolaris.org cname = strtok(linebuf, " \t\n"); 113711230Sgdamore@opensolaris.org /* skip comments and blank lines */ 113811230Sgdamore@opensolaris.org if ((cname == NULL) || (cname[0] == '#')) { 113911230Sgdamore@opensolaris.org continue; 114011230Sgdamore@opensolaris.org } 114111230Sgdamore@opensolaris.org value = strtok(NULL, " \t\n"); 114211230Sgdamore@opensolaris.org if ((value == NULL) || (*cname == 0)) { 114311230Sgdamore@opensolaris.org warn(_("Warning: missing value at line %d\n"), lineno); 114411230Sgdamore@opensolaris.org continue; 114511230Sgdamore@opensolaris.org } 114611230Sgdamore@opensolaris.org 114711230Sgdamore@opensolaris.org for (i = 0, found = 0; i < d->cmax; i++) { 114811230Sgdamore@opensolaris.org /* save and restore requires an exact match */ 114911230Sgdamore@opensolaris.org cinfop = &d->controls[i]; 115011230Sgdamore@opensolaris.org if (strcmp(cinfop->ci.extname, cname) != 0) { 115111230Sgdamore@opensolaris.org continue; 115211230Sgdamore@opensolaris.org } 115311230Sgdamore@opensolaris.org found = 1; 115411230Sgdamore@opensolaris.org rv = set_device_control(d, cinfop, value, 0); 115511230Sgdamore@opensolaris.org rval = rval ? rval : rv; 115611230Sgdamore@opensolaris.org } 115711230Sgdamore@opensolaris.org if (!found) { 115811230Sgdamore@opensolaris.org warn(_("No such control: %s\n"), cname); 115911230Sgdamore@opensolaris.org } 116011230Sgdamore@opensolaris.org } 116111230Sgdamore@opensolaris.org (void) fclose(fp); 116211230Sgdamore@opensolaris.org 116311230Sgdamore@opensolaris.org return (rval); 116411230Sgdamore@opensolaris.org } 116511230Sgdamore@opensolaris.org 116611230Sgdamore@opensolaris.org int 116711253Sgdamore@opensolaris.org mixer_walker(di_devlink_t dlink, void *arg) 116811253Sgdamore@opensolaris.org { 116911253Sgdamore@opensolaris.org const char *link; 117011253Sgdamore@opensolaris.org int num; 117111253Sgdamore@opensolaris.org int fd; 117211253Sgdamore@opensolaris.org int verbose = *(int *)arg; 117311253Sgdamore@opensolaris.org int num_offset; 117411253Sgdamore@opensolaris.org 117511253Sgdamore@opensolaris.org num_offset = sizeof ("/dev/mixer") - 1; 117611253Sgdamore@opensolaris.org 117711253Sgdamore@opensolaris.org link = di_devlink_path(dlink); 117811253Sgdamore@opensolaris.org 117911253Sgdamore@opensolaris.org if ((link == NULL) || 118011253Sgdamore@opensolaris.org (strncmp(link, "/dev/mixer", num_offset) != 0) || 118111253Sgdamore@opensolaris.org (!isdigit(link[num_offset]))) { 118211253Sgdamore@opensolaris.org return (DI_WALK_CONTINUE); 118311253Sgdamore@opensolaris.org } 118411253Sgdamore@opensolaris.org 118511253Sgdamore@opensolaris.org num = atoi(link + num_offset); 118611253Sgdamore@opensolaris.org if ((fd = open(link, O_RDWR)) < 0) { 118711253Sgdamore@opensolaris.org if (verbose) { 118811253Sgdamore@opensolaris.org if (errno == ENOENT) { 118911253Sgdamore@opensolaris.org msg(_("Device %s not present.\n"), link); 119011253Sgdamore@opensolaris.org } else { 119111253Sgdamore@opensolaris.org msg(_("Unable to open device %s: %s\n"), 119211253Sgdamore@opensolaris.org link, strerror(errno)); 119311253Sgdamore@opensolaris.org } 119411253Sgdamore@opensolaris.org } 119511253Sgdamore@opensolaris.org return (DI_WALK_CONTINUE); 119611253Sgdamore@opensolaris.org } 119711253Sgdamore@opensolaris.org 119811253Sgdamore@opensolaris.org if (verbose) { 119911253Sgdamore@opensolaris.org msg(_("Initializing link %s: "), link); 120011253Sgdamore@opensolaris.org } 120111253Sgdamore@opensolaris.org if (ioctl(fd, SNDCTL_SUN_SEND_NUMBER, &num) != 0) { 120211253Sgdamore@opensolaris.org if (verbose) { 120311253Sgdamore@opensolaris.org msg(_("failed: %s\n"), strerror(errno)); 120411253Sgdamore@opensolaris.org } 120511253Sgdamore@opensolaris.org } else { 120611253Sgdamore@opensolaris.org if (verbose) { 120711253Sgdamore@opensolaris.org msg(_("done.\n")); 120811253Sgdamore@opensolaris.org } 120911253Sgdamore@opensolaris.org } 121011253Sgdamore@opensolaris.org (void) close(fd); 121111253Sgdamore@opensolaris.org return (DI_WALK_CONTINUE); 121211253Sgdamore@opensolaris.org } 121311253Sgdamore@opensolaris.org 121411253Sgdamore@opensolaris.org int 121511253Sgdamore@opensolaris.org do_init_devices(int argc, char **argv) 121611253Sgdamore@opensolaris.org { 121711253Sgdamore@opensolaris.org int optc; 121811253Sgdamore@opensolaris.org di_devlink_handle_t dlh; 121911253Sgdamore@opensolaris.org int verbose = 0; 122011253Sgdamore@opensolaris.org 122111253Sgdamore@opensolaris.org while ((optc = getopt(argc, argv, "v")) != EOF) { 122211253Sgdamore@opensolaris.org switch (optc) { 122311253Sgdamore@opensolaris.org case 'v': 122411253Sgdamore@opensolaris.org verbose = 1; 122511253Sgdamore@opensolaris.org break; 122611253Sgdamore@opensolaris.org default: 122711253Sgdamore@opensolaris.org help(); 122811253Sgdamore@opensolaris.org return (-1); 122911253Sgdamore@opensolaris.org } 123011253Sgdamore@opensolaris.org } 123111253Sgdamore@opensolaris.org argc -= optind; 123211253Sgdamore@opensolaris.org argv += optind; 123311253Sgdamore@opensolaris.org 123411253Sgdamore@opensolaris.org if (argc != 0) { 123511253Sgdamore@opensolaris.org help(); 123611253Sgdamore@opensolaris.org return (-1); 123711253Sgdamore@opensolaris.org } 123811253Sgdamore@opensolaris.org 123911253Sgdamore@opensolaris.org dlh = di_devlink_init(NULL, 0); 124011253Sgdamore@opensolaris.org if (dlh == NULL) { 124111253Sgdamore@opensolaris.org perror(_("Unable to initialize devlink handle")); 124211253Sgdamore@opensolaris.org return (-1); 124311253Sgdamore@opensolaris.org } 124411253Sgdamore@opensolaris.org 124511253Sgdamore@opensolaris.org if (di_devlink_walk(dlh, "^mixer", NULL, 0, &verbose, 124611253Sgdamore@opensolaris.org mixer_walker) != 0) { 124711253Sgdamore@opensolaris.org perror(_("Unable to walk devlinks")); 124811253Sgdamore@opensolaris.org return (-1); 124911253Sgdamore@opensolaris.org } 125011253Sgdamore@opensolaris.org return (0); 125111253Sgdamore@opensolaris.org } 125211253Sgdamore@opensolaris.org 125311253Sgdamore@opensolaris.org int 125411230Sgdamore@opensolaris.org main(int argc, char **argv) 125511230Sgdamore@opensolaris.org { 125611230Sgdamore@opensolaris.org int rv = 0; 125711230Sgdamore@opensolaris.org int opt; 125811230Sgdamore@opensolaris.org 125911230Sgdamore@opensolaris.org (void) setlocale(LC_ALL, ""); 126011230Sgdamore@opensolaris.org (void) textdomain(TEXT_DOMAIN); 126111230Sgdamore@opensolaris.org 126211230Sgdamore@opensolaris.org while ((opt = getopt(argc, argv, "h")) != EOF) { 126311230Sgdamore@opensolaris.org switch (opt) { 126411230Sgdamore@opensolaris.org case 'h': 126511230Sgdamore@opensolaris.org help(); 126611230Sgdamore@opensolaris.org rv = 0; 126711230Sgdamore@opensolaris.org goto OUT; 126811230Sgdamore@opensolaris.org default: 126911230Sgdamore@opensolaris.org rv = EINVAL; 127011230Sgdamore@opensolaris.org break; 127111230Sgdamore@opensolaris.org } 127211230Sgdamore@opensolaris.org } 127311230Sgdamore@opensolaris.org 127411230Sgdamore@opensolaris.org if (rv) { 127511230Sgdamore@opensolaris.org goto OUT; 127611230Sgdamore@opensolaris.org } 127711230Sgdamore@opensolaris.org 127811230Sgdamore@opensolaris.org argc -= optind; 127911230Sgdamore@opensolaris.org argv += optind; 128011230Sgdamore@opensolaris.org 128111230Sgdamore@opensolaris.org if (argc < 1) { 128211230Sgdamore@opensolaris.org help(); 128311230Sgdamore@opensolaris.org rv = EINVAL; 128411230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "help") == 0) { 128511230Sgdamore@opensolaris.org help(); 128611230Sgdamore@opensolaris.org rv = 0; 128711230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "list-devices") == 0) { 128811230Sgdamore@opensolaris.org rv = do_list_devices(argc, argv); 128911230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "show-device") == 0) { 129011230Sgdamore@opensolaris.org rv = do_show_device(argc, argv); 129111230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "show-control") == 0) { 129211230Sgdamore@opensolaris.org rv = do_show_control(argc, argv); 129311230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "set-control") == 0) { 129411230Sgdamore@opensolaris.org rv = do_set_control(argc, argv); 129511230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "load-controls") == 0) { 129611230Sgdamore@opensolaris.org rv = do_load_controls(argc, argv); 129711230Sgdamore@opensolaris.org } else if (strcmp(argv[0], "save-controls") == 0) { 129811230Sgdamore@opensolaris.org rv = do_save_controls(argc, argv); 129911253Sgdamore@opensolaris.org } else if (strcmp(argv[0], "init-devices") == 0) { 130011253Sgdamore@opensolaris.org rv = do_init_devices(argc, argv); 130111230Sgdamore@opensolaris.org } else { 130211230Sgdamore@opensolaris.org help(); 130311230Sgdamore@opensolaris.org rv = EINVAL; 130411230Sgdamore@opensolaris.org } 130511230Sgdamore@opensolaris.org 130611230Sgdamore@opensolaris.org OUT: 130711230Sgdamore@opensolaris.org free_devices(); 130811230Sgdamore@opensolaris.org return (rv); 130911230Sgdamore@opensolaris.org } 1310