Re: massage volume control task
On 17 Jan 2015, at 11:06, Jim Smith j...@insec.sh wrote: On 2 Jan 2015, at 4:15 pm, David Gwynne da...@gwynne.id.au wrote: can someone test this? it allocates storage for the volume change details rather than cast arguments to a single global task. adds some safety while there if audio0 is a hotplug device. ok? The keyboard audio controls on my X120e following -current work same as before with this diff applied. cool, thank you. unless anyone objects im going to commit this tomorrow morning (tues 20th of jan around 11am, gmt+10). cheers, dlg Index: audio.c === RCS file: /cvs/src/sys/dev/audio.c,v retrieving revision 1.125 diff -u -p -r1.125 audio.c --- audio.c 19 Dec 2014 22:44:58 - 1.125 +++ audio.c 2 Jan 2015 06:08:39 - @@ -465,11 +465,6 @@ audioattach(struct device *parent, struc } DPRINTF((audio_attach: inputs ports=0x%x, output ports=0x%x\n, sc-sc_inports.allports, sc-sc_outports.allports)); - -#if NWSKBD 0 -task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, NULL, -NULL); -#endif /* NWSKBD 0 */ } int @@ -3432,27 +3427,39 @@ filt_audiowrite(struct knote *kn, long h } #if NWSKBD 0 +struct wskbd_vol_change { +struct task t; +long dir; +long out; +}; + int wskbd_set_mixervolume(long dir, long out) { struct audio_softc *sc; +struct wskbd_vol_change *ch; if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { DPRINTF((wskbd_set_mixervolume: audio_cd\n)); return (ENXIO); } -task_del(systq, sc-sc_mixer_task); -task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, -(void *)dir, (void *)out); -task_add(systq, sc-sc_mixer_task); +ch = malloc(sizeof(*ch), M_TEMP, M_NOWAIT); +if (ch == NULL) +return (ENOMEM); + +task_set(ch-t, wskbd_set_mixervolume_callback, ch, NULL); +ch-dir = dir; +ch-out = out; +task_add(systq, ch-t); return (0); } void -wskbd_set_mixervolume_callback(void *arg1, void *arg2) +wskbd_set_mixervolume_callback(void *xch, void *null) { +struct wskbd_vol_change *ch = xch; struct audio_softc *sc; struct au_mixer_ports *ports; mixer_devinfo_t mi; @@ -3461,19 +3468,19 @@ wskbd_set_mixervolume_callback(void *arg u_int gain; int error; -if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { -DPRINTF((%s: audio_cd\n, __func__)); -return; -} +dir = ch-dir; +out = ch-out; +free(ch, M_TEMP, sizeof(*ch)); -dir = (long)arg1; -out = (long)arg2; +sc = (struct audio_softc *)device_lookup(audio_cd, 0); +if (sc == NULL) +return; ports = out ? sc-sc_outports : sc-sc_inports; if (ports-master == -1) { DPRINTF((%s: master == -1\n, __func__)); -return; +goto done; } if (dir == 0) { @@ -3482,7 +3489,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_get_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_get_mute: %d\n, __func__, error)); -return; +goto done; } mute = !mute; @@ -3490,7 +3497,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_set_mute: %d\n, __func__, error)); -return; +goto done; } } else { /* Raise or lower volume */ @@ -3499,7 +3506,7 @@ wskbd_set_mixervolume_callback(void *arg error = sc-hw_if-query_devinfo(sc-hw_hdl, mi); if (error != 0) { DPRINTF((%s: query_devinfo: %d\n, __func__, error)); -return; +goto done; } au_get_gain(sc, ports, gain, balance); @@ -3512,8 +3519,11 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_gain(sc, ports, gain, balance); if (error != 0) { DPRINTF((%s: au_set_gain: %d\n, __func__, error)); -return; +goto done; } } + +done: +device_unref(sc-dev); } #endif /* NWSKBD 0 */
Re: massage volume control task
On 2 Jan 2015, at 4:15 pm, David Gwynne da...@gwynne.id.au wrote: can someone test this? it allocates storage for the volume change details rather than cast arguments to a single global task. adds some safety while there if audio0 is a hotplug device. ok? The keyboard audio controls on my X120e following -current work same as before with this diff applied. Index: audio.c === RCS file: /cvs/src/sys/dev/audio.c,v retrieving revision 1.125 diff -u -p -r1.125 audio.c --- audio.c 19 Dec 2014 22:44:58 - 1.125 +++ audio.c 2 Jan 2015 06:08:39 - @@ -465,11 +465,6 @@ audioattach(struct device *parent, struc } DPRINTF((audio_attach: inputs ports=0x%x, output ports=0x%x\n, sc-sc_inports.allports, sc-sc_outports.allports)); - -#if NWSKBD 0 - task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, NULL, - NULL); -#endif /* NWSKBD 0 */ } int @@ -3432,27 +3427,39 @@ filt_audiowrite(struct knote *kn, long h } #if NWSKBD 0 +struct wskbd_vol_change { + struct task t; + long dir; + long out; +}; + int wskbd_set_mixervolume(long dir, long out) { struct audio_softc *sc; + struct wskbd_vol_change *ch; if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { DPRINTF((wskbd_set_mixervolume: audio_cd\n)); return (ENXIO); } - task_del(systq, sc-sc_mixer_task); - task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, - (void *)dir, (void *)out); - task_add(systq, sc-sc_mixer_task); + ch = malloc(sizeof(*ch), M_TEMP, M_NOWAIT); + if (ch == NULL) + return (ENOMEM); + + task_set(ch-t, wskbd_set_mixervolume_callback, ch, NULL); + ch-dir = dir; + ch-out = out; + task_add(systq, ch-t); return (0); } void -wskbd_set_mixervolume_callback(void *arg1, void *arg2) +wskbd_set_mixervolume_callback(void *xch, void *null) { + struct wskbd_vol_change *ch = xch; struct audio_softc *sc; struct au_mixer_ports *ports; mixer_devinfo_t mi; @@ -3461,19 +3468,19 @@ wskbd_set_mixervolume_callback(void *arg u_int gain; int error; - if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { - DPRINTF((%s: audio_cd\n, __func__)); - return; - } + dir = ch-dir; + out = ch-out; + free(ch, M_TEMP, sizeof(*ch)); - dir = (long)arg1; - out = (long)arg2; + sc = (struct audio_softc *)device_lookup(audio_cd, 0); + if (sc == NULL) + return; ports = out ? sc-sc_outports : sc-sc_inports; if (ports-master == -1) { DPRINTF((%s: master == -1\n, __func__)); - return; + goto done; } if (dir == 0) { @@ -3482,7 +3489,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_get_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_get_mute: %d\n, __func__, error)); - return; + goto done; } mute = !mute; @@ -3490,7 +3497,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_set_mute: %d\n, __func__, error)); - return; + goto done; } } else { /* Raise or lower volume */ @@ -3499,7 +3506,7 @@ wskbd_set_mixervolume_callback(void *arg error = sc-hw_if-query_devinfo(sc-hw_hdl, mi); if (error != 0) { DPRINTF((%s: query_devinfo: %d\n, __func__, error)); - return; + goto done; } au_get_gain(sc, ports, gain, balance); @@ -3512,8 +3519,11 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_gain(sc, ports, gain, balance); if (error != 0) { DPRINTF((%s: au_set_gain: %d\n, __func__, error)); - return; + goto done; } } + +done: + device_unref(sc-dev); } #endif /* NWSKBD 0 */
Re: massage volume control task
On 3 Jan 2015, at 9:35 am, David Gwynne da...@gwynne.id.au wrote: On 2 Jan 2015, at 9:55 pm, Mark Kettenis mark.kette...@xs4all.nl wrote: Date: Fri, 2 Jan 2015 16:15:07 +1000 From: David Gwynne da...@gwynne.id.au can someone test this? it allocates storage for the volume change details rather than cast arguments to a single global task. adds some safety while there if audio0 is a hotplug device. ok? The problem with this approach is that things silently fail when memory allocation fails. Exactly the problem that workq_add_task() had. Perhaps the best thing is to store the event in the softc, although then you'd probably need some locking to make sure the task sees a consistent dir/out pair. is silently fail a pun here? you can lose events either way. if you get more than one keypress before the task runs, you'll lose. if you are in a situation where you cant allocate memory, you lose. i think the code generally is bogus so im trying to do as little as possible to it. the more i look at it the more i want to just remove it. its been unreliable in all incarnations. did anyone try this diff? dlg Index: audio.c === RCS file: /cvs/src/sys/dev/audio.c,v retrieving revision 1.125 diff -u -p -r1.125 audio.c --- audio.c 19 Dec 2014 22:44:58 - 1.125 +++ audio.c 2 Jan 2015 06:08:39 - @@ -465,11 +465,6 @@ audioattach(struct device *parent, struc } DPRINTF((audio_attach: inputs ports=0x%x, output ports=0x%x\n, sc-sc_inports.allports, sc-sc_outports.allports)); - -#if NWSKBD 0 - task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, NULL, - NULL); -#endif /* NWSKBD 0 */ } int @@ -3432,27 +3427,39 @@ filt_audiowrite(struct knote *kn, long h } #if NWSKBD 0 +struct wskbd_vol_change { + struct task t; + long dir; + long out; +}; + int wskbd_set_mixervolume(long dir, long out) { struct audio_softc *sc; + struct wskbd_vol_change *ch; if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { DPRINTF((wskbd_set_mixervolume: audio_cd\n)); return (ENXIO); } - task_del(systq, sc-sc_mixer_task); - task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, - (void *)dir, (void *)out); - task_add(systq, sc-sc_mixer_task); + ch = malloc(sizeof(*ch), M_TEMP, M_NOWAIT); + if (ch == NULL) + return (ENOMEM); + + task_set(ch-t, wskbd_set_mixervolume_callback, ch, NULL); + ch-dir = dir; + ch-out = out; + task_add(systq, ch-t); return (0); } void -wskbd_set_mixervolume_callback(void *arg1, void *arg2) +wskbd_set_mixervolume_callback(void *xch, void *null) { + struct wskbd_vol_change *ch = xch; struct audio_softc *sc; struct au_mixer_ports *ports; mixer_devinfo_t mi; @@ -3461,19 +3468,19 @@ wskbd_set_mixervolume_callback(void *arg u_int gain; int error; - if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { - DPRINTF((%s: audio_cd\n, __func__)); - return; - } + dir = ch-dir; + out = ch-out; + free(ch, M_TEMP, sizeof(*ch)); - dir = (long)arg1; - out = (long)arg2; + sc = (struct audio_softc *)device_lookup(audio_cd, 0); + if (sc == NULL) + return; ports = out ? sc-sc_outports : sc-sc_inports; if (ports-master == -1) { DPRINTF((%s: master == -1\n, __func__)); - return; + goto done; } if (dir == 0) { @@ -3482,7 +3489,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_get_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_get_mute: %d\n, __func__, error)); - return; + goto done; } mute = !mute; @@ -3490,7 +3497,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_set_mute: %d\n, __func__, error)); - return; + goto done; } } else { /* Raise or lower volume */ @@ -3499,7 +3506,7 @@ wskbd_set_mixervolume_callback(void *arg error = sc-hw_if-query_devinfo(sc-hw_hdl, mi); if (error != 0) { DPRINTF((%s: query_devinfo: %d\n, __func__, error)); - return; + goto done; } au_get_gain(sc, ports, gain, balance); @@ -3512,8 +3519,11 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_gain(sc, ports, gain, balance); if (error != 0) { DPRINTF((%s: au_set_gain: %d\n, __func__, error)); - return; + goto done; } } + +done: + device_unref(sc-dev); }
Re: massage volume control task
Date: Fri, 2 Jan 2015 16:15:07 +1000 From: David Gwynne da...@gwynne.id.au can someone test this? it allocates storage for the volume change details rather than cast arguments to a single global task. adds some safety while there if audio0 is a hotplug device. ok? The problem with this approach is that things silently fail when memory allocation fails. Exactly the problem that workq_add_task() had. Perhaps the best thing is to store the event in the softc, although then you'd probably need some locking to make sure the task sees a consistent dir/out pair. Index: audio.c === RCS file: /cvs/src/sys/dev/audio.c,v retrieving revision 1.125 diff -u -p -r1.125 audio.c --- audio.c 19 Dec 2014 22:44:58 - 1.125 +++ audio.c 2 Jan 2015 06:08:39 - @@ -465,11 +465,6 @@ audioattach(struct device *parent, struc } DPRINTF((audio_attach: inputs ports=0x%x, output ports=0x%x\n, sc-sc_inports.allports, sc-sc_outports.allports)); - -#if NWSKBD 0 - task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, NULL, - NULL); -#endif /* NWSKBD 0 */ } int @@ -3432,27 +3427,39 @@ filt_audiowrite(struct knote *kn, long h } #if NWSKBD 0 +struct wskbd_vol_change { + struct task t; + long dir; + long out; +}; + int wskbd_set_mixervolume(long dir, long out) { struct audio_softc *sc; + struct wskbd_vol_change *ch; if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { DPRINTF((wskbd_set_mixervolume: audio_cd\n)); return (ENXIO); } - task_del(systq, sc-sc_mixer_task); - task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, - (void *)dir, (void *)out); - task_add(systq, sc-sc_mixer_task); + ch = malloc(sizeof(*ch), M_TEMP, M_NOWAIT); + if (ch == NULL) + return (ENOMEM); + + task_set(ch-t, wskbd_set_mixervolume_callback, ch, NULL); + ch-dir = dir; + ch-out = out; + task_add(systq, ch-t); return (0); } void -wskbd_set_mixervolume_callback(void *arg1, void *arg2) +wskbd_set_mixervolume_callback(void *xch, void *null) { + struct wskbd_vol_change *ch = xch; struct audio_softc *sc; struct au_mixer_ports *ports; mixer_devinfo_t mi; @@ -3461,19 +3468,19 @@ wskbd_set_mixervolume_callback(void *arg u_int gain; int error; - if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { - DPRINTF((%s: audio_cd\n, __func__)); - return; - } + dir = ch-dir; + out = ch-out; + free(ch, M_TEMP, sizeof(*ch)); - dir = (long)arg1; - out = (long)arg2; + sc = (struct audio_softc *)device_lookup(audio_cd, 0); + if (sc == NULL) + return; ports = out ? sc-sc_outports : sc-sc_inports; if (ports-master == -1) { DPRINTF((%s: master == -1\n, __func__)); - return; + goto done; } if (dir == 0) { @@ -3482,7 +3489,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_get_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_get_mute: %d\n, __func__, error)); - return; + goto done; } mute = !mute; @@ -3490,7 +3497,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_set_mute: %d\n, __func__, error)); - return; + goto done; } } else { /* Raise or lower volume */ @@ -3499,7 +3506,7 @@ wskbd_set_mixervolume_callback(void *arg error = sc-hw_if-query_devinfo(sc-hw_hdl, mi); if (error != 0) { DPRINTF((%s: query_devinfo: %d\n, __func__, error)); - return; + goto done; } au_get_gain(sc, ports, gain, balance); @@ -3512,8 +3519,11 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_gain(sc, ports, gain, balance); if (error != 0) { DPRINTF((%s: au_set_gain: %d\n, __func__, error)); - return; + goto done; } } + +done: + device_unref(sc-dev); } #endif /* NWSKBD 0 */
Re: massage volume control task
On 2 Jan 2015, at 9:55 pm, Mark Kettenis mark.kette...@xs4all.nl wrote: Date: Fri, 2 Jan 2015 16:15:07 +1000 From: David Gwynne da...@gwynne.id.au can someone test this? it allocates storage for the volume change details rather than cast arguments to a single global task. adds some safety while there if audio0 is a hotplug device. ok? The problem with this approach is that things silently fail when memory allocation fails. Exactly the problem that workq_add_task() had. Perhaps the best thing is to store the event in the softc, although then you'd probably need some locking to make sure the task sees a consistent dir/out pair. is silently fail a pun here? you can lose events either way. if you get more than one keypress before the task runs, you'll lose. if you are in a situation where you cant allocate memory, you lose. i think the code generally is bogus so im trying to do as little as possible to it. the more i look at it the more i want to just remove it. its been unreliable in all incarnations. Index: audio.c === RCS file: /cvs/src/sys/dev/audio.c,v retrieving revision 1.125 diff -u -p -r1.125 audio.c --- audio.c 19 Dec 2014 22:44:58 - 1.125 +++ audio.c 2 Jan 2015 06:08:39 - @@ -465,11 +465,6 @@ audioattach(struct device *parent, struc } DPRINTF((audio_attach: inputs ports=0x%x, output ports=0x%x\n, sc-sc_inports.allports, sc-sc_outports.allports)); - -#if NWSKBD 0 -task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, NULL, -NULL); -#endif /* NWSKBD 0 */ } int @@ -3432,27 +3427,39 @@ filt_audiowrite(struct knote *kn, long h } #if NWSKBD 0 +struct wskbd_vol_change { +struct task t; +long dir; +long out; +}; + int wskbd_set_mixervolume(long dir, long out) { struct audio_softc *sc; +struct wskbd_vol_change *ch; if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { DPRINTF((wskbd_set_mixervolume: audio_cd\n)); return (ENXIO); } -task_del(systq, sc-sc_mixer_task); -task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, -(void *)dir, (void *)out); -task_add(systq, sc-sc_mixer_task); +ch = malloc(sizeof(*ch), M_TEMP, M_NOWAIT); +if (ch == NULL) +return (ENOMEM); + +task_set(ch-t, wskbd_set_mixervolume_callback, ch, NULL); +ch-dir = dir; +ch-out = out; +task_add(systq, ch-t); return (0); } void -wskbd_set_mixervolume_callback(void *arg1, void *arg2) +wskbd_set_mixervolume_callback(void *xch, void *null) { +struct wskbd_vol_change *ch = xch; struct audio_softc *sc; struct au_mixer_ports *ports; mixer_devinfo_t mi; @@ -3461,19 +3468,19 @@ wskbd_set_mixervolume_callback(void *arg u_int gain; int error; -if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { -DPRINTF((%s: audio_cd\n, __func__)); -return; -} +dir = ch-dir; +out = ch-out; +free(ch, M_TEMP, sizeof(*ch)); -dir = (long)arg1; -out = (long)arg2; +sc = (struct audio_softc *)device_lookup(audio_cd, 0); +if (sc == NULL) +return; ports = out ? sc-sc_outports : sc-sc_inports; if (ports-master == -1) { DPRINTF((%s: master == -1\n, __func__)); -return; +goto done; } if (dir == 0) { @@ -3482,7 +3489,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_get_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_get_mute: %d\n, __func__, error)); -return; +goto done; } mute = !mute; @@ -3490,7 +3497,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_set_mute: %d\n, __func__, error)); -return; +goto done; } } else { /* Raise or lower volume */ @@ -3499,7 +3506,7 @@ wskbd_set_mixervolume_callback(void *arg error = sc-hw_if-query_devinfo(sc-hw_hdl, mi); if (error != 0) { DPRINTF((%s: query_devinfo: %d\n, __func__, error)); -return; +goto done; } au_get_gain(sc, ports, gain, balance); @@ -3512,8 +3519,11 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_gain(sc, ports, gain, balance); if (error != 0) { DPRINTF((%s: au_set_gain: %d\n, __func__, error)); -return; +goto done; } } + +done: +device_unref(sc-dev); } #endif /* NWSKBD 0 */
massage volume control task
can someone test this? it allocates storage for the volume change details rather than cast arguments to a single global task. adds some safety while there if audio0 is a hotplug device. ok? Index: audio.c === RCS file: /cvs/src/sys/dev/audio.c,v retrieving revision 1.125 diff -u -p -r1.125 audio.c --- audio.c 19 Dec 2014 22:44:58 - 1.125 +++ audio.c 2 Jan 2015 06:08:39 - @@ -465,11 +465,6 @@ audioattach(struct device *parent, struc } DPRINTF((audio_attach: inputs ports=0x%x, output ports=0x%x\n, sc-sc_inports.allports, sc-sc_outports.allports)); - -#if NWSKBD 0 - task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, NULL, - NULL); -#endif /* NWSKBD 0 */ } int @@ -3432,27 +3427,39 @@ filt_audiowrite(struct knote *kn, long h } #if NWSKBD 0 +struct wskbd_vol_change { + struct task t; + long dir; + long out; +}; + int wskbd_set_mixervolume(long dir, long out) { struct audio_softc *sc; + struct wskbd_vol_change *ch; if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { DPRINTF((wskbd_set_mixervolume: audio_cd\n)); return (ENXIO); } - task_del(systq, sc-sc_mixer_task); - task_set(sc-sc_mixer_task, wskbd_set_mixervolume_callback, - (void *)dir, (void *)out); - task_add(systq, sc-sc_mixer_task); + ch = malloc(sizeof(*ch), M_TEMP, M_NOWAIT); + if (ch == NULL) + return (ENOMEM); + + task_set(ch-t, wskbd_set_mixervolume_callback, ch, NULL); + ch-dir = dir; + ch-out = out; + task_add(systq, ch-t); return (0); } void -wskbd_set_mixervolume_callback(void *arg1, void *arg2) +wskbd_set_mixervolume_callback(void *xch, void *null) { + struct wskbd_vol_change *ch = xch; struct audio_softc *sc; struct au_mixer_ports *ports; mixer_devinfo_t mi; @@ -3461,19 +3468,19 @@ wskbd_set_mixervolume_callback(void *arg u_int gain; int error; - if (audio_cd.cd_ndevs == 0 || (sc = audio_cd.cd_devs[0]) == NULL) { - DPRINTF((%s: audio_cd\n, __func__)); - return; - } + dir = ch-dir; + out = ch-out; + free(ch, M_TEMP, sizeof(*ch)); - dir = (long)arg1; - out = (long)arg2; + sc = (struct audio_softc *)device_lookup(audio_cd, 0); + if (sc == NULL) + return; ports = out ? sc-sc_outports : sc-sc_inports; if (ports-master == -1) { DPRINTF((%s: master == -1\n, __func__)); - return; + goto done; } if (dir == 0) { @@ -3482,7 +3489,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_get_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_get_mute: %d\n, __func__, error)); - return; + goto done; } mute = !mute; @@ -3490,7 +3497,7 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_mute(sc, ports, mute); if (error != 0) { DPRINTF((%s: au_set_mute: %d\n, __func__, error)); - return; + goto done; } } else { /* Raise or lower volume */ @@ -3499,7 +3506,7 @@ wskbd_set_mixervolume_callback(void *arg error = sc-hw_if-query_devinfo(sc-hw_hdl, mi); if (error != 0) { DPRINTF((%s: query_devinfo: %d\n, __func__, error)); - return; + goto done; } au_get_gain(sc, ports, gain, balance); @@ -3512,8 +3519,11 @@ wskbd_set_mixervolume_callback(void *arg error = au_set_gain(sc, ports, gain, balance); if (error != 0) { DPRINTF((%s: au_set_gain: %d\n, __func__, error)); - return; + goto done; } } + +done: + device_unref(sc-dev); } #endif /* NWSKBD 0 */