13ccb1966SGarrett D'Amore /* 23ccb1966SGarrett D'Amore * CDDL HEADER START 33ccb1966SGarrett D'Amore * 43ccb1966SGarrett D'Amore * The contents of this file are subject to the terms of the 53ccb1966SGarrett D'Amore * Common Development and Distribution License (the "License"). 63ccb1966SGarrett D'Amore * You may not use this file except in compliance with the License. 73ccb1966SGarrett D'Amore * 83ccb1966SGarrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93ccb1966SGarrett D'Amore * or http://www.opensolaris.org/os/licensing. 103ccb1966SGarrett D'Amore * See the License for the specific language governing permissions 113ccb1966SGarrett D'Amore * and limitations under the License. 123ccb1966SGarrett D'Amore * 133ccb1966SGarrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each 143ccb1966SGarrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153ccb1966SGarrett D'Amore * If applicable, add the following below this CDDL HEADER, with the 163ccb1966SGarrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying 173ccb1966SGarrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner] 183ccb1966SGarrett D'Amore * 193ccb1966SGarrett D'Amore * CDDL HEADER END 203ccb1966SGarrett D'Amore */ 213ccb1966SGarrett D'Amore /* 223ccb1966SGarrett D'Amore * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 233ccb1966SGarrett D'Amore * Use is subject to license terms. 243ccb1966SGarrett D'Amore */ 253ccb1966SGarrett D'Amore 263ccb1966SGarrett D'Amore #include <stdio.h> 273ccb1966SGarrett D'Amore #include <stdlib.h> 283ccb1966SGarrett D'Amore #include <errno.h> 293ccb1966SGarrett D'Amore #include <string.h> 303ccb1966SGarrett D'Amore #include <strings.h> 313ccb1966SGarrett D'Amore #include <locale.h> 323ccb1966SGarrett D'Amore #include <libintl.h> 333ccb1966SGarrett D'Amore #include <stdarg.h> 343ccb1966SGarrett D'Amore #include <stddef.h> 353ccb1966SGarrett D'Amore #include <sys/types.h> 363ccb1966SGarrett D'Amore #include <sys/stat.h> 373ccb1966SGarrett D'Amore #include <sys/mkdev.h> 383ccb1966SGarrett D'Amore #include <fcntl.h> 393ccb1966SGarrett D'Amore #include <unistd.h> 403ccb1966SGarrett D'Amore #include <ctype.h> 413ccb1966SGarrett D'Amore #include <sys/param.h> 423ccb1966SGarrett D'Amore #include <sys/soundcard.h> 43*aef5f291SGarrett D'Amore #include <libdevinfo.h> 443ccb1966SGarrett D'Amore 453ccb1966SGarrett D'Amore #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 463ccb1966SGarrett D'Amore #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 473ccb1966SGarrett D'Amore #endif 483ccb1966SGarrett D'Amore 493ccb1966SGarrett D'Amore #define _(s) gettext(s) 503ccb1966SGarrett D'Amore 513ccb1966SGarrett D'Amore #define MAXLINE 1024 523ccb1966SGarrett D'Amore 533ccb1966SGarrett D'Amore #define AUDIO_CTRL_STEREO_LEFT(v) ((uint8_t)((v) & 0xff)) 543ccb1966SGarrett D'Amore #define AUDIO_CTRL_STEREO_RIGHT(v) ((uint8_t)(((v) >> 8) & 0xff)) 553ccb1966SGarrett D'Amore #define AUDIO_CTRL_STEREO_VAL(l, r) (((l) & 0xff) | (((r) & 0xff) << 8)) 563ccb1966SGarrett D'Amore 573ccb1966SGarrett D'Amore /* 583ccb1966SGarrett D'Amore * These are borrowed from sys/audio/audio_common.h, where the values 593ccb1966SGarrett D'Amore * are protected by _KERNEL. 603ccb1966SGarrett D'Amore */ 613ccb1966SGarrett D'Amore #define AUDIO_MN_TYPE_NBITS (4) 623ccb1966SGarrett D'Amore #define AUDIO_MN_TYPE_MASK ((1U << AUDIO_MN_TYPE_NBITS) - 1) 633ccb1966SGarrett D'Amore #define AUDIO_MINOR_MIXER (0) 643ccb1966SGarrett D'Amore 653ccb1966SGarrett D'Amore 663ccb1966SGarrett D'Amore /* 673ccb1966SGarrett D'Amore * Column display information 683ccb1966SGarrett D'Amore * All are related to the types enumerated in col_t and any change should be 693ccb1966SGarrett D'Amore * reflected in the corresponding indices and offsets for all the variables 703ccb1966SGarrett D'Amore * accordingly. Most tweaks to the display can be done by adjusting the 713ccb1966SGarrett D'Amore * values here. 723ccb1966SGarrett D'Amore */ 733ccb1966SGarrett D'Amore 743ccb1966SGarrett D'Amore /* types of columns displayed */ 753ccb1966SGarrett D'Amore typedef enum { COL_DV = 0, COL_NM, COL_VAL, COL_SEL} col_t; 763ccb1966SGarrett D'Amore 773ccb1966SGarrett D'Amore /* corresponding sizes of columns; does not include trailing null */ 783ccb1966SGarrett D'Amore #define COL_DV_SZ 16 793ccb1966SGarrett D'Amore #define COL_NM_SZ 24 803ccb1966SGarrett D'Amore #define COL_VAL_SZ 10 813ccb1966SGarrett D'Amore #define COL_SEL_SZ 20 823ccb1966SGarrett D'Amore #define COL_MAX_SZ 64 833ccb1966SGarrett D'Amore 843ccb1966SGarrett D'Amore /* corresponding sizes of columns, indexed by col_t value */ 853ccb1966SGarrett D'Amore static int col_sz[] = { 863ccb1966SGarrett D'Amore COL_DV_SZ, COL_NM_SZ, COL_VAL_SZ, COL_SEL_SZ 873ccb1966SGarrett D'Amore }; 883ccb1966SGarrett D'Amore 893ccb1966SGarrett D'Amore /* used by callers of the printing function */ 903ccb1966SGarrett D'Amore typedef struct col_prt { 913ccb1966SGarrett D'Amore char *col_dv; 923ccb1966SGarrett D'Amore char *col_nm; 933ccb1966SGarrett D'Amore char *col_val; 943ccb1966SGarrett D'Amore char *col_sel; 953ccb1966SGarrett D'Amore } col_prt_t; 963ccb1966SGarrett D'Amore 973ccb1966SGarrett D'Amore /* columns displayed in order with vopt = 0 */ 983ccb1966SGarrett D'Amore static int col_dpy[] = {COL_NM, COL_VAL}; 993ccb1966SGarrett D'Amore static int col_dpy_len = sizeof (col_dpy) / sizeof (*col_dpy); 1003ccb1966SGarrett D'Amore 1013ccb1966SGarrett D'Amore /* tells the printing function what members to use; follows col_dpy[] */ 1023ccb1966SGarrett D'Amore static size_t col_dpy_prt[] = { 1033ccb1966SGarrett D'Amore offsetof(col_prt_t, col_nm), 1043ccb1966SGarrett D'Amore offsetof(col_prt_t, col_val), 1053ccb1966SGarrett D'Amore }; 1063ccb1966SGarrett D'Amore 1073ccb1966SGarrett D'Amore /* columns displayed in order with vopt = 1 */ 1083ccb1966SGarrett D'Amore static int col_dpy_vopt[] = { COL_DV, COL_NM, COL_VAL, COL_SEL}; 1093ccb1966SGarrett D'Amore static int col_dpy_vopt_len = sizeof (col_dpy_vopt) / sizeof (*col_dpy_vopt); 1103ccb1966SGarrett D'Amore 1113ccb1966SGarrett D'Amore /* tells the printing function what members to use; follows col_dpy_vopt[] */ 1123ccb1966SGarrett D'Amore static size_t col_dpy_prt_vopt[] = { 1133ccb1966SGarrett D'Amore offsetof(col_prt_t, col_dv), 1143ccb1966SGarrett D'Amore offsetof(col_prt_t, col_nm), 1153ccb1966SGarrett D'Amore offsetof(col_prt_t, col_val), 1163ccb1966SGarrett D'Amore offsetof(col_prt_t, col_sel) 1173ccb1966SGarrett D'Amore }; 1183ccb1966SGarrett D'Amore 1193ccb1966SGarrett D'Amore /* columns displayed in order with tofile = 1 */ 1203ccb1966SGarrett D'Amore static int col_dpy_tofile[] = { COL_NM, COL_VAL}; 1213ccb1966SGarrett D'Amore static int col_dpy_tofile_len = sizeof (col_dpy_tofile) / 1223ccb1966SGarrett D'Amore sizeof (*col_dpy_tofile); 1233ccb1966SGarrett D'Amore 1243ccb1966SGarrett D'Amore /* tells the printing function what members to use; follows col_dpy_tofile[] */ 1253ccb1966SGarrett D'Amore static size_t col_dpy_prt_tofile[] = { 1263ccb1966SGarrett D'Amore offsetof(col_prt_t, col_nm), 1273ccb1966SGarrett D'Amore offsetof(col_prt_t, col_val) 1283ccb1966SGarrett D'Amore }; 1293ccb1966SGarrett D'Amore 1303ccb1966SGarrett D'Amore 1313ccb1966SGarrett D'Amore /* 1323ccb1966SGarrett D'Amore * mixer and control accounting 1333ccb1966SGarrett D'Amore */ 1343ccb1966SGarrett D'Amore 1353ccb1966SGarrett D'Amore typedef struct cinfo { 1363ccb1966SGarrett D'Amore oss_mixext ci; 1373ccb1966SGarrett D'Amore oss_mixer_enuminfo *enump; 1383ccb1966SGarrett D'Amore } cinfo_t; 1393ccb1966SGarrett D'Amore 1403ccb1966SGarrett D'Amore typedef struct device { 1413ccb1966SGarrett D'Amore oss_card_info card; 1423ccb1966SGarrett D'Amore oss_mixerinfo mixer; 1433ccb1966SGarrett D'Amore 1443ccb1966SGarrett D'Amore int cmax; 1453ccb1966SGarrett D'Amore cinfo_t *controls; 1463ccb1966SGarrett D'Amore 1473ccb1966SGarrett D'Amore int mfd; 1483ccb1966SGarrett D'Amore dev_t devt; 1493ccb1966SGarrett D'Amore 1503ccb1966SGarrett D'Amore struct device *nextp; 1513ccb1966SGarrett D'Amore } device_t; 1523ccb1966SGarrett D'Amore 1533ccb1966SGarrett D'Amore static device_t *devices = NULL; 1543ccb1966SGarrett D'Amore 1553ccb1966SGarrett D'Amore /*PRINTFLIKE1*/ 1563ccb1966SGarrett D'Amore static void 1573ccb1966SGarrett D'Amore msg(char *fmt, ...) 1583ccb1966SGarrett D'Amore { 1593ccb1966SGarrett D'Amore va_list ap; 1603ccb1966SGarrett D'Amore 1613ccb1966SGarrett D'Amore va_start(ap, fmt); 1623ccb1966SGarrett D'Amore (void) vprintf(fmt, ap); 1633ccb1966SGarrett D'Amore va_end(ap); 1643ccb1966SGarrett D'Amore } 1653ccb1966SGarrett D'Amore 1663ccb1966SGarrett D'Amore /*PRINTFLIKE1*/ 1673ccb1966SGarrett D'Amore static void 1683ccb1966SGarrett D'Amore warn(char *fmt, ...) 1693ccb1966SGarrett D'Amore { 1703ccb1966SGarrett D'Amore va_list ap; 1713ccb1966SGarrett D'Amore 1723ccb1966SGarrett D'Amore va_start(ap, fmt); 1733ccb1966SGarrett D'Amore (void) vfprintf(stderr, fmt, ap); 1743ccb1966SGarrett D'Amore va_end(ap); 1753ccb1966SGarrett D'Amore } 1763ccb1966SGarrett D'Amore 1773ccb1966SGarrett D'Amore static void 1783ccb1966SGarrett D'Amore free_device(device_t *d) 1793ccb1966SGarrett D'Amore { 1803ccb1966SGarrett D'Amore int i; 1813ccb1966SGarrett D'Amore device_t **dpp; 1823ccb1966SGarrett D'Amore 1833ccb1966SGarrett D'Amore dpp = &devices; 1843ccb1966SGarrett D'Amore while ((*dpp) && ((*dpp) != d)) { 1853ccb1966SGarrett D'Amore dpp = &((*dpp)->nextp); 1863ccb1966SGarrett D'Amore } 1873ccb1966SGarrett D'Amore if (*dpp) { 1883ccb1966SGarrett D'Amore *dpp = d->nextp; 1893ccb1966SGarrett D'Amore } 1903ccb1966SGarrett D'Amore for (i = 0; i < d->cmax; i++) { 1913ccb1966SGarrett D'Amore if (d->controls[i].enump != NULL) 1923ccb1966SGarrett D'Amore free(d->controls[i].enump); 1933ccb1966SGarrett D'Amore } 1943ccb1966SGarrett D'Amore 1953ccb1966SGarrett D'Amore if (d->mfd >= 0) 1963ccb1966SGarrett D'Amore (void) close(d->mfd); 1973ccb1966SGarrett D'Amore 1983ccb1966SGarrett D'Amore free(d); 1993ccb1966SGarrett D'Amore } 2003ccb1966SGarrett D'Amore 2013ccb1966SGarrett D'Amore static void 2023ccb1966SGarrett D'Amore free_devices(void) 2033ccb1966SGarrett D'Amore { 2043ccb1966SGarrett D'Amore device_t *d = devices; 2053ccb1966SGarrett D'Amore 2063ccb1966SGarrett D'Amore while ((d = devices) != NULL) { 2073ccb1966SGarrett D'Amore free_device(d); 2083ccb1966SGarrett D'Amore } 2093ccb1966SGarrett D'Amore 2103ccb1966SGarrett D'Amore devices = NULL; 2113ccb1966SGarrett D'Amore } 2123ccb1966SGarrett D'Amore 2133ccb1966SGarrett D'Amore 2143ccb1966SGarrett D'Amore /* 2153ccb1966SGarrett D'Amore * adds to the end of global devices and returns a pointer to the new entry 2163ccb1966SGarrett D'Amore */ 2173ccb1966SGarrett D'Amore static device_t * 2183ccb1966SGarrett D'Amore alloc_device(void) 2193ccb1966SGarrett D'Amore { 2203ccb1966SGarrett D'Amore device_t *p; 2213ccb1966SGarrett D'Amore device_t *d = calloc(1, sizeof (*d)); 2223ccb1966SGarrett D'Amore 2233ccb1966SGarrett D'Amore d->card.card = -1; 2243ccb1966SGarrett D'Amore d->mixer.dev = -1; 2253ccb1966SGarrett D'Amore d->mfd = -1; 2263ccb1966SGarrett D'Amore 2273ccb1966SGarrett D'Amore if (devices == NULL) { 2283ccb1966SGarrett D'Amore devices = d; 2293ccb1966SGarrett D'Amore } else { 2303ccb1966SGarrett D'Amore for (p = devices; p->nextp != NULL; p = p->nextp) {} 2313ccb1966SGarrett D'Amore 2323ccb1966SGarrett D'Amore p->nextp = d; 2333ccb1966SGarrett D'Amore } 2343ccb1966SGarrett D'Amore return (d); 2353ccb1966SGarrett D'Amore } 2363ccb1966SGarrett D'Amore 2373ccb1966SGarrett D'Amore 2383ccb1966SGarrett D'Amore /* 2393ccb1966SGarrett D'Amore * cinfop->enump needs to be present 2403ccb1966SGarrett D'Amore * idx should be: >= 0 to < cinfop->ci.maxvalue 2413ccb1966SGarrett D'Amore */ 2423ccb1966SGarrett D'Amore static char * 2433ccb1966SGarrett D'Amore get_enum_str(cinfo_t *cinfop, int idx) 2443ccb1966SGarrett D'Amore { 2453ccb1966SGarrett D'Amore int sz = sizeof (*cinfop->ci.enum_present) * 8; 2463ccb1966SGarrett D'Amore 2473ccb1966SGarrett D'Amore if (cinfop->ci.enum_present[idx / sz] & (1 << (idx % sz))) 2483ccb1966SGarrett D'Amore return (cinfop->enump->strings + cinfop->enump->strindex[idx]); 2493ccb1966SGarrett D'Amore 2503ccb1966SGarrett D'Amore return (NULL); 2513ccb1966SGarrett D'Amore } 2523ccb1966SGarrett D'Amore 2533ccb1966SGarrett D'Amore 2543ccb1966SGarrett D'Amore /* 2553ccb1966SGarrett D'Amore * caller fills in d->mixer.devnode; func fills in the rest 2563ccb1966SGarrett D'Amore */ 2573ccb1966SGarrett D'Amore static int 2583ccb1966SGarrett D'Amore get_device_info(device_t *d) 2593ccb1966SGarrett D'Amore { 2603ccb1966SGarrett D'Amore int fd = -1; 2613ccb1966SGarrett D'Amore int i; 2623ccb1966SGarrett D'Amore cinfo_t *ci; 2633ccb1966SGarrett D'Amore 2643ccb1966SGarrett D'Amore if ((fd = open(d->mixer.devnode, O_RDWR)) < 0) { 2653ccb1966SGarrett D'Amore perror(_("Error opening device")); 2663ccb1966SGarrett D'Amore return (errno); 2673ccb1966SGarrett D'Amore } 2683ccb1966SGarrett D'Amore d->mfd = fd; 2693ccb1966SGarrett D'Amore 2703ccb1966SGarrett D'Amore d->cmax = -1; 2713ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_MIX_NREXT, &d->cmax) < 0) { 2723ccb1966SGarrett D'Amore perror(_("Error getting control count")); 2733ccb1966SGarrett D'Amore return (errno); 2743ccb1966SGarrett D'Amore } 2753ccb1966SGarrett D'Amore 2763ccb1966SGarrett D'Amore d->controls = calloc(d->cmax, sizeof (*d->controls)); 2773ccb1966SGarrett D'Amore 2783ccb1966SGarrett D'Amore for (i = 0; i < d->cmax; i++) { 2793ccb1966SGarrett D'Amore ci = &d->controls[i]; 2803ccb1966SGarrett D'Amore 2813ccb1966SGarrett D'Amore ci->ci.dev = -1; 2823ccb1966SGarrett D'Amore ci->ci.ctrl = i; 2833ccb1966SGarrett D'Amore 2843ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_MIX_EXTINFO, &ci->ci) < 0) { 2853ccb1966SGarrett D'Amore perror(_("Error getting control info")); 2863ccb1966SGarrett D'Amore return (errno); 2873ccb1966SGarrett D'Amore } 2883ccb1966SGarrett D'Amore 2893ccb1966SGarrett D'Amore if (ci->ci.type == MIXT_ENUM) { 2903ccb1966SGarrett D'Amore ci->enump = calloc(1, sizeof (*ci->enump)); 2913ccb1966SGarrett D'Amore ci->enump->dev = -1; 2923ccb1966SGarrett D'Amore ci->enump->ctrl = ci->ci.ctrl; 2933ccb1966SGarrett D'Amore 2943ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_MIX_ENUMINFO, ci->enump) < 0) { 2953ccb1966SGarrett D'Amore perror(_("Error getting enum info")); 2963ccb1966SGarrett D'Amore return (errno); 2973ccb1966SGarrett D'Amore } 2983ccb1966SGarrett D'Amore } 2993ccb1966SGarrett D'Amore } 3003ccb1966SGarrett D'Amore 3013ccb1966SGarrett D'Amore return (0); 3023ccb1966SGarrett D'Amore } 3033ccb1966SGarrett D'Amore 3043ccb1966SGarrett D'Amore 3053ccb1966SGarrett D'Amore static int 3063ccb1966SGarrett D'Amore load_devices(void) 3073ccb1966SGarrett D'Amore { 3083ccb1966SGarrett D'Amore int rv = -1; 3093ccb1966SGarrett D'Amore int fd = -1; 3103ccb1966SGarrett D'Amore int i; 3113ccb1966SGarrett D'Amore oss_sysinfo si; 3123ccb1966SGarrett D'Amore device_t *d; 3133ccb1966SGarrett D'Amore 314*aef5f291SGarrett D'Amore if (devices != NULL) { 315*aef5f291SGarrett D'Amore /* already loaded */ 316*aef5f291SGarrett D'Amore return (0); 317*aef5f291SGarrett D'Amore } 318*aef5f291SGarrett D'Amore 3193ccb1966SGarrett D'Amore if ((fd = open("/dev/mixer", O_RDWR)) < 0) { 3203ccb1966SGarrett D'Amore rv = errno; 3213ccb1966SGarrett D'Amore warn(_("Error opening mixer\n")); 3223ccb1966SGarrett D'Amore goto OUT; 3233ccb1966SGarrett D'Amore } 3243ccb1966SGarrett D'Amore 3253ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_SYSINFO, &si) < 0) { 3263ccb1966SGarrett D'Amore rv = errno; 3273ccb1966SGarrett D'Amore perror(_("Error getting system information")); 3283ccb1966SGarrett D'Amore goto OUT; 3293ccb1966SGarrett D'Amore } 3303ccb1966SGarrett D'Amore 3313ccb1966SGarrett D'Amore for (i = 0; i < si.nummixers; i++) { 3323ccb1966SGarrett D'Amore 3333ccb1966SGarrett D'Amore struct stat sbuf; 3343ccb1966SGarrett D'Amore 3353ccb1966SGarrett D'Amore d = alloc_device(); 3363ccb1966SGarrett D'Amore d->mixer.dev = i; 3373ccb1966SGarrett D'Amore 3383ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_MIXERINFO, &d->mixer) != 0) { 3393ccb1966SGarrett D'Amore continue; 3403ccb1966SGarrett D'Amore } 3413ccb1966SGarrett D'Amore 3423ccb1966SGarrett D'Amore d->card.card = d->mixer.card_number; 3433ccb1966SGarrett D'Amore 3443ccb1966SGarrett D'Amore if ((ioctl(fd, SNDCTL_CARDINFO, &d->card) != 0) || 3453ccb1966SGarrett D'Amore (stat(d->mixer.devnode, &sbuf) != 0) || 3463ccb1966SGarrett D'Amore ((sbuf.st_mode & S_IFCHR) == 0)) { 3473ccb1966SGarrett D'Amore warn(_("Device present: %s\n"), d->mixer.devnode); 3483ccb1966SGarrett D'Amore free_device(d); 3493ccb1966SGarrett D'Amore continue; 3503ccb1966SGarrett D'Amore } 3513ccb1966SGarrett D'Amore d->devt = makedev(major(sbuf.st_rdev), 3523ccb1966SGarrett D'Amore minor(sbuf.st_rdev) & ~(AUDIO_MN_TYPE_MASK)); 3533ccb1966SGarrett D'Amore 3543ccb1966SGarrett D'Amore if ((rv = get_device_info(d)) != 0) { 3553ccb1966SGarrett D'Amore free_device(d); 3563ccb1966SGarrett D'Amore goto OUT; 3573ccb1966SGarrett D'Amore } 3583ccb1966SGarrett D'Amore } 3593ccb1966SGarrett D'Amore 3603ccb1966SGarrett D'Amore rv = 0; 3613ccb1966SGarrett D'Amore 3623ccb1966SGarrett D'Amore OUT: 3633ccb1966SGarrett D'Amore if (fd >= 0) 3643ccb1966SGarrett D'Amore (void) close(fd); 3653ccb1966SGarrett D'Amore return (rv); 3663ccb1966SGarrett D'Amore } 3673ccb1966SGarrett D'Amore 3683ccb1966SGarrett D'Amore 3693ccb1966SGarrett D'Amore static int 3703ccb1966SGarrett D'Amore ctype_valid(int type) 3713ccb1966SGarrett D'Amore { 3723ccb1966SGarrett D'Amore switch (type) { 3733ccb1966SGarrett D'Amore case MIXT_ONOFF: 3743ccb1966SGarrett D'Amore case MIXT_ENUM: 3753ccb1966SGarrett D'Amore case MIXT_MONOSLIDER: 3763ccb1966SGarrett D'Amore case MIXT_STEREOSLIDER: 3773ccb1966SGarrett D'Amore return (1); 3783ccb1966SGarrett D'Amore default: 3793ccb1966SGarrett D'Amore return (0); 3803ccb1966SGarrett D'Amore } 3813ccb1966SGarrett D'Amore } 3823ccb1966SGarrett D'Amore 3833ccb1966SGarrett D'Amore 3843ccb1966SGarrett D'Amore static void 3853ccb1966SGarrett D'Amore print_control_line(FILE *sfp, col_prt_t *colp, int vopt) 3863ccb1966SGarrett D'Amore { 3873ccb1966SGarrett D'Amore int i; 3883ccb1966SGarrett D'Amore size_t *col_prtp; 3893ccb1966SGarrett D'Amore int *col_dpyp; 3903ccb1966SGarrett D'Amore int col_cnt; 3913ccb1966SGarrett D'Amore int col_type; 3923ccb1966SGarrett D'Amore int width; 3933ccb1966SGarrett D'Amore char *colstr; 3943ccb1966SGarrett D'Amore char cbuf[COL_MAX_SZ + 1]; 3953ccb1966SGarrett D'Amore char line[128]; 3963ccb1966SGarrett D'Amore char *colsep = " "; 3973ccb1966SGarrett D'Amore 3983ccb1966SGarrett D'Amore if (sfp != NULL) { 3993ccb1966SGarrett D'Amore col_prtp = col_dpy_prt_tofile; 4003ccb1966SGarrett D'Amore col_dpyp = col_dpy_tofile; 4013ccb1966SGarrett D'Amore col_cnt = col_dpy_tofile_len; 4023ccb1966SGarrett D'Amore } else if (vopt) { 4033ccb1966SGarrett D'Amore col_prtp = col_dpy_prt_vopt; 4043ccb1966SGarrett D'Amore col_dpyp = col_dpy_vopt; 4053ccb1966SGarrett D'Amore col_cnt = col_dpy_vopt_len; 4063ccb1966SGarrett D'Amore } else { 4073ccb1966SGarrett D'Amore col_prtp = col_dpy_prt; 4083ccb1966SGarrett D'Amore col_dpyp = col_dpy; 4093ccb1966SGarrett D'Amore col_cnt = col_dpy_len; 4103ccb1966SGarrett D'Amore } 4113ccb1966SGarrett D'Amore 4123ccb1966SGarrett D'Amore line[0] = '\0'; 4133ccb1966SGarrett D'Amore 4143ccb1966SGarrett D'Amore for (i = 0; i < col_cnt; i++) { 4153ccb1966SGarrett D'Amore col_type = col_dpyp[i]; 4163ccb1966SGarrett D'Amore width = col_sz[col_type]; 4173ccb1966SGarrett D'Amore colstr = *(char **)(((size_t)colp) + col_prtp[i]); 4183ccb1966SGarrett D'Amore 4193ccb1966SGarrett D'Amore (void) snprintf(cbuf, sizeof (cbuf), "%- *s", 4203ccb1966SGarrett D'Amore width > 0 ? width : 1, 4213ccb1966SGarrett D'Amore (colstr == NULL) ? "" : colstr); 4223ccb1966SGarrett D'Amore 4233ccb1966SGarrett D'Amore (void) strlcat(line, cbuf, sizeof (line)); 4243ccb1966SGarrett D'Amore if (i < col_cnt - 1) 4253ccb1966SGarrett D'Amore (void) strlcat(line, colsep, sizeof (line)); 4263ccb1966SGarrett D'Amore } 4273ccb1966SGarrett D'Amore 4283ccb1966SGarrett D'Amore (void) fprintf(sfp ? sfp : stdout, "%s\n", line); 4293ccb1966SGarrett D'Amore } 4303ccb1966SGarrett D'Amore 4313ccb1966SGarrett D'Amore 4323ccb1966SGarrett D'Amore static void 4333ccb1966SGarrett D'Amore print_header(FILE *sfp, int vopt) 4343ccb1966SGarrett D'Amore { 4353ccb1966SGarrett D'Amore col_prt_t col; 4363ccb1966SGarrett D'Amore 4373ccb1966SGarrett D'Amore if (sfp) { 4383ccb1966SGarrett D'Amore col.col_nm = _("#CONTROL"); 4393ccb1966SGarrett D'Amore col.col_val = _("VALUE"); 4403ccb1966SGarrett D'Amore } else { 4413ccb1966SGarrett D'Amore col.col_dv = _("DEVICE"); 4423ccb1966SGarrett D'Amore col.col_nm = _("CONTROL"); 4433ccb1966SGarrett D'Amore col.col_val = _("VALUE"); 4443ccb1966SGarrett D'Amore col.col_sel = _("POSSIBLE"); 4453ccb1966SGarrett D'Amore } 4463ccb1966SGarrett D'Amore print_control_line(sfp, &col, vopt); 4473ccb1966SGarrett D'Amore } 4483ccb1966SGarrett D'Amore 4493ccb1966SGarrett D'Amore 4503ccb1966SGarrett D'Amore static int 4513ccb1966SGarrett D'Amore print_control(FILE *sfp, device_t *d, cinfo_t *cinfop, int vopt) 4523ccb1966SGarrett D'Amore { 4533ccb1966SGarrett D'Amore int mfd = d->mfd; 4543ccb1966SGarrett D'Amore char *devnm = d->card.shortname; 4553ccb1966SGarrett D'Amore oss_mixer_value cval; 4563ccb1966SGarrett D'Amore char *str; 4573ccb1966SGarrett D'Amore int i; 4583ccb1966SGarrett D'Amore int idx = -1; 4593ccb1966SGarrett D'Amore int rv = -1; 4603ccb1966SGarrett D'Amore char valbuf[COL_VAL_SZ + 1]; 4613ccb1966SGarrett D'Amore char selbuf[COL_SEL_SZ + 1]; 4623ccb1966SGarrett D'Amore col_prt_t col; 4633ccb1966SGarrett D'Amore 4643ccb1966SGarrett D'Amore cval.dev = -1; 4653ccb1966SGarrett D'Amore cval.ctrl = cinfop->ci.ctrl; 4663ccb1966SGarrett D'Amore 4673ccb1966SGarrett D'Amore if (ctype_valid(cinfop->ci.type)) { 4683ccb1966SGarrett D'Amore if (ioctl(mfd, SNDCTL_MIX_READ, &cval) < 0) { 4693ccb1966SGarrett D'Amore rv = errno; 4703ccb1966SGarrett D'Amore perror(_("Error reading control\n")); 4713ccb1966SGarrett D'Amore return (rv); 4723ccb1966SGarrett D'Amore } 4733ccb1966SGarrett D'Amore } else { 4743ccb1966SGarrett D'Amore return (0); 4753ccb1966SGarrett D'Amore } 4763ccb1966SGarrett D'Amore 4773ccb1966SGarrett D'Amore /* 4783ccb1966SGarrett D'Amore * convert the control value into a string 4793ccb1966SGarrett D'Amore */ 4803ccb1966SGarrett D'Amore switch (cinfop->ci.type) { 4813ccb1966SGarrett D'Amore case MIXT_ONOFF: 4823ccb1966SGarrett D'Amore (void) snprintf(valbuf, sizeof (valbuf), "%s", 4833ccb1966SGarrett D'Amore cval.value ? _("on") : _("off")); 4843ccb1966SGarrett D'Amore break; 4853ccb1966SGarrett D'Amore 4863ccb1966SGarrett D'Amore case MIXT_MONOSLIDER: 4873ccb1966SGarrett D'Amore (void) snprintf(valbuf, sizeof (valbuf), "%d", 4883ccb1966SGarrett D'Amore cval.value & 0xff); 4893ccb1966SGarrett D'Amore break; 4903ccb1966SGarrett D'Amore 4913ccb1966SGarrett D'Amore case MIXT_STEREOSLIDER: 4923ccb1966SGarrett D'Amore (void) snprintf(valbuf, sizeof (valbuf), "%d:%d", 4933ccb1966SGarrett D'Amore (int)AUDIO_CTRL_STEREO_LEFT(cval.value), 4943ccb1966SGarrett D'Amore (int)AUDIO_CTRL_STEREO_RIGHT(cval.value)); 4953ccb1966SGarrett D'Amore break; 4963ccb1966SGarrett D'Amore 4973ccb1966SGarrett D'Amore case MIXT_ENUM: 4983ccb1966SGarrett D'Amore str = get_enum_str(cinfop, cval.value); 4993ccb1966SGarrett D'Amore if (str == NULL) { 5003ccb1966SGarrett D'Amore warn(_("Bad enum index %d for control '%s'\n"), 5013ccb1966SGarrett D'Amore cval.value, cinfop->ci.extname); 5023ccb1966SGarrett D'Amore return (EINVAL); 5033ccb1966SGarrett D'Amore } 5043ccb1966SGarrett D'Amore 5053ccb1966SGarrett D'Amore (void) snprintf(valbuf, sizeof (valbuf), "%s", str); 5063ccb1966SGarrett D'Amore break; 5073ccb1966SGarrett D'Amore 5083ccb1966SGarrett D'Amore default: 5093ccb1966SGarrett D'Amore return (0); 5103ccb1966SGarrett D'Amore } 5113ccb1966SGarrett D'Amore 5123ccb1966SGarrett D'Amore /* 5133ccb1966SGarrett D'Amore * possible control values (range/selection) 5143ccb1966SGarrett D'Amore */ 5153ccb1966SGarrett D'Amore switch (cinfop->ci.type) { 5163ccb1966SGarrett D'Amore case MIXT_ONOFF: 5173ccb1966SGarrett D'Amore (void) snprintf(selbuf, sizeof (selbuf), _("on,off")); 5183ccb1966SGarrett D'Amore break; 5193ccb1966SGarrett D'Amore 5203ccb1966SGarrett D'Amore case MIXT_MONOSLIDER: 5213ccb1966SGarrett D'Amore (void) snprintf(selbuf, sizeof (selbuf), "%d-%d", 5223ccb1966SGarrett D'Amore cinfop->ci.minvalue, cinfop->ci.maxvalue); 5233ccb1966SGarrett D'Amore break; 5243ccb1966SGarrett D'Amore case MIXT_STEREOSLIDER: 5253ccb1966SGarrett D'Amore (void) snprintf(selbuf, sizeof (selbuf), "%d-%d:%d-%d", 5263ccb1966SGarrett D'Amore cinfop->ci.minvalue, cinfop->ci.maxvalue, 5273ccb1966SGarrett D'Amore cinfop->ci.minvalue, cinfop->ci.maxvalue); 5283ccb1966SGarrett D'Amore break; 5293ccb1966SGarrett D'Amore 5303ccb1966SGarrett D'Amore case MIXT_ENUM: 5313ccb1966SGarrett D'Amore /* 5323ccb1966SGarrett D'Amore * display the first choice on the same line, then display 5333ccb1966SGarrett D'Amore * the rest on multiple lines 5343ccb1966SGarrett D'Amore */ 5353ccb1966SGarrett D'Amore selbuf[0] = 0; 5363ccb1966SGarrett D'Amore for (i = 0; i < cinfop->ci.maxvalue; i++) { 5373ccb1966SGarrett D'Amore str = get_enum_str(cinfop, i); 5383ccb1966SGarrett D'Amore if (str == NULL) 5393ccb1966SGarrett D'Amore continue; 5403ccb1966SGarrett D'Amore 5413ccb1966SGarrett D'Amore if ((strlen(str) + 1 + strlen(selbuf)) >= 5423ccb1966SGarrett D'Amore sizeof (selbuf)) { 5433ccb1966SGarrett D'Amore break; 5443ccb1966SGarrett D'Amore } 5453ccb1966SGarrett D'Amore if (strlen(selbuf)) { 5463ccb1966SGarrett D'Amore (void) strlcat(selbuf, ",", sizeof (selbuf)); 5473ccb1966SGarrett D'Amore } 5483ccb1966SGarrett D'Amore 5493ccb1966SGarrett D'Amore (void) strlcat(selbuf, str, sizeof (selbuf)); 5503ccb1966SGarrett D'Amore } 5513ccb1966SGarrett D'Amore idx = i; 5523ccb1966SGarrett D'Amore break; 5533ccb1966SGarrett D'Amore 5543ccb1966SGarrett D'Amore default: 5553ccb1966SGarrett D'Amore (void) snprintf(selbuf, sizeof (selbuf), "-"); 5563ccb1966SGarrett D'Amore } 5573ccb1966SGarrett D'Amore 5583ccb1966SGarrett D'Amore col.col_dv = devnm; 5593ccb1966SGarrett D'Amore col.col_nm = strlen(cinfop->ci.extname) ? 5603ccb1966SGarrett D'Amore cinfop->ci.extname : cinfop->ci.id; 5613ccb1966SGarrett D'Amore while (strchr(col.col_nm, '_') != NULL) { 5623ccb1966SGarrett D'Amore col.col_nm = strchr(col.col_nm, '_') + 1; 5633ccb1966SGarrett D'Amore } 5643ccb1966SGarrett D'Amore col.col_val = valbuf; 5653ccb1966SGarrett D'Amore col.col_sel = selbuf; 5663ccb1966SGarrett D'Amore print_control_line(sfp, &col, vopt); 5673ccb1966SGarrett D'Amore 5683ccb1966SGarrett D'Amore /* print leftover enum value selections */ 5693ccb1966SGarrett D'Amore while ((sfp == NULL) && (idx >= 0) && (idx < cinfop->ci.maxvalue)) { 5703ccb1966SGarrett D'Amore selbuf[0] = 0; 5713ccb1966SGarrett D'Amore for (i = idx; i < cinfop->ci.maxvalue; i++) { 5723ccb1966SGarrett D'Amore str = get_enum_str(cinfop, i); 5733ccb1966SGarrett D'Amore if (str == NULL) 5743ccb1966SGarrett D'Amore continue; 5753ccb1966SGarrett D'Amore 5763ccb1966SGarrett D'Amore if ((strlen(str) + 1 + strlen(selbuf)) >= 5773ccb1966SGarrett D'Amore sizeof (selbuf)) { 5783ccb1966SGarrett D'Amore break; 5793ccb1966SGarrett D'Amore } 5803ccb1966SGarrett D'Amore if (strlen(selbuf)) { 5813ccb1966SGarrett D'Amore (void) strlcat(selbuf, ",", sizeof (selbuf)); 5823ccb1966SGarrett D'Amore } 5833ccb1966SGarrett D'Amore 5843ccb1966SGarrett D'Amore (void) strlcat(selbuf, str, sizeof (selbuf)); 5853ccb1966SGarrett D'Amore } 5863ccb1966SGarrett D'Amore idx = i; 5873ccb1966SGarrett D'Amore col.col_dv = NULL; 5883ccb1966SGarrett D'Amore col.col_nm = NULL; 5893ccb1966SGarrett D'Amore col.col_val = NULL; 5903ccb1966SGarrett D'Amore col.col_sel = selbuf; 5913ccb1966SGarrett D'Amore print_control_line(sfp, &col, vopt); 5923ccb1966SGarrett D'Amore } 5933ccb1966SGarrett D'Amore 5943ccb1966SGarrett D'Amore return (0); 5953ccb1966SGarrett D'Amore } 5963ccb1966SGarrett D'Amore 5973ccb1966SGarrett D'Amore 5983ccb1966SGarrett D'Amore static int 5993ccb1966SGarrett D'Amore set_device_control(device_t *d, cinfo_t *cinfop, char *wstr, int vopt) 6003ccb1966SGarrett D'Amore { 6013ccb1966SGarrett D'Amore int mfd = d->mfd; 6023ccb1966SGarrett D'Amore oss_mixer_value cval; 6033ccb1966SGarrett D'Amore int wlen = strlen(wstr); 6043ccb1966SGarrett D'Amore int lval, rval; 6053ccb1966SGarrett D'Amore char *lstr, *rstr; 6063ccb1966SGarrett D'Amore char *str; 6073ccb1966SGarrett D'Amore int i; 6083ccb1966SGarrett D'Amore int rv = -1; 6093ccb1966SGarrett D'Amore 6103ccb1966SGarrett D'Amore cval.dev = -1; 6113ccb1966SGarrett D'Amore cval.ctrl = cinfop->ci.ctrl; 6123ccb1966SGarrett D'Amore cval.value = 0; 6133ccb1966SGarrett D'Amore 6143ccb1966SGarrett D'Amore switch (cinfop->ci.type) { 6153ccb1966SGarrett D'Amore case MIXT_ONOFF: 6163ccb1966SGarrett D'Amore cval.value = (strncmp(_("on"), wstr, wlen) == 0) ? 1 : 0; 6173ccb1966SGarrett D'Amore break; 6183ccb1966SGarrett D'Amore 6193ccb1966SGarrett D'Amore case MIXT_MONOSLIDER: 6203ccb1966SGarrett D'Amore cval.value = atoi(wstr); 6213ccb1966SGarrett D'Amore break; 6223ccb1966SGarrett D'Amore 6233ccb1966SGarrett D'Amore case MIXT_STEREOSLIDER: 6243ccb1966SGarrett D'Amore lstr = wstr; 6253ccb1966SGarrett D'Amore rstr = strchr(wstr, ':'); 6263ccb1966SGarrett D'Amore if (rstr != NULL) { 6273ccb1966SGarrett D'Amore *rstr = '\0'; 6283ccb1966SGarrett D'Amore rstr++; 6293ccb1966SGarrett D'Amore 6303ccb1966SGarrett D'Amore rval = atoi(rstr); 6313ccb1966SGarrett D'Amore lval = atoi(lstr); 6323ccb1966SGarrett D'Amore 6333ccb1966SGarrett D'Amore rstr--; 6343ccb1966SGarrett D'Amore *rstr = ':'; 6353ccb1966SGarrett D'Amore } else { 6363ccb1966SGarrett D'Amore lval = atoi(lstr); 6373ccb1966SGarrett D'Amore rval = lval; 6383ccb1966SGarrett D'Amore } 6393ccb1966SGarrett D'Amore 6403ccb1966SGarrett D'Amore cval.value = AUDIO_CTRL_STEREO_VAL(lval, rval); 6413ccb1966SGarrett D'Amore break; 6423ccb1966SGarrett D'Amore 6433ccb1966SGarrett D'Amore case MIXT_ENUM: 6443ccb1966SGarrett D'Amore for (i = 0; i < cinfop->ci.maxvalue; i++) { 6453ccb1966SGarrett D'Amore str = get_enum_str(cinfop, i); 6463ccb1966SGarrett D'Amore if (str == NULL) 6473ccb1966SGarrett D'Amore continue; 6483ccb1966SGarrett D'Amore 6493ccb1966SGarrett D'Amore if (strncmp(wstr, str, wlen) == 0) { 6503ccb1966SGarrett D'Amore cval.value = i; 6513ccb1966SGarrett D'Amore break; 6523ccb1966SGarrett D'Amore } 6533ccb1966SGarrett D'Amore } 6543ccb1966SGarrett D'Amore 6553ccb1966SGarrett D'Amore if (i >= cinfop->ci.maxvalue) { 6563ccb1966SGarrett D'Amore warn(_("Invalid enumeration value\n")); 6573ccb1966SGarrett D'Amore return (EINVAL); 6583ccb1966SGarrett D'Amore } 6593ccb1966SGarrett D'Amore break; 6603ccb1966SGarrett D'Amore 6613ccb1966SGarrett D'Amore default: 6623ccb1966SGarrett D'Amore warn(_("Unsupported control type: %d\n"), cinfop->ci.type); 6633ccb1966SGarrett D'Amore return (EINVAL); 6643ccb1966SGarrett D'Amore } 6653ccb1966SGarrett D'Amore 6663ccb1966SGarrett D'Amore if (vopt) { 6673ccb1966SGarrett D'Amore msg(_("%s: '%s' set to '%s'\n"), d->card.shortname, 6683ccb1966SGarrett D'Amore cinfop->ci.extname, wstr); 6693ccb1966SGarrett D'Amore } 6703ccb1966SGarrett D'Amore 6713ccb1966SGarrett D'Amore if (ioctl(mfd, SNDCTL_MIX_WRITE, &cval) < 0) { 6723ccb1966SGarrett D'Amore rv = errno; 6733ccb1966SGarrett D'Amore perror(_("Error writing control")); 6743ccb1966SGarrett D'Amore return (rv); 6753ccb1966SGarrett D'Amore } 6763ccb1966SGarrett D'Amore 6773ccb1966SGarrett D'Amore rv = 0; 6783ccb1966SGarrett D'Amore return (rv); 6793ccb1966SGarrett D'Amore } 6803ccb1966SGarrett D'Amore 6813ccb1966SGarrett D'Amore 6823ccb1966SGarrett D'Amore static void 6833ccb1966SGarrett D'Amore help(void) 6843ccb1966SGarrett D'Amore { 6853ccb1966SGarrett D'Amore #define HELP_STR _( \ 6863ccb1966SGarrett D'Amore "audioctl list-devices\n" \ 6873ccb1966SGarrett D'Amore " list all audio devices\n" \ 6883ccb1966SGarrett D'Amore "\n" \ 6893ccb1966SGarrett D'Amore "audioctl show-device [ -v ] [ -d <device> ]\n" \ 6903ccb1966SGarrett D'Amore " display information about an audio device\n" \ 6913ccb1966SGarrett D'Amore "\n" \ 6923ccb1966SGarrett D'Amore "audioctl show-control [ -v ] [ -d <device> ] [ <control> ... ]\n" \ 6933ccb1966SGarrett D'Amore " get the value of a specific control (all if not specified)\n" \ 6943ccb1966SGarrett D'Amore "\n" \ 6953ccb1966SGarrett D'Amore "audioctl set-control [ -v ] [ -d <device> ] <control> <value>\n" \ 6963ccb1966SGarrett D'Amore " set the value of a specific control\n" \ 6973ccb1966SGarrett D'Amore "\n" \ 6983ccb1966SGarrett D'Amore "audioctl save-controls [ -d <device> ] [ -f ] <file>\n" \ 6993ccb1966SGarrett D'Amore " save all control settings for the device to a file\n" \ 7003ccb1966SGarrett D'Amore "\n" \ 7013ccb1966SGarrett D'Amore "audioctl load-controls [ -d <device> ] <file>\n" \ 7023ccb1966SGarrett D'Amore " restore previously saved control settings to device\n" \ 7033ccb1966SGarrett D'Amore "\n" \ 7043ccb1966SGarrett D'Amore "audioctl help\n" \ 7053ccb1966SGarrett D'Amore " show this message.\n") 7063ccb1966SGarrett D'Amore 7073ccb1966SGarrett D'Amore (void) fprintf(stderr, HELP_STR); 7083ccb1966SGarrett D'Amore } 7093ccb1966SGarrett D'Amore 7103ccb1966SGarrett D'Amore dev_t 7113ccb1966SGarrett D'Amore device_devt(char *name) 7123ccb1966SGarrett D'Amore { 7133ccb1966SGarrett D'Amore struct stat sbuf; 7143ccb1966SGarrett D'Amore 7153ccb1966SGarrett D'Amore if ((stat(name, &sbuf) != 0) || 7163ccb1966SGarrett D'Amore ((sbuf.st_mode & S_IFCHR) == 0)) { 7173ccb1966SGarrett D'Amore /* Not a device node! */ 7183ccb1966SGarrett D'Amore return (0); 7193ccb1966SGarrett D'Amore } 7203ccb1966SGarrett D'Amore 7213ccb1966SGarrett D'Amore return (makedev(major(sbuf.st_rdev), 7223ccb1966SGarrett D'Amore minor(sbuf.st_rdev) & ~(AUDIO_MN_TYPE_MASK))); 7233ccb1966SGarrett D'Amore } 7243ccb1966SGarrett D'Amore 7253ccb1966SGarrett D'Amore static device_t * 7263ccb1966SGarrett D'Amore find_device(char *name) 7273ccb1966SGarrett D'Amore { 7283ccb1966SGarrett D'Amore dev_t devt; 7293ccb1966SGarrett D'Amore device_t *d; 7303ccb1966SGarrett D'Amore 7313ccb1966SGarrett D'Amore /* 7323ccb1966SGarrett D'Amore * User may have specified: 7333ccb1966SGarrett D'Amore * 7343ccb1966SGarrett D'Amore * /dev/dsp[<num>] 7353ccb1966SGarrett D'Amore * /dev/mixer[<num>] 7363ccb1966SGarrett D'Amore * /dev/audio[<num>9] 7373ccb1966SGarrett D'Amore * /dev/audioctl[<num>] 7383ccb1966SGarrett D'Amore * /dev/sound/<num>{,ctl,dsp,mixer} 7393ccb1966SGarrett D'Amore * /dev/sound/<driver>:<num>{,ctl,dsp,mixer} 7403ccb1966SGarrett D'Amore * 7413ccb1966SGarrett D'Amore * We can canonicalize these by looking at the dev_t though. 7423ccb1966SGarrett D'Amore */ 7433ccb1966SGarrett D'Amore 744*aef5f291SGarrett D'Amore if (load_devices() != 0) { 745*aef5f291SGarrett D'Amore return (NULL); 746*aef5f291SGarrett D'Amore } 747*aef5f291SGarrett D'Amore 7483ccb1966SGarrett D'Amore if (name == NULL) 7493ccb1966SGarrett D'Amore name = getenv("AUDIODEV"); 7503ccb1966SGarrett D'Amore 7513ccb1966SGarrett D'Amore if ((name == NULL) || 7523ccb1966SGarrett D'Amore (strcmp(name, "/dev/mixer") == 0)) { 7533ccb1966SGarrett D'Amore /* /dev/mixer node doesn't point to real hw */ 7543ccb1966SGarrett D'Amore name = "/dev/dsp"; 7553ccb1966SGarrett D'Amore } 7563ccb1966SGarrett D'Amore 7573ccb1966SGarrett D'Amore if (*name == '/') { 7583ccb1966SGarrett D'Amore /* if we have a full path, convert to the devt */ 7593ccb1966SGarrett D'Amore if ((devt = device_devt(name)) == 0) { 7603ccb1966SGarrett D'Amore warn(_("No such audio device.\n")); 7613ccb1966SGarrett D'Amore return (NULL); 7623ccb1966SGarrett D'Amore } 7633ccb1966SGarrett D'Amore name = NULL; 7643ccb1966SGarrett D'Amore } 7653ccb1966SGarrett D'Amore 7663ccb1966SGarrett D'Amore for (d = devices; d != NULL; d = d->nextp) { 7673ccb1966SGarrett D'Amore oss_card_info *card = &d->card; 7683ccb1966SGarrett D'Amore 7693ccb1966SGarrett D'Amore if ((name) && (strcmp(name, card->shortname) == 0)) { 7703ccb1966SGarrett D'Amore return (d); 7713ccb1966SGarrett D'Amore } 7723ccb1966SGarrett D'Amore if (devt == d->devt) { 7733ccb1966SGarrett D'Amore return (d); 7743ccb1966SGarrett D'Amore } 7753ccb1966SGarrett D'Amore } 7763ccb1966SGarrett D'Amore 7773ccb1966SGarrett D'Amore warn(_("No such audio device.\n")); 7783ccb1966SGarrett D'Amore return (NULL); 7793ccb1966SGarrett D'Amore } 7803ccb1966SGarrett D'Amore 7813ccb1966SGarrett D'Amore int 7823ccb1966SGarrett D'Amore do_list_devices(int argc, char **argv) 7833ccb1966SGarrett D'Amore { 7843ccb1966SGarrett D'Amore int optc; 7853ccb1966SGarrett D'Amore int verbose = 0; 7863ccb1966SGarrett D'Amore device_t *d; 7873ccb1966SGarrett D'Amore 7883ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "v")) != EOF) { 7893ccb1966SGarrett D'Amore switch (optc) { 7903ccb1966SGarrett D'Amore case 'v': 7913ccb1966SGarrett D'Amore verbose++; 7923ccb1966SGarrett D'Amore break; 7933ccb1966SGarrett D'Amore default: 7943ccb1966SGarrett D'Amore help(); 7953ccb1966SGarrett D'Amore return (-1); 7963ccb1966SGarrett D'Amore } 7973ccb1966SGarrett D'Amore } 7983ccb1966SGarrett D'Amore argc -= optind; 7993ccb1966SGarrett D'Amore argv += optind; 8003ccb1966SGarrett D'Amore if (argc != 0) { 8013ccb1966SGarrett D'Amore help(); 8023ccb1966SGarrett D'Amore return (-1); 8033ccb1966SGarrett D'Amore } 8043ccb1966SGarrett D'Amore 805*aef5f291SGarrett D'Amore if (load_devices() != 0) { 806*aef5f291SGarrett D'Amore return (-1); 807*aef5f291SGarrett D'Amore } 808*aef5f291SGarrett D'Amore 8093ccb1966SGarrett D'Amore for (d = devices; d != NULL; d = d->nextp) { 8103ccb1966SGarrett D'Amore 8113ccb1966SGarrett D'Amore if ((d->mixer.enabled == 0) && (!verbose)) 8123ccb1966SGarrett D'Amore continue; 8133ccb1966SGarrett D'Amore 8143ccb1966SGarrett D'Amore if (verbose) { 8153ccb1966SGarrett D'Amore msg(_("%s (%s)\n"), d->card.shortname, 8163ccb1966SGarrett D'Amore d->mixer.devnode); 8173ccb1966SGarrett D'Amore } else { 8183ccb1966SGarrett D'Amore msg(_("%s\n"), d->card.shortname); 8193ccb1966SGarrett D'Amore } 8203ccb1966SGarrett D'Amore } 8213ccb1966SGarrett D'Amore 8223ccb1966SGarrett D'Amore return (0); 8233ccb1966SGarrett D'Amore } 8243ccb1966SGarrett D'Amore 8253ccb1966SGarrett D'Amore int 8263ccb1966SGarrett D'Amore do_show_device(int argc, char **argv) 8273ccb1966SGarrett D'Amore { 8283ccb1966SGarrett D'Amore int optc; 8293ccb1966SGarrett D'Amore char *devname = NULL; 8303ccb1966SGarrett D'Amore device_t *d; 8313ccb1966SGarrett D'Amore 8323ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:v")) != EOF) { 8333ccb1966SGarrett D'Amore switch (optc) { 8343ccb1966SGarrett D'Amore case 'd': 8353ccb1966SGarrett D'Amore devname = optarg; 8363ccb1966SGarrett D'Amore break; 8373ccb1966SGarrett D'Amore case 'v': 8383ccb1966SGarrett D'Amore break; 8393ccb1966SGarrett D'Amore default: 8403ccb1966SGarrett D'Amore help(); 8413ccb1966SGarrett D'Amore return (-1); 8423ccb1966SGarrett D'Amore } 8433ccb1966SGarrett D'Amore } 8443ccb1966SGarrett D'Amore argc -= optind; 8453ccb1966SGarrett D'Amore argv += optind; 8463ccb1966SGarrett D'Amore if (argc != 0) { 8473ccb1966SGarrett D'Amore help(); 8483ccb1966SGarrett D'Amore return (-1); 8493ccb1966SGarrett D'Amore } 8503ccb1966SGarrett D'Amore 8513ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 8523ccb1966SGarrett D'Amore return (ENODEV); 8533ccb1966SGarrett D'Amore } 8543ccb1966SGarrett D'Amore 8553ccb1966SGarrett D'Amore msg(_("Device: %s\n"), d->mixer.devnode); 8563ccb1966SGarrett D'Amore msg(_(" Name = %s\n"), d->card.shortname); 8573ccb1966SGarrett D'Amore msg(_(" Config = %s\n"), d->card.longname); 8583ccb1966SGarrett D'Amore 8593ccb1966SGarrett D'Amore if (strlen(d->card.hw_info)) { 8603ccb1966SGarrett D'Amore msg(_(" HW Info = %s"), d->card.hw_info); 8613ccb1966SGarrett D'Amore } 8623ccb1966SGarrett D'Amore 8633ccb1966SGarrett D'Amore return (0); 8643ccb1966SGarrett D'Amore } 8653ccb1966SGarrett D'Amore 8663ccb1966SGarrett D'Amore int 8673ccb1966SGarrett D'Amore do_show_control(int argc, char **argv) 8683ccb1966SGarrett D'Amore { 8693ccb1966SGarrett D'Amore int optc; 8703ccb1966SGarrett D'Amore int rval = 0; 8713ccb1966SGarrett D'Amore int verbose = 0; 8723ccb1966SGarrett D'Amore device_t *d; 8733ccb1966SGarrett D'Amore char *devname = NULL; 8743ccb1966SGarrett D'Amore int i; 8753ccb1966SGarrett D'Amore int j; 8763ccb1966SGarrett D'Amore int rv; 8773ccb1966SGarrett D'Amore char *n; 8783ccb1966SGarrett D'Amore cinfo_t *cinfop; 8793ccb1966SGarrett D'Amore 8803ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:v")) != EOF) { 8813ccb1966SGarrett D'Amore switch (optc) { 8823ccb1966SGarrett D'Amore case 'd': 8833ccb1966SGarrett D'Amore devname = optarg; 8843ccb1966SGarrett D'Amore break; 8853ccb1966SGarrett D'Amore case 'v': 8863ccb1966SGarrett D'Amore verbose++; 8873ccb1966SGarrett D'Amore break; 8883ccb1966SGarrett D'Amore default: 8893ccb1966SGarrett D'Amore help(); 8903ccb1966SGarrett D'Amore return (-1); 8913ccb1966SGarrett D'Amore } 8923ccb1966SGarrett D'Amore } 8933ccb1966SGarrett D'Amore argc -= optind; 8943ccb1966SGarrett D'Amore argv += optind; 8953ccb1966SGarrett D'Amore 8963ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 8973ccb1966SGarrett D'Amore return (ENODEV); 8983ccb1966SGarrett D'Amore } 8993ccb1966SGarrett D'Amore 9003ccb1966SGarrett D'Amore print_header(NULL, verbose); 9013ccb1966SGarrett D'Amore if (argc == 0) { 9023ccb1966SGarrett D'Amore /* do them all! */ 9033ccb1966SGarrett D'Amore for (i = 0; i < d->cmax; i++) { 9043ccb1966SGarrett D'Amore 9053ccb1966SGarrett D'Amore cinfop = &d->controls[i]; 9063ccb1966SGarrett D'Amore rv = print_control(NULL, d, cinfop, verbose); 9073ccb1966SGarrett D'Amore rval = rval ? rval : rv; 9083ccb1966SGarrett D'Amore } 9093ccb1966SGarrett D'Amore return (rval); 9103ccb1966SGarrett D'Amore } 9113ccb1966SGarrett D'Amore 9123ccb1966SGarrett D'Amore for (i = 0; i < argc; i++) { 9133ccb1966SGarrett D'Amore for (j = 0; j < d->cmax; j++) { 9143ccb1966SGarrett D'Amore cinfop = &d->controls[j]; 9153ccb1966SGarrett D'Amore n = strrchr(cinfop->ci.extname, '_'); 9163ccb1966SGarrett D'Amore n = n ? n + 1 : cinfop->ci.extname; 9173ccb1966SGarrett D'Amore if (strcmp(argv[i], n) == 0) { 9183ccb1966SGarrett D'Amore rv = print_control(NULL, d, cinfop, verbose); 9193ccb1966SGarrett D'Amore rval = rval ? rval : rv; 9203ccb1966SGarrett D'Amore break; 9213ccb1966SGarrett D'Amore } 9223ccb1966SGarrett D'Amore } 9233ccb1966SGarrett D'Amore /* Didn't find requested control */ 9243ccb1966SGarrett D'Amore if (j == d->cmax) { 9253ccb1966SGarrett D'Amore warn(_("No such control: %s\n"), argv[i]); 9263ccb1966SGarrett D'Amore rval = rval ? rval : ENODEV; 9273ccb1966SGarrett D'Amore } 9283ccb1966SGarrett D'Amore } 9293ccb1966SGarrett D'Amore 9303ccb1966SGarrett D'Amore return (rval); 9313ccb1966SGarrett D'Amore } 9323ccb1966SGarrett D'Amore 9333ccb1966SGarrett D'Amore int 9343ccb1966SGarrett D'Amore do_set_control(int argc, char **argv) 9353ccb1966SGarrett D'Amore { 9363ccb1966SGarrett D'Amore int optc; 9373ccb1966SGarrett D'Amore int rval = 0; 9383ccb1966SGarrett D'Amore int verbose = 0; 9393ccb1966SGarrett D'Amore device_t *d; 9403ccb1966SGarrett D'Amore char *devname = NULL; 9413ccb1966SGarrett D'Amore char *cname; 9423ccb1966SGarrett D'Amore char *value; 9433ccb1966SGarrett D'Amore int i; 9443ccb1966SGarrett D'Amore int found; 9453ccb1966SGarrett D'Amore int rv; 9463ccb1966SGarrett D'Amore char *n; 9473ccb1966SGarrett D'Amore cinfo_t *cinfop; 9483ccb1966SGarrett D'Amore 9493ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:v")) != EOF) { 9503ccb1966SGarrett D'Amore switch (optc) { 9513ccb1966SGarrett D'Amore case 'd': 9523ccb1966SGarrett D'Amore devname = optarg; 9533ccb1966SGarrett D'Amore break; 9543ccb1966SGarrett D'Amore case 'v': 9553ccb1966SGarrett D'Amore verbose = 1; 9563ccb1966SGarrett D'Amore break; 9573ccb1966SGarrett D'Amore default: 9583ccb1966SGarrett D'Amore help(); 9593ccb1966SGarrett D'Amore return (-1); 9603ccb1966SGarrett D'Amore } 9613ccb1966SGarrett D'Amore } 9623ccb1966SGarrett D'Amore argc -= optind; 9633ccb1966SGarrett D'Amore argv += optind; 9643ccb1966SGarrett D'Amore 9653ccb1966SGarrett D'Amore if (argc != 2) { 9663ccb1966SGarrett D'Amore help(); 9673ccb1966SGarrett D'Amore return (-1); 9683ccb1966SGarrett D'Amore } 9693ccb1966SGarrett D'Amore cname = argv[0]; 9703ccb1966SGarrett D'Amore value = argv[1]; 9713ccb1966SGarrett D'Amore 9723ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 9733ccb1966SGarrett D'Amore return (ENODEV); 9743ccb1966SGarrett D'Amore } 9753ccb1966SGarrett D'Amore 9763ccb1966SGarrett D'Amore for (i = 0, found = 0; i < d->cmax; i++) { 9773ccb1966SGarrett D'Amore cinfop = &d->controls[i]; 9783ccb1966SGarrett D'Amore n = strrchr(cinfop->ci.extname, '_'); 9793ccb1966SGarrett D'Amore n = n ? n + 1 : cinfop->ci.extname; 9803ccb1966SGarrett D'Amore if (strcmp(cname, n) != 0) { 9813ccb1966SGarrett D'Amore continue; 9823ccb1966SGarrett D'Amore } 9833ccb1966SGarrett D'Amore found = 1; 9843ccb1966SGarrett D'Amore rv = set_device_control(d, cinfop, value, verbose); 9853ccb1966SGarrett D'Amore rval = rval ? rval : rv; 9863ccb1966SGarrett D'Amore } 9873ccb1966SGarrett D'Amore if (!found) { 9883ccb1966SGarrett D'Amore warn(_("No such control: %s\n"), cname); 9893ccb1966SGarrett D'Amore } 9903ccb1966SGarrett D'Amore 9913ccb1966SGarrett D'Amore return (rval); 9923ccb1966SGarrett D'Amore } 9933ccb1966SGarrett D'Amore 9943ccb1966SGarrett D'Amore int 9953ccb1966SGarrett D'Amore do_save_controls(int argc, char **argv) 9963ccb1966SGarrett D'Amore { 9973ccb1966SGarrett D'Amore int optc; 9983ccb1966SGarrett D'Amore int rval = 0; 9993ccb1966SGarrett D'Amore device_t *d; 10003ccb1966SGarrett D'Amore char *devname = NULL; 10013ccb1966SGarrett D'Amore char *fname; 10023ccb1966SGarrett D'Amore int i; 10033ccb1966SGarrett D'Amore int rv; 10043ccb1966SGarrett D'Amore cinfo_t *cinfop; 10053ccb1966SGarrett D'Amore FILE *fp; 10063ccb1966SGarrett D'Amore int fd; 10073ccb1966SGarrett D'Amore int mode; 10083ccb1966SGarrett D'Amore 10093ccb1966SGarrett D'Amore mode = O_WRONLY | O_CREAT | O_EXCL; 10103ccb1966SGarrett D'Amore 10113ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:f")) != EOF) { 10123ccb1966SGarrett D'Amore switch (optc) { 10133ccb1966SGarrett D'Amore case 'd': 10143ccb1966SGarrett D'Amore devname = optarg; 10153ccb1966SGarrett D'Amore break; 10163ccb1966SGarrett D'Amore case 'f': 10173ccb1966SGarrett D'Amore mode &= ~O_EXCL; 10183ccb1966SGarrett D'Amore mode |= O_TRUNC; 10193ccb1966SGarrett D'Amore break; 10203ccb1966SGarrett D'Amore default: 10213ccb1966SGarrett D'Amore help(); 10223ccb1966SGarrett D'Amore return (-1); 10233ccb1966SGarrett D'Amore } 10243ccb1966SGarrett D'Amore } 10253ccb1966SGarrett D'Amore argc -= optind; 10263ccb1966SGarrett D'Amore argv += optind; 10273ccb1966SGarrett D'Amore 10283ccb1966SGarrett D'Amore if (argc != 1) { 10293ccb1966SGarrett D'Amore help(); 10303ccb1966SGarrett D'Amore return (-1); 10313ccb1966SGarrett D'Amore } 10323ccb1966SGarrett D'Amore fname = argv[0]; 10333ccb1966SGarrett D'Amore 10343ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 10353ccb1966SGarrett D'Amore return (ENODEV); 10363ccb1966SGarrett D'Amore } 10373ccb1966SGarrett D'Amore 10383ccb1966SGarrett D'Amore if ((fd = open(fname, mode, 0666)) < 0) { 10393ccb1966SGarrett D'Amore perror(_("Failed to create file")); 10403ccb1966SGarrett D'Amore return (errno); 10413ccb1966SGarrett D'Amore } 10423ccb1966SGarrett D'Amore 10433ccb1966SGarrett D'Amore if ((fp = fdopen(fd, "w")) == NULL) { 10443ccb1966SGarrett D'Amore perror(_("Unable to open file\n")); 10453ccb1966SGarrett D'Amore (void) close(fd); 10463ccb1966SGarrett D'Amore (void) unlink(fname); 10473ccb1966SGarrett D'Amore return (errno); 10483ccb1966SGarrett D'Amore } 10493ccb1966SGarrett D'Amore 10503ccb1966SGarrett D'Amore (void) fprintf(fp, "# Device: %s\n", d->mixer.devnode); 10513ccb1966SGarrett D'Amore (void) fprintf(fp, "# Name = %s\n", d->card.shortname); 10523ccb1966SGarrett D'Amore (void) fprintf(fp, "# Config = %s\n", d->card.longname); 10533ccb1966SGarrett D'Amore 10543ccb1966SGarrett D'Amore if (strlen(d->card.hw_info)) { 10553ccb1966SGarrett D'Amore (void) fprintf(fp, "# HW Info = %s", d->card.hw_info); 10563ccb1966SGarrett D'Amore } 10573ccb1966SGarrett D'Amore (void) fprintf(fp, "#\n"); 10583ccb1966SGarrett D'Amore 10593ccb1966SGarrett D'Amore print_header(fp, 0); 10603ccb1966SGarrett D'Amore 10613ccb1966SGarrett D'Amore for (i = 0; i < d->cmax; i++) { 10623ccb1966SGarrett D'Amore cinfop = &d->controls[i]; 10633ccb1966SGarrett D'Amore rv = print_control(fp, d, cinfop, 0); 10643ccb1966SGarrett D'Amore rval = rval ? rval : rv; 10653ccb1966SGarrett D'Amore } 10663ccb1966SGarrett D'Amore 10673ccb1966SGarrett D'Amore (void) fclose(fp); 10683ccb1966SGarrett D'Amore 10693ccb1966SGarrett D'Amore return (rval); 10703ccb1966SGarrett D'Amore } 10713ccb1966SGarrett D'Amore 10723ccb1966SGarrett D'Amore int 10733ccb1966SGarrett D'Amore do_load_controls(int argc, char **argv) 10743ccb1966SGarrett D'Amore { 10753ccb1966SGarrett D'Amore int optc; 10763ccb1966SGarrett D'Amore int rval = 0; 10773ccb1966SGarrett D'Amore device_t *d; 10783ccb1966SGarrett D'Amore char *devname = NULL; 10793ccb1966SGarrett D'Amore char *fname; 10803ccb1966SGarrett D'Amore char *cname; 10813ccb1966SGarrett D'Amore char *value; 10823ccb1966SGarrett D'Amore int i; 10833ccb1966SGarrett D'Amore int rv; 10843ccb1966SGarrett D'Amore cinfo_t *cinfop; 10853ccb1966SGarrett D'Amore FILE *fp; 10863ccb1966SGarrett D'Amore char linebuf[MAXLINE]; 10873ccb1966SGarrett D'Amore int lineno = 0; 10883ccb1966SGarrett D'Amore int found; 10893ccb1966SGarrett D'Amore 10903ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:")) != EOF) { 10913ccb1966SGarrett D'Amore switch (optc) { 10923ccb1966SGarrett D'Amore case 'd': 10933ccb1966SGarrett D'Amore devname = optarg; 10943ccb1966SGarrett D'Amore break; 10953ccb1966SGarrett D'Amore default: 10963ccb1966SGarrett D'Amore help(); 10973ccb1966SGarrett D'Amore return (-1); 10983ccb1966SGarrett D'Amore } 10993ccb1966SGarrett D'Amore } 11003ccb1966SGarrett D'Amore argc -= optind; 11013ccb1966SGarrett D'Amore argv += optind; 11023ccb1966SGarrett D'Amore 11033ccb1966SGarrett D'Amore if (argc != 1) { 11043ccb1966SGarrett D'Amore help(); 11053ccb1966SGarrett D'Amore return (-1); 11063ccb1966SGarrett D'Amore } 11073ccb1966SGarrett D'Amore fname = argv[0]; 11083ccb1966SGarrett D'Amore 11093ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 11103ccb1966SGarrett D'Amore return (ENODEV); 11113ccb1966SGarrett D'Amore } 11123ccb1966SGarrett D'Amore 11133ccb1966SGarrett D'Amore if ((fp = fopen(fname, "r")) == NULL) { 11143ccb1966SGarrett D'Amore perror(_("Unable to open file")); 11153ccb1966SGarrett D'Amore return (errno); 11163ccb1966SGarrett D'Amore } 11173ccb1966SGarrett D'Amore 11183ccb1966SGarrett D'Amore while (fgets(linebuf, sizeof (linebuf), fp) != NULL) { 11193ccb1966SGarrett D'Amore lineno++; 11203ccb1966SGarrett D'Amore if (linebuf[strlen(linebuf) - 1] != '\n') { 11213ccb1966SGarrett D'Amore warn(_("Warning: line too long at line %d\n"), lineno); 11223ccb1966SGarrett D'Amore /* read in the rest of the line and discard it */ 11233ccb1966SGarrett D'Amore while (fgets(linebuf, sizeof (linebuf), fp) != NULL && 11243ccb1966SGarrett D'Amore (linebuf[strlen(linebuf) - 1] != '\n')) { 11253ccb1966SGarrett D'Amore continue; 11263ccb1966SGarrett D'Amore } 11273ccb1966SGarrett D'Amore continue; 11283ccb1966SGarrett D'Amore } 11293ccb1966SGarrett D'Amore 11303ccb1966SGarrett D'Amore /* we have a good line ... */ 11313ccb1966SGarrett D'Amore cname = strtok(linebuf, " \t\n"); 11323ccb1966SGarrett D'Amore /* skip comments and blank lines */ 11333ccb1966SGarrett D'Amore if ((cname == NULL) || (cname[0] == '#')) { 11343ccb1966SGarrett D'Amore continue; 11353ccb1966SGarrett D'Amore } 11363ccb1966SGarrett D'Amore value = strtok(NULL, " \t\n"); 11373ccb1966SGarrett D'Amore if ((value == NULL) || (*cname == 0)) { 11383ccb1966SGarrett D'Amore warn(_("Warning: missing value at line %d\n"), lineno); 11393ccb1966SGarrett D'Amore continue; 11403ccb1966SGarrett D'Amore } 11413ccb1966SGarrett D'Amore 11423ccb1966SGarrett D'Amore for (i = 0, found = 0; i < d->cmax; i++) { 11433ccb1966SGarrett D'Amore /* save and restore requires an exact match */ 11443ccb1966SGarrett D'Amore cinfop = &d->controls[i]; 11453ccb1966SGarrett D'Amore if (strcmp(cinfop->ci.extname, cname) != 0) { 11463ccb1966SGarrett D'Amore continue; 11473ccb1966SGarrett D'Amore } 11483ccb1966SGarrett D'Amore found = 1; 11493ccb1966SGarrett D'Amore rv = set_device_control(d, cinfop, value, 0); 11503ccb1966SGarrett D'Amore rval = rval ? rval : rv; 11513ccb1966SGarrett D'Amore } 11523ccb1966SGarrett D'Amore if (!found) { 11533ccb1966SGarrett D'Amore warn(_("No such control: %s\n"), cname); 11543ccb1966SGarrett D'Amore } 11553ccb1966SGarrett D'Amore } 11563ccb1966SGarrett D'Amore (void) fclose(fp); 11573ccb1966SGarrett D'Amore 11583ccb1966SGarrett D'Amore return (rval); 11593ccb1966SGarrett D'Amore } 11603ccb1966SGarrett D'Amore 11613ccb1966SGarrett D'Amore int 1162*aef5f291SGarrett D'Amore mixer_walker(di_devlink_t dlink, void *arg) 1163*aef5f291SGarrett D'Amore { 1164*aef5f291SGarrett D'Amore const char *link; 1165*aef5f291SGarrett D'Amore int num; 1166*aef5f291SGarrett D'Amore int fd; 1167*aef5f291SGarrett D'Amore int verbose = *(int *)arg; 1168*aef5f291SGarrett D'Amore int num_offset; 1169*aef5f291SGarrett D'Amore 1170*aef5f291SGarrett D'Amore num_offset = sizeof ("/dev/mixer") - 1; 1171*aef5f291SGarrett D'Amore 1172*aef5f291SGarrett D'Amore link = di_devlink_path(dlink); 1173*aef5f291SGarrett D'Amore 1174*aef5f291SGarrett D'Amore if ((link == NULL) || 1175*aef5f291SGarrett D'Amore (strncmp(link, "/dev/mixer", num_offset) != 0) || 1176*aef5f291SGarrett D'Amore (!isdigit(link[num_offset]))) { 1177*aef5f291SGarrett D'Amore return (DI_WALK_CONTINUE); 1178*aef5f291SGarrett D'Amore } 1179*aef5f291SGarrett D'Amore 1180*aef5f291SGarrett D'Amore num = atoi(link + num_offset); 1181*aef5f291SGarrett D'Amore if ((fd = open(link, O_RDWR)) < 0) { 1182*aef5f291SGarrett D'Amore if (verbose) { 1183*aef5f291SGarrett D'Amore if (errno == ENOENT) { 1184*aef5f291SGarrett D'Amore msg(_("Device %s not present.\n"), link); 1185*aef5f291SGarrett D'Amore } else { 1186*aef5f291SGarrett D'Amore msg(_("Unable to open device %s: %s\n"), 1187*aef5f291SGarrett D'Amore link, strerror(errno)); 1188*aef5f291SGarrett D'Amore } 1189*aef5f291SGarrett D'Amore } 1190*aef5f291SGarrett D'Amore return (DI_WALK_CONTINUE); 1191*aef5f291SGarrett D'Amore } 1192*aef5f291SGarrett D'Amore 1193*aef5f291SGarrett D'Amore if (verbose) { 1194*aef5f291SGarrett D'Amore msg(_("Initializing link %s: "), link); 1195*aef5f291SGarrett D'Amore } 1196*aef5f291SGarrett D'Amore if (ioctl(fd, SNDCTL_SUN_SEND_NUMBER, &num) != 0) { 1197*aef5f291SGarrett D'Amore if (verbose) { 1198*aef5f291SGarrett D'Amore msg(_("failed: %s\n"), strerror(errno)); 1199*aef5f291SGarrett D'Amore } 1200*aef5f291SGarrett D'Amore } else { 1201*aef5f291SGarrett D'Amore if (verbose) { 1202*aef5f291SGarrett D'Amore msg(_("done.\n")); 1203*aef5f291SGarrett D'Amore } 1204*aef5f291SGarrett D'Amore } 1205*aef5f291SGarrett D'Amore (void) close(fd); 1206*aef5f291SGarrett D'Amore return (DI_WALK_CONTINUE); 1207*aef5f291SGarrett D'Amore } 1208*aef5f291SGarrett D'Amore 1209*aef5f291SGarrett D'Amore int 1210*aef5f291SGarrett D'Amore do_init_devices(int argc, char **argv) 1211*aef5f291SGarrett D'Amore { 1212*aef5f291SGarrett D'Amore int optc; 1213*aef5f291SGarrett D'Amore di_devlink_handle_t dlh; 1214*aef5f291SGarrett D'Amore int verbose = 0; 1215*aef5f291SGarrett D'Amore 1216*aef5f291SGarrett D'Amore while ((optc = getopt(argc, argv, "v")) != EOF) { 1217*aef5f291SGarrett D'Amore switch (optc) { 1218*aef5f291SGarrett D'Amore case 'v': 1219*aef5f291SGarrett D'Amore verbose = 1; 1220*aef5f291SGarrett D'Amore break; 1221*aef5f291SGarrett D'Amore default: 1222*aef5f291SGarrett D'Amore help(); 1223*aef5f291SGarrett D'Amore return (-1); 1224*aef5f291SGarrett D'Amore } 1225*aef5f291SGarrett D'Amore } 1226*aef5f291SGarrett D'Amore argc -= optind; 1227*aef5f291SGarrett D'Amore argv += optind; 1228*aef5f291SGarrett D'Amore 1229*aef5f291SGarrett D'Amore if (argc != 0) { 1230*aef5f291SGarrett D'Amore help(); 1231*aef5f291SGarrett D'Amore return (-1); 1232*aef5f291SGarrett D'Amore } 1233*aef5f291SGarrett D'Amore 1234*aef5f291SGarrett D'Amore dlh = di_devlink_init(NULL, 0); 1235*aef5f291SGarrett D'Amore if (dlh == NULL) { 1236*aef5f291SGarrett D'Amore perror(_("Unable to initialize devlink handle")); 1237*aef5f291SGarrett D'Amore return (-1); 1238*aef5f291SGarrett D'Amore } 1239*aef5f291SGarrett D'Amore 1240*aef5f291SGarrett D'Amore if (di_devlink_walk(dlh, "^mixer", NULL, 0, &verbose, 1241*aef5f291SGarrett D'Amore mixer_walker) != 0) { 1242*aef5f291SGarrett D'Amore perror(_("Unable to walk devlinks")); 1243*aef5f291SGarrett D'Amore return (-1); 1244*aef5f291SGarrett D'Amore } 1245*aef5f291SGarrett D'Amore return (0); 1246*aef5f291SGarrett D'Amore } 1247*aef5f291SGarrett D'Amore 1248*aef5f291SGarrett D'Amore int 12493ccb1966SGarrett D'Amore main(int argc, char **argv) 12503ccb1966SGarrett D'Amore { 12513ccb1966SGarrett D'Amore int rv = 0; 12523ccb1966SGarrett D'Amore int opt; 12533ccb1966SGarrett D'Amore 12543ccb1966SGarrett D'Amore (void) setlocale(LC_ALL, ""); 12553ccb1966SGarrett D'Amore (void) textdomain(TEXT_DOMAIN); 12563ccb1966SGarrett D'Amore 12573ccb1966SGarrett D'Amore while ((opt = getopt(argc, argv, "h")) != EOF) { 12583ccb1966SGarrett D'Amore switch (opt) { 12593ccb1966SGarrett D'Amore case 'h': 12603ccb1966SGarrett D'Amore help(); 12613ccb1966SGarrett D'Amore rv = 0; 12623ccb1966SGarrett D'Amore goto OUT; 12633ccb1966SGarrett D'Amore default: 12643ccb1966SGarrett D'Amore rv = EINVAL; 12653ccb1966SGarrett D'Amore break; 12663ccb1966SGarrett D'Amore } 12673ccb1966SGarrett D'Amore } 12683ccb1966SGarrett D'Amore 12693ccb1966SGarrett D'Amore if (rv) { 12703ccb1966SGarrett D'Amore goto OUT; 12713ccb1966SGarrett D'Amore } 12723ccb1966SGarrett D'Amore 12733ccb1966SGarrett D'Amore argc -= optind; 12743ccb1966SGarrett D'Amore argv += optind; 12753ccb1966SGarrett D'Amore 12763ccb1966SGarrett D'Amore if (argc < 1) { 12773ccb1966SGarrett D'Amore help(); 12783ccb1966SGarrett D'Amore rv = EINVAL; 12793ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "help") == 0) { 12803ccb1966SGarrett D'Amore help(); 12813ccb1966SGarrett D'Amore rv = 0; 12823ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "list-devices") == 0) { 12833ccb1966SGarrett D'Amore rv = do_list_devices(argc, argv); 12843ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "show-device") == 0) { 12853ccb1966SGarrett D'Amore rv = do_show_device(argc, argv); 12863ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "show-control") == 0) { 12873ccb1966SGarrett D'Amore rv = do_show_control(argc, argv); 12883ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "set-control") == 0) { 12893ccb1966SGarrett D'Amore rv = do_set_control(argc, argv); 12903ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "load-controls") == 0) { 12913ccb1966SGarrett D'Amore rv = do_load_controls(argc, argv); 12923ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "save-controls") == 0) { 12933ccb1966SGarrett D'Amore rv = do_save_controls(argc, argv); 1294*aef5f291SGarrett D'Amore } else if (strcmp(argv[0], "init-devices") == 0) { 1295*aef5f291SGarrett D'Amore rv = do_init_devices(argc, argv); 12963ccb1966SGarrett D'Amore } else { 12973ccb1966SGarrett D'Amore help(); 12983ccb1966SGarrett D'Amore rv = EINVAL; 12993ccb1966SGarrett D'Amore } 13003ccb1966SGarrett D'Amore 13013ccb1966SGarrett D'Amore OUT: 13023ccb1966SGarrett D'Amore free_devices(); 13033ccb1966SGarrett D'Amore return (rv); 13043ccb1966SGarrett D'Amore } 1305