Home | History | Annotate | Line # | Download | only in ctl
ctl.c revision 1.41.2.1
      1  1.41.2.1    bouyer /*	$NetBSD: ctl.c,v 1.41.2.1 2017/04/21 16:54:14 bouyer Exp $	*/
      2       1.1  augustss 
      3       1.1  augustss /*
      4       1.1  augustss  * Copyright (c) 1997 The NetBSD Foundation, Inc.
      5       1.1  augustss  * All rights reserved.
      6       1.1  augustss  *
      7      1.21  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8      1.35      salo  * by Lennart Augustsson (augustss (at) NetBSD.org).
      9       1.1  augustss  *
     10       1.1  augustss  * Redistribution and use in source and binary forms, with or without
     11       1.1  augustss  * modification, are permitted provided that the following conditions
     12       1.1  augustss  * are met:
     13       1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     14       1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     15       1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     17       1.1  augustss  *    documentation and/or other materials provided with the distribution.
     18       1.1  augustss  *
     19       1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22      1.10       jtc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23      1.10       jtc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1  augustss  */
     31      1.34       agc #include <sys/cdefs.h>
     32      1.34       agc 
     33      1.34       agc #ifndef lint
     34  1.41.2.1    bouyer __RCSID("$NetBSD: ctl.c,v 1.41.2.1 2017/04/21 16:54:14 bouyer Exp $");
     35      1.34       agc #endif
     36      1.34       agc 
     37       1.1  augustss 
     38       1.1  augustss #include <sys/types.h>
     39       1.2  augustss #include <sys/stat.h>
     40       1.1  augustss #include <sys/ioctl.h>
     41       1.1  augustss #include <sys/audioio.h>
     42       1.1  augustss 
     43      1.22       mrg #include <err.h>
     44      1.22       mrg #include <fcntl.h>
     45      1.22       mrg #include <stdio.h>
     46      1.22       mrg #include <stdlib.h>
     47      1.22       mrg #include <string.h>
     48      1.22       mrg #include <unistd.h>
     49      1.22       mrg 
     50      1.22       mrg #include <paths.h>
     51      1.22       mrg 
     52      1.22       mrg #include "libaudio.h"
     53      1.19  augustss 
     54      1.39     joerg static struct field *findfield(const char *name);
     55      1.39     joerg static void prfield(const struct field *p, const char *sep);
     56      1.39     joerg static void rdfield(struct field *p, char *q);
     57      1.39     joerg static void getinfo(int fd);
     58      1.39     joerg static void audioctl_write(int, int, char *[]);
     59      1.39     joerg __dead static void usage(void);
     60       1.9  augustss 
     61      1.39     joerg static audio_device_t adev;
     62       1.1  augustss 
     63      1.39     joerg static audio_info_t info;
     64       1.1  augustss 
     65      1.39     joerg static char encbuf[1000];
     66       1.1  augustss 
     67      1.39     joerg static int properties, fullduplex, rerror;
     68       1.1  augustss 
     69  1.41.2.1    bouyer int channel;
     70      1.40       mrg int verbose;
     71      1.40       mrg 
     72      1.39     joerg static struct field {
     73      1.28       mrg 	const char *name;
     74       1.1  augustss 	void *valp;
     75       1.1  augustss 	int format;
     76       1.1  augustss #define STRING 1
     77       1.1  augustss #define INT 2
     78       1.1  augustss #define UINT 3
     79       1.1  augustss #define P_R 4
     80      1.18       mrg #define ULONG 5	/* XXX obsolete now */
     81       1.1  augustss #define UCHAR 6
     82       1.1  augustss #define ENC 7
     83       1.6  augustss #define PROPS 8
     84      1.12  augustss #define XINT 9
     85      1.17   mycroft #define	FORMAT 10
     86       1.2  augustss 	char flags;
     87       1.2  augustss #define READONLY 1
     88       1.2  augustss #define ALIAS 2
     89       1.2  augustss #define SET 4
     90       1.1  augustss } fields[] = {
     91      1.11  augustss 	{ "name", 		&adev.name, 		STRING, READONLY },
     92      1.11  augustss 	{ "version",		&adev.version,		STRING, READONLY },
     93      1.11  augustss 	{ "config",		&adev.config,		STRING, READONLY },
     94      1.11  augustss 	{ "encodings",		encbuf,			STRING, READONLY },
     95      1.11  augustss 	{ "properties",		&properties,		PROPS,	READONLY },
     96      1.15  augustss 	{ "full_duplex",	&fullduplex,		UINT,   0 },
     97      1.15  augustss 	{ "fullduplex",		&fullduplex,		UINT,   0 },
     98      1.11  augustss 	{ "blocksize",		&info.blocksize,	UINT,	0 },
     99      1.11  augustss 	{ "hiwat",		&info.hiwat,		UINT,	0 },
    100      1.11  augustss 	{ "lowat",		&info.lowat,		UINT,	0 },
    101      1.12  augustss 	{ "monitor_gain",	&info.monitor_gain,	UINT,	0 },
    102      1.11  augustss 	{ "mode",		&info.mode,		P_R,	READONLY },
    103      1.17   mycroft 	{ "play",		&info.play,		FORMAT,	ALIAS },
    104      1.11  augustss 	{ "play.rate",		&info.play.sample_rate,	UINT,	0 },
    105      1.11  augustss 	{ "play.sample_rate",	&info.play.sample_rate,	UINT,	ALIAS },
    106      1.11  augustss 	{ "play.channels",	&info.play.channels,	UINT,	0 },
    107      1.11  augustss 	{ "play.precision",	&info.play.precision,	UINT,	0 },
    108      1.11  augustss 	{ "play.encoding",	&info.play.encoding,	ENC,	0 },
    109      1.11  augustss 	{ "play.gain",		&info.play.gain,	UINT,	0 },
    110      1.12  augustss 	{ "play.balance",	&info.play.balance,	UCHAR,	0 },
    111      1.12  augustss 	{ "play.port",		&info.play.port,	XINT,	0 },
    112      1.12  augustss 	{ "play.avail_ports",	&info.play.avail_ports,	XINT,	0 },
    113      1.18       mrg 	{ "play.seek",		&info.play.seek,	UINT,	READONLY },
    114      1.11  augustss 	{ "play.samples",	&info.play.samples,	UINT,	READONLY },
    115      1.11  augustss 	{ "play.eof",		&info.play.eof,		UINT,	READONLY },
    116      1.11  augustss 	{ "play.pause",		&info.play.pause,	UCHAR,	0 },
    117      1.11  augustss 	{ "play.error",		&info.play.error,	UCHAR,	READONLY },
    118      1.11  augustss 	{ "play.waiting",	&info.play.waiting,	UCHAR,	READONLY },
    119      1.11  augustss 	{ "play.open",		&info.play.open,	UCHAR,	READONLY },
    120      1.11  augustss 	{ "play.active",	&info.play.active,	UCHAR,	READONLY },
    121      1.12  augustss 	{ "play.buffer_size",	&info.play.buffer_size,	UINT,	0 },
    122      1.17   mycroft 	{ "record",		&info.record,		FORMAT,	ALIAS },
    123      1.11  augustss 	{ "record.rate",	&info.record.sample_rate,UINT,	0 },
    124      1.11  augustss 	{ "record.sample_rate",	&info.record.sample_rate,UINT,	ALIAS },
    125      1.11  augustss 	{ "record.channels",	&info.record.channels,	UINT,	0 },
    126      1.11  augustss 	{ "record.precision",	&info.record.precision,	UINT,	0 },
    127      1.11  augustss 	{ "record.encoding",	&info.record.encoding,	ENC,	0 },
    128      1.11  augustss 	{ "record.gain",	&info.record.gain,	UINT,	0 },
    129      1.12  augustss 	{ "record.balance",	&info.record.balance,	UCHAR,	0 },
    130      1.12  augustss 	{ "record.port",	&info.record.port,	XINT,	0 },
    131      1.12  augustss 	{ "record.avail_ports",	&info.record.avail_ports,XINT,	0 },
    132      1.18       mrg 	{ "record.seek",	&info.record.seek,	UINT,	READONLY },
    133      1.11  augustss 	{ "record.samples",	&info.record.samples,	UINT,	READONLY },
    134      1.11  augustss 	{ "record.eof",		&info.record.eof,	UINT,	READONLY },
    135      1.11  augustss 	{ "record.pause",	&info.record.pause,	UCHAR,	0 },
    136      1.11  augustss 	{ "record.error",	&info.record.error,	UCHAR,	READONLY },
    137      1.11  augustss 	{ "record.waiting",	&info.record.waiting,	UCHAR,	READONLY },
    138      1.11  augustss 	{ "record.open",	&info.record.open,	UCHAR,	READONLY },
    139      1.11  augustss 	{ "record.active",	&info.record.active,	UCHAR,	READONLY },
    140      1.12  augustss 	{ "record.buffer_size",	&info.record.buffer_size,UINT,	0 },
    141      1.11  augustss 	{ "record.errors",	&rerror,		INT,	READONLY },
    142      1.36  christos 	{ .name = NULL },
    143       1.1  augustss };
    144       1.1  augustss 
    145      1.39     joerg static const struct {
    146      1.28       mrg 	const char *name;
    147      1.11  augustss 	u_int prop;
    148      1.11  augustss } props[] = {
    149      1.11  augustss 	{ "full_duplex",	AUDIO_PROP_FULLDUPLEX },
    150      1.11  augustss 	{ "mmap",		AUDIO_PROP_MMAP },
    151      1.11  augustss 	{ "independent",	AUDIO_PROP_INDEPENDENT },
    152      1.36  christos 	{ .name = NULL },
    153       1.1  augustss };
    154       1.1  augustss 
    155      1.39     joerg static struct field *
    156      1.39     joerg findfield(const char *name)
    157       1.1  augustss {
    158      1.11  augustss 	int i;
    159      1.22       mrg 	for (i = 0; fields[i].name; i++)
    160      1.11  augustss 		if (strcmp(fields[i].name, name) == 0)
    161      1.11  augustss 			return &fields[i];
    162      1.11  augustss 	return 0;
    163       1.1  augustss }
    164       1.1  augustss 
    165      1.39     joerg static void
    166      1.39     joerg prfield(const struct field *p, const char *sep)
    167       1.1  augustss {
    168      1.11  augustss 	u_int v;
    169      1.28       mrg 	const char *cm, *encstr;
    170      1.11  augustss 	int i;
    171      1.11  augustss 
    172      1.11  augustss 	if (sep)
    173      1.30  jdolecek 		printf("%s%s", p->name, sep);
    174      1.11  augustss 	switch(p->format) {
    175      1.11  augustss 	case STRING:
    176      1.39     joerg 		printf("%s", (const char*)p->valp);
    177      1.11  augustss 		break;
    178      1.11  augustss 	case INT:
    179      1.39     joerg 		printf("%d", *(const int*)p->valp);
    180      1.11  augustss 		break;
    181      1.11  augustss 	case UINT:
    182      1.39     joerg 		printf("%u", *(const u_int*)p->valp);
    183      1.11  augustss 		break;
    184      1.12  augustss 	case XINT:
    185      1.39     joerg 		printf("0x%x", *(const u_int*)p->valp);
    186      1.12  augustss 		break;
    187      1.11  augustss 	case UCHAR:
    188      1.39     joerg 		printf("%u", *(const u_char*)p->valp);
    189      1.11  augustss 		break;
    190      1.11  augustss 	case ULONG:
    191      1.39     joerg 		printf("%lu", *(const u_long*)p->valp);
    192      1.11  augustss 		break;
    193      1.11  augustss 	case P_R:
    194      1.39     joerg 		v = *(const u_int*)p->valp;
    195      1.11  augustss 		cm = "";
    196      1.11  augustss 		if (v & AUMODE_PLAY) {
    197      1.11  augustss 			if (v & AUMODE_PLAY_ALL)
    198      1.30  jdolecek 				printf("play");
    199      1.11  augustss 			else
    200      1.30  jdolecek 				printf("playsync");
    201      1.11  augustss 			cm = ",";
    202      1.11  augustss 		}
    203      1.11  augustss 		if (v & AUMODE_RECORD)
    204      1.30  jdolecek 			printf("%srecord", cm);
    205      1.11  augustss 		break;
    206      1.11  augustss 	case ENC:
    207      1.11  augustss 		v = *(u_int*)p->valp;
    208      1.22       mrg 		encstr = audio_enc_from_val(v);
    209      1.22       mrg 		if (encstr)
    210      1.30  jdolecek 			printf("%s", encstr);
    211      1.11  augustss 		else
    212      1.30  jdolecek 			printf("%u", v);
    213      1.11  augustss 		break;
    214      1.11  augustss 	case PROPS:
    215      1.11  augustss 		v = *(u_int*)p->valp;
    216      1.11  augustss 		for (cm = "", i = 0; props[i].name; i++) {
    217      1.11  augustss 			if (v & props[i].prop) {
    218      1.30  jdolecek 				printf("%s%s", cm, props[i].name);
    219      1.11  augustss 				cm = ",";
    220      1.11  augustss 			}
    221      1.11  augustss 		}
    222       1.1  augustss 		break;
    223      1.17   mycroft 	case FORMAT:
    224      1.17   mycroft 		prfield(p + 1, 0);
    225      1.30  jdolecek 		printf(",");
    226      1.17   mycroft 		prfield(p + 3, 0);
    227      1.30  jdolecek 		printf(",");
    228      1.17   mycroft 		prfield(p + 4, 0);
    229      1.30  jdolecek 		printf(",");
    230      1.17   mycroft 		prfield(p + 5, 0);
    231      1.17   mycroft 		break;
    232      1.11  augustss 	default:
    233      1.12  augustss 		errx(1, "Invalid print format.");
    234       1.6  augustss 	}
    235       1.2  augustss }
    236       1.2  augustss 
    237      1.39     joerg static void
    238      1.39     joerg rdfield(struct field *p, char *q)
    239       1.2  augustss {
    240      1.22       mrg 	int enc;
    241      1.12  augustss 	u_int u;
    242      1.17   mycroft 	char *s;
    243       1.2  augustss 
    244      1.11  augustss 	switch(p->format) {
    245      1.11  augustss 	case UINT:
    246      1.11  augustss 		if (sscanf(q, "%u", (unsigned int *)p->valp) != 1)
    247      1.17   mycroft 			errx(1, "Bad number: %s", q);
    248       1.1  augustss 		break;
    249      1.12  augustss 	case UCHAR:
    250      1.12  augustss 		if (sscanf(q, "%u", &u) != 1)
    251      1.17   mycroft 			errx(1, "Bad number: %s", q);
    252      1.12  augustss 		else
    253      1.12  augustss 			*(u_char *)p->valp = u;
    254      1.12  augustss 		break;
    255      1.12  augustss 	case XINT:
    256      1.12  augustss 		if (sscanf(q, "0x%x", (unsigned int *)p->valp) != 1 &&
    257      1.12  augustss 		    sscanf(q, "%x", (unsigned int *)p->valp) != 1)
    258      1.17   mycroft 			errx(1, "Bad number: %s", q);
    259      1.12  augustss 		break;
    260      1.11  augustss 	case ENC:
    261      1.22       mrg 		enc = audio_enc_to_val(q);
    262      1.22       mrg 		if (enc >= 0)
    263      1.22       mrg 			*(u_int*)p->valp = enc;
    264      1.11  augustss 		else
    265      1.17   mycroft 			errx(1, "Unknown encoding: %s", q);
    266      1.17   mycroft 		break;
    267      1.17   mycroft 	case FORMAT:
    268      1.17   mycroft 		s = strsep(&q, ",");
    269      1.17   mycroft 		if (s)
    270      1.17   mycroft 			rdfield(p + 1, s);
    271      1.17   mycroft 		s = strsep(&q, ",");
    272      1.17   mycroft 		if (s)
    273      1.17   mycroft 			rdfield(p + 3, s);
    274      1.17   mycroft 		s = strsep(&q, ",");
    275      1.17   mycroft 		if (s)
    276      1.17   mycroft 			rdfield(p + 4, s);
    277      1.17   mycroft 		s = strsep(&q, ",");
    278      1.17   mycroft 		if (s)
    279      1.17   mycroft 			rdfield(p + 5, s);
    280      1.17   mycroft 		if (!s || q)
    281      1.17   mycroft 			errx(1, "Bad format");
    282      1.11  augustss 		break;
    283      1.11  augustss 	default:
    284      1.12  augustss 		errx(1, "Invalid read format.");
    285      1.11  augustss 	}
    286      1.11  augustss 	p->flags |= SET;
    287       1.1  augustss }
    288       1.1  augustss 
    289      1.39     joerg static void
    290      1.39     joerg getinfo(int fd)
    291       1.1  augustss {
    292      1.11  augustss 	int pos, i;
    293       1.1  augustss 
    294  1.41.2.1    bouyer 	if (channel >= 0 && ioctl(fd, AUDIO_SETCHAN, &channel) < 0)
    295  1.41.2.1    bouyer 		err(1, "AUDIO_SETCHAN");
    296      1.41       nat 
    297      1.11  augustss 	if (ioctl(fd, AUDIO_GETDEV, &adev) < 0)
    298      1.11  augustss 		err(1, "AUDIO_GETDEV");
    299      1.16   mycroft 	for (pos = 0, i = 0; ; i++) {
    300      1.11  augustss 		audio_encoding_t enc;
    301      1.11  augustss 		enc.index = i;
    302      1.11  augustss 		if (ioctl(fd, AUDIO_GETENC, &enc) < 0)
    303      1.11  augustss 			break;
    304      1.38     lukem 		if (pos >= (int)sizeof(encbuf)-1)
    305      1.16   mycroft 			break;
    306      1.11  augustss 		if (pos)
    307      1.11  augustss 			encbuf[pos++] = ',';
    308      1.38     lukem 		if (pos >= (int)sizeof(encbuf)-1)
    309      1.16   mycroft 			break;
    310      1.16   mycroft 		pos += snprintf(encbuf+pos, sizeof(encbuf)-pos, "%s:%d%s",
    311      1.27    simonb 			enc.name, enc.precision,
    312      1.11  augustss 			enc.flags & AUDIO_ENCODINGFLAG_EMULATED ? "*" : "");
    313      1.11  augustss 	}
    314      1.11  augustss 	if (ioctl(fd, AUDIO_GETFD, &fullduplex) < 0)
    315      1.11  augustss 		err(1, "AUDIO_GETFD");
    316      1.11  augustss 	if (ioctl(fd, AUDIO_GETPROPS, &properties) < 0)
    317      1.11  augustss 		err(1, "AUDIO_GETPROPS");
    318      1.11  augustss 	if (ioctl(fd, AUDIO_RERROR, &rerror) < 0)
    319      1.11  augustss 		err(1, "AUDIO_RERROR");
    320      1.11  augustss 	if (ioctl(fd, AUDIO_GETINFO, &info) < 0)
    321      1.11  augustss 		err(1, "AUDIO_GETINFO");
    322       1.2  augustss }
    323       1.2  augustss 
    324      1.39     joerg static void
    325      1.39     joerg usage(void)
    326       1.2  augustss {
    327      1.26       cgd 	const char *prog = getprogname();
    328      1.22       mrg 
    329  1.41.2.1    bouyer 	fprintf(stderr, "Usage: %s [-d file] [-p] channel "
    330  1.41.2.1    bouyer 			"[-n] name ...\n", prog);
    331  1.41.2.1    bouyer 	fprintf(stderr, "Usage: %s [-d file] [-p] channel [-n] "
    332  1.41.2.1    bouyer 			"-w name=value ...\n", prog);
    333  1.41.2.1    bouyer 	fprintf(stderr, "Usage: %s [-d file] [-p] channel [-n] -a\n", prog);
    334      1.11  augustss 	exit(1);
    335       1.1  augustss }
    336       1.1  augustss 
    337       1.9  augustss int
    338      1.39     joerg main(int argc, char *argv[])
    339       1.1  augustss {
    340      1.11  augustss 	int fd, i, ch;
    341      1.11  augustss 	int aflag = 0, wflag = 0;
    342      1.32  augustss 	const char *deffile = _PATH_AUDIOCTL;
    343      1.16   mycroft 	const char *file;
    344      1.28       mrg 	const char *sep = "=";
    345      1.27    simonb 
    346  1.41.2.1    bouyer 	channel = -1;
    347      1.14  augustss 	file = getenv("AUDIOCTLDEVICE");
    348      1.31  augustss 	if (file == NULL)
    349      1.32  augustss 		file = deffile;
    350      1.27    simonb 
    351      1.41       nat 	while ((ch = getopt(argc, argv, "ad:f:np:w")) != -1) {
    352      1.11  augustss 		switch(ch) {
    353      1.11  augustss 		case 'a':
    354      1.11  augustss 			aflag++;
    355      1.11  augustss 			break;
    356      1.11  augustss 		case 'w':
    357      1.11  augustss 			wflag++;
    358      1.11  augustss 			break;
    359      1.11  augustss 		case 'n':
    360      1.11  augustss 			sep = 0;
    361      1.11  augustss 			break;
    362      1.41       nat 		case 'p':
    363  1.41.2.1    bouyer 			channel = atoi(optarg);
    364      1.41       nat 			break;
    365      1.33       wiz 		case 'f': /* compatibility */
    366      1.29  jdolecek 		case 'd':
    367      1.11  augustss 			file = optarg;
    368      1.11  augustss 			break;
    369      1.11  augustss 		case '?':
    370      1.11  augustss 		default:
    371      1.11  augustss 			usage();
    372      1.11  augustss 		}
    373       1.1  augustss 	}
    374      1.11  augustss 	argc -= optind;
    375      1.11  augustss 	argv += optind;
    376      1.27    simonb 
    377      1.11  augustss 	fd = open(file, O_WRONLY);
    378      1.11  augustss 	if (fd < 0)
    379      1.11  augustss 		fd = open(file, O_RDONLY);
    380      1.32  augustss         if (fd < 0 && file == deffile) {
    381      1.31  augustss         	file = _PATH_AUDIOCTL0;
    382      1.19  augustss                 fd = open(file, O_WRONLY);
    383      1.19  augustss 		if (fd < 0)
    384      1.19  augustss 			fd = open(file, O_RDONLY);
    385      1.19  augustss         }
    386      1.31  augustss 
    387      1.11  augustss 	if (fd < 0)
    388      1.11  augustss 		err(1, "%s", file);
    389      1.27    simonb 
    390      1.11  augustss 	if (!wflag)
    391       1.2  augustss 		getinfo(fd);
    392      1.11  augustss 
    393      1.11  augustss 	if (argc == 0 && aflag && !wflag) {
    394      1.22       mrg 		for (i = 0; fields[i].name; i++) {
    395      1.11  augustss 			if (!(fields[i].flags & ALIAS)) {
    396      1.11  augustss 				prfield(&fields[i], sep);
    397      1.30  jdolecek 				printf("\n");
    398      1.11  augustss 			}
    399       1.1  augustss 		}
    400      1.11  augustss 	} else if (argc > 0 && !aflag) {
    401      1.11  augustss 		if (wflag) {
    402      1.22       mrg 			audioctl_write(fd, argc, argv);
    403      1.11  augustss 			if (sep) {
    404      1.11  augustss 				getinfo(fd);
    405      1.22       mrg 				for (i = 0; fields[i].name; i++) {
    406      1.11  augustss 					if (fields[i].flags & SET) {
    407  1.41.2.1    bouyer 						printf("%s: -> ",
    408  1.41.2.1    bouyer 						    fields[i].name);
    409      1.11  augustss 						prfield(&fields[i], 0);
    410      1.30  jdolecek 						printf("\n");
    411      1.11  augustss 					}
    412      1.11  augustss 				}
    413      1.11  augustss 			}
    414       1.1  augustss 		} else {
    415      1.22       mrg 			struct field *p;
    416      1.22       mrg 			while (argc--) {
    417      1.11  augustss 				p = findfield(*argv);
    418      1.11  augustss 				if (p == 0) {
    419      1.11  augustss 					if (strchr(*argv, '='))
    420  1.41.2.1    bouyer 						warnx("field %s does not exist "
    421  1.41.2.1    bouyer 						      "(use -w to set a "
    422  1.41.2.1    bouyer 						      "variable)", *argv);
    423      1.11  augustss 					else
    424  1.41.2.1    bouyer 						warnx("field %s does not exist",
    425  1.41.2.1    bouyer 						      *argv);
    426      1.11  augustss 				} else {
    427      1.11  augustss 					prfield(p, sep);
    428      1.30  jdolecek 					printf("\n");
    429      1.11  augustss 				}
    430      1.11  augustss 				argv++;
    431      1.11  augustss 			}
    432       1.1  augustss 		}
    433      1.11  augustss 	} else
    434      1.11  augustss 		usage();
    435      1.11  augustss 	exit(0);
    436      1.22       mrg }
    437      1.22       mrg 
    438      1.39     joerg static void
    439      1.39     joerg audioctl_write(int fd, int argc, char *argv[])
    440      1.22       mrg {
    441      1.22       mrg 	struct field *p;
    442      1.22       mrg 
    443  1.41.2.1    bouyer 	if (channel >= 0 && ioctl(fd, AUDIO_SETCHAN, &channel) < 0)
    444  1.41.2.1    bouyer 		err(1, "AUDIO_SETCHAN");
    445      1.41       nat 
    446      1.22       mrg 	AUDIO_INITINFO(&info);
    447      1.22       mrg 	while (argc--) {
    448      1.22       mrg 		char *q;
    449      1.22       mrg 
    450      1.22       mrg 		q = strchr(*argv, '=');
    451      1.22       mrg 		if (q) {
    452      1.22       mrg 			*q++ = 0;
    453      1.22       mrg 			p = findfield(*argv);
    454      1.22       mrg 			if (p == 0)
    455      1.22       mrg 				warnx("field `%s' does not exist", *argv);
    456      1.22       mrg 			else {
    457      1.22       mrg 				if (p->flags & READONLY)
    458      1.22       mrg 					warnx("`%s' is read only", *argv);
    459      1.22       mrg 				else {
    460      1.22       mrg 					rdfield(p, q);
    461      1.22       mrg 					if (p->valp == &fullduplex)
    462  1.41.2.1    bouyer 						if (ioctl(fd, AUDIO_SETFD,
    463  1.41.2.1    bouyer 							   &fullduplex) < 0)
    464      1.22       mrg 							err(1, "set failed");
    465      1.22       mrg 				}
    466      1.22       mrg 			}
    467      1.22       mrg 		} else
    468      1.22       mrg 			warnx("No `=' in %s", *argv);
    469      1.22       mrg 		argv++;
    470      1.22       mrg 	}
    471      1.22       mrg 	if (ioctl(fd, AUDIO_SETINFO, &info) < 0)
    472      1.22       mrg 		err(1, "set failed");
    473       1.1  augustss }
    474