xref: /openbsd-src/usr.bin/sndiod/opt.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: opt.c,v 1.3 2016/01/08 10:54:07 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 struct opt *opt_list = NULL;
24 
25 /*
26  * create a new audio sub-device "configuration"
27  */
28 struct opt *
29 opt_new(char *name, struct dev *dev,
30     int pmin, int pmax, int rmin, int rmax,
31     int maxweight, int mmc, int dup, unsigned int mode)
32 {
33 	struct opt *o;
34 	unsigned int len;
35 	char c;
36 
37 	if (opt_byname(name, dev->num)) {
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 	o->dev = dev;
70 	memcpy(o->name, name, len + 1);
71 	o->next = opt_list;
72 	opt_list = o;
73 	if (log_level >= 2) {
74 		dev_log(o->dev);
75 		log_puts(".");
76 		log_puts(o->name);
77 		log_puts(":");
78 		if (o->mode & MODE_REC) {
79 			log_puts(" rec=");
80 			log_putu(o->rmin);
81 			log_puts(":");
82 			log_putu(o->rmax);
83 		}
84 		if (o->mode & MODE_PLAY) {
85 			log_puts(" play=");
86 			log_putu(o->pmin);
87 			log_puts(":");
88 			log_putu(o->pmax);
89 			log_puts(" vol=");
90 			log_putu(o->maxweight);
91 		}
92 		if (o->mode & MODE_MON) {
93 			log_puts(" mon=");
94 			log_putu(o->rmin);
95 			log_puts(":");
96 			log_putu(o->rmax);
97 		}
98 		if (o->mode & (MODE_RECMASK | MODE_PLAY)) {
99 			if (o->mmc)
100 				log_puts(" mmc");
101 			if (o->dup)
102 				log_puts(" dup");
103 		}
104 		log_puts("\n");
105 	}
106 	return o;
107 }
108 
109 struct opt *
110 opt_byname(char *name, unsigned int num)
111 {
112 	struct opt *o;
113 
114 	for (o = opt_list; o != NULL; o = o->next) {
115 		if (o->dev->num != num)
116 			continue;
117 		if (strcmp(name, o->name) == 0)
118 			return o;
119 	}
120 	return NULL;
121 }
122 
123 void
124 opt_del(struct opt *o)
125 {
126 	struct opt **po;
127 
128 	for (po = &opt_list; *po != o; po = &(*po)->next) {
129 #ifdef DEBUG
130 		if (*po == NULL) {
131 			log_puts("opt_del: not on list\n");
132 			panic();
133 		}
134 #endif
135 	}
136 	*po = o->next;
137 	xfree(o);
138 }
139