[BACK]Return to umidi.c CVS log [TXT][DIR] Up to [local] / sys / dev / usb

Annotation of sys/dev/usb/umidi.c, Revision 1.1.1.1

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

CVSweb