1*3ccb1966SGarrett D'Amore /* 2*3ccb1966SGarrett D'Amore * CDDL HEADER START 3*3ccb1966SGarrett D'Amore * 4*3ccb1966SGarrett D'Amore * The contents of this file are subject to the terms of the 5*3ccb1966SGarrett D'Amore * Common Development and Distribution License (the "License"). 6*3ccb1966SGarrett D'Amore * You may not use this file except in compliance with the License. 7*3ccb1966SGarrett D'Amore * 8*3ccb1966SGarrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*3ccb1966SGarrett D'Amore * or http://www.opensolaris.org/os/licensing. 10*3ccb1966SGarrett D'Amore * See the License for the specific language governing permissions 11*3ccb1966SGarrett D'Amore * and limitations under the License. 12*3ccb1966SGarrett D'Amore * 13*3ccb1966SGarrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each 14*3ccb1966SGarrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*3ccb1966SGarrett D'Amore * If applicable, add the following below this CDDL HEADER, with the 16*3ccb1966SGarrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying 17*3ccb1966SGarrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner] 18*3ccb1966SGarrett D'Amore * 19*3ccb1966SGarrett D'Amore * CDDL HEADER END 20*3ccb1966SGarrett D'Amore */ 21*3ccb1966SGarrett D'Amore /* 22*3ccb1966SGarrett D'Amore * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*3ccb1966SGarrett D'Amore * Use is subject to license terms. 24*3ccb1966SGarrett D'Amore */ 25*3ccb1966SGarrett D'Amore 26*3ccb1966SGarrett D'Amore #include <stdio.h> 27*3ccb1966SGarrett D'Amore #include <stdlib.h> 28*3ccb1966SGarrett D'Amore #include <errno.h> 29*3ccb1966SGarrett D'Amore #include <string.h> 30*3ccb1966SGarrett D'Amore #include <strings.h> 31*3ccb1966SGarrett D'Amore #include <locale.h> 32*3ccb1966SGarrett D'Amore #include <libintl.h> 33*3ccb1966SGarrett D'Amore #include <stdarg.h> 34*3ccb1966SGarrett D'Amore #include <stddef.h> 35*3ccb1966SGarrett D'Amore #include <sys/types.h> 36*3ccb1966SGarrett D'Amore #include <sys/stat.h> 37*3ccb1966SGarrett D'Amore #include <sys/mkdev.h> 38*3ccb1966SGarrett D'Amore #include <fcntl.h> 39*3ccb1966SGarrett D'Amore #include <unistd.h> 40*3ccb1966SGarrett D'Amore #include <ctype.h> 41*3ccb1966SGarrett D'Amore #include <sys/param.h> 42*3ccb1966SGarrett D'Amore #include <sys/soundcard.h> 43*3ccb1966SGarrett D'Amore 44*3ccb1966SGarrett D'Amore #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 45*3ccb1966SGarrett D'Amore #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 46*3ccb1966SGarrett D'Amore #endif 47*3ccb1966SGarrett D'Amore 48*3ccb1966SGarrett D'Amore #define _(s) gettext(s) 49*3ccb1966SGarrett D'Amore 50*3ccb1966SGarrett D'Amore #define MAXLINE 1024 51*3ccb1966SGarrett D'Amore 52*3ccb1966SGarrett D'Amore #define AUDIO_CTRL_STEREO_LEFT(v) ((uint8_t)((v) & 0xff)) 53*3ccb1966SGarrett D'Amore #define AUDIO_CTRL_STEREO_RIGHT(v) ((uint8_t)(((v) >> 8) & 0xff)) 54*3ccb1966SGarrett D'Amore #define AUDIO_CTRL_STEREO_VAL(l, r) (((l) & 0xff) | (((r) & 0xff) << 8)) 55*3ccb1966SGarrett D'Amore 56*3ccb1966SGarrett D'Amore /* 57*3ccb1966SGarrett D'Amore * These are borrowed from sys/audio/audio_common.h, where the values 58*3ccb1966SGarrett D'Amore * are protected by _KERNEL. 59*3ccb1966SGarrett D'Amore */ 60*3ccb1966SGarrett D'Amore #define AUDIO_MN_TYPE_NBITS (4) 61*3ccb1966SGarrett D'Amore #define AUDIO_MN_TYPE_MASK ((1U << AUDIO_MN_TYPE_NBITS) - 1) 62*3ccb1966SGarrett D'Amore #define AUDIO_MINOR_MIXER (0) 63*3ccb1966SGarrett D'Amore 64*3ccb1966SGarrett D'Amore 65*3ccb1966SGarrett D'Amore /* 66*3ccb1966SGarrett D'Amore * Column display information 67*3ccb1966SGarrett D'Amore * All are related to the types enumerated in col_t and any change should be 68*3ccb1966SGarrett D'Amore * reflected in the corresponding indices and offsets for all the variables 69*3ccb1966SGarrett D'Amore * accordingly. Most tweaks to the display can be done by adjusting the 70*3ccb1966SGarrett D'Amore * values here. 71*3ccb1966SGarrett D'Amore */ 72*3ccb1966SGarrett D'Amore 73*3ccb1966SGarrett D'Amore /* types of columns displayed */ 74*3ccb1966SGarrett D'Amore typedef enum { COL_DV = 0, COL_NM, COL_VAL, COL_SEL} col_t; 75*3ccb1966SGarrett D'Amore 76*3ccb1966SGarrett D'Amore /* corresponding sizes of columns; does not include trailing null */ 77*3ccb1966SGarrett D'Amore #define COL_DV_SZ 16 78*3ccb1966SGarrett D'Amore #define COL_NM_SZ 24 79*3ccb1966SGarrett D'Amore #define COL_VAL_SZ 10 80*3ccb1966SGarrett D'Amore #define COL_SEL_SZ 20 81*3ccb1966SGarrett D'Amore #define COL_MAX_SZ 64 82*3ccb1966SGarrett D'Amore 83*3ccb1966SGarrett D'Amore /* corresponding sizes of columns, indexed by col_t value */ 84*3ccb1966SGarrett D'Amore static int col_sz[] = { 85*3ccb1966SGarrett D'Amore COL_DV_SZ, COL_NM_SZ, COL_VAL_SZ, COL_SEL_SZ 86*3ccb1966SGarrett D'Amore }; 87*3ccb1966SGarrett D'Amore 88*3ccb1966SGarrett D'Amore /* used by callers of the printing function */ 89*3ccb1966SGarrett D'Amore typedef struct col_prt { 90*3ccb1966SGarrett D'Amore char *col_dv; 91*3ccb1966SGarrett D'Amore char *col_nm; 92*3ccb1966SGarrett D'Amore char *col_val; 93*3ccb1966SGarrett D'Amore char *col_sel; 94*3ccb1966SGarrett D'Amore } col_prt_t; 95*3ccb1966SGarrett D'Amore 96*3ccb1966SGarrett D'Amore /* columns displayed in order with vopt = 0 */ 97*3ccb1966SGarrett D'Amore static int col_dpy[] = {COL_NM, COL_VAL}; 98*3ccb1966SGarrett D'Amore static int col_dpy_len = sizeof (col_dpy) / sizeof (*col_dpy); 99*3ccb1966SGarrett D'Amore 100*3ccb1966SGarrett D'Amore /* tells the printing function what members to use; follows col_dpy[] */ 101*3ccb1966SGarrett D'Amore static size_t col_dpy_prt[] = { 102*3ccb1966SGarrett D'Amore offsetof(col_prt_t, col_nm), 103*3ccb1966SGarrett D'Amore offsetof(col_prt_t, col_val), 104*3ccb1966SGarrett D'Amore }; 105*3ccb1966SGarrett D'Amore 106*3ccb1966SGarrett D'Amore /* columns displayed in order with vopt = 1 */ 107*3ccb1966SGarrett D'Amore static int col_dpy_vopt[] = { COL_DV, COL_NM, COL_VAL, COL_SEL}; 108*3ccb1966SGarrett D'Amore static int col_dpy_vopt_len = sizeof (col_dpy_vopt) / sizeof (*col_dpy_vopt); 109*3ccb1966SGarrett D'Amore 110*3ccb1966SGarrett D'Amore /* tells the printing function what members to use; follows col_dpy_vopt[] */ 111*3ccb1966SGarrett D'Amore static size_t col_dpy_prt_vopt[] = { 112*3ccb1966SGarrett D'Amore offsetof(col_prt_t, col_dv), 113*3ccb1966SGarrett D'Amore offsetof(col_prt_t, col_nm), 114*3ccb1966SGarrett D'Amore offsetof(col_prt_t, col_val), 115*3ccb1966SGarrett D'Amore offsetof(col_prt_t, col_sel) 116*3ccb1966SGarrett D'Amore }; 117*3ccb1966SGarrett D'Amore 118*3ccb1966SGarrett D'Amore /* columns displayed in order with tofile = 1 */ 119*3ccb1966SGarrett D'Amore static int col_dpy_tofile[] = { COL_NM, COL_VAL}; 120*3ccb1966SGarrett D'Amore static int col_dpy_tofile_len = sizeof (col_dpy_tofile) / 121*3ccb1966SGarrett D'Amore sizeof (*col_dpy_tofile); 122*3ccb1966SGarrett D'Amore 123*3ccb1966SGarrett D'Amore /* tells the printing function what members to use; follows col_dpy_tofile[] */ 124*3ccb1966SGarrett D'Amore static size_t col_dpy_prt_tofile[] = { 125*3ccb1966SGarrett D'Amore offsetof(col_prt_t, col_nm), 126*3ccb1966SGarrett D'Amore offsetof(col_prt_t, col_val) 127*3ccb1966SGarrett D'Amore }; 128*3ccb1966SGarrett D'Amore 129*3ccb1966SGarrett D'Amore 130*3ccb1966SGarrett D'Amore /* 131*3ccb1966SGarrett D'Amore * mixer and control accounting 132*3ccb1966SGarrett D'Amore */ 133*3ccb1966SGarrett D'Amore 134*3ccb1966SGarrett D'Amore typedef struct cinfo { 135*3ccb1966SGarrett D'Amore oss_mixext ci; 136*3ccb1966SGarrett D'Amore oss_mixer_enuminfo *enump; 137*3ccb1966SGarrett D'Amore } cinfo_t; 138*3ccb1966SGarrett D'Amore 139*3ccb1966SGarrett D'Amore typedef struct device { 140*3ccb1966SGarrett D'Amore oss_card_info card; 141*3ccb1966SGarrett D'Amore oss_mixerinfo mixer; 142*3ccb1966SGarrett D'Amore 143*3ccb1966SGarrett D'Amore int cmax; 144*3ccb1966SGarrett D'Amore cinfo_t *controls; 145*3ccb1966SGarrett D'Amore 146*3ccb1966SGarrett D'Amore int mfd; 147*3ccb1966SGarrett D'Amore dev_t devt; 148*3ccb1966SGarrett D'Amore 149*3ccb1966SGarrett D'Amore struct device *nextp; 150*3ccb1966SGarrett D'Amore } device_t; 151*3ccb1966SGarrett D'Amore 152*3ccb1966SGarrett D'Amore static device_t *devices = NULL; 153*3ccb1966SGarrett D'Amore 154*3ccb1966SGarrett D'Amore /*PRINTFLIKE1*/ 155*3ccb1966SGarrett D'Amore static void 156*3ccb1966SGarrett D'Amore msg(char *fmt, ...) 157*3ccb1966SGarrett D'Amore { 158*3ccb1966SGarrett D'Amore va_list ap; 159*3ccb1966SGarrett D'Amore 160*3ccb1966SGarrett D'Amore va_start(ap, fmt); 161*3ccb1966SGarrett D'Amore (void) vprintf(fmt, ap); 162*3ccb1966SGarrett D'Amore va_end(ap); 163*3ccb1966SGarrett D'Amore } 164*3ccb1966SGarrett D'Amore 165*3ccb1966SGarrett D'Amore /*PRINTFLIKE1*/ 166*3ccb1966SGarrett D'Amore static void 167*3ccb1966SGarrett D'Amore warn(char *fmt, ...) 168*3ccb1966SGarrett D'Amore { 169*3ccb1966SGarrett D'Amore va_list ap; 170*3ccb1966SGarrett D'Amore 171*3ccb1966SGarrett D'Amore va_start(ap, fmt); 172*3ccb1966SGarrett D'Amore (void) vfprintf(stderr, fmt, ap); 173*3ccb1966SGarrett D'Amore va_end(ap); 174*3ccb1966SGarrett D'Amore } 175*3ccb1966SGarrett D'Amore 176*3ccb1966SGarrett D'Amore static void 177*3ccb1966SGarrett D'Amore free_device(device_t *d) 178*3ccb1966SGarrett D'Amore { 179*3ccb1966SGarrett D'Amore int i; 180*3ccb1966SGarrett D'Amore device_t **dpp; 181*3ccb1966SGarrett D'Amore 182*3ccb1966SGarrett D'Amore dpp = &devices; 183*3ccb1966SGarrett D'Amore while ((*dpp) && ((*dpp) != d)) { 184*3ccb1966SGarrett D'Amore dpp = &((*dpp)->nextp); 185*3ccb1966SGarrett D'Amore } 186*3ccb1966SGarrett D'Amore if (*dpp) { 187*3ccb1966SGarrett D'Amore *dpp = d->nextp; 188*3ccb1966SGarrett D'Amore } 189*3ccb1966SGarrett D'Amore for (i = 0; i < d->cmax; i++) { 190*3ccb1966SGarrett D'Amore if (d->controls[i].enump != NULL) 191*3ccb1966SGarrett D'Amore free(d->controls[i].enump); 192*3ccb1966SGarrett D'Amore } 193*3ccb1966SGarrett D'Amore 194*3ccb1966SGarrett D'Amore if (d->mfd >= 0) 195*3ccb1966SGarrett D'Amore (void) close(d->mfd); 196*3ccb1966SGarrett D'Amore 197*3ccb1966SGarrett D'Amore free(d); 198*3ccb1966SGarrett D'Amore } 199*3ccb1966SGarrett D'Amore 200*3ccb1966SGarrett D'Amore static void 201*3ccb1966SGarrett D'Amore free_devices(void) 202*3ccb1966SGarrett D'Amore { 203*3ccb1966SGarrett D'Amore device_t *d = devices; 204*3ccb1966SGarrett D'Amore 205*3ccb1966SGarrett D'Amore while ((d = devices) != NULL) { 206*3ccb1966SGarrett D'Amore free_device(d); 207*3ccb1966SGarrett D'Amore } 208*3ccb1966SGarrett D'Amore 209*3ccb1966SGarrett D'Amore devices = NULL; 210*3ccb1966SGarrett D'Amore } 211*3ccb1966SGarrett D'Amore 212*3ccb1966SGarrett D'Amore 213*3ccb1966SGarrett D'Amore /* 214*3ccb1966SGarrett D'Amore * adds to the end of global devices and returns a pointer to the new entry 215*3ccb1966SGarrett D'Amore */ 216*3ccb1966SGarrett D'Amore static device_t * 217*3ccb1966SGarrett D'Amore alloc_device(void) 218*3ccb1966SGarrett D'Amore { 219*3ccb1966SGarrett D'Amore device_t *p; 220*3ccb1966SGarrett D'Amore device_t *d = calloc(1, sizeof (*d)); 221*3ccb1966SGarrett D'Amore 222*3ccb1966SGarrett D'Amore d->card.card = -1; 223*3ccb1966SGarrett D'Amore d->mixer.dev = -1; 224*3ccb1966SGarrett D'Amore d->mfd = -1; 225*3ccb1966SGarrett D'Amore 226*3ccb1966SGarrett D'Amore if (devices == NULL) { 227*3ccb1966SGarrett D'Amore devices = d; 228*3ccb1966SGarrett D'Amore } else { 229*3ccb1966SGarrett D'Amore for (p = devices; p->nextp != NULL; p = p->nextp) {} 230*3ccb1966SGarrett D'Amore 231*3ccb1966SGarrett D'Amore p->nextp = d; 232*3ccb1966SGarrett D'Amore } 233*3ccb1966SGarrett D'Amore return (d); 234*3ccb1966SGarrett D'Amore } 235*3ccb1966SGarrett D'Amore 236*3ccb1966SGarrett D'Amore 237*3ccb1966SGarrett D'Amore /* 238*3ccb1966SGarrett D'Amore * cinfop->enump needs to be present 239*3ccb1966SGarrett D'Amore * idx should be: >= 0 to < cinfop->ci.maxvalue 240*3ccb1966SGarrett D'Amore */ 241*3ccb1966SGarrett D'Amore static char * 242*3ccb1966SGarrett D'Amore get_enum_str(cinfo_t *cinfop, int idx) 243*3ccb1966SGarrett D'Amore { 244*3ccb1966SGarrett D'Amore int sz = sizeof (*cinfop->ci.enum_present) * 8; 245*3ccb1966SGarrett D'Amore 246*3ccb1966SGarrett D'Amore if (cinfop->ci.enum_present[idx / sz] & (1 << (idx % sz))) 247*3ccb1966SGarrett D'Amore return (cinfop->enump->strings + cinfop->enump->strindex[idx]); 248*3ccb1966SGarrett D'Amore 249*3ccb1966SGarrett D'Amore return (NULL); 250*3ccb1966SGarrett D'Amore } 251*3ccb1966SGarrett D'Amore 252*3ccb1966SGarrett D'Amore 253*3ccb1966SGarrett D'Amore /* 254*3ccb1966SGarrett D'Amore * caller fills in d->mixer.devnode; func fills in the rest 255*3ccb1966SGarrett D'Amore */ 256*3ccb1966SGarrett D'Amore static int 257*3ccb1966SGarrett D'Amore get_device_info(device_t *d) 258*3ccb1966SGarrett D'Amore { 259*3ccb1966SGarrett D'Amore int fd = -1; 260*3ccb1966SGarrett D'Amore int i; 261*3ccb1966SGarrett D'Amore cinfo_t *ci; 262*3ccb1966SGarrett D'Amore 263*3ccb1966SGarrett D'Amore if ((fd = open(d->mixer.devnode, O_RDWR)) < 0) { 264*3ccb1966SGarrett D'Amore perror(_("Error opening device")); 265*3ccb1966SGarrett D'Amore return (errno); 266*3ccb1966SGarrett D'Amore } 267*3ccb1966SGarrett D'Amore d->mfd = fd; 268*3ccb1966SGarrett D'Amore 269*3ccb1966SGarrett D'Amore d->cmax = -1; 270*3ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_MIX_NREXT, &d->cmax) < 0) { 271*3ccb1966SGarrett D'Amore perror(_("Error getting control count")); 272*3ccb1966SGarrett D'Amore return (errno); 273*3ccb1966SGarrett D'Amore } 274*3ccb1966SGarrett D'Amore 275*3ccb1966SGarrett D'Amore d->controls = calloc(d->cmax, sizeof (*d->controls)); 276*3ccb1966SGarrett D'Amore 277*3ccb1966SGarrett D'Amore for (i = 0; i < d->cmax; i++) { 278*3ccb1966SGarrett D'Amore ci = &d->controls[i]; 279*3ccb1966SGarrett D'Amore 280*3ccb1966SGarrett D'Amore ci->ci.dev = -1; 281*3ccb1966SGarrett D'Amore ci->ci.ctrl = i; 282*3ccb1966SGarrett D'Amore 283*3ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_MIX_EXTINFO, &ci->ci) < 0) { 284*3ccb1966SGarrett D'Amore perror(_("Error getting control info")); 285*3ccb1966SGarrett D'Amore return (errno); 286*3ccb1966SGarrett D'Amore } 287*3ccb1966SGarrett D'Amore 288*3ccb1966SGarrett D'Amore if (ci->ci.type == MIXT_ENUM) { 289*3ccb1966SGarrett D'Amore ci->enump = calloc(1, sizeof (*ci->enump)); 290*3ccb1966SGarrett D'Amore ci->enump->dev = -1; 291*3ccb1966SGarrett D'Amore ci->enump->ctrl = ci->ci.ctrl; 292*3ccb1966SGarrett D'Amore 293*3ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_MIX_ENUMINFO, ci->enump) < 0) { 294*3ccb1966SGarrett D'Amore perror(_("Error getting enum info")); 295*3ccb1966SGarrett D'Amore return (errno); 296*3ccb1966SGarrett D'Amore } 297*3ccb1966SGarrett D'Amore } 298*3ccb1966SGarrett D'Amore } 299*3ccb1966SGarrett D'Amore 300*3ccb1966SGarrett D'Amore return (0); 301*3ccb1966SGarrett D'Amore } 302*3ccb1966SGarrett D'Amore 303*3ccb1966SGarrett D'Amore 304*3ccb1966SGarrett D'Amore static int 305*3ccb1966SGarrett D'Amore load_devices(void) 306*3ccb1966SGarrett D'Amore { 307*3ccb1966SGarrett D'Amore int rv = -1; 308*3ccb1966SGarrett D'Amore int fd = -1; 309*3ccb1966SGarrett D'Amore int i; 310*3ccb1966SGarrett D'Amore oss_sysinfo si; 311*3ccb1966SGarrett D'Amore device_t *d; 312*3ccb1966SGarrett D'Amore 313*3ccb1966SGarrett D'Amore if ((fd = open("/dev/mixer", O_RDWR)) < 0) { 314*3ccb1966SGarrett D'Amore rv = errno; 315*3ccb1966SGarrett D'Amore warn(_("Error opening mixer\n")); 316*3ccb1966SGarrett D'Amore goto OUT; 317*3ccb1966SGarrett D'Amore } 318*3ccb1966SGarrett D'Amore 319*3ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_SYSINFO, &si) < 0) { 320*3ccb1966SGarrett D'Amore rv = errno; 321*3ccb1966SGarrett D'Amore perror(_("Error getting system information")); 322*3ccb1966SGarrett D'Amore goto OUT; 323*3ccb1966SGarrett D'Amore } 324*3ccb1966SGarrett D'Amore 325*3ccb1966SGarrett D'Amore for (i = 0; i < si.nummixers; i++) { 326*3ccb1966SGarrett D'Amore 327*3ccb1966SGarrett D'Amore struct stat sbuf; 328*3ccb1966SGarrett D'Amore 329*3ccb1966SGarrett D'Amore d = alloc_device(); 330*3ccb1966SGarrett D'Amore d->mixer.dev = i; 331*3ccb1966SGarrett D'Amore 332*3ccb1966SGarrett D'Amore if (ioctl(fd, SNDCTL_MIXERINFO, &d->mixer) != 0) { 333*3ccb1966SGarrett D'Amore continue; 334*3ccb1966SGarrett D'Amore } 335*3ccb1966SGarrett D'Amore 336*3ccb1966SGarrett D'Amore d->card.card = d->mixer.card_number; 337*3ccb1966SGarrett D'Amore 338*3ccb1966SGarrett D'Amore if ((ioctl(fd, SNDCTL_CARDINFO, &d->card) != 0) || 339*3ccb1966SGarrett D'Amore (stat(d->mixer.devnode, &sbuf) != 0) || 340*3ccb1966SGarrett D'Amore ((sbuf.st_mode & S_IFCHR) == 0)) { 341*3ccb1966SGarrett D'Amore warn(_("Device present: %s\n"), d->mixer.devnode); 342*3ccb1966SGarrett D'Amore free_device(d); 343*3ccb1966SGarrett D'Amore continue; 344*3ccb1966SGarrett D'Amore } 345*3ccb1966SGarrett D'Amore d->devt = makedev(major(sbuf.st_rdev), 346*3ccb1966SGarrett D'Amore minor(sbuf.st_rdev) & ~(AUDIO_MN_TYPE_MASK)); 347*3ccb1966SGarrett D'Amore 348*3ccb1966SGarrett D'Amore if ((rv = get_device_info(d)) != 0) { 349*3ccb1966SGarrett D'Amore free_device(d); 350*3ccb1966SGarrett D'Amore goto OUT; 351*3ccb1966SGarrett D'Amore } 352*3ccb1966SGarrett D'Amore } 353*3ccb1966SGarrett D'Amore 354*3ccb1966SGarrett D'Amore rv = 0; 355*3ccb1966SGarrett D'Amore 356*3ccb1966SGarrett D'Amore OUT: 357*3ccb1966SGarrett D'Amore if (fd >= 0) 358*3ccb1966SGarrett D'Amore (void) close(fd); 359*3ccb1966SGarrett D'Amore return (rv); 360*3ccb1966SGarrett D'Amore } 361*3ccb1966SGarrett D'Amore 362*3ccb1966SGarrett D'Amore 363*3ccb1966SGarrett D'Amore static int 364*3ccb1966SGarrett D'Amore ctype_valid(int type) 365*3ccb1966SGarrett D'Amore { 366*3ccb1966SGarrett D'Amore switch (type) { 367*3ccb1966SGarrett D'Amore case MIXT_ONOFF: 368*3ccb1966SGarrett D'Amore case MIXT_ENUM: 369*3ccb1966SGarrett D'Amore case MIXT_MONOSLIDER: 370*3ccb1966SGarrett D'Amore case MIXT_STEREOSLIDER: 371*3ccb1966SGarrett D'Amore return (1); 372*3ccb1966SGarrett D'Amore default: 373*3ccb1966SGarrett D'Amore return (0); 374*3ccb1966SGarrett D'Amore } 375*3ccb1966SGarrett D'Amore } 376*3ccb1966SGarrett D'Amore 377*3ccb1966SGarrett D'Amore 378*3ccb1966SGarrett D'Amore static void 379*3ccb1966SGarrett D'Amore print_control_line(FILE *sfp, col_prt_t *colp, int vopt) 380*3ccb1966SGarrett D'Amore { 381*3ccb1966SGarrett D'Amore int i; 382*3ccb1966SGarrett D'Amore size_t *col_prtp; 383*3ccb1966SGarrett D'Amore int *col_dpyp; 384*3ccb1966SGarrett D'Amore int col_cnt; 385*3ccb1966SGarrett D'Amore int col_type; 386*3ccb1966SGarrett D'Amore int width; 387*3ccb1966SGarrett D'Amore char *colstr; 388*3ccb1966SGarrett D'Amore char cbuf[COL_MAX_SZ + 1]; 389*3ccb1966SGarrett D'Amore char line[128]; 390*3ccb1966SGarrett D'Amore char *colsep = " "; 391*3ccb1966SGarrett D'Amore 392*3ccb1966SGarrett D'Amore if (sfp != NULL) { 393*3ccb1966SGarrett D'Amore col_prtp = col_dpy_prt_tofile; 394*3ccb1966SGarrett D'Amore col_dpyp = col_dpy_tofile; 395*3ccb1966SGarrett D'Amore col_cnt = col_dpy_tofile_len; 396*3ccb1966SGarrett D'Amore } else if (vopt) { 397*3ccb1966SGarrett D'Amore col_prtp = col_dpy_prt_vopt; 398*3ccb1966SGarrett D'Amore col_dpyp = col_dpy_vopt; 399*3ccb1966SGarrett D'Amore col_cnt = col_dpy_vopt_len; 400*3ccb1966SGarrett D'Amore } else { 401*3ccb1966SGarrett D'Amore col_prtp = col_dpy_prt; 402*3ccb1966SGarrett D'Amore col_dpyp = col_dpy; 403*3ccb1966SGarrett D'Amore col_cnt = col_dpy_len; 404*3ccb1966SGarrett D'Amore } 405*3ccb1966SGarrett D'Amore 406*3ccb1966SGarrett D'Amore line[0] = '\0'; 407*3ccb1966SGarrett D'Amore 408*3ccb1966SGarrett D'Amore for (i = 0; i < col_cnt; i++) { 409*3ccb1966SGarrett D'Amore col_type = col_dpyp[i]; 410*3ccb1966SGarrett D'Amore width = col_sz[col_type]; 411*3ccb1966SGarrett D'Amore colstr = *(char **)(((size_t)colp) + col_prtp[i]); 412*3ccb1966SGarrett D'Amore 413*3ccb1966SGarrett D'Amore (void) snprintf(cbuf, sizeof (cbuf), "%- *s", 414*3ccb1966SGarrett D'Amore width > 0 ? width : 1, 415*3ccb1966SGarrett D'Amore (colstr == NULL) ? "" : colstr); 416*3ccb1966SGarrett D'Amore 417*3ccb1966SGarrett D'Amore (void) strlcat(line, cbuf, sizeof (line)); 418*3ccb1966SGarrett D'Amore if (i < col_cnt - 1) 419*3ccb1966SGarrett D'Amore (void) strlcat(line, colsep, sizeof (line)); 420*3ccb1966SGarrett D'Amore } 421*3ccb1966SGarrett D'Amore 422*3ccb1966SGarrett D'Amore (void) fprintf(sfp ? sfp : stdout, "%s\n", line); 423*3ccb1966SGarrett D'Amore } 424*3ccb1966SGarrett D'Amore 425*3ccb1966SGarrett D'Amore 426*3ccb1966SGarrett D'Amore static void 427*3ccb1966SGarrett D'Amore print_header(FILE *sfp, int vopt) 428*3ccb1966SGarrett D'Amore { 429*3ccb1966SGarrett D'Amore col_prt_t col; 430*3ccb1966SGarrett D'Amore 431*3ccb1966SGarrett D'Amore if (sfp) { 432*3ccb1966SGarrett D'Amore col.col_nm = _("#CONTROL"); 433*3ccb1966SGarrett D'Amore col.col_val = _("VALUE"); 434*3ccb1966SGarrett D'Amore } else { 435*3ccb1966SGarrett D'Amore col.col_dv = _("DEVICE"); 436*3ccb1966SGarrett D'Amore col.col_nm = _("CONTROL"); 437*3ccb1966SGarrett D'Amore col.col_val = _("VALUE"); 438*3ccb1966SGarrett D'Amore col.col_sel = _("POSSIBLE"); 439*3ccb1966SGarrett D'Amore } 440*3ccb1966SGarrett D'Amore print_control_line(sfp, &col, vopt); 441*3ccb1966SGarrett D'Amore } 442*3ccb1966SGarrett D'Amore 443*3ccb1966SGarrett D'Amore 444*3ccb1966SGarrett D'Amore static int 445*3ccb1966SGarrett D'Amore print_control(FILE *sfp, device_t *d, cinfo_t *cinfop, int vopt) 446*3ccb1966SGarrett D'Amore { 447*3ccb1966SGarrett D'Amore int mfd = d->mfd; 448*3ccb1966SGarrett D'Amore char *devnm = d->card.shortname; 449*3ccb1966SGarrett D'Amore oss_mixer_value cval; 450*3ccb1966SGarrett D'Amore char *str; 451*3ccb1966SGarrett D'Amore int i; 452*3ccb1966SGarrett D'Amore int idx = -1; 453*3ccb1966SGarrett D'Amore int rv = -1; 454*3ccb1966SGarrett D'Amore char valbuf[COL_VAL_SZ + 1]; 455*3ccb1966SGarrett D'Amore char selbuf[COL_SEL_SZ + 1]; 456*3ccb1966SGarrett D'Amore col_prt_t col; 457*3ccb1966SGarrett D'Amore 458*3ccb1966SGarrett D'Amore cval.dev = -1; 459*3ccb1966SGarrett D'Amore cval.ctrl = cinfop->ci.ctrl; 460*3ccb1966SGarrett D'Amore 461*3ccb1966SGarrett D'Amore if (ctype_valid(cinfop->ci.type)) { 462*3ccb1966SGarrett D'Amore if (ioctl(mfd, SNDCTL_MIX_READ, &cval) < 0) { 463*3ccb1966SGarrett D'Amore rv = errno; 464*3ccb1966SGarrett D'Amore perror(_("Error reading control\n")); 465*3ccb1966SGarrett D'Amore return (rv); 466*3ccb1966SGarrett D'Amore } 467*3ccb1966SGarrett D'Amore } else { 468*3ccb1966SGarrett D'Amore return (0); 469*3ccb1966SGarrett D'Amore } 470*3ccb1966SGarrett D'Amore 471*3ccb1966SGarrett D'Amore /* 472*3ccb1966SGarrett D'Amore * convert the control value into a string 473*3ccb1966SGarrett D'Amore */ 474*3ccb1966SGarrett D'Amore switch (cinfop->ci.type) { 475*3ccb1966SGarrett D'Amore case MIXT_ONOFF: 476*3ccb1966SGarrett D'Amore (void) snprintf(valbuf, sizeof (valbuf), "%s", 477*3ccb1966SGarrett D'Amore cval.value ? _("on") : _("off")); 478*3ccb1966SGarrett D'Amore break; 479*3ccb1966SGarrett D'Amore 480*3ccb1966SGarrett D'Amore case MIXT_MONOSLIDER: 481*3ccb1966SGarrett D'Amore (void) snprintf(valbuf, sizeof (valbuf), "%d", 482*3ccb1966SGarrett D'Amore cval.value & 0xff); 483*3ccb1966SGarrett D'Amore break; 484*3ccb1966SGarrett D'Amore 485*3ccb1966SGarrett D'Amore case MIXT_STEREOSLIDER: 486*3ccb1966SGarrett D'Amore (void) snprintf(valbuf, sizeof (valbuf), "%d:%d", 487*3ccb1966SGarrett D'Amore (int)AUDIO_CTRL_STEREO_LEFT(cval.value), 488*3ccb1966SGarrett D'Amore (int)AUDIO_CTRL_STEREO_RIGHT(cval.value)); 489*3ccb1966SGarrett D'Amore break; 490*3ccb1966SGarrett D'Amore 491*3ccb1966SGarrett D'Amore case MIXT_ENUM: 492*3ccb1966SGarrett D'Amore str = get_enum_str(cinfop, cval.value); 493*3ccb1966SGarrett D'Amore if (str == NULL) { 494*3ccb1966SGarrett D'Amore warn(_("Bad enum index %d for control '%s'\n"), 495*3ccb1966SGarrett D'Amore cval.value, cinfop->ci.extname); 496*3ccb1966SGarrett D'Amore return (EINVAL); 497*3ccb1966SGarrett D'Amore } 498*3ccb1966SGarrett D'Amore 499*3ccb1966SGarrett D'Amore (void) snprintf(valbuf, sizeof (valbuf), "%s", str); 500*3ccb1966SGarrett D'Amore break; 501*3ccb1966SGarrett D'Amore 502*3ccb1966SGarrett D'Amore default: 503*3ccb1966SGarrett D'Amore return (0); 504*3ccb1966SGarrett D'Amore } 505*3ccb1966SGarrett D'Amore 506*3ccb1966SGarrett D'Amore /* 507*3ccb1966SGarrett D'Amore * possible control values (range/selection) 508*3ccb1966SGarrett D'Amore */ 509*3ccb1966SGarrett D'Amore switch (cinfop->ci.type) { 510*3ccb1966SGarrett D'Amore case MIXT_ONOFF: 511*3ccb1966SGarrett D'Amore (void) snprintf(selbuf, sizeof (selbuf), _("on,off")); 512*3ccb1966SGarrett D'Amore break; 513*3ccb1966SGarrett D'Amore 514*3ccb1966SGarrett D'Amore case MIXT_MONOSLIDER: 515*3ccb1966SGarrett D'Amore (void) snprintf(selbuf, sizeof (selbuf), "%d-%d", 516*3ccb1966SGarrett D'Amore cinfop->ci.minvalue, cinfop->ci.maxvalue); 517*3ccb1966SGarrett D'Amore break; 518*3ccb1966SGarrett D'Amore case MIXT_STEREOSLIDER: 519*3ccb1966SGarrett D'Amore (void) snprintf(selbuf, sizeof (selbuf), "%d-%d:%d-%d", 520*3ccb1966SGarrett D'Amore cinfop->ci.minvalue, cinfop->ci.maxvalue, 521*3ccb1966SGarrett D'Amore cinfop->ci.minvalue, cinfop->ci.maxvalue); 522*3ccb1966SGarrett D'Amore break; 523*3ccb1966SGarrett D'Amore 524*3ccb1966SGarrett D'Amore case MIXT_ENUM: 525*3ccb1966SGarrett D'Amore /* 526*3ccb1966SGarrett D'Amore * display the first choice on the same line, then display 527*3ccb1966SGarrett D'Amore * the rest on multiple lines 528*3ccb1966SGarrett D'Amore */ 529*3ccb1966SGarrett D'Amore selbuf[0] = 0; 530*3ccb1966SGarrett D'Amore for (i = 0; i < cinfop->ci.maxvalue; i++) { 531*3ccb1966SGarrett D'Amore str = get_enum_str(cinfop, i); 532*3ccb1966SGarrett D'Amore if (str == NULL) 533*3ccb1966SGarrett D'Amore continue; 534*3ccb1966SGarrett D'Amore 535*3ccb1966SGarrett D'Amore if ((strlen(str) + 1 + strlen(selbuf)) >= 536*3ccb1966SGarrett D'Amore sizeof (selbuf)) { 537*3ccb1966SGarrett D'Amore break; 538*3ccb1966SGarrett D'Amore } 539*3ccb1966SGarrett D'Amore if (strlen(selbuf)) { 540*3ccb1966SGarrett D'Amore (void) strlcat(selbuf, ",", sizeof (selbuf)); 541*3ccb1966SGarrett D'Amore } 542*3ccb1966SGarrett D'Amore 543*3ccb1966SGarrett D'Amore (void) strlcat(selbuf, str, sizeof (selbuf)); 544*3ccb1966SGarrett D'Amore } 545*3ccb1966SGarrett D'Amore idx = i; 546*3ccb1966SGarrett D'Amore break; 547*3ccb1966SGarrett D'Amore 548*3ccb1966SGarrett D'Amore default: 549*3ccb1966SGarrett D'Amore (void) snprintf(selbuf, sizeof (selbuf), "-"); 550*3ccb1966SGarrett D'Amore } 551*3ccb1966SGarrett D'Amore 552*3ccb1966SGarrett D'Amore col.col_dv = devnm; 553*3ccb1966SGarrett D'Amore col.col_nm = strlen(cinfop->ci.extname) ? 554*3ccb1966SGarrett D'Amore cinfop->ci.extname : cinfop->ci.id; 555*3ccb1966SGarrett D'Amore while (strchr(col.col_nm, '_') != NULL) { 556*3ccb1966SGarrett D'Amore col.col_nm = strchr(col.col_nm, '_') + 1; 557*3ccb1966SGarrett D'Amore } 558*3ccb1966SGarrett D'Amore col.col_val = valbuf; 559*3ccb1966SGarrett D'Amore col.col_sel = selbuf; 560*3ccb1966SGarrett D'Amore print_control_line(sfp, &col, vopt); 561*3ccb1966SGarrett D'Amore 562*3ccb1966SGarrett D'Amore /* print leftover enum value selections */ 563*3ccb1966SGarrett D'Amore while ((sfp == NULL) && (idx >= 0) && (idx < cinfop->ci.maxvalue)) { 564*3ccb1966SGarrett D'Amore selbuf[0] = 0; 565*3ccb1966SGarrett D'Amore for (i = idx; i < cinfop->ci.maxvalue; i++) { 566*3ccb1966SGarrett D'Amore str = get_enum_str(cinfop, i); 567*3ccb1966SGarrett D'Amore if (str == NULL) 568*3ccb1966SGarrett D'Amore continue; 569*3ccb1966SGarrett D'Amore 570*3ccb1966SGarrett D'Amore if ((strlen(str) + 1 + strlen(selbuf)) >= 571*3ccb1966SGarrett D'Amore sizeof (selbuf)) { 572*3ccb1966SGarrett D'Amore break; 573*3ccb1966SGarrett D'Amore } 574*3ccb1966SGarrett D'Amore if (strlen(selbuf)) { 575*3ccb1966SGarrett D'Amore (void) strlcat(selbuf, ",", sizeof (selbuf)); 576*3ccb1966SGarrett D'Amore } 577*3ccb1966SGarrett D'Amore 578*3ccb1966SGarrett D'Amore (void) strlcat(selbuf, str, sizeof (selbuf)); 579*3ccb1966SGarrett D'Amore } 580*3ccb1966SGarrett D'Amore idx = i; 581*3ccb1966SGarrett D'Amore col.col_dv = NULL; 582*3ccb1966SGarrett D'Amore col.col_nm = NULL; 583*3ccb1966SGarrett D'Amore col.col_val = NULL; 584*3ccb1966SGarrett D'Amore col.col_sel = selbuf; 585*3ccb1966SGarrett D'Amore print_control_line(sfp, &col, vopt); 586*3ccb1966SGarrett D'Amore } 587*3ccb1966SGarrett D'Amore 588*3ccb1966SGarrett D'Amore return (0); 589*3ccb1966SGarrett D'Amore } 590*3ccb1966SGarrett D'Amore 591*3ccb1966SGarrett D'Amore 592*3ccb1966SGarrett D'Amore static int 593*3ccb1966SGarrett D'Amore set_device_control(device_t *d, cinfo_t *cinfop, char *wstr, int vopt) 594*3ccb1966SGarrett D'Amore { 595*3ccb1966SGarrett D'Amore int mfd = d->mfd; 596*3ccb1966SGarrett D'Amore oss_mixer_value cval; 597*3ccb1966SGarrett D'Amore int wlen = strlen(wstr); 598*3ccb1966SGarrett D'Amore int lval, rval; 599*3ccb1966SGarrett D'Amore char *lstr, *rstr; 600*3ccb1966SGarrett D'Amore char *str; 601*3ccb1966SGarrett D'Amore int i; 602*3ccb1966SGarrett D'Amore int rv = -1; 603*3ccb1966SGarrett D'Amore 604*3ccb1966SGarrett D'Amore cval.dev = -1; 605*3ccb1966SGarrett D'Amore cval.ctrl = cinfop->ci.ctrl; 606*3ccb1966SGarrett D'Amore cval.value = 0; 607*3ccb1966SGarrett D'Amore 608*3ccb1966SGarrett D'Amore switch (cinfop->ci.type) { 609*3ccb1966SGarrett D'Amore case MIXT_ONOFF: 610*3ccb1966SGarrett D'Amore cval.value = (strncmp(_("on"), wstr, wlen) == 0) ? 1 : 0; 611*3ccb1966SGarrett D'Amore break; 612*3ccb1966SGarrett D'Amore 613*3ccb1966SGarrett D'Amore case MIXT_MONOSLIDER: 614*3ccb1966SGarrett D'Amore cval.value = atoi(wstr); 615*3ccb1966SGarrett D'Amore break; 616*3ccb1966SGarrett D'Amore 617*3ccb1966SGarrett D'Amore case MIXT_STEREOSLIDER: 618*3ccb1966SGarrett D'Amore lstr = wstr; 619*3ccb1966SGarrett D'Amore rstr = strchr(wstr, ':'); 620*3ccb1966SGarrett D'Amore if (rstr != NULL) { 621*3ccb1966SGarrett D'Amore *rstr = '\0'; 622*3ccb1966SGarrett D'Amore rstr++; 623*3ccb1966SGarrett D'Amore 624*3ccb1966SGarrett D'Amore rval = atoi(rstr); 625*3ccb1966SGarrett D'Amore lval = atoi(lstr); 626*3ccb1966SGarrett D'Amore 627*3ccb1966SGarrett D'Amore rstr--; 628*3ccb1966SGarrett D'Amore *rstr = ':'; 629*3ccb1966SGarrett D'Amore } else { 630*3ccb1966SGarrett D'Amore lval = atoi(lstr); 631*3ccb1966SGarrett D'Amore rval = lval; 632*3ccb1966SGarrett D'Amore } 633*3ccb1966SGarrett D'Amore 634*3ccb1966SGarrett D'Amore cval.value = AUDIO_CTRL_STEREO_VAL(lval, rval); 635*3ccb1966SGarrett D'Amore break; 636*3ccb1966SGarrett D'Amore 637*3ccb1966SGarrett D'Amore case MIXT_ENUM: 638*3ccb1966SGarrett D'Amore for (i = 0; i < cinfop->ci.maxvalue; i++) { 639*3ccb1966SGarrett D'Amore str = get_enum_str(cinfop, i); 640*3ccb1966SGarrett D'Amore if (str == NULL) 641*3ccb1966SGarrett D'Amore continue; 642*3ccb1966SGarrett D'Amore 643*3ccb1966SGarrett D'Amore if (strncmp(wstr, str, wlen) == 0) { 644*3ccb1966SGarrett D'Amore cval.value = i; 645*3ccb1966SGarrett D'Amore break; 646*3ccb1966SGarrett D'Amore } 647*3ccb1966SGarrett D'Amore } 648*3ccb1966SGarrett D'Amore 649*3ccb1966SGarrett D'Amore if (i >= cinfop->ci.maxvalue) { 650*3ccb1966SGarrett D'Amore warn(_("Invalid enumeration value\n")); 651*3ccb1966SGarrett D'Amore return (EINVAL); 652*3ccb1966SGarrett D'Amore } 653*3ccb1966SGarrett D'Amore break; 654*3ccb1966SGarrett D'Amore 655*3ccb1966SGarrett D'Amore default: 656*3ccb1966SGarrett D'Amore warn(_("Unsupported control type: %d\n"), cinfop->ci.type); 657*3ccb1966SGarrett D'Amore return (EINVAL); 658*3ccb1966SGarrett D'Amore } 659*3ccb1966SGarrett D'Amore 660*3ccb1966SGarrett D'Amore if (vopt) { 661*3ccb1966SGarrett D'Amore msg(_("%s: '%s' set to '%s'\n"), d->card.shortname, 662*3ccb1966SGarrett D'Amore cinfop->ci.extname, wstr); 663*3ccb1966SGarrett D'Amore } 664*3ccb1966SGarrett D'Amore 665*3ccb1966SGarrett D'Amore if (ioctl(mfd, SNDCTL_MIX_WRITE, &cval) < 0) { 666*3ccb1966SGarrett D'Amore rv = errno; 667*3ccb1966SGarrett D'Amore perror(_("Error writing control")); 668*3ccb1966SGarrett D'Amore return (rv); 669*3ccb1966SGarrett D'Amore } 670*3ccb1966SGarrett D'Amore 671*3ccb1966SGarrett D'Amore rv = 0; 672*3ccb1966SGarrett D'Amore return (rv); 673*3ccb1966SGarrett D'Amore } 674*3ccb1966SGarrett D'Amore 675*3ccb1966SGarrett D'Amore 676*3ccb1966SGarrett D'Amore static void 677*3ccb1966SGarrett D'Amore help(void) 678*3ccb1966SGarrett D'Amore { 679*3ccb1966SGarrett D'Amore #define HELP_STR _( \ 680*3ccb1966SGarrett D'Amore "audioctl list-devices\n" \ 681*3ccb1966SGarrett D'Amore " list all audio devices\n" \ 682*3ccb1966SGarrett D'Amore "\n" \ 683*3ccb1966SGarrett D'Amore "audioctl show-device [ -v ] [ -d <device> ]\n" \ 684*3ccb1966SGarrett D'Amore " display information about an audio device\n" \ 685*3ccb1966SGarrett D'Amore "\n" \ 686*3ccb1966SGarrett D'Amore "audioctl show-control [ -v ] [ -d <device> ] [ <control> ... ]\n" \ 687*3ccb1966SGarrett D'Amore " get the value of a specific control (all if not specified)\n" \ 688*3ccb1966SGarrett D'Amore "\n" \ 689*3ccb1966SGarrett D'Amore "audioctl set-control [ -v ] [ -d <device> ] <control> <value>\n" \ 690*3ccb1966SGarrett D'Amore " set the value of a specific control\n" \ 691*3ccb1966SGarrett D'Amore "\n" \ 692*3ccb1966SGarrett D'Amore "audioctl save-controls [ -d <device> ] [ -f ] <file>\n" \ 693*3ccb1966SGarrett D'Amore " save all control settings for the device to a file\n" \ 694*3ccb1966SGarrett D'Amore "\n" \ 695*3ccb1966SGarrett D'Amore "audioctl load-controls [ -d <device> ] <file>\n" \ 696*3ccb1966SGarrett D'Amore " restore previously saved control settings to device\n" \ 697*3ccb1966SGarrett D'Amore "\n" \ 698*3ccb1966SGarrett D'Amore "audioctl help\n" \ 699*3ccb1966SGarrett D'Amore " show this message.\n") 700*3ccb1966SGarrett D'Amore 701*3ccb1966SGarrett D'Amore (void) fprintf(stderr, HELP_STR); 702*3ccb1966SGarrett D'Amore } 703*3ccb1966SGarrett D'Amore 704*3ccb1966SGarrett D'Amore dev_t 705*3ccb1966SGarrett D'Amore device_devt(char *name) 706*3ccb1966SGarrett D'Amore { 707*3ccb1966SGarrett D'Amore struct stat sbuf; 708*3ccb1966SGarrett D'Amore 709*3ccb1966SGarrett D'Amore if ((stat(name, &sbuf) != 0) || 710*3ccb1966SGarrett D'Amore ((sbuf.st_mode & S_IFCHR) == 0)) { 711*3ccb1966SGarrett D'Amore /* Not a device node! */ 712*3ccb1966SGarrett D'Amore return (0); 713*3ccb1966SGarrett D'Amore } 714*3ccb1966SGarrett D'Amore 715*3ccb1966SGarrett D'Amore return (makedev(major(sbuf.st_rdev), 716*3ccb1966SGarrett D'Amore minor(sbuf.st_rdev) & ~(AUDIO_MN_TYPE_MASK))); 717*3ccb1966SGarrett D'Amore } 718*3ccb1966SGarrett D'Amore 719*3ccb1966SGarrett D'Amore static device_t * 720*3ccb1966SGarrett D'Amore find_device(char *name) 721*3ccb1966SGarrett D'Amore { 722*3ccb1966SGarrett D'Amore dev_t devt; 723*3ccb1966SGarrett D'Amore device_t *d; 724*3ccb1966SGarrett D'Amore 725*3ccb1966SGarrett D'Amore /* 726*3ccb1966SGarrett D'Amore * User may have specified: 727*3ccb1966SGarrett D'Amore * 728*3ccb1966SGarrett D'Amore * /dev/dsp[<num>] 729*3ccb1966SGarrett D'Amore * /dev/mixer[<num>] 730*3ccb1966SGarrett D'Amore * /dev/audio[<num>9] 731*3ccb1966SGarrett D'Amore * /dev/audioctl[<num>] 732*3ccb1966SGarrett D'Amore * /dev/sound/<num>{,ctl,dsp,mixer} 733*3ccb1966SGarrett D'Amore * /dev/sound/<driver>:<num>{,ctl,dsp,mixer} 734*3ccb1966SGarrett D'Amore * 735*3ccb1966SGarrett D'Amore * We can canonicalize these by looking at the dev_t though. 736*3ccb1966SGarrett D'Amore */ 737*3ccb1966SGarrett D'Amore 738*3ccb1966SGarrett D'Amore if (name == NULL) 739*3ccb1966SGarrett D'Amore name = getenv("AUDIODEV"); 740*3ccb1966SGarrett D'Amore 741*3ccb1966SGarrett D'Amore if ((name == NULL) || 742*3ccb1966SGarrett D'Amore (strcmp(name, "/dev/mixer") == 0)) { 743*3ccb1966SGarrett D'Amore /* /dev/mixer node doesn't point to real hw */ 744*3ccb1966SGarrett D'Amore name = "/dev/dsp"; 745*3ccb1966SGarrett D'Amore } 746*3ccb1966SGarrett D'Amore 747*3ccb1966SGarrett D'Amore if (*name == '/') { 748*3ccb1966SGarrett D'Amore /* if we have a full path, convert to the devt */ 749*3ccb1966SGarrett D'Amore if ((devt = device_devt(name)) == 0) { 750*3ccb1966SGarrett D'Amore warn(_("No such audio device.\n")); 751*3ccb1966SGarrett D'Amore return (NULL); 752*3ccb1966SGarrett D'Amore } 753*3ccb1966SGarrett D'Amore name = NULL; 754*3ccb1966SGarrett D'Amore } 755*3ccb1966SGarrett D'Amore 756*3ccb1966SGarrett D'Amore for (d = devices; d != NULL; d = d->nextp) { 757*3ccb1966SGarrett D'Amore oss_card_info *card = &d->card; 758*3ccb1966SGarrett D'Amore 759*3ccb1966SGarrett D'Amore if ((name) && (strcmp(name, card->shortname) == 0)) { 760*3ccb1966SGarrett D'Amore return (d); 761*3ccb1966SGarrett D'Amore } 762*3ccb1966SGarrett D'Amore if (devt == d->devt) { 763*3ccb1966SGarrett D'Amore return (d); 764*3ccb1966SGarrett D'Amore } 765*3ccb1966SGarrett D'Amore } 766*3ccb1966SGarrett D'Amore 767*3ccb1966SGarrett D'Amore warn(_("No such audio device.\n")); 768*3ccb1966SGarrett D'Amore return (NULL); 769*3ccb1966SGarrett D'Amore } 770*3ccb1966SGarrett D'Amore 771*3ccb1966SGarrett D'Amore int 772*3ccb1966SGarrett D'Amore do_list_devices(int argc, char **argv) 773*3ccb1966SGarrett D'Amore { 774*3ccb1966SGarrett D'Amore int optc; 775*3ccb1966SGarrett D'Amore int verbose = 0; 776*3ccb1966SGarrett D'Amore device_t *d; 777*3ccb1966SGarrett D'Amore 778*3ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "v")) != EOF) { 779*3ccb1966SGarrett D'Amore switch (optc) { 780*3ccb1966SGarrett D'Amore case 'v': 781*3ccb1966SGarrett D'Amore verbose++; 782*3ccb1966SGarrett D'Amore break; 783*3ccb1966SGarrett D'Amore default: 784*3ccb1966SGarrett D'Amore help(); 785*3ccb1966SGarrett D'Amore return (-1); 786*3ccb1966SGarrett D'Amore } 787*3ccb1966SGarrett D'Amore } 788*3ccb1966SGarrett D'Amore argc -= optind; 789*3ccb1966SGarrett D'Amore argv += optind; 790*3ccb1966SGarrett D'Amore if (argc != 0) { 791*3ccb1966SGarrett D'Amore help(); 792*3ccb1966SGarrett D'Amore return (-1); 793*3ccb1966SGarrett D'Amore } 794*3ccb1966SGarrett D'Amore 795*3ccb1966SGarrett D'Amore for (d = devices; d != NULL; d = d->nextp) { 796*3ccb1966SGarrett D'Amore 797*3ccb1966SGarrett D'Amore if ((d->mixer.enabled == 0) && (!verbose)) 798*3ccb1966SGarrett D'Amore continue; 799*3ccb1966SGarrett D'Amore 800*3ccb1966SGarrett D'Amore if (verbose) { 801*3ccb1966SGarrett D'Amore msg(_("%s (%s)\n"), d->card.shortname, 802*3ccb1966SGarrett D'Amore d->mixer.devnode); 803*3ccb1966SGarrett D'Amore } else { 804*3ccb1966SGarrett D'Amore msg(_("%s\n"), d->card.shortname); 805*3ccb1966SGarrett D'Amore } 806*3ccb1966SGarrett D'Amore } 807*3ccb1966SGarrett D'Amore 808*3ccb1966SGarrett D'Amore return (0); 809*3ccb1966SGarrett D'Amore } 810*3ccb1966SGarrett D'Amore 811*3ccb1966SGarrett D'Amore int 812*3ccb1966SGarrett D'Amore do_show_device(int argc, char **argv) 813*3ccb1966SGarrett D'Amore { 814*3ccb1966SGarrett D'Amore int optc; 815*3ccb1966SGarrett D'Amore char *devname = NULL; 816*3ccb1966SGarrett D'Amore device_t *d; 817*3ccb1966SGarrett D'Amore 818*3ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:v")) != EOF) { 819*3ccb1966SGarrett D'Amore switch (optc) { 820*3ccb1966SGarrett D'Amore case 'd': 821*3ccb1966SGarrett D'Amore devname = optarg; 822*3ccb1966SGarrett D'Amore break; 823*3ccb1966SGarrett D'Amore case 'v': 824*3ccb1966SGarrett D'Amore break; 825*3ccb1966SGarrett D'Amore default: 826*3ccb1966SGarrett D'Amore help(); 827*3ccb1966SGarrett D'Amore return (-1); 828*3ccb1966SGarrett D'Amore } 829*3ccb1966SGarrett D'Amore } 830*3ccb1966SGarrett D'Amore argc -= optind; 831*3ccb1966SGarrett D'Amore argv += optind; 832*3ccb1966SGarrett D'Amore if (argc != 0) { 833*3ccb1966SGarrett D'Amore help(); 834*3ccb1966SGarrett D'Amore return (-1); 835*3ccb1966SGarrett D'Amore } 836*3ccb1966SGarrett D'Amore 837*3ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 838*3ccb1966SGarrett D'Amore return (ENODEV); 839*3ccb1966SGarrett D'Amore } 840*3ccb1966SGarrett D'Amore 841*3ccb1966SGarrett D'Amore msg(_("Device: %s\n"), d->mixer.devnode); 842*3ccb1966SGarrett D'Amore msg(_(" Name = %s\n"), d->card.shortname); 843*3ccb1966SGarrett D'Amore msg(_(" Config = %s\n"), d->card.longname); 844*3ccb1966SGarrett D'Amore 845*3ccb1966SGarrett D'Amore if (strlen(d->card.hw_info)) { 846*3ccb1966SGarrett D'Amore msg(_(" HW Info = %s"), d->card.hw_info); 847*3ccb1966SGarrett D'Amore } 848*3ccb1966SGarrett D'Amore 849*3ccb1966SGarrett D'Amore return (0); 850*3ccb1966SGarrett D'Amore } 851*3ccb1966SGarrett D'Amore 852*3ccb1966SGarrett D'Amore int 853*3ccb1966SGarrett D'Amore do_show_control(int argc, char **argv) 854*3ccb1966SGarrett D'Amore { 855*3ccb1966SGarrett D'Amore int optc; 856*3ccb1966SGarrett D'Amore int rval = 0; 857*3ccb1966SGarrett D'Amore int verbose = 0; 858*3ccb1966SGarrett D'Amore device_t *d; 859*3ccb1966SGarrett D'Amore char *devname = NULL; 860*3ccb1966SGarrett D'Amore int i; 861*3ccb1966SGarrett D'Amore int j; 862*3ccb1966SGarrett D'Amore int rv; 863*3ccb1966SGarrett D'Amore char *n; 864*3ccb1966SGarrett D'Amore cinfo_t *cinfop; 865*3ccb1966SGarrett D'Amore 866*3ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:v")) != EOF) { 867*3ccb1966SGarrett D'Amore switch (optc) { 868*3ccb1966SGarrett D'Amore case 'd': 869*3ccb1966SGarrett D'Amore devname = optarg; 870*3ccb1966SGarrett D'Amore break; 871*3ccb1966SGarrett D'Amore case 'v': 872*3ccb1966SGarrett D'Amore verbose++; 873*3ccb1966SGarrett D'Amore break; 874*3ccb1966SGarrett D'Amore default: 875*3ccb1966SGarrett D'Amore help(); 876*3ccb1966SGarrett D'Amore return (-1); 877*3ccb1966SGarrett D'Amore } 878*3ccb1966SGarrett D'Amore } 879*3ccb1966SGarrett D'Amore argc -= optind; 880*3ccb1966SGarrett D'Amore argv += optind; 881*3ccb1966SGarrett D'Amore 882*3ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 883*3ccb1966SGarrett D'Amore return (ENODEV); 884*3ccb1966SGarrett D'Amore } 885*3ccb1966SGarrett D'Amore 886*3ccb1966SGarrett D'Amore print_header(NULL, verbose); 887*3ccb1966SGarrett D'Amore if (argc == 0) { 888*3ccb1966SGarrett D'Amore /* do them all! */ 889*3ccb1966SGarrett D'Amore for (i = 0; i < d->cmax; i++) { 890*3ccb1966SGarrett D'Amore 891*3ccb1966SGarrett D'Amore cinfop = &d->controls[i]; 892*3ccb1966SGarrett D'Amore rv = print_control(NULL, d, cinfop, verbose); 893*3ccb1966SGarrett D'Amore rval = rval ? rval : rv; 894*3ccb1966SGarrett D'Amore } 895*3ccb1966SGarrett D'Amore return (rval); 896*3ccb1966SGarrett D'Amore } 897*3ccb1966SGarrett D'Amore 898*3ccb1966SGarrett D'Amore for (i = 0; i < argc; i++) { 899*3ccb1966SGarrett D'Amore for (j = 0; j < d->cmax; j++) { 900*3ccb1966SGarrett D'Amore cinfop = &d->controls[j]; 901*3ccb1966SGarrett D'Amore n = strrchr(cinfop->ci.extname, '_'); 902*3ccb1966SGarrett D'Amore n = n ? n + 1 : cinfop->ci.extname; 903*3ccb1966SGarrett D'Amore if (strcmp(argv[i], n) == 0) { 904*3ccb1966SGarrett D'Amore rv = print_control(NULL, d, cinfop, verbose); 905*3ccb1966SGarrett D'Amore rval = rval ? rval : rv; 906*3ccb1966SGarrett D'Amore break; 907*3ccb1966SGarrett D'Amore } 908*3ccb1966SGarrett D'Amore } 909*3ccb1966SGarrett D'Amore /* Didn't find requested control */ 910*3ccb1966SGarrett D'Amore if (j == d->cmax) { 911*3ccb1966SGarrett D'Amore warn(_("No such control: %s\n"), argv[i]); 912*3ccb1966SGarrett D'Amore rval = rval ? rval : ENODEV; 913*3ccb1966SGarrett D'Amore } 914*3ccb1966SGarrett D'Amore } 915*3ccb1966SGarrett D'Amore 916*3ccb1966SGarrett D'Amore return (rval); 917*3ccb1966SGarrett D'Amore } 918*3ccb1966SGarrett D'Amore 919*3ccb1966SGarrett D'Amore int 920*3ccb1966SGarrett D'Amore do_set_control(int argc, char **argv) 921*3ccb1966SGarrett D'Amore { 922*3ccb1966SGarrett D'Amore int optc; 923*3ccb1966SGarrett D'Amore int rval = 0; 924*3ccb1966SGarrett D'Amore int verbose = 0; 925*3ccb1966SGarrett D'Amore device_t *d; 926*3ccb1966SGarrett D'Amore char *devname = NULL; 927*3ccb1966SGarrett D'Amore char *cname; 928*3ccb1966SGarrett D'Amore char *value; 929*3ccb1966SGarrett D'Amore int i; 930*3ccb1966SGarrett D'Amore int found; 931*3ccb1966SGarrett D'Amore int rv; 932*3ccb1966SGarrett D'Amore char *n; 933*3ccb1966SGarrett D'Amore cinfo_t *cinfop; 934*3ccb1966SGarrett D'Amore 935*3ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:v")) != EOF) { 936*3ccb1966SGarrett D'Amore switch (optc) { 937*3ccb1966SGarrett D'Amore case 'd': 938*3ccb1966SGarrett D'Amore devname = optarg; 939*3ccb1966SGarrett D'Amore break; 940*3ccb1966SGarrett D'Amore case 'v': 941*3ccb1966SGarrett D'Amore verbose = 1; 942*3ccb1966SGarrett D'Amore break; 943*3ccb1966SGarrett D'Amore default: 944*3ccb1966SGarrett D'Amore help(); 945*3ccb1966SGarrett D'Amore return (-1); 946*3ccb1966SGarrett D'Amore } 947*3ccb1966SGarrett D'Amore } 948*3ccb1966SGarrett D'Amore argc -= optind; 949*3ccb1966SGarrett D'Amore argv += optind; 950*3ccb1966SGarrett D'Amore 951*3ccb1966SGarrett D'Amore if (argc != 2) { 952*3ccb1966SGarrett D'Amore help(); 953*3ccb1966SGarrett D'Amore return (-1); 954*3ccb1966SGarrett D'Amore } 955*3ccb1966SGarrett D'Amore cname = argv[0]; 956*3ccb1966SGarrett D'Amore value = argv[1]; 957*3ccb1966SGarrett D'Amore 958*3ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 959*3ccb1966SGarrett D'Amore return (ENODEV); 960*3ccb1966SGarrett D'Amore } 961*3ccb1966SGarrett D'Amore 962*3ccb1966SGarrett D'Amore for (i = 0, found = 0; i < d->cmax; i++) { 963*3ccb1966SGarrett D'Amore cinfop = &d->controls[i]; 964*3ccb1966SGarrett D'Amore n = strrchr(cinfop->ci.extname, '_'); 965*3ccb1966SGarrett D'Amore n = n ? n + 1 : cinfop->ci.extname; 966*3ccb1966SGarrett D'Amore if (strcmp(cname, n) != 0) { 967*3ccb1966SGarrett D'Amore continue; 968*3ccb1966SGarrett D'Amore } 969*3ccb1966SGarrett D'Amore found = 1; 970*3ccb1966SGarrett D'Amore rv = set_device_control(d, cinfop, value, verbose); 971*3ccb1966SGarrett D'Amore rval = rval ? rval : rv; 972*3ccb1966SGarrett D'Amore } 973*3ccb1966SGarrett D'Amore if (!found) { 974*3ccb1966SGarrett D'Amore warn(_("No such control: %s\n"), cname); 975*3ccb1966SGarrett D'Amore } 976*3ccb1966SGarrett D'Amore 977*3ccb1966SGarrett D'Amore return (rval); 978*3ccb1966SGarrett D'Amore } 979*3ccb1966SGarrett D'Amore 980*3ccb1966SGarrett D'Amore int 981*3ccb1966SGarrett D'Amore do_save_controls(int argc, char **argv) 982*3ccb1966SGarrett D'Amore { 983*3ccb1966SGarrett D'Amore int optc; 984*3ccb1966SGarrett D'Amore int rval = 0; 985*3ccb1966SGarrett D'Amore device_t *d; 986*3ccb1966SGarrett D'Amore char *devname = NULL; 987*3ccb1966SGarrett D'Amore char *fname; 988*3ccb1966SGarrett D'Amore int i; 989*3ccb1966SGarrett D'Amore int rv; 990*3ccb1966SGarrett D'Amore cinfo_t *cinfop; 991*3ccb1966SGarrett D'Amore FILE *fp; 992*3ccb1966SGarrett D'Amore int fd; 993*3ccb1966SGarrett D'Amore int mode; 994*3ccb1966SGarrett D'Amore 995*3ccb1966SGarrett D'Amore mode = O_WRONLY | O_CREAT | O_EXCL; 996*3ccb1966SGarrett D'Amore 997*3ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:f")) != EOF) { 998*3ccb1966SGarrett D'Amore switch (optc) { 999*3ccb1966SGarrett D'Amore case 'd': 1000*3ccb1966SGarrett D'Amore devname = optarg; 1001*3ccb1966SGarrett D'Amore break; 1002*3ccb1966SGarrett D'Amore case 'f': 1003*3ccb1966SGarrett D'Amore mode &= ~O_EXCL; 1004*3ccb1966SGarrett D'Amore mode |= O_TRUNC; 1005*3ccb1966SGarrett D'Amore break; 1006*3ccb1966SGarrett D'Amore default: 1007*3ccb1966SGarrett D'Amore help(); 1008*3ccb1966SGarrett D'Amore return (-1); 1009*3ccb1966SGarrett D'Amore } 1010*3ccb1966SGarrett D'Amore } 1011*3ccb1966SGarrett D'Amore argc -= optind; 1012*3ccb1966SGarrett D'Amore argv += optind; 1013*3ccb1966SGarrett D'Amore 1014*3ccb1966SGarrett D'Amore if (argc != 1) { 1015*3ccb1966SGarrett D'Amore help(); 1016*3ccb1966SGarrett D'Amore return (-1); 1017*3ccb1966SGarrett D'Amore } 1018*3ccb1966SGarrett D'Amore fname = argv[0]; 1019*3ccb1966SGarrett D'Amore 1020*3ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 1021*3ccb1966SGarrett D'Amore return (ENODEV); 1022*3ccb1966SGarrett D'Amore } 1023*3ccb1966SGarrett D'Amore 1024*3ccb1966SGarrett D'Amore if ((fd = open(fname, mode, 0666)) < 0) { 1025*3ccb1966SGarrett D'Amore perror(_("Failed to create file")); 1026*3ccb1966SGarrett D'Amore return (errno); 1027*3ccb1966SGarrett D'Amore } 1028*3ccb1966SGarrett D'Amore 1029*3ccb1966SGarrett D'Amore if ((fp = fdopen(fd, "w")) == NULL) { 1030*3ccb1966SGarrett D'Amore perror(_("Unable to open file\n")); 1031*3ccb1966SGarrett D'Amore (void) close(fd); 1032*3ccb1966SGarrett D'Amore (void) unlink(fname); 1033*3ccb1966SGarrett D'Amore return (errno); 1034*3ccb1966SGarrett D'Amore } 1035*3ccb1966SGarrett D'Amore 1036*3ccb1966SGarrett D'Amore (void) fprintf(fp, "# Device: %s\n", d->mixer.devnode); 1037*3ccb1966SGarrett D'Amore (void) fprintf(fp, "# Name = %s\n", d->card.shortname); 1038*3ccb1966SGarrett D'Amore (void) fprintf(fp, "# Config = %s\n", d->card.longname); 1039*3ccb1966SGarrett D'Amore 1040*3ccb1966SGarrett D'Amore if (strlen(d->card.hw_info)) { 1041*3ccb1966SGarrett D'Amore (void) fprintf(fp, "# HW Info = %s", d->card.hw_info); 1042*3ccb1966SGarrett D'Amore } 1043*3ccb1966SGarrett D'Amore (void) fprintf(fp, "#\n"); 1044*3ccb1966SGarrett D'Amore 1045*3ccb1966SGarrett D'Amore print_header(fp, 0); 1046*3ccb1966SGarrett D'Amore 1047*3ccb1966SGarrett D'Amore for (i = 0; i < d->cmax; i++) { 1048*3ccb1966SGarrett D'Amore cinfop = &d->controls[i]; 1049*3ccb1966SGarrett D'Amore rv = print_control(fp, d, cinfop, 0); 1050*3ccb1966SGarrett D'Amore rval = rval ? rval : rv; 1051*3ccb1966SGarrett D'Amore } 1052*3ccb1966SGarrett D'Amore 1053*3ccb1966SGarrett D'Amore (void) fclose(fp); 1054*3ccb1966SGarrett D'Amore 1055*3ccb1966SGarrett D'Amore return (rval); 1056*3ccb1966SGarrett D'Amore } 1057*3ccb1966SGarrett D'Amore 1058*3ccb1966SGarrett D'Amore int 1059*3ccb1966SGarrett D'Amore do_load_controls(int argc, char **argv) 1060*3ccb1966SGarrett D'Amore { 1061*3ccb1966SGarrett D'Amore int optc; 1062*3ccb1966SGarrett D'Amore int rval = 0; 1063*3ccb1966SGarrett D'Amore device_t *d; 1064*3ccb1966SGarrett D'Amore char *devname = NULL; 1065*3ccb1966SGarrett D'Amore char *fname; 1066*3ccb1966SGarrett D'Amore char *cname; 1067*3ccb1966SGarrett D'Amore char *value; 1068*3ccb1966SGarrett D'Amore int i; 1069*3ccb1966SGarrett D'Amore int rv; 1070*3ccb1966SGarrett D'Amore cinfo_t *cinfop; 1071*3ccb1966SGarrett D'Amore FILE *fp; 1072*3ccb1966SGarrett D'Amore char linebuf[MAXLINE]; 1073*3ccb1966SGarrett D'Amore int lineno = 0; 1074*3ccb1966SGarrett D'Amore int found; 1075*3ccb1966SGarrett D'Amore 1076*3ccb1966SGarrett D'Amore while ((optc = getopt(argc, argv, "d:")) != EOF) { 1077*3ccb1966SGarrett D'Amore switch (optc) { 1078*3ccb1966SGarrett D'Amore case 'd': 1079*3ccb1966SGarrett D'Amore devname = optarg; 1080*3ccb1966SGarrett D'Amore break; 1081*3ccb1966SGarrett D'Amore default: 1082*3ccb1966SGarrett D'Amore help(); 1083*3ccb1966SGarrett D'Amore return (-1); 1084*3ccb1966SGarrett D'Amore } 1085*3ccb1966SGarrett D'Amore } 1086*3ccb1966SGarrett D'Amore argc -= optind; 1087*3ccb1966SGarrett D'Amore argv += optind; 1088*3ccb1966SGarrett D'Amore 1089*3ccb1966SGarrett D'Amore if (argc != 1) { 1090*3ccb1966SGarrett D'Amore help(); 1091*3ccb1966SGarrett D'Amore return (-1); 1092*3ccb1966SGarrett D'Amore } 1093*3ccb1966SGarrett D'Amore fname = argv[0]; 1094*3ccb1966SGarrett D'Amore 1095*3ccb1966SGarrett D'Amore if ((d = find_device(devname)) == NULL) { 1096*3ccb1966SGarrett D'Amore return (ENODEV); 1097*3ccb1966SGarrett D'Amore } 1098*3ccb1966SGarrett D'Amore 1099*3ccb1966SGarrett D'Amore if ((fp = fopen(fname, "r")) == NULL) { 1100*3ccb1966SGarrett D'Amore perror(_("Unable to open file")); 1101*3ccb1966SGarrett D'Amore return (errno); 1102*3ccb1966SGarrett D'Amore } 1103*3ccb1966SGarrett D'Amore 1104*3ccb1966SGarrett D'Amore while (fgets(linebuf, sizeof (linebuf), fp) != NULL) { 1105*3ccb1966SGarrett D'Amore lineno++; 1106*3ccb1966SGarrett D'Amore if (linebuf[strlen(linebuf) - 1] != '\n') { 1107*3ccb1966SGarrett D'Amore warn(_("Warning: line too long at line %d\n"), lineno); 1108*3ccb1966SGarrett D'Amore /* read in the rest of the line and discard it */ 1109*3ccb1966SGarrett D'Amore while (fgets(linebuf, sizeof (linebuf), fp) != NULL && 1110*3ccb1966SGarrett D'Amore (linebuf[strlen(linebuf) - 1] != '\n')) { 1111*3ccb1966SGarrett D'Amore continue; 1112*3ccb1966SGarrett D'Amore } 1113*3ccb1966SGarrett D'Amore continue; 1114*3ccb1966SGarrett D'Amore } 1115*3ccb1966SGarrett D'Amore 1116*3ccb1966SGarrett D'Amore /* we have a good line ... */ 1117*3ccb1966SGarrett D'Amore cname = strtok(linebuf, " \t\n"); 1118*3ccb1966SGarrett D'Amore /* skip comments and blank lines */ 1119*3ccb1966SGarrett D'Amore if ((cname == NULL) || (cname[0] == '#')) { 1120*3ccb1966SGarrett D'Amore continue; 1121*3ccb1966SGarrett D'Amore } 1122*3ccb1966SGarrett D'Amore value = strtok(NULL, " \t\n"); 1123*3ccb1966SGarrett D'Amore if ((value == NULL) || (*cname == 0)) { 1124*3ccb1966SGarrett D'Amore warn(_("Warning: missing value at line %d\n"), lineno); 1125*3ccb1966SGarrett D'Amore continue; 1126*3ccb1966SGarrett D'Amore } 1127*3ccb1966SGarrett D'Amore 1128*3ccb1966SGarrett D'Amore for (i = 0, found = 0; i < d->cmax; i++) { 1129*3ccb1966SGarrett D'Amore /* save and restore requires an exact match */ 1130*3ccb1966SGarrett D'Amore cinfop = &d->controls[i]; 1131*3ccb1966SGarrett D'Amore if (strcmp(cinfop->ci.extname, cname) != 0) { 1132*3ccb1966SGarrett D'Amore continue; 1133*3ccb1966SGarrett D'Amore } 1134*3ccb1966SGarrett D'Amore found = 1; 1135*3ccb1966SGarrett D'Amore rv = set_device_control(d, cinfop, value, 0); 1136*3ccb1966SGarrett D'Amore rval = rval ? rval : rv; 1137*3ccb1966SGarrett D'Amore } 1138*3ccb1966SGarrett D'Amore if (!found) { 1139*3ccb1966SGarrett D'Amore warn(_("No such control: %s\n"), cname); 1140*3ccb1966SGarrett D'Amore } 1141*3ccb1966SGarrett D'Amore } 1142*3ccb1966SGarrett D'Amore (void) fclose(fp); 1143*3ccb1966SGarrett D'Amore 1144*3ccb1966SGarrett D'Amore return (rval); 1145*3ccb1966SGarrett D'Amore } 1146*3ccb1966SGarrett D'Amore 1147*3ccb1966SGarrett D'Amore int 1148*3ccb1966SGarrett D'Amore main(int argc, char **argv) 1149*3ccb1966SGarrett D'Amore { 1150*3ccb1966SGarrett D'Amore int rv = 0; 1151*3ccb1966SGarrett D'Amore int opt; 1152*3ccb1966SGarrett D'Amore 1153*3ccb1966SGarrett D'Amore (void) setlocale(LC_ALL, ""); 1154*3ccb1966SGarrett D'Amore (void) textdomain(TEXT_DOMAIN); 1155*3ccb1966SGarrett D'Amore 1156*3ccb1966SGarrett D'Amore while ((opt = getopt(argc, argv, "h")) != EOF) { 1157*3ccb1966SGarrett D'Amore switch (opt) { 1158*3ccb1966SGarrett D'Amore case 'h': 1159*3ccb1966SGarrett D'Amore help(); 1160*3ccb1966SGarrett D'Amore rv = 0; 1161*3ccb1966SGarrett D'Amore goto OUT; 1162*3ccb1966SGarrett D'Amore default: 1163*3ccb1966SGarrett D'Amore rv = EINVAL; 1164*3ccb1966SGarrett D'Amore break; 1165*3ccb1966SGarrett D'Amore } 1166*3ccb1966SGarrett D'Amore } 1167*3ccb1966SGarrett D'Amore 1168*3ccb1966SGarrett D'Amore if (rv) { 1169*3ccb1966SGarrett D'Amore goto OUT; 1170*3ccb1966SGarrett D'Amore } 1171*3ccb1966SGarrett D'Amore 1172*3ccb1966SGarrett D'Amore argc -= optind; 1173*3ccb1966SGarrett D'Amore argv += optind; 1174*3ccb1966SGarrett D'Amore 1175*3ccb1966SGarrett D'Amore rv = load_devices(); 1176*3ccb1966SGarrett D'Amore if (rv != 0) { 1177*3ccb1966SGarrett D'Amore goto OUT; 1178*3ccb1966SGarrett D'Amore } 1179*3ccb1966SGarrett D'Amore 1180*3ccb1966SGarrett D'Amore if (argc < 1) { 1181*3ccb1966SGarrett D'Amore help(); 1182*3ccb1966SGarrett D'Amore rv = EINVAL; 1183*3ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "help") == 0) { 1184*3ccb1966SGarrett D'Amore help(); 1185*3ccb1966SGarrett D'Amore rv = 0; 1186*3ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "list-devices") == 0) { 1187*3ccb1966SGarrett D'Amore rv = do_list_devices(argc, argv); 1188*3ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "show-device") == 0) { 1189*3ccb1966SGarrett D'Amore rv = do_show_device(argc, argv); 1190*3ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "show-control") == 0) { 1191*3ccb1966SGarrett D'Amore rv = do_show_control(argc, argv); 1192*3ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "set-control") == 0) { 1193*3ccb1966SGarrett D'Amore rv = do_set_control(argc, argv); 1194*3ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "load-controls") == 0) { 1195*3ccb1966SGarrett D'Amore rv = do_load_controls(argc, argv); 1196*3ccb1966SGarrett D'Amore } else if (strcmp(argv[0], "save-controls") == 0) { 1197*3ccb1966SGarrett D'Amore rv = do_save_controls(argc, argv); 1198*3ccb1966SGarrett D'Amore } else { 1199*3ccb1966SGarrett D'Amore help(); 1200*3ccb1966SGarrett D'Amore rv = EINVAL; 1201*3ccb1966SGarrett D'Amore } 1202*3ccb1966SGarrett D'Amore 1203*3ccb1966SGarrett D'Amore OUT: 1204*3ccb1966SGarrett D'Amore free_devices(); 1205*3ccb1966SGarrett D'Amore return (rv); 1206*3ccb1966SGarrett D'Amore } 1207