Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
Arquivo: umidi.c Projeto: bluhm/sys
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;
}