Bug Summary

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