| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: spkr_audio.c,v 1.3 2017/01/06 09:32:08 pgoyette Exp $ */ | | 1 | /* $NetBSD: spkr_audio.c,v 1.4 2017/06/11 03:25:02 nat Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> | | 4 | * Copyright (c) 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -17,70 +17,54 @@ | | | @@ -17,70 +17,54 @@ |
17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 17 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 19 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 20 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | * POSSIBILITY OF SUCH DAMAGE. | | 26 | * POSSIBILITY OF SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: spkr_audio.c,v 1.3 2017/01/06 09:32:08 pgoyette Exp $"); | | 30 | __KERNEL_RCSID(0, "$NetBSD: spkr_audio.c,v 1.4 2017/06/11 03:25:02 nat Exp $"); |
31 | | | 31 | |
32 | #include <sys/param.h> | | 32 | #include <sys/param.h> |
33 | #include <sys/systm.h> | | 33 | #include <sys/systm.h> |
34 | #include <sys/kernel.h> | | 34 | #include <sys/kernel.h> |
35 | #include <sys/errno.h> | | 35 | #include <sys/errno.h> |
36 | #include <sys/device.h> | | 36 | #include <sys/device.h> |
37 | #include <sys/malloc.h> | | 37 | #include <sys/malloc.h> |
38 | #include <sys/uio.h> | | 38 | #include <sys/uio.h> |
39 | #include <sys/proc.h> | | 39 | #include <sys/proc.h> |
40 | #include <sys/ioctl.h> | | 40 | #include <sys/ioctl.h> |
41 | #include <sys/conf.h> | | 41 | #include <sys/conf.h> |
42 | #include <sys/condvar.h> | | | |
43 | #include <sys/mutex.h> | | | |
44 | #include <sys/kthread.h> | | | |
45 | #include <sys/sysctl.h> | | 42 | #include <sys/sysctl.h> |
46 | #include <dev/audio_if.h> | | 43 | #include <dev/audio_if.h> |
47 | #include <dev/audiovar.h> | | 44 | #include <dev/audiovar.h> |
48 | | | 45 | |
49 | struct vbell_args { | | | |
50 | u_int pitch; | | | |
51 | u_int period; | | | |
52 | u_int volume; | | | |
53 | bool dying; | | | |
54 | }; | | | |
55 | | | | |
56 | static void bell_thread(void *) __dead; | | | |
57 | | | | |
58 | #include <dev/audiobellvar.h> | | 46 | #include <dev/audiobellvar.h> |
59 | | | 47 | |
60 | #include <dev/spkrvar.h> | | 48 | #include <dev/spkrvar.h> |
61 | #include <dev/spkrio.h> | | 49 | #include <dev/spkrio.h> |
62 | | | 50 | |
63 | static int spkr_audio_probe(device_t, cfdata_t, void *); | | 51 | static int spkr_audio_probe(device_t, cfdata_t, void *); |
64 | static void spkr_audio_attach(device_t, device_t, void *); | | 52 | static void spkr_audio_attach(device_t, device_t, void *); |
65 | static int spkr_audio_detach(device_t, int); | | 53 | static int spkr_audio_detach(device_t, int); |
66 | | | 54 | |
67 | struct spkr_audio_softc { | | 55 | struct spkr_audio_softc { |
68 | struct spkr_softc sc_spkr; | | 56 | struct spkr_softc sc_spkr; |
69 | lwp_t *sc_bellthread; | | | |
70 | kmutex_t sc_bellock; | | | |
71 | kcondvar_t sc_bellcv; | | | |
72 | device_t sc_audiodev; | | 57 | device_t sc_audiodev; |
73 | struct vbell_args sc_bell_args; | | | |
74 | }; | | 58 | }; |
75 | | | 59 | |
76 | CFATTACH_DECL_NEW(spkr_audio, sizeof(struct spkr_audio_softc), | | 60 | CFATTACH_DECL_NEW(spkr_audio, sizeof(struct spkr_audio_softc), |
77 | spkr_audio_probe, spkr_audio_attach, spkr_audio_detach, NULL); | | 61 | spkr_audio_probe, spkr_audio_attach, spkr_audio_detach, NULL); |
78 | | | 62 | |
79 | static void | | 63 | static void |
80 | spkr_audio_tone(device_t self, u_int xhz, u_int ticks) | | 64 | spkr_audio_tone(device_t self, u_int xhz, u_int ticks) |
81 | { | | 65 | { |
82 | struct spkr_audio_softc *sc = device_private(self); | | 66 | struct spkr_audio_softc *sc = device_private(self); |
83 | | | 67 | |
84 | #ifdef SPKRDEBUG | | 68 | #ifdef SPKRDEBUG |
85 | aprint_debug_dev(self, "%s: %u %d\n", __func__, xhz, ticks); | | 69 | aprint_debug_dev(self, "%s: %u %d\n", __func__, xhz, ticks); |
86 | #endif /* SPKRDEBUG */ | | 70 | #endif /* SPKRDEBUG */ |
| @@ -89,107 +73,48 @@ spkr_audio_tone(device_t self, u_int xhz | | | @@ -89,107 +73,48 @@ spkr_audio_tone(device_t self, u_int xhz |
89 | | | 73 | |
90 | static void | | 74 | static void |
91 | spkr_audio_rest(device_t self, int ticks) | | 75 | spkr_audio_rest(device_t self, int ticks) |
92 | { | | 76 | { |
93 | struct spkr_audio_softc *sc = device_private(self); | | 77 | struct spkr_audio_softc *sc = device_private(self); |
94 | | | 78 | |
95 | #ifdef SPKRDEBUG | | 79 | #ifdef SPKRDEBUG |
96 | aprint_debug_dev(self, "%s: %d\n", __func__, ticks); | | 80 | aprint_debug_dev(self, "%s: %d\n", __func__, ticks); |
97 | #endif /* SPKRDEBUG */ | | 81 | #endif /* SPKRDEBUG */ |
98 | if (ticks > 0) | | 82 | if (ticks > 0) |
99 | audiobell(sc->sc_audiodev, 0, ticks * (1000 / hz), 80, 0); | | 83 | audiobell(sc->sc_audiodev, 0, ticks * (1000 / hz), 80, 0); |
100 | } | | 84 | } |
101 | | | 85 | |
102 | #ifdef notyet | | | |
103 | static void | | | |
104 | spkr_audio_play(device_t self, u_int pitch, u_int period, u_int volume) | | | |
105 | { | | | |
106 | struct spkr_audio_softc *sc = device_private(self); | | | |
107 | | | | |
108 | mutex_enter(&sc->sc_bellock); | | | |
109 | sc->sc_bell_args.dying = false; | | | |
110 | sc->sc_bell_args.pitch = pitch; | | | |
111 | sc->sc_bell_args.period = period; | | | |
112 | sc->sc_bell_args.volume = volume; | | | |
113 | | | | |
114 | cv_broadcast(&sc->sc_bellcv); | | | |
115 | mutex_exit(&sc->sc_bellock); | | | |
116 | } | | | |
117 | #endif | | | |
118 | | | | |
119 | static int | | 86 | static int |
120 | spkr_audio_probe(device_t parent, cfdata_t cf, void *aux) | | 87 | spkr_audio_probe(device_t parent, cfdata_t cf, void *aux) |
121 | { | | 88 | { |
122 | | | 89 | |
123 | return 1; | | 90 | return 1; |
124 | } | | 91 | } |
125 | | | 92 | |
126 | static void | | 93 | static void |
127 | spkr_audio_attach(device_t parent, device_t self, void *aux) | | 94 | spkr_audio_attach(device_t parent, device_t self, void *aux) |
128 | { | | 95 | { |
129 | struct spkr_audio_softc *sc = device_private(self); | | 96 | struct spkr_audio_softc *sc = device_private(self); |
130 | | | 97 | |
131 | aprint_naive("\n"); | | 98 | aprint_naive("\n"); |
132 | aprint_normal(": PC Speaker (synthesized)\n"); | | 99 | aprint_normal(": PC Speaker (synthesized)\n"); |
133 | | | 100 | |
134 | sc->sc_audiodev = parent; | | 101 | sc->sc_audiodev = parent; |
135 | | | 102 | |
136 | if (!pmf_device_register(self, NULL, NULL)) | | 103 | if (!pmf_device_register(self, NULL, NULL)) |
137 | aprint_error_dev(self, "couldn't establish power handler\n"); | | 104 | aprint_error_dev(self, "couldn't establish power handler\n"); |
138 | mutex_init(&sc->sc_bellock, MUTEX_DEFAULT, IPL_SCHED); | | | |
139 | cv_init(&sc->sc_bellcv, "bellcv"); | | | |
140 | | | | |
141 | kthread_create(PRI_BIO, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL, | | | |
142 | bell_thread, sc, &sc->sc_bellthread, "%s", device_xname(self)); | | | |
143 | | | 105 | |
144 | spkr_attach(self, spkr_audio_tone, spkr_audio_rest); | | 106 | spkr_attach(self, spkr_audio_tone, spkr_audio_rest); |
145 | } | | 107 | } |
146 | | | 108 | |
147 | static int | | 109 | static int |
148 | spkr_audio_detach(device_t self, int flags) | | 110 | spkr_audio_detach(device_t self, int flags) |
149 | { | | 111 | { |
150 | struct spkr_audio_softc *sc = device_private(self); | | | |
151 | int error; | | 112 | int error; |
152 | | | 113 | |
153 | if ((error = spkr_detach(self, flags)) != 0) | | 114 | if ((error = spkr_detach(self, flags)) != 0) |
154 | return error; | | 115 | return error; |
155 | | | 116 | |
156 | pmf_device_deregister(self); | | 117 | pmf_device_deregister(self); |
157 | | | 118 | |
158 | mutex_enter(&sc->sc_bellock); | | | |
159 | sc->sc_bell_args.dying = true; | | | |
160 | | | | |
161 | cv_broadcast(&sc->sc_bellcv); | | | |
162 | mutex_exit(&sc->sc_bellock); | | | |
163 | | | | |
164 | kthread_join(sc->sc_bellthread); | | | |
165 | cv_destroy(&sc->sc_bellcv); | | | |
166 | mutex_destroy(&sc->sc_bellock); | | | |
167 | | | | |
168 | return 0; | | 119 | return 0; |
169 | } | | 120 | } |
170 | | | | |
171 | static void | | | |
172 | bell_thread(void *arg) | | | |
173 | { | | | |
174 | struct spkr_audio_softc *sc = arg; | | | |
175 | struct vbell_args *vb = &sc->sc_bell_args; | | | |
176 | u_int bpitch; | | | |
177 | u_int bperiod; | | | |
178 | u_int bvolume; | | | |
179 | | | | |
180 | for (;;) { | | | |
181 | mutex_enter(&sc->sc_bellock); | | | |
182 | cv_wait_sig(&sc->sc_bellcv, &sc->sc_bellock); | | | |
183 | | | | |
184 | if (vb->dying == true) { | | | |
185 | mutex_exit(&sc->sc_bellock); | | | |
186 | kthread_exit(0); | | | |
187 | } | | | |
188 | | | | |
189 | bpitch = vb->pitch; | | | |
190 | bperiod = vb->period; | | | |
191 | bvolume = vb->volume; | | | |
192 | mutex_exit(&sc->sc_bellock); | | | |
193 | audiobell(sc->sc_audiodev, bpitch, bperiod, bvolume, 0); | | | |
194 | } | | | |
195 | } | | | |