static usbd_status assign_all_jacks_automatically(struct umidi_softc *sc) { usbd_status err; int i; struct umidi_jack *out, *in; const signed char *asg_spec; err = alloc_all_mididevs(sc, max(sc->sc_out_num_jacks, sc->sc_in_num_jacks)); if (err!=USBD_NORMAL_COMPLETION) return err; if ( UMQ_ISTYPE(sc, UMQ_TYPE_MD_FIXED)) asg_spec = umidi_get_quirk_data_from_type(sc->sc_quirk, UMQ_TYPE_MD_FIXED); else asg_spec = NULL; for (i=0; i<sc->sc_num_mididevs; i++) { if ( asg_spec != NULL ) { if ( *asg_spec == -1 ) out = NULL; else out = &sc->sc_out_jacks[*asg_spec]; ++ asg_spec; if ( *asg_spec == -1 ) in = NULL; else in = &sc->sc_in_jacks[*asg_spec]; ++ asg_spec; } else { out = (i<sc->sc_out_num_jacks) ? &sc->sc_out_jacks[i] : NULL; in = (i<sc->sc_in_num_jacks) ? &sc->sc_in_jacks[i] : NULL; } err = bind_jacks_to_mididev(sc, out, in, &sc->sc_mididevs[i]); if (err!=USBD_NORMAL_COMPLETION) { free_all_mididevs(sc); return err; } } return USBD_NORMAL_COMPLETION; }
static usbd_status alloc_all_jacks(struct umidi_softc *sc) { int i, j; struct umidi_endpoint *ep; struct umidi_jack *jack; const unsigned char *cn_spec; if (UMQ_ISTYPE(sc, UMQ_TYPE_CN_SEQ_PER_EP)) sc->cblnums_global = 0; else if (UMQ_ISTYPE(sc, UMQ_TYPE_CN_SEQ_GLOBAL)) sc->cblnums_global = 1; else { /* * I don't think this default is correct, but it preserves * the prior behavior of the code. That's why I defined two * complementary quirks. Any device for which the default * behavior is wrong can be made to work by giving it an * explicit quirk, and if a pattern ever develops (as I suspect * it will) that a lot of otherwise standard USB MIDI devices * need the CN_SEQ_PER_EP "quirk," then this default can be * changed to 0, and the only devices that will break are those * listing neither quirk, and they'll easily be fixed by giving * them the CN_SEQ_GLOBAL quirk. */ sc->cblnums_global = 1; } if (UMQ_ISTYPE(sc, UMQ_TYPE_CN_FIXED)) cn_spec = umidi_get_quirk_data_from_type(sc->sc_quirk, UMQ_TYPE_CN_FIXED); else cn_spec = NULL; /* allocate/initialize structures */ sc->sc_jacks = malloc(sizeof(*sc->sc_out_jacks)*(sc->sc_in_num_jacks+ sc->sc_out_num_jacks), M_USBDEV, M_WAITOK); if (!sc->sc_jacks) return USBD_NOMEM; sc->sc_out_jacks = sc->sc_out_num_jacks ? sc->sc_jacks : NULL; sc->sc_in_jacks = sc->sc_in_num_jacks ? sc->sc_jacks+sc->sc_out_num_jacks : NULL; jack = &sc->sc_out_jacks[0]; for (i=0; i<sc->sc_out_num_jacks; i++) { jack->opened = 0; jack->binded = 0; jack->arg = NULL; jack->u.out.intr = NULL; jack->midiman_ppkt = NULL; if ( sc->cblnums_global ) jack->cable_number = i; jack++; } jack = &sc->sc_in_jacks[0]; for (i=0; i<sc->sc_in_num_jacks; i++) { jack->opened = 0; jack->binded = 0; jack->arg = NULL; jack->u.in.intr = NULL; if ( sc->cblnums_global ) jack->cable_number = i; jack++; } /* assign each jacks to each endpoints */ jack = &sc->sc_out_jacks[0]; ep = &sc->sc_out_ep[0]; for (i=0; i<sc->sc_out_num_endpoints; i++) { for (j=0; j<ep->num_jacks; j++) { jack->endpoint = ep; if ( cn_spec != NULL ) jack->cable_number = *cn_spec++; else if ( !sc->cblnums_global ) jack->cable_number = j; ep->jacks[jack->cable_number] = jack; jack++; } ep++; } jack = &sc->sc_in_jacks[0]; ep = &sc->sc_in_ep[0]; for (i=0; i<sc->sc_in_num_endpoints; i++) { for (j=0; j<ep->num_jacks; j++) { jack->endpoint = ep; if ( cn_spec != NULL ) jack->cable_number = *cn_spec++; else if ( !sc->cblnums_global ) jack->cable_number = j; ep->jacks[jack->cable_number] = jack; jack++; } ep++; } return USBD_NORMAL_COMPLETION; }
static usbd_status alloc_all_endpoints_fixed_ep(struct umidi_softc *sc) { usbd_status err; const struct umq_fixed_ep_desc *fp; struct umidi_endpoint *ep; usb_endpoint_descriptor_t *epd; int i; fp = umidi_get_quirk_data_from_type(sc->sc_quirk, UMQ_TYPE_FIXED_EP); sc->sc_out_num_jacks = 0; sc->sc_in_num_jacks = 0; sc->sc_out_num_endpoints = fp->num_out_ep; sc->sc_in_num_endpoints = fp->num_in_ep; sc->sc_endpoints = malloc(sizeof(*sc->sc_out_ep)* (sc->sc_out_num_endpoints+ sc->sc_in_num_endpoints), M_USBDEV, M_WAITOK); if (!sc->sc_endpoints) { return USBD_NOMEM; } sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL; sc->sc_in_ep = sc->sc_in_num_endpoints ? sc->sc_endpoints+sc->sc_out_num_endpoints : NULL; ep = &sc->sc_out_ep[0]; for (i=0; i<sc->sc_out_num_endpoints; i++) { epd = usbd_interface2endpoint_descriptor( sc->sc_iface, fp->out_ep[i].ep); if (!epd) { aprint_error_dev(sc->sc_dev, "cannot get endpoint descriptor(out:%d)\n", fp->out_ep[i].ep); err = USBD_INVAL; goto error; } if (UE_GET_XFERTYPE(epd->bmAttributes)!=UE_BULK || UE_GET_DIR(epd->bEndpointAddress)!=UE_DIR_OUT) { aprint_error_dev(sc->sc_dev, "illegal endpoint(out:%d)\n", fp->out_ep[i].ep); err = USBD_INVAL; goto error; } ep->sc = sc; ep->addr = epd->bEndpointAddress; ep->num_jacks = fp->out_ep[i].num_jacks; sc->sc_out_num_jacks += fp->out_ep[i].num_jacks; ep->num_open = 0; memset(ep->jacks, 0, sizeof(ep->jacks)); ep++; } ep = &sc->sc_in_ep[0]; for (i=0; i<sc->sc_in_num_endpoints; i++) { epd = usbd_interface2endpoint_descriptor( sc->sc_iface, fp->in_ep[i].ep); if (!epd) { aprint_error_dev(sc->sc_dev, "cannot get endpoint descriptor(in:%d)\n", fp->in_ep[i].ep); err = USBD_INVAL; goto error; } /* * MIDISPORT_2X4 inputs on an interrupt rather than a bulk * endpoint. The existing input logic in this driver seems * to work successfully if we just stop treating an interrupt * endpoint as illegal (or the in_progress status we get on * the initial transfer). It does not seem necessary to * actually use the interrupt flavor of alloc_pipe or make * other serious rearrangements of logic. I like that. */ switch ( UE_GET_XFERTYPE(epd->bmAttributes) ) { case UE_BULK: case UE_INTERRUPT: if ( UE_DIR_IN == UE_GET_DIR(epd->bEndpointAddress) ) break; /*FALLTHROUGH*/ default: aprint_error_dev(sc->sc_dev, "illegal endpoint(in:%d)\n", fp->in_ep[i].ep); err = USBD_INVAL; goto error; } ep->sc = sc; ep->addr = epd->bEndpointAddress; ep->num_jacks = fp->in_ep[i].num_jacks; sc->sc_in_num_jacks += fp->in_ep[i].num_jacks; ep->num_open = 0; memset(ep->jacks, 0, sizeof(ep->jacks)); ep++; } return USBD_NORMAL_COMPLETION; error: free(sc->sc_endpoints, M_USBDEV); sc->sc_endpoints = NULL; return err; }
static usbd_status alloc_all_endpoints_fixed_ep(struct umidi_softc *sc) { struct umq_fixed_ep_desc *fp; struct umidi_endpoint *ep; usb_endpoint_descriptor_t *epd; int i; fp = umidi_get_quirk_data_from_type(sc->sc_quirk, UMQ_TYPE_FIXED_EP); sc->sc_out_num_endpoints = fp->num_out_ep; sc->sc_in_num_endpoints = fp->num_in_ep; sc->sc_endpoints = mallocarray(sc->sc_out_num_endpoints + sc->sc_in_num_endpoints, sizeof(*sc->sc_endpoints), M_USBDEV, M_WAITOK | M_CANFAIL); if (!sc->sc_endpoints) return USBD_NOMEM; sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL; sc->sc_in_ep = sc->sc_in_num_endpoints ? sc->sc_endpoints+sc->sc_out_num_endpoints : NULL; ep = &sc->sc_out_ep[0]; for (i=0; i<sc->sc_out_num_endpoints; i++) { epd = usbd_interface2endpoint_descriptor( sc->sc_iface, fp->out_ep[i].ep); if (!epd) { DPRINTF(("%s: cannot get endpoint descriptor(out:%d)\n", sc->sc_dev.dv_xname, fp->out_ep[i].ep)); goto error; } if (UE_GET_XFERTYPE(epd->bmAttributes)!=UE_BULK || UE_GET_DIR(epd->bEndpointAddress)!=UE_DIR_OUT) { printf("%s: illegal endpoint(out:%d)\n", sc->sc_dev.dv_xname, fp->out_ep[i].ep); goto error; } ep->sc = sc; ep->packetsize = UGETW(epd->wMaxPacketSize); ep->addr = epd->bEndpointAddress; ep->num_jacks = fp->out_ep[i].num_jacks; sc->sc_out_num_jacks += fp->out_ep[i].num_jacks; ep->num_open = 0; memset(ep->jacks, 0, sizeof(ep->jacks)); ep++; } ep = &sc->sc_in_ep[0]; for (i=0; i<sc->sc_in_num_endpoints; i++) { epd = usbd_interface2endpoint_descriptor( sc->sc_iface, fp->in_ep[i].ep); if (!epd) { DPRINTF(("%s: cannot get endpoint descriptor(in:%d)\n", sc->sc_dev.dv_xname, fp->in_ep[i].ep)); goto error; } if (UE_GET_XFERTYPE(epd->bmAttributes)!=UE_BULK || UE_GET_DIR(epd->bEndpointAddress)!=UE_DIR_IN) { printf("%s: illegal endpoint(in:%d)\n", sc->sc_dev.dv_xname, fp->in_ep[i].ep); goto error; } ep->sc = sc; ep->addr = epd->bEndpointAddress; ep->packetsize = UGETW(epd->wMaxPacketSize); ep->num_jacks = fp->in_ep[i].num_jacks; sc->sc_in_num_jacks += fp->in_ep[i].num_jacks; ep->num_open = 0; memset(ep->jacks, 0, sizeof(ep->jacks)); ep++; } return USBD_NORMAL_COMPLETION; error: free(sc->sc_endpoints, M_USBDEV, (sc->sc_out_num_endpoints + sc->sc_in_num_endpoints) * sizeof(*sc->sc_endpoints)); sc->sc_endpoints = NULL; return USBD_INVAL; }