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
msg(char * fmt,...)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
warn(char * fmt,...)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
free_device(device_t * d)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
free_devices(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 *
alloc_device(void)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 *
get_enum_str(cinfo_t * cinfop,int idx)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
get_device_info(device_t * d)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
load_devices(void)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
ctype_valid(int type)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
print_control_line(FILE * sfp,col_prt_t * colp,int vopt)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
print_header(FILE * sfp,int vopt)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
print_control(FILE * sfp,device_t * d,cinfo_t * cinfop,int vopt)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
set_device_control(device_t * d,cinfo_t * cinfop,char * wstr,int vopt)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
help(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
device_devt(char * name)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 *
find_device(char * name)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
do_list_devices(int argc,char ** argv)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
do_show_device(int argc,char ** argv)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
do_show_control(int argc,char ** argv)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
do_set_control(int argc,char ** argv)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
do_save_controls(int argc,char ** argv)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
do_load_controls(int argc,char ** argv)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
mixer_walker(di_devlink_t dlink,void * arg)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
do_init_devices(int argc,char ** argv)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
main(int argc,char ** argv)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