Re: [hackers] [slstatus][PATCH] Use the sioctl_open(3) OpenBSD API to access audio controls

2020-11-30 Thread Aaron Marcher

Hi,

thanks for the great work! These changes are upstream now.

Regards,
Aaron

On 20-05-09 Sat, Ingo Feinerer wrote:

Starting with OpenBSD 6.7 regular users cannot access raw audio devices
anymore, for improved security. Instead use the sioctl_open(3) API to
access and manipulate audio controls exposed by sndiod(8). On the first
call a permanent connection is established with the running sndiod
daemon, and call-back functions are registered which are triggered when
audio controls are changed (e.g., a USB headset is attached) or when the
volume is modified. On subsequent calls we poll for changes; if there
are no volume changes this costs virtually nothing.

Joint work with Alexandre Ratchov.
---
LICENSE |   3 +-
components/volume.c | 210 +---
config.def.h|   1 +
config.mk   |   1 +
4 files changed, 163 insertions(+), 52 deletions(-)

diff --git a/LICENSE b/LICENSE
index 0eec587..c61489f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -19,7 +19,8 @@ Copyright 2018 David Demelier 
Copyright 2018-2019 Michael Buch 
Copyright 2018 Ian Remmler 
Copyright 2016-2019 Joerg Jung 
-Copyright 2019 Ingo Feinerer 
+Copyright 2019-2020 Ingo Feinerer 
+Copyright 2020 Alexandre Ratchov 

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/components/volume.c b/components/volume.c
index 61cec90..b6665da 100644
--- a/components/volume.c
+++ b/components/volume.c
@@ -8,69 +8,177 @@
#include "../util.h"

