xref: /openbsd/usr.bin/sndiod/opt.c (revision 3cab2bb3)
1 /*	$OpenBSD: opt.c,v 1.4 2018/06/26 07:12:35 ratchov Exp $	*/
2 /*
3  * Copyright (c) 2008-2011 Alexandre Ratchov <alex@caoua.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 #include <string.h>
18 
19 #include "dev.h"
20 #include "opt.h"
21 #include "utils.h"
22 
23 /*
24  * create a new audio sub-device "configuration"
25  */
26 struct opt *
27 opt_new(struct dev *d, char *name,
28     int pmin, int pmax, int rmin, int rmax,
29     int maxweight, int mmc, int dup, unsigned int mode)
30 {
31 	struct opt *o;
32 	unsigned int len;
33 	char c;
34 
35 	if (opt_byname(d, name)) {
36 		dev_log(d);
37 		log_puts(".");
38 		log_puts(name);
39 		log_puts(": already defined\n");
40 		return NULL;
41 	}
42 	for (len = 0; name[len] != '\0'; len++) {
43 		if (len == OPT_NAMEMAX) {
44 			log_puts(name);
45 			log_puts(": too long\n");
46 			return NULL;
47 		}
48 		c = name[len];
49 		if ((c < 'a' || c > 'z') &&
50 		    (c < 'A' || c > 'Z')) {
51 			log_puts(name);
52 			log_puts(": only alphabetic chars allowed\n");
53 			return NULL;
54 		}
55 	}
56 	o = xmalloc(sizeof(struct opt));
57 	if (mode & MODE_PLAY) {
58 		o->pmin = pmin;
59 		o->pmax = pmax;
60 	}
61 	if (mode & MODE_RECMASK) {
62 		o->rmin = rmin;
63 		o->rmax = rmax;
64 	}
65 	o->maxweight = maxweight;
66 	o->mmc = mmc;
67 	o->dup = dup;
68 	o->mode = mode;
69 	memcpy(o->name, name, len + 1);
70 	o->next = d->opt_list;
71 	d->opt_list = o;
72 	if (log_level >= 2) {
73 		dev_log(d);
74 		log_puts(".");
75 		log_puts(o->name);
76 		log_puts(":");
77 		if (o->mode & MODE_REC) {
78 			log_puts(" rec=");
79 			log_putu(o->rmin);
80 			log_puts(":");
81 			log_putu(o->rmax);
82 		}
83 		if (o->mode & MODE_PLAY) {
84 			log_puts(" play=");
85 			log_putu(o->pmin);
86 			log_puts(":");
87 			log_putu(o->pmax);
88 			log_puts(" vol=");
89 			log_putu(o->maxweight);
90 		}
91 		if (o->mode & MODE_MON) {
92 			log_puts(" mon=");
93 			log_putu(o->rmin);
94 			log_puts(":");
95 			log_putu(o->rmax);
96 		}
97 		if (o->mode & (MODE_RECMASK | MODE_PLAY)) {
98 			if (o->mmc)
99 				log_puts(" mmc");
100 			if (o->dup)
101 				log_puts(" dup");
102 		}
103 		log_puts("\n");
104 	}
105 	return o;
106 }
107 
108 struct opt *
109 opt_byname(struct dev *d, char *name)
110 {
111 	struct opt *o;
112 
113 	for (o = d->opt_list; o != NULL; o = o->next) {
114 		if (strcmp(name, o->name) == 0)
115 			return o;
116 	}
117 	return NULL;
118 }
119 
120 void
121 opt_del(struct dev *d, struct opt *o)
122 {
123 	struct opt **po;
124 
125 	for (po = &d->opt_list; *po != o; po = &(*po)->next) {
126 #ifdef DEBUG
127 		if (*po == NULL) {
128 			log_puts("opt_del: not on list\n");
129 			panic();
130 		}
131 #endif
132 	}
133 	*po = o->next;
134 	xfree(o);
135 }
136