From: Alexandre Ratchov Subject: Re: sndio: show the real device name in server.device control To: tech@openbsd.org Date: Tue, 14 May 2024 07:40:29 +0200 Here's a second (and shorter) version of the diff to add the device names to the sndioctl server.device control. Example: $ sndioctl -i output.level=* output.mute=* server.device=0(azalia0),1(envy0),2(envy1),3(uaudio0),4(uaudio1),5,6,7 Now, sndiod exposes the driver name of the devices that are connected. The plan is to change the low-level drivers to report the chipset, the vendor/product name, the codec models, or whatever appropriate. In summary: - Add a "char display[]" member to the sioctl_desc structure. To do so, we reuse the padding, which allows binaries linked to the old libsndio to use the new libsndio. So this is a shlib_minor bump, allowing to test this diff without rebuilding all audio ports. - The sndiod(8) network protocol gets a new AMSG_CTLSUB op-code to subscribe to the new version of the control descriptions (with the display string). The old op-code remains, which allows systems or VMs with the old libsndio version (or static binaries) to connect to the new sndiod. Compared to the previous diff version: - The SIGHUP handling and the kernel part are gone (already committed). - Showing only present devices was a bad idea (it broke hot-plugging in certain cases), so we retain the current behavior: show all devices, i.e. all sndiod -fF options OK? Index: include/sndio.h =================================================================== RCS file: /cvs/src/include/sndio.h,v diff -u -p -u -p -r1.14 sndio.h --- include/sndio.h 29 Apr 2022 08:30:48 -0000 1.14 +++ include/sndio.h 14 May 2024 05:07:42 -0000 @@ -27,8 +27,17 @@ /* * limits + * + * For now SIOCTL_DISPLAYMAX is 12 byte only. It nicely fits in the + * padding of the sioctl_desc structure: this allows any binary linked + * to the library version with no sioctl_desc->display to work with + * this library version. Currently, any string reported by the lower + * layers fits in the 12-byte buffer. Once larger strings start + * being used (or the ABI changes for any other reason) increase + * SIOCTL_DISPLAYMAX and properly pad the sioctl_desc structure. */ #define SIOCTL_NAMEMAX 12 /* max name length */ +#define SIOCTL_DISPLAYMAX 12 /* max display string length */ /* * private ``handle'' structure @@ -115,7 +124,7 @@ struct sioctl_desc { struct sioctl_node node0; /* affected node */ struct sioctl_node node1; /* dito for SIOCTL_{VEC,LIST,SEL} */ unsigned int maxval; /* max value */ - int __pad[3]; + char display[SIOCTL_DISPLAYMAX]; /* free-format hint */ }; /* Index: lib/libsndio/amsg.h =================================================================== RCS file: /cvs/src/lib/libsndio/amsg.h,v diff -u -p -u -p -r1.15 amsg.h --- lib/libsndio/amsg.h 29 Apr 2022 08:30:48 -0000 1.15 +++ lib/libsndio/amsg.h 14 May 2024 05:07:42 -0000 @@ -46,6 +46,13 @@ * limits */ #define AMSG_CTL_NAMEMAX 16 /* max name length */ +#define AMSG_CTL_DISPLAYMAX 32 /* max display string length */ + +/* + * Size of the struct amsg_ctl_desc expected by clients + * using the AMSG_CTLSUB_OLD request + */ +#define AMSG_OLD_DESC_SIZE 92 /* * WARNING: since the protocol may be simultaneously used by static @@ -69,9 +76,10 @@ struct amsg { #define AMSG_HELLO 10 /* say hello, check versions and so ... */ #define AMSG_BYE 11 /* ask server to drop connection */ #define AMSG_AUTH 12 /* send authentication cookie */ -#define AMSG_CTLSUB 13 /* ondesc/onctl subscription */ +#define AMSG_CTLSUB_OLD 13 /* amsg_ctl_desc with no "display" attribute */ #define AMSG_CTLSET 14 /* set control value */ #define AMSG_CTLSYNC 15 /* end of controls descriptions */ +#define AMSG_CTLSUB 16 /* ondesc/onctl subscription */ uint32_t cmd; uint32_t __pad; union { @@ -151,7 +159,8 @@ struct amsg_ctl_desc { uint16_t addr; /* control address */ uint16_t maxval; uint16_t curval; - uint32_t __pad2[3]; + uint32_t __pad2[4]; + char display[AMSG_CTL_DISPLAYMAX]; /* free-format hint */ }; /* Index: lib/libsndio/shlib_version =================================================================== RCS file: /cvs/src/lib/libsndio/shlib_version,v diff -u -p -u -p -r1.13 shlib_version --- lib/libsndio/shlib_version 29 Apr 2022 08:30:48 -0000 1.13 +++ lib/libsndio/shlib_version 14 May 2024 05:07:42 -0000 @@ -1,2 +1,2 @@ major=7 -minor=2 +minor=3 Index: lib/libsndio/sioctl_aucat.c =================================================================== RCS file: /cvs/src/lib/libsndio/sioctl_aucat.c,v diff -u -p -u -p -r1.1 sioctl_aucat.c --- lib/libsndio/sioctl_aucat.c 26 Feb 2020 13:53:58 -0000 1.1 +++ lib/libsndio/sioctl_aucat.c 14 May 2024 05:07:42 -0000 @@ -87,6 +87,7 @@ sioctl_aucat_rdata(struct sioctl_aucat_h strlcpy(desc.node1.name, c->node1.name, SIOCTL_NAMEMAX); desc.node1.unit = (int16_t)ntohs(c->node1.unit); strlcpy(desc.func, c->func, SIOCTL_NAMEMAX); + strlcpy(desc.display, c->display, SIOCTL_DISPLAYMAX); desc.type = c->type; desc.addr = ntohs(c->addr); desc.maxval = ntohs(c->maxval); Index: lib/libsndio/sioctl_open.3 =================================================================== RCS file: /cvs/src/lib/libsndio/sioctl_open.3,v diff -u -p -u -p -r1.13 sioctl_open.3 --- lib/libsndio/sioctl_open.3 3 May 2022 13:03:30 -0000 1.13 +++ lib/libsndio/sioctl_open.3 14 May 2024 05:07:42 -0000 @@ -168,6 +168,7 @@ struct sioctl_desc { struct sioctl_node node0; /* affected node */ struct sioctl_node node1; /* dito for SIOCTL_{VEC,LIST,SEL} */ unsigned int maxval; /* max value */ + char display[SIOCTL_DISPLAYMAX]; /* free-format hint */ }; .Ed .Pp @@ -238,6 +239,11 @@ The .Fa maxval attribute indicates the maximum value of this control. For boolean control types it is set to 1. +.Pp +The +.Fa display +attribute contains an optional free-format string providing additional +hints about the control, like the hardware model, or the units. .Ss Changing and reading control values Controls are changed with the .Fn sioctl_setval Index: lib/libsndio/sioctl_sun.c =================================================================== RCS file: /cvs/src/lib/libsndio/sioctl_sun.c,v diff -u -p -u -p -r1.2 sioctl_sun.c --- lib/libsndio/sioctl_sun.c 30 Apr 2020 12:30:47 -0000 1.2 +++ lib/libsndio/sioctl_sun.c 14 May 2024 05:07:42 -0000 @@ -53,6 +53,8 @@ struct volume struct sioctl_sun_hdl { struct sioctl_hdl sioctl; + char display[SIOCTL_DISPLAYMAX]; + int display_addr; struct volume output, input; int fd, events; }; @@ -147,6 +149,7 @@ init(struct sioctl_sun_hdl *hdl) {AudioCinputs, AudioNvolume}, {AudioCinputs, AudioNinput} }; + struct audio_device getdev; int i; for (i = 0; i < sizeof(output_names) / sizeof(output_names[0]); i++) { @@ -165,6 +168,13 @@ init(struct sioctl_sun_hdl *hdl) break; } } + + hdl->display_addr = 128; + if (ioctl(hdl->fd, AUDIO_GETDEV, &getdev) == -1) + strlcpy(hdl->display, "unknown", SIOCTL_DISPLAYMAX); + else + strlcpy(hdl->display, getdev.name, SIOCTL_DISPLAYMAX); + DPRINTF("init: server.device: display = %s\n", hdl->display); } static int @@ -407,12 +417,27 @@ static int sioctl_sun_ondesc(struct sioctl_hdl *addr) { struct sioctl_sun_hdl *hdl = (struct sioctl_sun_hdl *)addr; + struct sioctl_desc desc; if (!scanvol(hdl, &hdl->output) || !scanvol(hdl, &hdl->input)) { hdl->sioctl.eof = 1; return 0; } + + /* report "server.device" control */ + memset(&desc, 0, sizeof(struct sioctl_desc)); + desc.type = SIOCTL_SEL; + desc.maxval = 1; + strlcpy(desc.func, "device", SIOCTL_NAMEMAX); + strlcpy(desc.node0.name, "server", SIOCTL_NAMEMAX); + desc.node0.unit = -1; + strlcpy(desc.node1.name, "0", SIOCTL_NAMEMAX); + desc.node1.unit = -1; + strlcpy(desc.display, hdl->display, SIOCTL_DISPLAYMAX); + desc.addr = hdl->display_addr; + _sioctl_ondesc_cb(&hdl->sioctl, &desc, 1); + _sioctl_ondesc_cb(&hdl->sioctl, NULL, 0); return 1; } Index: usr.bin/sndiod/dev.c =================================================================== RCS file: /cvs/src/usr.bin/sndiod/dev.c,v diff -u -p -u -p -r1.113 dev.c --- usr.bin/sndiod/dev.c 6 May 2024 05:37:26 -0000 1.113 +++ usr.bin/sndiod/dev.c 14 May 2024 05:07:43 -0000 @@ -1054,6 +1054,8 @@ dev_allocbufs(struct dev *d) int dev_open(struct dev *d) { + struct opt *o; + d->mode = d->reqmode; d->round = d->reqround; d->bufsz = d->reqbufsz; @@ -1076,6 +1078,18 @@ dev_open(struct dev *d) return 0; d->pstate = DEV_INIT; + + /* add server.device if device is opened after opt_ref() call */ + for (o = opt_list; o != NULL; o = o->next) { + if (o->refcnt > 0 && !ctl_find(CTL_OPT_DEV, o, d)) { + ctl_new(CTL_OPT_DEV, o, d, + CTL_SEL, dev_getdisplay(d), + o->name, "server", -1, "device", + d->name, -1, 1, o->dev == d); + d->refcnt++; + } + } + return 1; } @@ -1150,6 +1164,14 @@ dev_freebufs(struct dev *d) void dev_close(struct dev *d) { + struct opt *o; + + /* remove server.device entries */ + for (o = opt_list; o != NULL; o = o->next) { + if (ctl_del(CTL_OPT_DEV, o, d)) + d->refcnt--; + } + d->pstate = DEV_CFG; dev_sio_close(d); dev_freebufs(d); @@ -1776,7 +1798,7 @@ slot_new(struct opt *opt, unsigned int i s->opt = opt; slot_ctlname(s, ctl_name, CTL_NAMEMAX); ctl_new(CTL_SLOT_LEVEL, s, NULL, - CTL_NUM, "app", ctl_name, -1, "level", + CTL_NUM, "", "app", ctl_name, -1, "level", NULL, -1, 127, s->vol); found: @@ -2290,6 +2312,14 @@ ctlslot_visible(struct ctlslot *s, struc return 1; switch (c->scope) { case CTL_HW: + /* + * Disable hardware's server.device control as its + * replaced by sndiod's one + */ + if (strcmp(c->node0.name, "server") == 0 && + strcmp(c->func, "device") == 0) + return 0; + /* FALLTHROUHG */ case CTL_DEV_MASTER: return (s->opt->dev == c->u.any.arg0); case CTL_OPT_DEV: @@ -2405,6 +2435,11 @@ ctl_log(struct ctl *c) default: log_puts("unknown"); } + if (c->display[0] != 0) { + log_puts(" ("); + log_puts(c->display); + log_puts(")"); + } } int @@ -2467,7 +2502,7 @@ ctl_setval(struct ctl *c, int val) */ struct ctl * ctl_new(int scope, void *arg0, void *arg1, - int type, char *gstr, + int type, char *display, char *gstr, char *str0, int unit0, char *func, char *str1, int unit1, int maxval, int val) { @@ -2491,6 +2526,7 @@ ctl_new(int scope, void *arg0, void *arg c->type = type; strlcpy(c->func, func, CTL_NAMEMAX); strlcpy(c->group, gstr, CTL_NAMEMAX); + strlcpy(c->display, display, CTL_DISPLAYMAX); strlcpy(c->node0.name, str0, CTL_NAMEMAX); c->node0.unit = unit0; if (c->type == CTL_VEC || c->type == CTL_LIST || c->type == CTL_SEL) { @@ -2637,6 +2673,54 @@ ctl_del(int scope, void *arg0, void *arg } void +dev_setdisplay(struct dev *d, char *display) +{ + struct ctl *c; + struct ctlslot *s; + int changed, i; + + changed = 0; + for (c = ctl_list; c != NULL; c = c->next) { + if (c->scope != CTL_OPT_DEV || + c->u.opt_dev.dev != d || + strcmp(c->display, display) == 0) + continue; + strlcpy(c->display, display, CTL_DISPLAYMAX); + c->desc_mask = ~0; + changed = 1; + } + + if (changed) { + for (s = ctlslot_array, i = 0; i < DEV_NCTLSLOT; i++, s++) { + if (s->ops == NULL) + continue; + if (s->opt->dev == d) + s->ops->sync(s->arg); + } + } +} + +char * +dev_getdisplay(struct dev *d) +{ + struct ctl *c; + char *display; + + display = ""; + for (c = ctl_list; c != NULL; c = c->next) { + if (c->scope == CTL_HW && + c->u.hw.dev == d && + c->type == CTL_SEL && + strcmp(c->group, d->name) == 0 && + strcmp(c->node0.name, "server") == 0 && + strcmp(c->func, "device") == 0 && + c->curval == 1) + display = c->display; + } + return display; +} + +void dev_ctlsync(struct dev *d) { struct ctl *c; @@ -2668,7 +2752,7 @@ dev_ctlsync(struct dev *d) } d->master_enabled = 1; ctl_new(CTL_DEV_MASTER, d, NULL, - CTL_NUM, d->name, "output", -1, "level", + CTL_NUM, "", d->name, "output", -1, "level", NULL, -1, 127, d->master); } Index: usr.bin/sndiod/dev.h =================================================================== RCS file: /cvs/src/usr.bin/sndiod/dev.h,v diff -u -p -u -p -r1.44 dev.h --- usr.bin/sndiod/dev.h 22 Apr 2024 10:39:51 -0000 1.44 +++ usr.bin/sndiod/dev.h 14 May 2024 05:07:43 -0000 @@ -155,9 +155,11 @@ struct ctl { } u; unsigned int addr; /* slot side control address */ -#define CTL_NAMEMAX 16 /* max name length */ +#define CTL_NAMEMAX 12 /* max name length */ +#define CTL_DISPLAYMAX 24 /* max name length */ char func[CTL_NAMEMAX]; /* parameter function name */ char group[CTL_NAMEMAX]; /* group aka namespace */ + char display[CTL_DISPLAYMAX]; /* free-format hint */ struct ctl_node { char name[CTL_NAMEMAX]; /* stream name */ int unit; @@ -351,7 +353,7 @@ void slot_detach(struct slot *); */ struct ctl *ctl_new(int, void *, void *, - int, char *, char *, int, char *, char *, int, int, int); + int, char *, char *, char *, int, char *, char *, int, int, int); int ctl_del(int, void *, void *); void ctl_log(struct ctl *); int ctl_setval(struct ctl *c, int val); @@ -367,6 +369,8 @@ struct ctl *ctlslot_lookup(struct ctlslo void ctlslot_update(struct ctlslot *); void dev_label(struct dev *, int); +void dev_setdisplay(struct dev *, char *); +char *dev_getdisplay(struct dev *); void dev_ctlsync(struct dev *); #endif /* !defined(DEV_H) */ Index: usr.bin/sndiod/dev_sioctl.c =================================================================== RCS file: /cvs/src/usr.bin/sndiod/dev_sioctl.c,v diff -u -p -u -p -r1.8 dev_sioctl.c --- usr.bin/sndiod/dev_sioctl.c 22 Apr 2024 10:43:55 -0000 1.8 +++ usr.bin/sndiod/dev_sioctl.c 14 May 2024 05:07:43 -0000 @@ -70,7 +70,7 @@ dev_sioctl_ondesc(void *arg, struct sioc } ctl_new(CTL_HW, d, &desc->addr, - desc->type, group, + desc->type, desc->display, group, desc->node0.name, desc->node0.unit, desc->func, desc->node1.name, desc->node1.unit, desc->maxval, val); } @@ -91,7 +91,8 @@ dev_sioctl_onval(void *arg, unsigned int } for (c = ctl_list; c != NULL; c = c->next) { - if (c->scope != CTL_HW || c->u.hw.addr != addr) + if (c->scope != CTL_HW || c->u.hw.dev != d || + c->u.hw.addr != addr) continue; if (log_level >= 2) { @@ -103,6 +104,14 @@ dev_sioctl_onval(void *arg, unsigned int c->val_mask = ~0U; c->curval = val; + + /* if hardware's server.device changed, update name */ + if (c->type == CTL_SEL && + strcmp(c->group, d->name) == 0 && + strcmp(c->node0.name, "server") == 0 && + strcmp(c->func, "device") == 0 && + c->curval == 1) + dev_setdisplay(d, c->display); } } Index: usr.bin/sndiod/opt.c =================================================================== RCS file: /cvs/src/usr.bin/sndiod/opt.c,v diff -u -p -u -p -r1.10 opt.c --- usr.bin/sndiod/opt.c 22 Apr 2024 10:42:04 -0000 1.10 +++ usr.bin/sndiod/opt.c 14 May 2024 05:07:43 -0000 @@ -346,15 +346,6 @@ opt_del(struct opt *o) void opt_init(struct opt *o) { - struct dev *d; - - if (strcmp(o->name, o->dev->name) != 0) { - for (d = dev_list; d != NULL; d = d->next) { - ctl_new(CTL_OPT_DEV, o, d, - CTL_SEL, o->name, "server", -1, "device", - d->name, -1, 1, o->dev == d); - } - } } void @@ -499,6 +490,17 @@ opt_ref(struct opt *o) /* if device changed, move everything to the new one */ if (d != o->dev) opt_setdev(o, d); + + /* create server.device control */ + for (d = dev_list; d != NULL; d = d->next) { + d->refcnt++; + if (d->pstate == DEV_CFG) + dev_open(d); + ctl_new(CTL_OPT_DEV, o, d, + CTL_SEL, dev_getdisplay(d), + o->name, "server", -1, "device", + d->name, -1, 1, o->dev == d); + } } } @@ -512,7 +514,15 @@ opt_ref(struct opt *o) void opt_unref(struct opt *o) { + struct dev *d; + o->refcnt--; - if (o->refcnt == 0) + if (o->refcnt == 0) { + /* delete server.device control */ + for (d = dev_list; d != NULL; d = d->next) { + if (ctl_del(CTL_OPT_DEV, o, d)) + dev_unref(d); + } dev_unref(o->dev); + } } Index: usr.bin/sndiod/sock.c =================================================================== RCS file: /cvs/src/usr.bin/sndiod/sock.c,v diff -u -p -u -p -r1.47 sock.c --- usr.bin/sndiod/sock.c 26 Dec 2022 19:16:03 -0000 1.47 +++ usr.bin/sndiod/sock.c 14 May 2024 05:07:43 -0000 @@ -33,7 +33,7 @@ #include "sock.h" #include "utils.h" -#define SOCK_CTLDESC_SIZE 16 /* number of entries in s->ctldesc */ +#define SOCK_CTLDESC_SIZE 0x800 /* size of s->ctldesc */ void sock_log(struct sock *); void sock_close(struct sock *); @@ -626,8 +626,7 @@ sock_wdata(struct sock *f) else if (f->midi) data = abuf_rgetblk(&f->midi->obuf, &count); else { - data = (unsigned char *)f->ctldesc + - (f->wsize - f->wtodo); + data = f->ctldesc + (f->wsize - f->wtodo); count = f->wtodo; } if (count > f->wtodo) @@ -961,8 +960,7 @@ sock_hello(struct sock *f) } return 0; } - f->ctldesc = xmalloc(SOCK_CTLDESC_SIZE * - sizeof(struct amsg_ctl_desc)); + f->ctldesc = xmalloc(SOCK_CTLDESC_SIZE); f->ctlops = 0; f->ctlsyncpending = 0; return 1; @@ -989,8 +987,10 @@ sock_execmsg(struct sock *f) struct amsg *m = &f->rmsg; unsigned char *data; int size, ctl; + int cmd; - switch (ntohl(m->cmd)) { + cmd = ntohl(m->cmd); + switch (cmd) { case AMSG_DATA: #ifdef DEBUG if (log_level >= 4) { @@ -1284,6 +1284,7 @@ sock_execmsg(struct sock *f) dev_midi_vol(s->opt->dev, s); ctl_onval(CTL_SLOT_LEVEL, s, NULL, ctl); break; + case AMSG_CTLSUB_OLD: case AMSG_CTLSUB: #ifdef DEBUG if (log_level >= 3) { @@ -1316,6 +1317,9 @@ sock_execmsg(struct sock *f) } f->ctlops |= SOCK_CTLDESC; f->ctlsyncpending = 1; + f->ctl_desc_size = (cmd == AMSG_CTLSUB) ? + sizeof(struct amsg_ctl_desc) : + AMSG_OLD_DESC_SIZE; } } else f->ctlops &= ~SOCK_CTLDESC; @@ -1604,7 +1608,6 @@ sock_buildmsg(struct sock *f) * searching for the {desc,val}_mask bits */ if (f->ctlslot && (f->ctlops & SOCK_CTLDESC)) { - desc = f->ctldesc; mask = f->ctlslot->self; size = 0; pc = &ctl_list; @@ -1614,9 +1617,9 @@ sock_buildmsg(struct sock *f) pc = &c->next; continue; } - if (size == SOCK_CTLDESC_SIZE * - sizeof(struct amsg_ctl_desc)) + if (size + f->ctl_desc_size > SOCK_CTLDESC_SIZE) break; + desc = (struct amsg_ctl_desc *)(f->ctldesc + size); c->desc_mask &= ~mask; c->val_mask &= ~mask; type = ctlslot_visible(f->ctlslot, c) ? @@ -1633,8 +1636,14 @@ sock_buildmsg(struct sock *f) desc->addr = htons(c->addr); desc->maxval = htons(c->maxval); desc->curval = htons(c->curval); - size += sizeof(struct amsg_ctl_desc); - desc++; + + /* old clients don't have the 'display' member */ + if (f->ctl_desc_size >= offsetof(struct amsg_ctl_desc, + display) + AMSG_CTL_DISPLAYMAX) { + strlcpy(desc->display, c->display, AMSG_CTL_DISPLAYMAX); + } + + size += f->ctl_desc_size; /* if this is a deleted entry unref it */ if (type == CTL_NONE) { Index: usr.bin/sndiod/sock.h =================================================================== RCS file: /cvs/src/usr.bin/sndiod/sock.h,v diff -u -p -u -p -r1.7 sock.h --- usr.bin/sndiod/sock.h 26 Apr 2020 14:13:22 -0000 1.7 +++ usr.bin/sndiod/sock.h 14 May 2024 05:07:43 -0000 @@ -59,7 +59,8 @@ struct sock { struct midi *midi; /* midi endpoint */ struct port *port; /* midi port */ struct ctlslot *ctlslot; - struct amsg_ctl_desc *ctldesc; /* temporary buffer */ + unsigned char *ctldesc; /* temporary buffer */ + size_t ctl_desc_size; /* size of client amsg_ctl_desc */ #define SOCK_CTLDESC 1 /* dump desc and send changes */ #define SOCK_CTLVAL 2 /* send value changes */ unsigned int ctlops; /* bitmap of above */ Index: usr.bin/sndioctl/sndioctl.c =================================================================== RCS file: /cvs/src/usr.bin/sndioctl/sndioctl.c,v diff -u -p -u -p -r1.20 sndioctl.c --- usr.bin/sndioctl/sndioctl.c 22 Apr 2024 10:49:01 -0000 1.20 +++ usr.bin/sndioctl/sndioctl.c 14 May 2024 05:07:43 -0000 @@ -47,6 +47,7 @@ int matchpar(struct info *, char *, int) int matchent(struct info *, char *, int); int ismono(struct info *); void print_node(struct sioctl_node *, int); +void print_display(struct info *); void print_desc(struct info *, int); void print_num(struct info *); void print_ent(struct info *, char *); @@ -310,6 +311,9 @@ ismono(struct info *g) continue; if (e1->curval != e2->curval) return 0; + if (strcmp(e1->desc.display, + e2->desc.display) != 0) + return 0; } } } @@ -330,6 +334,28 @@ print_node(struct sioctl_node *c, int mo } /* + * print display string, with '(' and ')' and non-printable chars removed + * in order to match command syntax + */ +void +print_display(struct info *p) +{ + char buf[SIOCTL_NAMEMAX], *s, *d; + unsigned int c; + + s = p->desc.display; + d = buf; + while ((c = *s++) != 0) { + if (c == '(' || c == ')' || c < ' ') + continue; + *d++ = c; + } + *d = 0; + if (buf[0] != 0) + printf("(%s)", buf); +} + +/* * print info about the parameter */ void @@ -342,6 +368,7 @@ print_desc(struct info *p, int mono) case SIOCTL_NUM: case SIOCTL_SW: printf("*"); + print_display(p); break; case SIOCTL_SEL: case SIOCTL_VEC: @@ -359,6 +386,8 @@ print_desc(struct info *p, int mono) print_node(&e->desc.node1, mono); if (p->desc.type != SIOCTL_SEL) printf(":*"); + if (e->desc.display[0] != 0) + print_display(e); more = 1; } } @@ -404,6 +433,7 @@ print_ent(struct info *e, char *comment) case SIOCTL_NUM: print_num(e); } + print_display(e); if (comment) printf("\t# %s", comment); printf("\n"); @@ -422,6 +452,7 @@ print_val(struct info *p, int mono) case SIOCTL_NUM: case SIOCTL_SW: print_num(p); + print_display(p); break; case SIOCTL_SEL: case SIOCTL_VEC: @@ -439,6 +470,7 @@ print_val(struct info *p, int mono) if (more) printf(","); print_node(&e->desc.node1, mono); + print_display(e); more = 1; } } else { @@ -447,6 +479,7 @@ print_val(struct info *p, int mono) print_node(&e->desc.node1, mono); printf(":"); print_num(e); + print_display(e); more = 1; } } @@ -631,6 +664,7 @@ dump(void) print_node(&i->desc.node1, 0); printf(":0..%d (%u)", i->desc.maxval, i->curval); } + print_display(i); printf("\n"); } } @@ -751,6 +785,12 @@ cmd(char *line) e->mode = mode; nent++; } + } + } + if (*pos == '(') { + while (*pos != 0) { + if (*pos++ == ')') + break; } } if (nent == 0) {