Bug Summary

File:dev/usb/umidi.c
Warning:line 753, column 19
Access to field 'endpoint' results in a dereference of a null pointer (loaded from variable 'jack')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name umidi.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -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 -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/lib/clang/13.0.0 -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/swsmu -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/powerplay -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/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 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 -D CONFIG_DRM_AMD_DC_DCN3_0 -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 -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 /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/umidi.c
1/* $OpenBSD: umidi.c,v 1.54 2020/07/31 10:49:33 mglocker Exp $ */
2/* $NetBSD: umidi.c,v 1.16 2002/07/11 21:14:32 augustss Exp $ */
3/*
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Takuya SHIOZAKI (tshiozak@netbsd.org).
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
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
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/device.h>
37#include <sys/ioctl.h>
38#include <sys/conf.h>
39#include <sys/fcntl.h>
40#include <sys/selinfo.h>
41#include <sys/poll.h>
42
43#include <dev/usb/usb.h>
44#include <dev/usb/usbdi.h>
45#include <dev/usb/usbdi_util.h>
46
47#include <dev/usb/umidireg.h>
48#include <dev/usb/umidivar.h>
49#include <dev/usb/umidi_quirks.h>
50
51#include <dev/audio_if.h>
52#include <dev/midi_if.h>
53
54#ifdef UMIDI_DEBUG
55#define DPRINTF(x) if (umididebug) printf x
56#define DPRINTFN(n,x) if (umididebug >= (n)) printf x
57int umididebug = 0;
58#else
59#define DPRINTF(x)
60#define DPRINTFN(n,x)
61#endif
62
63
64static int umidi_open(void *, int,
65 void (*)(void *, int), void (*)(void *), void *);
66static void umidi_close(void *);
67static int umidi_output(void *, int);
68static void umidi_flush(void *);
69static void umidi_getinfo(void *, struct midi_info *);
70
71static usbd_status alloc_pipe(struct umidi_endpoint *);
72static void free_pipe(struct umidi_endpoint *);
73
74static usbd_status alloc_all_endpoints(struct umidi_softc *);
75static void free_all_endpoints(struct umidi_softc *);
76
77static usbd_status alloc_all_jacks(struct umidi_softc *);
78static void free_all_jacks(struct umidi_softc *);
79static usbd_status bind_jacks_to_mididev(struct umidi_softc *,
80 struct umidi_jack *,
81 struct umidi_jack *,
82 struct umidi_mididev *);
83static void unbind_jacks_from_mididev(struct umidi_mididev *);
84static void unbind_all_jacks(struct umidi_softc *);
85static usbd_status assign_all_jacks_automatically(struct umidi_softc *);
86static usbd_status open_out_jack(struct umidi_jack *, void *,
87 void (*)(void *));
88static usbd_status open_in_jack(struct umidi_jack *, void *,
89 void (*)(void *, int));
90static void close_jack(struct umidi_jack *);
91
92static usbd_status attach_mididev(struct umidi_softc *,
93 struct umidi_mididev *);
94static usbd_status detach_mididev(struct umidi_mididev *, int);
95static usbd_status deactivate_mididev(struct umidi_mididev *);
96static usbd_status alloc_all_mididevs(struct umidi_softc *, int);
97static void free_all_mididevs(struct umidi_softc *);
98static usbd_status attach_all_mididevs(struct umidi_softc *);
99static usbd_status detach_all_mididevs(struct umidi_softc *, int);
100static usbd_status deactivate_all_mididevs(struct umidi_softc *);
101
102#ifdef UMIDI_DEBUG
103static void dump_sc(struct umidi_softc *);
104static void dump_ep(struct umidi_endpoint *);
105static void dump_jack(struct umidi_jack *);
106#endif
107
108static void init_packet(struct umidi_packet *);
109
110static usbd_status start_input_transfer(struct umidi_endpoint *);
111static usbd_status start_output_transfer(struct umidi_endpoint *);
112static int out_jack_output(struct umidi_jack *, int);
113static void out_jack_flush(struct umidi_jack *);
114static void in_intr(struct usbd_xfer *, void *, usbd_status);
115static void out_intr(struct usbd_xfer *, void *, usbd_status);
116static int out_build_packet(int, struct umidi_packet *, uByte, u_char *);
117
118
119struct midi_hw_if umidi_hw_if = {
120 umidi_open,
121 umidi_close,
122 umidi_output,
123 umidi_flush, /* flush */
124 umidi_getinfo,
125 0, /* ioctl */
126};
127
128int umidi_match(struct device *, void *, void *);
129void umidi_attach(struct device *, struct device *, void *);
130int umidi_detach(struct device *, int);
131int umidi_activate(struct device *, int);
132
133struct cfdriver umidi_cd = {
134 NULL((void *)0), "umidi", DV_DULL
135};
136
137const struct cfattach umidi_ca = {
138 sizeof(struct umidi_softc),
139 umidi_match,
140 umidi_attach,
141 umidi_detach,
142 umidi_activate,
143};
144
145int
146umidi_match(struct device *parent, void *match, void *aux)
147{
148 struct usb_attach_arg *uaa = aux;
149 usb_interface_descriptor_t *id;
150
151 DPRINTFN(1,("%s\n", __func__));
152
153 if (uaa->iface == NULL((void *)0))
154 return UMATCH_NONE0;
155
156 if (umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno))
157 return UMATCH_IFACECLASS_IFACESUBCLASS4;
158
159 id = usbd_get_interface_descriptor(uaa->iface);
160 if (id!=NULL((void *)0) &&
161 id->bInterfaceClass==UICLASS_AUDIO0x01 &&
162 id->bInterfaceSubClass==UISUBCLASS_MIDISTREAM3)
163 return UMATCH_IFACECLASS_IFACESUBCLASS4;
164
165 return UMATCH_NONE0;
166}
167
168void
169umidi_attach(struct device *parent, struct device *self, void *aux)
170{
171 usbd_status err;
172 struct umidi_softc *sc = (struct umidi_softc *)self;
173 struct usb_attach_arg *uaa = aux;
174 int i;
175
176 DPRINTFN(1,("%s\n", __func__));
177
178 sc->sc_iface = uaa->iface;
179 sc->sc_udev = uaa->device;
180
181 sc->sc_quirk =
182 umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno);
183 printf("%s: ", sc->sc_dev.dv_xname);
184 umidi_print_quirk(sc->sc_quirk);
185
186 err = alloc_all_endpoints(sc);
187 if (err!=USBD_NORMAL_COMPLETION)
1
Assuming 'err' is equal to USBD_NORMAL_COMPLETION
2
Taking false branch
188 goto error;
189 err = alloc_all_jacks(sc);
3
Calling 'alloc_all_jacks'
190 if (err!=USBD_NORMAL_COMPLETION) {
191 free_all_endpoints(sc);
192 goto error;
193 }
194 printf("%s: out=%d, in=%d\n",
195 sc->sc_dev.dv_xname,
196 sc->sc_out_num_jacks, sc->sc_in_num_jacks);
197
198 err = assign_all_jacks_automatically(sc);
199 if (err!=USBD_NORMAL_COMPLETION) {
200 unbind_all_jacks(sc);
201 free_all_jacks(sc);
202 free_all_endpoints(sc);
203 goto error;
204 }
205 err = attach_all_mididevs(sc);
206 if (err!=USBD_NORMAL_COMPLETION) {
207 unbind_all_jacks(sc);
208 free_all_jacks(sc);
209 free_all_endpoints(sc);
210 goto error;
211 }
212
213#ifdef UMIDI_DEBUG
214 dump_sc(sc);
215#endif
216
217 for (i = 0; i < sc->sc_in_num_endpoints; i++)
218 (void)start_input_transfer(&sc->sc_in_ep[i]);
219 return;
220error:
221 printf("%s: disabled.\n", sc->sc_dev.dv_xname);
222 usbd_deactivate(sc->sc_udev);
223}
224
225int
226umidi_activate(struct device *self, int act)
227{
228 struct umidi_softc *sc = (struct umidi_softc *)self;
229
230 if (act == DVACT_DEACTIVATE1) {
231 DPRINTFN(1,("%s (deactivate)\n", __func__));
232 usbd_deactivate(sc->sc_udev);
233 deactivate_all_mididevs(sc);
234 }
235 return 0;
236}
237
238int
239umidi_detach(struct device *self, int flags)
240{
241 struct umidi_softc *sc = (struct umidi_softc *)self;
242
243 DPRINTFN(1,("%s\n", __func__));
244
245 detach_all_mididevs(sc, flags);
246 free_all_mididevs(sc);
247 free_all_jacks(sc);
248 free_all_endpoints(sc);
249
250 return 0;
251}
252
253
254/*
255 * midi_if stuffs
256 */
257int
258umidi_open(void *addr,
259 int flags,
260 void (*iintr)(void *, int),
261 void (*ointr)(void *),
262 void *arg)
263{
264 struct umidi_mididev *mididev = addr;
265 struct umidi_softc *sc = mididev->sc;
266
267 DPRINTF(("%s: sc=%p\n", __func__, sc));
268
269 if (!sc)
270 return ENXIO6;
271 if (mididev->opened)
272 return EBUSY16;
273 if (usbd_is_dying(sc->sc_udev))
274 return EIO5;
275
276 mididev->opened = 1;
277 mididev->flags = flags;
278 if ((mididev->flags & FWRITE0x0002) && mididev->out_jack)
279 open_out_jack(mididev->out_jack, arg, ointr);
280 if ((mididev->flags & FREAD0x0001) && mididev->in_jack)
281 open_in_jack(mididev->in_jack, arg, iintr);
282 return 0;
283}
284
285void
286umidi_close(void *addr)
287{
288 int s;
289 struct umidi_mididev *mididev = addr;
290
291 s = splusb()splraise(0x5);
292 if ((mididev->flags & FWRITE0x0002) && mididev->out_jack)
293 close_jack(mididev->out_jack);
294 if ((mididev->flags & FREAD0x0001) && mididev->in_jack)
295 close_jack(mididev->in_jack);
296 mididev->opened = 0;
297 splx(s)spllower(s);
298}
299
300int
301umidi_output(void *addr, int d)
302{
303 struct umidi_mididev *mididev = addr;
304
305 if (!mididev->out_jack || !mididev->opened)
306 return 1;
307
308 return out_jack_output(mididev->out_jack, d);
309}
310
311void
312umidi_flush(void *addr)
313{
314 struct umidi_mididev *mididev = addr;
315
316 if (!mididev->out_jack || !mididev->opened)
317 return;
318
319 out_jack_flush(mididev->out_jack);
320}
321
322void
323umidi_getinfo(void *addr, struct midi_info *mi)
324{
325 struct umidi_mididev *mididev = addr;
326
327 mi->name = "USB MIDI I/F"; /* XXX: model name */
328 mi->props = MIDI_PROP_OUT_INTR1;
329 if (mididev->in_jack)
330 mi->props |= MIDI_PROP_CAN_INPUT2;
331}
332
333
334/*
335 * each endpoint stuffs
336 */
337
338/* alloc/free pipe */
339static usbd_status
340alloc_pipe(struct umidi_endpoint *ep)
341{
342 struct umidi_softc *sc = ep->sc;
343 usbd_status err;
344
345 DPRINTF(("%s: alloc_pipe %p\n", sc->sc_dev.dv_xname, ep));
346 SIMPLEQ_INIT(&ep->intrq)do { (&ep->intrq)->sqh_first = ((void *)0); (&ep
->intrq)->sqh_last = &(&ep->intrq)->sqh_first
; } while (0)
;
347 ep->pending = 0;
348 ep->busy = 0;
349 ep->used = 0;
350 ep->xfer = usbd_alloc_xfer(sc->sc_udev);
351 if (ep->xfer == NULL((void *)0))
352 return USBD_NOMEM;
353 ep->buffer = usbd_alloc_buffer(ep->xfer, ep->packetsize);
354 if (ep->buffer == NULL((void *)0)) {
355 usbd_free_xfer(ep->xfer);
356 return USBD_NOMEM;
357 }
358 err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe);
359 if (err != USBD_NORMAL_COMPLETION) {
360 usbd_free_xfer(ep->xfer);
361 return err;
362 }
363 return USBD_NORMAL_COMPLETION;
364}
365
366static void
367free_pipe(struct umidi_endpoint *ep)
368{
369 DPRINTF(("%s: %s %p\n", ep->sc->sc_dev.dv_xname, __func__, ep));
370 usbd_close_pipe(ep->pipe);
371 usbd_free_xfer(ep->xfer);
372}
373
374
375/* alloc/free the array of endpoint structures */
376
377static usbd_status alloc_all_endpoints_fixed_ep(struct umidi_softc *);
378static usbd_status alloc_all_endpoints_yamaha(struct umidi_softc *);
379static usbd_status alloc_all_endpoints_genuine(struct umidi_softc *);
380
381static usbd_status
382alloc_all_endpoints(struct umidi_softc *sc)
383{
384 usbd_status err;
385 struct umidi_endpoint *ep;
386 int i;
387
388 sc->sc_out_num_jacks = sc->sc_in_num_jacks = 0;
389
390 if (UMQ_ISTYPE(sc, UMQ_TYPE_FIXED_EP)((sc)->sc_quirk && ((sc)->sc_quirk->type_mask
& (1<<((1)-1))))
)
391 err = alloc_all_endpoints_fixed_ep(sc);
392 else if (UMQ_ISTYPE(sc, UMQ_TYPE_YAMAHA)((sc)->sc_quirk && ((sc)->sc_quirk->type_mask
& (1<<((2)-1))))
)
393 err = alloc_all_endpoints_yamaha(sc);
394 else
395 err = alloc_all_endpoints_genuine(sc);
396 if (err!=USBD_NORMAL_COMPLETION)
397 return err;
398
399 ep = sc->sc_endpoints;
400 for (i=sc->sc_out_num_endpoints+sc->sc_in_num_endpoints; i>0; i--) {
401 err = alloc_pipe(ep);
402 if (err!=USBD_NORMAL_COMPLETION) {
403 while(ep != sc->sc_endpoints) {
404 ep--;
405 free_pipe(ep);
406 }
407 free(sc->sc_endpoints, M_USBDEV102,
408 (sc->sc_out_num_endpoints + sc->sc_in_num_endpoints)
409 * sizeof(*sc->sc_endpoints));
410 sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL((void *)0);
411 break;
412 }
413 ep++;
414 }
415 return err;
416}
417
418static void
419free_all_endpoints(struct umidi_softc *sc)
420{
421 int i;
422
423 for (i=0; i<sc->sc_in_num_endpoints+sc->sc_out_num_endpoints; i++)
424 free_pipe(&sc->sc_endpoints[i]);
425 free(sc->sc_endpoints, M_USBDEV102, (sc->sc_out_num_endpoints +
426 sc->sc_in_num_endpoints) * sizeof(*sc->sc_endpoints));
427 sc->sc_endpoints = sc->sc_out_ep = sc->sc_in_ep = NULL((void *)0);
428}
429
430static usbd_status
431alloc_all_endpoints_fixed_ep(struct umidi_softc *sc)
432{
433 struct umq_fixed_ep_desc *fp;
434 struct umidi_endpoint *ep;
435 usb_endpoint_descriptor_t *epd;
436 int i;
437
438 fp = umidi_get_quirk_data_from_type(sc->sc_quirk,
439 UMQ_TYPE_FIXED_EP1);
440 sc->sc_out_num_endpoints = fp->num_out_ep;
441 sc->sc_in_num_endpoints = fp->num_in_ep;
442 sc->sc_endpoints = mallocarray(sc->sc_out_num_endpoints +
443 sc->sc_in_num_endpoints, sizeof(*sc->sc_endpoints), M_USBDEV102,
444 M_WAITOK0x0001 | M_CANFAIL0x0004);
445 if (!sc->sc_endpoints)
446 return USBD_NOMEM;
447 sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL((void *)0);
448 sc->sc_in_ep =
449 sc->sc_in_num_endpoints ?
450 sc->sc_endpoints+sc->sc_out_num_endpoints : NULL((void *)0);
451
452 if (sc->sc_in_ep == NULL((void *)0) || sc->sc_out_ep == NULL((void *)0)) {
453 printf("%s: cannot get valid endpoints", sc->sc_dev.dv_xname);
454 goto error;
455 }
456 ep = &sc->sc_out_ep[0];
457 for (i=0; i<sc->sc_out_num_endpoints; i++) {
458 epd = usbd_interface2endpoint_descriptor(
459 sc->sc_iface,
460 fp->out_ep[i].ep);
461 if (!epd) {
462 DPRINTF(("%s: cannot get endpoint descriptor(out:%d)\n",
463 sc->sc_dev.dv_xname, fp->out_ep[i].ep));
464 goto error;
465 }
466 if (UE_GET_XFERTYPE(epd->bmAttributes)((epd->bmAttributes) & 0x03)!=UE_BULK0x02 ||
467 UE_GET_DIR(epd->bEndpointAddress)((epd->bEndpointAddress) & 0x80)!=UE_DIR_OUT0x00) {
468 printf("%s: illegal endpoint(out:%d)\n",
469 sc->sc_dev.dv_xname, fp->out_ep[i].ep);
470 goto error;
471 }
472 ep->sc = sc;
473 ep->packetsize = UGETW(epd->wMaxPacketSize)(*(u_int16_t *)(epd->wMaxPacketSize));
474 ep->addr = epd->bEndpointAddress;
475 ep->num_jacks = fp->out_ep[i].num_jacks;
476 sc->sc_out_num_jacks += fp->out_ep[i].num_jacks;
477 ep->num_open = 0;
478 memset(ep->jacks, 0, sizeof(ep->jacks))__builtin_memset((ep->jacks), (0), (sizeof(ep->jacks)));
479 ep++;
480 }
481 ep = &sc->sc_in_ep[0];
482 for (i=0; i<sc->sc_in_num_endpoints; i++) {
483 epd = usbd_interface2endpoint_descriptor(
484 sc->sc_iface,
485 fp->in_ep[i].ep);
486 if (!epd) {
487 DPRINTF(("%s: cannot get endpoint descriptor(in:%d)\n",
488 sc->sc_dev.dv_xname, fp->in_ep[i].ep));
489 goto error;
490 }
491 if (UE_GET_XFERTYPE(epd->bmAttributes)((epd->bmAttributes) & 0x03)!=UE_BULK0x02 ||
492 UE_GET_DIR(epd->bEndpointAddress)((epd->bEndpointAddress) & 0x80)!=UE_DIR_IN0x80) {
493 printf("%s: illegal endpoint(in:%d)\n",
494 sc->sc_dev.dv_xname, fp->in_ep[i].ep);
495 goto error;
496 }
497 ep->sc = sc;
498 ep->addr = epd->bEndpointAddress;
499 ep->packetsize = UGETW(epd->wMaxPacketSize)(*(u_int16_t *)(epd->wMaxPacketSize));
500 ep->num_jacks = fp->in_ep[i].num_jacks;
501 sc->sc_in_num_jacks += fp->in_ep[i].num_jacks;
502 ep->num_open = 0;
503 memset(ep->jacks, 0, sizeof(ep->jacks))__builtin_memset((ep->jacks), (0), (sizeof(ep->jacks)));
504 ep++;
505 }
506
507 return USBD_NORMAL_COMPLETION;
508error:
509 free(sc->sc_endpoints, M_USBDEV102, (sc->sc_out_num_endpoints +
510 sc->sc_in_num_endpoints) * sizeof(*sc->sc_endpoints));
511 sc->sc_endpoints = NULL((void *)0);
512 return USBD_INVAL;
513}
514
515static usbd_status
516alloc_all_endpoints_yamaha(struct umidi_softc *sc)
517{
518 /* This driver currently supports max 1in/1out bulk endpoints */
519 usb_descriptor_t *desc;
520 usb_endpoint_descriptor_t *epd;
521 int out_addr, in_addr, in_packetsize, i, dir;
522 size_t remain, descsize;
523
524 out_addr = in_addr = 0;
525
526 /* detect endpoints */
527 desc = TO_D(usbd_get_interface_descriptor(sc->sc_iface))((usb_descriptor_t *)(usbd_get_interface_descriptor(sc->sc_iface
)))
;
528 for (i=(int)TO_IFD(desc)((usb_interface_descriptor_t *)(desc))->bNumEndpoints-1; i>=0; i--) {
529 epd = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
530 if (epd == NULL((void *)0))
531 continue;
532
533 if (UE_GET_XFERTYPE(epd->bmAttributes)((epd->bmAttributes) & 0x03) == UE_BULK0x02) {
534 dir = UE_GET_DIR(epd->bEndpointAddress)((epd->bEndpointAddress) & 0x80);
535 if (dir==UE_DIR_OUT0x00 && !out_addr)
536 out_addr = epd->bEndpointAddress;
537 else if (dir==UE_DIR_IN0x80 && !in_addr) {
538 in_addr = epd->bEndpointAddress;
539 in_packetsize = UGETW(epd->wMaxPacketSize)(*(u_int16_t *)(epd->wMaxPacketSize));
540 }
541 }
542 }
543 desc = NEXT_D(desc)((usb_descriptor_t *)((caddr_t)(desc)+(desc)->bLength));
544
545 /* count jacks */
546 if (!(desc->bDescriptorType==UDESC_CS_INTERFACE0x24 &&
547 desc->bDescriptorSubtype==UMIDI_MS_HEADER0x01))
548 return USBD_INVAL;
549 remain = (size_t)UGETW(TO_CSIFD(desc)->wTotalLength)(*(u_int16_t *)(((struct umidi_cs_interface_descriptor *)(desc
))->wTotalLength))
-
550 (size_t)desc->bLength;
551 desc = NEXT_D(desc)((usb_descriptor_t *)((caddr_t)(desc)+(desc)->bLength));
552
553 while (remain>=sizeof(usb_descriptor_t)) {
554 descsize = desc->bLength;
555 if (descsize>remain || descsize==0)
556 break;
557 if (desc->bDescriptorType==UDESC_CS_INTERFACE0x24 &&
558 remain>=UMIDI_JACK_DESCRIPTOR_SIZE5) {
559 if (desc->bDescriptorSubtype==UMIDI_OUT_JACK0x03)
560 sc->sc_out_num_jacks++;
561 else if (desc->bDescriptorSubtype==UMIDI_IN_JACK0x02)
562 sc->sc_in_num_jacks++;
563 }
564 desc = NEXT_D(desc)((usb_descriptor_t *)((caddr_t)(desc)+(desc)->bLength));
565 remain-=descsize;
566 }
567
568 /* validate some parameters */
569 if (sc->sc_out_num_jacks>UMIDI_MAX_EPJACKS16)
570 sc->sc_out_num_jacks = UMIDI_MAX_EPJACKS16;
571 if (sc->sc_in_num_jacks>UMIDI_MAX_EPJACKS16)
572 sc->sc_in_num_jacks = UMIDI_MAX_EPJACKS16;
573 if (sc->sc_out_num_jacks && out_addr)
574 sc->sc_out_num_endpoints = 1;
575 else {
576 sc->sc_out_num_endpoints = 0;
577 sc->sc_out_num_jacks = 0;
578 }
579 if (sc->sc_in_num_jacks && in_addr)
580 sc->sc_in_num_endpoints = 1;
581 else {
582 sc->sc_in_num_endpoints = 0;
583 sc->sc_in_num_jacks = 0;
584 }
585 sc->sc_endpoints = mallocarray(sc->sc_out_num_endpoints +
586 sc->sc_in_num_endpoints, sizeof(struct umidi_endpoint),
587 M_USBDEV102, M_WAITOK0x0001 | M_CANFAIL0x0004);
588 if (!sc->sc_endpoints)
589 return USBD_NOMEM;
590 if (sc->sc_out_num_endpoints) {
591 sc->sc_out_ep = sc->sc_endpoints;
592 sc->sc_out_ep->sc = sc;
593 sc->sc_out_ep->addr = out_addr;
594 sc->sc_out_ep->packetsize = UGETW(epd->wMaxPacketSize)(*(u_int16_t *)(epd->wMaxPacketSize));
595 sc->sc_out_ep->num_jacks = sc->sc_out_num_jacks;
596 sc->sc_out_ep->num_open = 0;
597 memset(sc->sc_out_ep->jacks, 0, sizeof(sc->sc_out_ep->jacks))__builtin_memset((sc->sc_out_ep->jacks), (0), (sizeof(sc
->sc_out_ep->jacks)))
;
598 } else
599 sc->sc_out_ep = NULL((void *)0);
600
601 if (sc->sc_in_num_endpoints) {
602 sc->sc_in_ep = sc->sc_endpoints+sc->sc_out_num_endpoints;
603 sc->sc_in_ep->sc = sc;
604 sc->sc_in_ep->addr = in_addr;
605 sc->sc_in_ep->packetsize = in_packetsize;
606 sc->sc_in_ep->num_jacks = sc->sc_in_num_jacks;
607 sc->sc_in_ep->num_open = 0;
608 memset(sc->sc_in_ep->jacks, 0, sizeof(sc->sc_in_ep->jacks))__builtin_memset((sc->sc_in_ep->jacks), (0), (sizeof(sc
->sc_in_ep->jacks)))
;
609 } else
610 sc->sc_in_ep = NULL((void *)0);
611
612 return USBD_NORMAL_COMPLETION;
613}
614
615static usbd_status
616alloc_all_endpoints_genuine(struct umidi_softc *sc)
617{
618 usb_interface_descriptor_t *interface_desc;
619 usb_config_descriptor_t *config_desc;
620 usb_descriptor_t *desc;
621 size_t remain, descsize;
622 struct umidi_endpoint *p, *q, *lowest, *endep, tmpep;
623 int epaddr, eppacketsize, num_ep;
624
625 interface_desc = usbd_get_interface_descriptor(sc->sc_iface);
626 num_ep = interface_desc->bNumEndpoints;
627 sc->sc_endpoints = p = mallocarray(num_ep,
628 sizeof(struct umidi_endpoint), M_USBDEV102, M_WAITOK0x0001 | M_CANFAIL0x0004);
629 if (!p)
630 return USBD_NOMEM;
631
632 sc->sc_out_num_endpoints = sc->sc_in_num_endpoints = 0;
633 epaddr = -1;
634
635 /* get the list of endpoints for midi stream */
636 config_desc = usbd_get_config_descriptor(sc->sc_udev);
637 desc = (usb_descriptor_t *) config_desc;
638 remain = (size_t)UGETW(config_desc->wTotalLength)(*(u_int16_t *)(config_desc->wTotalLength));
639 while (remain>=sizeof(usb_descriptor_t)) {
640 descsize = desc->bLength;
641 if (descsize>remain || descsize==0)
642 break;
643 if (desc->bDescriptorType==UDESC_ENDPOINT0x05 &&
644 remain>=USB_ENDPOINT_DESCRIPTOR_SIZE7 &&
645 UE_GET_XFERTYPE(TO_EPD(desc)->bmAttributes)((((usb_endpoint_descriptor_t *)(desc))->bmAttributes) &
0x03)
== UE_BULK0x02) {
646 epaddr = TO_EPD(desc)((usb_endpoint_descriptor_t *)(desc))->bEndpointAddress;
647 eppacketsize = UGETW(TO_EPD(desc)->wMaxPacketSize)(*(u_int16_t *)(((usb_endpoint_descriptor_t *)(desc))->wMaxPacketSize
))
;
648 } else if (desc->bDescriptorType==UDESC_CS_ENDPOINT0x25 &&
649 remain>=UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE4 &&
650 epaddr!=-1) {
651 if (num_ep>0) {
652 num_ep--;
653 p->sc = sc;
654 p->addr = epaddr;
655 p->packetsize = eppacketsize;
656 p->num_jacks = TO_CSEPD(desc)((struct umidi_cs_endpoint_descriptor *)(desc))->bNumEmbMIDIJack;
657 if (UE_GET_DIR(epaddr)((epaddr) & 0x80)==UE_DIR_OUT0x00) {
658 sc->sc_out_num_endpoints++;
659 sc->sc_out_num_jacks += p->num_jacks;
660 } else {
661 sc->sc_in_num_endpoints++;
662 sc->sc_in_num_jacks += p->num_jacks;
663 }
664 p++;
665 }
666 } else
667 epaddr = -1;
668 desc = NEXT_D(desc)((usb_descriptor_t *)((caddr_t)(desc)+(desc)->bLength));
669 remain-=descsize;
670 }
671
672 /* sort endpoints */
673 num_ep = sc->sc_out_num_endpoints + sc->sc_in_num_endpoints;
674 p = sc->sc_endpoints;
675 endep = p + num_ep;
676 while (p<endep) {
677 lowest = p;
678 for (q=p+1; q<endep; q++) {
679 if ((UE_GET_DIR(lowest->addr)((lowest->addr) & 0x80)==UE_DIR_IN0x80 &&
680 UE_GET_DIR(q->addr)((q->addr) & 0x80)==UE_DIR_OUT0x00) ||
681 ((UE_GET_DIR(lowest->addr)((lowest->addr) & 0x80)==
682 UE_GET_DIR(q->addr)((q->addr) & 0x80)) &&
683 (UE_GET_ADDR(lowest->addr)((lowest->addr) & 0x0f)>
684 UE_GET_ADDR(q->addr)((q->addr) & 0x0f))))
685 lowest = q;
686 }
687 if (lowest != p) {
688 memcpy((void *)&tmpep, (void *)p, sizeof(tmpep))__builtin_memcpy(((void *)&tmpep), ((void *)p), (sizeof(tmpep
)))
;
689 memcpy((void *)p, (void *)lowest, sizeof(tmpep))__builtin_memcpy(((void *)p), ((void *)lowest), (sizeof(tmpep
)))
;
690 memcpy((void *)lowest, (void *)&tmpep, sizeof(tmpep))__builtin_memcpy(((void *)lowest), ((void *)&tmpep), (sizeof
(tmpep)))
;
691 }
692 p->num_open = 0;
693 p++;
694 }
695
696 sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL((void *)0);
697 sc->sc_in_ep =
698 sc->sc_in_num_endpoints ?
699 sc->sc_endpoints+sc->sc_out_num_endpoints : NULL((void *)0);
700
701 return USBD_NORMAL_COMPLETION;
702}
703
704
705/*
706 * jack stuffs
707 */
708
709static usbd_status
710alloc_all_jacks(struct umidi_softc *sc)
711{
712 int i, j;
713 struct umidi_endpoint *ep;
714 struct umidi_jack *jack, **rjack;
715
716 /* allocate/initialize structures */
717 sc->sc_jacks = mallocarray(sc->sc_in_num_jacks + sc->sc_out_num_jacks,
718 sizeof(*sc->sc_out_jacks), M_USBDEV102, M_WAITOK0x0001 | M_CANFAIL0x0004);
719 if (!sc->sc_jacks)
4
Assuming field 'sc_jacks' is non-null
5
Taking false branch
720 return USBD_NOMEM;
721 sc->sc_out_jacks =
8
Null pointer value stored to field 'sc_out_jacks'
722 sc->sc_out_num_jacks ? sc->sc_jacks : NULL((void *)0);
6
Assuming field 'sc_out_num_jacks' is 0
7
'?' condition is false
723 sc->sc_in_jacks =
724 sc->sc_in_num_jacks ? sc->sc_jacks+sc->sc_out_num_jacks : NULL((void *)0);
9
Assuming field 'sc_in_num_jacks' is 0
10
'?' condition is false
725
726 jack = &sc->sc_out_jacks[0];
727 for (i=0; i<sc->sc_out_num_jacks; i++) {
11
Loop condition is false. Execution continues on line 736
728 jack->opened = 0;
729 jack->binded = 0;
730 jack->arg = NULL((void *)0);
731 jack->u.out.intr = NULL((void *)0);
732 jack->intr = 0;
733 jack->cable_number = i;
734 jack++;
735 }
736 jack = &sc->sc_in_jacks[0];
737 for (i=0; i<sc->sc_in_num_jacks; i++) {
12
Loop condition is false. Execution continues on line 747
738 jack->opened = 0;
739 jack->binded = 0;
740 jack->arg = NULL((void *)0);
741 jack->u.in.intr = NULL((void *)0);
742 jack->cable_number = i;
743 jack++;
744 }
745
746 /* assign each jacks to each endpoints */
747 jack = &sc->sc_out_jacks[0];
13
Null pointer value stored to 'jack'
748 ep = &sc->sc_out_ep[0];
749 for (i=0; i<sc->sc_out_num_endpoints; i++) {
14
Assuming 'i' is < field 'sc_out_num_endpoints'
15
Loop condition is true. Entering loop body
750 rjack = &ep->jacks[0];
751 for (j=0; j<ep->num_jacks; j++) {
16
Assuming 'j' is < field 'num_jacks'
17
Loop condition is true. Entering loop body
752 *rjack = jack;
753 jack->endpoint = ep;
18
Access to field 'endpoint' results in a dereference of a null pointer (loaded from variable 'jack')
754 jack++;
755 rjack++;
756 }
757 ep++;
758 }
759 jack = &sc->sc_in_jacks[0];
760 ep = &sc->sc_in_ep[0];
761 for (i=0; i<sc->sc_in_num_endpoints; i++) {
762 rjack = &ep->jacks[0];
763 for (j=0; j<ep->num_jacks; j++) {
764 *rjack = jack;
765 jack->endpoint = ep;
766 jack++;
767 rjack++;
768 }
769 ep++;
770 }
771
772 return USBD_NORMAL_COMPLETION;
773}
774
775static void
776free_all_jacks(struct umidi_softc *sc)
777{
778 int s, jacks = sc->sc_in_num_jacks + sc->sc_out_num_jacks;
779
780 s = splusb()splraise(0x5);
781 if (sc->sc_out_jacks) {
782 free(sc->sc_jacks, M_USBDEV102, jacks * sizeof(*sc->sc_out_jacks));
783 sc->sc_jacks = sc->sc_in_jacks = sc->sc_out_jacks = NULL((void *)0);
784 sc->sc_out_num_jacks = sc->sc_in_num_jacks = 0;
785 }
786 splx(s)spllower(s);
787}
788
789static usbd_status
790bind_jacks_to_mididev(struct umidi_softc *sc,
791 struct umidi_jack *out_jack,
792 struct umidi_jack *in_jack,
793 struct umidi_mididev *mididev)
794{
795 if ((out_jack && out_jack->binded) || (in_jack && in_jack->binded))
796 return USBD_IN_USE;
797 if (mididev->out_jack || mididev->in_jack)
798 return USBD_IN_USE;
799
800 if (out_jack)
801 out_jack->binded = 1;
802 if (in_jack)
803 in_jack->binded = 1;
804 mididev->in_jack = in_jack;
805 mididev->out_jack = out_jack;
806
807 return USBD_NORMAL_COMPLETION;
808}
809
810static void
811unbind_jacks_from_mididev(struct umidi_mididev *mididev)
812{
813 if ((mididev->flags & FWRITE0x0002) && mididev->out_jack)
814 close_jack(mididev->out_jack);
815 if ((mididev->flags & FREAD0x0001) && mididev->in_jack)
816 close_jack(mididev->in_jack);
817
818 if (mididev->out_jack)
819 mididev->out_jack->binded = 0;
820 if (mididev->in_jack)
821 mididev->in_jack->binded = 0;
822 mididev->out_jack = mididev->in_jack = NULL((void *)0);
823}
824
825static void
826unbind_all_jacks(struct umidi_softc *sc)
827{
828 int i;
829
830 if (sc->sc_mididevs)
831 for (i=0; i<sc->sc_num_mididevs; i++) {
832 unbind_jacks_from_mididev(&sc->sc_mididevs[i]);
833 }
834}
835
836static usbd_status
837assign_all_jacks_automatically(struct umidi_softc *sc)
838{
839 usbd_status err;
840 int i;
841 struct umidi_jack *out, *in;
842
843 err =
844 alloc_all_mididevs(sc,
845 max(sc->sc_out_num_jacks, sc->sc_in_num_jacks));
846 if (err!=USBD_NORMAL_COMPLETION)
847 return err;
848
849 for (i=0; i<sc->sc_num_mididevs; i++) {
850 out = (i<sc->sc_out_num_jacks) ? &sc->sc_out_jacks[i]:NULL((void *)0);
851 in = (i<sc->sc_in_num_jacks) ? &sc->sc_in_jacks[i]:NULL((void *)0);
852 err = bind_jacks_to_mididev(sc, out, in, &sc->sc_mididevs[i]);
853 if (err!=USBD_NORMAL_COMPLETION) {
854 free_all_mididevs(sc);
855 return err;
856 }
857 }
858
859 return USBD_NORMAL_COMPLETION;
860}
861
862static usbd_status
863open_out_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *))
864{
865 if (jack->opened)
866 return USBD_IN_USE;
867
868 jack->arg = arg;
869 jack->u.out.intr = intr;
870 init_packet(&jack->packet);
871 jack->opened = 1;
872 jack->endpoint->num_open++;
873
874 return USBD_NORMAL_COMPLETION;
875}
876
877static usbd_status
878open_in_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *, int))
879{
880 if (jack->opened)
881 return USBD_IN_USE;
882
883 jack->arg = arg;
884 jack->u.in.intr = intr;
885 jack->opened = 1;
886 jack->endpoint->num_open++;
887
888 return USBD_NORMAL_COMPLETION;
889}
890
891static void
892close_jack(struct umidi_jack *jack)
893{
894 if (jack->opened) {
895 jack->opened = 0;
896 jack->endpoint->num_open--;
897 }
898}
899
900static usbd_status
901attach_mididev(struct umidi_softc *sc, struct umidi_mididev *mididev)
902{
903 if (mididev->sc)
904 return USBD_IN_USE;
905
906 mididev->sc = sc;
907
908 mididev->mdev = midi_attach_mi(&umidi_hw_if, mididev, &sc->sc_dev);
909
910 return USBD_NORMAL_COMPLETION;
911}
912
913static usbd_status
914detach_mididev(struct umidi_mididev *mididev, int flags)
915{
916 if (!mididev->sc)
917 return USBD_NO_ADDR;
918
919 if (mididev->opened)
920 umidi_close(mididev);
921 unbind_jacks_from_mididev(mididev);
922
923 if (mididev->mdev)
924 config_detach(mididev->mdev, flags);
925
926 mididev->sc = NULL((void *)0);
927
928 return USBD_NORMAL_COMPLETION;
929}
930
931static usbd_status
932deactivate_mididev(struct umidi_mididev *mididev)
933{
934 if (mididev->out_jack)
935 mididev->out_jack->binded = 0;
936 if (mididev->in_jack)
937 mididev->in_jack->binded = 0;
938 config_deactivate(mididev->mdev);
939
940 return USBD_NORMAL_COMPLETION;
941}
942
943static usbd_status
944alloc_all_mididevs(struct umidi_softc *sc, int nmidi)
945{
946 sc->sc_num_mididevs = nmidi;
947 sc->sc_mididevs = mallocarray(nmidi, sizeof(*sc->sc_mididevs),
948 M_USBDEV102, M_WAITOK0x0001 | M_CANFAIL0x0004 | M_ZERO0x0008);
949 if (!sc->sc_mididevs)
950 return USBD_NOMEM;
951
952 return USBD_NORMAL_COMPLETION;
953}
954
955static void
956free_all_mididevs(struct umidi_softc *sc)
957{
958 if (sc->sc_mididevs)
959 free(sc->sc_mididevs, M_USBDEV102,
960 sc->sc_num_mididevs * sizeof(*sc->sc_mididevs));
961 sc->sc_mididevs = NULL((void *)0);
962 sc->sc_num_mididevs = 0;
963}
964
965static usbd_status
966attach_all_mididevs(struct umidi_softc *sc)
967{
968 usbd_status err;
969 int i;
970
971 if (sc->sc_mididevs)
972 for (i=0; i<sc->sc_num_mididevs; i++) {
973 err = attach_mididev(sc, &sc->sc_mididevs[i]);
974 if (err!=USBD_NORMAL_COMPLETION)
975 return err;
976 }
977
978 return USBD_NORMAL_COMPLETION;
979}
980
981static usbd_status
982detach_all_mididevs(struct umidi_softc *sc, int flags)
983{
984 usbd_status err;
985 int i;
986
987 if (sc->sc_mididevs)
988 for (i=0; i<sc->sc_num_mididevs; i++) {
989 err = detach_mididev(&sc->sc_mididevs[i], flags);
990 if (err!=USBD_NORMAL_COMPLETION)
991 return err;
992 }
993
994 return USBD_NORMAL_COMPLETION;
995}
996
997static usbd_status
998deactivate_all_mididevs(struct umidi_softc *sc)
999{
1000 usbd_status err;
1001 int i;
1002
1003 if (sc->sc_mididevs)
1004 for (i=0; i<sc->sc_num_mididevs; i++) {
1005 err = deactivate_mididev(&sc->sc_mididevs[i]);
1006 if (err!=USBD_NORMAL_COMPLETION)
1007 return err;
1008 }
1009
1010 return USBD_NORMAL_COMPLETION;
1011}
1012
1013#ifdef UMIDI_DEBUG
1014static void
1015dump_sc(struct umidi_softc *sc)
1016{
1017 int i;
1018
1019 DPRINTFN(10, ("%s: %s\n", sc->sc_dev.dv_xname, __func__));
1020 for (i=0; i<sc->sc_out_num_endpoints; i++) {
1021 DPRINTFN(10, ("\tout_ep(%p):\n", &sc->sc_out_ep[i]));
1022 dump_ep(&sc->sc_out_ep[i]);
1023 }
1024 for (i=0; i<sc->sc_in_num_endpoints; i++) {
1025 DPRINTFN(10, ("\tin_ep(%p):\n", &sc->sc_in_ep[i]));
1026 dump_ep(&sc->sc_in_ep[i]);
1027 }
1028}
1029
1030static void
1031dump_ep(struct umidi_endpoint *ep)
1032{
1033 int i;
1034 for (i=0; i<ep->num_jacks; i++) {
1035 DPRINTFN(10, ("\t\tjack(%p):\n", ep->jacks[i]));
1036 dump_jack(ep->jacks[i]);
1037 }
1038}
1039static void
1040dump_jack(struct umidi_jack *jack)
1041{
1042 DPRINTFN(10, ("\t\t\tep=%p\n",
1043 jack->endpoint));
1044}
1045
1046#endif /* UMIDI_DEBUG */
1047
1048
1049
1050/*
1051 * MUX MIDI PACKET
1052 */
1053
1054static const int packet_length[16] = {
1055 /*0*/ -1,
1056 /*1*/ -1,
1057 /*2*/ 2,
1058 /*3*/ 3,
1059 /*4*/ 3,
1060 /*5*/ 1,
1061 /*6*/ 2,
1062 /*7*/ 3,
1063 /*8*/ 3,
1064 /*9*/ 3,
1065 /*A*/ 3,
1066 /*B*/ 3,
1067 /*C*/ 2,
1068 /*D*/ 2,
1069 /*E*/ 3,
1070 /*F*/ 1,
1071};
1072
1073#define GET_CN(p)(((unsigned char)(p)>>4)&0x0F) (((unsigned char)(p)>>4)&0x0F)
1074#define GET_CIN(p)((unsigned char)(p)&0x0F) ((unsigned char)(p)&0x0F)
1075
1076static void
1077init_packet(struct umidi_packet *packet)
1078{
1079 packet->status = 0;
1080 packet->index = 0;
1081}
1082
1083static usbd_status
1084start_input_transfer(struct umidi_endpoint *ep)
1085{
1086 usbd_status err;
1087 usbd_setup_xfer(ep->xfer, ep->pipe,
1088 (void *)ep,
1089 ep->buffer, ep->packetsize,
1090 USBD_SHORT_XFER_OK0x04 | USBD_NO_COPY0x01, USBD_NO_TIMEOUT0, in_intr);
1091 err = usbd_transfer(ep->xfer);
1092 if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) {
1093 DPRINTF(("%s: %s: usbd_transfer() failed err=%s\n",
1094 ep->sc->sc_dev.dv_xname, __func__, usbd_errstr(err)));
1095 return err;
1096 }
1097 return USBD_NORMAL_COMPLETION;
1098}
1099
1100static usbd_status
1101start_output_transfer(struct umidi_endpoint *ep)
1102{
1103 usbd_status err;
1104 usbd_setup_xfer(ep->xfer, ep->pipe,
1105 (void *)ep,
1106 ep->buffer, ep->used,
1107 USBD_NO_COPY0x01, USBD_NO_TIMEOUT0, out_intr);
1108 err = usbd_transfer(ep->xfer);
1109 if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) {
1110 DPRINTF(("%s: %s: usbd_transfer() failed err=%s\n",
1111 ep->sc->sc_dev.dv_xname, __func__, usbd_errstr(err)));
1112 return err;
1113 }
1114 ep->used = ep->packetsize;
1115 return USBD_NORMAL_COMPLETION;
1116}
1117
1118
1119#ifdef UMIDI_DEBUG
1120#define DPR_PACKET(dir, sc, p) \
1121 DPRINTFN(500, \
1122 ("%s: umidi packet(" #dir "): %02X %02X %02X %02X\n", \
1123 sc->sc_dev.dv_xname, \
1124 (unsigned char)(p)->buffer[0], \
1125 (unsigned char)(p)->buffer[1], \
1126 (unsigned char)(p)->buffer[2], \
1127 (unsigned char)(p)->buffer[3]));
1128#else
1129#define DPR_PACKET(dir, sc, p)
1130#endif
1131
1132static int
1133out_jack_output(struct umidi_jack *j, int d)
1134{
1135 struct umidi_endpoint *ep = j->endpoint;
1136 struct umidi_softc *sc = ep->sc;
1137 int s;
1138
1139 if (usbd_is_dying(sc->sc_udev))
1140 return 1;
1141 if (!j->opened)
1142 return 1;
1143 s = splusb()splraise(0x5);
1144 if (ep->busy) {
1145 if (!j->intr) {
1146 SIMPLEQ_INSERT_TAIL(&ep->intrq, j, intrq_entry)do { (j)->intrq_entry.sqe_next = ((void *)0); *(&ep->
intrq)->sqh_last = (j); (&ep->intrq)->sqh_last =
&(j)->intrq_entry.sqe_next; } while (0)
;
1147 ep->pending++;
1148 j->intr = 1;
1149 }
1150 splx(s)spllower(s);
1151 return 0;
1152 }
1153 if (!out_build_packet(j->cable_number, &j->packet, d,
1154 ep->buffer + ep->used)) {
1155 splx(s)spllower(s);
1156 return 1;
1157 }
1158 ep->used += UMIDI_PACKET_SIZE4;
1159 if (ep->used == ep->packetsize) {
1160 ep->busy = 1;
1161 start_output_transfer(ep);
1162 }
1163 splx(s)spllower(s);
1164 return 1;
1165}
1166
1167static void
1168out_jack_flush(struct umidi_jack *j)
1169{
1170 struct umidi_endpoint *ep = j->endpoint;
1171 int s;
1172
1173 if (usbd_is_dying(ep->sc->sc_udev) || !j->opened)
1174 return;
1175
1176 s = splusb()splraise(0x5);
1177 if (ep->used != 0 && !ep->busy) {
1178 ep->busy = 1;
1179 start_output_transfer(ep);
1180 }
1181 splx(s)spllower(s);
1182}
1183
1184
1185static void
1186in_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1187{
1188 int cn, evlen, remain, i;
1189 unsigned char *buf;
1190 struct umidi_endpoint *ep = (struct umidi_endpoint *)priv;
1191 struct umidi_jack *jack;
1192
1193 if (usbd_is_dying(ep->sc->sc_udev))
1194 return;
1195
1196 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &remain, NULL((void *)0));
1197 if (status != USBD_NORMAL_COMPLETION) {
1198 DPRINTF(("%s: abnormal status: %s\n", __func__, usbd_errstr(status)));
1199 return;
1200 }
1201 buf = ep->buffer;
1202 while (remain >= UMIDI_PACKET_SIZE4) {
1203 cn = GET_CN(buf[0])(((unsigned char)(buf[0])>>4)&0x0F);
1204 if (cn < ep->num_jacks && (jack = ep->jacks[cn]) &&
1205 jack->binded && jack->opened && jack->u.in.intr) {
1206 evlen = packet_length[GET_CIN(buf[0])((unsigned char)(buf[0])&0x0F)];
1207 mtx_enter(&audio_lock);
1208 for (i=0; i<evlen; i++)
1209 (*jack->u.in.intr)(jack->arg, buf[i+1]);
1210 mtx_leave(&audio_lock);
1211 }
1212 buf += UMIDI_PACKET_SIZE4;
1213 remain -= UMIDI_PACKET_SIZE4;
1214 }
1215 (void)start_input_transfer(ep);
1216}
1217
1218static void
1219out_intr(struct usbd_xfer *xfer, void *priv, usbd_status status)
1220{
1221 struct umidi_endpoint *ep = (struct umidi_endpoint *)priv;
1222 struct umidi_softc *sc = ep->sc;
1223 struct umidi_jack *j;
1224 unsigned pending;
1225
1226 if (usbd_is_dying(sc->sc_udev))
1227 return;
1228
1229 ep->used = 0;
1230 ep->busy = 0;
1231 for (pending = ep->pending; pending > 0; pending--) {
1232 j = SIMPLEQ_FIRST(&ep->intrq)((&ep->intrq)->sqh_first);
1233#ifdef DIAGNOSTIC1
1234 if (j == NULL((void *)0)) {
1235 printf("umidi: missing intr entry\n");
1236 break;
1237 }
1238#endif
1239 SIMPLEQ_REMOVE_HEAD(&ep->intrq, intrq_entry)do { if (((&ep->intrq)->sqh_first = (&ep->intrq
)->sqh_first->intrq_entry.sqe_next) == ((void *)0)) (&
ep->intrq)->sqh_last = &(&ep->intrq)->sqh_first
; } while (0)
;
1240 ep->pending--;
1241 j->intr = 0;
1242 mtx_enter(&audio_lock);
1243 if (j->opened && j->u.out.intr)
1244 (*j->u.out.intr)(j->arg);
1245 mtx_leave(&audio_lock);
1246 }
1247}
1248
1249#define UMIDI_VOICELEN(status)(umidi_evlen[((status) >> 4) & 7]) (umidi_evlen[((status) >> 4) & 7])
1250static const unsigned int umidi_evlen[] = { 4, 4, 4, 4, 3, 3, 4 };
1251
1252#define EV_SYSEX0xf0 0xf0
1253#define EV_MTC0xf1 0xf1
1254#define EV_SPP0xf2 0xf2
1255#define EV_SONGSEL0xf3 0xf3
1256#define EV_TUNE_REQ0xf6 0xf6
1257#define EV_SYSEX_STOP0xf7 0xf7
1258
1259static int
1260out_build_packet(int cable_number, struct umidi_packet *packet,
1261 uByte data, u_char *obuf)
1262{
1263 if (data >= 0xf8) { /* is it a realtime message ? */
1264 obuf[0] = data >> 4 | cable_number << 4;
1265 obuf[1] = data;
1266 obuf[2] = 0;
1267 obuf[3] = 0;
1268 return 1;
1269 }
1270 if (data >= 0xf0) { /* is it a common message ? */
1271 switch(data) {
1272 case EV_SYSEX0xf0:
1273 packet->buf[1] = packet->status = data;
1274 packet->index = 2;
1275 break;
1276 case EV_SYSEX_STOP0xf7:
1277 if (packet->status != EV_SYSEX0xf0) break;
1278 if (packet->index == 0)
1279 packet->index = 1;
1280 packet->status = data;
1281 packet->buf[packet->index++] = data;
1282 packet->buf[0] = (0x4 - 1 + packet->index) | cable_number << 4;
1283 goto packetready;
1284 case EV_TUNE_REQ0xf6:
1285 packet->status = data;
1286 packet->buf[0] = 0x5 | cable_number << 4;
1287 packet->index = 1;
1288 goto packetready;
1289 default:
1290 packet->status = data;
1291 break;
1292 }
1293 return 0;
1294 }
1295 if (data >= 0x80) { /* is it a voice message ? */
1296 packet->status = data;
1297 packet->index = 0;
1298 return 0;
1299 }
1300
1301 /* else it is a data byte */
1302 if (packet->status >= 0xf0) {
1303 switch(packet->status) {
1304 case EV_SYSEX0xf0: /* sysex starts or continues */
1305 if (packet->index == 0)
1306 packet->index = 1;
1307
1308 packet->buf[packet->index++] = data;
1309 if (packet->index >= UMIDI_PACKET_SIZE4) {
1310 packet->buf[0] = 0x4 | cable_number << 4;
1311 goto packetready;
1312 }
1313 break;
1314 case EV_MTC0xf1: /* messages with 1 data byte */
1315 case EV_SONGSEL0xf3:
1316 packet->buf[0] = 0x2 | cable_number << 4;
1317 packet->buf[1] = packet->status;
1318 packet->buf[2] = data;
1319 packet->index = 3;
1320 goto packetready;
1321 case EV_SPP0xf2: /* messages with 2 data bytes */
1322 if (packet->index == 0) {
1323 packet->buf[0] = 0x3 | cable_number << 4;
1324 packet->index = 1;
1325 }
1326 packet->buf[packet->index++] = data;
1327 if (packet->index >= UMIDI_PACKET_SIZE4) {
1328 packet->buf[1] = packet->status;
1329 goto packetready;
1330 }
1331 break;
1332 default: /* ignore data with unknown status */
1333 break;
1334 }
1335 return 0;
1336 }
1337 if (packet->status >= 0x80) { /* is it a voice message ? */
1338 if (packet->index == 0) {
1339 packet->buf[0] = packet->status >> 4 | cable_number << 4;
1340 packet->buf[1] = packet->status;
1341 packet->index = 2;
1342 }
1343 packet->buf[packet->index++] = data;
1344 if (packet->index >= UMIDI_VOICELEN(packet->status)(umidi_evlen[((packet->status) >> 4) & 7]))
1345 goto packetready;
1346 }
1347 /* ignore data with unknown status */
1348 return 0;
1349
1350packetready:
1351 while (packet->index < UMIDI_PACKET_SIZE4)
1352 packet->buf[packet->index++] = 0;
1353 packet->index = 0;
1354 memcpy(obuf, packet->buf, UMIDI_PACKET_SIZE)__builtin_memcpy((obuf), (packet->buf), (4));
1355 return 1;
1356}