#if defined(__OpenBSD__)
-   #include 
+   #include 
+   #include 
+   #include 
+   #include 
+
+   struct control {
+   LIST_ENTRY(control) next;
+   unsigned intaddr;
+   #define CTRL_NONE   0
+   #define CTRL_LEVEL  1
+   #define CTRL_MUTE   2
+   unsigned inttype;
+   unsigned intmaxval;
+   unsigned intval;
+   };
+
+   static LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(controls);
+   static struct pollfd *pfds;
+   static struct sioctl_hdl *hdl;
+   static int initialized;
+
+   /*
+* Call-back to obtain the description of all audio controls.
+*/
+   static void
+   ondesc(void *unused, struct sioctl_desc *desc, int val)
+   {
+   struct control *c, *ctmp;
+   unsigned int type = CTRL_NONE;
+
+   if (desc == NULL)
+   return;
+
+   /* Delete existing audio control with the same address. */
+   LIST_FOREACH_SAFE(c, &controls, next, ctmp) {
+   if (desc->addr == c->addr) {
+   LIST_REMOVE(c, next);
+   free(c);
+   break;
+   }
+   }
+
+   /* Only match output.level and output.mute audio controls. */
+   if (desc->group[0] != 0 ||
+   strcmp(desc->node0.name, "output") != 0)
+   return;
+   if (desc->type == SIOCTL_NUM &&
+   strcmp(desc->func, "level") == 0)
+   type = CTRL_LEVEL;
+   else if (desc->type == SIOCTL_SW &&
+strcmp(desc->func, "mute") == 0)
+   type = CTRL_MUTE;
+   else
+   return;
+
+   c = malloc(sizeof(struct control));
+   if (c == NULL) {
+   warn("sndio: failed to allocate audio control\n");
+   return;
+   }
+
+   c->addr = desc->addr;
+   c->type = type;
+   c->maxval = desc->maxval;
+   c->val = val;
+   LIST_INSERT_HEAD(&controls, c, next);
+   }
+
+   /*
+* Call-back invoked whenever an audio control changes.
+*/
+   static void
+   onval(void *unused, unsigned int addr, unsigned int val)
+   {
+   struct control *c;
+
+   LIST_FOREACH(c, &controls, next) {
+   if (c->addr == addr)
+   break;
+   }
+   c->val = val;
+   }
+
+   static void
+   cleanup(void)
+   {
+   struct control *c;
+
+   if (hdl) {
+   sioctl_close(hdl);
+   hdl = NULL;
+   }
+
+   free(pfds);
+   pfds = NULL;
+
+   while (!LIST_EMPTY(&controls)) {
+   c = LIST_FIRST(&controls);
+   LIST_REMOVE(c, next);
+   free(c);
+   }
+   }
+
+   static int
+   init(void)
+   {
+   hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0);
+   if (hdl == NULL) {
+ 

[hackers] [slstatus][PATCH] Use the sioctl_open(3) OpenBSD API to access audio controls

2020-05-09 Thread Ingo Feinerer
Starting with OpenBSD 6.7 regular users cannot access raw audio devices
anymore, for improved security. Instead use the sioctl_open(3) API to
access and manipulate audio controls exposed by sndiod(8). On the first
call a permanent connection is established with the running sndiod
daemon, and call-back functions are registered which are triggered when
audio controls are changed (e.g., a USB headset is attached) or when the
volume is modified. On subsequent calls we poll for changes; if there
are no volume changes this costs virtually nothing.

Joint work with Alexandre Ratchov.
---
 LICENSE |   3 +-
 components/volume.c | 210 +---
 config.def.h|   1 +
 config.mk   |   1 +
 4 files changed, 163 insertions(+), 52 deletions(-)

diff --git a/LICENSE b/LICENSE
index 0eec587..c61489f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -19,7 +19,8 @@ Copyright 2018 David Demelier 
 Copyright 2018-2019 Michael Buch 
 Copyright 2018 Ian Remmler 
 Copyright 2016-2019 Joerg Jung 
-Copyright 2019 Ingo Feinerer 
+Copyright 2019-2020 Ingo Feinerer 
+Copyright 2020 Alexandre Ratchov 
 
 Permission to use, copy, modify, and/or distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
diff --git a/components/volume.c b/components/volume.c
index 61cec90..b6665da 100644
--- a/components/volume.c
+++ b/components/volume.c
@@ -8,69 +8,177 @@
 #include "../util.h"
 
 #if defined(__OpenBSD__)
-   #include 
+   #include 
+   #include 
+   #include 
+   #include 
+
+   struct control {
+   LIST_ENTRY(control) next;
+   unsigned intaddr;
+   #define CTRL_NONE   0
+   #define CTRL_LEVEL  1
+   #define CTRL_MUTE   2
+   unsigned inttype;
+   unsigned intmaxval;
+   unsigned intval;
+   };
+
+   static LIST_HEAD(, control) controls = LIST_HEAD_INITIALIZER(controls);
+   static struct pollfd *pfds;
+   static struct sioctl_hdl *hdl;
+   static int initialized;
+
+   /*
+* Call-back to obtain the description of all audio controls.
+*/
+   static void
+   ondesc(void *unused, struct sioctl_desc *desc, int val)
+   {
+   struct control *c, *ctmp;
+   unsigned int type = CTRL_NONE;
+
+   if (desc == NULL)
+   return;
+
+   /* Delete existing audio control with the same address. */
+   LIST_FOREACH_SAFE(c, &controls, next, ctmp) {
+   if (desc->addr == c->addr) {
+   LIST_REMOVE(c, next);
+   free(c);
+   break;
+   }
+   }
+
+   /* Only match output.level and output.mute audio controls. */
+   if (desc->group[0] != 0 ||
+   strcmp(desc->node0.name, "output") != 0)
+   return;
+   if (desc->type == SIOCTL_NUM &&
+   strcmp(desc->func, "level") == 0)
+   type = CTRL_LEVEL;
+   else if (desc->type == SIOCTL_SW &&
+strcmp(desc->func, "mute") == 0)
+   type = CTRL_MUTE;
+   else
+   return;
+
+   c = malloc(sizeof(struct control));
+   if (c == NULL) {
+   warn("sndio: failed to allocate audio control\n");
+   return;
+   }
+
+   c->addr = desc->addr;
+   c->type = type;
+   c->maxval = desc->maxval;
+   c->val = val;
+   LIST_INSERT_HEAD(&controls, c, next);
+   }
+
+   /*
+* Call-back invoked whenever an audio control changes.
+*/
+   static void
+   onval(void *unused, unsigned int addr, unsigned int val)
+   {
+   struct control *c;
+
+   LIST_FOREACH(c, &controls, next) {
+   if (c->addr == addr)
+   break;
+   }
+   c->val = val;
+   }
+
+   static void
+   cleanup(void)
+   {
+   struct control *c;
+
+   if (hdl) {
+   sioctl_close(hdl);
+   hdl = NULL;
+   }
+
+   free(pfds);
+   pfds = NULL;
+
+   while (!LIST_EMPTY(&controls)) {
+   c = LIST_FIRST(&controls);
+   LIST_REMOVE(c, next);
+   free(c);
+   }
+   }
+
+   static int
+   init(void)
+   {
+   hdl = sioctl_open(SIO_DEVANY, SIOCTL_READ, 0);
+   if (hdl == NULL) {
+   warn("sndio: cannot open device");
+   goto failed;
+