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