Pull up following revision(s) (requested by mrg in ticket #407): sys/dev/midivar.h: revision 1.20 sys/dev/usb/umidivar.h: file removal sys/dev/midi.c: revision 1.82 sys/dev/midi.c: revision 1.83 sys/dev/usb/FILES: revision 1.13 sys/dev/midi_if.h: revision 1.26 sys/dev/sequencer.c: revision 1.60 sys/dev/sequencer.c: revision 1.61 sys/dev/sequencer.c: revision 1.62 sys/dev/sequencer.c: revision 1.63 sys/dev/usb/umidi_quirks.c: revision 1.19 sys/dev/usb/umidi.c: revision 1.66 sys/dev/usb/umidi.c: revision 1.67 sys/dev/usb/umidi.c: revision 1.68 sys/dev/usb/umidireg.h: file removal sys/dev/sequencervar.h: revision 1.17 fix the midi_if documentation to properly describe the locks that will be held during various operations. various umidi clean ups: - move the contents of umidi{reg,var}.h into umidi.c directly as they are not referenced by any other file. - remove the useless include of umidi{reg,var}.h from umidi_quirks.c. - add reference counting and wait/broadcast support to the IO paths. - fix the error handling in midi_attach() and midi_open(). - sprinkle KASSERT() in several places. - drop the local interrupt lock before calling into various parts of the USB code. fixes lockdebug issues, and likely hangs. - rename "binded" member as "bound". with these most of the panics and problems i've seen are gone. there is still one lockdebug panic to deal with that happens when unplugging umidi while midiplay(1) is running. various clean ups for midi and sequencer: midi specific: - add reference counting for midi operations, and ensure that detach waits for other threads to complete before tearing down the device completely. - in detach, halt midi callouts before destroying them - re-check sc->dying after sleeping in midiread() - in real_writebytes(), make sure we're open and not dying - make sure we drop the interrupt lock before calling any code that may want to check thread locks. this is now safe due to the above changes. sequencer specific: - avoid caching the midi softc in the sequencer softc. instead, every time we want to use it, look it up again and make sure it still exists. this fixes various crashes i've seen in the usb midi code when detaching the umidi while it is active. use __func__ in some debug messages. - check sc->dying after sleeping in several more places, and convert it into EIO error where necessary. - remove a wrong additional mutex_exit() call. - make sure to check sc->dying under the device lock. - fix a confusion between midi(4) unit and connected to sequencer devices. - minor comment/debug clean ups. fixes problems attempting to read or write from the right midi(4) device using the sequencer(4) device when one or more of the non-final devices fails to open with midiseq_open(). fix !AUDIO_DEBUG build. CID/1261465: Dereference after NULL check. CID/1261467: Unreachable code actually fix one of the previous: don't test for NULL after deref.diff -r1.81 -r1.81.2.1 src/sys/dev/midi.c
(martin)
--- src/sys/dev/midi.c 2014/07/25 08:10:35 1.81
+++ src/sys/dev/midi.c 2015/01/11 14:13:25 1.81.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: midi.c,v 1.81 2014/07/25 08:10:35 dholland Exp $ */ | 1 | /* $NetBSD: midi.c,v 1.81.2.1 2015/01/11 14:13:25 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (augustss@NetBSD.org), (MIDI FST and Active | 8 | * by Lennart Augustsson (augustss@NetBSD.org), (MIDI FST and Active | |
9 | * Sense handling) Chapman Flack (chap@NetBSD.org), and Andrew Doran. | 9 | * Sense handling) Chapman Flack (chap@NetBSD.org), and Andrew Doran. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -21,27 +21,27 @@ | @@ -21,27 +21,27 @@ | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: midi.c,v 1.81 2014/07/25 08:10:35 dholland Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: midi.c,v 1.81.2.1 2015/01/11 14:13:25 martin Exp $"); | |
35 | 35 | |||
36 | #include "midi.h" | 36 | #include "midi.h" | |
37 | #include "sequencer.h" | 37 | #include "sequencer.h" | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/ioctl.h> | 40 | #include <sys/ioctl.h> | |
41 | #include <sys/fcntl.h> | 41 | #include <sys/fcntl.h> | |
42 | #include <sys/vnode.h> | 42 | #include <sys/vnode.h> | |
43 | #include <sys/select.h> | 43 | #include <sys/select.h> | |
44 | #include <sys/poll.h> | 44 | #include <sys/poll.h> | |
45 | #include <sys/proc.h> | 45 | #include <sys/proc.h> | |
46 | #include <sys/systm.h> | 46 | #include <sys/systm.h> | |
47 | #include <sys/callout.h> | 47 | #include <sys/callout.h> | |
@@ -194,26 +194,31 @@ midiactivate(device_t self, enum devact | @@ -194,26 +194,31 @@ midiactivate(device_t self, enum devact | |||
194 | 194 | |||
195 | int | 195 | int | |
196 | mididetach(device_t self, int flags) | 196 | mididetach(device_t self, int flags) | |
197 | { | 197 | { | |
198 | struct midi_softc *sc = device_private(self); | 198 | struct midi_softc *sc = device_private(self); | |
199 | int maj, mn; | 199 | int maj, mn; | |
200 | 200 | |||
201 | DPRINTFN(2,("%s: sc=%p flags=%d\n", __func__, sc, flags)); | 201 | DPRINTFN(2,("%s: sc=%p flags=%d\n", __func__, sc, flags)); | |
202 | 202 | |||
203 | pmf_device_deregister(self); | 203 | pmf_device_deregister(self); | |
204 | 204 | |||
205 | mutex_enter(sc->lock); | 205 | mutex_enter(sc->lock); | |
206 | sc->dying = 1; | 206 | sc->dying = 1; | |
207 | ||||
208 | if (--sc->refcnt >= 0) { | |||
209 | /* Wake anything? */ | |||
210 | (void)cv_timedwait(&sc->detach_cv, sc->lock, hz * 60); | |||
211 | } | |||
207 | cv_broadcast(&sc->wchan); | 212 | cv_broadcast(&sc->wchan); | |
208 | cv_broadcast(&sc->rchan); | 213 | cv_broadcast(&sc->rchan); | |
209 | mutex_exit(sc->lock); | 214 | mutex_exit(sc->lock); | |
210 | 215 | |||
211 | /* locate the major number */ | 216 | /* locate the major number */ | |
212 | maj = cdevsw_lookup_major(&midi_cdevsw); | 217 | maj = cdevsw_lookup_major(&midi_cdevsw); | |
213 | 218 | |||
214 | /* | 219 | /* | |
215 | * Nuke the vnodes for any open instances (calls close). | 220 | * Nuke the vnodes for any open instances (calls close). | |
216 | * Will wait until any activity on the device nodes has ceased. | 221 | * Will wait until any activity on the device nodes has ceased. | |
217 | * | 222 | * | |
218 | * XXXAD NOT YET. | 223 | * XXXAD NOT YET. | |
219 | * | 224 | * | |
@@ -226,28 +231,37 @@ mididetach(device_t self, int flags) | @@ -226,28 +231,37 @@ mididetach(device_t self, int flags) | |||
226 | evcnt_detach(&sc->xmt.bytesDiscarded); | 231 | evcnt_detach(&sc->xmt.bytesDiscarded); | |
227 | evcnt_detach(&sc->xmt.incompleteMessages); | 232 | evcnt_detach(&sc->xmt.incompleteMessages); | |
228 | } | 233 | } | |
229 | if (sc->props & MIDI_PROP_CAN_INPUT) { | 234 | if (sc->props & MIDI_PROP_CAN_INPUT) { | |
230 | evcnt_detach(&sc->rcv.bytesDiscarded); | 235 | evcnt_detach(&sc->rcv.bytesDiscarded); | |
231 | evcnt_detach(&sc->rcv.incompleteMessages); | 236 | evcnt_detach(&sc->rcv.incompleteMessages); | |
232 | } | 237 | } | |
233 | 238 | |||
234 | if (sc->sih != NULL) { | 239 | if (sc->sih != NULL) { | |
235 | softint_disestablish(sc->sih); | 240 | softint_disestablish(sc->sih); | |
236 | sc->sih = NULL; | 241 | sc->sih = NULL; | |
237 | } | 242 | } | |
238 | 243 | |||
244 | mutex_enter(sc->lock); | |||
245 | callout_halt(&sc->xmt_asense_co, sc->lock); | |||
246 | callout_halt(&sc->rcv_asense_co, sc->lock); | |||
247 | mutex_exit(sc->lock); | |||
248 | ||||
249 | callout_destroy(&sc->xmt_asense_co); | |||
250 | callout_destroy(&sc->rcv_asense_co); | |||
251 | ||||
239 | cv_destroy(&sc->wchan); | 252 | cv_destroy(&sc->wchan); | |
240 | cv_destroy(&sc->rchan); | 253 | cv_destroy(&sc->rchan); | |
254 | cv_destroy(&sc->detach_cv); | |||
241 | 255 | |||
242 | return (0); | 256 | return (0); | |
243 | } | 257 | } | |
244 | 258 | |||
245 | void | 259 | void | |
246 | midi_attach(struct midi_softc *sc) | 260 | midi_attach(struct midi_softc *sc) | |
247 | { | 261 | { | |
248 | struct midi_info mi; | 262 | struct midi_info mi; | |
249 | kmutex_t *dummy; | 263 | kmutex_t *dummy; | |
250 | static int first = 1; | 264 | static int first = 1; | |
251 | 265 | |||
252 | if (first) { | 266 | if (first) { | |
253 | mutex_init(&hwif_softc_lock, MUTEX_DEFAULT, IPL_NONE); | 267 | mutex_init(&hwif_softc_lock, MUTEX_DEFAULT, IPL_NONE); | |
@@ -256,29 +270,31 @@ midi_attach(struct midi_softc *sc) | @@ -256,29 +270,31 @@ midi_attach(struct midi_softc *sc) | |||
256 | 270 | |||
257 | sc->hw_if->get_locks(sc->hw_hdl, &sc->lock, &dummy); | 271 | sc->hw_if->get_locks(sc->hw_hdl, &sc->lock, &dummy); | |
258 | 272 | |||
259 | callout_init(&sc->xmt_asense_co, CALLOUT_MPSAFE); | 273 | callout_init(&sc->xmt_asense_co, CALLOUT_MPSAFE); | |
260 | callout_init(&sc->rcv_asense_co, CALLOUT_MPSAFE); | 274 | callout_init(&sc->rcv_asense_co, CALLOUT_MPSAFE); | |
261 | callout_setfunc(&sc->xmt_asense_co, midi_xmt_asense, sc); | 275 | callout_setfunc(&sc->xmt_asense_co, midi_xmt_asense, sc); | |
262 | callout_setfunc(&sc->rcv_asense_co, midi_rcv_asense, sc); | 276 | callout_setfunc(&sc->rcv_asense_co, midi_rcv_asense, sc); | |
263 | 277 | |||
264 | sc->sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE, | 278 | sc->sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE, | |
265 | midi_softint, sc); | 279 | midi_softint, sc); | |
266 | 280 | |||
267 | cv_init(&sc->rchan, "midird"); | 281 | cv_init(&sc->rchan, "midird"); | |
268 | cv_init(&sc->wchan, "midiwr"); | 282 | cv_init(&sc->wchan, "midiwr"); | |
283 | cv_init(&sc->detach_cv, "mididet"); | |||
269 | 284 | |||
270 | sc->dying = 0; | 285 | sc->dying = 0; | |
271 | sc->isopen = 0; | 286 | sc->isopen = 0; | |
287 | sc->refcnt = 0; | |||
272 | 288 | |||
273 | mutex_enter(&hwif_softc_lock); | 289 | mutex_enter(&hwif_softc_lock); | |
274 | mutex_enter(sc->lock); | 290 | mutex_enter(sc->lock); | |
275 | hwif_softc = sc; | 291 | hwif_softc = sc; | |
276 | sc->hw_if->getinfo(sc->hw_hdl, &mi); | 292 | sc->hw_if->getinfo(sc->hw_hdl, &mi); | |
277 | hwif_softc = NULL; | 293 | hwif_softc = NULL; | |
278 | mutex_exit(sc->lock); | 294 | mutex_exit(sc->lock); | |
279 | mutex_exit(&hwif_softc_lock); | 295 | mutex_exit(&hwif_softc_lock); | |
280 | 296 | |||
281 | sc->props = mi.props; | 297 | sc->props = mi.props; | |
282 | 298 | |||
283 | if (!(sc->props & MIDI_PROP_NO_OUTPUT)) { | 299 | if (!(sc->props & MIDI_PROP_NO_OUTPUT)) { | |
284 | evcnt_attach_dynamic(&sc->xmt.bytesDiscarded, | 300 | evcnt_attach_dynamic(&sc->xmt.bytesDiscarded, | |
@@ -854,26 +870,28 @@ static int | @@ -854,26 +870,28 @@ static int | |||
854 | midiclose(dev_t dev, int flags, int ifmt, struct lwp *l) | 870 | midiclose(dev_t dev, int flags, int ifmt, struct lwp *l) | |
855 | { | 871 | { | |
856 | struct midi_softc *sc; | 872 | struct midi_softc *sc; | |
857 | const struct midi_hw_if *hw; | 873 | const struct midi_hw_if *hw; | |
858 | 874 | |||
859 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | 875 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | |
860 | hw = sc->hw_if; | 876 | hw = sc->hw_if; | |
861 | 877 | |||
862 | DPRINTFN(3,("midiclose %p\n", sc)); | 878 | DPRINTFN(3,("midiclose %p\n", sc)); | |
863 | 879 | |||
864 | mutex_enter(sc->lock); | 880 | mutex_enter(sc->lock); | |
865 | /* midi_start_output(sc); anything buffered => pbus already set! */ | 881 | /* midi_start_output(sc); anything buffered => pbus already set! */ | |
866 | while (sc->pbus) { | 882 | while (sc->pbus) { | |
883 | if (sc->dying) | |||
884 | break; | |||
867 | DPRINTFN(8,("midiclose sleep ...\n")); | 885 | DPRINTFN(8,("midiclose sleep ...\n")); | |
868 | cv_wait(&sc->wchan, sc->lock); | 886 | cv_wait(&sc->wchan, sc->lock); | |
869 | } | 887 | } | |
870 | sc->isopen = 0; | 888 | sc->isopen = 0; | |
871 | callout_halt(&sc->xmt_asense_co, sc->lock); | 889 | callout_halt(&sc->xmt_asense_co, sc->lock); | |
872 | callout_halt(&sc->rcv_asense_co, sc->lock); | 890 | callout_halt(&sc->rcv_asense_co, sc->lock); | |
873 | hw->close(sc->hw_hdl); | 891 | hw->close(sc->hw_hdl); | |
874 | sc->seqopen = 0; | 892 | sc->seqopen = 0; | |
875 | sc->seq_md = 0; | 893 | sc->seq_md = 0; | |
876 | mutex_exit(sc->lock); | 894 | mutex_exit(sc->lock); | |
877 | 895 | |||
878 | return 0; | 896 | return 0; | |
879 | } | 897 | } | |
@@ -942,35 +960,43 @@ midiread(dev_t dev, struct uio *uio, int | @@ -942,35 +960,43 @@ midiread(dev_t dev, struct uio *uio, int | |||
942 | /* move the bytes */ | 960 | /* move the bytes */ | |
943 | if (appetite > 0) { | 961 | if (appetite > 0) { | |
944 | first = 0; /* we know we won't return empty-handed */ | 962 | first = 0; /* we know we won't return empty-handed */ | |
945 | /* do two uiomoves if data wrap around end of buf */ | 963 | /* do two uiomoves if data wrap around end of buf */ | |
946 | if (buf_cur + appetite > buf_end) { | 964 | if (buf_cur + appetite > buf_end) { | |
947 | DPRINTFN(8, | 965 | DPRINTFN(8, | |
948 | ("midiread: uiomove cc=%td (prewrap)\n", | 966 | ("midiread: uiomove cc=%td (prewrap)\n", | |
949 | buf_end - buf_cur)); | 967 | buf_end - buf_cur)); | |
950 | mutex_exit(sc->lock); | 968 | mutex_exit(sc->lock); | |
951 | error = uiomove(buf_cur, buf_end - buf_cur, uio); | 969 | error = uiomove(buf_cur, buf_end - buf_cur, uio); | |
952 | mutex_enter(sc->lock); | 970 | mutex_enter(sc->lock); | |
953 | if (error) | 971 | if (error) | |
954 | break; | 972 | break; | |
973 | if (sc->dying) { | |||
974 | error = EIO; | |||
975 | break; | |||
976 | } | |||
955 | appetite -= buf_end - buf_cur; | 977 | appetite -= buf_end - buf_cur; | |
956 | buf_cur = mb->buf; | 978 | buf_cur = mb->buf; | |
957 | } | 979 | } | |
958 | DPRINTFN(8, ("midiread: uiomove cc=%d\n", appetite)); | 980 | DPRINTFN(8, ("midiread: uiomove cc=%d\n", appetite)); | |
959 | mutex_exit(sc->lock); | 981 | mutex_exit(sc->lock); | |
960 | error = uiomove(buf_cur, appetite, uio); | 982 | error = uiomove(buf_cur, appetite, uio); | |
961 | mutex_enter(sc->lock); | 983 | mutex_enter(sc->lock); | |
962 | if (error) | 984 | if (error) | |
963 | break; | 985 | break; | |
986 | if (sc->dying) { | |||
987 | error = EIO; | |||
988 | break; | |||
989 | } | |||
964 | buf_cur += appetite; | 990 | buf_cur += appetite; | |
965 | } | 991 | } | |
966 | 992 | |||
967 | MIDI_BUF_WRAP(idx); | 993 | MIDI_BUF_WRAP(idx); | |
968 | MIDI_BUF_WRAP(buf); | 994 | MIDI_BUF_WRAP(buf); | |
969 | MIDI_BUF_CONSUMER_WBACK(mb,idx); | 995 | MIDI_BUF_CONSUMER_WBACK(mb,idx); | |
970 | MIDI_BUF_CONSUMER_WBACK(mb,buf); | 996 | MIDI_BUF_CONSUMER_WBACK(mb,buf); | |
971 | if (0 == uio->uio_resid) /* if read satisfied, we're done */ | 997 | if (0 == uio->uio_resid) /* if read satisfied, we're done */ | |
972 | break; | 998 | break; | |
973 | MIDI_BUF_CONSUMER_REFRESH(mb,idx); | 999 | MIDI_BUF_CONSUMER_REFRESH(mb,idx); | |
974 | if (idx_cur == idx_lim) { /* need to wait for data? */ | 1000 | if (idx_cur == idx_lim) { /* need to wait for data? */ | |
975 | if (!first || sc->rcv_eof) /* never block reader if */ | 1001 | if (!first || sc->rcv_eof) /* never block reader if */ | |
976 | break; /* any data already in hand */ | 1002 | break; /* any data already in hand */ | |
@@ -1243,33 +1269,33 @@ midi_intr_out(struct midi_softc *sc) | @@ -1243,33 +1269,33 @@ midi_intr_out(struct midi_softc *sc) | |||
1243 | while (idx_cur != idx_lim) { | 1269 | while (idx_cur != idx_lim) { | |
1244 | if (sc->hw_if_ext) { | 1270 | if (sc->hw_if_ext) { | |
1245 | error = midi_msg_out(sc, &idx_cur, &idx_lim, | 1271 | error = midi_msg_out(sc, &idx_cur, &idx_lim, | |
1246 | &buf_cur, &buf_lim); | 1272 | &buf_cur, &buf_lim); | |
1247 | if (!error ) /* no EINPROGRESS from extended hw_if */ | 1273 | if (!error ) /* no EINPROGRESS from extended hw_if */ | |
1248 | armed = 1; | 1274 | armed = 1; | |
1249 | break; | 1275 | break; | |
1250 | } | 1276 | } | |
1251 | /* or, lacking hw_if_ext ... */ | 1277 | /* or, lacking hw_if_ext ... */ | |
1252 | msglen = MB_IDX_LEN(*idx_cur); | 1278 | msglen = MB_IDX_LEN(*idx_cur); | |
1253 | error = sc->hw_if->output(sc->hw_hdl, *buf_cur); | 1279 | error = sc->hw_if->output(sc->hw_hdl, *buf_cur); | |
1254 | if (error && error != EINPROGRESS) | 1280 | if (error && error != EINPROGRESS) | |
1255 | break; | 1281 | break; | |
1256 | ++ buf_cur; | 1282 | ++buf_cur; | |
1257 | MIDI_BUF_WRAP(buf); | 1283 | MIDI_BUF_WRAP(buf); | |
1258 | -- msglen; | 1284 | --msglen; | |
1259 | if (msglen) | 1285 | if (msglen) | |
1260 | *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),msglen); | 1286 | *idx_cur = PACK_MB_IDX(MB_IDX_CAT(*idx_cur),msglen); | |
1261 | else { | 1287 | else { | |
1262 | ++ idx_cur; | 1288 | ++idx_cur; | |
1263 | MIDI_BUF_WRAP(idx); | 1289 | MIDI_BUF_WRAP(idx); | |
1264 | } | 1290 | } | |
1265 | if (!error) { | 1291 | if (!error) { | |
1266 | armed = 1; | 1292 | armed = 1; | |
1267 | break; | 1293 | break; | |
1268 | } | 1294 | } | |
1269 | } | 1295 | } | |
1270 | MIDI_BUF_CONSUMER_WBACK(mb,idx); | 1296 | MIDI_BUF_CONSUMER_WBACK(mb,idx); | |
1271 | MIDI_BUF_CONSUMER_WBACK(mb,buf); | 1297 | MIDI_BUF_CONSUMER_WBACK(mb,buf); | |
1272 | if (!armed) { | 1298 | if (!armed) { | |
1273 | sc->pbus = 0; | 1299 | sc->pbus = 0; | |
1274 | callout_schedule(&sc->xmt_asense_co, MIDI_XMT_ASENSE_PERIOD); | 1300 | callout_schedule(&sc->xmt_asense_co, MIDI_XMT_ASENSE_PERIOD); | |
1275 | } | 1301 | } | |
@@ -1296,115 +1322,128 @@ midi_start_output(struct midi_softc *sc) | @@ -1296,115 +1322,128 @@ midi_start_output(struct midi_softc *sc) | |||
1296 | return midi_intr_out(sc); | 1322 | return midi_intr_out(sc); | |
1297 | return midi_poll_out(sc); | 1323 | return midi_poll_out(sc); | |
1298 | } | 1324 | } | |
1299 | 1325 | |||
1300 | static int | 1326 | static int | |
1301 | real_writebytes(struct midi_softc *sc, u_char *ibuf, int cc) | 1327 | real_writebytes(struct midi_softc *sc, u_char *ibuf, int cc) | |
1302 | { | 1328 | { | |
1303 | u_char *iend; | 1329 | u_char *iend; | |
1304 | struct midi_buffer *mb; | 1330 | struct midi_buffer *mb; | |
1305 | int arming, count, got; | 1331 | int arming, count, got; | |
1306 | enum fst_form form; | 1332 | enum fst_form form; | |
1307 | MIDI_BUF_DECLARE(idx); | 1333 | MIDI_BUF_DECLARE(idx); | |
1308 | MIDI_BUF_DECLARE(buf); | 1334 | MIDI_BUF_DECLARE(buf); | |
1335 | int error; | |||
1309 | 1336 | |||
1310 | KASSERT(mutex_owned(sc->lock)); | 1337 | KASSERT(mutex_owned(sc->lock)); | |
1311 | 1338 | |||
1339 | if (sc->dying || !sc->isopen) | |||
1340 | return EIO; | |||
1341 | ||||
1342 | sc->refcnt++; | |||
1343 | ||||
1312 | iend = ibuf + cc; | 1344 | iend = ibuf + cc; | |
1313 | mb = &sc->outbuf; | 1345 | mb = &sc->outbuf; | |
1314 | arming = 0; | 1346 | arming = 0; | |
1315 | 1347 | |||
1316 | /* | 1348 | /* | |
1317 | * If the hardware uses the extended hw_if, pass it canonicalized | 1349 | * If the hardware uses the extended hw_if, pass it canonicalized | |
1318 | * messages (or compressed ones if it specifically requests, using | 1350 | * messages (or compressed ones if it specifically requests, using | |
1319 | * VCOMP form so the bottom half can still pass the op and chan along); | 1351 | * VCOMP form so the bottom half can still pass the op and chan along); | |
1320 | * if it does not, send it compressed messages (using COMPR form as | 1352 | * if it does not, send it compressed messages (using COMPR form as | |
1321 | * there is no need to preserve the status for the bottom half). | 1353 | * there is no need to preserve the status for the bottom half). | |
1322 | */ | 1354 | */ | |
1323 | if (NULL == sc->hw_if_ext) | 1355 | if (NULL == sc->hw_if_ext) | |
1324 | form = FST_COMPR; | 1356 | form = FST_COMPR; | |
1325 | else if (sc->hw_if_ext->compress) | 1357 | else if (sc->hw_if_ext->compress) | |
1326 | form = FST_VCOMP; | 1358 | form = FST_VCOMP; | |
1327 | else | 1359 | else | |
1328 | form = FST_CANON; | 1360 | form = FST_CANON; | |
1329 | 1361 | |||
1330 | MIDI_BUF_PRODUCER_INIT(mb,idx); | 1362 | MIDI_BUF_PRODUCER_INIT(mb,idx); | |
1331 | MIDI_BUF_PRODUCER_INIT(mb,buf); | 1363 | MIDI_BUF_PRODUCER_INIT(mb,buf); | |
1332 | ||||
1333 | if (sc->dying) | |||
1334 | return EIO; | |||
1335 | 1364 | |||
1336 | while (ibuf < iend) { | 1365 | while (ibuf < iend) { | |
1337 | got = midi_fst(&sc->xmt, *ibuf, form); | 1366 | got = midi_fst(&sc->xmt, *ibuf, form); | |
1338 | ++ ibuf; | 1367 | ++ibuf; | |
1339 | switch ( got) { | 1368 | switch ( got) { | |
1340 | case FST_MORE: | 1369 | case FST_MORE: | |
1341 | continue; | 1370 | continue; | |
1342 | case FST_ERR: | 1371 | case FST_ERR: | |
1343 | case FST_HUH: | 1372 | case FST_HUH: | |
1344 | return EPROTO; | 1373 | error = EPROTO; | |
1374 | goto out; | |||
1345 | case FST_CHN: | 1375 | case FST_CHN: | |
1346 | case FST_CHV: /* only occurs in VCOMP form */ | 1376 | case FST_CHV: /* only occurs in VCOMP form */ | |
1347 | case FST_COM: | 1377 | case FST_COM: | |
1348 | case FST_RT: | 1378 | case FST_RT: | |
1349 | case FST_SYX: | 1379 | case FST_SYX: | |
1350 | case FST_SXP: | 1380 | case FST_SXP: | |
1351 | break; /* go add to buffer */ | 1381 | break; /* go add to buffer */ | |
1352 | #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC) | 1382 | #if defined(AUDIO_DEBUG) || defined(DIAGNOSTIC) | |
1353 | default: | 1383 | default: | |
1354 | printf("midi_wr: midi_fst returned %d?!\n", got); | 1384 | printf("midi_wr: midi_fst returned %d?!\n", got); | |
1355 | #endif | 1385 | #endif | |
1356 | } | 1386 | } | |
1357 | count = sc->xmt.end - sc->xmt.pos; | 1387 | count = sc->xmt.end - sc->xmt.pos; | |
1358 | if (0 == count ) /* can happen with stray 0xf7; see midi_fst */ | 1388 | if (0 == count ) /* can happen with stray 0xf7; see midi_fst */ | |
1359 | continue; | 1389 | continue; | |
1360 | /* | 1390 | /* | |
1361 | * return EWOULDBLOCK if the data passed will not fit in | 1391 | * return EWOULDBLOCK if the data passed will not fit in | |
1362 | * the buffer; the caller should have taken steps to avoid that. | 1392 | * the buffer; the caller should have taken steps to avoid that. | |
1363 | * If got==FST_SXP we lose the new status byte, but we're losing | 1393 | * If got==FST_SXP we lose the new status byte, but we're losing | |
1364 | * anyway, so c'est la vie. | 1394 | * anyway, so c'est la vie. | |
1365 | */ | 1395 | */ | |
1366 | if (idx_cur == idx_lim || count > buf_lim - buf_cur) { | 1396 | if (idx_cur == idx_lim || count > buf_lim - buf_cur) { | |
1367 | MIDI_BUF_PRODUCER_REFRESH(mb,idx); /* get the most */ | 1397 | MIDI_BUF_PRODUCER_REFRESH(mb,idx); /* get the most */ | |
1368 | MIDI_BUF_PRODUCER_REFRESH(mb,buf); /* current facts */ | 1398 | MIDI_BUF_PRODUCER_REFRESH(mb,buf); /* current facts */ | |
1369 | if (idx_cur == idx_lim || count > buf_lim - buf_cur) | 1399 | if (idx_cur == idx_lim || count > buf_lim - buf_cur) { | |
1370 | return EWOULDBLOCK; /* caller's problem */ | 1400 | error = EWOULDBLOCK; /* caller's problem */ | |
1401 | goto out; | |||
1402 | } | |||
1371 | } | 1403 | } | |
1372 | *idx_cur++ = PACK_MB_IDX(got,count); | 1404 | *idx_cur++ = PACK_MB_IDX(got,count); | |
1373 | MIDI_BUF_WRAP(idx); | 1405 | MIDI_BUF_WRAP(idx); | |
1374 | while (count) { | 1406 | while (count) { | |
1375 | *buf_cur++ = *(sc->xmt.pos)++; | 1407 | *buf_cur++ = *(sc->xmt.pos)++; | |
1376 | MIDI_BUF_WRAP(buf); | 1408 | MIDI_BUF_WRAP(buf); | |
1377 | -- count; | 1409 | -- count; | |
1378 | } | 1410 | } | |
1379 | if (FST_SXP == got) | 1411 | if (FST_SXP == got) | |
1380 | -- ibuf; /* again with same status byte */ | 1412 | -- ibuf; /* again with same status byte */ | |
1381 | } | 1413 | } | |
1382 | MIDI_BUF_PRODUCER_WBACK(mb,buf); | 1414 | MIDI_BUF_PRODUCER_WBACK(mb,buf); | |
1383 | MIDI_BUF_PRODUCER_WBACK(mb,idx); | 1415 | MIDI_BUF_PRODUCER_WBACK(mb,idx); | |
1384 | /* | 1416 | /* | |
1385 | * If the output transfer is not already busy, and there is a message | 1417 | * If the output transfer is not already busy, and there is a message | |
1386 | * buffered, mark it busy, stop the Active Sense callout (what if we're | 1418 | * buffered, mark it busy, stop the Active Sense callout (what if we're | |
1387 | * too late and it's expired already? No big deal, an extra Active Sense | 1419 | * too late and it's expired already? No big deal, an extra Active Sense | |
1388 | * never hurt anybody) and start the output transfer once we're out of | 1420 | * never hurt anybody) and start the output transfer once we're out of | |
1389 | * the critical section (pbus==1 will stop anyone else doing the same). | 1421 | * the critical section (pbus==1 will stop anyone else doing the same). | |
1390 | */ | 1422 | */ | |
1391 | MIDI_BUF_CONSUMER_INIT(mb,idx); /* check what consumer's got to read */ | 1423 | MIDI_BUF_CONSUMER_INIT(mb,idx); /* check what consumer's got to read */ | |
1392 | if (!sc->pbus && idx_cur < idx_lim) { | 1424 | if (!sc->pbus && idx_cur < idx_lim) { | |
1393 | sc->pbus = 1; | 1425 | sc->pbus = 1; | |
1394 | callout_stop(&sc->xmt_asense_co); | 1426 | callout_stop(&sc->xmt_asense_co); | |
1395 | arming = 1; | 1427 | arming = 1; | |
1396 | } | 1428 | } | |
1397 | return arming ? midi_start_output(sc) : 0; | 1429 | ||
1430 | error = arming ? midi_start_output(sc) : 0; | |||
1431 | ||||
1432 | out: | |||
1433 | if (--sc->refcnt < 0) | |||
1434 | cv_broadcast(&sc->detach_cv); | |||
1435 | ||||
1436 | return error; | |||
1398 | } | 1437 | } | |
1399 | 1438 | |||
1400 | static int | 1439 | static int | |
1401 | midiwrite(dev_t dev, struct uio *uio, int ioflag) | 1440 | midiwrite(dev_t dev, struct uio *uio, int ioflag) | |
1402 | { | 1441 | { | |
1403 | struct midi_softc *sc; | 1442 | struct midi_softc *sc; | |
1404 | struct midi_buffer *mb; | 1443 | struct midi_buffer *mb; | |
1405 | int error; | 1444 | int error; | |
1406 | u_char inp[256]; | 1445 | u_char inp[256]; | |
1407 | MIDI_BUF_DECLARE(idx); | 1446 | MIDI_BUF_DECLARE(idx); | |
1408 | MIDI_BUF_DECLARE(buf); | 1447 | MIDI_BUF_DECLARE(buf); | |
1409 | size_t idxspace; | 1448 | size_t idxspace; | |
1410 | size_t bufspace; | 1449 | size_t bufspace; | |
@@ -1412,66 +1451,70 @@ midiwrite(dev_t dev, struct uio *uio, in | @@ -1412,66 +1451,70 @@ midiwrite(dev_t dev, struct uio *uio, in | |||
1412 | int pollout = 0; | 1451 | int pollout = 0; | |
1413 | 1452 | |||
1414 | (void)buf_end; (void)idx_end; | 1453 | (void)buf_end; (void)idx_end; | |
1415 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | 1454 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | |
1416 | 1455 | |||
1417 | DPRINTFN(6,("midiwrite: %p, unit=%d, count=%lu\n", sc, (int)minor(dev), | 1456 | DPRINTFN(6,("midiwrite: %p, unit=%d, count=%lu\n", sc, (int)minor(dev), | |
1418 | (unsigned long)uio->uio_resid)); | 1457 | (unsigned long)uio->uio_resid)); | |
1419 | 1458 | |||
1420 | mutex_enter(sc->lock); | 1459 | mutex_enter(sc->lock); | |
1421 | if (sc->dying) { | 1460 | if (sc->dying) { | |
1422 | mutex_exit(sc->lock); | 1461 | mutex_exit(sc->lock); | |
1423 | return EIO; | 1462 | return EIO; | |
1424 | } | 1463 | } | |
1464 | ||||
1465 | sc->refcnt++; | |||
1466 | ||||
1425 | mb = &sc->outbuf; | 1467 | mb = &sc->outbuf; | |
1426 | error = 0; | 1468 | error = 0; | |
1427 | while (uio->uio_resid > 0 && !error) { | 1469 | while (uio->uio_resid > 0 && !error) { | |
1428 | /* | 1470 | /* | |
1429 | * block if necessary for the minimum buffer space to guarantee | 1471 | * block if necessary for the minimum buffer space to guarantee | |
1430 | * we can write something. | 1472 | * we can write something. | |
1431 | */ | 1473 | */ | |
1432 | MIDI_BUF_PRODUCER_INIT(mb,idx); /* init can't go above loop; */ | 1474 | MIDI_BUF_PRODUCER_INIT(mb,idx); /* init can't go above loop; */ | |
1433 | MIDI_BUF_PRODUCER_INIT(mb,buf); /* real_writebytes moves cur */ | 1475 | MIDI_BUF_PRODUCER_INIT(mb,buf); /* real_writebytes moves cur */ | |
1434 | for (;;) { | 1476 | for (;;) { | |
1435 | idxspace = MIDI_BUF_PRODUCER_REFRESH(mb,idx) - idx_cur; | 1477 | idxspace = MIDI_BUF_PRODUCER_REFRESH(mb,idx) - idx_cur; | |
1436 | bufspace = MIDI_BUF_PRODUCER_REFRESH(mb,buf) - buf_cur; | 1478 | bufspace = MIDI_BUF_PRODUCER_REFRESH(mb,buf) - buf_cur; | |
1437 | if (idxspace >= 1 && bufspace >= 3 && !pollout) | 1479 | if (idxspace >= 1 && bufspace >= 3 && !pollout) | |
1438 | break; | 1480 | break; | |
1439 | DPRINTFN(8,("midi_write: sleep idx=%zd buf=%zd\n", | 1481 | DPRINTFN(8,("midi_write: sleep idx=%zd buf=%zd\n", | |
1440 | idxspace, bufspace)); | 1482 | idxspace, bufspace)); | |
1441 | if (ioflag & IO_NDELAY) { | 1483 | if (ioflag & IO_NDELAY) { | |
1442 | /* | 1484 | /* | |
1443 | * If some amount has already been transferred, | 1485 | * If some amount has already been transferred, | |
1444 | * the common syscall code will automagically | 1486 | * the common syscall code will automagically | |
1445 | * convert this to success with a short count. | 1487 | * convert this to success with a short count. | |
1446 | */ | 1488 | */ | |
1447 | mutex_exit(sc->lock); | 1489 | error = EWOULDBLOCK; | |
1448 | return EWOULDBLOCK; | 1490 | goto out; | |
1449 | } | 1491 | } | |
1450 | if (pollout) { | 1492 | if (pollout) { | |
1451 | mutex_exit(sc->lock); | 1493 | mutex_exit(sc->lock); | |
1452 | yield(); /* see midi_poll_output */ | 1494 | yield(); /* see midi_poll_output */ | |
1453 | mutex_enter(sc->lock); | 1495 | mutex_enter(sc->lock); | |
1454 | pollout = 0; | 1496 | pollout = 0; | |
1455 | } else | 1497 | } else | |
1456 | error = cv_wait_sig(&sc->wchan, sc->lock); | 1498 | error = cv_wait_sig(&sc->wchan, sc->lock); | |
1499 | if (sc->dying) | |||
1500 | error = EIO; | |||
1457 | if (error) { | 1501 | if (error) { | |
1458 | /* | 1502 | /* | |
1459 | * Similarly, the common code will handle | 1503 | * Similarly, the common code will handle | |
1460 | * EINTR and ERESTART properly here, changing to | 1504 | * EINTR and ERESTART properly here, changing to | |
1461 | * a short count if something transferred. | 1505 | * a short count if something transferred. | |
1462 | */ | 1506 | */ | |
1463 | mutex_exit(sc->lock); | 1507 | goto out; | |
1464 | return error; | |||
1465 | } | 1508 | } | |
1466 | } | 1509 | } | |
1467 | 1510 | |||
1468 | /* | 1511 | /* | |
1469 | * The number of bytes we can safely extract from the uio | 1512 | * The number of bytes we can safely extract from the uio | |
1470 | * depends on the available idx and buf space. Worst case, | 1513 | * depends on the available idx and buf space. Worst case, | |
1471 | * every byte is a message so 1 idx is required per byte. | 1514 | * every byte is a message so 1 idx is required per byte. | |
1472 | * Worst case, the first byte completes a 3-byte msg in prior | 1515 | * Worst case, the first byte completes a 3-byte msg in prior | |
1473 | * state, and every subsequent byte is a Program Change or | 1516 | * state, and every subsequent byte is a Program Change or | |
1474 | * Channel Pressure msg with running status and expands to 2 | 1517 | * Channel Pressure msg with running status and expands to 2 | |
1475 | * bytes, so the buf space reqd is 3+2(n-1) or 2n+1. So limit | 1518 | * bytes, so the buf space reqd is 3+2(n-1) or 2n+1. So limit | |
1476 | * the transfer to the min of idxspace and (bufspace-1)>>1. | 1519 | * the transfer to the min of idxspace and (bufspace-1)>>1. | |
1477 | */ | 1520 | */ | |
@@ -1482,192 +1525,220 @@ midiwrite(dev_t dev, struct uio *uio, in | @@ -1482,192 +1525,220 @@ midiwrite(dev_t dev, struct uio *uio, in | |||
1482 | xfrcount = sizeof inp; | 1525 | xfrcount = sizeof inp; | |
1483 | if (xfrcount > uio->uio_resid) | 1526 | if (xfrcount > uio->uio_resid) | |
1484 | xfrcount = uio->uio_resid; | 1527 | xfrcount = uio->uio_resid; | |
1485 | 1528 | |||
1486 | mutex_exit(sc->lock); | 1529 | mutex_exit(sc->lock); | |
1487 | error = uiomove(inp, xfrcount, uio); | 1530 | error = uiomove(inp, xfrcount, uio); | |
1488 | mutex_enter(sc->lock); | 1531 | mutex_enter(sc->lock); | |
1489 | #ifdef MIDI_DEBUG | 1532 | #ifdef MIDI_DEBUG | |
1490 | if (error) | 1533 | if (error) | |
1491 | printf("midi_write:(1) uiomove failed %d; " | 1534 | printf("midi_write:(1) uiomove failed %d; " | |
1492 | "xfrcount=%zu inp=%p\n", | 1535 | "xfrcount=%zu inp=%p\n", | |
1493 | error, xfrcount, inp); | 1536 | error, xfrcount, inp); | |
1494 | #endif | 1537 | #endif | |
1495 | if ( error ) | 1538 | if (error) | |
1496 | break; | 1539 | break; | |
1497 | 1540 | |||
1498 | /* | 1541 | /* | |
1499 | * The number of bytes we extracted being calculated to | 1542 | * The number of bytes we extracted being calculated to | |
1500 | * definitely fit in the buffer even with canonicalization, | 1543 | * definitely fit in the buffer even with canonicalization, | |
1501 | * there is no excuse for real_writebytes to return EWOULDBLOCK. | 1544 | * there is no excuse for real_writebytes to return EWOULDBLOCK. | |
1502 | */ | 1545 | */ | |
1503 | error = real_writebytes(sc, inp, xfrcount); | 1546 | error = real_writebytes(sc, inp, xfrcount); | |
1504 | KASSERT(error != EWOULDBLOCK); | 1547 | KASSERT(error != EWOULDBLOCK); | |
1505 | if (error) | 1548 | if (error) | |
1506 | break; | 1549 | break; | |
1507 | 1550 | |||
1508 | /* | 1551 | /* | |
1509 | * If this is a polling device and we just sent a buffer, let's | 1552 | * If this is a polling device and we just sent a buffer, let's | |
1510 | * not send another without giving some other process a chance. | 1553 | * not send another without giving some other process a chance. | |
1511 | */ | 1554 | */ | |
1512 | if ((sc->props & MIDI_PROP_OUT_INTR) == 0) | 1555 | if ((sc->props & MIDI_PROP_OUT_INTR) == 0) | |
1513 | pollout = 1; | 1556 | pollout = 1; | |
1514 | DPRINTFN(8,("midiwrite: uio_resid now %zu, props=%d\n", | 1557 | DPRINTFN(8,("midiwrite: uio_resid now %zu, props=%d\n", | |
1515 | uio->uio_resid, sc->props)); | 1558 | uio->uio_resid, sc->props)); | |
1516 | } | 1559 | } | |
1560 | ||||
1561 | out: | |||
1562 | if (--sc->refcnt < 0) | |||
1563 | cv_broadcast(&sc->detach_cv); | |||
1564 | ||||
1517 | mutex_exit(sc->lock); | 1565 | mutex_exit(sc->lock); | |
1518 | return error; | 1566 | return error; | |
1519 | } | 1567 | } | |
1520 | 1568 | |||
1521 | /* | 1569 | /* | |
1522 | * This write routine is only called from sequencer code and expects | 1570 | * This write routine is only called from sequencer code and expects | |
1523 | * a write that is smaller than the MIDI buffer. | 1571 | * a write that is smaller than the MIDI buffer. | |
1524 | */ | 1572 | */ | |
1525 | int | 1573 | int | |
1526 | midi_writebytes(int unit, u_char *bf, int cc) | 1574 | midi_writebytes(int unit, u_char *bf, int cc) | |
1527 | { | 1575 | { | |
1528 | struct midi_softc *sc = | 1576 | struct midi_softc *sc = | |
1529 | device_lookup_private(&midi_cd, unit); | 1577 | device_lookup_private(&midi_cd, unit); | |
1530 | int error; | 1578 | int error; | |
1531 | 1579 | |||
1580 | if (!sc) | |||
1581 | return EIO; | |||
1582 | ||||
1532 | DPRINTFN(7, ("midi_writebytes: %p, unit=%d, cc=%d %#02x %#02x %#02x\n", | 1583 | DPRINTFN(7, ("midi_writebytes: %p, unit=%d, cc=%d %#02x %#02x %#02x\n", | |
1533 | sc, unit, cc, bf[0], bf[1], bf[2])); | 1584 | sc, unit, cc, bf[0], bf[1], bf[2])); | |
1534 | 1585 | |||
1535 | mutex_enter(sc->lock); | 1586 | mutex_enter(sc->lock); | |
1536 | error = real_writebytes(sc, bf, cc); | 1587 | if (sc->dying) | |
1588 | error = EIO; | |||
1589 | else | |||
1590 | error = real_writebytes(sc, bf, cc); | |||
1537 | mutex_exit(sc->lock); | 1591 | mutex_exit(sc->lock); | |
1538 | 1592 | |||
1539 | return error; | 1593 | return error; | |
1540 | } | 1594 | } | |
1541 | 1595 | |||
1542 | static int | 1596 | static int | |
1543 | midiioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) | 1597 | midiioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) | |
1544 | { | 1598 | { | |
1545 | struct midi_softc *sc; | 1599 | struct midi_softc *sc; | |
1546 | const struct midi_hw_if *hw; | 1600 | const struct midi_hw_if *hw; | |
1547 | int error; | 1601 | int error; | |
1548 | MIDI_BUF_DECLARE(buf); | 1602 | MIDI_BUF_DECLARE(buf); | |
1549 | 1603 | |||
1550 | (void)buf_end; | 1604 | (void)buf_end; | |
1551 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev));; | 1605 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | |
1552 | if (sc->dying) | 1606 | ||
1607 | mutex_enter(sc->lock); | |||
1608 | if (sc->dying) { | |||
1609 | mutex_exit(sc->lock); | |||
1553 | return EIO; | 1610 | return EIO; | |
1611 | } | |||
1554 | hw = sc->hw_if; | 1612 | hw = sc->hw_if; | |
1555 | error = 0; | 1613 | error = 0; | |
1556 | 1614 | |||
1615 | sc->refcnt++; | |||
1616 | ||||
1557 | DPRINTFN(5,("midiioctl: %p cmd=0x%08lx\n", sc, cmd)); | 1617 | DPRINTFN(5,("midiioctl: %p cmd=0x%08lx\n", sc, cmd)); | |
1558 | 1618 | |||
1559 | switch (cmd) { | 1619 | switch (cmd) { | |
1560 | case FIONBIO: | 1620 | case FIONBIO: | |
1561 | /* All handled in the upper layer. */ | 1621 | /* All handled in the upper layer. */ | |
1562 | break; | 1622 | break; | |
1563 | 1623 | |||
1564 | case FIONREAD: | 1624 | case FIONREAD: | |
1565 | /* | 1625 | /* | |
1566 | * This code relies on the current implementation of midi_in | 1626 | * This code relies on the current implementation of midi_in | |
1567 | * always updating buf and idx together in a critical section, | 1627 | * always updating buf and idx together in a critical section, | |
1568 | * so buf always ends at a message boundary. Document this | 1628 | * so buf always ends at a message boundary. Document this | |
1569 | * ioctl as always returning a value such that the last message | 1629 | * ioctl as always returning a value such that the last message | |
1570 | * included is complete (SysEx the only exception), and then | 1630 | * included is complete (SysEx the only exception), and then | |
1571 | * make sure the implementation doesn't regress. NB that | 1631 | * make sure the implementation doesn't regress. NB that | |
1572 | * means if this ioctl returns n and the proc then issues a | 1632 | * means if this ioctl returns n and the proc then issues a | |
1573 | * read of n, n bytes will be read, but if the proc issues a | 1633 | * read of n, n bytes will be read, but if the proc issues a | |
1574 | * read of m < n, fewer than m bytes may be read to ensure the | 1634 | * read of m < n, fewer than m bytes may be read to ensure the | |
1575 | * read ends at a message boundary. | 1635 | * read ends at a message boundary. | |
1576 | */ | 1636 | */ | |
1577 | mutex_enter(sc->lock); | |||
1578 | MIDI_BUF_CONSUMER_INIT(&sc->inbuf,buf); | 1637 | MIDI_BUF_CONSUMER_INIT(&sc->inbuf,buf); | |
1579 | *(int *)addr = buf_lim - buf_cur; | 1638 | *(int *)addr = buf_lim - buf_cur; | |
1580 | mutex_exit(sc->lock); | |||
1581 | break; | 1639 | break; | |
1582 | 1640 | |||
1583 | case FIOASYNC: | 1641 | case FIOASYNC: | |
1642 | mutex_exit(sc->lock); | |||
1584 | mutex_enter(proc_lock); | 1643 | mutex_enter(proc_lock); | |
1585 | if (*(int *)addr) { | 1644 | if (*(int *)addr) { | |
1586 | if (sc->async) { | 1645 | if (sc->async) { | |
1587 | error = EBUSY; | 1646 | error = EBUSY; | |
1588 | } else { | 1647 | } else { | |
1589 | sc->async = curproc->p_pid; | 1648 | sc->async = curproc->p_pid; | |
1590 | } | 1649 | } | |
1591 | DPRINTFN(5,("midi_ioctl: FIOASYNC %d\n", | 1650 | DPRINTFN(5,("midi_ioctl: FIOASYNC %d\n", | |
1592 | curproc->p_pid)); | 1651 | curproc->p_pid)); | |
1593 | } else { | 1652 | } else { | |
1594 | sc->async = 0; | 1653 | sc->async = 0; | |
1595 | } | 1654 | } | |
1596 | mutex_exit(proc_lock); | 1655 | mutex_exit(proc_lock); | |
1656 | mutex_enter(sc->lock); | |||
1597 | break; | 1657 | break; | |
1598 | 1658 | |||
1599 | #if 0 | 1659 | #if 0 | |
1600 | case MIDI_PRETIME: | 1660 | case MIDI_PRETIME: | |
1601 | /* XXX OSS | 1661 | /* XXX OSS | |
1602 | * This should set up a read timeout, but that's | 1662 | * This should set up a read timeout, but that's | |
1603 | * why we have poll(), so there's nothing yet. */ | 1663 | * why we have poll(), so there's nothing yet. */ | |
1604 | error = EINVAL; | 1664 | error = EINVAL; | |
1605 | break; | 1665 | break; | |
1606 | #endif | 1666 | #endif | |
1607 | 1667 | |||
1608 | #ifdef MIDI_SAVE | 1668 | #ifdef MIDI_SAVE | |
1609 | case MIDI_GETSAVE: | 1669 | case MIDI_GETSAVE: | |
1670 | mutex_exit(sc->lock); | |||
1610 | error = copyout(&midisave, *(void **)addr, sizeof midisave); | 1671 | error = copyout(&midisave, *(void **)addr, sizeof midisave); | |
1672 | mutex_enter(sc->lock); | |||
1611 | break; | 1673 | break; | |
1612 | #endif | 1674 | #endif | |
1613 | 1675 | |||
1614 | default: | 1676 | default: | |
1615 | if (hw->ioctl != NULL) { | 1677 | if (hw->ioctl != NULL) { | |
1616 | mutex_enter(sc->lock); | |||
1617 | error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, l); | 1678 | error = hw->ioctl(sc->hw_hdl, cmd, addr, flag, l); | |
1618 | mutex_exit(sc->lock); | |||
1619 | } else { | 1679 | } else { | |
1620 | error = EINVAL; | 1680 | error = EINVAL; | |
1621 | } | 1681 | } | |
1622 | break; | 1682 | break; | |
1623 | } | 1683 | } | |
1684 | ||||
1685 | if (--sc->refcnt < 0) | |||
1686 | cv_broadcast(&sc->detach_cv); | |||
1687 | mutex_exit(sc->lock); | |||
1624 | return error; | 1688 | return error; | |
1625 | } | 1689 | } | |
1626 | 1690 | |||
1627 | static int | 1691 | static int | |
1628 | midipoll(dev_t dev, int events, struct lwp *l) | 1692 | midipoll(dev_t dev, int events, struct lwp *l) | |
1629 | { | 1693 | { | |
1630 | struct midi_softc *sc; | 1694 | struct midi_softc *sc; | |
1631 | int revents; | 1695 | int revents; | |
1632 | MIDI_BUF_DECLARE(idx); | 1696 | MIDI_BUF_DECLARE(idx); | |
1633 | MIDI_BUF_DECLARE(buf); | 1697 | MIDI_BUF_DECLARE(buf); | |
1634 | 1698 | |||
1635 | (void)buf_end; (void)idx_end; | 1699 | (void)buf_end; (void)idx_end; | |
1636 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | 1700 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | |
1637 | revents = 0; | 1701 | revents = 0; | |
1638 | 1702 | |||
1639 | DPRINTFN(6,("midipoll: %p events=0x%x\n", sc, events)); | 1703 | DPRINTFN(6,("midipoll: %p events=0x%x\n", sc, events)); | |
1640 | 1704 | |||
1641 | mutex_enter(sc->lock); | 1705 | mutex_enter(sc->lock); | |
1642 | if (sc->dying) { | 1706 | if (sc->dying) { | |
1643 | mutex_exit(sc->lock); | 1707 | mutex_exit(sc->lock); | |
1644 | return POLLHUP; | 1708 | return POLLHUP; | |
1645 | } | 1709 | } | |
1710 | ||||
1711 | sc->refcnt++; | |||
1712 | ||||
1646 | if ((events & (POLLIN | POLLRDNORM)) != 0) { | 1713 | if ((events & (POLLIN | POLLRDNORM)) != 0) { | |
1647 | MIDI_BUF_CONSUMER_INIT(&sc->inbuf, idx); | 1714 | MIDI_BUF_CONSUMER_INIT(&sc->inbuf, idx); | |
1648 | if (idx_cur < idx_lim) | 1715 | if (idx_cur < idx_lim) | |
1649 | revents |= events & (POLLIN | POLLRDNORM); | 1716 | revents |= events & (POLLIN | POLLRDNORM); | |
1650 | else | 1717 | else | |
1651 | selrecord(l, &sc->rsel); | 1718 | selrecord(l, &sc->rsel); | |
1652 | } | 1719 | } | |
1653 | if ((events & (POLLOUT | POLLWRNORM)) != 0) { | 1720 | if ((events & (POLLOUT | POLLWRNORM)) != 0) { | |
1654 | MIDI_BUF_PRODUCER_INIT(&sc->outbuf, idx); | 1721 | MIDI_BUF_PRODUCER_INIT(&sc->outbuf, idx); | |
1655 | MIDI_BUF_PRODUCER_INIT(&sc->outbuf, buf); | 1722 | MIDI_BUF_PRODUCER_INIT(&sc->outbuf, buf); | |
1656 | if (idx_lim - idx_cur >= 1 && buf_lim - buf_cur >= 3) | 1723 | if (idx_lim - idx_cur >= 1 && buf_lim - buf_cur >= 3) | |
1657 | revents |= events & (POLLOUT | POLLWRNORM); | 1724 | revents |= events & (POLLOUT | POLLWRNORM); | |
1658 | else | 1725 | else | |
1659 | selrecord(l, &sc->wsel); | 1726 | selrecord(l, &sc->wsel); | |
1660 | } | 1727 | } | |
1728 | ||||
1729 | if (--sc->refcnt < 0) | |||
1730 | cv_broadcast(&sc->detach_cv); | |||
1731 | ||||
1661 | mutex_exit(sc->lock); | 1732 | mutex_exit(sc->lock); | |
1662 | 1733 | |||
1663 | return revents; | 1734 | return revents; | |
1664 | } | 1735 | } | |
1665 | 1736 | |||
1666 | static void | 1737 | static void | |
1667 | filt_midirdetach(struct knote *kn) | 1738 | filt_midirdetach(struct knote *kn) | |
1668 | { | 1739 | { | |
1669 | struct midi_softc *sc = kn->kn_hook; | 1740 | struct midi_softc *sc = kn->kn_hook; | |
1670 | 1741 | |||
1671 | mutex_enter(sc->lock); | 1742 | mutex_enter(sc->lock); | |
1672 | SLIST_REMOVE(&sc->rsel.sel_klist, kn, knote, kn_selnext); | 1743 | SLIST_REMOVE(&sc->rsel.sel_klist, kn, knote, kn_selnext); | |
1673 | mutex_exit(sc->lock); | 1744 | mutex_exit(sc->lock); | |
@@ -1699,68 +1770,85 @@ filt_midiwdetach(struct knote *kn) | @@ -1699,68 +1770,85 @@ filt_midiwdetach(struct knote *kn) | |||
1699 | 1770 | |||
1700 | mutex_enter(sc->lock); | 1771 | mutex_enter(sc->lock); | |
1701 | SLIST_REMOVE(&sc->wsel.sel_klist, kn, knote, kn_selnext); | 1772 | SLIST_REMOVE(&sc->wsel.sel_klist, kn, knote, kn_selnext); | |
1702 | mutex_exit(sc->lock); | 1773 | mutex_exit(sc->lock); | |
1703 | } | 1774 | } | |
1704 | 1775 | |||
1705 | static int | 1776 | static int | |
1706 | filt_midiwrite(struct knote *kn, long hint) | 1777 | filt_midiwrite(struct knote *kn, long hint) | |
1707 | { | 1778 | { | |
1708 | struct midi_softc *sc = kn->kn_hook; | 1779 | struct midi_softc *sc = kn->kn_hook; | |
1709 | MIDI_BUF_DECLARE(idx); | 1780 | MIDI_BUF_DECLARE(idx); | |
1710 | MIDI_BUF_DECLARE(buf); | 1781 | MIDI_BUF_DECLARE(buf); | |
1711 | 1782 | |||
1783 | mutex_exit(sc->lock); | |||
1784 | sc->refcnt++; | |||
1785 | mutex_enter(sc->lock); | |||
1786 | ||||
1712 | (void)idx_end; (void)buf_end; | 1787 | (void)idx_end; (void)buf_end; | |
1713 | if (hint != NOTE_SUBMIT) | 1788 | if (hint != NOTE_SUBMIT) | |
1714 | mutex_enter(sc->lock); | 1789 | mutex_enter(sc->lock); | |
1715 | MIDI_BUF_PRODUCER_INIT(&sc->outbuf,idx); | 1790 | MIDI_BUF_PRODUCER_INIT(&sc->outbuf,idx); | |
1716 | MIDI_BUF_PRODUCER_INIT(&sc->outbuf,buf); | 1791 | MIDI_BUF_PRODUCER_INIT(&sc->outbuf,buf); | |
1717 | kn->kn_data = ((buf_lim - buf_cur)-1)>>1; | 1792 | kn->kn_data = ((buf_lim - buf_cur)-1)>>1; | |
1718 | if (kn->kn_data > idx_lim - idx_cur) | 1793 | if (kn->kn_data > idx_lim - idx_cur) | |
1719 | kn->kn_data = idx_lim - idx_cur; | 1794 | kn->kn_data = idx_lim - idx_cur; | |
1720 | if (hint != NOTE_SUBMIT) | 1795 | if (hint != NOTE_SUBMIT) | |
1721 | mutex_exit(sc->lock); | 1796 | mutex_exit(sc->lock); | |
1797 | ||||
1798 | // XXXMRG -- move this up, avoid the relock? | |||
1799 | mutex_enter(sc->lock); | |||
1800 | if (--sc->refcnt < 0) | |||
1801 | cv_broadcast(&sc->detach_cv); | |||
1802 | mutex_exit(sc->lock); | |||
1803 | ||||
1722 | return (kn->kn_data > 0); | 1804 | return (kn->kn_data > 0); | |
1723 | } | 1805 | } | |
1724 | 1806 | |||
1725 | static const struct filterops midiwrite_filtops = | 1807 | static const struct filterops midiwrite_filtops = | |
1726 | { 1, NULL, filt_midiwdetach, filt_midiwrite }; | 1808 | { 1, NULL, filt_midiwdetach, filt_midiwrite }; | |
1727 | 1809 | |||
1728 | int | 1810 | int | |
1729 | midikqfilter(dev_t dev, struct knote *kn) | 1811 | midikqfilter(dev_t dev, struct knote *kn) | |
1730 | { | 1812 | { | |
1731 | struct midi_softc *sc = | 1813 | struct midi_softc *sc = | |
1732 | device_lookup_private(&midi_cd, MIDIUNIT(dev)); | 1814 | device_lookup_private(&midi_cd, MIDIUNIT(dev)); | |
1733 | struct klist *klist; | 1815 | struct klist *klist; | |
1734 | 1816 | |||
1817 | mutex_exit(sc->lock); | |||
1818 | sc->refcnt++; | |||
1819 | mutex_enter(sc->lock); | |||
1820 | ||||
1735 | switch (kn->kn_filter) { | 1821 | switch (kn->kn_filter) { | |
1736 | case EVFILT_READ: | 1822 | case EVFILT_READ: | |
1737 | klist = &sc->rsel.sel_klist; | 1823 | klist = &sc->rsel.sel_klist; | |
1738 | kn->kn_fop = &midiread_filtops; | 1824 | kn->kn_fop = &midiread_filtops; | |
1739 | break; | 1825 | break; | |
1740 | 1826 | |||
1741 | case EVFILT_WRITE: | 1827 | case EVFILT_WRITE: | |
1742 | klist = &sc->wsel.sel_klist; | 1828 | klist = &sc->wsel.sel_klist; | |
1743 | kn->kn_fop = &midiwrite_filtops; | 1829 | kn->kn_fop = &midiwrite_filtops; | |
1744 | break; | 1830 | break; | |
1745 | 1831 | |||
1746 | default: | 1832 | default: | |
1747 | return (EINVAL); | 1833 | return (EINVAL); | |
1748 | } | 1834 | } | |
1749 | 1835 | |||
1750 | kn->kn_hook = sc; | 1836 | kn->kn_hook = sc; | |
1751 | 1837 | |||
1752 | mutex_enter(sc->lock); | 1838 | mutex_enter(sc->lock); | |
1753 | SLIST_INSERT_HEAD(klist, kn, kn_selnext); | 1839 | SLIST_INSERT_HEAD(klist, kn, kn_selnext); | |
1840 | if (--sc->refcnt < 0) | |||
1841 | cv_broadcast(&sc->detach_cv); | |||
1754 | mutex_exit(sc->lock); | 1842 | mutex_exit(sc->lock); | |
1755 | 1843 | |||
1756 | return (0); | 1844 | return (0); | |
1757 | } | 1845 | } | |
1758 | 1846 | |||
1759 | void | 1847 | void | |
1760 | midi_getinfo(dev_t dev, struct midi_info *mi) | 1848 | midi_getinfo(dev_t dev, struct midi_info *mi) | |
1761 | { | 1849 | { | |
1762 | struct midi_softc *sc; | 1850 | struct midi_softc *sc; | |
1763 | 1851 | |||
1764 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | 1852 | sc = device_lookup_private(&midi_cd, MIDIUNIT(dev)); | |
1765 | if (sc == NULL) | 1853 | if (sc == NULL) | |
1766 | return; | 1854 | return; |
--- src/sys/dev/midi_if.h 2012/04/09 10:18:16 1.25
+++ src/sys/dev/midi_if.h 2015/01/11 14:13:25 1.25.14.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: midi_if.h,v 1.25 2012/04/09 10:18:16 plunky Exp $ */ | 1 | /* $NetBSD: midi_if.h,v 1.25.14.1 2015/01/11 14:13:25 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (augustss@NetBSD.org). | 8 | * by Lennart Augustsson (augustss@NetBSD.org). | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -40,31 +40,31 @@ struct midi_info { | @@ -40,31 +40,31 @@ struct midi_info { | |||
40 | }; | 40 | }; | |
41 | #define MIDI_PROP_OUT_INTR 1 | 41 | #define MIDI_PROP_OUT_INTR 1 | |
42 | #define MIDI_PROP_CAN_INPUT 2 | 42 | #define MIDI_PROP_CAN_INPUT 2 | |
43 | #define MIDI_PROP_NO_OUTPUT 4 | 43 | #define MIDI_PROP_NO_OUTPUT 4 | |
44 | 44 | |||
45 | /* | 45 | /* | |
46 | * XXX expand | 46 | * XXX expand | |
47 | * | 47 | * | |
48 | * List of hardware interface methods, and when locks are held by each | 48 | * List of hardware interface methods, and when locks are held by each | |
49 | * called by this module: | 49 | * called by this module: | |
50 | * | 50 | * | |
51 | * METHOD INTR NOTES | 51 | * METHOD INTR NOTES | |
52 | * ----------------------- ------- ------------------------- | 52 | * ----------------------- ------- ------------------------- | |
53 | * open - | 53 | * open held | |
54 | * close - | 54 | * close held | |
55 | * output - | 55 | * output held | |
56 | * getinfo - Called at attach time | 56 | * getinfo held Called at attach time | |
57 | * ioctl - | 57 | * ioctl held | |
58 | * get_locks - Called at attach time | 58 | * get_locks - Called at attach time | |
59 | */ | 59 | */ | |
60 | 60 | |||
61 | struct midi_softc; | 61 | struct midi_softc; | |
62 | 62 | |||
63 | struct midi_hw_if { | 63 | struct midi_hw_if { | |
64 | int (*open)(void *, int, /* open hardware */ | 64 | int (*open)(void *, int, /* open hardware */ | |
65 | void (*)(void *, int), /* input callback */ | 65 | void (*)(void *, int), /* input callback */ | |
66 | void (*)(void *), /* output callback */ | 66 | void (*)(void *), /* output callback */ | |
67 | void *); | 67 | void *); | |
68 | void (*close)(void *); /* close hardware */ | 68 | void (*close)(void *); /* close hardware */ | |
69 | int (*output)(void *, int); /* output a byte */ | 69 | int (*output)(void *, int); /* output a byte */ | |
70 | void (*getinfo)(void *, struct midi_info *); | 70 | void (*getinfo)(void *, struct midi_info *); |
--- src/sys/dev/midivar.h 2012/04/05 20:25:53 1.19
+++ src/sys/dev/midivar.h 2015/01/11 14:13:25 1.19.14.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: midivar.h,v 1.19 2012/04/05 20:25:53 plunky Exp $ */ | 1 | /* $NetBSD: midivar.h,v 1.19.14.1 2015/01/11 14:13:25 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (augustss@NetBSD.org) and (midi FST refactoring and | 8 | * by Lennart Augustsson (augustss@NetBSD.org) and (midi FST refactoring and | |
9 | * Active Sense) Chapman Flack (chap@NetBSD.org). | 9 | * Active Sense) Chapman Flack (chap@NetBSD.org). | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -179,26 +179,28 @@ struct midi_state { | @@ -179,26 +179,28 @@ struct midi_state { | |||
179 | }; | 179 | }; | |
180 | 180 | |||
181 | struct midi_softc { | 181 | struct midi_softc { | |
182 | device_t dev; /* Hardware device struct */ | 182 | device_t dev; /* Hardware device struct */ | |
183 | void *hw_hdl; /* Hardware driver handle */ | 183 | void *hw_hdl; /* Hardware driver handle */ | |
184 | const struct midi_hw_if *hw_if; /* Hardware interface */ | 184 | const struct midi_hw_if *hw_if; /* Hardware interface */ | |
185 | const struct midi_hw_if_ext *hw_if_ext; /* see midi_if.h */ | 185 | const struct midi_hw_if_ext *hw_if_ext; /* see midi_if.h */ | |
186 | int isopen; /* Open indicator */ | 186 | int isopen; /* Open indicator */ | |
187 | int flags; /* Open flags */ | 187 | int flags; /* Open flags */ | |
188 | int dying; | 188 | int dying; | |
189 | struct midi_buffer outbuf; | 189 | struct midi_buffer outbuf; | |
190 | struct midi_buffer inbuf; | 190 | struct midi_buffer inbuf; | |
191 | int props; | 191 | int props; | |
192 | int refcnt; | |||
193 | kcondvar_t detach_cv; | |||
192 | kcondvar_t rchan; | 194 | kcondvar_t rchan; | |
193 | kcondvar_t wchan; | 195 | kcondvar_t wchan; | |
194 | kmutex_t *lock; | 196 | kmutex_t *lock; | |
195 | int pbus; | 197 | int pbus; | |
196 | int rcv_expect_asense; | 198 | int rcv_expect_asense; | |
197 | int rcv_quiescent; | 199 | int rcv_quiescent; | |
198 | int rcv_eof; | 200 | int rcv_eof; | |
199 | struct selinfo wsel; /* write selector */ | 201 | struct selinfo wsel; /* write selector */ | |
200 | struct selinfo rsel; /* read selector */ | 202 | struct selinfo rsel; /* read selector */ | |
201 | pid_t async; /* process who wants audio SIGIO */ | 203 | pid_t async; /* process who wants audio SIGIO */ | |
202 | void *sih; | 204 | void *sih; | |
203 | 205 | |||
204 | struct callout xmt_asense_co; | 206 | struct callout xmt_asense_co; |
--- src/sys/dev/sequencer.c 2014/07/25 08:10:35 1.59
+++ src/sys/dev/sequencer.c 2015/01/11 14:13:25 1.59.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: sequencer.c,v 1.59 2014/07/25 08:10:35 dholland Exp $ */ | 1 | /* $NetBSD: sequencer.c,v 1.59.2.1 2015/01/11 14:13:25 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (augustss@NetBSD.org) and by Andrew Doran. | 8 | * by Lennart Augustsson (augustss@NetBSD.org) and by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -45,27 +45,27 @@ | @@ -45,27 +45,27 @@ | |||
45 | * o MIDI softc locks. These can be spinlocks and there can be many of | 45 | * o MIDI softc locks. These can be spinlocks and there can be many of | |
46 | * them, because we can open many MIDI devices. We take these only in two | 46 | * them, because we can open many MIDI devices. We take these only in two | |
47 | * places: when enabling redirection from the MIDI device and when | 47 | * places: when enabling redirection from the MIDI device and when | |
48 | * disabling it (open/close). midiseq_in() is called by the MIDI driver | 48 | * disabling it (open/close). midiseq_in() is called by the MIDI driver | |
49 | * with its own lock held when passing data into this module. To avoid | 49 | * with its own lock held when passing data into this module. To avoid | |
50 | * lock order and context problems, we package the received message as a | 50 | * lock order and context problems, we package the received message as a | |
51 | * sequencer_pcqitem_t and put onto a producer-consumer queue. A soft | 51 | * sequencer_pcqitem_t and put onto a producer-consumer queue. A soft | |
52 | * interrupt is scheduled to dequeue and decode the message later where we | 52 | * interrupt is scheduled to dequeue and decode the message later where we | |
53 | * can safely acquire the sequencer device's sc_lock. PCQ is lockless for | 53 | * can safely acquire the sequencer device's sc_lock. PCQ is lockless for | |
54 | * multiple producer, single consumer settings like this one. | 54 | * multiple producer, single consumer settings like this one. | |
55 | */ | 55 | */ | |
56 | 56 | |||
57 | #include <sys/cdefs.h> | 57 | #include <sys/cdefs.h> | |
58 | __KERNEL_RCSID(0, "$NetBSD: sequencer.c,v 1.59 2014/07/25 08:10:35 dholland Exp $"); | 58 | __KERNEL_RCSID(0, "$NetBSD: sequencer.c,v 1.59.2.1 2015/01/11 14:13:25 martin Exp $"); | |
59 | 59 | |||
60 | #include "sequencer.h" | 60 | #include "sequencer.h" | |
61 | 61 | |||
62 | #include <sys/param.h> | 62 | #include <sys/param.h> | |
63 | #include <sys/ioctl.h> | 63 | #include <sys/ioctl.h> | |
64 | #include <sys/fcntl.h> | 64 | #include <sys/fcntl.h> | |
65 | #include <sys/vnode.h> | 65 | #include <sys/vnode.h> | |
66 | #include <sys/select.h> | 66 | #include <sys/select.h> | |
67 | #include <sys/poll.h> | 67 | #include <sys/poll.h> | |
68 | #include <sys/kmem.h> | 68 | #include <sys/kmem.h> | |
69 | #include <sys/proc.h> | 69 | #include <sys/proc.h> | |
70 | #include <sys/systm.h> | 70 | #include <sys/systm.h> | |
71 | #include <sys/syslog.h> | 71 | #include <sys/syslog.h> | |
@@ -164,91 +164,96 @@ const struct cdevsw sequencer_cdevsw = { | @@ -164,91 +164,96 @@ const struct cdevsw sequencer_cdevsw = { | |||
164 | .d_ioctl = sequencerioctl, | 164 | .d_ioctl = sequencerioctl, | |
165 | .d_stop = nostop, | 165 | .d_stop = nostop, | |
166 | .d_tty = notty, | 166 | .d_tty = notty, | |
167 | .d_poll = sequencerpoll, | 167 | .d_poll = sequencerpoll, | |
168 | .d_mmap = nommap, | 168 | .d_mmap = nommap, | |
169 | .d_kqfilter = sequencerkqfilter, | 169 | .d_kqfilter = sequencerkqfilter, | |
170 | .d_discard = nodiscard, | 170 | .d_discard = nodiscard, | |
171 | .d_flag = D_OTHER | D_MPSAFE | 171 | .d_flag = D_OTHER | D_MPSAFE | |
172 | }; | 172 | }; | |
173 | static LIST_HEAD(, sequencer_softc) sequencers = LIST_HEAD_INITIALIZER(sequencers); | 173 | static LIST_HEAD(, sequencer_softc) sequencers = LIST_HEAD_INITIALIZER(sequencers); | |
174 | static kmutex_t sequencer_lock; | 174 | static kmutex_t sequencer_lock; | |
175 | 175 | |||
176 | static void | 176 | static void | |
177 | sequencerdestroy(struct sequencer_softc *sc) { | 177 | sequencerdestroy(struct sequencer_softc *sc) | |
178 | { | |||
179 | callout_halt(&sc->sc_callout, &sc->lock); | |||
178 | callout_destroy(&sc->sc_callout); | 180 | callout_destroy(&sc->sc_callout); | |
179 | softint_disestablish(sc->sih); | 181 | softint_disestablish(sc->sih); | |
180 | cv_destroy(&sc->rchan); | 182 | cv_destroy(&sc->rchan); | |
181 | cv_destroy(&sc->wchan); | 183 | cv_destroy(&sc->wchan); | |
182 | cv_destroy(&sc->lchan); | 184 | cv_destroy(&sc->lchan); | |
183 | if (sc->pcq) | 185 | if (sc->pcq) | |
184 | pcq_destroy(sc->pcq); | 186 | pcq_destroy(sc->pcq); | |
185 | kmem_free(sc, sizeof(*sc)); | 187 | kmem_free(sc, sizeof(*sc)); | |
186 | } | 188 | } | |
187 | 189 | |||
188 | static struct sequencer_softc * | 190 | static struct sequencer_softc * | |
189 | sequencercreate(int unit) { | 191 | sequencercreate(int unit) | |
192 | { | |||
190 | struct sequencer_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); | 193 | struct sequencer_softc *sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); | |
191 | if (sc == NULL) { | 194 | if (sc == NULL) { | |
192 | #ifdef DIAGNOSTIC | 195 | #ifdef DIAGNOSTIC | |
193 | printf("%s: out of memory\n", __func__); | 196 | printf("%s: out of memory\n", __func__); | |
194 | #endif | 197 | #endif | |
195 | return NULL; | 198 | return NULL; | |
196 | } | 199 | } | |
197 | sc->sc_unit = unit; | 200 | sc->sc_unit = unit; | |
198 | callout_init(&sc->sc_callout, CALLOUT_MPSAFE); | 201 | callout_init(&sc->sc_callout, CALLOUT_MPSAFE); | |
199 | sc->sih = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, | 202 | sc->sih = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, | |
200 | seq_softintr, sc); | 203 | seq_softintr, sc); | |
201 | mutex_init(&sc->lock, MUTEX_DEFAULT, IPL_NONE); | 204 | mutex_init(&sc->lock, MUTEX_DEFAULT, IPL_NONE); | |
202 | cv_init(&sc->rchan, "midiseqr"); | 205 | cv_init(&sc->rchan, "midiseqr"); | |
203 | cv_init(&sc->wchan, "midiseqw"); | 206 | cv_init(&sc->wchan, "midiseqw"); | |
204 | cv_init(&sc->lchan, "midiseql"); | 207 | cv_init(&sc->lchan, "midiseql"); | |
205 | sc->pcq = pcq_create(SEQ_MAXQ, KM_SLEEP); | 208 | sc->pcq = pcq_create(SEQ_MAXQ, KM_SLEEP); | |
206 | if (sc->pcq == NULL) { | 209 | if (sc->pcq == NULL) { | |
207 | sequencerdestroy(sc); | 210 | sequencerdestroy(sc); | |
208 | return NULL; | 211 | return NULL; | |
209 | } | 212 | } | |
210 | return sc; | 213 | return sc; | |
211 | } | 214 | } | |
212 | 215 | |||
213 | 216 | |||
214 | static struct sequencer_softc * | 217 | static struct sequencer_softc * | |
215 | sequencerget(int unit) { | 218 | sequencerget(int unit) | |
219 | { | |||
216 | struct sequencer_softc *sc; | 220 | struct sequencer_softc *sc; | |
217 | if (unit < 0) { | 221 | if (unit < 0) { | |
218 | #ifdef DIAGNOSTIC | 222 | #ifdef DIAGNOSTIC | |
219 | panic("%s: unit %d!", __func__, unit); | 223 | panic("%s: unit %d!", __func__, unit); | |
220 | #endif | 224 | #endif | |
221 | return NULL; | 225 | return NULL; | |
222 | } | 226 | } | |
223 | mutex_enter(&sequencer_lock); | 227 | mutex_enter(&sequencer_lock); | |
224 | LIST_FOREACH(sc, &sequencers, sc_link) { | 228 | LIST_FOREACH(sc, &sequencers, sc_link) { | |
225 | if (sc->sc_unit == unit) { | 229 | if (sc->sc_unit == unit) { | |
226 | mutex_exit(&sequencer_lock); | 230 | mutex_exit(&sequencer_lock); | |
227 | return sc; | 231 | return sc; | |
228 | } | 232 | } | |
229 | } | 233 | } | |
230 | mutex_exit(&sequencer_lock); | 234 | mutex_exit(&sequencer_lock); | |
231 | if ((sc = sequencercreate(unit)) == NULL) | 235 | if ((sc = sequencercreate(unit)) == NULL) | |
232 | return NULL; | 236 | return NULL; | |
233 | mutex_enter(&sequencer_lock); | 237 | mutex_enter(&sequencer_lock); | |
234 | LIST_INSERT_HEAD(&sequencers, sc, sc_link); | 238 | LIST_INSERT_HEAD(&sequencers, sc, sc_link); | |
235 | mutex_exit(&sequencer_lock); | 239 | mutex_exit(&sequencer_lock); | |
236 | return sc; | 240 | return sc; | |
237 | } | 241 | } | |
238 | 242 | |||
239 | #ifdef notyet | 243 | #ifdef notyet | |
240 | static void | 244 | static void | |
241 | sequencerput(struct sequencer_softc *sc) { | 245 | sequencerput(struct sequencer_softc *sc) | |
246 | { | |||
242 | mutex_enter(&sequencer_lock); | 247 | mutex_enter(&sequencer_lock); | |
243 | LIST_REMOVE(sc, sc_link); | 248 | LIST_REMOVE(sc, sc_link); | |
244 | mutex_exit(&sequencer_lock); | 249 | mutex_exit(&sequencer_lock); | |
245 | sequencerdestroy(sc); | 250 | sequencerdestroy(sc); | |
246 | } | 251 | } | |
247 | #endif | 252 | #endif | |
248 | 253 | |||
249 | void | 254 | void | |
250 | sequencerattach(int n) | 255 | sequencerattach(int n) | |
251 | { | 256 | { | |
252 | mutex_init(&sequencer_lock, MUTEX_DEFAULT, IPL_NONE); | 257 | mutex_init(&sequencer_lock, MUTEX_DEFAULT, IPL_NONE); | |
253 | } | 258 | } | |
254 | 259 | |||
@@ -284,27 +289,27 @@ sequencer_enter(dev_t dev, struct sequen | @@ -284,27 +289,27 @@ sequencer_enter(dev_t dev, struct sequen | |||
284 | sequencer_exit(sc); | 289 | sequencer_exit(sc); | |
285 | return EIO; | 290 | return EIO; | |
286 | } | 291 | } | |
287 | *scp = sc; | 292 | *scp = sc; | |
288 | return 0; | 293 | return 0; | |
289 | } | 294 | } | |
290 | 295 | |||
291 | static int | 296 | static int | |
292 | sequenceropen(dev_t dev, int flags, int ifmt, struct lwp *l) | 297 | sequenceropen(dev_t dev, int flags, int ifmt, struct lwp *l) | |
293 | { | 298 | { | |
294 | struct sequencer_softc *sc; | 299 | struct sequencer_softc *sc; | |
295 | struct midi_dev *md; | 300 | struct midi_dev *md; | |
296 | struct midi_softc *msc; | 301 | struct midi_softc *msc; | |
297 | int error, unit; | 302 | int error, unit, mdno; | |
298 | 303 | |||
299 | DPRINTF(("sequenceropen\n")); | 304 | DPRINTF(("sequenceropen\n")); | |
300 | 305 | |||
301 | if ((error = sequencer_enter(dev, &sc)) != 0) | 306 | if ((error = sequencer_enter(dev, &sc)) != 0) | |
302 | return error; | 307 | return error; | |
303 | if (sc->isopen != 0) { | 308 | if (sc->isopen != 0) { | |
304 | sequencer_exit(sc); | 309 | sequencer_exit(sc); | |
305 | return EBUSY; | 310 | return EBUSY; | |
306 | } | 311 | } | |
307 | 312 | |||
308 | if (SEQ_IS_OLD(SEQUENCERUNIT(dev))) | 313 | if (SEQ_IS_OLD(SEQUENCERUNIT(dev))) | |
309 | sc->mode = SEQ_OLD; | 314 | sc->mode = SEQ_OLD; | |
310 | else | 315 | else | |
@@ -327,39 +332,48 @@ sequenceropen(dev_t dev, int flags, int | @@ -327,39 +332,48 @@ sequenceropen(dev_t dev, int flags, int | |||
327 | SEQ_QINIT(&sc->outq); | 332 | SEQ_QINIT(&sc->outq); | |
328 | sc->lowat = SEQ_MAXQ / 2; | 333 | sc->lowat = SEQ_MAXQ / 2; | |
329 | 334 | |||
330 | if (sc->ndevs > 0) { | 335 | if (sc->ndevs > 0) { | |
331 | mutex_exit(&sc->lock); | 336 | mutex_exit(&sc->lock); | |
332 | sc->devs = kmem_alloc(sc->ndevs * sizeof(struct midi_dev *), | 337 | sc->devs = kmem_alloc(sc->ndevs * sizeof(struct midi_dev *), | |
333 | KM_SLEEP); | 338 | KM_SLEEP); | |
334 | for (unit = 0; unit < sc->ndevs; unit++) { | 339 | for (unit = 0; unit < sc->ndevs; unit++) { | |
335 | md = midiseq_open(unit, flags); | 340 | md = midiseq_open(unit, flags); | |
336 | if (md) { | 341 | if (md) { | |
337 | sc->devs[sc->nmidi++] = md; | 342 | sc->devs[sc->nmidi++] = md; | |
338 | md->seq = sc; | 343 | md->seq = sc; | |
339 | md->doingsysex = 0; | 344 | md->doingsysex = 0; | |
345 | DPRINTF(("%s: midi unit %d opened as seq %p\n", | |||
346 | __func__, unit, md)); | |||
347 | } else { | |||
348 | DPRINTF(("%s: midi unit %d not opened as seq\n", | |||
349 | __func__, unit)); | |||
340 | } | 350 | } | |
341 | } | 351 | } | |
342 | mutex_enter(&sc->lock); | 352 | mutex_enter(&sc->lock); | |
343 | } else { | 353 | } else { | |
344 | sc->devs = NULL; | 354 | sc->devs = NULL; | |
345 | } | 355 | } | |
346 | 356 | |||
347 | /* Only now redirect input from MIDI devices. */ | 357 | /* Only now redirect input from MIDI devices. */ | |
348 | for (unit = 0; unit < sc->nmidi; unit++) { | 358 | for (mdno = 0; mdno < sc->nmidi; mdno++) { | |
349 | msc = sc->devs[unit]->msc; | 359 | extern struct cfdriver midi_cd; | |
350 | mutex_enter(msc->lock); | 360 | ||
351 | msc->seqopen = 1; | 361 | msc = device_lookup_private(&midi_cd, sc->devs[mdno]->unit); | |
352 | mutex_exit(msc->lock); | 362 | if (msc) { | |
363 | mutex_enter(msc->lock); | |||
364 | msc->seqopen = 1; | |||
365 | mutex_exit(msc->lock); | |||
366 | } | |||
353 | } | 367 | } | |
354 | 368 | |||
355 | seq_reset(sc); | 369 | seq_reset(sc); | |
356 | sequencer_exit(sc); | 370 | sequencer_exit(sc); | |
357 | 371 | |||
358 | DPRINTF(("%s: mode=%d, nmidi=%d\n", __func__, sc->mode, sc->nmidi)); | 372 | DPRINTF(("%s: mode=%d, nmidi=%d\n", __func__, sc->mode, sc->nmidi)); | |
359 | return 0; | 373 | return 0; | |
360 | } | 374 | } | |
361 | 375 | |||
362 | static int | 376 | static int | |
363 | seq_drain(struct sequencer_softc *sc) | 377 | seq_drain(struct sequencer_softc *sc) | |
364 | { | 378 | { | |
365 | int error; | 379 | int error; | |
@@ -419,58 +433,62 @@ seq_startoutput(struct sequencer_softc * | @@ -419,58 +433,62 @@ seq_startoutput(struct sequencer_softc * | |||
419 | while (!SEQ_QEMPTY(q) && !sc->timeout) { | 433 | while (!SEQ_QEMPTY(q) && !sc->timeout) { | |
420 | SEQ_QGET(q, cmd); | 434 | SEQ_QGET(q, cmd); | |
421 | seq_do_command(sc, &cmd); | 435 | seq_do_command(sc, &cmd); | |
422 | } | 436 | } | |
423 | } | 437 | } | |
424 | 438 | |||
425 | static int | 439 | static int | |
426 | sequencerclose(dev_t dev, int flags, int ifmt, struct lwp *l) | 440 | sequencerclose(dev_t dev, int flags, int ifmt, struct lwp *l) | |
427 | { | 441 | { | |
428 | struct sequencer_softc *sc; | 442 | struct sequencer_softc *sc; | |
429 | struct midi_softc *msc; | 443 | struct midi_softc *msc; | |
430 | int unit, error; | 444 | int unit, error; | |
431 | 445 | |||
432 | DPRINTF(("sequencerclose: %"PRIx64"\n", dev)); | 446 | DPRINTF(("%s: %"PRIx64"\n", __func__, dev)); | |
433 | 447 | |||
434 | if ((error = sequencer_enter(dev, &sc)) != 0) | 448 | if ((error = sequencer_enter(dev, &sc)) != 0) | |
435 | return error; | 449 | return error; | |
436 | seq_drain(sc); | 450 | seq_drain(sc); | |
437 | if (sc->timeout) { | 451 | if (sc->timeout) { | |
438 | callout_halt(&sc->sc_callout, &sc->lock); | 452 | callout_halt(&sc->sc_callout, &sc->lock); | |
439 | sc->timeout = 0; | 453 | sc->timeout = 0; | |
440 | } | 454 | } | |
441 | /* Bin input from MIDI devices. */ | 455 | /* Bin input from MIDI devices. */ | |
442 | for (unit = 0; unit < sc->nmidi; unit++) { | 456 | for (unit = 0; unit < sc->nmidi; unit++) { | |
443 | msc = sc->devs[unit]->msc; | 457 | extern struct cfdriver midi_cd; | |
444 | mutex_enter(msc->lock); | 458 | ||
445 | msc->seqopen = 0; | 459 | msc = device_lookup_private(&midi_cd, unit); | |
446 | mutex_exit(msc->lock); | 460 | if (msc) { | |
461 | mutex_enter(msc->lock); | |||
462 | msc->seqopen = 0; | |||
463 | mutex_exit(msc->lock); | |||
464 | } | |||
447 | } | 465 | } | |
448 | mutex_exit(&sc->lock); | 466 | mutex_exit(&sc->lock); | |
449 | 467 | |||
450 | for (unit = 0; unit < sc->nmidi; unit++) | 468 | for (unit = 0; unit < sc->nmidi; unit++) | |
451 | if (sc->devs[unit] != NULL) | 469 | if (sc->devs[unit] != NULL) | |
452 | midiseq_close(sc->devs[unit]); | 470 | midiseq_close(sc->devs[unit]); | |
453 | if (sc->devs != NULL) { | 471 | if (sc->devs != NULL) { | |
454 | KASSERT(sc->ndevs > 0); | 472 | KASSERT(sc->ndevs > 0); | |
455 | kmem_free(sc->devs, sc->ndevs * sizeof(struct midi_dev *)); | 473 | kmem_free(sc->devs, sc->ndevs * sizeof(struct midi_dev *)); | |
456 | sc->devs = NULL; | 474 | sc->devs = NULL; | |
457 | } | 475 | } | |
458 | 476 | |||
459 | mutex_enter(&sc->lock); | 477 | mutex_enter(&sc->lock); | |
460 | sc->isopen = 0; | 478 | sc->isopen = 0; | |
461 | sequencer_exit(sc); | 479 | sequencer_exit(sc); | |
462 | 480 | |||
463 | DPRINTF(("sequencerclose: %"PRIx64" done\n", dev)); | 481 | DPRINTF(("%s: %"PRIx64" done\n", __func__, dev)); | |
464 | 482 | |||
465 | return (0); | 483 | return (0); | |
466 | } | 484 | } | |
467 | 485 | |||
468 | static int | 486 | static int | |
469 | seq_input_event(struct sequencer_softc *sc, seq_event_t *cmd) | 487 | seq_input_event(struct sequencer_softc *sc, seq_event_t *cmd) | |
470 | { | 488 | { | |
471 | struct sequencer_queue *q; | 489 | struct sequencer_queue *q; | |
472 | 490 | |||
473 | KASSERT(mutex_owned(&sc->lock)); | 491 | KASSERT(mutex_owned(&sc->lock)); | |
474 | 492 | |||
475 | DPRINTFN(2, ("seq_input_event: %02x %02x %02x %02x %02x " | 493 | DPRINTFN(2, ("seq_input_event: %02x %02x %02x %02x %02x " | |
476 | "%02x %02x %02x\n", cmd->tag, | 494 | "%02x %02x %02x\n", cmd->tag, | |
@@ -550,41 +568,41 @@ seq_softintr(void *addr) | @@ -550,41 +568,41 @@ seq_softintr(void *addr) | |||
550 | default: /* this is now the point where MIDI_ACKs disappear */ | 568 | default: /* this is now the point where MIDI_ACKs disappear */ | |
551 | mutex_exit(&sc->lock); | 569 | mutex_exit(&sc->lock); | |
552 | return; | 570 | return; | |
553 | } | 571 | } | |
554 | microtime(&now); | 572 | microtime(&now); | |
555 | if (!sc->timer.running) | 573 | if (!sc->timer.running) | |
556 | now = sc->timer.stoptime; | 574 | now = sc->timer.stoptime; | |
557 | SUBTIMEVAL(&now, &sc->timer.reftime); | 575 | SUBTIMEVAL(&now, &sc->timer.reftime); | |
558 | t = now.tv_sec * 1000000 + now.tv_usec; | 576 | t = now.tv_sec * 1000000 + now.tv_usec; | |
559 | t /= sc->timer.usperdiv; | 577 | t /= sc->timer.usperdiv; | |
560 | t += sc->timer.divs_lastchange; | 578 | t += sc->timer.divs_lastchange; | |
561 | if (t != sc->input_stamp) { | 579 | if (t != sc->input_stamp) { | |
562 | seq_input_event(sc, &SEQ_MK_TIMING(WAIT_ABS, .divisions=t)); | 580 | seq_input_event(sc, &SEQ_MK_TIMING(WAIT_ABS, .divisions=t)); | |
563 | sc->input_stamp = t; /* XXX wha hoppen if timer is reset? */ | 581 | sc->input_stamp = t; /* XXX what happens if timer is reset? */ | |
564 | } | 582 | } | |
565 | seq_input_event(sc, &ev); | 583 | seq_input_event(sc, &ev); | |
566 | mutex_exit(&sc->lock); | 584 | mutex_exit(&sc->lock); | |
567 | } | 585 | } | |
568 | 586 | |||
569 | static int | 587 | static int | |
570 | sequencerread(dev_t dev, struct uio *uio, int ioflag) | 588 | sequencerread(dev_t dev, struct uio *uio, int ioflag) | |
571 | { | 589 | { | |
572 | struct sequencer_softc *sc; | 590 | struct sequencer_softc *sc; | |
573 | struct sequencer_queue *q; | 591 | struct sequencer_queue *q; | |
574 | seq_event_t ev; | 592 | seq_event_t ev; | |
575 | int error; | 593 | int error; | |
576 | 594 | |||
577 | DPRINTFN(20, ("sequencerread: %"PRIx64", count=%d, ioflag=%x\n", | 595 | DPRINTFN(2, ("sequencerread: %"PRIx64", count=%d, ioflag=%x\n", | |
578 | dev, (int)uio->uio_resid, ioflag)); | 596 | dev, (int)uio->uio_resid, ioflag)); | |
579 | 597 | |||
580 | if ((error = sequencer_enter(dev, &sc)) != 0) | 598 | if ((error = sequencer_enter(dev, &sc)) != 0) | |
581 | return error; | 599 | return error; | |
582 | q = &sc->inq; | 600 | q = &sc->inq; | |
583 | 601 | |||
584 | if (sc->mode == SEQ_OLD) { | 602 | if (sc->mode == SEQ_OLD) { | |
585 | sequencer_exit(sc); | 603 | sequencer_exit(sc); | |
586 | DPRINTFN(-1,("sequencerread: old read\n")); | 604 | DPRINTFN(-1,("sequencerread: old read\n")); | |
587 | return EINVAL; /* XXX unimplemented */ | 605 | return EINVAL; /* XXX unimplemented */ | |
588 | } | 606 | } | |
589 | while (SEQ_QEMPTY(q)) { | 607 | while (SEQ_QEMPTY(q)) { | |
590 | if (ioflag & IO_NDELAY) { | 608 | if (ioflag & IO_NDELAY) { | |
@@ -691,27 +709,27 @@ sequencerioctl(dev_t dev, u_long cmd, vo | @@ -691,27 +709,27 @@ sequencerioctl(dev_t dev, u_long cmd, vo | |||
691 | 709 | |||
692 | if ((error = sequencer_enter(dev, &sc)) != 0) | 710 | if ((error = sequencer_enter(dev, &sc)) != 0) | |
693 | return error; | 711 | return error; | |
694 | switch (cmd) { | 712 | switch (cmd) { | |
695 | case FIONBIO: | 713 | case FIONBIO: | |
696 | /* All handled in the upper FS layer. */ | 714 | /* All handled in the upper FS layer. */ | |
697 | break; | 715 | break; | |
698 | 716 | |||
699 | case FIOASYNC: | 717 | case FIOASYNC: | |
700 | if (*(int *)addr) { | 718 | if (*(int *)addr) { | |
701 | if (sc->async != 0) | 719 | if (sc->async != 0) | |
702 | return EBUSY; | 720 | return EBUSY; | |
703 | sc->async = curproc->p_pid; | 721 | sc->async = curproc->p_pid; | |
704 | DPRINTF(("sequencer_ioctl: FIOASYNC %d\n", | 722 | DPRINTF(("%s: FIOASYNC %d\n", __func__, | |
705 | sc->async)); | 723 | sc->async)); | |
706 | } else { | 724 | } else { | |
707 | sc->async = 0; | 725 | sc->async = 0; | |
708 | } | 726 | } | |
709 | break; | 727 | break; | |
710 | 728 | |||
711 | case SEQUENCER_RESET: | 729 | case SEQUENCER_RESET: | |
712 | seq_reset(sc); | 730 | seq_reset(sc); | |
713 | break; | 731 | break; | |
714 | 732 | |||
715 | case SEQUENCER_PANIC: | 733 | case SEQUENCER_PANIC: | |
716 | seq_reset(sc); | 734 | seq_reset(sc); | |
717 | /* Do more? OSS doesn't */ | 735 | /* Do more? OSS doesn't */ | |
@@ -777,26 +795,27 @@ sequencerioctl(dev_t dev, u_long cmd, vo | @@ -777,26 +795,27 @@ sequencerioctl(dev_t dev, u_long cmd, vo | |||
777 | break; | 795 | break; | |
778 | 796 | |||
779 | case SEQUENCER_TMR_STOP: | 797 | case SEQUENCER_TMR_STOP: | |
780 | error = seq_do_timing(sc, &SEQ_MK_TIMING(STOP)); | 798 | error = seq_do_timing(sc, &SEQ_MK_TIMING(STOP)); | |
781 | break; | 799 | break; | |
782 | 800 | |||
783 | case SEQUENCER_TMR_CONTINUE: | 801 | case SEQUENCER_TMR_CONTINUE: | |
784 | error = seq_do_timing(sc, &SEQ_MK_TIMING(CONTINUE)); | 802 | error = seq_do_timing(sc, &SEQ_MK_TIMING(CONTINUE)); | |
785 | break; | 803 | break; | |
786 | 804 | |||
787 | case SEQUENCER_TMR_TEMPO: | 805 | case SEQUENCER_TMR_TEMPO: | |
788 | error = seq_do_timing(sc, | 806 | error = seq_do_timing(sc, | |
789 | &SEQ_MK_TIMING(TEMPO, .bpm=*(int *)addr)); | 807 | &SEQ_MK_TIMING(TEMPO, .bpm=*(int *)addr)); | |
808 | RECALC_USPERDIV(&sc->timer); | |||
790 | if (error == 0) | 809 | if (error == 0) | |
791 | *(int *)addr = sc->timer.tempo_beatpermin; | 810 | *(int *)addr = sc->timer.tempo_beatpermin; | |
792 | break; | 811 | break; | |
793 | 812 | |||
794 | case SEQUENCER_TMR_SOURCE: | 813 | case SEQUENCER_TMR_SOURCE: | |
795 | *(int *)addr = SEQUENCER_TMR_INTERNAL; | 814 | *(int *)addr = SEQUENCER_TMR_INTERNAL; | |
796 | break; | 815 | break; | |
797 | 816 | |||
798 | case SEQUENCER_TMR_METRONOME: | 817 | case SEQUENCER_TMR_METRONOME: | |
799 | /* noop */ | 818 | /* noop */ | |
800 | break; | 819 | break; | |
801 | 820 | |||
802 | case SEQUENCER_THRESHOLD: | 821 | case SEQUENCER_THRESHOLD: | |
@@ -830,27 +849,27 @@ sequencerioctl(dev_t dev, u_long cmd, vo | @@ -830,27 +849,27 @@ sequencerioctl(dev_t dev, u_long cmd, vo | |||
830 | sequencer_exit(sc); | 849 | sequencer_exit(sc); | |
831 | 850 | |||
832 | return error; | 851 | return error; | |
833 | } | 852 | } | |
834 | 853 | |||
835 | static int | 854 | static int | |
836 | sequencerpoll(dev_t dev, int events, struct lwp *l) | 855 | sequencerpoll(dev_t dev, int events, struct lwp *l) | |
837 | { | 856 | { | |
838 | struct sequencer_softc *sc; | 857 | struct sequencer_softc *sc; | |
839 | int revents = 0; | 858 | int revents = 0; | |
840 | if ((sc = sequencerget(SEQUENCERUNIT(dev))) == NULL) | 859 | if ((sc = sequencerget(SEQUENCERUNIT(dev))) == NULL) | |
841 | return ENXIO; | 860 | return ENXIO; | |
842 | 861 | |||
843 | DPRINTF(("sequencerpoll: %p events=0x%x\n", sc, events)); | 862 | DPRINTF(("%s: %p events=0x%x\n", __func__, sc, events)); | |
844 | 863 | |||
845 | mutex_enter(&sc->lock); | 864 | mutex_enter(&sc->lock); | |
846 | if (events & (POLLIN | POLLRDNORM)) | 865 | if (events & (POLLIN | POLLRDNORM)) | |
847 | if ((sc->flags&FREAD) && !SEQ_QEMPTY(&sc->inq)) | 866 | if ((sc->flags&FREAD) && !SEQ_QEMPTY(&sc->inq)) | |
848 | revents |= events & (POLLIN | POLLRDNORM); | 867 | revents |= events & (POLLIN | POLLRDNORM); | |
849 | 868 | |||
850 | if (events & (POLLOUT | POLLWRNORM)) | 869 | if (events & (POLLOUT | POLLWRNORM)) | |
851 | if ((sc->flags&FWRITE) && SEQ_QLEN(&sc->outq) < sc->lowat) | 870 | if ((sc->flags&FWRITE) && SEQ_QLEN(&sc->outq) < sc->lowat) | |
852 | revents |= events & (POLLOUT | POLLWRNORM); | 871 | revents |= events & (POLLOUT | POLLWRNORM); | |
853 | 872 | |||
854 | if (revents == 0) { | 873 | if (revents == 0) { | |
855 | if ((sc->flags&FREAD) && (events & (POLLIN | POLLRDNORM))) | 874 | if ((sc->flags&FREAD) && (events & (POLLIN | POLLRDNORM))) | |
856 | selrecord(l, &sc->rsel); | 875 | selrecord(l, &sc->rsel); | |
@@ -961,27 +980,27 @@ sequencerkqfilter(dev_t dev, struct knot | @@ -961,27 +980,27 @@ sequencerkqfilter(dev_t dev, struct knot | |||
961 | mutex_exit(&sc->lock); | 980 | mutex_exit(&sc->lock); | |
962 | 981 | |||
963 | return (0); | 982 | return (0); | |
964 | } | 983 | } | |
965 | 984 | |||
966 | static void | 985 | static void | |
967 | seq_reset(struct sequencer_softc *sc) | 986 | seq_reset(struct sequencer_softc *sc) | |
968 | { | 987 | { | |
969 | int i, chn; | 988 | int i, chn; | |
970 | struct midi_dev *md; | 989 | struct midi_dev *md; | |
971 | 990 | |||
972 | KASSERT(mutex_owned(&sc->lock)); | 991 | KASSERT(mutex_owned(&sc->lock)); | |
973 | 992 | |||
974 | if ( !(sc->flags & FWRITE) ) | 993 | if (!(sc->flags & FWRITE)) | |
975 | return; | 994 | return; | |
976 | for (i = 0; i < sc->nmidi; i++) { | 995 | for (i = 0; i < sc->nmidi; i++) { | |
977 | md = sc->devs[i]; | 996 | md = sc->devs[i]; | |
978 | midiseq_reset(md); | 997 | midiseq_reset(md); | |
979 | for (chn = 0; chn < MAXCHAN; chn++) { | 998 | for (chn = 0; chn < MAXCHAN; chn++) { | |
980 | midiseq_ctlchange(md, chn, &SEQ_MK_CHN(CTL_CHANGE, | 999 | midiseq_ctlchange(md, chn, &SEQ_MK_CHN(CTL_CHANGE, | |
981 | .controller=MIDI_CTRL_NOTES_OFF)); | 1000 | .controller=MIDI_CTRL_NOTES_OFF)); | |
982 | midiseq_ctlchange(md, chn, &SEQ_MK_CHN(CTL_CHANGE, | 1001 | midiseq_ctlchange(md, chn, &SEQ_MK_CHN(CTL_CHANGE, | |
983 | .controller=MIDI_CTRL_RESET)); | 1002 | .controller=MIDI_CTRL_RESET)); | |
984 | midiseq_pitchbend(md, chn, &SEQ_MK_CHN(PITCH_BEND, | 1003 | midiseq_pitchbend(md, chn, &SEQ_MK_CHN(PITCH_BEND, | |
985 | .value=MIDI_BEND_NEUTRAL)); | 1004 | .value=MIDI_BEND_NEUTRAL)); | |
986 | } | 1005 | } | |
987 | } | 1006 | } | |
@@ -1104,27 +1123,27 @@ seq_do_local(struct sequencer_softc *sc, | @@ -1104,27 +1123,27 @@ seq_do_local(struct sequencer_softc *sc, | |||
1104 | 1123 | |||
1105 | static int | 1124 | static int | |
1106 | seq_do_sysex(struct sequencer_softc *sc, seq_event_t *b) | 1125 | seq_do_sysex(struct sequencer_softc *sc, seq_event_t *b) | |
1107 | { | 1126 | { | |
1108 | int dev, i; | 1127 | int dev, i; | |
1109 | struct midi_dev *md; | 1128 | struct midi_dev *md; | |
1110 | uint8_t *bf = b->sysex.buffer; | 1129 | uint8_t *bf = b->sysex.buffer; | |
1111 | 1130 | |||
1112 | KASSERT(mutex_owned(&sc->lock)); | 1131 | KASSERT(mutex_owned(&sc->lock)); | |
1113 | 1132 | |||
1114 | dev = b->sysex.device; | 1133 | dev = b->sysex.device; | |
1115 | if (dev < 0 || dev >= sc->nmidi) | 1134 | if (dev < 0 || dev >= sc->nmidi) | |
1116 | return (ENXIO); | 1135 | return (ENXIO); | |
1117 | DPRINTF(("seq_do_sysex: dev=%d\n", dev)); | 1136 | DPRINTF(("%s: dev=%d\n", __func__, dev)); | |
1118 | md = sc->devs[dev]; | 1137 | md = sc->devs[dev]; | |
1119 | 1138 | |||
1120 | if (!md->doingsysex) { | 1139 | if (!md->doingsysex) { | |
1121 | midiseq_out(md, (uint8_t[]){MIDI_SYSEX_START}, 1, 0); | 1140 | midiseq_out(md, (uint8_t[]){MIDI_SYSEX_START}, 1, 0); | |
1122 | md->doingsysex = 1; | 1141 | md->doingsysex = 1; | |
1123 | } | 1142 | } | |
1124 | 1143 | |||
1125 | for (i = 0; i < 6 && bf[i] != 0xff; i++) | 1144 | for (i = 0; i < 6 && bf[i] != 0xff; i++) | |
1126 | ; | 1145 | ; | |
1127 | midiseq_out(md, bf, i, 0); | 1146 | midiseq_out(md, bf, i, 0); | |
1128 | if (i < 6 || (i > 0 && bf[i-1] == MIDI_SYSEX_END)) | 1147 | if (i < 6 || (i > 0 && bf[i-1] == MIDI_SYSEX_END)) | |
1129 | md->doingsysex = 0; | 1148 | md->doingsysex = 0; | |
1130 | return 0; | 1149 | return 0; | |
@@ -1156,27 +1175,27 @@ seq_timer_waitabs(struct sequencer_softc | @@ -1156,27 +1175,27 @@ seq_timer_waitabs(struct sequencer_softc | |||
1156 | #ifdef DIAGNOSTIC | 1175 | #ifdef DIAGNOSTIC | |
1157 | if (ticks > 20 * hz) { | 1176 | if (ticks > 20 * hz) { | |
1158 | /* Waiting more than 20s */ | 1177 | /* Waiting more than 20s */ | |
1159 | printf("seq_timer_waitabs: funny ticks=%d, " | 1178 | printf("seq_timer_waitabs: funny ticks=%d, " | |
1160 | "usec=%lld\n", ticks, usec); | 1179 | "usec=%lld\n", ticks, usec); | |
1161 | } | 1180 | } | |
1162 | #endif | 1181 | #endif | |
1163 | sc->timeout = 1; | 1182 | sc->timeout = 1; | |
1164 | callout_reset(&sc->sc_callout, ticks, | 1183 | callout_reset(&sc->sc_callout, ticks, | |
1165 | seq_timeout, sc); | 1184 | seq_timeout, sc); | |
1166 | } | 1185 | } | |
1167 | #ifdef SEQUENCER_DEBUG | 1186 | #ifdef SEQUENCER_DEBUG | |
1168 | else if (tick < 0) | 1187 | else if (tick < 0) | |
1169 | DPRINTF(("seq_timer_waitabs: ticks = %d\n", ticks)); | 1188 | DPRINTF(("%s: ticks = %d\n", __func__, ticks)); | |
1170 | #endif | 1189 | #endif | |
1171 | } | 1190 | } | |
1172 | 1191 | |||
1173 | static int | 1192 | static int | |
1174 | seq_do_timing(struct sequencer_softc *sc, seq_event_t *b) | 1193 | seq_do_timing(struct sequencer_softc *sc, seq_event_t *b) | |
1175 | { | 1194 | { | |
1176 | struct syn_timer *t = &sc->timer; | 1195 | struct syn_timer *t = &sc->timer; | |
1177 | struct timeval when; | 1196 | struct timeval when; | |
1178 | int error; | 1197 | int error; | |
1179 | 1198 | |||
1180 | KASSERT(mutex_owned(&sc->lock)); | 1199 | KASSERT(mutex_owned(&sc->lock)); | |
1181 | 1200 | |||
1182 | error = 0; | 1201 | error = 0; | |
@@ -1217,31 +1236,31 @@ seq_do_timing(struct sequencer_softc *sc | @@ -1217,31 +1236,31 @@ seq_do_timing(struct sequencer_softc *sc | |||
1217 | t->divs_lastchange = t->divs_lastevent; | 1236 | t->divs_lastchange = t->divs_lastevent; | |
1218 | microtime(&t->reftime); | 1237 | microtime(&t->reftime); | |
1219 | RECALC_USPERDIV(t); | 1238 | RECALC_USPERDIV(t); | |
1220 | break; | 1239 | break; | |
1221 | case TMR_ECHO: | 1240 | case TMR_ECHO: | |
1222 | error = seq_input_event(sc, b); | 1241 | error = seq_input_event(sc, b); | |
1223 | break; | 1242 | break; | |
1224 | case TMR_RESET: | 1243 | case TMR_RESET: | |
1225 | t->divs_lastevent = t->divs_lastchange = 0; | 1244 | t->divs_lastevent = t->divs_lastchange = 0; | |
1226 | microtime(&t->reftime); | 1245 | microtime(&t->reftime); | |
1227 | break; | 1246 | break; | |
1228 | case TMR_SPP: | 1247 | case TMR_SPP: | |
1229 | case TMR_TIMESIG: | 1248 | case TMR_TIMESIG: | |
1230 | DPRINTF(("seq_do_timing: unimplemented %02x\n", b->timing.op)); | 1249 | DPRINTF(("%s: unimplemented %02x\n", __func__, b->timing.op)); | |
1231 | error = EINVAL; /* not quite accurate... */ | 1250 | error = EINVAL; /* not quite accurate... */ | |
1232 | break; | 1251 | break; | |
1233 | default: | 1252 | default: | |
1234 | DPRINTF(("seq_timer: unknown %02x\n", b->timing.op)); | 1253 | DPRINTF(("%s: unknown %02x\n", __func__, b->timing.op)); | |
1235 | error = EINVAL; | 1254 | error = EINVAL; | |
1236 | break; | 1255 | break; | |
1237 | } | 1256 | } | |
1238 | return (error); | 1257 | return (error); | |
1239 | } | 1258 | } | |
1240 | 1259 | |||
1241 | static int | 1260 | static int | |
1242 | seq_do_fullsize(struct sequencer_softc *sc, seq_event_t *b, struct uio *uio) | 1261 | seq_do_fullsize(struct sequencer_softc *sc, seq_event_t *b, struct uio *uio) | |
1243 | { | 1262 | { | |
1244 | struct sysex_info sysex; | 1263 | struct sysex_info sysex; | |
1245 | u_int dev; | 1264 | u_int dev; | |
1246 | 1265 | |||
1247 | #ifdef DIAGNOSTIC | 1266 | #ifdef DIAGNOSTIC | |
@@ -1335,27 +1354,27 @@ seq_to_new(seq_event_t *ev, struct uio * | @@ -1335,27 +1354,27 @@ seq_to_new(seq_event_t *ev, struct uio * | |||
1335 | */ | 1354 | */ | |
1336 | *ev = SEQ_MK_TIMING(RESET); | 1355 | *ev = SEQ_MK_TIMING(RESET); | |
1337 | break; | 1356 | break; | |
1338 | case SEQOLD_PGMCHANGE: | 1357 | case SEQOLD_PGMCHANGE: | |
1339 | *ev = SEQ_MK_CHN(PGM_CHANGE, | 1358 | *ev = SEQ_MK_CHN(PGM_CHANGE, | |
1340 | .device=0, .channel=chan, .program=note); | 1359 | .device=0, .channel=chan, .program=note); | |
1341 | break; | 1360 | break; | |
1342 | case SEQOLD_MIDIPUTC: | 1361 | case SEQOLD_MIDIPUTC: | |
1343 | break; /* interpret in normal mode */ | 1362 | break; /* interpret in normal mode */ | |
1344 | case SEQOLD_ECHO: | 1363 | case SEQOLD_ECHO: | |
1345 | case SEQOLD_PRIVATE: | 1364 | case SEQOLD_PRIVATE: | |
1346 | case SEQOLD_EXTENDED: | 1365 | case SEQOLD_EXTENDED: | |
1347 | default: | 1366 | default: | |
1348 | DPRINTF(("seq_to_new: not impl 0x%02x\n", cmd)); | 1367 | DPRINTF(("%s: not impl 0x%02x\n", __func__, cmd)); | |
1349 | return EINVAL; | 1368 | return EINVAL; | |
1350 | /* In case new-style events show up */ | 1369 | /* In case new-style events show up */ | |
1351 | case SEQ_TIMING: | 1370 | case SEQ_TIMING: | |
1352 | case SEQ_CHN_VOICE: | 1371 | case SEQ_CHN_VOICE: | |
1353 | case SEQ_CHN_COMMON: | 1372 | case SEQ_CHN_COMMON: | |
1354 | case SEQ_FULLSIZE: | 1373 | case SEQ_FULLSIZE: | |
1355 | break; | 1374 | break; | |
1356 | } | 1375 | } | |
1357 | return 0; | 1376 | return 0; | |
1358 | } | 1377 | } | |
1359 | 1378 | |||
1360 | /**********************************************/ | 1379 | /**********************************************/ | |
1361 | 1380 | |||
@@ -1410,27 +1429,26 @@ midiseq_open(int unit, int flags) | @@ -1410,27 +1429,26 @@ midiseq_open(int unit, int flags) | |||
1410 | /* Only after we have acquired reference via VOP_OPEN(). */ | 1429 | /* Only after we have acquired reference via VOP_OPEN(). */ | |
1411 | midi_getinfo(dev, &mi); | 1430 | midi_getinfo(dev, &mi); | |
1412 | oflags = flags; | 1431 | oflags = flags; | |
1413 | if ((mi.props & MIDI_PROP_CAN_INPUT) == 0) | 1432 | if ((mi.props & MIDI_PROP_CAN_INPUT) == 0) | |
1414 | flags &= ~FREAD; | 1433 | flags &= ~FREAD; | |
1415 | if ((flags & (FREAD|FWRITE)) == 0) { | 1434 | if ((flags & (FREAD|FWRITE)) == 0) { | |
1416 | VOP_CLOSE(vp, oflags, kauth_cred_get()); | 1435 | VOP_CLOSE(vp, oflags, kauth_cred_get()); | |
1417 | vrele(vp); | 1436 | vrele(vp); | |
1418 | return NULL; | 1437 | return NULL; | |
1419 | } | 1438 | } | |
1420 | 1439 | |||
1421 | sc = device_lookup_private(&midi_cd, unit); | 1440 | sc = device_lookup_private(&midi_cd, unit); | |
1422 | md = kmem_zalloc(sizeof(*md), KM_SLEEP); | 1441 | md = kmem_zalloc(sizeof(*md), KM_SLEEP); | |
1423 | md->msc = sc; | |||
1424 | md->unit = unit; | 1442 | md->unit = unit; | |
1425 | md->name = mi.name; | 1443 | md->name = mi.name; | |
1426 | md->subtype = 0; | 1444 | md->subtype = 0; | |
1427 | md->nr_voices = 128; /* XXX */ | 1445 | md->nr_voices = 128; /* XXX */ | |
1428 | md->instr_bank_size = 128; /* XXX */ | 1446 | md->instr_bank_size = 128; /* XXX */ | |
1429 | md->vp = vp; | 1447 | md->vp = vp; | |
1430 | if (mi.props & MIDI_PROP_CAN_INPUT) | 1448 | if (mi.props & MIDI_PROP_CAN_INPUT) | |
1431 | md->capabilities |= SYNTH_CAP_INPUT; | 1449 | md->capabilities |= SYNTH_CAP_INPUT; | |
1432 | sc->seq_md = md; | 1450 | sc->seq_md = md; | |
1433 | return (md); | 1451 | return (md); | |
1434 | } | 1452 | } | |
1435 | 1453 | |||
1436 | static void | 1454 | static void | |
@@ -1441,28 +1459,28 @@ midiseq_close(struct midi_dev *md) | @@ -1441,28 +1459,28 @@ midiseq_close(struct midi_dev *md) | |||
1441 | kmem_free(md, sizeof(*md)); | 1459 | kmem_free(md, sizeof(*md)); | |
1442 | } | 1460 | } | |
1443 | 1461 | |||
1444 | static void | 1462 | static void | |
1445 | midiseq_reset(struct midi_dev *md) | 1463 | midiseq_reset(struct midi_dev *md) | |
1446 | { | 1464 | { | |
1447 | /* XXX send GM reset? */ | 1465 | /* XXX send GM reset? */ | |
1448 | DPRINTFN(3, ("midiseq_reset: %d\n", md->unit)); | 1466 | DPRINTFN(3, ("midiseq_reset: %d\n", md->unit)); | |
1449 | } | 1467 | } | |
1450 | 1468 | |||
1451 | static int | 1469 | static int | |
1452 | midiseq_out(struct midi_dev *md, u_char *bf, u_int cc, int chk) | 1470 | midiseq_out(struct midi_dev *md, u_char *bf, u_int cc, int chk) | |
1453 | { | 1471 | { | |
1454 | DPRINTFN(5, ("midiseq_out: m=%p, unit=%d, bf[0]=0x%02x, cc=%d\n", | 1472 | DPRINTFN(5, ("midiseq_out: md=%p, unit=%d, bf[0]=0x%02x, cc=%d\n", | |
1455 | md->msc, md->unit, bf[0], cc)); | 1473 | md, md->unit, bf[0], cc)); | |
1456 | 1474 | |||
1457 | /* midi(4) does running status compression where appropriate. */ | 1475 | /* midi(4) does running status compression where appropriate. */ | |
1458 | return midi_writebytes(md->unit, bf, cc); | 1476 | return midi_writebytes(md->unit, bf, cc); | |
1459 | } | 1477 | } | |
1460 | 1478 | |||
1461 | /* | 1479 | /* | |
1462 | * If the writing process hands us a hidden note-off in a note-on event, | 1480 | * If the writing process hands us a hidden note-off in a note-on event, | |
1463 | * we will simply write it that way; no need to special case it here, | 1481 | * we will simply write it that way; no need to special case it here, | |
1464 | * as midi(4) will always canonicalize or compress as appropriate anyway. | 1482 | * as midi(4) will always canonicalize or compress as appropriate anyway. | |
1465 | */ | 1483 | */ | |
1466 | static int | 1484 | static int | |
1467 | midiseq_noteon(struct midi_dev *md, int chan, int key, seq_event_t *ev) | 1485 | midiseq_noteon(struct midi_dev *md, int chan, int key, seq_event_t *ev) | |
1468 | { | 1486 | { |
--- src/sys/dev/sequencervar.h 2013/04/27 22:12:42 1.16
+++ src/sys/dev/sequencervar.h 2015/01/11 14:13:25 1.16.10.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: sequencervar.h,v 1.16 2013/04/27 22:12:42 christos Exp $ */ | 1 | /* $NetBSD: sequencervar.h,v 1.16.10.1 2015/01/11 14:13:25 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Lennart Augustsson (augustss@NetBSD.org). | 8 | * by Lennart Augustsson (augustss@NetBSD.org). | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -58,27 +58,26 @@ struct sequencer_queue { | @@ -58,27 +58,26 @@ struct sequencer_queue { | |||
58 | #define SEQ_QLEN(q) ((q)->count) | 58 | #define SEQ_QLEN(q) ((q)->count) | |
59 | 59 | |||
60 | struct sequencer_softc; | 60 | struct sequencer_softc; | |
61 | 61 | |||
62 | #define MAXCHAN 16 | 62 | #define MAXCHAN 16 | |
63 | struct midi_dev { | 63 | struct midi_dev { | |
64 | const char *name; | 64 | const char *name; | |
65 | int subtype; | 65 | int subtype; | |
66 | int capabilities; | 66 | int capabilities; | |
67 | int nr_voices; | 67 | int nr_voices; | |
68 | int instr_bank_size; | 68 | int instr_bank_size; | |
69 | int unit; | 69 | int unit; | |
70 | struct sequencer_softc *seq; | 70 | struct sequencer_softc *seq; | |
71 | struct midi_softc *msc; | |||
72 | char doingsysex; /* doing a SEQ_SYSEX */ | 71 | char doingsysex; /* doing a SEQ_SYSEX */ | |
73 | vnode_t *vp; | 72 | vnode_t *vp; | |
74 | }; | 73 | }; | |
75 | 74 | |||
76 | struct sequencer_softc { | 75 | struct sequencer_softc { | |
77 | callout_t sc_callout; | 76 | callout_t sc_callout; | |
78 | kmutex_t lock; | 77 | kmutex_t lock; | |
79 | kcondvar_t wchan; | 78 | kcondvar_t wchan; | |
80 | kcondvar_t rchan; | 79 | kcondvar_t rchan; | |
81 | kcondvar_t lchan; | 80 | kcondvar_t lchan; | |
82 | int dvlock; | 81 | int dvlock; | |
83 | int dying; | 82 | int dying; | |
84 | u_int isopen; /* Open indicator */ | 83 | u_int isopen; /* Open indicator */ |
--- src/sys/dev/usb/FILES 2012/01/17 03:49:20 1.12
+++ src/sys/dev/usb/FILES 2015/01/11 14:13:25 1.12.22.1
@@ -45,28 +45,26 @@ ukbdmap.c wscons key mapping for ukbd | @@ -45,28 +45,26 @@ ukbdmap.c wscons key mapping for ukbd | |||
45 | ukbdvar.h API for ukbd.c | 45 | ukbdvar.h API for ukbd.c | |
46 | ulpt.c USB printer class driver | 46 | ulpt.c USB printer class driver | |
47 | umass.c USB mass storage wire protocol driver | 47 | umass.c USB mass storage wire protocol driver | |
48 | umass_isdata.c In-System Design ATA over bulk-only driver | 48 | umass_isdata.c In-System Design ATA over bulk-only driver | |
49 | umass_isdata.h and definitions for it | 49 | umass_isdata.h and definitions for it | |
50 | umass_quirks.c Table of strange umass devices | 50 | umass_quirks.c Table of strange umass devices | |
51 | umass_quirks.h and definitions for it | 51 | umass_quirks.h and definitions for it | |
52 | umass_scsipi.c umass command protocol driver | 52 | umass_scsipi.c umass command protocol driver | |
53 | umass_scsipi.h and definitions for it | 53 | umass_scsipi.h and definitions for it | |
54 | umassvar.h definitions for umass.c | 54 | umassvar.h definitions for umass.c | |
55 | umidi.c USB MIDI driver | 55 | umidi.c USB MIDI driver | |
56 | umidi_quirks.c Strange MIDI devices | 56 | umidi_quirks.c Strange MIDI devices | |
57 | umidi_quirks.h and definitions for it | 57 | umidi_quirks.h and definitions for it | |
58 | umidireg.h Protocol definitions for umidi.c | |||
59 | umidivar.h definitions for umidi.c | |||
60 | umodem.c USB modem (CDC ACM) driver | 58 | umodem.c USB modem (CDC ACM) driver | |
61 | ums.c USB mouse driver | 59 | ums.c USB mouse driver | |
62 | urio.c USB Diamond Rio500 driver | 60 | urio.c USB Diamond Rio500 driver | |
63 | urio.h USB Diamond Rio500 defines | 61 | urio.h USB Diamond Rio500 defines | |
64 | usb.c usb (bus) device driver | 62 | usb.c usb (bus) device driver | |
65 | usb.h general USB defines | 63 | usb.h general USB defines | |
66 | usb_mem.c memory allocation for DMAable memory | 64 | usb_mem.c memory allocation for DMAable memory | |
67 | usb_mem.h API for usb_mem.c | 65 | usb_mem.h API for usb_mem.c | |
68 | usb_quirks.c table of non-conforming USB devices and their problems | 66 | usb_quirks.c table of non-conforming USB devices and their problems | |
69 | usb_quirks.h API for usb_quirks.c | 67 | usb_quirks.h API for usb_quirks.c | |
70 | usb_subr.c various subroutines used by USB code | 68 | usb_subr.c various subroutines used by USB code | |
71 | usbcdc.h USB CDC class definitions | 69 | usbcdc.h USB CDC class definitions | |
72 | usbdevs data base of known device | 70 | usbdevs data base of known device |
--- src/sys/dev/usb/umidi.c 2013/01/22 21:29:53 1.65
+++ src/sys/dev/usb/umidi.c 2015/01/11 14:13:25 1.65.12.1
@@ -1,16 +1,17 @@ | @@ -1,16 +1,17 @@ | |||
1 | /* $NetBSD: umidi.c,v 1.65 2013/01/22 21:29:53 jmcneill Exp $ */ | 1 | /* $NetBSD: umidi.c,v 1.65.12.1 2015/01/11 14:13:25 martin Exp $ */ | |
2 | ||||
2 | /* | 3 | /* | |
3 | * Copyright (c) 2001, 2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2001, 2012, 2014 The NetBSD Foundation, Inc. | |
4 | * All rights reserved. | 5 | * All rights reserved. | |
5 | * | 6 | * | |
6 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
7 | * by Takuya SHIOZAKI (tshiozak@NetBSD.org), (full-size transfers, extended | 8 | * by Takuya SHIOZAKI (tshiozak@NetBSD.org), (full-size transfers, extended | |
8 | * hw_if) Chapman Flack (chap@NetBSD.org), and Matthew R. Green | 9 | * hw_if) Chapman Flack (chap@NetBSD.org), and Matthew R. Green | |
9 | * (mrg@eterna.com.au). | 10 | * (mrg@eterna.com.au). | |
10 | * | 11 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 14 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 15 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | 16 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | 17 | * 2. Redistributions in binary form must reproduce the above copyright | |
@@ -21,56 +22,205 @@ | @@ -21,56 +22,205 @@ | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 32 | */ | |
32 | 33 | |||
33 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: umidi.c,v 1.65 2013/01/22 21:29:53 jmcneill Exp $"); | 35 | __KERNEL_RCSID(0, "$NetBSD: umidi.c,v 1.65.12.1 2015/01/11 14:13:25 martin Exp $"); | |
35 | 36 | |||
36 | #include <sys/types.h> | 37 | #include <sys/types.h> | |
37 | #include <sys/param.h> | 38 | #include <sys/param.h> | |
38 | #include <sys/systm.h> | 39 | #include <sys/systm.h> | |
39 | #include <sys/kernel.h> | 40 | #include <sys/kernel.h> | |
40 | #include <sys/kmem.h> | 41 | #include <sys/kmem.h> | |
41 | #include <sys/device.h> | 42 | #include <sys/device.h> | |
42 | #include <sys/ioctl.h> | 43 | #include <sys/ioctl.h> | |
43 | #include <sys/conf.h> | 44 | #include <sys/conf.h> | |
44 | #include <sys/file.h> | 45 | #include <sys/file.h> | |
45 | #include <sys/select.h> | 46 | #include <sys/select.h> | |
46 | #include <sys/proc.h> | 47 | #include <sys/proc.h> | |
47 | #include <sys/vnode.h> | 48 | #include <sys/vnode.h> | |
48 | #include <sys/poll.h> | 49 | #include <sys/poll.h> | |
49 | #include <sys/intr.h> | 50 | #include <sys/intr.h> | |
50 | 51 | |||
51 | #include <dev/usb/usb.h> | 52 | #include <dev/usb/usb.h> | |
52 | #include <dev/usb/usbdi.h> | 53 | #include <dev/usb/usbdi.h> | |
53 | #include <dev/usb/usbdi_util.h> | 54 | #include <dev/usb/usbdi_util.h> | |
54 | 55 | |||
55 | #include <dev/auconv.h> | 56 | #include <dev/auconv.h> | |
56 | #include <dev/usb/usbdevs.h> | 57 | #include <dev/usb/usbdevs.h> | |
57 | #include <dev/usb/uaudioreg.h> | |||
58 | #include <dev/usb/umidireg.h> | |||
59 | #include <dev/usb/umidivar.h> | |||
60 | #include <dev/usb/umidi_quirks.h> | 58 | #include <dev/usb/umidi_quirks.h> | |
61 | ||||
62 | #include <dev/midi_if.h> | 59 | #include <dev/midi_if.h> | |
63 | 60 | |||
61 | /* Jack Descriptor */ | |||
62 | #define UMIDI_MS_HEADER 0x01 | |||
63 | #define UMIDI_IN_JACK 0x02 | |||
64 | #define UMIDI_OUT_JACK 0x03 | |||
65 | ||||
66 | /* Jack Type */ | |||
67 | #define UMIDI_EMBEDDED 0x01 | |||
68 | #define UMIDI_EXTERNAL 0x02 | |||
69 | ||||
70 | /* generic, for iteration */ | |||
71 | typedef struct { | |||
72 | uByte bLength; | |||
73 | uByte bDescriptorType; | |||
74 | uByte bDescriptorSubtype; | |||
75 | } UPACKED umidi_cs_descriptor_t; | |||
76 | ||||
77 | typedef struct { | |||
78 | uByte bLength; | |||
79 | uByte bDescriptorType; | |||
80 | uByte bDescriptorSubtype; | |||
81 | uWord bcdMSC; | |||
82 | uWord wTotalLength; | |||
83 | } UPACKED umidi_cs_interface_descriptor_t; | |||
84 | #define UMIDI_CS_INTERFACE_DESCRIPTOR_SIZE 7 | |||
85 | ||||
86 | typedef struct { | |||
87 | uByte bLength; | |||
88 | uByte bDescriptorType; | |||
89 | uByte bDescriptorSubtype; | |||
90 | uByte bNumEmbMIDIJack; | |||
91 | } UPACKED umidi_cs_endpoint_descriptor_t; | |||
92 | #define UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE 4 | |||
93 | ||||
94 | typedef struct { | |||
95 | uByte bLength; | |||
96 | uByte bDescriptorType; | |||
97 | uByte bDescriptorSubtype; | |||
98 | uByte bJackType; | |||
99 | uByte bJackID; | |||
100 | } UPACKED umidi_jack_descriptor_t; | |||
101 | #define UMIDI_JACK_DESCRIPTOR_SIZE 5 | |||
102 | ||||
103 | ||||
104 | #define TO_D(p) ((usb_descriptor_t *)(p)) | |||
105 | #define NEXT_D(desc) TO_D((char *)(desc)+(desc)->bLength) | |||
106 | #define TO_IFD(desc) ((usb_interface_descriptor_t *)(desc)) | |||
107 | #define TO_CSIFD(desc) ((umidi_cs_interface_descriptor_t *)(desc)) | |||
108 | #define TO_EPD(desc) ((usb_endpoint_descriptor_t *)(desc)) | |||
109 | #define TO_CSEPD(desc) ((umidi_cs_endpoint_descriptor_t *)(desc)) | |||
110 | ||||
111 | ||||
112 | #define UMIDI_PACKET_SIZE 4 | |||
113 | ||||
114 | /* | |||
115 | * hierarchie | |||
116 | * | |||
117 | * <-- parent child --> | |||
118 | * | |||
119 | * umidi(sc) -> endpoint -> jack <- (dynamically assignable) - mididev | |||
120 | * ^ | ^ | | |||
121 | * +-----+ +-----+ | |||
122 | */ | |||
123 | ||||
124 | /* midi device */ | |||
125 | struct umidi_mididev { | |||
126 | struct umidi_softc *sc; | |||
127 | device_t mdev; | |||
128 | /* */ | |||
129 | struct umidi_jack *in_jack; | |||
130 | struct umidi_jack *out_jack; | |||
131 | char *label; | |||
132 | size_t label_len; | |||
133 | /* */ | |||
134 | int opened; | |||
135 | int closing; | |||
136 | int flags; | |||
137 | }; | |||
138 | ||||
139 | /* Jack Information */ | |||
140 | struct umidi_jack { | |||
141 | struct umidi_endpoint *endpoint; | |||
142 | /* */ | |||
143 | int cable_number; | |||
144 | void *arg; | |||
145 | int bound; | |||
146 | int opened; | |||
147 | unsigned char *midiman_ppkt; | |||
148 | union { | |||
149 | struct { | |||
150 | void (*intr)(void *); | |||
151 | } out; | |||
152 | struct { | |||
153 | void (*intr)(void *, int); | |||
154 | } in; | |||
155 | } u; | |||
156 | }; | |||
157 | ||||
158 | #define UMIDI_MAX_EPJACKS 16 | |||
159 | typedef unsigned char (*umidi_packet_bufp)[UMIDI_PACKET_SIZE]; | |||
160 | /* endpoint data */ | |||
161 | struct umidi_endpoint { | |||
162 | struct umidi_softc *sc; | |||
163 | /* */ | |||
164 | int addr; | |||
165 | usbd_pipe_handle pipe; | |||
166 | usbd_xfer_handle xfer; | |||
167 | umidi_packet_bufp buffer; | |||
168 | umidi_packet_bufp next_slot; | |||
169 | u_int32_t buffer_size; | |||
170 | int num_scheduled; | |||
171 | int num_open; | |||
172 | int num_jacks; | |||
173 | int soliciting; | |||
174 | void *solicit_cookie; | |||
175 | int armed; | |||
176 | struct umidi_jack *jacks[UMIDI_MAX_EPJACKS]; | |||
177 | u_int16_t this_schedule; /* see UMIDI_MAX_EPJACKS */ | |||
178 | u_int16_t next_schedule; | |||
179 | }; | |||
180 | ||||
181 | /* software context */ | |||
182 | struct umidi_softc { | |||
183 | device_t sc_dev; | |||
184 | usbd_device_handle sc_udev; | |||
185 | usbd_interface_handle sc_iface; | |||
186 | const struct umidi_quirk *sc_quirk; | |||
187 | ||||
188 | int sc_dying; | |||
189 | ||||
190 | int sc_out_num_jacks; | |||
191 | struct umidi_jack *sc_out_jacks; | |||
192 | int sc_in_num_jacks; | |||
193 | struct umidi_jack *sc_in_jacks; | |||
194 | struct umidi_jack *sc_jacks; | |||
195 | ||||
196 | int sc_num_mididevs; | |||
197 | struct umidi_mididev *sc_mididevs; | |||
198 | ||||
199 | int sc_out_num_endpoints; | |||
200 | struct umidi_endpoint *sc_out_ep; | |||
201 | int sc_in_num_endpoints; | |||
202 | struct umidi_endpoint *sc_in_ep; | |||
203 | struct umidi_endpoint *sc_endpoints; | |||
204 | size_t sc_endpoints_len; | |||
205 | int cblnums_global; | |||
206 | ||||
207 | kmutex_t sc_lock; | |||
208 | kcondvar_t sc_cv; | |||
209 | kcondvar_t sc_detach_cv; | |||
210 | ||||
211 | int sc_refcnt; | |||
212 | }; | |||
213 | ||||
64 | #ifdef UMIDI_DEBUG | 214 | #ifdef UMIDI_DEBUG | |
65 | #define DPRINTF(x) if (umididebug) printf x | 215 | #define DPRINTF(x) if (umididebug) printf x | |
66 | #define DPRINTFN(n,x) if (umididebug >= (n)) printf x | 216 | #define DPRINTFN(n,x) if (umididebug >= (n)) printf x | |
67 | #include <sys/time.h> | 217 | #include <sys/time.h> | |
68 | static struct timeval umidi_tv; | 218 | static struct timeval umidi_tv; | |
69 | int umididebug = 0; | 219 | int umididebug = 0; | |
70 | #else | 220 | #else | |
71 | #define DPRINTF(x) | 221 | #define DPRINTF(x) | |
72 | #define DPRINTFN(n,x) | 222 | #define DPRINTFN(n,x) | |
73 | #endif | 223 | #endif | |
74 | 224 | |||
75 | #define UMIDI_ENDPOINT_SIZE(sc) (sizeof(*(sc)->sc_out_ep) * \ | 225 | #define UMIDI_ENDPOINT_SIZE(sc) (sizeof(*(sc)->sc_out_ep) * \ | |
76 | (sc->sc_out_num_endpoints + \ | 226 | (sc->sc_out_num_endpoints + \ | |
@@ -200,69 +350,74 @@ umidi_attach(device_t parent, device_t s | @@ -200,69 +350,74 @@ umidi_attach(device_t parent, device_t s | |||
200 | aprint_normal_dev(self, "%s\n", devinfop); | 350 | aprint_normal_dev(self, "%s\n", devinfop); | |
201 | usbd_devinfo_free(devinfop); | 351 | usbd_devinfo_free(devinfop); | |
202 | 352 | |||
203 | sc->sc_iface = uaa->iface; | 353 | sc->sc_iface = uaa->iface; | |
204 | sc->sc_udev = uaa->device; | 354 | sc->sc_udev = uaa->device; | |
205 | 355 | |||
206 | sc->sc_quirk = | 356 | sc->sc_quirk = | |
207 | umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno); | 357 | umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno); | |
208 | aprint_normal_dev(self, ""); | 358 | aprint_normal_dev(self, ""); | |
209 | umidi_print_quirk(sc->sc_quirk); | 359 | umidi_print_quirk(sc->sc_quirk); | |
210 | 360 | |||
211 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_USB); | 361 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_USB); | |
212 | cv_init(&sc->sc_cv, "umidopcl"); | 362 | cv_init(&sc->sc_cv, "umidopcl"); | |
363 | cv_init(&sc->sc_detach_cv, "umidetcv"); | |||
364 | sc->sc_refcnt = 0; | |||
213 | 365 | |||
214 | err = alloc_all_endpoints(sc); | 366 | err = alloc_all_endpoints(sc); | |
215 | if (err != USBD_NORMAL_COMPLETION) { | 367 | if (err != USBD_NORMAL_COMPLETION) { | |
216 | aprint_error_dev(self, | 368 | aprint_error_dev(self, | |
217 | "alloc_all_endpoints failed. (err=%d)\n", err); | 369 | "alloc_all_endpoints failed. (err=%d)\n", err); | |
218 | goto error; | 370 | goto out; | |
219 | } | 371 | } | |
220 | err = alloc_all_jacks(sc); | 372 | err = alloc_all_jacks(sc); | |
221 | if (err != USBD_NORMAL_COMPLETION) { | 373 | if (err != USBD_NORMAL_COMPLETION) { | |
222 | free_all_endpoints(sc); | |||
223 | aprint_error_dev(self, "alloc_all_jacks failed. (err=%d)\n", | 374 | aprint_error_dev(self, "alloc_all_jacks failed. (err=%d)\n", | |
224 | err); | 375 | err); | |
225 | goto error; | 376 | goto out_free_endpoints; | |
226 | } | 377 | } | |
227 | aprint_normal_dev(self, "out=%d, in=%d\n", | 378 | aprint_normal_dev(self, "out=%d, in=%d\n", | |
228 | sc->sc_out_num_jacks, sc->sc_in_num_jacks); | 379 | sc->sc_out_num_jacks, sc->sc_in_num_jacks); | |
229 | 380 | |||
230 | err = assign_all_jacks_automatically(sc); | 381 | err = assign_all_jacks_automatically(sc); | |
231 | if (err != USBD_NORMAL_COMPLETION) { | 382 | if (err != USBD_NORMAL_COMPLETION) { | |
232 | unbind_all_jacks(sc); | |||
233 | free_all_jacks(sc); | |||
234 | free_all_endpoints(sc); | |||
235 | aprint_error_dev(self, | 383 | aprint_error_dev(self, | |
236 | "assign_all_jacks_automatically failed. (err=%d)\n", err); | 384 | "assign_all_jacks_automatically failed. (err=%d)\n", err); | |
237 | goto error; | 385 | goto out_free_jacks; | |
238 | } | 386 | } | |
239 | err = attach_all_mididevs(sc); | 387 | err = attach_all_mididevs(sc); | |
240 | if (err != USBD_NORMAL_COMPLETION) { | 388 | if (err != USBD_NORMAL_COMPLETION) { | |
241 | free_all_jacks(sc); | |||
242 | free_all_endpoints(sc); | |||
243 | aprint_error_dev(self, | 389 | aprint_error_dev(self, | |
244 | "attach_all_mididevs failed. (err=%d)\n", err); | 390 | "attach_all_mididevs failed. (err=%d)\n", err); | |
391 | goto out_free_jacks; | |||
245 | } | 392 | } | |
246 | 393 | |||
247 | #ifdef UMIDI_DEBUG | 394 | #ifdef UMIDI_DEBUG | |
248 | dump_sc(sc); | 395 | dump_sc(sc); | |
249 | #endif | 396 | #endif | |
250 | 397 | |||
251 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, | 398 | usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, | |
252 | sc->sc_udev, sc->sc_dev); | 399 | sc->sc_udev, sc->sc_dev); | |
253 | 400 | |||
254 | return; | 401 | return; | |
255 | error: | 402 | ||
403 | out_free_jacks: | |||
404 | unbind_all_jacks(sc); | |||
405 | free_all_jacks(sc); | |||
406 | ||||
407 | out_free_endpoints: | |||
408 | free_all_endpoints(sc); | |||
409 | ||||
410 | out: | |||
256 | aprint_error_dev(self, "disabled.\n"); | 411 | aprint_error_dev(self, "disabled.\n"); | |
257 | sc->sc_dying = 1; | 412 | sc->sc_dying = 1; | |
258 | KERNEL_UNLOCK_ONE(curlwp); | 413 | KERNEL_UNLOCK_ONE(curlwp); | |
259 | return; | 414 | return; | |
260 | } | 415 | } | |
261 | 416 | |||
262 | void | 417 | void | |
263 | umidi_childdet(device_t self, device_t child) | 418 | umidi_childdet(device_t self, device_t child) | |
264 | { | 419 | { | |
265 | int i; | 420 | int i; | |
266 | struct umidi_softc *sc = device_private(self); | 421 | struct umidi_softc *sc = device_private(self); | |
267 | 422 | |||
268 | KASSERT(sc->sc_mididevs != NULL); | 423 | KASSERT(sc->sc_mididevs != NULL); | |
@@ -289,175 +444,202 @@ umidi_activate(device_t self, enum devac | @@ -289,175 +444,202 @@ umidi_activate(device_t self, enum devac | |||
289 | default: | 444 | default: | |
290 | DPRINTFN(1,("umidi_activate (%d)\n", act)); | 445 | DPRINTFN(1,("umidi_activate (%d)\n", act)); | |
291 | return EOPNOTSUPP; | 446 | return EOPNOTSUPP; | |
292 | } | 447 | } | |
293 | } | 448 | } | |
294 | 449 | |||
295 | int | 450 | int | |
296 | umidi_detach(device_t self, int flags) | 451 | umidi_detach(device_t self, int flags) | |
297 | { | 452 | { | |
298 | struct umidi_softc *sc = device_private(self); | 453 | struct umidi_softc *sc = device_private(self); | |
299 | 454 | |||
300 | DPRINTFN(1,("umidi_detach\n")); | 455 | DPRINTFN(1,("umidi_detach\n")); | |
301 | 456 | |||
457 | mutex_enter(&sc->sc_lock); | |||
302 | sc->sc_dying = 1; | 458 | sc->sc_dying = 1; | |
459 | if (--sc->sc_refcnt >= 0) | |||
460 | usb_detach_wait(sc->sc_dev, &sc->sc_detach_cv, &sc->sc_lock); | |||
461 | mutex_exit(&sc->sc_lock); | |||
462 | ||||
303 | detach_all_mididevs(sc, flags); | 463 | detach_all_mididevs(sc, flags); | |
304 | free_all_mididevs(sc); | 464 | free_all_mididevs(sc); | |
305 | free_all_jacks(sc); | 465 | free_all_jacks(sc); | |
306 | free_all_endpoints(sc); | 466 | free_all_endpoints(sc); | |
307 | 467 | |||
308 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, | 468 | usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, | |
309 | sc->sc_dev); | 469 | sc->sc_dev); | |
310 | 470 | |||
311 | mutex_destroy(&sc->sc_lock); | 471 | mutex_destroy(&sc->sc_lock); | |
472 | cv_destroy(&sc->sc_detach_cv); | |||
312 | cv_destroy(&sc->sc_cv); | 473 | cv_destroy(&sc->sc_cv); | |
313 | 474 | |||
314 | return 0; | 475 | return 0; | |
315 | } | 476 | } | |
316 | 477 | |||
317 | 478 | |||
318 | /* | 479 | /* | |
319 | * midi_if stuffs | 480 | * midi_if stuffs | |
320 | */ | 481 | */ | |
321 | int | 482 | int | |
322 | umidi_open(void *addr, | 483 | umidi_open(void *addr, | |
323 | int flags, | 484 | int flags, | |
324 | void (*iintr)(void *, int), | 485 | void (*iintr)(void *, int), | |
325 | void (*ointr)(void *), | 486 | void (*ointr)(void *), | |
326 | void *arg) | 487 | void *arg) | |
327 | { | 488 | { | |
328 | struct umidi_mididev *mididev = addr; | 489 | struct umidi_mididev *mididev = addr; | |
329 | struct umidi_softc *sc = mididev->sc; | 490 | struct umidi_softc *sc = mididev->sc; | |
330 | usbd_status err; | 491 | usbd_status err; | |
331 | 492 | |||
493 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
332 | DPRINTF(("umidi_open: sc=%p\n", sc)); | 494 | DPRINTF(("umidi_open: sc=%p\n", sc)); | |
333 | 495 | |||
334 | if (!sc) | |||
335 | return ENXIO; | |||
336 | if (mididev->opened) | 496 | if (mididev->opened) | |
337 | return EBUSY; | 497 | return EBUSY; | |
338 | if (sc->sc_dying) | 498 | if (sc->sc_dying) | |
339 | return EIO; | 499 | return EIO; | |
340 | 500 | |||
341 | mididev->opened = 1; | 501 | mididev->opened = 1; | |
342 | mididev->closing = 0; | |||
343 | mididev->flags = flags; | 502 | mididev->flags = flags; | |
344 | if ((mididev->flags & FWRITE) && mididev->out_jack) { | 503 | if ((mididev->flags & FWRITE) && mididev->out_jack) { | |
345 | err = open_out_jack(mididev->out_jack, arg, ointr); | 504 | err = open_out_jack(mididev->out_jack, arg, ointr); | |
346 | if ( err != USBD_NORMAL_COMPLETION ) | 505 | if (err != USBD_NORMAL_COMPLETION) | |
347 | goto bad; | 506 | goto bad; | |
348 | } | 507 | } | |
349 | if ((mididev->flags & FREAD) && mididev->in_jack) { | 508 | if ((mididev->flags & FREAD) && mididev->in_jack) { | |
350 | err = open_in_jack(mididev->in_jack, arg, iintr); | 509 | err = open_in_jack(mididev->in_jack, arg, iintr); | |
351 | if ( err != USBD_NORMAL_COMPLETION | 510 | KASSERT(mididev->opened); | |
352 | && err != USBD_IN_PROGRESS ) | 511 | if (err != USBD_NORMAL_COMPLETION && | |
512 | err != USBD_IN_PROGRESS) { | |||
513 | if (mididev->out_jack) | |||
514 | close_out_jack(mididev->out_jack); | |||
353 | goto bad; | 515 | goto bad; | |
516 | } | |||
354 | } | 517 | } | |
355 | 518 | |||
356 | return 0; | 519 | return 0; | |
357 | bad: | 520 | bad: | |
358 | mididev->opened = 0; | 521 | mididev->opened = 0; | |
359 | DPRINTF(("umidi_open: usbd_status %d\n", err)); | 522 | DPRINTF(("umidi_open: usbd_status %d\n", err)); | |
523 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
360 | return USBD_IN_USE == err ? EBUSY : EIO; | 524 | return USBD_IN_USE == err ? EBUSY : EIO; | |
361 | } | 525 | } | |
362 | 526 | |||
363 | void | 527 | void | |
364 | umidi_close(void *addr) | 528 | umidi_close(void *addr) | |
365 | { | 529 | { | |
366 | struct umidi_mididev *mididev = addr; | 530 | struct umidi_mididev *mididev = addr; | |
531 | struct umidi_softc *sc = mididev->sc; | |||
532 | ||||
533 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
534 | ||||
535 | if (mididev->closing) | |||
536 | return; | |||
367 | 537 | |||
368 | mididev->closing = 1; | 538 | mididev->closing = 1; | |
369 | 539 | |||
370 | mutex_spin_exit(&mididev->sc->sc_lock); | 540 | sc->sc_refcnt++; | |
371 | 541 | |||
372 | if ((mididev->flags & FWRITE) && mididev->out_jack) | 542 | if ((mididev->flags & FWRITE) && mididev->out_jack) | |
373 | close_out_jack(mididev->out_jack); | 543 | close_out_jack(mididev->out_jack); | |
374 | if ((mididev->flags & FREAD) && mididev->in_jack) | 544 | if ((mididev->flags & FREAD) && mididev->in_jack) | |
375 | close_in_jack(mididev->in_jack); | 545 | close_in_jack(mididev->in_jack); | |
376 | 546 | |||
377 | mutex_spin_enter(&mididev->sc->sc_lock); | 547 | if (--sc->sc_refcnt < 0) | |
548 | usb_detach_broadcast(sc->sc_dev, &sc->sc_detach_cv); | |||
378 | 549 | |||
379 | mididev->opened = 0; | 550 | mididev->opened = 0; | |
551 | mididev->closing = 0; | |||
380 | } | 552 | } | |
381 | 553 | |||
382 | int | 554 | int | |
383 | umidi_channelmsg(void *addr, int status, int channel, u_char *msg, | 555 | umidi_channelmsg(void *addr, int status, int channel, u_char *msg, | |
384 | int len) | 556 | int len) | |
385 | { | 557 | { | |
386 | struct umidi_mididev *mididev = addr; | 558 | struct umidi_mididev *mididev = addr; | |
387 | 559 | |||
560 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); | |||
561 | ||||
388 | if (!mididev->out_jack || !mididev->opened || mididev->closing) | 562 | if (!mididev->out_jack || !mididev->opened || mididev->closing) | |
389 | return EIO; | 563 | return EIO; | |
390 | 564 | |||
391 | return out_jack_output(mididev->out_jack, msg, len, (status>>4)&0xf); | 565 | return out_jack_output(mididev->out_jack, msg, len, (status>>4)&0xf); | |
392 | } | 566 | } | |
393 | 567 | |||
394 | int | 568 | int | |
395 | umidi_commonmsg(void *addr, int status, u_char *msg, int len) | 569 | umidi_commonmsg(void *addr, int status, u_char *msg, int len) | |
396 | { | 570 | { | |
397 | struct umidi_mididev *mididev = addr; | 571 | struct umidi_mididev *mididev = addr; | |
398 | int cin; | 572 | int cin; | |
399 | 573 | |||
574 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); | |||
575 | ||||
400 | if (!mididev->out_jack || !mididev->opened || mididev->closing) | 576 | if (!mididev->out_jack || !mididev->opened || mididev->closing) | |
401 | return EIO; | 577 | return EIO; | |
402 | 578 | |||
403 | switch ( len ) { | 579 | switch ( len ) { | |
404 | case 1: cin = 5; break; | 580 | case 1: cin = 5; break; | |
405 | case 2: cin = 2; break; | 581 | case 2: cin = 2; break; | |
406 | case 3: cin = 3; break; | 582 | case 3: cin = 3; break; | |
407 | default: return EIO; /* or gcc warns of cin uninitialized */ | 583 | default: return EIO; /* or gcc warns of cin uninitialized */ | |
408 | } | 584 | } | |
409 | 585 | |||
410 | return out_jack_output(mididev->out_jack, msg, len, cin); | 586 | return out_jack_output(mididev->out_jack, msg, len, cin); | |
411 | } | 587 | } | |
412 | 588 | |||
413 | int | 589 | int | |
414 | umidi_sysex(void *addr, u_char *msg, int len) | 590 | umidi_sysex(void *addr, u_char *msg, int len) | |
415 | { | 591 | { | |
416 | struct umidi_mididev *mididev = addr; | 592 | struct umidi_mididev *mididev = addr; | |
417 | int cin; | 593 | int cin; | |
418 | 594 | |||
595 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); | |||
596 | ||||
419 | if (!mididev->out_jack || !mididev->opened || mididev->closing) | 597 | if (!mididev->out_jack || !mididev->opened || mididev->closing) | |
420 | return EIO; | 598 | return EIO; | |
421 | 599 | |||
422 | switch ( len ) { | 600 | switch ( len ) { | |
423 | case 1: cin = 5; break; | 601 | case 1: cin = 5; break; | |
424 | case 2: cin = 6; break; | 602 | case 2: cin = 6; break; | |
425 | case 3: cin = (msg[2] == 0xf7) ? 7 : 4; break; | 603 | case 3: cin = (msg[2] == 0xf7) ? 7 : 4; break; | |
426 | default: return EIO; /* or gcc warns of cin uninitialized */ | 604 | default: return EIO; /* or gcc warns of cin uninitialized */ | |
427 | } | 605 | } | |
428 | 606 | |||
429 | return out_jack_output(mididev->out_jack, msg, len, cin); | 607 | return out_jack_output(mididev->out_jack, msg, len, cin); | |
430 | } | 608 | } | |
431 | 609 | |||
432 | int | 610 | int | |
433 | umidi_rtmsg(void *addr, int d) | 611 | umidi_rtmsg(void *addr, int d) | |
434 | { | 612 | { | |
435 | struct umidi_mididev *mididev = addr; | 613 | struct umidi_mididev *mididev = addr; | |
436 | u_char msg = d; | 614 | u_char msg = d; | |
437 | 615 | |||
616 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); | |||
617 | ||||
438 | if (!mididev->out_jack || !mididev->opened || mididev->closing) | 618 | if (!mididev->out_jack || !mididev->opened || mididev->closing) | |
439 | return EIO; | 619 | return EIO; | |
440 | 620 | |||
441 | return out_jack_output(mididev->out_jack, &msg, 1, 0xf); | 621 | return out_jack_output(mididev->out_jack, &msg, 1, 0xf); | |
442 | } | 622 | } | |
443 | 623 | |||
444 | void | 624 | void | |
445 | umidi_getinfo(void *addr, struct midi_info *mi) | 625 | umidi_getinfo(void *addr, struct midi_info *mi) | |
446 | { | 626 | { | |
447 | struct umidi_mididev *mididev = addr; | 627 | struct umidi_mididev *mididev = addr; | |
448 | struct umidi_softc *sc = mididev->sc; | 628 | struct umidi_softc *sc = mididev->sc; | |
449 | int mm = UMQ_ISTYPE(sc, UMQ_TYPE_MIDIMAN_GARBLE); | 629 | int mm = UMQ_ISTYPE(sc, UMQ_TYPE_MIDIMAN_GARBLE); | |
450 | 630 | |||
631 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
632 | ||||
451 | mi->name = mididev->label; | 633 | mi->name = mididev->label; | |
452 | mi->props = MIDI_PROP_OUT_INTR; | 634 | mi->props = MIDI_PROP_OUT_INTR; | |
453 | if (mididev->in_jack) | 635 | if (mididev->in_jack) | |
454 | mi->props |= MIDI_PROP_CAN_INPUT; | 636 | mi->props |= MIDI_PROP_CAN_INPUT; | |
455 | midi_register_hw_if_ext(mm? &umidi_hw_if_mm : &umidi_hw_if_ext); | 637 | midi_register_hw_if_ext(mm? &umidi_hw_if_mm : &umidi_hw_if_ext); | |
456 | } | 638 | } | |
457 | 639 | |||
458 | static void | 640 | static void | |
459 | umidi_get_locks(void *addr, kmutex_t **thread, kmutex_t **intr) | 641 | umidi_get_locks(void *addr, kmutex_t **thread, kmutex_t **intr) | |
460 | { | 642 | { | |
461 | struct umidi_mididev *mididev = addr; | 643 | struct umidi_mididev *mididev = addr; | |
462 | struct umidi_softc *sc = mididev->sc; | 644 | struct umidi_softc *sc = mididev->sc; | |
463 | 645 | |||
@@ -646,27 +828,27 @@ alloc_all_endpoints_fixed_ep(struct umid | @@ -646,27 +828,27 @@ alloc_all_endpoints_fixed_ep(struct umid | |||
646 | } | 828 | } | |
647 | /* | 829 | /* | |
648 | * MIDISPORT_2X4 inputs on an interrupt rather than a bulk | 830 | * MIDISPORT_2X4 inputs on an interrupt rather than a bulk | |
649 | * endpoint. The existing input logic in this driver seems | 831 | * endpoint. The existing input logic in this driver seems | |
650 | * to work successfully if we just stop treating an interrupt | 832 | * to work successfully if we just stop treating an interrupt | |
651 | * endpoint as illegal (or the in_progress status we get on | 833 | * endpoint as illegal (or the in_progress status we get on | |
652 | * the initial transfer). It does not seem necessary to | 834 | * the initial transfer). It does not seem necessary to | |
653 | * actually use the interrupt flavor of alloc_pipe or make | 835 | * actually use the interrupt flavor of alloc_pipe or make | |
654 | * other serious rearrangements of logic. I like that. | 836 | * other serious rearrangements of logic. I like that. | |
655 | */ | 837 | */ | |
656 | switch ( UE_GET_XFERTYPE(epd->bmAttributes) ) { | 838 | switch ( UE_GET_XFERTYPE(epd->bmAttributes) ) { | |
657 | case UE_BULK: | 839 | case UE_BULK: | |
658 | case UE_INTERRUPT: | 840 | case UE_INTERRUPT: | |
659 | if ( UE_DIR_IN == UE_GET_DIR(epd->bEndpointAddress) ) | 841 | if (UE_DIR_IN == UE_GET_DIR(epd->bEndpointAddress)) | |
660 | break; | 842 | break; | |
661 | /*FALLTHROUGH*/ | 843 | /*FALLTHROUGH*/ | |
662 | default: | 844 | default: | |
663 | aprint_error_dev(sc->sc_dev, | 845 | aprint_error_dev(sc->sc_dev, | |
664 | "illegal endpoint(in:%d)\n", fp->in_ep[i].ep); | 846 | "illegal endpoint(in:%d)\n", fp->in_ep[i].ep); | |
665 | err = USBD_INVAL; | 847 | err = USBD_INVAL; | |
666 | goto error; | 848 | goto error; | |
667 | } | 849 | } | |
668 | 850 | |||
669 | ep->sc = sc; | 851 | ep->sc = sc; | |
670 | ep->addr = epd->bEndpointAddress; | 852 | ep->addr = epd->bEndpointAddress; | |
671 | ep->num_jacks = fp->in_ep[i].num_jacks; | 853 | ep->num_jacks = fp->in_ep[i].num_jacks; | |
672 | sc->sc_in_num_jacks += fp->in_ep[i].num_jacks; | 854 | sc->sc_in_num_jacks += fp->in_ep[i].num_jacks; | |
@@ -906,38 +1088,38 @@ alloc_all_jacks(struct umidi_softc *sc) | @@ -906,38 +1088,38 @@ alloc_all_jacks(struct umidi_softc *sc) | |||
906 | /* allocate/initialize structures */ | 1088 | /* allocate/initialize structures */ | |
907 | sc->sc_jacks = kmem_zalloc(sizeof(*sc->sc_out_jacks)*(sc->sc_in_num_jacks+ | 1089 | sc->sc_jacks = kmem_zalloc(sizeof(*sc->sc_out_jacks)*(sc->sc_in_num_jacks+ | |
908 | sc->sc_out_num_jacks), KM_SLEEP); | 1090 | sc->sc_out_num_jacks), KM_SLEEP); | |
909 | if (!sc->sc_jacks) | 1091 | if (!sc->sc_jacks) | |
910 | return USBD_NOMEM; | 1092 | return USBD_NOMEM; | |
911 | sc->sc_out_jacks = | 1093 | sc->sc_out_jacks = | |
912 | sc->sc_out_num_jacks ? sc->sc_jacks : NULL; | 1094 | sc->sc_out_num_jacks ? sc->sc_jacks : NULL; | |
913 | sc->sc_in_jacks = | 1095 | sc->sc_in_jacks = | |
914 | sc->sc_in_num_jacks ? sc->sc_jacks+sc->sc_out_num_jacks : NULL; | 1096 | sc->sc_in_num_jacks ? sc->sc_jacks+sc->sc_out_num_jacks : NULL; | |
915 | 1097 | |||
916 | jack = &sc->sc_out_jacks[0]; | 1098 | jack = &sc->sc_out_jacks[0]; | |
917 | for (i = 0; i < sc->sc_out_num_jacks; i++) { | 1099 | for (i = 0; i < sc->sc_out_num_jacks; i++) { | |
918 | jack->opened = 0; | 1100 | jack->opened = 0; | |
919 | jack->binded = 0; | 1101 | jack->bound = 0; | |
920 | jack->arg = NULL; | 1102 | jack->arg = NULL; | |
921 | jack->u.out.intr = NULL; | 1103 | jack->u.out.intr = NULL; | |
922 | jack->midiman_ppkt = NULL; | 1104 | jack->midiman_ppkt = NULL; | |
923 | if (sc->cblnums_global) | 1105 | if (sc->cblnums_global) | |
924 | jack->cable_number = i; | 1106 | jack->cable_number = i; | |
925 | jack++; | 1107 | jack++; | |
926 | } | 1108 | } | |
927 | jack = &sc->sc_in_jacks[0]; | 1109 | jack = &sc->sc_in_jacks[0]; | |
928 | for (i = 0; i < sc->sc_in_num_jacks; i++) { | 1110 | for (i = 0; i < sc->sc_in_num_jacks; i++) { | |
929 | jack->opened = 0; | 1111 | jack->opened = 0; | |
930 | jack->binded = 0; | 1112 | jack->bound = 0; | |
931 | jack->arg = NULL; | 1113 | jack->arg = NULL; | |
932 | jack->u.in.intr = NULL; | 1114 | jack->u.in.intr = NULL; | |
933 | if (sc->cblnums_global) | 1115 | if (sc->cblnums_global) | |
934 | jack->cable_number = i; | 1116 | jack->cable_number = i; | |
935 | jack++; | 1117 | jack++; | |
936 | } | 1118 | } | |
937 | 1119 | |||
938 | /* assign each jacks to each endpoints */ | 1120 | /* assign each jacks to each endpoints */ | |
939 | jack = &sc->sc_out_jacks[0]; | 1121 | jack = &sc->sc_out_jacks[0]; | |
940 | ep = &sc->sc_out_ep[0]; | 1122 | ep = &sc->sc_out_ep[0]; | |
941 | for (i = 0; i < sc->sc_out_num_endpoints; i++) { | 1123 | for (i = 0; i < sc->sc_out_num_endpoints; i++) { | |
942 | for (j = 0; j < ep->num_jacks; j++) { | 1124 | for (j = 0; j < ep->num_jacks; j++) { | |
943 | jack->endpoint = ep; | 1125 | jack->endpoint = ep; | |
@@ -980,107 +1162,117 @@ free_all_jacks(struct umidi_softc *sc) | @@ -980,107 +1162,117 @@ free_all_jacks(struct umidi_softc *sc) | |||
980 | sc->sc_jacks = sc->sc_in_jacks = sc->sc_out_jacks = NULL; | 1162 | sc->sc_jacks = sc->sc_in_jacks = sc->sc_out_jacks = NULL; | |
981 | mutex_exit(&sc->sc_lock); | 1163 | mutex_exit(&sc->sc_lock); | |
982 | 1164 | |||
983 | if (jacks) | 1165 | if (jacks) | |
984 | kmem_free(jacks, len); | 1166 | kmem_free(jacks, len); | |
985 | } | 1167 | } | |
986 | 1168 | |||
987 | static usbd_status | 1169 | static usbd_status | |
988 | bind_jacks_to_mididev(struct umidi_softc *sc, | 1170 | bind_jacks_to_mididev(struct umidi_softc *sc, | |
989 | struct umidi_jack *out_jack, | 1171 | struct umidi_jack *out_jack, | |
990 | struct umidi_jack *in_jack, | 1172 | struct umidi_jack *in_jack, | |
991 | struct umidi_mididev *mididev) | 1173 | struct umidi_mididev *mididev) | |
992 | { | 1174 | { | |
993 | if ((out_jack && out_jack->binded) || (in_jack && in_jack->binded)) | 1175 | if ((out_jack && out_jack->bound) || (in_jack && in_jack->bound)) | |
994 | return USBD_IN_USE; | 1176 | return USBD_IN_USE; | |
995 | if (mididev->out_jack || mididev->in_jack) | 1177 | if (mididev->out_jack || mididev->in_jack) | |
996 | return USBD_IN_USE; | 1178 | return USBD_IN_USE; | |
997 | 1179 | |||
998 | if (out_jack) | 1180 | if (out_jack) | |
999 | out_jack->binded = 1; | 1181 | out_jack->bound = 1; | |
1000 | if (in_jack) | 1182 | if (in_jack) | |
1001 | in_jack->binded = 1; | 1183 | in_jack->bound = 1; | |
1002 | mididev->in_jack = in_jack; | 1184 | mididev->in_jack = in_jack; | |
1003 | mididev->out_jack = out_jack; | 1185 | mididev->out_jack = out_jack; | |
1004 | 1186 | |||
1187 | mididev->closing = 0; | |||
1188 | ||||
1005 | return USBD_NORMAL_COMPLETION; | 1189 | return USBD_NORMAL_COMPLETION; | |
1006 | } | 1190 | } | |
1007 | 1191 | |||
1008 | static void | 1192 | static void | |
1009 | unbind_jacks_from_mididev(struct umidi_mididev *mididev) | 1193 | unbind_jacks_from_mididev(struct umidi_mididev *mididev) | |
1010 | { | 1194 | { | |
1195 | KASSERT(mutex_owned(&mididev->sc->sc_lock)); | |||
1196 | ||||
1197 | mididev->closing = 1; | |||
1011 | 1198 | |||
1012 | if ((mididev->flags & FWRITE) && mididev->out_jack) | 1199 | if ((mididev->flags & FWRITE) && mididev->out_jack) | |
1013 | close_out_jack(mididev->out_jack); | 1200 | close_out_jack(mididev->out_jack); | |
1014 | if ((mididev->flags & FREAD) && mididev->in_jack) | 1201 | if ((mididev->flags & FREAD) && mididev->in_jack) | |
1015 | close_in_jack(mididev->in_jack); | 1202 | close_in_jack(mididev->in_jack); | |
1016 | 1203 | |||
1017 | if (mididev->out_jack) | 1204 | if (mididev->out_jack) { | |
1018 | mididev->out_jack->binded = 0; | 1205 | mididev->out_jack->bound = 0; | |
1019 | if (mididev->in_jack) | 1206 | mididev->out_jack = NULL; | |
1020 | mididev->in_jack->binded = 0; | 1207 | } | |
1021 | mididev->out_jack = mididev->in_jack = NULL; | 1208 | if (mididev->in_jack) { | |
1209 | mididev->in_jack->bound = 0; | |||
1210 | mididev->in_jack = NULL; | |||
1211 | } | |||
1022 | } | 1212 | } | |
1023 | 1213 | |||
1024 | static void | 1214 | static void | |
1025 | unbind_all_jacks(struct umidi_softc *sc) | 1215 | unbind_all_jacks(struct umidi_softc *sc) | |
1026 | { | 1216 | { | |
1027 | int i; | 1217 | int i; | |
1028 | 1218 | |||
1219 | mutex_spin_enter(&sc->sc_lock); | |||
1029 | if (sc->sc_mididevs) | 1220 | if (sc->sc_mididevs) | |
1030 | for (i = 0; i < sc->sc_num_mididevs; i++) | 1221 | for (i = 0; i < sc->sc_num_mididevs; i++) | |
1031 | unbind_jacks_from_mididev(&sc->sc_mididevs[i]); | 1222 | unbind_jacks_from_mididev(&sc->sc_mididevs[i]); | |
1223 | mutex_spin_exit(&sc->sc_lock); | |||
1032 | } | 1224 | } | |
1033 | 1225 | |||
1034 | static usbd_status | 1226 | static usbd_status | |
1035 | assign_all_jacks_automatically(struct umidi_softc *sc) | 1227 | assign_all_jacks_automatically(struct umidi_softc *sc) | |
1036 | { | 1228 | { | |
1037 | usbd_status err; | 1229 | usbd_status err; | |
1038 | int i; | 1230 | int i; | |
1039 | struct umidi_jack *out, *in; | 1231 | struct umidi_jack *out, *in; | |
1040 | const signed char *asg_spec; | 1232 | const signed char *asg_spec; | |
1041 | 1233 | |||
1042 | err = | 1234 | err = | |
1043 | alloc_all_mididevs(sc, | 1235 | alloc_all_mididevs(sc, | |
1044 | max(sc->sc_out_num_jacks, sc->sc_in_num_jacks)); | 1236 | max(sc->sc_out_num_jacks, sc->sc_in_num_jacks)); | |
1045 | if (err!=USBD_NORMAL_COMPLETION) | 1237 | if (err!=USBD_NORMAL_COMPLETION) | |
1046 | return err; | 1238 | return err; | |
1047 | 1239 | |||
1048 | if ( UMQ_ISTYPE(sc, UMQ_TYPE_MD_FIXED)) | 1240 | if (UMQ_ISTYPE(sc, UMQ_TYPE_MD_FIXED)) | |
1049 | asg_spec = umidi_get_quirk_data_from_type(sc->sc_quirk, | 1241 | asg_spec = umidi_get_quirk_data_from_type(sc->sc_quirk, | |
1050 | UMQ_TYPE_MD_FIXED); | 1242 | UMQ_TYPE_MD_FIXED); | |
1051 | else | 1243 | else | |
1052 | asg_spec = NULL; | 1244 | asg_spec = NULL; | |
1053 | 1245 | |||
1054 | for (i = 0; i < sc->sc_num_mididevs; i++) { | 1246 | for (i = 0; i < sc->sc_num_mididevs; i++) { | |
1055 | if (asg_spec != NULL) { | 1247 | if (asg_spec != NULL) { | |
1056 | if (*asg_spec == -1) | 1248 | if (*asg_spec == -1) | |
1057 | out = NULL; | 1249 | out = NULL; | |
1058 | else | 1250 | else | |
1059 | out = &sc->sc_out_jacks[*asg_spec]; | 1251 | out = &sc->sc_out_jacks[*asg_spec]; | |
1060 | ++ asg_spec; | 1252 | ++ asg_spec; | |
1061 | if (*asg_spec == -1) | 1253 | if (*asg_spec == -1) | |
1062 | in = NULL; | 1254 | in = NULL; | |
1063 | else | 1255 | else | |
1064 | in = &sc->sc_in_jacks[*asg_spec]; | 1256 | in = &sc->sc_in_jacks[*asg_spec]; | |
1065 | ++ asg_spec; | 1257 | ++ asg_spec; | |
1066 | } else { | 1258 | } else { | |
1067 | out = (i<sc->sc_out_num_jacks) ? &sc->sc_out_jacks[i] | 1259 | out = (i<sc->sc_out_num_jacks) ? &sc->sc_out_jacks[i] | |
1068 | : NULL; | 1260 | : NULL; | |
1069 | in = (i<sc->sc_in_num_jacks) ? &sc->sc_in_jacks[i] | 1261 | in = (i<sc->sc_in_num_jacks) ? &sc->sc_in_jacks[i] | |
1070 | : NULL; | 1262 | : NULL; | |
1071 | } | 1263 | } | |
1072 | err = bind_jacks_to_mididev(sc, out, in, &sc->sc_mididevs[i]); | 1264 | err = bind_jacks_to_mididev(sc, out, in, &sc->sc_mididevs[i]); | |
1073 | if (err!=USBD_NORMAL_COMPLETION) { | 1265 | if (err != USBD_NORMAL_COMPLETION) { | |
1074 | free_all_mididevs(sc); | 1266 | free_all_mididevs(sc); | |
1075 | return err; | 1267 | return err; | |
1076 | } | 1268 | } | |
1077 | } | 1269 | } | |
1078 | 1270 | |||
1079 | return USBD_NORMAL_COMPLETION; | 1271 | return USBD_NORMAL_COMPLETION; | |
1080 | } | 1272 | } | |
1081 | 1273 | |||
1082 | static usbd_status | 1274 | static usbd_status | |
1083 | open_out_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *)) | 1275 | open_out_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *)) | |
1084 | { | 1276 | { | |
1085 | struct umidi_endpoint *ep = jack->endpoint; | 1277 | struct umidi_endpoint *ep = jack->endpoint; | |
1086 | struct umidi_softc *sc = ep->sc; | 1278 | struct umidi_softc *sc = ep->sc; | |
@@ -1122,146 +1314,177 @@ open_in_jack(struct umidi_jack *jack, vo | @@ -1122,146 +1314,177 @@ open_in_jack(struct umidi_jack *jack, vo | |||
1122 | { | 1314 | { | |
1123 | usbd_status err = USBD_NORMAL_COMPLETION; | 1315 | usbd_status err = USBD_NORMAL_COMPLETION; | |
1124 | struct umidi_endpoint *ep = jack->endpoint; | 1316 | struct umidi_endpoint *ep = jack->endpoint; | |
1125 | 1317 | |||
1126 | KASSERT(mutex_owned(&ep->sc->sc_lock)); | 1318 | KASSERT(mutex_owned(&ep->sc->sc_lock)); | |
1127 | 1319 | |||
1128 | if (jack->opened) | 1320 | if (jack->opened) | |
1129 | return USBD_IN_USE; | 1321 | return USBD_IN_USE; | |
1130 | 1322 | |||
1131 | jack->arg = arg; | 1323 | jack->arg = arg; | |
1132 | jack->u.in.intr = intr; | 1324 | jack->u.in.intr = intr; | |
1133 | jack->opened = 1; | 1325 | jack->opened = 1; | |
1134 | if (ep->num_open++ == 0 && UE_GET_DIR(ep->addr)==UE_DIR_IN) { | 1326 | if (ep->num_open++ == 0 && UE_GET_DIR(ep->addr)==UE_DIR_IN) { | |
1327 | /* | |||
1328 | * Can't hold the interrupt lock while calling into USB, | |||
1329 | * but we can safely drop it here. | |||
1330 | */ | |||
1331 | mutex_exit(&ep->sc->sc_lock); | |||
1135 | err = start_input_transfer(ep); | 1332 | err = start_input_transfer(ep); | |
1136 | if (err != USBD_NORMAL_COMPLETION && | 1333 | if (err != USBD_NORMAL_COMPLETION && | |
1137 | err != USBD_IN_PROGRESS) { | 1334 | err != USBD_IN_PROGRESS) { | |
1138 | ep->num_open--; | 1335 | ep->num_open--; | |
1139 | } | 1336 | } | |
1337 | mutex_enter(&ep->sc->sc_lock); | |||
1140 | } | 1338 | } | |
1141 | 1339 | |||
1142 | return err; | 1340 | return err; | |
1143 | } | 1341 | } | |
1144 | 1342 | |||
1145 | static void | 1343 | static void | |
1146 | close_out_jack(struct umidi_jack *jack) | 1344 | close_out_jack(struct umidi_jack *jack) | |
1147 | { | 1345 | { | |
1148 | struct umidi_endpoint *ep; | 1346 | struct umidi_endpoint *ep; | |
1149 | struct umidi_softc *sc; | 1347 | struct umidi_softc *sc; | |
1150 | u_int16_t mask; | 1348 | u_int16_t mask; | |
1151 | int err; | 1349 | int err; | |
1152 | 1350 | |||
1153 | if (jack->opened) { | 1351 | if (jack->opened) { | |
1154 | ep = jack->endpoint; | 1352 | ep = jack->endpoint; | |
1155 | sc = ep->sc; | 1353 | sc = ep->sc; | |
1156 | mutex_spin_enter(&sc->sc_lock); | 1354 | ||
1355 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
1157 | mask = 1 << (jack->cable_number); | 1356 | mask = 1 << (jack->cable_number); | |
1158 | while (mask & (ep->this_schedule | ep->next_schedule)) { | 1357 | while (mask & (ep->this_schedule | ep->next_schedule)) { | |
1159 | err = cv_timedwait_sig(&sc->sc_cv, &sc->sc_lock, | 1358 | err = cv_timedwait_sig(&sc->sc_cv, &sc->sc_lock, | |
1160 | mstohz(10)); | 1359 | mstohz(10)); | |
1161 | if (err) | 1360 | if (err) | |
1162 | break; | 1361 | break; | |
1163 | } | 1362 | } | |
1164 | /* | 1363 | /* | |
1165 | * We can re-enter this function from both close() and | 1364 | * We can re-enter this function from both close() and | |
1166 | * detach(). Make sure only one of them does this part. | 1365 | * detach(). Make sure only one of them does this part. | |
1167 | */ | 1366 | */ | |
1168 | if (jack->opened) { | 1367 | if (jack->opened) { | |
1169 | jack->opened = 0; | 1368 | jack->opened = 0; | |
1170 | jack->endpoint->num_open--; | 1369 | jack->endpoint->num_open--; | |
1171 | ep->this_schedule &= ~mask; | 1370 | ep->this_schedule &= ~mask; | |
1172 | ep->next_schedule &= ~mask; | 1371 | ep->next_schedule &= ~mask; | |
1173 | } | 1372 | } | |
1174 | mutex_spin_exit(&sc->sc_lock); | |||
1175 | } | 1373 | } | |
1176 | } | 1374 | } | |
1177 | 1375 | |||
1178 | static void | 1376 | static void | |
1179 | close_in_jack(struct umidi_jack *jack) | 1377 | close_in_jack(struct umidi_jack *jack) | |
1180 | { | 1378 | { | |
1181 | if (jack->opened) { | 1379 | if (jack->opened) { | |
1380 | struct umidi_softc *sc = jack->endpoint->sc; | |||
1381 | ||||
1382 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
1383 | ||||
1182 | jack->opened = 0; | 1384 | jack->opened = 0; | |
1183 | if (--jack->endpoint->num_open == 0) { | 1385 | if (--jack->endpoint->num_open == 0) { | |
1386 | /* | |||
1387 | * We have to drop the (interrupt) lock so that | |||
1388 | * the USB thread lock can be safely taken by | |||
1389 | * the abort operation. This is safe as this | |||
1390 | * either closing or dying will be set proerly. | |||
1391 | */ | |||
1392 | mutex_spin_exit(&sc->sc_lock); | |||
1184 | usbd_abort_pipe(jack->endpoint->pipe); | 1393 | usbd_abort_pipe(jack->endpoint->pipe); | |
1394 | mutex_spin_enter(&sc->sc_lock); | |||
1185 | } | 1395 | } | |
1186 | } | 1396 | } | |
1187 | } | 1397 | } | |
1188 | 1398 | |||
1189 | static usbd_status | 1399 | static usbd_status | |
1190 | attach_mididev(struct umidi_softc *sc, struct umidi_mididev *mididev) | 1400 | attach_mididev(struct umidi_softc *sc, struct umidi_mididev *mididev) | |
1191 | { | 1401 | { | |
1192 | if (mididev->sc) | 1402 | if (mididev->sc) | |
1193 | return USBD_IN_USE; | 1403 | return USBD_IN_USE; | |
1194 | 1404 | |||
1195 | mididev->sc = sc; | 1405 | mididev->sc = sc; | |
1196 | 1406 | |||
1197 | describe_mididev(mididev); | 1407 | describe_mididev(mididev); | |
1198 | 1408 | |||
1199 | mididev->mdev = midi_attach_mi(&umidi_hw_if, mididev, sc->sc_dev); | 1409 | mididev->mdev = midi_attach_mi(&umidi_hw_if, mididev, sc->sc_dev); | |
1200 | 1410 | |||
1201 | return USBD_NORMAL_COMPLETION; | 1411 | return USBD_NORMAL_COMPLETION; | |
1202 | } | 1412 | } | |
1203 | 1413 | |||
1204 | static usbd_status | 1414 | static usbd_status | |
1205 | detach_mididev(struct umidi_mididev *mididev, int flags) | 1415 | detach_mididev(struct umidi_mididev *mididev, int flags) | |
1206 | { | 1416 | { | |
1207 | if (!mididev->sc) | 1417 | struct umidi_softc *sc = mididev->sc; | |
1418 | ||||
1419 | if (!sc) | |||
1208 | return USBD_NO_ADDR; | 1420 | return USBD_NO_ADDR; | |
1209 | 1421 | |||
1422 | mutex_spin_enter(&sc->sc_lock); | |||
1210 | if (mididev->opened) { | 1423 | if (mididev->opened) { | |
1211 | umidi_close(mididev); | 1424 | umidi_close(mididev); | |
1212 | } | 1425 | } | |
1213 | unbind_jacks_from_mididev(mididev); | 1426 | unbind_jacks_from_mididev(mididev); | |
1427 | mutex_spin_exit(&sc->sc_lock); | |||
1214 | 1428 | |||
1215 | if (mididev->mdev != NULL) | 1429 | if (mididev->mdev != NULL) | |
1216 | config_detach(mididev->mdev, flags); | 1430 | config_detach(mididev->mdev, flags); | |
1217 | 1431 | |||
1218 | if (NULL != mididev->label) { | 1432 | if (NULL != mididev->label) { | |
1219 | kmem_free(mididev->label, mididev->label_len); | 1433 | kmem_free(mididev->label, mididev->label_len); | |
1220 | mididev->label = NULL; | 1434 | mididev->label = NULL; | |
1221 | } | 1435 | } | |
1222 | 1436 | |||
1223 | mididev->sc = NULL; | 1437 | mididev->sc = NULL; | |
1224 | 1438 | |||
1225 | return USBD_NORMAL_COMPLETION; | 1439 | return USBD_NORMAL_COMPLETION; | |
1226 | } | 1440 | } | |
1227 | 1441 | |||
1228 | static void | 1442 | static void | |
1229 | deactivate_mididev(struct umidi_mididev *mididev) | 1443 | deactivate_mididev(struct umidi_mididev *mididev) | |
1230 | { | 1444 | { | |
1231 | if (mididev->out_jack) | 1445 | if (mididev->out_jack) | |
1232 | mididev->out_jack->binded = 0; | 1446 | mididev->out_jack->bound = 0; | |
1233 | if (mididev->in_jack) | 1447 | if (mididev->in_jack) | |
1234 | mididev->in_jack->binded = 0; | 1448 | mididev->in_jack->bound = 0; | |
1235 | } | 1449 | } | |
1236 | 1450 | |||
1237 | static usbd_status | 1451 | static usbd_status | |
1238 | alloc_all_mididevs(struct umidi_softc *sc, int nmidi) | 1452 | alloc_all_mididevs(struct umidi_softc *sc, int nmidi) | |
1239 | { | 1453 | { | |
1240 | sc->sc_num_mididevs = nmidi; | 1454 | sc->sc_num_mididevs = nmidi; | |
1241 | sc->sc_mididevs = kmem_zalloc(sizeof(*sc->sc_mididevs)*nmidi, KM_SLEEP); | 1455 | sc->sc_mididevs = kmem_zalloc(sizeof(*sc->sc_mididevs)*nmidi, KM_SLEEP); | |
1242 | if (!sc->sc_mididevs) | 1456 | if (!sc->sc_mididevs) | |
1243 | return USBD_NOMEM; | 1457 | return USBD_NOMEM; | |
1244 | 1458 | |||
1245 | return USBD_NORMAL_COMPLETION; | 1459 | return USBD_NORMAL_COMPLETION; | |
1246 | } | 1460 | } | |
1247 | 1461 | |||
1248 | static void | 1462 | static void | |
1249 | free_all_mididevs(struct umidi_softc *sc) | 1463 | free_all_mididevs(struct umidi_softc *sc) | |
1250 | { | 1464 | { | |
1251 | if (sc->sc_mididevs) | 1465 | struct umidi_mididev *mididevs; | |
1252 | kmem_free(sc->sc_mididevs, | 1466 | size_t len; | |
1253 | sizeof(*sc->sc_mididevs)*sc->sc_num_mididevs); | 1467 | ||
1468 | mutex_enter(&sc->sc_lock); | |||
1469 | mididevs = sc->sc_mididevs; | |||
1470 | if (mididevs) | |||
1471 | len = sizeof(*sc->sc_mididevs )* sc->sc_num_mididevs; | |||
1472 | sc->sc_mididevs = NULL; | |||
1254 | sc->sc_num_mididevs = 0; | 1473 | sc->sc_num_mididevs = 0; | |
1474 | mutex_exit(&sc->sc_lock); | |||
1475 | ||||
1476 | if (mididevs) | |||
1477 | kmem_free(mididevs, len); | |||
1255 | } | 1478 | } | |
1256 | 1479 | |||
1257 | static usbd_status | 1480 | static usbd_status | |
1258 | attach_all_mididevs(struct umidi_softc *sc) | 1481 | attach_all_mididevs(struct umidi_softc *sc) | |
1259 | { | 1482 | { | |
1260 | usbd_status err; | 1483 | usbd_status err; | |
1261 | int i; | 1484 | int i; | |
1262 | 1485 | |||
1263 | if (sc->sc_mididevs) | 1486 | if (sc->sc_mididevs) | |
1264 | for (i = 0; i < sc->sc_num_mididevs; i++) { | 1487 | for (i = 0; i < sc->sc_num_mididevs; i++) { | |
1265 | err = attach_mididev(sc, &sc->sc_mididevs[i]); | 1488 | err = attach_mididev(sc, &sc->sc_mididevs[i]); | |
1266 | if (err != USBD_NORMAL_COMPLETION) | 1489 | if (err != USBD_NORMAL_COMPLETION) | |
1267 | return err; | 1490 | return err; | |
@@ -1316,38 +1539,38 @@ describe_mididev(struct umidi_mididev *m | @@ -1316,38 +1539,38 @@ describe_mididev(struct umidi_mididev *m | |||
1316 | char in_label[16]; | 1539 | char in_label[16]; | |
1317 | char out_label[16]; | 1540 | char out_label[16]; | |
1318 | const char *unit_label; | 1541 | const char *unit_label; | |
1319 | char *final_label; | 1542 | char *final_label; | |
1320 | struct umidi_softc *sc; | 1543 | struct umidi_softc *sc; | |
1321 | int show_ep_in; | 1544 | int show_ep_in; | |
1322 | int show_ep_out; | 1545 | int show_ep_out; | |
1323 | size_t len; | 1546 | size_t len; | |
1324 | 1547 | |||
1325 | sc = md->sc; | 1548 | sc = md->sc; | |
1326 | show_ep_in = sc-> sc_in_num_endpoints > 1 && !sc->cblnums_global; | 1549 | show_ep_in = sc-> sc_in_num_endpoints > 1 && !sc->cblnums_global; | |
1327 | show_ep_out = sc->sc_out_num_endpoints > 1 && !sc->cblnums_global; | 1550 | show_ep_out = sc->sc_out_num_endpoints > 1 && !sc->cblnums_global; | |
1328 | 1551 | |||
1329 | if ( NULL == md->in_jack ) | 1552 | if (NULL == md->in_jack) | |
1330 | in_label[0] = '\0'; | 1553 | in_label[0] = '\0'; | |
1331 | else if ( show_ep_in ) | 1554 | else if (show_ep_in) | |
1332 | snprintf(in_label, sizeof in_label, "<%d(%x) ", | 1555 | snprintf(in_label, sizeof in_label, "<%d(%x) ", | |
1333 | md->in_jack->cable_number, md->in_jack->endpoint->addr); | 1556 | md->in_jack->cable_number, md->in_jack->endpoint->addr); | |
1334 | else | 1557 | else | |
1335 | snprintf(in_label, sizeof in_label, "<%d ", | 1558 | snprintf(in_label, sizeof in_label, "<%d ", | |
1336 | md->in_jack->cable_number); | 1559 | md->in_jack->cable_number); | |
1337 | 1560 | |||
1338 | if ( NULL == md->out_jack ) | 1561 | if (NULL == md->out_jack) | |
1339 | out_label[0] = '\0'; | 1562 | out_label[0] = '\0'; | |
1340 | else if ( show_ep_out ) | 1563 | else if (show_ep_out) | |
1341 | snprintf(out_label, sizeof out_label, ">%d(%x) ", | 1564 | snprintf(out_label, sizeof out_label, ">%d(%x) ", | |
1342 | md->out_jack->cable_number, md->out_jack->endpoint->addr); | 1565 | md->out_jack->cable_number, md->out_jack->endpoint->addr); | |
1343 | else | 1566 | else | |
1344 | snprintf(out_label, sizeof out_label, ">%d ", | 1567 | snprintf(out_label, sizeof out_label, ">%d ", | |
1345 | md->out_jack->cable_number); | 1568 | md->out_jack->cable_number); | |
1346 | 1569 | |||
1347 | unit_label = device_xname(sc->sc_dev); | 1570 | unit_label = device_xname(sc->sc_dev); | |
1348 | 1571 | |||
1349 | len = strlen(in_label) + strlen(out_label) + strlen(unit_label) + 4; | 1572 | len = strlen(in_label) + strlen(out_label) + strlen(unit_label) + 4; | |
1350 | 1573 | |||
1351 | final_label = kmem_alloc(len, KM_SLEEP); | 1574 | final_label = kmem_alloc(len, KM_SLEEP); | |
1352 | 1575 | |||
1353 | snprintf(final_label, len, "%s%son %s", | 1576 | snprintf(final_label, len, "%s%son %s", | |
@@ -1496,34 +1719,38 @@ if ((unsigned char)(p)[1]!=0xFE) \ | @@ -1496,34 +1719,38 @@ if ((unsigned char)(p)[1]!=0xFE) \ | |||
1496 | * as midi(4) hands us a complete message at a time, we'll never send one | 1719 | * as midi(4) hands us a complete message at a time, we'll never send one | |
1497 | * in a dribble of short packets. | 1720 | * in a dribble of short packets. | |
1498 | */ | 1721 | */ | |
1499 | 1722 | |||
1500 | static int | 1723 | static int | |
1501 | out_jack_output(struct umidi_jack *out_jack, u_char *src, int len, int cin) | 1724 | out_jack_output(struct umidi_jack *out_jack, u_char *src, int len, int cin) | |
1502 | { | 1725 | { | |
1503 | struct umidi_endpoint *ep = out_jack->endpoint; | 1726 | struct umidi_endpoint *ep = out_jack->endpoint; | |
1504 | struct umidi_softc *sc = ep->sc; | 1727 | struct umidi_softc *sc = ep->sc; | |
1505 | unsigned char *packet; | 1728 | unsigned char *packet; | |
1506 | int plen; | 1729 | int plen; | |
1507 | int poff; | 1730 | int poff; | |
1508 | 1731 | |||
1732 | KASSERT(mutex_owned(&sc->sc_lock)); | |||
1733 | ||||
1509 | if (sc->sc_dying) | 1734 | if (sc->sc_dying) | |
1510 | return EIO; | 1735 | return EIO; | |
1511 | 1736 | |||
1512 | if (!out_jack->opened) | 1737 | if (!out_jack->opened) | |
1513 | return ENODEV; /* XXX as it was, is this the right errno? */ | 1738 | return ENODEV; /* XXX as it was, is this the right errno? */ | |
1514 | 1739 | |||
1740 | sc->sc_refcnt++; | |||
1741 | ||||
1515 | #ifdef UMIDI_DEBUG | 1742 | #ifdef UMIDI_DEBUG | |
1516 | if ( umididebug >= 100 ) | 1743 | if (umididebug >= 100) | |
1517 | microtime(&umidi_tv); | 1744 | microtime(&umidi_tv); | |
1518 | #endif | 1745 | #endif | |
1519 | DPRINTFN(100, ("umidi out: %"PRIu64".%06"PRIu64"s ep=%p cn=%d len=%d cin=%#x\n", | 1746 | DPRINTFN(100, ("umidi out: %"PRIu64".%06"PRIu64"s ep=%p cn=%d len=%d cin=%#x\n", | |
1520 | umidi_tv.tv_sec%100, (uint64_t)umidi_tv.tv_usec, | 1747 | umidi_tv.tv_sec%100, (uint64_t)umidi_tv.tv_usec, | |
1521 | ep, out_jack->cable_number, len, cin)); | 1748 | ep, out_jack->cable_number, len, cin)); | |
1522 | 1749 | |||
1523 | packet = *ep->next_slot++; | 1750 | packet = *ep->next_slot++; | |
1524 | KASSERT(ep->buffer_size >= | 1751 | KASSERT(ep->buffer_size >= | |
1525 | (ep->next_slot - ep->buffer) * sizeof *ep->buffer); | 1752 | (ep->next_slot - ep->buffer) * sizeof *ep->buffer); | |
1526 | memset(packet, 0, UMIDI_PACKET_SIZE); | 1753 | memset(packet, 0, UMIDI_PACKET_SIZE); | |
1527 | if (UMQ_ISTYPE(sc, UMQ_TYPE_MIDIMAN_GARBLE)) { | 1754 | if (UMQ_ISTYPE(sc, UMQ_TYPE_MIDIMAN_GARBLE)) { | |
1528 | if (NULL != out_jack->midiman_ppkt) { /* fill out a prev pkt */ | 1755 | if (NULL != out_jack->midiman_ppkt) { /* fill out a prev pkt */ | |
1529 | poff = 0x0f & (out_jack->midiman_ppkt[3]); | 1756 | poff = 0x0f & (out_jack->midiman_ppkt[3]); | |
@@ -1546,37 +1773,40 @@ out_jack_output(struct umidi_jack *out_j | @@ -1546,37 +1773,40 @@ out_jack_output(struct umidi_jack *out_j | |||
1546 | memcpy(packet, src, len); | 1773 | memcpy(packet, src, len); | |
1547 | packet[3] = MIX_CN_CIN(out_jack->cable_number, len); | 1774 | packet[3] = MIX_CN_CIN(out_jack->cable_number, len); | |
1548 | DPR_PACKET(out, sc, packet); | 1775 | DPR_PACKET(out, sc, packet); | |
1549 | if (len < 3) | 1776 | if (len < 3) | |
1550 | out_jack->midiman_ppkt = packet; | 1777 | out_jack->midiman_ppkt = packet; | |
1551 | } | 1778 | } | |
1552 | } else { /* the nice simple USB class-compliant case */ | 1779 | } else { /* the nice simple USB class-compliant case */ | |
1553 | packet[0] = MIX_CN_CIN(out_jack->cable_number, cin); | 1780 | packet[0] = MIX_CN_CIN(out_jack->cable_number, cin); | |
1554 | memcpy(packet+1, src, len); | 1781 | memcpy(packet+1, src, len); | |
1555 | DPR_PACKET(out, sc, packet); | 1782 | DPR_PACKET(out, sc, packet); | |
1556 | } | 1783 | } | |
1557 | ep->next_schedule |= 1<<(out_jack->cable_number); | 1784 | ep->next_schedule |= 1<<(out_jack->cable_number); | |
1558 | ++ ep->num_scheduled; | 1785 | ++ ep->num_scheduled; | |
1559 | if ( !ep->armed && !ep->soliciting ) { | 1786 | if (!ep->armed && !ep->soliciting) { | |
1560 | /* | 1787 | /* | |
1561 | * It would be bad to call out_solicit directly here (the | 1788 | * It would be bad to call out_solicit directly here (the | |
1562 | * caller need not be reentrant) but a soft interrupt allows | 1789 | * caller need not be reentrant) but a soft interrupt allows | |
1563 | * solicit to run immediately the caller exits its critical | 1790 | * solicit to run immediately the caller exits its critical | |
1564 | * section, and if the caller has more to write we can get it | 1791 | * section, and if the caller has more to write we can get it | |
1565 | * before starting the USB transfer, and send a longer one. | 1792 | * before starting the USB transfer, and send a longer one. | |
1566 | */ | 1793 | */ | |
1567 | ep->soliciting = 1; | 1794 | ep->soliciting = 1; | |
1568 | softint_schedule(ep->solicit_cookie); | 1795 | softint_schedule(ep->solicit_cookie); | |
1569 | } | 1796 | } | |
1797 | ||||
1798 | if (--sc->sc_refcnt < 0) | |||
1799 | usb_detach_broadcast(sc->sc_dev, &sc->sc_detach_cv); | |||
1570 | 1800 | |||
1571 | return 0; | 1801 | return 0; | |
1572 | } | 1802 | } | |
1573 | 1803 | |||
1574 | static void | 1804 | static void | |
1575 | in_intr(usbd_xfer_handle xfer, usbd_private_handle priv, | 1805 | in_intr(usbd_xfer_handle xfer, usbd_private_handle priv, | |
1576 | usbd_status status) | 1806 | usbd_status status) | |
1577 | { | 1807 | { | |
1578 | int cn, len, i; | 1808 | int cn, len, i; | |
1579 | struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; | 1809 | struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; | |
1580 | struct umidi_softc *sc = ep->sc; | 1810 | struct umidi_softc *sc = ep->sc; | |
1581 | struct umidi_jack *jack; | 1811 | struct umidi_jack *jack; | |
1582 | unsigned char *packet; | 1812 | unsigned char *packet; | |
@@ -1614,27 +1844,27 @@ in_intr(usbd_xfer_handle xfer, usbd_priv | @@ -1614,27 +1844,27 @@ in_intr(usbd_xfer_handle xfer, usbd_priv | |||
1614 | } | 1844 | } | |
1615 | /* 0 <= cn <= 15 by inspection of above code */ | 1845 | /* 0 <= cn <= 15 by inspection of above code */ | |
1616 | if (!(jack = ep->jacks[cn]) || cn != jack->cable_number) { | 1846 | if (!(jack = ep->jacks[cn]) || cn != jack->cable_number) { | |
1617 | DPRINTF(("%s: stray input endpoint %p cable %d len %d: " | 1847 | DPRINTF(("%s: stray input endpoint %p cable %d len %d: " | |
1618 | "%02X %02X %02X (try CN_SEQ quirk?)\n", | 1848 | "%02X %02X %02X (try CN_SEQ quirk?)\n", | |
1619 | device_xname(ep->sc->sc_dev), ep, cn, len, | 1849 | device_xname(ep->sc->sc_dev), ep, cn, len, | |
1620 | (unsigned)data[0], | 1850 | (unsigned)data[0], | |
1621 | (unsigned)data[1], | 1851 | (unsigned)data[1], | |
1622 | (unsigned)data[2])); | 1852 | (unsigned)data[2])); | |
1623 | mutex_exit(&sc->sc_lock); | 1853 | mutex_exit(&sc->sc_lock); | |
1624 | return; | 1854 | return; | |
1625 | } | 1855 | } | |
1626 | 1856 | |||
1627 | if (!jack->binded || !jack->opened) | 1857 | if (!jack->bound || !jack->opened) | |
1628 | continue; | 1858 | continue; | |
1629 | 1859 | |||
1630 | DPRINTFN(500,("%s: input endpoint %p cable %d len %d: " | 1860 | DPRINTFN(500,("%s: input endpoint %p cable %d len %d: " | |
1631 | "%02X %02X %02X\n", | 1861 | "%02X %02X %02X\n", | |
1632 | device_xname(ep->sc->sc_dev), ep, cn, len, | 1862 | device_xname(ep->sc->sc_dev), ep, cn, len, | |
1633 | (unsigned)data[0], | 1863 | (unsigned)data[0], | |
1634 | (unsigned)data[1], | 1864 | (unsigned)data[1], | |
1635 | (unsigned)data[2])); | 1865 | (unsigned)data[2])); | |
1636 | 1866 | |||
1637 | if (jack->u.in.intr) { | 1867 | if (jack->u.in.intr) { | |
1638 | for (i = 0; i < len; i++) { | 1868 | for (i = 0; i < len; i++) { | |
1639 | (*jack->u.in.intr)(jack->arg, data[i]); | 1869 | (*jack->u.in.intr)(jack->arg, data[i]); | |
1640 | } | 1870 | } | |
@@ -1649,31 +1879,31 @@ in_intr(usbd_xfer_handle xfer, usbd_priv | @@ -1649,31 +1879,31 @@ in_intr(usbd_xfer_handle xfer, usbd_priv | |||
1649 | static void | 1879 | static void | |
1650 | out_intr(usbd_xfer_handle xfer, usbd_private_handle priv, | 1880 | out_intr(usbd_xfer_handle xfer, usbd_private_handle priv, | |
1651 | usbd_status status) | 1881 | usbd_status status) | |
1652 | { | 1882 | { | |
1653 | struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; | 1883 | struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; | |
1654 | struct umidi_softc *sc = ep->sc; | 1884 | struct umidi_softc *sc = ep->sc; | |
1655 | u_int32_t count; | 1885 | u_int32_t count; | |
1656 | 1886 | |||
1657 | if (sc->sc_dying) | 1887 | if (sc->sc_dying) | |
1658 | return; | 1888 | return; | |
1659 | 1889 | |||
1660 | mutex_enter(&sc->sc_lock); | 1890 | mutex_enter(&sc->sc_lock); | |
1661 | #ifdef UMIDI_DEBUG | 1891 | #ifdef UMIDI_DEBUG | |
1662 | if ( umididebug >= 200 ) | 1892 | if (umididebug >= 200) | |
1663 | microtime(&umidi_tv); | 1893 | microtime(&umidi_tv); | |
1664 | #endif | 1894 | #endif | |
1665 | usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); | 1895 | usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); | |
1666 | if ( 0 == count % UMIDI_PACKET_SIZE ) { | 1896 | if (0 == count % UMIDI_PACKET_SIZE) { | |
1667 | DPRINTFN(200,("%s: %"PRIu64".%06"PRIu64"s out ep %p xfer length %u\n", | 1897 | DPRINTFN(200,("%s: %"PRIu64".%06"PRIu64"s out ep %p xfer length %u\n", | |
1668 | device_xname(ep->sc->sc_dev), | 1898 | device_xname(ep->sc->sc_dev), | |
1669 | umidi_tv.tv_sec%100, (uint64_t)umidi_tv.tv_usec, ep, count)); | 1899 | umidi_tv.tv_sec%100, (uint64_t)umidi_tv.tv_usec, ep, count)); | |
1670 | } else { | 1900 | } else { | |
1671 | DPRINTF(("%s: output endpoint %p odd transfer length %u\n", | 1901 | DPRINTF(("%s: output endpoint %p odd transfer length %u\n", | |
1672 | device_xname(ep->sc->sc_dev), ep, count)); | 1902 | device_xname(ep->sc->sc_dev), ep, count)); | |
1673 | } | 1903 | } | |
1674 | count /= UMIDI_PACKET_SIZE; | 1904 | count /= UMIDI_PACKET_SIZE; | |
1675 | 1905 | |||
1676 | /* | 1906 | /* | |
1677 | * If while the transfer was pending we buffered any new messages, | 1907 | * If while the transfer was pending we buffered any new messages, | |
1678 | * move them to the start of the buffer. | 1908 | * move them to the start of the buffer. | |
1679 | */ | 1909 | */ | |
@@ -1751,28 +1981,35 @@ out_solicit_locked(void *arg) | @@ -1751,28 +1981,35 @@ out_solicit_locked(void *arg) | |||
1751 | 1981 | |||
1752 | --which; /* now 1s below mask - count 1s to get index */ | 1982 | --which; /* now 1s below mask - count 1s to get index */ | |
1753 | which -= ((which >> 1) & 0x5555);/* SWAR credit aggregate.org */ | 1983 | which -= ((which >> 1) & 0x5555);/* SWAR credit aggregate.org */ | |
1754 | which = (((which >> 2) & 0x3333) + (which & 0x3333)); | 1984 | which = (((which >> 2) & 0x3333) + (which & 0x3333)); | |
1755 | which = (((which >> 4) + which) & 0x0f0f); | 1985 | which = (((which >> 4) + which) & 0x0f0f); | |
1756 | which += (which >> 8); | 1986 | which += (which >> 8); | |
1757 | which &= 0x1f; /* the bit index a/k/a jack number */ | 1987 | which &= 0x1f; /* the bit index a/k/a jack number */ | |
1758 | 1988 | |||
1759 | jack = ep->jacks[which]; | 1989 | jack = ep->jacks[which]; | |
1760 | if (jack->u.out.intr) | 1990 | if (jack->u.out.intr) | |
1761 | (*jack->u.out.intr)(jack->arg); | 1991 | (*jack->u.out.intr)(jack->arg); | |
1762 | } | 1992 | } | |
1763 | /* intr lock held at loop exit */ | 1993 | /* intr lock held at loop exit */ | |
1764 | if (!ep->armed && ep->next_slot > ep->buffer) | 1994 | if (!ep->armed && ep->next_slot > ep->buffer) { | |
1995 | /* | |||
1996 | * Can't hold the interrupt lock while calling into USB, | |||
1997 | * but we can safely drop it here. | |||
1998 | */ | |||
1999 | mutex_exit(&ep->sc->sc_lock); | |||
1765 | ep->armed = (USBD_IN_PROGRESS == start_output_transfer(ep)); | 2000 | ep->armed = (USBD_IN_PROGRESS == start_output_transfer(ep)); | |
2001 | mutex_enter(&ep->sc->sc_lock); | |||
2002 | } | |||
1766 | ep->soliciting = 0; | 2003 | ep->soliciting = 0; | |
1767 | } | 2004 | } | |
1768 | 2005 | |||
1769 | /* Entry point for the softintr. */ | 2006 | /* Entry point for the softintr. */ | |
1770 | static void | 2007 | static void | |
1771 | out_solicit(void *arg) | 2008 | out_solicit(void *arg) | |
1772 | { | 2009 | { | |
1773 | struct umidi_endpoint *ep = arg; | 2010 | struct umidi_endpoint *ep = arg; | |
1774 | struct umidi_softc *sc = ep->sc; | 2011 | struct umidi_softc *sc = ep->sc; | |
1775 | 2012 | |||
1776 | mutex_enter(&sc->sc_lock); | 2013 | mutex_enter(&sc->sc_lock); | |
1777 | out_solicit_locked(arg); | 2014 | out_solicit_locked(arg); | |
1778 | mutex_exit(&sc->sc_lock); | 2015 | mutex_exit(&sc->sc_lock); |
--- src/sys/dev/usb/umidi_quirks.c 2012/05/18 07:52:54 1.18
+++ src/sys/dev/usb/umidi_quirks.c 2015/01/11 14:13:25 1.18.14.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: umidi_quirks.c,v 1.18 2012/05/18 07:52:54 jdc Exp $ */ | 1 | /* $NetBSD: umidi_quirks.c,v 1.18.14.1 2015/01/11 14:13:25 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2001 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2001 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Takuya SHIOZAKI (tshiozak@NetBSD.org). | 8 | * by Takuya SHIOZAKI (tshiozak@NetBSD.org). | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,50 +20,48 @@ | @@ -20,50 +20,48 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: umidi_quirks.c,v 1.18 2012/05/18 07:52:54 jdc Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: umidi_quirks.c,v 1.18.14.1 2015/01/11 14:13:25 martin Exp $"); | |
34 | 34 | |||
35 | #include <sys/param.h> | 35 | #include <sys/param.h> | |
36 | #include <sys/systm.h> | 36 | #include <sys/systm.h> | |
37 | #include <sys/kernel.h> | 37 | #include <sys/kernel.h> | |
38 | #include <sys/malloc.h> | 38 | #include <sys/malloc.h> | |
39 | #include <sys/device.h> | 39 | #include <sys/device.h> | |
40 | #include <sys/ioctl.h> | 40 | #include <sys/ioctl.h> | |
41 | #include <sys/conf.h> | 41 | #include <sys/conf.h> | |
42 | #include <sys/file.h> | 42 | #include <sys/file.h> | |
43 | #include <sys/select.h> | 43 | #include <sys/select.h> | |
44 | #include <sys/proc.h> | 44 | #include <sys/proc.h> | |
45 | #include <sys/vnode.h> | 45 | #include <sys/vnode.h> | |
46 | #include <sys/poll.h> | 46 | #include <sys/poll.h> | |
47 | 47 | |||
48 | #include <dev/usb/usb.h> | 48 | #include <dev/usb/usb.h> | |
49 | #include <dev/usb/usbdi.h> | 49 | #include <dev/usb/usbdi.h> | |
50 | #include <dev/usb/usbdi_util.h> | 50 | #include <dev/usb/usbdi_util.h> | |
51 | 51 | |||
52 | #include <dev/auconv.h> | 52 | #include <dev/auconv.h> | |
53 | #include <dev/usb/usbdevs.h> | 53 | #include <dev/usb/usbdevs.h> | |
54 | #include <dev/usb/uaudioreg.h> | 54 | #include <dev/usb/uaudioreg.h> | |
55 | #include <dev/usb/umidireg.h> | |||
56 | #include <dev/usb/umidivar.h> | |||
57 | #include <dev/usb/umidi_quirks.h> | 55 | #include <dev/usb/umidi_quirks.h> | |
58 | 56 | |||
59 | /* | 57 | /* | |
60 | * quirk codes for UMIDI | 58 | * quirk codes for UMIDI | |
61 | */ | 59 | */ | |
62 | 60 | |||
63 | #ifdef UMIDIQUIRK_DEBUG | 61 | #ifdef UMIDIQUIRK_DEBUG | |
64 | #define DPRINTF(x) if (umidiquirkdebug) printf x | 62 | #define DPRINTF(x) if (umidiquirkdebug) printf x | |
65 | #define DPRINTFN(n,x) if (umidiquirkdebug >= (n)) printf x | 63 | #define DPRINTFN(n,x) if (umidiquirkdebug >= (n)) printf x | |
66 | int umidiquirkdebug = 1; | 64 | int umidiquirkdebug = 1; | |
67 | #else | 65 | #else | |
68 | #define DPRINTF(x) | 66 | #define DPRINTF(x) | |
69 | #define DPRINTFN(n,x) | 67 | #define DPRINTFN(n,x) |