Bug Summary

File:dev/midi.c
Warning:line 463, column 2
Value stored to 'error' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name midi.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/midi.c
1/* $OpenBSD: midi.c,v 1.56 2023/09/26 19:55:24 mvs Exp $ */
2
3/*
4 * Copyright (c) 2003, 2004 Alexandre Ratchov
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>
20#include <sys/fcntl.h>
21#include <sys/systm.h>
22#include <sys/ioctl.h>
23#include <sys/conf.h>
24#include <sys/kernel.h>
25#include <sys/timeout.h>
26#include <sys/vnode.h>
27#include <sys/signalvar.h>
28#include <sys/device.h>
29
30#include <dev/midi_if.h>
31#include <dev/audio_if.h>
32#include <dev/midivar.h>
33
34#define DEVNAME(sc)((sc)->dev.dv_xname) ((sc)->dev.dv_xname)
35
36int midiopen(dev_t, int, int, struct proc *);
37int midiclose(dev_t, int, int, struct proc *);
38int midiread(dev_t, struct uio *, int);
39int midiwrite(dev_t, struct uio *, int);
40int midikqfilter(dev_t, struct knote *);
41int midiioctl(dev_t, u_long, caddr_t, int, struct proc *);
42int midiprobe(struct device *, void *, void *);
43void midiattach(struct device *, struct device *, void *);
44int mididetach(struct device *, int);
45int midiprint(void *, const char *);
46
47void midi_iintr(void *, int);
48void midi_ointr(void *);
49void midi_timeout(void *);
50void midi_out_start(struct midi_softc *);
51void midi_out_stop(struct midi_softc *);
52void midi_out_do(struct midi_softc *);
53void midi_attach(struct midi_softc *, struct device *);
54
55
56const struct cfattach midi_ca = {
57 sizeof(struct midi_softc), midiprobe, midiattach, mididetach
58};
59
60struct cfdriver midi_cd = {
61 NULL((void *)0), "midi", DV_DULL
62};
63
64
65void filt_midiwdetach(struct knote *);
66int filt_midiwrite(struct knote *, long);
67int filt_midimodify(struct kevent *, struct knote *);
68int filt_midiprocess(struct knote *, struct kevent *);
69
70const struct filterops midiwrite_filtops = {
71 .f_flags = FILTEROP_ISFD0x00000001 | FILTEROP_MPSAFE0x00000002,
72 .f_attach = NULL((void *)0),
73 .f_detach = filt_midiwdetach,
74 .f_event = filt_midiwrite,
75 .f_modify = filt_midimodify,
76 .f_process = filt_midiprocess,
77};
78
79void filt_midirdetach(struct knote *);
80int filt_midiread(struct knote *, long);
81
82const struct filterops midiread_filtops = {
83 .f_flags = FILTEROP_ISFD0x00000001 | FILTEROP_MPSAFE0x00000002,
84 .f_attach = NULL((void *)0),
85 .f_detach = filt_midirdetach,
86 .f_event = filt_midiread,
87 .f_modify = filt_midimodify,
88 .f_process = filt_midiprocess,
89};
90
91void
92midi_buf_wakeup(struct midi_buffer *buf)
93{
94 if (buf->blocking) {
95 wakeup(&buf->blocking);
96 buf->blocking = 0;
97 }
98 knote_locked(&buf->klist, 0);
99}
100
101void
102midi_iintr(void *addr, int data)
103{
104 struct midi_softc *sc = (struct midi_softc *)addr;
105 struct midi_buffer *mb = &sc->inbuf;
106
107 MUTEX_ASSERT_LOCKED(&audio_lock)do { if (((&audio_lock)->mtx_owner != ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})) && !(panicstr ||
db_active)) panic("mutex %p not held in %s", (&audio_lock
), __func__); } while (0)
;
108 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001) || !(sc->flags & FREAD0x0001))
109 return;
110
111 if (MIDIBUF_ISFULL(mb)((mb)->used >= (1 << 10)))
112 return; /* discard data */
113
114 MIDIBUF_WRITE(mb, data)do { (mb)->data[(((mb)->start + (mb)->used) & ((
1 << 10) - 1))] = (data); (mb)->used++; } while(0)
;
115
116 midi_buf_wakeup(mb);
117}
118
119int
120midiread(dev_t dev, struct uio *uio, int ioflag)
121{
122 struct midi_softc *sc;
123 struct midi_buffer *mb;
124 size_t count;
125 int error;
126
127 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
128 if (sc == NULL((void *)0))
129 return ENXIO6;
130 if (!(sc->flags & FREAD0x0001)) {
131 error = ENXIO6;
132 goto done;
133 }
134 mb = &sc->inbuf;
135
136 /* if there is no data then sleep (unless IO_NDELAY flag is set) */
137 error = 0;
138 mtx_enter(&audio_lock);
139 while (MIDIBUF_ISEMPTY(mb)((mb)->used == 0)) {
140 if (ioflag & IO_NDELAY0x10) {
141 error = EWOULDBLOCK35;
142 goto done_mtx;
143 }
144 sc->inbuf.blocking = 1;
145 error = msleep_nsec(&sc->inbuf.blocking, &audio_lock,
146 PWAIT32 | PCATCH0x100, "mid_rd", INFSLP0xffffffffffffffffULL);
147 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
148 error = EIO5;
149 if (error)
150 goto done_mtx;
151 }
152
153 /* at this stage, there is at least 1 byte */
154
155 while (uio->uio_resid > 0 && mb->used > 0) {
156 count = MIDIBUF_SIZE(1 << 10) - mb->start;
157 if (count > mb->used)
158 count = mb->used;
159 if (count > uio->uio_resid)
160 count = uio->uio_resid;
161 mtx_leave(&audio_lock);
162 error = uiomove(mb->data + mb->start, count, uio);
163 if (error)
164 goto done;
165 mtx_enter(&audio_lock);
166 MIDIBUF_REMOVE(mb, count)do { (mb)->start += (count); (mb)->start &= ((1 <<
10) - 1); (mb)->used -= (count); } while(0)
;
167 }
168
169done_mtx:
170 mtx_leave(&audio_lock);
171done:
172 device_unref(&sc->dev);
173 return error;
174}
175
176void
177midi_ointr(void *addr)
178{
179 struct midi_softc *sc = (struct midi_softc *)addr;
180 struct midi_buffer *mb;
181
182 MUTEX_ASSERT_LOCKED(&audio_lock)do { if (((&audio_lock)->mtx_owner != ({struct cpu_info
*__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof
(struct cpu_info, ci_self))); __ci;})) && !(panicstr ||
db_active)) panic("mutex %p not held in %s", (&audio_lock
), __func__); } while (0)
;
183 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001) || !(sc->flags & FWRITE0x0002))
184 return;
185
186 mb = &sc->outbuf;
187 if (mb->used > 0) {
188#ifdef MIDI_DEBUG
189 if (!sc->isbusy) {
190 printf("midi_ointr: output must be busy\n");
191 }
192#endif
193 midi_out_do(sc);
194 } else if (sc->isbusy)
195 midi_out_stop(sc);
196}
197
198void
199midi_timeout(void *addr)
200{
201 mtx_enter(&audio_lock);
202 midi_ointr(addr);
203 mtx_leave(&audio_lock);
204}
205
206void
207midi_out_start(struct midi_softc *sc)
208{
209 if (!sc->isbusy) {
210 sc->isbusy = 1;
211 midi_out_do(sc);
212 }
213}
214
215void
216midi_out_stop(struct midi_softc *sc)
217{
218 sc->isbusy = 0;
219 midi_buf_wakeup(&sc->outbuf);
220}
221
222void
223midi_out_do(struct midi_softc *sc)
224{
225 struct midi_buffer *mb = &sc->outbuf;
226
227 while (mb->used > 0) {
228 if (!sc->hw_if->output(sc->hw_hdl, mb->data[mb->start]))
229 break;
230 MIDIBUF_REMOVE(mb, 1)do { (mb)->start += (1); (mb)->start &= ((1 <<
10) - 1); (mb)->used -= (1); } while(0)
;
231 if (MIDIBUF_ISEMPTY(mb)((mb)->used == 0)) {
232 if (sc->hw_if->flush != NULL((void *)0))
233 sc->hw_if->flush(sc->hw_hdl);
234 midi_out_stop(sc);
235 return;
236 }
237 }
238
239 if (!(sc->props & MIDI_PROP_OUT_INTR1)) {
240 if (MIDIBUF_ISEMPTY(mb)((mb)->used == 0))
241 midi_out_stop(sc);
242 else
243 timeout_add(&sc->timeo, 1);
244 }
245}
246
247int
248midiwrite(dev_t dev, struct uio *uio, int ioflag)
249{
250 struct midi_softc *sc;
251 struct midi_buffer *mb;
252 size_t count;
253 int error;
254
255 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
256 if (sc == NULL((void *)0))
257 return ENXIO6;
258 if (!(sc->flags & FWRITE0x0002)) {
259 error = ENXIO6;
260 goto done;
261 }
262 mb = &sc->outbuf;
263
264 /*
265 * If IO_NDELAY flag is set then check if there is enough room
266 * in the buffer to store at least one byte. If not then dont
267 * start the write process.
268 */
269 error = 0;
270 mtx_enter(&audio_lock);
271 if ((ioflag & IO_NDELAY0x10) && MIDIBUF_ISFULL(mb)((mb)->used >= (1 << 10)) && (uio->uio_resid > 0)) {
272 error = EWOULDBLOCK35;
273 goto done_mtx;
274 }
275
276 while (uio->uio_resid > 0) {
277 while (MIDIBUF_ISFULL(mb)((mb)->used >= (1 << 10))) {
278 if (ioflag & IO_NDELAY0x10) {
279 /*
280 * At this stage at least one byte is already
281 * moved so we do not return EWOULDBLOCK
282 */
283 goto done_mtx;
284 }
285 sc->outbuf.blocking = 1;
286 error = msleep_nsec(&sc->outbuf.blocking, &audio_lock,
287 PWAIT32 | PCATCH0x100, "mid_wr", INFSLP0xffffffffffffffffULL);
288 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
289 error = EIO5;
290 if (error)
291 goto done_mtx;
292 }
293
294 count = MIDIBUF_SIZE(1 << 10) - MIDIBUF_END(mb)(((mb)->start + (mb)->used) & ((1 << 10) - 1)
)
;
295 if (count > MIDIBUF_AVAIL(mb)((1 << 10) - (mb)->used))
296 count = MIDIBUF_AVAIL(mb)((1 << 10) - (mb)->used);
297 if (count > uio->uio_resid)
298 count = uio->uio_resid;
299 mtx_leave(&audio_lock);
300 error = uiomove(mb->data + MIDIBUF_END(mb)(((mb)->start + (mb)->used) & ((1 << 10) - 1)
)
, count, uio);
301 if (error)
302 goto done;
303 mtx_enter(&audio_lock);
304 mb->used += count;
305 midi_out_start(sc);
306 }
307
308done_mtx:
309 mtx_leave(&audio_lock);
310done:
311 device_unref(&sc->dev);
312 return error;
313}
314
315int
316midikqfilter(dev_t dev, struct knote *kn)
317{
318 struct midi_softc *sc;
319 struct klist *klist;
320 int error;
321
322 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
323 if (sc == NULL((void *)0))
324 return ENXIO6;
325 error = 0;
326 switch (kn->kn_filterkn_kevent.filter) {
327 case EVFILT_READ(-1):
328 klist = &sc->inbuf.klist;
329 kn->kn_fop = &midiread_filtops;
330 break;
331 case EVFILT_WRITE(-2):
332 klist = &sc->outbuf.klist;
333 kn->kn_fop = &midiwrite_filtops;
334 break;
335 default:
336 error = EINVAL22;
337 goto done;
338 }
339 kn->kn_hook = (void *)sc;
340
341 klist_insert(klist, kn);
342done:
343 device_unref(&sc->dev);
344 return error;
345}
346
347void
348filt_midirdetach(struct knote *kn)
349{
350 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
351
352 klist_remove(&sc->inbuf.klist, kn);
353}
354
355int
356filt_midiread(struct knote *kn, long hint)
357{
358 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
359
360 return (!MIDIBUF_ISEMPTY(&sc->inbuf)((&sc->inbuf)->used == 0));
361}
362
363void
364filt_midiwdetach(struct knote *kn)
365{
366 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
367
368 klist_remove(&sc->outbuf.klist, kn);
369}
370
371int
372filt_midiwrite(struct knote *kn, long hint)
373{
374 struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
375
376 return (!MIDIBUF_ISFULL(&sc->outbuf)((&sc->outbuf)->used >= (1 << 10)));
377}
378
379int
380filt_midimodify(struct kevent *kev, struct knote *kn)
381{
382 int active;
383
384 mtx_enter(&audio_lock);
385 active = knote_modify(kev, kn);
386 mtx_leave(&audio_lock);
387
388 return active;
389}
390
391int
392filt_midiprocess(struct knote *kn, struct kevent *kev)
393{
394 int active;
395
396 mtx_enter(&audio_lock);
397 active = knote_process(kn, kev);
398 mtx_leave(&audio_lock);
399
400 return active;
401}
402
403int
404midiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
405{
406 struct midi_softc *sc;
407 int error;
408
409 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
410 if (sc == NULL((void *)0))
411 return ENXIO6;
412 error = 0;
413 switch(cmd) {
414 case FIONBIO((unsigned long)0x80000000 | ((sizeof(int) & 0x1fff) <<
16) | ((('f')) << 8) | ((126)))
:
415 /* All handled in the upper FS layer */
416 break;
417 default:
418 error = ENOTTY25;
419 }
420 device_unref(&sc->dev);
421 return error;
422}
423
424int
425midiopen(dev_t dev, int flags, int mode, struct proc *p)
426{
427 struct midi_softc *sc;
428 int error;
429
430 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
431 if (sc == NULL((void *)0))
432 return ENXIO6;
433 error = 0;
434 if (sc->flags) {
435 error = EBUSY16;
436 goto done;
437 }
438 MIDIBUF_INIT(&sc->inbuf)do { (&sc->inbuf)->start = (&sc->inbuf)->
used = 0; } while(0)
;
439 MIDIBUF_INIT(&sc->outbuf)do { (&sc->outbuf)->start = (&sc->outbuf)->
used = 0; } while(0)
;
440 sc->isbusy = 0;
441 sc->inbuf.blocking = sc->outbuf.blocking = 0;
442 sc->flags = flags;
443 error = sc->hw_if->open(sc->hw_hdl, flags, midi_iintr, midi_ointr, sc);
444 if (error)
445 sc->flags = 0;
446done:
447 device_unref(&sc->dev);
448 return error;
449}
450
451int
452midiclose(dev_t dev, int fflag, int devtype, struct proc *p)
453{
454 struct midi_softc *sc;
455 struct midi_buffer *mb;
456 int error;
457
458 sc = (struct midi_softc *)device_lookup(&midi_cd, minor(dev)((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >>
8))
);
459 if (sc == NULL((void *)0))
460 return ENXIO6;
461
462 /* start draining output buffer */
463 error = 0;
Value stored to 'error' is never read
464 mb = &sc->outbuf;
465 mtx_enter(&audio_lock);
466 if (!MIDIBUF_ISEMPTY(mb)((mb)->used == 0))
467 midi_out_start(sc);
468 while (sc->isbusy) {
469 sc->outbuf.blocking = 1;
470 error = msleep_nsec(&sc->outbuf.blocking, &audio_lock,
471 PWAIT32, "mid_dr", SEC_TO_NSEC(5));
472 if (!(sc->dev.dv_flags & DVF_ACTIVE0x0001))
473 error = EIO5;
474 if (error)
475 break;
476 }
477 mtx_leave(&audio_lock);
478
479 /*
480 * some hw_if->close() reset immediately the midi uart
481 * which flushes the internal buffer of the uart device,
482 * so we may lose some (important) data. To avoid this,
483 * sleep 20ms (around 64 bytes) to give the time to the
484 * uart to drain its internal buffers.
485 */
486 tsleep_nsec(&sc->outbuf.blocking, PWAIT32, "mid_cl", MSEC_TO_NSEC(20));
487 sc->hw_if->close(sc->hw_hdl);
488 sc->flags = 0;
489 device_unref(&sc->dev);
490 return 0;
491}
492
493int
494midiprobe(struct device *parent, void *match, void *aux)
495{
496 struct audio_attach_args *sa = aux;
497
498 return (sa != NULL((void *)0) && (sa->type == AUDIODEV_TYPE_MIDI1) ? 1 : 0);
499}
500
501void
502midiattach(struct device *parent, struct device *self, void *aux)
503{
504 struct midi_info mi;
505 struct midi_softc *sc = (struct midi_softc *)self;
506 struct audio_attach_args *sa = (struct audio_attach_args *)aux;
507 const struct midi_hw_if *hwif = sa->hwif;
508 void *hdl = sa->hdl;
509
510#ifdef DIAGNOSTIC1
511 if (hwif == 0 ||
512 hwif->open == 0 ||
513 hwif->close == 0 ||
514 hwif->output == 0 ||
515 hwif->getinfo == 0) {
516 printf("%s: missing method\n", DEVNAME(sc)((sc)->dev.dv_xname));
517 return;
518 }
519#endif
520
521 klist_init_mutex(&sc->inbuf.klist, &audio_lock);
522 klist_init_mutex(&sc->outbuf.klist, &audio_lock);
523
524 sc->hw_if = hwif;
525 sc->hw_hdl = hdl;
526 sc->hw_if->getinfo(sc->hw_hdl, &mi);
527 sc->props = mi.props;
528 sc->flags = 0;
529 timeout_set(&sc->timeo, midi_timeout, sc);
530 printf(": <%s>\n", mi.name);
531}
532
533int
534mididetach(struct device *self, int flags)
535{
536 struct midi_softc *sc = (struct midi_softc *)self;
537 int maj, mn;
538
539 /* locate the major number */
540 for (maj = 0; maj < nchrdev; maj++) {
541 if (cdevsw[maj].d_open == midiopen) {
542 /* Nuke the vnodes for any open instances (calls close). */
543 mn = self->dv_unit;
544 vdevgone(maj, mn, mn, VCHR);
545 }
546 }
547
548 /*
549 * The close() method did nothing (device_lookup() returns
550 * NULL), so quickly halt transfers (normally parent is already
551 * gone, and code below is no-op), and wake-up user-land blocked
552 * in read/write/ioctl, which return EIO.
553 */
554 if (sc->flags) {
555 KERNEL_ASSERT_LOCKED()((_kernel_lock_held()) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/midi.c"
, 555, "_kernel_lock_held()"))
;
556 if (sc->flags & FREAD0x0001)
557 wakeup(&sc->inbuf.blocking);
558 if (sc->flags & FWRITE0x0002)
559 wakeup(&sc->outbuf.blocking);
560 sc->hw_if->close(sc->hw_hdl);
561 sc->flags = 0;
562 }
563
564 klist_invalidate(&sc->inbuf.klist);
565 klist_invalidate(&sc->outbuf.klist);
566 klist_free(&sc->inbuf.klist);
567 klist_free(&sc->outbuf.klist);
568
569 return 0;
570}
571
572int
573midiprint(void *aux, const char *pnp)
574{
575 if (pnp)
576 printf("midi at %s", pnp);
577 return (UNCONF1);
578}
579
580struct device *
581midi_attach_mi(const struct midi_hw_if *hwif, void *hdl, struct device *dev)
582{
583 struct audio_attach_args arg;
584
585 arg.type = AUDIODEV_TYPE_MIDI1;
586 arg.hwif = hwif;
587 arg.hdl = hdl;
588 return config_found(dev, &arg, midiprint)config_found_sm((dev), (&arg), (midiprint), ((void *)0));
589}