static void in_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) { int cn, evlen, remain, i; unsigned char *buf; struct umidi_endpoint *ep = (struct umidi_endpoint *)priv; struct umidi_jack *jack; if (usbd_is_dying(ep->sc->sc_udev)) return; usbd_get_xfer_status(xfer, NULL, NULL, &remain, NULL); if (status != USBD_NORMAL_COMPLETION) { DPRINTF(("%s: abnormal status: %s\n", __func__, usbd_errstr(status))); return; } buf = ep->buffer; while (remain >= UMIDI_PACKET_SIZE) { cn = GET_CN(buf[0]); if (cn < ep->num_jacks && (jack = ep->jacks[cn]) && jack->binded && jack->opened && jack->u.in.intr) { evlen = packet_length[GET_CIN(buf[0])]; mtx_enter(&audio_lock); for (i=0; i<evlen; i++) (*jack->u.in.intr)(jack->arg, buf[i+1]); mtx_leave(&audio_lock); } buf += UMIDI_PACKET_SIZE; remain -= UMIDI_PACKET_SIZE; } (void)start_input_transfer(ep); }
void umidi_attach(struct device *parent, struct device *self, void *aux) { usbd_status err; struct umidi_softc *sc = (struct umidi_softc *)self; struct usb_attach_arg *uaa = aux; int i; DPRINTFN(1,("%s\n", __func__)); sc->sc_iface = uaa->iface; sc->sc_udev = uaa->device; sc->sc_quirk = umidi_search_quirk(uaa->vendor, uaa->product, uaa->ifaceno); printf("%s: ", sc->sc_dev.dv_xname); umidi_print_quirk(sc->sc_quirk); err = alloc_all_endpoints(sc); if (err!=USBD_NORMAL_COMPLETION) goto error; err = alloc_all_jacks(sc); if (err!=USBD_NORMAL_COMPLETION) { free_all_endpoints(sc); goto error; } printf("%s: out=%d, in=%d\n", sc->sc_dev.dv_xname, sc->sc_out_num_jacks, sc->sc_in_num_jacks); err = assign_all_jacks_automatically(sc); if (err!=USBD_NORMAL_COMPLETION) { unbind_all_jacks(sc); free_all_jacks(sc); free_all_endpoints(sc); goto error; } err = attach_all_mididevs(sc); if (err!=USBD_NORMAL_COMPLETION) { unbind_all_jacks(sc); free_all_jacks(sc); free_all_endpoints(sc); goto error; } #ifdef UMIDI_DEBUG dump_sc(sc); #endif for (i = 0; i < sc->sc_in_num_endpoints; i++) (void)start_input_transfer(&sc->sc_in_ep[i]); return; error: printf("%s: disabled.\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); }
static usbd_status open_in_jack(struct umidi_jack *jack, void *arg, void (*intr)(void *, int)) { usbd_status err = USBD_NORMAL_COMPLETION; struct umidi_endpoint *ep = jack->endpoint; if (jack->opened) return USBD_IN_USE; jack->arg = arg; jack->u.in.intr = intr; jack->opened = 1; if (ep->num_open++==0 && UE_GET_DIR(ep->addr)==UE_DIR_IN) { err = start_input_transfer(ep); if (err != USBD_NORMAL_COMPLETION && err != USBD_IN_PROGRESS) { ep->num_open--; } } return err; }