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